diff --git a/README.md b/README.md
index 37bef582..7d8050b3 100644
--- a/README.md
+++ b/README.md
@@ -14,3 +14,27 @@ python -m flask run
host for local network:
python -m flask run --host=0.0.0.0
+
+
+files dedicated to each page:
+CSS
+ page
+HTML
+ page
+ row
+JavaScript
+ page
+ api
+ router
+MySQL
+ get
+ save
+ table
+ staging table
+ audit table
+Python
+ business object
+ controller
+ datastore
+ form
+ model
\ No newline at end of file
diff --git a/__pycache__/__init__.cpython-312.pyc b/__pycache__/__init__.cpython-312.pyc
index 11e03992..83b8f224 100644
Binary files a/__pycache__/__init__.cpython-312.pyc and b/__pycache__/__init__.cpython-312.pyc differ
diff --git a/__pycache__/app.cpython-312.pyc b/__pycache__/app.cpython-312.pyc
index ffee5ff7..96d52adf 100644
Binary files a/__pycache__/app.cpython-312.pyc and b/__pycache__/app.cpython-312.pyc differ
diff --git a/__pycache__/config.cpython-312.pyc b/__pycache__/config.cpython-312.pyc
index f5face55..1e511593 100644
Binary files a/__pycache__/config.cpython-312.pyc and b/__pycache__/config.cpython-312.pyc differ
diff --git a/__pycache__/extensions.cpython-312.pyc b/__pycache__/extensions.cpython-312.pyc
index 80f2d10d..6006f0ab 100644
Binary files a/__pycache__/extensions.cpython-312.pyc and b/__pycache__/extensions.cpython-312.pyc differ
diff --git a/app.log b/app.log
index 383ef3ea..631dea86 100644
--- a/app.log
+++ b/app.log
@@ -1,46 +1,65 @@
-Traceback: Traceback (most recent call last):
- File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 1473, in wsgi_app
- response = self.full_dispatch_request()
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 882, in full_dispatch_request
- rv = self.handle_user_exception(e)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask_cors\extension.py", line 178, in wrapped_function
- return cors_after_request(app.make_response(f(*args, **kwargs)))
- ^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 880, in full_dispatch_request
- rv = self.dispatch_request()
- ^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 865, in dispatch_request
- return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\product.py", line 114, in products
- return render_template('pages/store/_products.html', model = model)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\templating.py", line 150, in render_template
- return _render(app, template, context)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\templating.py", line 131, in _render
- rv = template.render(context)
- ^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\jinja2\environment.py", line 1304, in render
- self.environment.handle_exception()
- File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\jinja2\environment.py", line 939, in handle_exception
- raise rewrite_traceback_stack(source=source)
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\pages\store\_products.html", line 1, in top-level template code
- {% extends 'layouts/layout.html' %}
- ^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\layouts\layout.html", line 316, in top-level template code
- {% block page_body %}{% endblock %}
- ^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\pages\store\_products.html", line 89, in block 'page_body'
- {% include 'components/store/_row_product.html' %}
- ^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\components\store\_row_product.html", line 38, in top-level template code
-
- ^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\jinja2\environment.py", line 487, in getattr
- return getattr(obj, attribute)
- ^^^^^^^^^^^^^^^^^^^^^^^
-jinja2.exceptions.UndefinedError: 'permutation' is undefined
-
+Request: 127.0.0.1 GET http /store/stock_items?id_category=3&id_product=&is_out_of_stock=false&quantity_min=&quantity_max= Host: 127.0.0.1:5000
+User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
+Accept-Language: en-GB,en;q=0.5
+Accept-Encoding: gzip, deflate, br, zstd
+Referer: http://127.0.0.1:5000/store/stock_items?id_category=3&id_product=3&is_out_of_stock=false&quantity_min=&quantity_max=
+Dnt: 1
+Connection: keep-alive
+Cookie: session=.eJytVlnPqzgS_SutSN1PnVz25ZOuZsgGJIEkhLC9ILBZzB6WLPTc_z4m3-2-_dCzSSOFYLtMnVOuclX9NguGPq1b1EXw2kXt7OO3GQgqP4Alqvyur9to9tG3Q_Trn5aH98bP1agMUDH7mEXwEbRwUSIIi6ivq65Effr3ZJIuQF3Ofp3FqO36KiixwpkZQfjCawj6YGjbqAIvH0ZxMBT97KMaiuItaqME1dVfCD4JkH-M_ckIAut9v__BsQIViiwQRBYSYsATYUAScRRPgJ3_ZuzfoxbFKIKzjzgouugtQRUoBhhB35LMH6ifdmJxNzQY6s_Gd0P73SDtd7vnl8nw2Td8Xl0b-32dRxWWg1gAbMCIPA0ZhuBogqZCigAEB4OQJ7kwZCkYEhyHKQ7f3RAAEHXdHxqi1y4NZYCOaJcHjooOq10Rlto0X2rZlTIIXVfRAwWOPqpZjQLFIICicYeXmHuO24cVTINRfeiZV3iZVx_lggkRS4IXm0LHqLUVm2FKd7UiFgtn617dFzzsYq1Rzr26GJ8usLan_Fjvjp4S3kxnpUgyw87l89Vlo-3TlTJ_v2eq_c7Ir-y-7kb_DC-I2SRjv_GsRD8YZbvpu7AW2uU6NIqIu7KR4kXD7gga1iSSw3wv1kbp1-d-wzV3F6zmNrKeCsk37E0E-gPUQxhc-tS3SjkOLTeu9sXa4q5ZtexW_mEfS-5yL9-qOIOsHDUKhGDeHQebvMQrD5zkKyqsjFyVjO3UaJNzohNJqIwAyJJUURgakRfZv_hldqiGuRdJr3oEFSuU0s1FibD3hbBORZvZjfd4GOLVSVyGYyfuHF7zGN3oLdZkD-yqY5e677rg8MwZP7mE5dgHQx1LOcvMx_MT1OeKJ-nt3k6s8C4sYihlxHlT6KlkeU8arNC51iQcBtGzQW3U-QEOQZKnBJ4UaI77sY5wUAgcQxDvW_AXUXK5jiqpI7VTK4MFK5VT88axVnhe9o03zSvrHjne1cgZJsx2d09JSCvfHrRtShqvnbjAyobA1tuw3PbeBX9QWjmkti9vxfaBbeShbBEhxY6hXRDBWzGbhvZ1Ai88BaagPA9Ylnvys4CyOACKbKCcSh5FpoH9GFxK7KeQBXKRQcV6fWKkBFSW4xEJdxyaFSi3lOsYKUCf4ek6Xgrl7eswXkdvrZdadia0Ncx1ExtLuYwuuy-d0lNtDRh9NJC3dokTrYn6OnnsKlUEMii9NVlDxXiA13U8X64vA-Gn1HN8Hf58FQotx1jllnCd3bgzd7Jnnwcgs9XEGTrLHPMqvK2YwukwM_WBufSaKeFne8X4nDaqnL6-DtqoMfbkiNLqXbvopuvp2QaN9eaHkmw82eg8x7iHld4HGP8sw_e-Q6nfw8uP7xzaK0BZlIFt5WrWlK79HL3L_-HKY3tcZ9KJeRHwFjnG08xJ50ylZuCkT3PEJ1VsOStPnbO9LS55w13LfEpBjeuc0THb0FqWUNq4YfUsmfgyU8BpJngd1y6ljzl1XGE_0xaaMDAWEayXgp5dGa1UWd3WmKNp5dq6SPVxiVxz8_BKq3zHBlW8ecEirUy7aU277o-bdONO53BVRzfzYpOAO6tqKLcydlrZTbwGHJfZO54yiIwcHi-K4WpKTXvYnx4FV1pmyVOqK1VFE2nHUXtOl-ICzTd519W2RUXkvXkMSJLofhWkdXTv6tNecCVkPG8X59CsvdMmlKvhUt5O7fa0fOmdq8DTQRt3FP-6w_acZE7S8HwzJKRGMZleWKvLvHavr7ZLU_VxN24A5_4BBu7QydSZXy2TU0EmIfNMLdY1IuuiNHWqMawEmqcSn7a-cpwvg7CshgHFxT60IYVW0m0jP4bLGvDpeLmC-W3r1KqrFkldtKaYWanVgKbjHXNfKQdWMh8rKSmgy0XQJtf9PeoFUeK0ZfUMVXtvnqBc7SFhioW-dLqWOfm0aD3sQLzKD8xTTG1PbY-7ka-OzjLMeOtCL4W56C0FV3N3hHhEp3lLJDh_daBupsqI_ysEf2raOkZF9NNnv_Dr7J2w_P713rOMghYXvc_ah6q4fte_ARfnWSJnr_6ma_YqvaDn7chTxnm0FFsKot0O3-_Z_9KC_IvSj1PqZ47lOF7kBJxQf0-6HE1-LnQdBkj7vuk-vnyB0X1ePYKcwgU7irlUQM9qMXSLd_cxQX3BWN8bg_9MqkIg_3ebpy11BSY5H25lXekdYuTjoE-SJcVusbhBoB-mRu0Pht0iaYN70Aftm87n8AtLQzqmcP_BQ5Zi-VhgYooHAcELPBNCjvlb95URiF_ar03yC_z61vUzLf1MbfEPwOqHfXj-qbLDowgumurtcTQ57O4kWpZr2VxQ1iE-5yUdcv5RVq3xHvYqlU8bh_C_6dWGBgY97sYmZ8wogmLmJDEnSZPgP2jqg2EXNC14s2_fvv0TX22jag.ZwjUoA.pitPRgpTPJyCaDMIr0TPpBG_lIc
+Upgrade-Insecure-Requests: 1
+Sec-Fetch-Dest: document
+Sec-Fetch-Mode: navigate
+Sec-Fetch-Site: same-origin
+Sec-Fetch-User: ?1
+Sec-Gpc: 1
+Priority: u=0, i
+
+
+Request data: b''
+Traceback: Traceback (most recent call last):
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 1473, in wsgi_app
+ response = self.full_dispatch_request()
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 882, in full_dispatch_request
+ rv = self.handle_user_exception(e)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask_cors\extension.py", line 178, in wrapped_function
+ return cors_after_request(app.make_response(f(*args, **kwargs)))
+ ^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 880, in full_dispatch_request
+ rv = self.dispatch_request()
+ ^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 865, in dispatch_request
+ return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\stock_item.py", line 45, in stock_items
+ return render_template('pages/store/_stock_items.html', model = model, datetime = datetime)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\templating.py", line 150, in render_template
+ return _render(app, template, context)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\templating.py", line 131, in _render
+ rv = template.render(context)
+ ^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\jinja2\environment.py", line 1304, in render
+ self.environment.handle_exception()
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\jinja2\environment.py", line 939, in handle_exception
+ raise rewrite_traceback_stack(source=source)
+ File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\pages\store\_stock_items.html", line 1, in top-level template code
+ {% extends 'layouts/layout.html' %}
+ ^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\layouts\layout.html", line 316, in top-level template code
+ {% block page_body %}{% endblock %}
+ ^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\pages\store\_stock_items.html", line 100, in block 'page_body'
+ {% include 'components/store/_row_stock_item.html' %}
+ ^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\components\store\_row_stock_item.html", line 78, in top-level template code
+ {{ model.ATTR_VALUE_CURRENT }}="{{ currency.id_currency_cost }}"
+ ^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\jinja2\environment.py", line 487, in getattr
+ return getattr(obj, attribute)
+ ^^^^^^^^^^^^^^^^^^^^^^^
+jinja2.exceptions.UndefinedError: 'currency' is undefined
+
diff --git a/app.log.1 b/app.log.1
index c31f5f8b..82d34c9e 100644
--- a/app.log.1
+++ b/app.log.1
@@ -1,4 +1,47 @@
-Exception on /store/products [GET]
+Request: 127.0.0.1 GET http /store/stock_items?id_category=3&id_product=3&is_out_of_stock=false&quantity_min=&quantity_max= Host: 127.0.0.1:5000
+User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
+Accept-Language: en-GB,en;q=0.5
+Accept-Encoding: gzip, deflate, br, zstd
+Referer: http://127.0.0.1:5000/store/stock_items?id_category=3&id_product=&is_out_of_stock=false&quantity_min=&quantity_max=
+Dnt: 1
+Connection: keep-alive
+Cookie: session=.eJytVlnPqzgS_SutSN1PnVz25ZOuZsgGJIEkhLC9ILBZzB6WLPTc_z4m3-2-_dCzSSOFYLtMnVOuclX9NguGPq1b1EXw2kXt7OO3GQgqP4Alqvyur9to9tG3Q_Trn5aH98bP1agMUDH7mEXwEbRwUSIIi6ivq65Effr3ZJIuQF3Ofp3FqO36KiixwpkZQfjCawj6YGjbqAIvH0ZxMBT97KMaiuItaqME1dVfCD4JkH-M_ckIAut9v__BsQIViiwQRBYSYsATYUAScRRPgJ3_ZuzfoxbFKIKzjzgouugtQRUoBhhB35LMH6ifdmJxNzQY6s_Gd0P73SDtd7vnl8nw2Td8Xl0b-32dRxWWg1gAbMCIPA0ZhuBogqZCigAEB4OQJ7kwZCkYEhyHKQ7f3RAAEHXdHxqi1y4NZYCOaJcHjooOq10Rlto0X2rZlTIIXVfRAwWOPqpZjQLFIICicYeXmHuO24cVTINRfeiZV3iZVx_lggkRS4IXm0LHqLUVm2FKd7UiFgtn617dFzzsYq1Rzr26GJ8usLan_Fjvjp4S3kxnpUgyw87l89Vlo-3TlTJ_v2eq_c7Ir-y-7kb_DC-I2SRjv_GsRD8YZbvpu7AW2uU6NIqIu7KR4kXD7gga1iSSw3wv1kbp1-d-wzV3F6zmNrKeCsk37E0E-gPUQxhc-tS3SjkOLTeu9sXa4q5ZtexW_mEfS-5yL9-qOIOsHDUKhGDeHQebvMQrD5zkKyqsjFyVjO3UaJNzohNJqIwAyJJUURgakRfZv_hldqiGuRdJr3oEFSuU0s1FibD3hbBORZvZjfd4GOLVSVyGYyfuHF7zGN3oLdZkD-yqY5e677rg8MwZP7mE5dgHQx1LOcvMx_MT1OeKJ-nt3k6s8C4sYihlxHlT6KlkeU8arNC51iQcBtGzQW3U-QEOQZKnBJ4UaI77sY5wUAgcQxDvW_AXUXK5jiqpI7VTK4MFK5VT88axVnhe9o03zSvrHjne1cgZJsx2d09JSCvfHrRtShqvnbjAyobA1tuw3PbeBX9QWjmkti9vxfaBbeShbBEhxY6hXRDBWzGbhvZ1Ai88BaagPA9Ylnvys4CyOACKbKCcSh5FpoH9GFxK7KeQBXKRQcV6fWKkBFSW4xEJdxyaFSi3lOsYKUCf4ek6Xgrl7eswXkdvrZdadia0Ncx1ExtLuYwuuy-d0lNtDRh9NJC3dokTrYn6OnnsKlUEMii9NVlDxXiA13U8X64vA-Gn1HN8Hf58FQotx1jllnCd3bgzd7Jnnwcgs9XEGTrLHPMqvK2YwukwM_WBufSaKeFne8X4nDaqnL6-DtqoMfbkiNLqXbvopuvp2QaN9eaHkmw82eg8x7iHld4HGP8sw_e-Q6nfw8uP7xzaK0BZlIFt5WrWlK79HL3L_-HKY3tcZ9KJeRHwFjnG08xJ50ylZuCkT3PEJ1VsOStPnbO9LS55w13LfEpBjeuc0THb0FqWUNq4YfUsmfgyU8BpJngd1y6ljzl1XGE_0xaaMDAWEayXgp5dGa1UWd3WmKNp5dq6SPVxiVxz8_BKq3zHBlW8ecEirUy7aU277o-bdONO53BVRzfzYpOAO6tqKLcydlrZTbwGHJfZO54yiIwcHi-K4WpKTXvYnx4FV1pmyVOqK1VFE2nHUXtOl-ICzTd519W2RUXkvXkMSJLofhWkdXTv6tNecCVkPG8X59CsvdMmlKvhUt5O7fa0fOmdq8DTQRt3FP-6w_acZE7S8HwzJKRGMZleWKvLvHavr7ZLU_VxN24A5_4BBu7QydSZXy2TU0EmIfNMLdY1IuuiNHWqMawEmqcSn7a-cpwvg7CshgHFxT60IYVW0m0jP4bLGvDpeLmC-W3r1KqrFkldtKaYWanVgKbjHXNfKQdWMh8rKSmgy0XQJtf9PeoFUeK0ZfUMVXtvnqBc7SFhioW-dLqWOfm0aD3sQLzKD8xTTG1PbY-7ka-OzjLMeOtCL4W56C0FV3N3hHhEp3lLJDh_daBupsqI_ysEf2raOkZF9NNnv_Dr7J2w_P713rOMghYXvc_ah6q4fte_ARfnWSJnr_6ma_YqvaDn7chTxnm0FFsKot0O3-_Z_9KC_IvSj1PqZ47lOF7kBJxQf0-6HE1-LnQdBkj7vuk-vnyB0X1ePYKcwgU7irlUQM9qMXSLd_cxQX3BWN8bg_9MqkIg_3ebpy11BSY5H25lXekdYuTjoE-SJcVusbhBoB-mRu0Pht0iaYN70Aftm87n8AtLQzqmcP_BQ5Zi-VhgYooHAcELPBNCjvlb95URiF_ar03yC_z61vUzLf1MbfEPwOqHfXj-qbLDowgumurtcTQ57O4kWpZr2VxQ1iE-5yUdcv5RVq3xHvYqlU8bh_C_6dWGBgY97sYmZ8wogmLmJDEnSZPgP2jqg2EXNC14s2_fvv0TX22jag.ZwjUoA.pitPRgpTPJyCaDMIr0TPpBG_lIc
+Upgrade-Insecure-Requests: 1
+Sec-Fetch-Dest: document
+Sec-Fetch-Mode: navigate
+Sec-Fetch-Site: same-origin
+Sec-Fetch-User: ?1
+Sec-Gpc: 1
+Priority: u=0, i
+
+
+Request data: b''
+Traceback: Traceback (most recent call last):
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 1473, in wsgi_app
+ response = self.full_dispatch_request()
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 882, in full_dispatch_request
+ rv = self.handle_user_exception(e)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask_cors\extension.py", line 178, in wrapped_function
+ return cors_after_request(app.make_response(f(*args, **kwargs)))
+ ^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 880, in full_dispatch_request
+ rv = self.dispatch_request()
+ ^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 865, in dispatch_request
+ return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\stock_item.py", line 40, in stock_items
+ model = Model_View_Store_Stock_Item(form_filters)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_stock_item.py", line 90, in __init__
+ print(f'product: {product}\n{product[Stock_Item.ATTR_ID_PRODUCT_CATEGORY]}\{nself.form_filters.id_category.data}')
+ ^^^^^
+NameError: name 'nself' is not defined. Did you mean: 'self'?
+
+Exception on /store/stock_items [GET]
Traceback (most recent call last):
File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 1473, in wsgi_app
response = self.full_dispatch_request()
@@ -15,9 +58,9 @@ Traceback (most recent call last):
File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 865, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\product.py", line 114, in products
- return render_template('pages/store/_products.html', model = model)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\stock_item.py", line 45, in stock_items
+ return render_template('pages/store/_stock_items.html', model = model, datetime = datetime)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\templating.py", line 150, in render_template
return _render(app, template, context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -28,38 +71,20 @@ Traceback (most recent call last):
self.environment.handle_exception()
File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\jinja2\environment.py", line 939, in handle_exception
raise rewrite_traceback_stack(source=source)
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\pages\store\_products.html", line 1, in top-level template code
+ File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\pages\store\_stock_items.html", line 1, in top-level template code
{% extends 'layouts/layout.html' %}
^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\layouts\layout.html", line 316, in top-level template code
{% block page_body %}{% endblock %}
^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\pages\store\_products.html", line 89, in block 'page_body'
- {% include 'components/store/_row_product.html' %}
+ File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\pages\store\_stock_items.html", line 100, in block 'page_body'
+ {% include 'components/store/_row_stock_item.html' %}
^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\components\store\_row_product.html", line 38, in top-level template code
- |
+ File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\components\store\_row_stock_item.html", line 78, in top-level template code
+ {{ model.ATTR_VALUE_CURRENT }}="{{ currency.id_currency_cost }}"
^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\jinja2\environment.py", line 487, in getattr
return getattr(obj, attribute)
^^^^^^^^^^^^^^^^^^^^^^^
-jinja2.exceptions.UndefinedError: 'permutation' is undefined
+jinja2.exceptions.UndefinedError: 'currency' is undefined
Server Error: 500 Internal Server Error: The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.
-Request: 127.0.0.1 GET http /store/products? Host: 127.0.0.1:5000
-User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0
-Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
-Accept-Language: en-GB,en;q=0.5
-Accept-Encoding: gzip, deflate, br, zstd
-Dnt: 1
-Connection: keep-alive
-Cookie: session=.eJytVlmzqkgS_isdRnQ_9fGyKyfixoyKAh5BQWR7IaCqkGJXQIGe-9-n8Nzu2w89W8REuFCVReaXlV8uv83Crk2qO24QvDToPnv_bQbCMghhgcugaas7mr239w79-qft7nXwcxcVIc5n7zMEn-EdzgsMYY7aqmwK3CZ_v07SOaiK2a-zGN-btgwLonBmIQgHsodhALr7HZVgCCCKwy5vZ-9ll-cv0R1dcVX-heATAP3HczA5QRG9r_9_CPySiUQeLEUeUmK4oKKQpmIUTwab4IU4eKA7jjGCs_c4zBv0kuAS5B1EMLBX1g-rn34ScdPVxNSfnW-6-3eHtN_9fjtPjs--kftq7nHQVhkqJ2AxRECkKQQBtVjwUBRYCjIAiSwLUMwxgAc8omiRQOy-hyEEADXNHxrQsE8iGeAj3mehq-LDZp9HhTat11p6YUxK11X8xKGrj2pa4VAxKaBowmEQM9_12qiESTiqTz31cz_1q6OccxHmaTDwCXTNStvwacRQD7Wk5nP69pEeN63Xs9qCtY7SPNPvelBJyWjCRoVL5xS_qcch6jvTfFv64zBIvtZq7DFmesA01INmH8M1UvcX6oPpRemNH24tqHUlTNHxKGin8-3UFH2lItye1Kpiec9glm9e6Ny2fT_y8IFF-Tgm0nmzUFSLSx4XvEykeC1KciuiJyuBvJIr1ts-ojI5yZuyP-XVclPvW1PHhxJFHYkuXgyHoaUT0fKTzEhE1m-kYH3gtos8o07W6iOV2coJ-BAd1K0aLJPuiQqVF_L1QU7PV1_sKnUXMzGIrxqDW3e4sSPd2HveXudvzaa63xB73nXJ5ZwPmmr2sd0v8rTJ8JA8alzRwZFyVsYQO81eFV0uyNvjkG9OaprWhwwgq8TRfC3rqwh_SLorJ9ytrKWjtpQNQgPU1_iOmiAkFKQXzIJb8Cwl_NjHhBRLgaOoVxb8BUvOl1Gldaw2amnyYKMKala79oasi7b2p3VpP5DrX8yM46J0__CVK21nu4O2S2hz2ItzoqwLHf0eFbvWP5MXCjuDzG7wN3wbOmYWyTYVMfwYOTkVvhTzSeRcJuO5r8AEFEZHZJkv9zmUxQ4wdA3lZOUzdBI6z85jxHaiLJDzFCr28GkjoaCyHo94-SDULEGxYzzXTAD-pKfn-gmUd8NhvIy-pBdaalCaBDPdIs4yHqfL3qAzeqJJgNNHE_uSR51YTdSl63NfqiKQQeFLdAUV8wmGy2icL4OJybfQM5IOf06FXMuIrWJHee5-3Ft72XeMDsh8OWGG7jojuHJ_JyZwusxUfRIsrSZlrZb6Fy1VBc26CJqkdZqljs4UiMJuPSdvpvT0HZMlerNDQde-bDa-axIq621I7BsyfJ07FPojOv94z2X9HBR5ETp2pqZ14Tn96J__DylP_PHcSSfBRcEbcs3eymjXYBIrdJPeGslN5TvBzhLXcHb5OauFS5FNJaj2XAMf0y2rpWA8Slee-Dvh5SbCaRYY9NEYdCl7agOJM2vjyQaxRYXSeqmnF04jCac7Gne07EyT8kQf19iztk-_sIsXN5j8E5eja2gLlShLSv3SmtEWjkamF7aUqOedeNEKj7HovW6UYMLVEV6mLz5luu3IKuXRJqex9tYo7Ifv7lL74vVTqasUVbPtymBpJ6WuPCmoSu4bT4aT1Nj4uLjMVcq8K7nM5Iykw5PnYLg2WXtVNxQ2Y1nBNAu45hQssjcufabSJUJ8TDJsOCtKCarTIj6p5rgZF0bAhdZtw36sFXf4WIVUsQKatH8AihMUwHCHmw2b2CrDTblqgnO81LitVfHr5NzXYXuWRy5ERd3E-TVZ9fx221egdsL6Lm8Fz1oeOit-eLlB6tSmaSk6CPEu_bAt2G0dUX-uFS4By_gSX_lYZy05FAWmk-W3Rx7oMtrwxoe9Pev1oQ8_qrRopdUTq3WlC8qyHMaTE-_larMbvVawbCE7DXfTrg8nuiL9mKSgnqzMnbq-YWXTNGi8Bt6T1K8GVPXUGclvieFP9b2KcY5--pwXfp29ClbQDq8zaxTeSdP77H24jKtX_-tIc55d5XRob7rmbJIz7m_HBWMao604qxDt9yS_Z__LCPIvWj8pqd9rLMOJFEsK6u9Fl10uPzeahhhI2rZu3r98gejxVj7DjKEEAcVCssR9Oe-a-Wv6mEx9Iba-Dwb_GVSJQfbvDk9HqhJM8s3FjThg9WwnrVGFbuCyo4m4xqDtpkHtD4TN_HoPH2Eb3l9wPh-_8CxkY4bjqAXkGX4RL7mYWYCQWiwXXAQF7m_NV25J_XL_Wl9_gV9fun5mVz8zO_IBsPzhH1l_qmzIE4LzurxOEcdTwBA49LJcKlf-w8jlZr2JraWiBBYTC0dTW7-o0UX_zazW1TBsyTQ2BWPGUAz3RolvjGAxzDvNv1PsnGZYf_bt27d_Agdyo3I.ZvXc6g.WpR0PQjTMWhM_qBkpa9CVzq95M8
-Upgrade-Insecure-Requests: 1
-Sec-Fetch-Dest: document
-Sec-Fetch-Mode: navigate
-Sec-Fetch-Site: none
-Sec-Fetch-User: ?1
-Sec-Gpc: 1
-Priority: u=0, i
-
-
-Request data: b''
diff --git a/app.log.2 b/app.log.2
index b5df9777..54248294 100644
--- a/app.log.2
+++ b/app.log.2
@@ -1,58 +1,16 @@
-Exception on /store/products [GET]
-Traceback (most recent call last):
- File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 1473, in wsgi_app
- response = self.full_dispatch_request()
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 882, in full_dispatch_request
- rv = self.handle_user_exception(e)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask_cors\extension.py", line 178, in wrapped_function
- return cors_after_request(app.make_response(f(*args, **kwargs)))
- ^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 880, in full_dispatch_request
- rv = self.dispatch_request()
- ^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 865, in dispatch_request
- return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\product.py", line 113, in products
- model = Model_View_Store_Product(form_filters)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_product.py", line 101, in __init__
- self.category_list_filters, errors_filters = datastore_store.get_many_product(
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\datastores\datastore_store_base.py", line 110, in get_many_product
- category_list.add_product(new_product)
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\business_objects\store\product_category.py", line 337, in add_product
- self.categories[index_category].add_product(product)
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\business_objects\store\product_category.py", line 100, in add_product
- raise ValueError(f"{av.error_msg_str(product, 'product', _m, Product)}\nProduct already in category.")
-ValueError: Invalid Category.add_product argument product. Type = . Value = Product
- id_product: 1
- id_category: 1
- name: Braille Keyboard Translator
- display_order: 1
- can_view: False
- can_edit: False
- can_admin: False
- has_variations: True
- permutations: []
- variation trees: []
-
-Product already in category.
-Server Error: 500 Internal Server Error: The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.
-Request: 127.0.0.1 GET http /store/products? Host: 127.0.0.1:5000
-User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0
+Request: 127.0.0.1 GET http /store/stock_items?id_category=3&id_product=3&is_out_of_stock=false&quantity_min=&quantity_max= Host: 127.0.0.1:5000
+User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate, br, zstd
+Referer: http://127.0.0.1:5000/store/stock_items?id_category=3&id_product=&is_out_of_stock=false&quantity_min=&quantity_max=
Dnt: 1
Connection: keep-alive
-Cookie: session=.eJytVlmzqkgS_isdRnQ_9fGyKyfixoyKAh5BQWR7IaCqkGJXQIGe-9-n8Nzu2w89W8REuFCVReaXlV8uv83Crk2qO24QvDToPnv_bQbCMghhgcugaas7mr239w79-qft7nXwcxcVIc5n7zMEn-EdzgsMYY7aqmwK3CZ_v07SOaiK2a-zGN-btgwLonBmIQgHsodhALr7HZVgCCCKwy5vZ-9ll-cv0R1dcVX-heATAP3HczA5QRG9r_9_CPySiUQeLEUeUmK4oKKQpmIUTwab4IU4eKA7jjGCs_c4zBv0kuAS5B1EMLBX1g-rn34ScdPVxNSfnW-6-3eHtN_9fjtPjs--kftq7nHQVhkqJ2AxRECkKQQBtVjwUBRYCjIAiSwLUMwxgAc8omiRQOy-hyEEADXNHxrQsE8iGeAj3mehq-LDZp9HhTat11p6YUxK11X8xKGrj2pa4VAxKaBowmEQM9_12qiESTiqTz31cz_1q6OccxHmaTDwCXTNStvwacRQD7Wk5nP69pEeN63Xs9qCtY7SPNPvelBJyWjCRoVL5xS_qcch6jvTfFv64zBIvtZq7DFmesA01INmH8M1UvcX6oPpRemNH24tqHUlTNHxKGin8-3UFH2lItye1Kpiec9glm9e6Ny2fT_y8IFF-Tgm0nmzUFSLSx4XvEykeC1KciuiJyuBvJIr1ts-ojI5yZuyP-XVclPvW1PHhxJFHYkuXgyHoaUT0fKTzEhE1m-kYH3gtos8o07W6iOV2coJ-BAd1K0aLJPuiQqVF_L1QU7PV1_sKnUXMzGIrxqDW3e4sSPd2HveXudvzaa63xB73nXJ5ZwPmmr2sd0v8rTJ8JA8alzRwZFyVsYQO81eFV0uyNvjkG9OaprWhwwgq8TRfC3rqwh_SLorJ9ytrKWjtpQNQgPU1_iOmiAkFKQXzIJb8Cwl_NjHhBRLgaOoVxb8BUvOl1Gldaw2amnyYKMKala79oasi7b2p3VpP5DrX8yM46J0__CVK21nu4O2S2hz2ItzoqwLHf0eFbvWP5MXCjuDzG7wN3wbOmYWyTYVMfwYOTkVvhTzSeRcJuO5r8AEFEZHZJkv9zmUxQ4wdA3lZOUzdBI6z85jxHaiLJDzFCr28GkjoaCyHo94-SDULEGxYzzXTAD-pKfn-gmUd8NhvIy-pBdaalCaBDPdIs4yHqfL3qAzeqJJgNNHE_uSR51YTdSl63NfqiKQQeFLdAUV8wmGy2icL4OJybfQM5IOf06FXMuIrWJHee5-3Ft72XeMDsh8OWGG7jojuHJ_JyZwusxUfRIsrSZlrZb6Fy1VBc26CJqkdZqljs4UiMJuPSdvpvT0HZMlerNDQde-bDa-axIq621I7BsyfJ07FPojOv94z2X9HBR5ETp2pqZ14Tn96J__DylP_PHcSSfBRcEbcs3eymjXYBIrdJPeGslN5TvBzhLXcHb5OauFS5FNJaj2XAMf0y2rpWA8Slee-Dvh5SbCaRYY9NEYdCl7agOJM2vjyQaxRYXSeqmnF04jCac7Gne07EyT8kQf19iztk-_sIsXN5j8E5eja2gLlShLSv3SmtEWjkamF7aUqOedeNEKj7HovW6UYMLVEV6mLz5luu3IKuXRJqex9tYo7Ifv7lL74vVTqasUVbPtymBpJ6WuPCmoSu4bT4aT1Nj4uLjMVcq8K7nM5Iykw5PnYLg2WXtVNxQ2Y1nBNAu45hQssjcufabSJUJ8TDJsOCtKCarTIj6p5rgZF0bAhdZtw36sFXf4WIVUsQKatH8AihMUwHCHmw2b2CrDTblqgnO81LitVfHr5NzXYXuWRy5ERd3E-TVZ9fx221egdsL6Lm8Fz1oeOit-eLlB6tSmaSk6CPEu_bAt2G0dUX-uFS4By_gSX_lYZy05FAWmk-W3Rx7oMtrwxoe9Pev1oQ8_qrRopdUTq3WlC8qyHMaTE-_larMbvVawbCE7DXfTrg8nuiL9mKSgnqzMnbq-YWXTNGi8Bt6T1K8GVPXUGclvieFP9b2KcY5--pwXfp29ClbQDq8zaxTeSdP77H24jKtX_-tIc55d5XRob7rmbJIz7m_HBWMao604qxDt9yS_Z__LCPIvWj8pqd9rLMOJFEsK6u9Fl10uPzeahhhI2rZu3r98gejxVj7DjKEEAcVCssR9Oe-a-Wv6mEx9Iba-Dwb_GVSJQfbvDk9HqhJM8s3FjThg9WwnrVGFbuCyo4m4xqDtpkHtD4TN_HoPH2Eb3l9wPh-_8CxkY4bjqAXkGX4RL7mYWYCQWiwXXAQF7m_NV25J_XL_Wl9_gV9fun5mVz8zO_IBsPzhH1l_qmzIE4LzurxOEcdTwBA49LJcKlf-w8jlZr2JraWiBBYTC0dTW7-o0UX_zazW1TBsyTQ2BWPGUAz3RolvjGAxzDvNv1PsnGZYf_bt27d_Agdyo3I.ZvXc6g.WpR0PQjTMWhM_qBkpa9CVzq95M8
+Cookie: session=.eJytVlnPqzgS_SutSN1PnVz25ZOuZsgGJIEkhLC9ILBZzB6WLPTc_z4m3-2-_dCzSSOFYLtMnVOuclX9NguGPq1b1EXw2kXt7OO3GQgqP4Alqvyur9to9tG3Q_Trn5aH98bP1agMUDH7mEXwEbRwUSIIi6ivq65Effr3ZJIuQF3Ofp3FqO36KiixwpkZQfjCawj6YGjbqAIvH0ZxMBT97KMaiuItaqME1dVfCD4JkH-M_ckIAut9v__BsQIViiwQRBYSYsATYUAScRRPgJ3_ZuzfoxbFKIKzjzgouugtQRUoBhhB35LMH6ifdmJxNzQY6s_Gd0P73SDtd7vnl8nw2Td8Xl0b-32dRxWWg1gAbMCIPA0ZhuBogqZCigAEB4OQJ7kwZCkYEhyHKQ7f3RAAEHXdHxqi1y4NZYCOaJcHjooOq10Rlto0X2rZlTIIXVfRAwWOPqpZjQLFIICicYeXmHuO24cVTINRfeiZV3iZVx_lggkRS4IXm0LHqLUVm2FKd7UiFgtn617dFzzsYq1Rzr26GJ8usLan_Fjvjp4S3kxnpUgyw87l89Vlo-3TlTJ_v2eq_c7Ir-y-7kb_DC-I2SRjv_GsRD8YZbvpu7AW2uU6NIqIu7KR4kXD7gga1iSSw3wv1kbp1-d-wzV3F6zmNrKeCsk37E0E-gPUQxhc-tS3SjkOLTeu9sXa4q5ZtexW_mEfS-5yL9-qOIOsHDUKhGDeHQebvMQrD5zkKyqsjFyVjO3UaJNzohNJqIwAyJJUURgakRfZv_hldqiGuRdJr3oEFSuU0s1FibD3hbBORZvZjfd4GOLVSVyGYyfuHF7zGN3oLdZkD-yqY5e677rg8MwZP7mE5dgHQx1LOcvMx_MT1OeKJ-nt3k6s8C4sYihlxHlT6KlkeU8arNC51iQcBtGzQW3U-QEOQZKnBJ4UaI77sY5wUAgcQxDvW_AXUXK5jiqpI7VTK4MFK5VT88axVnhe9o03zSvrHjne1cgZJsx2d09JSCvfHrRtShqvnbjAyobA1tuw3PbeBX9QWjmkti9vxfaBbeShbBEhxY6hXRDBWzGbhvZ1Ai88BaagPA9Ylnvys4CyOACKbKCcSh5FpoH9GFxK7KeQBXKRQcV6fWKkBFSW4xEJdxyaFSi3lOsYKUCf4ek6Xgrl7eswXkdvrZdadia0Ncx1ExtLuYwuuy-d0lNtDRh9NJC3dokTrYn6OnnsKlUEMii9NVlDxXiA13U8X64vA-Gn1HN8Hf58FQotx1jllnCd3bgzd7Jnnwcgs9XEGTrLHPMqvK2YwukwM_WBufSaKeFne8X4nDaqnL6-DtqoMfbkiNLqXbvopuvp2QaN9eaHkmw82eg8x7iHld4HGP8sw_e-Q6nfw8uP7xzaK0BZlIFt5WrWlK79HL3L_-HKY3tcZ9KJeRHwFjnG08xJ50ylZuCkT3PEJ1VsOStPnbO9LS55w13LfEpBjeuc0THb0FqWUNq4YfUsmfgyU8BpJngd1y6ljzl1XGE_0xaaMDAWEayXgp5dGa1UWd3WmKNp5dq6SPVxiVxz8_BKq3zHBlW8ecEirUy7aU277o-bdONO53BVRzfzYpOAO6tqKLcydlrZTbwGHJfZO54yiIwcHi-K4WpKTXvYnx4FV1pmyVOqK1VFE2nHUXtOl-ICzTd519W2RUXkvXkMSJLofhWkdXTv6tNecCVkPG8X59CsvdMmlKvhUt5O7fa0fOmdq8DTQRt3FP-6w_acZE7S8HwzJKRGMZleWKvLvHavr7ZLU_VxN24A5_4BBu7QydSZXy2TU0EmIfNMLdY1IuuiNHWqMawEmqcSn7a-cpwvg7CshgHFxT60IYVW0m0jP4bLGvDpeLmC-W3r1KqrFkldtKaYWanVgKbjHXNfKQdWMh8rKSmgy0XQJtf9PeoFUeK0ZfUMVXtvnqBc7SFhioW-dLqWOfm0aD3sQLzKD8xTTG1PbY-7ka-OzjLMeOtCL4W56C0FV3N3hHhEp3lLJDh_daBupsqI_ysEf2raOkZF9NNnv_Dr7J2w_P713rOMghYXvc_ah6q4fte_ARfnWSJnr_6ma_YqvaDn7chTxnm0FFsKot0O3-_Z_9KC_IvSj1PqZ47lOF7kBJxQf0-6HE1-LnQdBkj7vuk-vnyB0X1ePYKcwgU7irlUQM9qMXSLd_cxQX3BWN8bg_9MqkIg_3ebpy11BSY5H25lXekdYuTjoE-SJcVusbhBoB-mRu0Pht0iaYN70Aftm87n8AtLQzqmcP_BQ5Zi-VhgYooHAcELPBNCjvlb95URiF_ar03yC_z61vUzLf1MbfEPwOqHfXj-qbLDowgumurtcTQ57O4kWpZr2VxQ1iE-5yUdcv5RVq3xHvYqlU8bh_C_6dWGBgY97sYmZ8wogmLmJDEnSZPgP2jqg2EXNC14s2_fvv0TX22jag.ZwjUoA.pitPRgpTPJyCaDMIr0TPpBG_lIc
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
-Sec-Fetch-Site: none
+Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Sec-Gpc: 1
Priority: u=0, i
@@ -75,29 +33,36 @@ Traceback: Traceback (most recent call last):
File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 865, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\product.py", line 113, in products
- model = Model_View_Store_Product(form_filters)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_product.py", line 101, in __init__
- self.category_list_filters, errors_filters = datastore_store.get_many_product(
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\datastores\datastore_store_base.py", line 110, in get_many_product
- category_list.add_product(new_product)
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\business_objects\store\product_category.py", line 337, in add_product
- self.categories[index_category].add_product(product)
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\business_objects\store\product_category.py", line 100, in add_product
- raise ValueError(f"{av.error_msg_str(product, 'product', _m, Product)}\nProduct already in category.")
-ValueError: Invalid Category.add_product argument product. Type = . Value = Product
- id_product: 1
- id_category: 1
- name: Braille Keyboard Translator
- display_order: 1
- can_view: False
- can_edit: False
- can_admin: False
- has_variations: True
- permutations: []
- variation trees: []
-
-Product already in category.
+ File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\stock_item.py", line 40, in stock_items
+ model = Model_View_Store_Stock_Item(form_filters)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_stock_item.py", line 89, in __init__
+ if product.id_category != self.form_filters.id_category.data and self.form_filters.id_category.data != '':
+ ^^^^^^^^^^^^^^^^^^^
+AttributeError: 'dict' object has no attribute 'id_category'
+Exception on /store/stock_items [GET]
+Traceback (most recent call last):
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 1473, in wsgi_app
+ response = self.full_dispatch_request()
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 882, in full_dispatch_request
+ rv = self.handle_user_exception(e)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask_cors\extension.py", line 178, in wrapped_function
+ return cors_after_request(app.make_response(f(*args, **kwargs)))
+ ^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 880, in full_dispatch_request
+ rv = self.dispatch_request()
+ ^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 865, in dispatch_request
+ return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\stock_item.py", line 40, in stock_items
+ model = Model_View_Store_Stock_Item(form_filters)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_stock_item.py", line 90, in __init__
+ print(f'product: {product}\n{product[Stock_Item.ATTR_ID_PRODUCT_CATEGORY]}\{nself.form_filters.id_category.data}')
+ ^^^^^
+NameError: name 'nself' is not defined. Did you mean: 'self'?
+Server Error: 500 Internal Server Error: The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.
diff --git a/app.log.3 b/app.log.3
index c9275d8f..f3930331 100644
--- a/app.log.3
+++ b/app.log.3
@@ -1,58 +1,16 @@
-Exception on /store/products [GET]
-Traceback (most recent call last):
- File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 1473, in wsgi_app
- response = self.full_dispatch_request()
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 882, in full_dispatch_request
- rv = self.handle_user_exception(e)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask_cors\extension.py", line 178, in wrapped_function
- return cors_after_request(app.make_response(f(*args, **kwargs)))
- ^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 880, in full_dispatch_request
- rv = self.dispatch_request()
- ^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 865, in dispatch_request
- return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\product.py", line 113, in products
- model = Model_View_Store_Product(form_filters)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_product.py", line 101, in __init__
- self.category_list_filters, errors_filters = datastore_store.get_many_product(
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\datastores\datastore_store_base.py", line 109, in get_many_product
- category_list.add_product(new_product)
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\business_objects\store\product_category.py", line 337, in add_product
- self.categories[index_category].add_product(product)
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\business_objects\store\product_category.py", line 100, in add_product
- raise ValueError(f"{av.error_msg_str(product, 'product', _m, Product)}\nProduct already in category.")
-ValueError: Invalid Category.add_product argument product. Type = . Value = Product
- id_product: 1
- id_category: 1
- name: Braille Keyboard Translator
- display_order: 1
- can_view: False
- can_edit: False
- can_admin: False
- has_variations: True
- permutations: []
- variation trees: []
-
-Product already in category.
-Server Error: 500 Internal Server Error: The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.
-Request: 127.0.0.1 GET http /store/products? Host: 127.0.0.1:5000
-User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0
+Request: 127.0.0.1 GET http /store/stock_items?id_category=3&id_product=3&is_out_of_stock=false&quantity_min=&quantity_max= Host: 127.0.0.1:5000
+User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate, br, zstd
+Referer: http://127.0.0.1:5000/store/stock_items?id_category=3&id_product=&is_out_of_stock=false&quantity_min=&quantity_max=
Dnt: 1
Connection: keep-alive
-Cookie: session=.eJytVlmzqkgS_isdRnQ_9fGyKyfixoyKAh5BQWR7IaCqkGJXQIGe-9-n8Nzu2w89W8REuFCVReaXlV8uv83Crk2qO24QvDToPnv_bQbCMghhgcugaas7mr239w79-qft7nXwcxcVIc5n7zMEn-EdzgsMYY7aqmwK3CZ_v07SOaiK2a-zGN-btgwLonBmIQgHsodhALr7HZVgCCCKwy5vZ-9ll-cv0R1dcVX-heATAP3HczA5QRG9r_9_CPySiUQeLEUeUmK4oKKQpmIUTwab4IU4eKA7jjGCs_c4zBv0kuAS5B1EMLBX1g-rn34ScdPVxNSfnW-6-3eHtN_9fjtPjs--kftq7nHQVhkqJ2AxRECkKQQBtVjwUBRYCjIAiSwLUMwxgAc8omiRQOy-hyEEADXNHxrQsE8iGeAj3mehq-LDZp9HhTat11p6YUxK11X8xKGrj2pa4VAxKaBowmEQM9_12qiESTiqTz31cz_1q6OccxHmaTDwCXTNStvwacRQD7Wk5nP69pEeN63Xs9qCtY7SPNPvelBJyWjCRoVL5xS_qcch6jvTfFv64zBIvtZq7DFmesA01INmH8M1UvcX6oPpRemNH24tqHUlTNHxKGin8-3UFH2lItye1Kpiec9glm9e6Ny2fT_y8IFF-Tgm0nmzUFSLSx4XvEykeC1KciuiJyuBvJIr1ts-ojI5yZuyP-XVclPvW1PHhxJFHYkuXgyHoaUT0fKTzEhE1m-kYH3gtos8o07W6iOV2coJ-BAd1K0aLJPuiQqVF_L1QU7PV1_sKnUXMzGIrxqDW3e4sSPd2HveXudvzaa63xB73nXJ5ZwPmmr2sd0v8rTJ8JA8alzRwZFyVsYQO81eFV0uyNvjkG9OaprWhwwgq8TRfC3rqwh_SLorJ9ytrKWjtpQNQgPU1_iOmiAkFKQXzIJb8Cwl_NjHhBRLgaOoVxb8BUvOl1Gldaw2amnyYKMKala79oasi7b2p3VpP5DrX8yM46J0__CVK21nu4O2S2hz2ItzoqwLHf0eFbvWP5MXCjuDzG7wN3wbOmYWyTYVMfwYOTkVvhTzSeRcJuO5r8AEFEZHZJkv9zmUxQ4wdA3lZOUzdBI6z85jxHaiLJDzFCr28GkjoaCyHo94-SDULEGxYzzXTAD-pKfn-gmUd8NhvIy-pBdaalCaBDPdIs4yHqfL3qAzeqJJgNNHE_uSR51YTdSl63NfqiKQQeFLdAUV8wmGy2icL4OJybfQM5IOf06FXMuIrWJHee5-3Ft72XeMDsh8OWGG7jojuHJ_JyZwusxUfRIsrSZlrZb6Fy1VBc26CJqkdZqljs4UiMJuPSdvpvT0HZMlerNDQde-bDa-axIq621I7BsyfJ07FPojOv94z2X9HBR5ETp2pqZ14Tn96J__DylP_PHcSSfBRcEbcs3eymjXYBIrdJPeGslN5TvBzhLXcHb5OauFS5FNJaj2XAMf0y2rpWA8Slee-Dvh5SbCaRYY9NEYdCl7agOJM2vjyQaxRYXSeqmnF04jCac7Gne07EyT8kQf19iztk-_sIsXN5j8E5eja2gLlShLSv3SmtEWjkamF7aUqOedeNEKj7HovW6UYMLVEV6mLz5luu3IKuXRJqex9tYo7Ifv7lL74vVTqasUVbPtymBpJ6WuPCmoSu4bT4aT1Nj4uLjMVcq8K7nM5Iykw5PnYLg2WXtVNxQ2Y1nBNAu45hQssjcufabSJUJ8TDJsOCtKCarTIj6p5rgZF0bAhdZtw36sFXf4WIVUsQKatH8AihMUwHCHmw2b2CrDTblqgnO81LitVfHr5NzXYXuWRy5ERd3E-TVZ9fx221egdsL6Lm8Fz1oeOit-eLlB6tSmaSk6CPEu_bAt2G0dUX-uFS4By_gSX_lYZy05FAWmk-W3Rx7oMtrwxoe9Pev1oQ8_qrRopdUTq3WlC8qyHMaTE-_larMbvVawbCE7DXfTrg8nuiL9mKSgnqzMnbq-YWXTNGi8Bt6T1K8GVPXUGclvieFP9b2KcY5--pwXfp29ClbQDq8zaxTeSdP77H24jKtX_-tIc55d5XRob7rmbJIz7m_HBWMao604qxDt9yS_Z__LCPIvWj8pqd9rLMOJFEsK6u9Fl10uPzeahhhI2rZu3r98gejxVj7DjKEEAcVCssR9Oe-a-Wv6mEx9Iba-Dwb_GVSJQfbvDk9HqhJM8s3FjThg9WwnrVGFbuCyo4m4xqDtpkHtD4TN_HoPH2Eb3l9wPh-_8CxkY4bjqAXkGX4RL7mYWYCQWiwXXAQF7m_NV25J_XL_Wl9_gV9fun5mVz8zO_IBsPzhH1l_qmzIE4LzurxOEcdTwBA49LJcKlf-w8jlZr2JraWiBBYTC0dTW7-o0UX_zazW1TBsyTQ2BWPGUAz3RolvjGAxzDvNv1PsnGZYf_bt27d_Agdyo3I.ZvXc6g.WpR0PQjTMWhM_qBkpa9CVzq95M8
+Cookie: session=.eJytVlnPqzgS_SutSN1PnVz25ZOuZsgGJIEkhLC9ILBZzB6WLPTc_z4m3-2-_dCzSSOFYLtMnVOuclX9NguGPq1b1EXw2kXt7OO3GQgqP4Alqvyur9to9tG3Q_Trn5aH98bP1agMUDH7mEXwEbRwUSIIi6ivq65Effr3ZJIuQF3Ofp3FqO36KiixwpkZQfjCawj6YGjbqAIvH0ZxMBT97KMaiuItaqME1dVfCD4JkH-M_ckIAut9v__BsQIViiwQRBYSYsATYUAScRRPgJ3_ZuzfoxbFKIKzjzgouugtQRUoBhhB35LMH6ifdmJxNzQY6s_Gd0P73SDtd7vnl8nw2Td8Xl0b-32dRxWWg1gAbMCIPA0ZhuBogqZCigAEB4OQJ7kwZCkYEhyHKQ7f3RAAEHXdHxqi1y4NZYCOaJcHjooOq10Rlto0X2rZlTIIXVfRAwWOPqpZjQLFIICicYeXmHuO24cVTINRfeiZV3iZVx_lggkRS4IXm0LHqLUVm2FKd7UiFgtn617dFzzsYq1Rzr26GJ8usLan_Fjvjp4S3kxnpUgyw87l89Vlo-3TlTJ_v2eq_c7Ir-y-7kb_DC-I2SRjv_GsRD8YZbvpu7AW2uU6NIqIu7KR4kXD7gga1iSSw3wv1kbp1-d-wzV3F6zmNrKeCsk37E0E-gPUQxhc-tS3SjkOLTeu9sXa4q5ZtexW_mEfS-5yL9-qOIOsHDUKhGDeHQebvMQrD5zkKyqsjFyVjO3UaJNzohNJqIwAyJJUURgakRfZv_hldqiGuRdJr3oEFSuU0s1FibD3hbBORZvZjfd4GOLVSVyGYyfuHF7zGN3oLdZkD-yqY5e677rg8MwZP7mE5dgHQx1LOcvMx_MT1OeKJ-nt3k6s8C4sYihlxHlT6KlkeU8arNC51iQcBtGzQW3U-QEOQZKnBJ4UaI77sY5wUAgcQxDvW_AXUXK5jiqpI7VTK4MFK5VT88axVnhe9o03zSvrHjne1cgZJsx2d09JSCvfHrRtShqvnbjAyobA1tuw3PbeBX9QWjmkti9vxfaBbeShbBEhxY6hXRDBWzGbhvZ1Ai88BaagPA9Ylnvys4CyOACKbKCcSh5FpoH9GFxK7KeQBXKRQcV6fWKkBFSW4xEJdxyaFSi3lOsYKUCf4ek6Xgrl7eswXkdvrZdadia0Ncx1ExtLuYwuuy-d0lNtDRh9NJC3dokTrYn6OnnsKlUEMii9NVlDxXiA13U8X64vA-Gn1HN8Hf58FQotx1jllnCd3bgzd7Jnnwcgs9XEGTrLHPMqvK2YwukwM_WBufSaKeFne8X4nDaqnL6-DtqoMfbkiNLqXbvopuvp2QaN9eaHkmw82eg8x7iHld4HGP8sw_e-Q6nfw8uP7xzaK0BZlIFt5WrWlK79HL3L_-HKY3tcZ9KJeRHwFjnG08xJ50ylZuCkT3PEJ1VsOStPnbO9LS55w13LfEpBjeuc0THb0FqWUNq4YfUsmfgyU8BpJngd1y6ljzl1XGE_0xaaMDAWEayXgp5dGa1UWd3WmKNp5dq6SPVxiVxz8_BKq3zHBlW8ecEirUy7aU277o-bdONO53BVRzfzYpOAO6tqKLcydlrZTbwGHJfZO54yiIwcHi-K4WpKTXvYnx4FV1pmyVOqK1VFE2nHUXtOl-ICzTd519W2RUXkvXkMSJLofhWkdXTv6tNecCVkPG8X59CsvdMmlKvhUt5O7fa0fOmdq8DTQRt3FP-6w_acZE7S8HwzJKRGMZleWKvLvHavr7ZLU_VxN24A5_4BBu7QydSZXy2TU0EmIfNMLdY1IuuiNHWqMawEmqcSn7a-cpwvg7CshgHFxT60IYVW0m0jP4bLGvDpeLmC-W3r1KqrFkldtKaYWanVgKbjHXNfKQdWMh8rKSmgy0XQJtf9PeoFUeK0ZfUMVXtvnqBc7SFhioW-dLqWOfm0aD3sQLzKD8xTTG1PbY-7ka-OzjLMeOtCL4W56C0FV3N3hHhEp3lLJDh_daBupsqI_ysEf2raOkZF9NNnv_Dr7J2w_P713rOMghYXvc_ah6q4fte_ARfnWSJnr_6ma_YqvaDn7chTxnm0FFsKot0O3-_Z_9KC_IvSj1PqZ47lOF7kBJxQf0-6HE1-LnQdBkj7vuk-vnyB0X1ePYKcwgU7irlUQM9qMXSLd_cxQX3BWN8bg_9MqkIg_3ebpy11BSY5H25lXekdYuTjoE-SJcVusbhBoB-mRu0Pht0iaYN70Aftm87n8AtLQzqmcP_BQ5Zi-VhgYooHAcELPBNCjvlb95URiF_ar03yC_z61vUzLf1MbfEPwOqHfXj-qbLDowgumurtcTQ57O4kWpZr2VxQ1iE-5yUdcv5RVq3xHvYqlU8bh_C_6dWGBgY97sYmZ8wogmLmJDEnSZPgP2jqg2EXNC14s2_fvv0TX22jag.ZwjUoA.pitPRgpTPJyCaDMIr0TPpBG_lIc
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
-Sec-Fetch-Site: none
+Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Sec-Gpc: 1
Priority: u=0, i
@@ -75,29 +33,36 @@ Traceback: Traceback (most recent call last):
File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 865, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\product.py", line 113, in products
- model = Model_View_Store_Product(form_filters)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_product.py", line 101, in __init__
- self.category_list_filters, errors_filters = datastore_store.get_many_product(
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\datastores\datastore_store_base.py", line 109, in get_many_product
- category_list.add_product(new_product)
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\business_objects\store\product_category.py", line 337, in add_product
- self.categories[index_category].add_product(product)
- File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\business_objects\store\product_category.py", line 100, in add_product
- raise ValueError(f"{av.error_msg_str(product, 'product', _m, Product)}\nProduct already in category.")
-ValueError: Invalid Category.add_product argument product. Type = . Value = Product
- id_product: 1
- id_category: 1
- name: Braille Keyboard Translator
- display_order: 1
- can_view: False
- can_edit: False
- can_admin: False
- has_variations: True
- permutations: []
- variation trees: []
-
-Product already in category.
+ File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\stock_item.py", line 40, in stock_items
+ model = Model_View_Store_Stock_Item(form_filters)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_stock_item.py", line 89, in __init__
+ self.form_filters.import_values(filters_stock_item)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+AttributeError: 'Filters_Stock_Item' object has no attribute 'import_values'
+Exception on /store/stock_items [GET]
+Traceback (most recent call last):
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 1473, in wsgi_app
+ response = self.full_dispatch_request()
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 882, in full_dispatch_request
+ rv = self.handle_user_exception(e)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask_cors\extension.py", line 178, in wrapped_function
+ return cors_after_request(app.make_response(f(*args, **kwargs)))
+ ^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 880, in full_dispatch_request
+ rv = self.dispatch_request()
+ ^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 865, in dispatch_request
+ return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\stock_item.py", line 40, in stock_items
+ model = Model_View_Store_Stock_Item(form_filters)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_stock_item.py", line 89, in __init__
+ if product.id_category != self.form_filters.id_category.data and self.form_filters.id_category.data != '':
+ ^^^^^^^^^^^^^^^^^^^
+AttributeError: 'dict' object has no attribute 'id_category'
+Server Error: 500 Internal Server Error: The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.
diff --git a/business_objects/__pycache__/__init__.cpython-312.pyc b/business_objects/__pycache__/__init__.cpython-312.pyc
index f3873cc2..69c5ed95 100644
Binary files a/business_objects/__pycache__/__init__.cpython-312.pyc and b/business_objects/__pycache__/__init__.cpython-312.pyc differ
diff --git a/business_objects/__pycache__/base.cpython-312.pyc b/business_objects/__pycache__/base.cpython-312.pyc
index 0dfde09f..5f33a95b 100644
Binary files a/business_objects/__pycache__/base.cpython-312.pyc and b/business_objects/__pycache__/base.cpython-312.pyc differ
diff --git a/business_objects/__pycache__/currency.cpython-312.pyc b/business_objects/__pycache__/currency.cpython-312.pyc
index d800db15..ba5f57da 100644
Binary files a/business_objects/__pycache__/currency.cpython-312.pyc and b/business_objects/__pycache__/currency.cpython-312.pyc differ
diff --git a/business_objects/__pycache__/db_base.cpython-312.pyc b/business_objects/__pycache__/db_base.cpython-312.pyc
index 2530a31a..52964c18 100644
Binary files a/business_objects/__pycache__/db_base.cpython-312.pyc and b/business_objects/__pycache__/db_base.cpython-312.pyc differ
diff --git a/business_objects/__pycache__/sql_error.cpython-312.pyc b/business_objects/__pycache__/sql_error.cpython-312.pyc
index 18727de8..734fe7ea 100644
Binary files a/business_objects/__pycache__/sql_error.cpython-312.pyc and b/business_objects/__pycache__/sql_error.cpython-312.pyc differ
diff --git a/business_objects/__pycache__/unit_measurement.cpython-312.pyc b/business_objects/__pycache__/unit_measurement.cpython-312.pyc
index 2747280a..1ac57a37 100644
Binary files a/business_objects/__pycache__/unit_measurement.cpython-312.pyc and b/business_objects/__pycache__/unit_measurement.cpython-312.pyc differ
diff --git a/business_objects/__pycache__/user.cpython-312.pyc b/business_objects/__pycache__/user.cpython-312.pyc
index 06e7cefe..1e34e0f0 100644
Binary files a/business_objects/__pycache__/user.cpython-312.pyc and b/business_objects/__pycache__/user.cpython-312.pyc differ
diff --git a/business_objects/address.py b/business_objects/address.py
new file mode 100644
index 00000000..78199060
--- /dev/null
+++ b/business_objects/address.py
@@ -0,0 +1,97 @@
+"""
+Project: PARTS Website
+Author: Edward Middleton-Smith
+ Precision And Research Technology Systems Limited
+
+Technology: Business Objects
+Feature: Address Business Object
+
+Description:
+Business object for address
+"""
+
+# internal
+import lib.argument_validation as av
+from business_objects.base import Base
+from business_objects.region import Region
+from extensions import db
+# external
+from typing import ClassVar
+
+
+class Address(db.Model, Base):
+ FLAG_ADDRESS_LINE_1: ClassVar[str] = 'address_line_1'
+ FLAG_ADDRESS_LINE_2: ClassVar[str] = 'address_line_2'
+ FLAG_CITY: ClassVar[str] = 'city'
+ FLAG_COUNTY: ClassVar[str] = 'county'
+ NAME_ATTR_OPTION_VALUE: ClassVar[str] = Base.ATTR_ID_ADDRESS
+ NAME_ATTR_OPTION_TEXT: ClassVar[str] = Base.FLAG_POSTCODE
+ __tablename__ = 'Shop_Address'
+ id_address = db.Column(db.Integer, primary_key=True)
+ id_region = db.Column(db.Integer)
+ postcode = db.Column(db.String(20))
+ address_line_1 = db.Column(db.String(256))
+ address_line_2 = db.Column(db.String(256))
+ city = db.Column(db.String(256))
+ county = db.Column(db.String(256))
+ active = db.Column(db.Boolean)
+
+ # region = None
+
+ def __init__(self):
+ super().__init__()
+ Base.__init__(self)
+ self.region = None
+ @classmethod
+ def from_DB_storage_location(cls, query_row):
+ address = cls()
+ address.id_address = query_row[2]
+ address.id_region = query_row[3]
+ return address
+ @classmethod
+ def from_DB_plant(cls, query_row):
+ address = cls()
+ address.id_address = query_row[1]
+ address.id_region = query_row[2]
+ @classmethod
+ def from_DB_stock_item(cls, query_row):
+ address = cls()
+ address.id_address = query_row[6]
+ address.id_region = query_row[7]
+ return address
+ def __repr__(self):
+ return f'''
+ {self.ATTR_ID_ADDRESS}: {self.id_address}
+ {self.FLAG_REGION}: {self.region}
+ {self.FLAG_POSTCODE}: {self.postcode}
+ {self.FLAG_ADDRESS_LINE_1}: {self.address_line_1}
+ {self.FLAG_ADDRESS_LINE_2}: {self.address_line_2}
+ {self.FLAG_CITY}: {self.city}
+ {self.FLAG_COUNTY}: {self.county}
+ {self.FLAG_ACTIVE}: {self.active}
+ '''
+ def to_json(self):
+ return {
+ **self.get_shared_json_attributes(self),
+ self.ATTR_ID_ADDRESS: self.id_address,
+ self.FLAG_REGION: self.region.to_json(),
+ self.FLAG_POSTCODE: self.postcode,
+ self.FLAG_ADDRESS_LINE_1: self.address_line_1,
+ self.FLAG_ADDRESS_LINE_2: self.address_line_2,
+ self.FLAG_CITY: self.city,
+ self.FLAG_COUNTY: self.county,
+ self.FLAG_ACTIVE: 1 if av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json') else 0
+ }
+ @classmethod
+ def from_json(cls, json):
+ print(f'{cls.__name__}.from_json: {json}')
+ address = cls()
+ address.id_address = json[cls.ATTR_ID_ADDRESS],
+ address.region = Region.from_json(json[cls.FLAG_REGION]),
+ address.postcode = json[cls.FLAG_POSTCODE],
+ address.address_line_1 = json[cls.FLAG_ADDRESS_LINE_1],
+ address.address_line_2 = json.get(cls.FLAG_ADDRESS_LINE_2, ''),
+ address.city = json[cls.FLAG_CITY],
+ address.county = json[cls.FLAG_COUNTY],
+ address.active = json[cls.FLAG_ACTIVE]
+ return address
diff --git a/business_objects/base.py b/business_objects/base.py
index c5b1a1b2..6d6c9a9a 100644
--- a/business_objects/base.py
+++ b/business_objects/base.py
@@ -19,15 +19,20 @@ from typing import ClassVar
class Base():
ATTR_ID_ACCESS_LEVEL: ClassVar[str] = 'id_access_level'
+ ATTR_ID_ADDRESS: ClassVar[str] = 'id_address'
ATTR_ID_CURRENCY: ClassVar[str] = 'id_currency'
- ATTR_ID_DELIVERY_REGION: ClassVar[str] = 'id_delivery_region'
+ ATTR_ID_REGION: ClassVar[str] = 'id_region'
ATTR_ID_USER: ClassVar[str] = 'id_user'
+ ATTR_ID_USER_MANAGER: ClassVar[str] = 'id_user_manager'
FLAG_ACCESS_LEVEL_REQUIRED: ClassVar[str] = 'access_level_required'
FLAG_ACTIVE: ClassVar[str] = 'active'
+ FLAG_ADDRESS: ClassVar[str] = 'address'
FLAG_CAN_ADMIN: ClassVar[str] = 'can_admin'
FLAG_CAN_EDIT: ClassVar[str] = 'can_edit'
FLAG_CAN_VIEW: ClassVar[str] = 'can_view'
FLAG_CODE: ClassVar[str] = 'code'
+ FLAG_CURRENCY: ClassVar[str] = 'currency'
+ FLAG_CURRENCY_COST: ClassVar[str] = 'currency_cost'
FLAG_DESCRIPTION: ClassVar[str] = 'description'
FLAG_DISPLAY_ORDER: ClassVar[str] = 'display_order'
FLAG_GUID: ClassVar[str] = 'guid'
@@ -38,10 +43,14 @@ class Base():
FLAG_NAME_ATTR_OPTION_VALUE: ClassVar[str] = 'NAME_ATTR_OPTION_VALUE'
FLAG_NAME_SINGULAR: ClassVar[str] = 'name_singular'
FLAG_NAME_PLURAL: ClassVar[str] = 'name_plural'
+ FLAG_POSTCODE: ClassVar[str] = 'postcode'
FLAG_PRIORITY: ClassVar[str] = 'priority'
+ FLAG_REGION: ClassVar[str] = 'region'
FLAG_ROWS: ClassVar[str] = 'rows'
FLAG_SYMBOL: ClassVar[str] = 'symbol'
FLAG_URL: ClassVar[str] = 'url'
+ FLAG_VALUE_LOCAL_VAT_EXCL: ClassVar[str] = 'value_local_vat_excl'
+ FLAG_VALUE_LOCAL_VAT_INCL: ClassVar[str] = 'value_local_vat_incl'
NAME_ATTR_OPTION_TEXT: ClassVar[str] = 'name-attribute-option-text'
NAME_ATTR_OPTION_VALUE: ClassVar[str] = 'name-attribute-option-value'
diff --git a/business_objects/store/currency.py b/business_objects/currency.py
similarity index 93%
rename from business_objects/store/currency.py
rename to business_objects/currency.py
index eb67f2b9..5cfd09c6 100644
--- a/business_objects/store/currency.py
+++ b/business_objects/currency.py
@@ -81,6 +81,15 @@ class Currency(db.Model, Store_Base):
v_arg_type = 'class attribute'
currency = cls()
return currency
+ @classmethod
+ def from_DB_stock_item(cls, query_row):
+ _m = 'Currency.from_DB_get_many_stock_item'
+ v_arg_type = 'class attribute'
+ currency = cls()
+ currency.id_currency = query_row[12]
+ currency.code = query_row[13]
+ currency.symbol = query_row[14]
+ return currency
def __repr__(self):
return f'''
id: {self.id_currency}
diff --git a/business_objects/db_base.py b/business_objects/db_base.py
index d565b4a9..b711a9fd 100644
--- a/business_objects/db_base.py
+++ b/business_objects/db_base.py
@@ -30,11 +30,8 @@ class Get_Many_Parameters_Base(BaseModel, metaclass=ABCMeta):
@abstractmethod
def get_default(cls): # , id_user
pass
- """
- @abstractmethod
def to_json(self):
- pass
- """
+ return self.dict()
"""
@classmethod
@abstractmethod
diff --git a/business_objects/region.py b/business_objects/region.py
new file mode 100644
index 00000000..de0cff18
--- /dev/null
+++ b/business_objects/region.py
@@ -0,0 +1,82 @@
+"""
+Project: PARTS Website
+Author: Edward Middleton-Smith
+ Precision And Research Technology Systems Limited
+
+Technology: Business Objects
+Feature: Address Region Business Object
+
+Description:
+Business object for address region
+"""
+
+# internal
+import lib.argument_validation as av
+from business_objects.base import Base
+from extensions import db
+# external
+from typing import ClassVar
+
+
+class Region(db.Model, Base):
+ NAME_ATTR_OPTION_VALUE: ClassVar[str] = Base.ATTR_ID_REGION
+ NAME_ATTR_OPTION_TEXT: ClassVar[str] = Base.FLAG_NAME
+ __tablename__ = 'Shop_Region'
+ id_region = db.Column(db.Integer, primary_key=True)
+ code = db.Column(db.String(50))
+ name = db.Column(db.String(200))
+ active = db.Column(db.Boolean)
+
+ # region = None
+
+ def __init__(self):
+ super().__init__()
+ Base.__init__(self)
+ self.region = None
+
+ @classmethod
+ def from_DB_stock_item(cls, query_row):
+ plant = cls()
+ plant.id_region = query_row[7]
+ return plant
+ def __repr__(self):
+ return f'''
+ {self.ATTR_ID_REGION}: {self.id_region}
+ {self.FLAG_CODE}: {self.code}
+ {self.FLAG_NAME}: {self.name}
+ {self.FLAG_ACTIVE}: {self.active}
+ '''
+ def to_json(self):
+ return {
+ **self.get_shared_json_attributes(self),
+ self.ATTR_ID_REGION: self.id_region,
+ self.FLAG_CODE: self.code,
+ self.FLAG_NAME: self.name,
+ self.FLAG_ACTIVE: 1 if av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json') else 0
+ }
+ @classmethod
+ def from_json(cls, json):
+ print(f'{cls.__name__}.from_json: {json}')
+ plant = cls()
+ plant.id_region = json[cls.ATTR_ID_REGION]
+ plant.code = json[cls.FLAG_CODE]
+ plant.name = json[cls.FLAG_NAME]
+ plant.active = json[cls.FLAG_ACTIVE]
+ return plant
+ @classmethod
+ def from_DB_get_many_product_catalogue(cls, query_row):
+ region = cls()
+ region.id_region = query_row[0]
+ region.name = query_row[1]
+ region.code = query_row[2]
+ # self.display_order = query_row[3]
+ return region
+ @classmethod
+ def from_DB_region(cls, query_row):
+ region = cls()
+ region.id_region = query_row[0]
+ region.code = query_row[1]
+ region.name = query_row[2]
+ region.active = av.input_bool(query_row[3], cls.FLAG_ACTIVE, f'{cls.__name__}.from_DB_region')
+ region.display_order = query_row[4]
+ return region
diff --git a/business_objects/store/__pycache__/__init__.cpython-312.pyc b/business_objects/store/__pycache__/__init__.cpython-312.pyc
index 88186d32..1a9c3397 100644
Binary files a/business_objects/store/__pycache__/__init__.cpython-312.pyc and b/business_objects/store/__pycache__/__init__.cpython-312.pyc differ
diff --git a/business_objects/store/__pycache__/access_level.cpython-312.pyc b/business_objects/store/__pycache__/access_level.cpython-312.pyc
index 0253f0ed..3ab5f776 100644
Binary files a/business_objects/store/__pycache__/access_level.cpython-312.pyc and b/business_objects/store/__pycache__/access_level.cpython-312.pyc differ
diff --git a/business_objects/store/__pycache__/basket.cpython-312.pyc b/business_objects/store/__pycache__/basket.cpython-312.pyc
index e432aded..af53b5b5 100644
Binary files a/business_objects/store/__pycache__/basket.cpython-312.pyc and b/business_objects/store/__pycache__/basket.cpython-312.pyc differ
diff --git a/business_objects/store/__pycache__/currency.cpython-312.pyc b/business_objects/store/__pycache__/currency.cpython-312.pyc
index 81cebae2..5066849f 100644
Binary files a/business_objects/store/__pycache__/currency.cpython-312.pyc and b/business_objects/store/__pycache__/currency.cpython-312.pyc differ
diff --git a/business_objects/store/__pycache__/delivery_option.cpython-312.pyc b/business_objects/store/__pycache__/delivery_option.cpython-312.pyc
index c5117e83..178a1e92 100644
Binary files a/business_objects/store/__pycache__/delivery_option.cpython-312.pyc and b/business_objects/store/__pycache__/delivery_option.cpython-312.pyc differ
diff --git a/business_objects/store/__pycache__/delivery_region.cpython-312.pyc b/business_objects/store/__pycache__/delivery_region.cpython-312.pyc
index 07582857..0cc1259e 100644
Binary files a/business_objects/store/__pycache__/delivery_region.cpython-312.pyc and b/business_objects/store/__pycache__/delivery_region.cpython-312.pyc differ
diff --git a/business_objects/store/__pycache__/discount.cpython-312.pyc b/business_objects/store/__pycache__/discount.cpython-312.pyc
index aeb74573..77e3cbe7 100644
Binary files a/business_objects/store/__pycache__/discount.cpython-312.pyc and b/business_objects/store/__pycache__/discount.cpython-312.pyc differ
diff --git a/business_objects/store/__pycache__/image.cpython-312.pyc b/business_objects/store/__pycache__/image.cpython-312.pyc
index e7fabaf6..1ecc355a 100644
Binary files a/business_objects/store/__pycache__/image.cpython-312.pyc and b/business_objects/store/__pycache__/image.cpython-312.pyc differ
diff --git a/business_objects/store/__pycache__/order.cpython-312.pyc b/business_objects/store/__pycache__/order.cpython-312.pyc
index c700bb9b..2f778f4a 100644
Binary files a/business_objects/store/__pycache__/order.cpython-312.pyc and b/business_objects/store/__pycache__/order.cpython-312.pyc differ
diff --git a/business_objects/store/__pycache__/product.cpython-312.pyc b/business_objects/store/__pycache__/product.cpython-312.pyc
index 979001ec..3f2fa807 100644
Binary files a/business_objects/store/__pycache__/product.cpython-312.pyc and b/business_objects/store/__pycache__/product.cpython-312.pyc differ
diff --git a/business_objects/store/__pycache__/product_category.cpython-312.pyc b/business_objects/store/__pycache__/product_category.cpython-312.pyc
index 2b5014df..88c29724 100644
Binary files a/business_objects/store/__pycache__/product_category.cpython-312.pyc and b/business_objects/store/__pycache__/product_category.cpython-312.pyc differ
diff --git a/business_objects/store/__pycache__/product_permutation.cpython-312.pyc b/business_objects/store/__pycache__/product_permutation.cpython-312.pyc
index 3a940a64..32ad0912 100644
Binary files a/business_objects/store/__pycache__/product_permutation.cpython-312.pyc and b/business_objects/store/__pycache__/product_permutation.cpython-312.pyc differ
diff --git a/business_objects/store/__pycache__/product_price.cpython-312.pyc b/business_objects/store/__pycache__/product_price.cpython-312.pyc
index 3e0e4093..e976231d 100644
Binary files a/business_objects/store/__pycache__/product_price.cpython-312.pyc and b/business_objects/store/__pycache__/product_price.cpython-312.pyc differ
diff --git a/business_objects/store/__pycache__/product_variation.cpython-312.pyc b/business_objects/store/__pycache__/product_variation.cpython-312.pyc
index 62365a3e..84edbaa3 100644
Binary files a/business_objects/store/__pycache__/product_variation.cpython-312.pyc and b/business_objects/store/__pycache__/product_variation.cpython-312.pyc differ
diff --git a/business_objects/store/__pycache__/product_variation_tree.cpython-312.pyc b/business_objects/store/__pycache__/product_variation_tree.cpython-312.pyc
index 6664205a..ccd19133 100644
Binary files a/business_objects/store/__pycache__/product_variation_tree.cpython-312.pyc and b/business_objects/store/__pycache__/product_variation_tree.cpython-312.pyc differ
diff --git a/business_objects/store/__pycache__/product_variation_type.cpython-312.pyc b/business_objects/store/__pycache__/product_variation_type.cpython-312.pyc
index 45656987..e2236a27 100644
Binary files a/business_objects/store/__pycache__/product_variation_type.cpython-312.pyc and b/business_objects/store/__pycache__/product_variation_type.cpython-312.pyc differ
diff --git a/business_objects/store/__pycache__/stock_item.cpython-312.pyc b/business_objects/store/__pycache__/stock_item.cpython-312.pyc
index 76337416..737bdff6 100644
Binary files a/business_objects/store/__pycache__/stock_item.cpython-312.pyc and b/business_objects/store/__pycache__/stock_item.cpython-312.pyc differ
diff --git a/business_objects/store/__pycache__/store_base.cpython-312.pyc b/business_objects/store/__pycache__/store_base.cpython-312.pyc
index bdb86d5e..531592b9 100644
Binary files a/business_objects/store/__pycache__/store_base.cpython-312.pyc and b/business_objects/store/__pycache__/store_base.cpython-312.pyc differ
diff --git a/business_objects/store/delivery_option.py b/business_objects/store/delivery_option.py
index 36e4c0b6..2dd7ab6c 100644
--- a/business_objects/store/delivery_option.py
+++ b/business_objects/store/delivery_option.py
@@ -22,7 +22,7 @@ class Delivery_Option():
delay_max: int
quantity_min: float
quantity_max: float
- regions: list # [Enum_Delivery_Region]
+ regions: list # [Enum_Region]
cost: float
def __new__(cls, name, delay_min, delay_max, quantity_min, quantity_max, regions, cost):
@@ -33,7 +33,7 @@ class Delivery_Option():
av.val_int(delay_max, 'delay_max', _m, 0, v_arg_type = v_arg_type)
av.val_float(quantity_min, 'quantity_min', _m, 0, v_arg_type = v_arg_type)
av.val_float(quantity_max, 'quantity_max', _m, 0, v_arg_type = v_arg_type)
- av.val_list_instances(regions, 'regions', _m, Enum_Delivery_Region, v_arg_type = v_arg_type)
+ av.val_list_instances(regions, 'regions', _m, Enum_Region, v_arg_type = v_arg_type)
av.val_float(cost, 'cost', _m, 0, v_arg_type = v_arg_type)
return super(Delivery_Option, cls).__new__(cls)
diff --git a/business_objects/store/delivery_region.py b/business_objects/store/delivery_region.py
deleted file mode 100644
index 94516b64..00000000
--- a/business_objects/store/delivery_region.py
+++ /dev/null
@@ -1,103 +0,0 @@
-"""
-Project: PARTS Website
-Author: Edward Middleton-Smith
- Precision And Research Technology Systems Limited
-
-Technology: Business Objects
-Feature: Delivery Region Business Object
-
-Description:
-Business object for delivery region
-"""
-
-# internal
-from business_objects.store.store_base import Store_Base
-from extensions import db
-from lib import argument_validation as av
-# external
-from enum import Enum
-from typing import ClassVar
-
-
-class Enum_Delivery_Region(Enum):
- UK = 0
-
-class Delivery_Region(db.Model, Store_Base):
- NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_DELIVERY_REGION
- NAME_ATTR_OPTION_TEXT: ClassVar[str] = Store_Base.FLAG_NAME
-
- id_region = db.Column(db.Integer, primary_key=True)
- """
- id_category = db.Column(db.Integer)
- id_product = db.Column(db.Integer)
- id_discount = db.Column(db.Integer)
- """
- code = db.Column(db.String(50))
- name = db.Column(db.String(200))
- active = db.Column(db.Boolean)
- display_order = db.Column(db.Integer)
- """
- def __new__(cls, id, id_category, id_product, id_discount, code, name, display_order):
- _m = 'Delivery_Region.__new__'
- v_arg_type = 'class attribute'
- av.val_int(id, 'id', _m, 0, v_arg_type = v_arg_type)
- av.val_int(id_category, 'id_category', _m, 0, v_arg_type=v_arg_type)
- av.val_int(id_product, 'id_product', _m, 0, v_arg_type = v_arg_type)
- av.val_int(id_discount, 'id_discount', _m, v_arg_type = v_arg_type)
- av.val_str(code, 'code', _m, max_len = 50, v_arg_type = v_arg_type)
- av.val_str(name, 'name', _m, max_len = 100, v_arg_type = v_arg_type)
- av.val_int(display_order, 'display_order', _m, v_arg_type = v_arg_type)
- return super(Delivery_Region, cls).__new__(cls)
-
- def __init__(self, id, id_category, id_product, id_discount, code, name, display_order):
- self.id_region = id
- self.id_category = id_category
- self.id_product = id_product
- self.id_discount = id_discount
- self.name = name
- self.code = code
- self.display_order = display_order
- """
- @classmethod
- def from_DB_get_many_product_catalogue(cls, query_row):
- region = cls()
- region.id_region = query_row[0]
- region.name = query_row[1]
- region.code = query_row[2]
- # self.display_order = query_row[3]
- return region
- @classmethod
- def from_DB_region(cls, query_row):
- region = cls()
- region.id_region = query_row[0]
- region.code = query_row[1]
- region.name = query_row[2]
- region.active = av.input_bool(query_row[3], cls.FLAG_ACTIVE, f'{cls.__name__}.from_DB_region')
- region.display_order = query_row[4]
- return region
- def __repr__(self):
- return f'''
- id: {self.id_region}
- name: {self.name}
- code: {self.code}
- active: {self.active}
- display_order: {self.display_order}
- '''
- def to_json(self):
- return {
- **self.get_shared_json_attributes(self),
- self.ATTR_ID_REGION: self.id_region,
- self.FLAG_CODE: self.code,
- self.FLAG_NAME: self.name,
- self.FLAG_ACTIVE: self.active,
- self.FLAG_DISPLAY_ORDER: self.display_order
- }
- @staticmethod
- def from_json(json_region):
- region = Delivery_Region()
- region.id_region = json_region[Delivery_Region.ATTR_ID_REGION]
- region.code = json_region[Delivery_Region.FLAG_CODE]
- region.name = json_region[Delivery_Region.FLAG_NAME]
- region.active = json_region[Delivery_Region.FLAG_ACTIVE]
- region.display_order = json_region[Delivery_Region.FLAG_DISPLAY_ORDER]
- return region
diff --git a/business_objects/store/plant.py b/business_objects/store/plant.py
new file mode 100644
index 00000000..ec4d6c8a
--- /dev/null
+++ b/business_objects/store/plant.py
@@ -0,0 +1,92 @@
+"""
+Project: PARTS Website
+Author: Edward Middleton-Smith
+ Precision And Research Technology Systems Limited
+
+Technology: Business Objects
+Feature: Plant Business Object
+
+Description:
+Business object for plant
+"""
+
+# internal
+import lib.argument_validation as av
+from business_objects.address import Address
+from business_objects.store.store_base import Store_Base
+from extensions import db
+# external
+from typing import ClassVar
+
+
+class Plant(db.Model, Store_Base):
+ NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_PLANT
+ NAME_ATTR_OPTION_TEXT: ClassVar[str] = Store_Base.FLAG_NAME
+ __tablename__ = 'Shop_Plant'
+ id_plant = db.Column(db.Integer, primary_key=True)
+ code = db.Column(db.String(50))
+ name = db.Column(db.String(255))
+ id_address = db.Column(db.Integer)
+ id_user_manager = db.Column(db.Integer)
+ active = db.Column(db.Boolean)
+
+ # address = None
+
+ def __init__(self):
+ super().__init__()
+ Store_Base.__init__(self)
+ self.address = None
+ @classmethod
+ def from_DB_storage_location(cls, query_row):
+ plant = cls()
+ plant.id_plant = query_row[1]
+ plant.id_address = query_row[2]
+ plant.address = Address.from_DB_storage_location(query_row)
+ return plant
+ @classmethod
+ def from_DB_plant(cls, query_row):
+ plant = cls()
+ plant.id_plant = query_row[0]
+ plant.id_address = query_row[1]
+ plant.address = Address.from_DB_plant(query_row)
+ plant.code = query_row[4]
+ plant.name = query_row[5]
+ plant.active = query_row[6]
+ return plant
+ @classmethod
+ def from_DB_stock_item(cls, query_row):
+ plant = cls()
+ plant.id_plant = query_row[5]
+ plant.code = query_row[10]
+ plant.name = query_row[11]
+ return plant
+ def __repr__(self):
+ return f'''
+ {self.ATTR_ID_PLANT}: {self.id_plant}
+ {self.FLAG_CODE}: {self.code}
+ {self.FLAG_NAME}: {self.name}
+ {self.FLAG_ADDRESS}: {self.address}
+ {self.ATTR_ID_USER_MANAGER}: {self.id_user_manager}
+ {self.FLAG_ACTIVE}: {self.active}
+ '''
+ def to_json(self):
+ return {
+ **self.get_shared_json_attributes(self),
+ self.ATTR_ID_PLANT: self.id_plant,
+ self.FLAG_CODE: self.code,
+ self.FLAG_NAME: self.name,
+ self.FLAG_ADDRESS: self.address.to_json(),
+ self.ATTR_ID_USER_MANAGER: self.id_user_manager,
+ self.FLAG_ACTIVE: 1 if av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json') else 0
+ }
+ @classmethod
+ def from_json(cls, json):
+ print(f'{cls.__name__}.from_json: {json}')
+ plant = cls()
+ plant.id_plant = json[cls.ATTR_ID_PLANT],
+ plant.code = json[cls.FLAG_CODE],
+ plant.name = json[cls.FLAG_NAME],
+ plant.address = Address.from_json(json[cls.FLAG_ADDRESS]),
+ plant.id_user_manager = json[cls.ATTR_ID_USER_MANAGER],
+ plant.active = json[cls.FLAG_ACTIVE]
+ return plant
diff --git a/business_objects/store/product.py b/business_objects/store/product.py
index 7f1e460d..b04362ad 100644
--- a/business_objects/store/product.py
+++ b/business_objects/store/product.py
@@ -175,7 +175,7 @@ class Product(SQLAlchemy_ABC, Store_Base):
if self.variation_trees[index_tree].is_equal(variation_tree):
found_variation_tree_match = True
break
- if not found_variation_tree_match:
+ if not found_variation_tree_match and variation_tree is not None:
self.variation_trees.append(variation_tree)
def from_DB_Stripe_product(query_row):
permutation = Product_Permutation.from_DB_Stripe_product(query_row)
@@ -374,6 +374,13 @@ class Product(SQLAlchemy_ABC, Store_Base):
text_input += tree.get_text_input_types()
return text_input
"""
+ def get_csv_ids_permutation(self):
+ csv = ''
+ for permutation in self.permutations:
+ if csv != '':
+ csv += ','
+ csv += str(permutation.id_permutation)
+ return csv
class Parameters_Product(Get_Many_Parameters_Base):
@@ -482,7 +489,7 @@ class Parameters_Product(Get_Many_Parameters_Base):
@staticmethod
def from_form_filters_product_permutation(form):
# if not (form is Filters_Product_Permutation): raise ValueError(f'Invalid form type: {type(form)}')
- av.val_instance(form, 'form', 'Parameters_Product.from_form', Filters_Product_Permutation)
+ # av.val_instance(form, 'form', 'Parameters_Product.from_form', Filters_Product_Permutation)
has_category_filter = not (form.id_category.data == '0' or form.id_category.data == '')
has_product_filter = not (form.id_product.data == '0' or form.id_product.data == '')
get_permutations_stock_below_min = av.input_bool(form.is_out_of_stock.data, "is_out_of_stock", "Parameters_Product.from_form")
@@ -491,11 +498,11 @@ class Parameters_Product(Get_Many_Parameters_Base):
get_all_product_category = not has_category_filter,
get_inactive_product_category = False,
# get_first_product_category_only = False,
- ids_product_category = form.id_category.data,
+ ids_product_category = form.id_category.data if form.id_category.data is not None else '',
get_all_product = not has_product_filter,
get_inactive_product = False,
# get_first_product_only = False,
- ids_product = form.id_product.data,
+ ids_product = form.id_product.data if form.id_product.data is not None else '',
get_all_permutation = not get_permutations_stock_below_min,
get_inactive_permutation = False,
# get_first_permutation_only = False,
@@ -601,6 +608,9 @@ class Parameters_Product(Get_Many_Parameters_Base):
ids_image = '',
get_products_quantity_stock_below_min = False
)
+ @classmethod
+ def from_filters_stock_item(cls, filters_stock_item):
+ return cls.from_form_filters_product_permutation(filters_stock_item)
"""
class Parameters_Product(Get_Many_Parameters_Base):
diff --git a/business_objects/store/product_category.py b/business_objects/store/product_category.py
index cf000111..a025347a 100644
--- a/business_objects/store/product_category.py
+++ b/business_objects/store/product_category.py
@@ -242,6 +242,11 @@ class Product_Category(SQLAlchemy_ABC, Store_Base):
'value': self.id_category,
'text': self.name
}
+ def get_csv_ids_permutation(self):
+ list_ids = []
+ for product in self.products:
+ list_ids += product.get_csv_ids_permutation()
+ return list_ids
"""
class Filters_Product_Category(BaseModel, Store_Base):
ids_product_category: str
@@ -433,6 +438,11 @@ class Product_Category_Container(Store_Base):
if column.name not in ['created_on', 'created_by']
}
return self.to_object_with_missing_attributes(excluded_attributes)
+ def get_csv_ids_permutation(self):
+ list_ids = []
+ for category in self.categories:
+ list_ids += category.get_csv_ids_permutation()
+ return ','.join(list_ids)
"""
diff --git a/business_objects/store/product_permutation.py b/business_objects/store/product_permutation.py
index ee9285f2..faee9018 100644
--- a/business_objects/store/product_permutation.py
+++ b/business_objects/store/product_permutation.py
@@ -14,7 +14,7 @@ Business object for product permutation
import lib.argument_validation as av
from lib import data_types
from forms.forms import Form_Basket_Add, Form_Basket_Edit
-from business_objects.store.currency import Currency
+from business_objects.currency import Currency
from business_objects.store.delivery_option import Delivery_Option
from business_objects.store.discount import Discount
from business_objects.store.image import Image
@@ -309,6 +309,7 @@ class Product_Permutation(db.Model, Store_Base):
'value': self.id_permutation,
'text': self.get_name_variations()
}
+
def get_name(self):
return
def get_name_variations(self):
@@ -317,19 +318,14 @@ class Product_Permutation(db.Model, Store_Base):
return len(self.prices) > 0
def get_price(self):
return self.prices[0]
- def get_price_local_VAT_incl(self):
- price = self.get_price()
- return price.value_local_VAT_incl
- def get_price_local_VAT_excl(self):
- price = self.get_price()
- return price.value_local_VAT_excl
- def output_lead_time(self):
- return '1 day' if self.latency_manufacture_days == 1 else f'{self.latency_manufacture_days} days'
-
def output_delivery_date(self):
return (datetime.now() + timedelta(days=self.latency_manufacture_days)).strftime('%A, %d %B %Y')
+ """
+ def output_lead_time(self):
+ return '1 day' if self.latency_manufacture_days == 1 else f'{self.latency_manufacture_days} days'
+
def output_price(self, is_included_VAT):
if self.is_unavailable_in_currency_or_region:
return 'Not available in currency and region'
@@ -341,33 +337,14 @@ class Product_Permutation(db.Model, Store_Base):
return f'{price.symbol_currency} {locale.format_string("%d", price.value_local_VAT_incl, grouping=True)}'
else:
return f'{price.symbol_currency} {locale.format_string("%d", price.value_local_VAT_excl, grouping=True)}'
- def output_currency(self):
- if not self.is_available:
- return ''
- """
- price = self.get_price()
- return price.code_currency
- """
- return self.code_currency_cost if self.symbol_currency_cost == '' else self.symbol_currency_cost
+ """
def output_variations(self):
if not self.has_variations: return ''
return '\n'.join([f'{variation.name_variation_type}: {variation.name_variation}' for variation in self.variations])
def output_variations_jsonify(self):
if not self.has_variations: return ''
return ','.join([f'{variation.id_type}: {variation.id_variation}' for variation in self.variations])
- """
- def output_price_VAT_incl(self):
- locale.setlocale(locale.LC_ALL, '')
- return locale.format_string("%d", self.price_GBP_VAT_incl, grouping=True)
- def output_price_VAT_excl(self):
- locale.setlocale(locale.LC_ALL, '')
- return locale.format_string("%d", self.price_GBP_VAT_excl, grouping=True)
- def add_form_basket_add(self):
- self.form_basket_add = None
-
- def add_form_basket_edit(self):
- self.form_basket_edit = None
- """
+
def __repr__(self):
return f'''Product_Permutation
id_permutation: {self.id_permutation}
diff --git a/business_objects/store/product_price.py b/business_objects/store/product_price.py
index 10b58739..4822836c 100644
--- a/business_objects/store/product_price.py
+++ b/business_objects/store/product_price.py
@@ -11,8 +11,8 @@ Business object for product price
"""
# internal
-from business_objects.store.currency import Currency
-from business_objects.store.delivery_region import Delivery_Region
+from business_objects.currency import Currency
+from business_objects.region import Region
from business_objects.store.store_base import Store_Base
from extensions import db
# external
@@ -22,8 +22,6 @@ from typing import ClassVar
class Product_Price(db.Model, Store_Base):
NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_PRODUCT_PRICE
NAME_ATTR_OPTION_TEXT = Store_Base.FLAG_TEXT
- FLAG_VALUE_LOCAL_VAT_INCL: ClassVar[str] = 'value-local-vat-incl'
- FLAG_VALUE_LOCAL_VAT_EXCL: ClassVar[str] = 'value-local-vat-excl'
id_price = db.Column(db.Integer, primary_key=True)
id_permutation = db.Column(db.Integer)
@@ -87,7 +85,7 @@ class Product_Price(db.Model, Store_Base):
self.ATTR_ID_PRODUCT: self.id_product,
self.ATTR_ID_PRODUCT_CATEGORY: self.id_category,
self.FLAG_CURRENCY: self.currency.to_json(),
- # Delivery_Region.ATTR_ID_DELIVERY_REGION: self.id_region,
+ # Region.ATTR_ID_REGION_DELIVERY: self.id_region,
self.FLAG_VALUE_LOCAL_VAT_INCL: self.value_local_VAT_incl,
self.FLAG_VALUE_LOCAL_VAT_EXCL: self.value_local_VAT_excl,
self.FLAG_DISPLAY_ORDER: self.display_order
@@ -101,7 +99,7 @@ class Product_Price(db.Model, Store_Base):
price.id_product = json[cls.ATTR_ID_PRODUCT]
price.id_category = json[cls.ATTR_ID_PRODUCT_CATEGORY]
price.currency = Currency.from_json(json)
- # price.id_region = json[Delivery_Region.ATTR_ID_DELIVERY_REGION]
+ # price.id_region = json[Region.ATTR_ID_REGION_DELIVERY]
price.value_local_VAT_incl = json[cls.FLAG_VALUE_LOCAL_VAT_INCL]
price.value_local_VAT_excl = json[cls.FLAG_VALUE_LOCAL_VAT_EXCL]
price.display_order = json[cls.FLAG_DISPLAY_ORDER]
diff --git a/business_objects/store/product_variation_tree.py b/business_objects/store/product_variation_tree.py
index 392c8798..c434b746 100644
--- a/business_objects/store/product_variation_tree.py
+++ b/business_objects/store/product_variation_tree.py
@@ -82,6 +82,7 @@ class Product_Variation_Tree():
@classmethod
def from_json_str(cls, json_str):
variations = []
+ if json_str is None or json_str == '': return None
for json_variation in json_str.split(','):
parts = json_variation.split(':')
if len(parts) != 2: continue
diff --git a/business_objects/store/stock_item.py b/business_objects/store/stock_item.py
index df44f8d9..6ecfc783 100644
--- a/business_objects/store/stock_item.py
+++ b/business_objects/store/stock_item.py
@@ -13,13 +13,15 @@ import lib.argument_validation as av
from lib import data_types
from forms.store.stock_item import Filters_Stock_Item
from business_objects.db_base import Get_Many_Parameters_Base
-from business_objects.store.product_price import Product_Price
+from business_objects.currency import Currency
# from business_objects.discount import Discount
+from business_objects.store.product_variation_tree import Product_Variation_Tree
+from business_objects.store.storage_location import Storage_Location
from business_objects.store.store_base import Store_Base
from extensions import db
# external
from dataclasses import dataclass
-from typing import ClassVar
+from typing import ClassVar, Optional
from datetime import datetime
@@ -34,21 +36,19 @@ class Stock_Item(db.Model, Store_Base):
FLAG_DATE_UNSEALED: ClassVar[str] = 'date_unsealed'
FLAG_IS_CONSUMED: ClassVar[str] = 'is_consumed'
FLAG_IS_SEALED: ClassVar[str] = 'is_sealed'
- FLAG_VALUE_LOCAL_VAT_EXCL_COST: ClassVar[str] = f'{Product_Price.FLAG_VALUE_LOCAL_VAT_EXCL}_cost'
- FLAG_VALUE_LOCAL_VAT_INCL_COST: ClassVar[str] = f'{Product_Price.FLAG_VALUE_LOCAL_VAT_INCL}_cost'
id_stock = db.Column(db.Integer, primary_key=True)
id_permutation = db.Column(db.Integer)
id_product = db.Column(db.Integer)
id_category = db.Column(db.Integer)
- # name_category = db.Column(db.String(255))
- # name_product = db.Column(db.String(255))
+ id_location_storage = db.Column(db.Integer)
+ id_plant = db.Column(db.Integer)
+ id_region = db.Column(db.Integer)
+ id_currency_cost = db.Column(db.Integer)
+ cost_local_VAT_excl = db.Column(db.Float)
+ cost_local_VAT_incl = db.Column(db.Float)
date_purchased = db.Column(db.DateTime)
date_received = db.Column(db.DateTime)
- id_location_storage = db.Column(db.Integer)
- id_currency_cost = db.Column(db.Integer)
- cost_local_VAT_incl = db.Column(db.Float)
- cost_local_VAT_excl = db.Column(db.Float)
is_sealed = db.Column(db.Boolean)
date_unsealed = db.Column(db.DateTime)
date_expiration = db.Column(db.DateTime)
@@ -60,10 +60,15 @@ class Stock_Item(db.Model, Store_Base):
can_edit = db.Column(db.Boolean)
can_admin = db.Column(db.Boolean)
"""
+ # variation_tree: Product_Variation_Tree = None
def __init__(self):
super().__init__()
Store_Base.__init__(self)
+ self.currency_cost = None
+ self.storage_location = None
+ self.variation_tree = None
+ self.has_variations = False
def from_DB_stock_item(query_row):
_m = 'Product.from_DB_stock_item'
@@ -73,21 +78,20 @@ class Stock_Item(db.Model, Store_Base):
stock_item.id_permutation = query_row[1]
stock_item.id_product = query_row[2]
stock_item.id_category = query_row[3]
- # stock_item.name_category = query_row[4]
- # stock_item.name_product = query_row[5]
- stock_item.date_purchased = query_row[4]
- stock_item.date_received = query_row[5]
- stock_item.id_location_storage = query_row[6]
- # stock_item.name_location_storage = query_row[9]
- stock_item.id_currency_cost = query_row[7]
- stock_item.cost_local_VAT_incl = query_row[8]
- stock_item.cost_local_VAT_excl = query_row[9]
- stock_item.is_sealed = av.input_bool(query_row[10], "is_sealed", _m, v_arg_type=v_arg_type)
- stock_item.date_unsealed = query_row[11]
- stock_item.date_expiration = query_row[12]
- stock_item.is_consumed = av.input_bool(query_row[13], "is_consumed", _m, v_arg_type=v_arg_type)
- stock_item.date_consumed = query_row[14]
- stock_item.active = av.input_bool(query_row[15], "active", _m, v_arg_type=v_arg_type)
+ stock_item.id_location_storage = query_row[4]
+ stock_item.storage_location = Storage_Location.from_DB_stock_item(query_row)
+ stock_item.id_currency_cost = query_row[12]
+ stock_item.currency_cost = Currency.from_DB_stock_item(query_row)
+ stock_item.cost_local_VAT_excl = query_row[15]
+ stock_item.cost_local_VAT_incl = query_row[16]
+ stock_item.date_purchased = query_row[17]
+ stock_item.date_received = query_row[18]
+ stock_item.is_sealed = av.input_bool(query_row[19], "is_sealed", _m, v_arg_type=v_arg_type)
+ stock_item.date_unsealed = query_row[20]
+ stock_item.date_expiration = query_row[21]
+ stock_item.is_consumed = av.input_bool(query_row[22], "is_consumed", _m, v_arg_type=v_arg_type)
+ stock_item.date_consumed = query_row[23]
+ stock_item.active = av.input_bool(query_row[24], "active", _m, v_arg_type=v_arg_type)
"""
stock_item.can_view = av.input_bool(query_row[24], "can_view", _m, v_arg_type=v_arg_type)
stock_item.can_edit = av.input_bool(query_row[25], "can_edit", _m, v_arg_type=v_arg_type)
@@ -99,96 +103,55 @@ class Stock_Item(db.Model, Store_Base):
def from_json(cls, json):
stock_item = cls()
stock_item.id_stock = json[cls.ATTR_ID_STOCK_ITEM]
- stock_item.id_permutation = json[cls.ATTR_ID_PRODUCT_PERMUTATION]
+ stock_item.id_permutation = json.get(cls.ATTR_ID_PRODUCT_PERMUTATION, 0)
stock_item.id_product = json[cls.ATTR_ID_PRODUCT]
stock_item.id_category = json[cls.ATTR_ID_PRODUCT_CATEGORY]
+ print(f'json: {json}\nhalf stock item: {stock_item}')
+ stock_item.variation_tree = Product_Variation_Tree.from_json_str(json[cls.FLAG_PRODUCT_VARIATIONS])
stock_item.date_purchased = json[cls.FLAG_DATE_PURCHASED]
stock_item.date_received = json[cls.FLAG_DATE_RECEIVED]
- stock_item.id_location_storage = json[cls.ATTR_ID_LOCATION_STORAGE]
+ stock_item.id_location_storage = json[cls.ATTR_ID_STORAGE_LOCATION]
stock_item.id_currency_cost = json[cls.ATTR_ID_CURRENCY_COST]
- stock_item.cost_local_VAT_incl = json[cls.FLAG_VALUE_LOCAL_VAT_INCL_COST]
- stock_item.cost_local_VAT_excl = json[cls.FLAG_VALUE_LOCAL_VAT_EXCL_COST]
+ stock_item.cost_local_VAT_excl = json[cls.FLAG_COST_LOCAL_VAT_EXCL]
+ stock_item.cost_local_VAT_incl = json[cls.FLAG_COST_LOCAL_VAT_INCL]
stock_item.is_sealed = json[cls.FLAG_IS_SEALED]
stock_item.date_unsealed = json[cls.FLAG_DATE_UNSEALED]
stock_item.date_expiration = json[cls.FLAG_DATE_EXPIRATION]
stock_item.is_consumed = json[cls.FLAG_IS_CONSUMED]
stock_item.date_consumed = json[cls.FLAG_DATE_CONSUMED]
stock_item.active = json[cls.FLAG_ACTIVE]
- """
- stock_item.can_view = json[cls.FLAG_CAN_VIEW]
- stock_item.can_edit = json[cls.FLAG_CAN_EDIT]
- stock_item.can_admin = json[cls.FLAG_CAN_ADMIN]
- """
return stock_item
- """
- def from_json(json_basket_item, key_id_product, key_id_permutation):
- permutation = Product_Permutation.from_json(json_basket_item, key_id_product, key_id_permutation)
- product = Product.from_permutation(permutation)
- return product
-
- def output_lead_time(self):
- return self.get_permutation_selected().output_lead_time()
- def output_delivery_date(self):
- return self.get_permutation_selected().output_delivery_date()
- def output_price(self, is_included_VAT):
- return self.get_permutation_selected().output_price(is_included_VAT)
- def output_price_VAT_incl(self):
- return self.get_permutation_selected().output_price(True)
- def output_price_VAT_excl(self):
- return self.get_permutation_selected().output_price(False)
- def get_price_local(self, is_included_VAT):
- if is_included_VAT:
- return self.get_price_local_VAT_incl()
- else:
- return self.get_price_local_VAT_excl()
- def get_price_local_VAT_incl(self):
- return self.get_permutation_selected().get_price_local_VAT_incl()
- def get_price_local_VAT_excl(self):
- return self.get_permutation_selected().get_price_local_VAT_excl()
- def get_quantity_min(self):
- return self.get_permutation_selected().quantity_min
- def get_id_permutation(self):
- return self.get_permutation_selected().id_permutation
- def get_image_from_index(self, index_image):
- return self.get_permutation_selected().images[index_image]
- def get_name(self):
- return self.get_permutation_selected().name
- def get_description(self):
- return self.get_permutation_selected().description
- def output_currency(self):
- return self.get_permutation_selected().get_price().symbol_currency
- def add_form_basket_add(self):
- self.form_basket_add = None
-
- def add_form_basket_edit(self):
- self.form_basket_edit = None
- """
def __repr__(self):
- return f'''Product
+ return f'''Stock Item
+ id_stock: {self.id_stock}
+ id_permutation: {self.id_permutation}
id_product: {self.id_product}
id_category: {self.id_category}
- name: {self.name}
- display_order: {self.display_order}
- can_view: {self.can_view}
- can_edit: {self.can_edit}
- can_admin: {self.can_admin}
- has_variations: {self.has_variations}
- permutations: {self.permutations}
- variation trees: {self.variation_trees}
+ variations: {self.variation_tree.to_preview_str() if self.variation_tree is not None else 'None'}
+ storage_location: {self.storage_location}
+ currency: {self.currency_cost}
+ cost_local_VAT_excl: {self.cost_local_VAT_excl}
+ cost_local_VAT_incl: {self.cost_local_VAT_incl}
+ date_purchased: {self.date_purchased}
+ date_received: {self.date_received}
+ is_sealed: {self.is_sealed}
+ date_unsealed: {self.date_unsealed}
+ date_expiration: {self.date_expiration}
+ is_consumed: {self.is_consumed}
+ date_consumed: {self.date_consumed}
+ active: {self.active}
'''
def to_json(self):
return {
**self.get_shared_json_attributes(self),
- self.ATTR_ID_PRODUCT: {self.id_product},
- self.ATTR_ID_PRODUCT_CATEGORY: {self.id_category},
- self.FLAG_NAME: {self.name},
- self.FLAG_DISPLAY_ORDER: {self.display_order},
- self.FLAG_CAN_VIEW: {self.can_view},
- self.FLAG_CAN_EDIT: {self.can_edit},
- self.FLAG_CAN_ADMIN: {self.can_admin},
- self.FLAG_HAS_VARIATIONS: {self.has_variations},
- self.FLAG_PRODUCT_PERMUTATION: {self.permutations},
- self.FLAG_PRODUCT_VARIATION_TREES: {self.variation_trees},
+ self.ATTR_ID_STOCK_ITEM: self.id_stock,
+ self.ATTR_ID_PRODUCT_PERMUTATION: self.id_permutation,
+ self.ATTR_ID_PRODUCT: self.id_product,
+ self.ATTR_ID_PRODUCT_CATEGORY: self.id_category,
+ self.FLAG_STORAGE_LOCATION: self.storage_location.to_json(),
+ self.FLAG_CURRENCY_COST: self.currency_cost.to_json(),
+ self.FLAG_COST_LOCAL_VAT_EXCL: self.cost_local_VAT_excl,
+ self.FLAG_COST_LOCAL_VAT_INCL: self.cost_local_VAT_incl,
}
def has_permutations(self):
return len(self.permutations) > 0
@@ -224,12 +187,11 @@ class Parameters_Stock_Item(Get_Many_Parameters_Base):
a_ids_region_storage: str
a_get_all_plant_storage: bool
a_get_inactive_plant_storage: bool
- a_get_first_plant_storage_only: bool
a_ids_plant_storage: str
a_get_all_location_storage: bool
a_get_inactive_location_storage: bool
a_ids_location_storage: str
- a_date_received_to: datetime
+ a_date_received_to: Optional[datetime] = None
a_get_sealed_stock_item_only: bool
a_get_unsealed_stock_item_only: bool
a_get_expired_stock_item_only: bool
@@ -244,7 +206,7 @@ class Parameters_Stock_Item(Get_Many_Parameters_Base):
def get_default(cls):
return cls(
# a_id_user = id_user,
- a_get_all_product_permutation = True,
+ a_get_all_product_permutation = False,
a_get_inactive_product_permutation = False,
a_ids_product_permutation = '',
a_get_all_stock_item = True,
@@ -270,4 +232,71 @@ class Parameters_Stock_Item(Get_Many_Parameters_Base):
@classmethod
def from_form_stock_item(cls, form):
- return cls.get_default()
\ No newline at end of file
+ return cls.get_default()
+
+
+class Stock_Item_Temp(db.Model, Store_Base):
+ __tablename__: ClassVar[str] = 'Shop_Stock_Item_Temp'
+ __table_args__ = { 'extend_existing': True }
+ id_stock: int = db.Column(db.Integer, primary_key=True)
+ # id_category: int = db.Column(db.Integer)
+ id_product: int = db.Column(db.Integer)
+ # has_variations: bool = db.Column(db.Boolean)
+ id_permutation: int = db.Column(db.Integer)
+ id_pairs_variations: str = db.Column(db.String(4000))
+ date_purchased: datetime = db.Column(db.DateTime)
+ date_received: datetime = db.Column(db.DateTime, nullable=True)
+ id_location_storage: int = db.Column(db.Integer)
+ id_currency_cost: int = db.Column(db.Integer)
+ cost_local_VAT_excl: float = db.Column(db.Float)
+ cost_local_VAT_incl: float = db.Column(db.Float)
+ is_sealed: bool = db.Column(db.Boolean)
+ date_unsealed: datetime = db.Column(db.DateTime, nullable=True)
+ date_expiration: datetime = db.Column(db.DateTime, nullable=True)
+ is_consumed: bool = db.Column(db.Boolean)
+ date_consumed: datetime = db.Column(db.DateTime, nullable=True)
+ active: bool = db.Column(db.Boolean)
+ guid: str = db.Column(db.String(36))
+
+ @classmethod
+ def from_stock_item(cls, stock_item):
+ row = cls()
+ row.id_stock = stock_item.id_stock
+ # row.id_category = stock_item.id_category
+ row.id_product = stock_item.id_product
+ row.id_permutation = stock_item.id_permutation
+ # row.has_variations = stock_item.has_variations
+ row.id_pairs_variations = stock_item.variation_tree.to_json_str() if stock_item.variation_tree is not None else ''
+ row.date_purchased = stock_item.date_purchased
+ row.date_received = stock_item.date_received if stock_item.date_received else None
+ row.id_location_storage = stock_item.id_location_storage
+ row.id_currency_cost = stock_item.id_currency_cost
+ row.cost_local_VAT_excl = stock_item.cost_local_VAT_excl
+ row.cost_local_VAT_incl = stock_item.cost_local_VAT_incl
+ row.is_sealed = 1 if stock_item.is_sealed else 0
+ row.date_unsealed = stock_item.date_unsealed if stock_item.date_unsealed else None
+ row.date_expiration = stock_item.date_expiration if stock_item.date_expiration else None
+ row.is_consumed = 1 if stock_item.is_consumed else 0
+ row.date_consumed = stock_item.date_consumed if stock_item.date_consumed else None
+ row.active = 1 if stock_item.active else 0
+ return row
+ def __repr__(self):
+ return f'''
+id_stock: {self.id_stock}
+id_product: {self.id_product}
+id_permutation: {self.id_permutation}
+id_pairs_variations: {self.id_pairs_variations}
+date_purchased: {self.date_purchased}
+date_received: {self.date_received}
+id_location_storage: {self.id_location_storage}
+id_currency_cost: {self.id_currency_cost}
+cost_local_VAT_excl: {self.cost_local_VAT_excl}
+cost_local_VAT_incl: {self.cost_local_VAT_incl}
+is_sealed: {self.is_sealed}
+date_unsealed: {self.date_unsealed}
+date_expiration: {self.date_expiration}
+is_consumed: {self.is_consumed}
+date_consumed: {self.date_consumed}
+active: {self.active}
+guid: {self.guid}
+ '''
\ No newline at end of file
diff --git a/business_objects/store/storage_location.py b/business_objects/store/storage_location.py
index 72c8ff48..170291b0 100644
--- a/business_objects/store/storage_location.py
+++ b/business_objects/store/storage_location.py
@@ -12,6 +12,7 @@ Business object for product
# internal
import lib.argument_validation as av
+from business_objects.store.plant import Plant
from business_objects.store.store_base import Store_Base
from extensions import db
# external
@@ -27,19 +28,33 @@ class Storage_Location(db.Model, Store_Base):
code = db.Column(db.String(50))
name = db.Column(db.String(255))
active = db.Column(db.Boolean)
+
+ # plant = None
def __init__(self):
super().__init__()
Store_Base.__init__(self)
+ self.plant = None
+
@classmethod
def from_DB_storage_location(cls, query_row):
location = cls()
location.id_location = query_row[0]
location.id_plant = query_row[1]
+ location.plant = Plant.from_DB_storage_location(query_row)
location.code = query_row[2]
location.name = query_row[3]
location.active = query_row[4]
return location
+ @classmethod
+ def from_DB_stock_item(cls, query_row):
+ location = cls()
+ location.id_location = query_row[4]
+ location.id_plant = query_row[5]
+ location.code = query_row[8]
+ location.name = query_row[9]
+ location.plant = Plant.from_DB_stock_item(query_row)
+ return location
def __repr__(self):
return f'''
{self.ATTR_ID_STORAGE_LOCATION}: {self.id_location}
@@ -67,3 +82,6 @@ class Storage_Location(db.Model, Store_Base):
location.name = json[cls.FLAG_NAME],
location.active = json[cls.FLAG_ACTIVE]
return location
+
+ def get_full_name(self):
+ return f'{self.plant.name} - {self.name}'
\ No newline at end of file
diff --git a/business_objects/store/store_base.py b/business_objects/store/store_base.py
index fc921720..48b52505 100644
--- a/business_objects/store/store_base.py
+++ b/business_objects/store/store_base.py
@@ -58,9 +58,9 @@ class I_Store_Base():
class Store_Base(Base):
# ATTR_ID_CURRENCY_COST: ClassVar[str] = 'id_currency_cost'
+ ATTR_ID_DELIVERY_OPTION: ClassVar[str] = 'id_delivery_option'
ATTR_ID_DISCOUNT: ClassVar[str] = 'id_discount'
ATTR_ID_IMAGE: ClassVar[str] = 'id_image'
- ATTR_ID_LOCATION_STORAGE: ClassVar[str] = 'id_location_storage'
ATTR_ID_PLANT: ClassVar[str] = 'id_plant'
ATTR_ID_PRODUCT: ClassVar[str] = 'id_product'
ATTR_ID_PRODUCT_CATEGORY: ClassVar[str] = 'id_category'
@@ -70,10 +70,15 @@ class Store_Base(Base):
ATTR_ID_PRODUCT_VARIATION: ClassVar[str] = 'id_variation'
ATTR_ID_PRODUCT_VARIATION_TYPE: ClassVar[str] = 'id_type'
ATTR_ID_STOCK_ITEM: ClassVar[str] = 'id_stock_item'
- FLAG_CURRENCY: ClassVar[str] = 'currency'
+ ATTR_ID_STORAGE_LOCATION: ClassVar[str] = 'id_location'
+ FLAG_COST_LOCAL: ClassVar[str] = 'cost_local'
+ FLAG_COST_LOCAL_VAT_EXCL: ClassVar[str] = FLAG_COST_LOCAL + '_vat_excl'
+ FLAG_COST_LOCAL_VAT_INCL: ClassVar[str] = FLAG_COST_LOCAL + '_vat_incl'
FLAG_DELIVERY_OPTION: ClassVar[str] = 'delivery_option'
FLAG_HAS_VARIATIONS: ClassVar[str] = 'has_variations'
FLAG_IS_OUT_OF_STOCK: ClassVar[str] = 'is_out_of_stock'
+ FLAG_DISCOUNT: ClassVar[str] = 'discount'
+ FLAG_PLANT: ClassVar[str] = 'plant'
FLAG_PRODUCT: ClassVar[str] = 'product'
FLAG_PRODUCT_CATEGORY: ClassVar[str] = 'product_category'
FLAG_PRODUCT_IMAGE: ClassVar[str] = 'product_image'
@@ -85,6 +90,7 @@ class Store_Base(Base):
FLAG_QUANTITY_MIN: ClassVar[str] = 'quantity_min'
FLAG_QUANTITY_MAX: ClassVar[str] = 'quantity_max'
FLAG_STOCK_ITEM: ClassVar[str] = 'stock_item'
+ FLAG_STORAGE_LOCATION: ClassVar[str] = 'storage_location'
FLAG_TEXT: ClassVar[str] = 'text'
FLAG_VALUE_TEXT: ClassVar[str] = 'value_text'
\ No newline at end of file
diff --git a/business_objects/user.py b/business_objects/user.py
index d6b3f457..8dcbcd71 100644
--- a/business_objects/user.py
+++ b/business_objects/user.py
@@ -38,7 +38,9 @@ class User(db.Model, Base):
# is_logged_in: bool
def __init__(self):
+ self.id_user = 0
self.is_logged_in = False
+ super().__init__()
def from_DB_user(query_row):
_m = 'User.from_DB_user'
@@ -62,7 +64,7 @@ class User(db.Model, Base):
_m = 'User.from_json'
user = User()
if json is None: return user
- print(f'json: {json}')
+ print(f'{_m}\njson: {json}')
user.id_user = json['id_user']
user.id_user_auth0 = json['id_user_auth0']
user.firstname = json['firstname']
@@ -85,7 +87,7 @@ class User(db.Model, Base):
_m = 'User.from_json_auth0'
user = User()
if json is None: return user
- print(f'json: {json}')
+ print(f'{_m}\njson: {json}')
user_info = json['userinfo']
user.id_user = None
user.id_user_auth0 = user_info['sub']
@@ -136,11 +138,6 @@ class User(db.Model, Base):
can_admin_user: {self.can_admin_user}
'''
- @staticmethod
- def get_default():
- user = User()
- user.id_user = None
- return user
@dataclass
diff --git a/controllers/__pycache__/__init__.cpython-312.pyc b/controllers/__pycache__/__init__.cpython-312.pyc
index 387d9b83..ce29ae52 100644
Binary files a/controllers/__pycache__/__init__.cpython-312.pyc and b/controllers/__pycache__/__init__.cpython-312.pyc differ
diff --git a/controllers/__pycache__/core.cpython-312.pyc b/controllers/__pycache__/core.cpython-312.pyc
index 5c685fa2..0840b30c 100644
Binary files a/controllers/__pycache__/core.cpython-312.pyc and b/controllers/__pycache__/core.cpython-312.pyc differ
diff --git a/controllers/__pycache__/legal.cpython-312.pyc b/controllers/__pycache__/legal.cpython-312.pyc
index d5267cf6..6b38c463 100644
Binary files a/controllers/__pycache__/legal.cpython-312.pyc and b/controllers/__pycache__/legal.cpython-312.pyc differ
diff --git a/controllers/__pycache__/user.cpython-312.pyc b/controllers/__pycache__/user.cpython-312.pyc
index 59df1307..2d74953b 100644
Binary files a/controllers/__pycache__/user.cpython-312.pyc and b/controllers/__pycache__/user.cpython-312.pyc differ
diff --git a/controllers/core.py b/controllers/core.py
index a881a683..28a3ef54 100644
--- a/controllers/core.py
+++ b/controllers/core.py
@@ -88,6 +88,11 @@ def services():
def admin_home():
try:
model = Model_View_Admin_Home()
+ if not model.is_user_logged_in:
+ # return redirect(url_for('routes_user.login', callback = Model_View_Admin_Home.HASH_PAGE_ADMIN_HOME))
+ return redirect(url_for('routes_core.home'))
+ if not (model.user.can_admin_store or model.user.can_admin_user):
+ return redirect(url_for('routes_core.home'))
html_body = render_template('pages/core/_admin_home.html', model = model)
except Exception as e:
return jsonify(error=str(e)), 403
diff --git a/controllers/store/__pycache__/__init__.cpython-312.pyc b/controllers/store/__pycache__/__init__.cpython-312.pyc
index 13f4a71c..aa8a0685 100644
Binary files a/controllers/store/__pycache__/__init__.cpython-312.pyc and b/controllers/store/__pycache__/__init__.cpython-312.pyc differ
diff --git a/controllers/store/__pycache__/product.cpython-312.pyc b/controllers/store/__pycache__/product.cpython-312.pyc
index 26e3517c..cd9eeaf2 100644
Binary files a/controllers/store/__pycache__/product.cpython-312.pyc and b/controllers/store/__pycache__/product.cpython-312.pyc differ
diff --git a/controllers/store/__pycache__/product_category.cpython-312.pyc b/controllers/store/__pycache__/product_category.cpython-312.pyc
index 487be009..4474aca8 100644
Binary files a/controllers/store/__pycache__/product_category.cpython-312.pyc and b/controllers/store/__pycache__/product_category.cpython-312.pyc differ
diff --git a/controllers/store/__pycache__/product_permutation.cpython-312.pyc b/controllers/store/__pycache__/product_permutation.cpython-312.pyc
index fbaea038..bbc800b5 100644
Binary files a/controllers/store/__pycache__/product_permutation.cpython-312.pyc and b/controllers/store/__pycache__/product_permutation.cpython-312.pyc differ
diff --git a/controllers/store/__pycache__/stock_item.cpython-312.pyc b/controllers/store/__pycache__/stock_item.cpython-312.pyc
index 9a77a291..b46f8a1e 100644
Binary files a/controllers/store/__pycache__/stock_item.cpython-312.pyc and b/controllers/store/__pycache__/stock_item.cpython-312.pyc differ
diff --git a/controllers/store/__pycache__/store.cpython-312.pyc b/controllers/store/__pycache__/store.cpython-312.pyc
index edf2d772..7735cdd9 100644
Binary files a/controllers/store/__pycache__/store.cpython-312.pyc and b/controllers/store/__pycache__/store.cpython-312.pyc differ
diff --git a/controllers/store/__pycache__/supplier.cpython-312.pyc b/controllers/store/__pycache__/supplier.cpython-312.pyc
index 5697d5d5..bb02e2ea 100644
Binary files a/controllers/store/__pycache__/supplier.cpython-312.pyc and b/controllers/store/__pycache__/supplier.cpython-312.pyc differ
diff --git a/controllers/store/product.py b/controllers/store/product.py
index 045b0bd5..94d06d8a 100644
--- a/controllers/store/product.py
+++ b/controllers/store/product.py
@@ -111,6 +111,9 @@ def products():
form_filters = Filters_Product()
print(f'form_filters={form_filters}')
model = Model_View_Store_Product(form_filters)
+ if not model.is_user_logged_in:
+ # return redirect(url_for('routes_user.login', data = jsonify({ Model_View_Store_Product.KEY_CALLBACK: Model_View_Store_Product.HASH_PAGE_STORE_PRODUCTS })))
+ return redirect(url_for('routes_core.home'))
return render_template('pages/store/_products.html', model = model)
@routes_store_product.route(Model_View_Store_Product.HASH_GET_STORE_PRODUCT, methods=['POST'])
@@ -124,6 +127,8 @@ def filter_product():
Model_View_Store_Product.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}'
})
model = Model_View_Store_Product(form_filters = form_filters)
+ if not model.is_user_logged_in:
+ raise Exception('User not logged in')
return jsonify({
Model_View_Store_Product.FLAG_STATUS: Model_View_Store_Product.FLAG_SUCCESS,
Model_View_Store_Product.KEY_DATA: model.category_list.to_json()
@@ -161,6 +166,8 @@ def save_product():
save_errors = Model_View_Store_Product.save_products(data.get('comment', 'No comment'), objsProduct)
model_return = Model_View_Store_Product(form_filters=form_filters)
+ if not model_return.is_user_logged_in:
+ raise Exception('User not logged in')
print('nips')
return jsonify({
Model_View_Store_Product.FLAG_STATUS: Model_View_Store_Product.FLAG_SUCCESS,
diff --git a/controllers/store/product_category.py b/controllers/store/product_category.py
index 4eb4bf6b..d2b8fae4 100644
--- a/controllers/store/product_category.py
+++ b/controllers/store/product_category.py
@@ -54,6 +54,9 @@ def categories():
return redirect(url_for('routes_store_product_category.categories', **filters.to_json()))
"""
model = Model_View_Store_Product_Category(form_filters)
+ if not model.is_user_logged_in:
+ # return redirect(url_for('routes_user.login', data = jsonify({ Model_View_Store_Product_Category.KEY_CALLBACK: Model_View_Store_Product_Category.HASH_PAGE_STORE_PRODUCT_CATEGORIES })))
+ return redirect(url_for('routes_core.home'))
return render_template('pages/store/_product_categories.html', model = model)
@routes_store_product_category.route(Model_View_Store_Product_Category.HASH_GET_STORE_PRODUCT_CATEGORY, methods=['POST'])
@@ -70,6 +73,8 @@ def filter_category():
# ToDo: manually validate category, product
# filters_form = Filters_Product_Category.from_form(form_filters)
model = Model_View_Store_Product_Category(form_filters = form_filters)
+ if not model.is_user_logged_in:
+ raise Exception('User not logged in')
return jsonify({
Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_SUCCESS,
Model_View_Store_Product_Category.KEY_DATA: model.category_list.to_json()
@@ -106,7 +111,8 @@ def save_category():
Model_View_Store_Product_Category.save_categories(data.get('comment', 'No comment'), objsCategory)
model_return = Model_View_Store_Product_Category(form_filters=form_filters)
- print('nips')
+ if not model_return.is_user_logged_in:
+ raise Exception('User not logged in')
return jsonify({
Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_SUCCESS,
Model_View_Store_Product_Category.KEY_DATA: model_return.category_list.to_json()
diff --git a/controllers/store/product_permutation.py b/controllers/store/product_permutation.py
index dfd42dce..9584d2b1 100644
--- a/controllers/store/product_permutation.py
+++ b/controllers/store/product_permutation.py
@@ -96,6 +96,9 @@ def permutations():
form_filters = Filters_Product_Permutation()
print(f'form_filters={form_filters}')
model = Model_View_Store_Product_Permutation(form_filters)
+ if not model.is_user_logged_in:
+ # return redirect(url_for('routes_user.login', data = jsonify({ Model_View_Store_Product_Permutation.KEY_CALLBACK: Model_View_Store_Product_Permutation.HASH_PAGE_STORE_PRODUCT_PERMUTATIONS })))
+ return redirect(url_for('routes_core.home'))
return render_template('pages/store/_product_permutations.html', model = model)
@routes_store_product_permutation.route(Model_View_Store_Product_Permutation.HASH_GET_STORE_PRODUCT_PERMUTATION, methods=['POST'])
@@ -109,6 +112,8 @@ def filter_permutation():
Model_View_Store_Product_Permutation.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}'
})
model = Model_View_Store_Product_Permutation(form_filters = form_filters)
+ if not model.is_user_logged_in:
+ raise Exception('User not logged in')
return jsonify({
Model_View_Store_Product_Permutation.FLAG_STATUS: Model_View_Store_Product_Permutation.FLAG_SUCCESS,
Model_View_Store_Product_Permutation.KEY_DATA: model.category_list.to_json()
@@ -146,6 +151,8 @@ def save_permutation():
Model_View_Store_Product_Permutation.save_permutations(data.get('comment', 'No comment'), objsPermutation)
model_return = Model_View_Store_Product_Permutation(form_filters=form_filters)
+ if not model_return.is_user_logged_in:
+ raise Exception('User not logged in')
print('nips')
return jsonify({
Model_View_Store_Product_Permutation.FLAG_STATUS: Model_View_Store_Product_Permutation.FLAG_SUCCESS,
diff --git a/controllers/store/stock_item.py b/controllers/store/stock_item.py
index edbe07f7..82285608 100644
--- a/controllers/store/stock_item.py
+++ b/controllers/store/stock_item.py
@@ -11,91 +11,26 @@ Initializes the Flask application, sets the configuration based on the environme
"""
# internal
-from business_objects.store.product import Product, Parameters_Product, Product_Permutation
from business_objects.store.stock_item import Stock_Item
from forms.store.stock_item import Filters_Stock_Item
-from models.model_view_base import Model_View_Base
-from models.model_view_store import Model_View_Store
-from models.model_view_store_supplier import Model_View_Store_Supplier
-from models.model_view_store_product_category import Model_View_Store_Product_Category
-from models.model_view_store_product_permutation import Model_View_Store_Product_Permutation
from models.model_view_store_stock_item import Model_View_Store_Stock_Item
from helpers.helper_app import Helper_App
import lib.argument_validation as av
# external
+from datetime import datetime
from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session, Blueprint, current_app
from extensions import db, oauth
from urllib.parse import quote_plus, urlencode
from authlib.integrations.flask_client import OAuth
from authlib.integrations.base_client import OAuthError
from urllib.parse import quote, urlparse, parse_qs
-
+import requests
routes_store_stock_item = Blueprint('routes_store_stock_item', __name__)
-"""
-@routes_store_stock_item.route('/store/stock_items', methods=['GET'])
-def stock():
- filters = Filters_Stock_Item.get_default()
- model = Model_View_Store_Stock_Item(filters_stock_item=filters)
- return render_template('pages/store/_stock_items.html', model = model)
-
-@routes_store_stock_item.route('/store/stock_item_filter', methods=['POST'])
-def stock_filter():
- data = Helper_App.get_request_data(request)
- form_filters = None
- try:
- form_filters = get_Filters_Stock_Items(data)
- if not form_filters.validate_on_submit():
- return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}'})
- # ToDo: manually validate category, product
- filters_form = Filters_Stock_Item.from_form(form_filters)
- model = Model_View_Store_Stock_Item(filters_stock_item=filters_form)
- return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_SUCCESS, 'Success': True, Model_View_Base.KEY_DATA: model.category_list.to_permutation_row_list()})
- except Exception as e:
- return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Bad data received by controller.\n{e}'})
-
-def get_Filters_Stock_Items(data_request):
- data_form = data_request[Model_View_Store_Stock_Item.KEY_FORM]
- form_filters = Filters_Stock_Item(**data_form)
- form_filters.is_out_of_stock.data = av.input_bool(data_form['is_out_of_stock'], 'is_out_of_stock', 'permutations_post')
- return form_filters
-
-@routes_store_stock_item.route('/store/stock_item_save', methods=['POST'])
-def stock_save():
- data = Helper_App.get_request_data(request)
-""
- form_filters = None
- try:
- form_filters = get_Filters_Stock_Items(data)
- if not form_filters.validate_on_submit():
- return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Filters form invalid.\n{form_filters.errors}'})
-
- stock_items = data[Model_View_Store_Stock.KEY_PERMUTATIONS]
- print(f'stock_items: {stock_items}')
- if len(stock_items) == 0:
- return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_FAILURE, Model_View_Base.FLAG_MESSAGE: f'No stock items.'})
- objsStockItem = []
- for stock_item in stock_items:
- objsStockItem.append(Product_Permutation.from_json(stock_item))
- print(f'objsStockItem: {objsStockItem}')
-
- # ToDo: manually validate category, product
- filters_form = Stock_Filters.from_form(form_filters)
- model_save = Model_View_Store_Stock(filters_product=filters_form)
- model_save.save_stock_items(data.comment, objsPermutation)
-
- model_return = Model_View_Store_Stock(filters_product=filters_form)
- return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_SUCCESS, 'Success': True, Model_View_Base.KEY_DATA: model_return.category_list.to_permutation_row_list()})
- except Exception as e:
- return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Bad data received by controller.\n{e}'})
-""
-"""
-
-
@routes_store_stock_item.route(Model_View_Store_Stock_Item.HASH_PAGE_STORE_STOCK_ITEMS, methods=['GET'])
-def permutations():
- print('permutations')
+def stock_items():
+ print('stock_items')
try:
form_filters = Filters_Stock_Item.from_json(request.args)
except Exception as e:
@@ -103,19 +38,39 @@ def permutations():
form_filters = Filters_Stock_Item()
print(f'form_filters={form_filters}')
model = Model_View_Store_Stock_Item(form_filters)
- return render_template('pages/store/_stock_items.html', model = model)
+ if not model.is_user_logged_in:
+ # return redirect(url_for('routes_user.login', data = jsonify({ Model_View_Store_Stock_Item.KEY_CALLBACK: Model_View_Store_Stock_Item.HASH_PAGE_STORE_STOCK_ITEMS })))
+ # return requests.post(f"{current_app.config['URL_HOST']}{url_for('routes_user.login')}", json={ Model_View_Store_Stock_Item.KEY_CALLBACK: Model_View_Store_Stock_Item.HASH_PAGE_STORE_STOCK_ITEMS })
+ return redirect(url_for('routes_core.home'))
+ return render_template('pages/store/_stock_items.html', model = model, datetime = datetime)
@routes_store_stock_item.route(Model_View_Store_Stock_Item.HASH_GET_STORE_STOCK_ITEM, methods=['POST'])
-def filter_permutation():
+def filter_stock_item():
data = Helper_App.get_request_data(request)
try:
form_filters = Filters_Stock_Item.from_json(data)
if not form_filters.validate_on_submit():
- return jsonify({
- Model_View_Store_Stock_Item.FLAG_STATUS: Model_View_Store_Stock_Item.FLAG_FAILURE,
- Model_View_Store_Stock_Item.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}'
- })
- model = Model_View_Store_Stock_Item(form_filters = form_filters)
+ error_keys = list(form_filters.errors.keys())
+ try:
+ error_keys.remove(Stock_Item.ATTR_ID_PRODUCT_CATEGORY)
+ """
+ if not av.val_int(form_filters.id_product_category.data):
+ form_filters.errors[Stock_Item.ATTR_ID_PRODUCT_CATEGORY] = ['Invalid category.']
+ """
+ except:
+ pass
+ try:
+ error_keys.remove(Stock_Item.ATTR_ID_PRODUCT)
+ except:
+ pass
+ if error_keys:
+ return jsonify({
+ Model_View_Store_Stock_Item.FLAG_STATUS: Model_View_Store_Stock_Item.FLAG_FAILURE,
+ Model_View_Store_Stock_Item.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}'
+ })
+ model = Model_View_Store_Stock_Item(filters_stock_item = form_filters)
+ if not model.is_user_logged_in:
+ raise Exception('User not logged in.')
return jsonify({
Model_View_Store_Stock_Item.FLAG_STATUS: Model_View_Store_Stock_Item.FLAG_SUCCESS,
Model_View_Store_Stock_Item.KEY_DATA: model.category_list.to_json()
@@ -127,33 +82,55 @@ def filter_permutation():
})
@routes_store_stock_item.route(Model_View_Store_Stock_Item.HASH_SAVE_STORE_STOCK_ITEM, methods=['POST'])
-def save_permutation():
+def save_stock_item():
data = Helper_App.get_request_data(request)
try:
form_filters = Filters_Stock_Item.from_json(data[Model_View_Store_Stock_Item.FLAG_FORM_FILTERS])
+ """
if not form_filters.validate_on_submit():
- return jsonify({
- Model_View_Store_Stock_Item.FLAG_STATUS: Model_View_Store_Stock_Item.FLAG_FAILURE,
- Model_View_Store_Stock_Item.FLAG_MESSAGE: f'Filters form invalid.\n{form_filters.errors}'
- })
+ error_keys = list(form_filters.errors.keys())
+ try:
+ error_keys.remove(Stock_Item.ATTR_ID_PRODUCT_CATEGORY)
+ ""
+ if not av.val_int(form_filters.id_product_category.data):
+ form_filters.errors[Stock_Item.ATTR_ID_PRODUCT_CATEGORY] = ['Invalid category.']
+ ""
+ except:
+ pass
+ try:
+ error_keys.remove(Stock_Item.ATTR_ID_PRODUCT)
+ except:
+ pass
+ if error_keys:
+ return jsonify({
+ Model_View_Store_Stock_Item.FLAG_STATUS: Model_View_Store_Stock_Item.FLAG_FAILURE,
+ Model_View_Store_Stock_Item.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}'
+ })
+ """
# filters_form = Filters_Stock_Item.from_form(form_filters)
print(f'form_filters: {form_filters}')
- permutations = data[Model_View_Store_Stock_Item.FLAG_STOCK_ITEM]
- if len(permutations) == 0:
+ stock_items = data[Model_View_Store_Stock_Item.FLAG_STOCK_ITEM]
+ if len(stock_items) == 0:
return jsonify({
Model_View_Store_Stock_Item.FLAG_STATUS: Model_View_Store_Stock_Item.FLAG_FAILURE,
- Model_View_Store_Stock_Item.FLAG_MESSAGE: f'No permutations.'
+ Model_View_Store_Stock_Item.FLAG_MESSAGE: f'No stock items.'
})
- objsPermutation = []
- for permutation in permutations:
- objsPermutation.append(Stock_Item.from_json(permutation))
+ print(f'stock_items={stock_items}')
+ objs_stock_item = []
+ for stock_item in stock_items:
+ objs_stock_item.append(Stock_Item.from_json(stock_item))
# model_save = Model_View_Store_Stock_Item() # filters_product=filters_form)
- print(f'objsPermutation={objsPermutation}')
- Model_View_Store_Stock_Item.save_permutations(data.get('comment', 'No comment'), objsPermutation)
-
- model_return = Model_View_Store_Stock_Item(form_filters=form_filters)
- print('nips')
+ print(f'objs_stock_item={objs_stock_item}')
+ save_errors = Model_View_Store_Stock_Item.save_stock_items(data.get('comment', 'No comment'), objs_stock_item)
+ if len(save_errors) > 0:
+ return jsonify({
+ Model_View_Store_Stock_Item.FLAG_STATUS: Model_View_Store_Stock_Item.FLAG_FAILURE,
+ Model_View_Store_Stock_Item.FLAG_MESSAGE: f'Save errors: {save_errors}'
+ })
+ model_return = Model_View_Store_Stock_Item(filters_stock_item=form_filters)
+ if not model_return.is_user_logged_in:
+ raise Exception('User not logged in.')
return jsonify({
Model_View_Store_Stock_Item.FLAG_STATUS: Model_View_Store_Stock_Item.FLAG_SUCCESS,
Model_View_Store_Stock_Item.KEY_DATA: model_return.category_list.to_json()
diff --git a/controllers/store/supplier.py b/controllers/store/supplier.py
index bf7d98a0..07837bb6 100644
--- a/controllers/store/supplier.py
+++ b/controllers/store/supplier.py
@@ -53,6 +53,9 @@ def supplier():
# if not logged in:
try:
model = Model_View_Store_Supplier(form)
+ if not model.is_user_logged_in:
+ # return redirect(url_for('routes_user.login', data = jsonify({ Model_View_Store_Supplier.KEY_CALLBACK: Model_View_Store_Supplier.HASH_PAGE_STORE_SUPPLIERS })))
+ return redirect(url_for('routes_core.home'))
# print('importing basket')
# model.import_JSON_basket(data)
model.get_basket(data)
diff --git a/controllers/user.py b/controllers/user.py
index 5d28c569..08ca818c 100644
--- a/controllers/user.py
+++ b/controllers/user.py
@@ -170,6 +170,9 @@ def logout_callback():
def user():
try:
model = Model_View_User(current_app, db)
+ if not model.is_user_logged_in:
+ # return redirect(url_for('routes_user.login', data = jsonify({ Model_View_User.KEY_CALLBACK: Model_View_User.HASH_PAGE_USER_ACCOUNT })))
+ return redirect(url_for('routes_core.home'))
html_body = render_template('pages/user/_user.html', model = model)
except Exception as e:
return str(e)
diff --git a/datastores/__pycache__/__init__.cpython-312.pyc b/datastores/__pycache__/__init__.cpython-312.pyc
index 8c2301e6..0ae6ea85 100644
Binary files a/datastores/__pycache__/__init__.cpython-312.pyc and b/datastores/__pycache__/__init__.cpython-312.pyc differ
diff --git a/datastores/__pycache__/datastore_base.cpython-312.pyc b/datastores/__pycache__/datastore_base.cpython-312.pyc
index 4bb370e9..4037a563 100644
Binary files a/datastores/__pycache__/datastore_base.cpython-312.pyc and b/datastores/__pycache__/datastore_base.cpython-312.pyc differ
diff --git a/datastores/__pycache__/datastore_store_base.cpython-312.pyc b/datastores/__pycache__/datastore_store_base.cpython-312.pyc
index c1104160..8e01e1fb 100644
Binary files a/datastores/__pycache__/datastore_store_base.cpython-312.pyc and b/datastores/__pycache__/datastore_store_base.cpython-312.pyc differ
diff --git a/datastores/__pycache__/datastore_store_basket.cpython-312.pyc b/datastores/__pycache__/datastore_store_basket.cpython-312.pyc
index 420302be..6dd49865 100644
Binary files a/datastores/__pycache__/datastore_store_basket.cpython-312.pyc and b/datastores/__pycache__/datastore_store_basket.cpython-312.pyc differ
diff --git a/datastores/__pycache__/datastore_store_product_category.cpython-312.pyc b/datastores/__pycache__/datastore_store_product_category.cpython-312.pyc
index 28cef3c1..3869955d 100644
Binary files a/datastores/__pycache__/datastore_store_product_category.cpython-312.pyc and b/datastores/__pycache__/datastore_store_product_category.cpython-312.pyc differ
diff --git a/datastores/__pycache__/datastore_store_product_permutation.cpython-312.pyc b/datastores/__pycache__/datastore_store_product_permutation.cpython-312.pyc
index 1016f588..468fa292 100644
Binary files a/datastores/__pycache__/datastore_store_product_permutation.cpython-312.pyc and b/datastores/__pycache__/datastore_store_product_permutation.cpython-312.pyc differ
diff --git a/datastores/__pycache__/datastore_store_stock_item.cpython-312.pyc b/datastores/__pycache__/datastore_store_stock_item.cpython-312.pyc
index 030ca917..fdc41dd8 100644
Binary files a/datastores/__pycache__/datastore_store_stock_item.cpython-312.pyc and b/datastores/__pycache__/datastore_store_stock_item.cpython-312.pyc differ
diff --git a/datastores/__pycache__/datastore_user.cpython-312.pyc b/datastores/__pycache__/datastore_user.cpython-312.pyc
index df4968de..841398e0 100644
Binary files a/datastores/__pycache__/datastore_user.cpython-312.pyc and b/datastores/__pycache__/datastore_user.cpython-312.pyc differ
diff --git a/datastores/datastore_base.py b/datastores/datastore_base.py
index 20010460..8e6e85a7 100644
--- a/datastores/datastore_base.py
+++ b/datastores/datastore_base.py
@@ -20,7 +20,7 @@ from business_objects.store.product_category import Product_Category_Container,
from business_objects.store.currency import Currency
from business_objects.store.image import Image
from business_objects.store.delivery_option import Delivery_Option
-from business_objects.store.delivery_region import Delivery_Region
+from business_objects.store.delivery_region import Region
from business_objects.store.discount import Discount
from business_objects.store.order import Order
from business_objects.store.product import Product, Product_Permutation, Product_Price, Parameters_Product # Permutation_Variation_Link
@@ -145,7 +145,7 @@ class DataStore_Base(BaseModel):
result_set_1 = cursor.fetchall()
regions = []
for row in result_set_1:
- region = Delivery_Region.make_from_DB_region(row)
+ region = Region.make_from_DB_region(row)
regions.append(region)
print(f'regions: {regions}')
DataStore_Base.db_cursor_clear(cursor)
diff --git a/datastores/datastore_store_base.py b/datastores/datastore_store_base.py
index 947b68dd..764e77d7 100644
--- a/datastores/datastore_store_base.py
+++ b/datastores/datastore_store_base.py
@@ -14,10 +14,10 @@ Datastore for Store
# from routes import bp_home
from business_objects.store.basket import Basket, Basket_Item
from business_objects.store.product_category import Product_Category_Container, Product_Category
-from business_objects.store.currency import Currency
+from business_objects.currency import Currency
from business_objects.store.image import Image
from business_objects.store.delivery_option import Delivery_Option
-from business_objects.store.delivery_region import Delivery_Region
+from business_objects.region import Region
from business_objects.store.discount import Discount
from business_objects.store.order import Order
from business_objects.store.product import Product, Product_Permutation, Parameters_Product
@@ -235,7 +235,7 @@ class DataStore_Store_Base(DataStore_Base):
result_set_1 = cursor.fetchall()
regions = []
for row in result_set_1:
- region = Delivery_Region.from_DB_region(row)
+ region = Region.from_DB_region(row)
regions.append(region)
print(f'regions: {regions}')
DataStore_Store_Base.db_cursor_clear(cursor)
diff --git a/datastores/datastore_store_basket.py b/datastores/datastore_store_basket.py
index c68db87e..184636bf 100644
--- a/datastores/datastore_store_basket.py
+++ b/datastores/datastore_store_basket.py
@@ -15,10 +15,10 @@ Datastore for Store Baskets
import lib.argument_validation as av
from business_objects.store.basket import Basket, Basket_Item
from business_objects.store.product_category import Product_Category_Container, Product_Category
-from business_objects.store.currency import Currency
+from business_objects.currency import Currency
from business_objects.store.image import Image
from business_objects.store.delivery_option import Delivery_Option
-from business_objects.store.delivery_region import Delivery_Region
+from business_objects.region import Region
from business_objects.store.discount import Discount
from business_objects.store.order import Order
from business_objects.store.product import Product, Product_Permutation, Product_Price, Parameters_Product
diff --git a/datastores/datastore_store_product_category.py b/datastores/datastore_store_product_category.py
index 553615f7..ba0794c6 100644
--- a/datastores/datastore_store_product_category.py
+++ b/datastores/datastore_store_product_category.py
@@ -14,10 +14,10 @@ Datastore for Store Product Categories
import lib.argument_validation as av
from business_objects.store.basket import Basket, Basket_Item
from business_objects.store.product_category import Product_Category_Container, Product_Category, Product_Category_Temp
-from business_objects.store.currency import Currency
+from business_objects.currency import Currency
from business_objects.store.image import Image
from business_objects.store.delivery_option import Delivery_Option
-from business_objects.store.delivery_region import Delivery_Region
+from business_objects.region import Region
from business_objects.store.discount import Discount
from business_objects.store.order import Order
from business_objects.store.product import Product, Product_Permutation, Product_Price, Parameters_Product
diff --git a/datastores/datastore_store_product_variation.py b/datastores/datastore_store_product_variation.py
index e44263a0..2e3171e6 100644
--- a/datastores/datastore_store_product_variation.py
+++ b/datastores/datastore_store_product_variation.py
@@ -15,10 +15,10 @@ Datastore for Store Product Variations
import lib.argument_validation as av
from business_objects.store.basket import Basket, Basket_Item
from business_objects.store.product_category import Product_Category_Container, Product_Category
-from business_objects.store.currency import Currency
+from business_objects.currency import Currency
from business_objects.store.image import Image
from business_objects.store.delivery_option import Delivery_Option
-from business_objects.store.delivery_region import Delivery_Region
+from business_objects.region import Region
from business_objects.store.discount import Discount
from business_objects.store.order import Order
from business_objects.store.product import Product, Product_Permutation, Product_Price, Parameters_Product
diff --git a/datastores/datastore_store_stock_item.py b/datastores/datastore_store_stock_item.py
index 806dab05..683f64bd 100644
--- a/datastores/datastore_store_stock_item.py
+++ b/datastores/datastore_store_stock_item.py
@@ -13,21 +13,10 @@ Datastore for Store Stock Items
# internal
# from routes import bp_home
import lib.argument_validation as av
-from business_objects.store.basket import Basket, Basket_Item
-from business_objects.store.product_category import Product_Category_Container, Product_Category
-from business_objects.store.currency import Currency
-from business_objects.store.image import Image
-from business_objects.store.delivery_option import Delivery_Option
-from business_objects.store.delivery_region import Delivery_Region
-from business_objects.store.discount import Discount
-from business_objects.store.order import Order
-from business_objects.store.product import Product, Product_Permutation, Product_Price, Parameters_Product
from business_objects.sql_error import SQL_Error
-from business_objects.store.stock_item import Stock_Item
-from business_objects.user import User, User_Filters, User_Permission_Evaluation
-from business_objects.store.product_variation import Product_Variation, Product_Variation_Filters, Product_Variation_Container
+from business_objects.store.stock_item import Stock_Item, Parameters_Stock_Item, Stock_Item_Temp
from datastores.datastore_store_base import DataStore_Store_Base
-# from helpers.helper_db_mysql import Helper_DB_MySQL
+from helpers.helper_db_mysql import Helper_DB_MySQL
# from models.model_view_store_checkout import Model_View_Store_Checkout # circular!
from extensions import db
# external
@@ -52,11 +41,11 @@ class DataStore_Store_Stock_Item(DataStore_Store_Base):
super().__init__()
# Stock Items
- def get_many_stock_item(self, Parameters_Stock_Item, category_list):
+ def get_many_stock_item(self, parameters_stock_item, category_list):
# redundant argument validation?
_m = 'DataStore_Store_Stock_Item.get_many_stock_item'
- av.val_instance(Parameters_Stock_Item, 'Parameters_Stock_Item', _m, Parameters_Stock_Item)
- argument_dict = Parameters_Stock_Item.to_json()
+ av.val_instance(parameters_stock_item, 'parameters_stock_item', _m, Parameters_Stock_Item)
+ argument_dict = parameters_stock_item.to_json()
user = self.get_user_session()
"""
argument_dict['a_id_user'] = user.id_user # 'auth0|6582b95c895d09a70ba10fef' # id_user
@@ -67,6 +56,9 @@ class DataStore_Store_Stock_Item(DataStore_Store_Base):
, **argument_dict
, 'a_debug': 0
}
+ ids_permutation = category_list.get_csv_ids_permutation()
+ print(f'ids_permutation: {ids_permutation}')
+ argument_dict['a_ids_product_permutation'] = ids_permutation
print(f'argument_dict: {argument_dict}')
print('executing p_shop_get_many_stock_item')
result = self.db_procedure_execute('p_shop_get_many_stock_item', argument_dict)
@@ -85,7 +77,7 @@ class DataStore_Store_Stock_Item(DataStore_Store_Base):
print(f'raw categories: {result_set_1}')
for row in result_set_1:
new_stock_item = Stock_Item.from_DB_stock_item(row)
- category_list.add_stock_item(new_stock_item, row)
+ category_list.add_stock_item(new_stock_item) # , row)
# Errors
cursor.nextset()
@@ -112,5 +104,47 @@ class DataStore_Store_Stock_Item(DataStore_Store_Base):
if 'region' in error.msg or 'currency' in error.msg:
permutation.is_unavailable_in_currency_or_region = True
"""
+ DataStore_Store_Stock_Item.db_cursor_clear(cursor)
return category_list, errors # categories, category_index
-
\ No newline at end of file
+
+ @classmethod
+ def save_stock_items(cls, comment, stock_items):
+ _m = 'DataStore_Store_Stock_Item.save_stock_items'
+ av.val_str(comment, 'comment', _m)
+
+ guid = Helper_DB_MySQL.create_guid_str()
+ now = datetime.now()
+ user = cls.get_user_session()
+ rows = []
+ for stock_item in stock_items:
+ # row = permutation.to_temporary_record()
+ row = Stock_Item_Temp.from_stock_item(stock_item)
+ row.guid = guid
+ rows.append(row)
+
+ print(f'rows: {rows}')
+
+ DataStore_Store_Base.upload_bulk(Stock_Item_Temp.__tablename__, rows, 1000)
+ print('bulk uploaded')
+
+ argument_dict_list = {
+ 'a_comment': comment,
+ 'a_guid': guid,
+ 'a_id_user': user.id_user,
+ 'a_debug': 0
+ }
+ result = cls.db_procedure_execute('p_shop_save_stock_item', argument_dict_list)
+ print('saved product permutations')
+
+ # Errors
+ cursor = result.cursor
+ cursor.nextset()
+ result_set_e = cursor.fetchall()
+ print(f'raw errors: {result_set_e}')
+ errors = []
+ if len(result_set_e) > 0:
+ errors = [SQL_Error.from_DB_record(row) for row in result_set_e] # (row[0], row[1])
+ for error in errors:
+ print(f"Error [{error.code}]: {error.msg}")
+ DataStore_Store_Stock_Item.db_cursor_clear(cursor)
+ return errors
diff --git a/datastores/datastore_store_stripe.py b/datastores/datastore_store_stripe.py
index 0c11fe8f..4cae7b7f 100644
--- a/datastores/datastore_store_stripe.py
+++ b/datastores/datastore_store_stripe.py
@@ -15,10 +15,10 @@ Datastore for Store Stripe service
import lib.argument_validation as av
from business_objects.store.basket import Basket, Basket_Item
from business_objects.store.product_category import Product_Category_Container, Product_Category
-from business_objects.store.currency import Currency
+from business_objects.currency import Currency
from business_objects.store.image import Image
from business_objects.store.delivery_option import Delivery_Option
-from business_objects.store.delivery_region import Delivery_Region
+from business_objects.region import Region
from business_objects.store.discount import Discount
from business_objects.store.order import Order
from business_objects.store.product import Product, Product_Permutation, Product_Price, Parameters_Product
diff --git a/datastores/datastore_user.py b/datastores/datastore_user.py
index 1936cf13..b8c65261 100644
--- a/datastores/datastore_user.py
+++ b/datastores/datastore_user.py
@@ -139,6 +139,76 @@ class DataStore_User(DataStore_Base):
'a_id_user': user.id_user
, 'a_id_user_auth0': user.id_user_auth0
, **user_filters.to_json()
+ , 'a_debug': 0
+
+ }
+ # argument_dict_list['a_guid'] = guid
+ result = self.db_procedure_execute('p_get_many_user', argument_dict_list)
+ """
+ query = text(f"SELECT * FROM Shop_Calc_User_Temp UE_T WHERE UE_T.guid = '{guid}'")
+ result = self.db.session.execute(query)
+ """
+ cursor = result.cursor
+ result_set = cursor.fetchall()
+ print(f'raw users: {result_set}')
+ print(f'type result set: {str(type(result_set))}')
+ print(f'len result set: {len(result_set)}')
+ """
+ user_permission_evals = []
+ for row in result_set:
+ user_permission_eval = User_Permission_Evaluation.from_DB_user_eval(row)
+ user_permission_evals.append(user_permission_eval)
+ print(f'user_permission_evals: {user_permission_evals}')
+ """
+ users = []
+ if len(result_set) > 0:
+ for row in result_set:
+ print(f'row: {row}')
+ user = User.from_DB_user(row)
+ users.append(user)
+ print(f'user {str(type(user))}: {user}')
+ print(f'type users: {str(type(users))}\n type user 0: {str(type(None if len(users) == 0 else users[0]))}')
+ # error_list, cursor = self.get_error_list_from_cursor(cursor)
+ errors = []
+ cursor.nextset()
+ result_set_e = cursor.fetchall()
+ print(f'raw errors: {result_set_e}')
+ if len(result_set_e) > 0:
+ errors = [SQL_Error.from_DB_record(row) for row in result_set_e] # [SQL_Error(row[0], row[1]) for row in result_set_e]
+ for error in errors:
+ print(f"Error [{error.code}]: {error.msg}")
+
+ DataStore_User.db_cursor_clear(cursor)
+
+ return users, errors
+
+ def get_many_user(self, user_filters, user=None):
+ _m = 'DataStore_User.get_many_user'
+ print(_m)
+ # av.val_str(user_filters, 'user_filters', _m)
+ # av.val_list(permutations, 'list_permutations', _m, Product_Permutation, 1)
+ av.val_instance(user_filters, 'user_filters', _m, User_Filters)
+
+ guid = Helper_DB_MySQL.create_guid()
+ # now = datetime.now()
+ # user = self.get_user_session()
+
+ """
+ argument_dict_list = {
+ 'a_id_user': id_user,
+ 'a_comment': comment,
+ 'a_guid': guid
+ }
+ """
+ if user is None:
+ user = self.get_user_session()
+ argument_dict_list = {
+ # 'a_guid': guid
+ 'a_id_user': user.id_user
+ , 'a_id_user_auth0': user.id_user_auth0
+ , **user_filters.to_json()
+ , 'a_debug': 0
+
}
# argument_dict_list['a_guid'] = guid
result = self.db_procedure_execute('p_get_many_user', argument_dict_list)
diff --git a/forms/__pycache__/__init__.cpython-312.pyc b/forms/__pycache__/__init__.cpython-312.pyc
index 02f75864..4cfa2a5a 100644
Binary files a/forms/__pycache__/__init__.cpython-312.pyc and b/forms/__pycache__/__init__.cpython-312.pyc differ
diff --git a/forms/__pycache__/access_level.cpython-312.pyc b/forms/__pycache__/access_level.cpython-312.pyc
index 40a47abc..9174ed14 100644
Binary files a/forms/__pycache__/access_level.cpython-312.pyc and b/forms/__pycache__/access_level.cpython-312.pyc differ
diff --git a/forms/__pycache__/base.cpython-312.pyc b/forms/__pycache__/base.cpython-312.pyc
index 5ba31834..4fd011ac 100644
Binary files a/forms/__pycache__/base.cpython-312.pyc and b/forms/__pycache__/base.cpython-312.pyc differ
diff --git a/forms/__pycache__/forms.cpython-312.pyc b/forms/__pycache__/forms.cpython-312.pyc
index 92dd7e30..dfb3fa02 100644
Binary files a/forms/__pycache__/forms.cpython-312.pyc and b/forms/__pycache__/forms.cpython-312.pyc differ
diff --git a/forms/__pycache__/unit_measurement.cpython-312.pyc b/forms/__pycache__/unit_measurement.cpython-312.pyc
index a68ac77a..7827d856 100644
Binary files a/forms/__pycache__/unit_measurement.cpython-312.pyc and b/forms/__pycache__/unit_measurement.cpython-312.pyc differ
diff --git a/forms/access_level.py b/forms/access_level.py
index c9136e88..5fd6f2fc 100644
--- a/forms/access_level.py
+++ b/forms/access_level.py
@@ -23,7 +23,7 @@ from abc import ABCMeta, abstractmethod
class Filters_Access_Level(Form_Base):
- active = BooleanField("Active only?")
+ active = BooleanField("Active only?", default = True)
def __repr__(self):
return f'{self.__class__.__name__}(active={self.active.data})'
@classmethod
diff --git a/forms/forms.py b/forms/forms.py
index 1a5bad3d..93419717 100644
--- a/forms/forms.py
+++ b/forms/forms.py
@@ -122,7 +122,7 @@ class Form_Supplier(FlaskForm):
fax = StringField('Fax number')
website = StringField('Website')
id_currency = SelectField('Currency ID')
- is_active = BooleanField('Active')
+ is_active = BooleanField('Active', default = True)
# class Form_Supplier_Purchase_Order(FlaskForm):
@@ -130,5 +130,5 @@ class Form_Supplier(FlaskForm):
# User
class Form_Filters_User(FlaskForm):
- active = BooleanField('Active only?')
+ active = BooleanField('Active only?', default = True)
id_user = SelectField('User ID', validators=[Optional()], choices=[])
\ No newline at end of file
diff --git a/forms/store/__pycache__/__init__.cpython-312.pyc b/forms/store/__pycache__/__init__.cpython-312.pyc
index b0530ac6..f2679b87 100644
Binary files a/forms/store/__pycache__/__init__.cpython-312.pyc and b/forms/store/__pycache__/__init__.cpython-312.pyc differ
diff --git a/forms/store/__pycache__/product.cpython-312.pyc b/forms/store/__pycache__/product.cpython-312.pyc
index 7d88d192..2e89a74c 100644
Binary files a/forms/store/__pycache__/product.cpython-312.pyc and b/forms/store/__pycache__/product.cpython-312.pyc differ
diff --git a/forms/store/__pycache__/product_category.cpython-312.pyc b/forms/store/__pycache__/product_category.cpython-312.pyc
index 1acd6363..4b9588f9 100644
Binary files a/forms/store/__pycache__/product_category.cpython-312.pyc and b/forms/store/__pycache__/product_category.cpython-312.pyc differ
diff --git a/forms/store/__pycache__/product_permutation.cpython-312.pyc b/forms/store/__pycache__/product_permutation.cpython-312.pyc
index 3bfc0602..78ec6a34 100644
Binary files a/forms/store/__pycache__/product_permutation.cpython-312.pyc and b/forms/store/__pycache__/product_permutation.cpython-312.pyc differ
diff --git a/forms/store/product.py b/forms/store/product.py
index 7eb3df1d..b1c7c6da 100644
--- a/forms/store/product.py
+++ b/forms/store/product.py
@@ -24,7 +24,7 @@ from flask_wtf.recaptcha import RecaptchaField
class Filters_Product(FlaskForm):
id_category = SelectField('Category', validators=[Optional()], choices=[('', 'All')])
is_not_empty = BooleanField('Not empty only?')
- active = BooleanField("Active only?")
+ active = BooleanField("Active only?", default = True)
@classmethod
def from_filters_product(cls, filters_product):
form = Filters_Product()
diff --git a/forms/store/product_category.py b/forms/store/product_category.py
index f2229d47..463540ab 100644
--- a/forms/store/product_category.py
+++ b/forms/store/product_category.py
@@ -27,7 +27,7 @@ from abc import ABCMeta, abstractmethod
class Filters_Product_Category(Form_Base):
is_not_empty = BooleanField('Not empty only?')
- active = BooleanField("Active only?")
+ active = BooleanField("Active only?", default = True)
"""
@classmethod
def from_filters(cls, filters):
diff --git a/forms/store/stock_item.py b/forms/store/stock_item.py
index a1eab1d8..0388031f 100644
--- a/forms/store/stock_item.py
+++ b/forms/store/stock_item.py
@@ -25,8 +25,8 @@ from flask_wtf.recaptcha import RecaptchaField
from abc import ABCMeta, abstractmethod
class Filters_Stock_Item(Form_Base):
- id_category = SelectField('Category', validators=[Optional()], choices=[])
- id_product = SelectField('Product', validators=[Optional()], choices=[])
+ id_category = SelectField('Category', choices=[Form_Base.get_choice_all()], default='')
+ id_product = SelectField('Product', choices=[Form_Base.get_choice_all()], default='')
is_out_of_stock = BooleanField('Out of stock only?')
quantity_min = FloatField('Min stock')
quantity_max = FloatField('Max stock')
@@ -45,9 +45,9 @@ class Filters_Stock_Item(Form_Base):
@classmethod
def from_json(cls, json):
form = cls()
- form.id_category.choices = [(json[Store_Base.ATTR_ID_PRODUCT_CATEGORY], json[Store_Base.ATTR_ID_PRODUCT_CATEGORY])]
+ # form.id_category.choices = [(json[Store_Base.ATTR_ID_PRODUCT_CATEGORY], json[Store_Base.ATTR_ID_PRODUCT_CATEGORY])]
form.id_category.data = json[Store_Base.ATTR_ID_PRODUCT_CATEGORY]
- form.id_product.choices = [(json[Store_Base.ATTR_ID_PRODUCT], json[Store_Base.ATTR_ID_PRODUCT])]
+ # form.id_product.choices = [(json[Store_Base.ATTR_ID_PRODUCT], json[Store_Base.ATTR_ID_PRODUCT])]
form.id_product.data = json[Store_Base.ATTR_ID_PRODUCT]
form.is_out_of_stock.data = av.input_bool(json[Store_Base.FLAG_IS_OUT_OF_STOCK], Store_Base.FLAG_IS_OUT_OF_STOCK, f'{cls.__name__}.from_json')
form.quantity_min.data = json[Store_Base.FLAG_QUANTITY_MIN]
@@ -65,4 +65,12 @@ class Filters_Stock_Item(Form_Base):
def get_default(cls):
filters = cls()
filters.id_category.choices = cls.get_choices_blank()
- filters.id_product.choices = cls.get_choices_blank()
\ No newline at end of file
+ filters.id_product.choices = cls.get_choices_blank()
+ """
+ def import_values(self, form_filters):
+ self.id_category.data = form_filters.id_category.data
+ self.id_product.data = form_filters.id_product.data
+ self.is_out_of_stock.data = form_filters.is_out_of_stock.data
+ self.quantity_min.data = form_filters.quantity_min.data
+ self.quantity_max.data = form_filters.quantity_max.data
+ """
\ No newline at end of file
diff --git a/forms/unit_measurement.py b/forms/unit_measurement.py
index 9f69daa4..2c2d46e2 100644
--- a/forms/unit_measurement.py
+++ b/forms/unit_measurement.py
@@ -23,7 +23,7 @@ from abc import ABCMeta, abstractmethod
class Filters_Unit_Measurement(Form_Base):
- active = BooleanField("Active only?")
+ active = BooleanField("Active only?", default = True)
@classmethod
def from_filters(cls, filters):
form = Filters_Unit_Measurement()
diff --git a/helpers/__pycache__/__init__.cpython-312.pyc b/helpers/__pycache__/__init__.cpython-312.pyc
index d53abf27..2149f674 100644
Binary files a/helpers/__pycache__/__init__.cpython-312.pyc and b/helpers/__pycache__/__init__.cpython-312.pyc differ
diff --git a/helpers/__pycache__/helper_app.cpython-312.pyc b/helpers/__pycache__/helper_app.cpython-312.pyc
index 5ae92951..13087f28 100644
Binary files a/helpers/__pycache__/helper_app.cpython-312.pyc and b/helpers/__pycache__/helper_app.cpython-312.pyc differ
diff --git a/helpers/__pycache__/helper_db_mysql.cpython-312.pyc b/helpers/__pycache__/helper_db_mysql.cpython-312.pyc
index bc9fbf83..b0ddfb16 100644
Binary files a/helpers/__pycache__/helper_db_mysql.cpython-312.pyc and b/helpers/__pycache__/helper_db_mysql.cpython-312.pyc differ
diff --git a/lib/__pycache__/__init__.cpython-312.pyc b/lib/__pycache__/__init__.cpython-312.pyc
index 252f070f..a40d61ac 100644
Binary files a/lib/__pycache__/__init__.cpython-312.pyc and b/lib/__pycache__/__init__.cpython-312.pyc differ
diff --git a/lib/__pycache__/argument_validation.cpython-312.pyc b/lib/__pycache__/argument_validation.cpython-312.pyc
index 48ef064e..826d786d 100644
Binary files a/lib/__pycache__/argument_validation.cpython-312.pyc and b/lib/__pycache__/argument_validation.cpython-312.pyc differ
diff --git a/lib/__pycache__/data_types.cpython-312.pyc b/lib/__pycache__/data_types.cpython-312.pyc
index 65125b4d..e9f14a17 100644
Binary files a/lib/__pycache__/data_types.cpython-312.pyc and b/lib/__pycache__/data_types.cpython-312.pyc differ
diff --git a/models/__pycache__/__init__.cpython-312.pyc b/models/__pycache__/__init__.cpython-312.pyc
index 224e41c5..9cf8329f 100644
Binary files a/models/__pycache__/__init__.cpython-312.pyc and b/models/__pycache__/__init__.cpython-312.pyc differ
diff --git a/models/__pycache__/model_view_accessibility_report.cpython-312.pyc b/models/__pycache__/model_view_accessibility_report.cpython-312.pyc
index f478875b..23a454e0 100644
Binary files a/models/__pycache__/model_view_accessibility_report.cpython-312.pyc and b/models/__pycache__/model_view_accessibility_report.cpython-312.pyc differ
diff --git a/models/__pycache__/model_view_accessibility_statement.cpython-312.pyc b/models/__pycache__/model_view_accessibility_statement.cpython-312.pyc
index cb617569..03289019 100644
Binary files a/models/__pycache__/model_view_accessibility_statement.cpython-312.pyc and b/models/__pycache__/model_view_accessibility_statement.cpython-312.pyc differ
diff --git a/models/__pycache__/model_view_admin.cpython-312.pyc b/models/__pycache__/model_view_admin.cpython-312.pyc
index e2b594c3..b3c78373 100644
Binary files a/models/__pycache__/model_view_admin.cpython-312.pyc and b/models/__pycache__/model_view_admin.cpython-312.pyc differ
diff --git a/models/__pycache__/model_view_admin_home.cpython-312.pyc b/models/__pycache__/model_view_admin_home.cpython-312.pyc
index e7d0c4a1..52923e1d 100644
Binary files a/models/__pycache__/model_view_admin_home.cpython-312.pyc and b/models/__pycache__/model_view_admin_home.cpython-312.pyc differ
diff --git a/models/__pycache__/model_view_base.cpython-312.pyc b/models/__pycache__/model_view_base.cpython-312.pyc
index 856adc48..914d4d6b 100644
Binary files a/models/__pycache__/model_view_base.cpython-312.pyc and b/models/__pycache__/model_view_base.cpython-312.pyc differ
diff --git a/models/__pycache__/model_view_contact.cpython-312.pyc b/models/__pycache__/model_view_contact.cpython-312.pyc
index 1df0e1a0..013bcbdd 100644
Binary files a/models/__pycache__/model_view_contact.cpython-312.pyc and b/models/__pycache__/model_view_contact.cpython-312.pyc differ
diff --git a/models/__pycache__/model_view_home.cpython-312.pyc b/models/__pycache__/model_view_home.cpython-312.pyc
index a930b8ac..a3077269 100644
Binary files a/models/__pycache__/model_view_home.cpython-312.pyc and b/models/__pycache__/model_view_home.cpython-312.pyc differ
diff --git a/models/__pycache__/model_view_license.cpython-312.pyc b/models/__pycache__/model_view_license.cpython-312.pyc
index a642a516..9b6a6d0d 100644
Binary files a/models/__pycache__/model_view_license.cpython-312.pyc and b/models/__pycache__/model_view_license.cpython-312.pyc differ
diff --git a/models/__pycache__/model_view_privacy_policy.cpython-312.pyc b/models/__pycache__/model_view_privacy_policy.cpython-312.pyc
index 72352694..336261ec 100644
Binary files a/models/__pycache__/model_view_privacy_policy.cpython-312.pyc and b/models/__pycache__/model_view_privacy_policy.cpython-312.pyc differ
diff --git a/models/__pycache__/model_view_retention_schedule.cpython-312.pyc b/models/__pycache__/model_view_retention_schedule.cpython-312.pyc
index 67015cb5..f470d4c7 100644
Binary files a/models/__pycache__/model_view_retention_schedule.cpython-312.pyc and b/models/__pycache__/model_view_retention_schedule.cpython-312.pyc differ
diff --git a/models/__pycache__/model_view_services.cpython-312.pyc b/models/__pycache__/model_view_services.cpython-312.pyc
index e9b67bc5..17d8c19f 100644
Binary files a/models/__pycache__/model_view_services.cpython-312.pyc and b/models/__pycache__/model_view_services.cpython-312.pyc differ
diff --git a/models/__pycache__/model_view_store.cpython-312.pyc b/models/__pycache__/model_view_store.cpython-312.pyc
index 9b2631b7..550a7117 100644
Binary files a/models/__pycache__/model_view_store.cpython-312.pyc and b/models/__pycache__/model_view_store.cpython-312.pyc differ
diff --git a/models/__pycache__/model_view_store_product.cpython-312.pyc b/models/__pycache__/model_view_store_product.cpython-312.pyc
index d9585874..adf0be07 100644
Binary files a/models/__pycache__/model_view_store_product.cpython-312.pyc and b/models/__pycache__/model_view_store_product.cpython-312.pyc differ
diff --git a/models/__pycache__/model_view_store_product_category.cpython-312.pyc b/models/__pycache__/model_view_store_product_category.cpython-312.pyc
index a567b97f..3fd6ccd4 100644
Binary files a/models/__pycache__/model_view_store_product_category.cpython-312.pyc and b/models/__pycache__/model_view_store_product_category.cpython-312.pyc differ
diff --git a/models/__pycache__/model_view_store_product_permutation.cpython-312.pyc b/models/__pycache__/model_view_store_product_permutation.cpython-312.pyc
index a9b11f75..dea5d6ed 100644
Binary files a/models/__pycache__/model_view_store_product_permutation.cpython-312.pyc and b/models/__pycache__/model_view_store_product_permutation.cpython-312.pyc differ
diff --git a/models/__pycache__/model_view_store_stock_item.cpython-312.pyc b/models/__pycache__/model_view_store_stock_item.cpython-312.pyc
index b82b4079..e6a9c4a1 100644
Binary files a/models/__pycache__/model_view_store_stock_item.cpython-312.pyc and b/models/__pycache__/model_view_store_stock_item.cpython-312.pyc differ
diff --git a/models/__pycache__/model_view_store_supplier.cpython-312.pyc b/models/__pycache__/model_view_store_supplier.cpython-312.pyc
index 9bca2131..dc768bbc 100644
Binary files a/models/__pycache__/model_view_store_supplier.cpython-312.pyc and b/models/__pycache__/model_view_store_supplier.cpython-312.pyc differ
diff --git a/models/__pycache__/model_view_user.cpython-312.pyc b/models/__pycache__/model_view_user.cpython-312.pyc
index 3341b189..4f2a389e 100644
Binary files a/models/__pycache__/model_view_user.cpython-312.pyc and b/models/__pycache__/model_view_user.cpython-312.pyc differ
diff --git a/models/model_view_base.py b/models/model_view_base.py
index fb025248..bd3187e8 100644
--- a/models/model_view_base.py
+++ b/models/model_view_base.py
@@ -21,7 +21,7 @@ import lib.argument_validation as av
from forms.forms import Form_Is_Included_VAT, Form_Delivery_Region, Form_Currency
from datastores.datastore_base import DataStore_Base
from datastores.datastore_user import DataStore_User
-from business_objects.store.store_base import Store_Base
+from business_objects.base import Base
from business_objects.store.product_category import Product_Category
from forms.access_level import Filters_Access_Level
from forms.unit_measurement import Filters_Unit_Measurement
@@ -37,20 +37,25 @@ from typing import ClassVar
class Model_View_Base(BaseModel, ABC):
# Global constants
# ATTR_FOR: ClassVar[str] = 'for'
- ATTR_ID_ACCESS_LEVEL: ClassVar[str] = Store_Base.ATTR_ID_ACCESS_LEVEL
+ ATTR_ID_ACCESS_LEVEL: ClassVar[str] = Base.ATTR_ID_ACCESS_LEVEL
+ ATTR_ID_ADDRESS: ClassVar[str] = Base.ATTR_ID_ADDRESS
+ ATTR_ID_CURRENCY: ClassVar[str] = Base.ATTR_ID_CURRENCY
+ ATTR_ID_REGION: ClassVar[str] = Base.ATTR_ID_REGION
ATTR_TEXT_COLLAPSED: ClassVar[str] = 'textCollapsed'
ATTR_TEXT_EXPANDED: ClassVar[str] = 'textExpanded'
ATTR_VALUE_CURRENT: ClassVar[str] = 'current-value'
ATTR_VALUE_PREVIOUS: ClassVar[str] = 'previous-value'
FLAG_ACCESS_LEVEL: ClassVar[str] = 'access_level'
FLAG_ACCESS_LEVEL_REQUIRED: ClassVar[str] = Product_Category.FLAG_ACCESS_LEVEL_REQUIRED
- FLAG_ACTIVE: ClassVar[str] = Store_Base.FLAG_ACTIVE
+ FLAG_ACTIVE: ClassVar[str] = Base.FLAG_ACTIVE
FLAG_ADD: ClassVar[str] = 'add'
+ FLAG_BOOL_FALSE: ClassVar[str] = 'false'
+ FLAG_BOOL_TRUE: ClassVar[str] = 'true'
FLAG_CANCEL: ClassVar[str] = 'button-cancel'
# FLAG_CONTACT_US: ClassVar[str] = 'button-contact'
FLAG_CLOSE_TEMPORARY_ELEMENT: ClassVar[str] = 'button-temporary-element-close'
FLAG_CARD: ClassVar[str] = 'card'
- FLAG_CODE: ClassVar[str] = Store_Base.FLAG_CODE
+ FLAG_CODE: ClassVar[str] = Base.FLAG_CODE
FLAG_COLLAPSED: ClassVar[str] = 'collapsed'
FLAG_COLLAPSIBLE: ClassVar[str] = 'collapsible'
FLAG_COLUMN: ClassVar[str] = 'column'
@@ -59,11 +64,11 @@ class Model_View_Base(BaseModel, ABC):
FLAG_CONTAINER_INPUT: ClassVar[str] = FLAG_CONTAINER + '-input'
FLAG_CURRENCY: ClassVar[str] = 'currency'
FLAG_DELETE: ClassVar[str] = 'delete'
- FLAG_DESCRIPTION: ClassVar[str] = Store_Base.FLAG_DESCRIPTION
+ FLAG_DESCRIPTION: ClassVar[str] = Base.FLAG_DESCRIPTION
FLAG_DETAIL: ClassVar[str] = 'detail'
FLAG_DIALOG: ClassVar[str] = 'dialog' # try |