feat(UI): Stock Items page added with getting, filtering, and saving data.

This commit is contained in:
2024-10-13 19:40:25 +01:00
parent 8e1651d9d7
commit fdcf448bb1
187 changed files with 5939 additions and 8825 deletions

View File

@@ -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

Binary file not shown.

Binary file not shown.

Binary file not shown.

111
app.log
View File

@@ -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
<td class="{{ model.FLAG_PRODUCT_CATEGORY }}" {{ model.ATTR_VALUE_CURRENT }}="{{ permutation.id_category }}" {{ model.ATTR_VALUE_PREVIOUS }}="{{ permutation.id_category }}">
^^^^^^^^^^^^^^^^^^^^^^^^^
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)

View File

@@ -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
@@ -15,9 +58,9 @@ Traceback (most recent call last):
^^^^^
NameError: name 'nself' is not defined. Did you mean: 'self'?
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)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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
@@ -28,38 +71,20 @@ Traceback (most recent call last):
^^^^^^^^^^^^^^^^^^
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\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\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\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\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\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\components\store\_row_product.html", line 38, in top-level template code
<td class="{{ model.FLAG_PRODUCT_CATEGORY }}" {{ model.ATTR_VALUE_CURRENT }}="{{ permutation.id_category }}" {{ model.ATTR_VALUE_PREVIOUS }}="{{ permutation.id_category }}">
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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()
jinja2.exceptions.UndefinedError: 'permutation' is undefined
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)
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

109
app.log.2
View File

@@ -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 <class 'business_objects.store.product.Product'> argument product. Type = <class 'business_objects.store.product.Product'>. 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
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
@@ -75,29 +33,36 @@ Traceback: Traceback (most recent call last):
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 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
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 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)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

109
app.log.3
View File

@@ -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 <class 'business_objects.store.product.Product'> argument product. Type = <class 'business_objects.store.product.Product'>. 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
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
@@ -75,29 +33,36 @@ Traceback: Traceback (most recent call last):
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 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
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 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)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@@ -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

View File

@@ -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'

View File

@@ -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}

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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):

View File

@@ -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)
"""

View File

@@ -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}

View File

@@ -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]

View File

@@ -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

View File

@@ -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()
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}
'''

View File

@@ -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}'

View File

@@ -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'

View File

@@ -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

View File

@@ -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

View File

@@ -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,

View File

@@ -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()

View File

@@ -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,

View File

@@ -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()

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
@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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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=[])

View File

@@ -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()

View File

@@ -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):

View File

@@ -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()
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
"""

View File

@@ -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()

Some files were not shown because too many files have changed in this diff Show More