From 45ac0405b4ad3357f6dbfb895e8dff9a36eb4a58 Mon Sep 17 00:00:00 2001 From: teddy Date: Tue, 24 Sep 2024 23:25:52 +0100 Subject: [PATCH] 1. View, filter, and save Product Permutation. \n 2. Synchronised with Product Category page and all common functionality moved into base and base table css, js, and python files. --- __pycache__/app.cpython-312.pyc | Bin 5249 -> 5522 bytes app.log | 107 +- app.log.1 | 107 +- app.log.2 | 52 + app.log.3 | 83 + app.py | 25 +- .../__pycache__/base.cpython-312.pyc | Bin 3305 -> 3537 bytes .../__pycache__/db_base.cpython-312.pyc | Bin 3523 -> 3397 bytes .../unit_measurement.cpython-312.pyc | Bin 0 -> 7204 bytes .../__pycache__/user.cpython-312.pyc | Bin 12372 -> 12604 bytes business_objects/base.py | 59 + business_objects/db_base.py | 2 + .../__pycache__/access_level.cpython-312.pyc | Bin 7015 -> 6639 bytes .../store/__pycache__/basket.cpython-312.pyc | Bin 9687 -> 9850 bytes .../__pycache__/currency.cpython-312.pyc | Bin 4095 -> 6193 bytes .../delivery_region.cpython-312.pyc | Bin 4216 -> 4560 bytes .../store/__pycache__/image.cpython-312.pyc | Bin 5119 -> 5821 bytes .../store/__pycache__/order.cpython-312.pyc | Bin 3878 -> 4041 bytes .../store/__pycache__/product.cpython-312.pyc | Bin 28302 -> 29175 bytes .../product_category.cpython-312.pyc | Bin 25361 -> 29525 bytes .../product_permutation.cpython-312.pyc | Bin 22232 -> 42329 bytes .../__pycache__/product_price.cpython-312.pyc | Bin 7141 -> 6185 bytes .../product_variation.cpython-312.pyc | Bin 11466 -> 10691 bytes .../product_variation_tree.cpython-312.pyc | Bin 6590 -> 8757 bytes .../product_variation_type.cpython-312.pyc | Bin 0 -> 5793 bytes .../__pycache__/stock_item.cpython-312.pyc | Bin 16592 -> 16851 bytes .../__pycache__/store_base.cpython-312.pyc | Bin 3641 -> 2927 bytes business_objects/store/access_level.py | 24 +- business_objects/store/basket.py | 4 +- business_objects/store/currency.py | 91 +- business_objects/store/delivery_region.py | 34 +- business_objects/store/image.py | 14 +- business_objects/store/order.py | 4 +- business_objects/store/product.py | 41 +- business_objects/store/product_category.py | 109 +- business_objects/store/product_permutation.py | 396 +++- business_objects/store/product_price.py | 57 +- business_objects/store/product_variation.py | 154 +- .../store/product_variation_tree.py | 93 +- .../store/product_variation_type.py | 103 + business_objects/store/stock_item.py | 7 +- business_objects/store/store_base.py | 46 +- business_objects/unit_measurement.py | 160 ++ business_objects/user.py | 8 +- {routing => controllers}/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin controllers/__pycache__/core.cpython-312.pyc | Bin 0 -> 5629 bytes .../__pycache__/legal.cpython-312.pyc | Bin .../__pycache__/store.cpython-312.pyc | Bin .../store_product_category.cpython-312.pyc | Bin .../store_product_permutation.cpython-312.pyc | Bin .../store_stock_item.cpython-312.pyc | Bin .../store_supplier.cpython-312.pyc | Bin .../__pycache__/user.cpython-312.pyc | Bin {routing => controllers}/core.py | 4 + {routing => controllers}/legal.py | 0 {routing => controllers}/store/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin .../store/__pycache__/product.cpython-312.pyc | Bin .../product_category.cpython-312.pyc | Bin 6010 -> 6033 bytes .../product_permutation.cpython-312.pyc | Bin 0 -> 6333 bytes .../__pycache__/stock_item.cpython-312.pyc | Bin 0 -> 4943 bytes .../store/__pycache__/store.cpython-312.pyc | Bin .../__pycache__/supplier.cpython-312.pyc | Bin 4056 -> 4022 bytes {routing => controllers}/store/product.py | 0 .../store/product_category.py | 10 +- controllers/store/product_permutation.py | 159 ++ {routing => controllers}/store/stock_item.py | 2 +- {routing => controllers}/store/store.py | 0 {routing => controllers}/store/supplier.py | 2 +- {routing => controllers}/user.py | 0 .../datastore_base.cpython-312.pyc | Bin 9650 -> 11566 bytes .../datastore_store_base.cpython-312.pyc | Bin 11775 -> 13060 bytes .../datastore_store_basket.cpython-312.pyc | Bin 7324 -> 7329 bytes ...ore_store_product_category.cpython-312.pyc | Bin 7376 -> 4377 bytes ..._store_product_permutation.cpython-312.pyc | Bin 4450 -> 3089 bytes ...datastore_store_stock_item.cpython-312.pyc | Bin 7587 -> 7592 bytes .../datastore_user.cpython-312.pyc | Bin 6547 -> 5639 bytes datastores/datastore_base.py | 83 +- datastores/datastore_store_base.py | 71 +- datastores/datastore_store_basket.py | 2 +- datastores/datastore_store_product.py | 4 +- .../datastore_store_product_category.py | 71 +- .../datastore_store_product_permutation.py | 86 +- .../datastore_store_product_variation.py | 4 +- datastores/datastore_store_stock_item.py | 2 +- datastores/datastore_store_stripe.py | 2 +- datastores/datastore_user.py | 10 - .../__pycache__/access_level.cpython-312.pyc | Bin 0 -> 2667 bytes forms/__pycache__/base.cpython-312.pyc | Bin 1488 -> 1425 bytes forms/__pycache__/forms.cpython-312.pyc | Bin 6454 -> 6153 bytes .../unit_measurement.cpython-312.pyc | Bin 0 -> 2857 bytes forms/access_level.py | 37 + forms/base.py | 20 +- forms/forms.py | 7 - .../product_category.cpython-312.pyc | Bin 2815 -> 2446 bytes .../product_permutation.cpython-312.pyc | Bin 0 -> 3724 bytes forms/store/product_category.py | 2 + forms/store/product_permutation.py | 65 + forms/unit_measurement.py | 42 + .../model_view_base.cpython-312.pyc | Bin 13918 -> 16803 bytes .../model_view_store.cpython-312.pyc | Bin 18162 -> 21172 bytes ...iew_store_product_category.cpython-312.pyc | Bin 3129 -> 3056 bytes ..._store_product_permutation.cpython-312.pyc | Bin 4867 -> 6301 bytes models/model_view_base.py | 44 +- models/model_view_store.py | 94 +- models/model_view_store_product_category.py | 6 +- .../model_view_store_product_permutation.py | 78 +- routes.py | 54 - routing/__pycache__/core.cpython-312.pyc | Bin 5152 -> 0 bytes .../product_permutation.cpython-312.pyc | Bin 6840 -> 0 bytes .../__pycache__/stock_item.cpython-312.pyc | Bin 5001 -> 0 bytes routing/store/product_permutation.py | 90 - static/MySQL/0000_combine.sql | 1650 +++++++++-------- static/MySQL/0001_destroy.sql | 10 +- .../MySQL/1121_tbl_Shop_Unit_Measurement.sql | 1 + static/MySQL/1203_tbl_Shop_Product.sql | 10 +- .../1206_tbl_Shop_Product_Permutation.sql | 24 +- ...1208_tbl_Shop_Product_Permutation_Temp.sql | 26 +- static/MySQL/3203_tri_Shop_Product.sql | 16 +- .../3206_tri_Shop_Product_Permutation.sql | 58 +- ...6_fn_shop_get_product_permutation_name.sql | 33 + .../7003_p_shop_get_many_access_level.sql | 13 +- .../MySQL/7116_p_shop_get_many_currency.sql | 5 +- .../7122_p_shop_get_many_unit_measurement.sql | 41 + .../7200_p_shop_save_product_category.sql | 2 - static/MySQL/7204_p_shop_get_many_product.sql | 76 +- static/MySQL/7206_p_shop_save_permutation.sql | 605 ------ .../7206_p_shop_save_product_permutation.sql | 561 ++++++ ...7210_p_shop_get_many_product_variation.sql | 26 +- .../MySQL/7219_p_shop_get_many_stock_item.sql | 12 +- ...price_and_discount_and_delivery_option.sql | 54 +- .../7223_p_shop_get_many_stripe_price_new.sql | 6 +- ..._shop_get_many_supplier_purchase_order.sql | 24 +- ..._get_many_manufacturing_purchase_order.sql | 24 +- ...5_p_shop_get_many_customer_sales_order.sql | 24 +- static/MySQL/9000_populate.sql | 41 +- static/MySQL/9001_view.sql | 4 +- .../deprecated/000_init_tables_product.sql | 54 +- .../108_tbl_Shop_Recurrence_Interval.sql | 6 +- ...109_tbl_Shop_Recurrence_Interval_Audit.sql | 10 +- .../308_tri_Shop_Recurrence_Interval.sql | 14 +- .../deprecated/706_p_shop_get_product.sql | 20 +- static/MySQL/deprecated/dump.sql | 134 +- static/MySQL/deprecated/dump2.sql | 134 +- static/MySQL/temp.txt | 5 +- static/PostgreSQL/000_combine.sql | 218 +-- static/PostgreSQL/001_destroy.sql | 4 +- .../108_tbl_Shop_Recurrence_Interval.sql | 6 +- ...109_tbl_Shop_Recurrence_Interval_Audit.sql | 10 +- static/PostgreSQL/110.8_tbl_Shop_Product.sql | 10 +- .../117.1_tbl_Shop_Product_Permutation.sql | 12 +- .../308_tri_Shop_Recurrence_Interval.sql | 18 +- static/PostgreSQL/310.8_tri_Shop_Product.sql | 16 +- .../317.1_tri_Shop_Product_Permutation.sql | 18 +- static/PostgreSQL/600_p_shop_save_product.sql | 10 +- .../700_p_shop_get_many_product.sql | 34 +- .../705_p_shop_get_many_stripe_price_new.sql | 6 +- ..._shop_get_many_supplier_purchase_order.sql | 24 +- ..._get_many_manufacturing_purchase_order.sql | 24 +- ...0_p_shop_get_many_customer_sales_order.sql | 24 +- static/PostgreSQL/900_populate.sql | 8 +- static/PostgreSQL/901_view.sql | 4 +- static/PostgreSQL/temp.txt | 6 +- static/css/components/table.css | 35 + static/css/layouts/header.css | 15 + static/css/layouts/table-main.css | 15 + static/css/main.css | 57 +- static/css/pages/core/home.css | 3 + static/css/pages/store/product_categories.css | 65 +- .../css/pages/store/product_permutations.css | 114 +- static/css/sections/store.css | 3 +- static/dist/css/416.bundle.css | 1 + static/dist/css/core_home.bundle.css | 3 + static/dist/css/main.bundle.css | 184 +- static/dist/css/main.css | 2 +- static/dist/css/store_home.bundle.css | 53 + .../css/store_product_categories.bundle.css | 118 +- .../css/store_product_permutations.bundle.css | 167 +- static/dist/css/store_stock_items.bundle.css | 53 + .../legal_accessibility_statement.bundle.js | 2 +- static/dist/js/legal_license.bundle.js | 2 +- static/dist/js/legal_privacy_policy.bundle.js | 2 +- .../js/legal_retention_schedule.bundle.js | 2 +- static/dist/js/main.bundle.js | 2 +- static/dist/js/store_home.bundle.js | 1 - .../js/store_product_categories.bundle.js | 1 - .../js/store_product_permutations.bundle.js | 1 - static/dist/js/store_stock_items.bundle.js | 1 - static/dist/page_core_home.chunk.js | 2 +- static/dist/page_privacy_policy.chunk.js | 2 +- static/js/DEPRECATED/routing.js | 2 +- static/js/api.js | 21 +- static/js/app.js | 7 +- .../{ => common/inputs}/input_date.js | 4 +- .../components/{ => common/inputs}/select.js | 4 +- .../{ => common/inputs}/textarea.js | 4 +- static/js/components/{ => common}/table.js | 2 +- .../common/temporary/overlay_confirm.js | 26 + .../common/temporary/overlay_error.js | 19 + static/js/components/{ => common}/video.js | 0 static/js/dom.js | 86 +- static/js/lib/business_objects.js | 24 + static/js/lib/utils.js | 11 +- static/js/pages/base.js | 256 +-- static/js/pages/base_table.js | 383 ++-- static/js/pages/core/admin_home.js | 20 +- static/js/pages/core/home.js | 2 +- static/js/pages/store/basket.js | 8 +- static/js/pages/store/{base.js => mixin.js} | 403 ++-- static/js/pages/store/mixin_table.js | 25 + static/js/pages/store/product_categories.js | 54 +- static/js/pages/store/product_permutations.js | 917 ++++----- static/js/pages/store/stock_items.js | 94 +- static/js/pages/user/user.js | 2 +- static/js/router.js | 18 +- .../common/buttons/_buttons_save_cancel.html | 34 + .../common/buttons/_slider_display_order.html | 13 +- .../common/inputs/_option_blank.html | 1 + ...xtarea_product_permutation_variations.html | 18 - .../_textarea_product_variation_types.html | 20 - .../common/temporary/_overlay_confirm.html | 38 - .../common/temporary/_overlay_error.html | 24 - .../store/_preview_DDL_currency.html | 17 + .../store/_preview_DDL_product.html | 14 + .../store/_preview_DDL_product_category.html | 14 + ...mutation_interval_expiration_unsealed.html | 17 + ...oduct_permutation_interval_recurrence.html | 19 + ...permutation_unit_measurement_quantity.html | 21 + ...review_product_permutation_variations.html | 22 + .../_preview_product_variation_types.html | 15 + .../components/store/_row_permutation.html | 70 - templates/components/store/_row_product.html | 12 +- .../store/_row_product_category.html | 10 +- .../store/_row_product_permutation.html | 163 ++ .../components/store/_row_stock_item.html | 11 +- templates/js/sections/store.js | 52 +- templates/layouts/layout.html | 9 +- .../pages/store/_product_categories.html | 13 +- .../pages/store/_product_permutations.html | 86 +- templates/pages/store/_products.html | 4 +- templates/pages/store/_stock_items.html | 2 +- webpack.config.js | 33 +- 243 files changed, 6596 insertions(+), 4460 deletions(-) create mode 100644 app.log.2 create mode 100644 app.log.3 create mode 100644 business_objects/__pycache__/unit_measurement.cpython-312.pyc create mode 100644 business_objects/base.py create mode 100644 business_objects/store/__pycache__/product_variation_type.cpython-312.pyc create mode 100644 business_objects/store/product_variation_type.py create mode 100644 business_objects/unit_measurement.py rename {routing => controllers}/__init__.py (100%) rename {routing => controllers}/__pycache__/__init__.cpython-312.pyc (100%) create mode 100644 controllers/__pycache__/core.cpython-312.pyc rename {routing => controllers}/__pycache__/legal.cpython-312.pyc (100%) rename {routing => controllers}/__pycache__/store.cpython-312.pyc (100%) rename {routing => controllers}/__pycache__/store_product_category.cpython-312.pyc (100%) rename {routing => controllers}/__pycache__/store_product_permutation.cpython-312.pyc (100%) rename {routing => controllers}/__pycache__/store_stock_item.cpython-312.pyc (100%) rename {routing => controllers}/__pycache__/store_supplier.cpython-312.pyc (100%) rename {routing => controllers}/__pycache__/user.cpython-312.pyc (100%) rename {routing => controllers}/core.py (93%) rename {routing => controllers}/legal.py (100%) rename {routing => controllers}/store/__init__.py (100%) rename {routing => controllers}/store/__pycache__/__init__.cpython-312.pyc (100%) rename {routing => controllers}/store/__pycache__/product.cpython-312.pyc (100%) rename {routing => controllers}/store/__pycache__/product_category.cpython-312.pyc (75%) create mode 100644 controllers/store/__pycache__/product_permutation.cpython-312.pyc create mode 100644 controllers/store/__pycache__/stock_item.cpython-312.pyc rename {routing => controllers}/store/__pycache__/store.cpython-312.pyc (100%) rename {routing => controllers}/store/__pycache__/supplier.cpython-312.pyc (55%) rename {routing => controllers}/store/product.py (100%) rename {routing => controllers}/store/product_category.py (96%) create mode 100644 controllers/store/product_permutation.py rename {routing => controllers}/store/stock_item.py (98%) rename {routing => controllers}/store/store.py (100%) rename {routing => controllers}/store/supplier.py (97%) rename {routing => controllers}/user.py (100%) create mode 100644 forms/__pycache__/access_level.cpython-312.pyc create mode 100644 forms/__pycache__/unit_measurement.cpython-312.pyc create mode 100644 forms/access_level.py create mode 100644 forms/store/__pycache__/product_permutation.cpython-312.pyc create mode 100644 forms/store/product_permutation.py create mode 100644 forms/unit_measurement.py delete mode 100644 routes.py delete mode 100644 routing/__pycache__/core.cpython-312.pyc delete mode 100644 routing/store/__pycache__/product_permutation.cpython-312.pyc delete mode 100644 routing/store/__pycache__/stock_item.cpython-312.pyc delete mode 100644 routing/store/product_permutation.py create mode 100644 static/MySQL/6206_fn_shop_get_product_permutation_name.sql create mode 100644 static/MySQL/7122_p_shop_get_many_unit_measurement.sql delete mode 100644 static/MySQL/7206_p_shop_save_permutation.sql create mode 100644 static/MySQL/7206_p_shop_save_product_permutation.sql create mode 100644 static/css/components/table.css create mode 100644 static/css/layouts/table-main.css create mode 100644 static/dist/css/416.bundle.css rename static/js/components/{ => common/inputs}/input_date.js (98%) rename static/js/components/{ => common/inputs}/select.js (80%) rename static/js/components/{ => common/inputs}/textarea.js (94%) rename static/js/components/{ => common}/table.js (92%) create mode 100644 static/js/components/common/temporary/overlay_confirm.js create mode 100644 static/js/components/common/temporary/overlay_error.js rename static/js/components/{ => common}/video.js (100%) create mode 100644 static/js/lib/business_objects.js rename static/js/pages/store/{base.js => mixin.js} (55%) create mode 100644 static/js/pages/store/mixin_table.js create mode 100644 templates/components/common/inputs/_option_blank.html delete mode 100644 templates/components/common/inputs/_textarea_product_permutation_variations.html delete mode 100644 templates/components/common/inputs/_textarea_product_variation_types.html create mode 100644 templates/components/store/_preview_DDL_currency.html create mode 100644 templates/components/store/_preview_DDL_product.html create mode 100644 templates/components/store/_preview_DDL_product_category.html create mode 100644 templates/components/store/_preview_DDL_product_permutation_interval_expiration_unsealed.html create mode 100644 templates/components/store/_preview_DDL_product_permutation_interval_recurrence.html create mode 100644 templates/components/store/_preview_DDL_product_permutation_unit_measurement_quantity.html create mode 100644 templates/components/store/_preview_product_permutation_variations.html create mode 100644 templates/components/store/_preview_product_variation_types.html delete mode 100644 templates/components/store/_row_permutation.html create mode 100644 templates/components/store/_row_product_permutation.html diff --git a/__pycache__/app.cpython-312.pyc b/__pycache__/app.cpython-312.pyc index c0b82294cfb113e9fc118ca91776499613147dcc..55c1f30488686a211db72fb77d4fb34f2e1be8f5 100644 GIT binary patch delta 608 zcmZqFoTSZrnwOW00SGoFzD}Dokynz@Yoj_V8%wH9*38L_+``7{s~JJk3=An6Eexw6 zOok}mN?~ONLxy6;awbNGNCrkA?AcYp9LZ45sHwTxgRO_7{uXy~eqM2YPHKEketI(0 z5U_q`APK^sWq`zVh7!134Fk+FMur-OUNqyW%8B}Mr;IjKd(ddc}k zsYM`<-x5R?&Ph#A%qijqiHjqP7ncCl>w(E49+0dglI-LJei0reWPuufSsqnnfrb1E z0WwGe5Tih3a&~-XNosD90LWA+EJ{iX3UV@2i;4t63XuJ25Oz!1(Oyw!cFD=Q;OV>-zFG?)}8Fh;nCX|z!o|sd_4H6TEi4~Us z)#-uBA|8;8D5^|BQGQBka!C;{NKOtaH`!f4mO~N7DG*Rlmq678G%qh>w@3h_ zQ4FSbzknzQ%!!*H2y9?fT***m3RF^L3?zPW*yIAO%Sp8>$^mj2fw*|uWFkWc$DXBz_fx9DB^%Nz;dk L`3w`Q4>vmi=lE!V diff --git a/app.log b/app.log index d730f558..40115f3a 100644 --- a/app.log +++ b/app.log @@ -1,56 +1,51 @@ -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 /login_callback?code=JMmHntUooZqn-PHB_xXhxkzf0lBMA6CcFQC1whmN23xUb&state=%2F Host: 127.0.0.1:5000 -Connection: keep-alive -Pragma: no-cache -Cache-Control: no-cache -Dnt: 1 -Upgrade-Insecure-Requests: 1 -User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 -Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 -Sec-Fetch-Site: cross-site -Sec-Fetch-Mode: navigate -Sec-Fetch-User: ?1 -Sec-Fetch-Dest: document -Sec-Ch-Ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128" -Sec-Ch-Ua-Mobile: ?0 -Sec-Ch-Ua-Platform: "Windows" -Accept-Encoding: gzip, deflate, br, zstd -Accept-Language: en-GB,en-US;q=0.9,en;q=0.8 -Cookie: session=.eJxtkG1rwjAQx79LwL7R9SG2aVooww2cCJvMMX1ZYnq10ZrUND5M2XdfKmNsMHLhwt3_cj_-V5S3hhnI2cFUfu6h9IoKZliXpZIcUIoeJrMZDquFv6mO7-PqeCrDCA2QhkJo4CY_aGFVlTFN6nkBjl3fniCNfN_3arUWMuesrleMb-3UQdff4taqCzjeyRPbYp8QKElFxVm6h9a90bhc7bzupbS4wL2GtlGyhdx8NJBxVYDDawHS5KLI1k-bD7N_eV4-Vm_ivJ_FeP56WUyWIwbT6WUunN-0Wbe-Nxz18NjGD7GtdMy29JfaabmyG-2Voug3WpWihj7smKidm3mZHXFubmX_evU5QHBuUBrEmETJMKSBGyUUUxLaDm91mRu1BWl9CUpK4pWPCcEkLjEDUuAoSRJKOUkIJauSch7E9ssvTeiOWA.ZumruQ.WqTz2NgZC14EQFnfvllT6CC2T3U - - -Request data: b'' -Traceback: Traceback (most recent call last): - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\routing\user.py", line 91, in login_callback - users, errors = datastore_user.get_many_user(user_filters, user) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\datastores\datastore_user.py", line 134, in get_many_user - guid = Helper_DB_MySQL.create_guid() - ^^^^^^^^^^^^^^^ -NameError: name 'Helper_DB_MySQL' is not defined - -During handling of the above exception, another exception occurred: - -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\routing\user.py", line 120, in login_callback - return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.STATUS_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Controller error.\n{e}'}) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\pydantic\_internal\_model_construction.py", line 237, in __getattr__ - raise AttributeError(item) -AttributeError: STATUS_FAILURE - +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_category.py", line 57, in categories + return render_template('pages/store/_product_categories.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\_product_categories.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\_product_categories.html", line 99, in block 'page_body' + var currencies = {{ model.convert_list_objects_to_dict_json_by_attribute_key_default(model.access_levels) | tojson | safe }}; + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_base.py", line 330, in convert_list_objects_to_dict_json_by_attribute_key_default + return Model_View_Base.convert_list_objects_to_dict_json_by_attribute_key(list_objects, getattr(obj_class, obj_class.FLAG_NAME_ATTR_OPTION_VALUE)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_base.py", line 318, in convert_list_objects_to_dict_json_by_attribute_key + return {getattr(obj, key): obj.to_json() for obj in list_objects} + ^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\business_objects\store\access_level.py", line 66, in to_json + self.FLAG_ACTIVE: av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json') + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\lib\argument_validation.py", line 493, in input_bool + raise ValueError(error_msg) +ValueError: Invalid Access_Level.to_json argument active. Type = . Value = 2 + diff --git a/app.log.1 b/app.log.1 index dcc9f9e2..5712a4fc 100644 --- a/app.log.1 +++ b/app.log.1 @@ -1,4 +1,4 @@ -Exception on /store/products [GET] +Exception on /store/categories [GET] Traceback (most recent call last): File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 1473, in wsgi_app response = self.full_dispatch_request() @@ -15,89 +15,60 @@ Traceback (most recent call last): File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 865, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\routing\store\product.py", line 40, in products - filters.is_not_empty = filters.is_not_empty if arg_filter_is_not_empty is None else av.input_bool(arg_filter_is_not_empty, 'is_not_empty', 'filter') - ^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\pydantic\main.py", line 828, in __getattr__ - raise AttributeError(f'{type(self).__name__!r} object has no attribute {item!r}') -AttributeError: 'Filters_Product' object has no attribute 'is_not_empty' + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\product_category.py", line 57, in categories + return render_template('pages/store/_product_categories.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\_product_categories.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\_product_categories.html", line 99, in block 'page_body' + var currencies = {{ model.convert_list_objects_to_dict_json_by_attribute_key_default(model.access_levels) | tojson | safe }}; + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_base.py", line 330, in convert_list_objects_to_dict_json_by_attribute_key_default + return Model_View_Base.convert_list_objects_to_dict_json_by_attribute_key(list_objects, getattr(obj_class, obj_class.FLAG_NAME_ATTR_OPTION_VALUE)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_base.py", line 318, in convert_list_objects_to_dict_json_by_attribute_key + return {getattr(obj, key): obj.to_json() for obj in list_objects} + ^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\business_objects\store\access_level.py", line 66, in to_json + self.FLAG_ACTIVE: av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json') + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\lib\argument_validation.py", line 493, in input_bool + raise ValueError(error_msg) +ValueError: Invalid Access_Level.to_json argument active. Type = . Value = 2 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/categories? Host: 127.0.0.1:5000 Connection: keep-alive Pragma: no-cache Cache-Control: no-cache Sec-Ch-Ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128" Sec-Ch-Ua-Mobile: ?0 Sec-Ch-Ua-Platform: "Windows" -Upgrade-Insecure-Requests: 1 Dnt: 1 +Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document -Referer: http://127.0.0.1:5000/store/products +Referer: http://127.0.0.1:5000/store/categories Accept-Encoding: gzip, deflate, br, zstd Accept-Language: en-GB,en-US;q=0.9,en;q=0.8 -Cookie: session=.eJytVlmvqzgS_iutSN1PnXPB7EdqzWQFcgJJSFhfIseGYLYQlgTovv99TM6de_uhZ5NGCsF2FVVfudbfJ7Bt4ltF6hDbdVhN3n-fIFicIc5Jca6bWxVO3puqDX_903H7Yvw8DXNIssn7JMRPWOG3nGCchc2tqHPSxH-_jtQ3dMsnv04iUtVNAXMqcHIKMe7pGcFn1FZVWKD-jMMItlkzeS_aLHuRqvBKbsVfED4BsN_X59EIhsp9vf8QBRlcFAHJioAZBUrMBbJMFEajwvr8Qnx-hBWJSIgn7xHM6vBFIQXKWhziszM7_dD6aScl121JVf3Z-Lqtvhlk_NPu6XE0fPKV3lddRefmloYFpQMlwgoQsYKlSxRCSQKcKCGJh5iHUBIVXpAlxIkshdh-cwNEKKzr7xLCfhNfVER2ZJNCTyfbxSa75Ma4nxuJDSzGNHXyJNAzBz25EahZDNIMcdsraeD5zaXAMRz0p5kEWZAEt52a8RcisKgXYuxZN2MhJBfAPPSCeXvze4tKEYTwmU3D5zp7c4SZLjNFgfY8-gjvHnuYabF2nJVyG-RcftMz42oEkvshrnMju1PU_bkqJC3z5i1MdprqYeuYRPLixBtp1xIQA8Xp-dapiMF2q3XBR7DyhLpr0E7Wc0U_SbVnFpqqM4_iHkBj734cVW7rFlwjHLzNw_WZM75Ws6WzUE6mVZ8f25PTbk9q90xdrdib7sbkhZnk5Iv1dGb46v1cwKMpbhqIV7t-Olsqnn44cz2zFstD_vHs9oqg9OFB2HN8L2SsxXe4q4fkYzhraz0Jmfn8ZkgztLA0rXkmDNsN-5pM8-3DkvIti_VcXnv3_rhke1GlydQaInPyuhvjMqudLekflrk8V7IVgT1bK9usW5sw3byFSz-WpuG534rKND3C3f3jsZjRMAi7klRhfYY0BFkJ8JLCA4n7cU5oUMgizzCvLPiLKDnag86aRK_1whLQQhf1tPScBd3nTRmM-8J5hF5gWynPX5LNI9CurJOut8Y6Zq1-o7xRYS10zeqSr5vgSD_InRSDdR8shAa6VnpRHeYChOHiZgx8CRbii2uPyrNAwzHKDy2lpYHaZVhVWgTYEqvxLABsDN1n6wOlGUMWqVmCNaf_1BEzWJsPOyI_aGgWKF8D37NiRD7D0_eCGKvrfjvYQ7A0cyM5MMYSp-aJGgt83lT93gRmbCwRbw4WCZY-s-cMxVxen5tCV5CK8mDJ3rBmPVFvD4ej3VuEPrmZ0nT4cypkRkp15WvG9zbD5rRRA_fQIlUoRszYm6cUVxaslRiPl5noT4qlMZbXxkgC20hWojHQ56S3u6XRu6Mjcqfx3awe0zNwLY7KTbc5WwaqVQee9bgUZgOp_oOKX3zb3Hxcjj--87ggQ3mWQ9dJ9aTMfbcbguP_IeWpPb43yqS4GHwPPas7pax3APEJenF3GuhNZWvRSWPv4K6zY1qKdp6OJaj0vQPZJSuO2s593rkx4uXHgDNOqDeXiDGGK2f01M-cQ0YdVBcDl3PZTGzeyHXBdA1-d3JSY5nF5jAn_mn1DHInf8UGyF64fC4GFpupgeM8Ajue23lTBKqwN_Ly6J7i1k07YKhKYuSrEVdL4zJ5xVNyYEM1digtDoY5H6hpb3M4NtR4NZa62lxb5-BKHJ-5qoVdajZnlPuzVazqW-MRdyezCjSVVfjQFnay2OaaKUXA6QU9AF2xVze7JPUUwlv2gLj99n7XpG2UwvlSjqMqR_gBBj9sTZNfzbIbK88Jm8b6ScmwLboPgDwP28vzAe6Jve-rbLbWzdPUkjeLsJLSSJ0zRGkS3lxZ9rXNHd2XzMtuhYDdAbT1uzTxC6yWxqoaem56MUV1WGhXJlJMf1668VTeldou1ARNP2ERHmc7jdSYd4J0teM6Ge27w95p5_e5EIG2STucgGNM7BLuNGjNHwuwmw5G0JRbrduLW8VAZ24mrKKj5YNl1qvk3q8ObHe_xayr6i6u4xKtMCPx7JXWrxrdyrEz0v-C4J_K6haRLPzpc174dfIqWOemf_HMQ1jRpvfZ-0gR3V79r6XNeXJVk765m4a7iI-ku-8kYB0GR3NnMNxsaH5P_pcR5F-0flpSv9VYnpPHGku-F11G-jyoa6ogbpqyfv_yBYePafGEKWBEMYzEWCZd8dbWb6_pY1T1her6Nhj8Z1AFQem_Yx5ZbgUa6bzQxTZzg1emwwQcn5CJl5RcEtS046D2HWH9dq3gAzawesH5XH4ROMxFgOcZCQtAkCKZj4CE4Ggjf8Ei_7f6N15mfql-K6-_4N9esn7mZj-DNf0hXPywj-4_RdZ0FeK3snh5nIwOQ91D9dehfQu1mZVecbEDieXLRbB9MDcE4MjYXv6bWa0tMWzoNDY6YwIYwE8ZeQrEE2DfOfadBW8yB4LJ169f_wFsnZ0r.Zsz0IQ.CsqbE-G2jF9oYmUiZKS36HfeRw4 +Cookie: session=.eJytVlnTqkgS_SsdRnQ_tV5WgS_ixgyKoAioyP5iQBXIDrIp9Nz_PoXf7b790LNFTIQLVZlknqw8mZW_Lfy-i6smaUNotmGz-PhtAfzy5sMiKW9tVzXh4qNr-vDXP233b8XP3bDwk3zxsQjh02_gqkggzMOuKtsi6eK_32fpClTF4tdFlDRtV_oFMrgwQghHtJfAG-ibJizBeINh5Pd5t_go-zx_i5rwnlTlXwg-AeB_PN_mIDBk9_3_jzXNEgFHA5ajIcb5DBb4OBaF0eywvb0R34awSaIkhIuPyM_b8C1JSpD3MIQ3izd-eP2ME4nbvkau_hx82zffA1J_j3t5nQNffEPn1TbRrauysETyiGQIwFI050MqBCzJQJZZQ5JiYQQ53McjjgoRYogg9t_T4AMQtu0fFsJRjgMJJKdEznznkChbOQ8KdV5v1NQkdEzTDskz8R1tOqRV4u91DOzVtTJymee4XVDC2J8OTy31ci_1qpOUU0FC42CkY-jolbql04DAhkOJrVZ4n9zgPW_UttIjONSrmOV8heXutnKHMDvZjkRs4HXq8UySz1WP1W5xZ578UPS15lgaOHpFFrG3K2-KwrkYwUYfDLspeyqv24yIb0dSiGzHMXL2pGwd7jCFnJDLRXxWjnz5jGi60A1XXPO3IfBUoTT6uN_YJWljzLLFqaOQtnbKBDl8SntNI240lsbTeCJt3uaNc6B4JXO-hcNdleCVnKjWL4FYAckglMEQlmFaVje-60VR3lmVIk92l7g7esc1k8jDfkjOHhsMBK33ob08W8fA7yMI9zUjMolNWGIlc85u34mH55otmlTcFOmpF9fPnhwjke8LhhP7ZVNuhh31YEnV5ze2fIkC6wLxQ2zuy3tXPTi2bBrBXPlKoC1v2qSbxnEa6Gc7HXfiBdEgfNVJE7Y3H1EQZ4j1mmFxjvmxnyBSsGsKw95V8BcsuZrTAdeSQ3sodRpsD-tDVjvWFq2LrvbmdWkNoeOZekZRQSoP3v6OW5moqGKM66PMrZCx3re1JijEzruiFworg4Q4elu68209CyQLCwh6Cuwc89-G6Tiwzdl57u1hDIpLj2SZJ71yKHE9IPAaSjHvEXjs28_eJbhupiyQ8hTurfHTR4zB_WY6JeyAqFmCQiRcR49B8klP1_FiKImjMpmTJ2iFml4wVYCZZqBgCZfSJHfUCC1WBUChU008wcXOpMppwv0plwcOSKDwBLyCe_0JRnO6XM1RT9C30DJUDn8uhVzNkK9CxFxHnmRDljz70gOJLmfM0NlkCFfuiVwM58NMD0-EpVOFrFMNaKqGu9aEbK0ZWa9O6sueE1FYnWvn7Vyenq2TyG6mFHjtSXrrOfoQlFrnI_8XCb71lEIbguuP9xzSy0GRF75tZYe0Llz7NXnX_0PJo3hcZ7aJcGHwETr6y8hw50LEhu_EL2NCJ5WLayuLnYst5tesXptFNreg2nUuySndkWrq4idjR6kCP-OlZsKpBhi1FOVjuj_VLcozaSWzD-QL84UNq6UmpRYHWrNV6mRYmSrksTZtEtfYPb3CKt7cIPI3LheTNb3USm9XK1bOHS5OLOp7y7KMjQPxOtYn62yQULETbMbVI16mbz6VGa06snDNXp6ZiQ4wX74vWkSwi8m51WknEB7azjhfdEZ1sshI11ePfSn8stg8z4oRUWVvc6_lut0nU6w3BHu_nBrRiqPNqDCipeoPPF9uAvzxkp7OVt7jdjatRfPU9Nchf9Giae8f2SsDcjcJYSIwtAcFEssTd8zrTW09judpixsysSzNi8a5nSzxugbwzbKNNl1p5B2w475NFUehT4o3iNSJBn7U2A8KkiDa8lUaHA2dwCKW3IZSLp12hfPisfLSu5ozyJUXkBJqe2FtBUe-6KuXR98ft93oHl-vssBuo8uMB2W3g8dk_6qOPrZLzBIfyO4B2tSJNog8rM7uL7Vwx7xj4tSg4ZXtwYwmpwOvitlXN_y5t6txT06uU16WXLh8ov7Vgqqeb0b0Wybwp7qpoiQPf_qcF35dvBvWrRvfOpvQb9Cl93n3JWVUve-_Hl3Oi7uUjt1DU-1tfE1ejxND6JfJ2tu8H8oyqu_F_zKC_IurH7XU7z2WYNh3Q_296dIc_rnRtshB3HV1-_HlCwyHZfn0MwJbr8NoHbPJq1z17eo9fcyuviBf3weD_wyqTED275RnlaoEs3zk8GYrK67O2w_Fi80h389HXSeg6-dB7Q-E7ere-IPf-c0bzufjF5qEZERQFMZAmqCZiKUiggE-xrAMFcA19bf2K8VivzRf6_sv8Ovb1s8k_zMhog-A5Y_40PrTZIueQriqy_uc8WROGNioYnuH8tG67fnXTuhNE7Ofni_Rp9Pz6C1nxT74b2a1voZ-h6axORkLAiOoJcYtccbA1x8U90FzK5LEvcW3b9_-CTbvo8I.ZumzNg.3EndhjI8QnbotIPyN-mo04fvFAg 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\routing\store\product.py", line 40, in products - filters.is_not_empty = filters.is_not_empty if arg_filter_is_not_empty is None else av.input_bool(arg_filter_is_not_empty, 'is_not_empty', 'filter') - ^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\pydantic\main.py", line 828, in __getattr__ - raise AttributeError(f'{type(self).__name__!r} object has no attribute {item!r}') -AttributeError: 'Filters_Product' object has no attribute 'is_not_empty' - -Exception on /login_callback [GET] -Traceback (most recent call last): - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\routing\user.py", line 91, in login_callback - users, errors = datastore_user.get_many_user(user_filters, user) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\datastores\datastore_user.py", line 134, in get_many_user - guid = Helper_DB_MySQL.create_guid() - ^^^^^^^^^^^^^^^ -NameError: name 'Helper_DB_MySQL' is not defined - -During handling of the above exception, another exception occurred: - -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\routing\user.py", line 120, in login_callback - return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.STATUS_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Controller error.\n{e}'}) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\pydantic\_internal\_model_construction.py", line 237, in __getattr__ - raise AttributeError(item) -AttributeError: STATUS_FAILURE diff --git a/app.log.2 b/app.log.2 new file mode 100644 index 00000000..ef0caaaf --- /dev/null +++ b/app.log.2 @@ -0,0 +1,52 @@ +Request: 127.0.0.1 GET http /store/categories? Host: 127.0.0.1:5000 +Connection: keep-alive +Pragma: no-cache +Cache-Control: no-cache +Sec-Ch-Ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128" +Sec-Ch-Ua-Mobile: ?0 +Sec-Ch-Ua-Platform: "Windows" +Dnt: 1 +Upgrade-Insecure-Requests: 1 +User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 +Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 +Sec-Fetch-Site: same-origin +Sec-Fetch-Mode: navigate +Sec-Fetch-User: ?1 +Sec-Fetch-Dest: document +Referer: http://127.0.0.1:5000/store/categories +Accept-Encoding: gzip, deflate, br, zstd +Accept-Language: en-GB,en-US;q=0.9,en;q=0.8 +Cookie: session=.eJytVlnTqkgS_SsdRnQ_tV5WgS_ixgyKoAioyP5iQBXIDrIp9Nz_PoXf7b790LNFTIQLVZlknqw8mZW_Lfy-i6smaUNotmGz-PhtAfzy5sMiKW9tVzXh4qNr-vDXP233b8XP3bDwk3zxsQjh02_gqkggzMOuKtsi6eK_32fpClTF4tdFlDRtV_oFMrgwQghHtJfAG-ibJizBeINh5Pd5t_go-zx_i5rwnlTlXwg-AeB_PN_mIDBk9_3_jzXNEgFHA5ajIcb5DBb4OBaF0eywvb0R34awSaIkhIuPyM_b8C1JSpD3MIQ3izd-eP2ME4nbvkau_hx82zffA1J_j3t5nQNffEPn1TbRrauysETyiGQIwFI050MqBCzJQJZZQ5JiYQQ53McjjgoRYogg9t_T4AMQtu0fFsJRjgMJJKdEznznkChbOQ8KdV5v1NQkdEzTDskz8R1tOqRV4u91DOzVtTJymee4XVDC2J8OTy31ci_1qpOUU0FC42CkY-jolbql04DAhkOJrVZ4n9zgPW_UttIjONSrmOV8heXutnKHMDvZjkRs4HXq8UySz1WP1W5xZ578UPS15lgaOHpFFrG3K2-KwrkYwUYfDLspeyqv24yIb0dSiGzHMXL2pGwd7jCFnJDLRXxWjnz5jGi60A1XXPO3IfBUoTT6uN_YJWljzLLFqaOQtnbKBDl8SntNI240lsbTeCJt3uaNc6B4JXO-hcNdleCVnKjWL4FYAckglMEQlmFaVje-60VR3lmVIk92l7g7esc1k8jDfkjOHhsMBK33ob08W8fA7yMI9zUjMolNWGIlc85u34mH55otmlTcFOmpF9fPnhwjke8LhhP7ZVNuhh31YEnV5ze2fIkC6wLxQ2zuy3tXPTi2bBrBXPlKoC1v2qSbxnEa6Gc7HXfiBdEgfNVJE7Y3H1EQZ4j1mmFxjvmxnyBSsGsKw95V8BcsuZrTAdeSQ3sodRpsD-tDVjvWFq2LrvbmdWkNoeOZekZRQSoP3v6OW5moqGKM66PMrZCx3re1JijEzruiFworg4Q4elu68209CyQLCwh6Cuwc89-G6Tiwzdl57u1hDIpLj2SZJ71yKHE9IPAaSjHvEXjs28_eJbhupiyQ8hTurfHTR4zB_WY6JeyAqFmCQiRcR49B8klP1_FiKImjMpmTJ2iFml4wVYCZZqBgCZfSJHfUCC1WBUChU008wcXOpMppwv0plwcOSKDwBLyCe_0JRnO6XM1RT9C30DJUDn8uhVzNkK9CxFxHnmRDljz70gOJLmfM0NlkCFfuiVwM58NMD0-EpVOFrFMNaKqGu9aEbK0ZWa9O6sueE1FYnWvn7Vyenq2TyG6mFHjtSXrrOfoQlFrnI_8XCb71lEIbguuP9xzSy0GRF75tZYe0Llz7NXnX_0PJo3hcZ7aJcGHwETr6y8hw50LEhu_EL2NCJ5WLayuLnYst5tesXptFNreg2nUuySndkWrq4idjR6kCP-OlZsKpBhi1FOVjuj_VLcozaSWzD-QL84UNq6UmpRYHWrNV6mRYmSrksTZtEtfYPb3CKt7cIPI3LheTNb3USm9XK1bOHS5OLOp7y7KMjQPxOtYn62yQULETbMbVI16mbz6VGa06snDNXp6ZiQ4wX74vWkSwi8m51WknEB7azjhfdEZ1sshI11ePfSn8stg8z4oRUWVvc6_lut0nU6w3BHu_nBrRiqPNqDCipeoPPF9uAvzxkp7OVt7jdjatRfPU9Nchf9Giae8f2SsDcjcJYSIwtAcFEssTd8zrTW09judpixsysSzNi8a5nSzxugbwzbKNNl1p5B2w475NFUehT4o3iNSJBn7U2A8KkiDa8lUaHA2dwCKW3IZSLp12hfPisfLSu5ozyJUXkBJqe2FtBUe-6KuXR98ft93oHl-vssBuo8uMB2W3g8dk_6qOPrZLzBIfyO4B2tSJNog8rM7uL7Vwx7xj4tSg4ZXtwYwmpwOvitlXN_y5t6txT06uU16WXLh8ov7Vgqqeb0b0Wybwp7qpoiQPf_qcF35dvBvWrRvfOpvQb9Cl93n3JWVUve-_Hl3Oi7uUjt1DU-1tfE1ejxND6JfJ2tu8H8oyqu_F_zKC_IurH7XU7z2WYNh3Q_296dIc_rnRtshB3HV1-_HlCwyHZfn0MwJbr8NoHbPJq1z17eo9fcyuviBf3weD_wyqTED275RnlaoEs3zk8GYrK67O2w_Fi80h389HXSeg6-dB7Q-E7ere-IPf-c0bzufjF5qEZERQFMZAmqCZiKUiggE-xrAMFcA19bf2K8VivzRf6_sv8Ovb1s8k_zMhog-A5Y_40PrTZIueQriqy_uc8WROGNioYnuH8tG67fnXTuhNE7Ofni_Rp9Pz6C1nxT74b2a1voZ-h6axORkLAiOoJcYtccbA1x8U90FzK5LEvcW3b9_-CTbvo8I.ZumzNg.3EndhjI8QnbotIPyN-mo04fvFAg + + +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\product_category.py", line 56, in categories + model = Model_View_Store_Product_Category(form_filters) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_product_category.py", line 46, in __init__ + self.access_levels = self.get_many_access_level(Filters_Access_Level()) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_base.py", line 299, in get_many_access_level + access_levels, errors = DataStore_Base.get_many_access_level(filters) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\datastores\datastore_base.py", line 216, in get_many_access_level + argument_dict = filters.to_json() + ^^^^^^^^^^^^^^^ +AttributeError: 'Filters_Access_Level' object has no attribute 'to_json'. Did you mean: 'from_json'? + diff --git a/app.log.3 b/app.log.3 new file mode 100644 index 00000000..1e9193bb --- /dev/null +++ b/app.log.3 @@ -0,0 +1,83 @@ +Request: 127.0.0.1 GET http /store/categories? Host: 127.0.0.1:5000 +Connection: keep-alive +Pragma: no-cache +Cache-Control: no-cache +Sec-Ch-Ua: "Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128" +Sec-Ch-Ua-Mobile: ?0 +Sec-Ch-Ua-Platform: "Windows" +Dnt: 1 +Upgrade-Insecure-Requests: 1 +User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 +Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 +Sec-Fetch-Site: same-origin +Sec-Fetch-Mode: navigate +Sec-Fetch-User: ?1 +Sec-Fetch-Dest: document +Referer: http://127.0.0.1:5000/store/categories +Accept-Encoding: gzip, deflate, br, zstd +Accept-Language: en-GB,en-US;q=0.9,en;q=0.8 +Cookie: session=.eJytVlnTqkgS_SsdRnQ_tV5WgS_ixgyKoAioyP5iQBXIDrIp9Nz_PoXf7b790LNFTIQLVZlknqw8mZW_Lfy-i6smaUNotmGz-PhtAfzy5sMiKW9tVzXh4qNr-vDXP233b8XP3bDwk3zxsQjh02_gqkggzMOuKtsi6eK_32fpClTF4tdFlDRtV_oFMrgwQghHtJfAG-ibJizBeINh5Pd5t_go-zx_i5rwnlTlXwg-AeB_PN_mIDBk9_3_jzXNEgFHA5ajIcb5DBb4OBaF0eywvb0R34awSaIkhIuPyM_b8C1JSpD3MIQ3izd-eP2ME4nbvkau_hx82zffA1J_j3t5nQNffEPn1TbRrauysETyiGQIwFI050MqBCzJQJZZQ5JiYQQ53McjjgoRYogg9t_T4AMQtu0fFsJRjgMJJKdEznznkChbOQ8KdV5v1NQkdEzTDskz8R1tOqRV4u91DOzVtTJymee4XVDC2J8OTy31ci_1qpOUU0FC42CkY-jolbql04DAhkOJrVZ4n9zgPW_UttIjONSrmOV8heXutnKHMDvZjkRs4HXq8UySz1WP1W5xZ578UPS15lgaOHpFFrG3K2-KwrkYwUYfDLspeyqv24yIb0dSiGzHMXL2pGwd7jCFnJDLRXxWjnz5jGi60A1XXPO3IfBUoTT6uN_YJWljzLLFqaOQtnbKBDl8SntNI240lsbTeCJt3uaNc6B4JXO-hcNdleCVnKjWL4FYAckglMEQlmFaVje-60VR3lmVIk92l7g7esc1k8jDfkjOHhsMBK33ob08W8fA7yMI9zUjMolNWGIlc85u34mH55otmlTcFOmpF9fPnhwjke8LhhP7ZVNuhh31YEnV5ze2fIkC6wLxQ2zuy3tXPTi2bBrBXPlKoC1v2qSbxnEa6Gc7HXfiBdEgfNVJE7Y3H1EQZ4j1mmFxjvmxnyBSsGsKw95V8BcsuZrTAdeSQ3sodRpsD-tDVjvWFq2LrvbmdWkNoeOZekZRQSoP3v6OW5moqGKM66PMrZCx3re1JijEzruiFworg4Q4elu68209CyQLCwh6Cuwc89-G6Tiwzdl57u1hDIpLj2SZJ71yKHE9IPAaSjHvEXjs28_eJbhupiyQ8hTurfHTR4zB_WY6JeyAqFmCQiRcR49B8klP1_FiKImjMpmTJ2iFml4wVYCZZqBgCZfSJHfUCC1WBUChU008wcXOpMppwv0plwcOSKDwBLyCe_0JRnO6XM1RT9C30DJUDn8uhVzNkK9CxFxHnmRDljz70gOJLmfM0NlkCFfuiVwM58NMD0-EpVOFrFMNaKqGu9aEbK0ZWa9O6sueE1FYnWvn7Vyenq2TyG6mFHjtSXrrOfoQlFrnI_8XCb71lEIbguuP9xzSy0GRF75tZYe0Llz7NXnX_0PJo3hcZ7aJcGHwETr6y8hw50LEhu_EL2NCJ5WLayuLnYst5tesXptFNreg2nUuySndkWrq4idjR6kCP-OlZsKpBhi1FOVjuj_VLcozaSWzD-QL84UNq6UmpRYHWrNV6mRYmSrksTZtEtfYPb3CKt7cIPI3LheTNb3USm9XK1bOHS5OLOp7y7KMjQPxOtYn62yQULETbMbVI16mbz6VGa06snDNXp6ZiQ4wX74vWkSwi8m51WknEB7azjhfdEZ1sshI11ePfSn8stg8z4oRUWVvc6_lut0nU6w3BHu_nBrRiqPNqDCipeoPPF9uAvzxkp7OVt7jdjatRfPU9Nchf9Giae8f2SsDcjcJYSIwtAcFEssTd8zrTW09judpixsysSzNi8a5nSzxugbwzbKNNl1p5B2w475NFUehT4o3iNSJBn7U2A8KkiDa8lUaHA2dwCKW3IZSLp12hfPisfLSu5ozyJUXkBJqe2FtBUe-6KuXR98ft93oHl-vssBuo8uMB2W3g8dk_6qOPrZLzBIfyO4B2tSJNog8rM7uL7Vwx7xj4tSg4ZXtwYwmpwOvitlXN_y5t6txT06uU16WXLh8ov7Vgqqeb0b0Wybwp7qpoiQPf_qcF35dvBvWrRvfOpvQb9Cl93n3JWVUve-_Hl3Oi7uUjt1DU-1tfE1ejxND6JfJ2tu8H8oyqu_F_zKC_IurH7XU7z2WYNh3Q_296dIc_rnRtshB3HV1-_HlCwyHZfn0MwJbr8NoHbPJq1z17eo9fcyuviBf3weD_wyqTED275RnlaoEs3zk8GYrK67O2w_Fi80h389HXSeg6-dB7Q-E7ere-IPf-c0bzufjF5qEZERQFMZAmqCZiKUiggE-xrAMFcA19bf2K8VivzRf6_sv8Ovb1s8k_zMhog-A5Y_40PrTZIueQriqy_uc8WROGNioYnuH8tG67fnXTuhNE7Ofni_Rp9Pz6C1nxT74b2a1voZ-h6axORkLAiOoJcYtccbA1x8U90FzK5LEvcW3b9_-CTbvo8I.ZumzNg.3EndhjI8QnbotIPyN-mo04fvFAg + + +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\product_category.py", line 56, in categories + model = Model_View_Store_Product_Category(form_filters) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_product_category.py", line 46, in __init__ + self.access_levels = self.get_many_access_level(Filters_Access_Level()) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_base.py", line 299, in get_many_access_level + access_levels, errors = DataStore_Base.get_many_access_level(filters) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\datastores\datastore_base.py", line 214, in get_many_access_level + av.val_instance(filters, 'filters', _m, Filters_Access_Level) + ^^^^^^^^^^^^^^^^^^^^ +NameError: name 'Filters_Access_Level' is not defined + +Exception on /store/categories [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_category.py", line 56, in categories + model = Model_View_Store_Product_Category(form_filters) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_product_category.py", line 46, in __init__ + self.access_levels = self.get_many_access_level(Filters_Access_Level()) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_base.py", line 299, in get_many_access_level + access_levels, errors = DataStore_Base.get_many_access_level(filters) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\datastores\datastore_base.py", line 216, in get_many_access_level + argument_dict = filters.to_json() + ^^^^^^^^^^^^^^^ +AttributeError: 'Filters_Access_Level' object has no attribute 'to_json'. Did you mean: 'from_json'? +Server Error: 500 Internal Server Error: The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application. diff --git a/app.py b/app.py index 7794704e..bfc68cb7 100644 --- a/app.py +++ b/app.py @@ -37,15 +37,15 @@ from datastores.datastore_store_base import DataStore_Store from helpers.helper_app import Helper_App import lib.argument_validation as av """ -from routing.core import routes_core -from routing.legal import routes_legal -from routing.store.store import routes_store -from routing.store.product import routes_store_product -from routing.store.product_category import routes_store_product_category -from routing.store.product_permutation import routes_store_product_permutation -from routing.store.stock_item import routes_store_stock_item -from routing.store.supplier import routes_store_supplier -from routing.user import routes_user +from controllers.core import routes_core +from controllers.legal import routes_legal +from controllers.store.store import routes_store +from controllers.store.product import routes_store_product +from controllers.store.product_category import routes_store_product_category +from controllers.store.product_permutation import routes_store_product_permutation +from controllers.store.stock_item import routes_store_stock_item +from controllers.store.supplier import routes_store_supplier +from controllers.user import routes_user # external from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session # from flask_appconfig import AppConfig @@ -131,3 +131,10 @@ app.register_blueprint(routes_store_product_permutation) app.register_blueprint(routes_store_stock_item) app.register_blueprint(routes_store_supplier) app.register_blueprint(routes_user) + + + +@app.template_filter('console_log') +def console_log(value): + print(value) + return value \ No newline at end of file diff --git a/business_objects/__pycache__/base.cpython-312.pyc b/business_objects/__pycache__/base.cpython-312.pyc index c7ef2d0f861a4c399e393bc585374f6aa477f91c..0dfde09f232a7470dc35a5cab85333adbe557efc 100644 GIT binary patch literal 3537 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 diff --git a/business_objects/__pycache__/db_base.cpython-312.pyc b/business_objects/__pycache__/db_base.cpython-312.pyc index 75c2841ea8e8b4e21cb3dd1769c75a8870010ae3..57af9764f0784f2818ceb5a599c81498b02af473 100644 GIT binary patch delta 126 zcmX>seN>9~G%qg~0}wp)`;eBik(ZyH(P6SIyRi@_Lke39LlkEUJCNk6NGP+H!=T2tip8S~GhS6%WDvvMw2Nq^lj!ztuD|sFQWutk6 a#Kal7CIn57m>6+E)A}0&kXIxOv=9JW4k5e% delta 183 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 literal 0 HcmV?d00001 diff --git a/business_objects/__pycache__/user.cpython-312.pyc b/business_objects/__pycache__/user.cpython-312.pyc index 85d51bf66aae3cb9c0731ea5be97dbbdccf835c3..112be66af321ad0af0c96aaaa54bcf66d979b725 100644 GIT binary patch delta 3001 zcmbtWTW}Lq7~Yd?(p=l7=_N^TX;VtJt!XKu z6=%x8C~zJGpUUXqAU-hGH+@hZ7)Qn#7?`oM+F?fF&C#OpAft}wKbt}=E$G;XZ~t@7 z|9|H{|1G`I{drI86{pk2(Z9j1(|yqzj{6Z7Gk@lc@Y`i7yvs>kgp-hDh@*rdVn84p z#InPY-idws%^hu(04Cn zR3o`ooy$Q_oxpW6U2Jj<8-?tXw=P)(r17hxs!YzIjVMiiMFCQ7ELLxq~tLd z_<*9+^B4_wNvZdV8onoKv=>X(BV43JqJlUQ?52u>QR4?xC5e}U)zcJIBL%T|tGxGg)A*V*&DZ(HiE*EZ%n&7PoiLT$My)S{yc^&Z z01==YU{30obLo7@nz%L=Psvyfr4&|L?~zd13pDLYSqOVZaS zdu0qiu6nx;t)&lmfU<+y_KLi)kX=D>x(VwJ4 zI8QVDyO2g`9ZA&=nb%Xhv_Qsd10=7mGrR$4?06U`(*SJhkAQR#;1B@&^>_`WQGmk$ zuLI1jHRyqKfP7u;vxR0xgo8}geKo2_v0zRVu?bkh09^pgjqM;U=*tc`UC^O7;S{`> z6Lvd30Gj~Qq(1aV1B*K>g*+`w6eXos6t#k$AvKniRaI1a2ISt98tS3{5VCy4FC0N=G5?Bm_=-?nc5Xej?XG> z=G#B(IHk}CHoC29c~ink=UDsHf9Q=nwY20x`_w@I+H*)t=~bfLBzp$7q4R-nBIEePDf8eAn1xKq;~h!5;VO{Gsp zr8?>a(XfrvOkSredR&bz`Vf|V53J;z)_|d8F|5b5LY}U}Q~dxMc5*Ztr2#hSkC1`V ztbc$&EZ1t@CNqzL&Tt~BOn$6jShV619*g1UnUW_!F_uvk^Zv)dTB_yL=@YR2Z^Wzc z?xS&ZX{8&`+Y)8Ng^XmRq**}&?2-Oob-iQ{>kWJf?C%8jk^fVPX;(^_Ir<2!hFODazWL<92*Qsh#a?Zl1xE z8TPG(Y%!NN96R#5npP=yW!U%WQ0a8F_B9+^U>4L=zM|Kv1Z~D#kGHMId%T*S(letu zRX||K zq73guDhu5O%=4ov#rZIYYz&oFC8ej#jyQ;CEL7!Z(y9(;QlokXh5{$HVz4enyU2NV zGkTogc!Tt_)tznq{7O5&k{*QvX58r1bkEGuvW0XeFXM#JC0~+g)F5w7FHlwHXf_T0*x~S?lb!5xtc_e`KgI?QnXTiY!>D); zVHbd50A%?PasZ3q#BC_*QIYq*+3 zm_q14m_|5(@H)a92oEGfwfp4oU$ s!1cnUMG!r|i~YpCAOPG&ae<2p=^@s8`-wzq&j&sZeHgkgz>@dr-=K0UqW}N^ diff --git a/business_objects/base.py b/business_objects/base.py new file mode 100644 index 00000000..c5b1a1b2 --- /dev/null +++ b/business_objects/base.py @@ -0,0 +1,59 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Business Objects +Feature: Base Business Object + +Description: +Abstract business object +""" + +# internal +from extensions import db +import lib.argument_validation as av +# external +from typing import ClassVar + + +class Base(): + ATTR_ID_ACCESS_LEVEL: ClassVar[str] = 'id_access_level' + ATTR_ID_CURRENCY: ClassVar[str] = 'id_currency' + ATTR_ID_DELIVERY_REGION: ClassVar[str] = 'id_delivery_region' + ATTR_ID_USER: ClassVar[str] = 'id_user' + FLAG_ACCESS_LEVEL_REQUIRED: ClassVar[str] = 'access_level_required' + FLAG_ACTIVE: ClassVar[str] = 'active' + 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_DESCRIPTION: ClassVar[str] = 'description' + FLAG_DISPLAY_ORDER: ClassVar[str] = 'display_order' + FLAG_GUID: ClassVar[str] = 'guid' + FLAG_IS_NOT_EMPTY: ClassVar[str] = 'is_not_empty' + # FLAG_KEY_PRIMARY: ClassVar[str] = 'key_primary' + FLAG_NAME: ClassVar[str] = 'name' + FLAG_NAME_ATTR_OPTION_TEXT: ClassVar[str] = 'NAME_ATTR_OPTION_TEXT' + 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_PRIORITY: ClassVar[str] = 'priority' + FLAG_ROWS: ClassVar[str] = 'rows' + FLAG_SYMBOL: ClassVar[str] = 'symbol' + FLAG_URL: ClassVar[str] = 'url' + NAME_ATTR_OPTION_TEXT: ClassVar[str] = 'name-attribute-option-text' + NAME_ATTR_OPTION_VALUE: ClassVar[str] = 'name-attribute-option-value' + + @classmethod + def output_bool(cls, value): + return av.input_bool(value, f'{cls.__name__} bool attribute', f'{cls.__name__}.output_bool') + @staticmethod + def convert_list_objects_to_list_options(objects): + return [object.to_json_option() for object in objects] + @classmethod + def get_shared_json_attributes(cls, object): + return { + cls.FLAG_NAME_ATTR_OPTION_TEXT: object.NAME_ATTR_OPTION_TEXT, + cls.FLAG_NAME_ATTR_OPTION_VALUE: object.NAME_ATTR_OPTION_VALUE + } \ No newline at end of file diff --git a/business_objects/db_base.py b/business_objects/db_base.py index be09dc7b..cefee2ee 100644 --- a/business_objects/db_base.py +++ b/business_objects/db_base.py @@ -61,8 +61,10 @@ class SQLAlchemy_ABC(db.Model, metaclass=SQLAlchemy_ABCMeta): @classmethod def from_json(cls, json): pass + """ def to_json_option(self): pass + """ def to_temporary_record(self): pass def to_object_with_missing_attributes(self, excluded_attributes): diff --git a/business_objects/store/__pycache__/access_level.cpython-312.pyc b/business_objects/store/__pycache__/access_level.cpython-312.pyc index a5cfe08f00f019d0bb09350d67861744615484ce..0253f0edaffae2fcd7642eebac8eb34c993e21d5 100644 GIT binary patch delta 2219 zcmb7FTWAzl7(O$zm)YCwZuXMRnz)<9MAt-(S~Zrmag%J@H8)Mx+dMd|I}^>a*^Or= z(u!@QSn5Ne$^kE>wfZ0^DU?~Gs2Y?XfYc$|o?-=8dud@P-pBHZ}-wZ|>*@CnCPUw3emKkx{Bh%O=x z$()L0ejn0=ya*Q0F4?NtG!a79*gC%=kX3X$7`IT>)^sme*ds;44`xIB+FFxg}|LsFuv~6Bg_GI|z`aH`{sD6i6LRp%KrRmqQBr@GD{d9~`M zGNyW{j8lfRj8T6Uz0JuD!zkf3-N{@|({-g!JE0ZK@IbOZr6e<%A!Tq+COtTy>`(UX zOPQhPajTL^9n9P+Sax$ZKfU>6h{Pfxu94iet`ApA&jJEnpua~Sk%pRelbp&!6Q1Ig zO8uzLsX_%?GNhQLf`Ktx6th+^%QDPX!K_OdPhZSFfWg^)xaB_6z|Vd1z0Jwl$Q@g! zO)!OAK_^~&)B#8FcpL}GW_yRPneOxhRGdb?R7c4KdDp&|3*EY7?-F)Fvzu09V!WW? zI;!K<0Jv05&*9N=W3*JnF@WPB>Z!QNVVE)<;(!bGy4G-Qw@$cxTyuy*xuq=7O_2Ur zsz#{1h(^&Vl;_AfPmug&5&7#>^@n-GN)C%LP9*P%3G%n(Bt#659#1uAC7*ZzzwIdF zj~xMWo8b{D7FhZuEY2nNlDHHmrzIC@lmetaz+7K=3H3^adW}-Qld5+-O*YC$XxPs! z<6o|$FB2j2o;niq?sFTE8@BQd^bJGY8jvLG4MZppD)8LOuOmKZXp;YopMn(8HEO@k z(LxL5LZ1{j8YLyKmx_sy89k~QiheAMHI+e1)-dqskqJZ7%^+*;bdQqk?oJI4D}AZ` zsXn}xI>b<1yp9Uf@kU?rO{IIVC&j8<*$*T)^{2`e_c20GYPfqS&E^Crz|O*aDj*$o6NLL(ATtmX6tfb;5xU>aCJBSVtyQnZdio$p~tx!;u1jmZas=Eur)MJ;B`2o7ux_z#-cc!&>+7i9=*45$5{j-+ddoA1MS~_Q1I^ENjnoI3hyDz^s zYw0A8@ZI>l4cYt;dC^+?NTAw0XbV*it8XFbv^p2UC8f; zskDhz$^(gbqeV1P--PmjX~KhVKKnuiLNodRFY;t8EhP9CJ?HKZCFmr3=G^c6%)RG+ z=j?AUJ=o#-!R>YscxG?h8GPS+(Njr3ytr|!S|D9SwNDe(q1op|bRZ<@IU_`z-+r-| zRt^b-oFlVDBT1@~q@dEIC=g9z*X=<`lZIUEq&?`nCeDE$54Dx7T=~iqtW>2rnzt6; zN&A0zS&G);JL!1Ni(M507H0|O8@MdiSX|FT?jj_>Zr>8?EZ!o3`wlYMS5Q~#6R~;ZLR42%gR;jwC$z1+OBv~~>-lfUv1c|s!S2Ug03`6PG zPHWlu`_e&5y{y?)NGOOt|pzE~=I91I^>zR|e z%;<<-hwvH{^&qZL-3KoN&xs%S-npJ`ng7MzyWd;Eu6x@iGd7@!(4%7^BR(@29T@0W z;vGt~y*-vlDBZE6v2Gm;t78TA4IoT=XLqzqY47cb@lqDnJ<-Fld{uqi-VsZ*_s9DN z;=Mh3BZj#-+}9uP?T-%}liC*aPCAvf{U0U>_*wL|C0LUiO)_fd1aqtiO6<`9$@$UgB5(^c-_xtcr(yKqwGRp z15ji>@F`6-p$m83j2dT2Gip3`D{7n~TTsIj=`Wz*jA=m)X%i7mF`YF`X~+Odtp&tD zGK4uvua-B`PPR~fqX{V#sWD|m8A%OmiefqxWq4FQl||j9C}XEm*}R3_t7vTD?6oFx zdS>MKQ~KsNQKGGBYa1QSYN-*up6v)Vro8YCy#d806x&d22VpwX*_2@nYq@tuRed)i zZbji(TFYh?1*l&JD6jQ?-H&nDc3f1T;cpO6rU`ox`f+mEDqCuo{dS9QIcT>ymV=VT zvE(4uvWJ4hQoAC8_6Ri{kIYk~K`A}OPFZOKX!Tq_LNrm6RJs>%)xu|>Fl|p-R1qeg zRkNuQpLmlzQ&Q$5&kkI+n!(OYHmB)^vU>EHRmZiQk{L;*bD7hclFCoTEKbEVa=-ZC ze(<+~7yJo@F<7*a^TGtV08?s$UZcf-1lmc?VE;hL4uNAt&~X;%So(;_2MEXW^~Aj4 z@KnB{=rUec+$!5>q!{fecNMD?*Q1lT!Zo#QI@~c%~b0jRYC5E$wJ55NyCy^y#YQ3_TLn_?=NQ?W^9YiEjPFIEHwAd*lx>_MQ_E7hnFTYNjoDBeGg_v&gidz zFr~MlB}}iPq((+Yb19tjhNAHM$u~qNy5dgsE))kqtmgee1W_c=fPM7j1F~4Z?v}Lf zu|O?-bXgLC?=rBw=Aj^3LIuKumM1*MM!f8=%AJxaq)xNes#GISc!lI0u)Y3}_vV}b sRb7E4{_dphCQ_QqZemeFScGvJ|eJqG)`SKbZOUP0xzE6Ur|K)%K!iX diff --git a/business_objects/store/__pycache__/basket.cpython-312.pyc b/business_objects/store/__pycache__/basket.cpython-312.pyc index 053352a619101ca37e34592cf24b5656bdafbf6a..53e4e70ce41749fe08ce03c14e565334bf9ed205 100644 GIT binary patch delta 2243 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 Ye&%|WvGOMp;j?{~UdFpw%8J`0&@rBMgPGiea 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 J80=9U`43PDVsQWf literal 4095 zcmb7H-A^0Y6`!%kUxU3EV;lzv43GpI0-GhPZXxMz07FCqm>RNOylzLvGXzuHL+*^b z*dmf2Qk6)RV#))cs#=g%3Q_XVhyE9RD3({UW%Z#_TdBOU$?nU(wCCO#k8SW)+Ndy@Xu%Mt6NZq1#$#jL zm|#K-P1z^|b)OQLXOv(P4eMmi$~5ZxwNZVC%xSaFlKBt2fTVRXs*G{a7RG~1i`*~7 z6*;De?08C9lMoSbQ^FS!Bye*vL5PcrlpI=2#FRA_8&%o@5~DFWCMCJ?q`(D5S&X3Q z8n+}y*OF3PdYtAK)3PEaWNtPF#-hNoRoNIfk&jNGs5=Dt(ARGJKXwiLr`vgimS(-aeiqS{B za@_Y%Cda~$ zWD&_>5hu}bASwD$>^EZAFGW)cF{#L5$ia_MB$0?EABR7U$*D-3TU1g)OyWjvjf{jz zTIL}wha(#s;T0`W@@kfo!!po73|E#N-bk07WT*ZK{aBgHlNvXN&x=N3m+~X%vedU` z%H6p;wrwqS4;;4~Y;9Y=wsw}hJ%>F9_HFC$9ks*uzQgf@n}9Z#`feWo{OB%L=1M&` zjz2i+#N)0~^QGJhNGyMH0FSKmnHIKER^>(9KIb6CVWPQU1nr4zAEEb;7}Lz zWh>7kaRc#urbQ=51qy(IoP;h*of&9%OR1%;*wT}4={a%so>6pPYpM0p-ssL~ZVc84bZI|~x-}yW@2eRI-Qde)WYb4(_a&qN103UXiI=N!!aK3Z+q~m=6ZaK~z7N_%! zve=x6gC*;7j2!^NmXBfQkYnIeZH<`Gm=!fP4VclG6*V>um;p9;U*}ql4g3dpzJZPN zJVw=?$8}K(HtvgP%{utb&o!{YBskY%=0)JZ{3{2^c*p``l`uFWRKnQsi0}uWSmjR> z9uX4Z^AaYZUKrKV$f8L6x-2C#PMt*>@)_2QLzkugWp@|t*Yfsjhf1;kqkR8If5$*q z-rjY{ytEzJ8hvtkJ9l{X<>1jEk^1s>-|>gV!B6sopAeuwZ|^^L7kzi~zB`ygET#~9 zkwQ3y5DJZ{6v81uT5XxCacYBt3vQ>L=4M?Tw>nW;EzX72%eSM}n{RU*x^!0RB zr{91`n!dhroqhunY5F?Jx1gM&>)`2K@DJUtJqrHL?Q-q(o}Ax_^sUuJne0Y5b2cx>nSCs2r0 zi5fBZKFdZ~LFHzik0g_l62U(_WXPH%jz|cR=plhaVg@s>Y@U?jsYJ4DnMo?*V-bN>cMOSe*faP`>FB?sW@as%Kg8;pv$XST%)d0s# zx&eQ(1K9pss&xJK3FFSK?aMof0&~06J)E7{-rP4ne_CLM&wcfbWFO|d`+YlC3d~69 zhW~`|?hhQ^J{T%6{?fp`6UMV|J#0O26qtMeaCPK*_k26P{fRFh96b25|7+K1_F<{X zy*=_`^!aFRITzep-dWy9yT2?n^=17RCGzgC3Qbo*;_z$-Uo1ag&ZTo`FTImKbnQMZ zIId-W#`^9tjT-kVNKSz z9;?au)@3!ZXD-U@`o>^2dEXf;Bh^#bKl46I*~0UJ6va0$ZYp9D|9X{?dSyy_178lg zbJHAD^0?~SpMYuA-QQd9s*L#<-2nm4EwT@~Gb2sY-xye$`L3O!+y6~7%Q6yDig@7lZTpZqv&(liN8OXDUjrT_GYD2Yw6NS!uuD{2la+dBzPZEu-f z2ZBP~N(B{!gvtsv5vrOVDq01hRy`mNNEN372NDG-(TbuXPLVh`ttufT5O3CwG3Clg z{`}sXH?#A;_ukC!9rK-AzxR4228Mj1G`iW(Fuzh|Z3q?N@q3rIZcB=Y(U9iKx^td{ z$B~7sl#>%OVp!%Vqlp(8&5b>CTzOSOajYJ&N|+ySS=;oVf6UJD6<^<^98&H~v#3iN zF?E8~{-l9J$Y!+^U_+9O6>>OlsuRg2SWhT4!Osu@E;7p==|Vq& zSjsc$%XLBPXErd1xp6lbpBf1l7O>b1R_xZ$VfxRF*FWV1YC@{M$OIuCAI}5)pP`tvo}5urIMxS}BqNP?;%3Gr z>w*-tzLOe?pE8>3D!W$wKwWh;P$yJqsutiBJHmv-7@>g>I!S1Qtk5{#_U{-adQJ`Z zSNL0@T@vz;4b*KTg;oHYO-|TSCV#eIswrI$WNrDS!M>wv-#|QiDncadvbe$5297nv zekC4|H89n1dg!P1E!Vs=-r3A;bUk}};LD*qL-)BKly8-L=jKmp^AWtbe)N*?p?A5x z>t@}|)Ft6Zck8l0c*#rrcYEDCP?vKodZO~#LR8uYa0}VIfwQ9qtrwcsPdr;u%=+4+ zA-~n@ZdTkdafQi1>5U_xvC%hIsjM3aOsvCfN@}paa5q_&)Wn0aN;g$}j>lh816ArB zWtSW*-asSp?N~^*TgI@d8m}h_*3@xB&#Ot(B$-sf#D?v2S|}P;ha*R!iyU%okHg@= zP&nemQqgH=Ih2zw8XFDJu6I1c(UIeWeW%r-;c#Tw37Tw|VY(Xf$MTlqDQd_8oM%d` z7?75I^-I3(3%>0)wMF0V5(lP-N?=K8Ur^d-8$WBi-nOg+K8n2`n+{)#&P1P9mXy{7 zrFB}nc4p=b%q=OM3rgo~d}+)6g)RG6y|7z}5j~P~0j7aaYr<83caP#n2cL&Cgk(Z5 zH?o_8les-qa;j=Cm7GLY<0Sj2ZJQPKwxfWR@rICUSzgm=!dR%4(6@uoh>1dhman~T zjoENy5Grx_^cuwt)P;71%^4=K{i>SG=XKM$&J9&1&i5Os6D@dK7|^qYT;3L=c@vLe zQcjUD0x2x!$7&iu?AP@yPUfA=I9agebT(-iIc&bJYh)AMvYWzl6!z226@z{^UGX?b z?LG?5vk{<@LlXtsokj`ZU1qsw-%?L(p=VQUo^P3cd3I#x*diZW?%uo9-Mi4;JI^;y zADA7OIkL$2TAluL#ZnI=)UC3DtLZTZQi)0>pJNlNHjo|#L|5QZ!0nPs^^8!z%2sB} zQu$EyD6x>=7FAW#)2eDelPVaQJT?qfPmSZWY3wlQ(^*C}1rKPkoDd1WW#YU6uZK}) zmdj>R#0C42X8~*;=Lw)}~zJv4|)aaS~|)b`**1qno|dTHmKwH;ULwIli2cb<3N zoq3*_9X~wxXRH5vr&B_-{h;TkzjGn;A400V4|N&@k zvcAi`f}Q#w+z@u@{rt+3TD5|rUe!&pPW4c%SF0&DXpL&k3VJ}xp+%c=wE?eD719#% z_cW4I#=8P{u z^Mx5Jah)rscMLrT{RFfEpUYp zro{^p2qIk+%4&jghx$4YHz_Qm-(=q-xocnU+79hTb|Qz+?bw$)wz6O3KFj@A*S|0O zw`+HOJ3f}}*_V61;ve-5?)MEII|R3Mj0C$xoO_SuPAv4m{Jr`WR|~yG-gX7>oBGGD z>=GCm3HXQ&(slrFk}zp-Yz!`wB}SE^#8RnrHkPF~NJdcz6U?+SnM@(rZwN!_#C$Sk zh~ZRLo6!jK#}Fp6B%Ye7I8owYI-SsBODWSL=1x1z+zHSP& zG61`e;p;QE0zTY&`pXmK_bx})u5L`Mj~?*7`IheG@amln?xVX0eD}Y4&E5I7 zzU6Cc4IAgy&mQo7`ObldeBFj^t7g-Azz^un?t4p5y9I0AQ7fK6rNeHckQ*;znGAOB9kAA8-yrugmNP z5fsUlN+oh>Kyx6RfCFl15UrF$dnm1Xtg0R?4vAKvR;qg7)Bx#^+Cw{U9E6h2;hTBi zdvAWec{BgMc(1kmgRX0cx4S3T-}@qp&@W&-Ys%)}=_h<}73EO|<#ApzaZ$=h7{(sc zQO+JG6ux4)o$Jk}>o!%g)Q(mg_&J7S!G>SQc+Jv~u zxvV*3*sg44iw3QSFo|-}kgIG4!3L9jVpdktxP^VEoZxe6YD-rwchEWjNTa&}Ad~6< z4IFMG8iTRe6s#>akYJYDrU?gdlUJe%{ME`mbp>l6YbH9YrhF@oKaThMAjb~?H~I+l zd*lUxYfSm*ezv69IKp-Z-oiu73KVf{r?zh4+6D8AJ_0InnrV|fEkX&!)O^)o{~eH{=e17ZZL9bnq2X zR35rDFD273WNu|`P%6nAf91zwt@r}7Vhv?DU&_BtRM#_YIc}JctYwv)tTSD*;2V*1 zTrxTaQ=jJG>V!<1S=*j8Op}llrl&Y7-rce4Z!iF%046y0aQN$Ev=)hfG_n@2xi8nO z?PTG2ct~grVX2U-5|S@X^2PS%X6$Lpux(Px6^u#8K48OtSw)iLzb1um+0~5mj$zrb zMNtc^J>FKX0gr50GertNN%c$g4wdqTDXvg#YTE_>?R&LY%Fmd_Yjl$5z@K2JIjnmy z#*ZZp%fHtl-1QLEK15BwqQr($hhJLk+d#bAINE`=OFauG=1*KMY@j%|{&a8*AAEv1 Hh$8wA7FdaR delta 1147 zcmZ9KO=uKJ6vylJbXQO2!^}7{i5Wif_LImT(`aM!#QYv(A%mDfaX+%=BPpUXTnH`DaLG@+y&C{5hb+JaKDp;^fb zzx`)USP*GWMc#uyImgYYC^JSu-qEf@vAI9C93Ukd`eER*rT1rZs0abkC-CQ(NXewJ z0T#;<;}~S+ZR2)4iEhgfTpr=Qi;A?+LtPcMMyX3!*F?pkHAX#h>v093Uk%w z1-K!42oxq35-3un2ul$+n8=c?j;6~BLSCLVhq>C|@(;5Ier-N9o1iziWi~H%4j6&Hi@ULu4}xh=UD#^w2>k2iXp?rC7^QQeEGJgo_Zq*gybMiGLq7x#%uP&y7 zsyZn$M{70DEeB#f?W=P)k+p>|Ku|xfDl$mR1d;ND*X4uEwbbhcrjcoj2Ae-;??T@Q zZer6DC+xDQ+V#e9SBz5R4)Sx+B@gGmEs*H5TWqA|PI)u8kgKD1$@{r}sLJQLBUr0F z`SFda?=kUZoTZC-6#1n$qz3fiz(??Reh7}s5BYvoH>=~TvPH3}pdNMFb~y-Y^>Tfx z7KFAP=@qPs*hQ%)5K-E;C%tkQPP(3F+ZKp%^s3%$Z$FmpBqdbv3zs0?{lr?C+^IdS zT=xULyVWJH7CQ5)mL#)Mk!jmbZPK>o`@--{7y6=v`(xb=Lb^k{ow^%L`-1*PJ;cb^ zU2|Mds6J4ZuNw4ke5+q`ragC?IEcG|U$_l{Y f8BVjkTUJBnm(g=$XU1k3nr|yGAJ)EN2-Vt;98v4S diff --git a/business_objects/store/__pycache__/order.cpython-312.pyc b/business_objects/store/__pycache__/order.cpython-312.pyc index 8210f475c987ddf75cebc06cb9765d3bf46d830d..c700bb9b40ba7030ff73503d076efb72fe0765c1 100644 GIT binary patch delta 1083 zcmZ8g%}*0S6rb64%XZsc3RDUOTM&U%L?ax4K#39!hJ&ai95^s3-7OTBwwc{(AQ-Fh zK*WP)62IbwgCE3`;Xm+3yl6Z~iXl;T6y@(kgBtP14;j9mTT~ z%7PGazskv2jo`dIW~Hf4hGM3^ej7W5dY)?y^jAoXP7`Y(qf1;~Ns~MV%>tuN7B1vQogDT)3 zaps+-ZX{^Ai|GVg6D%6yIVD1psiZ~7qFPEW8_Cw*X~UJg|pngJpbt>L_ugI#EVGyBjH&RRGWZ%2>*H#Krr4Y2QWtWxU0QPwX_ z;xKzG^__8neGS`QCI((CfK~u4wQAN(r;>?dnL{5dYwubs*WOBvG|ZxM{jrCj zet?o_3C;2#2i6jLxu<=K*$pwkHUvMrDb}*TE%v~Ce| zCPsCQ@cblZSu{D7wRF?&KweI2Btz3$Hf|Nmx4RJm?@}4;o4cW9m@Cc!~i}IhE7ZZ?Zu6T>?lHVFC#^BTaM;e%i#vA$|9RZO)t$7@v;J_IF5M=D!4I5Q=D>}9gX#W5nKj|s} delta 941 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 delta 5853 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 K|K*^`wE2IYy@6f; delta 6212 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 literal 7141 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 HM%w&8)gR}} diff --git a/business_objects/store/__pycache__/product_variation.cpython-312.pyc b/business_objects/store/__pycache__/product_variation.cpython-312.pyc index 29babe0d1e8beda3044c9026ddf42bd7cd26e740..1dd0c7582021a996a24a4e6434cebc44f4890845 100644 GIT binary patch literal 10691 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 WCg(m@pRCY6x@$N1dkP+8gZ>vqRd^8q literal 11466 zcmdTqTWlLwb~EHq98#o2y)02rN)#oLdRdA$u_VWd9(E$fmK{k>Vpi^y;*4!-`A}vk zZzR}TZ8zIGK#H}oC?p|WSi*i-f)|MMweClOML$~<<&+LMm?lNq?tbV`v9s-Bf7)~I z3?CX&&IA3~E9%UhbM8I&an3#G+0f@PT>G_`qW%kCvZ+kZJbMJ04T`6N z6i@S}C>=8e%{1oCQ6^>yT1cLWmc^_=E6H1;Y|Iw4k$hRy9xD%)le{(Rh&h8!nle$Z zQ9S!T#oGkyQggP!{8O+zWVE+nrC=ka?NGY>p-IC&)QbjPgysO6Q*b^s>vgJDP5z1y zLsOLfl9*T$!pTt&q)X$o^K+iJg+(cn6ztQ6ZU#_s_*5 z$s2a8luegJAsmq+iMVGx&Us3WBQ)Ity?v#F;3eVyRW{f58K= zo`P3B%UAufI;(EMs-x->d}oQ;H4j1iFlC>?ns3dcHd{CQ4AvgS1I7^0+AD;)ddHqq z&r?`K%jfFVf5&v`@_*J!@(eKy$6AA6q)cJTE8y+SA7@II9@&_3P`*e<>iU^m|cu!nC3=)Xg~M+XCQ zl)pu-Dzba3D-=#fZVFt^imA14oVmh{PtH%jb%uLue0F+#e){5!T4yZBC0CaP)m^GE zH-F{Q8MPt|Hm!hfH5Q$`I915C=5QH}XMJ%&jbl9@k(Q&ORW2d&f>^-132RJE&s{n{ zeucX@J9TEZpy$m;)Y2OBJg2HYj(8|mG>)0^3x~#WxJxR`1OUiBGO7I>X}Qf@R5XP`1tVf z0*MMZhzb@$%gYOkx}WAWmntnt=rb2|ubLO`!1Ai-fiA2y7AfyQw(lMFDW!s+t{fHTk0;O<%mvAl&DL;p|VfJ|%o$oE0%gr|6 zOgb)C8*pYFr$<>>2bLl;vtJJN_Z9e9%U|tYo zD@hWysO9h;4kd-_32_xM7D>R-sdGe4({LtG!it$S@6n>p>5qsizK_$o zPjWbMBKCJ5b$TBqw2#xVkK^CR0q^4o_pyk-LQ`u8=xLr|1yICe08~@xCg^v3c_qm$ zCK6G?R;)&f6>6Y|5nWig0a1;_$Sy}$#85QPO)G_?6>9={@EsHAbh@@1bh$mSJG9e`I@^l6{N~OnO_vMupZU5UT-~|) zXyoympPWjK&!sNEo%X$h#X6L}?>!3boyWXiY4&Z0wn*Ns^b9>}-*X_|cPKx2@^RJP zEyVYI7U=u9f3N?s?bq#p=SZD>Cly>s2d*NiTNxUCJp4%u<_8K_QqDNRKrl~M67JSE z;1vuSpfJJu0h6|*y&QtN-sIO5mP4@{l3p&irU<{B?&k~Z<#Nu7l*?&qQMvqz!gf&; z3`ysgUr|^N)xePSa=8_C3-n*a9g5$fR*lck&vMgK`H(?GW2RPS@t0;VPFGYZqs)h<$(-v1y{eVm;B^iEgCs9Md z26yk8Gd-`!@bkWkC@{sH+jAM;hzvi^D56@Fp1$3=O#kaL{CcJl<)F}fBnj}L4 ziWMj&bPy;kP|#Qz5>RYFDWQ)*u>%Dym>~hB94IAp6DSU#pkf#jP@F$^YnHmoo;@GI zXM`X1tho)StSbjnOA#p_Gyu8LNY2I(K%0)C=R@ z0}6CLw*YYpP^#-tsUtQ5P_Flzl*=-89xCj25OYDS12F{Jvd_6KG3V_x??yZoDhP2` zd$iaNc?m779-=`+E(*&c$CZwFHQH6I^zQ)HsRI*TTcuRhWvV*ls*aS)dqB~hZpGbl zziq26)!>KMK#S7So@qHQw;WG34*_DhQE6<=GzR3xK+4?eYW*JYc(GII?8$VVmOD?UysrS_Rk};*3S_z_?v)G) zuqBS{0P8Ungjc|Jl*D$H#CDa$_LRh;lQkr04LzwL0T$ysLjvq^0}5UNJ6w#7II}@O zqw3B&Z{67&f&p<7s%rs2ldSU|b#;CkVgn@b8|;^p45BV+1iMI|d)s z{;K(tX7bu2J9>6IGl2;?FhLMr+2P%u&-hNtzLNwoBs+#4oyfc}FTXHP5ZN})$ph!U zA&+dg&&qvgNfn>$@NFkE-KXU4QwL2IF8cvhVY3%o8niOR(wu1g63s^LYq(Yx}E&Gaf zV_5;@_Oc`9Xc`b6$He9 z5o;H~SKMN0k(CE?g9vapua=W@%9sFmjJ)_dqTfL9CW6Zd-UgsL_4CZI5RG!2pBB-7 z5rg=ub~1olNOD$z3rhMD;<4ZVgi->hQcS~U&-M#j{b}ZuGI%z{v~0e&Yu>t@X3i=- zCsWL^O?JCx%b8|QD*Y2FrfKt??eNysG&7+Lol7xo+YP(kot89nPI+-Y#dL1p*p+r- zX=eWUb-$=-zB{}za&KgF_I_|H_-Ot~&FK1hrLOhv?8cRQS2kBS#rvyUtGm@7-A>o_ zug?@yYCig5x^4g{^`5)p#_GM*?dk`OJB{i3z7$idw03VU-j8fWc1<7K_w4D`7og)x zMg5({pGH22Y?|)dx9sT(@A_*>qj$68zJJTVJ-t2gV0veIckve&(v8C@roNaI{>4nX z5jfSu840xJ-f{1a><)iCvN!T*?&0Zl`)G=3g)@)MiTl%A)7y&=mUfoX%|j{14d*D^ z!w*JwMs{aE4(Z!EY zpL!UJ{l6Vni{=7|4unAmatSRZre`++6kfv$a0$!Pc;-oRrd-ZUau%SHYgj_HG)fn##6c+zQ;@k)9bEP%90*_gGN? zDTvn)Tt{#NK?K1Pg6|`UA~3i{VsF>li~L|#NwcBL2Go`20e}PS>C5y?$~}`x|4^p? zg4};W2@GTcugQVe$hL7z?i_;?r;K+*_Kv`5lwR29&-h-JeJ_)}=8)Vr^ktPDy`DWA z=>YRwvO|t27j8D-h6lIVB;ofp@Mq3Gf5|*#H3|sRGBbZxr9@os;3;@`>`^2>B(6d& zM<0}E7WUu-RaX6_ z$!@WuJ=JnrW7tj@{&NZE9@8@|hR%P&a-GsXVbSa-Z$it*n*myR1|Z8@0NPf|{8sf? z@eH4jNJ-V6Gj~$BaJP@443W7AnL?SDJQJW%1Ck7O5>xhTC>r;S$jOkF&|Dc3Tny=Y zg}1AI^9(uCUF$2|?|~4XyU)v;S-Ag0XP`P@w*WR9BpMG3#21Nwj`%XTG8N)HY#`d< zRXa1rLF*SAu)s@k{dRr$XW%E{LcvQ^`%f!BsNA$|kEM?P>61Tu_X#U1tOIcwwpC_Z zH&;Jp{l$AG>=K!K4`lGV4rUQ@#`F>Ob8UaL2IJMgz>-Eiu-I_0MYaV4y0x|=rZan5 zCPN_!<3+f!scPBe?lEJVmg?&ibrq%@uSiPX z3Y(U4ml?oFPg&oc*NYFm43*4XXTZGBI0tz;xfM3etW`xpwexC$lfr0|@)y8cTkjV5 zb|9XFi!M|JwbD?d#C<|FY+DSa*8E3IXK~Rd(2Ddr0GQau<~x=8$>LLrww=5)tvH%8 zjt<$;u|1OUo{+sK(%u(8b-Z+72I_BEXUf&SJ(y}APF1|{ggv2Dwx-zD=Lq8;pczdV zAP~G6fOlg8fq+8XHs3OrT+pVQv_yYceXFEkO4lhALn(1Wt(@rcy(uB&3kB0SuPfHaBJY7fhUICV*_HekW=YvM%vgy;U61FA0)l2(6h;F}6nEB|l6RYHdk zl5J~G!Oc)hTZ(PW3D|7AM1zDY8#0w1xzdyB8U5GFQN`7fartGJf7hQ0jLCtqC$3Y9 zt25*3m0i8N)0w{Wa^LxM-^{13iw9QZaKKWo&J^n?LP zcL#ImvW))hhloS)kMJ*f0Ki_Y-o1YAE|X^5Pa*sdJY{Li@uy`LOWU&wtEH1PPOA8; zRV&Bwi7;%0>!XpyfslBee7^##E*gQ4G~t6!wWb78GtlkE?^XuLcPkp?7U5G)@*$0C zhvOb0j-RngB1%s!&wc+XNFv${wG8gJachijMrD^*`A{6(xQMEzTF3{XngiegLAq|3 zhCi^Uv@QK<5yL7P{v`|*VC~T~_-C5=T^B|BKBrE8PPu!$JpeEn*TZlF6iul$aJ2bskG1ALS0-~a#s diff --git a/business_objects/store/__pycache__/product_variation_tree.cpython-312.pyc b/business_objects/store/__pycache__/product_variation_tree.cpython-312.pyc index 05f657741b0cb4b3f345dd1671cfe9d56d34efbc..6664205a98d2b9055d20b6330011eb89fc4682a5 100644 GIT binary patch delta 3120 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 diff --git a/business_objects/store/__pycache__/product_variation_type.cpython-312.pyc b/business_objects/store/__pycache__/product_variation_type.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..456569872e1a2f45376eb12400b3d5e59216f4ac GIT binary patch literal 5793 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 WS2&Je8NPFE_1fCZ*92><=l=nCP!$dU literal 0 HcmV?d00001 diff --git a/business_objects/store/__pycache__/stock_item.cpython-312.pyc b/business_objects/store/__pycache__/stock_item.cpython-312.pyc index c5e06616b95e0b8192eb39043a8bef4e0ed60425..f40d2f0600faf0dd4e132951fc17a96381b3e6e2 100644 GIT binary patch delta 2841 zcmai0TWlLe6y34cPVCrDV#n`i(zM{{&Aa)-tl@>R+>z&>L5t5J%U5Qzk)zM&2Ud=JGH}DPRikOwkzP%&M%I$m_J&!(AnWBSH?_#s zlC}qawUZ6-%KAsBk$AyW=GB2$(hKG?u8MKhf~AZzFwQ8{mT@(VGYNI_{dXoeGtwf| zmlwq)AOUTa-Cm|yRc$gtqIUZfdPgHT%Tybv8cudiwyiG?BFeVk z%}Na)+OKI;Uhr0Wmz-$#1O(s47XQYUKm|*$I#Fn2OJfB~yPBnGW6P!rmfdQW%^O>` zRIrSwS?;Z1St~lcv8APgWo@GSDp=Mgid3+$EMr2efxEyRL6YNKwXjukp5ugVa#V7i z=Tgj4rYMUO`RT&Ulq_L5 z#bI7CoS2dEX%Xk2P&DEcZUv{YP|Qy}E@q4JRDq{Nh(0(-zA<;Afs)SRMJQBiti7r6 zc_2qfv9gsU<6E1}G>sgL`8`Vr(Ft z+@Da3*DBhHTtVR{3;Ah0NIeBDg-}Qf#r|z=MwwEhZ5WEpHyqIDyCBt0^0gyt@`D+H znL1<6CNxJR=f@~S@(pg&A5^%=Wx1!gNkpD;HyE#hlRk5ZJnVAtl;_C}myx1urC8J8{AB}?mqrS+<`XxXu%r4*_6zS$ODFomzimm<3s zBD?1A>s>b0Ety&uOs&`XrD%L18lT^mSankK3THAHafl`)m#ZD*SMOjwEDo=mc+l5| zJ|(Apjr?unP2bDjEEriSrffmXoXli%nZr3btigVA$nVkzLC=vhejoabT=YM5=k34z zhfM2cm7e5R=OE3~Ro^!RqR8A6axN!|VT1#eW&7KY z+1E0G6~GNbksJ#(ha#Ozk)egi&^+(CwEIfxt>Hy}XxX=A$roMlMdx{U>7|fQ<2LJz zw|q#~a*NmN>?;<%uKITiucKRA`m|}zM2>e}Zp3qt{XKy90m^p(;-h49G>HBwC8Dot z=r!_P+lyM`c@UnbFi4)>c2QWL;R7yQgZrqcm`-MLVs^Sv%uG+n7;a&;2YGsnXVlH; z2XX<-y5l%IT~zqu>Ekj!N0~5>zafuy9YjHLvnzr&mwxJ+g%xDFtB?~`kXDy~Uw|AJ z0OrZr&R6dFe?{LyGQ@IX7_);-FTIYQC`y%%^qfJnAxe+XWfwp$0?bfQ_``JD@hOO( z0D%9OYzq|=EvlHEU>hu91^Dj)%JM@9bujpj4hlMYiJs?H^qkYX$a|K(!9_l}>~CD; ziP*cU4>2#<-?t0(kvIBo2HDH&6aHDi&&` NXypvK-tXff+rNc7WBmXC delta 2534 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 literal 3641 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 0 - if permutation.has_variations: - for jsonProductVariation in json[cls.ATTR_ID_PRODUCT_VARIATION]: - variation = Product_Variation.from_json(jsonProductVariation) - permutation.add_product_variation(variation) - permutation.quantity_stock = json[cls.FLAG_QUANTITY_STOCK] + permutation.id_product = json[cls.ATTR_ID_PRODUCT] + permutation.id_category = json[cls.ATTR_ID_PRODUCT_CATEGORY] + permutation.description = json[cls.FLAG_DESCRIPTION] + permutation.cost_local = json[cls.FLAG_COST_LOCAL] + permutation.currency_cost = Currency.from_json(json, '_cost') + permutation.profit_local_min = json[cls.FLAG_PROFIT_LOCAL_MIN] + permutation.latency_manufacture_days = json[cls.FLAG_LATENCY_MANUFACTURE_DAYS] + permutation.id_unit_measurement_quantity = json[cls.FLAG_UNIT_MEASUREMENT_QUANTITY] + permutation.symbol_unit_measurement_quantity = json.get(cls.FLAG_SYMBOL_UNIT_MEASUREMENT_QUANTITY) + permutation.symbol_is_suffix_not_prefix_unit_measurement_quantity = json.get(cls.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_QUANTITY) + permutation.name_singular_unit_measurement_quantity = json.get(cls.FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_QUANTITY) + permutation.name_plural_unit_measurement_quantity = json.get(cls.FLAG_NAME_PLURAL_UNIT_MEASUREMENT_QUANTITY) + permutation.count_unit_measurement_per_quantity_step = json[cls.FLAG_COUNT_UNIT_MEASUREMENT_PER_QUANTITY_STEP] permutation.quantity_min = json[cls.FLAG_QUANTITY_MIN] permutation.quantity_max = json[cls.FLAG_QUANTITY_MAX] + permutation.quantity_stock = json[cls.FLAG_QUANTITY_STOCK] + permutation.is_subscription = 1 if av.input_bool(json[cls.FLAG_IS_SUBSCRIPTION], cls.FLAG_IS_SUBSCRIPTION, _m) else 0 + permutation.id_unit_measurement_interval_recurrence = json[cls.FLAG_UNIT_MEASUREMENT_INTERVAL_RECURRENCE] if json[cls.FLAG_UNIT_MEASUREMENT_INTERVAL_RECURRENCE] != '' else None + permutation.symbol_unit_measurement_interval_recurrence = json.get(cls.FLAG_SYMBOL_UNIT_MEASUREMENT_INTERVAL_RECURRENCE) + permutation.symbol_is_suffix_not_prefix_unit_measurement_interval_recurrence = json.get(cls.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_INTERVAL_RECURRENCE) + permutation.name_singular_unit_measurement_interval_recurrence = json.get(cls.FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_INTERVAL_RECURRENCE) + permutation.name_plural_unit_measurement_interval_recurrence = json.get(cls.FLAG_NAME_PLURAL_UNIT_MEASUREMENT_INTERVAL_RECURRENCE) + permutation.count_interval_recurrence = json[cls.FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_RECURRENCE] if json[cls.FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_RECURRENCE] != '' else None + permutation.id_stripe_product = json[cls.FLAG_ID_STRIPE_PRODUCT] + permutation.does_expire_faster_once_unsealed = 1 if av.input_bool(json[cls.FLAG_DOES_EXPIRE_FASTER_ONCE_UNSEALED], cls.FLAG_DOES_EXPIRE_FASTER_ONCE_UNSEALED, _m) else 0 + permutation.id_unit_measurement_interval_expiration_unsealed = json[cls.FLAG_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED] if json[cls.FLAG_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED] != '' else None + permutation.symbol_unit_measurement_interval_expiration_unsealed = json.get(cls.FLAG_SYMBOL_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED) + permutation.symbol_is_suffix_not_prefix_unit_measurement_interval_expiration_unsealed = json.get(cls.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED) + permutation.name_singular_unit_measurement_interval_expiration_unsealed = json.get(cls.FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED) + permutation.name_plural_unit_measurement_interval_expiration_unsealed = json.get(cls.FLAG_NAME_PLURAL_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED) + permutation.count_interval_expiration_unsealed = json[cls.FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED] if json[cls.FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED] != '' else None + permutation.has_variations = json[cls.FLAG_HAS_VARIATIONS] + permutation.active = 1 if av.input_bool(json[cls.FLAG_ACTIVE], cls.FLAG_ACTIVE, _m) else 0 + if permutation.has_variations: + permutation.variation_tree = Product_Variation_Tree.from_json_str(json[cls.FLAG_PRODUCT_VARIATIONS]) + """ + for jsonProductVariation in json[cls.FLAG_PRODUCT_VARIATIONS]: + variation = Product_Variation.from_json(jsonProductVariation) + permutation.add_product_variation(variation) + """ return permutation def to_json(self): return { - 'id_product': {self.id_product}, - 'id_permutation': {self.id_permutation}, - 'description': {self.description}, - 'id_category': {self.id_category}, - 'latency_manufacture': {self.latency_manufacture}, - 'quantity_min': {self.quantity_min}, - 'quantity_max': {self.quantity_max}, - 'quantity_step': {self.quantity_step}, - 'quantity_stock': {self.quantity_stock}, - 'id_stripe_product': {self.id_stripe_product}, - 'is_subscription': {self.is_subscription}, - 'name_recurrence_interval': {self.name_recurrence_interval}, - 'name_plural_recurrence_interval': {self.name_plural_recurrence_interval}, - 'count_recurrence_interval': {self.count_recurrence_interval}, - 'display_order': {self.display_order}, - 'can_view': {self.can_view}, - 'can_edit': {self.can_edit}, - 'can_admin': {self.can_admin}, - 'variations': {self.variations}, - 'images': {self.images}, - 'delivery_options': {self.delivery_options}, - 'prices': {self.prices} + **self.get_shared_json_attributes(self), + 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_DESCRIPTION: self.description, + self.FLAG_COST_LOCAL: self.cost_local, + self.FLAG_CURRENCY_COST: self.currency_cost.to_json(), + self.FLAG_PROFIT_LOCAL_MIN: self.profit_local_min, + self.FLAG_LATENCY_MANUFACTURE_DAYS: self.latency_manufacture_days, + self.FLAG_UNIT_MEASUREMENT_QUANTITY: self.id_unit_measurement_quantity, + self.FLAG_SYMBOL_UNIT_MEASUREMENT_QUANTITY: self.symbol_unit_measurement_quantity, + self.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_QUANTITY: self.symbol_is_suffix_not_prefix_unit_measurement_quantity, + self.FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_QUANTITY: self.name_singular_unit_measurement_quantity, + self.FLAG_NAME_PLURAL_UNIT_MEASUREMENT_QUANTITY: self.name_plural_unit_measurement_quantity, + self.FLAG_COUNT_UNIT_MEASUREMENT_PER_QUANTITY_STEP: self.count_unit_measurement_per_quantity_step, + self.FLAG_QUANTITY_MIN: self.quantity_min, + self.FLAG_QUANTITY_MAX: self.quantity_max, + self.FLAG_QUANTITY_STOCK: self.quantity_stock, + self.FLAG_IS_SUBSCRIPTION: self.is_subscription, + self.FLAG_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: self.id_unit_measurement_interval_recurrence, + self.FLAG_SYMBOL_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: self.symbol_unit_measurement_interval_recurrence, + self.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: self.symbol_is_suffix_not_prefix_unit_measurement_interval_recurrence, + self.FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: self.name_singular_unit_measurement_interval_recurrence, + self.FLAG_NAME_PLURAL_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: self.name_plural_unit_measurement_interval_recurrence, + self.FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: self.count_interval_recurrence, + self.FLAG_ID_STRIPE_PRODUCT: self.id_stripe_product, + self.FLAG_DOES_EXPIRE_FASTER_ONCE_UNSEALED: self.does_expire_faster_once_unsealed, + self.FLAG_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: self.id_unit_measurement_interval_expiration_unsealed, + self.FLAG_SYMBOL_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: self.symbol_unit_measurement_interval_expiration_unsealed, + self.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: self.symbol_is_suffix_not_prefix_unit_measurement_interval_expiration_unsealed, + self.FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: self.name_singular_unit_measurement_interval_expiration_unsealed, + self.FLAG_NAME_PLURAL_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: self.name_plural_unit_measurement_interval_expiration_unsealed, + self.FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: self.count_interval_expiration_unsealed, + self.FLAG_HAS_VARIATIONS: self.has_variations, + self.FLAG_ACTIVE: self.active, + self.FLAG_CAN_VIEW: self.can_view, + self.FLAG_CAN_EDIT: self.can_edit, + self.FLAG_CAN_ADMIN: self.can_admin, + self.FLAG_PRODUCT_VARIATION: [variation.to_json() for variation in self.variations], + self.FLAG_PRODUCT_IMAGE: [image.to_json() for image in self.images], + self.FLAG_DELIVERY_OPTION: [option.to_json() for option in self.delivery_options], + self.FLAG_PRODUCT_PRICE: [price.to_json() for price in self.prices], } def to_json_option(self): return { 'value': self.id_permutation, 'text': self.get_name_variations() } + def get_name(self): + return def get_name_variations(self): return self.variation_tree.get_name_variations() def is_available(self): @@ -207,10 +325,10 @@ class Product_Permutation(db.Model, Store_Base): return price.value_local_VAT_excl def output_lead_time(self): - return '1 day' if self.latency_manufacture == 1 else f'{self.latency_manufacture} days' + 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)).strftime('%A, %d %B %Y') + return (datetime.now() + timedelta(days=self.latency_manufacture_days)).strftime('%A, %d %B %Y') def output_price(self, is_included_VAT): if self.is_unavailable_in_currency_or_region: @@ -252,21 +370,38 @@ class Product_Permutation(db.Model, Store_Base): """ def __repr__(self): return f'''Product_Permutation - id_product: {self.id_product} id_permutation: {self.id_permutation} - description: {self.description} + id_product: {self.id_product} id_category: {self.id_category} - latency_manufacture: {self.latency_manufacture} + description: {self.description} + cost_local: {self.cost_local} + currency_cost: {self.currency_cost} + latency_manufacture_days: {self.latency_manufacture_days} + id_unit_measurement_quantity: {self.id_unit_measurement_quantity} + symbol_unit_measurement_quantity: {self.symbol_unit_measurement_quantity} + symbol_is_suffix_not_prefix_unit_measurement_quantity: {self.symbol_is_suffix_not_prefix_unit_measurement_quantity} + name_singular_unit_measurement_quantity: {self.name_singular_unit_measurement_quantity} + name_plural_unit_measurement_quantity: {self.name_plural_unit_measurement_quantity} + count_unit_measurement_per_quantity_step: {self.count_unit_measurement_per_quantity_step} quantity_min: {self.quantity_min} quantity_max: {self.quantity_max} - quantity_step: {self.quantity_step} quantity_stock: {self.quantity_stock} - id_stripe_product: {self.id_stripe_product} is_subscription: {self.is_subscription} - name_recurrence_interval: {self.name_recurrence_interval} - name_plural_recurrence_interval: {self.name_plural_recurrence_interval} - count_recurrence_interval: {self.count_recurrence_interval} - display_order: {self.display_order} + id_unit_measurement_interval_recurrence: {self.id_unit_measurement_interval_recurrence} + symbol_unit_measurement_interval_recurrence: {self.symbol_unit_measurement_interval_recurrence} + symbol_is_suffix_not_prefix_unit_measurement_interval_recurrence: {self.symbol_is_suffix_not_prefix_unit_measurement_interval_recurrence} + name_singular_unit_measurement_interval_recurrence: {self.name_singular_unit_measurement_interval_recurrence} + name_plural_unit_measurement_interval_recurrence: {self.name_plural_unit_measurement_interval_recurrence} + count_interval_recurrence: {self.count_interval_recurrence} + id_stripe_product: {self.id_stripe_product} + does_expire_faster_once_unsealed: {self.does_expire_faster_once_unsealed} + id_unit_measurement_interval_expiration_unsealed: {self.id_unit_measurement_interval_expiration_unsealed} + symbol_unit_measurement_interval_expiration_unsealed: {self.symbol_unit_measurement_interval_expiration_unsealed} + symbol_is_suffix_not_prefix_unit_measurement_interval_expiration_unsealed: {self.symbol_is_suffix_not_prefix_unit_measurement_interval_expiration_unsealed} + name_singular_unit_measurement_interval_expiration_unsealed: {self.name_singular_unit_measurement_interval_expiration_unsealed} + name_plural_unit_measurement_interval_expiration_unsealed: {self.name_plural_unit_measurement_interval_expiration_unsealed} + count_interval_expiration_unsealed: {self.count_interval_expiration_unsealed} + has_variations: {self.has_variations} can_view: {self.can_view} can_edit: {self.can_edit} can_admin: {self.can_admin} @@ -378,3 +513,104 @@ class Permutation_Product_Variation_Link(db.Model): link.id_variation = query_row[3] return link """ + +class Product_Permutation_Temp(db.Model, Store_Base): + __tablename__: ClassVar[str] = 'Shop_Product_Permutation_Temp' + __table_args__ = { 'extend_existing': True } + id_permutation: int = db.Column(db.Integer, primary_key=True) + id_product: int = db.Column(db.Integer) + description: str = db.Column(db.String(4000)) + cost_local: float = db.Column(db.Float) + id_currency_cost: int = db.Column(db.Integer) + profit_local_min: float = db.Column(db.Float) + latency_manufacture_days: int = db.Column(db.Integer) + id_unit_measurement_quantity: int = db.Column(db.Integer) + count_unit_measurement_per_quantity_step: int = db.Column(db.Float) + quantity_min: int = db.Column(db.Integer) + quantity_max: int = db.Column(db.Integer) + quantity_stock: int = db.Column(db.Integer) + is_subscription: bool = db.Column(db.Boolean) + id_unit_measurement_interval_recurrence: int = db.Column(db.Integer) + count_interval_recurrence: int = db.Column(db.Float) + id_stripe_product: str = db.Column(db.String(50)) + does_expire_faster_once_unsealed: bool = db.Column(db.Boolean) + id_unit_measurement_interval_expiration_unsealed: int = db.Column(db.Integer) + count_interval_expiration_unsealed: int = db.Column(db.Integer) + active: bool = db.Column(db.Boolean) + guid: str = db.Column(db.String(36)) + + @classmethod + def from_product_permutation(cls, product_permutation): + row = cls() + row.id_permutation = product_permutation.id_permutation + row.id_product = product_permutation.id_product + row.description = product_permutation.description + row.cost_local = product_permutation.cost_local + row.id_currency_cost = product_permutation.currency_cost.id_currency + row.profit_local_min = product_permutation.profit_local_min + row.latency_manufacture_days = product_permutation.latency_manufacture_days + row.id_unit_measurement_quantity = product_permutation.id_unit_measurement_quantity + row.count_unit_measurement_per_quantity_step = product_permutation.count_unit_measurement_per_quantity_step + row.quantity_min = product_permutation.quantity_min + row.quantity_max = product_permutation.quantity_max + row.quantity_stock = product_permutation.quantity_stock + row.is_subscription = product_permutation.is_subscription + row.id_unit_measurement_interval_recurrence = product_permutation.id_unit_measurement_interval_recurrence + row.count_interval_recurrence = product_permutation.count_interval_recurrence + row.id_stripe_product = product_permutation.id_stripe_product + row.does_expire_faster_once_unsealed = product_permutation.does_expire_faster_once_unsealed + row.id_unit_measurement_interval_expiration_unsealed = product_permutation.id_unit_measurement_interval_expiration_unsealed + row.count_interval_expiration_unsealed = product_permutation.count_interval_expiration_unsealed + row.active = product_permutation.active + return row + def __repr__(self): + return f''' + id_permutation: {self.id_permutation} + id_product: {self.id_product} + description: {self.description} + cost_local: {self.cost_local} + id_currency_cost: {self.id_currency_cost} + profit_local_min: {self.profit_local_min} + latency_manufacture_days: {self.latency_manufacture_days} + id_unit_measurement_quantity: {self.id_unit_measurement_quantity} + {Product_Permutation.FLAG_COUNT_UNIT_MEASUREMENT_PER_QUANTITY_STEP}: {self.count_unit_measurement_per_quantity_step} + quantity_min: {self.quantity_min} + quantity_max: {self.quantity_max} + quantity_stock: {self.quantity_stock} + is_subscription: {self.is_subscription} + id_unit_measurement_interval_recurrence: {self.id_unit_measurement_interval_recurrence} + count_interval_recurrence: {self.count_interval_recurrence} + id_stripe_product: {self.id_stripe_product} + does_expire_faster_once_unsealed: {self.does_expire_faster_once_unsealed} + id_unit_measurement_interval_expiration_unsealed: {self.id_unit_measurement_interval_expiration_unsealed} + count_interval_expiration_unsealed: {self.count_interval_expiration_unsealed} + active: {self.active} + guid: {self.guid} + ''' + """ + def to_json(self): + return { + self.ATTR_ID_PRODUCT_PERMUTATION: int(self.id_permutation), + self.ATTR_ID_PRODUCT: int(self.id_product), + self.FLAG_DESCRIPTION: self.description, + Product_Permutation.FLAG_COST_LOCAL: float(self.cost_local), + Product_Permutation.FLAG_CURRENCY_COST: int(self.id_currency_cost), + Product_Permutation.FLAG_PROFIT_LOCAL_MIN: float(self.profit_local_min), + Product_Permutation.FLAG_LATENCY_MANUFACTURE_DAYS: int(self.latency_manufacture_days), + Product_Permutation.FLAG_UNIT_MEASUREMENT_QUANTITY: int(self.id_unit_measurement_quantity), + Product_Permutation.FLAG_COUNT_UNIT_MEASUREMENT_PER_QUANTITY_STEP: float(self.count_unit_measurement_per_quantity_step), + self.FLAG_QUANTITY_MIN: float(self.quantity_min), + self.FLAG_QUANTITY_MAX: float(self.quantity_max), + Product_Permutation.FLAG_QUANTITY_STOCK: float(self.quantity_stock), + Product_Permutation.FLAG_IS_SUBSCRIPTION: bool(self.is_subscription), + Product_Permutation.FLAG_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: int(self.id_unit_measurement_interval_recurrence) if self.id_unit_measurement_interval_recurrence != '' else None, + Product_Permutation.FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: float(self.count_interval_recurrence) if self.count_interval_recurrence != '' else None, + Product_Permutation.FLAG_ID_STRIPE_PRODUCT: self.id_stripe_product, + Product_Permutation.FLAG_DOES_EXPIRE_FASTER_ONCE_UNSEALED: bool(self.does_expire_faster_once_unsealed), + Product_Permutation.FLAG_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: int(self.id_unit_measurement_interval_expiration_unsealed) if self.id_unit_measurement_interval_expiration_unsealed != '' else None, + Product_Permutation.FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: float(self.count_interval_expiration_unsealed) if self.count_interval_expiration_unsealed != '' else None, + self.FLAG_ACTIVE: bool(self.active), + self.FLAG_GUID: self.guid + } + """ + \ No newline at end of file diff --git a/business_objects/store/product_price.py b/business_objects/store/product_price.py index 71adab43..8f5df9f3 100644 --- a/business_objects/store/product_price.py +++ b/business_objects/store/product_price.py @@ -20,19 +20,21 @@ from dataclasses import dataclass from typing import ClassVar class Product_Price(db.Model, Store_Base): - ATTR_ID_PRODUCT_PRICE: ClassVar[str] = 'id-price' + 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' - FLAG_DISPLAY_ORDER: ClassVar[str] = 'display-order-price' id_price = 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) + """ id_currency = db.Column(db.Integer) code_currency = db.Column(db.String(50)) name_currency = db.Column(db.String(255)) symbol_currency = db.Column(db.String(50)) + """ id_region = db.Column(db.Integer) value_local_VAT_incl = db.Column(db.Float) value_local_VAT_excl = db.Column(db.Float) @@ -41,18 +43,23 @@ class Product_Price(db.Model, Store_Base): def __init__(self): super().__init__() Store_Base.__init__(self) - - def from_DB_get_many_product_catalogue(query_row): + self.currency = None + self.delivery_region = None + @classmethod + def from_DB_get_many_product_catalogue(cls, query_row): # _m = 'Product_Price.from_DB_get_many_product_catalogue' - price = Product_Price() + price = cls() price.id_price = query_row[0] price.id_permutation = query_row[1] price.id_product = query_row[2] price.id_category = query_row[3] + price.currency = Currency.from_DB_get_many_product_price_and_discount_and_delivery_region(query_row) + """ price.id_currency = query_row[4] price.code_currency = query_row[5] price.name_currency = query_row[6] price.symbol_currency = query_row[7] + """ price.id_region = query_row[8] price.value_local_VAT_incl = query_row[9] price.value_local_VAT_excl = query_row[10] @@ -65,35 +72,26 @@ class Product_Price(db.Model, Store_Base): id_permutation: {self.id_permutation} id_product: {self.id_product} id_category: {self.id_category} - id_currency: {self.id_currency} - code_currency: {self.code_currency} - name_currency: {self.name_currency} - symbol_currency: {self.symbol_currency} + currency: {self.currency} id_region: {self.id_region} value_local (VAT incl): {self.value_local_VAT_incl} value_local (VAT excl): {self.value_local_VAT_excl} display_order (UID): {self.display_order} + {self.FLAG_TEXT}: {self.currency.symbol} {self.value_local_VAT_incl} ''' def to_json(self): return { - self.ATTR_ID_PRODUCT_PRICE: {self.id_price}, - self.ATTR_ID_PRODUCT_PERMUTATION: {self.id_permutation}, - self.ATTR_ID_PRODUCT: {self.id_product}, - self.ATTR_ID_PRODUCT_CATEGORY: {self.id_category}, - Currency.ATTR_ID_CURRENCY: {self.id_currency}, - Currency.FLAG_CODE: {self.code_currency}, - Currency.FLAG_NAME: {self.name_currency}, - Currency.FLAG_SYMBOL: {self.symbol_currency}, - Delivery_Region.ATTR_ID_REGION: {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} - } - def to_json_option(self): - return { - 'value': self.id_price, - 'text': f'{self.symbol_currency} {self.value_local_VAT_incl}' + **self.get_shared_json_attributes(self), + self.ATTR_ID_PRODUCT_PRICE: self.id_price, + 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_CURRENCY: self.currency.to_json(), + Delivery_Region.ATTR_ID_DELIVERY_REGION: 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 } @classmethod @@ -103,11 +101,8 @@ class Product_Price(db.Model, Store_Base): price.id_permutation = json[cls.ATTR_ID_PRODUCT_PERMUTATION] price.id_product = json[cls.ATTR_ID_PRODUCT] price.id_category = json[cls.ATTR_ID_PRODUCT_CATEGORY] - price.id_currency = json[Currency.ATTR_ID_CURRENCY] - price.code_currency = json[Currency.FLAG_CODE] - price.name_currency = json[Currency.FLAG_NAME] - price.symbol_currency = json[Currency.FLAG_SYMBOL] - price.id_region = json[Delivery_Region.ATTR_ID_REGION] + price.currency = Currency.from_json(json) + price.id_region = json[Delivery_Region.ATTR_ID_DELIVERY_REGION] price.value_local_VAT_incl = json[cls.FLAG_VALUE_LOCAL_VAT_INCL] price.value_local_VAT_excl = json[cls.FLAG_VALUE_LOCAL_VAT_EXCL] price.display_order = json[cls.FLAG_DISPLAY_ORDER] diff --git a/business_objects/store/product_variation.py b/business_objects/store/product_variation.py index e6782677..d359cc98 100644 --- a/business_objects/store/product_variation.py +++ b/business_objects/store/product_variation.py @@ -19,124 +19,103 @@ Business object for product variation # internal import lib.argument_validation as av from business_objects.store.store_base import Store_Base +from business_objects.store.product_variation_type import Product_Variation_Type from extensions import db # external from dataclasses import dataclass from typing import ClassVar from pydantic import BaseModel +from itertools import filterfalse +from operator import attrgetter -# CLASSES class Product_Variation(db.Model, Store_Base): - KEY_ACTIVE_VARIATION: ClassVar[str] = 'active_variation' - KEY_ACTIVE_VARIATION_TYPE: ClassVar[str] = 'active_variation_type' - KEY_CODE_VARIATION: ClassVar[str] = 'code_variation' - KEY_CODE_VARIATION_TYPE: ClassVar[str] = 'code_variation_type' - KEY_DISPLAY_ORDER_VARIATION: ClassVar[str] = 'display_order_variation' - KEY_DISPLAY_ORDER_VARIATION_TYPE: ClassVar[str] = 'display_order_variation_type' - KEY_NAME_VARIATION: ClassVar[str] = 'name_variation' - KEY_NAME_VARIATION_TYPE: ClassVar[str] = 'name_variation_type' - + NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_PRODUCT_VARIATION + NAME_ATTR_OPTION_TEXT = Store_Base.FLAG_NAME + id_variation = db.Column(db.Integer, primary_key=True) - code_variation = db.Column(db.String(50)) - name_variation = db.Column(db.String(255)) - active_variation = db.Column(db.Boolean) - display_order_variation = db.Column(db.Integer) id_type = db.Column(db.Integer) - code_variation_type = db.Column(db.String(50)) - name_variation_type = db.Column(db.String(255)) - name_plural_variation_type = db.Column(db.String(255)) - active_variation_type = db.Column(db.Boolean) - display_order_variation_type = db.Column(db.Integer) - id_product = db.Column(db.Integer) - id_permutation = db.Column(db.Integer) - id_category = db.Column(db.Integer) + code = db.Column(db.String(50)) + name = db.Column(db.String(255)) + display_order = db.Column(db.Integer) + active = db.Column(db.Boolean) + id_permutation = db.Column(db.Integer) + id_product = db.Column(db.Integer) + id_category = db.Column(db.Integer) + def __init__(self): super().__init__() - Store_Base.__init__(self) + self.variation_type = None - def from_DB_get_many_product_catalogue(query_row): - variation = Product_Variation.from_DB_variation(query_row) + @classmethod + def from_DB_get_many_product_catalogue(cls, query_row): + variation = Product_Variation.from_DB_get_many_product_variation(query_row) variation.id_product = query_row[11] variation.id_permutation = query_row[12] variation.id_category = query_row[13] + variation.variation_type = Product_Variation_Type.from_DB_get_many_product_catalogue(query_row) return variation - def from_DB_variation(query_row): - _m = 'Product_Variation.from_DB_variation' - variation = Product_Variation() + @classmethod + def from_DB_get_many_product_variation(cls, query_row): + variation = cls() variation.id_variation = query_row[0] - variation.code_variation = query_row[1] - variation.name_variation = query_row[2] - variation.active_variation = av.input_bool(query_row[3], 'active_variation', _m) - variation.display_order_variation = query_row[4] - variation.id_type = query_row[5] - variation.code_variation_type = query_row[6] - variation.name_variation_type = query_row[7] - variation.name_plural_variation_type = query_row[8] - variation.active_variation_type = av.input_bool(query_row[9], 'active_variation', _m) - variation.display_order_variation_type = query_row[10] + variation.id_type = query_row[1] + variation.code = query_row[2] + variation.name = query_row[3] + variation.display_order = query_row[4] + variation.active = av.input_bool(query_row[5], cls.FLAG_ACTIVE, f'{cls.__name__}.from_DB_get_many_product_variation') return variation @classmethod def from_json(cls, json): variation = cls() - variation.id_variation = json[cls.ATTR_ID_VARIATION] + variation.id_variation = json[cls.ATTR_ID_PRODUCT_VARIATION] + variation.code = json[cls.FLAG_CODE] + variation.name = json[cls.FLAG_NAME] + variation.display_order = json[cls.FLAG_DISPLAY_ORDER] + variation.active = json[cls.FLAG_ACTIVE] + variation.id_permutation = json[cls.ATTR_ID_PRODUCT_PERMUTATION] variation.id_product = json[cls.ATTR_ID_PRODUCT] - variation.id_permutation = json[cls.ATTR_ID_PERMUTATION] - variation.id_category = json[cls.ATTR_ID_CATEGORY] - variation.name_variation_type = json[cls.KEY_NAME_VARIATION_TYPE] - variation.name_variation = json[cls.KEY_NAME_VARIATION] + variation.id_category = json[cls.ATTR_ID_PRODUCT_CATEGORY] return variation def __repr__(self): return f''' - id: {self.id_variation} - id_product: {self.id_product} + {self.__class__.__name__} + id_variation: {self.id_variation} + id_type: {self.id_type} + code: {self.code} + name: {self.name} + display_order: {self.display_order} + active: {self.active} id_permutation: {self.id_permutation} + id_product: {self.id_product} id_category: {self.id_category} - code_variation_type: {self.code_variation_type} - name_variation_type: {self.name_variation_type} - code_variation: {self.code_variation} - name_variation: {self.name_variation} - active_variation: {self.active_variation} - active_variation_type: {self.active_variation_type} - display_order_variation: {self.display_order_variation} - display_order_variation_type: {self.display_order_variation_type} + variation_type: {self.variation_type} ''' def to_json(self): return { + **self.get_shared_json_attributes(self), self.ATTR_ID_PRODUCT_VARIATION: self.id_variation, + self.ATTR_ID_PRODUCT_VARIATION_TYPE: self.id_type, + self.FLAG_CODE: self.code, + self.FLAG_NAME: self.name, + self.FLAG_DISPLAY_ORDER: self.display_order, + self.FLAG_ACTIVE: self.active, self.ATTR_ID_PRODUCT: self.id_product, self.ATTR_ID_PRODUCT_PERMUTATION: self.id_permutation, self.ATTR_ID_PRODUCT_CATEGORY: self.id_category, - self.ATTR_ID_PRODUCT_VARIATION_TYPE: self.id_type, - self.KEY_CODE_VARIATION_TYPE: self.code_variation_type, - self.KEY_CODE_VARIATION: self.code_variation, - self.KEY_DISPLAY_ORDER_VARIATION_TYPE: self.display_order_variation_type, - self.KEY_DISPLAY_ORDER_VARIATION: self.display_order_variation, - self.KEY_NAME_VARIATION_TYPE: self.name_variation_type, - self.KEY_NAME_VARIATION: self.name_variation, - self.KEY_ACTIVE_VARIATION_TYPE: self.active_variation_type, - self.KEY_ACTIVE_VARIATION: self.active_variation, } def to_json_option(self): return { 'value': self.id_variation, - 'text': self.name_variation - } - - def to_json_variation_type(self): - return { - self.ATTR_ID_PRODUCT_VARIATION_TYPE: self.id_type, - self.KEY_CODE_VARIATION_TYPE: self.code_variation_type, - self.KEY_DISPLAY_ORDER_VARIATION_TYPE: self.display_order_variation_type, - self.KEY_NAME_VARIATION_TYPE: self.name_variation_type, - self.KEY_ACTIVE_VARIATION_TYPE: self.active_variation_type, + 'text': self.name } + @dataclass class Product_Variation_Filters(): get_all_variation_type: bool @@ -198,30 +177,35 @@ class Product_Variation_Filters(): get_first_variation = False, ids_variation = '' ) - -class Product_Variation_List(BaseModel): + + +class Product_Variation_Container(BaseModel): + variation_types: list = [] variations: list = [] + def add_product_variation_type(self, variation_type): + av.val_instance(variation_type, 'variation_type', 'Product_Variation_Container.add_product_variation_type', Product_Variation_Type) + self.variations.append(variation_type) def add_product_variation(self, variation): - av.val_instance(variation, 'variation', 'Product_Variation_List.add_product_variation', Product_Variation) + av.val_instance(variation, 'variation', 'Product_Variation_Container.add_product_variation', Product_Variation) + if variation.variation_type is None: + variation_type = next(filterfalse(lambda x: x.id_type != variation.id_type, self.variation_types), None) + if variation_type is not None: + variation.variation_type = variation_type self.variations.append(variation) def __repr__(self): - return f'variations: {self.variations}' + return f'Product_Variation_Container:\nvariations_types: {self.variation_types}\nvariations: {self.variations}' - def to_list_variations(self): + def to_list_variation_options(self): list_variations = [] for variation in self.variations: - list_variations.append(variation.to_json()) + list_variations.append(variation.to_json_option()) print(f'list_variations: {list_variations}') return list_variations - - def to_list_variation_types(self): + def to_list_variation_type_options(self): list_variation_types = [] - list_variation_ids = [] - for variation in self.variations: - if variation.id_type not in list_variation_ids: - list_variation_ids.append(variation.id_type) - list_variation_types.append(variation.to_json_variation_type()) + for variation_type in self.variation_types: + list_variation_types.append(variation_type.to_json_option()) return list_variation_types \ No newline at end of file diff --git a/business_objects/store/product_variation_tree.py b/business_objects/store/product_variation_tree.py index 51910d6f..392c8798 100644 --- a/business_objects/store/product_variation_tree.py +++ b/business_objects/store/product_variation_tree.py @@ -55,20 +55,42 @@ class Product_Variation_Tree(): is_equal = (sz_me == sz_other) if is_equal: for index_type in range(sz_me): - if sz_me[index_type] != sz_other[index_type]: + if my_type_list[index_type] != other_type_list[index_type]: is_equal = False break return is_equal - def from_product_permutation(product_permutation): + @classmethod + def from_product_permutation(cls, product_permutation): depth_max = len(product_permutation.variations) node_root = Product_Variation_Tree_Node.from_variation_and_node_parent(product_permutation.variations[0], None) node = node_root for depth in range(depth_max - 1): node = Product_Variation_Tree_Node.from_variation_and_node_parent(product_permutation.variations[depth + 1], node) - return Product_Variation_Tree.from_node_root(node_root) - def from_product_variation(product_variation): + return cls.from_node_root(node_root) + @classmethod + def from_product_variation(cls, product_variation): node_root = Product_Variation_Tree_Node.from_variation_and_node_parent(product_variation, None) - return Product_Variation_Tree.from_node_root(node_root) + return cls.from_node_root(node_root) + @classmethod + def from_product_variations(cls, product_variations): + node_root = Product_Variation_Tree_Node.from_variation_and_node_parent(product_variations[0], None) + tree = cls.from_node_root(node_root) + if len(product_variations) > 1: + for variation in product_variations[1:]: + tree.add_product_variation(variation) + return tree + @classmethod + def from_json_str(cls, json_str): + variations = [] + for json_variation in json_str.split(','): + parts = json_variation.split(':') + if len(parts) != 2: continue + variation = Product_Variation() + variation.id_type = parts[0] + variation.id_variation = parts[1] + variations.append(variation) + return cls.from_product_variations(variations) + """ def get_name_variations(self): node = self.node_root name = node.variation.name_variation_type @@ -78,6 +100,7 @@ class Product_Variation_Tree(): name += f', {node.variation.name_variation_type}' at_leaf_node = node.is_leaf() return name + """ def get_node_leaf(self): node = self.node_root at_leaf_node = node.is_leaf() @@ -102,8 +125,64 @@ class Product_Variation_Tree(): variations = [] node = self.node_root at_leaf_node = node.is_leaf() + variations.append(node.variation) while not at_leaf_node: - variations.append(node.variation) node = node.nodes_child[0] at_leaf_node = node.is_leaf() - return variations \ No newline at end of file + variations.append(node.variation) + return variations + def to_preview_str(self): + print(f'Product_Variation_Tree.to_preview_str') + variations = self.get_product_variations() + print(f'variations: {variations}') + preview_str = '' + for variation in variations: + is_first = (preview_str == '') + preview_str += f'{variation.variation_type.name_singular}: {variation.name}' + if is_first: + preview_str += '\n' + print(f'preview_str: {preview_str}') + return preview_str + def to_json(self): + variations = self.get_product_variations() + json_variations = [] + for variation in variations: + json_variations.append(variation.to_json()) + return json_variations + def to_variation_id_pairs_str(self): + variations = self.get_product_variations() + pairs_str = '' + for variation in variations: + pairs_str += f'{variation.id_type}:{variation.id_variation},' + return pairs_str +""" +class Product_Variation_Container(BaseModel): + variation_types: list = [] + variations: list = [] + + def add_product_variation_type(self, variation_type): + av.val_instance(variation_type, 'variation_type', 'Product_Variation_Container.add_product_variation_type', Product_Variation_Type) + self.variations.append(variation_type) + def add_product_variation(self, variation): + av.val_instance(variation, 'variation', 'Product_Variation_Container.add_product_variation', Product_Variation) + if variation.variation_type is None: + variation_type = next(filterfalse(lambda x: x.id_type != variation.id_type, self.variation_types), None) + if variation_type is not None: + variation.variation_type = variation_type + self.variations.append(variation) + + def __repr__(self): + return f'Product_Variation_Container:\nvariations_types: {self.variation_types}\nvariations: {self.variations}' + + def to_list_variation_options(self): + list_variations = [] + for variation in self.variations: + list_variations.append(variation.to_json_option()) + print(f'list_variations: {list_variations}') + return list_variations + def to_list_variation_type_options(self): + list_variation_types = [] + for variation_type in self.variation_types: + list_variation_types.append(variation_type.to_json_option()) + return list_variation_types +""" \ No newline at end of file diff --git a/business_objects/store/product_variation_type.py b/business_objects/store/product_variation_type.py new file mode 100644 index 00000000..2b77562e --- /dev/null +++ b/business_objects/store/product_variation_type.py @@ -0,0 +1,103 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Business Objects +Feature: Product Product_Variation Business Object + +Description: +Business object for product variation +""" + +# IMPORTS +# VARIABLE INSTANTIATION +# CLASSES +# METHODS + +# IMPORTS +# internal +import lib.argument_validation as av +from business_objects.store.store_base import Store_Base +from extensions import db +# external +from dataclasses import dataclass +from typing import ClassVar +from pydantic import BaseModel +from itertools import filterfalse +from operator import attrgetter + +class Product_Variation_Type(db.Model, Store_Base): + NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_PRODUCT_VARIATION_TYPE + NAME_ATTR_OPTION_TEXT = Store_Base.FLAG_NAME_SINGULAR + + id_type = db.Column(db.Integer, primary_key=True) + code = db.Column(db.String(50)) + name_singular = db.Column(db.String(255)) + name_plural = db.Column(db.String(255)) + display_order = db.Column(db.Integer) + active = db.Column(db.Boolean) + + def __init__(self): + super().__init__() + + @classmethod + def from_DB_get_many_product_catalogue(cls, query_row): + variation_type = cls() + variation_type.id_type = query_row[1] + variation_type.code = query_row[6] + variation_type.name_singular = query_row[7] + variation_type.name_plural = query_row[8] + variation_type.display_order = query_row[9] + variation_type.active = av.input_bool(query_row[10], cls.FLAG_ACTIVE, f'{cls.__name__}.from_DB_get_many_product_catalogue') + return variation_type + + @classmethod + def from_DB_get_many_product_variation(cls, query_row): + variation_type = cls() + variation_type.id_type = query_row[0] + variation_type.code = query_row[1] + variation_type.name_singular = query_row[2] + variation_type.name_plural = query_row[3] + variation_type.display_order = query_row[4] + variation_type.active = av.input_bool(query_row[5], cls.FLAG_ACTIVE, f'{cls.__name__}.from_DB_get_many_product_variation') + return variation_type + + @classmethod + def from_json(cls, json): + variation_type = cls() + variation_type.id_type = json[cls.ATTR_ID_PRODUCT_VARIATION_TYPE] + variation_type.code = json[cls.FLAG_CODE] + variation_type.name_singular = json[cls.FLAG_NAME_SINGULAR] + variation_type.name_plural = json[cls.FLAG_NAME_PLURAL] + variation_type.display_order = json[cls.FLAG_DISPLAY_ORDER] + variation_type.active = json[cls.FLAG_ACTIVE] + return variation_type + + def __repr__(self): + return f''' + {self.__class__.__name__} + id_type: {self.id_type} + code: {self.code} + name_singular: {self.name_singular} + name_plural: {self.name_plural} + display_order: {self.display_order} + active: {self.active} + ''' + + def to_json(self): + return { + **self.get_shared_json_attributes(self), + self.ATTR_ID_PRODUCT_VARIATION_TYPE: self.id_type, + self.FLAG_CODE: self.code, + self.FLAG_NAME_SINGULAR: self.name_singular, + self.FLAG_NAME_PLURAL: self.name_plural, + self.FLAG_DISPLAY_ORDER: self.display_order, + self.FLAG_ACTIVE: self.active, + } + def to_json_option(self): + return { + 'value': self.id_type, + 'text': self.name_singular + } + diff --git a/business_objects/store/stock_item.py b/business_objects/store/stock_item.py index 65b5e41a..9db66e44 100644 --- a/business_objects/store/stock_item.py +++ b/business_objects/store/stock_item.py @@ -24,6 +24,8 @@ from datetime import datetime class Stock_Item(db.Model, Store_Base): ATTR_ID_CURRENCY_COST: ClassVar[str] = f'{Store_Base.ATTR_ID_CURRENCY}-cost' + NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_CURRENCY + NAME_ATTR_OPTION_TEXT = Store_Base.FLAG_NAME FLAG_DATE_CONSUMED: ClassVar[str] = 'date-consumed' FLAG_DATE_EXPIRATION: ClassVar[str] = 'date-expiration' FLAG_DATE_PURCHASED: ClassVar[str] = 'date-purchased' @@ -175,6 +177,7 @@ class Stock_Item(db.Model, Store_Base): ''' 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}, @@ -183,8 +186,8 @@ class Stock_Item(db.Model, Store_Base): self.FLAG_CAN_EDIT: {self.can_edit}, self.FLAG_CAN_ADMIN: {self.can_admin}, self.FLAG_HAS_VARIATIONS: {self.has_variations}, - self.FLAG_PERMUTATIONS: {self.permutations}, - self.FLAG_VARIATION_TREES: {self.variation_trees}, + self.FLAG_PRODUCT_PERMUTATION: {self.permutations}, + self.FLAG_PRODUCT_VARIATION_TREES: {self.variation_trees}, } def has_permutations(self): return len(self.permutations) > 0 diff --git a/business_objects/store/store_base.py b/business_objects/store/store_base.py index 67a40d03..904c3308 100644 --- a/business_objects/store/store_base.py +++ b/business_objects/store/store_base.py @@ -12,6 +12,7 @@ Abstract business object for store objects # internal # from helpers.DEPRECATED.helper_abc import Interface_ABC +from business_objects.base import Base from extensions import db import lib.argument_validation as av # external @@ -55,40 +56,33 @@ class I_Store_Base(): "" """ -class Store_Base(): - ATTR_ID_ACCESS_LEVEL: ClassVar[str] = 'id_access_level' - ATTR_ID_CURRENCY: ClassVar[str] = 'id_currency' +class Store_Base(Base): # ATTR_ID_CURRENCY_COST: ClassVar[str] = 'id_currency_cost' - ATTR_ID_DELIVERY_REGION: ClassVar[str] = 'id_delivery_region' 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_PRODUCT: ClassVar[str] = 'id_product' ATTR_ID_PRODUCT_CATEGORY: ClassVar[str] = 'id_category' + ATTR_ID_PRODUCT_IMAGE: ClassVar[str] = 'id_image' ATTR_ID_PRODUCT_PERMUTATION: ClassVar[str] = 'id_permutation' ATTR_ID_PRODUCT_PRICE: ClassVar[str] = 'id_price' ATTR_ID_PRODUCT_VARIATION: ClassVar[str] = 'id_variation' - ATTR_ID_PRODUCT_VARIATION_TYPE: ClassVar[str] = 'id_variation_type' + ATTR_ID_PRODUCT_VARIATION_TYPE: ClassVar[str] = 'id_type' ATTR_ID_STOCK_ITEM: ClassVar[str] = 'id_stock_item' - FLAG_ACCESS_LEVEL_REQUIRED: ClassVar[str] = 'access_level_required' - FLAG_ACTIVE: ClassVar[str] = 'active' - 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_DESCRIPTION: ClassVar[str] = 'description' - FLAG_DISPLAY_ORDER: ClassVar[str] = 'display_order' + FLAG_CURRENCY: ClassVar[str] = 'currency' + FLAG_DELIVERY_OPTION: ClassVar[str] = 'delivery_option' FLAG_HAS_VARIATIONS: ClassVar[str] = 'has_variations' - FLAG_IS_NOT_EMPTY: ClassVar[str] = 'is_not_empty' - FLAG_KEY_PRIMARY: ClassVar[str] = 'key_primary' - FLAG_NAME: ClassVar[str] = 'name' - FLAG_PERMUTATIONS: ClassVar[str] = 'permutations' - FLAG_PRIORITY: ClassVar[str] = 'priority' - FLAG_ROWS: ClassVar[str] = 'rows' - FLAG_VARIATION_TREES: ClassVar[str] = 'variation_trees' - @classmethod - def output_bool(cls, value): - return av.input_bool(value, f'{cls.__name__} bool attribute', f'{cls.__name__}.output_bool') - @staticmethod - def convert_list_objects_to_list_options(objects): - return [object.to_json_option() for object in objects] + FLAG_IS_OUT_OF_STOCK: ClassVar[str] = 'is_out_of_stock' + FLAG_PRODUCT: ClassVar[str] = 'product' + FLAG_PRODUCT_CATEGORY: ClassVar[str] = 'product_category' + FLAG_PRODUCT_IMAGE: ClassVar[str] = 'product_image' + FLAG_PRODUCT_PERMUTATION: ClassVar[str] = 'product_permutation' + FLAG_PRODUCT_PRICE: ClassVar[str] = 'product_price' + FLAG_PRODUCT_VARIATION: ClassVar[str] = 'product_variation' + FLAG_PRODUCT_VARIATIONS: ClassVar[str] = f'{FLAG_PRODUCT_VARIATION}s' + FLAG_PRODUCT_VARIATION_TYPE: ClassVar[str] = 'product_variation_type' + FLAG_QUANTITY_MIN: ClassVar[str] = 'quantity_min' + FLAG_QUANTITY_MAX: ClassVar[str] = 'quantity_max' + FLAG_TEXT: ClassVar[str] = 'text' + FLAG_VALUE_TEXT: ClassVar[str] = 'value_text' + \ No newline at end of file diff --git a/business_objects/unit_measurement.py b/business_objects/unit_measurement.py new file mode 100644 index 00000000..ffa91077 --- /dev/null +++ b/business_objects/unit_measurement.py @@ -0,0 +1,160 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Business Objects +Feature: Unit of Measurement Business Object +""" + +# internal +from business_objects.base import Base +from business_objects.db_base import SQLAlchemy_ABC, Get_Many_Parameters_Base +from extensions import db +# from forms.forms import Form_Filters_User +import lib.argument_validation as av +# external +from dataclasses import dataclass +from typing import ClassVar + + +class Unit_Measurement(SQLAlchemy_ABC, Base): + ATTR_ID_UNIT_MEASUREMENT: ClassVar[str] = 'id_unit_measurement' + FLAG_IS_BASE_UNIT: ClassVar[str] = 'is_base_unit' + FLAG_IS_UNIT_OF_DISTANCE: ClassVar[str] = 'is_unit_of_distance' + FLAG_IS_UNIT_OF_MASS: ClassVar[str] = 'is_unit_of_mass' + FLAG_IS_UNIT_OF_TIME: ClassVar[str] = 'is_unit_of_time' + FLAG_IS_UNIT_OF_VOLUME: ClassVar[str] = 'is_unit_of_volume' + FLAG_NAME_PLURAL: ClassVar[str] = 'name_plural' + FLAG_NAME_SINGULAR: ClassVar[str] = 'name_singular' + FLAG_SYMBOL: ClassVar[str] = 'symbol' + FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX: ClassVar[str] = 'symbol_is_suffix_not_prefix' + # KEY_UNIT_MEASUREMENT: ClassVar[str] = 'unit_of_measurement' + NAME_ATTR_OPTION_VALUE: ClassVar[str] = ATTR_ID_UNIT_MEASUREMENT + NAME_ATTR_OPTION_TEXT: ClassVar[str] = FLAG_NAME_SINGULAR + + id_unit_measurement = db.Column(db.Integer, primary_key=True) + name_singular = db.Column(db.String(255)) + name_plural = db.Column(db.String(256)) + symbol = db.Column(db.String(50)) + symbol_is_suffix_not_prefix = db.Column(db.Boolean) + is_base_unit = db.Column(db.Boolean) + is_unit_of_distance = db.Column(db.Boolean) + is_unit_of_mass = db.Column(db.Boolean) + is_unit_of_time = db.Column(db.Boolean) + is_unit_of_volume = db.Column(db.Boolean) + active = db.Column(db.Boolean) + + def from_DB_unit_measurement(query_row): + _m = 'Unit_Measurement.from_DB_unit_measurement' + unit = Unit_Measurement() + unit.id_unit_measurement = query_row[0] + unit.name_singular = query_row[1] + unit.name_plural = query_row[2] + unit.symbol = query_row[3] + unit.symbol_is_suffix_not_prefix = av.input_bool(query_row[4], 'symbol_is_suffix_not_prefix', _m) + unit.is_base_unit = av.input_bool(query_row[5], 'is_base_unit', _m) + unit.is_unit_of_distance = av.input_bool(query_row[6], 'is_unit_of_distance', _m) + unit.is_unit_of_mass = av.input_bool(query_row[7], 'is_unit_of_mass', _m) + unit.is_unit_of_time = av.input_bool(query_row[8], 'is_unit_of_time', _m) + unit.is_unit_of_volume = av.input_bool(query_row[9], 'is_unit_of_volume', _m) + unit.active = av.input_bool(query_row[10], 'active', _m) + return unit + + def to_json(self): + return { + **self.get_shared_json_attributes(self), + self.ATTR_ID_UNIT_MEASUREMENT: self.id_unit_measurement, + self.FLAG_NAME_SINGULAR: self.name_singular, + self.FLAG_NAME_PLURAL: self.name_plural, + self.FLAG_SYMBOL: self.symbol, + self.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX: self.symbol_is_suffix_not_prefix, + self.FLAG_IS_BASE_UNIT: self.is_base_unit, + self.FLAG_IS_UNIT_OF_DISTANCE: self.is_unit_of_distance, + self.FLAG_IS_UNIT_OF_MASS: self.is_unit_of_mass, + self.FLAG_IS_UNIT_OF_TIME: self.is_unit_of_time, + self.FLAG_IS_UNIT_OF_VOLUME: self.is_unit_of_volume, + self.FLAG_ACTIVE: self.active, + } + @classmethod + def from_json(cls, json): + print(f' Unit_Measurement.from_json: {json}') + unit = cls() + unit.id_unit_measurement = json[cls.ATTR_ID_UNIT_MEASUREMENT] + unit.name_singular = json[cls.FLAG_NAME_SINGULAR] + unit.name_plural = json[cls.FLAG_NAME_PLURAL] + unit.symbol = json[cls.FLAG_SYMBOL] + unit.symbol_is_suffix_not_prefix = json[cls.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX] + unit.is_base_unit = json[cls.FLAG_IS_BASE_UNIT] + unit.is_unit_of_distance = json[cls.FLAG_IS_UNIT_OF_DISTANCE] + unit.is_unit_of_mass = json[cls.FLAG_IS_UNIT_OF_MASS] + unit.is_unit_of_time = json[cls.FLAG_IS_UNIT_OF_TIME] + unit.is_unit_of_volume = json[cls.FLAG_IS_UNIT_OF_VOLUME] + unit.active = json[cls.FLAG_ACTIVE] + return unit + + def __repr__(self): + return f''' + id_unit_of_measurement: {self.id_unit_measurement}, + name_singular: {self.name_singular}, + name_plural: {self.name_plural}, + symbol: {self.symbol}, + symbol_is_suffix_not_prefix: {self.symbol_is_suffix_not_prefix}, + is_base_unit: {self.is_base_unit}, + is_unit_of_distance: {self.is_unit_of_distance}, + is_unit_of_mass: {self.is_unit_of_mass}, + is_unit_of_time: {self.is_unit_of_time}, + is_unit_of_volume: {self.is_unit_of_volume}, + active: {self.active} + ''' + +""" +@dataclass +class Filters_Unit_Measurement(): + active_only: bool = False + + def to_json(self): + return { + **self.get_shared_json_attributes(self), + 'a_get_all_user': self.get_all_user, + 'a_get_inactive_user': self.get_inactive_user, + 'a_get_first_user_only': self.get_first_user_only, + 'a_ids_user': self.ids_user, + 'a_ids_user_auth0': self.ids_user_auth0, + } + + @staticmethod + def from_form(form): + av.val_instance(form, 'form', 'User_Filters.from_form', Form_Filters_User) + get_inactive = av.input_bool(form.active.data, "active", "User_Filters.from_form") + id_user = form.id_user.data + return User_Filters( + get_all_user = (id_user is None), + get_inactive_user = get_inactive, + get_first_user_only = False, + ids_user = id_user, + ids_user_auth0 = '', + ) + + @staticmethod + def from_user(user): + av.val_instance(user, 'user', 'User_Filters.from_user', User) + return User_Filters( + get_all_user = (user.id_user is None and user.id_user_auth0 is None), + get_inactive_user = False, + get_first_user_only = False, + ids_user = user.id_user, + ids_user_auth0 = user.id_user_auth0, + ) + + @staticmethod + def get_default(datastore_store): + user = datastore_store.get_login_user() + return User_Filters( + get_all_user = False, + get_inactive_user = False, + get_first_user_only = False, + ids_user = user.id_user, + ids_user_auth0 = '', + ) +""" \ No newline at end of file diff --git a/business_objects/user.py b/business_objects/user.py index a55331ca..9b15cbe5 100644 --- a/business_objects/user.py +++ b/business_objects/user.py @@ -8,6 +8,7 @@ Feature: User Business Object """ # internal +from business_objects.base import Base import lib.argument_validation as av from forms.forms import Form_Filters_User from extensions import db @@ -16,8 +17,10 @@ from dataclasses import dataclass from typing import ClassVar -class User(db.Model): +class User(db.Model, Base): KEY_USER: ClassVar[str] = 'authorisedUser' # 'user' already used + NAME_ATTR_OPTION_VALUE: ClassVar[str] = Base.ATTR_ID_USER + NAME_ATTR_OPTION_TEXT: ClassVar[str] = 'email' id_user = db.Column(db.Integer, primary_key=True) id_user_auth0 = db.Column(db.String(255)) @@ -200,8 +203,9 @@ class User_Filters(): ids_access_level: str ids_product: str - def to_json(self): + def to_json(self): return { + **self.get_shared_json_attributes(self), 'a_ids_user': self.ids_user, 'a_get_inactive_users': self.get_inactive_users, 'a_ids_permission': self.ids_permission, diff --git a/routing/__init__.py b/controllers/__init__.py similarity index 100% rename from routing/__init__.py rename to controllers/__init__.py diff --git a/routing/__pycache__/__init__.cpython-312.pyc b/controllers/__pycache__/__init__.cpython-312.pyc similarity index 100% rename from routing/__pycache__/__init__.cpython-312.pyc rename to controllers/__pycache__/__init__.cpython-312.pyc diff --git a/controllers/__pycache__/core.cpython-312.pyc b/controllers/__pycache__/core.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5c685fa271d1ff75ea584e3ae22808ee6727f580 GIT binary patch literal 5629 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 literal 0 HcmV?d00001 diff --git a/routing/__pycache__/legal.cpython-312.pyc b/controllers/__pycache__/legal.cpython-312.pyc similarity index 100% rename from routing/__pycache__/legal.cpython-312.pyc rename to controllers/__pycache__/legal.cpython-312.pyc diff --git a/routing/__pycache__/store.cpython-312.pyc b/controllers/__pycache__/store.cpython-312.pyc similarity index 100% rename from routing/__pycache__/store.cpython-312.pyc rename to controllers/__pycache__/store.cpython-312.pyc diff --git a/routing/__pycache__/store_product_category.cpython-312.pyc b/controllers/__pycache__/store_product_category.cpython-312.pyc similarity index 100% rename from routing/__pycache__/store_product_category.cpython-312.pyc rename to controllers/__pycache__/store_product_category.cpython-312.pyc diff --git a/routing/__pycache__/store_product_permutation.cpython-312.pyc b/controllers/__pycache__/store_product_permutation.cpython-312.pyc similarity index 100% rename from routing/__pycache__/store_product_permutation.cpython-312.pyc rename to controllers/__pycache__/store_product_permutation.cpython-312.pyc diff --git a/routing/__pycache__/store_stock_item.cpython-312.pyc b/controllers/__pycache__/store_stock_item.cpython-312.pyc similarity index 100% rename from routing/__pycache__/store_stock_item.cpython-312.pyc rename to controllers/__pycache__/store_stock_item.cpython-312.pyc diff --git a/routing/__pycache__/store_supplier.cpython-312.pyc b/controllers/__pycache__/store_supplier.cpython-312.pyc similarity index 100% rename from routing/__pycache__/store_supplier.cpython-312.pyc rename to controllers/__pycache__/store_supplier.cpython-312.pyc diff --git a/routing/__pycache__/user.cpython-312.pyc b/controllers/__pycache__/user.cpython-312.pyc similarity index 100% rename from routing/__pycache__/user.cpython-312.pyc rename to controllers/__pycache__/user.cpython-312.pyc diff --git a/routing/core.py b/controllers/core.py similarity index 93% rename from routing/core.py rename to controllers/core.py index d8a15b78..a881a683 100644 --- a/routing/core.py +++ b/controllers/core.py @@ -12,6 +12,7 @@ Initializes the Flask application, sets the configuration based on the environme # IMPORTS # internal +from datastores.datastore_base import DataStore_Base from forms.forms import Form_Contact from models.model_view_admin_home import Model_View_Admin_Home from models.model_view_contact import Model_View_Contact @@ -44,7 +45,10 @@ def home(): @routes_core.route(Model_View_Contact.HASH_PAGE_CONTACT, methods=['GET']) def contact(): try: + user = DataStore_Base.get_user_session() form = Form_Contact() + form.email.data = user.email + form.name.data = user.firstname + (' ' if user.firstname and user.surname else '') + user.surname model = Model_View_Contact(form) html_body = render_template('pages/core/_contact.html', model = model) except Exception as e: diff --git a/routing/legal.py b/controllers/legal.py similarity index 100% rename from routing/legal.py rename to controllers/legal.py diff --git a/routing/store/__init__.py b/controllers/store/__init__.py similarity index 100% rename from routing/store/__init__.py rename to controllers/store/__init__.py diff --git a/routing/store/__pycache__/__init__.cpython-312.pyc b/controllers/store/__pycache__/__init__.cpython-312.pyc similarity index 100% rename from routing/store/__pycache__/__init__.cpython-312.pyc rename to controllers/store/__pycache__/__init__.cpython-312.pyc diff --git a/routing/store/__pycache__/product.cpython-312.pyc b/controllers/store/__pycache__/product.cpython-312.pyc similarity index 100% rename from routing/store/__pycache__/product.cpython-312.pyc rename to controllers/store/__pycache__/product.cpython-312.pyc diff --git a/routing/store/__pycache__/product_category.cpython-312.pyc b/controllers/store/__pycache__/product_category.cpython-312.pyc similarity index 75% rename from routing/store/__pycache__/product_category.cpython-312.pyc rename to controllers/store/__pycache__/product_category.cpython-312.pyc index 4d83af2c8a849c28cccec77ad3f0d04f9f65a33a..487be009aab206363ef8ef99c3383c2d1d6173b8 100644 GIT binary patch delta 236 zcmeyRH&LJaG%qg~0}%Kf`?!&NJ{x1n`smTfg{EP~d*K^)u6r9}06~XT2=;;$0TPxsU}a>KnCv0Am_r4qOq0FHbn*|u jNJi()K|;(djAoO=#MBs_C)bKeF-A7&-6`tk)pCn4MMcY#B)lV!jv1v!P)7p|9Q-8J_TT(>HsTWkY6n7*ov&*Gt zmzJf_K@L6WkN~;GKu{ouUV`M%OMwI^kY6AM+5=gsV7icy0?nnDLXJ};a4vl_O zbqEgCDL6S=b}BB_Ew~x&Qaq|x@G{!1_*B2(XS7ENs6ipfXs;4dn}jAt`;=z2MF=z6 zue7RdLYvwyw5$7sed>N;zuF;ms1YHe9uN+w2Ze*`A>okPDRin`LKou+C{L(|g~RF* z;Rq`S6<+NYy44<`hm}K0ui7W{F}g{4QavghWpp$2>lgaf0bxLm3Q-O@5bl&(@Kf(P zDr**=_9Ogs=7yz;dX9q`p$Fb zV^~iUIY;Zx1+HXeLry938rFGZ8S@iLN`Hw@<#LLgW^BiJ9UGOlw3c0zm-3_{ZXu;( zi3hoq4QFr3M9Zo;YaHWKupS97%2_INMdJw@m>)R7T27=Epd1CZl))36l`!F9nK>l| zv*TAlO-!Pm1NAJ*FoYo+3f5zRf6|SLI?R>{Surrt#p)u>_9`LTRvYEa&W3&s%`Mk7 z2`l1t8Lx;VuomD5+p3rzp{}p7&KkBsT;MWRa+rv)FO$)r>1K*FTPh0_tp%FijIL$n z#Z}Ww@Xb8d4YQ-6i>Mm}Hq~s`K{w(e(Ns~A!B${jS4|(mm4fNb6GdFqi0Rd_PR+>l zk0^PZ175=nrt<{E8X{~YXv`rkm~Jfv_6dc+&Aet{F{k8p(+@&$HVuk^mAa>>1p^Ua z#5f@ui8@U;>u>s?Yc54}Z2DLx-qg+N&cckr=EPjZ=0wnfWpk$U()cV$^r{%nhNP#h zvqp0_{GITB;A2o}Kw9}E?%gWQAwM!`ANFM|aJ4ERH#}A$?{H{Myl6Y6R1O_pFJB=AM5UNfRgam9LWFOk( zFzJPQoh}T}?BUAjx#XM?NnNc#O!maB@sb=P4xUNjRZPB&Dig*vad%o=+)! z!pKXq#t)tx985AG6#+<-V6aKR8G~qwLM5{0CHF9`SZIK=La3%H>~= zZMqKbI9%>CTam$XWVjR={^N@uCO=4SM1HXz`o@Rcf%R*5kKH|73=C|#qFbSpzwg=z zU3hhTD|o2bIeKqyGngp465o9jM4|m(BL~RwHND}z%e|qmtDC+qkh&2${d(y89XGT+ z)FUwP>%H*~^l^uOgmZp;7et$I~{>kI(UdHAX$R@gAzzT2#T2>9Xj0o;gydEy~iJ zedYiNywwhXFmcEE6XyK*dUY0@yLFg$Fko@M;!IG0f!qcxuF19L2|y5D&fWrtFU11y zaAW|c{jhr^1r9r9q`)1gF&tcpUs&bqr!W?Xwh}+|G{Z~S5UY+$q#O)87@&|RX@@o@ z8a%nEWko%|0D%h$K?6e*GdOWIeo0Ks#%JdeW{4Fg;#aQD&5Tz|*Txfx_@!~vgQ@e; ztF?)_(NSnHeb0~I5Xa)PakB|x6TActQB-7bpDDbiNo*7bRRwFBYF$ zs>}E{mGS+K6WAZ>bXVVsKQ-EmKJmo6Ap5k}KQ`$6^w`kYap!0K9MGQ~cSE{2#+?SO z|8Fp^?t(Maz#6`TP_7{+#h;opuXnUgGN53qRcn*F*LkeD{mdRXXXD)i?HCH~flIqj zFrZ+kH5cgzp+vzJcfxw#6? zOt-bZdT#Vu^q&6AW$mPubLh1Jmt9lt3KG`ajhffX^jWg&c>!f8QZ#&$NAg-hUcqTm z5FXZKfnV}jW887ucFJ$nLhr}7B??pxpUsviTs3?Jcjj0_6%;ckepqMOxP3>!Tb;Ce zGH>Pi33GmY`wtX6yKTMdtvs)In74x5=BImft_7fTl_tl5+jM2+oK9juMh`MiN2o3voLj|*wN~8L z)XX(;;>y+8@tFjn+N^lFXDBsDlT$P~O%rN=<^jevJu@{nH##d$kI!72121@GYSMJV z1!uU@E;&P`Jxi0H(d6eeVGhqr&QhBBI~om}Ee%UI zgEnbqh+PN3jl-Kkw&ELUJV|{cd=>W?Zkz+T1YOqPum9~4&ar!!b7cPSc4_2x>HO+O zWbJVrWpO-NoR`bDn7mmWC5@gkfc(vGG~X@U%@&)FZ~9_?k92N!T`YIqD8Vlx ztcSLO&Fh7YVAtE+UxM8~?v{(=a}DBme5mt@^_DL>`@cqb>|;=SJ_fzlJ7voV3R`9+*%u%)fo4$UjqT9^CYu+VUMM`!1Ax7v48My#2xL zd;VfV+<5NS#f6)jKJry$=w8=mx5slDbfnA_0*g$VFgkG`;jYSB(z!2&y2n{qyJ54C4ngM*nzUt5hc=o|?#ip-%dW=m#Oe->=9idTy$?w^Zs?+L5 zZ$*R#AB5h7$P<*yCyLpWibaterbRb<$us*d#}k*uX$aIImY7KfOCD@ zg}7;M8(rE)gWKrzHcD=z=r-#6)`hrv$G5;^rS}>ACE~wCv2Ao}8~yA{G+07|_dTfZ zc=7mD@r4^3y+RT3JC0{L*A9XA@18Q(U*h_U16RufH%kLIcOb&yMjVh8xKT%u>xY>- z#vJz@er}d~;H2~pqjx%XGi#**4Y*$B;*@y}WK@|)fw_$fQr=PE1#)L#H*2mmkYfX~ TabMm&Zf}K^P60?V5Bm8JK?cUW literal 0 HcmV?d00001 diff --git a/controllers/store/__pycache__/stock_item.cpython-312.pyc b/controllers/store/__pycache__/stock_item.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ecd682426449cce9b7be9b3e59d084a58209ac25 GIT binary patch literal 4943 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 WPenmEgVOJTG@v`d!$OcB$^QUy7!v^i literal 0 HcmV?d00001 diff --git a/routing/store/__pycache__/store.cpython-312.pyc b/controllers/store/__pycache__/store.cpython-312.pyc similarity index 100% rename from routing/store/__pycache__/store.cpython-312.pyc rename to controllers/store/__pycache__/store.cpython-312.pyc diff --git a/routing/store/__pycache__/supplier.cpython-312.pyc b/controllers/store/__pycache__/supplier.cpython-312.pyc similarity index 55% rename from routing/store/__pycache__/supplier.cpython-312.pyc rename to controllers/store/__pycache__/supplier.cpython-312.pyc index c4075eccfb0e083a3b6c3dbf4b1bef6d6e160e21..1afe4c851cf6f942b77de1e1f98fa665cf0a8dfb 100644 GIT binary patch delta 634 zcmXAly>AmS7{<>b3CZPr`D_x}hLn$fT+$>YEmfe9Ze?IV0)d1FP6;t0<#q1lOP~_` z1q_uUZw#=o!4`zX!aq>4FrgD8BO4P{2W(@>uYb?;yp}(HR6kekV~kBhj@!3>Kly9T z>@ph6)_0#FV~B<^NHL38n&W_(O>E6)A3 z194nvvC6Y4`;(B@s^~A&U%jkV+`~%N~qip~H delta 701 zcmXw$yKmD#9LIfalIC^JyLq)FKto={Nnb>~J9PztRH{>jl`2=_a_5+{!$W0YK|*Zd zqz(-52QWrrV`ZrrU_uuB2W)JexI4ho{qFPm{!X@k_Q%TiihcrNR1;V5)sKS=oazN| zFs)yGNMk4lv>_M|`-j*}8Cqb0?VOusZow1FB*b<(6Q)S_+FR-PaiX$N(vfehtI(xpArQ=B5JbPcU3 zPK$HvXq|4L4Z4Xofi|b%`Y?kpeVCKeX&UO|{^28zKo?w|y$0VvYu<<3V@A!p6UQMI zW`05GwnaS5T=O<&bm9#>Yi!TR{JUT#C+^}04&AZs2OVbF9)o;2;)b#!XEA;p>4FUZ z9I1g8{}t(g5idn=)!2CAS@wfH*Bdju=l*+?;XL!h|AlSM-b7CTxWezppRX|aH~d99 z9%AAeYBL{O_=&kca50O?W}d%?`2`l2Toqj8Js1u_sSTk8z5`PsU20qDOPB=-{uVY% zNg1X`m^flW%EUO}gg* diff --git a/routing/store/product.py b/controllers/store/product.py similarity index 100% rename from routing/store/product.py rename to controllers/store/product.py diff --git a/routing/store/product_category.py b/controllers/store/product_category.py similarity index 96% rename from routing/store/product_category.py rename to controllers/store/product_category.py index 0c3d5618..4eb4bf6b 100644 --- a/routing/store/product_category.py +++ b/controllers/store/product_category.py @@ -64,7 +64,7 @@ def filter_category(): form_filters = Filters_Product_Category.from_json(data) if not form_filters.validate_on_submit(): return jsonify({ - Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_SUCCESS, + Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_FAILURE, Model_View_Store_Product_Category.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}' }) # ToDo: manually validate category, product @@ -76,7 +76,7 @@ def filter_category(): }) except Exception as e: return jsonify({ - Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_SUCCESS, + Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_FAILURE, Model_View_Store_Product_Category.FLAG_MESSAGE: f'Bad data received by controller.\n{e}' }) @@ -87,7 +87,7 @@ def save_category(): form_filters = Filters_Product_Category.from_json(data[Model_View_Store_Product_Category.FLAG_FORM_FILTERS]) if not form_filters.validate_on_submit(): return jsonify({ - Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_SUCCESS, + Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_FAILURE, Model_View_Store_Product_Category.FLAG_MESSAGE: f'Filters form invalid.\n{form_filters.errors}' }) # filters_form = Filters_Product_Category.from_form(form_filters) @@ -95,7 +95,7 @@ def save_category(): categories = data[Model_View_Store_Product_Category.FLAG_PRODUCT_CATEGORY] if len(categories) == 0: return jsonify({ - Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_SUCCESS, + Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_FAILURE, Model_View_Store_Product_Category.FLAG_MESSAGE: f'No categories.' }) objsCategory = [] @@ -113,7 +113,7 @@ def save_category(): }) except Exception as e: return jsonify({ - Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_SUCCESS, + Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_FAILURE, Model_View_Store_Product_Category.FLAG_MESSAGE: f'Bad data received by controller.\n{e}' }) \ No newline at end of file diff --git a/controllers/store/product_permutation.py b/controllers/store/product_permutation.py new file mode 100644 index 00000000..8a10e0d5 --- /dev/null +++ b/controllers/store/product_permutation.py @@ -0,0 +1,159 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: App Routing +Feature: Store Product Permutation Routes + +Description: +Initializes the Flask application, sets the configuration based on the environment, and defines two routes (/ and /about) that render templates with the specified titles. +""" + + +# internal +from business_objects.store.product import Filters_Product, Product_Permutation +from forms.store.product_permutation import Filters_Product_Permutation +from models.model_view_base import Model_View_Base +from models.model_view_store import Model_View_Store +from models.model_view_store_product_permutation import Model_View_Store_Product_Permutation +from helpers.helper_app import Helper_App +import lib.argument_validation as av +# external +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 + + +routes_store_product_permutation = Blueprint('routes_store_product_permutation', __name__) +""" + +@routes_store_product_permutation.route('/store/permutations', methods=['GET']) +def permutation(): + filters = Filters_Product.get_default() + model = Model_View_Store_Product_Permutation(filters_product=filters) + return render_template('pages/store/_product_permutations.html', model = model) + +@routes_store_product_permutation.route('/store/permutation_filter', methods=['POST']) +def permutation_filter(): + data = Helper_App.get_request_data(request) + form_filters = None + try: + form_filters = get_Form_Filters_Permutation(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_Product.from_form(form_filters) + model = Model_View_Store_Product_Permutation(filters_product=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_Form_Filters_Permutation(data_request): + data_form = data_request[Model_View_Store_Product_Permutation.KEY_FORM] + form_filters = Filters_Product_Permutation(**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_product_permutation.route('/store/permutation_save', methods=['POST']) +def permutation_save(): + data = Helper_App.get_request_data(request) + form_filters = None + try: + form_filters = get_Form_Filters_Permutation(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}'}) + + permutations = data[Model_View_Store_Product_Permutation.FLAG_PRODUCT_PERMUTATION] + if len(permutations) == 0: + return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_FAILURE, Model_View_Base.FLAG_MESSAGE: f'No permutations.'}) + objsPermutation = [] + for permutation in permutations: + objsPermutation.append(Product_Permutation.from_json(permutation)) + + # ToDo: manually validate category, product + filters_form = Filters_Product.from_form(form_filters) + model_save = Model_View_Store_Product_Permutation(filters_product=filters_form) + model_save.save_permutations(data.comment, objsPermutation) + + model_return = Model_View_Store_Product_Permutation(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_product_permutation.route(Model_View_Store_Product_Permutation.HASH_PAGE_STORE_PRODUCT_PERMUTATIONS, methods=['GET']) +def permutations(): + print('permutations') + try: + form_filters = Filters_Product_Permutation.from_json(request.args) + except Exception as e: + print(f'Error: {e}') + form_filters = Filters_Product_Permutation() + print(f'form_filters={form_filters}') + model = Model_View_Store_Product_Permutation(form_filters) + 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']) +def filter_permutation(): + data = Helper_App.get_request_data(request) + try: + form_filters = Filters_Product_Permutation.from_json(data) + if not form_filters.validate_on_submit(): + return jsonify({ + Model_View_Store_Product_Permutation.FLAG_STATUS: Model_View_Store_Product_Permutation.FLAG_FAILURE, + Model_View_Store_Product_Permutation.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}' + }) + model = Model_View_Store_Product_Permutation(form_filters = form_filters) + 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() + }) + except Exception as e: + return jsonify({ + Model_View_Store_Product_Permutation.FLAG_STATUS: Model_View_Store_Product_Permutation.FLAG_FAILURE, + Model_View_Store_Product_Permutation.FLAG_MESSAGE: f'Bad data received by controller.\n{e}' + }) + +@routes_store_product_permutation.route(Model_View_Store_Product_Permutation.HASH_SAVE_STORE_PRODUCT_PERMUTATION, methods=['POST']) +def save_permutation(): + data = Helper_App.get_request_data(request) + try: + form_filters = Filters_Product_Permutation.from_json(data[Model_View_Store_Product_Permutation.FLAG_FORM_FILTERS]) + if not form_filters.validate_on_submit(): + return jsonify({ + Model_View_Store_Product_Permutation.FLAG_STATUS: Model_View_Store_Product_Permutation.FLAG_FAILURE, + Model_View_Store_Product_Permutation.FLAG_MESSAGE: f'Filters form invalid.\n{form_filters.errors}' + }) + # filters_form = Filters_Product_Permutation.from_form(form_filters) + print(f'form_filters: {form_filters}') + + permutations = data[Model_View_Store_Product_Permutation.FLAG_PRODUCT_PERMUTATION] + if len(permutations) == 0: + return jsonify({ + Model_View_Store_Product_Permutation.FLAG_STATUS: Model_View_Store_Product_Permutation.FLAG_FAILURE, + Model_View_Store_Product_Permutation.FLAG_MESSAGE: f'No permutations.' + }) + objsPermutation = [] + for permutation in permutations: + objsPermutation.append(Product_Permutation.from_json(permutation)) + # model_save = Model_View_Store_Product_Permutation() # filters_product=filters_form) + print(f'objsPermutation={objsPermutation}') + Model_View_Store_Product_Permutation.save_permutations(data.get('comment', 'No comment'), objsPermutation) + + model_return = Model_View_Store_Product_Permutation(form_filters=form_filters) + print('nips') + return jsonify({ + Model_View_Store_Product_Permutation.FLAG_STATUS: Model_View_Store_Product_Permutation.FLAG_SUCCESS, + Model_View_Store_Product_Permutation.KEY_DATA: model_return.category_list.to_json() + }) + except Exception as e: + return jsonify({ + Model_View_Store_Product_Permutation.FLAG_STATUS: Model_View_Store_Product_Permutation.FLAG_FAILURE, + Model_View_Store_Product_Permutation.FLAG_MESSAGE: f'Bad data received by controller.\n{e}' + }) + \ No newline at end of file diff --git a/routing/store/stock_item.py b/controllers/store/stock_item.py similarity index 98% rename from routing/store/stock_item.py rename to controllers/store/stock_item.py index 4941b161..8f545be7 100644 --- a/routing/store/stock_item.py +++ b/controllers/store/stock_item.py @@ -13,7 +13,7 @@ Initializes the Flask application, sets the configuration based on the environme # internal from business_objects.store.product import Product, Filters_Product, Product_Permutation from business_objects.store.stock_item import Stock_Item, Stock_Item_Filters -from forms.forms import Form_Supplier, Form_Filters_Permutation, Form_Filters_Stock_Item +from forms.forms import Form_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 diff --git a/routing/store/store.py b/controllers/store/store.py similarity index 100% rename from routing/store/store.py rename to controllers/store/store.py diff --git a/routing/store/supplier.py b/controllers/store/supplier.py similarity index 97% rename from routing/store/supplier.py rename to controllers/store/supplier.py index 4c4e9500..44e42841 100644 --- a/routing/store/supplier.py +++ b/controllers/store/supplier.py @@ -14,7 +14,7 @@ Initializes the Flask application, sets the configuration based on the environme # internal from business_objects.store.product import Product, Filters_Product, Product_Permutation from business_objects.store.stock_item import Stock_Item, Stock_Item_Filters -from forms.forms import Form_Supplier, Form_Filters_Permutation, Form_Filters_Stock_Item +from forms.forms import Form_Supplier, Form_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 diff --git a/routing/user.py b/controllers/user.py similarity index 100% rename from routing/user.py rename to controllers/user.py diff --git a/datastores/__pycache__/datastore_base.cpython-312.pyc b/datastores/__pycache__/datastore_base.cpython-312.pyc index 60f70209102a3a78c3c4daad116f05f7ce5ffdd2..712b97feed8f4da33322448e2bb5d3c08b4df78c 100644 GIT binary patch delta 4023 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 delta 2888 zcmZuzYit}>6~1?NcXqvR@2=nL?D!RXV`sf_o_6fC@dM<%A8ksfgkdr>S#L74>)shB zU2Bbl2x=Ntt=$VDB|-!ViAWLrs0I8%YT6=%1V0?n&}fuk{vl9RIZYx0KY)8?*J(&I zyZg<#-#Pc3`#fiVA-=aa{D)A;kJ$6OZ{0b0Uswz`as|BDvu?Y=i#$duR^7VS@QFU7 zMyzq#9^G#Q#DEbLgHD^*Lq=E(JF-__oZmffw1_Q6QcN1HVyi=k^mRr`OgVB`7mPNs z&1e_fopwa;FgnFfqf6{E){E;ME~b*vv*yqSGeWQ^PGmaeB z`;Dxab!1N8ByLiVW0lhf!~r(;gudC>B5pCZid&6s;x@;qPTy|q5O)}Z;-J&6*N2Rq z;!a0y(1(p-aTp^GeHE#V=aJf^?YQoO^+8A+DRJp$+Jo%~X9ssHie{S9KJARA)3>;W zdCulXW%IOV*@4PinzS?{&DqU|NKu_pENM)(v|N#tq_JYblJf9w(W(d&= zN{PvyNkh(QOo)tYdj5>YIvcKvULnBp92_Wkj7*;dzqMlK>BG*U<=OCLxDkNeKBww*U*b~ z$))*V9S+2qiSwLF&<{d!dM@avzX`pI({xijUQgJD6bqgR~9>}Fmw>9@nLH#))g zv#w4kCoHL9P1+R^!rj0h1PB5pMLO{WJs%MRdw_$nk-hZqk+JrECfdz8&61uSYStM? z=d+ckS!Z*KP4XQ2Yj|+!ji?IC@mcL+Z9TZHIZ29!bjmCi*cvXxgp4!fK2W*j>1jJO zIWE0$aPPzc>BXZHN61d5Aj1HI07LXIv7KzGo8#N?C3-mC&0Lq_-+vB*rg`E-h&+xU z$urhemI%-@2hhgA=9OaMWIjjIz+?gX>Hfq3{wY0|$R>eMs&|r!2zl8L+V__+{bQmt zT7#^|YSm?V=#BbR`fCWyxy!ihW*=^rSvR9OPuVk$-sTl9hZOF3j9Ktyp8hM47#pdY!fS9y#q9~=w%eyA>v%HHc-#TuhGMfaNSaBFfD zqY{gP*>8?Ni#m`Mt@=fsh-{tneG#baVqy5QkA-nP9fmsm$s7>|$Vhtzu=TD^~`n z#EBXGG`m}-Ml8u-8_vAaM@{=SO+c?nF!4CPZN7Nol%`m=8v@u^GvOQyYY*GA*PHv= zf5tfTE(3PhLg@?K9baf6w%}gazZ`D=*w?Yj`RTcq#JoGS4=>=`jj5~nYTMO4Kj~X; z>|gNQ-ah>2hLLN>F7rPQzZ<^Q*t6U)vfyTLCt7#ed)0IK?A57j*0qz%^;*_U zZZ9i1WzKRhNgcoEsGQn@XX&NXOZWx)S*r2yY>>!j1&xp*F^7ce=1f3ScxBdgd`L(q z$aWUl4xW*9Sa(Yn7yikt;_I%CjRgjDnxXq@Z?`$*#SqL4c9MfzZ;9i>C$Wzc;W z05;DK$s{*pXa!4B^NK~DNGcU=rKIUl(o7=Je+m=qB9F8^AN>{6n@S~Pga$8gOFwM; zI*yqI26kk{;hqRXaPr4`1IX#fl0 zI{@!6utSpM*eRN>OA<@V8OAzk`FR4Vk2o_0fR=fM!K3r&9`E+}9?)$YUhNNg68Bw* zkF9b{T1_Ip_8!;f=>o3y0Z5g!0v^)4$R+yeh5@{trg}GeorSksX|cBA&Iyqgf=SsDn6E7I}z#s(%k!s2>If>m)0vF6fAt&%x%U%yey}DM=i%vl&foG^H z`P(T5Ro7~@zLOA`S6mmN&XX_@>%etmb$}$oC<1AQ)B?olWUqkZ^i*#*p8%qczTevt zg_KMh02&$CJ>X(~ZH{NwN}kn-RhM;TN;68N z)vV@Rwu`*SnvkMR!eG^fF}}z7vHM{X;jR^QWCe|^pl{wqTkfLFT{P-^ xL0&<*KcU>+dX!y3`&Q7Qo9NIAD&0h-hdjc~^gn&6+B}E57G8dc;O!iv{{hrV4K)A& diff --git a/datastores/__pycache__/datastore_store_base.cpython-312.pyc b/datastores/__pycache__/datastore_store_base.cpython-312.pyc index d413426211f182ac3047409701108d6139a9bd9f..88a9ec72cddfd4df36e2f140fc78d9bcc30bdbce 100644 GIT binary patch delta 3674 zcmdT{|8G;*6~FiSyYuW9+wr%2acn0};*gM#1Og-^DbP04N>-pi^$>eC_RBZkbHaU2 zX)?QE71F#4m1TEp=@5b+r=hNuB5jkVNkyCX%cRX2RLQ*2^3(RK3skH~>vryQ;v~@i z0ef=JJMY}{?VkI&=idDH^rdmywsI&tZ?w@D3)VO``@B5G8Os!d{(+AKD!F)^mg1!d{W zw#A(~?@_wcZn0bEYm{ATkJzL0Zlzc3g|yvDpV$X)ud-X+BkocA#eQ|KxL4QlDf`s@ z;(m2N9MHf0%Ak5cJfQOdWk?+ohcM#MizpSmgi^I~>n#H-8A9Ulyqk;H(RcBu%X8d5 z95fbvFO!+nTrwk_OpvKWW@;uay)r*5(+>?@qjk@Y9hymJ5>siJ#BtGiIFU&l&&&{6 zI+)O8kZ`H9K!s6RnU#rj_@H!T{`k?C#;C)X#ZmgU@jvY{pR!*rT!=v;A&jlhz~({KBO%eVc1=kQ*7 zy*7xC(O=gdGxvcp5vfr3JpMgBQAY=NgCGeAt2{>FSUDe#mT`x3fVv!)GNg=CIA_RI zbWfw z07CL2BcqIbi=J<+Yd^+V$Q_ZhK;m|iV!RBb=#*3`b+!_pe%jbDMkd*?Za>X*?3*#j zIX3hh5RG+#aOELv;fk(j(k@SO*S4wrnVJ6z$VGJDxhK!91$*<(k{LN#Zk{h0xK?|? z+C={u{^_CnLa<;Bl5d8<={>*AKEw(O2=Qx>BSpz6*lkEr~NzmB_1HKG{vUV|;AQN*c<-*?4 zr=Vb2k6y;X2)OxL90(O0l=T<%3HEK7;J=vZZ-Foj^Z^F^U3q>J12Mor|!OJ+>(KmNT({e zk8|WF;D%fS5;tz{4?>yrXFxR8IT+l_NUwithTFWAgB|^*U>H!V?F4sh?$5#8y@6G4 z`-->yj<+LkUvqm`-LVyS?2fxNZ&?$3SM3EMTChgRZW@UOIj4~hMo-b(^$ql+=pRDR zn`~1kXU|%pKlMX@s>%exwf;=kvc4o#ZM2>opS4XlFxe4)Lk8`L&)T#6bZEnB^F0Xc z<$c@QnJH_(hOTp4tS!?KhGhD7sJ=eufOMQ$2c!bFkV?~rvvMl^o2dv8RQS4}Ec>h= zxi>7c&T`6rVKeCEAtQoF)zEq?!C%d}wzOSy*0nv)Ol!rVYr|2>a_%rJ?^xD#7+tAK zauX=Yo$>35$2YX6+gZIjD~T_0mxD$KovX@L!!*Hb&b=kBHS3=4pcfrA=9CTCoxnEp zneK|WUj3xVg`9ZzkL?X^Th^Ja9yc6^z!?5=RTt=op+Zwh@chRl)AUU1UCo3sa+G1w&U@AI@tj#GINrQ9p^-NLN zo`F`Zc}k#r(YsdBot7_1+lPz%R(B-B5}IRVfsuJezK1NZYdyeHm)Bz{cY#_u8>^-M z)?F4W+tW6Vey8=F#X#tW@V;;-5YIbGR#exJ7uFgh1#A79C;R{zZO3r_&_5#ms}XS} zA{I`6_fAAA@S*#B-6|hl;iHA7-FNvtYr{tie7F$lU5yN^LKUR?plYSZQ6t@&L2AOS_5nT2H$&&ON)2>ZF&B_*AM-~)5xNB(pi5^>yF`% z9jhZJR^YeeWd6uqzU@BmTjd*8_=c zO;hE}*9FtzwvoxqY8qwFIj4uYV zE;dl4@5ax%bJ!GnXh3FHiDPW(O#`*JhtB#;wd+#gO5HI2Ip;U|*JZ$!dUTo5)U+-G zuEguI5p3$!g^xJK>SvQ4J3dmhNK$GhDM`f!x~s##e5<{h<47(2O-EyI9VAtR8(cT#&rISB?5N^(+G=Lws9(Y{5{ zNL`)&#W09Tgpnvyu+Gk>5^1O|VZE3%GnpCoFI*w@g(EFYtZz(qB$emV2iz0upbGz) zDDn^~z$dG+#&$xYaeq6pW+^Z)hSLN d4c>V{%@# zSBr~rtxsJ4yni)ma;@r+mJ(B@&8frUu=y%!G0mPnbwnE#N42BkQSF#`%#87?$F&pU z3GJkK(ww)cr?fF~%(MgQxHc}1W5l5skQ}^?AzjIkT*k;PElMxubc1$TBlMEBfI0em>*xF$x{1Y> zS(M<*k8Bq)9->o@ZhW$Q-SKxG2dLQc2JS0=+`?mgjDFG@$LFcrcLQH7zv**eJVM|0 zPuRy;Ir`D^hyJG+JLn$+J%K8Z+~I8@wI!t9b$=vGR=p0_R5eI90-Wfr{lXFuaih2Rp?M~RayC5vp8Z8==B z)}Jjql`qhv4I^N{J8QF0tuiWhtXRDR&*eplR0r$l5X@jc@EI_qJ{cn@hMBu_WxEF zX4MJ%)fuggx6AwJR;<;%U#Pn%K%wpKM(O`kt&2s}s`b#jha;@JibByf$ALIzX!=Ox z0#W9fjC3ipC`;KDLX^d9PSGpDWl3LHT9)P&L((#fg@&(CX?xaF%RnEscbvY(D>s$w zijiBKkC9WX?pwls&av1nSADm!SVADv%uk*NI1lgwJ=+m!x&&q)z%{zr6lu?qLx7!XTjgN*KR-U(ecjjS^nyD(+|3Tz~A9Fz1^G6ZZb+&9U(4g zp_Sg3o184QIr2?R{So?d{8s};s6lSjje{LwL>k_F6g21E*Bon(d?#?w9(+x3AXxhI zzB5-2G=#0_zKedy?JLvhY2+;K=~cGB%2YsRitcIjT|Udrqbzqd06l5M8`1eb*e$tN z!8-R=$jUY>@kN1k@L?8xun`?aPrjc%bo=bGlbHj|>=lf`y=*D7_KkiIPSb0AyN`7U zv_qD|>{H@zpo9w=BTYLJKKlu_tkOk)aVS8)n&4LnT#E!QA2JRw!5|T;3Hb~VX90o? zD&7lvb3Trgq(v_2O0sU@bwUO5~$KV zN0v0m^Uc}DrB7Z0?^gh30h$3W1AHCe3P7!gz%pCNTWg^^K$v}GH49N_W*|7Tr~V30 z6n#ZCBwaBGfml=gI#@RWZU7V*=w1e25PvLImp`3KMCizoVaHR5`xd6TBj1_!N8XXv zrF;IqHU6<3wGH0$C)fC$*7i>k=bBi1?&D~3J36%$oqFGLFFL(;aYty|76!M3!Jl6J zNEol$SWwkTKN!5*9=daU)7!;_|IbgGQQJkV+u1I^^+nG+tch0oMsmQ;6oE(&eJ>ea zW!F0*34j5BAqMP=P&2x&DaOK*OkM{@&<*xmnypi>K;-uUehf~xB$*4cimFOd0+Tdj zb=IfojQPH`gND-{2FH60{_!Sy80*`PrRn9ND=lX^Tl_N%vNu;bFstXS^w&cjCla=v zI?Jr;Wy}H|aVcB3Nj?UPjIvy2`o!sqLz3jBtR&H2rc?Ga%u#8le@O+(v#CQIT}VgA z!oacX*H9L9xX=l-aOKb(d)Zed{WUeCW)~E#K%!>c0ivCHM*^!Ij3%7`F$i!j7v#($ zI~39dTsLrbqp-{_b^?7&dI3z0L2K1Yh1>66&IyhEMNySW@*6gVbJ9UbRSU-W5yxZe zlPJRRPtfTH=-Mtix{HQ((YamvlacV`160^T1x7xxBOC_k-$jx8$bBEV9-!nFNwc{FKt2A~=lr~q#LT?Z UqRs!A6C_ybE;7_jPL{C*00sLPE&u=k delta 68 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 diff --git a/datastores/__pycache__/datastore_store_product_permutation.cpython-312.pyc b/datastores/__pycache__/datastore_store_product_permutation.cpython-312.pyc index 09b2f8a48d1a555c998181a65db7c4791aa73dc5..f4c9a94d87b3000cf25c052ec68d4d7b7a2546c7 100644 GIT binary patch literal 3089 zcmbVOTW=f36`ox#$>oX^b#WwFH?Qj&F;!blUGxH>Fd|D$-1;U*jty*C43@hiX_;Lv zGqbc!fdc$spcIXN3JI1WVPe4rdO?#XIg)`OdC8d}msA@C2)e+| zd~@cUnKNh3W&WDW83?|K{ZE&2y$Jn74B{`@2K#>l@IG>pggd%Xl*Mg*# zlvwjqLE1_Ox~0o;($55jWk{UzdxET$l{oF^f?lgvV%^UNeO8~u8NWXmum&Vn{XuI` z?sd#M2EF0G5)4^G!LT(Pj94R*r^i1Yj9R0?m^CKHS${m3uqGtV`IEtbb5@qOfvqG4P@lLkPv+0ws>eys%=Rw|(%F4xV)I*Ula%qt!U z6W1`hb2H|=9odUfNC`9EAa+!vMD8p}CMfCFoXA`tG^j;(BzEZt7{)wd4)v;nJYxtt z6APJ3AvM2No*5qtOI#}`+>lK8qRmJ_<%8|b@S)B4$Pq+*lLS=|Ki1I%A6iJ^`AfvF z5{l<9;;Z$=8&`l;bxU%;8&_t1XN3fH7-R0cN2s}8Xr6!V{Q08va}0i7 z1ltzDW-W(dU5KRz;cCn8FsK&$-E_51hd`0lv){lj)A4amg9L-rfMRCGH<bOL6Et& z`h#!cP|UtV4!a}cX(tSX*RQ5%c$dwX-haS31q3VfbJf1X(|2qi!iLf`9G>SL3R#@U z)g`rGP!pB#F7I0=kyHe?Qymp9%SV=I7#tOGT$3uMAXZ7m<;g1bDiIaV&3jr0#Nx0# zhjC<=d{VIkf-z6W$35nj#Ig=?p{QVTk2tl66nc2V@fj7qz_W*s!&My6SAk5wE#@?7 zGELZ)_Z;Hm2_W$Sn=Z?ogI&nR*!Nh(dO$2LiqKQxmc0Kf7x#bO_Ze7?{TrJ5=q;}RlONd5pW4iy zdXhig)OPay(2TwMDbg|%&CCBBnA#qg+Z>qt%jG8n3(dKm;j!l2dzW^yeGf0MU;ZHR zG&{bR0nURg%Je=;J&GPJHN!1^a!)&z$sSx%P-bFVKeMTy*(%I#7p`v>u5a9Ud*k*m zw)7$-ycTN;jZXe){CDF!$IYFg(HCiL(%8^P_Y9QDZtLczZf=~sxG{fgOTP^w8@*Fc z_3uy-%7wHj4DEY0Fb?1~;EOxXV*D;7_tuO|%TP8&wFn5jU0nJ@VS4ZjNppzrLt# z`(A0f;|vfA9+VYP#s`leQjsV4$x@AZ6{z+&EQu!=o0dhV)#4JAdnzgcpZXfUBZ?E% zK%f;)C%R>Ax&zx~O|C5iXm~}wQP^~=#}Fz(oxSU~g4lqU38{$J2&1}CrEf{RQ7|yr zt@jHR8Jru32%?zq6yyP~O1K&_o|H0FL0R{W=g8efukWJo u{|g;|nL^5$T{QL)%6)_~&(XO}bnZEt0?IA|f1Xp6vl~+vULpbHUS9$^DOvdd literal 4450 zcmbssU2hcE_0E3Ij(5EngKZXL#(b}{IE0Uq@DT+tv?vA~Oj2p&>UKPHZN|*qS?VxH(LXMEX<0N{LP2k0xLdZj66NA`_9di{PGvW%uaW}z}Mv|wD zl$(`idz3jQ(Y)zl6 z`2pj;KJI`pvo)@un9+OF$QzyV7%Jz-B#BqvyPG zU^-s|IlLA~$Cl0QoWII=2`IUy=H~hPujTL1h#jb9~FImID;M zB5Wp#i7?&VBkYYf>o|UxYaxYWu`qwZaRVlN+C;-bnaK~v>3JbM0f*7R5Y`QOv~Y79 zrcJS8JWPD(!@;sRM%b_*XSl87qigB;Tc%r;_6LccNQI9~;Yeh-Z5^t$R^NKkxZ~rA zx3pYIrMoEj0c{tvr(x9K7-wATI^$^AM8Iwbuy^u;3r-8uK9h=tU6wR{K+Q@8j+?bP6oh2r9n~ zQXiv?RvNKMLA5A0M=Lc^1V!$Yeu7;_qvN~@5`H%f-`^w8)Z9XPQ62bNExZ5>v6^WM zVUmWwG~Rn~S|}IF-FVP4?p)+Q$=Vp|P)zFaDD^3%gFDf|)&%P@J6?|msfc1H9yJRT zNU9Nbt}BAt@5p6$69JUC#xsW}TJyB{l65lIvxW%M7Clvujgem+A>?j4=#BX5X**d@ zbeyJ>lBy>+prq@mxh>He?RT5|cgGS0^yzEUB4}<~1hwBS9o4!zx4n&zAX}}+9yNWT zY_#rDX7D8;&ULcY6;At**;=_N~39 zm_0^)^A_Ch_O15AwB>OOp0LM-%=H@WTfBf_Vz%nop=JrFV9cgoxeZU(%!j~p@$%&P ztJn04m#zC|}c#OhKjPDzzG10EbW zQ@=XhD#20-Xa*Y9kU_G7!US~#6@?N+gM07jlpnN<3;ze0U<*V;=_>xi=|Il#s7yt%>|Q$JWNz zM6+geT>AClhAR30hT$Gr&K;YNJyW#@+Jg4!@!wzkLM*8xIPY5M`gHv9u48`@OD8Ws zp7>x%z50**(9`_LVt(XFzBHeB*4_8OU2uO}o{ul*d!Od_Eavw-$?uy_EN|ccPZH0Z zo`3&Yw)fNbzv%mN%Tji<0S|uZFJ+HJaPa5)SM{&6r=F*Q{kcXq_dV?YtpDNAXG2eV zhUZhuYWGvMu&5TE$4G7_wVWMznT%(&=PJqM9;6r254sn+m(+phDN-2v)8HQlm$&K5 zeTDDRi6QMV2x-9fR2^Pahac}c`S|peC3WI&YWIWeLiUqxaS%>lOku?@o19S^YLs$l zg6!8Wc67$o0(nDe&fN~f`0#>T;?~|7?CAs}y zsqM*rxvQiXPlstrZO?+;`dw#wv~>mGmOIcBKuZ|*{s>aM1B-?`rmH@5%g~p2)A)_y zkIIf=bXvCC0!z5S`Wx=wfU%kGsMT!11=eAKg*n{0fk>461U3ob;09a{cIN_XdAM%_ z7HAzCeY+?7c9Ho>%tChb0^?#s6(OI=L@2ucmx?mmi7c`VZJ=V)JOVu^(~Za@vt$}bl;PKaz>XsvUeAE-9J&a;6X5%di_N$iHW%U6b?~mjIWZ3MKZBUYKx?{Lf(6oB1!>=11n_vHzfBB$*huti{#)c83D`++3`}_ Psq{Y{dG{58w^ZrB^LrIe diff --git a/datastores/__pycache__/datastore_store_stock_item.cpython-312.pyc b/datastores/__pycache__/datastore_store_stock_item.cpython-312.pyc index 6a415a29d010236968c487feb72f523ef73489e5..3dfde80bf2b7949fba4b0c5eeee95872751e2422 100644 GIT binary patch delta 65 zcmZ2%y~3LJG%qg~0}%Yb_cqOWBkyBo8R>wc{FKt2A~=lr~q#LT?Z UqRs3q@sccc7a8g%XUSRu0REa6RR910 delta 60 zcmZ2sz1W)fG%qg~0}#BQd?U?nBkyBoaj}4+{FKt2A~pUmQt%{(me Pk}Q=M87e2|%US{eaak14 diff --git a/datastores/__pycache__/datastore_user.cpython-312.pyc b/datastores/__pycache__/datastore_user.cpython-312.pyc index 7abc960684d70a552f51c96737024031e641343d..5c27228d4c21ec122c0f12ae9d1633c33a086022 100644 GIT binary patch delta 938 zcmY+CyK59d9LIO|-h1y$?)^&6L~|NLOpL~uXv_l@1S1y0G|T386HjOM&Y8R5Ro4h& zBZT=2v=b|Hos9~1f{=E>M63i6w9rBWp|>|M~aC|FY(g=4$vSDy0MRhsD?Ef#$g)45!dsRD2?Hms{ zd?i#L9QZTDk_Ud+60;$>}jih zbX5FIJf1osm$6B}Nr`%aorZl>W56MM8QEejs;{l+U2ZYQZ?xN%ZL&F-hqBmNz&zj_04~oKBNq|~=4=@zF99wBRwQ^#V&uQU%Hm~e8g&O>Qa4nT z6HDpi3kAqu1>BNwqPlFM!Fj_XMAz$xm88p;GmV0NwxOkGTg)9HO`j~j1oLQ_ir*u;EULxaJ~*S|MJ6j=XTyFktoMoiY%vTS{M+!Ln9fyE zNNnWFDfqt~&AQ*QY~F0yoP|X{m+41bTW)KR#%+uCSQHGue3WL}a?}=gd|R@Py9~O( z;(!EX1lv8+ush8LOM;gI&o5uGX>YS3aE1X;-!p}|#X;4-f{V0ec8PU?Q5hnoCYy3y js&5{I(05fs-XA3ejek(450z_&%ErF3A#i@q3p@M)^u^y| delta 1801 zcma)6O>Y}T7~XXpXJf}-u^q>b6X!c|lQ?P9d^98}ibK;tplPX!m;=kkp12D$wt06Q z;gc^&APz`nPy7VbV}1Z9BqSuH3W>u?k&nQIj{_XIlzAsM0wN)B_XdES}XnP>LH zMQ1hibuj2x#P9c~Kc0S;c@i4-oT*Rd$C}(ne5z7XOJ3H;HKOr;(l6V+%+CWPAi0kX z@E{3F-p4{bOu~|DEW)ECDtSK}*TuR9(IG=cuTywhpm!T@l3Fre2uK}b+XPk$c8ix zu}yx9+~QkgOSY5j1-?zTB_C!xe246)ibpw6N~sT&Qkv$T_TVln3fXOVawASib(PzRuuVnguW zLvEC*AmM$=%rh#A@6~LxTKR|cfR@cSq^9kgR>w`J#h_2i((jdom*3@|SXQ&%LtUF!~A?K(0o`~0rwOI2NP zLf(wJdcNT8_o`86P0Oa{#8$fD(urQIgH;8+$fyB1KP)<2n^p_Xr&>YHJKt&Z>iYR} zt>9BPoI?1M{I)2A9fVy0xiq|l<9LiSci_xmx>>Poqf(@hK+A~pJiOoBLs~%CM{kd1 zgX^^$H3|nP#!(zNg(}zg_w>3Yj>u=!YP3>_g z7Q>OG<+@pdSFvm9HAI}>^#ir)%+@WDm|iqna34D#ARHsS?))4{iudk|uBgrP&FFoP znsYvmT?;H=??Z&g&KI#ndPz`A74RbDQI#t~SayDjO$L@bTJE+p65njTDcbJnN!=0= zv@E@P@(wN9R^GC!K=UUu!+`k)FB<2%7;EiR7u%_ZUM%rpNw!OgI9(C!X0ZW%Xv=i5 znV5Od&@$V_QtI4>s=N)*|G&&2?n$-M1pGvHU1X_!gCOu`KN*Sh6nL)rDey)HFA*S;WZJUelA)~wSk!WIUEla>JJ*uky z>hY`I-!h6i(^7U?%G(#p%?l-eq3q#*R5n^l`CFxYp{%r&qn2{~OgU~Tjb}>3`6jXE H#aaFY7jqIW diff --git a/datastores/datastore_base.py b/datastores/datastore_base.py index c316a45c..52e94f6b 100644 --- a/datastores/datastore_base.py +++ b/datastores/datastore_base.py @@ -13,7 +13,8 @@ Datastore for Store # internal # from routes import bp_home import lib.argument_validation as av -from business_objects.store.access_level import Access_Level, Filters_Access_Level +from business_objects.store.access_level import Access_Level +""" 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 @@ -23,13 +24,17 @@ 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, Filters_Product # Permutation_Variation_Link +""" from business_objects.sql_error import SQL_Error from business_objects.store.stock_item import Stock_Item, Stock_Item_Filters +from business_objects.unit_measurement import Unit_Measurement 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_List +# from business_objects.store.product_variation import Product_Variation, Product_Variation_Filters, Product_Variation_Container # 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 +from forms.access_level import Filters_Access_Level +from forms.unit_measurement import Filters_Unit_Measurement # external # from abc import ABC, abstractmethod, abstractproperty from flask_sqlalchemy import SQLAlchemy @@ -105,8 +110,8 @@ class DataStore_Base(BaseModel): while cursor.nextset(): print(f'new result set: {cursor.fetchall()}') @classmethod - def get_regions_and_currencies(cls): - _m = 'DataStore_Base.get_regions_and_currencies' + def get_many_region_and_currency(cls): + _m = 'DataStore_Base.get_many_region_and_currency' _m_db_currency = 'p_shop_get_many_currency' _m_db_region = 'p_shop_get_many_region' @@ -168,20 +173,45 @@ class DataStore_Base(BaseModel): def upload_bulk(permanent_table_name, records, batch_size): _m = 'DataStore_Base.upload_bulk' print(f'{_m}\nstarting...') + print(f'permanent_table_name: {permanent_table_name}') + if db.session.dirty or db.session.new or db.session.deleted: + print("Session is not clean") + return + # Assuming `permanent_table_name` is a string representing the table name + table_object = db.metadata.tables.get(permanent_table_name) + if table_object is None: + print(f"Table {permanent_table_name} not found in metadata.") + return + else: + expected_columns = set(column.name for column in db.inspect(table_object).columns) + print(f'expected_columns: {expected_columns}') + try: for i in range(0, len(records), batch_size): batch = records[i:i+batch_size] + print(f'batch: {batch}') + db.session.bulk_save_objects(batch) + """ data = [object.to_json() for object in batch] - print(f'batch: {batch}\ndata: {data}') - db.session.bulk_insert_mappings(permanent_table_name, data) + print(f'data: {data}') + for row in data: + row_keys = set(row.keys()) + if row_keys != expected_columns: + print(f"Column mismatch in row: {row}") + print(f'missing columns: {expected_columns - row_keys}') + print(f'extra columns: {row_keys - expected_columns}') + # db.session.bulk_insert_mappings(permanent_table_name, data) + """ db.session.commit() except Exception as e: print(f'{_m}\n{e}') db.session.rollback() raise e @classmethod - def get_many_access_level(cls, filters): + def get_many_access_level(cls, filters=None): _m = 'DataStore_Store_Base.get_many_access_level' + if filters is None: + filters = Filters_Access_Level() av.val_instance(filters, 'filters', _m, Filters_Access_Level) argument_dict = filters.to_json() # user = cls.get_user_session() @@ -213,4 +243,41 @@ class DataStore_Base(BaseModel): DataStore_Base.db_cursor_clear(cursor) cursor.close() - return access_levels, errors \ No newline at end of file + return access_levels, errors + @classmethod + def get_many_unit_measurement(cls, filters=None): + _m = 'DataStore_Store_Base.get_many_unit_measurement' + if filters is None: + filters = Filters_Unit_Measurement() + av.val_instance(filters, 'filters', _m, Filters_Unit_Measurement) + argument_dict = filters.to_json() + # user = cls.get_user_session() + # argument_dict['a_id_user'] = 1 # 'auth0|6582b95c895d09a70ba10fef' # id_user + print(f'argument_dict: {argument_dict}') + print('executing p_shop_get_many_unit_measurement') + result = cls.db_procedure_execute('p_shop_get_many_unit_measurement', argument_dict) + cursor = result.cursor + print('data received') + + # units of measurement + result_set_1 = cursor.fetchall() + print(f'raw units of measurement: {result_set_1}') + units = [] + for row in result_set_1: + new_unit = Unit_Measurement.from_DB_unit_measurement(row) + units.append(new_unit) + + # Errors + 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_Base.db_cursor_clear(cursor) + cursor.close() + + return units, errors \ No newline at end of file diff --git a/datastores/datastore_store_base.py b/datastores/datastore_store_base.py index 352856cf..042a17e5 100644 --- a/datastores/datastore_store_base.py +++ b/datastores/datastore_store_base.py @@ -12,8 +12,6 @@ Datastore for Store # internal # from routes import bp_home -import lib.argument_validation as av -# from business_objects.store.access_level import Access_Level, Filters_Access_Level 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 @@ -26,11 +24,12 @@ from business_objects.store.product import Product, Product_Permutation, Product from business_objects.sql_error import SQL_Error from business_objects.store.stock_item import Stock_Item, Stock_Item_Filters 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_List +from business_objects.store.product_variation import Product_Variation_Type, Product_Variation, Product_Variation_Filters, Product_Variation_Container from datastores.datastore_base import DataStore_Base -# 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 +from helpers.helper_db_mysql import Helper_DB_MySQL +import lib.argument_validation as av +# from models.model_view_store_checkout import Model_View_Store_Checkout # circular! # external # from abc import ABC, abstractmethod, abstractproperty from flask_sqlalchemy import SQLAlchemy @@ -118,12 +117,8 @@ class DataStore_Store_Base(DataStore_Base): # variations = [Product_Variation(**row) for row in result_set_4] variations = [] for row in result_set_4: - new_variation = Product_Variation.from_DB_get_many_product_catalogue(row) # (row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7]) + new_variation = Product_Variation.from_DB_get_many_product_catalogue(row) variations.append(new_variation) - # products[product_index[new_variation.id_product]].variations.append(new_variation) - # index_category = category_index[new_variation.id_category] - # index_product = categories[index_category].index_product_from_ids_product_permutation(new_variation.id_product, new_variation.id_permutation) - # categories[index_category].products[index_product].variations.append(new_variation) category_list.add_product_variation(new_variation) # print(f'variations: {variations}') # print(f'products: {[p.id_product for p in products]}') @@ -209,17 +204,13 @@ class DataStore_Store_Base(DataStore_Base): ids_permutation.append(msg_error_availability[:index_comma]) return ids_permutation @classmethod - def get_regions_and_currencies(cls): - _m = 'DataStore_Store_Base.get_regions_and_currencies' + def get_many_currency(cls): + _m = 'DataStore_Store_Base.get_many_currency' _m_db_currency = 'p_shop_get_many_currency' - _m_db_region = 'p_shop_get_many_region' argument_dict_list_currency = { 'a_get_inactive_currency': 0 } - argument_dict_list_region = { - 'a_get_inactive_currency': 0 - } print(f'executing {_m_db_currency}') result = cls.db_procedure_execute(_m_db_currency, argument_dict_list_currency) @@ -235,6 +226,17 @@ class DataStore_Store_Base(DataStore_Base): print(f'currencies: {currencies}') DataStore_Store_Base.db_cursor_clear(cursor) + return currencies + + @classmethod + def get_many_region(cls): + _m = 'DataStore_Store_Base.get_many_region' + _m_db_region = 'p_shop_get_many_region' + + argument_dict_list_region = { + 'a_get_inactive_currency': 0 + } + print(f'executing {_m_db_region}') result = cls.db_procedure_execute(_m_db_region, argument_dict_list_region) cursor = result.cursor @@ -250,7 +252,15 @@ class DataStore_Store_Base(DataStore_Base): DataStore_Store_Base.db_cursor_clear(cursor) cursor.close() + return regions + + @classmethod + def get_many_region_and_currency(cls): + _m = 'DataStore_Store_Base.get_many_region_and_currency' + currencies = cls.get_many_currency() + regions = cls.get_many_region() return regions, currencies + @classmethod def get_many_product_variation(cls, variation_filters): _m = 'DataStore_Store_Base.get_many_product_variation' @@ -278,13 +288,30 @@ class DataStore_Store_Base(DataStore_Base): result = cls.db_procedure_execute('p_shop_get_many_product_variation', argument_dict_list) cursor = result.cursor - result_set = cursor.fetchall() + result_set_vt = cursor.fetchall() + # Product_Variation Types + # variation_container = Product_Variation_Container() + variation_types = [] + variation_types_dict = {} + for row in result_set_vt: + new_variation_type = Product_Variation_Type.from_DB_get_many_product_variation(row) + # variation_container.add_product_variation_type(new_variation_type) + variation_types.append(new_variation_type) + variation_types_dict[new_variation_type.id_type] = new_variation_type + + print(f'variation_types_dict: {variation_types_dict}') + # Product_Variations - variations = Product_Variation_List() - for row in result_set: - new_variation = Product_Variation.from_DB_variation(row) - variations.add_product_variation(new_variation) + cursor.nextset() + result_set_v = cursor.fetchall() + # variations = Product_Variation_Container() + variations = [] + for row in result_set_v: + new_variation = Product_Variation.from_DB_get_many_product_variation(row) + new_variation.variation_type = variation_types_dict[new_variation.id_type] + # variation_container.add_product_variation(new_variation) + variations.append(new_variation) errors = [] cursor.nextset() @@ -299,5 +326,5 @@ class DataStore_Store_Base(DataStore_Base): cursor.close() - return variations, errors + return variation_types, variations, errors \ No newline at end of file diff --git a/datastores/datastore_store_basket.py b/datastores/datastore_store_basket.py index b4b31a3b..fd77dc9e 100644 --- a/datastores/datastore_store_basket.py +++ b/datastores/datastore_store_basket.py @@ -25,7 +25,7 @@ from business_objects.store.product import Product, Product_Permutation, Product from business_objects.sql_error import SQL_Error from business_objects.store.stock_item import Stock_Item, Stock_Item_Filters 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_List +from business_objects.store.product_variation import Product_Variation, Product_Variation_Filters, Product_Variation_Container from datastores.datastore_store_base import DataStore_Store_Base # from helpers.helper_db_mysql import Helper_DB_MySQL # from models.model_view_store_checkout import Model_View_Store_Checkout # circular! diff --git a/datastores/datastore_store_product.py b/datastores/datastore_store_product.py index 86b18e1e..bea50e2d 100644 --- a/datastores/datastore_store_product.py +++ b/datastores/datastore_store_product.py @@ -24,7 +24,7 @@ from business_objects.store.product import Product, Product_Permutation, Product from business_objects.sql_error import SQL_Error from business_objects.store.stock_item import Stock_Item, Stock_Item_Filters 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_List +from business_objects.store.product_variation import Product_Variation, Product_Variation_Filters, Product_Variation_Container # from datastores.datastore_base import Table_Shop_Product_Category, Table_Shop_Product_Category_Temp from datastores.datastore_store_base import DataStore_Store_Base from helpers.helper_db_mysql import Helper_DB_MySQL @@ -83,7 +83,7 @@ class Row_Shop_Product_Temp(db.Model): 'id_category': self.id_category, 'name': self.name, 'id_access_level_required': self.id_access_level_required, - 'active': self.active, + 'active': av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json'), 'display_order': self.display_order, 'guid': self.guid, } diff --git a/datastores/datastore_store_product_category.py b/datastores/datastore_store_product_category.py index 2c057cb0..ebfce816 100644 --- a/datastores/datastore_store_product_category.py +++ b/datastores/datastore_store_product_category.py @@ -13,7 +13,7 @@ Datastore for Store Product Categories # internal 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.product_category import Product_Category_Container, Product_Category, Product_Category_Temp from business_objects.store.currency import Currency from business_objects.store.image import Image from business_objects.store.delivery_option import Delivery_Option @@ -24,7 +24,7 @@ from business_objects.store.product import Product, Product_Permutation, Product from business_objects.sql_error import SQL_Error from business_objects.store.stock_item import Stock_Item, Stock_Item_Filters 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_List +from business_objects.store.product_variation import Product_Variation, Product_Variation_Filters, Product_Variation_Container # from datastores.datastore_base import Table_Shop_Product_Category, Table_Shop_Product_Category_Temp from datastores.datastore_store_base import DataStore_Store_Base from helpers.helper_db_mysql import Helper_DB_MySQL @@ -41,67 +41,6 @@ from pydantic import BaseModel, ConfigDict from typing import ClassVar from datetime import datetime -# db = SQLAlchemy() - -""" -class Table_Shop_Product_Category(db.Model): - __tablename__ = 'Shop_Product_Category' - id_category: int = db.Column(db.Integer, primary_key=True) - code: str = db.Column(db.String(50)) - name: str = db.Column(db.String(255)) - description: str = db.Column(db.String(4000)) - active: bool = db.Column(db.Boolean) - display_order: int = db.Column(db.Integer) - created_on: datetime = db.Column(db.DateTime) - created_by: int = db.Column(db.Integer) - id_change_set: int = db.Column(db.Integer) -""" -class Row_Shop_Product_Category_Temp(db.Model): - __tablename__ = 'Shop_Product_Category_Temp' - __table_args__ = { 'extend_existing': True } - id_category: int = db.Column(db.Integer, primary_key=True) - code: str = db.Column(db.String(50)) - name: str = db.Column(db.String(255)) - description: str = db.Column(db.String(4000)) - id_access_level_required: int = db.Column(db.Integer) - active: bool = db.Column(db.Boolean) - display_order: int = db.Column(db.Integer) - guid: str = db.Column(db.BINARY(36)) - # created_on: datetime = db.Column(db.DateTime) - # created_by: int = db.Column(db.Integer) - - @classmethod - def from_product_category(cls, product_category): - row = cls() - row.id_category = product_category.id_category[0] if isinstance(product_category.id_category, tuple) else product_category.id_category - row.code = product_category.code[0] if isinstance(product_category.code, tuple) else product_category.code - row.name = product_category.name[0] if isinstance(product_category.name, tuple) else product_category.name - row.description = product_category.description[0] if isinstance(product_category.description, tuple) else product_category.description - row.id_access_level_required = product_category.id_access_level_required[0] if isinstance(product_category.id_access_level_required, tuple) else product_category.id_access_level_required - row.active = product_category.active - row.display_order = product_category.display_order - """ - row.guid = product_category.guid - row.created_on = product_category.created_on - row.created_by = product_category.created_by - """ - return row - def to_json(self): - return { - 'id_category': self.id_category, - 'code': self.code, - 'name': self.name, - 'description': self.description, - 'id_access_level_required': self.id_access_level_required, - 'active': self.active, - 'display_order': self.display_order, - 'guid': self.guid, - } - """ - 'created_on': self.created_on, - 'created_by': self.created_by - """ - class DataStore_Store_Product_Category(DataStore_Store_Base): def __init__(self): @@ -120,8 +59,8 @@ class DataStore_Store_Product_Category(DataStore_Store_Base): rows = [] id_category_new = 0 for category in categories: - # row = Row_Shop_Product_Category_Temp.from_product_category(category) - row = category.to_temporary_record() + row = Product_Category_Temp.from_product_category(category) + # row = category.to_temporary_record() # id_tmp = if row.id_category == '': id_category_new -= 1 @@ -147,7 +86,7 @@ class DataStore_Store_Product_Category(DataStore_Store_Base): cursor.close() print('cursor closed') """ - DataStore_Store_Base.upload_bulk(rows, Product_Category.__tablename__, 1000) + DataStore_Store_Base.upload_bulk(Product_Category_Temp.__tablename__, rows, 1000) argument_dict_list = { 'a_id_user': user.id_user, diff --git a/datastores/datastore_store_product_permutation.py b/datastores/datastore_store_product_permutation.py index 65b32361..15121ae8 100644 --- a/datastores/datastore_store_product_permutation.py +++ b/datastores/datastore_store_product_permutation.py @@ -12,21 +12,10 @@ Datastore for Store Product Permutations # internal 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, Filters_Product -from business_objects.sql_error import SQL_Error -from business_objects.store.stock_item import Stock_Item, Stock_Item_Filters -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_List +from business_objects.store.store_base import Store_Base +from business_objects.store.product_permutation import Product_Permutation, Product_Permutation_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 @@ -43,35 +32,72 @@ from datetime import datetime # db = SQLAlchemy() + class DataStore_Store_Product_Permutation(DataStore_Store_Base): def __init__(self): super().__init__() - def save_permutations(self, comment, permutations): - _m = 'DataStore_Store_Base.save_permutations' + @classmethod + def save_permutations(cls, comment, permutations): + _m = 'DataStore_Store_Product_Permutation.save_permutations' av.val_str(comment, 'comment', _m) - av.val_list(permutations, 'list_permutations', _m, Product_Permutation, 1) + # av.val_list(permutations, 'list_permutations', _m, Product_Permutation, 1) - guid = Helper_DB_MySQL.create_guid() + guid = Helper_DB_MySQL.create_guid_str() now = datetime.now() - user = self.get_user_session() + user = cls.get_user_session() + rows = [] for permutation in permutations: - setattr(permutation, 'guid', guid) - setattr(permutation, 'created_on', now) - setattr(permutation, 'created_by', user.id_user) + # row = permutation.to_temporary_record() + row = Product_Permutation_Temp.from_product_permutation(permutation) + row.guid = guid + rows.append(row) - cursor = self.db.cursor() + print(f'rows: {rows}') + + """ + cursor = db.cursor() + print('cursor created') cursor.executemany( - 'INSERT INTO Shop_Product_Permutation_Temp (id_permutation, id_product, description, cost_local, id_currency_cost, profit_local_min, latency_manufacture, quantity_min, quantity_max, quantity_step, quantity_stock, is_subscription, id_recurrence_interval, count_recurrence_interval, id_stripe_product, active, display_order, guid) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)', - permutations + '''INSERT INTO Shop_Product_Permutation_Temp ( + id_permutation, + id_product, + description, + cost_local, + id_currency_cost, + profit_local_min, + latency_manufacture_days, + id_unit_measurement_quantity, + count_unit_measurement_quantity, + quantity_min, + quantity_max, + quantity_stock, + is_subscription, + id_unit_measurement_interval_recurrence, + count_interval_recurrence, + id_stripe_product, + does_expire_faster_once_unsealed, + id_unit_measurement_interval_expiration_unsealed, + count_interval_expiration_unsealed, + active, + guid + ) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)''', + rows ) - self.db.commit() - + print('cursor executed') + db.commit() + print('cursor committed') + cursor.close() + print('cursor closed') + """ + DataStore_Store_Base.upload_bulk(Product_Permutation_Temp.__tablename__, rows, 1000) + print('bulk uploaded') + argument_dict_list = { 'a_id_user': user.id_user, 'a_comment': comment, 'a_guid': guid } - self.db_procedure_execute('p_shop_save_permutation', argument_dict_list) - - cursor.close() + cls.db_procedure_execute('p_shop_save_product_permutation', argument_dict_list) + print('saved product permutations') diff --git a/datastores/datastore_store_product_variation.py b/datastores/datastore_store_product_variation.py index 6575a7e7..52859eb2 100644 --- a/datastores/datastore_store_product_variation.py +++ b/datastores/datastore_store_product_variation.py @@ -25,7 +25,7 @@ from business_objects.store.product import Product, Product_Permutation, Product from business_objects.sql_error import SQL_Error from business_objects.store.stock_item import Stock_Item, Stock_Item_Filters 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_List +from business_objects.store.product_variation import Product_Variation, Product_Variation_Filters, Product_Variation_Container from datastores.datastore_store_base import DataStore_Store_Base # from helpers.helper_db_mysql import Helper_DB_MySQL # from models.model_view_store_checkout import Model_View_Store_Checkout # circular! @@ -80,7 +80,7 @@ class DataStore_Store_Product_Variation(DataStore_Store_Base): result_set = cursor.fetchall() # Product_Variations - variations = Product_Variation_List() + variations = Product_Variation_Container() for row in result_set: new_variation = Product_Variation.from_DB_variation(row) variations.add_product_variation(new_variation) diff --git a/datastores/datastore_store_stock_item.py b/datastores/datastore_store_stock_item.py index 53318b99..b89e1c8b 100644 --- a/datastores/datastore_store_stock_item.py +++ b/datastores/datastore_store_stock_item.py @@ -25,7 +25,7 @@ from business_objects.store.product import Product, Product_Permutation, Product from business_objects.sql_error import SQL_Error from business_objects.store.stock_item import Stock_Item, Stock_Item_Filters 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_List +from business_objects.store.product_variation import Product_Variation, Product_Variation_Filters, Product_Variation_Container from datastores.datastore_store_base import DataStore_Store_Base # from helpers.helper_db_mysql import Helper_DB_MySQL # from models.model_view_store_checkout import Model_View_Store_Checkout # circular! diff --git a/datastores/datastore_store_stripe.py b/datastores/datastore_store_stripe.py index 6cc1942c..27db528a 100644 --- a/datastores/datastore_store_stripe.py +++ b/datastores/datastore_store_stripe.py @@ -25,7 +25,7 @@ from business_objects.store.product import Product, Product_Permutation, Product from business_objects.sql_error import SQL_Error from business_objects.store.stock_item import Stock_Item, Stock_Item_Filters 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_List +from business_objects.store.product_variation import Product_Variation, Product_Variation_Filters, Product_Variation_Container from datastores.datastore_store_base import DataStore_Store_Base # from helpers.helper_db_mysql import Helper_DB_MySQL # from models.model_view_store_checkout import Model_View_Store_Checkout # circular! diff --git a/datastores/datastore_user.py b/datastores/datastore_user.py index afbfe550..5628d1e4 100644 --- a/datastores/datastore_user.py +++ b/datastores/datastore_user.py @@ -13,19 +13,9 @@ Datastore for Users # 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, Filters_Product from business_objects.sql_error import SQL_Error from business_objects.store.stock_item import Stock_Item, Stock_Item_Filters 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_List from datastores.datastore_base import DataStore_Base from helpers.helper_db_mysql import Helper_DB_MySQL # from models.model_view_store_checkout import Model_View_Store_Checkout # circular! diff --git a/forms/__pycache__/access_level.cpython-312.pyc b/forms/__pycache__/access_level.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..40a47abcabf48e50b8b9a120ecc1a63e2bfedd77 GIT binary patch literal 2667 zcmaJ@O>7fK6rNqL|JHW?`At%`g%-9g76c9j8jzD<6bS;vA%vBy)p~cFY}g+&yADZ2 zB@Q{zQ`J+bDpXafR46^biCfhJxAtHQD$`XFmD(P-1yWRrQ{T+Sp+OcS>+O5<-n^N4 z-+OQTb0#Aq81w%=FONhK`jZOH0Wuq_-@|7a8Aw3}XYdwh^9s*VK4L{|K@k`)SW!Es z#2Fv85_VEaGCpRBc1lUvX(erEl#Jb`wAt-SyWOF5*qurzvx!?>cDK@P_b5H~CS{Yo zS=nrFQMNE$!rE$YQ?@ZaX>GTAm0r6~>EjTOP9Q^ELPiP;w4{Jo9ktVP{R|#g@ z=3N5jd!?MNV-MEhIc!OJ)ABL#Bt!Ex$#g1JUld2MrxUZ{!|sPcD4P!Uq`akh7x$i@ z$V+AB2dFfoIfi9A(~=gtw3y2>a~V3zice{fWG)bfG!Mf!NspmYVT?)CEuE6%L8{;r z@Rm2RWdxZCJn!cS)^L3#uNv2Kz$&7z=LaMZSOtZNltp9xPS^Fcf} zG<*vCTF|DIJfCQ~Z({)2(8Ih4=~|MY)sH}4Mi?m^BsI??95J}tkTY~Bg268#C5mH4 zWC`64Cy^321ei@MMCDk}vxbx!!lyF$7SlQ1H|MbAI@ZE5ea#zNE&!!_uaZQ#{6?8dUqO+9HC_MOn2o(Q0U}uQH-rL`BV&t+JrDvo&EQK;mW3dxsyd+SscMi= zRY$WiaIw%N5NN{Pg0%3kRrct?rI*I=;o>IFt7QkgMoX*XHHy7uiOaTfxtkbYoPOy9qsu_o)e@m~eLt9cqd=~r zzdCk3=y>m%@Oy9n*MnaU-t76oXk?Gp;U^!v-_yvQt>@0xCNDH5OZCZ8?VMiI?OMTk z(Cc0kK2Lp?dYIVysJ;7Iio6ZpHq;Rf0R!+CU;sd%;b>Jme)IW4t!f2;XaQg=aNfKN z_-O&wY+LhWuf7{WCJ}=-xdJjGl*$5BY}R)fm``b55}LRGE4?mxmy(^7?4o2HK0*^N zgp`G!m2L=Je9hTnUrX55wC})r?-L*ZTDqf=?yIN!z8&~(@SDLqJ@icu| z4>pDi_2EKos@Rw+*Qd&jDYri5*3MUImHFDag@-#AuWKt2zC&C=d{SKDQH~$tUrjI| z$K)hCX&|bq?HW~!cA&JXUV^?6_9K#9znlbIkYXJxY~w_xx(|WeLd+ezB};lnXdpal zvxI)jY`dO)kdd$EpYvSw1oua@;~5``_N+!wtaF8NiAYooz0j(W-wNWYYPdQaXj7@` z(I?hZ-4gxt;AKnjI)-&5vhoNg1XvervCL9dBh#!Os&krULL-HTI_PdO$?$`EqHnBv z*)J2Co5su@Y@ggU@ v*p9f}kCF5k?fM(-c!DYoRH>uN6LjHMbm1||K0&+xiKRL5`k@yHKFsxh!^Mwi literal 0 HcmV?d00001 diff --git a/forms/__pycache__/base.cpython-312.pyc b/forms/__pycache__/base.cpython-312.pyc index af6d106b28559519b5e8f6b78c28505ba1cf6b83..378d2077d028a6c3cfe1e356248520d6b7050ded 100644 GIT binary patch delta 335 zcmcb>J&~L5G%qg~0}w=g|CA=fwvlf;lZq9PJDnkwA&N1DA&M!5F^V~rC55SlVKqn{ z5Ja)2vQ7Taq#j=t&7}YY4#_!*#l^X)B^miC5P`&`;*z4ovC@?3Pak3zb4D(7xzsbj#%^2k-|7Esey~PaFHrbBF z$WsyMkYaWq(ZKM5je(Q5hzH2_)8r`P0MbRAAOhsCTkP@iDf!9q@kOj4Az_dZH_DP{;R723CvOoCkUcqOW-5EmOw4r0|56ldg^z_}pq8v~F5b_xJf4^tQb diff --git a/forms/__pycache__/forms.cpython-312.pyc b/forms/__pycache__/forms.cpython-312.pyc index b45e6575572b57fb926623de795c5e59a2c9b32c..023f70b945d28544bda03438ea8c87e2212e6a28 100644 GIT binary patch delta 186 zcmdmH)M>zXnwOW00SI=RzDfHpGLcV$v0$TmAtOtroTmKdO^iuGlRt<`Ox6{V*QpZn zFD+5XPg5u^$xqH!$j{5Ew6Egy&CG)c0GWvu5T>8zhp=P=NB~51f*5rmLKQ?bOpX(loE#*&m8%KF1rd`b3ySHmgIIo= zDwAEr?&~(dq>5BPEU-p3AnO;0O>TZlX-=wLQ4f&I2*kyQCVPu7;8kE{)SglKg#k!? K5t#f&TowSXcUJoV diff --git a/forms/__pycache__/unit_measurement.cpython-312.pyc b/forms/__pycache__/unit_measurement.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0907c0d3d157a50fa68093c614ca32f9f6d04b3c GIT binary patch literal 2857 zcmaJ@O>7%Q6rSDn@7m5!lm4cKZB%FtszoD&M4?4a6PF?q+9VXQGK|){<7D0aF|+Hm ziGt{%hj8Lp5JCtEiJx+S6IX<|aYRF+u9M#R~IXAE8-GW|l`}97yU+;GZ^Z|EJ9~3reXO}yq54pqou)AB|?e5X{ zxO?@zVlLzCbNB1}g`RZ|xFh6sKgPRN595WX@-|^>{wArN~WNx6nXv1P=sp|IJNp0LPFEP(jE6fO6oQZ8K zJ_qyT+RL6DYJOdtVnzUSF7raIVml$@fo2(@q1j%u6{_k43rub|LkQv|bn3Rp0;nhS%<$^FlVyc*l@Akd?Tj zRvh1m^KM<~c@Wo0*xsFV_kB}dks7@#zz*ArywfP{TCT{mkm>27!uNo6lmaLqf+&F$ zD=Lv@Th+ZjFq7c>2B5tBH4VZ|8oksrOEOI{ZarqcpJ&zvARKSJp0E zx;f(fn_n^Fz5GgpCxQ64pa9|^7m8eN1s_E6nqC&YKc_y2bRKlyF19j(#V z(YF7A;nD})T-p+FU7lXfltP~(oW+bt3qJ-c_@gL}qUe%5%2H~=!x2!5wI{Tsb-~tFpO@7Ztesn!Q`tkTDQy)$B7QlBeY)t6u6Z#r8H>kT#-3_|9 zP8Zi+zr1$&txZB+lgcvO1CNZ$n~FT3ZW1}Gio8u1Rel`2M=GVRZ?znVHp)}_2Ha%r z*t4DUMLBV>_#xpB;qVa@kD(}m_>2gjf`Nk3LST6W&w#i_ek$yLw{){myjr=H9Jnhh z$>A-9qy{%p`!gdYE7C9bjc;X?WE`vTR(vQ*Q)>Ap#Cf>Z3h-+npneTMcY;!Y&v`6q z4IcHlgj8|ymc#(oceK~BYbArvi%Xm?8jcOG0eoLXLpuzLEJxWoehtveVVxskqcmvv z<-w7(92w8?YTyDbEPtLufuxIewQWo7oqQhf0?s1+ct45(6oVk5q3%W{`1Xolb-oK{ z6r*PHAv7FDfj0*qLxESG0R3L(**J-(`6(Df!Ua!**iW}2r+oW`d9Q`XbD5>u*{Y~Icxc&!&UdC$x literal 0 HcmV?d00001 diff --git a/forms/access_level.py b/forms/access_level.py new file mode 100644 index 00000000..c9136e88 --- /dev/null +++ b/forms/access_level.py @@ -0,0 +1,37 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Backend +Feature: Forms - Access Level Filters data input + +Description: +Defines Flask-WTF forms for handling access level filter input. +""" + +# internal +from business_objects.base import Base +from forms.base import Form_Base +import lib.argument_validation as av +# external +from flask_wtf import FlaskForm +from wtforms import StringField, TextAreaField, SubmitField, BooleanField, IntegerField, SelectField, FloatField +from wtforms.validators import InputRequired, NumberRange, Regexp, DataRequired, Optional +from flask_wtf.recaptcha import RecaptchaField +from abc import ABCMeta, abstractmethod + + +class Filters_Access_Level(Form_Base): + active = BooleanField("Active only?") + def __repr__(self): + return f'{self.__class__.__name__}(active={self.active.data})' + @classmethod + def from_json(cls, json): + form = Filters_Access_Level() + form.active.data = av.input_bool(json[Base.FLAG_ACTIVE], Base.FLAG_ACTIVE, f'{cls.__name__}.from_json') + return form + def to_json(self): + return { + Base.FLAG_ACTIVE: 1 if av.input_bool(self.active.data, Base.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json') else 0, + } \ No newline at end of file diff --git a/forms/base.py b/forms/base.py index 823a370b..7e69481a 100644 --- a/forms/base.py +++ b/forms/base.py @@ -21,10 +21,12 @@ class Form_Base_Meta(type(FlaskForm), ABCMeta): class Form_Base(FlaskForm, metaclass=Form_Base_Meta): + """ @classmethod @abstractmethod def from_filters(cls, filters): pass + """ @abstractmethod def __repr__(self): pass @@ -43,4 +45,20 @@ class Form_Base(FlaskForm, metaclass=Form_Base_Meta): form_filters.is_not_empty.data = av.input_bool(data_form['is_not_empty'], 'is_not_empty', 'filter_category') form_filters.active.data = av.input_bool(data_form['active'], 'active', 'filter_category') return form_filters - """ \ No newline at end of file + """ + +''' +class Filters_Stored_Procedure_Base(Form_Base): + """ + @abstractmethod + def __repr__(self): + pass + @classmethod + @abstractmethod + def from_json(cls, json): + pass + """ + @abstractmethod + def to_json(self): + pass +''' \ No newline at end of file diff --git a/forms/forms.py b/forms/forms.py index 34b8b0af..d733ff65 100644 --- a/forms/forms.py +++ b/forms/forms.py @@ -126,13 +126,6 @@ class Form_Supplier(FlaskForm): # class Form_Supplier_Purchase_Order(FlaskForm): -class Form_Filters_Permutation(FlaskForm): - id_category = SelectField('Category', validators=[Optional()], choices=[]) - id_product = SelectField('Product', validators=[Optional()], choices=[]) - is_out_of_stock = BooleanField('Out of stock only?') - quantity_min = FloatField('Min stock') - quantity_max = FloatField('Max stock') - # submit = SubmitField('Submit') class Form_Filters_Stock_Item(FlaskForm): id_category = SelectField('Category', validators=[Optional()], choices=[]) diff --git a/forms/store/__pycache__/product_category.cpython-312.pyc b/forms/store/__pycache__/product_category.cpython-312.pyc index 6c5b475b7e92b06d7b54b33ff5c7b82ba8744690..e7d8f538617cbad6963aea1652b901c89c4a930a 100644 GIT binary patch delta 353 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 literal 0 HcmV?d00001 diff --git a/forms/store/product_category.py b/forms/store/product_category.py index 79b96a9f..c254ab65 100644 --- a/forms/store/product_category.py +++ b/forms/store/product_category.py @@ -28,12 +28,14 @@ from abc import ABCMeta, abstractmethod class Filters_Product_Category(Form_Base): is_not_empty = BooleanField('Not empty only?') active = BooleanField("Active only?") + """ @classmethod def from_filters(cls, filters): form = Filters_Product_Category() form.is_not_empty.data = filters.is_not_empty form.active.data = filters.active return form + """ def __repr__(self): return f'Filters_Product_Category(is_not_empty={self.is_not_empty.data}, active={self.active.data})' @classmethod diff --git a/forms/store/product_permutation.py b/forms/store/product_permutation.py new file mode 100644 index 00000000..06267c8f --- /dev/null +++ b/forms/store/product_permutation.py @@ -0,0 +1,65 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Backend +Feature: Forms - Product Category Filters data input + +Description: +Defines Flask-WTF forms for handling product category filter input. +""" + +# internal +from business_objects.store.store_base import Store_Base +# from business_objects.store.product_category import Filters_Product_Category +# from models.model_view_store import Model_View_Store # circular +# from helpers.DEPRECATED.helper_abc import Interface_ABC +from forms.base import Form_Base +import lib.argument_validation as av +# external +from flask_wtf import FlaskForm +from wtforms import StringField, TextAreaField, SubmitField, BooleanField, IntegerField, SelectField, FloatField +from wtforms.validators import InputRequired, NumberRange, Regexp, DataRequired, Optional +from flask_wtf.recaptcha import RecaptchaField +from abc import ABCMeta, abstractmethod + + +class Filters_Product_Permutation(Form_Base): + id_category = SelectField('Category', validators=[Optional()], choices=[]) + id_product = SelectField('Product', validators=[Optional()], choices=[]) + is_out_of_stock = BooleanField('Out of stock only?') + quantity_min = FloatField('Min stock') + quantity_max = FloatField('Max stock') + # submit = SubmitField('Submit') + """ + @classmethod + def from_filters(cls, filters): + form = Filters_Product_Permutation() + form.id_category.choices = Store_Base.convert_list_objects_to_list_options(filters.categories) + form.id_product.choices = Store_Base.convert_list_objects_to_list_options(filters.products) + form.is_out_of_stock.data = filters.is_out_of_stock + form.quantity_min.data = filters.quantity_min + form.quantity_max.data = filters.quantity_max + return form + """ + def __repr__(self): + return f''' + Filters_Product_Permutation( + id_category={self.id_category.data}, + id_product={self.id_product.data}, + is_out_of_stock={self.is_out_of_stock.data}, + quantity_min={self.quantity_min.data}, + quantity_max={self.quantity_max.data}) + ''' + @classmethod + def from_json(cls, json): + form = Filters_Product_Permutation() + 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.data = json[Store_Base.ATTR_ID_PRODUCT] + form.is_out_of_stock.data = av.input_bool(json[Store_Base.FLAG_IS_OUT_OF_STOCK], 'is_out_of_stock', 'Filters_Product_Permutation') + form.quantity_min.data = json[Store_Base.FLAG_QUANTITY_MIN] + form.quantity_max.data = json[Store_Base.FLAG_QUANTITY_MAX] + return form \ No newline at end of file diff --git a/forms/unit_measurement.py b/forms/unit_measurement.py new file mode 100644 index 00000000..9f69daa4 --- /dev/null +++ b/forms/unit_measurement.py @@ -0,0 +1,42 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Backend +Feature: Forms - Unit of Measurement Filters data input + +Description: +Defines Flask-WTF forms for handling unit of measurement filter input. +""" + +# internal +from business_objects.store.store_base import Store_Base +from forms.base import Form_Base +import lib.argument_validation as av +# external +from flask_wtf import FlaskForm +from wtforms import StringField, TextAreaField, SubmitField, BooleanField, IntegerField, SelectField, FloatField +from wtforms.validators import InputRequired, NumberRange, Regexp, DataRequired, Optional +from flask_wtf.recaptcha import RecaptchaField +from abc import ABCMeta, abstractmethod + + +class Filters_Unit_Measurement(Form_Base): + active = BooleanField("Active only?") + @classmethod + def from_filters(cls, filters): + form = Filters_Unit_Measurement() + form.active.data = filters.active + return form + def __repr__(self): + return f'Filters_Unit_Measurement(active={self.active.data})' + @classmethod + def from_json(cls, json): + form = Filters_Unit_Measurement() + form.active.data = av.input_bool(json[Store_Base.FLAG_ACTIVE], 'active', 'Filters_Unit_Measurement') + return form + def to_json(self): + return { + Store_Base.FLAG_ACTIVE: av.input_bool(self.active.data, Store_Base.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json'), + } \ No newline at end of file diff --git a/models/__pycache__/model_view_base.cpython-312.pyc b/models/__pycache__/model_view_base.cpython-312.pyc index bf75e6bc250cb497a7a0f95e6175c58b6e13b2e6..8dd81654607fdecd9c737992c6458ce6df13a5f3 100644 GIT binary patch delta 6171 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 Bf`kA7 diff --git a/models/__pycache__/model_view_store.cpython-312.pyc b/models/__pycache__/model_view_store.cpython-312.pyc index b611bf85c384d19e60bfc3701fc20b1a835e4522..82faaa32afbc080ec7528b791d1988dcd55ac732 100644 GIT binary patch delta 8240 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 KCkiM@{Qn2K(jr~} delta 5404 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 diff --git a/models/__pycache__/model_view_store_product_category.cpython-312.pyc b/models/__pycache__/model_view_store_product_category.cpython-312.pyc index ef762ed111567e571334aca1a544bfc59fffbc71..7683d6e50a069afd7550a5a26c23e6a525fb83c7 100644 GIT binary patch delta 615 zcmYjOzl#$=6rR~TH@n$Pc9TnPlUxY?I+86ELC!)XL@WeBy+Y(z&|zKPjf})j9p6#dOd4s^-%z-kw9>ZUR@h25Q`dJX(a3EQ)t-@v z#oDViR3^mlEKINd=G!$YE@}f&(>mg@cDKK^3wiW3EcwF#W;F(&jwKvbJ%D_dJGj0h{8Hd1>57(h8HHDAKrml1DH?hHrlwg1XR_g4BaZX+-ZD1w|Z?}b9 z1i`!1IjbixdXVDDi+_N6=}iK`lX&q^4_-VuGrc&6$M=2a&G$RZ?pg3L^uBnWgXH@D z{9FIivDd_Jk1s!Xj8TFUi+Q{pmw6?wa6k4nv)LT4##OByHqUEuU2B&$cn}9#msrS~ zaT6m0-A0M`3?*f1yvwN+gyPo3i7F?buVK+P!WTxn8SadLlbr#}D5RuAfgfhwY%m&% zt41eibYPSm_A>IQ3j>YGy+N9Ncx~+Ea8(%QMynugr(U<$qiISQJ)$gyyky{rhvsrr zRonhP%?R%fCuDr?2Xhif7Sz?C8iAI0Y2L9LN?w#joD^2Xh2m2jidV(2wIzvC<+>;r z=&49NvHDghS>(eN@ylwP$`nlD+x5Ekv}8ZEWaOAaHi1A~w^uin`_%2RZklqM9gGr) z6!8ertVbCmB*Jh>(iF?Gb)M%-3BGt^@3|@zR39yfsuSa7!JVM|{}Vt#95}17&-6`ox!$t5ZNiV~$IDev+}5-rR6sb#aae&X1UZ8^2oM6MOt!ImMHDrr)* zcUQKhl97P~hz>p|7!>iL1swDe#6gjql3NQDE#T(RWoVa+g$)=*(W334l7CvbMbXYI zxg;AqhwfqK{mlF3y*KmT>^lQL8Fzl^aM%F)ZvSm3^B?bLP76r~UdiTVL6qP_q8pBq z-wFoi#bSCjCG+1)irJ)`Ew1oKiYsz5yCR5ijT|Fn_%ZpxM%uCD6dZy%?V3V>h;s>U z#JL-sN9Q~Z&MR~wofmV04^dqWdAGjG*Wh{tKhkwKxL#e?)8P7a&fnk|L1%j#Y(VGw zFee1l%)8(=qVTsA68dv9b-I1b5St)Fqyz6-mso*I2iq*do8TI;6nP!QLs}Gec1GcY zjz90~P9FXO3{!%@) zn&*-r7FOkYcHhb;S1xLv)s?I)@dY6%t%^cHSdq1!=R~}mEeM+Jig7ZM=4#Tsymm>D zQbc>40D4V-AtvCzO+(~06C5Gz`@Hj6GV}F43M@>>}ZoPj*)J}7>1WE-5b^vxeQX|o82f)R=E|OHQk9B z<77(Kv>tkfe4o7Gr;tV2x{mbU;Ca+=pf$HeK4?g91NcL;^>Fhz+T8uWbJ78F!#Mu% zg%14^^%$F=eE1C-T_}(n$IIME+=>?DCU7>6*c#bD2`t-6w%k6$ur*7>4R^_gve2bx z0r|-X3@rlxwgDb$6CT9i9(w~EUD~p}WY10GrNiQa-=6eCkhOF7!thKJDQL8Q09cyjhrg7=EZ32g3pDiSp1% z^-kPOL|bDOS@@}qwc=Mn459)4%QoZYFoz3IwBjKQkJ{Od0Zhiwp!H$b3(1u=9{1k% zZY)Ny-j$W=nqo%p#Ud^t&C|3p-T)EbE6phv`J99v(0WK>KN7|rVjN8(i-)~v&`1kk z5b>3QWjh0ZW@k=VjCaEQbuTp9*g>=Md@7%mB%YUW4`*8*Vegs-NCoKCBDSbx5 zmpWtpQwrUCmtOn>6R$C6D$E&WexWv>tjs5?%v+l-c(s$;m^@mWJX@JOd%rWF4v(s1 zlj>kx4G*Y;d(?hb9oVf7kE!9P%Er{#ZZ+7iCXUwP{bp#^2EX zxdT)RJ=M*RLKNz{;4$u(AAmGbCR?pM*S50LFe!l&0k@n>LTUNl?>4;|B+-sOG^!L-^75KE3`6eGlSi+f9Vh?* delta 1881 zcmb7FO>7%Q6rNeH*Xy-+x3^E?Oen)#rbek6P*I4HhlJf}^|<5O8f)pXQFjRu=1wVX1W zGUQj2+Emh*%FW2frgQ_nMa3bDKBulzs(@ayg-`obM)3~ebPAvFt0LBXL{kHb{~EYO z>fn`VR)d-Ny4*<9un5vn5wAHDtxDh;NQ8>uGE9U|f>?7ciXvhZy-fd#a`q0%dr{S< zXN`3z=d#I}3pMVNg$?~_e*(9oKbRisYa80)I5BTk&I6gYDjF_Jvb+U4PiJ_`y2NVF+S6VA$8iA zOb5E?3e6Xs4QaT%^CNJBvi1Z)9k}yF@E(_<&Vv;7S^$6oXKZePQ(UbWj}?*U6gSb+ z)ce#sK^jLCxGPxy7kCjcZ*Ar&Z`j{f%V_l(ckpQ|8espg-CH@=Icj$WU^h7lfs9DO zg$Kih%ZMoB4%@jmK#WH>-N#zm@aM0L*T9uvDruVRrG{3JbiEif63k8C&&pys&C>4{#;6*JP!|xrZU(6iiRI*)v?}IaKO7 zWOg4mg(FMs(dxkPZD9p~Ie3!#ov^di{dM*TfCEsb&?RrDLng)n8Qt{m?h8Iw2_7s3 z50-;tMfY8nUl11ai!-LsyTtZY<3pd!;cQpnIECZ)!wDq$Ivo=vJU)TOeEWx_&Wbct zl7`CCz7iWMatq_tP_#(D+w}N>w_fn^1C|6*x*MO(H}Reck@=PhO|&v88=CZsJIU*K z9VoD1+nhvePBS*_d}ifgo|6o7y93UQEmQ&fJuBX&&R+eK>8^uTC1GO&nUGs--R~rAx^u9VpbHOjtouoS1aUIMPc4!*^ z*Rtw9?G&~Vl=>hhD>ew>eTswhS_r^h%i!!XIKB+xzkpLEaB3MGT?WxL2EdMG5PnGS Pf@h$)V{i=+p`QFN(=v`> diff --git a/models/model_view_base.py b/models/model_view_base.py index 39c5235f..5c77cefc 100644 --- a/models/model_view_base.py +++ b/models/model_view_base.py @@ -23,7 +23,8 @@ from datastores.datastore_base import DataStore_Base from datastores.datastore_user import DataStore_User from business_objects.store.store_base import Store_Base from business_objects.store.product_category import Product_Category -from business_objects.store.access_level import Filters_Access_Level +from forms.access_level import Filters_Access_Level +from forms.unit_measurement import Filters_Unit_Measurement from business_objects.user import User, User_Filters # external from abc import ABC, abstractmethod @@ -56,6 +57,7 @@ class Model_View_Base(BaseModel, ABC): FLAG_COMMENT: ClassVar[str] = 'comment' FLAG_CONTAINER: ClassVar[str] = 'container' FLAG_CONTAINER_INPUT: ClassVar[str] = FLAG_CONTAINER + '-input' + FLAG_CURRENCY: ClassVar[str] = 'currency' FLAG_DELETE: ClassVar[str] = 'delete' FLAG_DESCRIPTION: ClassVar[str] = Store_Base.FLAG_DESCRIPTION FLAG_DETAIL: ClassVar[str] = 'detail' @@ -70,10 +72,12 @@ class Model_View_Base(BaseModel, ABC): FLAG_HAMBURGER: ClassVar[str] = 'hamburger' FLAG_IMAGE_LOGO: ClassVar[str] = 'image-logo' FLAG_INITIALISED: ClassVar[str] = 'initialised' - FLAG_KEY_PRIMARY: ClassVar[str] = Store_Base.FLAG_KEY_PRIMARY + # FLAG_KEY_PRIMARY: ClassVar[str] = Store_Base.FLAG_KEY_PRIMARY FLAG_MESSAGE: ClassVar[str] = 'Message' FLAG_MODAL: ClassVar[str] = 'modal' FLAG_NAME: ClassVar[str] = Store_Base.FLAG_NAME + FLAG_NAME_ATTR_OPTION_TEXT: ClassVar[str] = Store_Base.FLAG_NAME_ATTR_OPTION_TEXT + FLAG_NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.FLAG_NAME_ATTR_OPTION_VALUE FLAG_NAV_ADMIN_HOME: ClassVar[str] = 'navAdminHome' FLAG_NAV_ADMIN_STORE_STRIPE_PRICES: ClassVar[str] = 'navAdminStoreStripePrices' FLAG_NAV_ADMIN_STORE_STRIPE_PRODUCTS: ClassVar[str] = 'navAdminStoreStripeProducts' @@ -289,17 +293,45 @@ class Model_View_Base(BaseModel, ABC): return False """ - def get_many_access_level(self, filters): + def get_many_access_level(self, filters=None): _m = 'Model_View_Store.get_many_access_level' - av.val_instance(filters, 'filters', _m, Filters_Access_Level) - + # av.val_instance(filters, 'filters', _m, Filters_Access_Level) access_levels, errors = DataStore_Base.get_many_access_level(filters) - return access_levels + def get_many_unit_measurement(self, filters=None): + _m = 'Model_View_Store.get_many_unit_measurement' + # av.val_instance(filters, 'filters', _m, Filters_Unit_Measurement) + units_measurement, errors = DataStore_Base.get_many_unit_measurement(filters) + return units_measurement + + @staticmethod + def convert_list_objects_to_json(list_objects): + return [obj.to_json() for obj in list_objects] @staticmethod def convert_list_objects_to_list_options(list_objects): return Store_Base.convert_list_objects_to_list_options(list_objects) @staticmethod + def convert_list_objects_to_dict_by_attribute_key(list_objects, key): + return {getattr(obj, key): obj for obj in list_objects} + @staticmethod + def convert_list_objects_to_dict_json_by_attribute_key(list_objects, key): + return {getattr(obj, key): obj.to_json() for obj in list_objects} + @staticmethod + def convert_list_objects_to_dict_by_attribute_key_default(list_objects): + if len(list_objects) == 0: + return {} + obj_class = list_objects[0].__class__ + return Model_View_Base.convert_list_objects_to_dict_by_attribute_key(list_objects, getattr(obj_class, obj_class.FLAG_NAME_ATTR_OPTION_VALUE)) + @staticmethod + def convert_list_objects_to_dict_json_by_attribute_key_default(list_objects): + if len(list_objects) == 0: + return {} + obj_class = list_objects[0].__class__ + return Model_View_Base.convert_list_objects_to_dict_json_by_attribute_key(list_objects, getattr(obj_class, obj_class.FLAG_NAME_ATTR_OPTION_VALUE)) + @staticmethod + def convert_dict_values_to_json(dict): + return {key: dict[key].to_json() for key in dict.keys()} + @staticmethod def join_with_linebreaks(strs): str_multiline = '' for str in strs: diff --git a/models/model_view_store.py b/models/model_view_store.py index 9b19b447..70349e59 100644 --- a/models/model_view_store.py +++ b/models/model_view_store.py @@ -17,19 +17,19 @@ Parent data model for store views # IMPORTS # internal # from context import models -from models.model_view_base import Model_View_Base from business_objects.store.store_base import Store_Base from business_objects.store.product import Product, Filters_Product, Product_Permutation # Product_Image_Filters, # from business_objects.store.product_category import Filters_Product_Category from business_objects.store.image import Resolution_Level_Enum -import lib.argument_validation as av +from business_objects.store.basket import Basket_Item, Basket +from business_objects.store.product_category import Product_Category +from business_objects.store.product_variation import Product_Variation_Filters, Product_Variation from datastores.datastore_store_base import DataStore_Store_Base from datastores.datastore_user import DataStore_User from datastores.datastore_store_basket import DataStore_Store_Basket from forms.forms import Form_Basket_Edit, Form_Is_Included_VAT, Form_Delivery_Region, Form_Currency -from business_objects.store.basket import Basket_Item, Basket -from business_objects.store.product_category import Product_Category -from business_objects.store.product_variation import Product_Variation_Filters, Product_Variation +import lib.argument_validation as av +from models.model_view_base import Model_View_Base # external from flask import send_file, jsonify from flask_sqlalchemy import SQLAlchemy @@ -37,40 +37,66 @@ import locale from typing import ClassVar from abc import abstractmethod -# VARIABLE INSTANTIATION - -# CLASSES class Model_View_Store(Model_View_Base): # Global constants ATTR_FORM_TYPE: ClassVar[str] = 'form-type' - ATTR_ID_CATEGORY: ClassVar[str] = Product.ATTR_ID_PRODUCT_CATEGORY - # ATTR_ID_PRODUCT_CATEGORY : ClassVar[str] = 'id-product-category' ATTR_ID_PRODUCT : ClassVar[str] = Product.ATTR_ID_PRODUCT # 'id-product' - ATTR_ID_PERMUTATION : ClassVar[str] = Product.ATTR_ID_PRODUCT_PERMUTATION # 'id-permutation' - ATTR_ID_VARIATION : ClassVar[str] = Product_Variation.ATTR_ID_PRODUCT_VARIATION # 'id-variation' - ATTR_ID_VARIATION_TYPE : ClassVar[str] = Product_Variation.ATTR_ID_PRODUCT_VARIATION_TYPE # 'id-variation-type' - FLAG_BUTTON_BASKET_ADD : ClassVar[str] = Model_View_Base.FLAG_SUBMIT + '.buttonAdd2Basket' + ATTR_ID_PRODUCT_CATEGORY: ClassVar[str] = Product.ATTR_ID_PRODUCT_CATEGORY + ATTR_ID_PRODUCT_PERMUTATION : ClassVar[str] = Product.ATTR_ID_PRODUCT_PERMUTATION # 'id-permutation' + ATTR_ID_PRODUCT_VARIATION : ClassVar[str] = Product_Variation.ATTR_ID_PRODUCT_VARIATION # 'id-variation' + ATTR_ID_PRODUCT_VARIATION_TYPE : ClassVar[str] = Product_Variation.ATTR_ID_PRODUCT_VARIATION_TYPE # 'id-variation-type' + FLAG_BUTTON_BASKET_ADD : ClassVar[str] = Model_View_Base.FLAG_SUBMIT + '.buttonAddToBasket' FLAG_BUTTON_BUY_NOW : ClassVar[str] = 'buttonBuyNow' - FLAG_COST_LOCAL_VAT_INCL: ClassVar[str] = 'cost-local-VAT-incl' - FLAG_CURRENCY: ClassVar[str] = 'currency' + FLAG_COST_LOCAL: ClassVar[str] = Product_Permutation.FLAG_COST_LOCAL + # FLAG_COST_LOCAL_VAT_INCL: ClassVar[str] = 'cost-local-VAT-incl' + FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: ClassVar[str] = Product_Permutation.FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED + FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: ClassVar[str] = Product_Permutation.FLAG_COUNT_UNIT_MEASUREMENT_INTERVAL_RECURRENCE + FLAG_COUNT_UNIT_MEASUREMENT_PER_QUANTITY_STEP: ClassVar[str] = Product_Permutation.FLAG_COUNT_UNIT_MEASUREMENT_PER_QUANTITY_STEP + FLAG_CURRENCY_COST: ClassVar[str] = Product_Permutation.FLAG_CURRENCY_COST FLAG_DATE_CONSUMED: ClassVar[str] = 'date-consumed' FLAG_DATE_EXPIRATION: ClassVar[str] = 'date-expiration' FLAG_DATE_PURCHASED: ClassVar[str] = 'date-purchased' FLAG_DATE_RECEIVED: ClassVar[str] = 'date-received' FLAG_DATE_UNSEALED: ClassVar[str] = 'date-unsealed' + FLAG_DOES_EXPIRE_FASTER_ONCE_UNSEALED: ClassVar[str] = Product_Permutation.FLAG_DOES_EXPIRE_FASTER_ONCE_UNSEALED + FLAG_HAS_VARIATIONS: ClassVar[str] = Product_Permutation.FLAG_HAS_VARIATIONS + FLAG_ID_STRIPE_PRODUCT: ClassVar[str] = Product_Permutation.FLAG_ID_STRIPE_PRODUCT FLAG_IS_NOT_EMPTY: ClassVar[str] = Store_Base.FLAG_IS_NOT_EMPTY FLAG_IS_OUT_OF_STOCK: ClassVar[str] = 'is-out-of-stock' + FLAG_IS_SUBSCRIPTION: ClassVar[str] = Product_Permutation.FLAG_IS_SUBSCRIPTION + FLAG_LATENCY_MANUFACTURE_DAYS: ClassVar[str] = Product_Permutation.FLAG_LATENCY_MANUFACTURE_DAYS FLAG_LOCATION_STORAGE: ClassVar[str] = 'storage-location' - FLAG_PRODUCT: ClassVar[str] = 'product' - FLAG_PRODUCT_CATEGORY: ClassVar[str] = 'category' + FLAG_NAME_PLURAL_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: ClassVar[str] = Product_Permutation.FLAG_NAME_PLURAL_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED + FLAG_NAME_PLURAL_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: ClassVar[str] = Product_Permutation.FLAG_NAME_PLURAL_UNIT_MEASUREMENT_INTERVAL_RECURRENCE + FLAG_NAME_PLURAL_UNIT_MEASUREMENT_QUANTITY: ClassVar[str] = Product_Permutation.FLAG_NAME_PLURAL_UNIT_MEASUREMENT_QUANTITY + FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: ClassVar[str] = Product_Permutation.FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED + FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: ClassVar[str] = Product_Permutation.FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_INTERVAL_RECURRENCE + FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_QUANTITY: ClassVar[str] = Product_Permutation.FLAG_NAME_SINGULAR_UNIT_MEASUREMENT_QUANTITY + FLAG_PRODUCT: ClassVar[str] = Store_Base.FLAG_PRODUCT + FLAG_PRODUCT_CATEGORY: ClassVar[str] = Store_Base.FLAG_PRODUCT_CATEGORY + FLAG_PRODUCT_PERMUTATION: ClassVar[str] = Store_Base.FLAG_PRODUCT_PERMUTATION + FLAG_PRODUCT_VARIATION: ClassVar[str] = Store_Base.FLAG_PRODUCT_VARIATION + FLAG_PRODUCT_VARIATIONS: ClassVar[str] = Store_Base.FLAG_PRODUCT_VARIATIONS + FLAG_PRODUCT_VARIATION_TYPE: ClassVar[str] = Store_Base.FLAG_PRODUCT_VARIATION_TYPE + FLAG_QUANTITY: ClassVar[str] = 'quantity' FLAG_QUANTITY_MAX: ClassVar[str] = Product_Permutation.FLAG_QUANTITY_MAX # 'quantity-max' FLAG_QUANTITY_MIN: ClassVar[str] = Product_Permutation.FLAG_QUANTITY_MIN # 'quantity-min' FLAG_QUANTITY_STOCK: ClassVar[str] = Product_Permutation.FLAG_QUANTITY_STOCK # 'quantity-stock' FLAG_PLANT_STORAGE: ClassVar[str] = 'plant-storage' FLAG_PRODUCT_CATEGORY: ClassVar[str] = 'category' + FLAG_PROFIT_LOCAL_MIN: ClassVar[str] = Product_Permutation.FLAG_PROFIT_LOCAL_MIN FLAG_REGION_STORAGE: ClassVar[str] = 'region-storage' - FLAG_VARIATIONS: ClassVar[str] = 'variations' + FLAG_SYMBOL_CURRENCY_COST: ClassVar[str] = Product_Permutation.FLAG_SYMBOL_CURRENCY_COST + FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: ClassVar[str] = Product_Permutation.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED + FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: ClassVar[str] = Product_Permutation.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_INTERVAL_RECURRENCE + FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_QUANTITY: ClassVar[str] = Product_Permutation.FLAG_SYMBOL_IS_SUFFIX_NOT_PREFIX_UNIT_MEASUREMENT_QUANTITY + FLAG_SYMBOL_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: ClassVar[str] = Product_Permutation.FLAG_SYMBOL_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED + FLAG_SYMBOL_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: ClassVar[str] = Product_Permutation.FLAG_SYMBOL_UNIT_MEASUREMENT_INTERVAL_RECURRENCE + FLAG_SYMBOL_UNIT_MEASUREMENT_QUANTITY: ClassVar[str] = Product_Permutation.FLAG_SYMBOL_UNIT_MEASUREMENT_QUANTITY + FLAG_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED: ClassVar[str] = Product_Permutation.FLAG_UNIT_MEASUREMENT_INTERVAL_EXPIRATION_UNSEALED + FLAG_UNIT_MEASUREMENT_INTERVAL_RECURRENCE: ClassVar[str] = Product_Permutation.FLAG_UNIT_MEASUREMENT_INTERVAL_RECURRENCE + FLAG_UNIT_MEASUREMENT_QUANTITY: ClassVar[str] = Product_Permutation.FLAG_UNIT_MEASUREMENT_QUANTITY HASH_PAGE_STORE_BASKET : ClassVar[str] = '/store/basket' HASH_STORE_BASKET_ADD : ClassVar[str] = '/store/basket_add' HASH_STORE_BASKET_DELETE : ClassVar[str] = '/store/basket_delete' @@ -78,10 +104,10 @@ class Model_View_Store(Model_View_Base): HASH_STORE_BASKET_LOAD : ClassVar[str] = '/store/basket_load' HASH_GET_STORE_PRODUCT: ClassVar[str] = '/store/product_get' HASH_GET_STORE_PRODUCT_CATEGORY: ClassVar[str] = '/store/category_get' - HASH_SAVE_STORE_PRODUCT: ClassVar[str] = '/store/product_save' + HASH_SAVE_STORE_PRODUCT: ClassVar[str] = '/store/save_product' HASH_GET_STORE_PRODUCT_PERMUTATION: ClassVar[str] = '/store/permutation_get' - HASH_SAVE_STORE_PRODUCT_CATEGORY: ClassVar[str] = '/store/category_save' - HASH_SAVE_STORE_PRODUCT_PERMUTATION: ClassVar[str] = '/store/permutation_save' + HASH_SAVE_STORE_PRODUCT_CATEGORY: ClassVar[str] = '/store/save_category' + HASH_SAVE_STORE_PRODUCT_PERMUTATION: ClassVar[str] = '/store/save_permutation' HASH_STORE_SET_CURRENCY : ClassVar[str] = '/store/set_currency' HASH_STORE_SET_DELIVERY_REGION : ClassVar[str] = '/store/set_delivery_region' HASH_STORE_SET_IS_INCLUDED_VAT : ClassVar[str] = '/store/set_is_included_VAT' @@ -91,13 +117,14 @@ class Model_View_Store(Model_View_Base): ID_BUTTON_CHECKOUT : ClassVar[str] = 'buttonCheckout' ID_BUTTON_BASKET_ADD : ClassVar[str] = 'buttonBasketAdd' ID_BUTTON_BUY_NOW : ClassVar[str] = 'buttonBuyNow' - ID_CATEGORY_DEFAULT: ClassVar[str] = 1 + ID_PRODUCT_CATEGORY_DEFAULT: ClassVar[str] = 1 ID_CURRENCY : ClassVar[str] = Form_Currency.id_id_currency # 'id_currency' ID_CURRENCY_DEFAULT : ClassVar[str] = 1 ID_LABEL_BASKET_EMPTY : ClassVar[str] = 'basketEmpty' ID_REGION_DELIVERY : ClassVar[str] = Form_Delivery_Region.id_id_region_delivery # 'id_region_delivery' ID_REGION_DELIVERY_DEFAULT : ClassVar[str] = 1 IS_INCLUDED_VAT_DEFAULT : ClassVar[str] = True + """ KEY_BASKET : ClassVar[str] = Basket.KEY_BASKET # 'basket' # KEY_CODE_CURRENCY : ClassVar[str] = 'code_currency' # KEY_FORM : ClassVar[str] = 'form' @@ -107,11 +134,10 @@ class Model_View_Store(Model_View_Base): KEY_ID_REGION_DELIVERY : ClassVar[str] = Basket.KEY_ID_REGION_DELIVERY # 'id_region_delivery' KEY_IS_INCLUDED_VAT : ClassVar[str] = Basket.KEY_IS_INCLUDED_VAT # 'is_included_VAT' KEY_ITEMS : ClassVar[str] = Basket.KEY_ITEMS # 'items' - KEY_NAME_VARIATION : ClassVar[str] = Product_Variation.KEY_NAME_VARIATION - KEY_NAME_VARIATION_TYPE : ClassVar[str] = Product_Variation.KEY_NAME_VARIATION_TYPE KEY_PRICE : ClassVar[str] = 'price' KEY_QUANTITY : ClassVar[str] = 'quantity' KEY_VALUE_DEFAULT : ClassVar[str] = 'default' + """ TYPE_FORM_BASKET_ADD : ClassVar[str] = 'Form_Basket_Add' TYPE_FORM_BASKET_EDIT : ClassVar[str] = 'Form_Basket_Edit' # development variables @@ -136,7 +162,7 @@ class Model_View_Store(Model_View_Base): print(f'{_m}\nstarting') # av.val_str(id_user, 'id_user', _m) # return super().__new__(cls, *args, **kwargs) - # cls.FLAG_BUTTON_BASKET_ADD = cls.FLAG_BUTTON_SUBMIT + '.buttonAdd2Basket' + # cls.FLAG_BUTTON_BASKET_ADD = cls.FLAG_BUTTON_SUBMIT + '.buttonAddToBasket' return super().__new__(cls, db, info_user, app) # Model_View_Store, cls """ @property @@ -160,7 +186,7 @@ class Model_View_Store(Model_View_Base): self.is_included_VAT = is_included_VAT self.show_delivery_option = True self.form_is_included_VAT = Form_Is_Included_VAT() - regions, currencies = self.get_regions_and_currencies() + regions, currencies = self.get_many_region_and_currency() self.form_currency = Form_Currency(id_currency=self.id_currency) self.form_currency.id_currency.choices = [(currency.id_currency, f'{currency.code} - {currency.name}') for currency in currencies] self.form_currency.id_currency.data = str(self.id_currency) if len(currencies) > 0 else None @@ -410,12 +436,18 @@ class Model_View_Store(Model_View_Base): # validation conducted by server return DataStore_User().get_many_user_order(self.info_user['sub'], ids_order, n_order_max, id_checkout_session) - def get_regions_and_currencies(self): - regions, currencies = DataStore_Store_Base().get_regions_and_currencies() + def get_many_currency(self): + currencies = DataStore_Store_Base().get_many_currency() + return currencies + def get_many_region(self): + regions = DataStore_Store_Base().get_many_region() + return regions + def get_many_region_and_currency(self): + regions, currencies = DataStore_Store_Base().get_many_region_and_currency() return regions, currencies def get_many_product_variation(self, variation_filters = None): if variation_filters is None: variation_filters = Product_Variation_Filters.get_default() - variations, errors = DataStore_Store_Base().get_many_product_variation(variation_filters) - return variations, errors \ No newline at end of file + variation_types, variations, errors = DataStore_Store_Base().get_many_product_variation(variation_filters) + return variation_types, variations, errors \ No newline at end of file diff --git a/models/model_view_store_product_category.py b/models/model_view_store_product_category.py index 34645d5d..bfc47126 100644 --- a/models/model_view_store_product_category.py +++ b/models/model_view_store_product_category.py @@ -14,13 +14,13 @@ Data model for store permutations view from models.model_view_store import Model_View_Store # from datastores.datastore_store_base import DataStore_Store_Base from datastores.datastore_store_product_category import DataStore_Store_Product_Category -from business_objects.store.access_level import Filters_Access_Level from business_objects.store.product_category import Product_Category_Container # , Filters_Product_Category -from forms.forms import Form_Filters_Permutation +from forms.access_level import Filters_Access_Level +# from forms.store.product_permutation import Filters_Product_Permutation from forms.store.product_category import Filters_Product_Category # from routes import bp_home from business_objects.store.product import Product, Filters_Product, Product_Permutation -from business_objects.store.product_variation import Product_Variation_List +from business_objects.store.product_variation import Product_Variation_Container import lib.argument_validation as av # external diff --git a/models/model_view_store_product_permutation.py b/models/model_view_store_product_permutation.py index 011b3244..fcbbceef 100644 --- a/models/model_view_store_product_permutation.py +++ b/models/model_view_store_product_permutation.py @@ -14,10 +14,10 @@ Data model for store permutations view from models.model_view_store import Model_View_Store from datastores.datastore_store_product_permutation import DataStore_Store_Product_Permutation from business_objects.store.product_category import Product_Category_Container -from forms.forms import Form_Filters_Permutation +from forms.store.product_permutation import Filters_Product_Permutation # from routes import bp_home from business_objects.store.product import Product, Filters_Product, Product_Permutation -from business_objects.store.product_variation import Product_Variation_List +from business_objects.store.product_variation import Product_Variation_Container import lib.argument_validation as av # external @@ -30,51 +30,67 @@ class Model_View_Store_Product_Permutation(Model_View_Store): ID_FILTER_IS_OUT_OF_STOCK: ClassVar[str] = 'is_out_of_stock' ID_FILTER_QUANTITY_MIN: ClassVar[str] = 'quantity_min' ID_FILTER_QUANTITY_MAX: ClassVar[str] = 'quantity_max' - # ID_Form_Filters_Permutation: ClassVar[str] = 'Form_Filters_Permutation' + # ID_Filters_Product_Permutation: ClassVar[str] = 'Filters_Product_Permutation' KEY_PERMUTATIONS: ClassVar[str] = 'permutations' - category_list: Product_Category_Container = None # (str) - filters_product: Filters_Product - form_filters: Form_Filters_Permutation = None + category_list: Product_Category_Container = None + category_list_filters: Product_Category_Container = None + currencies: list = None + currency_options: list = None + filters_product: Filters_Product = None + form_filters: Filters_Product_Permutation + list_options_product: list = None permutation_blank: Product_Permutation = None - variations: Product_Variation_List = None - + units_measurement: list = None + units_measurement_time: list = None + # variation_container: Product_Variation_Container = None + variations: list = None + variation_types: list = None + @property def title(self): return 'Product Permutations' - def __init__(self, filters_product, hash_page_current=Model_View_Store.HASH_PAGE_STORE_PRODUCT_PERMUTATIONS): + def __init__(self, form_filters, hash_page_current=Model_View_Store.HASH_PAGE_STORE_PRODUCT_PERMUTATIONS): _m = 'Model_View_Store_Permutation.__init__' print(f'{_m}\nstarting...') - super().__init__(hash_page_current=hash_page_current, filters_product=filters_product) - # BaseModel.__init__(self, app=app, filters_product=filters_product, **kwargs) - self.form_filters = Form_Filters_Permutation() + super().__init__(hash_page_current=hash_page_current, form_filters=form_filters) + # self.form_filters = Filters_Product_Permutation() + filters_product = Filters_Product.from_form_filters_product_permutation(self.form_filters) datastore_store = DataStore_Store_Product_Permutation() self.category_list, errors = datastore_store.get_many_product(filters_product) - category_list_filters, errors_filters = datastore_store.get_many_product( + self.category_list_filters, errors_filters = datastore_store.get_many_product( Filters_Product( - # self.info_user['sub'], - True, False, '', - True, False, '', - True, False, '', - False, False, '', - # False, False, False, '', - # False, False, False, '', - # False, False, '', - filters_product.get_products_quantity_stock_below_min + get_all_product_category = True, + get_inactive_product_category = False, + ids_product_category = '', + get_all_product = True, + get_inactive_product = False, + ids_product = '', + get_all_permutation = True, + get_inactive_permutation = False, + ids_permutation = '', + get_all_image = False, + get_inactive_image = False, + ids_image = '', + get_products_quantity_stock_below_min = filters_product.get_products_quantity_stock_below_min ) ) - print(f'category_list_filters: {category_list_filters.categories}') - self.form_filters.id_category.choices = [('0', 'All')] + [(str(category.id_category), category.name) for category in category_list_filters.categories] + print(f'category filters: {self.category_list_filters.categories}') + self.form_filters.id_category.choices = [('0', 'All')] + [(str(category.id_category), category.name) for category in self.category_list_filters.categories] print(f'category options: {self.form_filters.id_category.choices}') - product_list = category_list_filters.to_product_option_list() - print(f'product_list: {product_list}') - self.form_filters.id_product.choices = [('0', 'All')] + [(str(product['value']), product['text']) for product in product_list] + self.list_options_product = self.category_list_filters.to_product_option_list() + print(f'product options: {self.list_options_product}') + self.form_filters.id_product.choices = [('0', 'All')] + [(str(product['value']), product['text']) for product in self.list_options_product] self.permutation_blank = Product_Permutation() print(f'category options: {self.form_filters.id_category.choices}') - variations, errors = self.get_many_product_variation() - self.variations = variations + self.variation_types, self.variations, errors = self.get_many_product_variation() + self.units_measurement = self.get_many_unit_measurement() + self.units_measurement_time = [unit_measurement for unit_measurement in self.units_measurement if unit_measurement.is_unit_of_time] + self.currencies = self.get_many_currency() + self.currency_options = [currency.to_json_option() for currency in self.currencies] - def save_permutations(self, comment, list_permutations): + @staticmethod + def save_permutations(comment, list_permutations): _m = 'Model_View_Store_Permutation.save_permutations' - DataStore_Store_Product_Permutation().save_permutations(comment, list_permutations) \ No newline at end of file + DataStore_Store_Product_Permutation.save_permutations(comment, list_permutations) \ No newline at end of file diff --git a/routes.py b/routes.py deleted file mode 100644 index d93a97ad..00000000 --- a/routes.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Project: PARTS Website -Author: Edward Middleton-Smith - Precision And Research Technology Systems Limited - -Technology: Backend -Feature: Controller - Webpage routing - -Description: -Defines the routes and view functions for each page. -Manages the interaction between the frontend and backend. -""" - -from flask import render_template, url_for, Blueprint -from app import app -from app.forms import Form_Contact -# from forms import MyForm -# from app import MyForm -from model_view_contact import Model_View_Contact - -""" -@app.route('/', methods=['GET']) -def home(): - return render_template('_home.html', title='Home') - -@app.route('/store', methods=['GET']) -def store_home(): - return render_template('_store_home.html', title='Store Home') - -@app.route('/contact', methods=['GET', 'POST']) -def contact(): - form = Form_Contact() - if form.validate_on_submit(): - # Handle form submission - email = form.sender_email.data - CC = form.sender_CC.data - name = form.sender_name.data - msg = form.sender_message.data - # return render_template('contact.html', form=form) - # return render_template('_contact.html', title='Contact Us') - return render_template('contact.html', model=Model_View_Contact(form)) - -@app.route('/about') -def about(): - return render_template('about.html') - -@app.route('/contact', methods=['GET', 'POST']) -def contact(): - form = MyForm() - if form.validate_on_submit(): - # Handle form submission - pass - return render_template('contact.html', form=form) -""" \ No newline at end of file diff --git a/routing/__pycache__/core.cpython-312.pyc b/routing/__pycache__/core.cpython-312.pyc deleted file mode 100644 index d4671612d8e8d9810649e1775c23a63dd2c4cf04..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5152 zcmdT|T}&L;6~42(v%AcKSy=vT6EntujYDuuBD*Gy(=}il$Nbcbon}fq8Fnr(+nJrs zompcjb|b3~REgA}K2XVx( zl)t*qW|U7*N0R!flV(QFg}3xdgIU8hG}D-)j_giT`K+lqzmTQ*GsmXgZFqMWIr&6Z^NrD?o#!4=|wV* zoi!$By$GXk=BeX)4ZB2C$7NsyFX6xe)k$Vss&0U7U7O8%QAUd$FOp}bI%zX6;!p?8 z?p2&I^E3x*T`!i-Gf?ZQV2#dz7aGzG(~As&pf*K2gI++N@I+e!2lGM}%z=#bX5MzG znltl`R{^?dHVtgKJDu!GkFZiU}>V?H+@@b%pZ`J66J2GW7o0sgNCZUj3F}L&SL;M;{Yd9OtZk1r^c@sPF^$Rl$+NLTkd(jr)Qiaj0y-d4xTZNc0xfsLw9c0 z3*j-?^YFG-_&GlY@)p?)iQ>`w@s@k>gA3yQXw|~xJ5~4V4i(y7TE4tm_v%8$W|&mg z7eaMk|5F6!A4CB0>V`k0Zr9wpvRd7CJ6)*m{4Cn}@6900eDi1@Xua9mLEf)O#)E%q zNXCL6ivqA8$3&q2i+{`$--_3T68`{?xD(j+kH9=w^)delmi3RIuMhld%k%Wmwtoa~ z1i62}v&28d;kl+#&j92@u;I?Z+TiT01IZB};1pHvk0txY)X~dlE)Mo#zQBSc zXCN%i9qNZ_M80T44O709>5`K)C|-O84Bp!R%Ei zIP`A$EF>+=@3!pl>F$!Kiu0)QYPl#>2CAJ^i&B8dnC-lfuDO~Q=<5S0*DQ+3iDyPu z2baarhF%z=3Mv*agc!`w99{?$^6n6guorO6OGsWuavI4iK)fivYY;MjF=`_)hEWTx z7`T;Nfve_hK>mK1J^?@H6CfD9afDGGz3Z{+wOH#)taUZk_V>D`r3;G}mPQsw76#U9 z>X#Z98<(0Fn-|WkCmNSdEuLCBy?A<|f4yPflDTNEH5^`PIJ|J~i^cj(Ol&n=%STvQ8h=mnJ)=u~0aDokYy&Gy3icZTj)#(z8b zo56RdS1ViA6D{l2&wl+ytnRyD-Z=orxOwKpnO^cqZ$)2Q@Y7&JUrX@Qy#n$rBGB?6 z@-D1<5{Q(R0+94~K;2LJ+Yqvq^zqJl+ky9zq+bry%O`yR^}VH_4mp@tdSy{vWcb>0 zfX+BPBMxpmLDW~p&cg5o_&G?>0YaE|58aEm18Uc|721Dvw|%vK^l4H15u(q{#{J}0 zMN$m@u^~xQ($GDcKhu$J_h3 zh@bwkitrj9pXW6lFFyA@KDq6E=(1j;X-sr$Y>L;C>K1WDrN8|3t@YZV7_FSC|L~>4zdzots+jc1dby9dJ?_n(ky<`IIJE=8<21a zu7s}*+#~=_KV@(NK7J_FzxeeDSBra7(1Jb=gUf3WfACR6E z((^D(s+)dab^F@AJ}Kt@a3RsYmN>bRIJw-u+{mQ|x1}%q7wL}WCN6#9VW37hin?C~X<#=yN_2Ou zB~Gm*PAw1IJ+b@>mrp$mgo}F_19@OK<0bM())FtTBwoHN-o3i~D=z=qw){`v>Oh{o H0oVB-=}F(x diff --git a/routing/store/__pycache__/product_permutation.cpython-312.pyc b/routing/store/__pycache__/product_permutation.cpython-312.pyc deleted file mode 100644 index be337c63194107e18bfd5990da05819c123d7829..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6840 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 NEW.is_subscription UNION - # Changed id_recurrence_interval - SELECT NEW.id_product, 'id_recurrence_interval', CONVERT(OLD.id_recurrence_interval, CHAR), CONVERT(NEW.id_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.id_recurrence_interval <=> NEW.id_recurrence_interval + # Changed id_unit_measurement_interval_recurrence + SELECT NEW.id_product, 'id_unit_measurement_interval_recurrence', CONVERT(OLD.id_unit_measurement_interval_recurrence, CHAR), CONVERT(NEW.id_unit_measurement_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.id_unit_measurement_interval_recurrence <=> NEW.id_unit_measurement_interval_recurrence UNION - # Changed count_recurrence_interval - SELECT NEW.id_product, 'count_recurrence_interval', CONVERT(OLD.count_recurrence_interval, CHAR), CONVERT(NEW.count_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.count_recurrence_interval <=> NEW.count_recurrence_interval + # Changed count_interval_recurrence + SELECT NEW.id_product, 'count_interval_recurrence', CONVERT(OLD.count_interval_recurrence, CHAR), CONVERT(NEW.count_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.count_interval_recurrence <=> NEW.count_interval_recurrence UNION # Changed id_stripe_product SELECT NEW.id_product, 'id_stripe_product', OLD.id_stripe_product, NEW.id_stripe_product, NEW.id_change_set @@ -3759,16 +3774,16 @@ BEGIN END IF; IF (NOT ( - NEW.id_interval_recurrence IS NULL - OR NEW.id_interval_recurrence NOT IN (SELECT id_unit_measurement FROM Shop_Unit_Measurement WHERE is_unit_of_time = 1) + NEW.id_unit_measurement_interval_recurrence IS NULL + OR NEW.id_unit_measurement_interval_recurrence NOT IN (SELECT id_unit_measurement FROM Shop_Unit_Measurement WHERE is_unit_of_time = 1) )) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Recurrence interval ID must be a unit of time.'; END IF; IF (NOT ( - NEW.id_interval_expiration_unsealed IS NULL - OR NEW.id_interval_expiration_unsealed NOT IN (SELECT id_unit_measurement FROM Shop_Unit_Measurement WHERE is_unit_of_time = 1) + NEW.id_unit_measurement_interval_expiration_unsealed IS NULL + OR NEW.id_unit_measurement_interval_expiration_unsealed NOT IN (SELECT id_unit_measurement FROM Shop_Unit_Measurement WHERE is_unit_of_time = 1) )) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Unsealed expiration interval ID must be a unit of time.'; @@ -3807,11 +3822,11 @@ BEGIN SELECT NEW.id_permutation, 'id_currency_cost', CONVERT(OLD.id_currency_cost, CHAR), CONVERT(NEW.id_currency_cost, CHAR), NEW.id_change_set WHERE NOT (OLD.id_currency_cost <=> NEW.id_currency_cost) UNION + /* # Changed profit_local_min SELECT NEW.id_permutation, 'profit_local_min', CONVERT(OLD.profit_local_min, CHAR), CONVERT(NEW.profit_local_min, CHAR), NEW.id_change_set WHERE NOT (OLD.profit_local_min <=> NEW.profit_local_min) UNION - /* # Changed id_currency_profit_min SELECT NEW.id_permutation, 'id_currency_profit_min', CONVERT(OLD.id_currency_profit_min, CHAR), CONVERT(NEW.id_currency_profit_min, CHAR), NEW.id_change_set WHERE NOT (OLD.id_currency_profit_min <=> NEW.id_currency_profit_min) @@ -3823,36 +3838,40 @@ BEGIN WHERE NOT (OLD.price_GBP_min <=> NEW.price_GBP_min) UNION */ - # Changed latency_manufacture - SELECT NEW.id_product, 'latency_manufacture', CONVERT(OLD.latency_manufacture, CHAR), CONVERT(NEW.latency_manufacture, CHAR), NEW.id_change_set - WHERE NOT OLD.latency_manufacture <=> NEW.latency_manufacture + # Changed latency_manufacture_days + SELECT NEW.id_permutation, 'latency_manufacture_days', CONVERT(OLD.latency_manufacture_days, CHAR), CONVERT(NEW.latency_manufacture_days, CHAR), NEW.id_change_set + WHERE NOT OLD.latency_manufacture_days <=> NEW.latency_manufacture_days + UNION + # Changed id_unit_measurement_quantity + SELECT NEW.id_permutation, 'id_unit_measurement_quantity', CONVERT(OLD.id_unit_measurement_quantity, CHAR), CONVERT(NEW.id_unit_measurement_quantity, CHAR), NEW.id_change_set + WHERE NOT OLD.id_unit_measurement_quantity <=> NEW.id_unit_measurement_quantity + UNION + # Changed count_unit_measurement_per_quantity_step + SELECT NEW.id_permutation, 'count_unit_measurement_per_quantity_step', CONVERT(OLD.count_unit_measurement_per_quantity_step, CHAR), CONVERT(NEW.count_unit_measurement_per_quantity_step, CHAR), NEW.id_change_set + WHERE NOT OLD.count_unit_measurement_per_quantity_step <=> NEW.count_unit_measurement_per_quantity_step UNION # Changed quantity_min - SELECT NEW.id_product, 'quantity_min', CONVERT(OLD.quantity_min, CHAR), CONVERT(NEW.quantity_min, CHAR), NEW.id_change_set + SELECT NEW.id_permutation, 'quantity_min', CONVERT(OLD.quantity_min, CHAR), CONVERT(NEW.quantity_min, CHAR), NEW.id_change_set WHERE NOT OLD.quantity_min <=> NEW.quantity_min UNION # Changed quantity_max - SELECT NEW.id_product, 'quantity_max', CONVERT(OLD.quantity_max, CHAR), CONVERT(NEW.quantity_max, CHAR), NEW.id_change_set + SELECT NEW.id_permutation, 'quantity_max', CONVERT(OLD.quantity_max, CHAR), CONVERT(NEW.quantity_max, CHAR), NEW.id_change_set WHERE NOT OLD.quantity_max <=> NEW.quantity_max UNION - # Changed quantity_step - SELECT NEW.id_product, 'quantity_step', CONVERT(OLD.quantity_step, CHAR), CONVERT(NEW.quantity_step, CHAR), NEW.id_change_set - WHERE NOT OLD.quantity_step <=> NEW.quantity_step - UNION # Changed quantity_stock - SELECT NEW.id_product, 'quantity_stock', CONVERT(OLD.quantity_stock, CHAR), CONVERT(NEW.quantity_stock, CHAR), NEW.id_change_set + SELECT NEW.id_permutation, 'quantity_stock', CONVERT(OLD.quantity_stock, CHAR), CONVERT(NEW.quantity_stock, CHAR), NEW.id_change_set WHERE NOT OLD.quantity_stock <=> NEW.quantity_stock UNION # Changed is_subscription - SELECT NEW.id_product, 'is_subscription', CONVERT(CONVERT(OLD.is_subscription, SIGNED), CHAR), CONVERT(CONVERT(NEW.is_subscription, SIGNED), CHAR), NEW.id_change_set + SELECT NEW.id_permutation, 'is_subscription', CONVERT(CONVERT(OLD.is_subscription, SIGNED), CHAR), CONVERT(CONVERT(NEW.is_subscription, SIGNED), CHAR), NEW.id_change_set WHERE NOT OLD.is_subscription <=> NEW.is_subscription UNION - # Changed id_interval_recurrence - SELECT NEW.id_product, 'id_interval_recurrence', CONVERT(OLD.id_interval_recurrence, CHAR), CONVERT(NEW.id_interval_recurrence, CHAR), NEW.id_change_set - WHERE NOT OLD.id_interval_recurrence <=> NEW.id_interval_recurrence + # Changed id_unit_measurement_interval_recurrence + SELECT NEW.id_permutation, 'id_unit_measurement_interval_recurrence', CONVERT(OLD.id_unit_measurement_interval_recurrence, CHAR), CONVERT(NEW.id_unit_measurement_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.id_unit_measurement_interval_recurrence <=> NEW.id_unit_measurement_interval_recurrence UNION # Changed count_interval_recurrence - SELECT NEW.id_product, 'count_interval_recurrence', CONVERT(OLD.count_interval_recurrence, CHAR), CONVERT(NEW.count_interval_recurrence, CHAR), NEW.id_change_set + SELECT NEW.id_permutation, 'count_interval_recurrence', CONVERT(OLD.count_interval_recurrence, CHAR), CONVERT(NEW.count_interval_recurrence, CHAR), NEW.id_change_set WHERE NOT OLD.count_interval_recurrence <=> NEW.count_interval_recurrence UNION # Changed id_stripe_product @@ -3860,24 +3879,26 @@ BEGIN WHERE NOT (OLD.id_stripe_product <=> NEW.id_stripe_product) UNION # Changed does_expire_faster_once_unsealed - SELECT NEW.id_product, 'does_expire_faster_once_unsealed', CONVERT(OLD.does_expire_faster_once_unsealed, CHAR), CONVERT(NEW.does_expire_faster_once_unsealed, CHAR), NEW.id_change_set + SELECT NEW.id_permutation, 'does_expire_faster_once_unsealed', CONVERT(OLD.does_expire_faster_once_unsealed, CHAR), CONVERT(NEW.does_expire_faster_once_unsealed, CHAR), NEW.id_change_set WHERE NOT OLD.does_expire_faster_once_unsealed <=> NEW.does_expire_faster_once_unsealed UNION - # Changed id_interval_expiration_unsealed - SELECT NEW.id_product, 'id_interval_expiration_unsealed', CONVERT(OLD.id_interval_expiration_unsealed, CHAR), CONVERT(NEW.id_interval_expiration_unsealed, CHAR), NEW.id_change_set - WHERE NOT OLD.id_interval_expiration_unsealed <=> NEW.id_interval_expiration_unsealed + # Changed id_unit_measurement_interval_expiration_unsealed + SELECT NEW.id_permutation, 'id_unit_measurement_interval_expiration_unsealed', CONVERT(OLD.id_unit_measurement_interval_expiration_unsealed, CHAR), CONVERT(NEW.id_unit_measurement_interval_expiration_unsealed, CHAR), NEW.id_change_set + WHERE NOT OLD.id_unit_measurement_interval_expiration_unsealed <=> NEW.id_unit_measurement_interval_expiration_unsealed UNION # Changed count_interval_expiration_unsealed - SELECT NEW.id_product, 'count_interval_expiration_unsealed', CONVERT(OLD.count_interval_expiration_unsealed, CHAR), CONVERT(NEW.count_interval_expiration_unsealed, CHAR), NEW.id_change_set + SELECT NEW.id_permutation, 'count_interval_expiration_unsealed', CONVERT(OLD.count_interval_expiration_unsealed, CHAR), CONVERT(NEW.count_interval_expiration_unsealed, CHAR), NEW.id_change_set WHERE NOT OLD.count_interval_expiration_unsealed <=> NEW.count_interval_expiration_unsealed UNION # Changed active SELECT NEW.id_permutation, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set WHERE NOT (OLD.active <=> NEW.active) - UNION + /* + UNION # Changed display_order SELECT NEW.id_permutation, 'display_order', CONVERT(OLD.display_order, CHAR), CONVERT(NEW.display_order, CHAR), NEW.id_change_set WHERE NOT (OLD.display_order <=> NEW.display_order) + */ ; END // DELIMITER ;; @@ -5938,6 +5959,36 @@ FROM Shop_User_Eval_Temp; */ +DROP FUNCTION IF EXISTS fn_shop_get_product_permutation_name; + +DELIMITER // + +CREATE FUNCTION fn_shop_get_product_permutation_name(id_product_permutation INT) +RETURNS VARCHAR(4000) +DETERMINISTIC +BEGIN + DECLARE name VARCHAR(4000); + + SET name := ( + SELECT + CONCAT( + P.name + , CASE WHEN P.has_variations = 1 THEN + CONCAT(' - ', GROUP_CONCAT(CONCAT(VT.name, ': ', V.name) SEPARATOR ', ')) + ELSE '' END + ) + FROM Shop_Product_Permutation PP + INNER JOIN Shop_Product P ON PP.id_product = P.id_product + INNER JOIN Shop_Product_Permutation_Variation_Link PPVL ON PP.id_permutation = PPVL.id_permutation + INNER JOIN Shop_Product_Variation V ON PPVL.id_variation = V.id_variation + INNER JOIN Shop_Product_Variation_Type VT ON V.id_type = VT.id_type + ); + + RETURN name; +END // + +DELIMITER ; + @@ -6732,6 +6783,51 @@ FROM Shop_User_Eval_Temp; +/* + +CALL p_shop_get_many_access_level ( + 0 # a_get_inactive_access_level +) + +*/ + + +-- Clear previous proc +DROP PROCEDURE IF EXISTS p_shop_get_many_access_level; + + +DELIMITER // +CREATE PROCEDURE p_shop_get_many_access_level ( + IN a_get_inactive_access_level BIT +) +BEGIN + SET a_get_inactive_access_level = IFNULL(a_get_inactive_access_level, 0); + + SELECT + AL.id_access_level, + AL.code, + AL.name, + AL.active, + AL.priority, + AL.display_order + FROM Shop_Access_Level AL + WHERE + a_get_inactive_access_level = 1 + OR AL.active = 1 + ORDER BY AL.display_order + ; +END // +DELIMITER ;; + + +/* +CALL p_shop_get_many_access_level ( + 0 # a_get_inactive_access_level +); +*/ + + + /* CALL p_shop_get_many_region ( @@ -6803,9 +6899,10 @@ BEGIN C.id_currency, C.code, C.name, + C.symbol, C.factor_from_GBP, - C.active, - C.display_order + C.display_order, + C.active FROM Shop_Currency C WHERE a_get_inactive_currency OR C.active @@ -6821,8 +6918,47 @@ CALL p_shop_get_many_currency ( ); */ +-- Clear previous proc +DROP PROCEDURE IF EXISTS p_shop_get_many_unit_measurement; +DELIMITER // +CREATE PROCEDURE p_shop_get_many_unit_measurement ( + IN a_get_inactive_unit_measurement BIT +) +BEGIN + SET a_get_inactive_unit_measurement := IFNULL(a_get_inactive_unit_measurement, 0); + + SELECT + UM.id_unit_measurement, + UM.name_singular, + UM.name_plural, + UM.symbol, + UM.symbol_is_suffix_not_prefix, + UM.is_base_unit, + UM.is_unit_of_distance, + UM.is_unit_of_mass, + UM.is_unit_of_time, + UM.is_unit_of_volume, + UM.active + FROM Shop_Unit_Measurement UM + WHERE + a_get_inactive_unit_measurement = 1 + OR UM.active = 1 + ; +END // +DELIMITER ;; + + +/* +CALL p_shop_get_many_unit_measurement ( + 0 # a_get_inactive_unit_measurement +); + +select * +from shop_unit_measurement +*/ + -- Clear previous proc DROP PROCEDURE IF EXISTS p_save_category; @@ -6897,6 +7033,7 @@ BEGIN , code VARCHAR(50) NOT NULL , name VARCHAR(255) NOT NULL , description VARCHAR(4000) NULL + , id_access_level_required INT NOT NULL , active BIT NOT NULL , display_order INT NOT NULL , can_view BIT NULL @@ -6921,6 +7058,7 @@ BEGIN , code , name , description + , id_access_level_required , active , display_order , name_error @@ -6931,6 +7069,7 @@ BEGIN , IFNULL(PC_T.code, PC.code) AS code , IFNULL(PC_T.name, PC.code) AS name , IFNULL(PC_T.description, PC.description) AS description + , IFNULL(PC_T.id_access_level_required, PC.id_access_level_required) AS id_access_level_required , IFNULL(PC_T.active, PC.active) AS active , IFNULL(PC_T.display_order, PC.display_order) AS display_order , IFNULL(PC_T.name, IFNULL(PC.name, IFNULL(PC_T.code, IFNULL(PC.code, IFNULL(PC_T.id_category, '(No Product Category)'))))) AS name_error @@ -6940,9 +7079,6 @@ BEGIN WHERE PC_T.guid = a_guid ; - SELECT * - FROM tmp_Category; - -- Validation -- Missing mandatory fields -- code @@ -7045,6 +7181,7 @@ BEGIN , PC.code = t_C.code , PC.name = t_C.name , PC.description = t_C.description + , PC.id_access_level_required = t_C.id_access_level_required , PC.active = t_C.active , PC.display_order = t_C.display_order , PC.id_change_set = v_id_change_set @@ -7055,6 +7192,7 @@ BEGIN code , name , description + , id_access_level_required , active , display_order , created_by @@ -7065,6 +7203,7 @@ BEGIN t_C.code AS code , t_C.name AS name , t_C.description AS description + , t_C.id_access_level_required AS id_access_level_required , t_C.active AS active , t_C.display_order AS display_order , a_id_user AS created_by @@ -7680,10 +7819,10 @@ BEGIN DROP TEMPORARY TABLE IF EXISTS tmp_Permutation; DROP TEMPORARY TABLE IF EXISTS tmp_Product; DROP TEMPORARY TABLE IF EXISTS tmp_Image; - DROP TEMPORARY TABLE IF EXISTS tmp_Shop_Image; - DROP TEMPORARY TABLE IF EXISTS tmp_Shop_Product; - DROP TEMPORARY TABLE IF EXISTS tmp_Shop_Product_2; - DROP TEMPORARY TABLE IF EXISTS tmp_Shop_Product_Copy; + DROP TEMPORARY TABLE IF EXISTS tmp_Image; + DROP TEMPORARY TABLE IF EXISTS tmp_Product; + DROP TEMPORARY TABLE IF EXISTS tmp_Product_2; + DROP TEMPORARY TABLE IF EXISTS tmp_Product_Copy; CREATE TEMPORARY TABLE tmp_Category ( @@ -7693,23 +7832,23 @@ BEGIN ); CREATE TEMPORARY TABLE tmp_Product ( - -- id_category INT NOT NULL, + id_category INT NOT NULL, id_product INT NOT NULL, active BIT NOT NULL, - display_order INT NOT NULL - ); - - CREATE TEMPORARY TABLE tmp_Permutation ( - -- id_category INT NOT NULL, - id_product INT NOT NULL, - id_permutation INT NULL, - active BIT NOT NULL, display_order INT NOT NULL, can_view BIT, can_edit BIT, can_admin BIT ); + CREATE TEMPORARY TABLE tmp_Permutation ( + id_permutation INT NULL + -- id_category INT NOT NULL, + , id_product INT NOT NULL + , active BIT NOT NULL + -- , display_order INT NOT NULL + ); + CREATE TEMPORARY TABLE tmp_Image ( id_image INT NOT NULL, -- id_product INT NOT NULL, @@ -7760,13 +7899,13 @@ BEGIN ; INSERT INTO tmp_Product ( - -- id_category, + id_category, id_product, active, display_order ) SELECT - -- P.id_category, + P.id_category, P.id_product, P.active, P.display_order @@ -7786,18 +7925,18 @@ BEGIN ; INSERT INTO tmp_Permutation ( + id_permutation -- id_category, - id_product, - id_permutation, - active, - display_order + , id_product + , active + -- , display_order ) SELECT + PP.id_permutation -- P.id_category, - PP.id_product, - PP.id_permutation, - PP.active, - PP.display_order + , PP.id_product + , PP.active + -- , RANK() OVER (ORDER BY VT.display_order, V.display_order) FROM Shop_Product_Permutation PP INNER JOIN tmp_Product t_P ON PP.id_product = t_P.id_product WHERE ( @@ -7817,12 +7956,10 @@ BEGIN ) ; - select 'nips'; - # Product Images - -- CREATE TEMPORARY TABLE tmp_Shop_Product_Copy SELECT * FROM tmp_Shop_Product; + -- CREATE TEMPORARY TABLE tmp_Product_Copy SELECT * FROM tmp_Product; - INSERT INTO tmp_Shop_Image ( + INSERT INTO tmp_Image ( -- id_product id_permutation , id_image @@ -7837,7 +7974,7 @@ BEGIN , t_P.id_permutation , t_P.product_has_variations , t_P.rank_permutation - FROM tmp_Shop_Product t_P + FROM tmp_Product t_P ) */ SELECT @@ -7848,49 +7985,26 @@ BEGIN , I.display_order -- , RANK() OVER (PARTITION BY IPP.id_product, IPP.id_permutation ORDER BY IPP.display_order_product_temp, IPP.display_order_image) FROM Shop_Product_Image I - INNER JOIN tmp_Shop_Product t_P - ON I.id_permutation = t_P.id_permutation - AND NOT t_P.product_has_variations - /* - FROM ( - SELECT - -- t_P.id_product - I.id_permutation - , I.id_image - , I.active - , I.display_order AS display_order_image - -- , t_P.rank_permutation AS display_order_product_temp - FROM Shop_Product_Image I - INNER JOIN tmp_Shop_Product t_P - ON I.id_permutation = t_P.id_permutation - AND NOT t_P.product_has_variations - - UNION - SELECT - -- t_P2_Copy.id_product - I.id_permutation - , I.id_image - , I.active - , I.display_order AS display_order_image - -- , t_P2.rank_permutation AS display_order_product_temp - FROM Shop_Product_Image I - INNER JOIN tmp_Shop_Product_Copy t_P_Copy - ON I.id_permutation = t_P_Copy.id_permutation - AND t_P_Copy.product_has_variations - ) IPP - */ - WHERE (a_get_all_image OR FIND_IN_SET(id_image, a_ids_image) > 0) - AND (a_get_inactive_image OR I.active) + INNER JOIN tmp_Permutation t_PP ON I.id_permutation = t_PP.id_permutation + INNER JOIN Shop_Product P ON t_PP.id_product = P.id_product + WHERE + P.has_variations = 0 + AND ( + a_get_all_image = 1 OR + FIND_IN_SET(id_image, a_ids_image) > 0 + ) + AND ( + a_get_inactive_image = 1 + OR I.active = 1 + ) ; - select 'nips'; - -- Permissions - IF EXISTS (SELECT * FROM tmp_Shop_Product LIMIT 1) THEN + IF EXISTS (SELECT * FROM tmp_Product LIMIT 1) THEN # SET v_id_user := (SELECT id_user FROM Shop_User WHERE name = CURRENT_USER()); SET v_id_permission_product := (SELECT id_permission FROM Shop_Permission WHERE code = 'STORE_PRODUCT' LIMIT 1); - SET v_ids_product_permission := (SELECT GROUP_CONCAT(id_product SEPARATOR ',') FROM tmp_Shop_Product WHERE NOT ISNULL(id_product)); - -- SET v_ids_permutation_permission := (SELECT GROUP_CONCAT(id_permutation SEPARATOR ',') FROM tmp_Shop_Product WHERE NOT ISNULL(id_permutation)); + SET v_ids_product_permission := (SELECT GROUP_CONCAT(id_product SEPARATOR ',') FROM tmp_Product WHERE NOT ISNULL(id_product)); + -- SET v_ids_permutation_permission := (SELECT GROUP_CONCAT(id_permutation SEPARATOR ',') FROM tmp_Product WHERE NOT ISNULL(id_permutation)); -- SELECT v_guid, a_id_user, false, v_id_permission_product, v_id_access_level_view, v_ids_product_permission; -- select * from Shop_User_Eval_Temp; @@ -7908,18 +8022,18 @@ BEGIN t_P.can_admin = UE_T.can_admin ; -- select * from Shop_User_Eval_Temp; - -- select * from tmp_Shop_Product; + -- select * from tmp_Product; SET v_ids_product_invalid := ( - SELECT GROUP_CONCAT(UET.id_product SEPARATOR ',') - FROM tmp_Product P + SELECT GROUP_CONCAT(t_P.id_product SEPARATOR ',') + FROM tmp_Product t_P WHERE ISNULL(t_P.can_view) ); DELETE -- t_PC FROM tmp_Category t_PC WHERE t_PC.id_category IN ( - SELECT id_category + SELECT PC.id_category FROM Shop_Product_Category PC INNER JOIN Shop_Product P ON PC.id_category = P.id_category WHERE FIND_IN_SET(P.id_product, v_ids_product_invalid) > 0 @@ -7945,9 +8059,7 @@ BEGIN */ END IF; - select 'nips'; - - -- select * from tmp_Shop_Product; + -- select * from tmp_Product; -- Returns -- SET v_now := NOW(); @@ -7959,15 +8071,18 @@ BEGIN , PC.code , PC.name , PC.description + , PC.id_access_level_required + , AL.name AS name_access_level_required , PC.display_order , PC.active , MIN(t_P.can_view) AS can_view , MIN(t_P.can_edit) AS can_edit , MIN(t_P.can_admin) AS can_admin FROM tmp_Category t_C - INNER JOIN Shop_product_category PC - ON t_P.id_category = PC.id_category - -- GROUP BY t_P.id_category + INNER JOIN Shop_Product_Category PC ON t_C.id_category = PC.id_category + LEFT JOIN tmp_Product t_P ON t_C.id_category = t_P.id_product + INNER JOIN Shop_Access_Level AL ON PC.id_access_level_required = AL.id_access_level + GROUP BY t_C.id_category -- , t_P.id_product ORDER BY PC.display_order ; @@ -7976,24 +8091,20 @@ BEGIN t_P.id_product, P.id_category, P.name, - P.description, P.has_variations, - P.latency_manufacture, - P.quantity_min, - P.quantity_max, - P.quantity_step, - P.quantity_stock, - P.id_stripe_product, - P.is_subscription, + P.id_access_level_required, + AL.name AS name_access_level_required, P.active, P.display_order, t_P.can_view, t_P.can_edit, t_P.can_admin - FROM tmp_Shop_Product t_P + FROM tmp_Product t_P INNER JOIN Shop_Product P ON t_P.id_product = P.id_product - GROUP BY C.id_category, P.id_product - ORDER BY PC.display_order, P.display_order + INNER JOIN tmp_Category t_C ON t_P.id_category = t_C.id_category + INNER JOIN Shop_Access_Level AL ON P.id_access_level_required = AL.id_access_level + GROUP BY t_P.id_category, t_C.display_order, t_P.id_product, t_P.can_view, t_P.can_edit, t_P.can_admin + ORDER BY t_C.display_order, P.display_order ; # Product Permutations @@ -8001,47 +8112,73 @@ BEGIN t_PP.id_permutation, PP.id_product, P.id_category, + PP.description, PP.cost_local, PP.id_currency_cost, C.code AS code_currency_cost, C.symbol AS symbol_currency_cost, - PP.profit_local_min, - P.is_subscription, - UM.name_singular AS name_recurrence_interval, - UM.name_plural AS name_plural_recurrence_interval, + -- PP.profit_local_min, + PP.latency_manufacture_days, + PP.id_unit_measurement_quantity, + UM_Q.symbol AS symbol_unit_measurement_quantity, + UM_Q.symbol_is_suffix_not_prefix AS symbol_is_suffix_not_prefix_unit_measurement_quantity, + UM_Q.name_singular AS name_singular_unit_measurement_quantity, + UM_Q.name_plural AS name_plural_unit_measurement_quantity, + PP.count_unit_measurement_per_quantity_step, + PP.quantity_min, + PP.quantity_max, + PP.quantity_stock, + PP.is_subscription, + PP.id_unit_measurement_interval_recurrence, + UM_R.symbol AS symbol_unit_measurement_interval_recurrence, + UM_R.symbol_is_suffix_not_prefix AS symbol_is_suffix_not_prefix_unit_measurement_interval_recurrence, + UM_R.name_singular AS name_singular_unit_measurement_interval_recurrence, + UM_R.name_plural AS name_plural_unit_measurement_interval_recurrence, PP.count_interval_recurrence, - t_PP.active, - t_PP.display_order, - IFNULL(t_PP.can_view, 0) AS can_view, - IFNULL(t_PP.can_edit, 0) AS can_edit, - IFNULL(t_PP.can_admin, 0) AS can_admin - FROM tmp_Shop_Product_Permutation t_PP + PP.id_stripe_product, + PP.does_expire_faster_once_unsealed, + PP.id_unit_measurement_interval_expiration_unsealed, + UM_X.symbol AS symbol_unit_measurement_interval_expiration_unsealed, + UM_X.symbol_is_suffix_not_prefix AS symbol_is_suffix_not_prefix_unit_measurement_interval_expiration_unsealed, + UM_X.name_singular AS name_singular_unit_measurement_interval_expiration_unsealed, + UM_X.name_plural AS name_plural_unit_measurement_interval_expiration_unsealed, + PP.count_interval_expiration_unsealed, + NOT ISNULL(PPVL.id_permutation) AS has_variations, + PP.active, + -- PP.display_order, + IFNULL(t_P.can_view, 0) AS can_view, + IFNULL(t_P.can_edit, 0) AS can_edit, + IFNULL(t_P.can_admin, 0) AS can_admin + FROM tmp_Permutation t_PP INNER JOIN Shop_Product_Permutation PP ON t_PP.id_permutation = PP.id_permutation + INNER JOIN tmp_Product t_P ON t_PP.id_product = t_P.id_product INNER JOIN Shop_Product P ON t_PP.id_product = P.id_product INNER JOIN Shop_Product_Category PC ON P.id_category = PC.id_category - -- LEFT JOIN Shop_Recurrence_Interval RI ON t_P.id_interval_recurrence = RI.id_interval - LEFT JOIN Shop_Unit_Measurement UM ON PP.id_interval_recurrence = UM.id_unit_measurement + LEFT JOIN Shop_Product_Permutation_Variation_Link PPVL ON PP.id_permutation = PPVL.id_permutation + LEFT JOIN Shop_Unit_Measurement UM_Q ON PP.id_unit_measurement_quantity = UM_Q.id_unit_measurement + LEFT JOIN Shop_Unit_Measurement UM_R ON PP.id_unit_measurement_interval_recurrence = UM_R.id_unit_measurement + LEFT JOIN Shop_Unit_Measurement UM_X ON PP.id_unit_measurement_interval_expiration_unsealed = UM_X.id_unit_measurement INNER JOIN Shop_Currency C ON PP.id_currency_cost = C.id_currency - GROUP BY C.id_category, P.id_product, PP.id_permutation - ORDER BY PC.display_order, P.display_order, PP.display_order + GROUP BY PC.id_category, P.id_product, PP.id_permutation, t_P.can_view, t_P.can_edit, t_P.can_admin + ORDER BY PC.display_order, P.display_order -- , t_PP.display_order ; # Variations SELECT V.id_variation + , V.id_type , V.code AS code_variation , V.name AS name_variation + , V.display_order AS display_order_variation , V.active AS active_variation - , V.display_order - , V.id_type , VT.code AS code_variation_type , VT.name AS name_variation_type , VT.name_plural AS name_plural_variation_type + , VT.display_order AS display_order_variation_type , VT.active AS active_variation_type - , VT.display_order , t_P.id_product - , t_P.id_permutation - , t_P.id_category + , t_PP.id_permutation + , t_C.id_category FROM Shop_Variation V INNER JOIN Shop_Variation_Type VT ON V.id_type = VT.id_type INNER JOIN Shop_Product_Permutation_Variation_Link PPVL ON V.id_variation = PPVL.id_variation @@ -8059,7 +8196,7 @@ BEGIN t_P.id_category, id_variation FROM Shop_Product_Permutation_Variation_Link PPVL - INNER JOIN tmp_Shop_Product t_P + INNER JOIN tmp_Product t_P ON t_P.id_permutation = PPVL.id_permutation ORDER BY t_P.display_order ; @@ -8069,24 +8206,24 @@ BEGIN /* select * from tmp_Currency; select * from tmp_delivery_region; - select * from tmp_shop_product; + select * from tmp_product; */ # Images SELECT t_I.id_image, - t_P.id_product, + t_PP.id_product, t_I.id_permutation, - t_P.id_category, + t_C.id_category, I.url, I.active, I.display_order - FROM tmp_Shop_Image t_I - INNER JOIN Shop_Product_Image I - ON t_I.id_image = I.id_image - INNER JOIN tmp_Shop_Product t_P - ON t_I.id_permutation = t_P.id_permutation - ORDER BY t_P.rank_permutation, I.display_order + FROM tmp_Image t_I + INNER JOIN Shop_Product_Image I ON t_I.id_image = I.id_image + INNER JOIN tmp_Permutation t_PP ON t_I.id_permutation = t_PP.id_permutation + INNER JOIN tmp_Product t_P ON t_PP.id_product = t_P.id_product + INNER JOIN tmp_Category t_C ON t_P.id_category = t_C.id_category + ORDER BY t_C.display_order, t_P.display_order, I.display_order ; # Errors @@ -8121,22 +8258,23 @@ BEGIN */ # select 'other outputs'; - # select * from tmp_Shop_Product; + # select * from tmp_Product; -- Clean up DROP TEMPORARY TABLE IF EXISTS tmp_Image; - DROP TEMPORARY TABLE IF EXISTS tmp_Shop_Image; + DROP TEMPORARY TABLE IF EXISTS tmp_Image; DROP TEMPORARY TABLE IF EXISTS tmp_Category; DROP TEMPORARY TABLE IF EXISTS tmp_Permutation; DROP TEMPORARY TABLE IF EXISTS tmp_Product; - DROP TEMPORARY TABLE IF EXISTS tmp_Shop_Product; - DROP TEMPORARY TABLE IF EXISTS tmp_Shop_Product_2; - DROP TEMPORARY TABLE IF EXISTS tmp_Shop_Product_Copy; + DROP TEMPORARY TABLE IF EXISTS tmp_Product; + DROP TEMPORARY TABLE IF EXISTS tmp_Product_2; + DROP TEMPORARY TABLE IF EXISTS tmp_Product_Copy; END // DELIMITER ;; +/* CALL partsltd_prod.p_shop_get_many_product ( 1 #'auth0|6582b95c895d09a70ba10fef', # a_id_user @@ -8154,10 +8292,10 @@ CALL partsltd_prod.p_shop_get_many_product ( , '' # a_ids_image , 1 # a_get_products_quantity_stock_below_minimum ); -/* select * FROM Shop_User_Eval_Temp; +select * from Shop_Product_Category; select * from Shop_Product_Permutation; select * from shop_product_change_set; insert into shop_product_change_set ( comment ) values ('set stock quantities below minimum for testing'); @@ -8494,544 +8632,483 @@ CALL p_shop_user_eval ( */ - - -- Clear previous proc DROP PROCEDURE IF EXISTS p_shop_save_permutation; - -DROP TABLE IF EXISTS tmp_Shop_Manufacturing_Purchase_Order_Product_Link; -DROP TABLE IF EXISTS tmp_Msg_Error; +DROP PROCEDURE IF EXISTS p_shop_save_product_permutation; DELIMITER // -CREATE PROCEDURE p_shop_save_permutation ( +CREATE PROCEDURE p_shop_save_product_permutation ( IN a_guid VARCHAR(500), IN a_id_user INT, - IN a_id_order INT, - -- IN a_id_supplier_ordered INT, - IN a_id_currency_cost INT, - IN a_active BIT, IN a_comment VARCHAR(500) ) BEGIN - DECLARE v_id_error_type_bad_data INT; - DECLARE v_code_error_type_bad_data VARCHAR(50); - DECLARE v_id_error_type_no_permission INT; - DECLARE v_code_error_type_no_permission VARCHAR(50); - DECLARE v_guid_permission BINARY(36); - -- DECLARE v_id_user VARCHAR(100); - DECLARE v_id_permission_manufacturing_purchase_order INT; - DECLARE v_id_access_level_EDIT INT; - DECLARE v_ids_product VARCHAR(4000); - DECLARE v_ids_product_no_permission VARCHAR(4000); - -- DECLARE v_id_order_new INT; + + DECLARE v_code_type_error_bad_data VARCHAR(100); + DECLARE v_id_type_error_bad_data INT; + DECLARE v_id_permission_product INT; + DECLARE v_ids_product_permission LONGTEXT; DECLARE v_id_change_set INT; - DECLARE v_is_new_manufacturing_purchase_order BIT; + DECLARE v_id_access_level_edit INT; + DECLARE v_now TIMESTAMP; - SET SESSION sql_mode = sys.list_drop(@@session.sql_mode, 'ONLY_FULL_GROUP_BY'); - - SET v_code_error_type_bad_data = 'BAD_DATA'; - SET v_id_error_type_bad_data := (SELECT id_type FROM Shop_Msg_Error_Type WHERE code = v_code_error_type_bad_data LIMIT 1); - SET v_code_error_type_no_permission = 'NO_PERMISSION'; - SET v_id_error_type_no_permission := (SELECT id_type FROM Shop_Msg_Error_Type WHERE code = v_code_error_type_no_permission LIMIT 1); - SET v_guid_permission = UUID(); - -- SET v_id_user = CURRENT_USER(); - SET v_id_permission_manufacturing_purchase_order := (SELECT id_permission FROM Shop_Permission WHERE code = 'STORE_MANUFACTURING_PURCHASE_ORDER' LIMIT 1); - SET v_id_access_level_EDIT := (SELECT id_access_level FROM Shop_Access_Level WHERE code = 'EDIT'); - - -- Argument default values - IF a_guid IS NULL THEN - SET a_guid = UUID(); - END IF; - IF a_active IS NULL THEN - SET a_active = 0; - END IF; - - -- Temporary tables - /* - CREATE TABLE tmp_Shop_Supplier_Purchase_Order ( - id_order INT NOT NULL PRIMARY KEY, - id_supplier_ordered INT NOT NULL, - CONSTRAINT FK_tmp_Shop_Supplier_Purchase_Order_id_supplier_ordered - FOREIGN KEY (id_supplier_ordered) - REFERENCES Shop_Supplier(id_supplier), - cost_total_local FLOAT NOT NULL, - id_currency_cost INT NOT NULL - ); - */ - - CREATE TABLE tmp_Shop_Manufacturing_Purchase_Order_Product_Link ( - id_link INT NOT NULL PRIMARY KEY, - id_order INT NOT NULL, - /* - CONSTRAINT FK_tmp_Supplier_Purchase_Order_Product_Link_id_order - FOREIGN KEY (id_order) - REFERENCES Shop_Manufacturing_Purchase_Order(id_order), - */ - id_permutation INT NOT NULL, - CONSTRAINT FK_tmp_Manuf_Purch_Order_Product_Link_id_permutation - FOREIGN KEY (id_permutation) - REFERENCES Shop_Product_Permutation(id_permutation), - cost_total_local FLOAT NOT NULL, - id_currency_cost INT NOT NULL, - value_produced_total_local FLOAT NOT NULL, - quantity_used FLOAT NOT NULL, - id_unit_quantity INT NOT NULL, - CONSTRAINT FK_tmp_Manuf_Purch_Order_Product_Link_id_unit_quantity - FOREIGN KEY (id_unit_quantity) - REFERENCES Shop_Unit_Measurement(id_unit_measurement), - quantity_produced FLOAT NULL, - latency_manufacture_days INT NOT NULL, - display_order INT NOT NULL, - active BIT NOT NULL, - name_error VARCHAR(200) NOT NULL - ); - - CREATE TABLE IF NOT EXISTS tmp_Msg_Error ( - display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT, - guid BINARY(36) NOT NULL, - id_type INT NOT NULL, - CONSTRAINT FK_tmp_Msg_Error_id_type - FOREIGN KEY (id_type) - REFERENCES Shop_Msg_Error_Type (id_type), - code VARCHAR(50) NOT NULL, - msg VARCHAR(4000) NOT NULL - ); - - - -- Argument validation - # User ID - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - IF ISNULL(a_id_user) OR NOT EXISTS (SELECT * FROM Shop_User WHERE id_user = a_id_user) THEN - INSERT INTO tmp_Msg_Error ( - guid, id_type, code, msg - ) - VALUES - (a_guid, v_id_error_type_bad_data, v_code_error_type_bad_data, CONCAT('Invalid User ID: ', IFNULL(a_id_user, 'NULL'))) - ; - END IF; - END IF; - - # Order ID - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - IF ISNULL(a_id_order) OR ((a_id_order > 0) AND NOT EXISTS (SELECT * FROM Shop_Manufacturing_Purchase_Order WHERE id_order = a_id_order)) THEN - INSERT INTO tmp_Msg_Error ( - guid, id_type, code, msg - ) - VALUES - (a_guid, v_id_error_type_bad_data, v_code_error_type_bad_data, CONCAT('Invalid Manufacturing Purchase Order ID: ', IFNULL(a_id_order, 'NULL'))) - ; - END IF; - END IF; - - /* - # Supplier ID - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - IF ISNULL(a_id_supplier_ordered) OR NOT EXISTS (SELECT * FROM Shop_Supplier WHERE id_supplier = a_id_supplier_ordered) THEN - INSERT INTO tmp_Msg_Error ( - guid, id_type, code, msg - ) - VALUES - (a_guid, v_id_error_type_bad_data, v_code_error_type_bad_data, CONCAT('Invalid supplier ID: ', IFNULL(a_id_supplier_ordered, 'NULL'))) - ; - END IF; - END IF; - */ - - # Currency ID - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - IF ISNULL(a_id_currency_cost) OR NOT EXISTS (SELECT * FROM Shop_Currency WHERE id_currency = a_id_currency_cost) THEN - INSERT INTO tmp_Msg_Error ( - guid, id_type, code, msg - ) - VALUES - (a_guid, v_id_error_type_bad_data, v_code_error_type_bad_data, CONCAT('Invalid currency ID: ', IFNULL(a_id_currency, 'NULL'))) - ; - END IF; - END IF; - - # Comment - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - IF ISNULL(a_comment) OR TRIM(a_comment) = '' THEN - INSERT INTO tmp_Msg_Error ( - guid, id_type, code, msg - ) - VALUES - (a_guid, v_id_error_type_bad_data, v_code_error_type_bad_data, 'A comment must be provided.') - ; - END IF; - END IF; - - - -- Get data from Temp table - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - SET v_is_new_manufacturing_purchase_order := CASE WHEN a_id_order <= 0 THEN 1 ELSE 0 END; - - INSERT INTO tmp_Shop_Manufacturing_Purchase_Order_Product_Link ( - id_link, - id_order, - id_permutation, - cost_total_local, - id_currency_cost, - quantity_used, - id_unit_quantity, - quantity_produced, - value_produced_total_local, - latency_manufacture_days, - display_order, - active, - name_error + DECLARE exit handler for SQLEXCEPTION + BEGIN + -- Get diagnostic information + GET DIAGNOSTICS CONDITION 1 + @sqlstate = RETURNED_SQLSTATE + , @errno = MYSQL_ERRNO + , @text = MESSAGE_TEXT + ; + + -- Rollback the transaction + ROLLBACK; + + -- Select the error information + -- SELECT 'Error' AS status, @errno AS error_code, @sqlstate AS sql_state, @text AS message; + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error ( + display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , guid BINARY(36) NOT NULL + , id_type INT NULL + , code VARCHAR(50) NOT NULL + , msg VARCHAR(4000) NOT NULL + ); + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , code + , msg ) - /* - VALUES - (a_id_supplier, a_name_company, a_name_contact, a_department_contact, a_id_address, a_phone_number, a_fax, a_email, a_website, a_id_currency, a_active) - */ - SELECT - MPOPL_T.id_link, - MPOPL_T.id_order, - MPOPL_T.id_permutation, - PP.cost_local * MPOPL_T.quantity_used AS cost_total_local, - MPOPL_T.id_currency_cost, - MPOPL_T.quantity_used, - MPOPL_T.id_unit_quantity, - MPOPL_T.quantity_produced, - (PP.cost_local + PP.profit_local_min) * MPOPL_T.quantity_produced AS value_produced_total_local, - MPOPL_T.latency_manufacture_days, - MPOPL_T.display_order, - MPOPL_T.active, - CONCAT(PP.id_permutation, ' - ', IFNULL(P.name ,'')) AS name_error - FROM Shop_Manufacturing_Purchase_Order_Product_Link_Temp MPOPL_T - INNER JOIN Shop_Product_Permutation PP ON MPOPL_T.id_permutation = PP.id_permutation - INNER JOIN Shop_Product P ON PP.id_product = P.id_product - WHERE MPOPL_T.GUID = a_guid - -- GROUP BY MPOPL_T.id_order, name_error, MPOPL_T.id_link - /* - group by - MPOPL_T.id_link, - MPOPL_T.id_order, - MPOPL_T.id_permutation, - cost_total_local, - MPOPL_T.id_currency_cost, - MPOPL_T.quantity_used, - MPOPL_T.id_unit_quantity, - MPOPL_T.quantity_produced, - value_produced_total_local, - MPOPL_T.latency_manufacture_days, - MPOPL_T.display_order, - MPOPL_T.active, - name_error - */ - -- GROUP BY id_link, P.id_product, PP.id_permutation - -- GROUP BY name_error, ID_LINK, cost_total_local, value_produced_total_local - ; - DELETE MPOPL_T - FROM Shop_Manufacturing_Purchase_Order_Product_Link_Temp MPOPL_T - WHERE MPOPL_T.GUID = a_guid - ; + SELECT + a_guid + , NULL + , @errno + , @text + ; + SELECT * + FROM tmp_Msg_Error; + DROP TABLE IF EXISTS tmp_Msg_Error; + END; + + SET v_code_type_error_bad_data := 'BAD_DATA'; + SET v_id_type_error_bad_data := (SELECT id_type FROM Shop_Msg_Error_Type WHERE code = v_code_type_error_bad_data LIMIT 1); + SET v_id_access_level_edit := (SELECT id_access_level FROM Shop_Access_Level WHERE code = 'EDIT' LIMIT 1); + + SET a_guid := IFNULL(a_guid, UUID()); + + DROP TABLE IF EXISTS tmp_Permutation; + + CREATE TEMPORARY TABLE tmp_Permutation ( + id_permutation INT NOT NULL + , id_product INT NOT NULL + , description VARCHAR(4000) NOT NULL + , cost_local FLOAT NOT NULL + , id_currency_cost INT NOT NULL + , profit_local_min FLOAT NOT NULL + , latency_manufacture_days INT NOT NULL + , id_unit_measurement_quantity INT NOT NULL + , count_unit_measurement_per_quantity_step FLOAT NOT NULL + , quantity_min FLOAT NOT NULL + , quantity_max FLOAT NOT NULL + , quantity_stock FLOAT NOT NULL + , is_subscription BIT NOT NULL + , id_unit_measurement_interval_recurrence INT + , count_interval_recurrence INT + , id_stripe_product VARCHAR(100) NULL + , does_expire_faster_once_unsealed BIT NOT NULL + , id_unit_measurement_interval_expiration_unsealed INT + , count_interval_expiration_unsealed INT + , active BIT NOT NULL DEFAULT 1 + , can_view BIT NULL + , can_edit BIT NULL + , can_admin BIT NULL + , name_error VARCHAR(255) NOT NULL + , is_new BIT NOT NULL + ); + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error ( + display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , guid BINARY(36) NOT NULL + , id_type INT NULL + , code VARCHAR(50) NOT NULL + , msg VARCHAR(4000) NOT NULL + ); + + + -- Get data from Temp table + INSERT INTO tmp_Permutation ( + id_permutation + , id_product + , description + , cost_local + , id_currency_cost + , profit_local_min + , latency_manufacture_days + , id_unit_measurement_quantity + , count_unit_measurement_per_quantity_step + , quantity_min + , quantity_max + , quantity_stock + , is_subscription + , id_unit_measurement_interval_recurrence + , count_interval_recurrence + , id_stripe_product + , does_expire_faster_once_unsealed + , id_unit_measurement_interval_expiration_unsealed + , count_interval_expiration_unsealed + , active + , name_error + , is_new + ) + SELECT + PP_T.id_permutation + , IFNULL(PP_T.id_product, PP.id_product) AS id_product + , IFNULL(PP_T.description, PP.description) AS description + , IFNULL(PP_T.cost_local, PP.cost_local) AS cost_local + , IFNULL(PP_T.id_currency_cost, PP.id_currency_cost) AS a_id_currency_cost + , IFNULL(PP_T.profit_local_min, PP.profit_local_min) AS profit_local_min + , IFNULL(PP_T.latency_manufacture_days, PP.latency_manufacture_days) AS latency_manufacture_days + , IFNULL(PP_T.id_unit_measurement_quantity, PP.id_unit_measurement_quantity) AS id_unit_measurement_quantity + , IFNULL(PP_T.count_unit_measurement_per_quantity_step, PP.count_unit_measurement_per_quantity_step) AS count_unit_measurement_per_quantity_step + , IFNULL(PP_T.quantity_min, PP.quantity_min) AS quantity_min + , IFNULL(PP_T.quantity_max, PP.quantity_max) AS quantity_max + , IFNULL(PP_T.quantity_stock, PP.quantity_stock) AS quantity_stock + , IFNULL(PP_T.is_subscription, PP.is_subscription) AS is_subscription + , IFNULL(PP_T.id_unit_measurement_interval_recurrence, PP.id_unit_measurement_interval_recurrence) AS id_unit_measurement_interval_recurrence + , IFNULL(PP_T.count_interval_recurrence, PP.count_interval_recurrence) AS count_interval_recurrence + , IFNULL(PP_T.id_stripe_product, PP.id_stripe_product) AS id_stripe_product + , IFNULL(PP_T.does_expire_faster_once_unsealed, PP.does_expire_faster_once_unsealed) AS does_expire_faster_once_unsealed + , IFNULL(PP_T.id_unit_measurement_interval_expiration_unsealed, PP.id_unit_measurement_interval_expiration_unsealed) AS id_unit_measurement_interval_expiration_unsealed + , IFNULL(PP_T.count_interval_expiration_unsealed, PP.count_interval_expiration_unsealed) AS count_interval_expiration_unsealed + , IFNULL(PP_T.active, PP.active) AS active + , fn_shop_get_name_product_permutation(PP_T.id_permutation) + , CASE WHEN IFNULL(PP_T.id_category, 0) < 1 THEN 1 ELSE 0 END AS is_new + FROM Shop_Product_Permutation_Temp PP_T + LEFT JOIN Shop_Product_Permutation PP ON PP_T.id_category = PP.id_category + WHERE PP_T.guid = a_guid + ; + + -- Validation + -- Missing mandatory fields + -- id_product + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.id_product) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , id_product + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have a product: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.id_product) + ; END IF; - - -- Invalid quantity used - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - IF EXISTS ( - SELECT * - FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link - WHERE - NOT ISNULL(quantity_used) - AND quantity_used < 0 - ) THEN - INSERT INTO tmp_Msg_Error ( - guid, id_type, code, msg - ) - SELECT - a_guid, - v_id_error_type_bad_data, - v_code_error_type_bad_data, - CONCAT('Invalid quantity used property for the following permutations: ', GROUP_CONCAT(t_MPOPL.name_error SEPARATOR ', ')) - FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPOPL - WHERE t_MPOPL.quantity_used < 0 - ; - END IF; + -- cost_local + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.cost_local) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , cost_local + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have a local cost: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.cost_local) + ; END IF; - - -- Invalid quantity produced - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - IF EXISTS ( - SELECT * - FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link - WHERE - NOT ISNULL(quantity_produced) - AND quantity_produced < 0 - ) THEN - INSERT INTO tmp_Msg_Error ( - guid, id_type, code, msg - ) - SELECT - a_guid, - v_id_error_type_bad_data, - v_code_error_type_bad_data, - CONCAT('Invalid quantity produced property for the following permutations: ', GROUP_CONCAT(t_MPOPL.name_error SEPARATOR ', ')) - FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPOPL - WHERE t_MPOPL.quantity_produced < 0 - ; - END IF; + -- profit_local_min + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.profit_local_min) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , profit_local_min + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have a local minimum profit: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.profit_local_min) + ; + END IF; + -- latency_manufacture_days + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.latency_manufacture_days) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , latency_manufacture_days + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have a manufacturing latency: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.latency_manufacture_days) + ; + END IF; + -- id_unit_measurement_quantity + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.id_unit_measurement_quantity) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , id_unit_measurement_quantity + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have a unit measurement for stock quantities: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.id_unit_measurement_quantity) + ; + END IF; + -- count_unit_measurement_per_quantity_step + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.count_unit_measurement_per_quantity_step) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , count_unit_measurement_per_quantity_step + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have a count unit measurement per quantity step: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.count_unit_measurement_per_quantity_step) + ; + END IF; + -- quantity_min + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.quantity_min) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , quantity_min + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have a minimum quantity: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.quantity_min) + ; + END IF; + -- quantity_max + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.quantity_max) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , quantity_max + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have a maximum quantity: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.quantity_max) + ; + END IF; + -- is_subscription + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.is_subscription) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , is_subscription + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have an is subscription?: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.is_subscription) + ; + END IF; + -- does_expire_faster_once_unsealed + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.does_expire_faster_once_unsealed) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , does_expire_faster_once_unsealed + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have a does expire faster once unsealed: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.does_expire_faster_once_unsealed) + ; END IF; - - -- Duplicates - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - IF EXISTS (SELECT id_permutation, name_error, COUNT(*) FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPOPL GROUP BY id_permutation HAVING COUNT(*) > 1) THEN - INSERT INTO tmp_Msg_Error ( - guid, id_type, code, msg - ) - SELECT - a_guid, - v_id_error_type_bad_data, - v_code_error_type_bad_data, - CONCAT('Duplicate records: ', GROUP_CONCAT(t_MPOPLC.name_error SEPARATOR ', ')) - FROM (SELECT id_permutation, name_error, COUNT(*) FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPOPL GROUP BY id_permutation HAVING COUNT(*) > 1) t_MPOPLC - ; - END IF; - END IF; - -- Permissions - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - SET v_ids_product := ( - SELECT GROUP_CONCAT(G.id_product SEPARATOR ',') - FROM ( - SELECT DISTINCT PP.id_product - FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPO - INNER JOIN Shop_Product_Permutation PP ON t_MPO.id_permutation = PP.id_permutation - ) G + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN -- (SELECT * FROM tmp_Product WHERE is_new = 0 LIMIT 1) THEN + SET v_ids_product_permission := ( + SELECT GROUP_CONCAT(P.id_product SEPARATOR ',') + FROM Shop_Product P + INNER JOIN tmp_Permutation t_P + ON P.id_product = t_P.id_product + -- AND t_P.is_new = 0 ); - - CALL p_shop_user_eval(v_guid_permission, a_id_user, 0, v_id_permission_manufacturing_purchase_order, v_id_access_level_edit, v_ids_product); - - /* - UPDATE tmp_Shop_Supplier t_S - INNER JOIN Shop_User_Eval_Temp TP - ON TP.GUID = v_guid_permission - SET tP.can_view = TP.can_view, - tP.can_edit = TP.can_edit, - tP.can_admin = TP.can_admin; - */ - /* - SET v_has_permission := ( - SELECT can_edit - FROM Shop_User_Eval_Temp - WHERE - GUID = v_guid_permission - AND can_edit = 0 - ); - - IF v_has_permission = 0 THEN - SET v_id_error_type_no_permission := (SELECT id_type FROM Shop_Msg_Error_Type WHERE code = 'NO_PERMISSION'); - INSERT INTO tmp_Msg_Error ( - guid, id_type, msg - ) - SELECT - a_guid, - v_id_error_type_no_permission, - CONCAT('You do not have ', name, ' permissions.') - FROM Shop_Permission - WHERE id_permission = v_id_permission_manufacturing_purchase_order - ; - END IF; - */ - SET v_ids_product_no_permission := ( - SELECT GROUP_CONCAT(PT.id_product SEPARATOR ',') - FROM Shop_User_Eval_Temp PT - WHERE - PT.can_edit = 0 - AND NOT ISNULL(PT.id_product) - ); - IF NOT ISNULL(v_ids_product_no_permission) THEN - INSERT INTO tmp_Msg_Error ( - guid, id_type, code, msg - ) - VALUES ( - a_guid, - v_id_error_type_no_permission, - v_code_error_type_no_permission, - CONCAT('You do not have permission to edit the following product IDs: ', v_ids_product_no_permission) - ) - ; - END IF; - END IF; - - -- Transaction - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - START TRANSACTION; - INSERT INTO Shop_Sales_And_Purchasing_Change_Set ( - comment, - updated_last_by, - updated_last_on - ) - VALUES ( - CONCAT( - 'Save ', - CASE WHEN v_is_new_manufacturing_purchase_order = 1 THEN 'new ' ELSE '' END, - 'Manufacturing Purchase Order - ', - a_comment - ), - a_id_user, - CURRENT_TIME() - ); + IF NOT ISNULL(v_ids_product_permission) THEN + SET v_id_permission_product = (SELECT id_permission FROM Shop_Permission WHERE code = 'STORE_PRODUCT' LIMIT 1); - SET v_id_change_set := (SELECT id_change_set FROM Shop_Sales_And_Purchasing_Change_Set ORDER BY id_change_set DESC LIMIT 1); + CALL p_shop_user_eval(a_guid, a_id_user, FALSE, v_id_permission_product, v_id_access_level_edit, v_ids_product_permission); - IF (v_is_new_manufacturing_purchase_order = 1) THEN - INSERT INTO Shop_Manufacturing_Purchase_Order ( - -- id_supplier_ordered, - cost_total_local, - id_currency_cost, - value_produced_total_local, - created_by, - id_change_set, - active + UPDATE tmp_Permutation t_P + INNER JOIN Shop_Product P ON t_P.id_product = P.id_product + INNER JOIN Shop_User_Eval_Temp UE_T + ON P.id_product = UE_T.id_product + AND UE_T.GUID = a_guid + SET + t_P.can_view = UE_T.can_view + , t_P.can_edit = UE_T.can_edit + , t_P.can_admin = UE_T.can_admin + ; + + CALL p_clear_shop_user_eval_temp(a_guid); + + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.can_edit) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , code + , msg ) - SELECT - -- a_id_supplier_ordered, - SUM(t_MPOPL.cost_total_local), - a_id_currency_cost, - SUM(t_MPOPL.value_produced_total_local), - a_id_user, - v_id_change_set, - a_active - FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPOPL + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have product edit permission: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.can_edit) ; - -- SET v_id_order_new - SET a_id_order := (SELECT id_order FROM Shop_Manufacturing_Purchase_Order ORDER BY id_order DESC LIMIT 1); - - INSERT INTO Shop_Manufacturing_Purchase_Order_Product_Link ( - id_order, - id_permutation, - cost_total_local, - value_produced_total_local, - id_currency_cost, - quantity_used, - id_unit_quantity, - quantity_produced, - latency_manufacture_days, - display_order, - active, - created_by, - id_change_set - ) - SELECT - a_id_order, -- v_id_order_new, - id_permutation, - cost_total_local, - value_produced_total_local, - id_currency_cost, - quantity_used, - id_unit_quantity, - quantity_produced, - latency_manufacture_days, - display_order, - active, - a_id_user, - v_id_change_set - FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPOPL - ; - ELSE - UPDATE Shop_Manufacturing_Purchase_Order MPO - INNER JOIN tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPOPL ON MPO.id_order = t_MPOPL.id_order - SET - -- MPO.id_supplier_ordered = a_id_supplier_ordered, - MPO.cost_total_local = SUM(t_MPOPL.cost_total_local), - MPO.value_produced_total_local = SUM(t_MPOPL.value_produced_total_local), - MPO.id_currency = a_id_currency_cost, - MPO.id_change_set = v_id_change_set, - MPO.active = a_active - WHERE MPO.id_order = a_id_order - ; - IF EXISTS (SELECT * FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPOPL INNER JOIN Shop_Manufacturing_Purchase_Order_Product_Link MPOPL ON t_MPOPL.id_link = MPOPL.id_link) THEN - UPDATE Shop_Manufacturing_Purchase_Order_Product_Link MPOPL - INNER JOIN tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPOPL - ON MPOPL.id_link = t_MPOPL.id_link - SET - MPOPL.id_order = t_MPOPL.id_order, - MPOPL.id_permutation = t_MPOPL.id_permutation, - MPOPL.cost_total_local = t_MPOPL.cost_total_local, - MPOPL.value_produced_total_local = t_MPOPL.value_produced_total_local, - MPOPL.id_currency_cost = t_MPOPL.id_currency_cost, - MPOPL.quantity_used = t_MPOPL.quantity_used, - MPOPL.id_unit_quantity = t_MPOPL.id_unit_quantity, - MPOPL.quantity_produced = t_MPOPL.quantity_produced, - MPOPL.latency_manufacture_days = t_MPOPL.latency_manufacture_days, - MPOPL.display_order = t_MPOPL.display_order, - MPOPL.active = t_MPOPL.active, - MPOPL.id_change_set = v_id_change_set - ; - ELSE - INSERT INTO Shop_Manufacturing_Purchase_Order_Product_Link ( - id_order, - id_permutation, - cost_total_local, - value_produced_total_local, - id_currency_cost, - quantity_used, - id_unit_quantity, - quantity_produced, - latency_manufacture_days, - display_order, - active, - created_by, - id_change_set - ) - SELECT - id_order, - id_permutation, - cost_total_local, - value_produced_total_local, - id_currency_cost, - quantity_used, - id_unit_quantity, - quantity_produced, - latency_manufacture_days, - display_order, - active, - a_id_user, - v_id_change_set - FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPOPL - WHERE t_MPOPL.id_link < 0 - ; - END IF; END IF; - - IF EXISTS (SELECT * FROM tmp_Msg_Error) THEN - ROLLBACK; - ELSE - COMMIT; END IF; END IF; - -- Returns - # SET v_now = NOW(); + SET v_now := CURRENT_TIMESTAMP(); - # Manufacturing Purchase Orders - SELECT * - FROM Shop_Manufacturing_Purchase_Order - WHERE - id_order = a_id_order - -- GUID = a_guid - ; + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN + START TRANSACTION; + + IF NOT ISNULL(v_ids_product_permission) THEN + INSERT INTO Shop_Product_Change_Set ( comment ) + VALUES ( a_comment ) + ; + + SET v_id_change_set := LAST_INSERT_ID(); + + UPDATE Shop_Product_Permutation PP + INNER JOIN tmp_Permutation t_P ON PP.id_permutation = t_P.id_permutation + SET + PP.id_permutation = t_P.id_permutation + , PP.id_product = t_P.id_product + , PP.description = t_P.description + , PP.cost_local = t_P.cost_local + , PP.id_currency_cost = t_P.id_currency_cost + , PP.profit_local_min = t_P.profit_local_min + , PP.latency_manufacture_days = t_P.latency_manufacture_days + , PP.id_unit_measurement_quantity = t_P.id_unit_measurement_quantity + , PP.count_unit_measurement_per_quantity_step = t_P.count_unit_measurement_per_quantity_step + , PP.quantity_min = t_P.quantity_min + , PP.quantity_max = t_P.quantity_max + , PP.quantity_stock = t_P.quantity_stock + , PP.is_subscription = t_P.is_subscription + , PP.id_unit_measurement_interval_recurrence = t_P.id_unit_measurement_interval_recurrence + , PP.count_interval_recurrence = t_P.count_interval_recurrence + , PP.id_stripe_product = t_P.id_stripe_product + , PP.does_expire_faster_once_unsealed = t_P.does_expire_faster_once_unsealed + , PP.id_unit_measurement_interval_expiration_unsealed = t_P.id_unit_measurement_interval_expiration_unsealed + , PP.count_interval_expiration_unsealed = t_P.count_interval_expiration_unsealed + , PP.active = t_P.active + , PP.id_change_set = v_id_change_set + ; + END IF; + + INSERT INTO Shop_Product_Permutation ( + id_product + , description + , cost_local + , id_currency_cost + , profit_local_min + , latency_manufacture_days + , id_unit_measurement_quantity + , count_unit_measurement_per_quantity_step + , quantity_min + , quantity_max + , quantity_stock + , is_subscription + , id_unit_measurement_interval_recurrence + , count_interval_recurrence + , id_stripe_product + , does_expire_faster_once_unsealed + , id_unit_measurement_interval_expiration_unsealed + , count_interval_expiration_unsealed + , active + , display_order + , created_by + , created_on + ) + SELECT + t_P.id_product AS id_product + , t_P.description AS description + , t_P.cost_local AS cost_local + , t_P.id_currency_cost AS id_currency_cost + , t_P.profit_local_min AS profit_local_min + , t_P.latency_manufacture_days AS latency_manufacture_days + , t_P.id_unit_measurement_quantity AS id_unit_measurement_quantity + , t_P.count_unit_measurement_per_quantity_step AS count_unit_measurement_per_quantity_step + , t_P.quantity_min AS quantity_min + , t_P.quantity_max AS quantity_max + , t_P.quantity_stock AS quantity_stock + , t_P.is_subscription AS is_subscription + , t_P.id_unit_measurement_interval_recurrence AS id_unit_measurement_interval_recurrence + , t_P.count_interval_recurrence AS count_interval_recurrence + , t_P.id_stripe_product AS id_stripe_product + , t_P.does_expire_faster_once_unsealed AS does_expire_faster_once_unsealed + , t_P.id_unit_measurement_interval_expiration_unsealed AS id_unit_measurement_interval_expiration_unsealed + , t_P.count_interval_expiration_unsealed AS count_interval_expiration_unsealed + , t_P.active AS active + , a_id_user AS created_by + , v_now AS created_on + FROM tmp_Permutation t_P + WHERE + is_new = 1 + AND active = 1 + ; + + COMMIT; + END IF; - # Manufacturing Purchase Order Product Links - SELECT * - FROM Shop_Manufacturing_Purchase_Order_Product_Link - WHERE - id_order = a_id_order - -- GUID = a_guid - ; + DELETE FROM Shop_Product_Category_Temp + WHERE GUID = a_guid; - # Errors - SELECT * - FROM tmp_Msg_Error - ; + SELECT * FROM tmp_Msg_Error; - # DROP TABLE tmp_Shop_Manufacturing_Purchase_Order; - DROP TABLE tmp_Shop_Manufacturing_Purchase_Order_Product_Link; - DROP TABLE tmp_Msg_Error; + DROP TEMPORARY TABLE IF EXISTS tmp_Catgory; + DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error; END // DELIMITER ;; @@ -9098,25 +9175,8 @@ DELETE FROM Shop_Manufacturing_Purchase_Order; */ - - -/* - -CALL p_shop_get_many_product_variation ( - '', # a_id_user - 1, # a_get_all_supplier - 0, # a_get_inactive_variation - 0, # a_get_first_variation_only - '', # a_ids_variation -); - -*/ - - --- Clear previous proc DROP PROCEDURE IF EXISTS p_shop_get_many_product_variation; - DELIMITER // CREATE PROCEDURE p_shop_get_many_product_variation ( IN a_id_user INT, @@ -9335,32 +9395,33 @@ BEGIN END IF; -- Returns - /* # Variation Types SELECT t_VT.id_type , VT.code , VT.name , VT.name_plural + , VT.display_order , VT.active FROM tmp_Variation_Type t_VT INNER JOIN Shop_Variation_Type VT ON t_VT.id_type = VT.id_type ; - */ # Variations SELECT t_V.id_variation + , t_V.id_type , V.code AS code_variation , V.name AS name_variation - , V.active AS active_variation , V.display_order - , t_V.id_type + , V.active AS active_variation + /* , VT.code AS code_variation_type , VT.name AS name_variation_type , VT.name_plural AS name_plural_variation_type , VT.active AS active_variation_type , VT.display_order + */ FROM tmp_Variation t_V INNER JOIN Shop_Variation V ON t_V.id_variation = V.id_variation INNER JOIN tmp_Variation_Type t_VT ON V.id_type = t_VT.id_type @@ -9613,17 +9674,17 @@ BEGIN price_GBP_full FLOAT NOT NULL, price_GBP_min FLOAT NOT NULL, * - , latency_manufacture INT NOT NULL + , latency_manufacture_days INT NOT NULL , quantity_min FLOAT NOT NULL , quantity_max FLOAT NOT NULL , quantity_step FLOAT NOT NULL , quantity_stock FLOAT NOT NULL , is_subscription BIT NOT NULL - , id_recurrence_interval INT - , CONSTRAINT FK_tmp_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval) - , count_recurrence_interval INT + , id_unit_measurement_interval_recurrence INT + , CONSTRAINT FK_tmp_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval) + , count_interval_recurrence INT , id_stripe_product VARCHAR(100) , product_has_variations INT NOT NULL , can_view BIT @@ -10797,15 +10858,15 @@ BEGIN CURRENCY.code AS code_currency_cost, CURRENCY.symbol AS symbol_currency_cost, PP.profit_local_min, - t_P.latency_manufacture, + t_P.latency_manufacture_days, t_P.quantity_min, t_P.quantity_max, t_P.quantity_step, t_P.quantity_stock, t_P.id_stripe_product, t_P.is_subscription, - UM.name_singular AS name_recurrence_interval, - UM.name_plural AS name_plural_recurrence_interval, + UM.name_singular AS name_interval_recurrence, + UM.name_plural AS name_plural_interval_recurrence, PP.count_interval_recurrence, t_P.display_order_category, t_P.display_order_product, @@ -10816,8 +10877,8 @@ BEGIN FROM tmp_Shop_Product t_P INNER JOIN Shop_Product P ON t_P.id_product = P.id_product INNER JOIN Shop_Product_Permutation PP ON t_P.id_permutation = PP.id_permutation - -- LEFT JOIN Shop_Recurrence_Interval RI ON t_P.id_interval_recurrence = RI.id_interval - LEFT JOIN Shop_Unit_Measurement UM ON PP.id_interval_recurrence = UM.id_unit_measurement + -- LEFT JOIN Shop_Interval_Recurrence RI ON t_P.id_unit_measurement_interval_recurrence = RI.id_interval + LEFT JOIN Shop_Unit_Measurement UM ON PP.id_unit_measurement_interval_recurrence = UM.id_unit_measurement INNER JOIN Shop_Currency CURRENCY ON PP.id_currency_cost = CURRENCY.id_currency ORDER BY t_P.rank_permutation ; @@ -11339,13 +11400,13 @@ BEGIN P.id_stripe_product, P.is_subscription, LOWER(RI.code) AS name_recurring_interval, - P.count_recurrence_interval + P.count_interval_recurrence FROM tmp_Shop_Product_Currency_Link t_PCL INNER JOIN Shop_Product P ON t_PCL.id_product = P.id_product AND P.active - INNER JOIN Shop_Recurrence_Interval RI - ON P.id_recurrence_interval = RI.id_interval + INNER JOIN Shop_Interval_Recurrence RI + ON P.id_unit_measurement_interval_recurrence = RI.id_interval AND RI.active INNER JOIN Shop_Currency C ON t_PCL.id_currency = C.id_currency @@ -13967,17 +14028,17 @@ BEGIN price_GBP_full FLOAT NOT NULL, price_GBP_min FLOAT NOT NULL, */ - latency_manufacture INT NOT NULL, + latency_manufacture_days INT NOT NULL, quantity_min FLOAT NOT NULL, quantity_max FLOAT NOT NULL, quantity_step FLOAT NOT NULL, quantity_stock FLOAT NOT NULL, is_subscription BIT NOT NULL, - id_recurrence_interval INT, - CONSTRAINT FK_tmp_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), - count_recurrence_interval INT, + id_unit_measurement_interval_recurrence INT, + CONSTRAINT FK_tmp_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), + count_interval_recurrence INT, id_stripe_product VARCHAR(100), product_has_variations INT NOT NULL, can_view BIT, @@ -14159,14 +14220,14 @@ BEGIN price_GBP_VAT_excl, price_GBP_min, * - latency_manufacture, + latency_manufacture_days, quantity_min, quantity_max, quantity_step, quantity_stock, is_subscription, - id_recurrence_interval, - count_recurrence_interval, + id_unit_measurement_interval_recurrence, + count_interval_recurrence, id_stripe_product, product_has_variations */ @@ -14191,14 +14252,14 @@ BEGIN PP.price_GBP_VAT_excl, PP.price_GBP_min, * - PP.latency_manufacture, + PP.latency_manufacture_days, PP.quantity_min, PP.quantity_max, PP.quantity_step, PP.quantity_stock, PP.is_subscription, - PP.id_recurrence_interval, - PP.count_recurrence_interval, + PP.id_unit_measurement_interval_recurrence, + PP.count_interval_recurrence, PP.id_stripe_product, P.has_variations */ @@ -15309,17 +15370,17 @@ BEGIN price_GBP_min FLOAT NOT NULL, */ /* - latency_manufacture INT NOT NULL, + latency_manufacture_days INT NOT NULL, quantity_min FLOAT NOT NULL, quantity_max FLOAT NOT NULL, quantity_step FLOAT NOT NULL, quantity_stock FLOAT NOT NULL, is_subscription BIT NOT NULL, - id_recurrence_interval INT, - CONSTRAINT FK_tmp_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), - count_recurrence_interval INT, + id_unit_measurement_interval_recurrence INT, + CONSTRAINT FK_tmp_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), + count_interval_recurrence INT, id_stripe_product VARCHAR(100), product_has_variations INT NOT NULL, */ @@ -15449,14 +15510,14 @@ BEGIN price_GBP_VAT_excl, price_GBP_min, * - latency_manufacture, + latency_manufacture_days, quantity_min, quantity_max, quantity_step, quantity_stock, is_subscription, - id_recurrence_interval, - count_recurrence_interval, + id_unit_measurement_interval_recurrence, + count_interval_recurrence, id_stripe_product, product_has_variations */ @@ -15481,14 +15542,14 @@ BEGIN PP.price_GBP_VAT_excl, PP.price_GBP_min, * - PP.latency_manufacture, + PP.latency_manufacture_days, PP.quantity_min, PP.quantity_max, PP.quantity_step, PP.quantity_stock, PP.is_subscription, - PP.id_recurrence_interval, - PP.count_recurrence_interval, + PP.id_unit_measurement_interval_recurrence, + PP.count_interval_recurrence, PP.id_stripe_product, P.has_variations */ @@ -17130,17 +17191,17 @@ BEGIN price_GBP_min FLOAT NOT NULL, */ /* - latency_manufacture INT NOT NULL, + latency_manufacture_days INT NOT NULL, quantity_min FLOAT NOT NULL, quantity_max FLOAT NOT NULL, quantity_step FLOAT NOT NULL, quantity_stock FLOAT NOT NULL, is_subscription BIT NOT NULL, - id_recurrence_interval INT, - CONSTRAINT FK_tmp_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), - count_recurrence_interval INT, + id_unit_measurement_interval_recurrence INT, + CONSTRAINT FK_tmp_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), + count_interval_recurrence INT, id_stripe_product VARCHAR(100), product_has_variations INT NOT NULL, */ @@ -17325,14 +17386,14 @@ BEGIN price_GBP_VAT_excl, price_GBP_min, * - latency_manufacture, + latency_manufacture_days, quantity_min, quantity_max, quantity_step, quantity_stock, is_subscription, - id_recurrence_interval, - count_recurrence_interval, + id_unit_measurement_interval_recurrence, + count_interval_recurrence, id_stripe_product, product_has_variations */ @@ -17357,14 +17418,14 @@ BEGIN PP.price_GBP_VAT_excl, PP.price_GBP_min, * - PP.latency_manufacture, + PP.latency_manufacture_days, PP.quantity_min, PP.quantity_max, PP.quantity_step, PP.quantity_stock, PP.is_subscription, - PP.id_recurrence_interval, - PP.count_recurrence_interval, + PP.id_unit_measurement_interval_recurrence, + PP.count_interval_recurrence, PP.id_stripe_product, P.has_variations */ @@ -17843,13 +17904,13 @@ VALUES # Unit of Measurement INSERT INTO Shop_Unit_Measurement ( - name_singular, name_plural, symbol, is_base_unit + name_singular, name_plural, symbol, is_base_unit, is_unit_of_distance, is_unit_of_mass, is_unit_of_time, is_unit_of_volume ) VALUES - ('metre', 'metres', 'm', 1), - ('kilogram', 'kilograms', 'kg', 1), - ('item', 'items', 'x', 0), - ('hour', 'hours', 'h', 1) + ('metre', 'metres', 'm', 1, 1, 0, 0, 0), + ('kilogram', 'kilograms', 'kg', 1, 0, 1, 0, 0), + ('item', 'items', 'x', 0, 0, 0, 0, 0), + ('hour', 'hours', 'h', 1, 0, 0, 1, 0) ; /* @@ -17880,7 +17941,7 @@ VALUES /* # Recurrence Interval -INSERT INTO Shop_Recurrence_Interval ( +INSERT INTO Shop_Interval_Recurrence ( code, name, name_plural ) VALUES @@ -17951,18 +18012,19 @@ INSERT INTO Shop_Product_Permutation ( id_currency_cost, profit_local_min, # id_currency_profit_min, - latency_manufacture, - quantity_min, + latency_manufacture_days, + id_unit_measurement_quantity, + count_unit_measurement_per_quantity_step, + quantity_min, quantity_max, - quantity_step, quantity_stock, is_subscription, - id_interval_recurrence, + id_unit_measurement_interval_recurrence, count_interval_recurrence, -- id_access_level_required, id_stripe_product , does_expire_faster_once_unsealed - , id_interval_expiration_unsealed + , id_unit_measurement_interval_expiration_unsealed , count_interval_expiration_unsealed ) VALUES @@ -17976,9 +18038,10 @@ VALUES # 1, 14, 1, - 3, 1, + 3, 99, + 1, 0, NULL, NULL, @@ -17998,9 +18061,10 @@ VALUES # 1, 14, 1, - 3, 1, + 3, 99, + 1, 0, NULL, NULL, @@ -18020,9 +18084,10 @@ VALUES # 1, 14, 1, - 2, 1, + 2, 99, + 1, 0, NULL, NULL, @@ -18042,9 +18107,10 @@ VALUES # 1, 14, 1, - 2, 1, + 2, 99, + 1, 0, NULL, NULL, @@ -18064,9 +18130,10 @@ VALUES # 1, 14, 1, - 2, 1, + 2, 99, + 1, 0, NULL, NULL, @@ -18086,9 +18153,10 @@ VALUES # 1, 14, 1, - 2, 1, + 2, 99, + 1, 0, NULL, NULL, @@ -18537,8 +18605,8 @@ SELECT * FROM Shop_Unit_Measurement_Conversion_Audit; /* # Recurrence Interval -SELECT * FROM Shop_Recurrence_Interval; -SELECT * FROM Shop_Recurrence_Interval_Audit; +SELECT * FROM Shop_Interval_Recurrence; +SELECT * FROM Shop_Interval_Recurrence_Audit; */ diff --git a/static/MySQL/0001_destroy.sql b/static/MySQL/0001_destroy.sql index 31a3994d..5b3f89e4 100644 --- a/static/MySQL/0001_destroy.sql +++ b/static/MySQL/0001_destroy.sql @@ -146,8 +146,8 @@ DROP TABLE IF EXISTS Shop_Product_Permutation_Temp; DROP TABLE IF EXISTS Shop_Product_Permutation_Audit; DROP TABLE IF EXISTS Shop_Product_Permutation; -DROP TABLE IF EXISTS Shop_Recurrence_Interval_Audit; -DROP TABLE IF EXISTS Shop_Recurrence_Interval; +DROP TABLE IF EXISTS Shop_Interval_Recurrence_Audit; +DROP TABLE IF EXISTS Shop_Interval_Recurrence; DROP TABLE IF EXISTS Shop_Product_Audit; DROP TABLE IF EXISTS Shop_Product; @@ -221,9 +221,14 @@ DROP TABLE IF EXISTS Shop_Product_Change_Set; DROP PROCEDURE IF EXISTS p_split; DROP PROCEDURE IF EXISTS p_clear_split_temp; +DROP FUNCTION IF EXISTS fn_shop_get_product_permutation_name; + DROP PROCEDURE IF EXISTS p_shop_user_eval; DROP PROCEDURE IF EXISTS p_clear_shop_user_eval_temp; +DROP PROCEDURE IF EXISTS p_shop_get_many_access_level; +DROP PROCEDURE IF EXISTS p_shop_get_many_unit_measurement; + DROP PROCEDURE IF EXISTS p_shop_get_many_region; DROP PROCEDURE IF EXISTS p_shop_get_many_currency; @@ -234,6 +239,7 @@ DROP PROCEDURE IF EXISTS p_shop_save_product; DROP PROCEDURE IF EXISTS p_shop_get_many_product; DROP PROCEDURE IF EXISTS p_shop_get_many_stripe_product_new; DROP PROCEDURE IF EXISTS p_shop_save_permutation; +DROP PROCEDURE IF EXISTS p_shop_save_product_permutation; DROP PROCEDURE IF EXISTS p_shop_get_many_product_variation; DROP PROCEDURE IF EXISTS p_shop_get_many_stock_item; DROP PROCEDURE IF EXISTS p_shop_get_many_product_price_and_discount_and_delivery_option; diff --git a/static/MySQL/1121_tbl_Shop_Unit_Measurement.sql b/static/MySQL/1121_tbl_Shop_Unit_Measurement.sql index c8b62ba5..44c3eb0c 100644 --- a/static/MySQL/1121_tbl_Shop_Unit_Measurement.sql +++ b/static/MySQL/1121_tbl_Shop_Unit_Measurement.sql @@ -10,6 +10,7 @@ CREATE TABLE IF NOT EXISTS Shop_Unit_Measurement ( name_singular VARCHAR(255) NOT NULL, name_plural VARCHAR(256) NOT NULL, symbol VARCHAR(50) NOT NULL, + symbol_is_suffix_not_prefix BIT NOT NULL DEFAULT 1, is_base_unit BIT NOT NULL DEFAULT 0, is_unit_of_distance BIT NOT NULL DEFAULT 0, is_unit_of_mass BIT NOT NULL DEFAULT 0, diff --git a/static/MySQL/1203_tbl_Shop_Product.sql b/static/MySQL/1203_tbl_Shop_Product.sql index fce7bd2e..f0dc160a 100644 --- a/static/MySQL/1203_tbl_Shop_Product.sql +++ b/static/MySQL/1203_tbl_Shop_Product.sql @@ -25,11 +25,11 @@ CREATE TABLE IF NOT EXISTS Shop_Product ( quantity_step FLOAT, quantity_stock FLOAT, is_subscription BIT, - id_recurrence_interval INT, - CONSTRAINT FK_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), - count_recurrence_interval INT, + id_unit_measurement_interval_recurrence INT, + CONSTRAINT FK_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), + count_interval_recurrence INT, */ id_access_level_required INT NOT NULL, CONSTRAINT FK_Shop_Product_id_access_level_required diff --git a/static/MySQL/1206_tbl_Shop_Product_Permutation.sql b/static/MySQL/1206_tbl_Shop_Product_Permutation.sql index 3473bbba..49302982 100644 --- a/static/MySQL/1206_tbl_Shop_Product_Permutation.sql +++ b/static/MySQL/1206_tbl_Shop_Product_Permutation.sql @@ -18,26 +18,30 @@ CREATE TABLE IF NOT EXISTS Shop_Product_Permutation ( id_currency_cost INT NOT NULL, profit_local_min FLOAT NOT NULL, -- id_currency_profit_min INT NOT NULL, - latency_manufacture INT NOT NULL, + latency_manufacture_days INT NOT NULL, + id_unit_measurement_quantity INT NOT NULL, + CONSTRAINT FK_Shop_Product_Permutation_id_unit_quantity + FOREIGN KEY (id_unit_measurement_quantity) + REFERENCES Shop_Unit_Measurement(id_unit_measurement), + count_unit_measurement_per_quantity_step FLOAT NOT NULL, quantity_min FLOAT NOT NULL, quantity_max FLOAT NOT NULL, - quantity_step FLOAT NOT NULL, quantity_stock FLOAT NOT NULL, is_subscription BIT NOT NULL, - id_interval_recurrence INT, - CONSTRAINT FK_Shop_Product_Permutation_id_interval_recurrence - FOREIGN KEY (id_interval_recurrence) + id_unit_measurement_interval_recurrence INT, + CONSTRAINT FK_Shop_Product_Permutation_id_unit_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) REFERENCES Shop_Unit_Measurement(id_unit_measurement), /* - CONSTRAINT CHECK_FK_Shop_Product_Permutation_id_interval_recurrence - CHECK (id_interval_recurrence IN (SELECT id_unit_measurement FROM Shop_Unit_Measurement WHERE is_unit_of_time = 1)), + CONSTRAINT CHECK_FK_Shop_Product_Permutation_id_unit_measurement_interval_recurrence + CHECK (id_unit_measurement_interval_recurrence IN (SELECT id_unit_measurement FROM Shop_Unit_Measurement WHERE is_unit_of_time = 1)), */ count_interval_recurrence INT, id_stripe_product VARCHAR(100) NULL, does_expire_faster_once_unsealed BIT NOT NULL DEFAULT 0, - id_interval_expiration_unsealed INT, - CONSTRAINT FK_Shop_Product_Permutation_id_interval_expiration_unsealed - FOREIGN KEY (id_interval_expiration_unsealed) + id_unit_measurement_interval_expiration_unsealed INT, + CONSTRAINT FK_Shop_Product_Permutation_id_unit_interval_expiration_unsealed + FOREIGN KEY (id_unit_measurement_interval_expiration_unsealed) REFERENCES Shop_Unit_Measurement(id_unit_measurement), /* CONSTRAINT CHECK_FK_Shop_Product_Permutation_id_interval_expiration_unsealed diff --git a/static/MySQL/1208_tbl_Shop_Product_Permutation_Temp.sql b/static/MySQL/1208_tbl_Shop_Product_Permutation_Temp.sql index ed763447..41f4a958 100644 --- a/static/MySQL/1208_tbl_Shop_Product_Permutation_Temp.sql +++ b/static/MySQL/1208_tbl_Shop_Product_Permutation_Temp.sql @@ -16,27 +16,29 @@ CREATE TABLE IF NOT EXISTS Shop_Product_Permutation_Temp ( cost_local FLOAT NOT NULL, id_currency_cost INT NOT NULL, profit_local_min FLOAT NOT NULL, - latency_manufacture INT NOT NULL, + latency_manufacture_days INT NOT NULL, + id_unit_measurement_quantity INT NOT NULL, + CONSTRAINT FK_Shop_Product_Permutation_Temp_id_unit_quantity + FOREIGN KEY (id_unit_measurement_quantity) + REFERENCES Shop_Unit_Measurement(id_unit_measurement), + count_unit_measurement_per_quantity_step FLOAT NOT NULL, quantity_min FLOAT NOT NULL, quantity_max FLOAT NOT NULL, - quantity_step FLOAT NOT NULL, - quantity_stock FLOAT NOT NULL, + quantity_stock FLOAT NULL, is_subscription BIT NOT NULL, - id_interval_recurrence INT, - CONSTRAINT FK_Shop_Product_Permutation_Temp_id_interval_recurrence - FOREIGN KEY (id_interval_recurrence) + id_unit_measurement_interval_recurrence INT, + CONSTRAINT FK_Shop_Product_Permutation_Temp_id_unit_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) REFERENCES Shop_Unit_Measurement(id_unit_measurement), count_interval_recurrence INT, id_stripe_product VARCHAR(100) NULL, does_expire_faster_once_unsealed BIT NOT NULL DEFAULT 0, - id_interval_expiration_unsealed INT, - CONSTRAINT FK_Shop_Product_Permutation_Temp_id_interval_expiration_unsealed - FOREIGN KEY (id_interval_expiration_unsealed) + id_unit_measurement_interval_expiration_unsealed INT, + CONSTRAINT FK_Shop_Product_Permutation_Temp_id_unit_expiration + FOREIGN KEY (id_unit_measurement_interval_expiration_unsealed) REFERENCES Shop_Unit_Measurement(id_unit_measurement), count_interval_expiration_unsealed INT, active BIT NOT NULL DEFAULT 1, - display_order INT NOT NULL, - created_on TIMESTAMP, - created_by INT, + -- display_order INT NOT NULL, guid BINARY(36) ); diff --git a/static/MySQL/3203_tri_Shop_Product.sql b/static/MySQL/3203_tri_Shop_Product.sql index f94f065d..d302762d 100644 --- a/static/MySQL/3203_tri_Shop_Product.sql +++ b/static/MySQL/3203_tri_Shop_Product.sql @@ -62,11 +62,11 @@ BEGIN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Product must have subscription status or variations (with subscription statuses).'; END IF; - IF ISNULL(NEW.id_recurrence_interval) THEN + IF ISNULL(NEW.id_unit_measurement_interval_recurrence) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Product must have recurrence interval or variations (with recurrence intervals).'; END IF; - IF ISNULL(NEW.count_recurrence_interval) THEN + IF ISNULL(NEW.count_interval_recurrence) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Product must have recurrence interval count or variations (with recurrence interval counts).'; END IF; @@ -136,13 +136,13 @@ BEGIN SELECT NEW.id_product, 'is_subscription', CONVERT(CONVERT(OLD.is_subscription, SIGNED), CHAR), CONVERT(CONVERT(NEW.is_subscription, SIGNED), CHAR), NEW.id_change_set WHERE NOT OLD.is_subscription <=> NEW.is_subscription UNION - # Changed id_recurrence_interval - SELECT NEW.id_product, 'id_recurrence_interval', CONVERT(OLD.id_recurrence_interval, CHAR), CONVERT(NEW.id_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.id_recurrence_interval <=> NEW.id_recurrence_interval + # Changed id_unit_measurement_interval_recurrence + SELECT NEW.id_product, 'id_unit_measurement_interval_recurrence', CONVERT(OLD.id_unit_measurement_interval_recurrence, CHAR), CONVERT(NEW.id_unit_measurement_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.id_unit_measurement_interval_recurrence <=> NEW.id_unit_measurement_interval_recurrence UNION - # Changed count_recurrence_interval - SELECT NEW.id_product, 'count_recurrence_interval', CONVERT(OLD.count_recurrence_interval, CHAR), CONVERT(NEW.count_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.count_recurrence_interval <=> NEW.count_recurrence_interval + # Changed count_interval_recurrence + SELECT NEW.id_product, 'count_interval_recurrence', CONVERT(OLD.count_interval_recurrence, CHAR), CONVERT(NEW.count_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.count_interval_recurrence <=> NEW.count_interval_recurrence UNION # Changed id_stripe_product SELECT NEW.id_product, 'id_stripe_product', OLD.id_stripe_product, NEW.id_stripe_product, NEW.id_change_set diff --git a/static/MySQL/3206_tri_Shop_Product_Permutation.sql b/static/MySQL/3206_tri_Shop_Product_Permutation.sql index 4f1075a3..4ef35e7f 100644 --- a/static/MySQL/3206_tri_Shop_Product_Permutation.sql +++ b/static/MySQL/3206_tri_Shop_Product_Permutation.sql @@ -29,16 +29,16 @@ BEGIN END IF; IF (NOT ( - NEW.id_interval_recurrence IS NULL - OR NEW.id_interval_recurrence NOT IN (SELECT id_unit_measurement FROM Shop_Unit_Measurement WHERE is_unit_of_time = 1) + NEW.id_unit_measurement_interval_recurrence IS NULL + OR NEW.id_unit_measurement_interval_recurrence NOT IN (SELECT id_unit_measurement FROM Shop_Unit_Measurement WHERE is_unit_of_time = 1) )) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Recurrence interval ID must be a unit of time.'; END IF; IF (NOT ( - NEW.id_interval_expiration_unsealed IS NULL - OR NEW.id_interval_expiration_unsealed NOT IN (SELECT id_unit_measurement FROM Shop_Unit_Measurement WHERE is_unit_of_time = 1) + NEW.id_unit_measurement_interval_expiration_unsealed IS NULL + OR NEW.id_unit_measurement_interval_expiration_unsealed NOT IN (SELECT id_unit_measurement FROM Shop_Unit_Measurement WHERE is_unit_of_time = 1) )) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Unsealed expiration interval ID must be a unit of time.'; @@ -77,11 +77,11 @@ BEGIN SELECT NEW.id_permutation, 'id_currency_cost', CONVERT(OLD.id_currency_cost, CHAR), CONVERT(NEW.id_currency_cost, CHAR), NEW.id_change_set WHERE NOT (OLD.id_currency_cost <=> NEW.id_currency_cost) UNION + /* # Changed profit_local_min SELECT NEW.id_permutation, 'profit_local_min', CONVERT(OLD.profit_local_min, CHAR), CONVERT(NEW.profit_local_min, CHAR), NEW.id_change_set WHERE NOT (OLD.profit_local_min <=> NEW.profit_local_min) UNION - /* # Changed id_currency_profit_min SELECT NEW.id_permutation, 'id_currency_profit_min', CONVERT(OLD.id_currency_profit_min, CHAR), CONVERT(NEW.id_currency_profit_min, CHAR), NEW.id_change_set WHERE NOT (OLD.id_currency_profit_min <=> NEW.id_currency_profit_min) @@ -93,36 +93,40 @@ BEGIN WHERE NOT (OLD.price_GBP_min <=> NEW.price_GBP_min) UNION */ - # Changed latency_manufacture - SELECT NEW.id_product, 'latency_manufacture', CONVERT(OLD.latency_manufacture, CHAR), CONVERT(NEW.latency_manufacture, CHAR), NEW.id_change_set - WHERE NOT OLD.latency_manufacture <=> NEW.latency_manufacture + # Changed latency_manufacture_days + SELECT NEW.id_permutation, 'latency_manufacture_days', CONVERT(OLD.latency_manufacture_days, CHAR), CONVERT(NEW.latency_manufacture_days, CHAR), NEW.id_change_set + WHERE NOT OLD.latency_manufacture_days <=> NEW.latency_manufacture_days + UNION + # Changed id_unit_measurement_quantity + SELECT NEW.id_permutation, 'id_unit_measurement_quantity', CONVERT(OLD.id_unit_measurement_quantity, CHAR), CONVERT(NEW.id_unit_measurement_quantity, CHAR), NEW.id_change_set + WHERE NOT OLD.id_unit_measurement_quantity <=> NEW.id_unit_measurement_quantity + UNION + # Changed count_unit_measurement_per_quantity_step + SELECT NEW.id_permutation, 'count_unit_measurement_per_quantity_step', CONVERT(OLD.count_unit_measurement_per_quantity_step, CHAR), CONVERT(NEW.count_unit_measurement_per_quantity_step, CHAR), NEW.id_change_set + WHERE NOT OLD.count_unit_measurement_per_quantity_step <=> NEW.count_unit_measurement_per_quantity_step UNION # Changed quantity_min - SELECT NEW.id_product, 'quantity_min', CONVERT(OLD.quantity_min, CHAR), CONVERT(NEW.quantity_min, CHAR), NEW.id_change_set + SELECT NEW.id_permutation, 'quantity_min', CONVERT(OLD.quantity_min, CHAR), CONVERT(NEW.quantity_min, CHAR), NEW.id_change_set WHERE NOT OLD.quantity_min <=> NEW.quantity_min UNION # Changed quantity_max - SELECT NEW.id_product, 'quantity_max', CONVERT(OLD.quantity_max, CHAR), CONVERT(NEW.quantity_max, CHAR), NEW.id_change_set + SELECT NEW.id_permutation, 'quantity_max', CONVERT(OLD.quantity_max, CHAR), CONVERT(NEW.quantity_max, CHAR), NEW.id_change_set WHERE NOT OLD.quantity_max <=> NEW.quantity_max UNION - # Changed quantity_step - SELECT NEW.id_product, 'quantity_step', CONVERT(OLD.quantity_step, CHAR), CONVERT(NEW.quantity_step, CHAR), NEW.id_change_set - WHERE NOT OLD.quantity_step <=> NEW.quantity_step - UNION # Changed quantity_stock - SELECT NEW.id_product, 'quantity_stock', CONVERT(OLD.quantity_stock, CHAR), CONVERT(NEW.quantity_stock, CHAR), NEW.id_change_set + SELECT NEW.id_permutation, 'quantity_stock', CONVERT(OLD.quantity_stock, CHAR), CONVERT(NEW.quantity_stock, CHAR), NEW.id_change_set WHERE NOT OLD.quantity_stock <=> NEW.quantity_stock UNION # Changed is_subscription - SELECT NEW.id_product, 'is_subscription', CONVERT(CONVERT(OLD.is_subscription, SIGNED), CHAR), CONVERT(CONVERT(NEW.is_subscription, SIGNED), CHAR), NEW.id_change_set + SELECT NEW.id_permutation, 'is_subscription', CONVERT(CONVERT(OLD.is_subscription, SIGNED), CHAR), CONVERT(CONVERT(NEW.is_subscription, SIGNED), CHAR), NEW.id_change_set WHERE NOT OLD.is_subscription <=> NEW.is_subscription UNION - # Changed id_interval_recurrence - SELECT NEW.id_product, 'id_interval_recurrence', CONVERT(OLD.id_interval_recurrence, CHAR), CONVERT(NEW.id_interval_recurrence, CHAR), NEW.id_change_set - WHERE NOT OLD.id_interval_recurrence <=> NEW.id_interval_recurrence + # Changed id_unit_measurement_interval_recurrence + SELECT NEW.id_permutation, 'id_unit_measurement_interval_recurrence', CONVERT(OLD.id_unit_measurement_interval_recurrence, CHAR), CONVERT(NEW.id_unit_measurement_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.id_unit_measurement_interval_recurrence <=> NEW.id_unit_measurement_interval_recurrence UNION # Changed count_interval_recurrence - SELECT NEW.id_product, 'count_interval_recurrence', CONVERT(OLD.count_interval_recurrence, CHAR), CONVERT(NEW.count_interval_recurrence, CHAR), NEW.id_change_set + SELECT NEW.id_permutation, 'count_interval_recurrence', CONVERT(OLD.count_interval_recurrence, CHAR), CONVERT(NEW.count_interval_recurrence, CHAR), NEW.id_change_set WHERE NOT OLD.count_interval_recurrence <=> NEW.count_interval_recurrence UNION # Changed id_stripe_product @@ -130,24 +134,26 @@ BEGIN WHERE NOT (OLD.id_stripe_product <=> NEW.id_stripe_product) UNION # Changed does_expire_faster_once_unsealed - SELECT NEW.id_product, 'does_expire_faster_once_unsealed', CONVERT(OLD.does_expire_faster_once_unsealed, CHAR), CONVERT(NEW.does_expire_faster_once_unsealed, CHAR), NEW.id_change_set + SELECT NEW.id_permutation, 'does_expire_faster_once_unsealed', CONVERT(OLD.does_expire_faster_once_unsealed, CHAR), CONVERT(NEW.does_expire_faster_once_unsealed, CHAR), NEW.id_change_set WHERE NOT OLD.does_expire_faster_once_unsealed <=> NEW.does_expire_faster_once_unsealed UNION - # Changed id_interval_expiration_unsealed - SELECT NEW.id_product, 'id_interval_expiration_unsealed', CONVERT(OLD.id_interval_expiration_unsealed, CHAR), CONVERT(NEW.id_interval_expiration_unsealed, CHAR), NEW.id_change_set - WHERE NOT OLD.id_interval_expiration_unsealed <=> NEW.id_interval_expiration_unsealed + # Changed id_unit_measurement_interval_expiration_unsealed + SELECT NEW.id_permutation, 'id_unit_measurement_interval_expiration_unsealed', CONVERT(OLD.id_unit_measurement_interval_expiration_unsealed, CHAR), CONVERT(NEW.id_unit_measurement_interval_expiration_unsealed, CHAR), NEW.id_change_set + WHERE NOT OLD.id_unit_measurement_interval_expiration_unsealed <=> NEW.id_unit_measurement_interval_expiration_unsealed UNION # Changed count_interval_expiration_unsealed - SELECT NEW.id_product, 'count_interval_expiration_unsealed', CONVERT(OLD.count_interval_expiration_unsealed, CHAR), CONVERT(NEW.count_interval_expiration_unsealed, CHAR), NEW.id_change_set + SELECT NEW.id_permutation, 'count_interval_expiration_unsealed', CONVERT(OLD.count_interval_expiration_unsealed, CHAR), CONVERT(NEW.count_interval_expiration_unsealed, CHAR), NEW.id_change_set WHERE NOT OLD.count_interval_expiration_unsealed <=> NEW.count_interval_expiration_unsealed UNION # Changed active SELECT NEW.id_permutation, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set WHERE NOT (OLD.active <=> NEW.active) - UNION + /* + UNION # Changed display_order SELECT NEW.id_permutation, 'display_order', CONVERT(OLD.display_order, CHAR), CONVERT(NEW.display_order, CHAR), NEW.id_change_set WHERE NOT (OLD.display_order <=> NEW.display_order) + */ ; END // DELIMITER ;; diff --git a/static/MySQL/6206_fn_shop_get_product_permutation_name.sql b/static/MySQL/6206_fn_shop_get_product_permutation_name.sql new file mode 100644 index 00000000..a5b8545a --- /dev/null +++ b/static/MySQL/6206_fn_shop_get_product_permutation_name.sql @@ -0,0 +1,33 @@ + +DROP FUNCTION IF EXISTS fn_shop_get_product_permutation_name; + +DELIMITER // + +CREATE FUNCTION fn_shop_get_product_permutation_name(id_product_permutation INT) +RETURNS VARCHAR(4000) +DETERMINISTIC +BEGIN + DECLARE name VARCHAR(4000); + + SET name := ( + SELECT + CONCAT( + P.name + , CASE WHEN P.has_variations = 1 THEN + CONCAT(' - ', GROUP_CONCAT(CONCAT(VT.name, ': ', V.name) SEPARATOR ', ')) + ELSE '' END + ) + FROM Shop_Product_Permutation PP + INNER JOIN Shop_Product P ON PP.id_product = P.id_product + INNER JOIN Shop_Product_Permutation_Variation_Link PPVL ON PP.id_permutation = PPVL.id_permutation + INNER JOIN Shop_Variation V ON PPVL.id_variation = V.id_variation + INNER JOIN Shop_Variation_Type VT ON V.id_type = VT.id_type + WHERE PP.id_permutation = id_product_permutation + GROUP BY P.id_product, P.name, P.has_variations, VT.display_order, VT.name, V.display_order, V.name + LIMIT 1 + ); + + RETURN name; +END // + +DELIMITER ; diff --git a/static/MySQL/7003_p_shop_get_many_access_level.sql b/static/MySQL/7003_p_shop_get_many_access_level.sql index 9cd0b285..8959e2e7 100644 --- a/static/MySQL/7003_p_shop_get_many_access_level.sql +++ b/static/MySQL/7003_p_shop_get_many_access_level.sql @@ -16,19 +16,18 @@ DROP PROCEDURE IF EXISTS p_shop_get_many_access_level; DELIMITER // CREATE PROCEDURE p_shop_get_many_access_level ( - IN a_id_user INT, IN a_get_inactive_access_level BIT ) BEGIN SET a_get_inactive_access_level = IFNULL(a_get_inactive_access_level, 0); SELECT - AL.id_access_level, - AL.code, - AL.name, - AL.active, - AL.priority, - AL.display_order + AL.id_access_level + , AL.code + , AL.name + , AL.active + , AL.priority + , AL.display_order FROM Shop_Access_Level AL WHERE a_get_inactive_access_level = 1 diff --git a/static/MySQL/7116_p_shop_get_many_currency.sql b/static/MySQL/7116_p_shop_get_many_currency.sql index 929eba44..29c99957 100644 --- a/static/MySQL/7116_p_shop_get_many_currency.sql +++ b/static/MySQL/7116_p_shop_get_many_currency.sql @@ -27,9 +27,10 @@ BEGIN C.id_currency, C.code, C.name, + C.symbol, C.factor_from_GBP, - C.active, - C.display_order + C.display_order, + C.active FROM Shop_Currency C WHERE a_get_inactive_currency OR C.active diff --git a/static/MySQL/7122_p_shop_get_many_unit_measurement.sql b/static/MySQL/7122_p_shop_get_many_unit_measurement.sql new file mode 100644 index 00000000..4beb7a25 --- /dev/null +++ b/static/MySQL/7122_p_shop_get_many_unit_measurement.sql @@ -0,0 +1,41 @@ + +-- Clear previous proc +DROP PROCEDURE IF EXISTS p_shop_get_many_unit_measurement; + + +DELIMITER // +CREATE PROCEDURE p_shop_get_many_unit_measurement ( + IN a_get_inactive_unit_measurement BIT +) +BEGIN + SET a_get_inactive_unit_measurement := IFNULL(a_get_inactive_unit_measurement, 0); + + SELECT + UM.id_unit_measurement, + UM.name_singular, + UM.name_plural, + UM.symbol, + UM.symbol_is_suffix_not_prefix, + UM.is_base_unit, + UM.is_unit_of_distance, + UM.is_unit_of_mass, + UM.is_unit_of_time, + UM.is_unit_of_volume, + UM.active + FROM Shop_Unit_Measurement UM + WHERE + a_get_inactive_unit_measurement = 1 + OR UM.active = 1 + ; +END // +DELIMITER ;; + + +/* +CALL p_shop_get_many_unit_measurement ( + 0 # a_get_inactive_unit_measurement +); + +select * +from shop_unit_measurement +*/ diff --git a/static/MySQL/7200_p_shop_save_product_category.sql b/static/MySQL/7200_p_shop_save_product_category.sql index 84cecf5b..abc3e0a2 100644 --- a/static/MySQL/7200_p_shop_save_product_category.sql +++ b/static/MySQL/7200_p_shop_save_product_category.sql @@ -1,7 +1,5 @@ - - -- Clear previous proc DROP PROCEDURE IF EXISTS p_save_category; DROP PROCEDURE IF EXISTS p_shop_save_category; diff --git a/static/MySQL/7204_p_shop_get_many_product.sql b/static/MySQL/7204_p_shop_get_many_product.sql index 6b20ac92..1d005268 100644 --- a/static/MySQL/7204_p_shop_get_many_product.sql +++ b/static/MySQL/7204_p_shop_get_many_product.sql @@ -95,11 +95,11 @@ BEGIN ); CREATE TEMPORARY TABLE tmp_Permutation ( - -- id_category INT NOT NULL, - id_product INT NOT NULL, - id_permutation INT NULL, - active BIT NOT NULL, - display_order INT NOT NULL + id_permutation INT NULL + -- id_category INT NOT NULL, + , id_product INT NOT NULL + , active BIT NOT NULL + -- , display_order INT NOT NULL ); CREATE TEMPORARY TABLE tmp_Image ( @@ -178,18 +178,18 @@ BEGIN ; INSERT INTO tmp_Permutation ( + id_permutation -- id_category, - id_product, - id_permutation, - active, - display_order + , id_product + , active + -- , display_order ) SELECT + PP.id_permutation -- P.id_category, - PP.id_product, - PP.id_permutation, - PP.active, - PP.display_order + , PP.id_product + , PP.active + -- , RANK() OVER (ORDER BY VT.display_order, V.display_order) FROM Shop_Product_Permutation PP INNER JOIN tmp_Product t_P ON PP.id_product = t_P.id_product WHERE ( @@ -370,19 +370,35 @@ BEGIN PP.id_currency_cost, C.code AS code_currency_cost, C.symbol AS symbol_currency_cost, - PP.profit_local_min, - PP.latency_manufacture, + -- PP.profit_local_min, + PP.latency_manufacture_days, + PP.id_unit_measurement_quantity, + UM_Q.symbol AS symbol_unit_measurement_quantity, + UM_Q.symbol_is_suffix_not_prefix AS symbol_is_suffix_not_prefix_unit_measurement_quantity, + UM_Q.name_singular AS name_singular_unit_measurement_quantity, + UM_Q.name_plural AS name_plural_unit_measurement_quantity, + PP.count_unit_measurement_per_quantity_step, PP.quantity_min, PP.quantity_max, - PP.quantity_step, PP.quantity_stock, - PP.id_stripe_product, PP.is_subscription, - UM.name_singular AS name_recurrence_interval, - UM.name_plural AS name_plural_recurrence_interval, + PP.id_unit_measurement_interval_recurrence, + UM_R.symbol AS symbol_unit_measurement_interval_recurrence, + UM_R.symbol_is_suffix_not_prefix AS symbol_is_suffix_not_prefix_unit_measurement_interval_recurrence, + UM_R.name_singular AS name_singular_unit_measurement_interval_recurrence, + UM_R.name_plural AS name_plural_unit_measurement_interval_recurrence, PP.count_interval_recurrence, + PP.id_stripe_product, + PP.does_expire_faster_once_unsealed, + PP.id_unit_measurement_interval_expiration_unsealed, + UM_X.symbol AS symbol_unit_measurement_interval_expiration_unsealed, + UM_X.symbol_is_suffix_not_prefix AS symbol_is_suffix_not_prefix_unit_measurement_interval_expiration_unsealed, + UM_X.name_singular AS name_singular_unit_measurement_interval_expiration_unsealed, + UM_X.name_plural AS name_plural_unit_measurement_interval_expiration_unsealed, + PP.count_interval_expiration_unsealed, + NOT ISNULL(PPVL.id_permutation) AS has_variations, PP.active, - PP.display_order, + -- PP.display_order, IFNULL(t_P.can_view, 0) AS can_view, IFNULL(t_P.can_edit, 0) AS can_edit, IFNULL(t_P.can_admin, 0) AS can_admin @@ -391,26 +407,28 @@ BEGIN INNER JOIN tmp_Product t_P ON t_PP.id_product = t_P.id_product INNER JOIN Shop_Product P ON t_PP.id_product = P.id_product INNER JOIN Shop_Product_Category PC ON P.id_category = PC.id_category - -- LEFT JOIN Shop_Recurrence_Interval RI ON t_P.id_interval_recurrence = RI.id_interval - LEFT JOIN Shop_Unit_Measurement UM ON PP.id_interval_recurrence = UM.id_unit_measurement + LEFT JOIN Shop_Product_Permutation_Variation_Link PPVL ON PP.id_permutation = PPVL.id_permutation + LEFT JOIN Shop_Unit_Measurement UM_Q ON PP.id_unit_measurement_quantity = UM_Q.id_unit_measurement + LEFT JOIN Shop_Unit_Measurement UM_R ON PP.id_unit_measurement_interval_recurrence = UM_R.id_unit_measurement + LEFT JOIN Shop_Unit_Measurement UM_X ON PP.id_unit_measurement_interval_expiration_unsealed = UM_X.id_unit_measurement INNER JOIN Shop_Currency C ON PP.id_currency_cost = C.id_currency GROUP BY PC.id_category, P.id_product, PP.id_permutation, t_P.can_view, t_P.can_edit, t_P.can_admin - ORDER BY PC.display_order, P.display_order, PP.display_order + ORDER BY PC.display_order, P.display_order -- , t_PP.display_order ; # Variations SELECT V.id_variation + , V.id_type , V.code AS code_variation , V.name AS name_variation + , V.display_order AS display_order_variation , V.active AS active_variation - , V.display_order - , V.id_type , VT.code AS code_variation_type , VT.name AS name_variation_type , VT.name_plural AS name_plural_variation_type + , VT.display_order AS display_order_variation_type , VT.active AS active_variation_type - , VT.display_order , t_P.id_product , t_PP.id_permutation , t_C.id_category @@ -458,7 +476,7 @@ BEGIN INNER JOIN tmp_Permutation t_PP ON t_I.id_permutation = t_PP.id_permutation INNER JOIN tmp_Product t_P ON t_PP.id_product = t_P.id_product INNER JOIN tmp_Category t_C ON t_P.id_category = t_C.id_category - ORDER BY t_C.display_order, t_P.display_order, t_PP.display_order, I.display_order + ORDER BY t_C.display_order, t_P.display_order, I.display_order ; # Errors @@ -514,7 +532,7 @@ DELIMITER ;; CALL partsltd_prod.p_shop_get_many_product ( 1 #'auth0|6582b95c895d09a70ba10fef', # a_id_user , 1 # a_get_all_product_category - , 1 # a_get_inactive_product_category + , 0 # a_get_inactive_product_category , '' # a_ids_product_category , 1 # a_get_all_product , 0 # a_get_inactive_product @@ -525,7 +543,7 @@ CALL partsltd_prod.p_shop_get_many_product ( , 1 # a_get_all_image , 0 # a_get_inactive_image , '' # a_ids_image - , 1 # a_get_products_quantity_stock_below_minimum + , 0 # a_get_products_quantity_stock_below_minimum ); select * FROM Shop_User_Eval_Temp; diff --git a/static/MySQL/7206_p_shop_save_permutation.sql b/static/MySQL/7206_p_shop_save_permutation.sql deleted file mode 100644 index b64dab31..00000000 --- a/static/MySQL/7206_p_shop_save_permutation.sql +++ /dev/null @@ -1,605 +0,0 @@ - - - - --- Clear previous proc -DROP PROCEDURE IF EXISTS p_shop_save_permutation; - -DROP TABLE IF EXISTS tmp_Shop_Manufacturing_Purchase_Order_Product_Link; -DROP TABLE IF EXISTS tmp_Msg_Error; - -DELIMITER // -CREATE PROCEDURE p_shop_save_permutation ( - IN a_guid VARCHAR(500), - IN a_id_user INT, - IN a_id_order INT, - -- IN a_id_supplier_ordered INT, - IN a_id_currency_cost INT, - IN a_active BIT, - IN a_comment VARCHAR(500) -) -BEGIN - DECLARE v_id_error_type_bad_data INT; - DECLARE v_code_error_type_bad_data VARCHAR(50); - DECLARE v_id_error_type_no_permission INT; - DECLARE v_code_error_type_no_permission VARCHAR(50); - DECLARE v_guid_permission BINARY(36); - -- DECLARE v_id_user VARCHAR(100); - DECLARE v_id_permission_manufacturing_purchase_order INT; - DECLARE v_id_access_level_EDIT INT; - DECLARE v_ids_product VARCHAR(4000); - DECLARE v_ids_product_no_permission VARCHAR(4000); - -- DECLARE v_id_order_new INT; - DECLARE v_id_change_set INT; - DECLARE v_is_new_manufacturing_purchase_order BIT; - - SET SESSION sql_mode = sys.list_drop(@@session.sql_mode, 'ONLY_FULL_GROUP_BY'); - - SET v_code_error_type_bad_data = 'BAD_DATA'; - SET v_id_error_type_bad_data := (SELECT id_type FROM Shop_Msg_Error_Type WHERE code = v_code_error_type_bad_data LIMIT 1); - SET v_code_error_type_no_permission = 'NO_PERMISSION'; - SET v_id_error_type_no_permission := (SELECT id_type FROM Shop_Msg_Error_Type WHERE code = v_code_error_type_no_permission LIMIT 1); - SET v_guid_permission = UUID(); - -- SET v_id_user = CURRENT_USER(); - SET v_id_permission_manufacturing_purchase_order := (SELECT id_permission FROM Shop_Permission WHERE code = 'STORE_MANUFACTURING_PURCHASE_ORDER' LIMIT 1); - SET v_id_access_level_EDIT := (SELECT id_access_level FROM Shop_Access_Level WHERE code = 'EDIT'); - - -- Argument default values - IF a_guid IS NULL THEN - SET a_guid = UUID(); - END IF; - IF a_active IS NULL THEN - SET a_active = 0; - END IF; - - -- Temporary tables - /* - CREATE TABLE tmp_Shop_Supplier_Purchase_Order ( - id_order INT NOT NULL PRIMARY KEY, - id_supplier_ordered INT NOT NULL, - CONSTRAINT FK_tmp_Shop_Supplier_Purchase_Order_id_supplier_ordered - FOREIGN KEY (id_supplier_ordered) - REFERENCES Shop_Supplier(id_supplier), - cost_total_local FLOAT NOT NULL, - id_currency_cost INT NOT NULL - ); - */ - - CREATE TABLE tmp_Shop_Manufacturing_Purchase_Order_Product_Link ( - id_link INT NOT NULL PRIMARY KEY, - id_order INT NOT NULL, - /* - CONSTRAINT FK_tmp_Supplier_Purchase_Order_Product_Link_id_order - FOREIGN KEY (id_order) - REFERENCES Shop_Manufacturing_Purchase_Order(id_order), - */ - id_permutation INT NOT NULL, - CONSTRAINT FK_tmp_Manuf_Purch_Order_Product_Link_id_permutation - FOREIGN KEY (id_permutation) - REFERENCES Shop_Product_Permutation(id_permutation), - cost_total_local FLOAT NOT NULL, - id_currency_cost INT NOT NULL, - value_produced_total_local FLOAT NOT NULL, - quantity_used FLOAT NOT NULL, - id_unit_quantity INT NOT NULL, - CONSTRAINT FK_tmp_Manuf_Purch_Order_Product_Link_id_unit_quantity - FOREIGN KEY (id_unit_quantity) - REFERENCES Shop_Unit_Measurement(id_unit_measurement), - quantity_produced FLOAT NULL, - latency_manufacture_days INT NOT NULL, - display_order INT NOT NULL, - active BIT NOT NULL, - name_error VARCHAR(200) NOT NULL - ); - - CREATE TABLE IF NOT EXISTS tmp_Msg_Error ( - display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT, - guid BINARY(36) NOT NULL, - id_type INT NOT NULL, - CONSTRAINT FK_tmp_Msg_Error_id_type - FOREIGN KEY (id_type) - REFERENCES Shop_Msg_Error_Type (id_type), - code VARCHAR(50) NOT NULL, - msg VARCHAR(4000) NOT NULL - ); - - - -- Argument validation - # User ID - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - IF ISNULL(a_id_user) OR NOT EXISTS (SELECT * FROM Shop_User WHERE id_user = a_id_user) THEN - INSERT INTO tmp_Msg_Error ( - guid, id_type, code, msg - ) - VALUES - (a_guid, v_id_error_type_bad_data, v_code_error_type_bad_data, CONCAT('Invalid User ID: ', IFNULL(a_id_user, 'NULL'))) - ; - END IF; - END IF; - - # Order ID - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - IF ISNULL(a_id_order) OR ((a_id_order > 0) AND NOT EXISTS (SELECT * FROM Shop_Manufacturing_Purchase_Order WHERE id_order = a_id_order)) THEN - INSERT INTO tmp_Msg_Error ( - guid, id_type, code, msg - ) - VALUES - (a_guid, v_id_error_type_bad_data, v_code_error_type_bad_data, CONCAT('Invalid Manufacturing Purchase Order ID: ', IFNULL(a_id_order, 'NULL'))) - ; - END IF; - END IF; - - /* - # Supplier ID - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - IF ISNULL(a_id_supplier_ordered) OR NOT EXISTS (SELECT * FROM Shop_Supplier WHERE id_supplier = a_id_supplier_ordered) THEN - INSERT INTO tmp_Msg_Error ( - guid, id_type, code, msg - ) - VALUES - (a_guid, v_id_error_type_bad_data, v_code_error_type_bad_data, CONCAT('Invalid supplier ID: ', IFNULL(a_id_supplier_ordered, 'NULL'))) - ; - END IF; - END IF; - */ - - # Currency ID - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - IF ISNULL(a_id_currency_cost) OR NOT EXISTS (SELECT * FROM Shop_Currency WHERE id_currency = a_id_currency_cost) THEN - INSERT INTO tmp_Msg_Error ( - guid, id_type, code, msg - ) - VALUES - (a_guid, v_id_error_type_bad_data, v_code_error_type_bad_data, CONCAT('Invalid currency ID: ', IFNULL(a_id_currency, 'NULL'))) - ; - END IF; - END IF; - - # Comment - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - IF ISNULL(a_comment) OR TRIM(a_comment) = '' THEN - INSERT INTO tmp_Msg_Error ( - guid, id_type, code, msg - ) - VALUES - (a_guid, v_id_error_type_bad_data, v_code_error_type_bad_data, 'A comment must be provided.') - ; - END IF; - END IF; - - - -- Get data from Temp table - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - SET v_is_new_manufacturing_purchase_order := CASE WHEN a_id_order <= 0 THEN 1 ELSE 0 END; - - INSERT INTO tmp_Shop_Manufacturing_Purchase_Order_Product_Link ( - id_link, - id_order, - id_permutation, - cost_total_local, - id_currency_cost, - quantity_used, - id_unit_quantity, - quantity_produced, - value_produced_total_local, - latency_manufacture_days, - display_order, - active, - name_error - ) - /* - VALUES - (a_id_supplier, a_name_company, a_name_contact, a_department_contact, a_id_address, a_phone_number, a_fax, a_email, a_website, a_id_currency, a_active) - */ - SELECT - MPOPL_T.id_link, - MPOPL_T.id_order, - MPOPL_T.id_permutation, - PP.cost_local * MPOPL_T.quantity_used AS cost_total_local, - MPOPL_T.id_currency_cost, - MPOPL_T.quantity_used, - MPOPL_T.id_unit_quantity, - MPOPL_T.quantity_produced, - (PP.cost_local + PP.profit_local_min) * MPOPL_T.quantity_produced AS value_produced_total_local, - MPOPL_T.latency_manufacture_days, - MPOPL_T.display_order, - MPOPL_T.active, - CONCAT(PP.id_permutation, ' - ', IFNULL(P.name ,'')) AS name_error - FROM Shop_Manufacturing_Purchase_Order_Product_Link_Temp MPOPL_T - INNER JOIN Shop_Product_Permutation PP ON MPOPL_T.id_permutation = PP.id_permutation - INNER JOIN Shop_Product P ON PP.id_product = P.id_product - WHERE MPOPL_T.GUID = a_guid - -- GROUP BY MPOPL_T.id_order, name_error, MPOPL_T.id_link - /* - group by - MPOPL_T.id_link, - MPOPL_T.id_order, - MPOPL_T.id_permutation, - cost_total_local, - MPOPL_T.id_currency_cost, - MPOPL_T.quantity_used, - MPOPL_T.id_unit_quantity, - MPOPL_T.quantity_produced, - value_produced_total_local, - MPOPL_T.latency_manufacture_days, - MPOPL_T.display_order, - MPOPL_T.active, - name_error - */ - -- GROUP BY id_link, P.id_product, PP.id_permutation - -- GROUP BY name_error, ID_LINK, cost_total_local, value_produced_total_local - ; - DELETE MPOPL_T - FROM Shop_Manufacturing_Purchase_Order_Product_Link_Temp MPOPL_T - WHERE MPOPL_T.GUID = a_guid - ; - END IF; - - -- Invalid quantity used - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - IF EXISTS ( - SELECT * - FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link - WHERE - NOT ISNULL(quantity_used) - AND quantity_used < 0 - ) THEN - INSERT INTO tmp_Msg_Error ( - guid, id_type, code, msg - ) - SELECT - a_guid, - v_id_error_type_bad_data, - v_code_error_type_bad_data, - CONCAT('Invalid quantity used property for the following permutations: ', GROUP_CONCAT(t_MPOPL.name_error SEPARATOR ', ')) - FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPOPL - WHERE t_MPOPL.quantity_used < 0 - ; - END IF; - END IF; - - -- Invalid quantity produced - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - IF EXISTS ( - SELECT * - FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link - WHERE - NOT ISNULL(quantity_produced) - AND quantity_produced < 0 - ) THEN - INSERT INTO tmp_Msg_Error ( - guid, id_type, code, msg - ) - SELECT - a_guid, - v_id_error_type_bad_data, - v_code_error_type_bad_data, - CONCAT('Invalid quantity produced property for the following permutations: ', GROUP_CONCAT(t_MPOPL.name_error SEPARATOR ', ')) - FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPOPL - WHERE t_MPOPL.quantity_produced < 0 - ; - END IF; - END IF; - - -- Duplicates - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - IF EXISTS (SELECT id_permutation, name_error, COUNT(*) FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPOPL GROUP BY id_permutation HAVING COUNT(*) > 1) THEN - INSERT INTO tmp_Msg_Error ( - guid, id_type, code, msg - ) - SELECT - a_guid, - v_id_error_type_bad_data, - v_code_error_type_bad_data, - CONCAT('Duplicate records: ', GROUP_CONCAT(t_MPOPLC.name_error SEPARATOR ', ')) - FROM (SELECT id_permutation, name_error, COUNT(*) FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPOPL GROUP BY id_permutation HAVING COUNT(*) > 1) t_MPOPLC - ; - END IF; - END IF; - - - -- Permissions - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - SET v_ids_product := ( - SELECT GROUP_CONCAT(G.id_product SEPARATOR ',') - FROM ( - SELECT DISTINCT PP.id_product - FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPO - INNER JOIN Shop_Product_Permutation PP ON t_MPO.id_permutation = PP.id_permutation - ) G - ); - - CALL p_shop_user_eval(v_guid_permission, a_id_user, 0, v_id_permission_manufacturing_purchase_order, v_id_access_level_edit, v_ids_product); - - /* - UPDATE tmp_Shop_Supplier t_S - INNER JOIN Shop_User_Eval_Temp TP - ON TP.GUID = v_guid_permission - SET tP.can_view = TP.can_view, - tP.can_edit = TP.can_edit, - tP.can_admin = TP.can_admin; - */ - /* - SET v_has_permission := ( - SELECT can_edit - FROM Shop_User_Eval_Temp - WHERE - GUID = v_guid_permission - AND can_edit = 0 - ); - - IF v_has_permission = 0 THEN - SET v_id_error_type_no_permission := (SELECT id_type FROM Shop_Msg_Error_Type WHERE code = 'NO_PERMISSION'); - INSERT INTO tmp_Msg_Error ( - guid, id_type, msg - ) - SELECT - a_guid, - v_id_error_type_no_permission, - CONCAT('You do not have ', name, ' permissions.') - FROM Shop_Permission - WHERE id_permission = v_id_permission_manufacturing_purchase_order - ; - END IF; - */ - SET v_ids_product_no_permission := ( - SELECT GROUP_CONCAT(PT.id_product SEPARATOR ',') - FROM Shop_User_Eval_Temp PT - WHERE - PT.can_edit = 0 - AND NOT ISNULL(PT.id_product) - ); - IF NOT ISNULL(v_ids_product_no_permission) THEN - INSERT INTO tmp_Msg_Error ( - guid, id_type, code, msg - ) - VALUES ( - a_guid, - v_id_error_type_no_permission, - v_code_error_type_no_permission, - CONCAT('You do not have permission to edit the following product IDs: ', v_ids_product_no_permission) - ) - ; - END IF; - END IF; - - -- Transaction - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error) THEN - START TRANSACTION; - INSERT INTO Shop_Sales_And_Purchasing_Change_Set ( - comment, - updated_last_by, - updated_last_on - ) - VALUES ( - CONCAT( - 'Save ', - CASE WHEN v_is_new_manufacturing_purchase_order = 1 THEN 'new ' ELSE '' END, - 'Manufacturing Purchase Order - ', - a_comment - ), - a_id_user, - CURRENT_TIME() - ); - - SET v_id_change_set := (SELECT id_change_set FROM Shop_Sales_And_Purchasing_Change_Set ORDER BY id_change_set DESC LIMIT 1); - - IF (v_is_new_manufacturing_purchase_order = 1) THEN - INSERT INTO Shop_Manufacturing_Purchase_Order ( - -- id_supplier_ordered, - cost_total_local, - id_currency_cost, - value_produced_total_local, - created_by, - id_change_set, - active - ) - SELECT - -- a_id_supplier_ordered, - SUM(t_MPOPL.cost_total_local), - a_id_currency_cost, - SUM(t_MPOPL.value_produced_total_local), - a_id_user, - v_id_change_set, - a_active - FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPOPL - ; - -- SET v_id_order_new - SET a_id_order := (SELECT id_order FROM Shop_Manufacturing_Purchase_Order ORDER BY id_order DESC LIMIT 1); - - INSERT INTO Shop_Manufacturing_Purchase_Order_Product_Link ( - id_order, - id_permutation, - cost_total_local, - value_produced_total_local, - id_currency_cost, - quantity_used, - id_unit_quantity, - quantity_produced, - latency_manufacture_days, - display_order, - active, - created_by, - id_change_set - ) - SELECT - a_id_order, -- v_id_order_new, - id_permutation, - cost_total_local, - value_produced_total_local, - id_currency_cost, - quantity_used, - id_unit_quantity, - quantity_produced, - latency_manufacture_days, - display_order, - active, - a_id_user, - v_id_change_set - FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPOPL - ; - ELSE - UPDATE Shop_Manufacturing_Purchase_Order MPO - INNER JOIN tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPOPL ON MPO.id_order = t_MPOPL.id_order - SET - -- MPO.id_supplier_ordered = a_id_supplier_ordered, - MPO.cost_total_local = SUM(t_MPOPL.cost_total_local), - MPO.value_produced_total_local = SUM(t_MPOPL.value_produced_total_local), - MPO.id_currency = a_id_currency_cost, - MPO.id_change_set = v_id_change_set, - MPO.active = a_active - WHERE MPO.id_order = a_id_order - ; - IF EXISTS (SELECT * FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPOPL INNER JOIN Shop_Manufacturing_Purchase_Order_Product_Link MPOPL ON t_MPOPL.id_link = MPOPL.id_link) THEN - UPDATE Shop_Manufacturing_Purchase_Order_Product_Link MPOPL - INNER JOIN tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPOPL - ON MPOPL.id_link = t_MPOPL.id_link - SET - MPOPL.id_order = t_MPOPL.id_order, - MPOPL.id_permutation = t_MPOPL.id_permutation, - MPOPL.cost_total_local = t_MPOPL.cost_total_local, - MPOPL.value_produced_total_local = t_MPOPL.value_produced_total_local, - MPOPL.id_currency_cost = t_MPOPL.id_currency_cost, - MPOPL.quantity_used = t_MPOPL.quantity_used, - MPOPL.id_unit_quantity = t_MPOPL.id_unit_quantity, - MPOPL.quantity_produced = t_MPOPL.quantity_produced, - MPOPL.latency_manufacture_days = t_MPOPL.latency_manufacture_days, - MPOPL.display_order = t_MPOPL.display_order, - MPOPL.active = t_MPOPL.active, - MPOPL.id_change_set = v_id_change_set - ; - ELSE - INSERT INTO Shop_Manufacturing_Purchase_Order_Product_Link ( - id_order, - id_permutation, - cost_total_local, - value_produced_total_local, - id_currency_cost, - quantity_used, - id_unit_quantity, - quantity_produced, - latency_manufacture_days, - display_order, - active, - created_by, - id_change_set - ) - SELECT - id_order, - id_permutation, - cost_total_local, - value_produced_total_local, - id_currency_cost, - quantity_used, - id_unit_quantity, - quantity_produced, - latency_manufacture_days, - display_order, - active, - a_id_user, - v_id_change_set - FROM tmp_Shop_Manufacturing_Purchase_Order_Product_Link t_MPOPL - WHERE t_MPOPL.id_link < 0 - ; - END IF; - END IF; - - IF EXISTS (SELECT * FROM tmp_Msg_Error) THEN - ROLLBACK; - ELSE - COMMIT; - END IF; - END IF; - - -- Returns - # SET v_now = NOW(); - - # Manufacturing Purchase Orders - SELECT * - FROM Shop_Manufacturing_Purchase_Order - WHERE - id_order = a_id_order - -- GUID = a_guid - ; - - # Manufacturing Purchase Order Product Links - SELECT * - FROM Shop_Manufacturing_Purchase_Order_Product_Link - WHERE - id_order = a_id_order - -- GUID = a_guid - ; - - # Errors - SELECT * - FROM tmp_Msg_Error - ; - - # DROP TABLE tmp_Shop_Manufacturing_Purchase_Order; - DROP TABLE tmp_Shop_Manufacturing_Purchase_Order_Product_Link; - DROP TABLE tmp_Msg_Error; -END // -DELIMITER ;; - - -/* - -DELETE FROM Shop_Manufacturing_Purchase_Order_Product_Link_Audit; -DELETE FROM Shop_Manufacturing_Purchase_Order_Product_Link; -DELETE FROM Shop_Manufacturing_Purchase_Order_Product_Link_Temp; -DELETE FROM Shop_Manufacturing_Purchase_Order_Audit; -DELETE FROM Shop_Manufacturing_Purchase_Order; - -INSERT INTO Shop_Manufacturing_Purchase_Order_Product_Link_Temp ( - guid, - id_link, - id_order, - id_permutation, - cost_total_local, - id_currency_cost, - quantity_used, - id_unit_quantity, - quantity_produced, - latency_manufacture_days, - display_order, - active -) -VALUES - ( - 'NIPS', # guid - -1, # id_link, - -1, # id_order, - 1, # id_permutation, - 100, # cost_total_local, - 1, # id_currency_cost, - 1, # quantity_used, - 1, # id_unit_quantity, - 1, # quantity_produced, - 14, # latency_manufacture_days , - 1, # display_order - 1 # active - ) -; - -SELECT * FROM Shop_Manufacturing_Purchase_Order_Product_Link_Temp; - -CALL p_shop_save_manufacturing_purchase_order ( - 'NIPS', # a_guid - 'auth0|6582b95c895d09a70ba10fef', # a_id_user - -1, # a_id_order - 1, # a_id_currency_cost - 1, # a_active - 'Initial data' # a_comment -); - -SELECT * FROM Shop_Manufacturing_Purchase_Order_Product_Link_Temp; - -DELETE FROM Shop_Manufacturing_Purchase_Order_Product_Link_Audit; -DELETE FROM Shop_Manufacturing_Purchase_Order_Product_Link; -DELETE FROM Shop_Manufacturing_Purchase_Order_Product_Link_Temp; -DELETE FROM Shop_Manufacturing_Purchase_Order_Audit; -DELETE FROM Shop_Manufacturing_Purchase_Order; - - -*/ - diff --git a/static/MySQL/7206_p_shop_save_product_permutation.sql b/static/MySQL/7206_p_shop_save_product_permutation.sql new file mode 100644 index 00000000..fa7dc476 --- /dev/null +++ b/static/MySQL/7206_p_shop_save_product_permutation.sql @@ -0,0 +1,561 @@ + + +-- Clear previous proc +DROP PROCEDURE IF EXISTS p_shop_save_permutation; +DROP PROCEDURE IF EXISTS p_shop_save_product_permutation; + +DELIMITER // +CREATE PROCEDURE p_shop_save_product_permutation ( + IN a_id_user INT, + IN a_comment VARCHAR(500), + IN a_guid BINARY(36) +) +BEGIN + + DECLARE v_code_type_error_bad_data VARCHAR(100); + DECLARE v_id_type_error_bad_data INT; + DECLARE v_id_permission_product INT; + DECLARE v_ids_product_permission LONGTEXT; + DECLARE v_id_change_set INT; + DECLARE v_id_access_level_edit INT; + DECLARE v_now TIMESTAMP; + + DECLARE exit handler for SQLEXCEPTION + BEGIN + -- Get diagnostic information + GET DIAGNOSTICS CONDITION 1 + @sqlstate = RETURNED_SQLSTATE + , @errno = MYSQL_ERRNO + , @text = MESSAGE_TEXT + ; + + -- Rollback the transaction + ROLLBACK; + + -- Select the error information + -- SELECT 'Error' AS status, @errno AS error_code, @sqlstate AS sql_state, @text AS message; + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error ( + display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , guid BINARY(36) NOT NULL + , id_type INT NULL + , code VARCHAR(50) NOT NULL + , msg VARCHAR(4000) NOT NULL + ); + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , code + , msg + ) + SELECT + a_guid + , NULL + , @errno + , @text + ; + SELECT * + FROM tmp_Msg_Error; + DROP TABLE IF EXISTS tmp_Msg_Error; + END; + + SET v_code_type_error_bad_data := 'BAD_DATA'; + SET v_id_type_error_bad_data := (SELECT id_type FROM Shop_Msg_Error_Type WHERE code = v_code_type_error_bad_data LIMIT 1); + SET v_id_access_level_edit := (SELECT id_access_level FROM Shop_Access_Level WHERE code = 'EDIT' LIMIT 1); + + SET a_guid := IFNULL(a_guid, UUID()); + + DROP TABLE IF EXISTS tmp_Permutation; + + CREATE TEMPORARY TABLE tmp_Permutation ( + id_permutation INT NOT NULL + , id_product INT NOT NULL + , description VARCHAR(4000) NOT NULL + , cost_local FLOAT NOT NULL + , id_currency_cost INT NOT NULL + , profit_local_min FLOAT NOT NULL + , latency_manufacture_days INT NOT NULL + , id_unit_measurement_quantity INT NOT NULL + , count_unit_measurement_per_quantity_step FLOAT NOT NULL + , quantity_min FLOAT NOT NULL + , quantity_max FLOAT NOT NULL + , quantity_stock FLOAT NOT NULL + , is_subscription BIT NOT NULL + , id_unit_measurement_interval_recurrence INT + , count_interval_recurrence INT + , id_stripe_product VARCHAR(100) NULL + , does_expire_faster_once_unsealed BIT NOT NULL + , id_unit_measurement_interval_expiration_unsealed INT + , count_interval_expiration_unsealed INT + , active BIT NOT NULL DEFAULT 1 + , can_view BIT NULL + , can_edit BIT NULL + , can_admin BIT NULL + , name_error VARCHAR(255) NOT NULL + , is_new BIT NOT NULL + ); + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error ( + display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , guid BINARY(36) NOT NULL + , id_type INT NULL + , code VARCHAR(50) NOT NULL + , msg VARCHAR(4000) NOT NULL + ); + + + -- Get data from Temp table + INSERT INTO tmp_Permutation ( + id_permutation + , id_product + , description + , cost_local + , id_currency_cost + , profit_local_min + , latency_manufacture_days + , id_unit_measurement_quantity + , count_unit_measurement_per_quantity_step + , quantity_min + , quantity_max + , quantity_stock + , is_subscription + , id_unit_measurement_interval_recurrence + , count_interval_recurrence + , id_stripe_product + , does_expire_faster_once_unsealed + , id_unit_measurement_interval_expiration_unsealed + , count_interval_expiration_unsealed + , active + , name_error + , is_new + ) + SELECT + PP_T.id_permutation + , IFNULL(PP_T.id_product, PP.id_product) AS id_product + , IFNULL(PP_T.description, PP.description) AS description + , IFNULL(PP_T.cost_local, PP.cost_local) AS cost_local + , IFNULL(PP_T.id_currency_cost, PP.id_currency_cost) AS a_id_currency_cost + , IFNULL(PP_T.profit_local_min, PP.profit_local_min) AS profit_local_min + , IFNULL(PP_T.latency_manufacture_days, PP.latency_manufacture_days) AS latency_manufacture_days + , IFNULL(PP_T.id_unit_measurement_quantity, PP.id_unit_measurement_quantity) AS id_unit_measurement_quantity + , IFNULL(PP_T.count_unit_measurement_per_quantity_step, PP.count_unit_measurement_per_quantity_step) AS count_unit_measurement_per_quantity_step + , IFNULL(PP_T.quantity_min, PP.quantity_min) AS quantity_min + , IFNULL(PP_T.quantity_max, PP.quantity_max) AS quantity_max + , IFNULL(PP_T.quantity_stock, PP.quantity_stock) AS quantity_stock + , IFNULL(PP_T.is_subscription, PP.is_subscription) AS is_subscription + , IFNULL(PP_T.id_unit_measurement_interval_recurrence, PP.id_unit_measurement_interval_recurrence) AS id_unit_measurement_interval_recurrence + , IFNULL(PP_T.count_interval_recurrence, PP.count_interval_recurrence) AS count_interval_recurrence + , IFNULL(PP_T.id_stripe_product, PP.id_stripe_product) AS id_stripe_product + , IFNULL(PP_T.does_expire_faster_once_unsealed, PP.does_expire_faster_once_unsealed) AS does_expire_faster_once_unsealed + , IFNULL(PP_T.id_unit_measurement_interval_expiration_unsealed, PP.id_unit_measurement_interval_expiration_unsealed) AS id_unit_measurement_interval_expiration_unsealed + , IFNULL(PP_T.count_interval_expiration_unsealed, PP.count_interval_expiration_unsealed) AS count_interval_expiration_unsealed + , IFNULL(PP_T.active, PP.active) AS active + , fn_shop_get_product_permutation_name(PP_T.id_permutation) + , CASE WHEN IFNULL(PP_T.id_permutation, 0) < 1 THEN 1 ELSE 0 END AS is_new + FROM Shop_Product_Permutation_Temp PP_T + LEFT JOIN Shop_Product_Permutation PP ON PP_T.id_permutation = PP.id_permutation + WHERE PP_T.guid = a_guid + ; + + -- Validation + -- Missing mandatory fields + -- id_product + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.id_product) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , id_product + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have a product: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.id_product) + ; + END IF; + -- cost_local + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.cost_local) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , cost_local + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have a local cost: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.cost_local) + ; + END IF; + -- profit_local_min + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.profit_local_min) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , profit_local_min + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have a local minimum profit: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.profit_local_min) + ; + END IF; + -- latency_manufacture_days + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.latency_manufacture_days) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , latency_manufacture_days + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have a manufacturing latency: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.latency_manufacture_days) + ; + END IF; + -- id_unit_measurement_quantity + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.id_unit_measurement_quantity) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , id_unit_measurement_quantity + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have a unit measurement for stock quantities: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.id_unit_measurement_quantity) + ; + END IF; + -- count_unit_measurement_per_quantity_step + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.count_unit_measurement_per_quantity_step) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , count_unit_measurement_per_quantity_step + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have a count unit measurement per quantity step: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.count_unit_measurement_per_quantity_step) + ; + END IF; + -- quantity_min + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.quantity_min) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , quantity_min + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have a minimum quantity: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.quantity_min) + ; + END IF; + -- quantity_max + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.quantity_max) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , quantity_max + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have a maximum quantity: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.quantity_max) + ; + END IF; + -- is_subscription + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.is_subscription) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , is_subscription + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have an is subscription?: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.is_subscription) + ; + END IF; + -- does_expire_faster_once_unsealed + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.does_expire_faster_once_unsealed) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , does_expire_faster_once_unsealed + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have a does expire faster once unsealed: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.does_expire_faster_once_unsealed) + ; + END IF; + + -- Permissions + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN -- (SELECT * FROM tmp_Product WHERE is_new = 0 LIMIT 1) THEN + SET v_ids_product_permission := ( + SELECT GROUP_CONCAT(P.id_product SEPARATOR ',') + FROM Shop_Product P + INNER JOIN tmp_Permutation t_P + ON P.id_product = t_P.id_product + -- AND t_P.is_new = 0 + ); + IF NOT ISNULL(v_ids_product_permission) THEN + SET v_id_permission_product = (SELECT id_permission FROM Shop_Permission WHERE code = 'STORE_PRODUCT' LIMIT 1); + + CALL p_shop_user_eval(a_guid, a_id_user, FALSE, v_id_permission_product, v_id_access_level_edit, v_ids_product_permission); + + UPDATE tmp_Permutation t_P + INNER JOIN Shop_Product P ON t_P.id_product = P.id_product + INNER JOIN Shop_User_Eval_Temp UE_T + ON P.id_product = UE_T.id_product + AND UE_T.GUID = a_guid + SET + t_P.can_view = UE_T.can_view + , t_P.can_edit = UE_T.can_edit + , t_P.can_admin = UE_T.can_admin + ; + + CALL p_clear_shop_user_eval_temp(a_guid); + + IF EXISTS (SELECT * FROM tmp_Permutation t_P WHERE ISNULL(t_P.can_edit) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + guid + , id_type + , code + , msg + ) + SELECT + a_guid AS GUID + , v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following product permutation(s) do not have product edit permission: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Permutation t_P + WHERE ISNULL(t_P.can_edit) + ; + END IF; + END IF; + END IF; + + SET v_now := CURRENT_TIMESTAMP(); + + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN + START TRANSACTION; + + IF NOT ISNULL(v_ids_product_permission) THEN + INSERT INTO Shop_Product_Change_Set ( comment ) + VALUES ( a_comment ) + ; + + SET v_id_change_set := LAST_INSERT_ID(); + + UPDATE Shop_Product_Permutation PP + INNER JOIN tmp_Permutation t_P ON PP.id_permutation = t_P.id_permutation + SET + PP.id_product = t_P.id_product + , PP.description = t_P.description + , PP.cost_local = t_P.cost_local + , PP.id_currency_cost = t_P.id_currency_cost + , PP.profit_local_min = t_P.profit_local_min + , PP.latency_manufacture_days = t_P.latency_manufacture_days + , PP.id_unit_measurement_quantity = t_P.id_unit_measurement_quantity + , PP.count_unit_measurement_per_quantity_step = t_P.count_unit_measurement_per_quantity_step + , PP.quantity_min = t_P.quantity_min + , PP.quantity_max = t_P.quantity_max + , PP.quantity_stock = t_P.quantity_stock + , PP.is_subscription = t_P.is_subscription + , PP.id_unit_measurement_interval_recurrence = t_P.id_unit_measurement_interval_recurrence + , PP.count_interval_recurrence = t_P.count_interval_recurrence + , PP.id_stripe_product = t_P.id_stripe_product + , PP.does_expire_faster_once_unsealed = t_P.does_expire_faster_once_unsealed + , PP.id_unit_measurement_interval_expiration_unsealed = t_P.id_unit_measurement_interval_expiration_unsealed + , PP.count_interval_expiration_unsealed = t_P.count_interval_expiration_unsealed + , PP.active = t_P.active + , PP.id_change_set = v_id_change_set + ; + END IF; + + INSERT INTO Shop_Product_Permutation ( + id_product + , description + , cost_local + , id_currency_cost + , profit_local_min + , latency_manufacture_days + , id_unit_measurement_quantity + , count_unit_measurement_per_quantity_step + , quantity_min + , quantity_max + , quantity_stock + , is_subscription + , id_unit_measurement_interval_recurrence + , count_interval_recurrence + , id_stripe_product + , does_expire_faster_once_unsealed + , id_unit_measurement_interval_expiration_unsealed + , count_interval_expiration_unsealed + , active + , created_by + , created_on + ) + SELECT + t_P.id_product AS id_product + , t_P.description AS description + , t_P.cost_local AS cost_local + , t_P.id_currency_cost AS id_currency_cost + , t_P.profit_local_min AS profit_local_min + , t_P.latency_manufacture_days AS latency_manufacture_days + , t_P.id_unit_measurement_quantity AS id_unit_measurement_quantity + , t_P.count_unit_measurement_per_quantity_step AS count_unit_measurement_per_quantity_step + , t_P.quantity_min AS quantity_min + , t_P.quantity_max AS quantity_max + , t_P.quantity_stock AS quantity_stock + , t_P.is_subscription AS is_subscription + , t_P.id_unit_measurement_interval_recurrence AS id_unit_measurement_interval_recurrence + , t_P.count_interval_recurrence AS count_interval_recurrence + , t_P.id_stripe_product AS id_stripe_product + , t_P.does_expire_faster_once_unsealed AS does_expire_faster_once_unsealed + , t_P.id_unit_measurement_interval_expiration_unsealed AS id_unit_measurement_interval_expiration_unsealed + , t_P.count_interval_expiration_unsealed AS count_interval_expiration_unsealed + , t_P.active AS active + , a_id_user AS created_by + , v_now AS created_on + FROM tmp_Permutation t_P + WHERE + is_new = 1 + AND active = 1 + ; + + DELETE FROM Shop_Product_Permutation_Temp + WHERE GUID = a_guid; + + COMMIT; + END IF; + + SELECT * FROM tmp_Msg_Error; + + DROP TEMPORARY TABLE IF EXISTS tmp_Permutation; + DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error; +END // +DELIMITER ;; + + +/* + +DELETE FROM Shop_Product_Permutation_Temp +WHERE id_permutation = 1 +; + +INSERT INTO Shop_Product_Permutation_Temp ( + id_permutation, + id_product, + description, + cost_local, + id_currency_cost, + profit_local_min, + latency_manufacture_days, + id_unit_measurement_quantity, + count_unit_measurement_per_quantity_step, + quantity_min, + quantity_max, + quantity_stock, + is_subscription, + id_unit_measurement_interval_recurrence, + count_interval_recurrence, + id_stripe_product, + does_expire_faster_once_unsealed, + id_unit_measurement_interval_expiration_unsealed, + count_interval_expiration_unsealed, + active, + guid +) +VALUES + ( + 1 -- id_permutation, + , 1 -- id_product, + , 'Good Reddy Teddy' -- description, + , 5.0 -- cost_local, + , 1 -- id_currency_cost, + , 3.0 -- profit_local_min, + , 14 -- latency_manufacture_days, + , 1 -- id_unit_measurement_quantity, + , 1.0 -- count_unit_measurement_quantity, + , 3.0 -- quantity_min, + , 99.0 -- quantity_max, + , 1.0 -- quantity_stock, + , False -- is_subscription, + , null -- id_unit_measurement_interval_recurrence, + , null -- count_interval_recurrence, + , null -- id_stripe_product, + , False -- does_expire_faster_once_unsealed, + , null -- id_unit_measurement_interval_expiration_unsealed, + , null -- count_interval_expiration_unsealed, + , True -- active, + , 'NIPS' -- guid + ) +; + +select 'Shop_Product_Permutation_Temp before call'; +SELECT * FROM Shop_Product_Permutation_Temp; + +SELECT 'Shop_Product_Permutation before call' AS result_name; +select * FROM Shop_Product_Permutation; + +CALL p_shop_save_product_permutation ( + 1, -- 'auth0|6582b95c895d09a70ba10fef', # a_id_user + 'Initial data', # a_comment + 'NIPS' # a_guid +); + +SELECT 'Shop_Product_Permutation_Temp after call' AS result_name; +select * FROM Shop_Product_Permutation_Temp; + +SELECT 'Shop_Product_Permutation after call' AS result_name; +select * FROM Shop_Product_Permutation; + + +DELETE FROM Shop_Product_Permutation_Temp +WHERE id_permutation = 1; + + +*/ + diff --git a/static/MySQL/7210_p_shop_get_many_product_variation.sql b/static/MySQL/7210_p_shop_get_many_product_variation.sql index 04af5d47..95db8753 100644 --- a/static/MySQL/7210_p_shop_get_many_product_variation.sql +++ b/static/MySQL/7210_p_shop_get_many_product_variation.sql @@ -1,23 +1,6 @@ - - -/* - -CALL p_shop_get_many_product_variation ( - '', # a_id_user - 1, # a_get_all_supplier - 0, # a_get_inactive_variation - 0, # a_get_first_variation_only - '', # a_ids_variation -); - -*/ - - --- Clear previous proc DROP PROCEDURE IF EXISTS p_shop_get_many_product_variation; - DELIMITER // CREATE PROCEDURE p_shop_get_many_product_variation ( IN a_id_user INT, @@ -236,32 +219,33 @@ BEGIN END IF; -- Returns - /* # Variation Types SELECT t_VT.id_type , VT.code , VT.name , VT.name_plural + , VT.display_order , VT.active FROM tmp_Variation_Type t_VT INNER JOIN Shop_Variation_Type VT ON t_VT.id_type = VT.id_type ; - */ # Variations SELECT t_V.id_variation + , t_V.id_type , V.code AS code_variation , V.name AS name_variation - , V.active AS active_variation , V.display_order - , t_V.id_type + , V.active AS active_variation + /* , VT.code AS code_variation_type , VT.name AS name_variation_type , VT.name_plural AS name_plural_variation_type , VT.active AS active_variation_type , VT.display_order + */ FROM tmp_Variation t_V INNER JOIN Shop_Variation V ON t_V.id_variation = V.id_variation INNER JOIN tmp_Variation_Type t_VT ON V.id_type = t_VT.id_type diff --git a/static/MySQL/7219_p_shop_get_many_stock_item.sql b/static/MySQL/7219_p_shop_get_many_stock_item.sql index 8a649694..35936cf1 100644 --- a/static/MySQL/7219_p_shop_get_many_stock_item.sql +++ b/static/MySQL/7219_p_shop_get_many_stock_item.sql @@ -166,17 +166,17 @@ BEGIN price_GBP_full FLOAT NOT NULL, price_GBP_min FLOAT NOT NULL, * - , latency_manufacture INT NOT NULL + , latency_manufacture_days INT NOT NULL , quantity_min FLOAT NOT NULL , quantity_max FLOAT NOT NULL , quantity_step FLOAT NOT NULL , quantity_stock FLOAT NOT NULL , is_subscription BIT NOT NULL - , id_recurrence_interval INT - , CONSTRAINT FK_tmp_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval) - , count_recurrence_interval INT + , id_unit_measurement_interval_recurrence INT + , CONSTRAINT FK_tmp_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval) + , count_interval_recurrence INT , id_stripe_product VARCHAR(100) , product_has_variations INT NOT NULL , can_view BIT diff --git a/static/MySQL/7221_p_get_many_shop_product_price_and_discount_and_delivery_option.sql b/static/MySQL/7221_p_get_many_shop_product_price_and_discount_and_delivery_option.sql index d732910f..b1135907 100644 --- a/static/MySQL/7221_p_get_many_shop_product_price_and_discount_and_delivery_option.sql +++ b/static/MySQL/7221_p_get_many_shop_product_price_and_discount_and_delivery_option.sql @@ -480,15 +480,15 @@ BEGIN CURRENCY.code AS code_currency_cost, CURRENCY.symbol AS symbol_currency_cost, PP.profit_local_min, - t_P.latency_manufacture, + t_P.latency_manufacture_days, t_P.quantity_min, t_P.quantity_max, t_P.quantity_step, t_P.quantity_stock, t_P.id_stripe_product, t_P.is_subscription, - UM.name_singular AS name_recurrence_interval, - UM.name_plural AS name_plural_recurrence_interval, + UM.name_singular AS name_interval_recurrence, + UM.name_plural AS name_plural_interval_recurrence, PP.count_interval_recurrence, t_P.display_order_category, t_P.display_order_product, @@ -499,8 +499,8 @@ BEGIN FROM tmp_Shop_Product t_P INNER JOIN Shop_Product P ON t_P.id_product = P.id_product INNER JOIN Shop_Product_Permutation PP ON t_P.id_permutation = PP.id_permutation - -- LEFT JOIN Shop_Recurrence_Interval RI ON t_P.id_interval_recurrence = RI.id_interval - LEFT JOIN Shop_Unit_Measurement UM ON PP.id_interval_recurrence = UM.id_unit_measurement + -- LEFT JOIN Shop_Interval_Recurrence RI ON t_P.id_unit_measurement_interval_recurrence = RI.id_interval + LEFT JOIN Shop_Unit_Measurement UM ON PP.id_unit_measurement_interval_recurrence = UM.id_unit_measurement INNER JOIN Shop_Currency CURRENCY ON PP.id_currency_cost = CURRENCY.id_currency ORDER BY t_P.rank_permutation ; @@ -764,36 +764,20 @@ DELIMITER ;; /* -CALL partsltd_prod.p_shop_get_many_product ( - 1, #'auth0|6582b95c895d09a70ba10fef', # a_id_user - 1, # a_get_all_category - 1, # a_get_inactive_category - 0, # a_get_first_category_only - '', # a_ids_category - 1, # a_get_all_product - 0, # a_get_inactive_product - 0, # a_get_first_product_only - '', # a_ids_product - 1, # a_get_all_product_permutation - 0, # a_get_inactive_permutation - 0, # a_get_first_permutation_only - '', # a_ids_permutation - 1, # a_get_all_image - 0, # a_get_inactive_image - 0, # a_get_first_image_only - '', # a_ids_image - 1, # a_get_all_delivery_region - 0, # a_get_inactive_delivery_region - 0, # a_get_first_delivery_region_only - '', # a_ids_delivery_region - 1, # a_get_all_currency - 0, # a_get_inactive_currency - 0, # a_get_first_currency_only - '', # a_ids_currency - 1, # a_get_all_discount - 0, # a_get_inactive_discount - '', # a_ids_discount - 1 # a_get_products_quantity_stock_below_minimum +CALL partsltd_prod.p_shop_get_many_product_price_and_discount_and_delivery_region ( + IN a_id_user INT, + IN a_get_all_product_permutation BIT, + IN a_get_inactive_permutation BIT, + IN a_ids_permutation VARCHAR(4000), + IN a_get_all_delivery_region BIT, + IN a_get_inactive_delivery_region BIT, + IN a_ids_delivery_region VARCHAR(4000), + IN a_get_all_currency BIT, + IN a_get_inactive_currency BIT, + IN a_ids_currency VARCHAR(4000), + IN a_get_all_discount BIT, + IN a_get_inactive_discount BIT, + IN a_ids_discount VARCHAR(4000) ); select * FROM Shop_User_Eval_Temp; diff --git a/static/MySQL/7223_p_shop_get_many_stripe_price_new.sql b/static/MySQL/7223_p_shop_get_many_stripe_price_new.sql index 4502cc41..bf44f939 100644 --- a/static/MySQL/7223_p_shop_get_many_stripe_price_new.sql +++ b/static/MySQL/7223_p_shop_get_many_stripe_price_new.sql @@ -195,13 +195,13 @@ BEGIN P.id_stripe_product, P.is_subscription, LOWER(RI.code) AS name_recurring_interval, - P.count_recurrence_interval + P.count_interval_recurrence FROM tmp_Shop_Product_Currency_Link t_PCL INNER JOIN Shop_Product P ON t_PCL.id_product = P.id_product AND P.active - INNER JOIN Shop_Recurrence_Interval RI - ON P.id_recurrence_interval = RI.id_interval + INNER JOIN Shop_Interval_Recurrence RI + ON P.id_unit_measurement_interval_recurrence = RI.id_interval AND RI.active INNER JOIN Shop_Currency C ON t_PCL.id_currency = C.id_currency diff --git a/static/MySQL/7404_p_shop_get_many_supplier_purchase_order.sql b/static/MySQL/7404_p_shop_get_many_supplier_purchase_order.sql index 64756059..f1bbf4cb 100644 --- a/static/MySQL/7404_p_shop_get_many_supplier_purchase_order.sql +++ b/static/MySQL/7404_p_shop_get_many_supplier_purchase_order.sql @@ -196,17 +196,17 @@ BEGIN price_GBP_full FLOAT NOT NULL, price_GBP_min FLOAT NOT NULL, */ - latency_manufacture INT NOT NULL, + latency_manufacture_days INT NOT NULL, quantity_min FLOAT NOT NULL, quantity_max FLOAT NOT NULL, quantity_step FLOAT NOT NULL, quantity_stock FLOAT NOT NULL, is_subscription BIT NOT NULL, - id_recurrence_interval INT, - CONSTRAINT FK_tmp_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), - count_recurrence_interval INT, + id_unit_measurement_interval_recurrence INT, + CONSTRAINT FK_tmp_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), + count_interval_recurrence INT, id_stripe_product VARCHAR(100), product_has_variations INT NOT NULL, can_view BIT, @@ -388,14 +388,14 @@ BEGIN price_GBP_VAT_excl, price_GBP_min, * - latency_manufacture, + latency_manufacture_days, quantity_min, quantity_max, quantity_step, quantity_stock, is_subscription, - id_recurrence_interval, - count_recurrence_interval, + id_unit_measurement_interval_recurrence, + count_interval_recurrence, id_stripe_product, product_has_variations */ @@ -420,14 +420,14 @@ BEGIN PP.price_GBP_VAT_excl, PP.price_GBP_min, * - PP.latency_manufacture, + PP.latency_manufacture_days, PP.quantity_min, PP.quantity_max, PP.quantity_step, PP.quantity_stock, PP.is_subscription, - PP.id_recurrence_interval, - PP.count_recurrence_interval, + PP.id_unit_measurement_interval_recurrence, + PP.count_interval_recurrence, PP.id_stripe_product, P.has_variations */ diff --git a/static/MySQL/7416_p_shop_get_many_manufacturing_purchase_order.sql b/static/MySQL/7416_p_shop_get_many_manufacturing_purchase_order.sql index 25432aa5..a78eb37a 100644 --- a/static/MySQL/7416_p_shop_get_many_manufacturing_purchase_order.sql +++ b/static/MySQL/7416_p_shop_get_many_manufacturing_purchase_order.sql @@ -168,17 +168,17 @@ BEGIN price_GBP_min FLOAT NOT NULL, */ /* - latency_manufacture INT NOT NULL, + latency_manufacture_days INT NOT NULL, quantity_min FLOAT NOT NULL, quantity_max FLOAT NOT NULL, quantity_step FLOAT NOT NULL, quantity_stock FLOAT NOT NULL, is_subscription BIT NOT NULL, - id_recurrence_interval INT, - CONSTRAINT FK_tmp_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), - count_recurrence_interval INT, + id_unit_measurement_interval_recurrence INT, + CONSTRAINT FK_tmp_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), + count_interval_recurrence INT, id_stripe_product VARCHAR(100), product_has_variations INT NOT NULL, */ @@ -308,14 +308,14 @@ BEGIN price_GBP_VAT_excl, price_GBP_min, * - latency_manufacture, + latency_manufacture_days, quantity_min, quantity_max, quantity_step, quantity_stock, is_subscription, - id_recurrence_interval, - count_recurrence_interval, + id_unit_measurement_interval_recurrence, + count_interval_recurrence, id_stripe_product, product_has_variations */ @@ -340,14 +340,14 @@ BEGIN PP.price_GBP_VAT_excl, PP.price_GBP_min, * - PP.latency_manufacture, + PP.latency_manufacture_days, PP.quantity_min, PP.quantity_max, PP.quantity_step, PP.quantity_stock, PP.is_subscription, - PP.id_recurrence_interval, - PP.count_recurrence_interval, + PP.id_unit_measurement_interval_recurrence, + PP.count_interval_recurrence, PP.id_stripe_product, P.has_variations */ diff --git a/static/MySQL/7425_p_shop_get_many_customer_sales_order.sql b/static/MySQL/7425_p_shop_get_many_customer_sales_order.sql index deb220fe..6097a4d7 100644 --- a/static/MySQL/7425_p_shop_get_many_customer_sales_order.sql +++ b/static/MySQL/7425_p_shop_get_many_customer_sales_order.sql @@ -203,17 +203,17 @@ BEGIN price_GBP_min FLOAT NOT NULL, */ /* - latency_manufacture INT NOT NULL, + latency_manufacture_days INT NOT NULL, quantity_min FLOAT NOT NULL, quantity_max FLOAT NOT NULL, quantity_step FLOAT NOT NULL, quantity_stock FLOAT NOT NULL, is_subscription BIT NOT NULL, - id_recurrence_interval INT, - CONSTRAINT FK_tmp_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), - count_recurrence_interval INT, + id_unit_measurement_interval_recurrence INT, + CONSTRAINT FK_tmp_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), + count_interval_recurrence INT, id_stripe_product VARCHAR(100), product_has_variations INT NOT NULL, */ @@ -398,14 +398,14 @@ BEGIN price_GBP_VAT_excl, price_GBP_min, * - latency_manufacture, + latency_manufacture_days, quantity_min, quantity_max, quantity_step, quantity_stock, is_subscription, - id_recurrence_interval, - count_recurrence_interval, + id_unit_measurement_interval_recurrence, + count_interval_recurrence, id_stripe_product, product_has_variations */ @@ -430,14 +430,14 @@ BEGIN PP.price_GBP_VAT_excl, PP.price_GBP_min, * - PP.latency_manufacture, + PP.latency_manufacture_days, PP.quantity_min, PP.quantity_max, PP.quantity_step, PP.quantity_stock, PP.is_subscription, - PP.id_recurrence_interval, - PP.count_recurrence_interval, + PP.id_unit_measurement_interval_recurrence, + PP.count_interval_recurrence, PP.id_stripe_product, P.has_variations */ diff --git a/static/MySQL/9000_populate.sql b/static/MySQL/9000_populate.sql index da7abdd9..0b035493 100644 --- a/static/MySQL/9000_populate.sql +++ b/static/MySQL/9000_populate.sql @@ -140,13 +140,13 @@ VALUES # Unit of Measurement INSERT INTO Shop_Unit_Measurement ( - name_singular, name_plural, symbol, is_base_unit + name_singular, name_plural, symbol, is_base_unit, is_unit_of_distance, is_unit_of_mass, is_unit_of_time, is_unit_of_volume ) VALUES - ('metre', 'metres', 'm', 1), - ('kilogram', 'kilograms', 'kg', 1), - ('item', 'items', 'x', 0), - ('hour', 'hours', 'h', 1) + ('metre', 'metres', 'm', 1, 1, 0, 0, 0), + ('kilogram', 'kilograms', 'kg', 1, 0, 1, 0, 0), + ('item', 'items', 'x', 0, 0, 0, 0, 0), + ('hour', 'hours', 'h', 1, 0, 0, 1, 0) ; /* @@ -177,7 +177,7 @@ VALUES /* # Recurrence Interval -INSERT INTO Shop_Recurrence_Interval ( +INSERT INTO Shop_Interval_Recurrence ( code, name, name_plural ) VALUES @@ -248,18 +248,19 @@ INSERT INTO Shop_Product_Permutation ( id_currency_cost, profit_local_min, # id_currency_profit_min, - latency_manufacture, - quantity_min, + latency_manufacture_days, + id_unit_measurement_quantity, + count_unit_measurement_per_quantity_step, + quantity_min, quantity_max, - quantity_step, quantity_stock, is_subscription, - id_interval_recurrence, + id_unit_measurement_interval_recurrence, count_interval_recurrence, -- id_access_level_required, id_stripe_product , does_expire_faster_once_unsealed - , id_interval_expiration_unsealed + , id_unit_measurement_interval_expiration_unsealed , count_interval_expiration_unsealed ) VALUES @@ -273,9 +274,10 @@ VALUES # 1, 14, 1, - 3, 1, + 3, 99, + 1, 0, NULL, NULL, @@ -295,9 +297,10 @@ VALUES # 1, 14, 1, - 3, 1, + 3, 99, + 1, 0, NULL, NULL, @@ -317,9 +320,10 @@ VALUES # 1, 14, 1, - 2, 1, + 2, 99, + 1, 0, NULL, NULL, @@ -339,9 +343,10 @@ VALUES # 1, 14, 1, - 2, 1, + 2, 99, + 1, 0, NULL, NULL, @@ -361,9 +366,10 @@ VALUES # 1, 14, 1, - 2, 1, + 2, 99, + 1, 0, NULL, NULL, @@ -383,9 +389,10 @@ VALUES # 1, 14, 1, - 2, 1, + 2, 99, + 1, 0, NULL, NULL, diff --git a/static/MySQL/9001_view.sql b/static/MySQL/9001_view.sql index 644de0f7..291e0c58 100644 --- a/static/MySQL/9001_view.sql +++ b/static/MySQL/9001_view.sql @@ -68,8 +68,8 @@ SELECT * FROM Shop_Unit_Measurement_Conversion_Audit; /* # Recurrence Interval -SELECT * FROM Shop_Recurrence_Interval; -SELECT * FROM Shop_Recurrence_Interval_Audit; +SELECT * FROM Shop_Interval_Recurrence; +SELECT * FROM Shop_Interval_Recurrence_Audit; */ diff --git a/static/MySQL/deprecated/000_init_tables_product.sql b/static/MySQL/deprecated/000_init_tables_product.sql index 12ab4c35..8df93a55 100644 --- a/static/MySQL/deprecated/000_init_tables_product.sql +++ b/static/MySQL/deprecated/000_init_tables_product.sql @@ -36,8 +36,8 @@ DROP TABLE IF EXISTS Shop_Variation_Type; DROP TABLE IF EXISTS Shop_Product_Audit; DROP TABLE IF EXISTS Shop_Product; -DROP TABLE IF EXISTS Shop_Recurrence_Interval_Audit; -DROP TABLE IF EXISTS Shop_Recurrence_Interval; +DROP TABLE IF EXISTS Shop_Interval_Recurrence_Audit; +DROP TABLE IF EXISTS Shop_Interval_Recurrence; DROP TABLE IF EXISTS Shop_Product_Category_Audit; DROP TABLE IF EXISTS Shop_Product_Category; @@ -342,7 +342,7 @@ SELECT * FROM Shop_Product_Category_Audit; # Recurrence Interval -CREATE TABLE Shop_Recurrence_Interval ( +CREATE TABLE Shop_Interval_Recurrence ( id_interval INT NOT NULL AUTO_INCREMENT PRIMARY KEY, code VARCHAR(50), name VARCHAR(255), @@ -350,14 +350,14 @@ CREATE TABLE Shop_Recurrence_Interval ( created_on TIMESTAMP, created_by INT, id_change_set INT, - CONSTRAINT FK_Shop_Recurrence_Interval_id_change_set + CONSTRAINT FK_Shop_Interval_Recurrence_id_change_set FOREIGN KEY (id_change_set) REFERENCES Shop_Product_Change_Set(id_change_set) ); DELIMITER // -CREATE TRIGGER before_insert_Shop_Recurrence_Interval -BEFORE INSERT ON Shop_Recurrence_Interval +CREATE TRIGGER before_insert_Shop_Interval_Recurrence +BEFORE INSERT ON Shop_Interval_Recurrence FOR EACH ROW BEGIN SET NEW.created_on := IFNULL(NEW.created_on, NOW()); @@ -365,28 +365,28 @@ BEGIN END // DELIMITER ;; -CREATE TABLE Shop_Recurrence_Interval_Audit ( +CREATE TABLE Shop_Interval_Recurrence_Audit ( id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY, id_interval INT NOT NULL, - CONSTRAINT FK_Shop_Recurrence_Interval_Audit_id_interval + CONSTRAINT FK_Shop_Interval_Recurrence_Audit_id_interval FOREIGN KEY (id_interval) - REFERENCES Shop_Recurrence_Interval(id_interval) + REFERENCES Shop_Interval_Recurrence(id_interval) ON UPDATE RESTRICT, name_field VARCHAR(50), value_prev VARCHAR(256), value_new VARCHAR(256), id_change_set INT NOT NULL, - CONSTRAINT FK_Shop_Recurrence_Interval_Audit_id_change_set + CONSTRAINT FK_Shop_Interval_Recurrence_Audit_id_change_set FOREIGN KEY (id_change_set) REFERENCES Shop_Product_Change_Set(id_change_set) ); DELIMITER // -CREATE TRIGGER before_update_Shop_Recurrence_Interval -BEFORE UPDATE ON Shop_Recurrence_Interval +CREATE TRIGGER before_update_Shop_Interval_Recurrence +BEFORE UPDATE ON Shop_Interval_Recurrence FOR EACH ROW BEGIN - INSERT INTO Shop_Recurrence_Interval_Audit ( + INSERT INTO Shop_Interval_Recurrence_Audit ( id_interval, name_field, value_prev, @@ -408,7 +408,7 @@ BEGIN END // DELIMITER ;; -INSERT INTO Shop_Recurrence_Interval ( +INSERT INTO Shop_Interval_Recurrence ( code, name, name_plural ) VALUES @@ -417,8 +417,8 @@ VALUES ('YEAR', 'Year', 'Years') ; -SELECT * FROM Shop_Recurrence_Interval; -SELECT * FROM Shop_Recurrence_Interval_Audit; +SELECT * FROM Shop_Interval_Recurrence; +SELECT * FROM Shop_Interval_Recurrence_Audit; @@ -439,11 +439,11 @@ CREATE TABLE Shop_Product ( quantity_step FLOAT NOT NULL DEFAULT 1, quantity_stock FLOAT NOT NULL DEFAULT 0, is_subscription BIT NOT NULL DEFAULT 0, - id_recurrence_interval INT, - CONSTRAINT FK_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), - count_recurrence_interval INT, + id_unit_measurement_interval_recurrence INT, + CONSTRAINT FK_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), + count_interval_recurrence INT, id_stripe_product VARCHAR(100), id_stripe_price VARCHAR(100), active BIT NOT NULL DEFAULT 1, @@ -534,13 +534,13 @@ BEGIN SELECT NEW.id_product, 'is_subscription', CONVERT(CONVERT(OLD.is_subscription, SIGNED), CHAR), CONVERT(CONVERT(NEW.is_subscription, SIGNED), CHAR), NEW.id_change_set WHERE NOT OLD.is_subscription <=> NEW.is_subscription UNION - # Changed id_recurrence_interval - SELECT NEW.id_product, 'id_recurrence_interval', CONVERT(OLD.id_recurrence_interval, CHAR), CONVERT(NEW.id_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.id_recurrence_interval <=> NEW.id_recurrence_interval + # Changed id_unit_measurement_interval_recurrence + SELECT NEW.id_product, 'id_unit_measurement_interval_recurrence', CONVERT(OLD.id_unit_measurement_interval_recurrence, CHAR), CONVERT(NEW.id_unit_measurement_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.id_unit_measurement_interval_recurrence <=> NEW.id_unit_measurement_interval_recurrence UNION - # Changed count_recurrence_interval - SELECT NEW.id_product, 'count_recurrence_interval', CONVERT(OLD.count_recurrence_interval, CHAR), CONVERT(NEW.count_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.count_recurrence_interval <=> NEW.count_recurrence_interval + # Changed count_interval_recurrence + SELECT NEW.id_product, 'count_interval_recurrence', CONVERT(OLD.count_interval_recurrence, CHAR), CONVERT(NEW.count_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.count_interval_recurrence <=> NEW.count_interval_recurrence UNION # Changed id_stripe_product SELECT NEW.id_product, 'id_stripe_product', OLD.id_stripe_product, NEW.id_stripe_product, NEW.id_change_set diff --git a/static/MySQL/deprecated/108_tbl_Shop_Recurrence_Interval.sql b/static/MySQL/deprecated/108_tbl_Shop_Recurrence_Interval.sql index e75895d3..0f0906b5 100644 --- a/static/MySQL/deprecated/108_tbl_Shop_Recurrence_Interval.sql +++ b/static/MySQL/deprecated/108_tbl_Shop_Recurrence_Interval.sql @@ -3,9 +3,9 @@ -SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Recurrence_Interval'; +SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Interval_Recurrence'; -CREATE TABLE IF NOT EXISTS Shop_Recurrence_Interval ( +CREATE TABLE IF NOT EXISTS Shop_Interval_Recurrence ( id_interval INT NOT NULL AUTO_INCREMENT PRIMARY KEY, code VARCHAR(50), name VARCHAR(255), @@ -14,7 +14,7 @@ CREATE TABLE IF NOT EXISTS Shop_Recurrence_Interval ( created_on TIMESTAMP, created_by INT, id_change_set INT, - CONSTRAINT FK_Shop_Recurrence_Interval_id_change_set + CONSTRAINT FK_Shop_Interval_Recurrence_id_change_set FOREIGN KEY (id_change_set) REFERENCES Shop_Product_Change_Set(id_change_set) ); diff --git a/static/MySQL/deprecated/109_tbl_Shop_Recurrence_Interval_Audit.sql b/static/MySQL/deprecated/109_tbl_Shop_Recurrence_Interval_Audit.sql index c38c8110..d84813f4 100644 --- a/static/MySQL/deprecated/109_tbl_Shop_Recurrence_Interval_Audit.sql +++ b/static/MySQL/deprecated/109_tbl_Shop_Recurrence_Interval_Audit.sql @@ -3,20 +3,20 @@ -SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Recurrence_Interval_Audit'; +SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Interval_Recurrence_Audit'; -CREATE TABLE IF NOT EXISTS Shop_Recurrence_Interval_Audit ( +CREATE TABLE IF NOT EXISTS Shop_Interval_Recurrence_Audit ( id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY, id_interval INT NOT NULL, - CONSTRAINT FK_Shop_Recurrence_Interval_Audit_id_interval + CONSTRAINT FK_Shop_Interval_Recurrence_Audit_id_interval FOREIGN KEY (id_interval) - REFERENCES Shop_Recurrence_Interval(id_interval) + REFERENCES Shop_Interval_Recurrence(id_interval) ON UPDATE RESTRICT, name_field VARCHAR(50), value_prev VARCHAR(256), value_new VARCHAR(256), id_change_set INT NOT NULL, - CONSTRAINT FK_Shop_Recurrence_Interval_Audit_id_change_set + CONSTRAINT FK_Shop_Interval_Recurrence_Audit_id_change_set FOREIGN KEY (id_change_set) REFERENCES Shop_Product_Change_Set(id_change_set) ); diff --git a/static/MySQL/deprecated/308_tri_Shop_Recurrence_Interval.sql b/static/MySQL/deprecated/308_tri_Shop_Recurrence_Interval.sql index d3088c7d..32f479ae 100644 --- a/static/MySQL/deprecated/308_tri_Shop_Recurrence_Interval.sql +++ b/static/MySQL/deprecated/308_tri_Shop_Recurrence_Interval.sql @@ -4,13 +4,13 @@ -DROP TRIGGER IF EXISTS before_insert_Shop_Recurrence_Interval; -DROP TRIGGER IF EXISTS before_update_Shop_Recurrence_Interval; +DROP TRIGGER IF EXISTS before_insert_Shop_Interval_Recurrence; +DROP TRIGGER IF EXISTS before_update_Shop_Interval_Recurrence; DELIMITER // -CREATE TRIGGER before_insert_Shop_Recurrence_Interval -BEFORE INSERT ON Shop_Recurrence_Interval +CREATE TRIGGER before_insert_Shop_Interval_Recurrence +BEFORE INSERT ON Shop_Interval_Recurrence FOR EACH ROW BEGIN SET NEW.created_on := IFNULL(NEW.created_on, NOW()); @@ -20,8 +20,8 @@ DELIMITER ;; DELIMITER // -CREATE TRIGGER before_update_Shop_Recurrence_Interval -BEFORE UPDATE ON Shop_Recurrence_Interval +CREATE TRIGGER before_update_Shop_Interval_Recurrence +BEFORE UPDATE ON Shop_Interval_Recurrence FOR EACH ROW BEGIN IF OLD.id_change_set <=> NEW.id_change_set THEN @@ -29,7 +29,7 @@ BEGIN SET MESSAGE_TEXT = 'New change Set ID must be provided.'; END IF; - INSERT INTO Shop_Recurrence_Interval_Audit ( + INSERT INTO Shop_Interval_Recurrence_Audit ( id_interval, name_field, value_prev, diff --git a/static/MySQL/deprecated/706_p_shop_get_product.sql b/static/MySQL/deprecated/706_p_shop_get_product.sql index 15fd3d94..7c034293 100644 --- a/static/MySQL/deprecated/706_p_shop_get_product.sql +++ b/static/MySQL/deprecated/706_p_shop_get_product.sql @@ -309,14 +309,14 @@ BEGIN P.quantity_stock, P.id_stripe_product, P.is_subscription, - RI.name AS name_recurrence_interval, - RI.name_plural AS name_plural_recurrence_interval, - P.count_recurrence_interval + RI.name AS name_interval_recurrence, + RI.name_plural AS name_plural_interval_recurrence, + P.count_interval_recurrence FROM tmp_Shop_Product t_P INNER JOIN Shop_Product P ON t_P.id_product = P.id_product - LEFT JOIN Shop_Recurrence_Interval RI - ON P.id_recurrence_interval = RI.id_interval + LEFT JOIN Shop_Interval_Recurrence RI + ON P.id_unit_measurement_interval_recurrence = RI.id_interval WHERE ISNULL(t_P.id_permutation) ORDER BY t_P.display_order ; @@ -336,17 +336,17 @@ BEGIN P.quantity_stock, P.id_stripe_product, P.is_subscription, - RI.name AS name_recurrence_interval, - RI.name_plural AS name_plural_recurrence_interval, - P.count_recurrence_interval + RI.name AS name_interval_recurrence, + RI.name_plural AS name_plural_interval_recurrence, + P.count_interval_recurrence FROM tmp_Shop_Product t_P INNER JOIN Shop_Product_Permutation PP ON t_P.id_permutation = PP.id_permutation AND PP.active INNER JOIN Shop_Product P ON PP.id_product = P.id_product - LEFT JOIN Shop_Recurrence_Interval RI - ON P.id_recurrence_interval = RI.id_interval + LEFT JOIN Shop_Interval_Recurrence RI + ON P.id_unit_measurement_interval_recurrence = RI.id_interval WHERE NOT ISNULL(t_P.id_permutation) ORDER BY t_P.display_order ; diff --git a/static/MySQL/deprecated/dump.sql b/static/MySQL/deprecated/dump.sql index 63450d0f..86b1b6de 100644 --- a/static/MySQL/deprecated/dump.sql +++ b/static/MySQL/deprecated/dump.sql @@ -1964,11 +1964,11 @@ DELIMITER ;;; SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Product must have subscription status or variations (with subscription statuses).'; END IF; - IF ISNULL(NEW.id_recurrence_interval) THEN + IF ISNULL(NEW.id_unit_measurement_interval_recurrence) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Product must have recurrence interval or variations (with recurrence intervals).'; END IF; - IF ISNULL(NEW.count_recurrence_interval) THEN + IF ISNULL(NEW.count_interval_recurrence) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Product must have recurrence interval count or variations (with recurrence interval counts).'; END IF; @@ -2038,13 +2038,13 @@ DELIMITER ;;; SELECT NEW.id_product, 'is_subscription', CONVERT(CONVERT(OLD.is_subscription, SIGNED), CHAR), CONVERT(CONVERT(NEW.is_subscription, SIGNED), CHAR), NEW.id_change_set WHERE NOT OLD.is_subscription <=> NEW.is_subscription UNION - # Changed id_recurrence_interval - SELECT NEW.id_product, 'id_recurrence_interval', CONVERT(OLD.id_recurrence_interval, CHAR), CONVERT(NEW.id_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.id_recurrence_interval <=> NEW.id_recurrence_interval + # Changed id_unit_measurement_interval_recurrence + SELECT NEW.id_product, 'id_unit_measurement_interval_recurrence', CONVERT(OLD.id_unit_measurement_interval_recurrence, CHAR), CONVERT(NEW.id_unit_measurement_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.id_unit_measurement_interval_recurrence <=> NEW.id_unit_measurement_interval_recurrence UNION - # Changed count_recurrence_interval - SELECT NEW.id_product, 'count_recurrence_interval', CONVERT(OLD.count_recurrence_interval, CHAR), CONVERT(NEW.count_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.count_recurrence_interval <=> NEW.count_recurrence_interval + # Changed count_interval_recurrence + SELECT NEW.id_product, 'count_interval_recurrence', CONVERT(OLD.count_interval_recurrence, CHAR), CONVERT(NEW.count_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.count_interval_recurrence <=> NEW.count_interval_recurrence UNION # Changed id_access_level_required SELECT NEW.id_product, 'id_access_level_required', CONVERT(OLD.id_access_level_required, CHAR), CONVERT(NEW.id_access_level_required, CHAR), NEW.id_change_set @@ -2674,14 +2674,14 @@ CREATE TABLE `shop_product_permutation` ( `id_currency_cost_manufacturing` int NOT NULL, `profit_local_min` float NOT NULL, `id_currency_profit_min` int NOT NULL, - `latency_manufacture` int NOT NULL, + `latency_manufacture_days` int NOT NULL, `quantity_min` float NOT NULL, `quantity_max` float NOT NULL, `quantity_step` float NOT NULL, `quantity_stock` float NOT NULL, `is_subscription` bit(1) NOT NULL, - `id_recurrence_interval` int DEFAULT NULL, - `count_recurrence_interval` int DEFAULT NULL, + `id_unit_measurement_interval_recurrence` int DEFAULT NULL, + `count_interval_recurrence` int DEFAULT NULL, `id_access_level_required` int NOT NULL, `id_stripe_product` varchar(100) DEFAULT NULL, `active` bit(1) NOT NULL DEFAULT b'1', @@ -2691,11 +2691,11 @@ CREATE TABLE `shop_product_permutation` ( `id_change_set` int DEFAULT NULL, PRIMARY KEY (`id_permutation`), KEY `FK_Shop_Product_Variation_Link_id_product` (`id_product`), - KEY `FK_Shop_Product_Permutation_id_recurrence_interval` (`id_recurrence_interval`), + KEY `FK_Shop_Product_Permutation_id_unit_measurement_interval_recurrence` (`id_unit_measurement_interval_recurrence`), KEY `FK_Shop_Product_Permutation_id_access_level_required` (`id_access_level_required`), KEY `FK_Shop_Product_Variation_Link_id_change_set` (`id_change_set`), CONSTRAINT `FK_Shop_Product_Permutation_id_access_level_required` FOREIGN KEY (`id_access_level_required`) REFERENCES `shop_access_level` (`id_access_level`), - CONSTRAINT `FK_Shop_Product_Permutation_id_recurrence_interval` FOREIGN KEY (`id_recurrence_interval`) REFERENCES `shop_recurrence_interval` (`id_interval`), + CONSTRAINT `FK_Shop_Product_Permutation_id_unit_measurement_interval_recurrence` FOREIGN KEY (`id_unit_measurement_interval_recurrence`) REFERENCES `shop_interval_recurrence` (`id_interval`), CONSTRAINT `FK_Shop_Product_Variation_Link_id_change_set` FOREIGN KEY (`id_change_set`) REFERENCES `shop_product_change_set` (`id_change_set`), CONSTRAINT `FK_Shop_Product_Variation_Link_id_product` FOREIGN KEY (`id_product`) REFERENCES `shop_product` (`id_product`) ON UPDATE RESTRICT ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; @@ -2794,9 +2794,9 @@ DELIMITER ;;; WHERE NOT (OLD.price_GBP_min <=> NEW.price_GBP_min) UNION */ - # Changed latency_manufacture - SELECT NEW.id_product, 'latency_manufacture', CONVERT(OLD.latency_manufacture, CHAR), CONVERT(NEW.latency_manufacture, CHAR), NEW.id_change_set - WHERE NOT OLD.latency_manufacture <=> NEW.latency_manufacture + # Changed latency_manufacture_days + SELECT NEW.id_product, 'latency_manufacture_days', CONVERT(OLD.latency_manufacture_days, CHAR), CONVERT(NEW.latency_manufacture_days, CHAR), NEW.id_change_set + WHERE NOT OLD.latency_manufacture_days <=> NEW.latency_manufacture_days UNION # Changed quantity_min SELECT NEW.id_product, 'quantity_min', CONVERT(OLD.quantity_min, CHAR), CONVERT(NEW.quantity_min, CHAR), NEW.id_change_set @@ -2818,13 +2818,13 @@ DELIMITER ;;; SELECT NEW.id_product, 'is_subscription', CONVERT(CONVERT(OLD.is_subscription, SIGNED), CHAR), CONVERT(CONVERT(NEW.is_subscription, SIGNED), CHAR), NEW.id_change_set WHERE NOT OLD.is_subscription <=> NEW.is_subscription UNION - # Changed id_recurrence_interval - SELECT NEW.id_product, 'id_recurrence_interval', CONVERT(OLD.id_recurrence_interval, CHAR), CONVERT(NEW.id_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.id_recurrence_interval <=> NEW.id_recurrence_interval + # Changed id_unit_measurement_interval_recurrence + SELECT NEW.id_product, 'id_unit_measurement_interval_recurrence', CONVERT(OLD.id_unit_measurement_interval_recurrence, CHAR), CONVERT(NEW.id_unit_measurement_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.id_unit_measurement_interval_recurrence <=> NEW.id_unit_measurement_interval_recurrence UNION - # Changed count_recurrence_interval - SELECT NEW.id_product, 'count_recurrence_interval', CONVERT(OLD.count_recurrence_interval, CHAR), CONVERT(NEW.count_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.count_recurrence_interval <=> NEW.count_recurrence_interval + # Changed count_interval_recurrence + SELECT NEW.id_product, 'count_interval_recurrence', CONVERT(OLD.count_interval_recurrence, CHAR), CONVERT(NEW.count_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.count_interval_recurrence <=> NEW.count_interval_recurrence UNION # Changed id_stripe_product SELECT NEW.id_permutation, 'id_stripe_product', OLD.id_stripe_product, NEW.id_stripe_product, NEW.id_change_set @@ -3012,13 +3012,13 @@ LOCK TABLES `shop_product_permutation_variation_link_audit` WRITE; UNLOCK TABLES; -- --- Table structure for table `shop_recurrence_interval` +-- Table structure for table `shop_interval_recurrence` -- -DROP TABLE IF EXISTS `shop_recurrence_interval`; +DROP TABLE IF EXISTS `shop_interval_recurrence`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `shop_recurrence_interval` ( +CREATE TABLE `shop_interval_recurrence` ( `id_interval` int NOT NULL AUTO_INCREMENT, `code` varchar(50) DEFAULT NULL, `name` varchar(255) DEFAULT NULL, @@ -3028,19 +3028,19 @@ CREATE TABLE `shop_recurrence_interval` ( `created_by` varchar(100) DEFAULT NULL, `id_change_set` int DEFAULT NULL, PRIMARY KEY (`id_interval`), - KEY `FK_Shop_Recurrence_Interval_id_change_set` (`id_change_set`), - CONSTRAINT `FK_Shop_Recurrence_Interval_id_change_set` FOREIGN KEY (`id_change_set`) REFERENCES `shop_product_change_set` (`id_change_set`) + KEY `FK_Shop_Interval_Recurrence_id_change_set` (`id_change_set`), + CONSTRAINT `FK_Shop_Interval_Recurrence_id_change_set` FOREIGN KEY (`id_change_set`) REFERENCES `shop_product_change_set` (`id_change_set`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- --- Dumping data for table `shop_recurrence_interval` +-- Dumping data for table `shop_interval_recurrence` -- -LOCK TABLES `shop_recurrence_interval` WRITE; -/*!40000 ALTER TABLE `shop_recurrence_interval` DISABLE KEYS */; -INSERT INTO `shop_recurrence_interval` VALUES (1,'WEEK','Week','Weeks',_binary '','2024-04-28 19:03:07','root@localhost',NULL),(2,'MONTH','Month','Months',_binary '','2024-04-28 19:03:07','root@localhost',NULL),(3,'YEAR','Year','Years',_binary '','2024-04-28 19:03:07','root@localhost',NULL); -/*!40000 ALTER TABLE `shop_recurrence_interval` ENABLE KEYS */; +LOCK TABLES `shop_interval_recurrence` WRITE; +/*!40000 ALTER TABLE `shop_interval_recurrence` DISABLE KEYS */; +INSERT INTO `shop_interval_recurrence` VALUES (1,'WEEK','Week','Weeks',_binary '','2024-04-28 19:03:07','root@localhost',NULL),(2,'MONTH','Month','Months',_binary '','2024-04-28 19:03:07','root@localhost',NULL),(3,'YEAR','Year','Years',_binary '','2024-04-28 19:03:07','root@localhost',NULL); +/*!40000 ALTER TABLE `shop_interval_recurrence` ENABLE KEYS */; UNLOCK TABLES; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -3051,7 +3051,7 @@ UNLOCK TABLES; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;;; -/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `before_insert_Shop_Recurrence_Interval` BEFORE INSERT ON `shop_recurrence_interval` FOR EACH ROW BEGIN +/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `before_insert_Shop_Interval_Recurrence` BEFORE INSERT ON `shop_interval_recurrence` FOR EACH ROW BEGIN SET NEW.created_on := IFNULL(NEW.created_on, NOW()); SET NEW.created_by := IFNULL(NEW.created_by, IFNULL((SELECT id_user FROM Shop_User WHERE firstname = CURRENT_USER()), -1)); END */;; @@ -3069,13 +3069,13 @@ DELIMITER ;; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;;; -/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `before_update_Shop_Recurrence_Interval` BEFORE UPDATE ON `shop_recurrence_interval` FOR EACH ROW BEGIN +/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `before_update_Shop_Interval_Recurrence` BEFORE UPDATE ON `shop_interval_recurrence` FOR EACH ROW BEGIN IF OLD.id_change_set <=> NEW.id_change_set THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'New change Set ID must be provided.'; END IF; - INSERT INTO Shop_Recurrence_Interval_Audit ( + INSERT INTO Shop_Interval_Recurrence_Audit ( id_interval, name_field, value_prev, @@ -3106,13 +3106,13 @@ DELIMITER ;; /*!50003 SET collation_connection = @saved_col_connection */ ; -- --- Table structure for table `shop_recurrence_interval_audit` +-- Table structure for table `shop_interval_recurrence_audit` -- -DROP TABLE IF EXISTS `shop_recurrence_interval_audit`; +DROP TABLE IF EXISTS `shop_interval_recurrence_audit`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `shop_recurrence_interval_audit` ( +CREATE TABLE `shop_interval_recurrence_audit` ( `id_audit` int NOT NULL AUTO_INCREMENT, `id_interval` int NOT NULL, `name_field` varchar(50) DEFAULT NULL, @@ -3120,20 +3120,20 @@ CREATE TABLE `shop_recurrence_interval_audit` ( `value_new` varchar(256) DEFAULT NULL, `id_change_set` int NOT NULL, PRIMARY KEY (`id_audit`), - KEY `FK_Shop_Recurrence_Interval_Audit_id_interval` (`id_interval`), - KEY `FK_Shop_Recurrence_Interval_Audit_id_change_set` (`id_change_set`), - CONSTRAINT `FK_Shop_Recurrence_Interval_Audit_id_change_set` FOREIGN KEY (`id_change_set`) REFERENCES `shop_product_change_set` (`id_change_set`), - CONSTRAINT `FK_Shop_Recurrence_Interval_Audit_id_interval` FOREIGN KEY (`id_interval`) REFERENCES `shop_recurrence_interval` (`id_interval`) ON UPDATE RESTRICT + KEY `FK_Shop_Interval_Recurrence_Audit_id_interval` (`id_interval`), + KEY `FK_Shop_Interval_Recurrence_Audit_id_change_set` (`id_change_set`), + CONSTRAINT `FK_Shop_Interval_Recurrence_Audit_id_change_set` FOREIGN KEY (`id_change_set`) REFERENCES `shop_product_change_set` (`id_change_set`), + CONSTRAINT `FK_Shop_Interval_Recurrence_Audit_id_interval` FOREIGN KEY (`id_interval`) REFERENCES `shop_interval_recurrence` (`id_interval`) ON UPDATE RESTRICT ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- --- Dumping data for table `shop_recurrence_interval_audit` +-- Dumping data for table `shop_interval_recurrence_audit` -- -LOCK TABLES `shop_recurrence_interval_audit` WRITE; -/*!40000 ALTER TABLE `shop_recurrence_interval_audit` DISABLE KEYS */; -/*!40000 ALTER TABLE `shop_recurrence_interval_audit` ENABLE KEYS */; +LOCK TABLES `shop_interval_recurrence_audit` WRITE; +/*!40000 ALTER TABLE `shop_interval_recurrence_audit` DISABLE KEYS */; +/*!40000 ALTER TABLE `shop_interval_recurrence_audit` ENABLE KEYS */; UNLOCK TABLES; -- @@ -6110,17 +6110,17 @@ BEGIN price_GBP_full FLOAT NOT NULL, price_GBP_min FLOAT NOT NULL, */ - latency_manufacture INT NOT NULL, + latency_manufacture_days INT NOT NULL, quantity_min FLOAT NOT NULL, quantity_max FLOAT NOT NULL, quantity_step FLOAT NOT NULL, quantity_stock FLOAT NOT NULL, is_subscription BIT NOT NULL, - id_recurrence_interval INT, - CONSTRAINT FK_tmp_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), - count_recurrence_interval INT, + id_unit_measurement_interval_recurrence INT, + CONSTRAINT FK_tmp_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), + count_interval_recurrence INT, id_stripe_product VARCHAR(100), product_has_variations INT NOT NULL, can_view BIT, @@ -6224,14 +6224,14 @@ BEGIN price_GBP_VAT_excl, price_GBP_min, */ - latency_manufacture, + latency_manufacture_days, quantity_min, quantity_max, quantity_step, quantity_stock, is_subscription, - id_recurrence_interval, - count_recurrence_interval, + id_unit_measurement_interval_recurrence, + count_interval_recurrence, id_stripe_product, product_has_variations ) @@ -6254,14 +6254,14 @@ BEGIN PP.price_GBP_VAT_excl, PP.price_GBP_min, */ - PP.latency_manufacture, + PP.latency_manufacture_days, PP.quantity_min, PP.quantity_max, PP.quantity_step, PP.quantity_stock, PP.is_subscription, - PP.id_recurrence_interval, - PP.count_recurrence_interval, + PP.id_unit_measurement_interval_recurrence, + PP.count_interval_recurrence, PP.id_stripe_product, P.has_variations FROM Shop_Product P @@ -6705,16 +6705,16 @@ BEGIN t_P.description, P.has_variations, P.id_category, - t_P.latency_manufacture, + t_P.latency_manufacture_days, t_P.quantity_min, t_P.quantity_max, t_P.quantity_step, t_P.quantity_stock, t_P.id_stripe_product, t_P.is_subscription, - RI.name AS name_recurrence_interval, - RI.name_plural AS name_plural_recurrence_interval, - t_P.count_recurrence_interval, + RI.name AS name_interval_recurrence, + RI.name_plural AS name_plural_interval_recurrence, + t_P.count_interval_recurrence, t_P.display_order_category, t_P.display_order_product, t_P.display_order_permutation, @@ -6724,8 +6724,8 @@ BEGIN FROM tmp_Shop_Product t_P INNER JOIN Shop_Product P ON t_P.id_product = P.id_product - LEFT JOIN Shop_Recurrence_Interval RI - ON t_P.id_recurrence_interval = RI.id_interval + LEFT JOIN Shop_Interval_Recurrence RI + ON t_P.id_unit_measurement_interval_recurrence = RI.id_interval ORDER BY t_P.rank_permutation ; @@ -7206,13 +7206,13 @@ BEGIN P.id_stripe_product, P.is_subscription, LOWER(RI.code) AS name_recurring_interval, - P.count_recurrence_interval + P.count_interval_recurrence FROM tmp_Shop_Product_Currency_Link t_PCL INNER JOIN Shop_Product P ON t_PCL.id_product = P.id_product AND P.active - INNER JOIN Shop_Recurrence_Interval RI - ON P.id_recurrence_interval = RI.id_interval + INNER JOIN Shop_Interval_Recurrence RI + ON P.id_unit_measurement_interval_recurrence = RI.id_interval AND RI.active INNER JOIN Shop_Currency C ON t_PCL.id_currency = C.id_currency diff --git a/static/MySQL/deprecated/dump2.sql b/static/MySQL/deprecated/dump2.sql index 450d859c..3fb5cd83 100644 --- a/static/MySQL/deprecated/dump2.sql +++ b/static/MySQL/deprecated/dump2.sql @@ -1964,11 +1964,11 @@ DELIMITER ;;; SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Product must have subscription status or variations (with subscription statuses).'; END IF; - IF ISNULL(NEW.id_recurrence_interval) THEN + IF ISNULL(NEW.id_unit_measurement_interval_recurrence) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Product must have recurrence interval or variations (with recurrence intervals).'; END IF; - IF ISNULL(NEW.count_recurrence_interval) THEN + IF ISNULL(NEW.count_interval_recurrence) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Product must have recurrence interval count or variations (with recurrence interval counts).'; END IF; @@ -2038,13 +2038,13 @@ DELIMITER ;;; SELECT NEW.id_product, 'is_subscription', CONVERT(CONVERT(OLD.is_subscription, SIGNED), CHAR), CONVERT(CONVERT(NEW.is_subscription, SIGNED), CHAR), NEW.id_change_set WHERE NOT OLD.is_subscription <=> NEW.is_subscription UNION - # Changed id_recurrence_interval - SELECT NEW.id_product, 'id_recurrence_interval', CONVERT(OLD.id_recurrence_interval, CHAR), CONVERT(NEW.id_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.id_recurrence_interval <=> NEW.id_recurrence_interval + # Changed id_unit_measurement_interval_recurrence + SELECT NEW.id_product, 'id_unit_measurement_interval_recurrence', CONVERT(OLD.id_unit_measurement_interval_recurrence, CHAR), CONVERT(NEW.id_unit_measurement_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.id_unit_measurement_interval_recurrence <=> NEW.id_unit_measurement_interval_recurrence UNION - # Changed count_recurrence_interval - SELECT NEW.id_product, 'count_recurrence_interval', CONVERT(OLD.count_recurrence_interval, CHAR), CONVERT(NEW.count_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.count_recurrence_interval <=> NEW.count_recurrence_interval + # Changed count_interval_recurrence + SELECT NEW.id_product, 'count_interval_recurrence', CONVERT(OLD.count_interval_recurrence, CHAR), CONVERT(NEW.count_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.count_interval_recurrence <=> NEW.count_interval_recurrence UNION # Changed id_access_level_required SELECT NEW.id_product, 'id_access_level_required', CONVERT(OLD.id_access_level_required, CHAR), CONVERT(NEW.id_access_level_required, CHAR), NEW.id_change_set @@ -2674,14 +2674,14 @@ CREATE TABLE `shop_product_permutation` ( `id_currency_cost_manufacturing` int NOT NULL, `profit_local_min` float NOT NULL, `id_currency_profit_min` int NOT NULL, - `latency_manufacture` int NOT NULL, + `latency_manufacture_days` int NOT NULL, `quantity_min` float NOT NULL, `quantity_max` float NOT NULL, `quantity_step` float NOT NULL, `quantity_stock` float NOT NULL, `is_subscription` bit(1) NOT NULL, - `id_recurrence_interval` int DEFAULT NULL, - `count_recurrence_interval` int DEFAULT NULL, + `id_unit_measurement_interval_recurrence` int DEFAULT NULL, + `count_interval_recurrence` int DEFAULT NULL, `id_access_level_required` int NOT NULL, `id_stripe_product` varchar(100) DEFAULT NULL, `active` bit(1) NOT NULL DEFAULT b'1', @@ -2691,11 +2691,11 @@ CREATE TABLE `shop_product_permutation` ( `id_change_set` int DEFAULT NULL, PRIMARY KEY (`id_permutation`), KEY `FK_Shop_Product_Variation_Link_id_product` (`id_product`), - KEY `FK_Shop_Product_Permutation_id_recurrence_interval` (`id_recurrence_interval`), + KEY `FK_Shop_Product_Permutation_id_unit_measurement_interval_recurrence` (`id_unit_measurement_interval_recurrence`), KEY `FK_Shop_Product_Permutation_id_access_level_required` (`id_access_level_required`), KEY `FK_Shop_Product_Variation_Link_id_change_set` (`id_change_set`), CONSTRAINT `FK_Shop_Product_Permutation_id_access_level_required` FOREIGN KEY (`id_access_level_required`) REFERENCES `shop_access_level` (`id_access_level`), - CONSTRAINT `FK_Shop_Product_Permutation_id_recurrence_interval` FOREIGN KEY (`id_recurrence_interval`) REFERENCES `shop_recurrence_interval` (`id_interval`), + CONSTRAINT `FK_Shop_Product_Permutation_id_unit_measurement_interval_recurrence` FOREIGN KEY (`id_unit_measurement_interval_recurrence`) REFERENCES `shop_interval_recurrence` (`id_interval`), CONSTRAINT `FK_Shop_Product_Variation_Link_id_change_set` FOREIGN KEY (`id_change_set`) REFERENCES `shop_product_change_set` (`id_change_set`), CONSTRAINT `FK_Shop_Product_Variation_Link_id_product` FOREIGN KEY (`id_product`) REFERENCES `shop_product` (`id_product`) ON UPDATE RESTRICT ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; @@ -2794,9 +2794,9 @@ DELIMITER ;;; WHERE NOT (OLD.price_GBP_min <=> NEW.price_GBP_min) UNION */ - # Changed latency_manufacture - SELECT NEW.id_product, 'latency_manufacture', CONVERT(OLD.latency_manufacture, CHAR), CONVERT(NEW.latency_manufacture, CHAR), NEW.id_change_set - WHERE NOT OLD.latency_manufacture <=> NEW.latency_manufacture + # Changed latency_manufacture_days + SELECT NEW.id_product, 'latency_manufacture_days', CONVERT(OLD.latency_manufacture_days, CHAR), CONVERT(NEW.latency_manufacture_days, CHAR), NEW.id_change_set + WHERE NOT OLD.latency_manufacture_days <=> NEW.latency_manufacture_days UNION # Changed quantity_min SELECT NEW.id_product, 'quantity_min', CONVERT(OLD.quantity_min, CHAR), CONVERT(NEW.quantity_min, CHAR), NEW.id_change_set @@ -2818,13 +2818,13 @@ DELIMITER ;;; SELECT NEW.id_product, 'is_subscription', CONVERT(CONVERT(OLD.is_subscription, SIGNED), CHAR), CONVERT(CONVERT(NEW.is_subscription, SIGNED), CHAR), NEW.id_change_set WHERE NOT OLD.is_subscription <=> NEW.is_subscription UNION - # Changed id_recurrence_interval - SELECT NEW.id_product, 'id_recurrence_interval', CONVERT(OLD.id_recurrence_interval, CHAR), CONVERT(NEW.id_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.id_recurrence_interval <=> NEW.id_recurrence_interval + # Changed id_unit_measurement_interval_recurrence + SELECT NEW.id_product, 'id_unit_measurement_interval_recurrence', CONVERT(OLD.id_unit_measurement_interval_recurrence, CHAR), CONVERT(NEW.id_unit_measurement_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.id_unit_measurement_interval_recurrence <=> NEW.id_unit_measurement_interval_recurrence UNION - # Changed count_recurrence_interval - SELECT NEW.id_product, 'count_recurrence_interval', CONVERT(OLD.count_recurrence_interval, CHAR), CONVERT(NEW.count_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.count_recurrence_interval <=> NEW.count_recurrence_interval + # Changed count_interval_recurrence + SELECT NEW.id_product, 'count_interval_recurrence', CONVERT(OLD.count_interval_recurrence, CHAR), CONVERT(NEW.count_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.count_interval_recurrence <=> NEW.count_interval_recurrence UNION # Changed id_stripe_product SELECT NEW.id_permutation, 'id_stripe_product', OLD.id_stripe_product, NEW.id_stripe_product, NEW.id_change_set @@ -3012,13 +3012,13 @@ LOCK TABLES `shop_product_permutation_variation_link_audit` WRITE; UNLOCK TABLES; -- --- Table structure for table `shop_recurrence_interval` +-- Table structure for table `shop_interval_recurrence` -- -DROP TABLE IF EXISTS `shop_recurrence_interval`; +DROP TABLE IF EXISTS `shop_interval_recurrence`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `shop_recurrence_interval` ( +CREATE TABLE `shop_interval_recurrence` ( `id_interval` int NOT NULL AUTO_INCREMENT, `code` varchar(50) DEFAULT NULL, `name` varchar(255) DEFAULT NULL, @@ -3028,19 +3028,19 @@ CREATE TABLE `shop_recurrence_interval` ( `created_by` varchar(100) DEFAULT NULL, `id_change_set` int DEFAULT NULL, PRIMARY KEY (`id_interval`), - KEY `FK_Shop_Recurrence_Interval_id_change_set` (`id_change_set`), - CONSTRAINT `FK_Shop_Recurrence_Interval_id_change_set` FOREIGN KEY (`id_change_set`) REFERENCES `shop_product_change_set` (`id_change_set`) + KEY `FK_Shop_Interval_Recurrence_id_change_set` (`id_change_set`), + CONSTRAINT `FK_Shop_Interval_Recurrence_id_change_set` FOREIGN KEY (`id_change_set`) REFERENCES `shop_product_change_set` (`id_change_set`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- --- Dumping data for table `shop_recurrence_interval` +-- Dumping data for table `shop_interval_recurrence` -- -LOCK TABLES `shop_recurrence_interval` WRITE; -/*!40000 ALTER TABLE `shop_recurrence_interval` DISABLE KEYS */; -INSERT INTO `shop_recurrence_interval` VALUES (1,'WEEK','Week','Weeks',_binary '','2024-04-28 19:03:07','root@localhost',NULL),(2,'MONTH','Month','Months',_binary '','2024-04-28 19:03:07','root@localhost',NULL),(3,'YEAR','Year','Years',_binary '','2024-04-28 19:03:07','root@localhost',NULL); -/*!40000 ALTER TABLE `shop_recurrence_interval` ENABLE KEYS */; +LOCK TABLES `shop_interval_recurrence` WRITE; +/*!40000 ALTER TABLE `shop_interval_recurrence` DISABLE KEYS */; +INSERT INTO `shop_interval_recurrence` VALUES (1,'WEEK','Week','Weeks',_binary '','2024-04-28 19:03:07','root@localhost',NULL),(2,'MONTH','Month','Months',_binary '','2024-04-28 19:03:07','root@localhost',NULL),(3,'YEAR','Year','Years',_binary '','2024-04-28 19:03:07','root@localhost',NULL); +/*!40000 ALTER TABLE `shop_interval_recurrence` ENABLE KEYS */; UNLOCK TABLES; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -3051,7 +3051,7 @@ UNLOCK TABLES; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;;; -/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `before_insert_Shop_Recurrence_Interval` BEFORE INSERT ON `shop_recurrence_interval` FOR EACH ROW BEGIN +/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `before_insert_Shop_Interval_Recurrence` BEFORE INSERT ON `shop_interval_recurrence` FOR EACH ROW BEGIN SET NEW.created_on := IFNULL(NEW.created_on, NOW()); SET NEW.created_by := IFNULL(NEW.created_by, IFNULL((SELECT id_user FROM Shop_User WHERE firstname = CURRENT_USER()), -1)); END */;; @@ -3069,13 +3069,13 @@ DELIMITER ;; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;;; -/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `before_update_Shop_Recurrence_Interval` BEFORE UPDATE ON `shop_recurrence_interval` FOR EACH ROW BEGIN +/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `before_update_Shop_Interval_Recurrence` BEFORE UPDATE ON `shop_interval_recurrence` FOR EACH ROW BEGIN IF OLD.id_change_set <=> NEW.id_change_set THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'New change Set ID must be provided.'; END IF; - INSERT INTO Shop_Recurrence_Interval_Audit ( + INSERT INTO Shop_Interval_Recurrence_Audit ( id_interval, name_field, value_prev, @@ -3106,13 +3106,13 @@ DELIMITER ;; /*!50003 SET collation_connection = @saved_col_connection */ ; -- --- Table structure for table `shop_recurrence_interval_audit` +-- Table structure for table `shop_interval_recurrence_audit` -- -DROP TABLE IF EXISTS `shop_recurrence_interval_audit`; +DROP TABLE IF EXISTS `shop_interval_recurrence_audit`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!50503 SET character_set_client = utf8mb4 */; -CREATE TABLE `shop_recurrence_interval_audit` ( +CREATE TABLE `shop_interval_recurrence_audit` ( `id_audit` int NOT NULL AUTO_INCREMENT, `id_interval` int NOT NULL, `name_field` varchar(50) DEFAULT NULL, @@ -3120,20 +3120,20 @@ CREATE TABLE `shop_recurrence_interval_audit` ( `value_new` varchar(256) DEFAULT NULL, `id_change_set` int NOT NULL, PRIMARY KEY (`id_audit`), - KEY `FK_Shop_Recurrence_Interval_Audit_id_interval` (`id_interval`), - KEY `FK_Shop_Recurrence_Interval_Audit_id_change_set` (`id_change_set`), - CONSTRAINT `FK_Shop_Recurrence_Interval_Audit_id_change_set` FOREIGN KEY (`id_change_set`) REFERENCES `shop_product_change_set` (`id_change_set`), - CONSTRAINT `FK_Shop_Recurrence_Interval_Audit_id_interval` FOREIGN KEY (`id_interval`) REFERENCES `shop_recurrence_interval` (`id_interval`) ON UPDATE RESTRICT + KEY `FK_Shop_Interval_Recurrence_Audit_id_interval` (`id_interval`), + KEY `FK_Shop_Interval_Recurrence_Audit_id_change_set` (`id_change_set`), + CONSTRAINT `FK_Shop_Interval_Recurrence_Audit_id_change_set` FOREIGN KEY (`id_change_set`) REFERENCES `shop_product_change_set` (`id_change_set`), + CONSTRAINT `FK_Shop_Interval_Recurrence_Audit_id_interval` FOREIGN KEY (`id_interval`) REFERENCES `shop_interval_recurrence` (`id_interval`) ON UPDATE RESTRICT ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- --- Dumping data for table `shop_recurrence_interval_audit` +-- Dumping data for table `shop_interval_recurrence_audit` -- -LOCK TABLES `shop_recurrence_interval_audit` WRITE; -/*!40000 ALTER TABLE `shop_recurrence_interval_audit` DISABLE KEYS */; -/*!40000 ALTER TABLE `shop_recurrence_interval_audit` ENABLE KEYS */; +LOCK TABLES `shop_interval_recurrence_audit` WRITE; +/*!40000 ALTER TABLE `shop_interval_recurrence_audit` DISABLE KEYS */; +/*!40000 ALTER TABLE `shop_interval_recurrence_audit` ENABLE KEYS */; UNLOCK TABLES; -- @@ -6110,17 +6110,17 @@ BEGIN price_GBP_full FLOAT NOT NULL, price_GBP_min FLOAT NOT NULL, */ - latency_manufacture INT NOT NULL, + latency_manufacture_days INT NOT NULL, quantity_min FLOAT NOT NULL, quantity_max FLOAT NOT NULL, quantity_step FLOAT NOT NULL, quantity_stock FLOAT NOT NULL, is_subscription BIT NOT NULL, - id_recurrence_interval INT, - CONSTRAINT FK_tmp_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), - count_recurrence_interval INT, + id_unit_measurement_interval_recurrence INT, + CONSTRAINT FK_tmp_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), + count_interval_recurrence INT, id_stripe_product VARCHAR(100), product_has_variations INT NOT NULL, can_view BIT, @@ -6224,14 +6224,14 @@ BEGIN price_GBP_VAT_excl, price_GBP_min, */ - latency_manufacture, + latency_manufacture_days, quantity_min, quantity_max, quantity_step, quantity_stock, is_subscription, - id_recurrence_interval, - count_recurrence_interval, + id_unit_measurement_interval_recurrence, + count_interval_recurrence, id_stripe_product, product_has_variations ) @@ -6254,14 +6254,14 @@ BEGIN PP.price_GBP_VAT_excl, PP.price_GBP_min, */ - PP.latency_manufacture, + PP.latency_manufacture_days, PP.quantity_min, PP.quantity_max, PP.quantity_step, PP.quantity_stock, PP.is_subscription, - PP.id_recurrence_interval, - PP.count_recurrence_interval, + PP.id_unit_measurement_interval_recurrence, + PP.count_interval_recurrence, PP.id_stripe_product, P.has_variations FROM Shop_Product P @@ -6705,16 +6705,16 @@ BEGIN t_P.description, P.has_variations, P.id_category, - t_P.latency_manufacture, + t_P.latency_manufacture_days, t_P.quantity_min, t_P.quantity_max, t_P.quantity_step, t_P.quantity_stock, t_P.id_stripe_product, t_P.is_subscription, - RI.name AS name_recurrence_interval, - RI.name_plural AS name_plural_recurrence_interval, - t_P.count_recurrence_interval, + RI.name AS name_interval_recurrence, + RI.name_plural AS name_plural_interval_recurrence, + t_P.count_interval_recurrence, t_P.display_order_category, t_P.display_order_product, t_P.display_order_permutation, @@ -6724,8 +6724,8 @@ BEGIN FROM tmp_Shop_Product t_P INNER JOIN Shop_Product P ON t_P.id_product = P.id_product - LEFT JOIN Shop_Recurrence_Interval RI - ON t_P.id_recurrence_interval = RI.id_interval + LEFT JOIN Shop_Interval_Recurrence RI + ON t_P.id_unit_measurement_interval_recurrence = RI.id_interval ORDER BY t_P.rank_permutation ; @@ -7206,13 +7206,13 @@ BEGIN P.id_stripe_product, P.is_subscription, LOWER(RI.code) AS name_recurring_interval, - P.count_recurrence_interval + P.count_interval_recurrence FROM tmp_Shop_Product_Currency_Link t_PCL INNER JOIN Shop_Product P ON t_PCL.id_product = P.id_product AND P.active - INNER JOIN Shop_Recurrence_Interval RI - ON P.id_recurrence_interval = RI.id_interval + INNER JOIN Shop_Interval_Recurrence RI + ON P.id_unit_measurement_interval_recurrence = RI.id_interval AND RI.active INNER JOIN Shop_Currency C ON t_PCL.id_currency = C.id_currency diff --git a/static/MySQL/temp.txt b/static/MySQL/temp.txt index cc5d1c8a..0e9a6c2c 100644 --- a/static/MySQL/temp.txt +++ b/static/MySQL/temp.txt @@ -153,16 +153,19 @@ 3427_tri_Shop_Customer_Sales_Order_Product_Link.sql 6000_p_split.sql 6001_p_clear_split_temp.sql +6206_fn_shop_get_product_permutation_name.sql 6500_p_shop_user_eval.sql 6501_p_clear_shop_user_eval_temp.sql +7003_p_shop_get_many_access_level.sql 7101_p_shop_get_many_region.sql 7116_p_shop_get_many_currency.sql +7122_p_shop_get_many_unit_measurement.sql 7200_p_shop_save_product_category.sql 7200_p_shop_save_product_category_test.sql 7203_p_shop_save_product.sql 7204_p_shop_get_many_product.sql 7205_p_shop_get_many_stripe_product_new.sql -7206_p_shop_save_permutation.sql +7206_p_shop_save_product_permutation.sql 7210_p_shop_get_many_product_variation.sql 7219_p_shop_get_many_stock_item.sql 7221_p_get_many_shop_product_price_and_discount_and_delivery_option.sql diff --git a/static/PostgreSQL/000_combine.sql b/static/PostgreSQL/000_combine.sql index 43cd95ef..98cb65d4 100644 --- a/static/PostgreSQL/000_combine.sql +++ b/static/PostgreSQL/000_combine.sql @@ -157,8 +157,8 @@ DROP TABLE IF EXISTS Shop_Delivery_Region; DROP TABLE IF EXISTS Shop_Region_Audit; DROP TABLE IF EXISTS Shop_Region; -DROP TABLE IF EXISTS Shop_Recurrence_Interval_Audit; -DROP TABLE IF EXISTS Shop_Recurrence_Interval; +DROP TABLE IF EXISTS Shop_Interval_Recurrence_Audit; +DROP TABLE IF EXISTS Shop_Interval_Recurrence; DROP TABLE IF EXISTS Shop_Product_Category_Audit; DROP TABLE IF EXISTS Shop_Product_Category; @@ -503,9 +503,9 @@ CREATE TABLE IF NOT EXISTS Shop_Product_Category_Audit ( -SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Recurrence_Interval'; +SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Interval_Recurrence'; -CREATE TABLE IF NOT EXISTS Shop_Recurrence_Interval ( +CREATE TABLE IF NOT EXISTS Shop_Interval_Recurrence ( id_interval INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY, code VARCHAR(50), name VARCHAR(255), @@ -514,7 +514,7 @@ CREATE TABLE IF NOT EXISTS Shop_Recurrence_Interval ( created_on TIMESTAMP, created_by INT, id_change_set INTEGER, - CONSTRAINT FK_Shop_Recurrence_Interval_id_change_set + CONSTRAINT FK_Shop_Interval_Recurrence_id_change_set FOREIGN KEY (id_change_set) REFERENCES Shop_Product_Change_Set(id_change_set) ); @@ -523,20 +523,20 @@ CREATE TABLE IF NOT EXISTS Shop_Recurrence_Interval ( -SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Recurrence_Interval_Audit'; +SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Interval_Recurrence_Audit'; -CREATE TABLE IF NOT EXISTS Shop_Recurrence_Interval_Audit ( +CREATE TABLE IF NOT EXISTS Shop_Interval_Recurrence_Audit ( id_audit INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY, id_interval INTEGER NOT NULL, - CONSTRAINT FK_Shop_Recurrence_Interval_Audit_id_interval + CONSTRAINT FK_Shop_Interval_Recurrence_Audit_id_interval FOREIGN KEY (id_interval) - REFERENCES Shop_Recurrence_Interval(id_interval) + REFERENCES Shop_Interval_Recurrence(id_interval) ON UPDATE RESTRICT, name_field VARCHAR(50), value_prev VARCHAR(256), value_new VARCHAR(256), id_change_set INTEGER NOT NULL, - CONSTRAINT FK_Shop_Recurrence_Interval_Audit_id_change_set + CONSTRAINT FK_Shop_Interval_Recurrence_Audit_id_change_set FOREIGN KEY (id_change_set) REFERENCES Shop_Product_Change_Set(id_change_set) ); @@ -760,11 +760,11 @@ CREATE TABLE IF NOT EXISTS Shop_Product ( quantity_step REAL, quantity_stock REAL, is_subscription BOOLEAN, - id_recurrence_interval INTEGER, - CONSTRAINT FK_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), - count_recurrence_interval INTEGER, + id_unit_measurement_interval_recurrence INTEGER, + CONSTRAINT FK_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), + count_interval_recurrence INTEGER, */ id_access_level_required INTEGER NOT NULL, CONSTRAINT FK_Shop_Product_id_access_level_required @@ -911,17 +911,17 @@ CREATE TABLE IF NOT EXISTS Shop_Product_Permutation ( id_currency_cost INTEGER NOT NULL, profit_local_min REAL NOT NULL, -- id_currency_profit_min INTEGER NOT NULL, - latency_manufacture INTEGER NOT NULL, + latency_manufacture_days INTEGER NOT NULL, quantity_min REAL NOT NULL, quantity_max REAL NOT NULL, quantity_step REAL NOT NULL, quantity_stock REAL NOT NULL, is_subscription BOOLEAN NOT NULL, - id_recurrence_interval INTEGER, - CONSTRAINT FK_Shop_Product_Permutation_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), - count_recurrence_interval INTEGER, + id_unit_measurement_interval_recurrence INTEGER, + CONSTRAINT FK_Shop_Product_Permutation_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), + count_interval_recurrence INTEGER, /* id_access_level_required INTEGER NOT NULL, CONSTRAINT FK_Shop_Product_Permutation_id_access_level_required @@ -2814,7 +2814,7 @@ EXECUTE FUNCTION before_update_Shop_Product_Category(); -- Shop Recurrence Interval -CREATE OR REPLACE FUNCTION before_insert_Shop_Recurrence_Interval() +CREATE OR REPLACE FUNCTION before_insert_Shop_Interval_Recurrence() RETURNS TRIGGER AS $$ BEGIN NEW.created_on = CURRENT_TIMESTAMP; @@ -2824,13 +2824,13 @@ BEGIN END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE TRIGGER tri_before_insert_Shop_Recurrence_Interval -BEFORE INSERT ON Shop_Recurrence_Interval +CREATE OR REPLACE TRIGGER tri_before_insert_Shop_Interval_Recurrence +BEFORE INSERT ON Shop_Interval_Recurrence FOR EACH ROW -EXECUTE FUNCTION before_insert_Shop_Recurrence_Interval(); +EXECUTE FUNCTION before_insert_Shop_Interval_Recurrence(); -CREATE OR REPLACE FUNCTION before_update_Shop_Recurrence_Interval() +CREATE OR REPLACE FUNCTION before_update_Shop_Interval_Recurrence() RETURNS TRIGGER AS $$ BEGIN IF OLD.id_change_set IS NOT DISTINCT FROM NEW.id_change_set THEN @@ -2838,7 +2838,7 @@ BEGIN USING ERRCODE = '45000'; END IF; - INSERT INTO Shop_Recurrence_Interval_Audit ( + INSERT INTO Shop_Interval_Recurrence_Audit ( id_interval, name_field, value_prev, @@ -2866,10 +2866,10 @@ BEGIN END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE TRIGGER tri_before_update_Shop_Recurrence_Interval -BEFORE UPDATE ON Shop_Recurrence_Interval +CREATE OR REPLACE TRIGGER tri_before_update_Shop_Interval_Recurrence +BEFORE UPDATE ON Shop_Interval_Recurrence FOR EACH ROW -EXECUTE FUNCTION before_update_Shop_Recurrence_Interval(); +EXECUTE FUNCTION before_update_Shop_Interval_Recurrence(); -- Shop Delivery Region @@ -3197,11 +3197,11 @@ BEGIN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Product must have subscription status or variations (with subscription statuses).'; END IF; - IF ISNULL(NEW.id_recurrence_interval) THEN + IF ISNULL(NEW.id_unit_measurement_interval_recurrence) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Product must have recurrence interval or variations (with recurrence intervals).'; END IF; - IF ISNULL(NEW.count_recurrence_interval) THEN + IF ISNULL(NEW.count_interval_recurrence) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Product must have recurrence interval count or variations (with recurrence interval counts).'; END IF; @@ -3271,13 +3271,13 @@ BEGIN SELECT NEW.id_product, 'is_subscription', CONVERT(CONVERT(OLD.is_subscription, SIGNED), CHAR), CONVERT(CONVERT(NEW.is_subscription, SIGNED), CHAR), NEW.id_change_set WHERE NOT OLD.is_subscription <=> NEW.is_subscription UNION - -- Changed id_recurrence_interval - SELECT NEW.id_product, 'id_recurrence_interval', CONVERT(OLD.id_recurrence_interval, CHAR), CONVERT(NEW.id_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.id_recurrence_interval <=> NEW.id_recurrence_interval + -- Changed id_unit_measurement_interval_recurrence + SELECT NEW.id_product, 'id_unit_measurement_interval_recurrence', CONVERT(OLD.id_unit_measurement_interval_recurrence, CHAR), CONVERT(NEW.id_unit_measurement_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.id_unit_measurement_interval_recurrence <=> NEW.id_unit_measurement_interval_recurrence UNION - -- Changed count_recurrence_interval - SELECT NEW.id_product, 'count_recurrence_interval', CONVERT(OLD.count_recurrence_interval, CHAR), CONVERT(NEW.count_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.count_recurrence_interval <=> NEW.count_recurrence_interval + -- Changed count_interval_recurrence + SELECT NEW.id_product, 'count_interval_recurrence', CONVERT(OLD.count_interval_recurrence, CHAR), CONVERT(NEW.count_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.count_interval_recurrence <=> NEW.count_interval_recurrence UNION -- Changed id_stripe_product SELECT NEW.id_product, 'id_stripe_product', OLD.id_stripe_product, NEW.id_stripe_product, NEW.id_change_set @@ -3512,9 +3512,9 @@ BEGIN WHERE NOT (OLD.price_GBP_min <=> NEW.price_GBP_min) UNION */ - -- Changed latency_manufacture - SELECT NEW.id_product, 'latency_manufacture', CONVERT(OLD.latency_manufacture, CHAR), CONVERT(NEW.latency_manufacture, CHAR), NEW.id_change_set - WHERE NOT OLD.latency_manufacture <=> NEW.latency_manufacture + -- Changed latency_manufacture_days + SELECT NEW.id_product, 'latency_manufacture_days', CONVERT(OLD.latency_manufacture_days, CHAR), CONVERT(NEW.latency_manufacture_days, CHAR), NEW.id_change_set + WHERE NOT OLD.latency_manufacture_days <=> NEW.latency_manufacture_days UNION -- Changed quantity_min SELECT NEW.id_product, 'quantity_min', CONVERT(OLD.quantity_min, CHAR), CONVERT(NEW.quantity_min, CHAR), NEW.id_change_set @@ -3536,13 +3536,13 @@ BEGIN SELECT NEW.id_product, 'is_subscription', CONVERT(CONVERT(OLD.is_subscription, SIGNED), CHAR), CONVERT(CONVERT(NEW.is_subscription, SIGNED), CHAR), NEW.id_change_set WHERE NOT OLD.is_subscription <=> NEW.is_subscription UNION - -- Changed id_recurrence_interval - SELECT NEW.id_product, 'id_recurrence_interval', CONVERT(OLD.id_recurrence_interval, CHAR), CONVERT(NEW.id_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.id_recurrence_interval <=> NEW.id_recurrence_interval + -- Changed id_unit_measurement_interval_recurrence + SELECT NEW.id_product, 'id_unit_measurement_interval_recurrence', CONVERT(OLD.id_unit_measurement_interval_recurrence, CHAR), CONVERT(NEW.id_unit_measurement_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.id_unit_measurement_interval_recurrence <=> NEW.id_unit_measurement_interval_recurrence UNION - -- Changed count_recurrence_interval - SELECT NEW.id_product, 'count_recurrence_interval', CONVERT(OLD.count_recurrence_interval, CHAR), CONVERT(NEW.count_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.count_recurrence_interval <=> NEW.count_recurrence_interval + -- Changed count_interval_recurrence + SELECT NEW.id_product, 'count_interval_recurrence', CONVERT(OLD.count_interval_recurrence, CHAR), CONVERT(NEW.count_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.count_interval_recurrence <=> NEW.count_interval_recurrence UNION -- Changed id_stripe_product SELECT NEW.id_permutation, 'id_stripe_product', OLD.id_stripe_product, NEW.id_stripe_product, NEW.id_change_set @@ -9749,19 +9749,19 @@ BEGIN price_GBP_full REAL NOT NULL, price_GBP_min REAL NOT NULL, */ - latency_manufacture INTEGER NOT NULL, + latency_manufacture_days INTEGER NOT NULL, quantity_min REAL NOT NULL, quantity_max REAL NOT NULL, quantity_step REAL NOT NULL, quantity_stock REAL NOT NULL, is_subscription BOOLEAN NOT NULL, - id_recurrence_interval INTEGER, + id_unit_measurement_interval_recurrence INTEGER, /* - CONSTRAINT FK_tmp_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), + CONSTRAINT FK_tmp_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), */ - count_recurrence_interval INTEGER, + count_interval_recurrence INTEGER, id_stripe_product VARCHAR(100), product_has_variations BOOLEAN NOT NULL, can_view BOOLEAN, @@ -9872,14 +9872,14 @@ BEGIN price_GBP_VAT_excl, price_GBP_min, */ - latency_manufacture, + latency_manufacture_days, quantity_min, quantity_max, quantity_step, quantity_stock, is_subscription, - id_recurrence_interval, - count_recurrence_interval, + id_unit_measurement_interval_recurrence, + count_interval_recurrence, id_stripe_product, product_has_variations ) @@ -9905,14 +9905,14 @@ BEGIN PP.price_GBP_VAT_excl, PP.price_GBP_min, */ - PP.latency_manufacture, + PP.latency_manufacture_days, PP.quantity_min, PP.quantity_max, PP.quantity_step, PP.quantity_stock, PP.is_subscription, - PP.id_recurrence_interval, - PP.count_recurrence_interval, + PP.id_unit_measurement_interval_recurrence, + PP.count_interval_recurrence, PP.id_stripe_product, P.has_variations FROM Shop_Product P @@ -10412,16 +10412,16 @@ BEGIN PP.cost_local, PP.id_currency_cost, PP.profit_local_min, - t_P.latency_manufacture, + t_P.latency_manufacture_days, t_P.quantity_min, t_P.quantity_max, t_P.quantity_step, t_P.quantity_stock, t_P.id_stripe_product, t_P.is_subscription, - RI.name AS name_recurrence_interval, - RI.name_plural AS name_plural_recurrence_interval, - t_P.count_recurrence_interval, + RI.name AS name_interval_recurrence, + RI.name_plural AS name_plural_interval_recurrence, + t_P.count_interval_recurrence, t_P.display_order_category, t_P.display_order_product, t_P.display_order_permutation, @@ -10431,7 +10431,7 @@ BEGIN FROM tmp_Shop_Product t_P INNER JOIN Shop_Product P ON t_P.id_product = P.id_product INNER JOIN Shop_Product_Permutation PP ON t_P.id_permutation = PP.id_permutation - LEFT JOIN Shop_Recurrence_Interval RI ON t_P.id_recurrence_interval = RI.id_interval + LEFT JOIN Shop_Interval_Recurrence RI ON t_P.id_unit_measurement_interval_recurrence = RI.id_interval ORDER BY t_P.rank_permutation ; RETURN NEXT result_products; @@ -11663,13 +11663,13 @@ BEGIN P.id_stripe_product, P.is_subscription, LOWER(RI.code) AS name_recurring_interval, - P.count_recurrence_interval + P.count_interval_recurrence FROM tmp_Shop_Product_Currency_Link t_PCL INNER JOIN Shop_Product P ON t_PCL.id_product = P.id_product AND P.active - INNER JOIN Shop_Recurrence_Interval RI - ON P.id_recurrence_interval = RI.id_interval + INNER JOIN Shop_Interval_Recurrence RI + ON P.id_unit_measurement_interval_recurrence = RI.id_interval AND RI.active INNER JOIN Shop_Currency C ON t_PCL.id_currency = C.id_currency @@ -12162,17 +12162,17 @@ BEGIN price_GBP_full REAL NOT NULL, price_GBP_min REAL NOT NULL, */ - latency_manufacture INTEGER NOT NULL, + latency_manufacture_days INTEGER NOT NULL, quantity_min REAL NOT NULL, quantity_max REAL NOT NULL, quantity_step REAL NOT NULL, quantity_stock REAL NOT NULL, is_subscription BOOLEAN NOT NULL, - id_recurrence_interval INTEGER, - CONSTRAINT FK_tmp_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), - count_recurrence_interval INTEGER, + id_unit_measurement_interval_recurrence INTEGER, + CONSTRAINT FK_tmp_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), + count_interval_recurrence INTEGER, id_stripe_product VARCHAR(100), product_has_variations INTEGER NOT NULL, can_view BOOLEAN, @@ -12318,14 +12318,14 @@ BEGIN price_GBP_VAT_excl, price_GBP_min, */ - latency_manufacture, + latency_manufacture_days, quantity_min, quantity_max, quantity_step, quantity_stock, is_subscription, - id_recurrence_interval, - count_recurrence_interval, + id_unit_measurement_interval_recurrence, + count_interval_recurrence, id_stripe_product, product_has_variations */ @@ -12350,14 +12350,14 @@ BEGIN PP.price_GBP_VAT_excl, PP.price_GBP_min, */ - PP.latency_manufacture, + PP.latency_manufacture_days, PP.quantity_min, PP.quantity_max, PP.quantity_step, PP.quantity_stock, PP.is_subscription, - PP.id_recurrence_interval, - PP.count_recurrence_interval, + PP.id_unit_measurement_interval_recurrence, + PP.count_interval_recurrence, PP.id_stripe_product, P.has_variations */ @@ -12849,17 +12849,17 @@ BEGIN price_GBP_min REAL NOT NULL, */ /* - latency_manufacture INTEGER NOT NULL, + latency_manufacture_days INTEGER NOT NULL, quantity_min REAL NOT NULL, quantity_max REAL NOT NULL, quantity_step REAL NOT NULL, quantity_stock REAL NOT NULL, is_subscription BOOLEAN NOT NULL, - id_recurrence_interval INTEGER, - CONSTRAINT FK_tmp_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), - count_recurrence_interval INTEGER, + id_unit_measurement_interval_recurrence INTEGER, + CONSTRAINT FK_tmp_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), + count_interval_recurrence INTEGER, id_stripe_product VARCHAR(100), product_has_variations INTEGER NOT NULL, */ @@ -12953,14 +12953,14 @@ BEGIN price_GBP_VAT_excl, price_GBP_min, */ - latency_manufacture, + latency_manufacture_days, quantity_min, quantity_max, quantity_step, quantity_stock, is_subscription, - id_recurrence_interval, - count_recurrence_interval, + id_unit_measurement_interval_recurrence, + count_interval_recurrence, id_stripe_product, product_has_variations */ @@ -12985,14 +12985,14 @@ BEGIN PP.price_GBP_VAT_excl, PP.price_GBP_min, */ - PP.latency_manufacture, + PP.latency_manufacture_days, PP.quantity_min, PP.quantity_max, PP.quantity_step, PP.quantity_stock, PP.is_subscription, - PP.id_recurrence_interval, - PP.count_recurrence_interval, + PP.id_unit_measurement_interval_recurrence, + PP.count_interval_recurrence, PP.id_stripe_product, P.has_variations */ @@ -13731,17 +13731,17 @@ BEGIN price_GBP_min REAL NOT NULL, */ /* - latency_manufacture INTEGER NOT NULL, + latency_manufacture_days INTEGER NOT NULL, quantity_min REAL NOT NULL, quantity_max REAL NOT NULL, quantity_step REAL NOT NULL, quantity_stock REAL NOT NULL, is_subscription BOOLEAN NOT NULL, - id_recurrence_interval INTEGER, - CONSTRAINT FK_tmp_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), - count_recurrence_interval INTEGER, + id_unit_measurement_interval_recurrence INTEGER, + CONSTRAINT FK_tmp_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), + count_interval_recurrence INTEGER, id_stripe_product VARCHAR(100), product_has_variations INTEGER NOT NULL, */ @@ -13887,14 +13887,14 @@ BEGIN price_GBP_VAT_excl, price_GBP_min, */ - latency_manufacture, + latency_manufacture_days, quantity_min, quantity_max, quantity_step, quantity_stock, is_subscription, - id_recurrence_interval, - count_recurrence_interval, + id_unit_measurement_interval_recurrence, + count_interval_recurrence, id_stripe_product, product_has_variations */ @@ -13919,14 +13919,14 @@ BEGIN PP.price_GBP_VAT_excl, PP.price_GBP_min, */ - PP.latency_manufacture, + PP.latency_manufacture_days, PP.quantity_min, PP.quantity_max, PP.quantity_step, PP.quantity_stock, PP.is_subscription, - PP.id_recurrence_interval, - PP.count_recurrence_interval, + PP.id_unit_measurement_interval_recurrence, + PP.count_interval_recurrence, PP.id_stripe_product, P.has_variations */ @@ -14345,7 +14345,7 @@ VALUES ; -- Recurrence Interval -INSERT INTO Shop_Recurrence_Interval ( +INSERT INTO Shop_Interval_Recurrence ( code, name, name_plural ) VALUES @@ -14468,14 +14468,14 @@ INSERT INTO Shop_Product_Permutation ( id_currency_cost, profit_local_min, -- id_currency_profit_min, - latency_manufacture, + latency_manufacture_days, quantity_min, quantity_max, quantity_step, quantity_stock, is_subscription, - id_recurrence_interval, - count_recurrence_interval, + id_unit_measurement_interval_recurrence, + count_interval_recurrence, -- id_access_level_required, id_stripe_product ) @@ -14956,8 +14956,8 @@ SELECT * FROM Shop_Product_Category; SELECT * FROM Shop_Product_Category_Audit; -- Recurrence Interval -SELECT * FROM Shop_Recurrence_Interval; -SELECT * FROM Shop_Recurrence_Interval_Audit; +SELECT * FROM Shop_Interval_Recurrence; +SELECT * FROM Shop_Interval_Recurrence_Audit; -- Region SELECT * FROM Shop_Region; diff --git a/static/PostgreSQL/001_destroy.sql b/static/PostgreSQL/001_destroy.sql index 74c16589..060a3a4f 100644 --- a/static/PostgreSQL/001_destroy.sql +++ b/static/PostgreSQL/001_destroy.sql @@ -157,8 +157,8 @@ DROP TABLE IF EXISTS Shop_Delivery_Region; DROP TABLE IF EXISTS Shop_Region_Audit; DROP TABLE IF EXISTS Shop_Region; -DROP TABLE IF EXISTS Shop_Recurrence_Interval_Audit; -DROP TABLE IF EXISTS Shop_Recurrence_Interval; +DROP TABLE IF EXISTS Shop_Interval_Recurrence_Audit; +DROP TABLE IF EXISTS Shop_Interval_Recurrence; DROP TABLE IF EXISTS Shop_Product_Category_Audit; DROP TABLE IF EXISTS Shop_Product_Category; diff --git a/static/PostgreSQL/108_tbl_Shop_Recurrence_Interval.sql b/static/PostgreSQL/108_tbl_Shop_Recurrence_Interval.sql index 95d974ca..4075a57e 100644 --- a/static/PostgreSQL/108_tbl_Shop_Recurrence_Interval.sql +++ b/static/PostgreSQL/108_tbl_Shop_Recurrence_Interval.sql @@ -3,9 +3,9 @@ -SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Recurrence_Interval'; +SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Interval_Recurrence'; -CREATE TABLE IF NOT EXISTS Shop_Recurrence_Interval ( +CREATE TABLE IF NOT EXISTS Shop_Interval_Recurrence ( id_interval INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY, code VARCHAR(50), name VARCHAR(255), @@ -14,7 +14,7 @@ CREATE TABLE IF NOT EXISTS Shop_Recurrence_Interval ( created_on TIMESTAMP, created_by INT, id_change_set INTEGER, - CONSTRAINT FK_Shop_Recurrence_Interval_id_change_set + CONSTRAINT FK_Shop_Interval_Recurrence_id_change_set FOREIGN KEY (id_change_set) REFERENCES Shop_Product_Change_Set(id_change_set) ); diff --git a/static/PostgreSQL/109_tbl_Shop_Recurrence_Interval_Audit.sql b/static/PostgreSQL/109_tbl_Shop_Recurrence_Interval_Audit.sql index d3192fc6..8ca9184b 100644 --- a/static/PostgreSQL/109_tbl_Shop_Recurrence_Interval_Audit.sql +++ b/static/PostgreSQL/109_tbl_Shop_Recurrence_Interval_Audit.sql @@ -3,20 +3,20 @@ -SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Recurrence_Interval_Audit'; +SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Interval_Recurrence_Audit'; -CREATE TABLE IF NOT EXISTS Shop_Recurrence_Interval_Audit ( +CREATE TABLE IF NOT EXISTS Shop_Interval_Recurrence_Audit ( id_audit INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY, id_interval INTEGER NOT NULL, - CONSTRAINT FK_Shop_Recurrence_Interval_Audit_id_interval + CONSTRAINT FK_Shop_Interval_Recurrence_Audit_id_interval FOREIGN KEY (id_interval) - REFERENCES Shop_Recurrence_Interval(id_interval) + REFERENCES Shop_Interval_Recurrence(id_interval) ON UPDATE RESTRICT, name_field VARCHAR(50), value_prev VARCHAR(256), value_new VARCHAR(256), id_change_set INTEGER NOT NULL, - CONSTRAINT FK_Shop_Recurrence_Interval_Audit_id_change_set + CONSTRAINT FK_Shop_Interval_Recurrence_Audit_id_change_set FOREIGN KEY (id_change_set) REFERENCES Shop_Product_Change_Set(id_change_set) ); diff --git a/static/PostgreSQL/110.8_tbl_Shop_Product.sql b/static/PostgreSQL/110.8_tbl_Shop_Product.sql index 67e3019d..ed44d554 100644 --- a/static/PostgreSQL/110.8_tbl_Shop_Product.sql +++ b/static/PostgreSQL/110.8_tbl_Shop_Product.sql @@ -25,11 +25,11 @@ CREATE TABLE IF NOT EXISTS Shop_Product ( quantity_step REAL, quantity_stock REAL, is_subscription BOOLEAN, - id_recurrence_interval INTEGER, - CONSTRAINT FK_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), - count_recurrence_interval INTEGER, + id_unit_measurement_interval_recurrence INTEGER, + CONSTRAINT FK_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), + count_interval_recurrence INTEGER, */ id_access_level_required INTEGER NOT NULL, CONSTRAINT FK_Shop_Product_id_access_level_required diff --git a/static/PostgreSQL/117.1_tbl_Shop_Product_Permutation.sql b/static/PostgreSQL/117.1_tbl_Shop_Product_Permutation.sql index c64cd4f4..9b60cf1e 100644 --- a/static/PostgreSQL/117.1_tbl_Shop_Product_Permutation.sql +++ b/static/PostgreSQL/117.1_tbl_Shop_Product_Permutation.sql @@ -18,17 +18,17 @@ CREATE TABLE IF NOT EXISTS Shop_Product_Permutation ( id_currency_cost INTEGER NOT NULL, profit_local_min REAL NOT NULL, -- id_currency_profit_min INTEGER NOT NULL, - latency_manufacture INTEGER NOT NULL, + latency_manufacture_days INTEGER NOT NULL, quantity_min REAL NOT NULL, quantity_max REAL NOT NULL, quantity_step REAL NOT NULL, quantity_stock REAL NOT NULL, is_subscription BOOLEAN NOT NULL, - id_recurrence_interval INTEGER, - CONSTRAINT FK_Shop_Product_Permutation_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), - count_recurrence_interval INTEGER, + id_unit_measurement_interval_recurrence INTEGER, + CONSTRAINT FK_Shop_Product_Permutation_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), + count_interval_recurrence INTEGER, /* id_access_level_required INTEGER NOT NULL, CONSTRAINT FK_Shop_Product_Permutation_id_access_level_required diff --git a/static/PostgreSQL/308_tri_Shop_Recurrence_Interval.sql b/static/PostgreSQL/308_tri_Shop_Recurrence_Interval.sql index 127b00e3..0a82210f 100644 --- a/static/PostgreSQL/308_tri_Shop_Recurrence_Interval.sql +++ b/static/PostgreSQL/308_tri_Shop_Recurrence_Interval.sql @@ -1,7 +1,7 @@ -- Shop Recurrence Interval -CREATE OR REPLACE FUNCTION before_insert_Shop_Recurrence_Interval() +CREATE OR REPLACE FUNCTION before_insert_Shop_Interval_Recurrence() RETURNS TRIGGER AS $$ BEGIN NEW.created_on = CURRENT_TIMESTAMP; @@ -11,13 +11,13 @@ BEGIN END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE TRIGGER tri_before_insert_Shop_Recurrence_Interval -BEFORE INSERT ON Shop_Recurrence_Interval +CREATE OR REPLACE TRIGGER tri_before_insert_Shop_Interval_Recurrence +BEFORE INSERT ON Shop_Interval_Recurrence FOR EACH ROW -EXECUTE FUNCTION before_insert_Shop_Recurrence_Interval(); +EXECUTE FUNCTION before_insert_Shop_Interval_Recurrence(); -CREATE OR REPLACE FUNCTION before_update_Shop_Recurrence_Interval() +CREATE OR REPLACE FUNCTION before_update_Shop_Interval_Recurrence() RETURNS TRIGGER AS $$ BEGIN IF OLD.id_change_set IS NOT DISTINCT FROM NEW.id_change_set THEN @@ -25,7 +25,7 @@ BEGIN USING ERRCODE = '45000'; END IF; - INSERT INTO Shop_Recurrence_Interval_Audit ( + INSERT INTO Shop_Interval_Recurrence_Audit ( id_interval, name_field, value_prev, @@ -53,7 +53,7 @@ BEGIN END; $$ LANGUAGE plpgsql; -CREATE OR REPLACE TRIGGER tri_before_update_Shop_Recurrence_Interval -BEFORE UPDATE ON Shop_Recurrence_Interval +CREATE OR REPLACE TRIGGER tri_before_update_Shop_Interval_Recurrence +BEFORE UPDATE ON Shop_Interval_Recurrence FOR EACH ROW -EXECUTE FUNCTION before_update_Shop_Recurrence_Interval(); +EXECUTE FUNCTION before_update_Shop_Interval_Recurrence(); diff --git a/static/PostgreSQL/310.8_tri_Shop_Product.sql b/static/PostgreSQL/310.8_tri_Shop_Product.sql index 6a4c797f..4f25d19a 100644 --- a/static/PostgreSQL/310.8_tri_Shop_Product.sql +++ b/static/PostgreSQL/310.8_tri_Shop_Product.sql @@ -58,11 +58,11 @@ BEGIN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Product must have subscription status or variations (with subscription statuses).'; END IF; - IF ISNULL(NEW.id_recurrence_interval) THEN + IF ISNULL(NEW.id_unit_measurement_interval_recurrence) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Product must have recurrence interval or variations (with recurrence intervals).'; END IF; - IF ISNULL(NEW.count_recurrence_interval) THEN + IF ISNULL(NEW.count_interval_recurrence) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Product must have recurrence interval count or variations (with recurrence interval counts).'; END IF; @@ -132,13 +132,13 @@ BEGIN SELECT NEW.id_product, 'is_subscription', CONVERT(CONVERT(OLD.is_subscription, SIGNED), CHAR), CONVERT(CONVERT(NEW.is_subscription, SIGNED), CHAR), NEW.id_change_set WHERE NOT OLD.is_subscription <=> NEW.is_subscription UNION - -- Changed id_recurrence_interval - SELECT NEW.id_product, 'id_recurrence_interval', CONVERT(OLD.id_recurrence_interval, CHAR), CONVERT(NEW.id_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.id_recurrence_interval <=> NEW.id_recurrence_interval + -- Changed id_unit_measurement_interval_recurrence + SELECT NEW.id_product, 'id_unit_measurement_interval_recurrence', CONVERT(OLD.id_unit_measurement_interval_recurrence, CHAR), CONVERT(NEW.id_unit_measurement_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.id_unit_measurement_interval_recurrence <=> NEW.id_unit_measurement_interval_recurrence UNION - -- Changed count_recurrence_interval - SELECT NEW.id_product, 'count_recurrence_interval', CONVERT(OLD.count_recurrence_interval, CHAR), CONVERT(NEW.count_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.count_recurrence_interval <=> NEW.count_recurrence_interval + -- Changed count_interval_recurrence + SELECT NEW.id_product, 'count_interval_recurrence', CONVERT(OLD.count_interval_recurrence, CHAR), CONVERT(NEW.count_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.count_interval_recurrence <=> NEW.count_interval_recurrence UNION -- Changed id_stripe_product SELECT NEW.id_product, 'id_stripe_product', OLD.id_stripe_product, NEW.id_stripe_product, NEW.id_change_set diff --git a/static/PostgreSQL/317.1_tri_Shop_Product_Permutation.sql b/static/PostgreSQL/317.1_tri_Shop_Product_Permutation.sql index cc511b34..78abd0aa 100644 --- a/static/PostgreSQL/317.1_tri_Shop_Product_Permutation.sql +++ b/static/PostgreSQL/317.1_tri_Shop_Product_Permutation.sql @@ -78,9 +78,9 @@ BEGIN WHERE NOT (OLD.price_GBP_min <=> NEW.price_GBP_min) UNION */ - -- Changed latency_manufacture - SELECT NEW.id_product, 'latency_manufacture', CONVERT(OLD.latency_manufacture, CHAR), CONVERT(NEW.latency_manufacture, CHAR), NEW.id_change_set - WHERE NOT OLD.latency_manufacture <=> NEW.latency_manufacture + -- Changed latency_manufacture_days + SELECT NEW.id_product, 'latency_manufacture_days', CONVERT(OLD.latency_manufacture_days, CHAR), CONVERT(NEW.latency_manufacture_days, CHAR), NEW.id_change_set + WHERE NOT OLD.latency_manufacture_days <=> NEW.latency_manufacture_days UNION -- Changed quantity_min SELECT NEW.id_product, 'quantity_min', CONVERT(OLD.quantity_min, CHAR), CONVERT(NEW.quantity_min, CHAR), NEW.id_change_set @@ -102,13 +102,13 @@ BEGIN SELECT NEW.id_product, 'is_subscription', CONVERT(CONVERT(OLD.is_subscription, SIGNED), CHAR), CONVERT(CONVERT(NEW.is_subscription, SIGNED), CHAR), NEW.id_change_set WHERE NOT OLD.is_subscription <=> NEW.is_subscription UNION - -- Changed id_recurrence_interval - SELECT NEW.id_product, 'id_recurrence_interval', CONVERT(OLD.id_recurrence_interval, CHAR), CONVERT(NEW.id_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.id_recurrence_interval <=> NEW.id_recurrence_interval + -- Changed id_unit_measurement_interval_recurrence + SELECT NEW.id_product, 'id_unit_measurement_interval_recurrence', CONVERT(OLD.id_unit_measurement_interval_recurrence, CHAR), CONVERT(NEW.id_unit_measurement_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.id_unit_measurement_interval_recurrence <=> NEW.id_unit_measurement_interval_recurrence UNION - -- Changed count_recurrence_interval - SELECT NEW.id_product, 'count_recurrence_interval', CONVERT(OLD.count_recurrence_interval, CHAR), CONVERT(NEW.count_recurrence_interval, CHAR), NEW.id_change_set - WHERE NOT OLD.count_recurrence_interval <=> NEW.count_recurrence_interval + -- Changed count_interval_recurrence + SELECT NEW.id_product, 'count_interval_recurrence', CONVERT(OLD.count_interval_recurrence, CHAR), CONVERT(NEW.count_interval_recurrence, CHAR), NEW.id_change_set + WHERE NOT OLD.count_interval_recurrence <=> NEW.count_interval_recurrence UNION -- Changed id_stripe_product SELECT NEW.id_permutation, 'id_stripe_product', OLD.id_stripe_product, NEW.id_stripe_product, NEW.id_change_set diff --git a/static/PostgreSQL/600_p_shop_save_product.sql b/static/PostgreSQL/600_p_shop_save_product.sql index 659f298a..de30cd13 100644 --- a/static/PostgreSQL/600_p_shop_save_product.sql +++ b/static/PostgreSQL/600_p_shop_save_product.sql @@ -211,17 +211,17 @@ BEGIN P.id_stripe_product, P.id_stripe_price, P.is_subscription, - RI.name AS name_recurrence_interval, - RI.name_plural AS name_plural_recurrence_interval, - P.count_recurrence_interval, + RI.name AS name_interval_recurrence, + RI.name_plural AS name_plural_interval_recurrence, + P.count_interval_recurrence, tP.can_view, tP.can_edit, tP.can_admin FROM tmp_Shop_Product tP INNER JOIN Shop_Product P ON tP.id_product = P.id_product - INNER JOIN Shop_Recurrence_Interval RI - ON P.id_recurrence_interval = RI.id_interval + INNER JOIN Shop_Interval_Recurrence RI + ON P.id_unit_measurement_interval_recurrence = RI.id_interval ; -- Variations diff --git a/static/PostgreSQL/700_p_shop_get_many_product.sql b/static/PostgreSQL/700_p_shop_get_many_product.sql index 0ba000d9..bd9c39cf 100644 --- a/static/PostgreSQL/700_p_shop_get_many_product.sql +++ b/static/PostgreSQL/700_p_shop_get_many_product.sql @@ -203,19 +203,19 @@ BEGIN price_GBP_full REAL NOT NULL, price_GBP_min REAL NOT NULL, */ - latency_manufacture INTEGER NOT NULL, + latency_manufacture_days INTEGER NOT NULL, quantity_min REAL NOT NULL, quantity_max REAL NOT NULL, quantity_step REAL NOT NULL, quantity_stock REAL NOT NULL, is_subscription BOOLEAN NOT NULL, - id_recurrence_interval INTEGER, + id_unit_measurement_interval_recurrence INTEGER, /* - CONSTRAINT FK_tmp_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), + CONSTRAINT FK_tmp_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), */ - count_recurrence_interval INTEGER, + count_interval_recurrence INTEGER, id_stripe_product VARCHAR(100), product_has_variations BOOLEAN NOT NULL, can_view BOOLEAN, @@ -326,14 +326,14 @@ BEGIN price_GBP_VAT_excl, price_GBP_min, */ - latency_manufacture, + latency_manufacture_days, quantity_min, quantity_max, quantity_step, quantity_stock, is_subscription, - id_recurrence_interval, - count_recurrence_interval, + id_unit_measurement_interval_recurrence, + count_interval_recurrence, id_stripe_product, product_has_variations ) @@ -359,14 +359,14 @@ BEGIN PP.price_GBP_VAT_excl, PP.price_GBP_min, */ - PP.latency_manufacture, + PP.latency_manufacture_days, PP.quantity_min, PP.quantity_max, PP.quantity_step, PP.quantity_stock, PP.is_subscription, - PP.id_recurrence_interval, - PP.count_recurrence_interval, + PP.id_unit_measurement_interval_recurrence, + PP.count_interval_recurrence, PP.id_stripe_product, P.has_variations FROM Shop_Product P @@ -866,16 +866,16 @@ BEGIN PP.cost_local, PP.id_currency_cost, PP.profit_local_min, - t_P.latency_manufacture, + t_P.latency_manufacture_days, t_P.quantity_min, t_P.quantity_max, t_P.quantity_step, t_P.quantity_stock, t_P.id_stripe_product, t_P.is_subscription, - RI.name AS name_recurrence_interval, - RI.name_plural AS name_plural_recurrence_interval, - t_P.count_recurrence_interval, + RI.name AS name_interval_recurrence, + RI.name_plural AS name_plural_interval_recurrence, + t_P.count_interval_recurrence, t_P.display_order_category, t_P.display_order_product, t_P.display_order_permutation, @@ -885,7 +885,7 @@ BEGIN FROM tmp_Shop_Product t_P INNER JOIN Shop_Product P ON t_P.id_product = P.id_product INNER JOIN Shop_Product_Permutation PP ON t_P.id_permutation = PP.id_permutation - LEFT JOIN Shop_Recurrence_Interval RI ON t_P.id_recurrence_interval = RI.id_interval + LEFT JOIN Shop_Interval_Recurrence RI ON t_P.id_unit_measurement_interval_recurrence = RI.id_interval ORDER BY t_P.rank_permutation ; RETURN NEXT result_products; diff --git a/static/PostgreSQL/705_p_shop_get_many_stripe_price_new.sql b/static/PostgreSQL/705_p_shop_get_many_stripe_price_new.sql index eedb5102..fff041f4 100644 --- a/static/PostgreSQL/705_p_shop_get_many_stripe_price_new.sql +++ b/static/PostgreSQL/705_p_shop_get_many_stripe_price_new.sql @@ -170,13 +170,13 @@ BEGIN P.id_stripe_product, P.is_subscription, LOWER(RI.code) AS name_recurring_interval, - P.count_recurrence_interval + P.count_interval_recurrence FROM tmp_Shop_Product_Currency_Link t_PCL INNER JOIN Shop_Product P ON t_PCL.id_product = P.id_product AND P.active - INNER JOIN Shop_Recurrence_Interval RI - ON P.id_recurrence_interval = RI.id_interval + INNER JOIN Shop_Interval_Recurrence RI + ON P.id_unit_measurement_interval_recurrence = RI.id_interval AND RI.active INNER JOIN Shop_Currency C ON t_PCL.id_currency = C.id_currency diff --git a/static/PostgreSQL/706_p_shop_get_many_supplier_purchase_order.sql b/static/PostgreSQL/706_p_shop_get_many_supplier_purchase_order.sql index 3de58a84..f29b480d 100644 --- a/static/PostgreSQL/706_p_shop_get_many_supplier_purchase_order.sql +++ b/static/PostgreSQL/706_p_shop_get_many_supplier_purchase_order.sql @@ -169,17 +169,17 @@ BEGIN price_GBP_full REAL NOT NULL, price_GBP_min REAL NOT NULL, */ - latency_manufacture INTEGER NOT NULL, + latency_manufacture_days INTEGER NOT NULL, quantity_min REAL NOT NULL, quantity_max REAL NOT NULL, quantity_step REAL NOT NULL, quantity_stock REAL NOT NULL, is_subscription BOOLEAN NOT NULL, - id_recurrence_interval INTEGER, - CONSTRAINT FK_tmp_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), - count_recurrence_interval INTEGER, + id_unit_measurement_interval_recurrence INTEGER, + CONSTRAINT FK_tmp_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), + count_interval_recurrence INTEGER, id_stripe_product VARCHAR(100), product_has_variations INTEGER NOT NULL, can_view BOOLEAN, @@ -325,14 +325,14 @@ BEGIN price_GBP_VAT_excl, price_GBP_min, */ - latency_manufacture, + latency_manufacture_days, quantity_min, quantity_max, quantity_step, quantity_stock, is_subscription, - id_recurrence_interval, - count_recurrence_interval, + id_unit_measurement_interval_recurrence, + count_interval_recurrence, id_stripe_product, product_has_variations */ @@ -357,14 +357,14 @@ BEGIN PP.price_GBP_VAT_excl, PP.price_GBP_min, */ - PP.latency_manufacture, + PP.latency_manufacture_days, PP.quantity_min, PP.quantity_max, PP.quantity_step, PP.quantity_stock, PP.is_subscription, - PP.id_recurrence_interval, - PP.count_recurrence_interval, + PP.id_unit_measurement_interval_recurrence, + PP.count_interval_recurrence, PP.id_stripe_product, P.has_variations */ diff --git a/static/PostgreSQL/708_p_shop_get_many_manufacturing_purchase_order.sql b/static/PostgreSQL/708_p_shop_get_many_manufacturing_purchase_order.sql index e88881f8..29c50208 100644 --- a/static/PostgreSQL/708_p_shop_get_many_manufacturing_purchase_order.sql +++ b/static/PostgreSQL/708_p_shop_get_many_manufacturing_purchase_order.sql @@ -147,17 +147,17 @@ BEGIN price_GBP_min REAL NOT NULL, */ /* - latency_manufacture INTEGER NOT NULL, + latency_manufacture_days INTEGER NOT NULL, quantity_min REAL NOT NULL, quantity_max REAL NOT NULL, quantity_step REAL NOT NULL, quantity_stock REAL NOT NULL, is_subscription BOOLEAN NOT NULL, - id_recurrence_interval INTEGER, - CONSTRAINT FK_tmp_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), - count_recurrence_interval INTEGER, + id_unit_measurement_interval_recurrence INTEGER, + CONSTRAINT FK_tmp_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), + count_interval_recurrence INTEGER, id_stripe_product VARCHAR(100), product_has_variations INTEGER NOT NULL, */ @@ -251,14 +251,14 @@ BEGIN price_GBP_VAT_excl, price_GBP_min, */ - latency_manufacture, + latency_manufacture_days, quantity_min, quantity_max, quantity_step, quantity_stock, is_subscription, - id_recurrence_interval, - count_recurrence_interval, + id_unit_measurement_interval_recurrence, + count_interval_recurrence, id_stripe_product, product_has_variations */ @@ -283,14 +283,14 @@ BEGIN PP.price_GBP_VAT_excl, PP.price_GBP_min, */ - PP.latency_manufacture, + PP.latency_manufacture_days, PP.quantity_min, PP.quantity_max, PP.quantity_step, PP.quantity_stock, PP.is_subscription, - PP.id_recurrence_interval, - PP.count_recurrence_interval, + PP.id_unit_measurement_interval_recurrence, + PP.count_interval_recurrence, PP.id_stripe_product, P.has_variations */ diff --git a/static/PostgreSQL/710_p_shop_get_many_customer_sales_order.sql b/static/PostgreSQL/710_p_shop_get_many_customer_sales_order.sql index 140f1e1c..89e21735 100644 --- a/static/PostgreSQL/710_p_shop_get_many_customer_sales_order.sql +++ b/static/PostgreSQL/710_p_shop_get_many_customer_sales_order.sql @@ -179,17 +179,17 @@ BEGIN price_GBP_min REAL NOT NULL, */ /* - latency_manufacture INTEGER NOT NULL, + latency_manufacture_days INTEGER NOT NULL, quantity_min REAL NOT NULL, quantity_max REAL NOT NULL, quantity_step REAL NOT NULL, quantity_stock REAL NOT NULL, is_subscription BOOLEAN NOT NULL, - id_recurrence_interval INTEGER, - CONSTRAINT FK_tmp_Shop_Product_id_recurrence_interval - FOREIGN KEY (id_recurrence_interval) - REFERENCES Shop_Recurrence_Interval(id_interval), - count_recurrence_interval INTEGER, + id_unit_measurement_interval_recurrence INTEGER, + CONSTRAINT FK_tmp_Shop_Product_id_unit_measurement_interval_recurrence + FOREIGN KEY (id_unit_measurement_interval_recurrence) + REFERENCES Shop_Interval_Recurrence(id_interval), + count_interval_recurrence INTEGER, id_stripe_product VARCHAR(100), product_has_variations INTEGER NOT NULL, */ @@ -335,14 +335,14 @@ BEGIN price_GBP_VAT_excl, price_GBP_min, */ - latency_manufacture, + latency_manufacture_days, quantity_min, quantity_max, quantity_step, quantity_stock, is_subscription, - id_recurrence_interval, - count_recurrence_interval, + id_unit_measurement_interval_recurrence, + count_interval_recurrence, id_stripe_product, product_has_variations */ @@ -367,14 +367,14 @@ BEGIN PP.price_GBP_VAT_excl, PP.price_GBP_min, */ - PP.latency_manufacture, + PP.latency_manufacture_days, PP.quantity_min, PP.quantity_max, PP.quantity_step, PP.quantity_stock, PP.is_subscription, - PP.id_recurrence_interval, - PP.count_recurrence_interval, + PP.id_unit_measurement_interval_recurrence, + PP.count_interval_recurrence, PP.id_stripe_product, P.has_variations */ diff --git a/static/PostgreSQL/900_populate.sql b/static/PostgreSQL/900_populate.sql index 18b7cdd5..d283d4ec 100644 --- a/static/PostgreSQL/900_populate.sql +++ b/static/PostgreSQL/900_populate.sql @@ -75,7 +75,7 @@ VALUES ; -- Recurrence Interval -INSERT INTO Shop_Recurrence_Interval ( +INSERT INTO Shop_Interval_Recurrence ( code, name, name_plural ) VALUES @@ -198,14 +198,14 @@ INSERT INTO Shop_Product_Permutation ( id_currency_cost, profit_local_min, -- id_currency_profit_min, - latency_manufacture, + latency_manufacture_days, quantity_min, quantity_max, quantity_step, quantity_stock, is_subscription, - id_recurrence_interval, - count_recurrence_interval, + id_unit_measurement_interval_recurrence, + count_interval_recurrence, -- id_access_level_required, id_stripe_product ) diff --git a/static/PostgreSQL/901_view.sql b/static/PostgreSQL/901_view.sql index bccf70d5..68af54f2 100644 --- a/static/PostgreSQL/901_view.sql +++ b/static/PostgreSQL/901_view.sql @@ -31,8 +31,8 @@ SELECT * FROM Shop_Product_Category; SELECT * FROM Shop_Product_Category_Audit; -- Recurrence Interval -SELECT * FROM Shop_Recurrence_Interval; -SELECT * FROM Shop_Recurrence_Interval_Audit; +SELECT * FROM Shop_Interval_Recurrence; +SELECT * FROM Shop_Interval_Recurrence_Audit; -- Region SELECT * FROM Shop_Region; diff --git a/static/PostgreSQL/temp.txt b/static/PostgreSQL/temp.txt index be9b6d25..3a4d329e 100644 --- a/static/PostgreSQL/temp.txt +++ b/static/PostgreSQL/temp.txt @@ -11,8 +11,8 @@ 105_tbl_Shop_General_Audit.sql 106_tbl_Shop_Product_Category.sql 107_tbl_Shop_Product_Category_Audit.sql -108_tbl_Shop_Recurrence_Interval.sql -109_tbl_Shop_Recurrence_Interval_Audit.sql +108_tbl_Shop_Interval_Recurrence.sql +109_tbl_Shop_Interval_Recurrence_Audit.sql 110.0_tbl_Shop_Region.sql 110.1_tbl_Shop_Region_Audit.sql 110.2_tbl_Shop_Region_Branch.sql @@ -94,7 +94,7 @@ 303_tri_File_Type_Audit.sql 304_tri_Shop_General.sql 306_tri_Shop_Product_Category.sql -308_tri_Shop_Recurrence_Interval.sql +308_tri_Shop_Interval_Recurrence.sql 310.0_tri_Shop_Region.sql 310.2_tri_Shop_Region_Branch.sql 310.4_tri_Shop_Currency.sql diff --git a/static/css/components/table.css b/static/css/components/table.css new file mode 100644 index 00000000..89830f09 --- /dev/null +++ b/static/css/components/table.css @@ -0,0 +1,35 @@ + +thead, tbody { + padding-top: 0px !important; + padding-bottom: 0px !important; +} + +th { + +} +td { + font-size: min(12px, calc(1vh * 3)); +} + +th, td { + min-width: fit-content; +} +tr:not(:last-child) > td { + border-bottom: 1px dashed var(--c_purple_dark); +} +td > table > tbody > tr > td { + border: none !important; +} +tr { + min-height: 1px; + border-bottom: 1px solid var(--c_purple_dark); + border-top: 1px solid var(--c_purple_dark); + padding-bottom: 1vh; + background-color: transparent; +} + +/* +.row-new { + visibility: hidden; +} +*/ diff --git a/static/css/layouts/header.css b/static/css/layouts/header.css index e69de29b..fe4e207a 100644 --- a/static/css/layouts/header.css +++ b/static/css/layouts/header.css @@ -0,0 +1,15 @@ + + +button.collapsed { + display: block; + opacity: 0; +} + +form.filter button.save, form.filter button.button-cancel { + margin-top: 0; + margin-bottom: 0; +} +form.filter button.save, form.filter button.button-cancel { + margin-top: 0; + margin-bottom: 0; +} \ No newline at end of file diff --git a/static/css/layouts/table-main.css b/static/css/layouts/table-main.css new file mode 100644 index 00000000..dfc49c54 --- /dev/null +++ b/static/css/layouts/table-main.css @@ -0,0 +1,15 @@ +#tableMain { + overflow-x: auto; + padding: 1vh 2vh; + max-width: min(calc(1vh * 80), calc(1vw * 90)); + width: fit-content; + margin: 1vh 2vh; + align-items: normal; + justify-content: normal; +} + +#tableMain thead tr th, #tableMain tbody tr td { + width: 20vh; + min-width: 20vh; + padding: 0 0.5vh; +} \ No newline at end of file diff --git a/static/css/main.css b/static/css/main.css index 2cc9dcd2..83a8064e 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -1,5 +1,5 @@ -/* + /* Base styles * @import 'lib/reset.css'; @import 'lib/typography.css'; @@ -9,6 +9,7 @@ /* Layout styles * @import 'layouts/header.css'; @import 'layouts/footer.css'; +@import 'layouts/table-main.css'; /* Component styles * @import 'components/button.css'; @@ -21,6 +22,7 @@ /* Section styles * @import 'sections/store.css'; +*/ /* Page-specific styles * @import 'pages/page_admin.css'; @@ -31,15 +33,14 @@ @import 'pages/page_store_home.css'; @import 'pages/page_store_product_permutations.css'; @import 'pages/page_store_stock_items.css'; -* +*/ /* Theme styles * @import 'themes/light.css'; -/* Uncomment the line below to enable dark theme * -/* @import 'themes/dark.css'; * +/* Uncomment the line below to enable dark theme */ +/* @import 'themes/dark.css'; */ -*/ /* Custom styles */ /* Add any custom styles or overrides here */ @@ -234,10 +235,9 @@ h5 { text-align: center; width: 100%; align-self: center; - font-size: min(20px, calc(1vh * 6)); + font-size: min(16px, calc(1vh * 4)); } #pageBody > * > * { - width: 100%; align-self: center; padding-top: 1vh; padding-bottom: 1vh; @@ -374,6 +374,7 @@ img.header-logo { display: flex; flex-direction: column; align-items: center; + margin: auto 0; } .row { @@ -521,10 +522,10 @@ button:hover, input[type="submit"]:hover, #overlayHamburger .row *:hover { z-index: 999; } .overlay.expanded { - display: block !important; + display: block; } .collapsed { - display: none !important; + display: none; } #overlayHamburger { @@ -593,39 +594,5 @@ td.dirty { /* Tables */ #pageBody > *, button { - font-size: min(14px, calc(1vh * 5)) !important; -} -thead, tbody { - padding-top: 0px !important; - padding-bottom: 0px !important; -} - -th { - -} -td { - font-size: min(14px, calc(1vh * 5)); -} - -th, td { - min-width: fit-content; -} -tr:not(:last-child) > td { - border-bottom: 1px dashed var(--c_purple_dark); -} -td > table > tbody > tr > td { - border: none !important; -} -tr { - min-height: 1px; - border-bottom: 1px solid var(--c_purple_dark); - border-top: 1px solid var(--c_purple_dark); - padding-bottom: 1vh; - background-color: transparent; -} - -/* -.row-new { - visibility: hidden; -} -*/ + font-size: min(12px, calc(1vh * 3)); +} \ No newline at end of file diff --git a/static/css/pages/core/home.css b/static/css/pages/core/home.css index 1a67abe6..642e9327 100644 --- a/static/css/pages/core/home.css +++ b/static/css/pages/core/home.css @@ -1,4 +1,7 @@ +#pageBody > * > * { + width: 100%; +} #pageBody > * { height: 100%; } diff --git a/static/css/pages/store/product_categories.css b/static/css/pages/store/product_categories.css index 5872ca5b..6d2d635e 100644 --- a/static/css/pages/store/product_categories.css +++ b/static/css/pages/store/product_categories.css @@ -1,23 +1,58 @@ +#formFilters { + width: 50vh; +} -td.display-order, th.display-order { - width: 8% !important; +#formFilters .container { + max-width: fit-content; } -td.code, th.code { - width: 15% !important; + +#formFilters .container-input.filter.is_not_empty { + width: 10vh; +} + +#formFilters .container-input.filter.active { + width: 8vh; } -td.name, th.name { - width: 25% !important; + +#tableMain { + max-width: min(calc(1vh * 79), calc(1vw * 90)); } -td.description, th.description { - width: 35% !important; + +/* +#tableMain thead tr th, #tableMain tbody tr td { + margin-left: 1vh; + margin-right: 1vh; } -td.access_level, th.access_level { - width: 10% !important; +*/ + +#tableMain tbody tr td.display_order, #tableMain thead tr th.display_order { + width: 5vh; + min-width: 5vh; } -td.active, th.active { - width: 7% !important; +#tableMain tbody tr td.code, #tableMain thead tr th.code { + width: 10vh; + min-width: 10vh; } +#tableMain tbody tr td.name, #tableMain thead tr th.name { + width: 15vh; + min-width: 15vh; +} +#tableMain tbody tr td.description, #tableMain thead tr th.description { + width: 25vh; + min-width: 25vh; +} +#tableMain tbody tr td.access_level, #tableMain thead tr th.access_level { + width: 7vh; + min-width: 7vh; +} +#tableMain tbody tr td.active, #tableMain thead tr th.active { + width: 5vh; + min-width: 5vh; +} +/* +nips +*/ /* .row-new { @@ -26,15 +61,15 @@ td.active, th.active { */ textarea { - width: 95% !important; + width: 95%; } select { - width: 100% !important; + width: 100%; } input { - width: 90% !important; + width: 90%; } td > input, td > select, td > textarea, .container-input > input, .container-input > select, .container-input > textarea { diff --git a/static/css/pages/store/product_permutations.css b/static/css/pages/store/product_permutations.css index d7ef8140..8a5e45a4 100644 --- a/static/css/pages/store/product_permutations.css +++ b/static/css/pages/store/product_permutations.css @@ -1,28 +1,110 @@ +#formFilters { + width: 50vh; +} + +#formFilters .container { + max-width: fit-content; +} + -td.category, th.category { - width: 16% !important; +#tableMain { + max-width: 90vw; } -td.product, th.product { - width: 23% !important; +#tableMain thead tr th.category, #tableMain tbody tr td.category { + width: 8vh; + min-width: 8vh; } -td.variations, th.variations { - width: 19% !important; +#tableMain thead tr th.product, #tableMain tbody tr td.product { + width: 10vh; + min-width: 10vh; } -td.quantity-stock, th.quantity-stock { - width: 10% !important; +#tableMain thead tr th.product_variations.collapsed, #tableMain tbody tr td.product_variations.collapsed { + width: 10vh; + min-width: 10vh; + display: table-cell !important; } -td.quantity-min, th.quantity-min { - width: 10% !important; +#tableMain thead tr th.product_variations, #tableMain tbody tr td.product_variations { + width: 20vh; + min-width: 20vh; } -td.quantity-max, th.quantity-max { - width: 10% !important; +#tableMain tbody tr td.product_variations table thead tr th, #tableMain tbody tr td.product_variations table tbody tr td { + width: 8vh; + min-width: 8vh; } -td.cost-local-VAT-incl, th.cost-local-VAT-incl { - width: 6% !important; +#tableMain tbody tr td.product_variations table thead tr th:last-of-type, #tableMain tbody tr td.product_variations table tbody tr td:last-of-type { + width: 4vh; + min-width: 4vh; } -td.detail, th.detail { - width: 6% !important; +#tableMain thead tr th.description, #tableMain tbody tr td.description { +} +#tableMain thead tr th.quantity_stock, #tableMain tbody tr td.quantity_stock { + width: 6vh; + min-width: 6vh; +} +#tableMain thead tr th.quantity_min, #tableMain tbody tr td.quantity_min { + width: 6vh; + min-width: 6vh; +} +#tableMain thead tr th.quantity_max, #tableMain tbody tr td.quantity_max { + width: 6vh; + min-width: 6vh; +} +#tableMain thead tr th.count_unit_measurement_per_quantity_step, #tableMain tbody tr td.count_unit_measurement_per_quantity_step { + width: 6vh; + min-width: 6vh; +} +#tableMain thead tr th.id_unit_measurement_quantity, #tableMain tbody tr td.id_unit_measurement_quantity { + width: 8vh; + min-width: 8vh; +} +#tableMain thead tr th.is_subscription, #tableMain tbody tr td.is_subscription { + width: 9vh; + min-width: 9vh; +} +#tableMain thead tr th.count_interval_recurrence, #tableMain tbody tr td.count_interval_recurrence { + width: 8vh; + min-width: 8vh; +} +#tableMain thead tr th.id_unit_measurement_interval_recurrence, #tableMain tbody tr td.id_unit_measurement_interval_recurrence { + width: 8vh; + min-width: 8vh; +} +#tableMain thead tr th.id_stripe_product, #tableMain tbody tr td.id_stripe_product { + width: 10vh; + min-width: 10vh; +} +#tableMain thead tr th.does_expire_faster_once_unsealed, #tableMain tbody tr td.does_expire_faster_once_unsealed { + width: 7vh; + min-width: 7vh; +} +#tableMain thead tr th.count_interval_expiration_unsealed, #tableMain tbody tr td.count_interval_expiration_unsealed { + width: 8vh; + min-width: 8vh; +} +#tableMain thead tr th.id_unit_measurement_interval_expiration_unsealed, #tableMain tbody tr td.id_unit_measurement_interval_expiration_unsealed { + width: 8vh; + min-width: 8vh; +} +#tableMain thead tr th.cost_local, #tableMain tbody tr td.cost_local { + width: 9vh; + min-width: 9vh; +} +#tableMain thead tr th.id_currency_cost, #tableMain tbody tr td.id_currency_cost { + width: 6vh; + min-width: 6vh; +} +#tableMain thead tr th.profit_local_min, #tableMain tbody tr td.profit_local_min { + width: 9vh; + min-width: 9vh; +} +#tableMain thead tr th.latency_manufacture_days, #tableMain tbody tr td.latency_manufacture_days { + width: 9vh; + min-width: 9vh; +} +#tableMain thead tr th.active, #tableMain tbody tr td.active { + width: 6vh; + min-width: 6vh; } textarea { diff --git a/static/css/sections/store.css b/static/css/sections/store.css index 11a7d43d..2b9096a2 100644 --- a/static/css/sections/store.css +++ b/static/css/sections/store.css @@ -1,3 +1,4 @@ + .img-product { max-width: 20vh; max-height: 20vh; @@ -12,7 +13,7 @@ justify-self: left; } -.buttonAdd2Basket { +.buttonAddToBasket { background-color: var(--c_blue_pastel); color: var(--c_blue_dark); border-color: var(--c_blue_dark); diff --git a/static/dist/css/416.bundle.css b/static/dist/css/416.bundle.css new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/static/dist/css/416.bundle.css @@ -0,0 +1 @@ + diff --git a/static/dist/css/core_home.bundle.css b/static/dist/css/core_home.bundle.css index 281052e4..b80d8192 100644 --- a/static/dist/css/core_home.bundle.css +++ b/static/dist/css/core_home.bundle.css @@ -1,4 +1,7 @@ +#pageBody > * > * { + width: 100%; +} #pageBody > * { height: 100%; } diff --git a/static/dist/css/main.bundle.css b/static/dist/css/main.bundle.css index 7cebe8d8..c229ab4c 100644 --- a/static/dist/css/main.bundle.css +++ b/static/dist/css/main.bundle.css @@ -1,75 +1,5 @@ - - - - - - - - - - -#overlayConfirm { - position: absolute; - left: 25vw; - width: 50vw; - height: 50vh; -} -.img-product { - max-width: 20vh; - max-height: 20vh; - border-radius: 3vh; - justify-self: left; -} - -.img-thumbnail { - max-width: 10vh; - max-height: 10vh; - border-radius: 3vh; - justify-self: left; -} - -.buttonAdd2Basket { - background-color: var(--c_blue_pastel); - color: var(--c_blue_dark); - border-color: var(--c_blue_dark); -} - -#buttonCheckout, .buttonBuyNow { - background-color: var(--c_purple_pastel); - color: var(--c_purple_dark); - border-color: var(--c_purple_dark); -} - -.button-increment, .button-decrement { - border: 2px solid darkgrey; - background-color: lightgray; - margin: 1vh 1vh; - width: 2.5vh; - height: 2.5vh; - border-radius: 1.25vh; - font-size: 2vh; -} - -.container-input > input { - padding: 0vh 1vh; - border-radius: 0.5vh; - max-width: 7vh; -} - -#basket { - max-width: 100%; -} - - - -/* Right column */ -.rightcolumn { - min-width: fit-content; -} - -/* /* Base styles * @import 'lib/reset.css'; @import 'lib/typography.css'; @@ -79,6 +9,7 @@ /* Layout styles * @import 'layouts/header.css'; @import 'layouts/footer.css'; +@import 'layouts/table-main.css'; /* Component styles * @import 'components/button.css'; @@ -91,6 +22,7 @@ /* Section styles * @import 'sections/store.css'; +*/ /* Page-specific styles * @import 'pages/page_admin.css'; @@ -101,15 +33,14 @@ @import 'pages/page_store_home.css'; @import 'pages/page_store_product_permutations.css'; @import 'pages/page_store_stock_items.css'; -* +*/ /* Theme styles * @import 'themes/light.css'; -/* Uncomment the line below to enable dark theme * -/* @import 'themes/dark.css'; * +/* Uncomment the line below to enable dark theme */ +/* @import 'themes/dark.css'; */ -*/ /* Custom styles */ /* Add any custom styles or overrides here */ @@ -304,10 +235,9 @@ h5 { text-align: center; width: 100%; align-self: center; - font-size: min(20px, calc(1vh * 6)); + font-size: min(16px, calc(1vh * 4)); } #pageBody > * > * { - width: 100%; align-self: center; padding-top: 1vh; padding-bottom: 1vh; @@ -444,6 +374,7 @@ img.header-logo { display: flex; flex-direction: column; align-items: center; + margin: auto 0; } .row { @@ -591,10 +522,10 @@ button:hover, input[type="submit"]:hover, #overlayHamburger .row *:hover { z-index: 999; } .overlay.expanded { - display: block !important; + display: block; } .collapsed { - display: none !important; + display: none; } #overlayHamburger { @@ -663,8 +594,21 @@ td.dirty { /* Tables */ #pageBody > *, button { - font-size: min(14px, calc(1vh * 5)) !important; + font-size: min(12px, calc(1vh * 3)); } + + + + + + +#overlayConfirm { + position: absolute; + left: 25vw; + width: 50vw; + height: 50vh; +} + thead, tbody { padding-top: 0px !important; padding-bottom: 0px !important; @@ -674,7 +618,7 @@ th { } td { - font-size: min(14px, calc(1vh * 5)); + font-size: min(12px, calc(1vh * 3)); } th, td { @@ -700,3 +644,83 @@ tr { } */ + + +button.collapsed { + display: block; + opacity: 0; +} + +form.filter button.save, form.filter button.button-cancel { + margin-top: 0; + margin-bottom: 0; +} +form.filter button.save, form.filter button.button-cancel { + margin-top: 0; + margin-bottom: 0; +} + +#tableMain { + overflow-x: auto; + padding: 1vh 2vh; + max-width: min(calc(1vh * 80), calc(1vw * 90)); + width: fit-content; + margin: 1vh 2vh; + align-items: normal; + justify-content: normal; +} + +#tableMain thead tr th, #tableMain tbody tr td { + width: 20vh; + min-width: 20vh; + padding: 0 0.5vh; +} + + + + +:root { + --background-color: #ffffff; + --text-color: #333333; + --primary-color: #007bff; + --secondary-color: #6c757d; + --success-color: #28a745; + --danger-color: #dc3545; + --warning-color: #ffc107; + --info-color: #17a2b8; + --light-color: #f8f9fa; + --dark-color: #343a40; + --border-color: #dee2e6; + --shadow-color: rgba(0, 0, 0, 0.1); + + /* Header */ + --header-bg: #f8f9fa; + --header-text: #333333; + + /* Footer */ + --footer-bg: #f8f9fa; + --footer-text: #6c757d; + + /* Navigation */ + --nav-bg: #ffffff; + --nav-text: #333333; + --nav-hover-bg: #f1f3f5; + --nav-hover-text: #007bff; + + /* Buttons */ + --Button-primary-bg: #007bff; + --Button-primary-text: #ffffff; + --Button-secondary-bg: #6c757d; + --Button-secondary-text: #ffffff; + + /* Forms */ + --input-bg: #ffffff; + --input-border: #ced4da; + --input-text: #495057; + --input-focus-border: #80bdff; + + /* Cards */ + --card-bg: #ffffff; + --card-border: #dee2e6; + --card-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); +} diff --git a/static/dist/css/main.css b/static/dist/css/main.css index 7cebe8d8..c2b1ad45 100644 --- a/static/dist/css/main.css +++ b/static/dist/css/main.css @@ -30,7 +30,7 @@ justify-self: left; } -.buttonAdd2Basket { +.buttonAddToBasket { background-color: var(--c_blue_pastel); color: var(--c_blue_dark); border-color: var(--c_blue_dark); diff --git a/static/dist/css/store_home.bundle.css b/static/dist/css/store_home.bundle.css index 8b137891..1ca221b1 100644 --- a/static/dist/css/store_home.bundle.css +++ b/static/dist/css/store_home.bundle.css @@ -1 +1,54 @@ +.img-product { + max-width: 20vh; + max-height: 20vh; + border-radius: 3vh; + justify-self: left; +} + +.img-thumbnail { + max-width: 10vh; + max-height: 10vh; + border-radius: 3vh; + justify-self: left; +} + +.buttonAddToBasket { + background-color: var(--c_blue_pastel); + color: var(--c_blue_dark); + border-color: var(--c_blue_dark); +} + +#buttonCheckout, .buttonBuyNow { + background-color: var(--c_purple_pastel); + color: var(--c_purple_dark); + border-color: var(--c_purple_dark); +} + +.button-increment, .button-decrement { + border: 2px solid darkgrey; + background-color: lightgray; + margin: 1vh 1vh; + width: 2.5vh; + height: 2.5vh; + border-radius: 1.25vh; + font-size: 2vh; +} + +.container-input > input { + padding: 0vh 1vh; + border-radius: 0.5vh; + max-width: 7vh; +} + +#basket { + max-width: 100%; +} + + + +/* Right column */ +.rightcolumn { + min-width: fit-content; +} + diff --git a/static/dist/css/store_product_categories.bundle.css b/static/dist/css/store_product_categories.bundle.css index 619f1e43..e4d4fbd0 100644 --- a/static/dist/css/store_product_categories.bundle.css +++ b/static/dist/css/store_product_categories.bundle.css @@ -1,23 +1,111 @@ +.img-product { + max-width: 20vh; + max-height: 20vh; + border-radius: 3vh; + justify-self: left; +} + +.img-thumbnail { + max-width: 10vh; + max-height: 10vh; + border-radius: 3vh; + justify-self: left; +} + +.buttonAddToBasket { + background-color: var(--c_blue_pastel); + color: var(--c_blue_dark); + border-color: var(--c_blue_dark); +} + +#buttonCheckout, .buttonBuyNow { + background-color: var(--c_purple_pastel); + color: var(--c_purple_dark); + border-color: var(--c_purple_dark); +} + +.button-increment, .button-decrement { + border: 2px solid darkgrey; + background-color: lightgray; + margin: 1vh 1vh; + width: 2.5vh; + height: 2.5vh; + border-radius: 1.25vh; + font-size: 2vh; +} + +.container-input > input { + padding: 0vh 1vh; + border-radius: 0.5vh; + max-width: 7vh; +} + +#basket { + max-width: 100%; +} + -td.display-order, th.display-order { - width: 8% !important; + +/* Right column */ +.rightcolumn { + min-width: fit-content; } -td.code, th.code { - width: 15% !important; + +#formFilters { + width: 50vh; } -td.name, th.name { - width: 25% !important; + +#formFilters .container { + max-width: fit-content; } -td.description, th.description { - width: 35% !important; + +#formFilters .container-input.filter.is_not_empty { + width: 10vh; +} + +#formFilters .container-input.filter.active { + width: 8vh; } -td.access_level, th.access_level { - width: 10% !important; + +#tableMain { + max-width: min(calc(1vh * 79), calc(1vw * 90)); } -td.active, th.active { - width: 7% !important; + +/* +#tableMain thead tr th, #tableMain tbody tr td { + margin-left: 1vh; + margin-right: 1vh; } +*/ + +#tableMain tbody tr td.display_order, #tableMain thead tr th.display_order { + width: 5vh; + min-width: 5vh; +} +#tableMain tbody tr td.code, #tableMain thead tr th.code { + width: 10vh; + min-width: 10vh; +} +#tableMain tbody tr td.name, #tableMain thead tr th.name { + width: 15vh; + min-width: 15vh; +} +#tableMain tbody tr td.description, #tableMain thead tr th.description { + width: 25vh; + min-width: 25vh; +} +#tableMain tbody tr td.access_level, #tableMain thead tr th.access_level { + width: 7vh; + min-width: 7vh; +} +#tableMain tbody tr td.active, #tableMain thead tr th.active { + width: 5vh; + min-width: 5vh; +} +/* +nips +*/ /* .row-new { @@ -26,15 +114,15 @@ td.active, th.active { */ textarea { - width: 95% !important; + width: 95%; } select { - width: 100% !important; + width: 100%; } input { - width: 90% !important; + width: 90%; } td > input, td > select, td > textarea, .container-input > input, .container-input > select, .container-input > textarea { diff --git a/static/dist/css/store_product_permutations.bundle.css b/static/dist/css/store_product_permutations.bundle.css index 5fa4f30c..f5aac066 100644 --- a/static/dist/css/store_product_permutations.bundle.css +++ b/static/dist/css/store_product_permutations.bundle.css @@ -1,28 +1,163 @@ +.img-product { + max-width: 20vh; + max-height: 20vh; + border-radius: 3vh; + justify-self: left; +} + +.img-thumbnail { + max-width: 10vh; + max-height: 10vh; + border-radius: 3vh; + justify-self: left; +} + +.buttonAddToBasket { + background-color: var(--c_blue_pastel); + color: var(--c_blue_dark); + border-color: var(--c_blue_dark); +} + +#buttonCheckout, .buttonBuyNow { + background-color: var(--c_purple_pastel); + color: var(--c_purple_dark); + border-color: var(--c_purple_dark); +} + +.button-increment, .button-decrement { + border: 2px solid darkgrey; + background-color: lightgray; + margin: 1vh 1vh; + width: 2.5vh; + height: 2.5vh; + border-radius: 1.25vh; + font-size: 2vh; +} + +.container-input > input { + padding: 0vh 1vh; + border-radius: 0.5vh; + max-width: 7vh; +} + +#basket { + max-width: 100%; +} + -td.category, th.category { - width: 16% !important; + +/* Right column */ +.rightcolumn { + min-width: fit-content; } -td.product, th.product { - width: 23% !important; + +#formFilters { + width: 50vh; } -td.variations, th.variations { - width: 19% !important; + +#formFilters .container { + max-width: fit-content; } -td.quantity-stock, th.quantity-stock { - width: 10% !important; + + +#tableMain { + max-width: 90vw; } -td.quantity-min, th.quantity-min { - width: 10% !important; +#tableMain thead tr th.category, #tableMain tbody tr td.category { + width: 8vh; + min-width: 8vh; } -td.quantity-max, th.quantity-max { - width: 10% !important; +#tableMain thead tr th.product, #tableMain tbody tr td.product { + width: 10vh; + min-width: 10vh; } -td.cost-local-VAT-incl, th.cost-local-VAT-incl { - width: 6% !important; +#tableMain thead tr th.product_variations.collapsed, #tableMain tbody tr td.product_variations.collapsed { + width: 10vh; + min-width: 10vh; + display: table-cell !important; } -td.detail, th.detail { - width: 6% !important; +#tableMain thead tr th.product_variations, #tableMain tbody tr td.product_variations { + width: 20vh; + min-width: 20vh; +} +#tableMain tbody tr td.product_variations table thead tr th, #tableMain tbody tr td.product_variations table tbody tr td { + width: 8vh; + min-width: 8vh; +} +#tableMain tbody tr td.product_variations table thead tr th:last-of-type, #tableMain tbody tr td.product_variations table tbody tr td:last-of-type { + width: 4vh; + min-width: 4vh; +} +#tableMain thead tr th.description, #tableMain tbody tr td.description { +} +#tableMain thead tr th.quantity_stock, #tableMain tbody tr td.quantity_stock { + width: 6vh; + min-width: 6vh; +} +#tableMain thead tr th.quantity_min, #tableMain tbody tr td.quantity_min { + width: 6vh; + min-width: 6vh; +} +#tableMain thead tr th.quantity_max, #tableMain tbody tr td.quantity_max { + width: 6vh; + min-width: 6vh; +} +#tableMain thead tr th.count_unit_measurement_per_quantity_step, #tableMain tbody tr td.count_unit_measurement_per_quantity_step { + width: 6vh; + min-width: 6vh; +} +#tableMain thead tr th.id_unit_measurement_quantity, #tableMain tbody tr td.id_unit_measurement_quantity { + width: 8vh; + min-width: 8vh; +} +#tableMain thead tr th.is_subscription, #tableMain tbody tr td.is_subscription { + width: 9vh; + min-width: 9vh; +} +#tableMain thead tr th.count_interval_recurrence, #tableMain tbody tr td.count_interval_recurrence { + width: 8vh; + min-width: 8vh; +} +#tableMain thead tr th.id_unit_measurement_interval_recurrence, #tableMain tbody tr td.id_unit_measurement_interval_recurrence { + width: 8vh; + min-width: 8vh; +} +#tableMain thead tr th.id_stripe_product, #tableMain tbody tr td.id_stripe_product { + width: 10vh; + min-width: 10vh; +} +#tableMain thead tr th.does_expire_faster_once_unsealed, #tableMain tbody tr td.does_expire_faster_once_unsealed { + width: 7vh; + min-width: 7vh; +} +#tableMain thead tr th.count_interval_expiration_unsealed, #tableMain tbody tr td.count_interval_expiration_unsealed { + width: 8vh; + min-width: 8vh; +} +#tableMain thead tr th.id_unit_measurement_interval_expiration_unsealed, #tableMain tbody tr td.id_unit_measurement_interval_expiration_unsealed { + width: 8vh; + min-width: 8vh; +} +#tableMain thead tr th.cost_local, #tableMain tbody tr td.cost_local { + width: 9vh; + min-width: 9vh; +} +#tableMain thead tr th.id_currency_cost, #tableMain tbody tr td.id_currency_cost { + width: 6vh; + min-width: 6vh; +} +#tableMain thead tr th.profit_local_min, #tableMain tbody tr td.profit_local_min { + width: 9vh; + min-width: 9vh; +} +#tableMain thead tr th.latency_manufacture_days, #tableMain tbody tr td.latency_manufacture_days { + width: 9vh; + min-width: 9vh; +} +#tableMain thead tr th.active, #tableMain tbody tr td.active { + width: 6vh; + min-width: 6vh; } textarea { diff --git a/static/dist/css/store_stock_items.bundle.css b/static/dist/css/store_stock_items.bundle.css index d9dbd18a..99a06b67 100644 --- a/static/dist/css/store_stock_items.bundle.css +++ b/static/dist/css/store_stock_items.bundle.css @@ -1,4 +1,57 @@ +.img-product { + max-width: 20vh; + max-height: 20vh; + border-radius: 3vh; + justify-self: left; +} + +.img-thumbnail { + max-width: 10vh; + max-height: 10vh; + border-radius: 3vh; + justify-self: left; +} + +.buttonAddToBasket { + background-color: var(--c_blue_pastel); + color: var(--c_blue_dark); + border-color: var(--c_blue_dark); +} + +#buttonCheckout, .buttonBuyNow { + background-color: var(--c_purple_pastel); + color: var(--c_purple_dark); + border-color: var(--c_purple_dark); +} + +.button-increment, .button-decrement { + border: 2px solid darkgrey; + background-color: lightgray; + margin: 1vh 1vh; + width: 2.5vh; + height: 2.5vh; + border-radius: 1.25vh; + font-size: 2vh; +} + +.container-input > input { + padding: 0vh 1vh; + border-radius: 0.5vh; + max-width: 7vh; +} + +#basket { + max-width: 100%; +} + + + +/* Right column */ +.rightcolumn { + min-width: fit-content; +} + th, td { min-width: fit-content; } diff --git a/static/dist/js/legal_accessibility_statement.bundle.js b/static/dist/js/legal_accessibility_statement.bundle.js index 30747bf4..7e20a39a 100644 --- a/static/dist/js/legal_accessibility_statement.bundle.js +++ b/static/dist/js/legal_accessibility_statement.bundle.js @@ -1 +1 @@ -(()=>{"use strict";var r,e={780:()=>{},711:()=>{}},o={};function t(r){var a=o[r];if(void 0!==a)return a.exports;var n=o[r]={exports:{}};return e[r](n,n.exports,t),n.exports}t.m=e,r=[],t.O=(e,o,a,n)=>{if(!o){var i=1/0;for(f=0;f=n)&&Object.keys(t.O).every((r=>t.O[r](o[v])))?o.splice(v--,1):(p=!1,n0&&r[f-1][2]>n;f--)r[f]=r[f-1];r[f]=[o,a,n]},t.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),(()=>{var r={841:0,466:0};t.O.j=e=>0===r[e];var e=(e,o)=>{var a,n,[i,p,v]=o,s=0;if(i.some((e=>0!==r[e]))){for(a in p)t.o(p,a)&&(t.m[a]=p[a]);if(v)var f=v(t)}for(e&&e(o);st(711)));var a=t.O(void 0,[466],(()=>t(780)));a=t.O(a)})(); \ No newline at end of file +(()=>{"use strict";var r,e={780:()=>{},359:()=>{}},o={};function t(r){var a=o[r];if(void 0!==a)return a.exports;var n=o[r]={exports:{}};return e[r](n,n.exports,t),n.exports}t.m=e,r=[],t.O=(e,o,a,n)=>{if(!o){var i=1/0;for(f=0;f=n)&&Object.keys(t.O).every((r=>t.O[r](o[v])))?o.splice(v--,1):(p=!1,n0&&r[f-1][2]>n;f--)r[f]=r[f-1];r[f]=[o,a,n]},t.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),(()=>{var r={841:0,416:0};t.O.j=e=>0===r[e];var e=(e,o)=>{var a,n,[i,p,v]=o,s=0;if(i.some((e=>0!==r[e]))){for(a in p)t.o(p,a)&&(t.m[a]=p[a]);if(v)var f=v(t)}for(e&&e(o);st(359)));var a=t.O(void 0,[416],(()=>t(780)));a=t.O(a)})(); \ No newline at end of file diff --git a/static/dist/js/legal_license.bundle.js b/static/dist/js/legal_license.bundle.js index 69452ac8..3ace2e9c 100644 --- a/static/dist/js/legal_license.bundle.js +++ b/static/dist/js/legal_license.bundle.js @@ -1 +1 @@ -(()=>{"use strict";var r,e={623:()=>{},711:()=>{}},o={};function t(r){var a=o[r];if(void 0!==a)return a.exports;var n=o[r]={exports:{}};return e[r](n,n.exports,t),n.exports}t.m=e,r=[],t.O=(e,o,a,n)=>{if(!o){var i=1/0;for(f=0;f=n)&&Object.keys(t.O).every((r=>t.O[r](o[v])))?o.splice(v--,1):(p=!1,n0&&r[f-1][2]>n;f--)r[f]=r[f-1];r[f]=[o,a,n]},t.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),(()=>{var r={690:0,466:0};t.O.j=e=>0===r[e];var e=(e,o)=>{var a,n,[i,p,v]=o,s=0;if(i.some((e=>0!==r[e]))){for(a in p)t.o(p,a)&&(t.m[a]=p[a]);if(v)var f=v(t)}for(e&&e(o);st(711)));var a=t.O(void 0,[466],(()=>t(623)));a=t.O(a)})(); \ No newline at end of file +(()=>{"use strict";var r,e={623:()=>{},359:()=>{}},o={};function t(r){var a=o[r];if(void 0!==a)return a.exports;var n=o[r]={exports:{}};return e[r](n,n.exports,t),n.exports}t.m=e,r=[],t.O=(e,o,a,n)=>{if(!o){var i=1/0;for(f=0;f=n)&&Object.keys(t.O).every((r=>t.O[r](o[v])))?o.splice(v--,1):(p=!1,n0&&r[f-1][2]>n;f--)r[f]=r[f-1];r[f]=[o,a,n]},t.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),(()=>{var r={690:0,416:0};t.O.j=e=>0===r[e];var e=(e,o)=>{var a,n,[i,p,v]=o,s=0;if(i.some((e=>0!==r[e]))){for(a in p)t.o(p,a)&&(t.m[a]=p[a]);if(v)var f=v(t)}for(e&&e(o);st(359)));var a=t.O(void 0,[416],(()=>t(623)));a=t.O(a)})(); \ No newline at end of file diff --git a/static/dist/js/legal_privacy_policy.bundle.js b/static/dist/js/legal_privacy_policy.bundle.js index 092566b3..a1769ac5 100644 --- a/static/dist/js/legal_privacy_policy.bundle.js +++ b/static/dist/js/legal_privacy_policy.bundle.js @@ -1 +1 @@ -(()=>{"use strict";var r,e={713:()=>{},711:()=>{}},o={};function t(r){var a=o[r];if(void 0!==a)return a.exports;var n=o[r]={exports:{}};return e[r](n,n.exports,t),n.exports}t.m=e,r=[],t.O=(e,o,a,n)=>{if(!o){var i=1/0;for(f=0;f=n)&&Object.keys(t.O).every((r=>t.O[r](o[v])))?o.splice(v--,1):(p=!1,n0&&r[f-1][2]>n;f--)r[f]=r[f-1];r[f]=[o,a,n]},t.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),(()=>{var r={364:0,466:0};t.O.j=e=>0===r[e];var e=(e,o)=>{var a,n,[i,p,v]=o,s=0;if(i.some((e=>0!==r[e]))){for(a in p)t.o(p,a)&&(t.m[a]=p[a]);if(v)var f=v(t)}for(e&&e(o);st(711)));var a=t.O(void 0,[466],(()=>t(713)));a=t.O(a)})(); \ No newline at end of file +(()=>{"use strict";var r,e={713:()=>{},359:()=>{}},o={};function t(r){var a=o[r];if(void 0!==a)return a.exports;var n=o[r]={exports:{}};return e[r](n,n.exports,t),n.exports}t.m=e,r=[],t.O=(e,o,a,n)=>{if(!o){var i=1/0;for(f=0;f=n)&&Object.keys(t.O).every((r=>t.O[r](o[v])))?o.splice(v--,1):(p=!1,n0&&r[f-1][2]>n;f--)r[f]=r[f-1];r[f]=[o,a,n]},t.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),(()=>{var r={364:0,416:0};t.O.j=e=>0===r[e];var e=(e,o)=>{var a,n,[i,p,v]=o,s=0;if(i.some((e=>0!==r[e]))){for(a in p)t.o(p,a)&&(t.m[a]=p[a]);if(v)var f=v(t)}for(e&&e(o);st(359)));var a=t.O(void 0,[416],(()=>t(713)));a=t.O(a)})(); \ No newline at end of file diff --git a/static/dist/js/legal_retention_schedule.bundle.js b/static/dist/js/legal_retention_schedule.bundle.js index dd7b5194..db92da46 100644 --- a/static/dist/js/legal_retention_schedule.bundle.js +++ b/static/dist/js/legal_retention_schedule.bundle.js @@ -1 +1 @@ -(()=>{"use strict";var r,e={930:()=>{},711:()=>{}},o={};function t(r){var a=o[r];if(void 0!==a)return a.exports;var n=o[r]={exports:{}};return e[r](n,n.exports,t),n.exports}t.m=e,r=[],t.O=(e,o,a,n)=>{if(!o){var i=1/0;for(f=0;f=n)&&Object.keys(t.O).every((r=>t.O[r](o[v])))?o.splice(v--,1):(p=!1,n0&&r[f-1][2]>n;f--)r[f]=r[f-1];r[f]=[o,a,n]},t.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),(()=>{var r={607:0,466:0};t.O.j=e=>0===r[e];var e=(e,o)=>{var a,n,[i,p,v]=o,s=0;if(i.some((e=>0!==r[e]))){for(a in p)t.o(p,a)&&(t.m[a]=p[a]);if(v)var f=v(t)}for(e&&e(o);st(711)));var a=t.O(void 0,[466],(()=>t(930)));a=t.O(a)})(); \ No newline at end of file +(()=>{"use strict";var r,e={930:()=>{},359:()=>{}},o={};function t(r){var a=o[r];if(void 0!==a)return a.exports;var n=o[r]={exports:{}};return e[r](n,n.exports,t),n.exports}t.m=e,r=[],t.O=(e,o,a,n)=>{if(!o){var i=1/0;for(f=0;f=n)&&Object.keys(t.O).every((r=>t.O[r](o[v])))?o.splice(v--,1):(p=!1,n0&&r[f-1][2]>n;f--)r[f]=r[f-1];r[f]=[o,a,n]},t.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),(()=>{var r={607:0,416:0};t.O.j=e=>0===r[e];var e=(e,o)=>{var a,n,[i,p,v]=o,s=0;if(i.some((e=>0!==r[e]))){for(a in p)t.o(p,a)&&(t.m[a]=p[a]);if(v)var f=v(t)}for(e&&e(o);st(359)));var a=t.O(void 0,[416],(()=>t(930)));a=t.O(a)})(); \ No newline at end of file diff --git a/static/dist/js/main.bundle.js b/static/dist/js/main.bundle.js index f99376f3..7fb44013 100644 --- a/static/dist/js/main.bundle.js +++ b/static/dist/js/main.bundle.js @@ -1,2 +1,2 @@ /*! For license information please see main.bundle.js.LICENSE.txt */ -(()=>{"use strict";(()=>{function e(t){return e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e(t)}function t(e,t){for(var n=0;n0)if(r)t=!1;else if("string"!=typeof e[0])t=!1;else for(var n=0;n0)}},{key:"getDataContentType",value:function(t){var r=null,n="";return e.isEmpty(t)||("string"==typeof t?(r=t,n="application/x-www-form-urlencoded; charset=UTF-8"):(r=JSON.stringify(t),n="application/json; charset=UTF-8")),{Data:r,ContentType:n}}},{key:"arrayContainsItem",value:function(t,r){var n=!1;if(!e.isEmpty(t)&&!e.isEmpty(r))if(t[0]instanceof jQuery){for(var o=0;o=0;--i){var a=this.tryEntries[i],l=a.completion;if("root"===a.tryLoc)return o("end");if(a.tryLoc<=this.prev){var u=n.call(a,"catchLoc"),c=n.call(a,"finallyLoc");if(u&&c){if(this.prev=0;--r){var o=this.tryEntries[r];if(o.tryLoc<=this.prev&&n.call(o,"finallyLoc")&&this.prev=0;--t){var r=this.tryEntries[t];if(r.finallyLoc===e)return this.complete(r.completion,r.afterLoc),A(r),m}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var r=this.tryEntries[t];if(r.tryLoc===e){var n=r.completion;if("throw"===n.type){var o=n.arg;A(r)}return o}}throw Error("illegal catch attempt")},delegateYield:function(t,r,n){return this.delegate={iterator:D(t),resultName:r,nextLoc:n},"next"===this.method&&(this.arg=e),m}},t}function m(e,t,r,n,o,i,a){try{var l=e[i](a),u=l.value}catch(e){return void r(e)}l.done?t(u):Promise.resolve(u).then(n,o)}function b(e){return function(){var t=this,r=arguments;return new Promise((function(n,o){var i=e.apply(t,r);function a(e){m(i,n,o,a,l,"next",e)}function l(e){m(i,n,o,a,l,"throw",e)}a(void 0)}))}}function S(e,t){for(var r=0;r1&&void 0!==c[1]?c[1]:"GET",o=c.length>2&&void 0!==c[2]?c[2]:null,i=c.length>3&&void 0!==c[3]?c[3]:null,a=e.getUrlFromHash(r,i),l={method:n,headers:{"Content-Type":"application/json","X-CSRFToken":e.getCsrfToken()}},!o||"POST"!==n&&"PUT"!==n&&"PATCH"!==n||(l.body=JSON.stringify(o)),console.log("API request:",n,a,o),t.prev=7,t.next=10,fetch(a,l);case 10:if((u=t.sent).ok){t.next=13;break}throw new Error("HTTP error! status: ".concat(u.status));case 13:return t.next=15,u.json();case 15:return t.abrupt("return",t.sent);case 18:throw t.prev=18,t.t0=t.catch(7),console.error("API request failed:",t.t0),t.t0;case 22:case"end":return t.stop()}}),t,null,[[7,18]])}))),function(e){return u.apply(this,arguments)})},{key:"getUrlFromHash",value:function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;null==t&&(t=hashPageHome),console.log("getUrlFromHash:"),console.log("base url: "+_pathHost+"\nhash: "+t+"\nparams: "+r);var n=e.parameteriseUrl(_pathHost+t,r);return console.log("url: "+n),n}},{key:"parameteriseUrl",value:function(e,t){return t&&(e+="?"+new URLSearchParams(t).toString()),e}},{key:"goToUrl",value:function(e){window.location.href=e}},{key:"goToHash",value:function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=e.getUrlFromHash(t,r);e.goToUrl(n)}},{key:"loginUser",value:(a=b(g().mark((function t(){var r;return g().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return(r={})[keyCallback]=l.getHashPageCurrent(),t.next=4,e.request(hashPageUserLogin,"POST",r);case 4:return t.abrupt("return",t.sent);case 5:case"end":return t.stop()}}),t)}))),function(){return a.apply(this,arguments)})},{key:"getCategories",value:(i=b(g().mark((function t(){return g().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,e.request(hashGetStoreProductCategory);case 2:return t.abrupt("return",t.sent);case 3:case"end":return t.stop()}}),t)}))),function(){return i.apply(this,arguments)})},{key:"getCategoriesByFilters",value:(o=b(g().mark((function t(r){return g().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:e.goToHash(hashPageStoreProductCategories,r);case 1:case"end":return t.stop()}}),t)}))),function(e){return o.apply(this,arguments)})},{key:"saveCategories",value:(n=b(g().mark((function t(r,n,o){var i;return g().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return(i={})[flagFormFilters]=l.convertForm2JSON(n),i[flagCategory]=r,i[flagComment]=o,t.next=6,e.request(hashSaveStoreProductCategory,"POST",i);case 6:return t.abrupt("return",t.sent);case 7:case"end":return t.stop()}}),t)}))),function(e,t,r){return n.apply(this,arguments)})}],r&&S(t,r),Object.defineProperty(t,"prototype",{writable:!1}),t;var t,r,n,o,i,a,u}();function w(e){return w="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},w(e)}function E(e,t){for(var r=0;r1&&void 0!==arguments[1]?arguments[1]:null,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;null==t&&(t=document.querySelector("form."+flagFilter+" button."+flagSave)),null==r&&(r=document.querySelector("form."+flagFilter+" button."+flagCancel)),e?(r.classList.remove(flagCollapsed),t.classList.remove(flagCollapsed)):(r.classList.add(flagCollapsed),t.classList.add(flagCollapsed))}}],n=[{key:"isDirtyFilter",value:function(e){var t=l.isElementDirty(e);return t&&document.querySelectorAll(idTableMain+" tbody tr").remove(),t}}],r&&E(t.prototype,r),n&&E(t,n),Object.defineProperty(t,"prototype",{writable:!1}),t;var t,r,n}();function L(e){return L="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},L(e)}function j(e,t){for(var r=0;r at "+r[keyPostcode]+"",document.querySelectorAll(idOverlayInfoBilling).css("display","none"),document.querySelectorAll(idOverlayInfoBilling).querySelector("form").classList.add(flagSubmitted)}else document.querySelectorAll(idContainerInfoDelivery).querySelector("div").innerHTML=""+r[keyNameFull]+" at "+r[keyPostcode]+"",document.querySelectorAll(idOverlayInfoDelivery).css("display","none"),document.querySelectorAll(idOverlayInfoDelivery).querySelector("form").classList.add(flagSubmitted)}},{key:"convertFormBilling2JSON",value:function(e,t){var r;r=document.querySelectorAll(t).querySelector("form"),r=document.querySelectorAll(idOverlayInfoDelivery).querySelector("form"),console.log("converting billing form to json\nform ID: "+r.id),e[keyForm]=convertForm2JSON(r);var n=[keyNameFull,keyPhoneNumber,keyPostcode,keyAddress1,keyAddress2,keyCity,keyCounty];for(var o in console.log("ajaxData:"),console.log(e),e[keyForm][keyInfoIdentical]=getElementCurrentValue(r.querySelector("#"+keyInfoIdentical)),n)t==idOverlayInfoBilling&&e[keyForm][keyInfoIdentical]?e[keyForm][n[o]]=getElementCurrentValue((void 0).querySelector("#"+n[o])):e[keyForm][n[o]]=getElementCurrentValue(r.querySelector("#"+n[o]));return console.log("ajaxData:"),console.log(e),e}},{key:"hookupButtonCheckoutSession",value:function(){var e=document.querySelectorAll(idButtonCheckout);e.classList.remove(flagInitialised),f.initialiseEventHandler(idButtonCheckout,flagInitialised,(function(){e.removeEventListener("click"),e.addEventListener("click",(function(e){var t=v.getLocalStorage(keyBasket),r={};r[keyBasket]=t,r=convertFormBilling2JSON(r,idOverlayInfoDelivery),(r=convertFormBilling2JSON(r,idOverlayInfoBilling))[key_code_currency]=getCurrencySelected(),ajaxJSONData("checkout session",mapHashToController(hashPageStoreCheckout),r,handleResponseCheckout,!1)}))}))}},{key:"handleResponseCheckout",value:function(e){window.location.href=e.data[keyUrlCheckout]}},{key:"hookupButtonFormBillingCopy",value:function(){f.initialiseEventHandler(idButtonFormBillingCopy,flagInitialised,(function(){document.querySelectorAll(idButtonFormBillingCopy).addEventListener("click",(function(e){var t=[keyNameFull,keyPhoneNumber,keyPostcode,keyAddress1,keyAddress2,keyCity,keyCounty],r=document.querySelectorAll(idOverlayInfoBilling).querySelector("form"),n=document.querySelectorAll(idOverlayInfoDelivery).querySelector("form");for(var o in t)r.querySelector("#"+t[o]).value=getElementCurrentValue(n.querySelector("#"+t[o]))}))}))}},{key:"leave",value:function(){!function(e,t,r){var n=Qe(ze(e.prototype),"leave",r);return"function"==typeof n?function(e){return n.apply(r,e)}:n}(t,0,this)([])}}])}(C);function Ke(e){return Ke="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Ke(e)}function Xe(e,t){for(var r=0;r0&&void 0!==arguments[0]&&arguments[0];if(this.constructor===t)throw new Error("Must implement initialize() method.");if(r){var o=this.getLocalStoragePage()[flagFormFilters],i=this.getFormFilters(),a=l.convertForm2JSON(i);n.areEqualDicts(o,a)}else this.sharedInitialize(),this.hookupFilters(),this.hookupButtonsAddSaveCancel(),this.hookupTableMain(),hookupOverlayConfirm((function(){e.leave(),e.saveRecordsTableDirty()}))}},{key:"hookupFilters",value:function(){if(this.constructor===t)throw new Error("Subclass of TableBasePage must implement method hookupFilters().");this.hookupButtonApplyFilters()}},{key:"hookupFilterActive",value:function(){f.initialiseEventHandler(idFormFilters+"."+flagActive,flagInitialised,(function(e){e.addEventListener("change",(function(r){t.isDirtyFilter(e)}))}))}},{key:"hookupButtonApplyFilters",value:function(){var e=this;f.initialiseEventHandler(idButtonApplyFilters,flagInitialised,(function(t){t.addEventListener("click",(function(t){t.stopPropagation(),e.getAndLoadFilteredTableContent()}))}))}},{key:"getAndLoadFilteredTableContent",value:function(){var e=this.getFormFilters(),t=l.convertForm2JSON(e);this.callFilterTableContent(t).catch((function(e){return console.error("Error:",e)}))}},{key:"getFormFilters",value:function(){return document.querySelector(idFormFilters)}},{key:"callbackLoadTableContent",value:function(e){this.getTableMain().querySelector("tbody").querySelectorAll("tr").forEach((function(e){e.remove()}));var t=e.data[flagRows];!n.isEmpty(t)&&t.every((function(e){return e.hasOwnProperty("display_order")}))&&(t=t.sort((function(e,t){return e.display_order-t.display_order}))),t.forEach(this.loadRowTable.bind(this)),this.hookupTableMain()}},{key:"getTableMain",value:function(){return document.querySelector(idTableMain)}},{key:"loadRowTable",value:function(e){throw new Error("Subclass of TableBasePage must implement method loadRowTable().")}},{key:"hookupButtonsAddSaveCancel",value:function(){this.hookupButtonSave(),this.hookupButtonCancel(),this.hookupButtonAddRowTable()}},{key:"saveRecordsTableDirty",value:function(){var e=this,t=this.getTableRecords(!0);if(0!=t.length){var r=this.getFormFilters(),n=l.getElementValueCurrent(document.querySelector(idTextareaConfirm));this.callSaveTableContent(t,r,n).then((function(t){t[flagStatus]==flagSuccess?(console.log("Data received:",t),e.callbackLoadTableContent(t),console.log("Records saved!")):showOverlayError(t[flagMessage])})).catch((function(e){return console.error("Error:",e)}))}else showOverlayError("No records to save")}},{key:"getTableRecords",value:function(){var e,t=this,r=arguments.length>0&&void 0!==arguments[0]&&arguments[0],n=this.getTableMain(),o=[];return n.querySelectorAll("tbody tr").forEach((function(n){r&&!n.classList.contains(flagDirty)||(e=t.getJsonRow(n),o.push(e))})),o}},{key:"getJsonRow",value:function(e){throw new Error("Subclass of TableBasePage must implement method getJsonRow().")}},{key:"hookupButtonCancel",value:function(){f.initialiseEventHandler(idFormFilters+" button."+flagCancel,flagInitialised,(function(e){e.addEventListener("click",(function(e){e.stopPropagation(),getAndLoadFilteredTableContent()})),e.classList.add(flagCollapsed)}))}},{key:"hookupButtonAddRowTable",value:function(){var e=this;f.initialiseEventHandler(idFormFilters+" button."+flagAdd,flagInitialised,(function(t){t.addEventListener("click",(function(t){t.stopPropagation();var r=document.querySelector(idTableMain+" tbody"),n=_rowBlank.cloneNode(!0);n.classList.remove(flagInitialised),n.querySelectorAll("."+flagInitialised).forEach((function(e){e.classList.remove(flagInitialised)}));var o=parseInt(r.querySelector("tr:last-child").querySelector("td."+flagDisplayOrder+" ."+flagSlider).getAttribute(attrValueCurrent))+1;r.appendChild(n);var i=r.querySelector("tr:last-child").querySelector("td."+flagDisplayOrder+" ."+flagSlider);i&&(i.setAttribute(attrValueCurrent,o),i.setAttribute(attrValuePrevious,o)),e.hookupTableMain()}))}))}},{key:"hookupTableMain",value:function(){if(this.constructor===t)throw new Error("Must implement hookupTableMain() method.");null==_rowBlank&&this.cacheRowBlank()}},{key:"cacheRowBlank",value:function(){var e=idTableMain+" tbody tr."+flagRowNew,t=document.querySelector(e);console.log("row blank temp: ",t),_rowBlank=t.cloneNode(!0),document.querySelectorAll(e).forEach((function(e){e.remove()}))}},{key:"hookupSlidersDisplayOrderTable",value:function(){var e=this,t=idTableMain+" tbody tr td."+flagDisplayOrder+" input."+flagSlider+"."+flagDisplayOrder;f.initialiseEventHandler(t,flagInitialised,(function(t){t.addEventListener("change",(function(r){console.log("slider change event"),e.handleChangeElementCellTable(t)}))}))}},{key:"hookupTextareasCodeTable",value:function(){var e=this,t=idTableMain+" tbody tr td."+flagCode+" textarea";f.initialiseEventHandler(t,flagInitialised,(function(t){t.addEventListener("change",(function(r){console.log("textarea change event"),e.handleChangeElementCellTable(t)}))}))}},{key:"handleChangeElementCellTable",value:function(e){var t=l.getRowFromElement(e),r=l.getCellFromElement(e);console.log("td: ",r);var n=this.isDirtyRow(t),o=e.classList.contains(flagDirty),i=l.isElementDirty(e);if(console.log("isDirtyElement: ",i),console.log("wasDirtyElement: ",o),i!=o){l.handleDirtyElement(r,i);var a=this.isDirtyRow(t);if(console.log("isNowDirtyRow: ",a),console.log("wasDirtyRow: ",n),a!=n){l.handleDirtyElement(t,a);var u=this.getTableRecords(!0),c=u.length>0;console.log("dirty records:",u),console.log("existsDirtyRecord:",c),this.toggleShowButtonsSaveCancel(c)}}}},{key:"isDirtyRow",value:function(e){throw new Error("Subclass of TableBasePage must implement method isDirtyRow().")}},{key:"toggleShowButtonsSaveCancel",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;null==t&&(t=document.querySelector(idFormFilters+" button."+flagSave)),null==r&&(r=document.querySelector(idFormFilters+" button."+flagCancel)),e?(r.classList.remove(flagCollapsed),t.classList.remove(flagCollapsed)):(r.classList.add(flagCollapsed),t.classList.add(flagCollapsed))}},{key:"handleChangeSelectCellTable",value:function(e){var t=l.getRowFromElement(e),r=l.getCellFromElement(e);console.log("td: ",r);var n=this.isDirtyRow(t),o=e.classList.contains(flagDirty),i=l.isElementDirty(e);if(console.log("isDirtyElement: ",i),console.log("wasDirtyElement: ",o),i!=o){l.handleDirtyElement(r,i);var a=e.options[e.selectedIndex];r.setAttribute(attrIdAccessLevel,a.value),r.setAttribute(flagAccessLevelRequired,a.textcontent);var u=this.isDirtyRow(t);if(console.log("isNowDirtyRow: ",u),console.log("wasDirtyRow: ",n),u!=n){l.handleDirtyElement(t,u);var c=this.getTableRecords(!0),s=c.length>0;console.log("dirty records:",c),console.log("existsDirtyRecord:",s),this.toggleShowButtonsSaveCancel(s)}}}},{key:"hookupTextareasNameTable",value:function(){var e=this,t=idTableMain+" tbody tr td."+flagName+" textarea";f.initialiseEventHandler(t,flagInitialised,(function(t){t.addEventListener("change",(function(r){console.log("textarea change event"),e.handleChangeElementCellTable(t)}))}))}},{key:"hookupTextareasDescriptionTable",value:function(){var e=this,t=idTableMain+" tbody tr td."+flagDescription+" textarea";f.initialiseEventHandler(t,flagInitialised,(function(t){t.addEventListener("change",(function(r){console.log("textarea change event"),e.handleChangeElementCellTable(t)}))}))}},{key:"hookupInputsActiveTable",value:function(){var e=this,t=idTableMain+" tbody tr td."+flagActive+' input[type="checkbox"]';f.initialiseEventHandler(t,flagInitialised,(function(t){t.addEventListener("change",(function(r){console.log("input change event"),e.handleChangeElementCellTable(t)}))}))}},{key:"hookupTdsAccessLevel",value:function(){var e=this;f.initialiseEventHandler(idTableMain+" tbody td."+flagAccessLevel,flagInitialised,(function(t){t.addEventListener("click",(function(t){e.handleClickTdAccessLevel(t)}))}))}},{key:"handleClickTdAccessLevel",value:function(e){console.log("tdAccessLevel clicked"),e.stopPropagation();var t=l.getCellFromElement(e.target);console.log("tdAccessLevel: ",t);var r=l.getRowFromElement(t),n=t.querySelector("div."+flagAccessLevel).getAttribute(attrIdAccessLevel),o=document.createElement("select");o.classList.add(flagAccessLevel),o.setAttribute(attrValueCurrent,n),o.setAttribute(attrValuePrevious,n),optionsAccessLevel.forEach((function(e){var t=document.createElement("option");t.value=e.value,t.textContent=e.text,e.value==n&&(t.selected=!0),o.appendChild(t)}));var i=t.cloneNode(!0);i.innerHTML="",i.appendChild(o),r.replaceChild(i,t),this.hookupDdlsAccessLevelTable()}},{key:"hookupDdlsAccessLevelTable",value:function(){var e=this;f.initialiseEventHandler(idTableMain+" tbody select."+flagAccessLevel,flagInitialised,(function(t){t.addEventListener("change",(function(r){r.stopPropagation(),e.handleChangeDdlAccessLevelTable(t)}))}))}},{key:"handleChangeDdlAccessLevelTable",value:function(e){var t=l.getRowFromElement(e),r=l.getCellFromElement(e);console.log("td: ",r);var n=this.isDirtyRow(t),o=e.classList.contains(flagDirty),i=l.isElementDirty(e);if(console.log("isDirtyElement: ",i),console.log("wasDirtyElement: ",o),i!=o){l.handleDirtyElement(r,i);var a=e.options[e.selectedIndex];r.setAttribute(attrIdAccessLevel,a.value),r.setAttribute(flagAccessLevelRequired,a.textcontent);var u=this.isDirtyRow(t);if(console.log("isNowDirtyRow: ",u),console.log("wasDirtyRow: ",n),u!=n){l.handleDirtyElement(t,u);var c=this.getTableRecords(!0),s=c.length>0;console.log("dirty records:",c),console.log("existsDirtyRecord:",s),this.toggleShowButtonsSaveCancel(s)}}}},{key:"leave",value:function(){if(this.constructor===t)throw new Error("Must implement leave() method.");!function(e,t,r){var n=ut(ct(e.prototype),"leave",r);return"function"==typeof n?function(e){return n.apply(r,e)}:n}(t,0,this)([]);var e=this.getFormFilters(),r={};r[flagFormFilters]=l.convertForm2JSON(e),this.setLocalStoragePage(r),_rowBlank=null}}],[{key:"isDirtyFilter",value:function(e){var t=l.isElementDirty(e);if(t){var r=document.querySelector(idTableMain+" tbody");r.querySelectorAll("tr").remove(),r.appendChild(document.createElement('
Press "Apply Filters" to refresh the table.
'))}return t}}])}(C);function yt(e){return yt="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},yt(e)}function dt(e,t){for(var r=0;r",t))})),e.addEventListener("change",(function(e){loadPermutations()}))})),f.initialiseEventHandler(idFilterIsOutOfStock,flagInitialised,(function(e){e.addEventListener("change",(function(e){loadPermutations()}))})),f.initialiseEventHandler(idFilterQuantityMin,flagInitialised,(function(e){e.addEventListener("change",(function(e){loadPermutations()}))})),f.initialiseEventHandler(idFilterQuantityMax,flagInitialised,(function(e){e.addEventListener("change",(function(e){loadPermutations()}))}))}},{key:"loadPermutations",value:function(){var e=document.querySelectorAll(idFormFiltersPermutations),t={};t[keyForm]=convertForm2JSON(e),t.csrf_token=t[keyForm].csrf_token,console.log("ajaxData:"),console.log(t),ajaxJSONData("permutations",mapHashToController(hashPageStorePermutationsPost),t,callbackLoadPermutations,!1,{"X-CSRFToken":t.csrf_token})}},{key:"callbackLoadPermutations",value:function(e){console.log("ajax:"),console.log(e.data);var t,r,n,o=document.querySelectorAll(idTableMain);(t=o.querySelector("tbody")).querySelector("tr").remove(),e.data.forEach((function(e){r=_rowBlank.cloneNode(!0),(r=document.querySelectorAll(r)).classList.remove(flagRowNew),console.log("applying data row: ",e),r.querySelector("td."+flagCategory+" select").value=e[attrIdCategory],n=r.querySelector("td."+flagProduct+" select"),listProducts.forEach((function(t){t[attrIdCategory]==e[attrIdCategory]&&n.appendChild(document.createElement("