[Flask] Simple ERP for a farm.
Modularization.
Changed files
- app/forms.py
- app/main.py
- app/model.py
- app/models.py
- app/modules/__init__.py
- app/modules/auth/forms.py
- app/modules/auth/routes.py
- app/modules/common.py
- app/modules/customers/forms.py
- app/modules/customers/routes.py
- app/modules/ferti/forms.py
- app/modules/ferti/routes.py
- app/modules/forms.py
- app/modules/forms.py.bkp
- app/modules/invoices/forms.py
- app/modules/invoices/routes.py
- app/modules/modules.py.bkp
- app/modules/orders/forms.py
- app/modules/orders/routes.py
- app/modules/products/forms.py
- app/modules/products/routes.py
- app/routes.py
app/forms.py
@@ -1,93 +0,0 @@
1
Removed:
"""
2
Removed:
Form classes must be named 'Add{Item}', Item referring to the
3
Removed:
model concerned.
4
Removed:
"""
5
Removed:
6
Removed:
from flask_wtf import FlaskForm
7
Removed:
from wtforms import (
8
Removed:
SubmitField,
9
Removed:
SelectField,
10
Removed:
RadioField,
11
Removed:
HiddenField,
12
Removed:
StringField,
13
Removed:
PasswordField,
14
Removed:
IntegerField,
15
Removed:
FloatField,
16
Removed:
DateTimeField,
17
Removed:
)
18
Removed:
from wtforms.validators import InputRequired, Length, NumberRange
19
Removed:
20
Removed:
21
Removed:
class AddCustomer(FlaskForm):
22
Removed:
name = StringField("Customer name", validators=[InputRequired()])
23
Removed:
name_alternative = StringField("Alternative name")
24
Removed:
# date_time_created = DateTimeField("Creation date")
25
Removed:
code_customer = StringField("Customer code")
26
Removed:
code_accounting = StringField("Accounting code")
27
Removed:
address = StringField("Address")
28
Removed:
postal_code = StringField("Postal Code")
29
Removed:
city = StringField("City")
30
Removed:
country = StringField("Country")
31
Removed:
phone = StringField("Phone")
32
Removed:
website = StringField("Website")
33
Removed:
email = StringField("E-mail")
34
Removed:
professional_id_1 = StringField("Professional ID 1")
35
Removed:
professional_id_2 = StringField("Professional ID 2")
36
Removed:
tax_id = StringField("Tax ID")
37
Removed:
payment_terms = StringField("Payment Terms", default="Tu vas payer sale chien!")
38
Removed:
submit = SubmitField("Add/Update Product")
39
Removed:
40
Removed:
41
Removed:
class AddProduct(FlaskForm):
42
Removed:
name = StringField("Product name", validators=[InputRequired()])
43
Removed:
code_accounting = StringField("Accounting code", default=0)
44
Removed:
unit_weight = FloatField("Unit weight", default=0)
45
Removed:
price_net = FloatField("Price (net)", default=0)
46
Removed:
price_gross = FloatField("Price (gross)", default=0)
47
Removed:
tax_rate = FloatField("Tax rate", default=0)
48
Removed:
submit = SubmitField("Add/Update Product")
49
Removed:
50
Removed:
51
Removed:
class AddLog(FlaskForm):
52
Removed:
target = SelectField(
53
Removed:
"Type",
54
Removed:
choices=[("False", "Log"), ("True", "Target")],
55
Removed:
validators=[InputRequired()],
56
Removed:
)
57
Removed:
nno3 = FloatField("NNO3", default=0)
58
Removed:
p = FloatField("P", default=0)
59
Removed:
k = FloatField("K", default=0)
60
Removed:
ca = FloatField("Ca", default=0)
61
Removed:
mg = FloatField("Mg", default=0)
62
Removed:
s = FloatField("S", default=0)
63
Removed:
na = FloatField("Na", default=0)
64
Removed:
cl = FloatField("Cl", default=0)
65
Removed:
fe = FloatField("Fe", default=0)
66
Removed:
zn = FloatField("Zn", default=0)
67
Removed:
b = FloatField("B", default=0)
68
Removed:
mn = FloatField("Mn", default=0)
69
Removed:
cu = FloatField("Cu", default=0)
70
Removed:
mo = FloatField("Mo", default=0)
71
Removed:
si = FloatField("Si", default=0)
72
Removed:
nnh4 = FloatField("NNH4", default=0)
73
Removed:
submit = SubmitField("Add/Update Log")
74
Removed:
75
Removed:
76
Removed:
class AddOrder(FlaskForm): # TODO
77
Removed:
name = StringField("Product name", validators=[InputRequired()])
78
Removed:
code_accounting = StringField("Accounting code", default=0)
79
Removed:
unit_weight = FloatField("Unit weight", default=0)
80
Removed:
price_net = FloatField("Price (net)", default=0)
81
Removed:
price_gross = FloatField("Price (gross)", default=0)
82
Removed:
tax_rate = FloatField("Tax rate", default=0)
83
Removed:
submit = SubmitField("Add/Update Product")
84
Removed:
85
Removed:
86
Removed:
class AddInvoice(FlaskForm):
87
Removed:
name = StringField("Product name", validators=[InputRequired()])
88
Removed:
code_accounting = StringField("Accounting code", default=0)
89
Removed:
unit_weight = FloatField("Unit weight", default=0)
90
Removed:
price_net = FloatField("Price (net)", default=0)
91
Removed:
price_gross = FloatField("Price (gross)", default=0)
92
Removed:
tax_rate = FloatField("Tax rate", default=0)
93
Removed:
submit = SubmitField("Add/Update Product")
app/main.py
@@ -0,0 +1,75 @@
1
Added:
# -*- mode: python; -*-
2
Added:
3
Added:
"""
4
Added:
routes.py module
5
Added:
----------------
6
Added:
7
Added:
This Python module contains the logic supporting:
8
Added:
1. Navigating between website pages
9
Added:
2. Interpreting user requests to the server
10
Added:
3. Dispatching requested content back to the user
11
Added:
12
Added:
Python dependencies:
13
Added:
- flask: provides web application features
14
Added:
- forms: provides secure user form submission
15
Added:
- sqlalchemy: provides communication with database on server.
16
Added:
17
Added:
Personal imports:
18
Added:
These are used to avoid cluttering this file with
19
Added:
placeholder data for posts' content.
20
Added:
"""
21
Added:
22
Added:
23
Added:
from flask import (
24
Added:
Blueprint,
25
Added:
render_template,
26
Added:
send_file,
27
Added:
request,
28
Added:
redirect,
29
Added:
flash,
30
Added:
url_for,
31
Added:
jsonify,
32
Added:
abort,
33
Added:
)
34
Added:
from flask_login import login_required, current_user
35
Added:
36
Added:
37
Added:
# from datetime import datetime
38
Added:
# import inspect
39
Added:
40
Added:
from . import db
41
Added:
42
Added:
main = Blueprint("main", __name__)
43
Added:
44
Added:
from .models import Module, User
45
Added:
46
Added:
modules = [
47
Added:
"auth",
48
Added:
"customers",
49
Added:
"ferti",
50
Added:
"invoices",
51
Added:
"orders",
52
Added:
"products",
53
Added:
]
54
Added:
55
Added:
56
Added:
@main.route("/")
57
Added:
@main.route("/index")
58
Added:
def home():
59
Added:
"""This is our project home page."""
60
Added:
modules = Module.query.all()
61
Added:
return render_template(
62
Added:
"home.html", user=current_user, project="fapg", modules=modules
63
Added:
)
64
Added:
65
Added:
66
Added:
@main.route("/download-database")
67
Added:
def download_database():
68
Added:
return send_file("fapg.db")
69
Added:
70
Added:
71
Added:
@main.route("/modules")
72
Added:
def all_modules():
73
Added:
# If unlogged, should present promotional material for available
74
Added:
# modules.
75
Added:
return render_template("modules-promo.html", modules=modules)
app/model.py
@@ -1,161 +0,0 @@
1
Removed:
# import SQLAlchemy
2
Removed:
from flask_sqlalchemy import SQLAlchemy
3
Removed:
from datetime import datetime
4
Removed:
5
Removed:
db = SQLAlchemy()
6
Removed:
7
Removed:
8
Removed:
class Module(db.Model):
9
Removed:
name = db.Column(
10
Removed:
"Name", db.String(20), unique=True, nullable=False, primary_key=True
11
Removed:
)
12
Removed:
description = db.Column("Description", db.String(50), nullable=False)
13
Removed:
14
Removed:
def __repr__(self):
15
Removed:
return f"<Module {self.name}>"
16
Removed:
17
Removed:
18
Removed:
class Customer(db.Model):
19
Removed:
primary_key = db.Column("CustomerId", db.Integer, nullable=False, primary_key=True)
20
Removed:
name = db.Column("Name", db.String(20), nullable=False)
21
Removed:
name_alternative = db.Column("NameAlternative", db.String(20))
22
Removed:
date_time_created = db.Column("DateTimeCreated", db.String(20), nullable=False)
23
Removed:
date_time_updated = db.Column("DateTimeUpdated", db.String(20), nullable=False)
24
Removed:
code_customer = db.Column("CodeCustomer", db.String(20), unique=True)
25
Removed:
code_accounting = db.Column("CodeAccounting", db.String(20), unique=True)
26
Removed:
address = db.Column("Address", db.String(20))
27
Removed:
postal_code = db.Column("PostalCode", db.Integer)
28
Removed:
city = db.Column("City", db.String(20))
29
Removed:
country = db.Column("Country", db.String(20))
30
Removed:
phone = db.Column("Phone", db.String(20))
31
Removed:
website = db.Column("Website", db.String(20))
32
Removed:
email = db.Column("Email", db.String(20))
33
Removed:
professional_id_1 = db.Column("ProfessionalId1", db.String(20), unique=True)
34
Removed:
professional_id_2 = db.Column("ProfessionalId2", db.String(20), unique=True)
35
Removed:
tax_id = db.Column("TaxId", db.String(20), unique=True)
36
Removed:
payment_terms = db.Column("PaymentTerms", db.String(20), unique=True)
37
Removed:
38
Removed:
def __repr__(self):
39
Removed:
return f"<Customer {self.name}>"
40
Removed:
41
Removed:
42
Removed:
class Product(db.Model):
43
Removed:
primary_key = db.Column("ProductId", db.Integer, primary_key=True)
44
Removed:
name = db.Column("Name", db.String(20), nullable=False, unique=True)
45
Removed:
code_accounting = db.Column("CodeAccounting", db.String(20))
46
Removed:
unit_weight = db.Column("UnitWeight", db.Float)
47
Removed:
price_net = db.Column("PriceNet", db.Float)
48
Removed:
price_gross = db.Column("PriceGross", db.Float)
49
Removed:
tax_rate = db.Column("TaxRate", db.Float)
50
Removed:
date_time_created = db.Column(
51
Removed:
"DateTimeCreated",
52
Removed:
db.String,
53
Removed:
default=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
54
Removed:
)
55
Removed:
date_time_updated = db.Column(
56
Removed:
"DateTimeUpdated",
57
Removed:
db.String,
58
Removed:
default=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
59
Removed:
)
60
Removed:
61
Removed:
def __init__(
62
Removed:
self,
63
Removed:
name,
64
Removed:
code_accounting,
65
Removed:
unit_weight,
66
Removed:
price_net,
67
Removed:
price_gross,
68
Removed:
tax_rate,
69
Removed:
):
70
Removed:
self.name = name
71
Removed:
self.code_accounting = code_accounting
72
Removed:
self.unit_weight = unit_weight
73
Removed:
self.price_net = price_net
74
Removed:
self.price_gross = price_gross
75
Removed:
self.tax_rate = tax_rate
76
Removed:
77
Removed:
def __repr__(self):
78
Removed:
return f"<Product {self.name}>"
79
Removed:
80
Removed:
81
Removed:
class Log(db.Model):
82
Removed:
primary_key = db.Column("LogId", db.Integer, primary_key=True)
83
Removed:
target = db.Column("Target", db.String, default="False")
84
Removed:
nno3 = db.Column("NNO3", db.Float, default=0)
85
Removed:
p = db.Column("P", db.Float, default=0)
86
Removed:
k = db.Column("K", db.Float, default=0)
87
Removed:
ca = db.Column("Ca", db.Float, default=0)
88
Removed:
mg = db.Column("Mg", db.Float, default=0)
89
Removed:
s = db.Column("S", db.Float, default=0)
90
Removed:
na = db.Column("Na", db.Float, default=0)
91
Removed:
cl = db.Column("Cl", db.Float, default=0)
92
Removed:
fe = db.Column("Fe", db.Float, default=0)
93
Removed:
zn = db.Column("Zn", db.Float, default=0)
94
Removed:
b = db.Column("B", db.Float, default=0)
95
Removed:
mn = db.Column("Mn", db.Float, default=0)
96
Removed:
cu = db.Column("Cu", db.Float, default=0)
97
Removed:
mo = db.Column("Mo", db.Float, default=0)
98
Removed:
si = db.Column("Si", db.Float, default=0)
99
Removed:
nnh4 = db.Column("NNH4", db.Float, default=0)
100
Removed:
date_time_created = db.Column(
101
Removed:
"DateTimeCreated",
102
Removed:
db.String,
103
Removed:
default=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
104
Removed:
)
105
Removed:
date_time_updated = db.Column(
106
Removed:
"DateTimeUpdated",
107
Removed:
db.String,
108
Removed:
default=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
109
Removed:
)
110
Removed:
111
Removed:
def __init__(
112
Removed:
self, target, nno3, p, k, ca, mg, s, na, cl, fe, zn, b, mn, cu, mo, si, nnh4
113
Removed:
):
114
Removed:
self.target = target
115
Removed:
self.nno3 = nno3
116
Removed:
self.p = p
117
Removed:
self.k = k
118
Removed:
self.ca = ca
119
Removed:
self.mg = mg
120
Removed:
self.s = s
121
Removed:
self.na = na
122
Removed:
self.cl = cl
123
Removed:
self.fe = fe
124
Removed:
self.zn = zn
125
Removed:
self.b = b
126
Removed:
self.mn = mn
127
Removed:
self.cu = cu
128
Removed:
self.mo = mo
129
Removed:
self.si = si
130
Removed:
self.nnh4 = nnh4
131
Removed:
self.date_time_created = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
132
Removed:
133
Removed:
def __repr__(self):
134
Removed:
return f"<Log from {self.date_time_created} updated {self.date_time_updated}>"
135
Removed:
136
Removed:
137
Removed:
# Everything after here is garbage
138
Removed:
139
Removed:
140
Removed:
class User(db.Model):
141
Removed:
id = db.Column(db.Integer, primary_key=True)
142
Removed:
name_first = db.Column(db.String(20), nullable=False)
143
Removed:
name_last = db.Column(db.String(20), nullable=False)
144
Removed:
email = db.Column(db.String(20), nullable=False)
145
Removed:
phone_mobile = db.Column(db.Integer, nullable=False)
146
Removed:
phone_alternative = db.Column(db.Integer)
147
Removed:
updated = db.Column(db.String)
148
Removed:
149
Removed:
def __repr__(self):
150
Removed:
return f"<User {self.name_first} {self.name_last}>"
151
Removed:
152
Removed:
153
Removed:
class Order(db.Model): # TODO
154
Removed:
id = db.Column(db.Integer, primary_key=True)
155
Removed:
date = db.Column(db.String(20), nullable=False)
156
Removed:
customer = db.Column(db.String(20), nullable=False)
157
Removed:
content = db.Column(db.String(10), nullable=False)
158
Removed:
updated = db.Column(db.String)
159
Removed:
160
Removed:
def __repr__(self):
161
Removed:
return f"<Order {self.name} at {self.updated}>"
app/models.py
@@ -0,0 +1,260 @@
1
Added:
# -*- mode: python; -*-
2
Added:
3
Added:
4
Added:
from flask_sqlalchemy import SQLAlchemy
5
Added:
6
Added:
from datetime import datetime
7
Added:
from flask_login import UserMixin
8
Added:
from . import db
9
Added:
10
Added:
11
Added:
def date_time_now():
12
Added:
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
13
Added:
14
Added:
15
Added:
class User(UserMixin, db.Model):
16
Added:
__tablename__ = "User"
17
Added:
18
Added:
def get_id(self):
19
Added:
return self.primary_key
20
Added:
21
Added:
primary_key = db.Column("UserId", db.Integer, primary_key=True)
22
Added:
username = db.Column("Username", db.String(20), nullable=False)
23
Added:
hashed_password = db.Column("HashedPassword", db.String(100), nullable=False)
24
Added:
name_first = db.Column("NameFirst", db.String(20), nullable=False)
25
Added:
name_last = db.Column("NameLast", db.String(20), nullable=False)
26
Added:
email = db.Column("Email", db.String(20), nullable=False)
27
Added:
phone_mobile = db.Column("PhoneMobile", db.Integer)
28
Added:
phone_alternative = db.Column("PhoneAlternative", db.Integer)
29
Added:
date_time_created = db.Column(
30
Added:
"DateTimeCreated", db.String, server_default=date_time_now()
31
Added:
)
32
Added:
date_time_updated = db.Column(
33
Added:
"DateTimeUpdated", db.String, server_onupdate=date_time_now()
34
Added:
)
35
Added:
36
Added:
def __repr__(self):
37
Added:
return f"<User {self.name_first} {self.name_last}>"
38
Added:
39
Added:
40
Added:
class Module(db.Model):
41
Added:
__tablename__ = "Module"
42
Added:
name = db.Column(
43
Added:
"Name", db.String(20), unique=True, nullable=False, primary_key=True
44
Added:
)
45
Added:
description = db.Column("Description", db.String(50), nullable=False)
46
Added:
47
Added:
def __repr__(self):
48
Added:
return f"<Module {self.name}>"
49
Added:
50
Added:
51
Added:
class Customer(db.Model):
52
Added:
__tablename__ = "Customer"
53
Added:
primary_key = db.Column("CustomerId", db.Integer, nullable=False, primary_key=True)
54
Added:
name = db.Column("Name", db.String(20), nullable=False)
55
Added:
name_alternative = db.Column("NameAlternative", db.String(20))
56
Added:
code_customer = db.Column("CodeCustomer", db.String(20), unique=True)
57
Added:
code_accounting = db.Column("CodeAccounting", db.String(20), unique=True)
58
Added:
address = db.Column("Address", db.String(20))
59
Added:
postal_code = db.Column("PostalCode", db.Integer)
60
Added:
city = db.Column("City", db.String(20))
61
Added:
country = db.Column("Country", db.String(20))
62
Added:
phone = db.Column("Phone", db.String(20))
63
Added:
website = db.Column("Website", db.String(20))
64
Added:
email = db.Column("Email", db.String(20))
65
Added:
professional_id_1 = db.Column("ProfessionalId1", db.String(20), unique=True)
66
Added:
professional_id_2 = db.Column("ProfessionalId2", db.String(20), unique=True)
67
Added:
tax_id = db.Column("TaxId", db.String(20), unique=True)
68
Added:
payment_terms = db.Column("PaymentTerms", db.String(20), unique=True)
69
Added:
date_time_created = db.Column("DateTimeCreated", db.String(20), nullable=False)
70
Added:
date_time_updated = db.Column("DateTimeUpdated", db.String(20), nullable=False)
71
Added:
invoices = db.relationship("Invoice", back_populates="customer")
72
Added:
73
Added:
def __init__(
74
Added:
self,
75
Added:
name,
76
Added:
name_alternative,
77
Added:
code_customer,
78
Added:
code_accounting,
79
Added:
address,
80
Added:
postal_code,
81
Added:
city,
82
Added:
country,
83
Added:
phone,
84
Added:
website,
85
Added:
email,
86
Added:
professional_id_1,
87
Added:
professional_id_2,
88
Added:
tax_id,
89
Added:
payment_terms,
90
Added:
):
91
Added:
self.name = name
92
Added:
self.name_alternative = name_alternative
93
Added:
self.code_customer = code_customer
94
Added:
self.code_accounting = code_accounting
95
Added:
self.address = address
96
Added:
self.postal_code = postal_code
97
Added:
self.city = city
98
Added:
self.country = country
99
Added:
self.phone = phone
100
Added:
self.website = website
101
Added:
self.email = email
102
Added:
self.professional_id_1 = professional_id_1
103
Added:
self.professional_id_2 = professional_id_2
104
Added:
self.tax_id = tax_id
105
Added:
self.payment_terms = payment_terms
106
Added:
107
Added:
def __repr__(self):
108
Added:
return f"<Customer {self.name}>"
109
Added:
110
Added:
111
Added:
class Invoice(db.Model):
112
Added:
__tablename__ = "Invoice"
113
Added:
primary_key = db.Column("InvoiceId", db.Integer, primary_key=True)
114
Added:
invoice_id_alt = db.Column("InvoiceIdAlt", db.String)
115
Added:
customer_reference = db.Column("CustomerReference", db.String)
116
Added:
date_billed = db.Column("DateBilled", db.String)
117
Added:
date_due = db.Column("DateDue", db.String)
118
Added:
amount_net = db.Column("AmountNet", db.String)
119
Added:
amount_gross = db.Column("AmountGross", db.String)
120
Added:
amount_tax = db.Column("AmountTax", db.String)
121
Added:
date_time_created = db.Column(
122
Added:
"DateTimeCreated", db.String, default=date_time_now()
123
Added:
)
124
Added:
customer_id = db.Column(
125
Added:
"CustomerId", db.Integer, db.ForeignKey("Customer.CustomerId")
126
Added:
)
127
Added:
customer = db.relationship("Customer", back_populates="invoices")
128
Added:
129
Added:
def __init__(
130
Added:
self,
131
Added:
invoice_id_alt,
132
Added:
customer_id,
133
Added:
customer_reference,
134
Added:
date_billed,
135
Added:
date_due,
136
Added:
amount_net,
137
Added:
amount_gross,
138
Added:
amount_tax,
139
Added:
):
140
Added:
self.invoice_id_alt = invoice_id_alt
141
Added:
self.customer_id = customer_id
142
Added:
self.customer_reference = customer_reference
143
Added:
self.date_billed = date_billed
144
Added:
self.date_due = date_due
145
Added:
self.amount_net = amount_net
146
Added:
self.amount_gross = amount_gross
147
Added:
self.amount_tax = amount_tax
148
Added:
149
Added:
def __repr__(self):
150
Added:
return f"<Invoice for {self.customer.name} at {self.updated}>"
151
Added:
152
Added:
153
Added:
class Product(db.Model):
154
Added:
__tablename__ = "Product"
155
Added:
primary_key = db.Column("ProductId", db.Integer, primary_key=True)
156
Added:
name = db.Column("Name", db.String(20), nullable=False, unique=True)
157
Added:
code_accounting = db.Column("CodeAccounting", db.String(20))
158
Added:
unit_weight = db.Column("UnitWeight", db.Float)
159
Added:
price_net = db.Column("PriceNet", db.Float)
160
Added:
price_gross = db.Column("PriceGross", db.Float)
161
Added:
tax_rate = db.Column("TaxRate", db.Float)
162
Added:
date_time_created = db.Column(
163
Added:
"DateTimeCreated", db.String, server_default=date_time_now()
164
Added:
)
165
Added:
date_time_updated = db.Column(
166
Added:
"DateTimeUpdated", db.String, server_onupdate=date_time_now()
167
Added:
)
168
Added:
169
Added:
def __init__(
170
Added:
self,
171
Added:
name,
172
Added:
code_accounting,
173
Added:
unit_weight,
174
Added:
price_net,
175
Added:
price_gross,
176
Added:
tax_rate,
177
Added:
):
178
Added:
self.name = name
179
Added:
self.code_accounting = code_accounting
180
Added:
self.unit_weight = unit_weight
181
Added:
self.price_net = price_net
182
Added:
self.price_gross = price_gross
183
Added:
self.tax_rate = tax_rate
184
Added:
185
Added:
def __repr__(self):
186
Added:
return f"<Product {self.name}>"
187
Added:
188
Added:
189
Added:
class FertiLog(db.Model):
190
Added:
__tablename__ = "Fertilog"
191
Added:
primary_key = db.Column("FertiLogId", db.Integer, primary_key=True)
192
Added:
nno3 = db.Column("NNO3", db.Float, default=0)
193
Added:
p = db.Column("P", db.Float, default=0)
194
Added:
k = db.Column("K", db.Float, default=0)
195
Added:
ca = db.Column("Ca", db.Float, default=0)
196
Added:
mg = db.Column("Mg", db.Float, default=0)
197
Added:
s = db.Column("S", db.Float, default=0)
198
Added:
na = db.Column("Na", db.Float, default=0)
199
Added:
cl = db.Column("Cl", db.Float, default=0)
200
Added:
fe = db.Column("Fe", db.Float, default=0)
201
Added:
zn = db.Column("Zn", db.Float, default=0)
202
Added:
b = db.Column("B", db.Float, default=0)
203
Added:
mn = db.Column("Mn", db.Float, default=0)
204
Added:
cu = db.Column("Cu", db.Float, default=0)
205
Added:
mo = db.Column("Mo", db.Float, default=0)
206
Added:
si = db.Column("Si", db.Float, default=0)
207
Added:
nnh4 = db.Column("NNH4", db.Float, default=0)
208
Added:
date_time_created = db.Column(
209
Added:
"DateTimeCreated", db.String, server_default=date_time_now()
210
Added:
)
211
Added:
date_time_updated = db.Column(
212
Added:
"DateTimeUpdated", db.String, server_onupdate=date_time_now()
213
Added:
)
214
Added:
215
Added:
def __init__(self, nno3, p, k, ca, mg, s, na, cl, fe, zn, b, mn, cu, mo, si, nnh4):
216
Added:
self.nno3 = nno3
217
Added:
self.p = p
218
Added:
self.k = k
219
Added:
self.ca = ca
220
Added:
self.mg = mg
221
Added:
self.s = s
222
Added:
self.na = na
223
Added:
self.cl = cl
224
Added:
self.fe = fe
225
Added:
self.zn = zn
226
Added:
self.b = b
227
Added:
self.mn = mn
228
Added:
self.cu = cu
229
Added:
self.mo = mo
230
Added:
self.si = si
231
Added:
self.nnh4 = nnh4
232
Added:
self.date_time_created = date_time_now
233
Added:
234
Added:
def __repr__(self):
235
Added:
return f"<Log ID {self.primary_key}>"
236
Added:
237
Added:
238
Added:
class FertiTarget(FertiLog):
239
Added:
__tablename__ = "Fertitarget"
240
Added:
primary_key = db.Column("FertiTargetId", db.Integer, primary_key=True)
241
Added:
targeted_log = db.Column(
242
Added:
"FertiLogId", db.Integer, db.ForeignKey("Fertilog.FertiLogId")
243
Added:
)
244
Added:
245
Added:
def __repr__(self):
246
Added:
return f"<Target ID {self.primary_key}>"
247
Added:
248
Added:
249
Added:
# Everything after here is garbage
250
Added:
251
Added:
252
Added:
class Order(db.Model): # TODO
253
Added:
id = db.Column(db.Integer, primary_key=True)
254
Added:
date = db.Column(db.String(20), nullable=False)
255
Added:
customer = db.Column(db.String(20), nullable=False)
256
Added:
content = db.Column(db.String(10), nullable=False)
257
Added:
updated = db.Column(db.String)
258
Added:
259
Added:
def __repr__(self):
260
Added:
return f"<Order {self.name} at {self.updated}>"
app/modules/__init__.py
@@ -0,0 +1,8 @@
1
Added:
# -*- mode: python; -*-
2
Added:
3
Added:
from .common import common
4
Added:
from .auth.routes import auth
5
Added:
from .products.routes import products
6
Added:
from .customers.routes import customers
7
Added:
from .ferti.routes import ferti
8
Added:
from .invoices.routes import invoices
app/modules/auth/forms.py
@@ -0,0 +1,29 @@
1
Added:
from flask_wtf import FlaskForm
2
Added:
from wtforms import (
3
Added:
SubmitField,
4
Added:
SelectField,
5
Added:
HiddenField,
6
Added:
StringField,
7
Added:
PasswordField,
8
Added:
IntegerField,
9
Added:
FloatField,
10
Added:
BooleanField,
11
Added:
DateTimeField,
12
Added:
)
13
Added:
from wtforms.validators import InputRequired, Length, NumberRange
14
Added:
15
Added:
16
Added:
class LoginForm(FlaskForm):
17
Added:
username = StringField("Username", validators=[InputRequired()])
18
Added:
password = PasswordField("Password", validators=[InputRequired()])
19
Added:
remember = BooleanField("Remember")
20
Added:
submit = SubmitField("Login")
21
Added:
22
Added:
23
Added:
class RegisterForm(LoginForm):
24
Added:
name_first = StringField("First name")
25
Added:
name_last = StringField("Last name")
26
Added:
email = StringField("E-mail address")
27
Added:
phone_mobile = StringField("Phone number (mobile)")
28
Added:
phone_alternative = StringField("Phone number (alternative)")
29
Added:
submit = SubmitField("Register")
app/modules/auth/routes.py
@@ -0,0 +1,73 @@
1
Added:
# -*- mode: python; -*-
2
Added:
3
Added:
from flask import Blueprint, render_template, redirect, url_for, request, flash
4
Added:
from flask_login import login_user, login_required, logout_user
5
Added:
from werkzeug.security import generate_password_hash, check_password_hash
6
Added:
7
Added:
from ... import db
8
Added:
from ...models import User
9
Added:
from .forms import LoginForm, RegisterForm
10
Added:
11
Added:
12
Added:
auth = Blueprint("auth", __name__)
13
Added:
14
Added:
15
Added:
@auth.route("/login", methods=["GET", "POST"])
16
Added:
def login():
17
Added:
form = LoginForm()
18
Added:
if form.validate_on_submit():
19
Added:
req = request.form
20
Added:
# print(req["remember"])
21
Added:
remember = True if req.get("remember") else False
22
Added:
user = User.query.filter_by(username=req["username"]).first()
23
Added:
if user is None:
24
Added:
flash("User not registered.", "error")
25
Added:
return redirect(url_for("auth.register"))
26
Added:
if check_password_hash(user.hashed_password, req["password"]) is False:
27
Added:
flash("Wrong password.", "error")
28
Added:
return redirect(url_for("auth.login"))
29
Added:
login_user(user, remember=remember)
30
Added:
flash(
31
Added:
f"Logged in as user {user.username} successfully. "
32
Added:
+ f"You will {'not' if remember is False else ''} be remembered next time!"
33
Added:
)
34
Added:
return redirect(url_for("main.home"))
35
Added:
return render_template("modules/login.html", form=form)
36
Added:
37
Added:
38
Added:
@auth.route("/register", methods=["GET", "POST"])
39
Added:
def register():
40
Added:
form = RegisterForm()
41
Added:
if form.validate_on_submit():
42
Added:
req = request.form
43
Added:
user_already_exists = User.query.filter_by(
44
Added:
name_first=req["name_first"],
45
Added:
name_last=req["name_last"],
46
Added:
).first()
47
Added:
if user_already_exists:
48
Added:
flash(
49
Added:
f"User {req['name_first']} {req['name_last']} already exists.", "error"
50
Added:
)
51
Added:
return redirect(url_for("auth.login"))
52
Added:
new_user = User(
53
Added:
username=req["username"],
54
Added:
hashed_password=generate_password_hash(req["password"], method="sha256"),
55
Added:
name_first=req["name_first"],
56
Added:
name_last=req["name_last"],
57
Added:
email=req["email"],
58
Added:
phone_mobile=req["phone_mobile"],
59
Added:
phone_alternative=req["phone_alternative"],
60
Added:
)
61
Added:
db.session.add(new_user)
62
Added:
db.session.commit()
63
Added:
flash(f"Created user {req['name_first']} {req['name_last']} successfully.")
64
Added:
return redirect(url_for("main.home"))
65
Added:
return render_template("register.html", form=form)
66
Added:
67
Added:
68
Added:
@auth.route("/logout")
69
Added:
@login_required
70
Added:
def logout():
71
Added:
logout_user()
72
Added:
flash(f"Logged out successfully.")
73
Added:
return redirect(url_for("main.home"))
app/modules/common.py
@@ -0,0 +1,75 @@
1
Added:
# -*- mode: python; -*-
2
Added:
3
Added:
import inspect
4
Added:
from flask import Blueprint, request, render_template, redirect, flash, jsonify
5
Added:
from flask_login import login_required, current_user
6
Added:
7
Added:
from .. import db
8
Added:
from .. import models
9
Added:
from . import forms
10
Added:
11
Added:
from wtforms import SelectField
12
Added:
13
Added:
14
Added:
common = Blueprint("common", __name__)
15
Added:
16
Added:
17
Added:
@common.route("/modules/<module>/add/<table>", methods=["GET", "POST"])
18
Added:
@login_required
19
Added:
def add_item(module, table):
20
Added:
"""Add new item to table accessible via module."""
21
Added:
# print("db table keys are", db.metadata.tables.keys())
22
Added:
if table not in db.metadata.tables.keys():
23
Added:
return render_template("errors/item-not-found.html", table=table)
24
Added:
form = getattr(forms, f"Add{table}")()
25
Added:
if form.validate_on_submit():
26
Added:
model = getattr(models, table)
27
Added:
table_fields = inspect.signature(model).parameters
28
Added:
form_values = {key: request.form[key] for key in table_fields}
29
Added:
print(f"Ready to insert {form_values}")
30
Added:
record = model(**form_values)
31
Added:
db.session.add(record)
32
Added:
db.session.commit()
33
Added:
item_pk = model.query.order_by(model.primary_key.desc()).first().primary_key
34
Added:
flash(f"Successfully added item #{item_pk} to {table} table.", "info")
35
Added:
return redirect(f"/modules/{module}")
36
Added:
return render_template("modules/add-item.html", table=table, form=form)
37
Added:
38
Added:
39
Added:
@common.route("/modules/<module>/edit/<table>/<int:pk>", methods=["GET", "POST"])
40
Added:
@login_required
41
Added:
def edit_item(module, table, pk):
42
Added:
"""Edit existing item in table accessible via module."""
43
Added:
if table not in db.metadata.tables.keys():
44
Added:
return render_template("errors/item-not-found.html", table=table)
45
Added:
model = getattr(models, table)
46
Added:
item = model.query.filter_by(primary_key=pk).first()
47
Added:
# Instantiate form with selected item's field values.
48
Added:
form = getattr(forms, f"Add{table}")(**item.__dict__)
49
Added:
if form.validate_on_submit():
50
Added:
table_fields = inspect.signature(model).parameters
51
Added:
form_values = {key: request.form[key] for key in table_fields}
52
Added:
print(f"Ready to update {form_values}")
53
Added:
model.query.filter_by(primary_key=pk).update(form_values)
54
Added:
db.session.commit()
55
Added:
flash(f"Successfully edited item #{pk} in {table} table.", "info")
56
Added:
return redirect(f"/modules/{module}")
57
Added:
return render_template("modules/edit-item.html", table=table, pk=pk, form=form)
58
Added:
59
Added:
60
Added:
@common.route("/modules/<module>/delete/<table>/<int:pk>", methods=["POST"])
61
Added:
@login_required
62
Added:
def delete_item(module, table, pk):
63
Added:
"""Delete item with Primary Key = pk from table in module."""
64
Added:
model = getattr(models, table)
65
Added:
record = model.query.filter_by(primary_key=pk).first()
66
Added:
db.session.delete(record)
67
Added:
db.session.commit()
68
Added:
flash(f"Successfully removed item #{pk} from {table} table.", "info")
69
Added:
return redirect(f"/modules/{module}")
70
Added:
71
Added:
72
Added:
@common.route("/modules/settings")
73
Added:
@login_required
74
Added:
def settings():
75
Added:
return render_template("modules/settings.html", user=current_user)
app/modules/customers/forms.py
@@ -0,0 +1,36 @@
1
Added:
# -*- mode: python; -*-
2
Added:
3
Added:
4
Added:
from flask_wtf import FlaskForm
5
Added:
from wtforms import (
6
Added:
SubmitField,
7
Added:
SelectField,
8
Added:
HiddenField,
9
Added:
StringField,
10
Added:
PasswordField,
11
Added:
IntegerField,
12
Added:
FloatField,
13
Added:
BooleanField,
14
Added:
DateTimeField,
15
Added:
)
16
Added:
from wtforms.validators import InputRequired, Length, NumberRange
17
Added:
18
Added:
19
Added:
class AddCustomer(FlaskForm):
20
Added:
name = StringField("Customer name", validators=[InputRequired()])
21
Added:
name_alternative = StringField("Alternative name")
22
Added:
# date_time_created = DateTimeField("Creation date")
23
Added:
code_customer = StringField("Customer code")
24
Added:
code_accounting = StringField("Accounting code")
25
Added:
address = StringField("Address")
26
Added:
postal_code = StringField("Postal Code")
27
Added:
city = StringField("City")
28
Added:
country = StringField("Country")
29
Added:
phone = StringField("Phone")
30
Added:
website = StringField("Website")
31
Added:
email = StringField("E-mail")
32
Added:
professional_id_1 = StringField("Professional ID 1")
33
Added:
professional_id_2 = StringField("Professional ID 2")
34
Added:
tax_id = StringField("Tax ID")
35
Added:
payment_terms = StringField("Payment Terms", default="Tu vas payer sale chien!")
36
Added:
submit = SubmitField("Add/Update Product")
app/modules/customers/routes.py
@@ -0,0 +1,38 @@
1
Added:
# -*- mode: python; -*-
2
Added:
3
Added:
4
Added:
from flask import (
5
Added:
Blueprint,
6
Added:
render_template,
7
Added:
send_file,
8
Added:
request,
9
Added:
redirect,
10
Added:
flash,
11
Added:
url_for,
12
Added:
jsonify,
13
Added:
abort,
14
Added:
)
15
Added:
from flask_login import login_required, current_user
16
Added:
import inspect
17
Added:
18
Added:
19
Added:
from ... import db
20
Added:
from ...models import *
21
Added:
from .forms import *
22
Added:
23
Added:
customers = Blueprint("customers", __name__)
24
Added:
25
Added:
26
Added:
@customers.route("/modules/customers")
27
Added:
@login_required
28
Added:
def view():
29
Added:
modules = Module.query.all()
30
Added:
cust = Customer.query.order_by(Customer.primary_key.desc())
31
Added:
module = "customers"
32
Added:
flash(f"Successfully accessed module {module}.", "info")
33
Added:
flash(f"Still fighting against styling in {module}.", "error")
34
Added:
return render_template(
35
Added:
f"modules/{module}.html",
36
Added:
modules=modules,
37
Added:
customers=cust,
38
Added:
)
app/modules/ferti/forms.py
@@ -0,0 +1,47 @@
1
Added:
from flask_wtf import FlaskForm
2
Added:
from wtforms import (
3
Added:
SubmitField,
4
Added:
SelectField,
5
Added:
HiddenField,
6
Added:
StringField,
7
Added:
PasswordField,
8
Added:
IntegerField,
9
Added:
FloatField,
10
Added:
BooleanField,
11
Added:
DateTimeField,
12
Added:
)
13
Added:
from wtforms.validators import InputRequired, Length, NumberRange
14
Added:
15
Added:
16
Added:
class AddFertiLog(FlaskForm):
17
Added:
target = SelectField(
18
Added:
"Type",
19
Added:
choices=[("False", "Log"), ("True", "Target")],
20
Added:
validators=[InputRequired()],
21
Added:
)
22
Added:
nno3 = FloatField("NNO3", default=0)
23
Added:
p = FloatField("P", default=0)
24
Added:
k = FloatField("K", default=0)
25
Added:
ca = FloatField("Ca", default=0)
26
Added:
mg = FloatField("Mg", default=0)
27
Added:
s = FloatField("S", default=0)
28
Added:
na = FloatField("Na", default=0)
29
Added:
cl = FloatField("Cl", default=0)
30
Added:
fe = FloatField("Fe", default=0)
31
Added:
zn = FloatField("Zn", default=0)
32
Added:
b = FloatField("B", default=0)
33
Added:
mn = FloatField("Mn", default=0)
34
Added:
cu = FloatField("Cu", default=0)
35
Added:
mo = FloatField("Mo", default=0)
36
Added:
si = FloatField("Si", default=0)
37
Added:
nnh4 = FloatField("NNH4", default=0)
38
Added:
submit = SubmitField("Add/Update Log")
39
Added:
40
Added:
41
Added:
class AddFertiTarget(AddFertiLog):
42
Added:
targeted_log = SelectField(
43
Added:
"Log to target",
44
Added:
choices=[("value1", "Last"), ("value2", "Named")],
45
Added:
validators=[InputRequired()],
46
Added:
)
47
Added:
submit = SubmitField("Add/Update Log")
app/modules/ferti/routes.py
@@ -0,0 +1,46 @@
1
Added:
# -*- mode: python; -*-
2
Added:
3
Added:
4
Added:
from flask import (
5
Added:
Blueprint,
6
Added:
render_template,
7
Added:
send_file,
8
Added:
request,
9
Added:
redirect,
10
Added:
flash,
11
Added:
url_for,
12
Added:
jsonify,
13
Added:
abort,
14
Added:
)
15
Added:
from flask_login import login_required, current_user
16
Added:
17
Added:
18
Added:
# from datetime import datetime
19
Added:
import inspect
20
Added:
21
Added:
22
Added:
23
Added:
24
Added:
from ... import db
25
Added:
from ...models import *
26
Added:
from .forms import *
27
Added:
28
Added:
29
Added:
ferti = Blueprint("ferti", __name__)
30
Added:
31
Added:
32
Added:
33
Added:
@ferti.route("/modules/ferti")
34
Added:
@login_required
35
Added:
def view():
36
Added:
modules = Module.query.all()
37
Added:
logs = Fertilog.query.order_by(Fertilog.primary_key.desc()).all()
38
Added:
targets = Fertitarget.query.all()
39
Added:
module = "ferti"
40
Added:
flash(f"Latest target is {targets}.", "info")
41
Added:
flash(f"Still fighting against styling in {module}.", "error")
42
Added:
return render_template(
43
Added:
f"modules/{module}.html",
44
Added:
modules=modules,
45
Added:
logs=logs,
46
Added:
)
app/modules/forms.py
@@ -0,0 +1,6 @@
1
Added:
# -*- mode: python; -*-
2
Added:
3
Added:
from .customers.forms import AddCustomer
4
Added:
from .ferti.forms import AddFertiLog, AddFertiTarget
5
Added:
from .invoices.forms import AddInvoice
6
Added:
from .products.forms import AddProduct
app/modules/forms.py.bkp
@@ -0,0 +1,118 @@
1
Added:
# -*- mode: python; -*-
2
Added:
3
Added:
from flask_wtf import FlaskForm
4
Added:
from wtforms import (
5
Added:
SubmitField,
6
Added:
SelectField,
7
Added:
HiddenField,
8
Added:
StringField,
9
Added:
PasswordField,
10
Added:
IntegerField,
11
Added:
FloatField,
12
Added:
BooleanField,
13
Added:
DateTimeField,
14
Added:
)
15
Added:
from wtforms.validators import InputRequired, Length, NumberRange
16
Added:
17
Added:
18
Added:
class LoginForm(FlaskForm):
19
Added:
username = StringField("Username", validators=[InputRequired()])
20
Added:
password = PasswordField("Password", validators=[InputRequired()])
21
Added:
remember = BooleanField("Remember")
22
Added:
submit = SubmitField("Login")
23
Added:
24
Added:
25
Added:
class RegisterForm(LoginForm):
26
Added:
name_first = StringField("First name")
27
Added:
name_last = StringField("Last name")
28
Added:
email = StringField("E-mail address")
29
Added:
phone_mobile = StringField("Phone number (mobile)")
30
Added:
phone_alternative = StringField("Phone number (alternative)")
31
Added:
submit = SubmitField("Register")
32
Added:
33
Added:
34
Added:
class AddCustomer(FlaskForm):
35
Added:
name = StringField("Customer name", validators=[InputRequired()])
36
Added:
name_alternative = StringField("Alternative name")
37
Added:
# date_time_created = DateTimeField("Creation date")
38
Added:
code_customer = StringField("Customer code")
39
Added:
code_accounting = StringField("Accounting code")
40
Added:
address = StringField("Address")
41
Added:
postal_code = StringField("Postal Code")
42
Added:
city = StringField("City")
43
Added:
country = StringField("Country")
44
Added:
phone = StringField("Phone")
45
Added:
website = StringField("Website")
46
Added:
email = StringField("E-mail")
47
Added:
professional_id_1 = StringField("Professional ID 1")
48
Added:
professional_id_2 = StringField("Professional ID 2")
49
Added:
tax_id = StringField("Tax ID")
50
Added:
payment_terms = StringField("Payment Terms", default="Tu vas payer sale chien!")
51
Added:
submit = SubmitField("Add/Update Product")
52
Added:
53
Added:
54
Added:
class AddProduct(FlaskForm):
55
Added:
name = StringField("Product name", validators=[InputRequired()])
56
Added:
code_accounting = StringField("Accounting code", default=0)
57
Added:
unit_weight = FloatField("Unit weight", default=0)
58
Added:
price_net = FloatField("Price (net)", default=0)
59
Added:
price_gross = FloatField("Price (gross)", default=0)
60
Added:
tax_rate = FloatField("Tax rate", default=0)
61
Added:
submit = SubmitField("Add/Update Product")
62
Added:
63
Added:
64
Added:
class AddFertilog(FlaskForm):
65
Added:
target = SelectField(
66
Added:
"Type",
67
Added:
choices=[("False", "Log"), ("True", "Target")],
68
Added:
validators=[InputRequired()],
69
Added:
)
70
Added:
nno3 = FloatField("NNO3", default=0)
71
Added:
p = FloatField("P", default=0)
72
Added:
k = FloatField("K", default=0)
73
Added:
ca = FloatField("Ca", default=0)
74
Added:
mg = FloatField("Mg", default=0)
75
Added:
s = FloatField("S", default=0)
76
Added:
na = FloatField("Na", default=0)
77
Added:
cl = FloatField("Cl", default=0)
78
Added:
fe = FloatField("Fe", default=0)
79
Added:
zn = FloatField("Zn", default=0)
80
Added:
b = FloatField("B", default=0)
81
Added:
mn = FloatField("Mn", default=0)
82
Added:
cu = FloatField("Cu", default=0)
83
Added:
mo = FloatField("Mo", default=0)
84
Added:
si = FloatField("Si", default=0)
85
Added:
nnh4 = FloatField("NNH4", default=0)
86
Added:
submit = SubmitField("Add/Update Log")
87
Added:
88
Added:
89
Added:
class AddFertitarget(AddFertilog):
90
Added:
targeted_log = SelectField(
91
Added:
"Log to target",
92
Added:
choices=[("value1", "Last"), ("value2", "Named")],
93
Added:
validators=[InputRequired()],
94
Added:
)
95
Added:
submit = SubmitField("Add/Update Log")
96
Added:
97
Added:
98
Added:
99
Added:
class AddOrder(FlaskForm): # TODO
100
Added:
name = StringField("Product name", validators=[InputRequired()])
101
Added:
code_accounting = StringField("Accounting code", default=0)
102
Added:
unit_weight = FloatField("Unit weight", default=0)
103
Added:
price_net = FloatField("Price (net)", default=0)
104
Added:
price_gross = FloatField("Price (gross)", default=0)
105
Added:
tax_rate = FloatField("Tax rate", default=0)
106
Added:
submit = SubmitField("Add/Update Product")
107
Added:
108
Added:
109
Added:
class AddInvoice(FlaskForm):
110
Added:
invoice_id_alt = StringField("Alternative invoice ID")
111
Added:
customer_id = StringField("Customer ID")
112
Added:
customer_reference = StringField("Customer reference")
113
Added:
date_billed = StringField("Date billed")
114
Added:
date_due = StringField("Date due")
115
Added:
amount_net = FloatField("Amount without tax", default=0)
116
Added:
amount_gross = FloatField("Amount with tax", default=0)
117
Added:
amount_tax = FloatField("Amount of tax", default=0)
118
Added:
submit = SubmitField("Add new Invoice")
app/modules/invoices/forms.py
@@ -0,0 +1,33 @@
1
Added:
from flask_wtf import FlaskForm
2
Added:
from wtforms import (
3
Added:
SubmitField,
4
Added:
SelectField,
5
Added:
HiddenField,
6
Added:
StringField,
7
Added:
PasswordField,
8
Added:
IntegerField,
9
Added:
FloatField,
10
Added:
BooleanField,
11
Added:
DateTimeField,
12
Added:
)
13
Added:
from wtforms.validators import InputRequired, Length, NumberRange
14
Added:
15
Added:
from ...models import Customer
16
Added:
17
Added:
18
Added:
class AddInvoice(FlaskForm):
19
Added:
customer_id = SelectField("Customer", choices=[])
20
Added:
invoice_id_alt = StringField("Alternative invoice ID")
21
Added:
customer_reference = StringField("Customer reference")
22
Added:
date_billed = StringField("Date billed")
23
Added:
date_due = StringField("Date due")
24
Added:
amount_net = FloatField("Amount without tax", default=0)
25
Added:
amount_gross = FloatField("Amount with tax", default=0)
26
Added:
amount_tax = FloatField("Amount of tax", default=0)
27
Added:
submit = SubmitField("Add new Invoice")
28
Added:
29
Added:
def __init__(self, **kwargs):
30
Added:
super().__init__()
31
Added:
self.customer_id.choices = [
32
Added:
(cus.primary_key, cus.name) for cus in Customer.query.all()
33
Added:
]
app/modules/invoices/routes.py
@@ -0,0 +1,47 @@
1
Added:
# -*- mode: python; -*-
2
Added:
3
Added:
4
Added:
from flask import (
5
Added:
Blueprint,
6
Added:
render_template,
7
Added:
send_file,
8
Added:
request,
9
Added:
redirect,
10
Added:
flash,
11
Added:
url_for,
12
Added:
jsonify,
13
Added:
abort,
14
Added:
)
15
Added:
from flask_login import login_required, current_user
16
Added:
17
Added:
18
Added:
from ... import db
19
Added:
from ...models import *
20
Added:
from .forms import *
21
Added:
22
Added:
23
Added:
invoices = Blueprint("invoices", __name__)
24
Added:
25
Added:
26
Added:
27
Added:
@invoices.route("/modules/invoices")
28
Added:
@login_required
29
Added:
def view():
30
Added:
modules = Module.query.all()
31
Added:
page = request.args.get('page', 1, type=int)
32
Added:
invoices = Invoice.query.order_by(Invoice.primary_key.desc()).paginate(page=page, per_page=5)
33
Added:
module = "invoices"
34
Added:
flash(f"Successfully accessed module {module}.", "info")
35
Added:
flash(f"Still fighting against styling in {module}.", "error")
36
Added:
return render_template(
37
Added:
f"modules/{module}.html",
38
Added:
modules=modules,
39
Added:
invoices=invoices,
40
Added:
)
41
Added:
42
Added:
43
Added:
@invoices.route("/modules/invoices/preview/<int:pk>")
44
Added:
@login_required
45
Added:
def preview(pk):
46
Added:
invoice = Invoice.query.filter_by(primary_key=pk).first()
47
Added:
return render_template("modules/invoice-preview.html", invoice=invoice)
app/modules/modules.py.bkp
@@ -0,0 +1,136 @@
1
Added:
# -*- mode: python; -*-
2
Added:
3
Added:
4
Added:
from flask import (
5
Added:
Blueprint,
6
Added:
render_template,
7
Added:
send_file,
8
Added:
request,
9
Added:
redirect,
10
Added:
flash,
11
Added:
url_for,
12
Added:
jsonify,
13
Added:
abort,
14
Added:
)
15
Added:
from flask_login import login_required, current_user
16
Added:
17
Added:
18
Added:
# from datetime import datetime
19
Added:
import inspect
20
Added:
21
Added:
from . import db
22
Added:
23
Added:
modules = Blueprint("modules", __name__)
24
Added:
25
Added:
26
Added:
from .models import *
27
Added:
from .forms import *
28
Added:
29
Added:
30
Added:
@modules.route("/modules")
31
Added:
def modules_home():
32
Added:
return redirect("/index")
33
Added:
34
Added:
35
Added:
@modules.route("/add-<item>", methods=["GET", "POST"])
36
Added:
@login_required
37
Added:
def add_item(item):
38
Added:
"""Add a new item to a corresponding database table.
39
Added:
40
Added:
The item must match a database model class name (table). Then, we
41
Added:
match the model class attributes with request.form values.
42
Added:
43
Added:
"""
44
Added:
print("db table keys are", db.metadata.tables.keys())
45
Added:
if item.capitalize() not in db.metadata.tables.keys():
46
Added:
return render_template("errors/item-not-found.html", item=item)
47
Added:
if request.method == "GET":
48
Added:
form = globals()[f"Add{item.capitalize()}"]()
49
Added:
return render_template("add-item.html", item=item, form=form)
50
Added:
if request.method == "POST":
51
Added:
table = globals()[item.capitalize()]
52
Added:
table_fields = inspect.signature(table).parameters
53
Added:
form_values = {key: request.form[key] for key in table_fields}
54
Added:
print(f"Ready to insert {form_values}")
55
Added:
record = table(**form_values)
56
Added:
db.session.add(record)
57
Added:
db.session.commit()
58
Added:
item_pk = table.query.order_by(table.primary_key.desc()).first().primary_key
59
Added:
flash(
60
Added:
f"Successfully added item #{item_pk} to {table.__table__.name.capitalize()} table.",
61
Added:
"info",
62
Added:
)
63
Added:
return redirect("/modules")
64
Added:
65
Added:
66
Added:
@modules.route("/delete-<pk>-from-<table>", methods=["POST"])
67
Added:
@login_required
68
Added:
def delete_item(pk, table):
69
Added:
"""Delete item with Primary Key = pk from corresponding database
70
Added:
table.
71
Added:
"""
72
Added:
model = globals()[table]
73
Added:
record = model.query.filter_by(primary_key=pk).first()
74
Added:
db.session.delete(record)
75
Added:
db.session.commit()
76
Added:
flash(f"Successfully removed item #{pk} from {table} table.", "info")
77
Added:
return redirect("/modules")
78
Added:
79
Added:
80
Added:
@modules.route("/modules/customers")
81
Added:
@login_required
82
Added:
def customers():
83
Added:
modules = Module.query.all()
84
Added:
customers = Customer.query.order_by(Customer.primary_key.desc())
85
Added:
module = "customers"
86
Added:
flash(f"Successfully accessed module {module}.", "info")
87
Added:
flash(f"Still fighting against styling in {module}.", "error")
88
Added:
return render_template(
89
Added:
f"modules/{module}.html",
90
Added:
modules=modules,
91
Added:
customers=customers,
92
Added:
)
93
Added:
94
Added:
95
Added:
@modules.route("/modules/products")
96
Added:
@login_required
97
Added:
def products():
98
Added:
modules = Module.query.all()
99
Added:
products = Product.query.order_by(Product.primary_key.desc())
100
Added:
module = "products"
101
Added:
flash(f"Successfully accessed module {module}.", "info")
102
Added:
flash(f"Still fighting against styling in {module}.", "error")
103
Added:
return render_template(
104
Added:
f"modules/{module}.html",
105
Added:
modules=modules,
106
Added:
products=products,
107
Added:
)
108
Added:
109
Added:
110
Added:
@modules.route("/modules/ferti")
111
Added:
@login_required
112
Added:
def ferti():
113
Added:
modules = Module.query.all()
114
Added:
logs = Fertilog.query.order_by(Fertilog.primary_key.desc()).all()
115
Added:
targets = Fertitarget.query.all()
116
Added:
module = "ferti"
117
Added:
flash(f"Latest target is {targets}.", "info")
118
Added:
flash(f"Still fighting against styling in {module}.", "error")
119
Added:
return render_template(
120
Added:
f"modules/{module}.html",
121
Added:
modules=modules,
122
Added:
logs=logs,
123
Added:
)
124
Added:
125
Added:
126
Added:
# @main.route("/add-invoice", methods=["GET", "POST"])
127
Added:
# def add_invoice():
128
Added:
# form = AddInvoice()
129
Added:
# if request.method == "GET":
130
Added:
# return render_template("add-invoice.html")
131
Added:
132
Added:
133
Added:
# @main.route("/preview-invoice", methods=["GET", "POST"])
134
Added:
# def preview_invoice():
135
Added:
# if request.method == "GET":
136
Added:
# return render_template("preview-invoice.html")
app/modules/orders/forms.py
@@ -0,0 +1,35 @@
1
Added:
from flask_wtf import FlaskForm
2
Added:
from wtforms import (
3
Added:
SubmitField,
4
Added:
SelectField,
5
Added:
HiddenField,
6
Added:
StringField,
7
Added:
PasswordField,
8
Added:
IntegerField,
9
Added:
FloatField,
10
Added:
BooleanField,
11
Added:
DateTimeField,
12
Added:
)
13
Added:
from wtforms.validators import InputRequired, Length, NumberRange
14
Added:
15
Added:
16
Added:
class AddOrder(FlaskForm): # TODO
17
Added:
name = StringField("Product name", validators=[InputRequired()])
18
Added:
code_accounting = StringField("Accounting code", default=0)
19
Added:
unit_weight = FloatField("Unit weight", default=0)
20
Added:
price_net = FloatField("Price (net)", default=0)
21
Added:
price_gross = FloatField("Price (gross)", default=0)
22
Added:
tax_rate = FloatField("Tax rate", default=0)
23
Added:
submit = SubmitField("Add/Update Product")
24
Added:
25
Added:
26
Added:
class AddInvoice(FlaskForm):
27
Added:
invoice_id_alt = StringField("Alternative invoice ID")
28
Added:
customer_id = StringField("Customer ID")
29
Added:
customer_reference = StringField("Customer reference")
30
Added:
date_billed = StringField("Date billed")
31
Added:
date_due = StringField("Date due")
32
Added:
amount_net = FloatField("Amount without tax", default=0)
33
Added:
amount_gross = FloatField("Amount with tax", default=0)
34
Added:
amount_tax = FloatField("Amount of tax", default=0)
35
Added:
submit = SubmitField("Add new Invoice")
app/modules/orders/routes.py
@@ -0,0 +1,30 @@
1
Added:
# -*- mode: python; -*-
2
Added:
3
Added:
4
Added:
from flask import (
5
Added:
Blueprint,
6
Added:
render_template,
7
Added:
send_file,
8
Added:
request,
9
Added:
redirect,
10
Added:
flash,
11
Added:
url_for,
12
Added:
jsonify,
13
Added:
abort,
14
Added:
)
15
Added:
from flask_login import login_required, current_user
16
Added:
17
Added:
18
Added:
# from datetime import datetime
19
Added:
import inspect
20
Added:
21
Added:
22
Added:
23
Added:
from ... import db
24
Added:
from ...models import *
25
Added:
from .forms import *
26
Added:
27
Added:
28
Added:
orders = Blueprint("orders", __name__)
29
Added:
30
Added:
app/modules/products/forms.py
@@ -0,0 +1,23 @@
1
Added:
from flask_wtf import FlaskForm
2
Added:
from wtforms import (
3
Added:
SubmitField,
4
Added:
SelectField,
5
Added:
HiddenField,
6
Added:
StringField,
7
Added:
PasswordField,
8
Added:
IntegerField,
9
Added:
FloatField,
10
Added:
BooleanField,
11
Added:
DateTimeField,
12
Added:
)
13
Added:
from wtforms.validators import InputRequired, Length, NumberRange
14
Added:
15
Added:
16
Added:
class AddProduct(FlaskForm):
17
Added:
name = StringField("Product name", validators=[InputRequired()])
18
Added:
code_accounting = StringField("Accounting code", default=0)
19
Added:
unit_weight = FloatField("Unit weight", default=0)
20
Added:
price_net = FloatField("Price (net)", default=0)
21
Added:
price_gross = FloatField("Price (gross)", default=0)
22
Added:
tax_rate = FloatField("Tax rate", default=0)
23
Added:
submit = SubmitField("Add/Update Product")
app/modules/products/routes.py
@@ -0,0 +1,26 @@
1
Added:
# -*- mode: python; -*-
2
Added:
3
Added:
4
Added:
from flask import Blueprint, render_template, request, redirect, flash
5
Added:
from flask_login import login_required
6
Added:
7
Added:
from ... import db
8
Added:
from ...models import Module, Product
9
Added:
from .forms import *
10
Added:
11
Added:
products = Blueprint("products", __name__)
12
Added:
13
Added:
14
Added:
@products.route("/modules/products")
15
Added:
@login_required
16
Added:
def list():
17
Added:
modules = Module.query.all()
18
Added:
prods = Product.query.order_by(Product.primary_key.desc())
19
Added:
module = "products"
20
Added:
flash(f"Successfully accessed module {module}.", "info")
21
Added:
flash(f"Still fighting against styling in {module}.", "error")
22
Added:
return render_template(
23
Added:
f"modules/{module}.html",
24
Added:
modules=modules,
25
Added:
products=prods,
26
Added:
)
app/routes.py
@@ -1,135 +0,0 @@
1
Removed:
"""
2
Removed:
routes.py module
3
Removed:
----------------
4
Removed:
5
Removed:
This Python module contains the logic supporting:
6
Removed:
1. Navigating between website pages
7
Removed:
2. Interpreting user requests to the server
8
Removed:
3. Dispatching requested content back to the user
9
Removed:
10
Removed:
Python dependencies:
11
Removed:
- flask: provides web application features
12
Removed:
- forms: provides secure user form submission
13
Removed:
- sqlalchemy: provides communication with database on server.
14
Removed:
15
Removed:
Personal imports:
16
Removed:
These are used to avoid cluttering this file with
17
Removed:
placeholder data for posts' content.
18
Removed:
"""
19
Removed:
20
Removed:
21
Removed:
from flask import Flask, render_template, request, redirect, flash, url_for, jsonify
22
Removed:
from flask_bootstrap import Bootstrap
23
Removed:
24
Removed:
from datetime import datetime
25
Removed:
import inspect
26
Removed:
27
Removed:
from model import *
28
Removed:
from forms import *
29
Removed:
30
Removed:
app = Flask(__name__)
31
Removed:
32
Removed:
33
Removed:
app.config.from_pyfile("../config.py")
34
Removed:
db.init_app(app)
35
Removed:
36
Removed:
37
Removed:
@app.route("/")
38
Removed:
@app.route("/fapg/home")
39
Removed:
def project():
40
Removed:
"""This is our project welcome page."""
41
Removed:
michel = User(
42
Removed:
name_first="Michel",
43
Removed:
name_last="Peter",
44
Removed:
email="le-boss@fapg.com",
45
Removed:
phone_mobile="00000000",
46
Removed:
phone_alternative="0000000000",
47
Removed:
updated="2022-04-21",
48
Removed:
)
49
Removed:
modules = Module.query.all()
50
Removed:
print(module.name for module in modules)
51
Removed:
return render_template("home.html", user=michel, project="fapg", modules=modules)
52
Removed:
53
Removed:
54
Removed:
@app.route("/modules")
55
Removed:
def all_modules():
56
Removed:
return redirect("/")
57
Removed:
58
Removed:
59
Removed:
@app.route("/modules/<module>")
60
Removed:
def render_module(module):
61
Removed:
modules = Module.query.all()
62
Removed:
if module not in [mod.name for mod in modules]:
63
Removed:
return render_template("errors/module-not-found.html", module=module)
64
Removed:
customers = Customer.query.order_by(Customer.primary_key.desc())
65
Removed:
products = Product.query.order_by(Product.primary_key.desc())
66
Removed:
logs = Log.query.order_by(Log.primary_key.desc())
67
Removed:
latest_target = (
68
Removed:
Log.query.filter_by(target="True").order_by(Log.primary_key.desc()).first()
69
Removed:
)
70
Removed:
flash(f"Successfully accessed module {module}.", "info")
71
Removed:
flash(f"Still fighting against styling in {module}.", "error")
72
Removed:
return render_template(
73
Removed:
f"modules/{module}.html",
74
Removed:
module=module,
75
Removed:
modules=modules,
76
Removed:
customers=customers,
77
Removed:
products=products,
78
Removed:
logs=logs,
79
Removed:
target=latest_target,
80
Removed:
)
81
Removed:
82
Removed:
83
Removed:
@app.route("/delete-<pk>-from-<table>", methods=["POST"])
84
Removed:
def delete_item(pk, table):
85
Removed:
"""Delete item with Primary Key = pk from corresponding database
86
Removed:
table.
87
Removed:
"""
88
Removed:
model = globals()[table]
89
Removed:
record = model.query.filter_by(primary_key=pk).first()
90
Removed:
db.session.delete(record)
91
Removed:
db.session.commit()
92
Removed:
flash(f"Successfully removed item #{pk} from {table} table.", "info")
93
Removed:
return redirect("/modules")
94
Removed:
95
Removed:
96
Removed:
@app.route("/add-<item>", methods=["GET", "POST"])
97
Removed:
def add_item(item):
98
Removed:
"""Add a new item to a corresponding database table.
99
Removed:
100
Removed:
The item must match a database model class name (table). Then, we
101
Removed:
match the model class attributes with request.form values.
102
Removed:
103
Removed:
"""
104
Removed:
if item not in db.metadata.tables.keys():
105
Removed:
return render_template("errors/item-not-found.html", item=item)
106
Removed:
if request.method == "GET":
107
Removed:
form = globals()[f"Add{item.capitalize()}"]()
108
Removed:
return render_template("add-item.html", item=item, form=form)
109
Removed:
if request.method == "POST":
110
Removed:
table = globals()[item.capitalize()]
111
Removed:
table_fields = inspect.signature(table).parameters
112
Removed:
form_values = [request.form[key] for key in table_fields]
113
Removed:
debug = f"Ready to insert {form_values}"
114
Removed:
record = table(*form_values)
115
Removed:
db.session.add(record)
116
Removed:
db.session.commit()
117
Removed:
item_pk = table.query.order_by(table.primary_key.desc()).first().primary_key
118
Removed:
flash(
119
Removed:
f"Successfully added item #{item_pk} to {table.__table__.name.capitalize()} table.",
120
Removed:
"info",
121
Removed:
)
122
Removed:
return redirect(f"/modules")
123
Removed:
124
Removed:
125
Removed:
@app.route("/add-invoice", methods=["GET", "POST"])
126
Removed:
def add_invoice():
127
Removed:
form = AddInvoice()
128
Removed:
if request.method == "GET":
129
Removed:
return render_template("add-invoice.html")
130
Removed:
131
Removed:
132
Removed:
@app.route("/preview-invoice", methods=["GET", "POST"])
133
Removed:
def preview_invoice():
134
Removed:
if request.method == "GET":
135
Removed:
return render_template("preview-invoice.html")