Modularization.

Commit
e084f90c19e779592f6e3f14eb8f70a7287f0dad
Author
Marius Peter <marius.peter@tutanota.com>
Author date
Committer
Marius Peter <marius.peter@tutanota.com>
Committer date
Changed files
app/forms.py
index 302db586..00000000 100644..000000
@@ -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
index 00000000..ac5625fa 000000..100644
@@ -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
index 1cf59d80..00000000 100644..000000
@@ -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
index 00000000..507d1351 000000..100644
@@ -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
index 00000000..56f1d5af 000000..100644
@@ -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
index 00000000..c0511339 000000..100644
@@ -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
index 00000000..dd9e3967 000000..100644
@@ -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
index 00000000..9e96f416 000000..100644
@@ -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
index 00000000..2c5bcaa8 000000..100644
@@ -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
index 00000000..c8ae0720 000000..100644
@@ -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
index 00000000..d926931d 000000..100644
@@ -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
index 00000000..b3bb03f2 000000..100644
@@ -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
index 00000000..f98995df 000000..100644
@@ -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
index 00000000..f0f6bfb9 000000..100644
@@ -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
index 00000000..8ef7bd03 000000..100644
@@ -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
index 00000000..b8a0a684 000000..100644
@@ -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
index 00000000..b962a0f6 000000..100644
@@ -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
index 00000000..66ab47b0 000000..100644
@@ -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
index 00000000..4027a449 000000..100644
@@ -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
index 00000000..f00441f8 000000..100644
@@ -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
index 00000000..735fef9e 000000..100644
@@ -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
index 11cd3c2f..00000000 100644..000000
@@ -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")