From fdcf448bb1478a9158477ec9787635c142228ad7 Mon Sep 17 00:00:00 2001 From: teddy Date: Sun, 13 Oct 2024 19:40:25 +0100 Subject: [PATCH] feat(UI): Stock Items page added with getting, filtering, and saving data. --- README.md | 24 + __pycache__/__init__.cpython-312.pyc | Bin 657 -> 657 bytes __pycache__/app.cpython-312.pyc | Bin 5522 -> 5522 bytes __pycache__/config.cpython-312.pyc | Bin 2715 -> 2715 bytes __pycache__/extensions.cpython-312.pyc | Bin 845 -> 845 bytes app.log | 111 +- app.log.1 | 81 +- app.log.2 | 109 +- app.log.3 | 109 +- .../__pycache__/__init__.cpython-312.pyc | Bin 460 -> 460 bytes .../__pycache__/base.cpython-312.pyc | Bin 3537 -> 4168 bytes .../__pycache__/currency.cpython-312.pyc | Bin 2619 -> 6549 bytes .../__pycache__/db_base.cpython-312.pyc | Bin 3094 -> 3259 bytes .../__pycache__/sql_error.cpython-312.pyc | Bin 2082 -> 2082 bytes .../unit_measurement.cpython-312.pyc | Bin 7204 -> 7204 bytes .../__pycache__/user.cpython-312.pyc | Bin 12606 -> 12558 bytes business_objects/address.py | 97 + business_objects/base.py | 11 +- business_objects/{store => }/currency.py | 9 + business_objects/db_base.py | 5 +- business_objects/region.py | 82 + .../__pycache__/__init__.cpython-312.pyc | Bin 210 -> 210 bytes .../__pycache__/access_level.cpython-312.pyc | Bin 6639 -> 6639 bytes .../store/__pycache__/basket.cpython-312.pyc | Bin 9850 -> 9850 bytes .../__pycache__/currency.cpython-312.pyc | Bin 6193 -> 6555 bytes .../delivery_option.cpython-312.pyc | Bin 4224 -> 4224 bytes .../delivery_region.cpython-312.pyc | Bin 4560 -> 4560 bytes .../__pycache__/discount.cpython-312.pyc | Bin 4601 -> 4601 bytes .../store/__pycache__/image.cpython-312.pyc | Bin 5824 -> 5824 bytes .../store/__pycache__/order.cpython-312.pyc | Bin 4041 -> 4041 bytes .../store/__pycache__/product.cpython-312.pyc | Bin 27709 -> 28382 bytes .../product_category.cpython-312.pyc | Bin 29597 -> 30241 bytes .../product_permutation.cpython-312.pyc | Bin 42329 -> 40395 bytes .../__pycache__/product_price.cpython-312.pyc | Bin 5802 -> 5638 bytes .../product_variation.cpython-312.pyc | Bin 10479 -> 10479 bytes .../product_variation_tree.cpython-312.pyc | Bin 8757 -> 8792 bytes .../product_variation_type.cpython-312.pyc | Bin 5793 -> 5793 bytes .../__pycache__/stock_item.cpython-312.pyc | Bin 11566 -> 18179 bytes .../__pycache__/store_base.cpython-312.pyc | Bin 3059 -> 3519 bytes business_objects/store/delivery_option.py | 4 +- business_objects/store/delivery_region.py | 103 - business_objects/store/plant.py | 92 + business_objects/store/product.py | 18 +- business_objects/store/product_category.py | 10 + business_objects/store/product_permutation.py | 39 +- business_objects/store/product_price.py | 10 +- .../store/product_variation_tree.py | 1 + business_objects/store/stock_item.py | 229 +- business_objects/store/storage_location.py | 18 + business_objects/store/store_base.py | 10 +- business_objects/user.py | 11 +- .../__pycache__/__init__.cpython-312.pyc | Bin 195 -> 199 bytes controllers/__pycache__/core.cpython-312.pyc | Bin 5629 -> 6014 bytes controllers/__pycache__/legal.cpython-312.pyc | Bin 4048 -> 4052 bytes controllers/__pycache__/user.cpython-312.pyc | Bin 8541 -> 8676 bytes controllers/core.py | 5 + .../__pycache__/__init__.cpython-312.pyc | Bin 201 -> 205 bytes .../store/__pycache__/product.cpython-312.pyc | Bin 6078 -> 6384 bytes .../product_category.cpython-312.pyc | Bin 6033 -> 6304 bytes .../product_permutation.cpython-312.pyc | Bin 6336 -> 6642 bytes .../__pycache__/stock_item.cpython-312.pyc | Bin 6568 -> 6872 bytes .../store/__pycache__/store.cpython-312.pyc | Bin 1915 -> 1919 bytes .../__pycache__/supplier.cpython-312.pyc | Bin 3957 -> 4099 bytes controllers/store/product.py | 7 + controllers/store/product_category.py | 8 +- controllers/store/product_permutation.py | 7 + controllers/store/stock_item.py | 161 +- controllers/store/supplier.py | 3 + controllers/user.py | 3 + .../__pycache__/__init__.cpython-312.pyc | Bin 442 -> 442 bytes .../datastore_base.cpython-312.pyc | Bin 11537 -> 11528 bytes .../datastore_store_base.cpython-312.pyc | Bin 13513 -> 13483 bytes .../datastore_store_basket.cpython-312.pyc | Bin 7303 -> 7273 bytes ...ore_store_product_category.cpython-312.pyc | Bin 4351 -> 4321 bytes ..._store_product_permutation.cpython-312.pyc | Bin 3089 -> 3089 bytes ...datastore_store_stock_item.cpython-312.pyc | Bin 4855 -> 6137 bytes .../datastore_user.cpython-312.pyc | Bin 5610 -> 6958 bytes datastores/datastore_base.py | 4 +- datastores/datastore_store_base.py | 6 +- datastores/datastore_store_basket.py | 4 +- .../datastore_store_product_category.py | 4 +- .../datastore_store_product_variation.py | 4 +- datastores/datastore_store_stock_item.py | 70 +- datastores/datastore_store_stripe.py | 4 +- datastores/datastore_user.py | 70 + forms/__pycache__/__init__.cpython-312.pyc | Bin 193 -> 193 bytes .../__pycache__/access_level.cpython-312.pyc | Bin 2667 -> 2685 bytes forms/__pycache__/base.cpython-312.pyc | Bin 2499 -> 2499 bytes forms/__pycache__/forms.cpython-312.pyc | Bin 5646 -> 5672 bytes .../unit_measurement.cpython-312.pyc | Bin 2857 -> 2875 bytes forms/access_level.py | 2 +- forms/forms.py | 4 +- .../__pycache__/__init__.cpython-312.pyc | Bin 199 -> 199 bytes .../store/__pycache__/product.cpython-312.pyc | Bin 2590 -> 2608 bytes .../product_category.cpython-312.pyc | Bin 2509 -> 2527 bytes .../product_permutation.cpython-312.pyc | Bin 3831 -> 3831 bytes forms/store/product.py | 2 +- forms/store/product_category.py | 2 +- forms/store/stock_item.py | 18 +- forms/unit_measurement.py | 2 +- helpers/__pycache__/__init__.cpython-312.pyc | Bin 433 -> 433 bytes .../__pycache__/helper_app.cpython-312.pyc | Bin 1195 -> 1195 bytes .../helper_db_mysql.cpython-312.pyc | Bin 2580 -> 2580 bytes lib/__pycache__/__init__.cpython-312.pyc | Bin 429 -> 429 bytes .../argument_validation.cpython-312.pyc | Bin 34919 -> 34919 bytes lib/__pycache__/data_types.cpython-312.pyc | Bin 692 -> 692 bytes models/__pycache__/__init__.cpython-312.pyc | Bin 440 -> 440 bytes ..._view_accessibility_report.cpython-312.pyc | Bin 1293 -> 1293 bytes ...ew_accessibility_statement.cpython-312.pyc | Bin 1320 -> 1320 bytes .../model_view_admin.cpython-312.pyc | Bin 1186 -> 1186 bytes .../model_view_admin_home.cpython-312.pyc | Bin 1297 -> 1297 bytes .../model_view_base.cpython-312.pyc | Bin 16883 -> 17421 bytes .../model_view_contact.cpython-312.pyc | Bin 1655 -> 1655 bytes .../model_view_home.cpython-312.pyc | Bin 1164 -> 1164 bytes .../model_view_license.cpython-312.pyc | Bin 1189 -> 1189 bytes .../model_view_privacy_policy.cpython-312.pyc | Bin 1245 -> 1245 bytes ...el_view_retention_schedule.cpython-312.pyc | Bin 1282 -> 1282 bytes .../model_view_services.cpython-312.pyc | Bin 1193 -> 1193 bytes .../model_view_store.cpython-312.pyc | Bin 21359 -> 22454 bytes .../model_view_store_product.cpython-312.pyc | Bin 5548 -> 5499 bytes ...iew_store_product_category.cpython-312.pyc | Bin 3059 -> 3059 bytes ..._store_product_permutation.cpython-312.pyc | Bin 6046 -> 5959 bytes ...odel_view_store_stock_item.cpython-312.pyc | Bin 4712 -> 6446 bytes .../model_view_store_supplier.cpython-312.pyc | Bin 1468 -> 1469 bytes .../model_view_user.cpython-312.pyc | Bin 1459 -> 1459 bytes models/model_view_base.py | 47 +- models/model_view_store.py | 53 +- models/model_view_store_product.py | 2 +- .../model_view_store_product_permutation.py | 6 +- models/model_view_store_stock_item.py | 52 +- models/model_view_store_supplier.py | 2 +- requirements.txt | 2 +- static/MySQL/0000_combine.sql | 3173 ++++++--- static/MySQL/0001_destroy.sql | 18 +- ...1001_tbl_Split_Key_Value_Pair_Csv_Temp.sql | 13 + static/MySQL/1100_tbl_Shop_Region.sql | 2 - static/MySQL/1106_tbl_Shop_Address.sql | 22 + static/MySQL/1106_tbl_Shop_Plant.sql | 5 +- ...it.sql => 1107_tbl_Shop_Address_Audit.sql} | 0 static/MySQL/1108_tbl_Shop_Plant_Temp.sql | 13 +- static/MySQL/1218_tbl_Shop_Stock_Item.sql | 18 +- .../MySQL/1220_tbl_Shop_Stock_Item_Temp.sql | 33 +- ...ess.sql => 1318_tbl_Shop_User_Address.sql} | 20 +- .../1319_tbl_Shop_User_Address_Audit.sql | 21 + ..._Address.sql => 3106_tri_Shop_Address.sql} | 8 - static/MySQL/3318_tri_Shop_User_Address.sql | 75 + static/MySQL/6000_p_split.sql | 2 + .../MySQL/6003_p_split_key_value_pair_csv.sql | 108 + ..._p_clear_split_key_value_pair_csv_temp.sql | 29 + static/MySQL/7106_p_shop_get_many_plant.sql | 36 + .../7109_p_shop_get_many_storage_location.sql | 37 + .../MySQL/7203_p_shop_save_product_test.sql | 4 +- static/MySQL/7204_p_shop_get_many_product.sql | 2 +- ...ct_permutation_from_variation_csv_list.sql | 221 + .../MySQL/7219_p_shop_get_many_stock_item.sql | 14 +- static/MySQL/7220_p_shop_save_stock_item.sql | 646 ++ .../7220_p_shop_save_stock_item_test.sql | 101 + static/MySQL/7313_p_get_many_user.sql | 509 +- static/MySQL/9000_populate.sql | 19 +- static/MySQL/9010_anal.sql | 7 +- static/MySQL/temp.txt | 22 +- static/css/components/table.css | 12 + .../css/pages/store/product_permutations.css | 11 - static/css/pages/store/stock_items.css | 98 +- static/dist/css/main.bundle.css | 11 + .../css/store_product_permutations.bundle.css | 11 - static/dist/css/store_stock_items.bundle.css | 97 +- static/dist/js/main.bundle.js | 2 +- static/js/api.js | 15 + static/js/pages/base_table.js | 197 +- static/js/pages/store/product_permutations.js | 192 +- static/js/pages/store/stock_items.js | 791 +-- stderr.log | 5932 ----------------- .../store/_preview_DDL_product.html | 11 +- .../store/_preview_DDL_product_category.html | 11 +- ...eview_DDL_stock_item_storage_location.html | 13 + templates/components/store/_row_product.html | 11 +- .../store/_row_product_category.html | 2 +- .../store/_row_product_permutation.html | 42 +- .../components/store/_row_stock_item.html | 157 +- templates/js/sections/store.js | 45 +- templates/layouts/layout.html | 32 +- .../pages/store/_product_categories.html | 7 +- .../pages/store/_product_permutations.html | 24 +- templates/pages/store/_products.html | 27 +- templates/pages/store/_stock_items.html | 96 +- templates/pages/store/_supplier.html | 2 +- 187 files changed, 5939 insertions(+), 8825 deletions(-) create mode 100644 business_objects/address.py rename business_objects/{store => }/currency.py (93%) create mode 100644 business_objects/region.py delete mode 100644 business_objects/store/delivery_region.py create mode 100644 business_objects/store/plant.py create mode 100644 static/MySQL/1001_tbl_Split_Key_Value_Pair_Csv_Temp.sql create mode 100644 static/MySQL/1106_tbl_Shop_Address.sql rename static/MySQL/{1319_tbl_Shop_Address_Audit.sql => 1107_tbl_Shop_Address_Audit.sql} (100%) rename static/MySQL/{1318_tbl_Shop_Address.sql => 1318_tbl_Shop_User_Address.sql} (66%) create mode 100644 static/MySQL/1319_tbl_Shop_User_Address_Audit.sql rename static/MySQL/{3318_tri_Shop_Address.sql => 3106_tri_Shop_Address.sql} (85%) create mode 100644 static/MySQL/3318_tri_Shop_User_Address.sql create mode 100644 static/MySQL/6003_p_split_key_value_pair_csv.sql create mode 100644 static/MySQL/6004_p_clear_split_key_value_pair_csv_temp.sql create mode 100644 static/MySQL/7106_p_shop_get_many_plant.sql create mode 100644 static/MySQL/7109_p_shop_get_many_storage_location.sql create mode 100644 static/MySQL/7210_fn_shop_get_id_product_permutation_from_variation_csv_list.sql create mode 100644 static/MySQL/7220_p_shop_save_stock_item.sql create mode 100644 static/MySQL/7220_p_shop_save_stock_item_test.sql create mode 100644 templates/components/store/_preview_DDL_stock_item_storage_location.html diff --git a/README.md b/README.md index 37bef582..7d8050b3 100644 --- a/README.md +++ b/README.md @@ -14,3 +14,27 @@ python -m flask run host for local network: python -m flask run --host=0.0.0.0 + + +files dedicated to each page: +CSS + page +HTML + page + row +JavaScript + page + api + router +MySQL + get + save + table + staging table + audit table +Python + business object + controller + datastore + form + model \ No newline at end of file diff --git a/__pycache__/__init__.cpython-312.pyc b/__pycache__/__init__.cpython-312.pyc index 11e03992e4f9c8940ce4122ab610e70793bb1f6d..83b8f2242bb8182b99f63e43081cb9e4cf83c810 100644 GIT binary patch delta 21 bcmbQpI+2y diff --git a/__pycache__/extensions.cpython-312.pyc b/__pycache__/extensions.cpython-312.pyc index 80f2d10d92df258376a00cc050f0c3ae5715f286..6006f0ab268ee54d8777c411b96c4e716651fdf4 100644 GIT binary patch delta 21 bcmX@hc9xCjG%qg~0}wp!WlG=3 - ^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\jinja2\environment.py", line 487, in getattr - return getattr(obj, attribute) - ^^^^^^^^^^^^^^^^^^^^^^^ -jinja2.exceptions.UndefinedError: 'permutation' is undefined - +Request: 127.0.0.1 GET http /store/stock_items?id_category=3&id_product=&is_out_of_stock=false&quantity_min=&quantity_max= Host: 127.0.0.1:5000 +User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0 +Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8 +Accept-Language: en-GB,en;q=0.5 +Accept-Encoding: gzip, deflate, br, zstd +Referer: http://127.0.0.1:5000/store/stock_items?id_category=3&id_product=3&is_out_of_stock=false&quantity_min=&quantity_max= +Dnt: 1 +Connection: keep-alive +Cookie: session=.eJytVlnPqzgS_SutSN1PnVz25ZOuZsgGJIEkhLC9ILBZzB6WLPTc_z4m3-2-_dCzSSOFYLtMnVOuclX9NguGPq1b1EXw2kXt7OO3GQgqP4Alqvyur9to9tG3Q_Trn5aH98bP1agMUDH7mEXwEbRwUSIIi6ivq65Effr3ZJIuQF3Ofp3FqO36KiixwpkZQfjCawj6YGjbqAIvH0ZxMBT97KMaiuItaqME1dVfCD4JkH-M_ckIAut9v__BsQIViiwQRBYSYsATYUAScRRPgJ3_ZuzfoxbFKIKzjzgouugtQRUoBhhB35LMH6ifdmJxNzQY6s_Gd0P73SDtd7vnl8nw2Td8Xl0b-32dRxWWg1gAbMCIPA0ZhuBogqZCigAEB4OQJ7kwZCkYEhyHKQ7f3RAAEHXdHxqi1y4NZYCOaJcHjooOq10Rlto0X2rZlTIIXVfRAwWOPqpZjQLFIICicYeXmHuO24cVTINRfeiZV3iZVx_lggkRS4IXm0LHqLUVm2FKd7UiFgtn617dFzzsYq1Rzr26GJ8usLan_Fjvjp4S3kxnpUgyw87l89Vlo-3TlTJ_v2eq_c7Ir-y-7kb_DC-I2SRjv_GsRD8YZbvpu7AW2uU6NIqIu7KR4kXD7gga1iSSw3wv1kbp1-d-wzV3F6zmNrKeCsk37E0E-gPUQxhc-tS3SjkOLTeu9sXa4q5ZtexW_mEfS-5yL9-qOIOsHDUKhGDeHQebvMQrD5zkKyqsjFyVjO3UaJNzohNJqIwAyJJUURgakRfZv_hldqiGuRdJr3oEFSuU0s1FibD3hbBORZvZjfd4GOLVSVyGYyfuHF7zGN3oLdZkD-yqY5e677rg8MwZP7mE5dgHQx1LOcvMx_MT1OeKJ-nt3k6s8C4sYihlxHlT6KlkeU8arNC51iQcBtGzQW3U-QEOQZKnBJ4UaI77sY5wUAgcQxDvW_AXUXK5jiqpI7VTK4MFK5VT88axVnhe9o03zSvrHjne1cgZJsx2d09JSCvfHrRtShqvnbjAyobA1tuw3PbeBX9QWjmkti9vxfaBbeShbBEhxY6hXRDBWzGbhvZ1Ai88BaagPA9Ylnvys4CyOACKbKCcSh5FpoH9GFxK7KeQBXKRQcV6fWKkBFSW4xEJdxyaFSi3lOsYKUCf4ek6Xgrl7eswXkdvrZdadia0Ncx1ExtLuYwuuy-d0lNtDRh9NJC3dokTrYn6OnnsKlUEMii9NVlDxXiA13U8X64vA-Gn1HN8Hf58FQotx1jllnCd3bgzd7Jnnwcgs9XEGTrLHPMqvK2YwukwM_WBufSaKeFne8X4nDaqnL6-DtqoMfbkiNLqXbvopuvp2QaN9eaHkmw82eg8x7iHld4HGP8sw_e-Q6nfw8uP7xzaK0BZlIFt5WrWlK79HL3L_-HKY3tcZ9KJeRHwFjnG08xJ50ylZuCkT3PEJ1VsOStPnbO9LS55w13LfEpBjeuc0THb0FqWUNq4YfUsmfgyU8BpJngd1y6ljzl1XGE_0xaaMDAWEayXgp5dGa1UWd3WmKNp5dq6SPVxiVxz8_BKq3zHBlW8ecEirUy7aU277o-bdONO53BVRzfzYpOAO6tqKLcydlrZTbwGHJfZO54yiIwcHi-K4WpKTXvYnx4FV1pmyVOqK1VFE2nHUXtOl-ICzTd519W2RUXkvXkMSJLofhWkdXTv6tNecCVkPG8X59CsvdMmlKvhUt5O7fa0fOmdq8DTQRt3FP-6w_acZE7S8HwzJKRGMZleWKvLvHavr7ZLU_VxN24A5_4BBu7QydSZXy2TU0EmIfNMLdY1IuuiNHWqMawEmqcSn7a-cpwvg7CshgHFxT60IYVW0m0jP4bLGvDpeLmC-W3r1KqrFkldtKaYWanVgKbjHXNfKQdWMh8rKSmgy0XQJtf9PeoFUeK0ZfUMVXtvnqBc7SFhioW-dLqWOfm0aD3sQLzKD8xTTG1PbY-7ka-OzjLMeOtCL4W56C0FV3N3hHhEp3lLJDh_daBupsqI_ysEf2raOkZF9NNnv_Dr7J2w_P713rOMghYXvc_ah6q4fte_ARfnWSJnr_6ma_YqvaDn7chTxnm0FFsKot0O3-_Z_9KC_IvSj1PqZ47lOF7kBJxQf0-6HE1-LnQdBkj7vuk-vnyB0X1ePYKcwgU7irlUQM9qMXSLd_cxQX3BWN8bg_9MqkIg_3ebpy11BSY5H25lXekdYuTjoE-SJcVusbhBoB-mRu0Pht0iaYN70Aftm87n8AtLQzqmcP_BQ5Zi-VhgYooHAcELPBNCjvlb95URiF_ar03yC_z61vUzLf1MbfEPwOqHfXj-qbLDowgumurtcTQ57O4kWpZr2VxQ1iE-5yUdcv5RVq3xHvYqlU8bh_C_6dWGBgY97sYmZ8wogmLmJDEnSZPgP2jqg2EXNC14s2_fvv0TX22jag.ZwjUoA.pitPRgpTPJyCaDMIr0TPpBG_lIc +Upgrade-Insecure-Requests: 1 +Sec-Fetch-Dest: document +Sec-Fetch-Mode: navigate +Sec-Fetch-Site: same-origin +Sec-Fetch-User: ?1 +Sec-Gpc: 1 +Priority: u=0, i + + +Request data: b'' +Traceback: Traceback (most recent call last): + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 1473, in wsgi_app + response = self.full_dispatch_request() + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 882, in full_dispatch_request + rv = self.handle_user_exception(e) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask_cors\extension.py", line 178, in wrapped_function + return cors_after_request(app.make_response(f(*args, **kwargs))) + ^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 880, in full_dispatch_request + rv = self.dispatch_request() + ^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 865, in dispatch_request + return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\stock_item.py", line 45, in stock_items + return render_template('pages/store/_stock_items.html', model = model, datetime = datetime) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\templating.py", line 150, in render_template + return _render(app, template, context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\templating.py", line 131, in _render + rv = template.render(context) + ^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\jinja2\environment.py", line 1304, in render + self.environment.handle_exception() + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\jinja2\environment.py", line 939, in handle_exception + raise rewrite_traceback_stack(source=source) + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\pages\store\_stock_items.html", line 1, in top-level template code + {% extends 'layouts/layout.html' %} + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\layouts\layout.html", line 316, in top-level template code + {% block page_body %}{% endblock %} + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\pages\store\_stock_items.html", line 100, in block 'page_body' + {% include 'components/store/_row_stock_item.html' %} + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\components\store\_row_stock_item.html", line 78, in top-level template code + {{ model.ATTR_VALUE_CURRENT }}="{{ currency.id_currency_cost }}" + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\jinja2\environment.py", line 487, in getattr + return getattr(obj, attribute) + ^^^^^^^^^^^^^^^^^^^^^^^ +jinja2.exceptions.UndefinedError: 'currency' is undefined + diff --git a/app.log.1 b/app.log.1 index c31f5f8b..82d34c9e 100644 --- a/app.log.1 +++ b/app.log.1 @@ -1,4 +1,47 @@ -Exception on /store/products [GET] +Request: 127.0.0.1 GET http /store/stock_items?id_category=3&id_product=3&is_out_of_stock=false&quantity_min=&quantity_max= Host: 127.0.0.1:5000 +User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0 +Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8 +Accept-Language: en-GB,en;q=0.5 +Accept-Encoding: gzip, deflate, br, zstd +Referer: http://127.0.0.1:5000/store/stock_items?id_category=3&id_product=&is_out_of_stock=false&quantity_min=&quantity_max= +Dnt: 1 +Connection: keep-alive +Cookie: session=.eJytVlnPqzgS_SutSN1PnVz25ZOuZsgGJIEkhLC9ILBZzB6WLPTc_z4m3-2-_dCzSSOFYLtMnVOuclX9NguGPq1b1EXw2kXt7OO3GQgqP4Alqvyur9to9tG3Q_Trn5aH98bP1agMUDH7mEXwEbRwUSIIi6ivq65Effr3ZJIuQF3Ofp3FqO36KiixwpkZQfjCawj6YGjbqAIvH0ZxMBT97KMaiuItaqME1dVfCD4JkH-M_ckIAut9v__BsQIViiwQRBYSYsATYUAScRRPgJ3_ZuzfoxbFKIKzjzgouugtQRUoBhhB35LMH6ifdmJxNzQY6s_Gd0P73SDtd7vnl8nw2Td8Xl0b-32dRxWWg1gAbMCIPA0ZhuBogqZCigAEB4OQJ7kwZCkYEhyHKQ7f3RAAEHXdHxqi1y4NZYCOaJcHjooOq10Rlto0X2rZlTIIXVfRAwWOPqpZjQLFIICicYeXmHuO24cVTINRfeiZV3iZVx_lggkRS4IXm0LHqLUVm2FKd7UiFgtn617dFzzsYq1Rzr26GJ8usLan_Fjvjp4S3kxnpUgyw87l89Vlo-3TlTJ_v2eq_c7Ir-y-7kb_DC-I2SRjv_GsRD8YZbvpu7AW2uU6NIqIu7KR4kXD7gga1iSSw3wv1kbp1-d-wzV3F6zmNrKeCsk37E0E-gPUQxhc-tS3SjkOLTeu9sXa4q5ZtexW_mEfS-5yL9-qOIOsHDUKhGDeHQebvMQrD5zkKyqsjFyVjO3UaJNzohNJqIwAyJJUURgakRfZv_hldqiGuRdJr3oEFSuU0s1FibD3hbBORZvZjfd4GOLVSVyGYyfuHF7zGN3oLdZkD-yqY5e677rg8MwZP7mE5dgHQx1LOcvMx_MT1OeKJ-nt3k6s8C4sYihlxHlT6KlkeU8arNC51iQcBtGzQW3U-QEOQZKnBJ4UaI77sY5wUAgcQxDvW_AXUXK5jiqpI7VTK4MFK5VT88axVnhe9o03zSvrHjne1cgZJsx2d09JSCvfHrRtShqvnbjAyobA1tuw3PbeBX9QWjmkti9vxfaBbeShbBEhxY6hXRDBWzGbhvZ1Ai88BaagPA9Ylnvys4CyOACKbKCcSh5FpoH9GFxK7KeQBXKRQcV6fWKkBFSW4xEJdxyaFSi3lOsYKUCf4ek6Xgrl7eswXkdvrZdadia0Ncx1ExtLuYwuuy-d0lNtDRh9NJC3dokTrYn6OnnsKlUEMii9NVlDxXiA13U8X64vA-Gn1HN8Hf58FQotx1jllnCd3bgzd7Jnnwcgs9XEGTrLHPMqvK2YwukwM_WBufSaKeFne8X4nDaqnL6-DtqoMfbkiNLqXbvopuvp2QaN9eaHkmw82eg8x7iHld4HGP8sw_e-Q6nfw8uP7xzaK0BZlIFt5WrWlK79HL3L_-HKY3tcZ9KJeRHwFjnG08xJ50ylZuCkT3PEJ1VsOStPnbO9LS55w13LfEpBjeuc0THb0FqWUNq4YfUsmfgyU8BpJngd1y6ljzl1XGE_0xaaMDAWEayXgp5dGa1UWd3WmKNp5dq6SPVxiVxz8_BKq3zHBlW8ecEirUy7aU277o-bdONO53BVRzfzYpOAO6tqKLcydlrZTbwGHJfZO54yiIwcHi-K4WpKTXvYnx4FV1pmyVOqK1VFE2nHUXtOl-ICzTd519W2RUXkvXkMSJLofhWkdXTv6tNecCVkPG8X59CsvdMmlKvhUt5O7fa0fOmdq8DTQRt3FP-6w_acZE7S8HwzJKRGMZleWKvLvHavr7ZLU_VxN24A5_4BBu7QydSZXy2TU0EmIfNMLdY1IuuiNHWqMawEmqcSn7a-cpwvg7CshgHFxT60IYVW0m0jP4bLGvDpeLmC-W3r1KqrFkldtKaYWanVgKbjHXNfKQdWMh8rKSmgy0XQJtf9PeoFUeK0ZfUMVXtvnqBc7SFhioW-dLqWOfm0aD3sQLzKD8xTTG1PbY-7ka-OzjLMeOtCL4W56C0FV3N3hHhEp3lLJDh_daBupsqI_ysEf2raOkZF9NNnv_Dr7J2w_P713rOMghYXvc_ah6q4fte_ARfnWSJnr_6ma_YqvaDn7chTxnm0FFsKot0O3-_Z_9KC_IvSj1PqZ47lOF7kBJxQf0-6HE1-LnQdBkj7vuk-vnyB0X1ePYKcwgU7irlUQM9qMXSLd_cxQX3BWN8bg_9MqkIg_3ebpy11BSY5H25lXekdYuTjoE-SJcVusbhBoB-mRu0Pht0iaYN70Aftm87n8AtLQzqmcP_BQ5Zi-VhgYooHAcELPBNCjvlb95URiF_ar03yC_z61vUzLf1MbfEPwOqHfXj-qbLDowgumurtcTQ57O4kWpZr2VxQ1iE-5yUdcv5RVq3xHvYqlU8bh_C_6dWGBgY97sYmZ8wogmLmJDEnSZPgP2jqg2EXNC14s2_fvv0TX22jag.ZwjUoA.pitPRgpTPJyCaDMIr0TPpBG_lIc +Upgrade-Insecure-Requests: 1 +Sec-Fetch-Dest: document +Sec-Fetch-Mode: navigate +Sec-Fetch-Site: same-origin +Sec-Fetch-User: ?1 +Sec-Gpc: 1 +Priority: u=0, i + + +Request data: b'' +Traceback: Traceback (most recent call last): + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 1473, in wsgi_app + response = self.full_dispatch_request() + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 882, in full_dispatch_request + rv = self.handle_user_exception(e) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask_cors\extension.py", line 178, in wrapped_function + return cors_after_request(app.make_response(f(*args, **kwargs))) + ^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 880, in full_dispatch_request + rv = self.dispatch_request() + ^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 865, in dispatch_request + return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\stock_item.py", line 40, in stock_items + model = Model_View_Store_Stock_Item(form_filters) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_stock_item.py", line 90, in __init__ + print(f'product: {product}\n{product[Stock_Item.ATTR_ID_PRODUCT_CATEGORY]}\{nself.form_filters.id_category.data}') + ^^^^^ +NameError: name 'nself' is not defined. Did you mean: 'self'? + +Exception on /store/stock_items [GET] Traceback (most recent call last): File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 1473, in wsgi_app response = self.full_dispatch_request() @@ -15,9 +58,9 @@ Traceback (most recent call last): File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 865, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\product.py", line 114, in products - return render_template('pages/store/_products.html', model = model) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\stock_item.py", line 45, in stock_items + return render_template('pages/store/_stock_items.html', model = model, datetime = datetime) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\templating.py", line 150, in render_template return _render(app, template, context) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,38 +71,20 @@ Traceback (most recent call last): self.environment.handle_exception() File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\jinja2\environment.py", line 939, in handle_exception raise rewrite_traceback_stack(source=source) - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\pages\store\_products.html", line 1, in top-level template code + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\pages\store\_stock_items.html", line 1, in top-level template code {% extends 'layouts/layout.html' %} ^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\layouts\layout.html", line 316, in top-level template code {% block page_body %}{% endblock %} ^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\pages\store\_products.html", line 89, in block 'page_body' - {% include 'components/store/_row_product.html' %} + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\pages\store\_stock_items.html", line 100, in block 'page_body' + {% include 'components/store/_row_stock_item.html' %} ^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\components\store\_row_product.html", line 38, in top-level template code - + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\templates\components\store\_row_stock_item.html", line 78, in top-level template code + {{ model.ATTR_VALUE_CURRENT }}="{{ currency.id_currency_cost }}" ^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\jinja2\environment.py", line 487, in getattr return getattr(obj, attribute) ^^^^^^^^^^^^^^^^^^^^^^^ -jinja2.exceptions.UndefinedError: 'permutation' is undefined +jinja2.exceptions.UndefinedError: 'currency' is undefined Server Error: 500 Internal Server Error: The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application. -Request: 127.0.0.1 GET http /store/products? Host: 127.0.0.1:5000 -User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0 -Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8 -Accept-Language: en-GB,en;q=0.5 -Accept-Encoding: gzip, deflate, br, zstd -Dnt: 1 -Connection: keep-alive -Cookie: session=.eJytVlmzqkgS_isdRnQ_9fGyKyfixoyKAh5BQWR7IaCqkGJXQIGe-9-n8Nzu2w89W8REuFCVReaXlV8uv83Crk2qO24QvDToPnv_bQbCMghhgcugaas7mr239w79-qft7nXwcxcVIc5n7zMEn-EdzgsMYY7aqmwK3CZ_v07SOaiK2a-zGN-btgwLonBmIQgHsodhALr7HZVgCCCKwy5vZ-9ll-cv0R1dcVX-heATAP3HczA5QRG9r_9_CPySiUQeLEUeUmK4oKKQpmIUTwab4IU4eKA7jjGCs_c4zBv0kuAS5B1EMLBX1g-rn34ScdPVxNSfnW-6-3eHtN_9fjtPjs--kftq7nHQVhkqJ2AxRECkKQQBtVjwUBRYCjIAiSwLUMwxgAc8omiRQOy-hyEEADXNHxrQsE8iGeAj3mehq-LDZp9HhTat11p6YUxK11X8xKGrj2pa4VAxKaBowmEQM9_12qiESTiqTz31cz_1q6OccxHmaTDwCXTNStvwacRQD7Wk5nP69pEeN63Xs9qCtY7SPNPvelBJyWjCRoVL5xS_qcch6jvTfFv64zBIvtZq7DFmesA01INmH8M1UvcX6oPpRemNH24tqHUlTNHxKGin8-3UFH2lItye1Kpiec9glm9e6Ny2fT_y8IFF-Tgm0nmzUFSLSx4XvEykeC1KciuiJyuBvJIr1ts-ojI5yZuyP-XVclPvW1PHhxJFHYkuXgyHoaUT0fKTzEhE1m-kYH3gtos8o07W6iOV2coJ-BAd1K0aLJPuiQqVF_L1QU7PV1_sKnUXMzGIrxqDW3e4sSPd2HveXudvzaa63xB73nXJ5ZwPmmr2sd0v8rTJ8JA8alzRwZFyVsYQO81eFV0uyNvjkG9OaprWhwwgq8TRfC3rqwh_SLorJ9ytrKWjtpQNQgPU1_iOmiAkFKQXzIJb8Cwl_NjHhBRLgaOoVxb8BUvOl1Gldaw2amnyYKMKala79oasi7b2p3VpP5DrX8yM46J0__CVK21nu4O2S2hz2ItzoqwLHf0eFbvWP5MXCjuDzG7wN3wbOmYWyTYVMfwYOTkVvhTzSeRcJuO5r8AEFEZHZJkv9zmUxQ4wdA3lZOUzdBI6z85jxHaiLJDzFCr28GkjoaCyHo94-SDULEGxYzzXTAD-pKfn-gmUd8NhvIy-pBdaalCaBDPdIs4yHqfL3qAzeqJJgNNHE_uSR51YTdSl63NfqiKQQeFLdAUV8wmGy2icL4OJybfQM5IOf06FXMuIrWJHee5-3Ft72XeMDsh8OWGG7jojuHJ_JyZwusxUfRIsrSZlrZb6Fy1VBc26CJqkdZqljs4UiMJuPSdvpvT0HZMlerNDQde-bDa-axIq621I7BsyfJ07FPojOv94z2X9HBR5ETp2pqZ14Tn96J__DylP_PHcSSfBRcEbcs3eymjXYBIrdJPeGslN5TvBzhLXcHb5OauFS5FNJaj2XAMf0y2rpWA8Slee-Dvh5SbCaRYY9NEYdCl7agOJM2vjyQaxRYXSeqmnF04jCac7Gne07EyT8kQf19iztk-_sIsXN5j8E5eja2gLlShLSv3SmtEWjkamF7aUqOedeNEKj7HovW6UYMLVEV6mLz5luu3IKuXRJqex9tYo7Ifv7lL74vVTqasUVbPtymBpJ6WuPCmoSu4bT4aT1Nj4uLjMVcq8K7nM5Iykw5PnYLg2WXtVNxQ2Y1nBNAu45hQssjcufabSJUJ8TDJsOCtKCarTIj6p5rgZF0bAhdZtw36sFXf4WIVUsQKatH8AihMUwHCHmw2b2CrDTblqgnO81LitVfHr5NzXYXuWRy5ERd3E-TVZ9fx221egdsL6Lm8Fz1oeOit-eLlB6tSmaSk6CPEu_bAt2G0dUX-uFS4By_gSX_lYZy05FAWmk-W3Rx7oMtrwxoe9Pev1oQ8_qrRopdUTq3WlC8qyHMaTE-_larMbvVawbCE7DXfTrg8nuiL9mKSgnqzMnbq-YWXTNGi8Bt6T1K8GVPXUGclvieFP9b2KcY5--pwXfp29ClbQDq8zaxTeSdP77H24jKtX_-tIc55d5XRob7rmbJIz7m_HBWMao604qxDt9yS_Z__LCPIvWj8pqd9rLMOJFEsK6u9Fl10uPzeahhhI2rZu3r98gejxVj7DjKEEAcVCssR9Oe-a-Wv6mEx9Iba-Dwb_GVSJQfbvDk9HqhJM8s3FjThg9WwnrVGFbuCyo4m4xqDtpkHtD4TN_HoPH2Eb3l9wPh-_8CxkY4bjqAXkGX4RL7mYWYCQWiwXXAQF7m_NV25J_XL_Wl9_gV9fun5mVz8zO_IBsPzhH1l_qmzIE4LzurxOEcdTwBA49LJcKlf-w8jlZr2JraWiBBYTC0dTW7-o0UX_zazW1TBsyTQ2BWPGUAz3RolvjGAxzDvNv1PsnGZYf_bt27d_Agdyo3I.ZvXc6g.WpR0PQjTMWhM_qBkpa9CVzq95M8 -Upgrade-Insecure-Requests: 1 -Sec-Fetch-Dest: document -Sec-Fetch-Mode: navigate -Sec-Fetch-Site: none -Sec-Fetch-User: ?1 -Sec-Gpc: 1 -Priority: u=0, i - - -Request data: b'' diff --git a/app.log.2 b/app.log.2 index b5df9777..54248294 100644 --- a/app.log.2 +++ b/app.log.2 @@ -1,58 +1,16 @@ -Exception on /store/products [GET] -Traceback (most recent call last): - File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 1473, in wsgi_app - response = self.full_dispatch_request() - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 882, in full_dispatch_request - rv = self.handle_user_exception(e) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask_cors\extension.py", line 178, in wrapped_function - return cors_after_request(app.make_response(f(*args, **kwargs))) - ^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 880, in full_dispatch_request - rv = self.dispatch_request() - ^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 865, in dispatch_request - return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return] - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\product.py", line 113, in products - model = Model_View_Store_Product(form_filters) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_product.py", line 101, in __init__ - self.category_list_filters, errors_filters = datastore_store.get_many_product( - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\datastores\datastore_store_base.py", line 110, in get_many_product - category_list.add_product(new_product) - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\business_objects\store\product_category.py", line 337, in add_product - self.categories[index_category].add_product(product) - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\business_objects\store\product_category.py", line 100, in add_product - raise ValueError(f"{av.error_msg_str(product, 'product', _m, Product)}\nProduct already in category.") -ValueError: Invalid Category.add_product argument product. Type = . Value = Product - id_product: 1 - id_category: 1 - name: Braille Keyboard Translator - display_order: 1 - can_view: False - can_edit: False - can_admin: False - has_variations: True - permutations: [] - variation trees: [] - -Product already in category. -Server Error: 500 Internal Server Error: The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application. -Request: 127.0.0.1 GET http /store/products? Host: 127.0.0.1:5000 -User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0 +Request: 127.0.0.1 GET http /store/stock_items?id_category=3&id_product=3&is_out_of_stock=false&quantity_min=&quantity_max= Host: 127.0.0.1:5000 +User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8 Accept-Language: en-GB,en;q=0.5 Accept-Encoding: gzip, deflate, br, zstd +Referer: http://127.0.0.1:5000/store/stock_items?id_category=3&id_product=&is_out_of_stock=false&quantity_min=&quantity_max= Dnt: 1 Connection: keep-alive -Cookie: session=.eJytVlmzqkgS_isdRnQ_9fGyKyfixoyKAh5BQWR7IaCqkGJXQIGe-9-n8Nzu2w89W8REuFCVReaXlV8uv83Crk2qO24QvDToPnv_bQbCMghhgcugaas7mr239w79-qft7nXwcxcVIc5n7zMEn-EdzgsMYY7aqmwK3CZ_v07SOaiK2a-zGN-btgwLonBmIQgHsodhALr7HZVgCCCKwy5vZ-9ll-cv0R1dcVX-heATAP3HczA5QRG9r_9_CPySiUQeLEUeUmK4oKKQpmIUTwab4IU4eKA7jjGCs_c4zBv0kuAS5B1EMLBX1g-rn34ScdPVxNSfnW-6-3eHtN_9fjtPjs--kftq7nHQVhkqJ2AxRECkKQQBtVjwUBRYCjIAiSwLUMwxgAc8omiRQOy-hyEEADXNHxrQsE8iGeAj3mehq-LDZp9HhTat11p6YUxK11X8xKGrj2pa4VAxKaBowmEQM9_12qiESTiqTz31cz_1q6OccxHmaTDwCXTNStvwacRQD7Wk5nP69pEeN63Xs9qCtY7SPNPvelBJyWjCRoVL5xS_qcch6jvTfFv64zBIvtZq7DFmesA01INmH8M1UvcX6oPpRemNH24tqHUlTNHxKGin8-3UFH2lItye1Kpiec9glm9e6Ny2fT_y8IFF-Tgm0nmzUFSLSx4XvEykeC1KciuiJyuBvJIr1ts-ojI5yZuyP-XVclPvW1PHhxJFHYkuXgyHoaUT0fKTzEhE1m-kYH3gtos8o07W6iOV2coJ-BAd1K0aLJPuiQqVF_L1QU7PV1_sKnUXMzGIrxqDW3e4sSPd2HveXudvzaa63xB73nXJ5ZwPmmr2sd0v8rTJ8JA8alzRwZFyVsYQO81eFV0uyNvjkG9OaprWhwwgq8TRfC3rqwh_SLorJ9ytrKWjtpQNQgPU1_iOmiAkFKQXzIJb8Cwl_NjHhBRLgaOoVxb8BUvOl1Gldaw2amnyYKMKala79oasi7b2p3VpP5DrX8yM46J0__CVK21nu4O2S2hz2ItzoqwLHf0eFbvWP5MXCjuDzG7wN3wbOmYWyTYVMfwYOTkVvhTzSeRcJuO5r8AEFEZHZJkv9zmUxQ4wdA3lZOUzdBI6z85jxHaiLJDzFCr28GkjoaCyHo94-SDULEGxYzzXTAD-pKfn-gmUd8NhvIy-pBdaalCaBDPdIs4yHqfL3qAzeqJJgNNHE_uSR51YTdSl63NfqiKQQeFLdAUV8wmGy2icL4OJybfQM5IOf06FXMuIrWJHee5-3Ft72XeMDsh8OWGG7jojuHJ_JyZwusxUfRIsrSZlrZb6Fy1VBc26CJqkdZqljs4UiMJuPSdvpvT0HZMlerNDQde-bDa-axIq621I7BsyfJ07FPojOv94z2X9HBR5ETp2pqZ14Tn96J__DylP_PHcSSfBRcEbcs3eymjXYBIrdJPeGslN5TvBzhLXcHb5OauFS5FNJaj2XAMf0y2rpWA8Slee-Dvh5SbCaRYY9NEYdCl7agOJM2vjyQaxRYXSeqmnF04jCac7Gne07EyT8kQf19iztk-_sIsXN5j8E5eja2gLlShLSv3SmtEWjkamF7aUqOedeNEKj7HovW6UYMLVEV6mLz5luu3IKuXRJqex9tYo7Ifv7lL74vVTqasUVbPtymBpJ6WuPCmoSu4bT4aT1Nj4uLjMVcq8K7nM5Iykw5PnYLg2WXtVNxQ2Y1nBNAu45hQssjcufabSJUJ8TDJsOCtKCarTIj6p5rgZF0bAhdZtw36sFXf4WIVUsQKatH8AihMUwHCHmw2b2CrDTblqgnO81LitVfHr5NzXYXuWRy5ERd3E-TVZ9fx221egdsL6Lm8Fz1oeOit-eLlB6tSmaSk6CPEu_bAt2G0dUX-uFS4By_gSX_lYZy05FAWmk-W3Rx7oMtrwxoe9Pev1oQ8_qrRopdUTq3WlC8qyHMaTE-_larMbvVawbCE7DXfTrg8nuiL9mKSgnqzMnbq-YWXTNGi8Bt6T1K8GVPXUGclvieFP9b2KcY5--pwXfp29ClbQDq8zaxTeSdP77H24jKtX_-tIc55d5XRob7rmbJIz7m_HBWMao604qxDt9yS_Z__LCPIvWj8pqd9rLMOJFEsK6u9Fl10uPzeahhhI2rZu3r98gejxVj7DjKEEAcVCssR9Oe-a-Wv6mEx9Iba-Dwb_GVSJQfbvDk9HqhJM8s3FjThg9WwnrVGFbuCyo4m4xqDtpkHtD4TN_HoPH2Eb3l9wPh-_8CxkY4bjqAXkGX4RL7mYWYCQWiwXXAQF7m_NV25J_XL_Wl9_gV9fun5mVz8zO_IBsPzhH1l_qmzIE4LzurxOEcdTwBA49LJcKlf-w8jlZr2JraWiBBYTC0dTW7-o0UX_zazW1TBsyTQ2BWPGUAz3RolvjGAxzDvNv1PsnGZYf_bt27d_Agdyo3I.ZvXc6g.WpR0PQjTMWhM_qBkpa9CVzq95M8 +Cookie: session=.eJytVlnPqzgS_SutSN1PnVz25ZOuZsgGJIEkhLC9ILBZzB6WLPTc_z4m3-2-_dCzSSOFYLtMnVOuclX9NguGPq1b1EXw2kXt7OO3GQgqP4Alqvyur9to9tG3Q_Trn5aH98bP1agMUDH7mEXwEbRwUSIIi6ivq65Effr3ZJIuQF3Ofp3FqO36KiixwpkZQfjCawj6YGjbqAIvH0ZxMBT97KMaiuItaqME1dVfCD4JkH-M_ckIAut9v__BsQIViiwQRBYSYsATYUAScRRPgJ3_ZuzfoxbFKIKzjzgouugtQRUoBhhB35LMH6ifdmJxNzQY6s_Gd0P73SDtd7vnl8nw2Td8Xl0b-32dRxWWg1gAbMCIPA0ZhuBogqZCigAEB4OQJ7kwZCkYEhyHKQ7f3RAAEHXdHxqi1y4NZYCOaJcHjooOq10Rlto0X2rZlTIIXVfRAwWOPqpZjQLFIICicYeXmHuO24cVTINRfeiZV3iZVx_lggkRS4IXm0LHqLUVm2FKd7UiFgtn617dFzzsYq1Rzr26GJ8usLan_Fjvjp4S3kxnpUgyw87l89Vlo-3TlTJ_v2eq_c7Ir-y-7kb_DC-I2SRjv_GsRD8YZbvpu7AW2uU6NIqIu7KR4kXD7gga1iSSw3wv1kbp1-d-wzV3F6zmNrKeCsk37E0E-gPUQxhc-tS3SjkOLTeu9sXa4q5ZtexW_mEfS-5yL9-qOIOsHDUKhGDeHQebvMQrD5zkKyqsjFyVjO3UaJNzohNJqIwAyJJUURgakRfZv_hldqiGuRdJr3oEFSuU0s1FibD3hbBORZvZjfd4GOLVSVyGYyfuHF7zGN3oLdZkD-yqY5e677rg8MwZP7mE5dgHQx1LOcvMx_MT1OeKJ-nt3k6s8C4sYihlxHlT6KlkeU8arNC51iQcBtGzQW3U-QEOQZKnBJ4UaI77sY5wUAgcQxDvW_AXUXK5jiqpI7VTK4MFK5VT88axVnhe9o03zSvrHjne1cgZJsx2d09JSCvfHrRtShqvnbjAyobA1tuw3PbeBX9QWjmkti9vxfaBbeShbBEhxY6hXRDBWzGbhvZ1Ai88BaagPA9Ylnvys4CyOACKbKCcSh5FpoH9GFxK7KeQBXKRQcV6fWKkBFSW4xEJdxyaFSi3lOsYKUCf4ek6Xgrl7eswXkdvrZdadia0Ncx1ExtLuYwuuy-d0lNtDRh9NJC3dokTrYn6OnnsKlUEMii9NVlDxXiA13U8X64vA-Gn1HN8Hf58FQotx1jllnCd3bgzd7Jnnwcgs9XEGTrLHPMqvK2YwukwM_WBufSaKeFne8X4nDaqnL6-DtqoMfbkiNLqXbvopuvp2QaN9eaHkmw82eg8x7iHld4HGP8sw_e-Q6nfw8uP7xzaK0BZlIFt5WrWlK79HL3L_-HKY3tcZ9KJeRHwFjnG08xJ50ylZuCkT3PEJ1VsOStPnbO9LS55w13LfEpBjeuc0THb0FqWUNq4YfUsmfgyU8BpJngd1y6ljzl1XGE_0xaaMDAWEayXgp5dGa1UWd3WmKNp5dq6SPVxiVxz8_BKq3zHBlW8ecEirUy7aU277o-bdONO53BVRzfzYpOAO6tqKLcydlrZTbwGHJfZO54yiIwcHi-K4WpKTXvYnx4FV1pmyVOqK1VFE2nHUXtOl-ICzTd519W2RUXkvXkMSJLofhWkdXTv6tNecCVkPG8X59CsvdMmlKvhUt5O7fa0fOmdq8DTQRt3FP-6w_acZE7S8HwzJKRGMZleWKvLvHavr7ZLU_VxN24A5_4BBu7QydSZXy2TU0EmIfNMLdY1IuuiNHWqMawEmqcSn7a-cpwvg7CshgHFxT60IYVW0m0jP4bLGvDpeLmC-W3r1KqrFkldtKaYWanVgKbjHXNfKQdWMh8rKSmgy0XQJtf9PeoFUeK0ZfUMVXtvnqBc7SFhioW-dLqWOfm0aD3sQLzKD8xTTG1PbY-7ka-OzjLMeOtCL4W56C0FV3N3hHhEp3lLJDh_daBupsqI_ysEf2raOkZF9NNnv_Dr7J2w_P713rOMghYXvc_ah6q4fte_ARfnWSJnr_6ma_YqvaDn7chTxnm0FFsKot0O3-_Z_9KC_IvSj1PqZ47lOF7kBJxQf0-6HE1-LnQdBkj7vuk-vnyB0X1ePYKcwgU7irlUQM9qMXSLd_cxQX3BWN8bg_9MqkIg_3ebpy11BSY5H25lXekdYuTjoE-SJcVusbhBoB-mRu0Pht0iaYN70Aftm87n8AtLQzqmcP_BQ5Zi-VhgYooHAcELPBNCjvlb95URiF_ar03yC_z61vUzLf1MbfEPwOqHfXj-qbLDowgumurtcTQ57O4kWpZr2VxQ1iE-5yUdcv5RVq3xHvYqlU8bh_C_6dWGBgY97sYmZ8wogmLmJDEnSZPgP2jqg2EXNC14s2_fvv0TX22jag.ZwjUoA.pitPRgpTPJyCaDMIr0TPpBG_lIc Upgrade-Insecure-Requests: 1 Sec-Fetch-Dest: document Sec-Fetch-Mode: navigate -Sec-Fetch-Site: none +Sec-Fetch-Site: same-origin Sec-Fetch-User: ?1 Sec-Gpc: 1 Priority: u=0, i @@ -75,29 +33,36 @@ Traceback: Traceback (most recent call last): File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 865, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\product.py", line 113, in products - model = Model_View_Store_Product(form_filters) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_product.py", line 101, in __init__ - self.category_list_filters, errors_filters = datastore_store.get_many_product( - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\datastores\datastore_store_base.py", line 110, in get_many_product - category_list.add_product(new_product) - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\business_objects\store\product_category.py", line 337, in add_product - self.categories[index_category].add_product(product) - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\business_objects\store\product_category.py", line 100, in add_product - raise ValueError(f"{av.error_msg_str(product, 'product', _m, Product)}\nProduct already in category.") -ValueError: Invalid Category.add_product argument product. Type = . Value = Product - id_product: 1 - id_category: 1 - name: Braille Keyboard Translator - display_order: 1 - can_view: False - can_edit: False - can_admin: False - has_variations: True - permutations: [] - variation trees: [] - -Product already in category. + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\stock_item.py", line 40, in stock_items + model = Model_View_Store_Stock_Item(form_filters) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_stock_item.py", line 89, in __init__ + if product.id_category != self.form_filters.id_category.data and self.form_filters.id_category.data != '': + ^^^^^^^^^^^^^^^^^^^ +AttributeError: 'dict' object has no attribute 'id_category' +Exception on /store/stock_items [GET] +Traceback (most recent call last): + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 1473, in wsgi_app + response = self.full_dispatch_request() + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 882, in full_dispatch_request + rv = self.handle_user_exception(e) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask_cors\extension.py", line 178, in wrapped_function + return cors_after_request(app.make_response(f(*args, **kwargs))) + ^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 880, in full_dispatch_request + rv = self.dispatch_request() + ^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 865, in dispatch_request + return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\stock_item.py", line 40, in stock_items + model = Model_View_Store_Stock_Item(form_filters) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_stock_item.py", line 90, in __init__ + print(f'product: {product}\n{product[Stock_Item.ATTR_ID_PRODUCT_CATEGORY]}\{nself.form_filters.id_category.data}') + ^^^^^ +NameError: name 'nself' is not defined. Did you mean: 'self'? +Server Error: 500 Internal Server Error: The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application. diff --git a/app.log.3 b/app.log.3 index c9275d8f..f3930331 100644 --- a/app.log.3 +++ b/app.log.3 @@ -1,58 +1,16 @@ -Exception on /store/products [GET] -Traceback (most recent call last): - File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 1473, in wsgi_app - response = self.full_dispatch_request() - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 882, in full_dispatch_request - rv = self.handle_user_exception(e) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask_cors\extension.py", line 178, in wrapped_function - return cors_after_request(app.make_response(f(*args, **kwargs))) - ^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 880, in full_dispatch_request - rv = self.dispatch_request() - ^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 865, in dispatch_request - return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return] - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\product.py", line 113, in products - model = Model_View_Store_Product(form_filters) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_product.py", line 101, in __init__ - self.category_list_filters, errors_filters = datastore_store.get_many_product( - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\datastores\datastore_store_base.py", line 109, in get_many_product - category_list.add_product(new_product) - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\business_objects\store\product_category.py", line 337, in add_product - self.categories[index_category].add_product(product) - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\business_objects\store\product_category.py", line 100, in add_product - raise ValueError(f"{av.error_msg_str(product, 'product', _m, Product)}\nProduct already in category.") -ValueError: Invalid Category.add_product argument product. Type = . Value = Product - id_product: 1 - id_category: 1 - name: Braille Keyboard Translator - display_order: 1 - can_view: False - can_edit: False - can_admin: False - has_variations: True - permutations: [] - variation trees: [] - -Product already in category. -Server Error: 500 Internal Server Error: The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application. -Request: 127.0.0.1 GET http /store/products? Host: 127.0.0.1:5000 -User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0 +Request: 127.0.0.1 GET http /store/stock_items?id_category=3&id_product=3&is_out_of_stock=false&quantity_min=&quantity_max= Host: 127.0.0.1:5000 +User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8 Accept-Language: en-GB,en;q=0.5 Accept-Encoding: gzip, deflate, br, zstd +Referer: http://127.0.0.1:5000/store/stock_items?id_category=3&id_product=&is_out_of_stock=false&quantity_min=&quantity_max= Dnt: 1 Connection: keep-alive -Cookie: session=.eJytVlmzqkgS_isdRnQ_9fGyKyfixoyKAh5BQWR7IaCqkGJXQIGe-9-n8Nzu2w89W8REuFCVReaXlV8uv83Crk2qO24QvDToPnv_bQbCMghhgcugaas7mr239w79-qft7nXwcxcVIc5n7zMEn-EdzgsMYY7aqmwK3CZ_v07SOaiK2a-zGN-btgwLonBmIQgHsodhALr7HZVgCCCKwy5vZ-9ll-cv0R1dcVX-heATAP3HczA5QRG9r_9_CPySiUQeLEUeUmK4oKKQpmIUTwab4IU4eKA7jjGCs_c4zBv0kuAS5B1EMLBX1g-rn34ScdPVxNSfnW-6-3eHtN_9fjtPjs--kftq7nHQVhkqJ2AxRECkKQQBtVjwUBRYCjIAiSwLUMwxgAc8omiRQOy-hyEEADXNHxrQsE8iGeAj3mehq-LDZp9HhTat11p6YUxK11X8xKGrj2pa4VAxKaBowmEQM9_12qiESTiqTz31cz_1q6OccxHmaTDwCXTNStvwacRQD7Wk5nP69pEeN63Xs9qCtY7SPNPvelBJyWjCRoVL5xS_qcch6jvTfFv64zBIvtZq7DFmesA01INmH8M1UvcX6oPpRemNH24tqHUlTNHxKGin8-3UFH2lItye1Kpiec9glm9e6Ny2fT_y8IFF-Tgm0nmzUFSLSx4XvEykeC1KciuiJyuBvJIr1ts-ojI5yZuyP-XVclPvW1PHhxJFHYkuXgyHoaUT0fKTzEhE1m-kYH3gtos8o07W6iOV2coJ-BAd1K0aLJPuiQqVF_L1QU7PV1_sKnUXMzGIrxqDW3e4sSPd2HveXudvzaa63xB73nXJ5ZwPmmr2sd0v8rTJ8JA8alzRwZFyVsYQO81eFV0uyNvjkG9OaprWhwwgq8TRfC3rqwh_SLorJ9ytrKWjtpQNQgPU1_iOmiAkFKQXzIJb8Cwl_NjHhBRLgaOoVxb8BUvOl1Gldaw2amnyYKMKala79oasi7b2p3VpP5DrX8yM46J0__CVK21nu4O2S2hz2ItzoqwLHf0eFbvWP5MXCjuDzG7wN3wbOmYWyTYVMfwYOTkVvhTzSeRcJuO5r8AEFEZHZJkv9zmUxQ4wdA3lZOUzdBI6z85jxHaiLJDzFCr28GkjoaCyHo94-SDULEGxYzzXTAD-pKfn-gmUd8NhvIy-pBdaalCaBDPdIs4yHqfL3qAzeqJJgNNHE_uSR51YTdSl63NfqiKQQeFLdAUV8wmGy2icL4OJybfQM5IOf06FXMuIrWJHee5-3Ft72XeMDsh8OWGG7jojuHJ_JyZwusxUfRIsrSZlrZb6Fy1VBc26CJqkdZqljs4UiMJuPSdvpvT0HZMlerNDQde-bDa-axIq621I7BsyfJ07FPojOv94z2X9HBR5ETp2pqZ14Tn96J__DylP_PHcSSfBRcEbcs3eymjXYBIrdJPeGslN5TvBzhLXcHb5OauFS5FNJaj2XAMf0y2rpWA8Slee-Dvh5SbCaRYY9NEYdCl7agOJM2vjyQaxRYXSeqmnF04jCac7Gne07EyT8kQf19iztk-_sIsXN5j8E5eja2gLlShLSv3SmtEWjkamF7aUqOedeNEKj7HovW6UYMLVEV6mLz5luu3IKuXRJqex9tYo7Ifv7lL74vVTqasUVbPtymBpJ6WuPCmoSu4bT4aT1Nj4uLjMVcq8K7nM5Iykw5PnYLg2WXtVNxQ2Y1nBNAu45hQssjcufabSJUJ8TDJsOCtKCarTIj6p5rgZF0bAhdZtw36sFXf4WIVUsQKatH8AihMUwHCHmw2b2CrDTblqgnO81LitVfHr5NzXYXuWRy5ERd3E-TVZ9fx221egdsL6Lm8Fz1oeOit-eLlB6tSmaSk6CPEu_bAt2G0dUX-uFS4By_gSX_lYZy05FAWmk-W3Rx7oMtrwxoe9Pev1oQ8_qrRopdUTq3WlC8qyHMaTE-_larMbvVawbCE7DXfTrg8nuiL9mKSgnqzMnbq-YWXTNGi8Bt6T1K8GVPXUGclvieFP9b2KcY5--pwXfp29ClbQDq8zaxTeSdP77H24jKtX_-tIc55d5XRob7rmbJIz7m_HBWMao604qxDt9yS_Z__LCPIvWj8pqd9rLMOJFEsK6u9Fl10uPzeahhhI2rZu3r98gejxVj7DjKEEAcVCssR9Oe-a-Wv6mEx9Iba-Dwb_GVSJQfbvDk9HqhJM8s3FjThg9WwnrVGFbuCyo4m4xqDtpkHtD4TN_HoPH2Eb3l9wPh-_8CxkY4bjqAXkGX4RL7mYWYCQWiwXXAQF7m_NV25J_XL_Wl9_gV9fun5mVz8zO_IBsPzhH1l_qmzIE4LzurxOEcdTwBA49LJcKlf-w8jlZr2JraWiBBYTC0dTW7-o0UX_zazW1TBsyTQ2BWPGUAz3RolvjGAxzDvNv1PsnGZYf_bt27d_Agdyo3I.ZvXc6g.WpR0PQjTMWhM_qBkpa9CVzq95M8 +Cookie: session=.eJytVlnPqzgS_SutSN1PnVz25ZOuZsgGJIEkhLC9ILBZzB6WLPTc_z4m3-2-_dCzSSOFYLtMnVOuclX9NguGPq1b1EXw2kXt7OO3GQgqP4Alqvyur9to9tG3Q_Trn5aH98bP1agMUDH7mEXwEbRwUSIIi6ivq65Effr3ZJIuQF3Ofp3FqO36KiixwpkZQfjCawj6YGjbqAIvH0ZxMBT97KMaiuItaqME1dVfCD4JkH-M_ckIAut9v__BsQIViiwQRBYSYsATYUAScRRPgJ3_ZuzfoxbFKIKzjzgouugtQRUoBhhB35LMH6ifdmJxNzQY6s_Gd0P73SDtd7vnl8nw2Td8Xl0b-32dRxWWg1gAbMCIPA0ZhuBogqZCigAEB4OQJ7kwZCkYEhyHKQ7f3RAAEHXdHxqi1y4NZYCOaJcHjooOq10Rlto0X2rZlTIIXVfRAwWOPqpZjQLFIICicYeXmHuO24cVTINRfeiZV3iZVx_lggkRS4IXm0LHqLUVm2FKd7UiFgtn617dFzzsYq1Rzr26GJ8usLan_Fjvjp4S3kxnpUgyw87l89Vlo-3TlTJ_v2eq_c7Ir-y-7kb_DC-I2SRjv_GsRD8YZbvpu7AW2uU6NIqIu7KR4kXD7gga1iSSw3wv1kbp1-d-wzV3F6zmNrKeCsk37E0E-gPUQxhc-tS3SjkOLTeu9sXa4q5ZtexW_mEfS-5yL9-qOIOsHDUKhGDeHQebvMQrD5zkKyqsjFyVjO3UaJNzohNJqIwAyJJUURgakRfZv_hldqiGuRdJr3oEFSuU0s1FibD3hbBORZvZjfd4GOLVSVyGYyfuHF7zGN3oLdZkD-yqY5e677rg8MwZP7mE5dgHQx1LOcvMx_MT1OeKJ-nt3k6s8C4sYihlxHlT6KlkeU8arNC51iQcBtGzQW3U-QEOQZKnBJ4UaI77sY5wUAgcQxDvW_AXUXK5jiqpI7VTK4MFK5VT88axVnhe9o03zSvrHjne1cgZJsx2d09JSCvfHrRtShqvnbjAyobA1tuw3PbeBX9QWjmkti9vxfaBbeShbBEhxY6hXRDBWzGbhvZ1Ai88BaagPA9Ylnvys4CyOACKbKCcSh5FpoH9GFxK7KeQBXKRQcV6fWKkBFSW4xEJdxyaFSi3lOsYKUCf4ek6Xgrl7eswXkdvrZdadia0Ncx1ExtLuYwuuy-d0lNtDRh9NJC3dokTrYn6OnnsKlUEMii9NVlDxXiA13U8X64vA-Gn1HN8Hf58FQotx1jllnCd3bgzd7Jnnwcgs9XEGTrLHPMqvK2YwukwM_WBufSaKeFne8X4nDaqnL6-DtqoMfbkiNLqXbvopuvp2QaN9eaHkmw82eg8x7iHld4HGP8sw_e-Q6nfw8uP7xzaK0BZlIFt5WrWlK79HL3L_-HKY3tcZ9KJeRHwFjnG08xJ50ylZuCkT3PEJ1VsOStPnbO9LS55w13LfEpBjeuc0THb0FqWUNq4YfUsmfgyU8BpJngd1y6ljzl1XGE_0xaaMDAWEayXgp5dGa1UWd3WmKNp5dq6SPVxiVxz8_BKq3zHBlW8ecEirUy7aU277o-bdONO53BVRzfzYpOAO6tqKLcydlrZTbwGHJfZO54yiIwcHi-K4WpKTXvYnx4FV1pmyVOqK1VFE2nHUXtOl-ICzTd519W2RUXkvXkMSJLofhWkdXTv6tNecCVkPG8X59CsvdMmlKvhUt5O7fa0fOmdq8DTQRt3FP-6w_acZE7S8HwzJKRGMZleWKvLvHavr7ZLU_VxN24A5_4BBu7QydSZXy2TU0EmIfNMLdY1IuuiNHWqMawEmqcSn7a-cpwvg7CshgHFxT60IYVW0m0jP4bLGvDpeLmC-W3r1KqrFkldtKaYWanVgKbjHXNfKQdWMh8rKSmgy0XQJtf9PeoFUeK0ZfUMVXtvnqBc7SFhioW-dLqWOfm0aD3sQLzKD8xTTG1PbY-7ka-OzjLMeOtCL4W56C0FV3N3hHhEp3lLJDh_daBupsqI_ysEf2raOkZF9NNnv_Dr7J2w_P713rOMghYXvc_ah6q4fte_ARfnWSJnr_6ma_YqvaDn7chTxnm0FFsKot0O3-_Z_9KC_IvSj1PqZ47lOF7kBJxQf0-6HE1-LnQdBkj7vuk-vnyB0X1ePYKcwgU7irlUQM9qMXSLd_cxQX3BWN8bg_9MqkIg_3ebpy11BSY5H25lXekdYuTjoE-SJcVusbhBoB-mRu0Pht0iaYN70Aftm87n8AtLQzqmcP_BQ5Zi-VhgYooHAcELPBNCjvlb95URiF_ar03yC_z61vUzLf1MbfEPwOqHfXj-qbLDowgumurtcTQ57O4kWpZr2VxQ1iE-5yUdcv5RVq3xHvYqlU8bh_C_6dWGBgY97sYmZ8wogmLmJDEnSZPgP2jqg2EXNC14s2_fvv0TX22jag.ZwjUoA.pitPRgpTPJyCaDMIr0TPpBG_lIc Upgrade-Insecure-Requests: 1 Sec-Fetch-Dest: document Sec-Fetch-Mode: navigate -Sec-Fetch-Site: none +Sec-Fetch-Site: same-origin Sec-Fetch-User: ?1 Sec-Gpc: 1 Priority: u=0, i @@ -75,29 +33,36 @@ Traceback: Traceback (most recent call last): File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 865, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\product.py", line 113, in products - model = Model_View_Store_Product(form_filters) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_product.py", line 101, in __init__ - self.category_list_filters, errors_filters = datastore_store.get_many_product( - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\datastores\datastore_store_base.py", line 109, in get_many_product - category_list.add_product(new_product) - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\business_objects\store\product_category.py", line 337, in add_product - self.categories[index_category].add_product(product) - File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\business_objects\store\product_category.py", line 100, in add_product - raise ValueError(f"{av.error_msg_str(product, 'product', _m, Product)}\nProduct already in category.") -ValueError: Invalid Category.add_product argument product. Type = . Value = Product - id_product: 1 - id_category: 1 - name: Braille Keyboard Translator - display_order: 1 - can_view: False - can_edit: False - can_admin: False - has_variations: True - permutations: [] - variation trees: [] - -Product already in category. + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\stock_item.py", line 40, in stock_items + model = Model_View_Store_Stock_Item(form_filters) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_stock_item.py", line 89, in __init__ + self.form_filters.import_values(filters_stock_item) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +AttributeError: 'Filters_Stock_Item' object has no attribute 'import_values' +Exception on /store/stock_items [GET] +Traceback (most recent call last): + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 1473, in wsgi_app + response = self.full_dispatch_request() + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 882, in full_dispatch_request + rv = self.handle_user_exception(e) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask_cors\extension.py", line 178, in wrapped_function + return cors_after_request(app.make_response(f(*args, **kwargs))) + ^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 880, in full_dispatch_request + rv = self.dispatch_request() + ^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 865, in dispatch_request + return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\controllers\store\stock_item.py", line 40, in stock_items + model = Model_View_Store_Stock_Item(form_filters) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\edwar\OneDrive\Documents\Programming\Visual Studio 2022\PARTS_Web\app\models\model_view_store_stock_item.py", line 89, in __init__ + if product.id_category != self.form_filters.id_category.data and self.form_filters.id_category.data != '': + ^^^^^^^^^^^^^^^^^^^ +AttributeError: 'dict' object has no attribute 'id_category' +Server Error: 500 Internal Server Error: The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application. diff --git a/business_objects/__pycache__/__init__.cpython-312.pyc b/business_objects/__pycache__/__init__.cpython-312.pyc index f3873cc20fd71798c65604e58b7475296b7a8bb9..69c5ed95e6fc81e341d2418312665f670379ebe6 100644 GIT binary patch delta 21 bcmX@Ze1@6lG%qg~0}wpwWlG=3bAS;5K|uxZ delta 21 bcmX@Ze1@6lG%qg~0}!k#&raRQbAS;5K~n|^ diff --git a/business_objects/__pycache__/base.cpython-312.pyc b/business_objects/__pycache__/base.cpython-312.pyc index 0dfde09f232a7470dc35a5cab85333adbe557efc..5f33a95bb2989a43af0792d39b779de0ffb2f013 100644 GIT binary patch delta 1166 zcmZ{i%TE(Q9LKvd6xepbXhV3Uyg^Du9tGqL%XTS9AKC}tCc4?|Zh)jvoh<|oraj=* zw3$nZ7q~$*CWgfSz=VWLO)t&<0UnH8JQ@$qth8A)PO{(m&F4Gc{mnkUG+(sUUNQ`A z!DILXy>UfY{a!{RfY}b5n4@b#9*UBn~9AX?4i(Z zV&evz5IRh3(qL0Ur-@A)Y$hdinc%De=Y(z(n>QFM^q82-U<<-M6LS-$_A1<=>-v7^^so2VDGcGY3NtEo`jmUg5K73z*sG#25*Vt@^@ zKI8=}^;Mp&%Nuj!L>?Pm1rVVmu*BadA&dit4@`*Bgy}tE@l9 zi~bPD`o&c?D)Q@`|KGsY&VK{TLGFChiYRIV{i?d80_dVTN=+kY&DqEk{MB3l4&n(8 z5E&*iMCdKJLh2|M?G~1{HWtrQ)N4zzZz>NOa=pi%qy7SzDs~U0Lz(rQoPAaRL&Y9X9yl_aIW4&!X}z*SCG z8c~$DO)#DP=|E;Y$7N>gnx-vKv=tp@L4BPG*pze^{^>TYdvDVb4iLYE~qG>ugi$!npRu*|xq0E%{l+>Kevecr= z_@dPG%>2At;*KF9LGhk0@h+}Do?)&*k&~aZ$WPW~^_bkl8n;=E&5&_&0lWC*IqW8z zjW{MTG8#-i%6Xd6dh$fB5Juz4&$w3V+XEe<$x@^Sq>5BQga(LE2Z=HjS%TP3K%$rl zNGK>2Sx?@_?Z9X@`9HTMr!7#(PgAAHVzML8ntHHakhWXg$vKI|#kr{^8TlziAYb3& zDK1GY$xMa{IRk}?T!F+&h9Zy|Mb;pK4MvCn8O2K(85mj_ZfIFwV3C-ivA}qy?qwG1 z8*0WESVSgd%qX6idzr=fhOXlU7U>xg3zBEXUe;xCyrHDs;4?vEhVew8V(l9S?iX0( z7I3T(UdVfy#r=k&W`p+xi5bchWiPX6PX54aIoXYG@?>c~zRAq|GLvoj!x(KRPvH+X zGy__Hi>;)xATuw$hy~`TA|DV7?%H1*Ho5sJr8%i~MM0A#1eAHz8M!_&012=X08NvQ AnE(I) diff --git a/business_objects/__pycache__/currency.cpython-312.pyc b/business_objects/__pycache__/currency.cpython-312.pyc index d800db15498b4cf255c0e6db4fad172f5602f8ff..ba5f57da7528893a19c9e4f8c7901fa3302d23b8 100644 GIT binary patch literal 6549 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 D6iu>v literal 2619 zcmbVN&2JM&6rWvxt=C!XkT?lo%qFxHw=|`JOCr=NAq0hz5D2u*VrjMBog|y=dd=(_ zaFj}}${|RVNZNx*s|t`Rl`1{-+<&1LP%6dR3UR0^H8<11g;U?GKN8b$VGeKK{C@N1 z&Axf>&F_N1BN)FeRqzIAf6+;O1Zv9Gcc7Gzh9smh8f!2nEBP3z`wYJskOH3WH-ctJ z3Ynb5dGmk~HhGEn^q>(jBT~d{ky^YtYY376_90`B8I__8ViAt6)!a$3FwD;)jk|@k zFpkaj)DN`%UGr6SX>Wl|@eBX(6U3Ussxu(Mm>9ftc~blgXKdZU{9xXhwTMTEXS5p% z(Zn%b(+uob+4m<+-I?X7QGHAhtm?LIWyQg)CSJleR){()UdHNd)-tS_f;d^Q9c>69eq~L2U_cUA4*&6tyL*m}ZD*Q%P{A;Z`s;Aj08z*det<^3OX;=xG?-r8w zgpuZlZ?q6d1zqlRo)DZ>3zy+qA~~X)3Mt6*xS-ae;rXZWq*bu>4TutQ8eF}OzF-!i zM)v``$jA*AFt&!(ZUlIw`D$3Lt~|_N!|EA8*9B@=y*E%SSi^$g${UN!Bua(G33aeZ zJ#Ts%-FuU6wn?p1ArgU)8__jct^Kg;S1k>@{;UGo8MF&##xmUKw4yo|k*A4e%4dfr zTtU-Ed1L-R^CUzRr;!j`5;$fm+$LV29 z&6_yu*lFk;Gej{>Jv)>BRJZerAx=7ZO}E6p<9&T;ubs%yPSQ#)m(J7*T&`B9ovu6V z%@y3Zsm$Z*L5GJLf3=XTUuf^H{1BYfz5=3%o(EBT;@g2Gu6*d|!`9WsCGHO{QSR!# z-@V$h#CyRgNbkQs0d&m@EXdGV|!1#b^%ZBX=OF908Tc+)ie`nnu(BRz$cpcrmO>2Xkt@A z(guG-;#9O#L7N5Xq@oK1ZNN4*rfpgeA~^uk&c0Y>sR1kBxt=!gG>R;(!eh+5J=2^TP-&eZ2a&>tOxSnJ=*|U-Cdz|ch zbnpZKCllp_xRL06oalXY-~#}T3l$+0i&ao493uz8<#;Ma&qgCE%Pud=CcIk))mvow z8q`OPVYQ4KJZ%|yGwX&%vksoY#EXI(oOB43Q#BA?NN6o91-sH-|k<&RGM0uT8|tm z4)1~p(K}POrjMiyi_ZOHem+fnYQhlQdeSOJW zbWLCkvfQXfEk#j!hh8LKa;K_S_YpY>7)?FzD_orMKkq%l#FogNo40SiK%jaK{sVw4T;2cx diff --git a/business_objects/__pycache__/db_base.cpython-312.pyc b/business_objects/__pycache__/db_base.cpython-312.pyc index 2530a31a78e4feb3d83e1fa0d0f5543040ae630e..52964c18d3113afe3f6b2c6c9391d5ab9c280df6 100644 GIT binary patch delta 526 zcmbOxv0IY&G%qg~0}#Zru%z$b$eYE)=rFm0$yg+XxrHH$os*%1p@K1rBbY&x<(945?!Ak7TKpOt{bbcPy+EM!@zqSa73n4w4%$kb%K#gdYlT(Xj} zh#$x;2I){J5(1L9*h})`vx@WcsuY0sNvcA5iXc^dK%#-+2ETBBWoKn~^#u;8B4MDA zCgB$FJBH2H&FtSR2V41AI8gC;5lr5445pp1c2Sk8$fNd&L2C+bdF%TEC z0*Mxe8!Q|U70Q!$v(8{DlA0XOro(7CxrNP|QEKu5HbYKpkS=u~F?k}Jo`@7kE5h|f z(jW;3b_q6Hu(HWJ=z|Dz5P{|?Rgf5nFq=G;%au`e@@=m5Y+#?NPM*Lm e%ji6L9k&jjC?m&=$_?&c8Gwv0CX-)q>j40a+-K|n delta 430 zcmdljIZcB1G%qg~0}$-iVoblWkvEHp(PnZ5lQADB11CcVLj_|LdoY70^X9!wCm5MD zIVNkeI!w-E4P*bn!ote&fot+<)_5BUp!On35FrI3ctC_Oh!6r1@-V^-$S7t75-kij zSU4am*bN<&K^hr>gaX*aTkIwI z@maF&U#RB2e4KU0dhq$(_}|>waLaDc8pGwi#R~$uj6oM z^8_o}{F|eJkTZlX-=wLk>liG9vwajMvfVk8{EG# N02yDbCin8_0RSdYTDbrK diff --git a/business_objects/__pycache__/sql_error.cpython-312.pyc b/business_objects/__pycache__/sql_error.cpython-312.pyc index 18727de8567c67f9f9778b15419c1b8d7b52f05d..734fe7eae95a1ba99bab279ffaf7b362893ab879 100644 GIT binary patch delta 20 acmZ1^ut8Hmp9QS_Z^|}Q3eLUcdw}0qeC$>qeAe_s&EbUflPKc4H^Q^?4vF&or2~*@~ za72&`**V)(7PJKXyR#4AZL%ap$+V!rI{%AWKq8xxA#SebLF-MgAgpX`5aEmaL>nb%pnyw^L@wggQw4`a%(-W{MDIjQuqR4)WDe7t>W;zvRJQ2}#MbXhm zV3zgRwQjl%)*0^@cxu_S*#TR6HNd@D;bw(zPCW0qSyeYD-jMvaB=5ZAy5##-s=Onx z{ceBmw*8XDMoU4Pz2)3X>ew}BxabKGX(NJ+(8MHHkoZ~H6(Y@S*!2skL|bx@9doyq zPm{|6cHy${u61Rj6NJ?{hI2o;uaT_7by80yy8=804Wqwigcby7kU;AYc(it0bs+Ez z^1(q|w_~fi0&+2Rf@s<%sFpOg_SlLp+7Rk`5g+NCmVt_FHAT#m?n3?D06Gpm5C~8| zn<}WW4P@O+FR9j45iouyIQM@juXEKriszBb! zag`!n@;6AsLopgLBKaX6MH?$U!ENHI0XC6wLz`6j@dLN!lRyKx!hQ&x;t^NLZq`&^ z-N{4Rc}RK+gJ6Lao&LiS=mo!ln`1ju-$34HSL$ER=gumEiv1*7#MpGuH+J7xwwQ&O zsBWaFs&LFZ;twVe0BlS*<{VXHk#xey_>ewIpO!FGs<%9F@)7$!xc4x!WKed~=P}qI z!VtO;j{_y>Fv^Dz_)w4FDv2kBr{H6H;eUw=<4XhOQb|*cr?n_8WdXULG%`)zPdeF( z+z1c&H}V0p&U`zU;gVe4nIWW~JsnQlp9LownQ7r5TMds49Yoh|nt=~}6@kA3)3};J zcnyKSL|I(TBD{|92ExPC8(=fdJBX9L*Zf5miyoBAAL=Kyq1_0=C;|_R@6*=N598^U zDV)Vqykv9|0i*I6xOuxc{LJpP{AuSWQ*6EUMbgSf+g=DAMOEzSLze4O_vutLoly7D h1@>iIxa<`|ism{N_RQ~D9K9=`bbFGy+S~ZU@;6`^(#QY+ delta 2224 zcmb`IU2IfE6oBvS|8IBMZp)S~%hE1wZ`p3Q6(dDrC_e=Ww3ZgN_;X#lx9f%NZkT(w z$hOiNcv!-Z4f9~AQ6G3}Fh;U38Y3~j*vOOdk6e8)#s_0e=#NiC!E@%8(h@5^ILUr@ z=FFKhXU;h@d+F$nqu!fduSqgZwYBKCP>gT+9^Rab$5wG_b95A&1W)lT2gY;M7OAN zc1R_l6=lq(xO9gE6N)BDjM#&IbZ0`i72a5~eCw!L5ZJr!nsTrGipi0%$bTODcBnDDmnj;XxhZZPez z9aHnUZBg2c3pXR;h!%twu>rwtC$ZOt;QK9Zb);h5(5j0QsNITqgc($+1c+wcf*#Sw zP_hM}Vr-+)D6M9CMZ~rpMM-wIBI2@5YLi2y{5OtBd9%+$j6<3Z5caV<@!*sf{q2N2 z!9H8lq;Ma$f&tM_o$#R@i2ucT(L%SOF~e=v8wf%Cj|G}-eIQjoWmAFW{<1FuS4gOw zs_Y}v$=v}PBs4B`QK9YcnG4~5AnbJqM=8v^kl{Fd6%HECk+HHOB8v;g-6*YP$c z^a&#A1{Zi@FeuZ+$p4~kkm&A=tVwBkC{@U6ML+jzndCgEs8xUo;TK=!`H_<4*4o;V z<$~vyud?K(=ux*A!;6+nvAG(`L$BNVG^*q>|5W?BeP=$Ol~cL@QoU=zJbfIXdsHo@ zDTBkZ_G&&&pG0{lVh>_J;visJSkGOe7;WR!cyu1l%W&qhzji0F&pU{Qb_rOx64O zonkj4J0QRJBF)5+0X5M<6Ra(|b}zrh$3UW6(kU%vl-moaVWtX-J(vn5mm1WR5t&av zxVkv+9HRMQc-^95a+SRwJr4KvUZjS#ZT!3k?|HF$g+E-m03LQx?uL!>wM^f1Wlyp9)TQUVDO`F+l(>}6^b%>p$ zosEi(@Yr1ycay)^ui`XR&*kPKA$yrOUa;*0BSn#Q#Ov9$cwf)cXxdFr!G{(R{P`Qj z-WcL_1pl`=jlFTi1mX?E!*#r$9c*bL9yZc4Gj4>m>Yr9PB#Y8 delta 21 bcmaEF{N9-7G%qg~0}#CW^(k#5&tpjdR}Ba? diff --git a/business_objects/store/__pycache__/basket.cpython-312.pyc b/business_objects/store/__pycache__/basket.cpython-312.pyc index e432aded360e396ac000211e6639d17622203c29..af53b5b57571c322b327870f005b27b4be411ef8 100644 GIT binary patch delta 20 acmez6^UH_(G%qg~0}wpwW!lJ{uLb~1y9P-B delta 20 acmez6^UH_(G%qg~0}#|oFmB||R|5b>H3e<} diff --git a/business_objects/store/__pycache__/currency.cpython-312.pyc b/business_objects/store/__pycache__/currency.cpython-312.pyc index 81cebae296cb5fa748a148f7e4e9f473e912edb7..5066849f921b5641070f3665e497cdcbab03b534 100644 GIT binary patch delta 558 zcmdmJFx!~#G%qg~0}z}K<4Ug=-pF@=k+E&_dB$KSi&V)Jo)(7HAW0yIl1<@lVTh7T z;RBNLKslil{uV~KtU`(aP+YN6P*Zrb7mEiA-xs51E@hm=Bb zNq%y6d}c{%Zjk`c%$GbMf)_;a0f{2*$qP6nvV_u#@^j-|oZ=CxtE8Pvi;7b7k}LHv zB}0H(i>-h}1H%Je;|``9qG}ynH-*I}n|5&Akk?otG_$sY;|hn&4GF~sN;7#oIC^+* zNGUIHnyEY4QAB$46|UQijIo^2mH5mIWPJd!J_$^=5uYiAs{I#-O>TZlX-=wLQQYMB;@aX7 VjEr0zMg0|>6*Hv1GJtqsy8v2GiKGAk delta 313 zcmbPjywQN~G%qg~0}vEE`Iu%Tw2|)sBV*a-^Nhhv8Yw(23{kQvyg*VeRWd~|g|CHi zHApECM9HV{1H~081vG^=N3nRYFlugI%wfv3S(4{DBV)*BMm|<%MuW-hf|`tRn+*j| zGkKZ-b!qY!nFFaJNg#2HIX$(c$O6Qb0ug2)LK;L^f(RK9!3iQ{L4*~EkOL9clU+q( z7_&Do63J!++Q27f&R9O#O-!FradMfM7dO~^kcW!QCZ86|k=F(>^+1FXh_C?>jv&Gn zMCeYA7MEeP*jynl!N~N9Yw|LQnT)!V9V8_fBPK^mYK!|bGIDhk^;dLO%#ixZ0OA#C H0QCU?CRIZy diff --git a/business_objects/store/__pycache__/delivery_option.cpython-312.pyc b/business_objects/store/__pycache__/delivery_option.cpython-312.pyc index c5117e839fdd1fb0d6f7de198313e21b20d724e9..178a1e924b6ec2b67b1ba2f706e9753c012ad81b 100644 GIT binary patch delta 22 ccmZorY*6Gq&CAQh00eK>a-|1vF>AMh<_dv0QS5Kp#T5? diff --git a/business_objects/store/__pycache__/discount.cpython-312.pyc b/business_objects/store/__pycache__/discount.cpython-312.pyc index aeb74573a9097f756db08a4e4267c942c3aaf959..77e3cbe7beffbd733d5733efed95e8fdded6a0cc 100644 GIT binary patch delta 21 bcmeyV{8O3dG%qg~0}wpwWlG=3^HvZ5O>+jv delta 21 bcmeyV{8O3dG%qg~0}z~_d?Rfm&s#wNQUnK& diff --git a/business_objects/store/__pycache__/image.cpython-312.pyc b/business_objects/store/__pycache__/image.cpython-312.pyc index e7fabaf660c587732a57477627969fa9b8103e89..1ecc355a28409ae78430d999626f25df7196f38d 100644 GIT binary patch delta 20 acmX@0dq9`_G%qg~0}wpwW!lKSRSW<>KLyPI delta 20 acmX@0dq9`_G%qg~0}#|oFmB}DDh2>Kxdie6 diff --git a/business_objects/store/__pycache__/order.cpython-312.pyc b/business_objects/store/__pycache__/order.cpython-312.pyc index c700bb9b40ba7030ff73503d076efb72fe0765c1..2f778f4a70a06dcbd3d59baed48f38af4720a9ab 100644 GIT binary patch delta 21 bcmX>pe^Q?3G%qg~0}wpwWlG=3vzH$LMEM3S delta 21 bcmX>pe^Q?3G%qg~0}xCL{E)VhXD>ehMuY~E diff --git a/business_objects/store/__pycache__/product.cpython-312.pyc b/business_objects/store/__pycache__/product.cpython-312.pyc index 979001ecefdbe4c9b7d9b2bf417956917c80a075..3f2fa8071dd17395f88cb7c744e325446d4062e1 100644 GIT binary patch delta 1665 zcmZ{ke{54#6vyvy*|Sg+v9>m<*T;GBn=vx-G=So4!xK z_ndR@J@?&n--QJI@dujyc~+K%@OJc!rStmx!S3t`luOX3hc)(vl0JE1kVfF6Z`+zC1cP0kVNTxrbb z*RMG5dExLQ&h*`Usgp#Z&{yN~6!STR2vunJYC@RAm9Q@h=Z#QJ#H6rAgk2^WU$dwp zbdJ0sKCC2*18HhqrX-+MJ}SL;h---JFuL3Uuln8e9sR8TSHZ+C5dv>C)zNAAzG<0v z27@XQNe+*R-Qj;p`_6VX(9zYSg;*fiu7x_ote?$*cXNP#svp~2KqV&dp!-q7u}l#a)7b3c z4~iNuhg4G}O`g*cIBv~_{ZhL1O`@blL{76N!`9{kdBJ=PwGt)WC`rDaaL_p?Eq%Pq zB7)(a%?7=*vexj5=v4&%a7M(l8Dq0~@Vc`!vb%f{e4!*Mcd3E!9xV{=2&h^(*vT(0hm~L@i<+g79)RWZbY`iS)tB?8WqrNStir*?bT^3(d`t_pH=+kYm_o+x0=EsaI zC`$s}wwC7Tk8LXx7Tn;DdiEQ-e@9$`ldT0#b_?}w#1!IB#58=^T1U(Enbs<5#tG}W zsb>2S-2xZ4Z^#SsYM5_$X87DLhJz(8xRPUmhYQUcJd~OEPCNo*+?lkc%1ceXu0WR- z>Q!+Tx0{usKd*y@duMC#{-Avi!KmMU;D5ZBi0a_uhsagg7MCkya%FVQ#tGRUP4^r3 zu+bwM7m+nNOBY3bJIGbd$6NHw7wfqPN9)nHq_w4^h#nhn_tz(RO`t z@QOg4@OP+zv#z6*z5rUs2WhF?p|rE4asn6p22sV46ubJg)K;p|_AR0YVeITOs^th7 zUhj0RaAL}F?7L9m#{atw8#)lp`sGfUQk#Bl=Sjhai6*5@VI|aKcv%`8?_OwG%>((5 os7GMDyQ#22qW0mwQ@f@Js;L%BP^6n^G{1a`7;5qfaQ7_!7nOX=RR910 delta 1079 zcmZ9}TTBya6ae7=%yin)Qbwh%g1aCVff8&n5W|CJiwjjW+`N)St!SYwkdB#-iNs>e zMiYHnlk>1_H2S6wN{ks3U&O>)jN+wrWvNY8Hyd|FOblp)mzd~(+VJ9}^UXQ`Ii3H^ z%=5otECmJQHk*aGPKhQX**jD^U?G$Js&n<)=5NSGP?GkVa=`GtA=7&J{Hu zsHuUN;J6Lydwxk5hI?XxzQ~}~s|NP!by%I8ep-gU5=1&9BWj320kTieE!c9PKFlAt(if3nJf^AH$-y zFc&cvG-`#oJ5+*)C3F5M7Bt00u9+{M*;*z$=G)?s&w_cFlxbVLF)n1&+!XfGxJYTx zz)x;mylA;#%l(so4{IBCblVrE_F#Ee+%`vhWQPNF0!O>n zK%PF`B1u#bW?b37bfrwgWe2uXbe$^S4Q!0gW0MopeMS-Qp+3pkHwB+N3?yJPXhDt=tzHtQIzpp_K09f6s^iI3TB${ HM)b#Td8jT_ diff --git a/business_objects/store/__pycache__/product_category.cpython-312.pyc b/business_objects/store/__pycache__/product_category.cpython-312.pyc index 2b5014dfc027d903c8348997c6a384a9150849ff..88c29724768df10f191af6dbec126a1792dfca43 100644 GIT binary patch delta 1527 zcmZ{kZA?>F7{~9^-eOlOWxU8;VcIrivk8PKZ>2~qpu7mH^#v&vEYQoa$l7|_xvt>m z2eTFDHplrON{~1A!j?tY-6A-a_{C(2FImTegeB8tF}loT3~?s=vYqGNuynHBG{5_t zbN=@^&vWkmcj!KhK7^#}>(^@-dfCrwIt6|zDNzYFQLijylX>Gw#$|~zVQ`h~W6UP8 zX!CwR>5<%8}(hw#d)p|+6M?=vffY?^6N-R%vAa8anE!=RGFU@!Fd4M##a_p*e`k#C!HoC!?1XMHcdvg<#z0&~znt-# zef1C!HT&Ib#KAbRAd62m*dRo%H%uo=hxi)Keo5Xt;D9i>b07j=Nbl3vXoem#&=`{5 zZz?f3E8!&Jo&9wD#Oa2&NMqAaG%j-W!8_!t>k5r~4tByB@#ljEfLnxZc^S@=BP~zp zg6Gf}42cPD4&*)ivE`abSxz3yLzjwdNlqh^X=*Dqp2Geo3MT#ZyKjo0<%7{*O~^qEzkaaqHvivs}caA0i}|qMPM*KEkK~F^VWe z6d_U(ACsH@tlS3}O65PqNb2UPqVM4X;-4+t%82~_~>ibK%@U>eb{FnC|;Rch&^J_ob|6~i^> NYDT&qGjt%G#@~)}rqcib delta 1173 zcmZXSTS!z<6o${5TjK2@N#tmy8O211khjV)$MHU?nb~+rPcx}UYi#t4nfZ|QVoE-U zi^xz*Q_3ib+NPEfL70RO5`0A-3A~j$X*eSq!#yG{m_=+ir@|P{noY0|^=V(Z{+=d-nN?W2fDb;UUxjqm znc=4i80V`iWrQ*8&k9@rfJ>uZ*-Djzgb93}bpdi&e)cp(O;TkSVT@40VbrQ-D-|Yi zN3IEqSZ!|Y8uL*fv!t4rtvO(0d-vBtfKM{s&D+3Rn#s%3lmjk{p=@iubxoY?6IY|g zbr)Db!oEV0eJRNPH_}{4k+wn$9AkZjRcq4febSt2T4YfM$gHNw^>5PqLzMI+Dii~Y z6W|216iaK;+&*cFn${K_imwmv02k_PQvu%7J54k9aMpGJ+!$8U3U?7pOwf!kOPcs4 zWtJX>HXJDJ;X1ZVg7es2_Lgf`c_*~vukuG+j~|iYB8#Yq1eilpWer@yk;pnFi_X(QP*@zTmc1Hrd!d{03ZV$h4fZ+yNZsOvxr~Lons+O31<0fS< z75fPT93Gvs&fTP3qwyBPeS-Ju9%5HbLh%fZ&kEBCDCnEcptpi*y2Iw>N&~!PF(+pB2qBrn zqjR`iP9>3~AuT80e6UoZEh(b{Z$|k*(%bldO}?WE!ZX&dgaf=|Q|`wQN45Ew{vG%p_dW(JXO^h>TJy8wGP2rzzL>TyjY;h!!oV zgPA5gGyRl(kc$!Zp`ajAhzNojKS)JNMJ1D^wpj1HAR>Gpe(!(p`Jd%p?u!Y2@(%Ae zX*BwB%GWdN>ont--&rqkvp%mbJ+I?1+7yd>Oksx8+%d4%7jV{1ZZrDlnb~#I)E2Pe zsa<1`j<&o9kb%p2*I*kC?T%&gUIRcDj^?K_`+*{Wee7o8Mlilnx>yA>Zop#0=L#xQR1pDbvi^H1$+s5f}1Rf1OpC8MQ{xlr2%h0CB)9x zcLPQ@Il%|Jn}T9iN=#N06|>b#%pz^Z<(Ad>vMB>bF}!*FpF$NahtkxcwB$=AXla0z z%BK8Zc8yZD6vpvT>mc|cv`vJnrS#;p{WbG{W(daFwrse|Hnhh8+{gUmPaqQ4bvWP= zJJaFh_3tR*1|bZma{}Qi%KL*bw6hoBDL&&BIaKc)DV~OpR_-jTRKSR^bFz7f6?eh_{V zmI=QI93H-s;60;A9P9~DJDTy~mF*$fRPU*>FDZhH5Oc^)hi{FfXO7bs1k4=JK{(qv zz<9ld>{dc1YUQNl%_LI@qLS$La@9155|v1$y+%?tQh^i|DywQs8$|WEkcNG7LcH2O zog6y|>a9PctXzUR%vK5zJ_1{kYkAm;uAy@Opt45ERpXGPlG?H(j`9YHy&f6?ty@!7 xTV7h_z;nZKiu3mHTByM1!|Na(e+=V&$8V8o1((BC#qA3Fd5 delta 2351 zcma)-e{54#6vyAW-P_*Qt#7cl)Q-&pW3Jnnjt#f*L)``l2pv#BK;yIPdmB%?cHF)W z)(p{vKM*28q6nI_6YVIVXf(!X;+%${iReAu<_{#nm-N%y zbI$$V({t`=FPtKm&J){(f`UAOKPN{Bk&V!r}4I`55i$)C{GY>cLxg#H-m)J*Bn(mU##S;b%AB_pC5f zXy0esWBa7gvt1mL?J3!tl)VYb%Wf_!zI~!A?v$vuIT)hXxcZ$l#L&?UC;gov8e4gW z^ee7`d5{)?J>hU$Rd~9Bn~6&NEZ}f2viT0m6{y-SOi@t)b)ycIcf{<1yHH$=UB6EBauH05qcx*JZ^4!Y-V z-;|K_GpkYy+LH^~6Z39qNfBoD6_${(1 z^a9&D$0; zYT;n7ClFRWRO{3u;dsHnqUa%hY#KaqGF@Heg|yU3Be8Bh-097u4{;a0jL6*U>`bGz zbZ&I3W{j<~m$oX+OP8kQXm3}0B&3WVm@epu(5`@?L=DQt=ohH+HHX)dnS->fM>BH~ zQ#BQbWOOjF44(1H$RF!?W;o)W;ADWh84(;XdOwQfa*;^4!SDNRRc2*Wxain*q*cJC=nfW-%!BvXiOAbr zHr)Lq%*n_~7~P2QU>>(itKn9`dq)M|q>sQy>{ogO%Gtr_`N93aiUk0qdqz1yR~HFN5wPC^K_-%6R^p=62DB= ze2H@3AihQXfVhtM4M8w(3E@VRAf_X{h#83c5Os(K#B9U^?3XQd&}ddXb4Fa02ckTZ z1!5DT3{g6gMa0UHY=i{jQ!tVZqRyEo_P~fU2iJu}?Bf<9cENCVz9@~jP5ZWrJXpu( z?fMW(&72oov-0!sFe@S-*c!H=r2yA9#9auyZB)ipAz}hzBBBUkM>r5p#3Y1^U1c-* z)hpcV;zxP+t}9-T=39m)Q;ql(*1W@&SEDFY>!ylwzj=DENvscIJpSF%N7_$BXw70kAOW=-b&l^CHQGJW_IcP&87 zN32E%LL_E*e}uql_W8je+tu$f{r#_jNQZe8`{PhGcT^9QK%6ZZmq$iw8L9!FX8H#EU0yM(@rH2NBrAxBqDP&_Z^dZnva+rQg!A6#(RHM`g0F zHyiCIvW}Bjv(pUz@p?m) zUoui`rJCuG7T5rHV6JT%gw15iaC+yfVIHr6g2bL zWON*fiCIw-)Rpq0QhEWgiz+Il5X2thYwCe9a`DTWa#L;~reKQ9kU%gG}aGoM#me zF&9!{yJkd4Qt}9C{>7SFsK}~{l*OW) zud0!J4P&{IU%@=tmSZ~k?!i17dc$VD;qX8m^wq&|9r%BMP#pw*8$<{_kFGtL*qnG; L`~%nsv%~)aQXKrP delta 1292 zcmah}O-vI(6rQ2K&|g{$)Rs~ze?`Hc;1329OIs9!P%D~PW0tx*DrD&JY!&chU9w`j_6vxXza$>f{WewJ}cmK0wq_GgZjnrgn_-=P=BSk4k@uHS)DWd#1ih{kGn(%8k`SfbG# zW^@T14gX`L8kf*DtT-2(g(ebKY8TMT#_kKdmAVB~h$t?OQC@Rzsx>d6SzL&nM@bKh zT00x&cFh#kGU-t@xv2Kc6pfzAlB}|?-pDp3GRsR|U!;<@UdA}U9@!#zZ{@XZ72_aV zbWGSAxdb!8V$KBfIuGFkEahCpO_g^}qoys+YqS+00k8)k2+$7D0no`NTw!;JhdSmE zr;Y56s~u?5&%JIt+=&xr+#~?m!EkU}pl) z?M*;#Ve5fz+{e0tZMc`64Myh0aAAZU#@N%ETAnVMj^UC)t`k}n{rBrLZ9}S7G&a9L z-bw?|?~>J`u1^!=hNjTHkUj_iwo&+tO^+lAicC~hl9CBb8+ck+d=eBR3a5quQSf8- zGuRRPyg&QV+Ppmb#Paa=Cu?@glC|&pa0NCf`bLvJ(;-QUCQFjpaIr1G%qg~0}zCLJ;en`l2iFa5;S1c-Gb&aX&8pjwvU$01FC$~-WK+?HjG>do#Yz|pHus2? zGBSotW|Bx^EZLkYu?oZykaA_L-5e&hlaZy!gMnePfXoiY_RS|{<}xx)o}4cCNCqg# zP~-(7Jb{EJbCCgv?F%COCa20*G0vR)Kz^A(5J(^tM7V&6n90)=*7I|*ntx_yU=#en f1Y~^>n;fEeMzoxfQSu`Li2P8%EC;kz0H_`So!(9V delta 277 zcmccNvekv}G%qg~0}$xH`fL7q=Q?sSH9hFYc?#>odnMVL|;CkqIvPv#fm zoa`VZ&d5ADLP%beMG~m2hBclUq#FckSW;Lg_XtHYvH4AYDRh*(7AV%h@IX|&gKP6~ z;a*0@jLD&*4;e!yn~Rk&=5JmjR?5g2JXuL1iLrQdtHdf0$3V)Jv1W6b)J{gmTa%4t zb}+VWej_uNk#W-GF1bfCaX diff --git a/business_objects/store/__pycache__/product_variation_type.cpython-312.pyc b/business_objects/store/__pycache__/product_variation_type.cpython-312.pyc index 456569872e1a2f45376eb12400b3d5e59216f4ac..e2236a2789ab90efdea8b89153bd17d622de4fa7 100644 GIT binary patch delta 21 bcmZ3eyHJcw1t2 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 M48LUXjGl`B1VXr2o&W#< delta 5039 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 ld8B$n#;PxvFF7tcE^mFrKNl#UWfWl3d~ z1hP`uQe(a7ITPFLlScYi#bK9BZ)bK#ayB^ki=X;VwG;1?zgyt%}Vl%QsbQx zi&Jk2Wv0ZZq~>Inr507j=NFV@=I7lKcMJ&$iuZJhcX9Rc408>NjQ0-+@$~nbEWu*A zxq-!;v7Q^KDDde^I&+yOw=gF$rI<~A$E+q$X{Bj>iz~P!zbG}{DX}7be?sb+d0}WMF7z zcrf`Mmn@&2^92@}85s+TXXajJai08(tBqG#x50OU#SG_(wwGCSCm-R~o6N_vdh!V# y8AkWXPkCCU+<<;6at9F}K;jpNO>TZlX-=wLQNZLDULAfpMxzNLUm1WDSP=k-N?-T@ diff --git a/business_objects/store/delivery_option.py b/business_objects/store/delivery_option.py index 36e4c0b6..2dd7ab6c 100644 --- a/business_objects/store/delivery_option.py +++ b/business_objects/store/delivery_option.py @@ -22,7 +22,7 @@ class Delivery_Option(): delay_max: int quantity_min: float quantity_max: float - regions: list # [Enum_Delivery_Region] + regions: list # [Enum_Region] cost: float def __new__(cls, name, delay_min, delay_max, quantity_min, quantity_max, regions, cost): @@ -33,7 +33,7 @@ class Delivery_Option(): av.val_int(delay_max, 'delay_max', _m, 0, v_arg_type = v_arg_type) av.val_float(quantity_min, 'quantity_min', _m, 0, v_arg_type = v_arg_type) av.val_float(quantity_max, 'quantity_max', _m, 0, v_arg_type = v_arg_type) - av.val_list_instances(regions, 'regions', _m, Enum_Delivery_Region, v_arg_type = v_arg_type) + av.val_list_instances(regions, 'regions', _m, Enum_Region, v_arg_type = v_arg_type) av.val_float(cost, 'cost', _m, 0, v_arg_type = v_arg_type) return super(Delivery_Option, cls).__new__(cls) diff --git a/business_objects/store/delivery_region.py b/business_objects/store/delivery_region.py deleted file mode 100644 index 94516b64..00000000 --- a/business_objects/store/delivery_region.py +++ /dev/null @@ -1,103 +0,0 @@ -""" -Project: PARTS Website -Author: Edward Middleton-Smith - Precision And Research Technology Systems Limited - -Technology: Business Objects -Feature: Delivery Region Business Object - -Description: -Business object for delivery region -""" - -# internal -from business_objects.store.store_base import Store_Base -from extensions import db -from lib import argument_validation as av -# external -from enum import Enum -from typing import ClassVar - - -class Enum_Delivery_Region(Enum): - UK = 0 - -class Delivery_Region(db.Model, Store_Base): - NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_DELIVERY_REGION - NAME_ATTR_OPTION_TEXT: ClassVar[str] = Store_Base.FLAG_NAME - - id_region = db.Column(db.Integer, primary_key=True) - """ - id_category = db.Column(db.Integer) - id_product = db.Column(db.Integer) - id_discount = db.Column(db.Integer) - """ - code = db.Column(db.String(50)) - name = db.Column(db.String(200)) - active = db.Column(db.Boolean) - display_order = db.Column(db.Integer) - """ - def __new__(cls, id, id_category, id_product, id_discount, code, name, display_order): - _m = 'Delivery_Region.__new__' - v_arg_type = 'class attribute' - av.val_int(id, 'id', _m, 0, v_arg_type = v_arg_type) - av.val_int(id_category, 'id_category', _m, 0, v_arg_type=v_arg_type) - av.val_int(id_product, 'id_product', _m, 0, v_arg_type = v_arg_type) - av.val_int(id_discount, 'id_discount', _m, v_arg_type = v_arg_type) - av.val_str(code, 'code', _m, max_len = 50, v_arg_type = v_arg_type) - av.val_str(name, 'name', _m, max_len = 100, v_arg_type = v_arg_type) - av.val_int(display_order, 'display_order', _m, v_arg_type = v_arg_type) - return super(Delivery_Region, cls).__new__(cls) - - def __init__(self, id, id_category, id_product, id_discount, code, name, display_order): - self.id_region = id - self.id_category = id_category - self.id_product = id_product - self.id_discount = id_discount - self.name = name - self.code = code - self.display_order = display_order - """ - @classmethod - def from_DB_get_many_product_catalogue(cls, query_row): - region = cls() - region.id_region = query_row[0] - region.name = query_row[1] - region.code = query_row[2] - # self.display_order = query_row[3] - return region - @classmethod - def from_DB_region(cls, query_row): - region = cls() - region.id_region = query_row[0] - region.code = query_row[1] - region.name = query_row[2] - region.active = av.input_bool(query_row[3], cls.FLAG_ACTIVE, f'{cls.__name__}.from_DB_region') - region.display_order = query_row[4] - return region - def __repr__(self): - return f''' - id: {self.id_region} - name: {self.name} - code: {self.code} - active: {self.active} - display_order: {self.display_order} - ''' - def to_json(self): - return { - **self.get_shared_json_attributes(self), - self.ATTR_ID_REGION: self.id_region, - self.FLAG_CODE: self.code, - self.FLAG_NAME: self.name, - self.FLAG_ACTIVE: self.active, - self.FLAG_DISPLAY_ORDER: self.display_order - } - @staticmethod - def from_json(json_region): - region = Delivery_Region() - region.id_region = json_region[Delivery_Region.ATTR_ID_REGION] - region.code = json_region[Delivery_Region.FLAG_CODE] - region.name = json_region[Delivery_Region.FLAG_NAME] - region.active = json_region[Delivery_Region.FLAG_ACTIVE] - region.display_order = json_region[Delivery_Region.FLAG_DISPLAY_ORDER] - return region diff --git a/business_objects/store/plant.py b/business_objects/store/plant.py new file mode 100644 index 00000000..ec4d6c8a --- /dev/null +++ b/business_objects/store/plant.py @@ -0,0 +1,92 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Business Objects +Feature: Plant Business Object + +Description: +Business object for plant +""" + +# internal +import lib.argument_validation as av +from business_objects.address import Address +from business_objects.store.store_base import Store_Base +from extensions import db +# external +from typing import ClassVar + + +class Plant(db.Model, Store_Base): + NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_PLANT + NAME_ATTR_OPTION_TEXT: ClassVar[str] = Store_Base.FLAG_NAME + __tablename__ = 'Shop_Plant' + id_plant = db.Column(db.Integer, primary_key=True) + code = db.Column(db.String(50)) + name = db.Column(db.String(255)) + id_address = db.Column(db.Integer) + id_user_manager = db.Column(db.Integer) + active = db.Column(db.Boolean) + + # address = None + + def __init__(self): + super().__init__() + Store_Base.__init__(self) + self.address = None + @classmethod + def from_DB_storage_location(cls, query_row): + plant = cls() + plant.id_plant = query_row[1] + plant.id_address = query_row[2] + plant.address = Address.from_DB_storage_location(query_row) + return plant + @classmethod + def from_DB_plant(cls, query_row): + plant = cls() + plant.id_plant = query_row[0] + plant.id_address = query_row[1] + plant.address = Address.from_DB_plant(query_row) + plant.code = query_row[4] + plant.name = query_row[5] + plant.active = query_row[6] + return plant + @classmethod + def from_DB_stock_item(cls, query_row): + plant = cls() + plant.id_plant = query_row[5] + plant.code = query_row[10] + plant.name = query_row[11] + return plant + def __repr__(self): + return f''' + {self.ATTR_ID_PLANT}: {self.id_plant} + {self.FLAG_CODE}: {self.code} + {self.FLAG_NAME}: {self.name} + {self.FLAG_ADDRESS}: {self.address} + {self.ATTR_ID_USER_MANAGER}: {self.id_user_manager} + {self.FLAG_ACTIVE}: {self.active} + ''' + def to_json(self): + return { + **self.get_shared_json_attributes(self), + self.ATTR_ID_PLANT: self.id_plant, + self.FLAG_CODE: self.code, + self.FLAG_NAME: self.name, + self.FLAG_ADDRESS: self.address.to_json(), + self.ATTR_ID_USER_MANAGER: self.id_user_manager, + self.FLAG_ACTIVE: 1 if av.input_bool(self.active, self.FLAG_ACTIVE, f'{self.__class__.__name__}.to_json') else 0 + } + @classmethod + def from_json(cls, json): + print(f'{cls.__name__}.from_json: {json}') + plant = cls() + plant.id_plant = json[cls.ATTR_ID_PLANT], + plant.code = json[cls.FLAG_CODE], + plant.name = json[cls.FLAG_NAME], + plant.address = Address.from_json(json[cls.FLAG_ADDRESS]), + plant.id_user_manager = json[cls.ATTR_ID_USER_MANAGER], + plant.active = json[cls.FLAG_ACTIVE] + return plant diff --git a/business_objects/store/product.py b/business_objects/store/product.py index 7f1e460d..b04362ad 100644 --- a/business_objects/store/product.py +++ b/business_objects/store/product.py @@ -175,7 +175,7 @@ class Product(SQLAlchemy_ABC, Store_Base): if self.variation_trees[index_tree].is_equal(variation_tree): found_variation_tree_match = True break - if not found_variation_tree_match: + if not found_variation_tree_match and variation_tree is not None: self.variation_trees.append(variation_tree) def from_DB_Stripe_product(query_row): permutation = Product_Permutation.from_DB_Stripe_product(query_row) @@ -374,6 +374,13 @@ class Product(SQLAlchemy_ABC, Store_Base): text_input += tree.get_text_input_types() return text_input """ + def get_csv_ids_permutation(self): + csv = '' + for permutation in self.permutations: + if csv != '': + csv += ',' + csv += str(permutation.id_permutation) + return csv class Parameters_Product(Get_Many_Parameters_Base): @@ -482,7 +489,7 @@ class Parameters_Product(Get_Many_Parameters_Base): @staticmethod def from_form_filters_product_permutation(form): # if not (form is Filters_Product_Permutation): raise ValueError(f'Invalid form type: {type(form)}') - av.val_instance(form, 'form', 'Parameters_Product.from_form', Filters_Product_Permutation) + # av.val_instance(form, 'form', 'Parameters_Product.from_form', Filters_Product_Permutation) has_category_filter = not (form.id_category.data == '0' or form.id_category.data == '') has_product_filter = not (form.id_product.data == '0' or form.id_product.data == '') get_permutations_stock_below_min = av.input_bool(form.is_out_of_stock.data, "is_out_of_stock", "Parameters_Product.from_form") @@ -491,11 +498,11 @@ class Parameters_Product(Get_Many_Parameters_Base): get_all_product_category = not has_category_filter, get_inactive_product_category = False, # get_first_product_category_only = False, - ids_product_category = form.id_category.data, + ids_product_category = form.id_category.data if form.id_category.data is not None else '', get_all_product = not has_product_filter, get_inactive_product = False, # get_first_product_only = False, - ids_product = form.id_product.data, + ids_product = form.id_product.data if form.id_product.data is not None else '', get_all_permutation = not get_permutations_stock_below_min, get_inactive_permutation = False, # get_first_permutation_only = False, @@ -601,6 +608,9 @@ class Parameters_Product(Get_Many_Parameters_Base): ids_image = '', get_products_quantity_stock_below_min = False ) + @classmethod + def from_filters_stock_item(cls, filters_stock_item): + return cls.from_form_filters_product_permutation(filters_stock_item) """ class Parameters_Product(Get_Many_Parameters_Base): diff --git a/business_objects/store/product_category.py b/business_objects/store/product_category.py index cf000111..a025347a 100644 --- a/business_objects/store/product_category.py +++ b/business_objects/store/product_category.py @@ -242,6 +242,11 @@ class Product_Category(SQLAlchemy_ABC, Store_Base): 'value': self.id_category, 'text': self.name } + def get_csv_ids_permutation(self): + list_ids = [] + for product in self.products: + list_ids += product.get_csv_ids_permutation() + return list_ids """ class Filters_Product_Category(BaseModel, Store_Base): ids_product_category: str @@ -433,6 +438,11 @@ class Product_Category_Container(Store_Base): if column.name not in ['created_on', 'created_by'] } return self.to_object_with_missing_attributes(excluded_attributes) + def get_csv_ids_permutation(self): + list_ids = [] + for category in self.categories: + list_ids += category.get_csv_ids_permutation() + return ','.join(list_ids) """ diff --git a/business_objects/store/product_permutation.py b/business_objects/store/product_permutation.py index ee9285f2..faee9018 100644 --- a/business_objects/store/product_permutation.py +++ b/business_objects/store/product_permutation.py @@ -14,7 +14,7 @@ Business object for product permutation import lib.argument_validation as av from lib import data_types from forms.forms import Form_Basket_Add, Form_Basket_Edit -from business_objects.store.currency import Currency +from business_objects.currency import Currency from business_objects.store.delivery_option import Delivery_Option from business_objects.store.discount import Discount from business_objects.store.image import Image @@ -309,6 +309,7 @@ class Product_Permutation(db.Model, Store_Base): 'value': self.id_permutation, 'text': self.get_name_variations() } + def get_name(self): return def get_name_variations(self): @@ -317,19 +318,14 @@ class Product_Permutation(db.Model, Store_Base): return len(self.prices) > 0 def get_price(self): return self.prices[0] - def get_price_local_VAT_incl(self): - price = self.get_price() - return price.value_local_VAT_incl - def get_price_local_VAT_excl(self): - price = self.get_price() - return price.value_local_VAT_excl - def output_lead_time(self): - return '1 day' if self.latency_manufacture_days == 1 else f'{self.latency_manufacture_days} days' - def output_delivery_date(self): return (datetime.now() + timedelta(days=self.latency_manufacture_days)).strftime('%A, %d %B %Y') + """ + def output_lead_time(self): + return '1 day' if self.latency_manufacture_days == 1 else f'{self.latency_manufacture_days} days' + def output_price(self, is_included_VAT): if self.is_unavailable_in_currency_or_region: return 'Not available in currency and region' @@ -341,33 +337,14 @@ class Product_Permutation(db.Model, Store_Base): return f'{price.symbol_currency} {locale.format_string("%d", price.value_local_VAT_incl, grouping=True)}' else: return f'{price.symbol_currency} {locale.format_string("%d", price.value_local_VAT_excl, grouping=True)}' - def output_currency(self): - if not self.is_available: - return '' - """ - price = self.get_price() - return price.code_currency - """ - return self.code_currency_cost if self.symbol_currency_cost == '' else self.symbol_currency_cost + """ def output_variations(self): if not self.has_variations: return '' return '\n'.join([f'{variation.name_variation_type}: {variation.name_variation}' for variation in self.variations]) def output_variations_jsonify(self): if not self.has_variations: return '' return ','.join([f'{variation.id_type}: {variation.id_variation}' for variation in self.variations]) - """ - def output_price_VAT_incl(self): - locale.setlocale(locale.LC_ALL, '') - return locale.format_string("%d", self.price_GBP_VAT_incl, grouping=True) - def output_price_VAT_excl(self): - locale.setlocale(locale.LC_ALL, '') - return locale.format_string("%d", self.price_GBP_VAT_excl, grouping=True) - def add_form_basket_add(self): - self.form_basket_add = None - - def add_form_basket_edit(self): - self.form_basket_edit = None - """ + def __repr__(self): return f'''Product_Permutation id_permutation: {self.id_permutation} diff --git a/business_objects/store/product_price.py b/business_objects/store/product_price.py index 10b58739..4822836c 100644 --- a/business_objects/store/product_price.py +++ b/business_objects/store/product_price.py @@ -11,8 +11,8 @@ Business object for product price """ # internal -from business_objects.store.currency import Currency -from business_objects.store.delivery_region import Delivery_Region +from business_objects.currency import Currency +from business_objects.region import Region from business_objects.store.store_base import Store_Base from extensions import db # external @@ -22,8 +22,6 @@ from typing import ClassVar class Product_Price(db.Model, Store_Base): NAME_ATTR_OPTION_VALUE: ClassVar[str] = Store_Base.ATTR_ID_PRODUCT_PRICE NAME_ATTR_OPTION_TEXT = Store_Base.FLAG_TEXT - FLAG_VALUE_LOCAL_VAT_INCL: ClassVar[str] = 'value-local-vat-incl' - FLAG_VALUE_LOCAL_VAT_EXCL: ClassVar[str] = 'value-local-vat-excl' id_price = db.Column(db.Integer, primary_key=True) id_permutation = db.Column(db.Integer) @@ -87,7 +85,7 @@ class Product_Price(db.Model, Store_Base): self.ATTR_ID_PRODUCT: self.id_product, self.ATTR_ID_PRODUCT_CATEGORY: self.id_category, self.FLAG_CURRENCY: self.currency.to_json(), - # Delivery_Region.ATTR_ID_DELIVERY_REGION: self.id_region, + # Region.ATTR_ID_REGION_DELIVERY: self.id_region, self.FLAG_VALUE_LOCAL_VAT_INCL: self.value_local_VAT_incl, self.FLAG_VALUE_LOCAL_VAT_EXCL: self.value_local_VAT_excl, self.FLAG_DISPLAY_ORDER: self.display_order @@ -101,7 +99,7 @@ class Product_Price(db.Model, Store_Base): price.id_product = json[cls.ATTR_ID_PRODUCT] price.id_category = json[cls.ATTR_ID_PRODUCT_CATEGORY] price.currency = Currency.from_json(json) - # price.id_region = json[Delivery_Region.ATTR_ID_DELIVERY_REGION] + # price.id_region = json[Region.ATTR_ID_REGION_DELIVERY] price.value_local_VAT_incl = json[cls.FLAG_VALUE_LOCAL_VAT_INCL] price.value_local_VAT_excl = json[cls.FLAG_VALUE_LOCAL_VAT_EXCL] price.display_order = json[cls.FLAG_DISPLAY_ORDER] diff --git a/business_objects/store/product_variation_tree.py b/business_objects/store/product_variation_tree.py index 392c8798..c434b746 100644 --- a/business_objects/store/product_variation_tree.py +++ b/business_objects/store/product_variation_tree.py @@ -82,6 +82,7 @@ class Product_Variation_Tree(): @classmethod def from_json_str(cls, json_str): variations = [] + if json_str is None or json_str == '': return None for json_variation in json_str.split(','): parts = json_variation.split(':') if len(parts) != 2: continue diff --git a/business_objects/store/stock_item.py b/business_objects/store/stock_item.py index df44f8d9..6ecfc783 100644 --- a/business_objects/store/stock_item.py +++ b/business_objects/store/stock_item.py @@ -13,13 +13,15 @@ import lib.argument_validation as av from lib import data_types from forms.store.stock_item import Filters_Stock_Item from business_objects.db_base import Get_Many_Parameters_Base -from business_objects.store.product_price import Product_Price +from business_objects.currency import Currency # from business_objects.discount import Discount +from business_objects.store.product_variation_tree import Product_Variation_Tree +from business_objects.store.storage_location import Storage_Location from business_objects.store.store_base import Store_Base from extensions import db # external from dataclasses import dataclass -from typing import ClassVar +from typing import ClassVar, Optional from datetime import datetime @@ -34,21 +36,19 @@ class Stock_Item(db.Model, Store_Base): FLAG_DATE_UNSEALED: ClassVar[str] = 'date_unsealed' FLAG_IS_CONSUMED: ClassVar[str] = 'is_consumed' FLAG_IS_SEALED: ClassVar[str] = 'is_sealed' - FLAG_VALUE_LOCAL_VAT_EXCL_COST: ClassVar[str] = f'{Product_Price.FLAG_VALUE_LOCAL_VAT_EXCL}_cost' - FLAG_VALUE_LOCAL_VAT_INCL_COST: ClassVar[str] = f'{Product_Price.FLAG_VALUE_LOCAL_VAT_INCL}_cost' id_stock = db.Column(db.Integer, primary_key=True) id_permutation = db.Column(db.Integer) id_product = db.Column(db.Integer) id_category = db.Column(db.Integer) - # name_category = db.Column(db.String(255)) - # name_product = db.Column(db.String(255)) + id_location_storage = db.Column(db.Integer) + id_plant = db.Column(db.Integer) + id_region = db.Column(db.Integer) + id_currency_cost = db.Column(db.Integer) + cost_local_VAT_excl = db.Column(db.Float) + cost_local_VAT_incl = db.Column(db.Float) date_purchased = db.Column(db.DateTime) date_received = db.Column(db.DateTime) - id_location_storage = db.Column(db.Integer) - id_currency_cost = db.Column(db.Integer) - cost_local_VAT_incl = db.Column(db.Float) - cost_local_VAT_excl = db.Column(db.Float) is_sealed = db.Column(db.Boolean) date_unsealed = db.Column(db.DateTime) date_expiration = db.Column(db.DateTime) @@ -60,10 +60,15 @@ class Stock_Item(db.Model, Store_Base): can_edit = db.Column(db.Boolean) can_admin = db.Column(db.Boolean) """ + # variation_tree: Product_Variation_Tree = None def __init__(self): super().__init__() Store_Base.__init__(self) + self.currency_cost = None + self.storage_location = None + self.variation_tree = None + self.has_variations = False def from_DB_stock_item(query_row): _m = 'Product.from_DB_stock_item' @@ -73,21 +78,20 @@ class Stock_Item(db.Model, Store_Base): stock_item.id_permutation = query_row[1] stock_item.id_product = query_row[2] stock_item.id_category = query_row[3] - # stock_item.name_category = query_row[4] - # stock_item.name_product = query_row[5] - stock_item.date_purchased = query_row[4] - stock_item.date_received = query_row[5] - stock_item.id_location_storage = query_row[6] - # stock_item.name_location_storage = query_row[9] - stock_item.id_currency_cost = query_row[7] - stock_item.cost_local_VAT_incl = query_row[8] - stock_item.cost_local_VAT_excl = query_row[9] - stock_item.is_sealed = av.input_bool(query_row[10], "is_sealed", _m, v_arg_type=v_arg_type) - stock_item.date_unsealed = query_row[11] - stock_item.date_expiration = query_row[12] - stock_item.is_consumed = av.input_bool(query_row[13], "is_consumed", _m, v_arg_type=v_arg_type) - stock_item.date_consumed = query_row[14] - stock_item.active = av.input_bool(query_row[15], "active", _m, v_arg_type=v_arg_type) + stock_item.id_location_storage = query_row[4] + stock_item.storage_location = Storage_Location.from_DB_stock_item(query_row) + stock_item.id_currency_cost = query_row[12] + stock_item.currency_cost = Currency.from_DB_stock_item(query_row) + stock_item.cost_local_VAT_excl = query_row[15] + stock_item.cost_local_VAT_incl = query_row[16] + stock_item.date_purchased = query_row[17] + stock_item.date_received = query_row[18] + stock_item.is_sealed = av.input_bool(query_row[19], "is_sealed", _m, v_arg_type=v_arg_type) + stock_item.date_unsealed = query_row[20] + stock_item.date_expiration = query_row[21] + stock_item.is_consumed = av.input_bool(query_row[22], "is_consumed", _m, v_arg_type=v_arg_type) + stock_item.date_consumed = query_row[23] + stock_item.active = av.input_bool(query_row[24], "active", _m, v_arg_type=v_arg_type) """ stock_item.can_view = av.input_bool(query_row[24], "can_view", _m, v_arg_type=v_arg_type) stock_item.can_edit = av.input_bool(query_row[25], "can_edit", _m, v_arg_type=v_arg_type) @@ -99,96 +103,55 @@ class Stock_Item(db.Model, Store_Base): def from_json(cls, json): stock_item = cls() stock_item.id_stock = json[cls.ATTR_ID_STOCK_ITEM] - stock_item.id_permutation = json[cls.ATTR_ID_PRODUCT_PERMUTATION] + stock_item.id_permutation = json.get(cls.ATTR_ID_PRODUCT_PERMUTATION, 0) stock_item.id_product = json[cls.ATTR_ID_PRODUCT] stock_item.id_category = json[cls.ATTR_ID_PRODUCT_CATEGORY] + print(f'json: {json}\nhalf stock item: {stock_item}') + stock_item.variation_tree = Product_Variation_Tree.from_json_str(json[cls.FLAG_PRODUCT_VARIATIONS]) stock_item.date_purchased = json[cls.FLAG_DATE_PURCHASED] stock_item.date_received = json[cls.FLAG_DATE_RECEIVED] - stock_item.id_location_storage = json[cls.ATTR_ID_LOCATION_STORAGE] + stock_item.id_location_storage = json[cls.ATTR_ID_STORAGE_LOCATION] stock_item.id_currency_cost = json[cls.ATTR_ID_CURRENCY_COST] - stock_item.cost_local_VAT_incl = json[cls.FLAG_VALUE_LOCAL_VAT_INCL_COST] - stock_item.cost_local_VAT_excl = json[cls.FLAG_VALUE_LOCAL_VAT_EXCL_COST] + stock_item.cost_local_VAT_excl = json[cls.FLAG_COST_LOCAL_VAT_EXCL] + stock_item.cost_local_VAT_incl = json[cls.FLAG_COST_LOCAL_VAT_INCL] stock_item.is_sealed = json[cls.FLAG_IS_SEALED] stock_item.date_unsealed = json[cls.FLAG_DATE_UNSEALED] stock_item.date_expiration = json[cls.FLAG_DATE_EXPIRATION] stock_item.is_consumed = json[cls.FLAG_IS_CONSUMED] stock_item.date_consumed = json[cls.FLAG_DATE_CONSUMED] stock_item.active = json[cls.FLAG_ACTIVE] - """ - stock_item.can_view = json[cls.FLAG_CAN_VIEW] - stock_item.can_edit = json[cls.FLAG_CAN_EDIT] - stock_item.can_admin = json[cls.FLAG_CAN_ADMIN] - """ return stock_item - """ - def from_json(json_basket_item, key_id_product, key_id_permutation): - permutation = Product_Permutation.from_json(json_basket_item, key_id_product, key_id_permutation) - product = Product.from_permutation(permutation) - return product - - def output_lead_time(self): - return self.get_permutation_selected().output_lead_time() - def output_delivery_date(self): - return self.get_permutation_selected().output_delivery_date() - def output_price(self, is_included_VAT): - return self.get_permutation_selected().output_price(is_included_VAT) - def output_price_VAT_incl(self): - return self.get_permutation_selected().output_price(True) - def output_price_VAT_excl(self): - return self.get_permutation_selected().output_price(False) - def get_price_local(self, is_included_VAT): - if is_included_VAT: - return self.get_price_local_VAT_incl() - else: - return self.get_price_local_VAT_excl() - def get_price_local_VAT_incl(self): - return self.get_permutation_selected().get_price_local_VAT_incl() - def get_price_local_VAT_excl(self): - return self.get_permutation_selected().get_price_local_VAT_excl() - def get_quantity_min(self): - return self.get_permutation_selected().quantity_min - def get_id_permutation(self): - return self.get_permutation_selected().id_permutation - def get_image_from_index(self, index_image): - return self.get_permutation_selected().images[index_image] - def get_name(self): - return self.get_permutation_selected().name - def get_description(self): - return self.get_permutation_selected().description - def output_currency(self): - return self.get_permutation_selected().get_price().symbol_currency - def add_form_basket_add(self): - self.form_basket_add = None - - def add_form_basket_edit(self): - self.form_basket_edit = None - """ def __repr__(self): - return f'''Product + return f'''Stock Item + id_stock: {self.id_stock} + id_permutation: {self.id_permutation} id_product: {self.id_product} id_category: {self.id_category} - name: {self.name} - display_order: {self.display_order} - can_view: {self.can_view} - can_edit: {self.can_edit} - can_admin: {self.can_admin} - has_variations: {self.has_variations} - permutations: {self.permutations} - variation trees: {self.variation_trees} + variations: {self.variation_tree.to_preview_str() if self.variation_tree is not None else 'None'} + storage_location: {self.storage_location} + currency: {self.currency_cost} + cost_local_VAT_excl: {self.cost_local_VAT_excl} + cost_local_VAT_incl: {self.cost_local_VAT_incl} + date_purchased: {self.date_purchased} + date_received: {self.date_received} + is_sealed: {self.is_sealed} + date_unsealed: {self.date_unsealed} + date_expiration: {self.date_expiration} + is_consumed: {self.is_consumed} + date_consumed: {self.date_consumed} + active: {self.active} ''' def to_json(self): return { **self.get_shared_json_attributes(self), - self.ATTR_ID_PRODUCT: {self.id_product}, - self.ATTR_ID_PRODUCT_CATEGORY: {self.id_category}, - self.FLAG_NAME: {self.name}, - self.FLAG_DISPLAY_ORDER: {self.display_order}, - self.FLAG_CAN_VIEW: {self.can_view}, - self.FLAG_CAN_EDIT: {self.can_edit}, - self.FLAG_CAN_ADMIN: {self.can_admin}, - self.FLAG_HAS_VARIATIONS: {self.has_variations}, - self.FLAG_PRODUCT_PERMUTATION: {self.permutations}, - self.FLAG_PRODUCT_VARIATION_TREES: {self.variation_trees}, + self.ATTR_ID_STOCK_ITEM: self.id_stock, + self.ATTR_ID_PRODUCT_PERMUTATION: self.id_permutation, + self.ATTR_ID_PRODUCT: self.id_product, + self.ATTR_ID_PRODUCT_CATEGORY: self.id_category, + self.FLAG_STORAGE_LOCATION: self.storage_location.to_json(), + self.FLAG_CURRENCY_COST: self.currency_cost.to_json(), + self.FLAG_COST_LOCAL_VAT_EXCL: self.cost_local_VAT_excl, + self.FLAG_COST_LOCAL_VAT_INCL: self.cost_local_VAT_incl, } def has_permutations(self): return len(self.permutations) > 0 @@ -224,12 +187,11 @@ class Parameters_Stock_Item(Get_Many_Parameters_Base): a_ids_region_storage: str a_get_all_plant_storage: bool a_get_inactive_plant_storage: bool - a_get_first_plant_storage_only: bool a_ids_plant_storage: str a_get_all_location_storage: bool a_get_inactive_location_storage: bool a_ids_location_storage: str - a_date_received_to: datetime + a_date_received_to: Optional[datetime] = None a_get_sealed_stock_item_only: bool a_get_unsealed_stock_item_only: bool a_get_expired_stock_item_only: bool @@ -244,7 +206,7 @@ class Parameters_Stock_Item(Get_Many_Parameters_Base): def get_default(cls): return cls( # a_id_user = id_user, - a_get_all_product_permutation = True, + a_get_all_product_permutation = False, a_get_inactive_product_permutation = False, a_ids_product_permutation = '', a_get_all_stock_item = True, @@ -270,4 +232,71 @@ class Parameters_Stock_Item(Get_Many_Parameters_Base): @classmethod def from_form_stock_item(cls, form): - return cls.get_default() \ No newline at end of file + return cls.get_default() + + +class Stock_Item_Temp(db.Model, Store_Base): + __tablename__: ClassVar[str] = 'Shop_Stock_Item_Temp' + __table_args__ = { 'extend_existing': True } + id_stock: int = db.Column(db.Integer, primary_key=True) + # id_category: int = db.Column(db.Integer) + id_product: int = db.Column(db.Integer) + # has_variations: bool = db.Column(db.Boolean) + id_permutation: int = db.Column(db.Integer) + id_pairs_variations: str = db.Column(db.String(4000)) + date_purchased: datetime = db.Column(db.DateTime) + date_received: datetime = db.Column(db.DateTime, nullable=True) + id_location_storage: int = db.Column(db.Integer) + id_currency_cost: int = db.Column(db.Integer) + cost_local_VAT_excl: float = db.Column(db.Float) + cost_local_VAT_incl: float = db.Column(db.Float) + is_sealed: bool = db.Column(db.Boolean) + date_unsealed: datetime = db.Column(db.DateTime, nullable=True) + date_expiration: datetime = db.Column(db.DateTime, nullable=True) + is_consumed: bool = db.Column(db.Boolean) + date_consumed: datetime = db.Column(db.DateTime, nullable=True) + active: bool = db.Column(db.Boolean) + guid: str = db.Column(db.String(36)) + + @classmethod + def from_stock_item(cls, stock_item): + row = cls() + row.id_stock = stock_item.id_stock + # row.id_category = stock_item.id_category + row.id_product = stock_item.id_product + row.id_permutation = stock_item.id_permutation + # row.has_variations = stock_item.has_variations + row.id_pairs_variations = stock_item.variation_tree.to_json_str() if stock_item.variation_tree is not None else '' + row.date_purchased = stock_item.date_purchased + row.date_received = stock_item.date_received if stock_item.date_received else None + row.id_location_storage = stock_item.id_location_storage + row.id_currency_cost = stock_item.id_currency_cost + row.cost_local_VAT_excl = stock_item.cost_local_VAT_excl + row.cost_local_VAT_incl = stock_item.cost_local_VAT_incl + row.is_sealed = 1 if stock_item.is_sealed else 0 + row.date_unsealed = stock_item.date_unsealed if stock_item.date_unsealed else None + row.date_expiration = stock_item.date_expiration if stock_item.date_expiration else None + row.is_consumed = 1 if stock_item.is_consumed else 0 + row.date_consumed = stock_item.date_consumed if stock_item.date_consumed else None + row.active = 1 if stock_item.active else 0 + return row + def __repr__(self): + return f''' +id_stock: {self.id_stock} +id_product: {self.id_product} +id_permutation: {self.id_permutation} +id_pairs_variations: {self.id_pairs_variations} +date_purchased: {self.date_purchased} +date_received: {self.date_received} +id_location_storage: {self.id_location_storage} +id_currency_cost: {self.id_currency_cost} +cost_local_VAT_excl: {self.cost_local_VAT_excl} +cost_local_VAT_incl: {self.cost_local_VAT_incl} +is_sealed: {self.is_sealed} +date_unsealed: {self.date_unsealed} +date_expiration: {self.date_expiration} +is_consumed: {self.is_consumed} +date_consumed: {self.date_consumed} +active: {self.active} +guid: {self.guid} + ''' \ No newline at end of file diff --git a/business_objects/store/storage_location.py b/business_objects/store/storage_location.py index 72c8ff48..170291b0 100644 --- a/business_objects/store/storage_location.py +++ b/business_objects/store/storage_location.py @@ -12,6 +12,7 @@ Business object for product # internal import lib.argument_validation as av +from business_objects.store.plant import Plant from business_objects.store.store_base import Store_Base from extensions import db # external @@ -27,19 +28,33 @@ class Storage_Location(db.Model, Store_Base): code = db.Column(db.String(50)) name = db.Column(db.String(255)) active = db.Column(db.Boolean) + + # plant = None def __init__(self): super().__init__() Store_Base.__init__(self) + self.plant = None + @classmethod def from_DB_storage_location(cls, query_row): location = cls() location.id_location = query_row[0] location.id_plant = query_row[1] + location.plant = Plant.from_DB_storage_location(query_row) location.code = query_row[2] location.name = query_row[3] location.active = query_row[4] return location + @classmethod + def from_DB_stock_item(cls, query_row): + location = cls() + location.id_location = query_row[4] + location.id_plant = query_row[5] + location.code = query_row[8] + location.name = query_row[9] + location.plant = Plant.from_DB_stock_item(query_row) + return location def __repr__(self): return f''' {self.ATTR_ID_STORAGE_LOCATION}: {self.id_location} @@ -67,3 +82,6 @@ class Storage_Location(db.Model, Store_Base): location.name = json[cls.FLAG_NAME], location.active = json[cls.FLAG_ACTIVE] return location + + def get_full_name(self): + return f'{self.plant.name} - {self.name}' \ No newline at end of file diff --git a/business_objects/store/store_base.py b/business_objects/store/store_base.py index fc921720..48b52505 100644 --- a/business_objects/store/store_base.py +++ b/business_objects/store/store_base.py @@ -58,9 +58,9 @@ class I_Store_Base(): class Store_Base(Base): # ATTR_ID_CURRENCY_COST: ClassVar[str] = 'id_currency_cost' + ATTR_ID_DELIVERY_OPTION: ClassVar[str] = 'id_delivery_option' ATTR_ID_DISCOUNT: ClassVar[str] = 'id_discount' ATTR_ID_IMAGE: ClassVar[str] = 'id_image' - ATTR_ID_LOCATION_STORAGE: ClassVar[str] = 'id_location_storage' ATTR_ID_PLANT: ClassVar[str] = 'id_plant' ATTR_ID_PRODUCT: ClassVar[str] = 'id_product' ATTR_ID_PRODUCT_CATEGORY: ClassVar[str] = 'id_category' @@ -70,10 +70,15 @@ class Store_Base(Base): ATTR_ID_PRODUCT_VARIATION: ClassVar[str] = 'id_variation' ATTR_ID_PRODUCT_VARIATION_TYPE: ClassVar[str] = 'id_type' ATTR_ID_STOCK_ITEM: ClassVar[str] = 'id_stock_item' - FLAG_CURRENCY: ClassVar[str] = 'currency' + ATTR_ID_STORAGE_LOCATION: ClassVar[str] = 'id_location' + FLAG_COST_LOCAL: ClassVar[str] = 'cost_local' + FLAG_COST_LOCAL_VAT_EXCL: ClassVar[str] = FLAG_COST_LOCAL + '_vat_excl' + FLAG_COST_LOCAL_VAT_INCL: ClassVar[str] = FLAG_COST_LOCAL + '_vat_incl' FLAG_DELIVERY_OPTION: ClassVar[str] = 'delivery_option' FLAG_HAS_VARIATIONS: ClassVar[str] = 'has_variations' FLAG_IS_OUT_OF_STOCK: ClassVar[str] = 'is_out_of_stock' + FLAG_DISCOUNT: ClassVar[str] = 'discount' + FLAG_PLANT: ClassVar[str] = 'plant' FLAG_PRODUCT: ClassVar[str] = 'product' FLAG_PRODUCT_CATEGORY: ClassVar[str] = 'product_category' FLAG_PRODUCT_IMAGE: ClassVar[str] = 'product_image' @@ -85,6 +90,7 @@ class Store_Base(Base): FLAG_QUANTITY_MIN: ClassVar[str] = 'quantity_min' FLAG_QUANTITY_MAX: ClassVar[str] = 'quantity_max' FLAG_STOCK_ITEM: ClassVar[str] = 'stock_item' + FLAG_STORAGE_LOCATION: ClassVar[str] = 'storage_location' FLAG_TEXT: ClassVar[str] = 'text' FLAG_VALUE_TEXT: ClassVar[str] = 'value_text' \ No newline at end of file diff --git a/business_objects/user.py b/business_objects/user.py index d6b3f457..8dcbcd71 100644 --- a/business_objects/user.py +++ b/business_objects/user.py @@ -38,7 +38,9 @@ class User(db.Model, Base): # is_logged_in: bool def __init__(self): + self.id_user = 0 self.is_logged_in = False + super().__init__() def from_DB_user(query_row): _m = 'User.from_DB_user' @@ -62,7 +64,7 @@ class User(db.Model, Base): _m = 'User.from_json' user = User() if json is None: return user - print(f'json: {json}') + print(f'{_m}\njson: {json}') user.id_user = json['id_user'] user.id_user_auth0 = json['id_user_auth0'] user.firstname = json['firstname'] @@ -85,7 +87,7 @@ class User(db.Model, Base): _m = 'User.from_json_auth0' user = User() if json is None: return user - print(f'json: {json}') + print(f'{_m}\njson: {json}') user_info = json['userinfo'] user.id_user = None user.id_user_auth0 = user_info['sub'] @@ -136,11 +138,6 @@ class User(db.Model, Base): can_admin_user: {self.can_admin_user} ''' - @staticmethod - def get_default(): - user = User() - user.id_user = None - return user @dataclass diff --git a/controllers/__pycache__/__init__.cpython-312.pyc b/controllers/__pycache__/__init__.cpython-312.pyc index 387d9b83c5a52dfb7ad3b46325a6046267aea3e6..ce29ae52ff041f81a5a53483b88af0c22d340e7f 100644 GIT binary patch delta 40 ucmX@ic$|^vG%qg~0}wpwWlEpOW5k#?(cYgsIX|zYC_g7BwWxUFR6PLcqzuad delta 36 qcmX@kc$ksrG%qg~0}#YJol2X?W5k#=(cYiED8IBMGcSGOOg#X%j0+I} diff --git a/controllers/__pycache__/core.cpython-312.pyc b/controllers/__pycache__/core.cpython-312.pyc index 5c685fa271d1ff75ea584e3ae22808ee6727f580..0840b30c7b99d13c16780bdb768cda2cd7eb0ee8 100644 GIT binary patch delta 546 zcmeyX{ZEhYG%qg~0}wni=1hOUzmac&0Aumw^#aCB0gRIq_@!KG7_yi^@~EI#q=XeF zQo;^nr7*5$gs@?BFauCO$K;3H!jfQHU@9SWu@+3$o(EM1#3SC068_1rS>>e#U}mT= z6e-p+l?cQ5C8Cp6+3ba?1d8%YOHzyDlkUwe)fxL1{Fta$mv^cdW zJ|{mtJvAjhGp~prC|(3Iwa6Nzfpx(iHgJ0x2zuF~!wI{;TbKEbem|d1JzbtHVfyd&8far9t ziCotOv@Qu~tw>#;wKD6vp8F*|_dDn+C;t|-)-Bcm8s4PoXw9(39!MP2;RTV_oKC9D zhgig%6qpZ5F@o3%tUz+JwU95949Hz889oC^h9UzX@r%PIH$SB`C)KVfYx5EjH%4J@ UM$ymA3``M>ADMv6qD-J7024ZT+yDRo delta 125 zcmeyT_g9jjJ_$MMgY>?5SZ##+P*l%9N0$XLc7 z$Os4GVlN=k!0>^Eg;nd0fa+xd^$ym_A;Q+IMZQ3Z&3lA>nHc>ibBReYW^7g!b7K@{ VV-)?&%)k`E_>l?7EJ_Ee0swXZ9G%qg~0}wpwWlG=3BhJQ{JXwX!pF24}ucRnHCnvS2cykq77$*Q78Vytc delta 40 ucmca2e?gw-G%qg~0}y;W{UmK8k2o7+{A3k2fA*sM(vr-)^v!i_VVnR4u?*Az diff --git a/controllers/__pycache__/user.cpython-312.pyc b/controllers/__pycache__/user.cpython-312.pyc index 59df130751d1d2560cce51807cf0bc5073fa0190..2d74953b6aa8eb0d43f54f3e33379e8b959b177b 100644 GIT binary patch delta 357 zcmccX^u(F(G%qg~0}w=B;YjzC-N?rw!}x2mxXcR1+{p)IEGFNP=43oGnMqckv1amo zNzs^MkrGajau6uthR_TQDU7QbA#4~O%uvD$mu0G9Si`)U3Bs>stYHjhP-ZCMgUPEf z6p7X{l?YBwmeprx@hi#!N=%+2tLVU4!~$d%34;g`AaP4DvpBxAIJGD~CqF$sH6=bX zuZSNcDF7ls-Y9Yh5gtH7les8=@(o#i!&o4vf#CxSJFD0o0r@4|Yl1Ed7<91S;1{{h zuXc%F?TN7T9QO+;EbI)WZS$(4t zc92>SNMWpDSi`iM3Bs#otYHjhP-ZCMfbba@R2YgxYne*8Coh)OXJYo7d{b6YnXL$9 zT#+z{5CIV&n~U5*ga?q&WG>2^Y$c~J?hNEKFnnNPVHLY0AisorP0(clgAUfov*Zk= z#DQ{6imD7tIUSjq*Kye~?_dNn_OUuLZ~h>6h*2>IWLgxESjkY71!CI(iC-Kxx%nxj dIjMFKpIU7rSYnoek7!loNu(Ws|ZF0kpbGm0M zYntaDnCU&!ge#xs&Y|Q7o|nR|0q)s=b*M#ncCcZnNmy<&4Ykn6QZu@>v@Ug^ z2n^p~Tz}hZSZ_4`(tw08+7?%;t62<0(=|7pHYH2*DC7^MQI7xlh=$ zhJ){L@NQ`p_goyQ@=kgc&v-s4?lmR2q6F8Sjpe4^RcEwZ7p0%^jlFSh*_?!?+DAqSL&zrfkh9Qro^c*K2fd`&^7|Utyc5SvyA#os*z9Bj9<7`ehIOXy1YA z=ofpcISeHv0#Fg>vZplC12p6#Yy{Fv^NucGlu^u}k3ozwA@(&{ke7vR(W{Ek*_OV^z}2*he!Q^G4s z_#3gFxNdj&xn*ynW6aMzKRE0M_u6kwMugX$gUOKarVRmq6EYapWTM<#|(5O$eGZUd03-Sw+w-z+?-eC7aA>7yMB&N`Gt8v@6t nP?cxA+C+cx2JCKxSyY86&}uim<_)-ZZ3a{5GY^#f3Wxp+%)bL# delta 833 zcmZ{hOH5Ni6ozN+quk!x_q7iShGLOYrIeSVfSN+FT^Jw~j2cPX*h<mH>+nO*td8StW$q+zS!Di$m(A1iFLo;yliyY5pq8W3L8!H8n7+ zIZoT2X`11;W)A1zaaq9pRdH@rw7s_OD4{JO^y{YrWs*;|p%t693-c>gjzA~B(kXUf z2uVk|GzW9~E3hoRhm72U9k8fZ!LOCE6Sj@2ol939T;^YzN zS1$D4GF%)dW3E(YDn6P@G|2OqcxWRuC^gs&5oHoSD2>CUmU>>HASB|scxeMUMjcW| zkrgOhw1}6Ag5hRrG?ygN2{N9TypbbkshMNjM2yf3`leVvDYe^5?bG~6#Xl1)awfQ@ z8-ak;2}Rv>wHvK!0+rovwC2_ZoB6f+j-ZcU_h72meIh0FN;cfO^hE!Kv*jx2;8G>D z&*^wp7=ho|g6m4DWDGJs0cNum_Dm|5_8*4O2uX7m%kbIk!!&J6%u!E!3qmF}ktIGV zz2!ur3u%B^%Sor7Nrj=2p^2fHp#|Pp&Q-TEd5YmQLmNXWF^QaE+5`1!d#Dr^8_L3B zbr6^?8=p!Z#ucLf@6j*2^Pjk?mljk%hTS8NJQ7;92RtDOtzGDr=&~Vc!*+hd+!40$ zn>tMOrbP_fmlmxY*UsLdU=If(;b>KEb_7C(0hq?y|J9ZxJQ=-zX{z#o; z^!-MY=gBbqus^V9aTxFOh>PJO$8^yK_Z=>i1uM*rQkTkN9lUb5RQG`y!@C@nRpd8`i(?y9)^``0*Jwnf9;+_P?}uSJ;T8vB}s$z}`kIdNdu;9hv-Y~XM5Fzq}5 zo9(Y-s6(T9lDgMrBVw-df_dr-1fEGL(gbO#nJk5@6b!0nRo$0bVZask6nS&oAlJ$n zVVIC~BEl+1G-}y-%Dt^Z%W84tcy73uk2&rVs$qv8zI`Z!I#MyzMKQ1f%8nJp2Ui`V z4!RO+=n4d|$%%BEI49a-Esy*DKHJ#eh!#(ej`X%9ou(4kh zUi1>=FGWkg1P`4dl9-rsKILQMmJ*x!kD-|DW+-nrRY5TaJSnmk#q@VAe50(U6f-O9 z9=j&$E0dK{|C4zQ^m)F8*f_eDK@_1aOs$N^V3)T&9A{Kwz?#w|gAN8MxaQ4heT366{s2CD4S%6?+($V$D{F6L z?ao+Dj-T5)&o7_QeJa5Vh|DU{872D91uTOne!6_F-t32cQ@N5K9WM0JLvXX8|vh2I#UaS zF1qNVcrUt(2qCO)V%HHmQ=uCpArSGZt00)HAR?mon^Z4+&-**i_kQR5c%HUB@>|}U z%?d{~x_KCX<9uy75JADO;^T@;IkQ?2X`Hr#0%Wz7c z(h}2ik;z1~MOg*Cp5BaS)H<-@Rdp8k)z)FXjy$ipCq^TgNNGUV$kE*-X^}*u(me!w zP`nMj~jbc#45kL3)OIDb4-`*%Mozl0+O4#SoXXrLr&pb-zv zcEONrW-)*t&nsSN#dFs0&PJNv6Q>h1X}yWi>(V7^dNW?MHC6c-nwYdO@iS><(uNOh zp_AvFvRsV9Zz-zgTT?6C3Y`!0VU@nE1KbCD6?%~!Q0T;D=+mK9cv&R%N30p#M zNEEgPfOuOpgiN{Xl{^pK7<0I**?m5R6peD1hsbHODj3LL)# l1)g!C3;Uf~MJ1@rT_BgR(1KG=&3@|0T!cfOP#>e8{sCvtxqkov diff --git a/controllers/store/__pycache__/product_permutation.cpython-312.pyc b/controllers/store/__pycache__/product_permutation.cpython-312.pyc index fbaea038d28e0995f7d952a7872ac3af99893756..bbc800b52479d5b8d433b45f64d607c51e977ff0 100644 GIT binary patch delta 1144 zcmZ`$U1(Eh7(UITS^A@PgH5p(HW0FCvNj<<@|_ba zqnpJ$2b;*tU_vjq3)w)Ww_eQZXkoBrjZmpxdLx4C)?G+1#P>@{y9&PWJ@50q@B96{ z@AGT&-<0cjr&H$8N)K(5yY}629hb-$Oi16Kn&FEsme^@Vo9S&uOka!T#GlC~Z~1Y~ z^lxRQ8U7awY)BKnQjYtId`+gwGXiV_AV=XpSlBc)_Sz3 z5ll7Qy>(mf6D3p+k1S0*RL1M#_{;yi@WPt#^>O$5?8AG6dxOE@h_DcmhWCJO+s*&L zL(=&v{ABw>#{mReEo^&3F~hB0PH44zg}|S-6nx|I!AV&m@4|JPFTfY0t;%g*?0~=R z8VSKWvOz@nR!$_OPrh^=uhMd~P`Q{b6>_?KlTZzhY^W31cC=D8qnoW`1vKP+M1_}f zO{QH~Lpu?mtaP8%#8okuHM7m5w1ediAQ&P-6phA_tg2rWN+!-+MD$a6G75|D7`%8)aINeYV&5o||D!fvr{EysiEAH5`JN85k*CX8xHCcBg;g%x= zvyMwg(%gb&C^eGi?x*d??7{<~|ClH|I7*QJCQ69s@r5n3Aro+|pPTP?KIYRiQjvA@ zhT*W;r<<0uZx8!_637tnd_WGukkbdRoHEgyqnC=^t#jMHm}-vx04#b8L7B0@HQ5iR zy}O753f`&RI#$v{2&-bHaKWJL1}#MGES!XA-gu~oQ3rz*gI)%Q8T5g!ejMA9gTBXt zM;N@%AdR3|X+Pr{%&CVzY6@e;Jrf3PQyY(wy_nyj%!gQV8JF?mEy{Gvhkd;Sr3tUN z6U*+z4rxxd-RNxR76L<^C)&CDgCp(e7TfJ(y0F;QKc)#w9R&H3CXMOyZvQAx2H;FU zi?By;a_fj(^IsdbfpRrhE9H;U&*4U3PIZtoWL@C+QGShQd@TYef^kn9QCM^Yqe#~d U!j)j$w|_G@%KyV7r5U{RHO%t@#sB~S delta 783 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 LtPe;`Q1yQTReTiZ literal 6568 zcmcgwUrZZE8lUwa{1-4J!QoF}2_(S@F{yzP2)W7$5Yj+Ev6CuW(v9&hW}RKzon423 zOx2U_frnP=+eNBQ>O&u{Y9CtZq~@{zq(-_I`{3ki1?oxHmwO{kPp#6I`)17Ai-A_D zsvFre-^_gT?Kd;u{JwAI@3pmV1ZnjslbGv7=-;GbB-;-06j>1ZGZGMo1V*sPjAG#| zij}h}HqOS7Hmht`YPcFo+hm90pq%DTD`&VfwClSb=cq}}@PTr)UzO8rl5=6%8)%7P1|jz>PAA2< zHo`)h4c~}H*jL1PRnkOvIIAtDG3{W-g{2r4*l9@+WKm0}&PEhTTXd5_Mw-Q9TvDZU ziVdd(_J*j6F&tlHqhfq9m6p?qWj3;`YNDdDQxXgo1-HA>H^PQ98TLjxt4XPZdqRw9 zSuD~|N3=8+S;*t}*sCy{GKs3&JtnGgEM+wK;)wfdO46j5EUkztt1XJ`gd9`vv9U}> zmf|tO(#xu%R_cqVQwvfei)lMMA5%qv1+B?2F?C69X-v|cs_(-6c3DMe&1rCAKx z0ol_>d-`JYP!GVcn8so;C5V^>^)hmdFfGCAP>E^=R%JngPiT@Ri)zsQAF@*ctL}i6 z7qW3pZ=8+cm?CN-R(YfC&9ioq{4Ggb z;xEDEfYE1aqU#B5&DCvuBukb{#L(Hfr_<2qGE6U##>>FeeIV0rrCay#?b6phDasiU z^I!ni10LN@w@$AwEh%p-sqRRs>6EmvtUIvydRA05y{U?YS2YaQqaRXXH~0mdR(L@I zqXYw5)}2@^Rdh!d%ltwb>kd^^iM{HsOLA7sz*tT9#IqR0YCM=uz@l4(dEK6l!9jqE z`}J&E6ZwpsRdp8#5mRwkX;=vR3^^)5xG6D?aT>!0+bO^91lCLptD^3t1^>FL`%AV2 z8iR3@JbsUdBcbTlE8|fRJTxT@ zz&9G8)M|`M(rHkY(vY)imTt|VchO%gMjwN;T4O{G8Lg`pt=?!AY&pwEb^{0_s0(S- zDUtqegpaQ>CfzMLrb>EQe*->O(QR;6tIQkBTT`WSiCIDqthdn;6R5ead%=8+L!z!Y z==zVaE48r63cpY~BNtbWWnu|Y?W0THXIgVLxTq;I*+zvNoPbleQ(M3eP*-_ zuykLX8%xKt1aj0lIAsaI0tL)??v|uxV=^FLR*=$c=v*i?NAZ~le4YdIoC6%wa9Wm$ zL^>;y?-)`rvy4v>%}90^{wi@0Z=&yPuC?HXt$EvGv-fWL14Vy-!QcP4E1yn%GPUjx zuX%rPBD;HS`eEORB~LeTvIgU^E6&pI!~AP$IWG4S$n5zec?&M&i-!xwZ18Za>r z-IowGe#blUWCVo_iX-?mVQ8eH!GrSY6t8CIAq>I|&_O{&_e@NMukev*IC?Xpdue4N ze0A#Pjq#n@^mrr^zA~=Yh{VIFJFStMmoGzy?z}dBn;#2D!+I@*Jk&|^vIKt8p{02W zV7>6EfK9hi)yUi^KH(rxDmh6clEZyK=#3@R zOY5G#H^;UuKD(!kC?Ail`-j)O-_*Aj>w|^*;70wq%|k7lzB5JNP{B8}F&r%p#|pzS z+H$_&JO60r@l<3q5)&Q4f(8`rTRIuIy zM~#R7FEh27p)mn4l(USXJ10RmTh5y7H0D<+wJw9+*PYpnois`Yz13qguavz6gq41+ z?DUe|hU`k2LrD@eR3)KCa2OF?&T3E)3zlVpTXGuTShbsW%4M_y_w(Bl38AWz$(9JL zR;8RhNr0{@B?+!oCBw$eI|9z?oWVw&Rn2eE`T6bNovYbx>pRY>=8YQate`YGE6??n zrk%SVOG3_y(^{!BhoB=YCQ;Lh?|PawLAe@S@ulaJ>TD%!zNkCmX@vx#D{f%kp>YUC z>$a4XQE@+zfoAIH@Bq+NzOCfK8cJSk=EgKXadj#>ej|bh2`_bWFA{2qWamjXOtJuE zdi{>$o4I_AzZxB%)~#^2(rX~bg^L^}7Z$xijopWZse+ar|x0yVJcsDcEcI` zm%nwRZK&9Gr2s$w-|NV;FXZb&8_xbsXIIfV zSa1%0EPT57$>O8s$Gz(>zLLMaxZ#w(^M^k3ZuqA`O=s=e!dtZm`)2CodyAo|LTIWO ziWWlA_0X+~gZ|x}JTa$t!xyeN(HH*kDJZ^t>9P}wubr+*zxC^e3zLo3$6f~L$BlN# z1Eacw=Y@2f=k@matV-UGR35AkULw>Wy{H8EBCt6X=oyc z+>mAJBqpmjQBzifC5ygKo`J|47bZ6=-M_b!YJ^>+mpz~tV%5^q5GFoe?>UHVXIi`w ze`4Ys^fSN4ZaRqAOGX?&XoP95fT^xX%OD-=FP+B?aM66t^^ClN0EcW9+SvHx6`*Ky>&7indE2T{s32unHx0U!P^LZCD5BG z2RuOSVW6?U-a`8$;ahtpP$c{SJ%#Tf3YO2Dqp*irS^NV|KpVg#yn{dv;J`3XEN;g3 zV+&&Dm;!or3!UFWgIg%Hg$B0J#1^`>h32-<%UdY0g}Q&VA?A+dM-XA;PbmE@V!uVf zE!4k-hQ39i0t!8;L9N~S?u(BethY?&k$>AZ%-FUcz`K5Pk!de5?fH(8V#lpQ$E|#9 zA%8cKXWG}9#U~aQbB%dwMHY$Kru25x?h(;KM>Nli`PUZch{O|1BjX_h7GVI8+daGa aZx%Xk=I<`#`SKUKO8gQ`97wzXi}62PEf;YB diff --git a/controllers/store/__pycache__/store.cpython-312.pyc b/controllers/store/__pycache__/store.cpython-312.pyc index edf2d77235b0853c4d9aad2039df21c1cbfab2af..7735cdd9afeffb64407e4340791a9fee1750648e 100644 GIT binary patch delta 44 ycmey(_n(jFG%qg~0}wpwWlG=3^M-{nbMj9Xf9~Y`ypp2)oSf96;?4f7I!pjcjSklU delta 40 ucmey*_nVLBG%qg~0}u%I-ALQW^M-{nb@ERZfA*sM(vr-)^v%JnI!pi!9}Ou0 diff --git a/controllers/store/__pycache__/supplier.cpython-312.pyc b/controllers/store/__pycache__/supplier.cpython-312.pyc index 5697d5d5355202f48b371dd8b16823e1ceb72f4b..bb02e2ea31ad34258bd1d007444074509d4261d6 100644 GIT binary patch delta 681 zcmew=*Q~&InwOW00SLNYbEQAy-NMMgA_`-ru&!o=uwisCLk)A5_~eOfB786*Mv#ysP)L(e8b}J)v(&Jru&ri>Xk=t4 z(S#evQNz53b2Sr$AIwl950fcTfU&ZaU@QcUB&&iDg|U!i)j(n*FbN2q!d1hRr8PN` zUBBL>f;p0*oKcyfL$Ylp) zf&5y$VsaW+l?FFw0@EE4-4!X9MT|RKZwO0V7uLEYto1}(ehK>p4Xeuv)|bU?E(q96 ze#f_ z!F*K6+D(}G7%wA`eN33uO=7buPcM@^$Pq;vK;knHGZfhZiC-Kxx%nxjIjMF6^0_W zS~l7^1ZD@+9c+{RIdmDhC)aWqOy19t!6-aggVS|$7pEg5mn~3<8W0!vO}@%i#mB*! zz;s7McSXu&5#tWm$>rROcuW~tg>LW*cC-BcqB2>PCq`EbsJuzQMV{dhha-!NCc_bV z78f<HueW(Fqfk4zwDQ7}*u03yy*WdHyG diff --git a/controllers/store/product.py b/controllers/store/product.py index 045b0bd5..94d06d8a 100644 --- a/controllers/store/product.py +++ b/controllers/store/product.py @@ -111,6 +111,9 @@ def products(): form_filters = Filters_Product() print(f'form_filters={form_filters}') model = Model_View_Store_Product(form_filters) + if not model.is_user_logged_in: + # return redirect(url_for('routes_user.login', data = jsonify({ Model_View_Store_Product.KEY_CALLBACK: Model_View_Store_Product.HASH_PAGE_STORE_PRODUCTS }))) + return redirect(url_for('routes_core.home')) return render_template('pages/store/_products.html', model = model) @routes_store_product.route(Model_View_Store_Product.HASH_GET_STORE_PRODUCT, methods=['POST']) @@ -124,6 +127,8 @@ def filter_product(): Model_View_Store_Product.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}' }) model = Model_View_Store_Product(form_filters = form_filters) + if not model.is_user_logged_in: + raise Exception('User not logged in') return jsonify({ Model_View_Store_Product.FLAG_STATUS: Model_View_Store_Product.FLAG_SUCCESS, Model_View_Store_Product.KEY_DATA: model.category_list.to_json() @@ -161,6 +166,8 @@ def save_product(): save_errors = Model_View_Store_Product.save_products(data.get('comment', 'No comment'), objsProduct) model_return = Model_View_Store_Product(form_filters=form_filters) + if not model_return.is_user_logged_in: + raise Exception('User not logged in') print('nips') return jsonify({ Model_View_Store_Product.FLAG_STATUS: Model_View_Store_Product.FLAG_SUCCESS, diff --git a/controllers/store/product_category.py b/controllers/store/product_category.py index 4eb4bf6b..d2b8fae4 100644 --- a/controllers/store/product_category.py +++ b/controllers/store/product_category.py @@ -54,6 +54,9 @@ def categories(): return redirect(url_for('routes_store_product_category.categories', **filters.to_json())) """ model = Model_View_Store_Product_Category(form_filters) + if not model.is_user_logged_in: + # return redirect(url_for('routes_user.login', data = jsonify({ Model_View_Store_Product_Category.KEY_CALLBACK: Model_View_Store_Product_Category.HASH_PAGE_STORE_PRODUCT_CATEGORIES }))) + return redirect(url_for('routes_core.home')) return render_template('pages/store/_product_categories.html', model = model) @routes_store_product_category.route(Model_View_Store_Product_Category.HASH_GET_STORE_PRODUCT_CATEGORY, methods=['POST']) @@ -70,6 +73,8 @@ def filter_category(): # ToDo: manually validate category, product # filters_form = Filters_Product_Category.from_form(form_filters) model = Model_View_Store_Product_Category(form_filters = form_filters) + if not model.is_user_logged_in: + raise Exception('User not logged in') return jsonify({ Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_SUCCESS, Model_View_Store_Product_Category.KEY_DATA: model.category_list.to_json() @@ -106,7 +111,8 @@ def save_category(): Model_View_Store_Product_Category.save_categories(data.get('comment', 'No comment'), objsCategory) model_return = Model_View_Store_Product_Category(form_filters=form_filters) - print('nips') + if not model_return.is_user_logged_in: + raise Exception('User not logged in') return jsonify({ Model_View_Store_Product_Category.FLAG_STATUS: Model_View_Store_Product_Category.FLAG_SUCCESS, Model_View_Store_Product_Category.KEY_DATA: model_return.category_list.to_json() diff --git a/controllers/store/product_permutation.py b/controllers/store/product_permutation.py index dfd42dce..9584d2b1 100644 --- a/controllers/store/product_permutation.py +++ b/controllers/store/product_permutation.py @@ -96,6 +96,9 @@ def permutations(): form_filters = Filters_Product_Permutation() print(f'form_filters={form_filters}') model = Model_View_Store_Product_Permutation(form_filters) + if not model.is_user_logged_in: + # return redirect(url_for('routes_user.login', data = jsonify({ Model_View_Store_Product_Permutation.KEY_CALLBACK: Model_View_Store_Product_Permutation.HASH_PAGE_STORE_PRODUCT_PERMUTATIONS }))) + return redirect(url_for('routes_core.home')) return render_template('pages/store/_product_permutations.html', model = model) @routes_store_product_permutation.route(Model_View_Store_Product_Permutation.HASH_GET_STORE_PRODUCT_PERMUTATION, methods=['POST']) @@ -109,6 +112,8 @@ def filter_permutation(): Model_View_Store_Product_Permutation.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}' }) model = Model_View_Store_Product_Permutation(form_filters = form_filters) + if not model.is_user_logged_in: + raise Exception('User not logged in') return jsonify({ Model_View_Store_Product_Permutation.FLAG_STATUS: Model_View_Store_Product_Permutation.FLAG_SUCCESS, Model_View_Store_Product_Permutation.KEY_DATA: model.category_list.to_json() @@ -146,6 +151,8 @@ def save_permutation(): Model_View_Store_Product_Permutation.save_permutations(data.get('comment', 'No comment'), objsPermutation) model_return = Model_View_Store_Product_Permutation(form_filters=form_filters) + if not model_return.is_user_logged_in: + raise Exception('User not logged in') print('nips') return jsonify({ Model_View_Store_Product_Permutation.FLAG_STATUS: Model_View_Store_Product_Permutation.FLAG_SUCCESS, diff --git a/controllers/store/stock_item.py b/controllers/store/stock_item.py index edbe07f7..82285608 100644 --- a/controllers/store/stock_item.py +++ b/controllers/store/stock_item.py @@ -11,91 +11,26 @@ Initializes the Flask application, sets the configuration based on the environme """ # internal -from business_objects.store.product import Product, Parameters_Product, Product_Permutation from business_objects.store.stock_item import Stock_Item from forms.store.stock_item import Filters_Stock_Item -from models.model_view_base import Model_View_Base -from models.model_view_store import Model_View_Store -from models.model_view_store_supplier import Model_View_Store_Supplier -from models.model_view_store_product_category import Model_View_Store_Product_Category -from models.model_view_store_product_permutation import Model_View_Store_Product_Permutation from models.model_view_store_stock_item import Model_View_Store_Stock_Item from helpers.helper_app import Helper_App import lib.argument_validation as av # external +from datetime import datetime from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session, Blueprint, current_app from extensions import db, oauth from urllib.parse import quote_plus, urlencode from authlib.integrations.flask_client import OAuth from authlib.integrations.base_client import OAuthError from urllib.parse import quote, urlparse, parse_qs - +import requests routes_store_stock_item = Blueprint('routes_store_stock_item', __name__) -""" -@routes_store_stock_item.route('/store/stock_items', methods=['GET']) -def stock(): - filters = Filters_Stock_Item.get_default() - model = Model_View_Store_Stock_Item(filters_stock_item=filters) - return render_template('pages/store/_stock_items.html', model = model) - -@routes_store_stock_item.route('/store/stock_item_filter', methods=['POST']) -def stock_filter(): - data = Helper_App.get_request_data(request) - form_filters = None - try: - form_filters = get_Filters_Stock_Items(data) - if not form_filters.validate_on_submit(): - return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}'}) - # ToDo: manually validate category, product - filters_form = Filters_Stock_Item.from_form(form_filters) - model = Model_View_Store_Stock_Item(filters_stock_item=filters_form) - return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_SUCCESS, 'Success': True, Model_View_Base.KEY_DATA: model.category_list.to_permutation_row_list()}) - except Exception as e: - return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Bad data received by controller.\n{e}'}) - -def get_Filters_Stock_Items(data_request): - data_form = data_request[Model_View_Store_Stock_Item.KEY_FORM] - form_filters = Filters_Stock_Item(**data_form) - form_filters.is_out_of_stock.data = av.input_bool(data_form['is_out_of_stock'], 'is_out_of_stock', 'permutations_post') - return form_filters - -@routes_store_stock_item.route('/store/stock_item_save', methods=['POST']) -def stock_save(): - data = Helper_App.get_request_data(request) -"" - form_filters = None - try: - form_filters = get_Filters_Stock_Items(data) - if not form_filters.validate_on_submit(): - return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Filters form invalid.\n{form_filters.errors}'}) - - stock_items = data[Model_View_Store_Stock.KEY_PERMUTATIONS] - print(f'stock_items: {stock_items}') - if len(stock_items) == 0: - return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_FAILURE, Model_View_Base.FLAG_MESSAGE: f'No stock items.'}) - objsStockItem = [] - for stock_item in stock_items: - objsStockItem.append(Product_Permutation.from_json(stock_item)) - print(f'objsStockItem: {objsStockItem}') - - # ToDo: manually validate category, product - filters_form = Stock_Filters.from_form(form_filters) - model_save = Model_View_Store_Stock(filters_product=filters_form) - model_save.save_stock_items(data.comment, objsPermutation) - - model_return = Model_View_Store_Stock(filters_product=filters_form) - return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_SUCCESS, 'Success': True, Model_View_Base.KEY_DATA: model_return.category_list.to_permutation_row_list()}) - except Exception as e: - return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Bad data received by controller.\n{e}'}) -"" -""" - - @routes_store_stock_item.route(Model_View_Store_Stock_Item.HASH_PAGE_STORE_STOCK_ITEMS, methods=['GET']) -def permutations(): - print('permutations') +def stock_items(): + print('stock_items') try: form_filters = Filters_Stock_Item.from_json(request.args) except Exception as e: @@ -103,19 +38,39 @@ def permutations(): form_filters = Filters_Stock_Item() print(f'form_filters={form_filters}') model = Model_View_Store_Stock_Item(form_filters) - return render_template('pages/store/_stock_items.html', model = model) + if not model.is_user_logged_in: + # return redirect(url_for('routes_user.login', data = jsonify({ Model_View_Store_Stock_Item.KEY_CALLBACK: Model_View_Store_Stock_Item.HASH_PAGE_STORE_STOCK_ITEMS }))) + # return requests.post(f"{current_app.config['URL_HOST']}{url_for('routes_user.login')}", json={ Model_View_Store_Stock_Item.KEY_CALLBACK: Model_View_Store_Stock_Item.HASH_PAGE_STORE_STOCK_ITEMS }) + return redirect(url_for('routes_core.home')) + return render_template('pages/store/_stock_items.html', model = model, datetime = datetime) @routes_store_stock_item.route(Model_View_Store_Stock_Item.HASH_GET_STORE_STOCK_ITEM, methods=['POST']) -def filter_permutation(): +def filter_stock_item(): data = Helper_App.get_request_data(request) try: form_filters = Filters_Stock_Item.from_json(data) if not form_filters.validate_on_submit(): - return jsonify({ - Model_View_Store_Stock_Item.FLAG_STATUS: Model_View_Store_Stock_Item.FLAG_FAILURE, - Model_View_Store_Stock_Item.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}' - }) - model = Model_View_Store_Stock_Item(form_filters = form_filters) + error_keys = list(form_filters.errors.keys()) + try: + error_keys.remove(Stock_Item.ATTR_ID_PRODUCT_CATEGORY) + """ + if not av.val_int(form_filters.id_product_category.data): + form_filters.errors[Stock_Item.ATTR_ID_PRODUCT_CATEGORY] = ['Invalid category.'] + """ + except: + pass + try: + error_keys.remove(Stock_Item.ATTR_ID_PRODUCT) + except: + pass + if error_keys: + return jsonify({ + Model_View_Store_Stock_Item.FLAG_STATUS: Model_View_Store_Stock_Item.FLAG_FAILURE, + Model_View_Store_Stock_Item.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}' + }) + model = Model_View_Store_Stock_Item(filters_stock_item = form_filters) + if not model.is_user_logged_in: + raise Exception('User not logged in.') return jsonify({ Model_View_Store_Stock_Item.FLAG_STATUS: Model_View_Store_Stock_Item.FLAG_SUCCESS, Model_View_Store_Stock_Item.KEY_DATA: model.category_list.to_json() @@ -127,33 +82,55 @@ def filter_permutation(): }) @routes_store_stock_item.route(Model_View_Store_Stock_Item.HASH_SAVE_STORE_STOCK_ITEM, methods=['POST']) -def save_permutation(): +def save_stock_item(): data = Helper_App.get_request_data(request) try: form_filters = Filters_Stock_Item.from_json(data[Model_View_Store_Stock_Item.FLAG_FORM_FILTERS]) + """ if not form_filters.validate_on_submit(): - return jsonify({ - Model_View_Store_Stock_Item.FLAG_STATUS: Model_View_Store_Stock_Item.FLAG_FAILURE, - Model_View_Store_Stock_Item.FLAG_MESSAGE: f'Filters form invalid.\n{form_filters.errors}' - }) + error_keys = list(form_filters.errors.keys()) + try: + error_keys.remove(Stock_Item.ATTR_ID_PRODUCT_CATEGORY) + "" + if not av.val_int(form_filters.id_product_category.data): + form_filters.errors[Stock_Item.ATTR_ID_PRODUCT_CATEGORY] = ['Invalid category.'] + "" + except: + pass + try: + error_keys.remove(Stock_Item.ATTR_ID_PRODUCT) + except: + pass + if error_keys: + return jsonify({ + Model_View_Store_Stock_Item.FLAG_STATUS: Model_View_Store_Stock_Item.FLAG_FAILURE, + Model_View_Store_Stock_Item.FLAG_MESSAGE: f'Form invalid.\n{form_filters.errors}' + }) + """ # filters_form = Filters_Stock_Item.from_form(form_filters) print(f'form_filters: {form_filters}') - permutations = data[Model_View_Store_Stock_Item.FLAG_STOCK_ITEM] - if len(permutations) == 0: + stock_items = data[Model_View_Store_Stock_Item.FLAG_STOCK_ITEM] + if len(stock_items) == 0: return jsonify({ Model_View_Store_Stock_Item.FLAG_STATUS: Model_View_Store_Stock_Item.FLAG_FAILURE, - Model_View_Store_Stock_Item.FLAG_MESSAGE: f'No permutations.' + Model_View_Store_Stock_Item.FLAG_MESSAGE: f'No stock items.' }) - objsPermutation = [] - for permutation in permutations: - objsPermutation.append(Stock_Item.from_json(permutation)) + print(f'stock_items={stock_items}') + objs_stock_item = [] + for stock_item in stock_items: + objs_stock_item.append(Stock_Item.from_json(stock_item)) # model_save = Model_View_Store_Stock_Item() # filters_product=filters_form) - print(f'objsPermutation={objsPermutation}') - Model_View_Store_Stock_Item.save_permutations(data.get('comment', 'No comment'), objsPermutation) - - model_return = Model_View_Store_Stock_Item(form_filters=form_filters) - print('nips') + print(f'objs_stock_item={objs_stock_item}') + save_errors = Model_View_Store_Stock_Item.save_stock_items(data.get('comment', 'No comment'), objs_stock_item) + if len(save_errors) > 0: + return jsonify({ + Model_View_Store_Stock_Item.FLAG_STATUS: Model_View_Store_Stock_Item.FLAG_FAILURE, + Model_View_Store_Stock_Item.FLAG_MESSAGE: f'Save errors: {save_errors}' + }) + model_return = Model_View_Store_Stock_Item(filters_stock_item=form_filters) + if not model_return.is_user_logged_in: + raise Exception('User not logged in.') return jsonify({ Model_View_Store_Stock_Item.FLAG_STATUS: Model_View_Store_Stock_Item.FLAG_SUCCESS, Model_View_Store_Stock_Item.KEY_DATA: model_return.category_list.to_json() diff --git a/controllers/store/supplier.py b/controllers/store/supplier.py index bf7d98a0..07837bb6 100644 --- a/controllers/store/supplier.py +++ b/controllers/store/supplier.py @@ -53,6 +53,9 @@ def supplier(): # if not logged in: try: model = Model_View_Store_Supplier(form) + if not model.is_user_logged_in: + # return redirect(url_for('routes_user.login', data = jsonify({ Model_View_Store_Supplier.KEY_CALLBACK: Model_View_Store_Supplier.HASH_PAGE_STORE_SUPPLIERS }))) + return redirect(url_for('routes_core.home')) # print('importing basket') # model.import_JSON_basket(data) model.get_basket(data) diff --git a/controllers/user.py b/controllers/user.py index 5d28c569..08ca818c 100644 --- a/controllers/user.py +++ b/controllers/user.py @@ -170,6 +170,9 @@ def logout_callback(): def user(): try: model = Model_View_User(current_app, db) + if not model.is_user_logged_in: + # return redirect(url_for('routes_user.login', data = jsonify({ Model_View_User.KEY_CALLBACK: Model_View_User.HASH_PAGE_USER_ACCOUNT }))) + return redirect(url_for('routes_core.home')) html_body = render_template('pages/user/_user.html', model = model) except Exception as e: return str(e) diff --git a/datastores/__pycache__/__init__.cpython-312.pyc b/datastores/__pycache__/__init__.cpython-312.pyc index 8c2301e66430787b58bc7d9a32acd7d9c6c49227..0ae6ea857eb08e3eb834367216724b4e3ee5b0f8 100644 GIT binary patch delta 21 bcmdnRyo;IVG%qg~0}wpwWlG=3vyKq}K1~I> delta 21 bcmdnRyo;IVG%qg~0}ya6&QIOQvyKq}I;#a^ diff --git a/datastores/__pycache__/datastore_base.cpython-312.pyc b/datastores/__pycache__/datastore_base.cpython-312.pyc index 4bb370e9582ca53dd6d9559bc49d5c54b68f2aac..4037a56320a48bcc7c8c26dbfaf5aaeb18d70df5 100644 GIT binary patch delta 47 zcmbOj)e*&enwOW00SMl%@uO wq|)Ndywu|2`23`-)Z~)l$+d>@LgMJ6dYk_mCNXj8-DLnGr@IVVlQT^c005FEvH$=8 delta 90 zcmZ3Tc`}ptG%qg~0}$loFsA!%uFo}uFaeRJKR%&ud@#G%K dcp-6gQN7JPQc_G@dUqLs$muSF)?@>jZ~!)v9j5>Q delta 84 zcmaE9(Qe6mnwOW00SIa(7}G5`@;+eV;&(~S$t+7Ps*K^6%;^O%Hq^#8BlH$qF fdEiODy4;~3Q@ dPv8~jOo2;!@>wu(ncQX2yUXANM3cJ(!T|nJ8D#(f diff --git a/datastores/__pycache__/datastore_store_product_permutation.cpython-312.pyc b/datastores/__pycache__/datastore_store_product_permutation.cpython-312.pyc index 1016f58861d09f61108aa6496e24bc2bfed5273f..468fa29212dbf0e5281d9e9f977cecb94b957e27 100644 GIT binary patch delta 20 acmbOzF;Rm1G%qg~0}wpwW!lKi#sdH|=>&`b delta 20 acmbOzF;Rm1G%qg~0}!NTGH&E%;{gCKr~~T& diff --git a/datastores/__pycache__/datastore_store_stock_item.cpython-312.pyc b/datastores/__pycache__/datastore_store_stock_item.cpython-312.pyc index 030ca917da8e57182739cd7f0c83d41c49e106cd..fdc41dd885f65e4c7251d410dbef7b55b56ef6df 100644 GIT binary patch delta 3245 zcmZt|ZEV}d^+-_^Nr|GR#I`KSw(LZ;<$T%sYT_nMnmB2iCT%(w>!2-Q8Ig9RP?C3~ zliHx6VGU3P3y`GuV;Q=k`8Ny>wgSce>|X~AC^l@c7q>Rp1l@oP*nkai+yq-P4A?u$ zvShah@bTTd_uk#T&--`!>8|h}WLZKm{uv34pNQQG$JjrkTm4-@2I-8>nS3#jz4gZF z3Ttl8ZUzc#wq{%5FPUw{_H27GmW>rVvK=0G(2N%o*+em!O?vZ?*;(w$c6qpLb{D&| z-3(&U%SaDjMY>`HXMJ>MgtDnAHq$cw59u5(7mS=eoPu%grEk4CntIE)VC8Lt{F3>+ zopHs{H_oUhFfQYa&y_~)a_*A)3ULF87nIeBZ4}ivjp9UxaW{`>wgzNus5N*@vkags zrwnt#!0N~`_3RWVBntOKW|+LsrQ-&#b63%9?NlfmsG@h6tT2i){*OQ5ScY$hmFX?y zSAm46s`*mhR@Hv;FaHqpIqBwi#B6R=63wn+404!4fP5$={G5XdBE>|%h;*OhFG%DL z-^)2{L8jyiZ!2|iop<;T(9hUerbYoZyu;~%LojXP5*%(lSJRry5`1TmmF@E zt<7fwPM}hVHWusHjL@Vq*idP2u5%QqO*RZiaM-%)@4*%`?2OnX(XoLYrj9VXsc~1< z5yx1tdWhT&?1@fjSSuQ~fi2bYJf0_y0-ZY|dEHXMkHtw_v-9QBaLVn_RF8- zUL>-Ri^(plU3Np4H4}Vi*;*-QU_We5-WAfZ_Hn~jbJpdWhK5@5bKyB=Gx?LSU661L zxN#?8#qBRB8@6|OY*>?~jR%0ouBGSBuDPDwbKyM;!rrBQBUO2>ZD?ND4QnJQ znTZ4_$*uYkP=o^T(Zu>{g}g7FX8Oqk>13$ky6XcU4+WD<#%`m`bQHeHA!tp4oC#(3 zJ_}*(N~(6N;S{F(Jqvi5nELKB-}&KGMs|fU!_HmQOcVFRGUkXI+Ryk%MDB`V8ZVgM zHzRr$!aFEoCpj$dOYZ^H_1AQZfY;5H^6Z7T0cm=WCLO7STKUs3wVskc$~%~YvX|AH{Qq$F>T%_&>wgso3kGN|n=WAUKiw=K!z zd%4_d{Q*Lg+0OY$ir+5PixY#$U!^Wm;-!#HPv;HDU7FK=$Z0Qm6@DB+60sxb{4R)h zfqW9|t_XD#&WH}@i0YcO6DYLSH8uWDQ_5Z+;*h_DOt49L)9svK zq4(>eGa)BbNP}JDJnSDT^m$cLZc-sR@_I9X(ZhD8uF8??=hyj5BM@G%Ir0d)A?Da| z$dL13PAEe(n!Hh<(YRqWTyTrM-ob(P{ouPWc(o6Nm8PQv9i^~ygEUM(KzayP21#FN z>tTC$ouRO=jy3*HQ%*YJQ8*z3-;8(#W#reUx6yd7SlVTyUi6@|S#BU#E*6cFJB(^|2u^6w0vRGyp)=pFw2^5=w5PWI9JrvRc@Ep)bYu@j;T9wHvqS7LbWcI0j%F) zI!+0CYQig_6+6{bU@g3#ia$@m0RWi>L?m=hC5Nw1X;C}S1m25Yxc=?z_3Rc-BpX_TNJs49Mr>Z9JT zRTSDB@j(g>Q$TYYzevFm3XW3Hs6s8SFK1f#WuUsj)wV({jHy%c>lB=&8H5KZ2S=^# zN)0}IjFO`o9-pM{Q1v|Y8#519pgymi2OCFGx3}Ytqfo-$bF?uXlM znAgl7m8!laCAz3=nOC;lQ_@v#Nr?c6r&kasc2-Y6jP@)>hvuV09}V1#9Jr%ObEo4k0molfP--9IKWWgsz7|a#84?7y9pZFJ?~8XHI^~ zeX1`AqtKqb^<^H#dzRYbOC6mbCV!G#YL7h<{awpeBahfVf7@3+z#dZ!Lr)fJ(U$2UuPX= zhbS%WZB3!X0o8klV4mEKq$?2k$ZfyqJyNZmwZE!gP>WO6_sv?8Nya<2QL^CGV`17= z+?Fx8-6a(mG&6V6C{AJe@_>kK5Q3DzLxkoh43{liuHTcvA)sTK0@^iPp)xV0Yb86M z!}K|dY1q2FJvEUpjbr+Z#5AG3O!@_)7e$`2o(YGF@ai&+7cmV`YDMcTfMp-UFppS? z;hrQBlYW2(zeI1(qqiTRqYu!YzoCvNJYxDEpu`tQ{sM_#q8(&08jfOyX`AcW_XJVI G+vWc-ap!>m delta 2316 zcmah~U2Gdg5Z*o8=kwXlukAQaoY-luiSy&6O`5i$Eul#ZErq6yK;me1z1WxZ+*>={ zJBKE6Y6KM&2??rwK|+;~c&fr165_E!s6z0Ps^aA!N?(vb2&q&p&{&d$uuJsS8^s`)M$6aoGHGz@2FLf2}d+zh0bflI{}e-S5fAxAv$*D`1GhgI`}X4(GAQ#od7D8<<^O34;8mNKqd+H3(Y zDC32^rRsSN+jURxrJya07ctiInFXqQjv;kcqe|_BX6W-8H9k3K>4p4%pwrr{UUo2H zLN_yoV%}o5CvjH8DYxxiKg4dVo;ImrRJ2s)$PPXMv7XWFhDjBxNV7C-D(gGcmv8FS z3FQdJ1xy#>lvT)Fs9euwyI(QsMFM5^P>$*bv$SK*iXEeyCOt(tGOrp%=fIT9uCE^X zs*3eW6wOhnH5UzWv;Sb;!Aw4W@E3a zEqOP2^f?~u=^g}DU6qn+BuTL`?k#auXJ@F>C2mRB;E=J}aCCD(TuGSWXlBHh7t<^u zwc*78R^LceLKsb8mhnZe)6$987hPvZ6Dhwf%xG5TylNPj#e*BjNMHok6BKBx zN%@>h-~(*qAo(<~M|zH`wx{CpsXH;!C>4u?PFih$gg;G}=5J&u*bfg8H5eDaZ2UfO z@ScbB9U|`p-%Z|2fV%icGb^>7D?;a^`&}UN5;S>g^i_T9c*33XlFMPq&zct>W@41w z42Q>hm{-0QdJDFjRq?Ix&j^u(9?2Xh|rMC26p>4CK+eal`{+2 z%V@3J&~!EgvA`%hx1nUK>IajklFQ-irEXlZHxsrY;k~5 z+O~;tJwcca0nFZVT+2jVk{QLe8eKFLr@3%Fxf1C*$BJo(x6q1o?&3z~D8xjVvAVag zDz&VZXudjkafI14F%czSM5J;vGZ(c>mX>F8+r%*j)Xf;Q3l#IBp&FU<8d|_D4sR3C z$^hQ9us)~RT*0(Gjt!1e9Jevi&KSbnLRQUNdIl#L=3Je(7UuN)EbaiH4Db$yvo^i~ zDviqe`mt~T(T}L19l`~=WDRecRNQkx2!H29=ziD=ptJ@Ku7Pu_V0aazSHWTD&-68r zy908oU~m=eTLY7~!Q>jad>dR|1!E6+0AoyauY#5z$nB;`!vuuVN^;Lbz!WEje*vFW BlIs8f diff --git a/datastores/__pycache__/datastore_user.cpython-312.pyc b/datastores/__pycache__/datastore_user.cpython-312.pyc index df4968de402ec33ccc70fd59ab3729b5e4b3e5f5..841398e066913313849f98f555d8575969f54709 100644 GIT binary patch delta 674 zcmaE*z0Qp9G%qg~0}v$Xa-}DzY~(x1#Ar7829uH`YYKArmX(u{1A)3^iK*lRduGt8a5pGS<5W3mFT=;W8& zT8x~NMR;swS+iXj7>eR*I9wQFBN-TKxk?y87K19!m{p3hU%1-a7X!b< z48f1wK=uU=sSiS%7YZI>q?Nd4h;gAW_T*Bot6U zkqk&O3P^wgly4`97Y!m}Ktct=W{gpjmkS#!Dge1ZS{S}?FtSR2Vv}Xn|6r%V%JDgb t(TR~&_PYm@)8sG0?u=fWZA5$-8H*=(iTVqMF*C|ei2KR_qKjmK`T<*xo%a9$ delta 373 zcmZ2y_DY-YG%qg~0}$B7{7hRdxsmTA6Qkbb8%#=qEGf(_j8Uu|3>Az~Y{3kgteb_I zz1bP(O^)aKIyr`0l96R{8FwHXYYoS2hPji^^N2CBO*Ry@XJnsTC~C{dF?qeHG$ZHa zI-Yb!E}*#RxluxHvL?U!dL z!pRHx9T+tyKjh!fsmWI)1r#ZAnY>b9GE=ebWIMq`X;wL|4;&1FveyMvE()kz7Et@Z z2^6}(A@zZ8^D)6AjNHX+Kt0FRWjwi9Ca;w+V+@=8M8a4~5-9kih2aYaBdhc$Hd$8v u4|W=?9N$A29VS~yx-+_OZjkh4WXzd-PRd^}fQeCdLflsd5M3k-)Cd4D?^{a% diff --git a/datastores/datastore_base.py b/datastores/datastore_base.py index 20010460..8e6e85a7 100644 --- a/datastores/datastore_base.py +++ b/datastores/datastore_base.py @@ -20,7 +20,7 @@ from business_objects.store.product_category import Product_Category_Container, from business_objects.store.currency import Currency from business_objects.store.image import Image from business_objects.store.delivery_option import Delivery_Option -from business_objects.store.delivery_region import Delivery_Region +from business_objects.store.delivery_region import Region from business_objects.store.discount import Discount from business_objects.store.order import Order from business_objects.store.product import Product, Product_Permutation, Product_Price, Parameters_Product # Permutation_Variation_Link @@ -145,7 +145,7 @@ class DataStore_Base(BaseModel): result_set_1 = cursor.fetchall() regions = [] for row in result_set_1: - region = Delivery_Region.make_from_DB_region(row) + region = Region.make_from_DB_region(row) regions.append(region) print(f'regions: {regions}') DataStore_Base.db_cursor_clear(cursor) diff --git a/datastores/datastore_store_base.py b/datastores/datastore_store_base.py index 947b68dd..764e77d7 100644 --- a/datastores/datastore_store_base.py +++ b/datastores/datastore_store_base.py @@ -14,10 +14,10 @@ Datastore for Store # from routes import bp_home from business_objects.store.basket import Basket, Basket_Item from business_objects.store.product_category import Product_Category_Container, Product_Category -from business_objects.store.currency import Currency +from business_objects.currency import Currency from business_objects.store.image import Image from business_objects.store.delivery_option import Delivery_Option -from business_objects.store.delivery_region import Delivery_Region +from business_objects.region import Region from business_objects.store.discount import Discount from business_objects.store.order import Order from business_objects.store.product import Product, Product_Permutation, Parameters_Product @@ -235,7 +235,7 @@ class DataStore_Store_Base(DataStore_Base): result_set_1 = cursor.fetchall() regions = [] for row in result_set_1: - region = Delivery_Region.from_DB_region(row) + region = Region.from_DB_region(row) regions.append(region) print(f'regions: {regions}') DataStore_Store_Base.db_cursor_clear(cursor) diff --git a/datastores/datastore_store_basket.py b/datastores/datastore_store_basket.py index c68db87e..184636bf 100644 --- a/datastores/datastore_store_basket.py +++ b/datastores/datastore_store_basket.py @@ -15,10 +15,10 @@ Datastore for Store Baskets import lib.argument_validation as av from business_objects.store.basket import Basket, Basket_Item from business_objects.store.product_category import Product_Category_Container, Product_Category -from business_objects.store.currency import Currency +from business_objects.currency import Currency from business_objects.store.image import Image from business_objects.store.delivery_option import Delivery_Option -from business_objects.store.delivery_region import Delivery_Region +from business_objects.region import Region from business_objects.store.discount import Discount from business_objects.store.order import Order from business_objects.store.product import Product, Product_Permutation, Product_Price, Parameters_Product diff --git a/datastores/datastore_store_product_category.py b/datastores/datastore_store_product_category.py index 553615f7..ba0794c6 100644 --- a/datastores/datastore_store_product_category.py +++ b/datastores/datastore_store_product_category.py @@ -14,10 +14,10 @@ Datastore for Store Product Categories import lib.argument_validation as av from business_objects.store.basket import Basket, Basket_Item from business_objects.store.product_category import Product_Category_Container, Product_Category, Product_Category_Temp -from business_objects.store.currency import Currency +from business_objects.currency import Currency from business_objects.store.image import Image from business_objects.store.delivery_option import Delivery_Option -from business_objects.store.delivery_region import Delivery_Region +from business_objects.region import Region from business_objects.store.discount import Discount from business_objects.store.order import Order from business_objects.store.product import Product, Product_Permutation, Product_Price, Parameters_Product diff --git a/datastores/datastore_store_product_variation.py b/datastores/datastore_store_product_variation.py index e44263a0..2e3171e6 100644 --- a/datastores/datastore_store_product_variation.py +++ b/datastores/datastore_store_product_variation.py @@ -15,10 +15,10 @@ Datastore for Store Product Variations import lib.argument_validation as av from business_objects.store.basket import Basket, Basket_Item from business_objects.store.product_category import Product_Category_Container, Product_Category -from business_objects.store.currency import Currency +from business_objects.currency import Currency from business_objects.store.image import Image from business_objects.store.delivery_option import Delivery_Option -from business_objects.store.delivery_region import Delivery_Region +from business_objects.region import Region from business_objects.store.discount import Discount from business_objects.store.order import Order from business_objects.store.product import Product, Product_Permutation, Product_Price, Parameters_Product diff --git a/datastores/datastore_store_stock_item.py b/datastores/datastore_store_stock_item.py index 806dab05..683f64bd 100644 --- a/datastores/datastore_store_stock_item.py +++ b/datastores/datastore_store_stock_item.py @@ -13,21 +13,10 @@ Datastore for Store Stock Items # internal # from routes import bp_home import lib.argument_validation as av -from business_objects.store.basket import Basket, Basket_Item -from business_objects.store.product_category import Product_Category_Container, Product_Category -from business_objects.store.currency import Currency -from business_objects.store.image import Image -from business_objects.store.delivery_option import Delivery_Option -from business_objects.store.delivery_region import Delivery_Region -from business_objects.store.discount import Discount -from business_objects.store.order import Order -from business_objects.store.product import Product, Product_Permutation, Product_Price, Parameters_Product from business_objects.sql_error import SQL_Error -from business_objects.store.stock_item import Stock_Item -from business_objects.user import User, User_Filters, User_Permission_Evaluation -from business_objects.store.product_variation import Product_Variation, Product_Variation_Filters, Product_Variation_Container +from business_objects.store.stock_item import Stock_Item, Parameters_Stock_Item, Stock_Item_Temp from datastores.datastore_store_base import DataStore_Store_Base -# from helpers.helper_db_mysql import Helper_DB_MySQL +from helpers.helper_db_mysql import Helper_DB_MySQL # from models.model_view_store_checkout import Model_View_Store_Checkout # circular! from extensions import db # external @@ -52,11 +41,11 @@ class DataStore_Store_Stock_Item(DataStore_Store_Base): super().__init__() # Stock Items - def get_many_stock_item(self, Parameters_Stock_Item, category_list): + def get_many_stock_item(self, parameters_stock_item, category_list): # redundant argument validation? _m = 'DataStore_Store_Stock_Item.get_many_stock_item' - av.val_instance(Parameters_Stock_Item, 'Parameters_Stock_Item', _m, Parameters_Stock_Item) - argument_dict = Parameters_Stock_Item.to_json() + av.val_instance(parameters_stock_item, 'parameters_stock_item', _m, Parameters_Stock_Item) + argument_dict = parameters_stock_item.to_json() user = self.get_user_session() """ argument_dict['a_id_user'] = user.id_user # 'auth0|6582b95c895d09a70ba10fef' # id_user @@ -67,6 +56,9 @@ class DataStore_Store_Stock_Item(DataStore_Store_Base): , **argument_dict , 'a_debug': 0 } + ids_permutation = category_list.get_csv_ids_permutation() + print(f'ids_permutation: {ids_permutation}') + argument_dict['a_ids_product_permutation'] = ids_permutation print(f'argument_dict: {argument_dict}') print('executing p_shop_get_many_stock_item') result = self.db_procedure_execute('p_shop_get_many_stock_item', argument_dict) @@ -85,7 +77,7 @@ class DataStore_Store_Stock_Item(DataStore_Store_Base): print(f'raw categories: {result_set_1}') for row in result_set_1: new_stock_item = Stock_Item.from_DB_stock_item(row) - category_list.add_stock_item(new_stock_item, row) + category_list.add_stock_item(new_stock_item) # , row) # Errors cursor.nextset() @@ -112,5 +104,47 @@ class DataStore_Store_Stock_Item(DataStore_Store_Base): if 'region' in error.msg or 'currency' in error.msg: permutation.is_unavailable_in_currency_or_region = True """ + DataStore_Store_Stock_Item.db_cursor_clear(cursor) return category_list, errors # categories, category_index - \ No newline at end of file + + @classmethod + def save_stock_items(cls, comment, stock_items): + _m = 'DataStore_Store_Stock_Item.save_stock_items' + av.val_str(comment, 'comment', _m) + + guid = Helper_DB_MySQL.create_guid_str() + now = datetime.now() + user = cls.get_user_session() + rows = [] + for stock_item in stock_items: + # row = permutation.to_temporary_record() + row = Stock_Item_Temp.from_stock_item(stock_item) + row.guid = guid + rows.append(row) + + print(f'rows: {rows}') + + DataStore_Store_Base.upload_bulk(Stock_Item_Temp.__tablename__, rows, 1000) + print('bulk uploaded') + + argument_dict_list = { + 'a_comment': comment, + 'a_guid': guid, + 'a_id_user': user.id_user, + 'a_debug': 0 + } + result = cls.db_procedure_execute('p_shop_save_stock_item', argument_dict_list) + print('saved product permutations') + + # Errors + cursor = result.cursor + cursor.nextset() + result_set_e = cursor.fetchall() + print(f'raw errors: {result_set_e}') + errors = [] + if len(result_set_e) > 0: + errors = [SQL_Error.from_DB_record(row) for row in result_set_e] # (row[0], row[1]) + for error in errors: + print(f"Error [{error.code}]: {error.msg}") + DataStore_Store_Stock_Item.db_cursor_clear(cursor) + return errors diff --git a/datastores/datastore_store_stripe.py b/datastores/datastore_store_stripe.py index 0c11fe8f..4cae7b7f 100644 --- a/datastores/datastore_store_stripe.py +++ b/datastores/datastore_store_stripe.py @@ -15,10 +15,10 @@ Datastore for Store Stripe service import lib.argument_validation as av from business_objects.store.basket import Basket, Basket_Item from business_objects.store.product_category import Product_Category_Container, Product_Category -from business_objects.store.currency import Currency +from business_objects.currency import Currency from business_objects.store.image import Image from business_objects.store.delivery_option import Delivery_Option -from business_objects.store.delivery_region import Delivery_Region +from business_objects.region import Region from business_objects.store.discount import Discount from business_objects.store.order import Order from business_objects.store.product import Product, Product_Permutation, Product_Price, Parameters_Product diff --git a/datastores/datastore_user.py b/datastores/datastore_user.py index 1936cf13..b8c65261 100644 --- a/datastores/datastore_user.py +++ b/datastores/datastore_user.py @@ -139,6 +139,76 @@ class DataStore_User(DataStore_Base): 'a_id_user': user.id_user , 'a_id_user_auth0': user.id_user_auth0 , **user_filters.to_json() + , 'a_debug': 0 + + } + # argument_dict_list['a_guid'] = guid + result = self.db_procedure_execute('p_get_many_user', argument_dict_list) + """ + query = text(f"SELECT * FROM Shop_Calc_User_Temp UE_T WHERE UE_T.guid = '{guid}'") + result = self.db.session.execute(query) + """ + cursor = result.cursor + result_set = cursor.fetchall() + print(f'raw users: {result_set}') + print(f'type result set: {str(type(result_set))}') + print(f'len result set: {len(result_set)}') + """ + user_permission_evals = [] + for row in result_set: + user_permission_eval = User_Permission_Evaluation.from_DB_user_eval(row) + user_permission_evals.append(user_permission_eval) + print(f'user_permission_evals: {user_permission_evals}') + """ + users = [] + if len(result_set) > 0: + for row in result_set: + print(f'row: {row}') + user = User.from_DB_user(row) + users.append(user) + print(f'user {str(type(user))}: {user}') + print(f'type users: {str(type(users))}\n type user 0: {str(type(None if len(users) == 0 else users[0]))}') + # error_list, cursor = self.get_error_list_from_cursor(cursor) + errors = [] + cursor.nextset() + result_set_e = cursor.fetchall() + print(f'raw errors: {result_set_e}') + if len(result_set_e) > 0: + errors = [SQL_Error.from_DB_record(row) for row in result_set_e] # [SQL_Error(row[0], row[1]) for row in result_set_e] + for error in errors: + print(f"Error [{error.code}]: {error.msg}") + + DataStore_User.db_cursor_clear(cursor) + + return users, errors + + def get_many_user(self, user_filters, user=None): + _m = 'DataStore_User.get_many_user' + print(_m) + # av.val_str(user_filters, 'user_filters', _m) + # av.val_list(permutations, 'list_permutations', _m, Product_Permutation, 1) + av.val_instance(user_filters, 'user_filters', _m, User_Filters) + + guid = Helper_DB_MySQL.create_guid() + # now = datetime.now() + # user = self.get_user_session() + + """ + argument_dict_list = { + 'a_id_user': id_user, + 'a_comment': comment, + 'a_guid': guid + } + """ + if user is None: + user = self.get_user_session() + argument_dict_list = { + # 'a_guid': guid + 'a_id_user': user.id_user + , 'a_id_user_auth0': user.id_user_auth0 + , **user_filters.to_json() + , 'a_debug': 0 + } # argument_dict_list['a_guid'] = guid result = self.db_procedure_execute('p_get_many_user', argument_dict_list) diff --git a/forms/__pycache__/__init__.cpython-312.pyc b/forms/__pycache__/__init__.cpython-312.pyc index 02f75864ae425e821ec80eebeb3424344372a43b..4cfa2a5afa6a6cb617a79b62b137aed8c50c9ece 100644 GIT binary patch delta 20 acmX@ec#x6jG%qg~0}wp!WlEpOvlRe20|l!9 delta 20 acmX@ec#x6jG%qg~0}uo$T~3?GvlRd~n+1OW diff --git a/forms/__pycache__/access_level.cpython-312.pyc b/forms/__pycache__/access_level.cpython-312.pyc index 40a47abcabf48e50b8b9a120ecc1a63e2bfedd77..9174ed14a1c341390ca4263adb8eb4367df003db 100644 GIT binary patch delta 343 zcmaDY@>hiSG%qg~0}v$Xa;1lCv>A!DkyFF`XfmA&N1DA&QBKA(c6WF@iJVG6wx1?vk@Vzz4rOn!$%;UsTinSxiN(dasU;ctDMea9ks@6nv67(( zq@hRwM2Nu%Ng$(G8%VS;+~k#13a{nl+Z+mvN|XO^@>+!VG%qg~0}xbv|CHvkk@q2!J2Qw21fMN{#B_#KhA74qhA1W`hE(Ph#?_2q zIff{f6s8u2DArWA6y_F&)eu33DE1T4fE2^^{^GF7%}*)KNwq7oo@~tJ#sZQ70I`!k A_W%F@ diff --git a/forms/__pycache__/base.cpython-312.pyc b/forms/__pycache__/base.cpython-312.pyc index 5ba3183424ed4cdd2500c036250a6a6eb5f4337e..4fd011ac2b7852661225431ed731de2022ed4744 100644 GIT binary patch delta 20 acmX>sd{~(KG%qg~0}wp!W!lKSgA)Ke2?dq_ delta 20 acmX>sd{~(KG%qg~0}$A_GH&GF!3h90!vv-P diff --git a/forms/__pycache__/forms.cpython-312.pyc b/forms/__pycache__/forms.cpython-312.pyc index 92dd7e30bfe9b1e8d599409fecaeb0d668918827..dfb3fa02ab09c5c11c7a7a331547fac60d1b22e8 100644 GIT binary patch delta 298 zcmeCvS)s#wnwOW00SJJ%`k~8!+xLo12Y;e2DCpklNqr_&Z4Lk>uuJCy_x)-Se6%`dt4iR}E z57w;$;)4a%fUI8}Ho5sJr8%i~MKzOyMHfh$Pw@Q0z{6<%MU9Eki*W|$R|XIb)&KzC C`$sqc delta 218 zcmZ3X)2G9GnwOW00SK5rd`oNH$U94b@yO&A0=xNEGlE1J7@`C#`84?_mkQ3FEFrXm zv2yZ7p>pQS0&0_eg_RiXChPIZsxdL7vZgQrNw(DxJq+oL=?rU_S2IJnQS6m0nyizz z3oA~(Cme2G2ox;>5iLMmEC*)XdCpH3#8R2cz$8vVO0O3#>D8wID_*m1BeEz1_1U(I3551 diff --git a/forms/__pycache__/unit_measurement.cpython-312.pyc b/forms/__pycache__/unit_measurement.cpython-312.pyc index a68ac77a853a8af0b221fd623f3d376fede7b0cc..7827d856dd4cc5cd17a2d5ad0123b4625acfa808 100644 GIT binary patch delta 452 zcmYk0Jxjwt7{~AO)+Cy>G!bi{lp0?u)Jf5bAPyqpAPxZurFZp(w3SOM)=rf!ZbAkH zKS8L7;^;?kb+B0+{Q&CXf2m3mkZLW}(c)BiDW|Nn z(baO}@Pyj+n%`R4ad4aRZn0z) z=jRp40GY)g$0{g*biHIN0P2cj|6-*96f05#5$YfUuKgBge0*|FVsUYN{4I|7_`Jm2 z)cE)!C7>F()g2t2obo^cKTWP8-N{m%%6=f-x46ODa#Kq(@>7cBK!&P-2rUqy2P9T9 z6oGUV$$|(m7y2 TKczG$)vm~P@<%Q=7LW`8%xPL0 diff --git a/forms/access_level.py b/forms/access_level.py index c9136e88..5fd6f2fc 100644 --- a/forms/access_level.py +++ b/forms/access_level.py @@ -23,7 +23,7 @@ from abc import ABCMeta, abstractmethod class Filters_Access_Level(Form_Base): - active = BooleanField("Active only?") + active = BooleanField("Active only?", default = True) def __repr__(self): return f'{self.__class__.__name__}(active={self.active.data})' @classmethod diff --git a/forms/forms.py b/forms/forms.py index 1a5bad3d..93419717 100644 --- a/forms/forms.py +++ b/forms/forms.py @@ -122,7 +122,7 @@ class Form_Supplier(FlaskForm): fax = StringField('Fax number') website = StringField('Website') id_currency = SelectField('Currency ID') - is_active = BooleanField('Active') + is_active = BooleanField('Active', default = True) # class Form_Supplier_Purchase_Order(FlaskForm): @@ -130,5 +130,5 @@ class Form_Supplier(FlaskForm): # User class Form_Filters_User(FlaskForm): - active = BooleanField('Active only?') + active = BooleanField('Active only?', default = True) id_user = SelectField('User ID', validators=[Optional()], choices=[]) \ No newline at end of file diff --git a/forms/store/__pycache__/__init__.cpython-312.pyc b/forms/store/__pycache__/__init__.cpython-312.pyc index b0530ac6c6b7d6cefd1e95079d15b17c1d23b2c1..f2679b8774c2f7f7a8bde0e2fd6a9998e2fafac0 100644 GIT binary patch delta 20 acmX@kc$|^vG%qg~0}wp!WlEpOvl{?8?FGF6 delta 20 acmX@kc$|^vG%qg~0}yyBT~3?Gvl{?6Mg@of diff --git a/forms/store/__pycache__/product.cpython-312.pyc b/forms/store/__pycache__/product.cpython-312.pyc index 7d88d1926360d409583a6ebe498450290c5dcf79..2e89a74cc3f3fa2bcf9eca135fa44368e4b14247 100644 GIT binary patch delta 349 zcmbOyvO$FRG%qg~0}#0Da;4AR$eYW=ST(tt$=xD_Z4LWsCXfsRLlj3UX9`CP!)geZ zA&M)7vxOmw8z{m4>n3Sb}T8pGXgbav~ z1rk6tEXAogX~m2{jzW>*RF1w0$>BcMuA0{i{vKn zW|wAEoP3?VoKbnQKZmI|SRFgaBDlI++{rnK#l^X)B^miCMM@w!br7KqBvvvMf$S|( z1Q9|oLITJr4xfCULz8ub%N1VB$-g;tf#z#+&XqC%sexrd|#ONG%qg~0}%M?a-}zKnFRx?3_qF6Z@QdnCU zqS#W|Q`lMf>Qw~>!- z@LEpR=TKl&m>j@S&8R&2499FKeUMHC5CJmi7l%!5eoARhs$G%Qp7LW`8f%`*s delta 282 zcmcaFd{&tEG%qg~0}!nI@GY%)Bky}AE@luH2tK<^W@A=XTg?dJMzL}-q%gNIM6so^ zr?9jztcD0PL~&HIYO+lZX13fsgZV!bn44Jlh4J delta 21 bcmdnUypfsbG%qg~0}y;{%un6Ovy>44KYIoZ diff --git a/helpers/__pycache__/helper_app.cpython-312.pyc b/helpers/__pycache__/helper_app.cpython-312.pyc index 5ae92951ddf929c1a0715bad9ebd4e92d25c0852..13087f28e930b0da529a131e726a018ec8243258 100644 GIT binary patch delta 21 bcmZ3@xtf#bG%qg~0}wp!WlG=3GoJ+jJjMl` delta 21 bcmZ3@xtf#bG%qg~0}!~z-$>iYGoJ+jJCg;b diff --git a/helpers/__pycache__/helper_db_mysql.cpython-312.pyc b/helpers/__pycache__/helper_db_mysql.cpython-312.pyc index bc9fbf8346d8e944dbfcb1229822c4a708f499ba..b0ddfb16b2b4b1e92906668ecea9ae6af1ff7fe2 100644 GIT binary patch delta 21 bcmbOtGDU>vG%qg~0}wp!WlG=3!@&grIj98m delta 21 bcmbOtGDU>vG%qg~0}zNsTuIx=!@&grHnar8 diff --git a/lib/__pycache__/__init__.cpython-312.pyc b/lib/__pycache__/__init__.cpython-312.pyc index 252f070f58a0a89e28540c73456246fbfaeda1b3..a40d61acb110c3d5e8bb7a33b67713dd525a4976 100644 GIT binary patch delta 21 bcmZ3>yq1~gG%qg~0}wp!WlG=3vyc%0JTnE9 delta 21 bcmZ3>yq1~gG%qg~0}xCp&raRQvyc%0JBJ^=-_ delta 21 bcmdnNyn~tNG%qg~0}zy#XQyuDS;GhbJaYw_ diff --git a/models/__pycache__/model_view_accessibility_report.cpython-312.pyc b/models/__pycache__/model_view_accessibility_report.cpython-312.pyc index f478875bc246aed78dad09210749b03a029b4c54..23a454e0d3aa1c062ace872eef7678ca156b17ac 100644 GIT binary patch delta 21 bcmeC>>gD1&&CAQh00fVFnbJ4%FtP#wHvt63 delta 21 bcmeC>>gD1&&CAQh00b!~o}_K$VPpjWIqd~w diff --git a/models/__pycache__/model_view_accessibility_statement.cpython-312.pyc b/models/__pycache__/model_view_accessibility_statement.cpython-312.pyc index cb6175697ed192dab2900699c0b731a50922c1c0..03289019f5546341e7ab25d9a8825a5e10929081 100644 GIT binary patch delta 21 bcmZ3%wStT1G%qg~0}wp!WlG=3Bf|;+J8uOS delta 21 bcmZ3%wStT1G%qg~0}vP-eUi43M}`#uJf;PG diff --git a/models/__pycache__/model_view_admin.cpython-312.pyc b/models/__pycache__/model_view_admin.cpython-312.pyc index e2b594c34da20cb615749605c1afe9ba0d8d7289..b3c78373683e14ebfa0b71f26c6714ee6a9d4286 100644 GIT binary patch delta 21 bcmZ3)xrmeJG%qg~0}wp!WlG=3GmQlRJ4^+F delta 21 bcmZ3)xrmeJG%qg~0}xaeUr5`?GmQlRJQW4Y diff --git a/models/__pycache__/model_view_admin_home.cpython-312.pyc b/models/__pycache__/model_view_admin_home.cpython-312.pyc index e7d0c4a12be87a3272bd312b2537519257d888a9..52923e1d12756dcf6475827534a62ca24733065b 100644 GIT binary patch delta 21 bcmbQpHIa+wG%qg~0}wp!WlG=3!^#Q(H>m{D delta 21 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 delta 3926 zcmZwKc~n&Q6~OWLn;BMx5k>^UCL+VCY_e|xA|fElrd}6Z-cukTIG}MK8jaOdU%@~!Xbv}w(<$#C89*(8~3%xX~$;H`ORo}v1t z=A{}7^xvupe3*HVd4ex9FEVeK#LS1x7bY{Cgr@nmh0C>GmLPvNnM@O7TO>|2Gn@F) zdHi7tGc(x~2w)aK76^gNEM!x`!Yl|)Gq%O!J=v$S$u!yyh9G7kWT7yP*#l%@5X>x` zECNE9MUq89D6{EkTBsVmL;npA6tK|@T91J+W;4lRA)J|&PGM}z!zWM}!6tFE9S@Pr z637xEidhm_GEA3l4~r4~tju!A zav_dc9$7xbGbCB(cR(H2vx>!zUG#%qC@bCqR=~Y%=fe zWF=1IZO>f0x)9RXLKWRnHKa4EAzK6)%xcLN!yINy$m$@ISv^?;WHD=U2A zrG(2Mhb=BA1IT5zf@~$^F%wp&ZK4hrw@+12%gDiqyERU_K~#mqL6 zwZL3vtz>Ob!t6n^b|_`mLAD9Xn01l`cfmY{n-TSE`Y2u>dpVofXuTWeGwUJS0u{`* zl05_qm~A854wcMyknMzp%yyCOhN?Ser?=i7LOWEm#a^;+K@GEq$@an`X8Xt~UCTXV_0T0Lz&Tl05;y>?GMKSi$Tx*%?^LY>4bEtYUVK?7Oh~uG#T>=}E$;pqVW` zP4*0|VRoMEd$5+-vt$=w9kb`io`?0!zEAc7sLU=FDEjNKUILBb4`|T|8<@RF_Cwgn z>@wMppoQ5LvL8b$vzN$z0&UD*Ci^KosM+s-JHJBsGiYavuadn69n7wh{Twzid!6hT z(8=r#vR^_Mvuk9(g3S|V*I)iO3Eu+S1nTxS*{`9S**j#vfgWZqG#^EE!xpCR(&jL1 zWi~?gTX=}sdw1Udqp*$P7%jdJ+nJ4%{SJ08`#sqoU?;OblKlyGG5a&wb=b}912k>7 z`e8VIaqnTHk7#6fh&F}3KrZ_|YsXjVGdj%;IHVocZ+(up42t%c`o(i!UJ&{X{RfU{ z4y{l9*FNRK9k}-!j_R+`SNjx@>eqUYskihVS8wY*;iEW&>ZN|OPr&1J^l$yBUmH;W zGjSgMO$vkBfId_vNS7x_1e22_1}3LSj7(0Gn3$X)@nAAU;(1TJ6ga#6M!dH?Xik!U zF@Nm5HRYCvydIn+znJz{=j4zsW1u;u8~^%D>E6=S)!wSv#zW+hun_0@urfoHUq`39 zw!L1nZEanzb&m&B&TFozomW!bTwh+-R9RMDKOR6E4chvaO`YwX8(a0QpnF>lDvPa^4U*`wbC?OJ^hWG*@Qk=yJW+5_VZQ?(} zbM%YaZPBk|ukw*ObktnrHWyvlHEgbSc~{F-N#BTk=ZfU{LKHdA%?c8tNnV+KMwB?0 zr4-_g6R9UXEAR}f<*JlaXG>a|5H-%hbRooIc`~EI%l5H;>V$K0f9ArrF#XULfr-RK zVWKfU82zs!#TJ8!#aJsV@}8g*)zmxxgk5>jvqeT^OzSfmoQGu zi3I5<&UN diff --git a/models/__pycache__/model_view_privacy_policy.cpython-312.pyc b/models/__pycache__/model_view_privacy_policy.cpython-312.pyc index 72352694ead131e71e3edf0bcc1eaf59c06e3163..336261ec0e6781ee32dfdb0de82182272bdd67b9 100644 GIT binary patch delta 21 bcmcc1d6$#tG%qg~0}wp!WlG=3bCCrAMEV9Z delta 21 bcmcc1d6$#tG%qg~0}#wT`Xp^5&qWphNtp)* diff --git a/models/__pycache__/model_view_retention_schedule.cpython-312.pyc b/models/__pycache__/model_view_retention_schedule.cpython-312.pyc index 67015cb567062c31c5037b00fab8beead659e097..f470d4c730800acd67ea29ec52fc127013bf28d4 100644 GIT binary patch delta 21 bcmZqTYU1KK&CAQh00fVFnbJ4%d}9FsH!=mJ delta 21 bcmZqTYU1KK&CAQh00d&ko}_K$`NjeOH=qUa diff --git a/models/__pycache__/model_view_services.cpython-312.pyc b/models/__pycache__/model_view_services.cpython-312.pyc index e9b67bc5ccfa9f81707bfbbcd08e68456b0565d1..17d8c19ff77ecbfcf8bf83f5fb7d9247dad4c99e 100644 GIT binary patch delta 21 bcmZ3 delta 21 bcmZ3KKBME diff --git a/models/__pycache__/model_view_store.cpython-312.pyc b/models/__pycache__/model_view_store.cpython-312.pyc index 9b2631b7495e8b248292ee71e03683271072ab52..550a7117d07969036e66c4fac6769caa25357773 100644 GIT binary patch delta 5781 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 delta 4693 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 diff --git a/models/__pycache__/model_view_store_product.cpython-312.pyc b/models/__pycache__/model_view_store_product.cpython-312.pyc index d9585874a88412765ea1c06e946c5c4323bdbe25..adf0be07905dbdd46a8a8bdc26493c5a4cd96ad8 100644 GIT binary patch delta 479 zcmYk0J5R$f6ounHP+#sNP182eDhLKzBqYSZQX#}pkPuziB1DK9_kr@L99K{nSUPk? z9$;jL0n~vX!OoD0U%0MUQF2YLHHSG&f;NeuqD7h@f*LI}LF|IK#Oy>@HwUvD@F=thl2RDO zAEAw;(!ZdcO-O4iSbG%Cw~62sFYoi+%y;H~8b4#~5cs>Uq5a(lT(F=Ywqr5QJ!C|& z=XgRvB`>jYatz65l5Y9FOJOpu zc>g-wyd}~Rj!`MPEu?*{DBienlQxuA#gO;3a{Z|LCI;+imVLVNqhUUhhS(}jgaX|5 zJ*qCZ>Z&0(sL^pU;M_iT$D_z`DkUS)wSXL@Hd-2r8=2iC9n(DDjiJ(OHUCN+H Z6iVSZv-8WAtMO0L$RZ_dF0f{W%rC|6Y-|7k 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 a567b97fad97049b0a400a00e427baf2d1ac72c1..3fd6ccd4348eb9675a5fe1d71e31d961683d61aa 100644 GIT binary patch delta 20 acmew?{#l&+G%qg~0}wp!W!lL7f*Sxt8wM}{ delta 20 acmew?{#l&+G%qg~0}#|oFmB|2!3_XDjs;Wz diff --git a/models/__pycache__/model_view_store_product_permutation.cpython-312.pyc b/models/__pycache__/model_view_store_product_permutation.cpython-312.pyc index a9b11f7563019ed924d7feaad3a646376b544804..dea5d6ed1c6a1ca91e6c5a93279c34789f4c3e73 100644 GIT binary patch delta 1184 zcmZ8gO>7%Q6y6y-n^~{dvAuRSaY*8*Hi=8ps4;CQsrXSN(mHL`$`KXDVr6;P$wqNp zW?eO{QdN`)^#FqE-8gWhhaM<$M2nDmsRW4-s-3E`wBmp`Ax>=wpumNhb*x6r;m!BG zpYOeyo&93`heOJbisBR4TAS*apZQw3jq$bs-{8yFB~vtf$63U{xuD6JyvIT=^Y5{+ z%M{K`)d;K!ceor|xriBE9BtwKwuEj9C1iB1Njc5zF@pOldT$CVC>P5LsStJ&@RgXT z{o=WeYM*z!j!+sLaReQ#c{)Et5SFxP&wkYwUO`YN5jaZ@!a4~l{q2lZve*O5oiQ&1 z1Mrj#rWHXbVx8I6s-iYBq*Ypm6l^$q%l z-+bOvGUQ%XduLC2RWkgXm+&q8vF2s%uSr+`HwJ4x3=e!meUWzaRY8xo@imdf$5=cD zzxn)LMh-zjPQnKs74ovGaCLXF$Pu0vWYvB9oJZkHIf;((P=E~)afgsuQa|j-X{6Lf z{5KG+D@V`({H~PHIGhhelQE4Cz;D$fnczq6MvKRHb`%iBpW2zBx74-tX_WqZ$Vf_C-Jk^=CW*yW$|BvFfoVg z1#3NhccnQw+nAhvoIbs=@Tk05-kQj7yJ1!-&EY376Pn9D?~!PbM3anek+hNC2ky?_pKly}>+!_QhE_j+VRLZn@HIziSV$<2`(3B!kHJQ?ZOlHsYa-?A@5~GP^mXWrFZ9{GED&UxJ63 zcsx$sn>qux)G3sQpVT37kOfkGu%lj%X$(^SOHlq99CDFXE}FD@g$}@{k@1uKejUGE zEmW;y*{m*940?vU6kRVa6>Pg`E-mSL3ej2SwfU2Mqt!0JAmxTXB>NtS(YIkCdMb6G zBafbDkRXPiVcd~Je|Q+&aUtbnxiu+`W@}C~k7B&K<>!a^ha4|gj7v-AYt)2u+N+Ui QgmS3<($t@Vi`>lr0641@z5oCK delta 1213 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 delta 2031 zcmZuyO>7%Q6rNpgytDpUJB}U4Nl0DCY2v0oPDu)wkp9v%ZIxDvpsm|xaqW$3XKjbw zP1^)JjZhB}LMrVD5rIJ5Xq5^TxL1`Z5)ud2bt*@zMB>1qTu}c}IWe=g8zUIWGw;oN z^S$rQynX(5$AcjMi`{MkcobTw?GQ5{=K&sLn#e-ng_o*0#68Xyvmix z0OB9fpWHN|A-0dQp()mXs74|W1crE#p;{{|cuBFqf*Irf&l#0Pw_$s8fh|A|s8kIs!Q|O=GvYb_r9?xLB1+A) zzU~KCxHz2zar#Urj=-tDnk~SY7*7o(?nlwRQr9bXsFj|3|#hZDMCKri5 zWgX}QbbE!DH&92@oJUt!53!@~@z2jWOl*218nU$}3zj-RHgEX?d`Z_B;G!d0S#So{ zY6c#hfwe9JYXXvVYA5p61V?m(rPp9-HCP()ZJc|cj$apcG)CQ`}q$E|8m54t?>r_}b?U5wp zeK> z>+IdaR!{4kAjGAZq6mUQJ^_E-n3r1!QYZS;8Dh6%QF%b2j>fR5)E-9h#{HMHkyF~4 znNrtm5e62RW!SoSU?se(93Cr%$5w3}C7b_=iSDx$;Z_a4vN-q9?BHxq1AyZ-XSde# zR=MY3vFD)HJ)-f4mf_)*zPE1i4*{5?#^}GuGEP6LEYAVhO9{00{>o?)B$rruAB`ReIWlZn!%*3e12I zJv!Tq8*1-{5G|9#xE<%B#s6a-SFf`D##f+J46DU-b99z5v| zL5O9uxk^vRg(j1lmq|01D<1-pNC6wAtV3Ly_)kEck$ouAyeWeF9FPew-CnKLxF|`2 z5TfMQ@UB8S-0li{p16{U&{ib$O><9s%jOcZd8NB|{)pxZmYCj^t$iBf(Y$!O4-I(z zzF@-<>iH3hZa796=@=7T}==7T}= element FLAG_DIRTY: ClassVar[str] = 'dirty' - FLAG_DISPLAY_ORDER: ClassVar[str] = Store_Base.FLAG_DISPLAY_ORDER + FLAG_DISPLAY_ORDER: ClassVar[str] = Base.FLAG_DISPLAY_ORDER FLAG_ERROR: ClassVar[str] = 'error' FLAG_EXPANDED: ClassVar[str] = 'expanded' FLAG_FAILURE: ClassVar[str] = 'failure' @@ -75,9 +80,9 @@ class Model_View_Base(BaseModel, ABC): # 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_NAME: ClassVar[str] = Base.FLAG_NAME + FLAG_NAME_ATTR_OPTION_TEXT: ClassVar[str] = Base.FLAG_NAME_ATTR_OPTION_TEXT + FLAG_NAME_ATTR_OPTION_VALUE: ClassVar[str] = 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' @@ -96,11 +101,10 @@ class Model_View_Base(BaseModel, ABC): FLAG_NAV_USER_LOGIN: ClassVar[str] = 'navUserLogin' FLAG_NAV_USER_LOGOUT: ClassVar[str] = 'navUserLogout' FLAG_OVERLAY: ClassVar[str] = 'overlay' - FLAG_TEMPORARY_ELEMENT: ClassVar[str] = 'temporary-element' FLAG_PAGE_BODY: ClassVar[str] = 'page-body' FLAG_ROW: ClassVar[str] = 'row' FLAG_ROW_NEW: ClassVar[str] = 'row-new' - FLAG_ROWS: ClassVar[str] = Store_Base.FLAG_ROWS + FLAG_ROWS: ClassVar[str] = Base.FLAG_ROWS FLAG_SAVE: ClassVar[str] = 'save' FLAG_SCROLLABLE: ClassVar[str] = 'scrollable' FLAG_SLIDER: ClassVar[str] = 'slider' @@ -108,6 +112,7 @@ class Model_View_Base(BaseModel, ABC): FLAG_SUBMIT: ClassVar[str] = 'submit' FLAG_SUBMITTED: ClassVar[str] = 'submitted' FLAG_SUCCESS: ClassVar[str] = 'success' + FLAG_TEMPORARY_ELEMENT: ClassVar[str] = 'temporary-element' # flagIsDatePicker: ClassVar[str] = 'is-date-picker' HASH_APPLY_FILTERS_STORE_PRODUCT_PERMUTATION: ClassVar[str] = '/store/permutation_filter' HASH_CALLBACK_LOGIN: ClassVar[str] = '/callback-login' @@ -130,7 +135,7 @@ class Model_View_Base(BaseModel, ABC): HASH_PAGE_STORE_PRODUCT_PRICES: ClassVar[str] = '/store/prices' HASH_PAGE_STORE_PRODUCT_VARIATIONS: ClassVar[str] = '/store/variations' HASH_PAGE_STORE_STOCK_ITEMS: ClassVar[str] = '/store/stock_items' - HASH_PAGE_STORE_SUPPLIER: ClassVar[str] = '/store/supplier' + HASH_PAGE_STORE_SUPPLIERS: ClassVar[str] = '/store/suppliers' HASH_PAGE_USER_ACCOUNT: ClassVar[str] = '/user' HASH_PAGE_USER_ADMIN: ClassVar[str] = '/user/admin' HASH_PAGE_USER_LOGIN: ClassVar[str] = '/login' @@ -148,9 +153,9 @@ class Model_View_Base(BaseModel, ABC): ID_FORM_FILTERS: ClassVar[str] = 'formFilters' ID_FORM_IS_INCLUDED_VAT: ClassVar[str] = 'formIsIncludedVAT' ID_LABEL_ERROR: ClassVar[str] = 'labelError' + """ ID_MODAL_SERVICES: ClassVar[str] = 'modalServices' ID_MODAL_TECHNOLOGIES: ClassVar[str] = 'modalTechnologies' - """ ID_BUTTON_NAV_ADMIN_HOME: ClassVar[str] = 'navAdminHome' ID_BUTTON_NAV_ADMIN_STORE_STRIPE_PRICE: ClassVar[str] = 'navAdminStoreStripePrice' ID_BUTTON_NAV_ADMIN_STORE_STRIPE_PRODUCT: ClassVar[str] = 'navAdminStoreStripeProduct' @@ -179,8 +184,6 @@ class Model_View_Base(BaseModel, ABC): # KEY_CSRF_TOKEN: ClassVar[str] = 'X-CSRFToken' KEY_DATA: ClassVar[str] = 'data' KEY_FORM: ClassVar[str] = 'form' - KEY_FORM_FILTERS: ClassVar[str] = KEY_FORM + 'Filters' - KEY_USER: ClassVar[str] = User.KEY_USER NAME_COMPANY: ClassVar[str] = 'Precision And Research Technology Systems Limited' NAME_CSRF_TOKEN: ClassVar[str] = 'csrf-token' # URL_HOST: ClassVar[str] = os.env() 'http://127.0.0.1:5000' # 'https://www.partsltd.co.uk' @@ -311,7 +314,7 @@ class Model_View_Base(BaseModel, ABC): 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) + return 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} @@ -340,4 +343,14 @@ class Model_View_Base(BaseModel, ABC): if str_multiline != '': str_multiline += '\n' str_multiline += str - return str_multiline \ No newline at end of file + return str_multiline + @staticmethod + def format_date(date): + if date is None: + return '' + return date.strftime('%Y-%m-%d') + @staticmethod + def format_datetime(date_time): + if date_time is None: + return '' + return date_time.strftime('%Y-%m-%dT%H:%M') \ No newline at end of file diff --git a/models/model_view_store.py b/models/model_view_store.py index a0a102e3..1509f051 100644 --- a/models/model_view_store.py +++ b/models/model_view_store.py @@ -24,6 +24,7 @@ from business_objects.store.image import Resolution_Level_Enum 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 business_objects.store.stock_item import Stock_Item 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 @@ -41,52 +42,63 @@ from abc import abstractmethod class Model_View_Store(Model_View_Base): # Global constants ATTR_FORM_TYPE: ClassVar[str] = 'form-type' + ATTR_ID_DELIVERY_OPTION: ClassVar[str] = Store_Base.ATTR_ID_DELIVERY_OPTION + ATTR_ID_DISCOUNT: ClassVar[str] = Store_Base.ATTR_ID_DISCOUNT + ATTR_ID_PLANT: ClassVar[str] = 'id-plant' ATTR_ID_PRODUCT : ClassVar[str] = Product.ATTR_ID_PRODUCT # 'id-product' 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_PRICE: ClassVar[str] = Product.ATTR_ID_PRODUCT_PRICE 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' + ATTR_ID_STOCK_ITEM: ClassVar[str] = Store_Base.ATTR_ID_STOCK_ITEM + ATTR_ID_STORAGE_LOCATION: ClassVar[str] = Store_Base.ATTR_ID_STORAGE_LOCATION FLAG_BUTTON_BASKET_ADD : ClassVar[str] = Model_View_Base.FLAG_SUBMIT + '.buttonAddToBasket' FLAG_BUTTON_BUY_NOW : ClassVar[str] = 'buttonBuyNow' - FLAG_COST_LOCAL: ClassVar[str] = Product_Permutation.FLAG_COST_LOCAL - # FLAG_COST_LOCAL_VAT_INCL: ClassVar[str] = 'cost-local-VAT-incl' + FLAG_COST_LOCAL: ClassVar[str] = Store_Base.FLAG_COST_LOCAL + FLAG_COST_LOCAL_VAT_EXCL: ClassVar[str] = Store_Base.FLAG_COST_LOCAL_VAT_EXCL + FLAG_COST_LOCAL_VAT_INCL: ClassVar[str] = Store_Base.FLAG_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_DATE_CONSUMED: ClassVar[str] = Stock_Item.FLAG_DATE_CONSUMED + FLAG_DATE_EXPIRATION: ClassVar[str] = Stock_Item.FLAG_DATE_EXPIRATION + FLAG_DATE_PURCHASED: ClassVar[str] = Stock_Item.FLAG_DATE_PURCHASED + FLAG_DATE_RECEIVED: ClassVar[str] = Stock_Item.FLAG_DATE_RECEIVED + FLAG_DATE_UNSEALED: ClassVar[str] = Stock_Item.FLAG_DATE_UNSEALED + FLAG_DISCOUNT: ClassVar[str] = Store_Base.FLAG_DISCOUNT 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_CONSUMED: ClassVar[str] = Stock_Item.FLAG_IS_CONSUMED 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_OUT_OF_STOCK: ClassVar[str] = Store_Base.FLAG_IS_OUT_OF_STOCK + FLAG_IS_SEALED: ClassVar[str] = Stock_Item.FLAG_IS_SEALED 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_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_PLANT: ClassVar[str] = Store_Base.FLAG_PLANT 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_PRICE: ClassVar[str] = Store_Base.FLAG_PRODUCT_PRICE 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_PROFIT_LOCAL_MIN: ClassVar[str] = Product_Permutation.FLAG_PROFIT_LOCAL_MIN 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_REGION: ClassVar[str] = Store_Base.FLAG_REGION + FLAG_STOCK_ITEM: ClassVar[str] = Store_Base.FLAG_STOCK_ITEM + FLAG_STORAGE_LOCATION: ClassVar[str] = Store_Base.FLAG_STORAGE_LOCATION 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 @@ -97,33 +109,32 @@ class Model_View_Store(Model_View_Base): 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' - HASH_STORE_BASKET_EDIT : ClassVar[str] = '/store/basket_edit' - 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_GET_STORE_PRODUCT_PERMUTATION: ClassVar[str] = '/store/permutation_get' HASH_GET_STORE_STOCK_ITEM: ClassVar[str] = '/store/stock_item_get' + HASH_PAGE_STORE_BASKET : ClassVar[str] = '/store/basket' HASH_SAVE_STORE_PRODUCT: ClassVar[str] = '/store/save_product' HASH_SAVE_STORE_PRODUCT_CATEGORY: ClassVar[str] = '/store/save_category' HASH_SAVE_STORE_PRODUCT_PERMUTATION: ClassVar[str] = '/store/save_permutation' HASH_SAVE_STORE_STOCK_ITEM: ClassVar[str] = '/store/save_stock_item' + HASH_STORE_BASKET_ADD : ClassVar[str] = '/store/basket_add' + HASH_STORE_BASKET_DELETE : ClassVar[str] = '/store/basket_delete' + HASH_STORE_BASKET_EDIT : ClassVar[str] = '/store/basket_edit' + HASH_STORE_BASKET_LOAD : ClassVar[str] = '/store/basket_load' 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' ID_BASKET : ClassVar[str] = 'basket' ID_BASKET_CONTAINER : ClassVar[str] = 'basketContainer' ID_BASKET_TOTAL : ClassVar[str] = 'basketTotal' - ID_BUTTON_CHECKOUT : ClassVar[str] = 'buttonCheckout' ID_BUTTON_BASKET_ADD : ClassVar[str] = 'buttonBasketAdd' ID_BUTTON_BUY_NOW : ClassVar[str] = 'buttonBuyNow' - ID_PRODUCT_CATEGORY_DEFAULT: ClassVar[str] = 1 + ID_BUTTON_CHECKOUT : ClassVar[str] = 'buttonCheckout' 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_PRODUCT_CATEGORY_DEFAULT: ClassVar[str] = 1 ID_REGION_DELIVERY_DEFAULT : ClassVar[str] = 1 IS_INCLUDED_VAT_DEFAULT : ClassVar[str] = True """ diff --git a/models/model_view_store_product.py b/models/model_view_store_product.py index 3528adcb..e5c42ed2 100644 --- a/models/model_view_store_product.py +++ b/models/model_view_store_product.py @@ -75,7 +75,7 @@ class Model_View_Store_Product(Model_View_Store): filters_product: Parameters_Product = None form_filters: Filters_Product list_options_product: list = None - product_blank: Product = None + # product_blank: Product = None units_measurement: list = None units_measurement_time: list = None # variation_container: Product_Variation_Container = None diff --git a/models/model_view_store_product_permutation.py b/models/model_view_store_product_permutation.py index 7bac6751..62cae7b9 100644 --- a/models/model_view_store_product_permutation.py +++ b/models/model_view_store_product_permutation.py @@ -42,7 +42,6 @@ class Model_View_Store_Product_Permutation(Model_View_Store): filters_product: Parameters_Product = None form_filters: Filters_Product_Permutation list_options_product: list = None - permutation_blank: Product_Permutation = None units_measurement: list = None units_measurement_time: list = None # variation_container: Product_Variation_Container = None @@ -79,12 +78,11 @@ class Model_View_Store_Product_Permutation(Model_View_Store): ) ) 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] + self.form_filters.id_category.choices += [(str(category.id_category), category.name) for category in self.category_list_filters.categories] print(f'category options: {self.form_filters.id_category.choices}') 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() + self.form_filters.id_product.choices += [(str(product['value']), product['text']) for product in self.list_options_product] 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] diff --git a/models/model_view_store_stock_item.py b/models/model_view_store_stock_item.py index 705a1349..95e193e7 100644 --- a/models/model_view_store_stock_item.py +++ b/models/model_view_store_stock_item.py @@ -16,7 +16,7 @@ from datastores.datastore_store_stock_item import DataStore_Store_Stock_Item from business_objects.store.product_category import Product_Category_Container # from routes import bp_home from business_objects.store.product import Product, Parameters_Product, Product_Permutation -from business_objects.store.stock_item import Stock_Item +from business_objects.store.stock_item import Stock_Item, Parameters_Stock_Item from forms.store.stock_item import Filters_Stock_Item import lib.argument_validation as av @@ -35,10 +35,17 @@ class Model_View_Store_Stock_Item(Model_View_Store): """ KEY_PERMUTATIONS: ClassVar[str] = 'permutations' - category_list: Product_Category_Container = None # (str) + category_list: Product_Category_Container = None + category_list_filters: Product_Category_Container = None + currencies: list = None + currency_options: list = None filters_stock_item: Filters_Stock_Item form_filters: Filters_Stock_Item = None - permutation_blank: Product_Permutation = None + list_options_product: list = None + units_measurement: list = None + units_measurement_time: list = None + variations: list = None + variation_types: list = None @property def title(self): @@ -49,13 +56,11 @@ class Model_View_Store_Stock_Item(Model_View_Store): print(f'{_m}\nstarting...') super().__init__(hash_page_current=hash_page_current, filters_stock_item=filters_stock_item) # BaseModel.__init__(self, app=app, filters_stock_item=filters_stock_item, **kwargs) - self.form_filters = Filters_Stock_Item() + self.form_filters = Filters_Stock_Item.from_json(filters_stock_item.to_json()) # .from_form_stock_item(filters_stock_item) datastore_store = DataStore_Store_Stock_Item() tmp_category_list_stock_item, errors = datastore_store.get_many_product(Parameters_Product.from_filters_stock_item(filters_stock_item)) - self.category_list, errors = datastore_store.get_many_stock_item(filters_stock_item, tmp_category_list_stock_item) - category_list_filters, errors_filters = datastore_store.get_many_stock_item( - Filters_Stock_Item() - ) + self.category_list, errors = datastore_store.get_many_stock_item(Parameters_Stock_Item.from_form_stock_item(filters_stock_item), tmp_category_list_stock_item) + self.category_list_filters, errors_filters = datastore_store.get_many_product(Parameters_Product.get_default()) """ Parameters_Stock_Item( # self.info_user['sub'], @@ -73,15 +78,26 @@ class Model_View_Store_Stock_Item(Model_View_Store): ) """ - 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 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.permutation_blank = Product_Permutation() + print(f'category_list_filters: {self.category_list_filters.categories}') + self.form_filters.id_category.choices += [(str(category.id_category), category.name) for category in self.category_list_filters.categories] # [Filters_Stock_Item.get_choice_all()] + print(f'category options: {self.form_filters.id_category.choices}') + product_list = self.category_list_filters.to_product_option_list() + filtered_product_list = [] + if product_list is not None: + for product in product_list: + # print(f'product: {product}\n{product[Stock_Item.ATTR_ID_PRODUCT_CATEGORY]}\n{self.form_filters.id_category.data}\n{str(type(product[Stock_Item.ATTR_ID_PRODUCT_CATEGORY]))}\n{str(type(self.form_filters.id_category.data))}') + if (self.form_filters.id_category.data == '' or str(product[Stock_Item.ATTR_ID_PRODUCT_CATEGORY]) == self.form_filters.id_category.data): + filtered_product_list.append(product) + print(f'product_list: {product_list}\nfiltered_product_list: {filtered_product_list}') + self.form_filters.id_product.choices += [(str(product['value']), product['text']) for product in filtered_product_list] # [Filters_Stock_Item.get_choice_all()] + + # self.form_filters.import_values(filters_stock_item) + 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_stock_item(self, comment, list_stock_items): - _m = 'Model_View_Store_Stock_Item.save_stock_item' - DataStore_Store_Stock_Item().save_stock_item(comment, list_stock_items) \ No newline at end of file + @classmethod + def save_stock_items(cls, comment, list_stock_items): + _m = f'{cls.__name__}.save_stock_items' + return DataStore_Store_Stock_Item().save_stock_items(comment, list_stock_items) \ No newline at end of file diff --git a/models/model_view_store_supplier.py b/models/model_view_store_supplier.py index afdb4d27..c210fb1c 100644 --- a/models/model_view_store_supplier.py +++ b/models/model_view_store_supplier.py @@ -34,5 +34,5 @@ class Model_View_Store_Supplier(Model_View_Store): av.val_instance(form, 'form', _m, FlaskForm) return super(Model_View_Supplier, cls).__new__(cls, db, info_user, app) """ - def __init__(self,form, hash_page_current=Model_View_Base.HASH_PAGE_STORE_SUPPLIER): + def __init__(self,form, hash_page_current=Model_View_Base.HASH_PAGE_STORE_SUPPLIERS): super().__init__(hash_page_current=hash_page_current, form=form) diff --git a/requirements.txt b/requirements.txt index fe8064e2..cad5cd2f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,4 +12,4 @@ python_dotenv authlib pydantic # psycopg2 - +requests diff --git a/static/MySQL/0000_combine.sql b/static/MySQL/0000_combine.sql index b25480b3..8e50d762 100644 --- a/static/MySQL/0000_combine.sql +++ b/static/MySQL/0000_combine.sql @@ -41,6 +41,8 @@ DROP TABLE IF EXISTS tmp_Shop_Customer_Sale_Order; # Delete old tables DROP TABLE IF EXISTS Split_Temp; +DROP TABLE IF EXISTS Split_Key_Value_Pair_Csv_Temp; +DROP TABLE IF EXISTS Split_Key_Value_Pair_Temp; DROP TABLE IF EXISTS Shop_User_Eval_Temp; DROP TABLE IF EXISTS Shop_Calc_User_Temp; @@ -87,8 +89,8 @@ DROP TABLE IF EXISTS Shop_User_Order_Status; DROP TABLE IF EXISTS Shop_User_Basket_Audit; DROP TABLE IF EXISTS Shop_User_Basket; -DROP TABLE IF EXISTS Shop_Address_Audit; -DROP TABLE IF EXISTS Shop_Address; +DROP TABLE IF EXISTS Shop_User_Address_Audit; +DROP TABLE IF EXISTS Shop_User_Address; DROP TABLE IF EXISTS Shop_User_Role_Link_Audit; DROP TABLE IF EXISTS Shop_User_Role_Link; @@ -190,6 +192,9 @@ DROP TABLE IF EXISTS Shop_Plant_Temp; DROP TABLE IF EXISTS Shop_Plant_Audit; DROP TABLE IF EXISTS Shop_Plant; +DROP TABLE IF EXISTS Shop_Address_Audit; +DROP TABLE IF EXISTS Shop_Address; + DROP TABLE IF EXISTS Shop_Delivery_Region_Branch_Audit; DROP TABLE IF EXISTS Shop_Delivery_Region_Branch; DROP TABLE IF EXISTS Shop_Region_Branch_Temp; @@ -232,6 +237,9 @@ DROP TABLE IF EXISTS Shop_Product_Change_Set; -- Procedures DROP PROCEDURE IF EXISTS p_split; DROP PROCEDURE IF EXISTS p_clear_split_temp; +DROP PROCEDURE IF EXISTS p_split_key_value_pair_csv; +DROP PROCEDURE IF EXISTS p_clear_split_key_value_csv_temp; +DROP PROCEDURE IF EXISTS p_clear_split_key_value_pair_csv_temp; DROP PROCEDURE IF EXISTS p_debug_timing_reporting; DROP PROCEDURE IF EXISTS p_validate_guid; @@ -248,12 +256,15 @@ 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_plant; +DROP PROCEDURE IF EXISTS p_shop_get_many_storage_location; DROP PROCEDURE IF EXISTS p_shop_get_many_currency; DROP PROCEDURE IF EXISTS p_shop_save_category; DROP PROCEDURE IF EXISTS p_shop_save_product_category; DROP PROCEDURE IF EXISTS p_shop_save_product_category_test; DROP PROCEDURE IF EXISTS p_shop_save_product; +DROP PROCEDURE IF EXISTS p_shop_save_product_test; DROP PROCEDURE IF EXISTS p_shop_calc_product_permutation; DROP PROCEDURE IF EXISTS p_shop_clear_calc_product_permutation; DROP PROCEDURE IF EXISTS p_shop_get_many_product; @@ -261,6 +272,9 @@ 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 FUNCTION IF EXISTS fn_shop_get_id_product_permutation_from_variation_csv_list; +DROP PROCEDURE IF EXISTS p_shop_save_stock_item; +DROP PROCEDURE IF EXISTS p_shop_save_stock_item_test; 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; DROP PROCEDURE IF EXISTS p_shop_get_many_product_price_and_discount_and_delivery_option; @@ -318,6 +332,19 @@ CREATE TABLE IF NOT EXISTS Shop_User_Change_Set ( updated_last_on TIMESTAMP, updated_last_by VARCHAR(100) ); +# Split Key Value Pair CSV Staging +-- USE partsltd_prod; +-- DROP TABLE IF EXISTS Split_Temp; + +SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Split_Key_Value_Pair_Csv_Temp'; + +CREATE TABLE Split_Key_Value_Pair_Csv_Temp ( + guid BINARY(36) NOT NULL + , id INT NOT NULL + , key_column VARCHAR(4000) NULL + , value_column VARCHAR(4000) NULL +); + # Sales And Purchasing Change Sets @@ -512,8 +539,6 @@ CREATE TABLE IF NOT EXISTS Shop_Image_Type_Audit ( ); # Regions - - SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Region'; CREATE TABLE IF NOT EXISTS Shop_Region ( @@ -632,10 +657,29 @@ CREATE TABLE IF NOT EXISTS Shop_Region_Branch_Temp ( active BIT NOT NULL DEFAULT 1, display_order INT NOT NULL ); +# Addresses + + +SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Address'; + +CREATE TABLE Shop_Address ( + id_address INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + id_region INT NOT NULL, + postcode VARCHAR(20) NOT NULL, + address_line_1 VARCHAR(256) NOT NULL, + address_line_2 VARCHAR(256) NOT NULL, + city VARCHAR(256) NOT NULL, + county VARCHAR(256) NOT NULL, + active BIT NOT NULL DEFAULT 1, + created_on TIMESTAMP, + created_by INT, + id_change_set INT, + CONSTRAINT FK_Shop_Address_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES Shop_User_Change_Set(id_change_set) +); # Plant - - SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Plant'; CREATE TABLE IF NOT EXISTS Shop_Plant ( @@ -643,6 +687,9 @@ CREATE TABLE IF NOT EXISTS Shop_Plant ( code VARCHAR(50) NOT NULL, name VARCHAR(500) NOT NULL, id_address INT NOT NULL, + CONSTRAINT FK_Shop_Plant_id_address + FOREIGN KEY (id_address) + REFERENCES Shop_Address(id_address), id_user_manager INT NOT NULL, active BIT NOT NULL DEFAULT 1, created_on TIMESTAMP, @@ -653,6 +700,28 @@ CREATE TABLE IF NOT EXISTS Shop_Plant ( REFERENCES Shop_Product_Change_Set(id_change_set) ); +# Address Audits + + + +SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Address_Audit'; + +CREATE TABLE IF NOT EXISTS Shop_Address_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + id_address INT NOT NULL, + CONSTRAINT FK_Shop_Address_Audit_id_address + FOREIGN KEY (id_address) + REFERENCES Shop_Address(id_address) + ON UPDATE RESTRICT, + name_field VARCHAR(50), + value_prev VARCHAR(500), + value_new VARCHAR(500), + id_change_set INT NOT NULL, + CONSTRAINT FK_Shop_Address_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES Shop_User_Change_Set(id_change_set) + ON UPDATE RESTRICT +); # Plant Audits @@ -682,12 +751,13 @@ CREATE TABLE IF NOT EXISTS Shop_Plant_Audit ( SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Plant_Temp'; CREATE TABLE IF NOT EXISTS Shop_Plant_Temp ( - id_plant INT NOT NULL PRIMARY KEY, - code VARCHAR(50) NOT NULL, - name VARCHAR(500) NOT NULL, - id_address INT NOT NULL, - id_user_manager INT NOT NULL, - active BIT NOT NULL DEFAULT 1 + id_plant INT NOT NULL PRIMARY KEY + , code VARCHAR(50) NOT NULL + , name VARCHAR(500) NOT NULL + , id_address INT NOT NULL + , id_user_manager INT NOT NULL + , active BIT NOT NULL DEFAULT 1 + , guid BINARY(36) NOT NULL ); # Storage Location @@ -1457,7 +1527,7 @@ CREATE TABLE IF NOT EXISTS Shop_Product_Permutation_Variation_Link_Audit ( ); # Stock Stock Item - +-- DROP TABLE IF EXISTS Shop_Stock_Item; SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Stock_Item'; @@ -1467,8 +1537,8 @@ CREATE TABLE IF NOT EXISTS Shop_Stock_Item ( CONSTRAINT FK_Shop_Stock_Item_id_permutation FOREIGN KEY (id_permutation) REFERENCES Shop_Product_Permutation(id_permutation), - date_purchased TIMESTAMP NOT NULL, - date_received TIMESTAMP NULL, + date_purchased DATETIME NOT NULL, + date_received DATETIME NULL, id_location_storage INT NOT NULL, CONSTRAINT FK_Shop_Stock_Item_id_location_storage FOREIGN KEY (id_location_storage) @@ -1477,15 +1547,15 @@ CREATE TABLE IF NOT EXISTS Shop_Stock_Item ( CONSTRAINT FK_Shop_Stock_Item_id_currency FOREIGN KEY (id_currency_cost) REFERENCES Shop_Currency(id_currency), - cost_local_VAT_incl FLOAT NOT NULL, - cost_local_VAT_excl FLOAT NOT NULL, + cost_local_VAT_incl FLOAT NULL, + cost_local_VAT_excl FLOAT NULL, is_sealed BIT NOT NULL DEFAULT 1, - date_unsealed TIMESTAMP NULL, - date_expiration TIMESTAMP NOT NULL, + date_unsealed DATETIME NULL, + date_expiration DATETIME NOT NULL, is_consumed BIT NOT NULL DEFAULT 0, - date_consumed TIMESTAMP NULL, + date_consumed DATETIME NULL, active BIT NOT NULL DEFAULT 1, - created_on TIMESTAMP, + created_on DATETIME, created_by INT, id_change_set INT, CONSTRAINT FK_Shop_Stock_Item_id_change_set @@ -1518,24 +1588,29 @@ CREATE TABLE IF NOT EXISTS Shop_Stock_Item_Audit ( # Stock Stock Item Temp - +DROP TABLE IF EXISTS Shop_Stock_Item_Temp; SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Stock_Item_Temp'; CREATE TABLE IF NOT EXISTS Shop_Stock_Item_Temp ( - id_stock INT NOT NULL PRIMARY KEY, - id_permutation INT NOT NULL, - date_purchased TIMESTAMP NOT NULL, - id_location_storage INT NOT NULL, - id_currency INT NOT NULL, - cost_local_VAT_incl FLOAT NOT NULL, - cost_local_VAT_excl FLOAT NOT NULL, - is_sealed BIT NOT NULL DEFAULT 1, - date_unsealed TIMESTAMP NULL, - date_expiration TIMESTAMP NULL, - is_consumed BIT NOT NULL DEFAULT 0, - date_consumed TIMESTAMP NULL, - active BIT NOT NULL DEFAULT 1 + id_stock INT NULL + -- , id_category INT NULL + , id_product INT NOT NULL + , id_permutation INT NULL + , id_pairs_variations VARCHAR(4000) NULL + , date_purchased DATETIME NOT NULL + , date_received DATETIME NULL + , id_location_storage INT NOT NULL + , id_currency_cost INT NOT NULL + , cost_local_VAT_incl FLOAT NOT NULL + , cost_local_VAT_excl FLOAT NOT NULL + , is_sealed BIT NOT NULL + , date_unsealed DATETIME NULL + , date_expiration DATETIME NULL + , is_consumed BIT NOT NULL + , date_consumed DATETIME NULL + , active BIT NOT NULL + , guid BINARY(36) NOT NULL ); # Product Price @@ -1868,45 +1943,6 @@ CREATE TABLE IF NOT EXISTS Shop_Discount_Region_Currency_Link ( FOREIGN KEY (id_change_set) REFERENCES Shop_Product_Change_Set(id_change_set) ); -# Product Currency Region link - - - -SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Product_Currency_Region_Link'; - -CREATE TABLE IF NOT EXISTS Shop_Product_Currency_Region_Link ( - id_link INT NOT NULL AUTO_INCREMENT PRIMARY KEY, - id_product INT NOT NULL, - CONSTRAINT FK_Shop_Product_Currency_Region_Link_id_product - FOREIGN KEY (id_product) - REFERENCES Shop_Product(id_product) - ON UPDATE RESTRICT, - id_permutation INT NULL, - CONSTRAINT FK_Shop_Product_Currency_Region_Link_id_permutation - FOREIGN KEY (id_permutation) - REFERENCES Shop_Product_Permutation(id_permutation) - ON UPDATE RESTRICT, - id_currency INT NOT NULL, - CONSTRAINT FK_Shop_Product_Currency_Region_Link_id_currency - FOREIGN KEY (id_currency) - REFERENCES Shop_Currency(id_currency) - ON UPDATE RESTRICT, - id_region_purchase INT NOT NULL, - CONSTRAINT FK_Shop_Product_Currency_Region_Link_id_region_purchase - FOREIGN KEY (id_region_purchase) - REFERENCES Shop_Region(id_region) - ON UPDATE RESTRICT, - price_local_VAT_incl FLOAT NULL, - price_local_VAT_excl FLOAT NULL, - id_stripe_price VARCHAR(200), - active BIT NOT NULL DEFAULT 1, - created_on TIMESTAMP, - created_by INT, - id_change_set INT, - CONSTRAINT FK_Shop_Product_Currency_Region_Link_id_change_set - FOREIGN KEY (id_change_set) - REFERENCES Shop_Product_Change_Set(id_change_set) -); # Discount Region Currency Link Audits @@ -1929,28 +1965,6 @@ CREATE TABLE IF NOT EXISTS Shop_Discount_Region_Currency_Link_Audit ( REFERENCES Shop_Product_Change_Set(id_change_set) ON UPDATE RESTRICT ); -# Product Currency Region Link Audits - - - -SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Product_Currency_Region_Link_Audit'; - -CREATE TABLE IF NOT EXISTS Shop_Product_Currency_Region_Link_Audit ( - id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY, - id_link INT NOT NULL, - CONSTRAINT FK_Shop_Product_Currency_Region_Link_Audit_id_link - FOREIGN KEY (id_link) - REFERENCES Shop_Product_Currency_Region_Link(id_link) - ON UPDATE RESTRICT, - name_field VARCHAR(50), - value_prev VARCHAR(500), - value_new VARCHAR(500), - id_change_set INT NOT NULL, - CONSTRAINT FK_Shop_Product_Currency_Region_Link_Audit_id_change_set - FOREIGN KEY (id_change_set) - REFERENCES Shop_Product_Change_Set(id_change_set) -); - # Permission Groups @@ -2230,14 +2244,12 @@ CREATE TABLE IF NOT EXISTS Shop_User_Role_Link_Audit ( REFERENCES Shop_User_Change_Set(id_change_set) ); -# Addresses +# User Addresses +SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_User_Address'; - -SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Address'; - -CREATE TABLE Shop_Address ( - id_address INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +CREATE TABLE Shop_User_Address ( + id_user_address INT NOT NULL AUTO_INCREMENT PRIMARY KEY, id_user INT NOT NULL, CONSTRAINT FK_Shop_Address_id_user FOREIGN KEY (id_user) @@ -2248,36 +2260,34 @@ CREATE TABLE Shop_Address ( name_full VARCHAR(255) NOT NULL, phone_number VARCHAR(20) NOT NULL, postcode VARCHAR(20) NOT NULL, - address_line_1 VARCHAR(100) NOT NULL, - address_line_2 VARCHAR(100) NOT NULL, - city VARCHAR(50) NOT NULL, - county VARCHAR(100) NOT NULL, + address_line_1 VARCHAR(256) NOT NULL, + address_line_2 VARCHAR(256) NOT NULL, + city VARCHAR(256) NOT NULL, + county VARCHAR(256) NOT NULL, active BIT NOT NULL DEFAULT 1, created_on TIMESTAMP, created_by INT, id_change_set INT, - CONSTRAINT FK_Shop_Address_id_change_set + CONSTRAINT FK_Shop_User_Address_id_change_set FOREIGN KEY (id_change_set) REFERENCES Shop_User_Change_Set(id_change_set) ); # Address Audits +SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_User_Address_Audit'; - -SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Address_Audit'; - -CREATE TABLE IF NOT EXISTS Shop_Address_Audit ( +CREATE TABLE IF NOT EXISTS Shop_User_Address_Audit ( id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY, - id_address INT NOT NULL, - CONSTRAINT FK_Shop_Address_Audit_id_address - FOREIGN KEY (id_address) - REFERENCES Shop_Address(id_address) + id_user_address INT NOT NULL, + CONSTRAINT FK_Shop_User_Address_Audit_id_address + FOREIGN KEY (id_user_address) + REFERENCES Shop_User_Address(id_user_address) ON UPDATE RESTRICT, name_field VARCHAR(50), value_prev VARCHAR(500), value_new VARCHAR(500), id_change_set INT NOT NULL, - CONSTRAINT FK_Shop_Address_Audit_id_change_set + CONSTRAINT FK_Shop_User_Address_Audit_id_change_set FOREIGN KEY (id_change_set) REFERENCES Shop_User_Change_Set(id_change_set) ON UPDATE RESTRICT @@ -3378,6 +3388,72 @@ BEGIN END // DELIMITER ;; +# Shop Address + + + +DROP TRIGGER IF EXISTS before_insert_Shop_Address; +DROP TRIGGER IF EXISTS before_update_Shop_Address; + + +DELIMITER // +CREATE TRIGGER before_insert_Shop_Address +BEFORE INSERT ON Shop_Address +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 // +DELIMITER ;; + + +DELIMITER // +CREATE TRIGGER before_update_Shop_Address +BEFORE UPDATE ON Shop_Address +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_Address_Audit ( + id_address, + name_field, + value_prev, + value_new, + id_change_set + ) + # Changed region + SELECT NEW.id_address, 'id_region', OLD.id_region, NEW.id_region, NEW.id_change_set + WHERE NOT OLD.id_region <=> NEW.id_region + UNION + # Changed postcode + SELECT NEW.id_address, 'postcode', OLD.postcode, NEW.postcode, NEW.id_change_set + WHERE NOT OLD.postcode <=> NEW.postcode + UNION + # Changed address_line_1 + SELECT NEW.id_address, 'address_line_1', OLD.address_line_1, NEW.address_line_1, NEW.id_change_set + WHERE NOT OLD.address_line_1 <=> NEW.address_line_1 + UNION + # Changed address_line_2 + SELECT NEW.id_address, 'address_line_2', OLD.address_line_2, NEW.address_line_2, NEW.id_change_set + WHERE NOT OLD.address_line_2 <=> NEW.address_line_2 + UNION + # Changed city + SELECT NEW.id_address, 'city', OLD.city, NEW.city, NEW.id_change_set + WHERE NOT OLD.city <=> NEW.city + UNION + # Changed county + SELECT NEW.id_address, 'county', OLD.county, NEW.county, NEW.id_change_set + WHERE NOT OLD.county <=> NEW.county + UNION + # Changed active + SELECT NEW.id_address, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ;; # Shop Storage Location @@ -5018,13 +5094,13 @@ DELIMITER ;; -DROP TRIGGER IF EXISTS before_insert_Shop_Address; -DROP TRIGGER IF EXISTS before_update_Shop_Address; +DROP TRIGGER IF EXISTS before_insert_Shop_User_Address; +DROP TRIGGER IF EXISTS before_update_Shop_User_Address; DELIMITER // -CREATE TRIGGER before_insert_Shop_Address -BEFORE INSERT ON Shop_Address +CREATE TRIGGER before_insert_Shop_User_Address +BEFORE INSERT ON Shop_User_Address FOR EACH ROW BEGIN SET NEW.created_on := IFNULL(NEW.created_on, NOW()); @@ -5034,8 +5110,8 @@ DELIMITER ;; DELIMITER // -CREATE TRIGGER before_update_Shop_Address -BEFORE UPDATE ON Shop_Address +CREATE TRIGGER before_update_Shop_User_Address +BEFORE UPDATE ON Shop_User_Address FOR EACH ROW BEGIN IF OLD.id_change_set <=> NEW.id_change_set THEN @@ -5043,47 +5119,47 @@ BEGIN SET MESSAGE_TEXT = 'New change Set ID must be provided.'; END IF; - INSERT INTO Shop_Address_Audit ( - id_address, + INSERT INTO Shop_User_Address_Audit ( + id_user_address, name_field, value_prev, value_new, id_change_set ) # Changed region - SELECT NEW.id_address, 'id_region', OLD.id_region, NEW.id_region, NEW.id_change_set + SELECT NEW.id_user_address, 'id_region', OLD.id_region, NEW.id_region, NEW.id_change_set WHERE NOT OLD.id_region <=> NEW.id_region UNION # Changed name_full - SELECT NEW.id_address, 'name_full', OLD.name_full, NEW.name_full, NEW.id_change_set + SELECT NEW.id_user_address, 'name_full', OLD.name_full, NEW.name_full, NEW.id_change_set WHERE NOT OLD.name_full <=> NEW.name_full UNION # Changed phone_number - SELECT NEW.id_address, 'phone_number', OLD.phone_number, NEW.phone_number, NEW.id_change_set + SELECT NEW.id_user_address, 'phone_number', OLD.phone_number, NEW.phone_number, NEW.id_change_set WHERE NOT OLD.phone_number <=> NEW.phone_number UNION # Changed postcode - SELECT NEW.id_address, 'postcode', OLD.postcode, NEW.postcode, NEW.id_change_set + SELECT NEW.id_user_address, 'postcode', OLD.postcode, NEW.postcode, NEW.id_change_set WHERE NOT OLD.postcode <=> NEW.postcode UNION # Changed address_line_1 - SELECT NEW.id_address, 'address_line_1', OLD.address_line_1, NEW.address_line_1, NEW.id_change_set + SELECT NEW.id_user_address, 'address_line_1', OLD.address_line_1, NEW.address_line_1, NEW.id_change_set WHERE NOT OLD.address_line_1 <=> NEW.address_line_1 UNION # Changed address_line_2 - SELECT NEW.id_address, 'address_line_2', OLD.address_line_2, NEW.address_line_2, NEW.id_change_set + SELECT NEW.id_user_address, 'address_line_2', OLD.address_line_2, NEW.address_line_2, NEW.id_change_set WHERE NOT OLD.address_line_2 <=> NEW.address_line_2 UNION # Changed city - SELECT NEW.id_address, 'city', OLD.city, NEW.city, NEW.id_change_set + SELECT NEW.id_user_address, 'city', OLD.city, NEW.city, NEW.id_change_set WHERE NOT OLD.city <=> NEW.city UNION # Changed county - SELECT NEW.id_address, 'county', OLD.county, NEW.county, NEW.id_change_set + SELECT NEW.id_user_address, 'county', OLD.county, NEW.county, NEW.id_change_set WHERE NOT OLD.county <=> NEW.county UNION # Changed active - SELECT NEW.id_address, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + SELECT NEW.id_user_address, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set WHERE NOT (OLD.active <=> NEW.active) ; END // @@ -6028,6 +6104,8 @@ BEGIN COMMIT; END IF; + DROP TABLE IF EXISTS tmp_Split_Split; + IF a_debug = 1 THEN CALL p_debug_timing_reporting ( v_time_start ); END IF; @@ -6138,6 +6216,143 @@ END // DELIMITER ;; CALL p_validate_guid_test(); + +DROP PROCEDURE IF EXISTS p_split_key_value_pair_csv; + +DELIMITER // +CREATE PROCEDURE p_split_key_value_pair_csv ( + IN a_guid BINARY(36) + , IN a_string LONGTEXT + , IN a_debug BIT +) +BEGIN + DECLARE v_has_string BIT; + DECLARE v_current_item VARCHAR(4000); + DECLARE v_time_start TIMESTAMP(6); + + SET v_time_start := CURRENT_TIMESTAMP(6); + SET a_string := IFNULL(a_string, ''); + SET a_debug := IFNULL(a_debug, 0); + + SET v_has_string = CASE WHEN a_string = '' THEN 0 ELSE 1 END; + + IF a_debug = 1 THEN + SELECT + a_guid + , a_string + , a_debug + ; + END IF; + + CALL p_validate_guid ( a_guid ); + + DROP TEMPORARY TABLE IF EXISTS tmp_Split_Input; + DROP TEMPORARY TABLE IF EXISTS tmp_Split_Split; + + CREATE TEMPORARY TABLE tmp_Split_Input ( + input_string TEXT + ); + + CREATE TEMPORARY TABLE tmp_Split_Split ( + id INT AUTO_INCREMENT PRIMARY KEY + , key_column VARCHAR(4000) + , value_column VARCHAR(4000) + ); + + INSERT INTO tmp_Split_Input ( + input_string + ) + VALUES ( + a_string + ); + + INSERT INTO tmp_Split_Split (key_column, value_column) + SELECT + SUBSTRING_INDEX(SUBSTRING_INDEX(t.pair, ':', 1), ',', -1) AS key_column, + SUBSTRING_INDEX(t.pair, ':', -1) AS value_column + FROM ( + SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(input_string, ',', n), ',', -1) pair + FROM temp_input + CROSS JOIN ( + SELECT a.N + b.N * 10 + 1 n + FROM (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a + CROSS JOIN (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b + ORDER BY n + ) numbers + WHERE n <= 1 + (LENGTH(input_string) - LENGTH(REPLACE(input_string, ',', ''))) + ) t; + + IF EXISTS (SELECT * FROM tmp_Split_Split LIMIT 1) THEN + START TRANSACTION; + INSERT INTO Split_Key_Value_Pair_Csv_Temp ( + guid + , id + , key_column + , value_column + ) + SELECT + a_guid + , id + , key_column + , value_column + FROM tmp_Split_Split + ; + COMMIT; + END IF; + + DROP TEMPORARY TABLE IF EXISTS tmp_Split_Input; + DROP TEMPORARY TABLE IF EXISTS tmp_Split_Split; + + IF a_debug = 1 THEN + CALL p_debug_timing_reporting ( v_time_start ); + END IF; +END // +DELIMITER ;; + + +/* +CALL p_split_key_value_pair_csv ( + 'nipsnipsnipsnipsnipsnipsnipsnipsnips' + , '1:100,2:200,3:300,4:400' # a_string + , 1 +); + +SELECT * +FROM Split_key_value_pair_csv_Temp +WHERE GUID = 'nipsnipsnipsnipsnipsnipsnipsnipsnips'; + +CALL p_clear_split_key_value_pair_csv_temp( 'nipsnipsnipsnipsnipsnipsnipsnipsnips' ); +*/ + +-- Clear previous proc +DROP PROCEDURE IF EXISTS p_clear_split_key_value_pair_csv_temp; + + +DELIMITER // +CREATE PROCEDURE p_clear_split_key_value_pair_csv_temp ( + IN a_guid BINARY(36) +) +BEGIN + CALL p_validate_guid( a_guid ); + + START TRANSACTION; + + -- DROP TABLE IF EXISTS + DELETE FROM Split_Key_Value_Pair_Csv_Temp + WHERE GUID = a_guid + ; + + COMMIT; +END // +DELIMITER ;; + +/* + +CALL p_clear_split_key_value_pair_csv_temp ( 'nipsnipsnipsnipsnipsnipsnipsnipsnips' ); + + +*/ + DROP FUNCTION IF EXISTS fn_shop_get_product_permutation_name; DELIMITER // @@ -6863,6 +7078,79 @@ CALL p_shop_get_many_region ( */ +-- Clear previous proc +DROP PROCEDURE IF EXISTS p_shop_get_many_plant; + + +DELIMITER // +CREATE PROCEDURE p_shop_get_many_plant ( + IN a_get_inactive_plant BIT +) +BEGIN + SET a_get_inactive_plant = IFNULL(a_get_inactive_plant, 0); + + SELECT + P.id_plant + , P.id_address + , A.id_region + , P.id_user_manager + , P.code + , P.name + , P.active + FROM Shop_Plant P + INNER JOIN Shop_Address A ON P.id_address = A.id_address + WHERE + a_get_inactive_plant = 1 + OR P.active = 1 + ; +END // +DELIMITER ;; + + +/* +CALL p_shop_get_many_plant ( + 0 # a_get_inactive_plant +); +*/ + + +-- Clear previous proc +DROP PROCEDURE IF EXISTS p_shop_get_many_storage_location; + + +DELIMITER // +CREATE PROCEDURE p_shop_get_many_storage_location ( + IN a_get_inactive_storage_location BIT +) +BEGIN + SET a_get_inactive_storage_location = IFNULL(a_get_inactive_storage_location, 0); + + SELECT + SL.id_storage_location + , P.id_plant + , P.id_address + , A.id_region + , SL.code + , SL.name + , P.active + FROM Shop_Storage_Location SL + INNER JOIN Shop_Plant P ON SL.id_plant = P.id_plant + INNER JOIN Shop_Address A ON P.id_address = A.id_address + WHERE + a_get_inactive_storage_location = 1 + OR SL.active = 1 + ; +END // +DELIMITER ;; + + +/* +CALL p_shop_get_many_storage_location ( + 0 # a_get_inactive_storage_location +); +*/ + + /* @@ -6959,9 +7247,9 @@ DROP PROCEDURE IF EXISTS p_shop_save_product_category; DELIMITER // CREATE PROCEDURE p_shop_save_product_category ( - IN a_id_user INT, + IN a_comment VARCHAR(500), IN a_guid BINARY(36), - IN a_comment VARCHAR(500) + IN a_id_user INT ) BEGIN DECLARE v_code_type_error_bad_data VARCHAR(100); @@ -7157,59 +7445,59 @@ BEGIN 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(); + 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_Category PC + INNER JOIN tmp_Category t_C ON PC.id_category = t_C.id_category + SET + PC.id_category = t_C.id_category + , 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 + ; + END IF; - UPDATE Shop_Product_Category PC - INNER JOIN tmp_Category t_C ON PC.id_category = t_C.id_category - SET - PC.id_category = t_C.id_category - , 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 + INSERT INTO Shop_Product_Category ( + code + , name + , description + , id_access_level_required + , active + , display_order + , created_by + , created_on + ) + SELECT + -- t_C.id_category AS id_category + 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 + , v_now AS created_on + FROM tmp_Category t_C + WHERE is_new = 1 + AND active = 1 ; - END IF; - - INSERT INTO Shop_Product_Category ( - code - , name - , description - , id_access_level_required - , active - , display_order - , created_by - , created_on - ) - SELECT - -- t_C.id_category AS id_category - 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 - , v_now AS created_on - FROM tmp_Category t_C - WHERE is_new = 1 - AND active = 1 - ; + DELETE FROM Shop_Product_Category_Temp + WHERE GUID = a_guid; + COMMIT; END IF; - DELETE FROM Shop_Product_Category_Temp - WHERE GUID = a_guid; - SELECT * FROM tmp_Msg_Error; DROP TEMPORARY TABLE IF EXISTS tmp_Catgory; @@ -7554,16 +7842,19 @@ DROP PROCEDURE IF EXISTS p_shop_save_product; DELIMITER // CREATE PROCEDURE p_shop_save_product ( + IN a_comment VARCHAR(500), IN a_guid BINARY(36), - IN a_id_user INT, - IN a_comment VARCHAR(500) + IN a_id_user INT, + IN a_debug BIT ) BEGIN DECLARE v_code_type_error_bad_data VARCHAR(100); + DECLARE v_id_access_level_edit INT; 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_time_start TIMESTAMP(6); DECLARE exit handler for SQLEXCEPTION BEGIN @@ -7580,24 +7871,44 @@ BEGIN -- Select the error information -- SELECT 'Error' AS status, @errno AS error_code, @sqlstate AS sql_state, @text AS message; INSERT INTO tmp_Msg_Error ( - guid - , id_type + -- guid + id_type , code , msg ) SELECT - a_guid - , NULL + -- a_guid + (SELECT id_type FROM Shop_Msg_Error_Type WHERE code = 'MYSQL_ERROR' LIMIT 1) , @errno - , @text + , IFNULL(@text, 'NULL') ; + + SELECT * + FROM tmp_Msg_Error t_ME + INNER JOIN partsltd_prod.Shop_Msg_Error_Type MET ON t_ME.id_type = MET.id_type + ; + + DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error; + DROP TEMPORARY TABLE IF EXISTS tmp_Product; END; - SET v_code_type_error_bad_data := 'BAD_DATA'; + SET v_time_start := CURRENT_TIMESTAMP(6); + SET v_code_type_error_bad_data := (SELECT code FROM Shop_Msg_Error_Type WHERE code = 'BAD_DATA' LIMIT 1); 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()); + SET a_debug := IFNULL(a_debug, 0); + IF a_debug = 1 THEN + SELECT + v_code_type_error_bad_data + , v_id_type_error_bad_data + ; + END IF; + + DROP TEMPORARY TABLE IF EXISTS tmp_Product; + DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error; CREATE TEMPORARY TABLE tmp_Product ( id_category INT NOT NULL @@ -7616,7 +7927,7 @@ BEGIN CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error ( display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT - , guid BINARY(36) NOT NULL + -- , guid BINARY(36) NOT NULL , id_type INT NOT NULL /* CONSTRAINT FK_tmp_Msg_Error_id_type @@ -7643,79 +7954,115 @@ BEGIN SELECT IFNULL(P_T.id_category, P.id_category) AS id_category , IFNULL(P_T.id_product, 0) AS id_product - , IFNULL(PT.name, P.name) AS name - , IFNULL(PT.has_variations, P.has_variations) AS has_variations - , IFNULL(PT.id_access_level_required, P.id_access_level_required) AS id_access_level_required + , IFNULL(P_T.name, P.name) AS name + , IFNULL(P_T.has_variations, P.has_variations) AS has_variations + , IFNULL(P_T.id_access_level_required, P.id_access_level_required) AS id_access_level_required , IFNULL(P_T.active, P.active) AS active , IFNULL(P_T.display_order, P.display_order) AS display_order - , IFNULL(PT.name, IFNULL(P.name, IFNULL(P_T.id_product, '(No Product)'))) AS name_error + , IFNULL(P_T.name, IFNULL(P.name, IFNULL(P_T.id_product, '(No Product)'))) AS name_error , CASE WHEN IFNULL(P_T.id_product, 0) < 1 THEN 1 ELSE 0 END AS is_new - FROM Shop_Product_Tenp P_T - LEFT JOIN Shop_Product P ON P_T.id_product = P.id_product + FROM partsltd_prod.Shop_Product_Temp P_T + LEFT JOIN partsltd_prod.Shop_Product P ON P_T.id_product = P.id_product ; -- Validation - -- Missing mandatory fields - INSERT INTO tmp_Msg_Error ( - guid - , id_type - , code - , msg - ) + -- Missing mandatory fields -- id_category - SELECT - a_guid AS GUID - , v_id_type_error_bad_data - , v_code_error_bad_data - , CONCAT('The following product(s) do not have a category: ', GROUP_CONCAT(t_P.name_error SEPARATOR ', ')) - FROM tmp_Product t_P - WHERE ISNULL(t_P.id_category) - UNION + IF EXISTS (SELECT * FROM tmp_Product t_P WHERE ISNULL(t_P.id_category) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , IFNULL(CONCAT('The following product(s) do not have a category: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')), 'NULL') + FROM tmp_Product t_P + WHERE ISNULL(t_P.id_category) + ; + END IF; + -- name - SELECT - a_guid AS GUID - , v_id_type_error_bad_data - , v_code_error_bad_data - , CONCAT('The following product(s) do not have a name: ', GROUP_CONCAT(t_P.name_error SEPARATOR ', ')) - FROM tmp_Product t_P - WHERE ISNULL(t_P.name) - UNION + IF EXISTS (SELECT * FROM tmp_Product t_P WHERE ISNULL(t_P.name) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , IFNULL(CONCAT('The following product(s) do not have a name: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')), 'NULL') + FROM tmp_Product t_P + WHERE ISNULL(t_P.name) + ; + END IF; + -- has_variations - SELECT - a_guid AS GUID - , v_id_type_error_bad_data - , v_code_error_bad_data - , CONCAT('The following product(s) do not have a has-variations setting: ', GROUP_CONCAT(t_P.name_error SEPARATOR ', ')) - FROM tmp_Product t_P - WHERE ISNULL(t_P.has_variations) - UNION + IF EXISTS (SELECT * FROM tmp_Product t_P WHERE ISNULL(t_P.has_variations) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , IFNULL(CONCAT('The following product(s) do not have a has-variations setting: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')), 'NULL') + FROM tmp_Product t_P + WHERE ISNULL(t_P.has_variations) + ; + END IF; + -- id_access_level_required - SELECT - a_guid AS GUID - , v_id_type_error_bad_data - , v_code_error_bad_data - , CONCAT('The following product(s) do not have a required access level ID: ', GROUP_CONCAT(t_P.name_error SEPARATOR ', ')) - FROM tmp_Product t_P - WHERE ISNULL(t_P.id_access_level_required) - UNION + IF EXISTS (SELECT * FROM tmp_Product t_P WHERE ISNULL(t_P.id_access_level_required) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , IFNULL(CONCAT('The following product(s) do not have a required access level ID: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')), 'NULL') + FROM tmp_Product t_P + WHERE ISNULL(t_P.id_access_level_required) + ; + END IF; + -- display_order - SELECT - a_guid AS GUID - , v_id_type_error_bad_data - , v_code_error_bad_data - , CONCAT('The following product(s) do not have a display order: ', GROUP_CONCAT(t_P.name_error SEPARATOR ', ')) - FROM tmp_Product t_P - WHERE ISNULL(t_P.display_order) - ; + IF EXISTS (SELECT * FROM tmp_Product t_P WHERE ISNULL(t_P.display_order) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , IFNULL(CONCAT('The following product(s) do not have a display order: ', GROUP_CONCAT(IFNULL(t_P.name_error, 'NULL') SEPARATOR ', ')), 'NULL') + FROM tmp_Product t_P + WHERE ISNULL(t_P.display_order) + ; + 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(item SEPARATOR ',') FROM tmp_Shop_Product WHERE is_new = 0); + SET v_ids_product_permission := (SELECT GROUP_CONCAT(id_product SEPARATOR ',') FROM tmp_Product WHERE 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_calc_user(a_guid, a_id_user, v_id_permission_product, v_ids_product_permission); + CALL partsltd_prod.p_shop_calc_user( + a_guid + , a_id_user + , FALSE -- get_inactive_users + , v_id_permission_product + , v_id_access_level_edit + , v_ids_product_permission + , 0 -- debug + ); UPDATE tmp_Product t_P INNER JOIN Shop_Calc_User_Temp UE_T @@ -7727,68 +8074,153 @@ BEGIN , t_P.can_admin = UE_T.can_admin ; - CALL p_shop_clear_calc_user(a_guid); + CALL partsltd_prod.p_shop_clear_calc_user( + a_guid + , 0 -- debug + ); END IF; END IF; IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN - -- Start the transaction START TRANSACTION; + IF NOT ISNULL(v_ids_product_permission) THEN + INSERT INTO partsltd_prod.Shop_Product_Change_Set ( comment ) + VALUES ( a_comment ) + ; + + SET v_id_change_set := LAST_INSERT_ID(); + + UPDATE partsltd_prod.Shop_Product P + INNER JOIN tmp_Product t_P ON P.id_product = t_P.id_product + SET + P.id_category = t_P.id_category + , P.name = t_P.name + , P.has_variations = t_P.has_variations + , P.id_access_level_required = t_P.id_access_level_required + , P.display_order = t_P.display_order + , P.id_change_set = v_id_change_set + ; + END IF; + + INSERT INTO partsltd_prod.Shop_Product ( + id_category + , name + , has_variations + , id_access_level_required + , display_order + , created_by + , created_on + ) + SELECT + t_P.id_category AS id_category + , t_P.name AS name + , t_P.has_variations AS has_variations + , t_P.id_access_level_required AS id_access_level_required + , t_P.display_order AS display_order + , a_id_user AS created_by + , v_time_start AS created_on + FROM tmp_Product t_P + WHERE is_new = 1 + ; + + DELETE FROM partsltd_prod.Shop_Product_Category_Temp + WHERE GUID = a_guid; + COMMIT; + END IF; + + SELECT * + FROM tmp_Msg_Error t_ME + INNER JOIN partsltd_prod.Shop_Msg_Error_Type MET ON t_ME.id_type = MET.id_type + ; + + DROP TEMPORARY TABLE IF EXISTS tmp_Product; + DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error; + + IF a_debug = 1 THEN + CALL partsltd_prod.p_debug_timing_reporting ( v_time_start ); + END IF; +END // +DELIMITER ;; + + + +-- Clear previous proc +DROP PROCEDURE IF EXISTS partsltd_prod.p_shop_save_product_test; + + +DELIMITER // +CREATE PROCEDURE p_shop_save_product_test () +BEGIN + + DECLARE v_guid BINARY(36); + DECLARE v_time_start TIMESTAMP(6); + + SET v_time_start := CURRENT_TIMESTAMP(6); + SET v_guid := 'nips'; + + SELECT * + FROM partsltd_prod.Shop_Product + ; + SELECT * + FROM partsltd_prod.Shop_Product_Temp + ; + + START TRANSACTION; - -- Your transaction logic goes here - 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 P - INNER JOIN tmp_Product t_P ON P.id_product = t_P.id_product - SET - P.id_category = t_P.id_category - , P.name = t_P.name - , P.has_variations = t_P.has_variations - , P.id_access_level_required = t_P.id_access_level_required - , P.display_order = t_P.display_order - , P.id_change_set = v_id_change_set - ; - END IF; - - INSERT INTO Shop_Product ( - id_category + INSERT INTO partsltd_prod.Shop_Product_Temp ( + id_product + , id_category , name , has_variations , id_access_level_required , display_order - , created_by - , created_on + , active + , guid ) - SELECT - t_P.id_category AS id_category - , t_P.name AS name - , t_P.has_variations AS has_variations - , t_P.id_access_level_required AS id_access_level_required - , t_P.display_order AS display_order - , a_id_user AS created_by - , v_now AS created_on - FROM tmp_Product t_P - WHERE is_new = 1 - ; + VALUES ( + 4 -- id_product + , 1 -- id_category + , 'Laptops' -- name + , 0 -- has_variations + , 2 -- id_access_level_required + , 2 -- display_order + , 1 -- active + , v_guid + ); - -- If we reach here without error, commit the transaction - COMMIT; - END IF; + COMMIT; - SELECT * FROM tmp_Msg_Error; + SELECT * + FROM partsltd_prod.Shop_Product_Temp + WHERE GUID = v_guid + ; - DROP TEMPORARY TABLE IF EXISTS tmp_Product; - DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error; + CALL partsltd_prod.p_shop_save_product ( + 'Test save product' -- comment + , v_guid -- guid + , 1 -- id_user + , 1 -- debug + ); + + SELECT * + FROM partsltd_prod.Shop_Product + ; + SELECT * + FROM partsltd_prod.Shop_Product_Temp + ; + + CALL partsltd_prod.p_debug_timing_reporting ( v_time_start ); END // DELIMITER ;; --- USE partsltd_prod; +/* +CALL partsltd_prod.p_shop_save_product_test (); + +DELETE FROM partsltd_prod.Shop_Product_Temp; + +DROP TABLE IF EXISTS tmp_Msg_Error; +*/-- USE partsltd_prod; -- Clear previous proc DROP PROCEDURE IF EXISTS p_shop_calc_product_permutation; @@ -8945,6 +9377,7 @@ END // DELIMITER ;; +/* CALL partsltd_prod.p_shop_get_many_product ( 1 #'auth0|6582b95c895d09a70ba10fef', # a_id_user @@ -8964,7 +9397,6 @@ CALL partsltd_prod.p_shop_get_many_product ( , 0 # a_debug ); -/* select * FROM partsltd_prod.Shop_Calc_User_Temp; select * FROM partsltd_prod.Shop_Product_Category; @@ -9304,620 +9736,15 @@ CALL p_shop_calc_user ( */ - - --- 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_calc_user(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_Calc_User_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_Calc_User_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_Calc_User_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; - - -*/ - - - -- 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) + IN a_guid BINARY(36), + IN a_id_user INT ) BEGIN @@ -10469,6 +10296,227 @@ WHERE id_permutation = 1; */ +DROP FUNCTION IF EXISTS fn_shop_get_id_product_permutation_from_variation_csv_list; + +DELIMITER // + +CREATE FUNCTION fn_shop_get_id_product_permutation_from_variation_csv_list ( + a_id_product INT + , a_variation_csv TEXT +) +RETURNS INT +DETERMINISTIC +READS SQL DATA +BEGIN + DECLARE v_id_permutation INT; + DECLARE done INT DEFAULT FALSE; + DECLARE v_id_variation_type INT; + DECLARE v_id_variation INT; + DECLARE v_id_permutation_tmp INT; + DECLARE cur CURSOR FOR + SELECT + CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(t.pair, ':', 1), ',', -1) AS UNSIGNED) AS id_variation_type, + CAST(SUBSTRING_INDEX(t.pair, ':', -1) AS UNSIGNED) AS id_variation + FROM ( + SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(a_variation_csv, ',', n), ',', -1) pair + FROM ( + SELECT a.N + b.N * 10 + 1 n + FROM (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a + CROSS JOIN (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b + ORDER BY n + ) numbers + WHERE n <= 1 + (LENGTH(a_variation_csv) - LENGTH(REPLACE(a_variation_csv, ',', ''))) + ) t; + + DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; + + SET v_id_permutation = NULL; + + OPEN cur; + + read_loop: LOOP + FETCH cur INTO v_id_variation_type, v_id_variation; + IF done THEN + LEAVE read_loop; + END IF; + + IF v_id_permutation IS NULL THEN + -- First iteration: find initial v_id_permutations + SELECT PPVL.id_permutation INTO v_id_permutation + FROM partsltd_prod.Shop_Product_Permutation_Variation_Link PPVL + INNER JOIN partsltd_prod.Shop_Product_Permutation PP ON PPVL.id_permutation = PP.id_permutation + INNER JOIN partsltd_prod.Shop_Variation PV ON PPVL.id_variation = PV.id_variation + WHERE 1=1 + AND PP.id_product = a_id_product + AND PPVL.id_variation = v_id_variation + AND PV.id_type = v_id_variation_type + ; + ELSE + -- Subsequent iterations: narrow down the v_id_permutation + SELECT PPVL.id_permutation INTO v_id_permutation_tmp + FROM partsltd_prod.Shop_Product_Permutation_Variation_Link PPVL + INNER JOIN partsltd_prod.Shop_Product_Permutation PP ON PPVL.id_permutation = PP.id_permutation + INNER JOIN partsltd_prod.Shop_Variation PV ON PPVL.id_variation = PV.id_variation + WHERE 1=1 + AND PP.id_product = a_id_product + AND PPVL.v_id_permutation = v_id_permutation + AND PPVL.id_variation = v_id_variation + AND PV.id_type = v_id_variation_type + ; + + IF v_id_permutation_tmp IS NULL THEN + -- If no match found, exit the loop + SET v_id_permutation := NULL; + LEAVE read_loop; + ELSE + SET v_id_permutation := v_id_permutation_tmp; + END IF; + END IF; + END LOOP; + + CLOSE cur; + + RETURN v_id_permutation; +END // + +DELIMITER ; + +/* +SELECT fn_shop_get_id_product_permutation_from_variation_csv_list ( 1, '1:1' ) AS id_permutation; +SELECT fn_shop_get_id_product_permutation_from_variation_csv_list ( 3, '' ) AS id_permutation; +*/ + + +/* +-- Update the table using the function +UPDATE product_permutation_input +SET v_id_permutation = find_v_id_permutation(variation_csv) +WHERE v_id_permutation IS NULL; +*/ + +/* +select * from partsltd_prod.Shop_Variation + +DROP PROCEDURE IF EXISTS p_shop_get_id_product_permutation_from_variation_csv_list; + +DELIMITER // +CREATE PROCEDURE p_shop_get_id_product_permutation_from_variation_csv_list ( + IN a_guid BINARY(36) + , IN a_debug BIT +) +BEGIN + DECLARE done INT DEFAULT FALSE; + DECLARE v_id INT; + DECLARE v_row_id INT; + DECLARE v_variation_csv TEXT; + DECLARE v_id_permutation INT; + DECLARE v_time_start TIMESTAMP(6); + + -- Cursor to iterate through unprocessed rows + DECLARE cur CURSOR FOR + SELECT id, session_guid, row_id, variation_csv + FROM product_permutation_input + WHERE v_id_permutation IS NULL; + + DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; + + SET v_time_start := CURRENT_TIMESTAMP(6); + SET a_debug := IFNULL(a_debug, 0); + + IF a_debug = 1 THEN + SELECT + a_guid + , a_debug + ; + END IF; + + CALL p_validate_guid ( a_guid ); + + OPEN cur; + + read_loop: LOOP + FETCH cur INTO v_id, v_session_guid, v_row_id, v_variation_csv; + IF done THEN + LEAVE read_loop; + END IF; + + -- Find matching v_id_permutation + SET v_id_permutation = NULL; + + SELECT ppvl.v_id_permutation INTO v_id_permutation + FROM ( + SELECT + SUBSTRING_INDEX(SUBSTRING_INDEX(t.pair, ':', 1), ',', -1) AS id_variation_type, + SUBSTRING_INDEX(t.pair, ':', -1) AS id_variation + FROM ( + SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(v_variation_csv, ',', numbers.n), ',', -1) pair + FROM ( + SELECT 1 n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 -- add more if needed + ) numbers + WHERE CHAR_LENGTH(v_variation_csv) - CHAR_LENGTH(REPLACE(v_variation_csv, ',', '')) >= numbers.n - 1 + ) t + ) parsed + INNER JOIN product_permutation_variation_link ppvl + ON parsed.id_variation_type = ppvl.id_variation_type + AND parsed.id_variation = ppvl.id_variation + GROUP BY ppvl.v_id_permutation + HAVING COUNT(*) = (LENGTH(v_variation_csv) - LENGTH(REPLACE(v_variation_csv, ',', '')) + 1) + LIMIT 1; + + -- Update the v_id_permutation in the input table + UPDATE product_permutation_input + SET v_id_permutation = v_id_permutation + WHERE id = v_id; + + END LOOP; + + CLOSE cur; + + + IF EXISTS ( SELECT * FROM Shop_Get_Id_Product_Permutation_From_Variation_Csv_List_Temp WHERE GUID = a_guid LIMIT 1 ) THEN + IF EXISTS (SELECT * FROM tmp_Split_Split LIMIT 1) THEN + START TRANSACTION; + INSERT INTO Split_Key_Value_Pair_Csv_Temp ( + guid + , id + , key_column + , value_column + ) + SELECT + a_guid + , id + , key_column + , value_column + FROM tmp_Split_Split + ; + COMMIT; + END IF; + END IF; + + DROP TEMPORARY TABLE IF EXISTS tmp_Split_Input; + DROP TEMPORARY TABLE IF EXISTS tmp_Split_Split; + + IF a_debug = 1 THEN + CALL p_debug_timing_reporting ( v_time_start ); + END IF; +END // +DELIMITER ;; +*/ + +/* +CALL p_shop_get_id_product_permutation_from_variation_csv_list ( + 'nipsnipsnipsnipsnipsnipsnipsnipsnips' + , '1:100,2:200,3:300,4:400' # a_string + , 1 +); + +SELECT * +FROM Split_key_value_pair_csv_Temp +WHERE GUID = 'nipsnipsnipsnipsnipsnipsnipsnipsnips'; + +CALL p_clear_split_key_value_pair_csv_temp( 'nipsnipsnipsnipsnipsnipsnipsnipsnips' ); +*/ + DROP PROCEDURE IF EXISTS p_shop_get_many_product_variation; DELIMITER // @@ -10496,14 +10544,14 @@ BEGIN DECLARE v_id_access_level_view INT; DECLARE v_time_start TIMESTAMP(6); DECLARE v_id_minimum INT; - DECLARE v_code_error_data VARCHAR(50); - DECLARE v_id_type_error_data INT; + DECLARE v_code_error_bad_data VARCHAR(50); + DECLARE v_id_type_error_bad_data INT; SET v_time_start := CURRENT_TIMESTAMP(6); SET v_guid := UUID(); SET v_id_access_level_view := (SELECT id_access_level FROM Shop_Access_Level WHERE code = 'VIEW' LIMIT 1); - SET v_code_error_data := (SELECT code FROM Shop_Msg_Error_Type WHERE code = 'BAD_DATA' LIMIT 1); - SET v_id_type_error_data := (SELECT id_type FROM Shop_Msg_Error_Type WHERE code = v_code_error_data LIMIT 1); + SET v_code_error_bad_data := (SELECT code FROM Shop_Msg_Error_Type WHERE code = 'BAD_DATA' LIMIT 1); + SET v_id_type_error_bad_data := (SELECT id_type FROM Shop_Msg_Error_Type WHERE code = v_code_error_bad_data LIMIT 1); -- Argument validation + default values SET a_id_user = IFNULL(a_id_user, 0); @@ -10752,8 +10800,8 @@ BEGIN ) VALUES ( -- v_guid, - v_id_type_error_data, - v_code_error_data, + v_id_type_error_bad_data, + v_code_error_bad_data, CONCAT('You do not have view permissions for ', (SELECT name FROM Shop_Permission WHERE id_permission = v_id_permission_variation LIMIT 1)) ) ; @@ -11508,6 +11556,7 @@ BEGIN select * from tmp_Stock_Item; select * from tmp_Permutation; select * from tmp_Location_Storage; + select * from Shop_Storage_Location; select * from tmp_Plant_Storage; select * from tmp_Region_Storage; */ @@ -11522,14 +11571,19 @@ BEGIN P.id_category, t_SI.id_location_storage, t_PS.id_plant, - t_RS.id_region, + PLANT.id_address AS id_address_plant, + t_RS.id_region AS id_region_plant, + SL.code AS code_storage_location, + SL.name AS name_storage_location, + PLANT.code AS code_plant, + PLANT.name AS name_plant, SI.id_currency_cost, CURRENCY.symbol AS symbol_currency_cost, CURRENCY.code AS code_currency_cost, + SI.cost_local_VAT_excl, + SI.cost_local_VAT_incl, SI.date_purchased, SI.date_received, - SI.cost_local_VAT_incl, - SI.cost_local_VAT_excl, SI.is_sealed, SI.date_unsealed, SI.date_expiration, @@ -11608,6 +11662,7 @@ END // DELIMITER ;; +/* CALL p_shop_get_many_stock_item ( 1, # a_id_user 1, # a_get_all_product_permutation @@ -11636,7 +11691,6 @@ CALL p_shop_get_many_stock_item ( , 0 # a_debug ); -/* DROP TABLE IF EXISTS tmp_Msg_Error; @@ -11653,7 +11707,768 @@ insert into shop_product_change_set (comment) id_change_set = (select id_change_set FROM partsltd_prod.Shop_product_change_set order by id_change_set desc limit 1) where id_product = 1 */ --- USE partsltd_prod; + + +-- Clear previous proc +DROP PROCEDURE IF EXISTS p_shop_save_stock_item; + +DELIMITER // +CREATE PROCEDURE p_shop_save_stock_item ( + IN a_comment VARCHAR(500) + , IN a_guid BINARY(36) + , IN a_id_user INT + , IN a_debug BIT +) +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_time_start TIMESTAMP(6); + DECLARE v_time_expire 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_time_start := CURRENT_TIMESTAMP(6); + SET v_time_expire := DATE_ADD(v_time_start, INTERVAL 1000 YEAR); + 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_Stock_Item; + + CREATE TEMPORARY TABLE tmp_Stock_Item ( + id_stock INT NOT NULL + , id_category INT NULL + , id_product INT NOT NULL + , id_permutation INT NULL + , id_pairs_variations VARCHAR(4000) NULL + , has_variations BIT NULL + , date_purchased DATETIME NOT NULL + , date_received DATETIME NULL + , id_location_storage INT NOT NULL + , id_currency_cost INT NOT NULL + , cost_local_VAT_incl FLOAT NOT NULL + , cost_local_VAT_excl FLOAT NOT NULL + , is_sealed BIT NOT NULL + , date_unsealed DATETIME NULL + , date_expiration DATETIME NOT NULL + , is_consumed BIT NOT NULL + , date_consumed DATETIME NULL + , active BIT NOT NULL + , 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 + , id_type INT NULL + , code VARCHAR(50) NOT NULL + , msg VARCHAR(4000) NOT NULL + ); + + + -- Get data from Temp table + INSERT INTO tmp_Stock_Item ( + id_stock + -- , id_category + , id_product + , id_permutation + , id_pairs_variations + , has_variations + , date_purchased + , date_received + , id_location_storage + , id_currency_cost + , cost_local_VAT_incl + , cost_local_VAT_excl + , is_sealed + , date_unsealed + , date_expiration + , is_consumed + , date_consumed + , active + # , name_error + , is_new + ) + SELECT + SI_T.id_stock + -- , IFNULL(SI_T.id_category, P.id_category) AS id_category + , IFNULL(IFNULL(SI_T.id_product, PP.id_product), 0) AS id_product + , IFNULL(IFNULL(SI_T.id_permutation, PP.id_permutation), 0) AS id_permutation + , TRIM(IFNULL(SI_T.id_pairs_variations, '')) + , CASE WHEN TRIM(IFNULL(SI_T.id_pairs_variations, '')) = '' THEN 0 ELSE 1 END AS has_variations + , IFNULL(IFNULL(SI_T.date_purchased, PP.date_purchased), v_time_start) AS date_purchased + , IFNULL(SI_T.date_received, PP.date_received) AS date_received + , IFNULL(IFNULL(SI_T.id_location_storage, PP.id_location_storage), 0) AS id_location_storage + , IFNULL(IFNULL(SI_T.id_currency_cost, PP.id_currency_cost), 0) AS id_currency_cost + , IFNULL(SI_T.cost_local_VAT_incl, PP.cost_local_VAT_incl) AS cost_local_VAT_incl + , IFNULL(SI_T.cost_local_VAT_excl, PP.cost_local_VAT_excl) AS cost_local_VAT_excl + , IFNULL(IFNULL(SI_T.is_sealed, PP.is_sealed), 1) AS is_sealed + , IFNULL(SI_T.date_unsealed, PP.date_unsealed) AS date_unsealed + , IFNULL(IFNULL(SI_T.date_expiration, PP.date_expiration), v_time_expire) AS date_expiration + , IFNULL(IFNULL(SI_T.is_consumed, PP.is_consumed), 0) AS is_consumed + , IFNULL(SI_T.date_consumed, PP.date_consumed) AS date_consumed + , IFNULL(IFNULL(SI_T.active, PP.active), 1) AS active + # , fn_shop_get_product_permutation_name(SI_T.id_permutation) + , CASE WHEN IFNULL(SI_T.id_stock, 0) < 1 THEN 1 ELSE 0 END AS is_new + FROM Shop_Stock_Item_Temp SI_T + LEFT JOIN Shop_Product_Permutation PP ON SI_T.id_permutation = PP.id_permutation + -- LEFT JOIN Shop_Product P ON PP.id_product = P.id_product + WHERE SI_T.guid = a_guid + ; + + -- Missing Permutation IDs for setting new permutation for stock item + -- With variations + UPDATE tmp_Stock_Item t_SI + INNER JOIN partsltd_prod.Shop_Product P ON t_SI.id_product = P.id_product + SET t_SI.id_permutation = IFNULL(fn_shop_get_id_product_permutation_from_variation_csv_list ( t_SI.id_product, t_SI.id_pairs_variations ), 0) + WHERE 1=1 + AND t_SI.id_permutation = 0 + AND t_SI.has_variations = 1 + ; + -- Without variations + UPDATE tmp_Stock_Item t_SI + -- INNER JOIN Shop_Product P ON t_SI.id_product = P.id_product + INNER JOIN partsltd_prod.Shop_Product_Permutation PP ON t_SI.id_product = PP.id_product + SET t_SI.id_permutation = IFNULL(PP.id_permutation, 0) + WHERE 1=1 + AND t_SI.id_permutation = 0 + AND t_SI.has_variations = 0 + ; + + -- Add stock item error names + UPDATE tmp_Stock_Item t_SI + INNER JOIN partsltd_prod.Shop_Product P ON t_SI.id_product = P.id_product + INNER JOIN partsltd_prod.Shop_Category PC ON P.id_category = PC.id_category + -- INNER JOIN Shop_Product_Permutation PP ON t_SI.id_product = PP.id_product + SET t_SI.name_error = CONCAT( + C.name, + ' - ', + P.name, + ' - ', + CASE WHEN IFNULL(t_SI.id_permutation, 0) = 0 THEN '(No permutation)' ELSE fn_shop_get_product_permutation_name ( t_SI.id_permutation ) END + ) + ; + + + -- Validation + -- Missing mandatory fields + -- id_product + IF EXISTS (SELECT * FROM tmp_Stock_Item t_SI WHERE t_SI.id_product = 0 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 stock item(s) do not have a product: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + WHERE t_SI.id_product = 0 + ; + END IF; + -- id_permutation + IF EXISTS ( + SELECT * + FROM tmp_Stock_Item t_SI + LEFT JOIN partsltd_prod.Shop_Product_Permutation PP ON t_SI.id_permutation = PP.id_permutation + WHERE 1=1 + AND ( + t_SI.id_permutation = 0 + OR PP.active = 0 + ) + 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('A valid permutation could not be found for the variations selected for the following stock item(s): ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + LEFT JOIN partsltd_prod.Shop_Product_Permutation PP ON t_SI.id_permutation = PP.id_permutation + WHERE 1=1 + AND ( + t_SI.id_permutation = 0 + OR PP.active = 0 + ) + ; + END IF; + -- date_purchased + IF EXISTS (SELECT * FROM tmp_Stock_Item t_SI WHERE ISNULL(t_SI.date_purchased) 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 stock item(s) do not have an purchase date: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + WHERE ISNULL(t_SI.date_purchased) + ; + END IF; + -- id_location_storage + IF EXISTS ( + SELECT * + FROM tmp_Stock_Item t_SI + INNER JOIN partsltd_prod.Shop_Storage_Location SL + ON t_SI.id_location_storage = SL.id_location + AND SL.active = 1 + WHERE ISNULL(SL.id_location) + 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 stock item(s) do not have a valid storage location: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + INNER JOIN partsltd_prod.Shop_Storage_Location SL + ON t_SI.id_location_storage = SL.id_location + AND SL.active = 1 + WHERE ISNULL(SL.id_location) + ; + END IF; + -- id_currency_cost + IF EXISTS ( + SELECT * + FROM tmp_Stock_Item t_SI + INNER JOIN partsltd_prod.Shop_Currency C + ON t_SI.id_curency_cost = C.id_currency + AND C.active = 1 + WHERE ISNULL(C.id_currency) + 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 stock item(s) do not have a valid cost currency: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + INNER JOIN partsltd_prod.Shop_Currency C + ON t_SI.id_curency_cost = C.id_currency + AND C.active = 1 + WHERE ISNULL(C.id_currency) + ; + END IF; + -- cost_local_VAT_excl + IF EXISTS ( + SELECT * + FROM tmp_Stock_Item t_SI + WHERE 1=1 + AND ( + ISNULL(t_SI.cost_local_VAT_excl) + OR t_SI.cost_local_VAT_excl < 0 + ) + 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 stock item(s) do not have a valid cost excluding VAT: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + WHERE 1=1 + AND ( + ISNULL(t_SI.cost_local_VAT_excl) + OR t_SI.cost_local_VAT_excl < 0 + ) + ; + END IF; + -- cost_local_VAT_incl + IF EXISTS ( + SELECT * + FROM tmp_Stock_Item t_SI + WHERE 1=1 + AND ( + ISNULL(t_SI.cost_local_VAT_incl) + OR t_SI.cost_local_VAT_incl < 0 + ) + 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 stock item(s) do not have a valid cost including VAT: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + WHERE 1=1 + AND ( + ISNULL(t_SI.cost_local_VAT_incl) + OR t_SI.cost_local_VAT_incl < t_SI.cost_local_VAT_excl + ) + ; + END IF; + -- date_received + IF EXISTS (SELECT * FROM tmp_Stock_Item t_SI WHERE ISNULL(t_SI.date_received) OR t_SI.date_received < t_SI.date_purchased 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 stock item(s) do not have a valid received date: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + WHERE 1=1 + AND ( + ISNULL(t_SI.date_received) + OR t_SI.date_received < t_SI.date_purchased + ) + ; + END IF; + -- date_unsealed + IF EXISTS (SELECT * FROM tmp_Stock_Item t_SI WHERE ISNULL(t_SI.date_unsealed) OR t_SI.date_unsealed < t_SI.date_purchased 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 stock item(s) do not have a valid unsealed date: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + WHERE 1=1 + AND ( + ISNULL(t_SI.date_unsealed) + OR t_SI.date_unsealed < t_SI.date_purchased + ) + ; + END IF; + -- date_expiration + IF EXISTS (SELECT * FROM tmp_Stock_Item t_SI WHERE ISNULL(t_SI.date_expiration) OR t_SI.date_expiration < t_SI.date_purchased 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 stock item(s) do not have a valid expiration date: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + WHERE 1=1 + AND ( + ISNULL(t_SI.date_expiration) + OR t_SI.date_expiration < t_SI.date_purchased + ) + ; + END IF; + -- date_consumed + IF EXISTS (SELECT * FROM tmp_Stock_Item t_SI WHERE ISNULL(t_SI.date_consumed) OR t_SI.date_consumed < t_SI.date_purchased 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 stock item(s) do not have a valid consumed date: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + WHERE 1=1 + AND ( + ISNULL(t_SI.date_consumed) + OR t_SI.date_consumed < t_SI.date_purchased + ) + ; + END IF; + + -- Permissions + SET v_ids_product_permission := ( SELECT GROUP_CONCAT(t_SI.id_product SEPARATOR ',') FROM tmp_Stock_Item t_SI ); + + 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_calc_user(a_guid, a_id_user, FALSE, v_id_permission_product, v_id_access_level_edit, v_ids_product_permission); + + UPDATE tmp_Stock_Item t_SI + INNER JOIN Shop_Product P ON t_SI.id_product = P.id_product + INNER JOIN Shop_Calc_User_Temp UE_T + ON P.id_product = UE_T.id_product + AND UE_T.GUID = a_guid + SET + t_SI.can_view = UE_T.can_view + , t_SI.can_edit = UE_T.can_edit + , t_SI.can_admin = UE_T.can_admin + ; + + CALL p_shop_clear_calc_user(a_guid); + + IF EXISTS (SELECT * FROM tmp_Stock_Item t_SI WHERE IFNULL(t_SI.can_edit, 0) = 0 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 stock item(s) do not have product edit permission: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + WHERE IFNULL(t_SI.can_edit, 0) = 0 + ; + END IF; + END IF; + + 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(); + -- select * from partsltd_prod.Shop_Stock_Item + UPDATE partsltd_prod.Shop_Stock_Item + INNER JOIN tmp_Stock_Item t_SI ON SI.id_stock = t_SI.id_stock + SET + SI.id_permutation = t_SI.id_permutation + , SI.date_purchased = t_SI.date_purchased + , SI.date_received = t_SI.date_received + , SI.id_location_storage = t_SI.id_location_storage + , SI.id_currency_cost = t_SI.id_currency_cost + , SI.cost_local_VAT_excl = t_SI.cost_local_VAT_excl + , SI.cost_local_VAT_incl = t_SI.cost_local_VAT_incl + , SI.is_sealed = t_SI.is_sealed + , SI.date_unsealed = t_SI.date_unsealed + , SI.date_expiration = t_SI.date_expiration + , SI.is_consumed = t_SI.is_consumed + , SI.date_consumed = t_SI.date_consumed + , SI.active = t_SI.active + , SI.id_change_set = v_id_change_set + ; + END IF; + + INSERT INTO partsltd_prod.Shop_Stock_Item ( + id_permutation + , date_purchased + , date_received + , id_location_storage + , id_currency_cost + , cost_local_VAT_excl + , cost_local_VAT_incl + , is_sealed + , date_unsealed + , date_expiration + , is_consumed + , date_consumed + , active + , created_by + , created_on + ) + SELECT + t_SI.id_permutation + , t_SI.date_purchased + , t_SI.date_received + , t_SI.id_location_storage + , t_SI.id_currency_cost + , t_SI.cost_local_VAT_excl + , t_SI.cost_local_VAT_incl + , t_SI.is_sealed + , t_SI.date_unsealed + , t_SI.date_expiration + , t_SI.is_consumed + , t_SI.date_consumed + , t_SI.active + , a_id_user AS created_by + , v_time_start AS created_on + FROM tmp_Stock_Item t_SI + WHERE + is_new = 1 + AND active = 1 + ; + + DELETE FROM partsltd_prod.Shop_Stock_Item_Temp + WHERE GUID = a_guid; + + COMMIT; + END IF; + + SELECT * FROM tmp_Msg_Error; + + DROP TEMPORARY TABLE IF EXISTS tmp_Stock_Item; + 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; + + +*/ + + + +-- Clear previous proc +DROP PROCEDURE IF EXISTS partsltd_prod.p_shop_save_stock_item_test; + + +DELIMITER // +CREATE PROCEDURE p_shop_save_stock_item_test () +BEGIN + + DECLARE v_guid BINARY(36); + DECLARE v_time_start TIMESTAMP(6); + + SET v_time_start := CURRENT_TIMESTAMP(6); + SET v_guid := 'nips'; + + SELECT * + FROM partsltd_prod.Shop_Stock_Item + ; + SELECT * + FROM partsltd_prod.Shop_Stock_Item_Temp + ; + + START TRANSACTION; + + INSERT INTO partsltd_prod.Shop_Stock_Item_Temp ( + id_stock + -- id_category + , id_product + , id_permutation + , id_pairs_variations + -- , has_variations + , date_purchased + , date_received + , id_location_storage + , id_currency_cost + , cost_local_VAT_incl + , cost_local_VAT_excl + , is_sealed + , date_unsealed + , date_expiration + , is_consumed + , date_consumed + , active + , guid + ) + VALUES ( + -1 -- id_stock + -- 1 -- id_category + , 4 -- id_product + , NULL -- id_permutation + , NULL -- id_pairs_variations + -- , FALSE -- 0 -- has_variations + , '05-09-2025' -- date_purchased + , NULL -- date_received + , 1 -- id_location_storage + , 1 -- id_currency_cost + , 10 -- cost_local_VAT_incl + , 12 -- cost_local_VAT_excl + , 1 -- is_sealed + , NULL -- date_unsealed + , NULL -- date_expiration + , FALSE -- 0 -- is_consumed + , NULL -- date_consumed + , 1 -- active + , v_guid + ); + + COMMIT; + + SELECT * + FROM partsltd_prod.Shop_Stock_Item_Temp + WHERE GUID = v_guid + ; + + CALL partsltd_prod.p_shop_save_Stock_Item ( + 'Test save Stock_Item' -- comment + , v_guid -- guid + , 1 -- id_user + , 1 -- debug + ); + + SELECT * + FROM partsltd_prod.Shop_Stock_Item + ; + SELECT * + FROM partsltd_prod.Shop_Stock_Item_Temp + ; + + CALL partsltd_prod.p_debug_timing_reporting ( v_time_start ); +END // +DELIMITER ;; + +/* +CALL partsltd_prod.p_shop_save_stock_item_test (); + +DELETE FROM partsltd_prod.Shop_Stock_Item_Temp; + +update shop_product p set p.has_variations = 0 where id_product = 4 +DROP TABLE IF EXISTS tmp_Msg_Error; +*/-- USE partsltd_prod; -- Clear previous proc DROP PROCEDURE IF EXISTS p_shop_get_many_product_price_and_discount_and_delivery_option; @@ -13084,8 +13899,6 @@ CALL p_shop_edit_user ( */ - - -- Clear previous proc DROP PROCEDURE IF EXISTS p_get_many_user; @@ -13099,48 +13912,81 @@ CREATE PROCEDURE p_get_many_user ( , IN a_get_first_user_only BIT , IN a_ids_user LONGTEXT , IN a_ids_user_auth0 LONGTEXT + , IN a_debug BIT ) BEGIN + DECLARE v_id_access_level_admin INT; DECLARE v_id_access_level_view INT; DECLARE v_id_permission_store_admin INT; DECLARE v_id_permission_user INT; DECLARE v_id_permission_user_admin INT; + DECLARE v_ids_permission_required VARCHAR(4000); DECLARE v_now TIMESTAMP; DECLARE v_id_minimum INT; - DECLARE v_code_error_data VARCHAR(50); - DECLARE v_id_type_error_data INT; + DECLARE v_code_error_bad_data VARCHAR(50); + DECLARE v_id_type_error_bad_data INT; DECLARE v_has_filter_user BIT; + DECLARE v_has_filter_user_auth0 BIT; DECLARE v_guid BINARY(36); + DECLARE v_rank_max INT; + DECLARE v_time_start TIMESTAMP(6); + SET v_time_start := CURRENT_TIMESTAMP(6); SET v_guid := UUID(); - SET v_id_access_level_view := (SELECT id_access_level FROM Shop_Access_Level WHERE code = 'VIEW' LIMIT 1); - SET v_id_permission_store_admin := (SELECT id_permission FROM Shop_Permission WHERE code = 'STORE_ADMIN' LIMIT 1); - SET v_id_permission_user := (SELECT id_permission FROM Shop_Permission WHERE code = 'STORE_USER' LIMIT 1); - SET v_id_permission_user_admin := (SELECT id_permission FROM Shop_Permission WHERE code = 'STORE_USER_ADMIN' LIMIT 1); - SET v_code_error_data := (SELECT code FROM Shop_Msg_Error_Type WHERE code = 'BAD_DATA' LIMIT 1); - SET v_id_type_error_data := (SELECT id_type FROM Shop_Msg_Error_Type WHERE code = v_code_error_data LIMIT 1); + SET v_id_access_level_admin := (SELECT id_access_level FROM partsltd_prod.Shop_Access_Level WHERE code = 'ADMIN' LIMIT 1); + SET v_id_access_level_view := (SELECT id_access_level FROM partsltd_prod.Shop_Access_Level WHERE code = 'VIEW' LIMIT 1); + SET v_id_permission_store_admin := (SELECT id_permission FROM partsltd_prod.Shop_Permission WHERE code = 'STORE_ADMIN' LIMIT 1); + SET v_id_permission_user := (SELECT id_permission FROM partsltd_prod.Shop_Permission WHERE code = 'STORE_USER' LIMIT 1); + SET v_id_permission_user_admin := (SELECT id_permission FROM partsltd_prod.Shop_Permission WHERE code = 'STORE_USER_ADMIN' LIMIT 1); + SET v_code_error_bad_data := (SELECT code FROM partsltd_prod.Shop_Msg_Error_Type WHERE code = 'BAD_DATA' LIMIT 1); + SET v_id_type_error_bad_data := (SELECT id_type FROM partsltd_prod.Shop_Msg_Error_Type WHERE code = v_code_error_bad_data LIMIT 1); + SET v_ids_permission_required := CONCAT(v_id_permission_user, ',', v_id_permission_user_admin, ',', v_id_permission_store_admin); + SET a_get_all_user := IFNULL(a_get_all_user, 1); + SET a_get_inactive_user := IFNULL(a_get_inactive_user, 0); + SET a_get_first_user_only := IFNULL(a_get_first_user_only, 0); SET a_ids_user := TRIM(IFNULL(a_ids_user, '')); SET a_ids_user_auth0 := TRIM(IFNULL(a_ids_user_auth0, '')); + SET a_debug := IFNULL(a_debug, 0); + + IF a_debug = 1 THEN + SELECT + a_id_user + , a_id_user_auth0 + , a_get_all_user + , a_get_inactive_user + , a_get_first_user_only + , a_ids_user + , a_ids_user_auth0 + , a_debug + ; + END IF; DROP TEMPORARY TABLE IF EXISTS tmp_User; DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error; CREATE TEMPORARY TABLE tmp_User ( - id_user INT NOT NULL, - rank_user INT NULL + id_user INT NULL + , rank_user INT NULL + , can_admin_store BIT NULL + , can_admin_user BIT NULL ); CREATE TEMPORARY TABLE tmp_Msg_Error ( display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT, - guid BINARY(36) NOT NULL, + -- guid BINARY(36) NOT NULL, id_type INT NOT NULL, code VARCHAR(50) NOT NULL, msg VARCHAR(4000) NOT NULL ); + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Split ( + substring VARCHAR(4000) NOT NULL + , as_int INT NULL + ); + IF ISNULL(a_id_user) AND NOT ISNULL(a_id_user_auth0) THEN - SET a_id_user := (SELECT U.id_user FROM Shop_User U WHERE U.id_user_auth0 LIKE CONCAT('%', a_id_user_auth0, '%') LIMIT 1); + SET a_id_user := (SELECT U.id_user FROM partsltd_prod.Shop_User U WHERE U.id_user_auth0 = a_id_user_auth0 LIMIT 1); -- LIKE CONCAT('%', a_id_user_auth0, '%') LIMIT 1); END IF; IF ISNULL(a_id_user) THEN @@ -13152,150 +13998,352 @@ BEGIN ) VALUES ( v_guid, - v_id_type_error_data, - v_code_error_data, + v_id_type_error_bad_data, + v_code_error_bad_data, CONCAT('User ID required for authorisation.') ) ; END IF; - SET v_has_filter_user := CASE WHEN a_ids_user = '' AND a_ids_user_auth0= '' THEN 0 ELSE 1 END; + SET v_has_filter_user := CASE WHEN a_ids_user = '' THEN 0 ELSE 1 END; + SET v_has_filter_user_auth0 := CASE WHEN a_ids_user_auth0 = '' THEN 0 ELSE 1 END; - IF v_has_filter_user THEN - INSERT INTO tmp_User ( - id_user - -- , active - , rank_user - ) - SELECT - DISTINCT U.id_user - -- S.active - , RANK() OVER (ORDER BY id_user ASC) AS rank_user - FROM Shop_User U - WHERE 1=1 - AND ( - FIND_IN_SET(U.id_user, a_ids_user) > 0 - OR FIND_IN_SET(U.id_user_auth0, a_ids_user_auth0) > 0 - ) - AND ( - a_get_inactive_user - OR U.active - ) - /*Shop_Calc_User_Temp UE_T - WHERE 1=1 - AND UE_T.guid = v_guid - AND UE_T.active = 1 - */ + IF a_debug = 1 THEN + SELECT + v_has_filter_user + , v_has_filter_user_auth0 ; - - IF a_get_first_user_only THEN - DELETE t_U - FROM tmp_User t_U - WHERE t_U.rank_user > 1 - ; - END IF; END IF; - -- Permissions - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN - -- SELECT v_guid, a_id_user, false, v_id_permission_product, v_id_access_level_view, v_ids_permutation_permission; - -- select * from Shop_Calc_User_Temp; + -- User IDs + IF (NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) AND v_has_filter_user = 1) THEN + CALL partsltd_prod.p_split(v_guid, a_ids_user, ',', FALSE); - CALL p_shop_calc_user( - v_guid, -- guid - a_id_user, -- ids_user - FALSE, -- get_inactive_user - CONCAT(v_id_permission_user, ',', v_id_permission_user_admin, ',', v_id_permission_store_admin), -- ids_permission - v_id_access_level_view, -- ids_access_level - '' -- ids_product + DELETE FROM tmp_Split; + + INSERT INTO tmp_Split ( + substring + , as_int + ) + SELECT + substring + , CONVERT(substring, DECIMAL(10,0)) AS as_int + FROM partsltd_prod.Split_Temp + WHERE 1=1 + AND GUID = v_guid + AND NOT ISNULL(substring) + AND substring != '' + ; + + CALL partsltd_prod.p_clear_split_temp( v_guid ); + END IF; + + IF (NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) AND v_has_filter_user = 1) THEN + IF EXISTS ( + SELECT * + FROM tmp_Split t_S + LEFT JOIN partsltd_prod.Shop_User U ON t_S.as_int = U.id_user + WHERE + ISNULL(t_S.as_int) + OR ISNULL(U.id_user) + ) THEN + INSERT INTO tmp_Msg_Error ( + -- guid, + id_type, + code, + msg + ) + SELECT + -- v_guid, + v_id_type_error_bad_data, + v_code_error_bad_data, + CONCAT('Invalid or inactive User IDs: ', IFNULL(GROUP_CONCAT(t_S.substring SEPARATOR ', '), 'NULL')) + FROM tmp_Split t_S + LEFT JOIN partsltd_prod.Shop_User U ON t_S.as_int = U.id_user + WHERE + ISNULL(t_S.as_int) + OR ISNULL(U.id_user) + ; + ELSE + INSERT INTO tmp_User ( + id_user + , rank_user + ) + SELECT + U.id_user + , RANK() OVER (ORDER BY U.id_user DESC) AS rank_user + FROM tmp_Split t_S + RIGHT JOIN partsltd_prod.Shop_User U ON t_S.as_int = U.id_user + WHERE + ( + a_get_all_user = 1 + OR ( + v_has_filter_user = 1 + AND NOT ISNULL(t_S.as_int) + ) + ) + AND ( + a_get_inactive_user = 1 + OR U.active = 1 + ) + ; + END IF; + END IF; + + -- Auth0 User IDs + IF (NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) AND v_has_filter_user_auth0 = 1) THEN + CALL partsltd_prod.p_split(v_guid, a_ids_user_auth0, ',', FALSE); + + DELETE FROM tmp_Split; + + INSERT INTO tmp_Split ( + substring + ) + SELECT + substring + FROM partsltd_prod.Split_Temp + WHERE 1=1 + AND GUID = v_guid + AND NOT ISNULL(substring) + AND substring != '' + ; + + CALL partsltd_prod.p_clear_split_temp( v_guid ); + END IF; + + IF (NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) AND v_has_filter_user_auth0 = 1) THEN + IF EXISTS ( + SELECT * + FROM tmp_Split t_S + LEFT JOIN partsltd_prod.Shop_User U ON t_S.substring = U.id_user_auth0 + WHERE + ISNULL(t_S.substring) + OR ISNULL(U.id_user_auth0) + ) THEN + INSERT INTO tmp_Msg_Error ( + -- guid, + id_type, + code, + msg + ) + SELECT + -- v_guid, + v_id_type_error_bad_data, + v_code_error_bad_data, + CONCAT('Invalid or inactive Auth0 User IDs: ', IFNULL(GROUP_CONCAT(t_S.substring SEPARATOR ', '), 'NULL')) + FROM tmp_Split t_S + LEFT JOIN partsltd_prod.Shop_User U ON t_S.substring = U.id_user_auth0 + WHERE + ISNULL(t_S.substring) + OR ISNULL(U.id_user_auth0) + ; + ELSE + SET v_rank_max := IFNULL((SELECT rank_user FROM tmp_User ORDER BY rank_user DESC LIMIT 1), 0); + + INSERT INTO tmp_User ( + id_user + , rank_user + ) + SELECT + U.id_user + , v_rank_max + (RANK() OVER (ORDER BY U.id_user DESC)) AS rank_user + FROM tmp_Split t_S + RIGHT JOIN partsltd_prod.Shop_User U ON t_S.substring = U.id_user_auth0 + WHERE + ( + a_get_all_user = 1 + OR ( + v_has_filter_user_auth0 = 1 + AND NOT ISNULL(t_S.substring) + ) + ) + AND ( + a_get_inactive_user = 1 + OR U.active = 1 + ) + ; + END IF; + END IF; + + IF a_debug = 1 THEN + SELECT * FROM tmp_User; + END IF; + + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN + IF a_get_first_user_only THEN + DELETE t_U + FROM tmp_User t_U + WHERE t_U.rank_user > 1 + ; + END IF; + END IF; + + IF a_debug = 1 THEN + SELECT * FROM tmp_User; + END IF; + + -- Can admin store + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN + IF a_debug = 1 THEN + SELECT + v_guid -- guid + , a_id_user -- ids_user + , FALSE -- get_inactive_user + , v_id_permission_store_admin -- ids_permission + , v_id_access_level_admin -- ids_access_level + , '' -- ids_product + , 0 -- a_debug + ; + SELECT * FROM partsltd_prod.Shop_Calc_User_Temp; + END IF; + + CALL partsltd_prod.p_shop_calc_user( + v_guid -- guid + , a_id_user -- ids_user + , FALSE -- get_inactive_user + , v_id_permission_store_admin -- ids_permission + , v_id_access_level_admin -- ids_access_level + , '' -- ids_product + , 0 -- a_debug ); - -- select * from Shop_Calc_User_Temp; + IF a_debug = 1 THEN + SELECT * FROM partsltd_prod.Shop_Calc_User_Temp WHERE GUID = v_guid; + END IF; + + UPDATE tmp_User t_U + INNER JOIN partsltd_prod.Shop_Calc_User_Temp CUT + ON CUT.GUID = v_guid + AND t_U.id_user = CUT.id_user + SET t_U.can_admin_store = CUT.can_admin + ; + + CALL partsltd_prod.p_shop_clear_calc_user( v_guid, FALSE ); + END IF; + + -- Can admin user + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN + IF a_debug = 1 THEN + SELECT + v_guid -- guid + , a_id_user -- ids_user + , FALSE -- get_inactive_user + , v_id_permission_user_admin -- ids_permission + , v_id_access_level_admin -- ids_access_level + , '' -- ids_product + , 0 -- a_debug + ; + SELECT * FROM partsltd_prod.Shop_Calc_User_Temp; + END IF; + + CALL partsltd_prod.p_shop_calc_user( + v_guid -- guid + , a_id_user -- ids_user + , FALSE -- get_inactive_user + , v_id_permission_user_admin -- ids_permission + , v_id_access_level_admin -- ids_access_level + , '' -- ids_product + , 0 -- a_debug + ); + + IF a_debug = 1 THEN + SELECT * FROM partsltd_prod.Shop_Calc_User_Temp WHERE GUID = v_guid; + END IF; + + UPDATE tmp_User t_U + INNER JOIN partsltd_prod.Shop_Calc_User_Temp CUT + ON CUT.GUID = v_guid + AND t_U.id_user = CUT.id_user + SET t_U.can_admin_user = CUT.can_admin + ; + + CALL partsltd_prod.p_shop_clear_calc_user( v_guid, FALSE ); + END IF; + + -- Permissions + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN + IF a_debug = 1 THEN + SELECT + v_guid -- guid + , a_id_user -- ids_user + , FALSE -- get_inactive_user + , v_ids_permission_required -- ids_permission + , v_id_access_level_view -- ids_access_level + , '' -- ids_product + , 0 -- a_debug + ; + SELECT * FROM partsltd_prod.Shop_Calc_User_Temp; + END IF; + + CALL partsltd_prod.p_shop_calc_user( + v_guid -- guid + , a_id_user -- ids_user + , FALSE -- get_inactive_user + , v_ids_permission_required -- ids_permission + , v_id_access_level_view -- ids_access_level + , '' -- ids_product + , 0 -- a_debug + ); + + IF a_debug = 1 THEN + SELECT * FROM partsltd_prod.Shop_Calc_User_Temp WHERE GUID = v_guid; + END IF; IF NOT EXISTS ( SELECT can_view - FROM Shop_Calc_User_Temp UE_T + FROM partsltd_prod.Shop_Calc_User_Temp CUT WHERE 1=1 - AND UE_T.GUID = v_guid - AND UE_T.id_permission_required = v_id_permission_user + AND CUT.GUID = v_guid + AND can_view = 1 + -- AND FIND_IN_SET(v_ids_permission_required, CUT.id_permission_required) > 0 ) THEN INSERT INTO tmp_Msg_Error ( - guid, id_type, code, msg ) VALUES ( - v_guid, - v_id_type_error_data, - v_code_error_data, - CONCAT('You do not have view permissions for ', (SELECT name FROM Shop_Permission WHERE id_permission = v_id_permission_user LIMIT 1)) + v_id_type_error_bad_data, + v_code_error_bad_data, + -- CONCAT('You do not have view permissions for ', (SELECT name FROM partsltd_prod.Shop_Permission WHERE id_permission = v_id_permission_user LIMIT 1)) + -- CONCAT('You do not have view permissions for ', (SELECT GROUP_CONCAT(name SEPARATOR ', ') FROM partsltd_prod.Shop_Permission WHERE FIND_IN_SET(v_id_permission_user, id_permission) > 0)) + CONCAT('You do not have view permissions for ', (SELECT name FROM partsltd_prod.Shop_Permission P INNER JOIN partsltd_prod.Shop_Calc_User_Temp CUT ON P.id_permission = CUT.id_permission_required WHERE GUID = v_guid AND IFNULL(can_view, 0) = 0 LIMIT 1)) -- WHERE IFNULL(CUT.can_view, 0) = 0 ) ; + ELSE + -- INSERT INTO + SET a_debug := a_debug; END IF; + + CALL partsltd_prod.p_shop_clear_calc_user( v_guid, FALSE ); END IF; -- Returns - /* NULL record required for flask sql_alchemy to detect result set - IF EXISTS (SELECT * FROM tmp_Msg_Error WHERE GUID = v_guid) THEN + /* NULL record required for flask sql_alchemy to detect result set */ + IF EXISTS (SELECT * FROM tmp_Msg_Error) THEN DELETE FROM tmp_User; + INSERT INTO tmp_User ( id_user ) + VALUES ( NULL ); END IF; - */ - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error WHERE GUID = v_guid) THEN - SELECT - U.id_user - , U.id_user_auth0 - , U.firstname - , U.surname - , U.email - , U.is_email_verified - , U.id_currency_default - , U.id_region_default - , U.is_included_VAT_default - , U.is_super_user - , UE_T_STORE.can_admin_store AS can_admin_store - , UE_T_USER.can_admin_user AS can_admin_user - FROM tmp_User t_U - INNER JOIN Shop_User U ON t_U.id_user = U.id_user - INNER JOIN ( - SELECT - id_user - , id_permission_required - , can_admin AS can_admin_store - FROM Shop_Calc_User_Temp UE_T_STORE - WHERE 1=1 - AND UE_T_STORE.guid = v_guid - AND UE_T_STORE.id_permission_required = v_id_permission_store_admin - ) UE_T_STORE ON t_U.id_user = UE_T_STORE.id_user - INNER JOIN ( - SELECT - id_user - , id_permission_required - , can_admin AS can_admin_user - FROM Shop_Calc_User_Temp UE_T_USER - WHERE 1=1 - AND UE_T_USER.guid = v_guid - AND UE_T_USER.id_permission_required = v_id_permission_user_admin - ) UE_T_USER ON t_U.id_user = UE_T_USER.id_user - ; - ELSE - SELECT - NULL AS id_user - , NULL AS id_user_auth0 - , NULL AS firstname - , NULL AS surname - , NULL AS email - , NULL AS is_email_verified - , NULL AS id_currency_default - , NULL AS id_region_default - , NULL AS is_included_VAT_default - , NULL AS is_super_user - , NULL AS can_admin_store - , NULL AS can_admin_user - ; - END IF; + + SELECT + U.id_user + , U.id_user_auth0 + , U.firstname + , U.surname + , U.email + , U.is_email_verified + , U.id_currency_default + , U.id_region_default + , U.is_included_VAT_default + , U.is_super_user + , t_U.can_admin_store + , t_U.can_admin_user + FROM tmp_User t_U + INNER JOIN partsltd_prod.Shop_User U ON t_U.id_user = U.id_user + ; # Errors SELECT @@ -13305,27 +14353,33 @@ BEGIN MET.name, MET.description FROM tmp_Msg_Error t_ME - INNER JOIN Shop_Msg_Error_Type MET + INNER JOIN partsltd_prod.Shop_Msg_Error_Type MET ON t_ME.id_type = MET.id_type - WHERE guid = v_guid ; + IF a_debug = 1 THEN + SELECT * FROM tmp_User; + END IF; + -- Clean up DROP TEMPORARY TABLE IF EXISTS tmp_User; DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error; /* - DELETE FROM Shop_Calc_User_Temp + DELETE FROM partsltd_prod.Shop_Calc_User_Temp WHERE GUID = v_guid; */ - CALL p_shop_clear_calc_user(v_guid); + + IF a_debug = 1 THEN + CALL partsltd_prod.p_debug_timing_reporting ( v_time_start ); + END IF; END // DELIMITER ;; - /* + CALL p_get_many_user ( NULL # a_id_user , 'auth0|6582b95c895d09a70ba10fef' # a_id_user_auth0 @@ -13333,13 +14387,15 @@ CALL p_get_many_user ( , 0 # a_get_inactive_user , 0 # a_get_first_user_only , NULL # a_ids_user - , 'auth0|6582b95c895d09a70ba10fef' # a_ids_user_auth0 # ' -- + , 'auth0|6582b95c895d09a70ba10fef' # a_ids_user_auth0 + , 1 -- a_debug ); -select * from Shop_Calc_User_Temp; -delete from Shop_Calc_User_Temp; + +select * FROM partsltd_prod.Shop_Calc_User_Temp; +delete FROM partsltd_prod.Shop_Calc_User_Temp; SELECT * -FROM SHOP_USER; +FROM partsltd_prod.Shop_USER; CALL p_get_many_user( NULL -- :a_id_user, @@ -19253,9 +20309,10 @@ INSERT INTO Shop_Msg_Error_Type ( code, name, description ) VALUES - ('BAD_DATA', 'Invalid data', 'Rubbish data'), - ('NO_PERMISSION', 'No permission', 'Not authorised'), - ('PRODUCT_AVAILABILITY', 'Product not available', 'Product not available') + ('BAD_DATA', 'Invalid data', 'Rubbish data') + , ('NO_PERMISSION', 'No permission', 'Not authorised') + , ('PRODUCT_AVAILABILITY', 'Product not available', 'Product not available') + , ('MYSQL_ERROR', 'MySQL error', 'MySQL execution error.') ; # File Types @@ -19305,6 +20362,14 @@ VALUES ; */ +# Addresses +INSERT INTO Shop_Address ( + id_region, postcode, address_line_1, address_line_2, city, county +) +VALUES ( + 1, 'CV22 6DN', '53 Alfred Green Close', '', 'Rugby', 'Warwickshire' +); + # Plants INSERT INTO Shop_Plant ( code, name, id_address, id_user_manager @@ -19771,7 +20836,10 @@ VALUES (4, 'SALES_AND_PURCHASING', 'Sales and Purchasing'), (5, 'MANUFACTURING', 'Manufacturing') ; - +/* +select * from Shop_Permission +select * from Shop_Role_Permission_Link +*/ # Permissions INSERT INTO Shop_Permission ( display_order, code, name, id_permission_group, id_access_level_required @@ -19846,8 +20914,8 @@ VALUES (1, 1) ; -# Addresses -INSERT INTO Shop_Address ( +# User Addresses +INSERT INTO Shop_User_Address ( id_user, id_region, name_full, phone_number, postcode, address_line_1, address_line_2, city, county ) SELECT U.id_user, 1, CONCAT(U.firstname, ' ', U.surname), '07375 571430', 'CV22 6DN', '53 Alfred Green Close', '', 'Rugby', 'Warwickshire' @@ -19916,7 +20984,7 @@ INSERT INTO Shop_Supplier ( , id_currency ) VALUES - ('Malt Kiln Farm Shop', NULL, NULL, 2, '01788 832640', NULL, 'farmshop@maltkilnfarmshop.co.uk', 'https://www.maltkilnfarmshop.co.uk/', 1) + ('Malt Kiln Farm Shop', NULL, NULL, 1, '01788 832640', NULL, 'farmshop@maltkilnfarmshop.co.uk', 'https://www.maltkilnfarmshop.co.uk/', 1) ; /* @@ -20200,7 +21268,7 @@ SELECT * FROM Shop_Customer_Sales_Order_Product_Link_Audit; - +/* SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES @@ -20224,4 +21292,7 @@ FROM WHERE TABLE_SCHEMA = 'PARTS' -- AND TABLE_NAME = 'your_table_name' -; \ No newline at end of file +; + +*/ + diff --git a/static/MySQL/0001_destroy.sql b/static/MySQL/0001_destroy.sql index be06d199..561523ff 100644 --- a/static/MySQL/0001_destroy.sql +++ b/static/MySQL/0001_destroy.sql @@ -41,6 +41,8 @@ DROP TABLE IF EXISTS tmp_Shop_Customer_Sale_Order; # Delete old tables DROP TABLE IF EXISTS Split_Temp; +DROP TABLE IF EXISTS Split_Key_Value_Pair_Csv_Temp; +DROP TABLE IF EXISTS Split_Key_Value_Pair_Temp; DROP TABLE IF EXISTS Shop_User_Eval_Temp; DROP TABLE IF EXISTS Shop_Calc_User_Temp; @@ -87,8 +89,8 @@ DROP TABLE IF EXISTS Shop_User_Order_Status; DROP TABLE IF EXISTS Shop_User_Basket_Audit; DROP TABLE IF EXISTS Shop_User_Basket; -DROP TABLE IF EXISTS Shop_Address_Audit; -DROP TABLE IF EXISTS Shop_Address; +DROP TABLE IF EXISTS Shop_User_Address_Audit; +DROP TABLE IF EXISTS Shop_User_Address; DROP TABLE IF EXISTS Shop_User_Role_Link_Audit; DROP TABLE IF EXISTS Shop_User_Role_Link; @@ -190,6 +192,9 @@ DROP TABLE IF EXISTS Shop_Plant_Temp; DROP TABLE IF EXISTS Shop_Plant_Audit; DROP TABLE IF EXISTS Shop_Plant; +DROP TABLE IF EXISTS Shop_Address_Audit; +DROP TABLE IF EXISTS Shop_Address; + DROP TABLE IF EXISTS Shop_Delivery_Region_Branch_Audit; DROP TABLE IF EXISTS Shop_Delivery_Region_Branch; DROP TABLE IF EXISTS Shop_Region_Branch_Temp; @@ -232,6 +237,9 @@ DROP TABLE IF EXISTS Shop_Product_Change_Set; -- Procedures DROP PROCEDURE IF EXISTS p_split; DROP PROCEDURE IF EXISTS p_clear_split_temp; +DROP PROCEDURE IF EXISTS p_split_key_value_pair_csv; +DROP PROCEDURE IF EXISTS p_clear_split_key_value_csv_temp; +DROP PROCEDURE IF EXISTS p_clear_split_key_value_pair_csv_temp; DROP PROCEDURE IF EXISTS p_debug_timing_reporting; DROP PROCEDURE IF EXISTS p_validate_guid; @@ -248,12 +256,15 @@ 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_plant; +DROP PROCEDURE IF EXISTS p_shop_get_many_storage_location; DROP PROCEDURE IF EXISTS p_shop_get_many_currency; DROP PROCEDURE IF EXISTS p_shop_save_category; DROP PROCEDURE IF EXISTS p_shop_save_product_category; DROP PROCEDURE IF EXISTS p_shop_save_product_category_test; DROP PROCEDURE IF EXISTS p_shop_save_product; +DROP PROCEDURE IF EXISTS p_shop_save_product_test; DROP PROCEDURE IF EXISTS p_shop_calc_product_permutation; DROP PROCEDURE IF EXISTS p_shop_clear_calc_product_permutation; DROP PROCEDURE IF EXISTS p_shop_get_many_product; @@ -261,6 +272,9 @@ 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 FUNCTION IF EXISTS fn_shop_get_id_product_permutation_from_variation_csv_list; +DROP PROCEDURE IF EXISTS p_shop_save_stock_item; +DROP PROCEDURE IF EXISTS p_shop_save_stock_item_test; 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; DROP PROCEDURE IF EXISTS p_shop_get_many_product_price_and_discount_and_delivery_option; diff --git a/static/MySQL/1001_tbl_Split_Key_Value_Pair_Csv_Temp.sql b/static/MySQL/1001_tbl_Split_Key_Value_Pair_Csv_Temp.sql new file mode 100644 index 00000000..75275214 --- /dev/null +++ b/static/MySQL/1001_tbl_Split_Key_Value_Pair_Csv_Temp.sql @@ -0,0 +1,13 @@ + +# Split Key Value Pair CSV Staging +-- USE partsltd_prod; +-- DROP TABLE IF EXISTS Split_Temp; + +SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Split_Key_Value_Pair_Csv_Temp'; + +CREATE TABLE Split_Key_Value_Pair_Csv_Temp ( + guid BINARY(36) NOT NULL + , id INT NOT NULL + , key_column VARCHAR(4000) NULL + , value_column VARCHAR(4000) NULL +); diff --git a/static/MySQL/1100_tbl_Shop_Region.sql b/static/MySQL/1100_tbl_Shop_Region.sql index bab1a4e1..6ce12b78 100644 --- a/static/MySQL/1100_tbl_Shop_Region.sql +++ b/static/MySQL/1100_tbl_Shop_Region.sql @@ -1,8 +1,6 @@ # Regions - - SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Region'; CREATE TABLE IF NOT EXISTS Shop_Region ( diff --git a/static/MySQL/1106_tbl_Shop_Address.sql b/static/MySQL/1106_tbl_Shop_Address.sql new file mode 100644 index 00000000..0c66b3d8 --- /dev/null +++ b/static/MySQL/1106_tbl_Shop_Address.sql @@ -0,0 +1,22 @@ + +# Addresses + + +SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Address'; + +CREATE TABLE Shop_Address ( + id_address INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + id_region INT NOT NULL, + postcode VARCHAR(20) NOT NULL, + address_line_1 VARCHAR(256) NOT NULL, + address_line_2 VARCHAR(256) NOT NULL, + city VARCHAR(256) NOT NULL, + county VARCHAR(256) NOT NULL, + active BIT NOT NULL DEFAULT 1, + created_on TIMESTAMP, + created_by INT, + id_change_set INT, + CONSTRAINT FK_Shop_Address_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES Shop_User_Change_Set(id_change_set) +); \ No newline at end of file diff --git a/static/MySQL/1106_tbl_Shop_Plant.sql b/static/MySQL/1106_tbl_Shop_Plant.sql index a040ea03..7ebc467d 100644 --- a/static/MySQL/1106_tbl_Shop_Plant.sql +++ b/static/MySQL/1106_tbl_Shop_Plant.sql @@ -1,8 +1,6 @@ # Plant - - SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Plant'; CREATE TABLE IF NOT EXISTS Shop_Plant ( @@ -10,6 +8,9 @@ CREATE TABLE IF NOT EXISTS Shop_Plant ( code VARCHAR(50) NOT NULL, name VARCHAR(500) NOT NULL, id_address INT NOT NULL, + CONSTRAINT FK_Shop_Plant_id_address + FOREIGN KEY (id_address) + REFERENCES Shop_Address(id_address), id_user_manager INT NOT NULL, active BIT NOT NULL DEFAULT 1, created_on TIMESTAMP, diff --git a/static/MySQL/1319_tbl_Shop_Address_Audit.sql b/static/MySQL/1107_tbl_Shop_Address_Audit.sql similarity index 100% rename from static/MySQL/1319_tbl_Shop_Address_Audit.sql rename to static/MySQL/1107_tbl_Shop_Address_Audit.sql diff --git a/static/MySQL/1108_tbl_Shop_Plant_Temp.sql b/static/MySQL/1108_tbl_Shop_Plant_Temp.sql index f0f9560d..79c9ad90 100644 --- a/static/MySQL/1108_tbl_Shop_Plant_Temp.sql +++ b/static/MySQL/1108_tbl_Shop_Plant_Temp.sql @@ -6,10 +6,11 @@ SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Plant_Temp'; CREATE TABLE IF NOT EXISTS Shop_Plant_Temp ( - id_plant INT NOT NULL PRIMARY KEY, - code VARCHAR(50) NOT NULL, - name VARCHAR(500) NOT NULL, - id_address INT NOT NULL, - id_user_manager INT NOT NULL, - active BIT NOT NULL DEFAULT 1 + id_plant INT NOT NULL PRIMARY KEY + , code VARCHAR(50) NOT NULL + , name VARCHAR(500) NOT NULL + , id_address INT NOT NULL + , id_user_manager INT NOT NULL + , active BIT NOT NULL DEFAULT 1 + , guid BINARY(36) NOT NULL ); diff --git a/static/MySQL/1218_tbl_Shop_Stock_Item.sql b/static/MySQL/1218_tbl_Shop_Stock_Item.sql index f8591647..810c8b0f 100644 --- a/static/MySQL/1218_tbl_Shop_Stock_Item.sql +++ b/static/MySQL/1218_tbl_Shop_Stock_Item.sql @@ -1,7 +1,7 @@ # Stock Stock Item - +-- DROP TABLE IF EXISTS Shop_Stock_Item; SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Stock_Item'; @@ -11,8 +11,8 @@ CREATE TABLE IF NOT EXISTS Shop_Stock_Item ( CONSTRAINT FK_Shop_Stock_Item_id_permutation FOREIGN KEY (id_permutation) REFERENCES Shop_Product_Permutation(id_permutation), - date_purchased TIMESTAMP NOT NULL, - date_received TIMESTAMP NULL, + date_purchased DATETIME NOT NULL, + date_received DATETIME NULL, id_location_storage INT NOT NULL, CONSTRAINT FK_Shop_Stock_Item_id_location_storage FOREIGN KEY (id_location_storage) @@ -21,15 +21,15 @@ CREATE TABLE IF NOT EXISTS Shop_Stock_Item ( CONSTRAINT FK_Shop_Stock_Item_id_currency FOREIGN KEY (id_currency_cost) REFERENCES Shop_Currency(id_currency), - cost_local_VAT_incl FLOAT NOT NULL, - cost_local_VAT_excl FLOAT NOT NULL, + cost_local_VAT_incl FLOAT NULL, + cost_local_VAT_excl FLOAT NULL, is_sealed BIT NOT NULL DEFAULT 1, - date_unsealed TIMESTAMP NULL, - date_expiration TIMESTAMP NOT NULL, + date_unsealed DATETIME NULL, + date_expiration DATETIME NOT NULL, is_consumed BIT NOT NULL DEFAULT 0, - date_consumed TIMESTAMP NULL, + date_consumed DATETIME NULL, active BIT NOT NULL DEFAULT 1, - created_on TIMESTAMP, + created_on DATETIME, created_by INT, id_change_set INT, CONSTRAINT FK_Shop_Stock_Item_id_change_set diff --git a/static/MySQL/1220_tbl_Shop_Stock_Item_Temp.sql b/static/MySQL/1220_tbl_Shop_Stock_Item_Temp.sql index 4f6b4bc6..8393de95 100644 --- a/static/MySQL/1220_tbl_Shop_Stock_Item_Temp.sql +++ b/static/MySQL/1220_tbl_Shop_Stock_Item_Temp.sql @@ -1,22 +1,27 @@ # Stock Stock Item Temp - +DROP TABLE IF EXISTS Shop_Stock_Item_Temp; SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Stock_Item_Temp'; CREATE TABLE IF NOT EXISTS Shop_Stock_Item_Temp ( - id_stock INT NOT NULL PRIMARY KEY, - id_permutation INT NOT NULL, - date_purchased TIMESTAMP NOT NULL, - id_location_storage INT NOT NULL, - id_currency INT NOT NULL, - cost_local_VAT_incl FLOAT NOT NULL, - cost_local_VAT_excl FLOAT NOT NULL, - is_sealed BIT NOT NULL DEFAULT 1, - date_unsealed TIMESTAMP NULL, - date_expiration TIMESTAMP NULL, - is_consumed BIT NOT NULL DEFAULT 0, - date_consumed TIMESTAMP NULL, - active BIT NOT NULL DEFAULT 1 + id_stock INT NULL + -- , id_category INT NULL + , id_product INT NOT NULL + , id_permutation INT NULL + , id_pairs_variations VARCHAR(4000) NULL + , date_purchased DATETIME NOT NULL + , date_received DATETIME NULL + , id_location_storage INT NOT NULL + , id_currency_cost INT NOT NULL + , cost_local_VAT_incl FLOAT NOT NULL + , cost_local_VAT_excl FLOAT NOT NULL + , is_sealed BIT NOT NULL + , date_unsealed DATETIME NULL + , date_expiration DATETIME NULL + , is_consumed BIT NOT NULL + , date_consumed DATETIME NULL + , active BIT NOT NULL + , guid BINARY(36) NOT NULL ); diff --git a/static/MySQL/1318_tbl_Shop_Address.sql b/static/MySQL/1318_tbl_Shop_User_Address.sql similarity index 66% rename from static/MySQL/1318_tbl_Shop_Address.sql rename to static/MySQL/1318_tbl_Shop_User_Address.sql index ed309ee4..a18c999e 100644 --- a/static/MySQL/1318_tbl_Shop_Address.sql +++ b/static/MySQL/1318_tbl_Shop_User_Address.sql @@ -1,12 +1,10 @@ -# Addresses +# User Addresses +SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_User_Address'; - -SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_Address'; - -CREATE TABLE Shop_Address ( - id_address INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +CREATE TABLE Shop_User_Address ( + id_user_address INT NOT NULL AUTO_INCREMENT PRIMARY KEY, id_user INT NOT NULL, CONSTRAINT FK_Shop_Address_id_user FOREIGN KEY (id_user) @@ -17,15 +15,15 @@ CREATE TABLE Shop_Address ( name_full VARCHAR(255) NOT NULL, phone_number VARCHAR(20) NOT NULL, postcode VARCHAR(20) NOT NULL, - address_line_1 VARCHAR(100) NOT NULL, - address_line_2 VARCHAR(100) NOT NULL, - city VARCHAR(50) NOT NULL, - county VARCHAR(100) NOT NULL, + address_line_1 VARCHAR(256) NOT NULL, + address_line_2 VARCHAR(256) NOT NULL, + city VARCHAR(256) NOT NULL, + county VARCHAR(256) NOT NULL, active BIT NOT NULL DEFAULT 1, created_on TIMESTAMP, created_by INT, id_change_set INT, - CONSTRAINT FK_Shop_Address_id_change_set + CONSTRAINT FK_Shop_User_Address_id_change_set FOREIGN KEY (id_change_set) REFERENCES Shop_User_Change_Set(id_change_set) ); \ No newline at end of file diff --git a/static/MySQL/1319_tbl_Shop_User_Address_Audit.sql b/static/MySQL/1319_tbl_Shop_User_Address_Audit.sql new file mode 100644 index 00000000..48ae53fa --- /dev/null +++ b/static/MySQL/1319_tbl_Shop_User_Address_Audit.sql @@ -0,0 +1,21 @@ + +# Address Audits + +SELECT CONCAT('WARNING: Table ', TABLE_NAME, ' already exists.') AS msg_warning FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Shop_User_Address_Audit'; + +CREATE TABLE IF NOT EXISTS Shop_User_Address_Audit ( + id_audit INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + id_user_address INT NOT NULL, + CONSTRAINT FK_Shop_User_Address_Audit_id_address + FOREIGN KEY (id_user_address) + REFERENCES Shop_User_Address(id_user_address) + ON UPDATE RESTRICT, + name_field VARCHAR(50), + value_prev VARCHAR(500), + value_new VARCHAR(500), + id_change_set INT NOT NULL, + CONSTRAINT FK_Shop_User_Address_Audit_id_change_set + FOREIGN KEY (id_change_set) + REFERENCES Shop_User_Change_Set(id_change_set) + ON UPDATE RESTRICT +); \ No newline at end of file diff --git a/static/MySQL/3318_tri_Shop_Address.sql b/static/MySQL/3106_tri_Shop_Address.sql similarity index 85% rename from static/MySQL/3318_tri_Shop_Address.sql rename to static/MySQL/3106_tri_Shop_Address.sql index 6fa1df86..30d2d987 100644 --- a/static/MySQL/3318_tri_Shop_Address.sql +++ b/static/MySQL/3106_tri_Shop_Address.sql @@ -39,14 +39,6 @@ BEGIN SELECT NEW.id_address, 'id_region', OLD.id_region, NEW.id_region, NEW.id_change_set WHERE NOT OLD.id_region <=> NEW.id_region UNION - # Changed name_full - SELECT NEW.id_address, 'name_full', OLD.name_full, NEW.name_full, NEW.id_change_set - WHERE NOT OLD.name_full <=> NEW.name_full - UNION - # Changed phone_number - SELECT NEW.id_address, 'phone_number', OLD.phone_number, NEW.phone_number, NEW.id_change_set - WHERE NOT OLD.phone_number <=> NEW.phone_number - UNION # Changed postcode SELECT NEW.id_address, 'postcode', OLD.postcode, NEW.postcode, NEW.id_change_set WHERE NOT OLD.postcode <=> NEW.postcode diff --git a/static/MySQL/3318_tri_Shop_User_Address.sql b/static/MySQL/3318_tri_Shop_User_Address.sql new file mode 100644 index 00000000..99420d98 --- /dev/null +++ b/static/MySQL/3318_tri_Shop_User_Address.sql @@ -0,0 +1,75 @@ + +# Shop Address + + + +DROP TRIGGER IF EXISTS before_insert_Shop_User_Address; +DROP TRIGGER IF EXISTS before_update_Shop_User_Address; + + +DELIMITER // +CREATE TRIGGER before_insert_Shop_User_Address +BEFORE INSERT ON Shop_User_Address +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 // +DELIMITER ;; + + +DELIMITER // +CREATE TRIGGER before_update_Shop_User_Address +BEFORE UPDATE ON Shop_User_Address +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_User_Address_Audit ( + id_user_address, + name_field, + value_prev, + value_new, + id_change_set + ) + # Changed region + SELECT NEW.id_user_address, 'id_region', OLD.id_region, NEW.id_region, NEW.id_change_set + WHERE NOT OLD.id_region <=> NEW.id_region + UNION + # Changed name_full + SELECT NEW.id_user_address, 'name_full', OLD.name_full, NEW.name_full, NEW.id_change_set + WHERE NOT OLD.name_full <=> NEW.name_full + UNION + # Changed phone_number + SELECT NEW.id_user_address, 'phone_number', OLD.phone_number, NEW.phone_number, NEW.id_change_set + WHERE NOT OLD.phone_number <=> NEW.phone_number + UNION + # Changed postcode + SELECT NEW.id_user_address, 'postcode', OLD.postcode, NEW.postcode, NEW.id_change_set + WHERE NOT OLD.postcode <=> NEW.postcode + UNION + # Changed address_line_1 + SELECT NEW.id_user_address, 'address_line_1', OLD.address_line_1, NEW.address_line_1, NEW.id_change_set + WHERE NOT OLD.address_line_1 <=> NEW.address_line_1 + UNION + # Changed address_line_2 + SELECT NEW.id_user_address, 'address_line_2', OLD.address_line_2, NEW.address_line_2, NEW.id_change_set + WHERE NOT OLD.address_line_2 <=> NEW.address_line_2 + UNION + # Changed city + SELECT NEW.id_user_address, 'city', OLD.city, NEW.city, NEW.id_change_set + WHERE NOT OLD.city <=> NEW.city + UNION + # Changed county + SELECT NEW.id_user_address, 'county', OLD.county, NEW.county, NEW.id_change_set + WHERE NOT OLD.county <=> NEW.county + UNION + # Changed active + SELECT NEW.id_user_address, 'active', CONVERT(CONVERT(OLD.active, SIGNED), CHAR), CONVERT(CONVERT(NEW.active, SIGNED), CHAR), NEW.id_change_set + WHERE NOT (OLD.active <=> NEW.active) + ; +END // +DELIMITER ;; \ No newline at end of file diff --git a/static/MySQL/6000_p_split.sql b/static/MySQL/6000_p_split.sql index cf10e634..33fbcfe7 100644 --- a/static/MySQL/6000_p_split.sql +++ b/static/MySQL/6000_p_split.sql @@ -78,6 +78,8 @@ BEGIN COMMIT; END IF; + DROP TABLE IF EXISTS tmp_Split_Split; + IF a_debug = 1 THEN CALL p_debug_timing_reporting ( v_time_start ); END IF; diff --git a/static/MySQL/6003_p_split_key_value_pair_csv.sql b/static/MySQL/6003_p_split_key_value_pair_csv.sql new file mode 100644 index 00000000..bacbb427 --- /dev/null +++ b/static/MySQL/6003_p_split_key_value_pair_csv.sql @@ -0,0 +1,108 @@ + + +DROP PROCEDURE IF EXISTS p_split_key_value_pair_csv; + +DELIMITER // +CREATE PROCEDURE p_split_key_value_pair_csv ( + IN a_guid BINARY(36) + , IN a_string LONGTEXT + , IN a_debug BIT +) +BEGIN + DECLARE v_has_string BIT; + DECLARE v_current_item VARCHAR(4000); + DECLARE v_time_start TIMESTAMP(6); + + SET v_time_start := CURRENT_TIMESTAMP(6); + SET a_string := IFNULL(a_string, ''); + SET a_debug := IFNULL(a_debug, 0); + + SET v_has_string = CASE WHEN a_string = '' THEN 0 ELSE 1 END; + + IF a_debug = 1 THEN + SELECT + a_guid + , a_string + , a_debug + ; + END IF; + + CALL p_validate_guid ( a_guid ); + + DROP TEMPORARY TABLE IF EXISTS tmp_Split_Input; + DROP TEMPORARY TABLE IF EXISTS tmp_Split_Split; + + CREATE TEMPORARY TABLE tmp_Split_Input ( + input_string TEXT + ); + + CREATE TEMPORARY TABLE tmp_Split_Split ( + id INT AUTO_INCREMENT PRIMARY KEY + , key_column VARCHAR(4000) + , value_column VARCHAR(4000) + ); + + INSERT INTO tmp_Split_Input ( + input_string + ) + VALUES ( + a_string + ); + + INSERT INTO tmp_Split_Split (key_column, value_column) + SELECT + SUBSTRING_INDEX(SUBSTRING_INDEX(t.pair, ':', 1), ',', -1) AS key_column, + SUBSTRING_INDEX(t.pair, ':', -1) AS value_column + FROM ( + SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(input_string, ',', n), ',', -1) pair + FROM temp_input + CROSS JOIN ( + SELECT a.N + b.N * 10 + 1 n + FROM (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a + CROSS JOIN (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b + ORDER BY n + ) numbers + WHERE n <= 1 + (LENGTH(input_string) - LENGTH(REPLACE(input_string, ',', ''))) + ) t; + + IF EXISTS (SELECT * FROM tmp_Split_Split LIMIT 1) THEN + START TRANSACTION; + INSERT INTO Split_Key_Value_Pair_Csv_Temp ( + guid + , id + , key_column + , value_column + ) + SELECT + a_guid + , id + , key_column + , value_column + FROM tmp_Split_Split + ; + COMMIT; + END IF; + + DROP TEMPORARY TABLE IF EXISTS tmp_Split_Input; + DROP TEMPORARY TABLE IF EXISTS tmp_Split_Split; + + IF a_debug = 1 THEN + CALL p_debug_timing_reporting ( v_time_start ); + END IF; +END // +DELIMITER ;; + + +/* +CALL p_split_key_value_pair_csv ( + 'nipsnipsnipsnipsnipsnipsnipsnipsnips' + , '1:100,2:200,3:300,4:400' # a_string + , 1 +); + +SELECT * +FROM Split_key_value_pair_csv_Temp +WHERE GUID = 'nipsnipsnipsnipsnipsnipsnipsnipsnips'; + +CALL p_clear_split_key_value_pair_csv_temp( 'nipsnipsnipsnipsnipsnipsnipsnipsnips' ); +*/ diff --git a/static/MySQL/6004_p_clear_split_key_value_pair_csv_temp.sql b/static/MySQL/6004_p_clear_split_key_value_pair_csv_temp.sql new file mode 100644 index 00000000..3ab910cf --- /dev/null +++ b/static/MySQL/6004_p_clear_split_key_value_pair_csv_temp.sql @@ -0,0 +1,29 @@ + +-- Clear previous proc +DROP PROCEDURE IF EXISTS p_clear_split_key_value_pair_csv_temp; + + +DELIMITER // +CREATE PROCEDURE p_clear_split_key_value_pair_csv_temp ( + IN a_guid BINARY(36) +) +BEGIN + CALL p_validate_guid( a_guid ); + + START TRANSACTION; + + -- DROP TABLE IF EXISTS + DELETE FROM Split_Key_Value_Pair_Csv_Temp + WHERE GUID = a_guid + ; + + COMMIT; +END // +DELIMITER ;; + +/* + +CALL p_clear_split_key_value_pair_csv_temp ( 'nipsnipsnipsnipsnipsnipsnipsnipsnips' ); + + +*/ diff --git a/static/MySQL/7106_p_shop_get_many_plant.sql b/static/MySQL/7106_p_shop_get_many_plant.sql new file mode 100644 index 00000000..7f6775c9 --- /dev/null +++ b/static/MySQL/7106_p_shop_get_many_plant.sql @@ -0,0 +1,36 @@ + + +-- Clear previous proc +DROP PROCEDURE IF EXISTS p_shop_get_many_plant; + + +DELIMITER // +CREATE PROCEDURE p_shop_get_many_plant ( + IN a_get_inactive_plant BIT +) +BEGIN + SET a_get_inactive_plant = IFNULL(a_get_inactive_plant, 0); + + SELECT + P.id_plant + , P.id_address + , A.id_region + , P.id_user_manager + , P.code + , P.name + , P.active + FROM Shop_Plant P + INNER JOIN Shop_Address A ON P.id_address = A.id_address + WHERE + a_get_inactive_plant = 1 + OR P.active = 1 + ; +END // +DELIMITER ;; + + +/* +CALL p_shop_get_many_plant ( + 0 # a_get_inactive_plant +); +*/ diff --git a/static/MySQL/7109_p_shop_get_many_storage_location.sql b/static/MySQL/7109_p_shop_get_many_storage_location.sql new file mode 100644 index 00000000..d4de385e --- /dev/null +++ b/static/MySQL/7109_p_shop_get_many_storage_location.sql @@ -0,0 +1,37 @@ + + +-- Clear previous proc +DROP PROCEDURE IF EXISTS p_shop_get_many_storage_location; + + +DELIMITER // +CREATE PROCEDURE p_shop_get_many_storage_location ( + IN a_get_inactive_storage_location BIT +) +BEGIN + SET a_get_inactive_storage_location = IFNULL(a_get_inactive_storage_location, 0); + + SELECT + SL.id_storage_location + , P.id_plant + , P.id_address + , A.id_region + , SL.code + , SL.name + , P.active + FROM Shop_Storage_Location SL + INNER JOIN Shop_Plant P ON SL.id_plant = P.id_plant + INNER JOIN Shop_Address A ON P.id_address = A.id_address + WHERE + a_get_inactive_storage_location = 1 + OR SL.active = 1 + ; +END // +DELIMITER ;; + + +/* +CALL p_shop_get_many_storage_location ( + 0 # a_get_inactive_storage_location +); +*/ diff --git a/static/MySQL/7203_p_shop_save_product_test.sql b/static/MySQL/7203_p_shop_save_product_test.sql index 18666a78..34651f91 100644 --- a/static/MySQL/7203_p_shop_save_product_test.sql +++ b/static/MySQL/7203_p_shop_save_product_test.sql @@ -37,7 +37,7 @@ BEGIN 4 -- id_product , 1 -- id_category , 'Laptops' -- name - , 1 -- has_variations + , 0 -- has_variations , 2 -- id_access_level_required , 2 -- display_order , 1 -- active @@ -69,10 +69,10 @@ BEGIN END // DELIMITER ;; +/* CALL partsltd_prod.p_shop_save_product_test (); DELETE FROM partsltd_prod.Shop_Product_Temp; -/* DROP TABLE IF EXISTS tmp_Msg_Error; */ \ No newline at end of file diff --git a/static/MySQL/7204_p_shop_get_many_product.sql b/static/MySQL/7204_p_shop_get_many_product.sql index 0b26f7c4..783d2273 100644 --- a/static/MySQL/7204_p_shop_get_many_product.sql +++ b/static/MySQL/7204_p_shop_get_many_product.sql @@ -464,6 +464,7 @@ END // DELIMITER ;; +/* CALL partsltd_prod.p_shop_get_many_product ( 1 #'auth0|6582b95c895d09a70ba10fef', # a_id_user @@ -483,7 +484,6 @@ CALL partsltd_prod.p_shop_get_many_product ( , 0 # a_debug ); -/* select * FROM partsltd_prod.Shop_Calc_User_Temp; select * FROM partsltd_prod.Shop_Product_Category; diff --git a/static/MySQL/7210_fn_shop_get_id_product_permutation_from_variation_csv_list.sql b/static/MySQL/7210_fn_shop_get_id_product_permutation_from_variation_csv_list.sql new file mode 100644 index 00000000..a31b0b8d --- /dev/null +++ b/static/MySQL/7210_fn_shop_get_id_product_permutation_from_variation_csv_list.sql @@ -0,0 +1,221 @@ + +DROP FUNCTION IF EXISTS fn_shop_get_id_product_permutation_from_variation_csv_list; + +DELIMITER // + +CREATE FUNCTION fn_shop_get_id_product_permutation_from_variation_csv_list ( + a_id_product INT + , a_variation_csv TEXT +) +RETURNS INT +DETERMINISTIC +READS SQL DATA +BEGIN + DECLARE v_id_permutation INT; + DECLARE done INT DEFAULT FALSE; + DECLARE v_id_variation_type INT; + DECLARE v_id_variation INT; + DECLARE v_id_permutation_tmp INT; + DECLARE cur CURSOR FOR + SELECT + CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(t.pair, ':', 1), ',', -1) AS UNSIGNED) AS id_variation_type, + CAST(SUBSTRING_INDEX(t.pair, ':', -1) AS UNSIGNED) AS id_variation + FROM ( + SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(a_variation_csv, ',', n), ',', -1) pair + FROM ( + SELECT a.N + b.N * 10 + 1 n + FROM (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a + CROSS JOIN (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b + ORDER BY n + ) numbers + WHERE n <= 1 + (LENGTH(a_variation_csv) - LENGTH(REPLACE(a_variation_csv, ',', ''))) + ) t; + + DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; + + SET v_id_permutation = NULL; + + OPEN cur; + + read_loop: LOOP + FETCH cur INTO v_id_variation_type, v_id_variation; + IF done THEN + LEAVE read_loop; + END IF; + + IF v_id_permutation IS NULL THEN + -- First iteration: find initial v_id_permutations + SELECT PPVL.id_permutation INTO v_id_permutation + FROM partsltd_prod.Shop_Product_Permutation_Variation_Link PPVL + INNER JOIN partsltd_prod.Shop_Product_Permutation PP ON PPVL.id_permutation = PP.id_permutation + INNER JOIN partsltd_prod.Shop_Variation PV ON PPVL.id_variation = PV.id_variation + WHERE 1=1 + AND PP.id_product = a_id_product + AND PPVL.id_variation = v_id_variation + AND PV.id_type = v_id_variation_type + ; + ELSE + -- Subsequent iterations: narrow down the v_id_permutation + SELECT PPVL.id_permutation INTO v_id_permutation_tmp + FROM partsltd_prod.Shop_Product_Permutation_Variation_Link PPVL + INNER JOIN partsltd_prod.Shop_Product_Permutation PP ON PPVL.id_permutation = PP.id_permutation + INNER JOIN partsltd_prod.Shop_Variation PV ON PPVL.id_variation = PV.id_variation + WHERE 1=1 + AND PP.id_product = a_id_product + AND PPVL.v_id_permutation = v_id_permutation + AND PPVL.id_variation = v_id_variation + AND PV.id_type = v_id_variation_type + ; + + IF v_id_permutation_tmp IS NULL THEN + -- If no match found, exit the loop + SET v_id_permutation := NULL; + LEAVE read_loop; + ELSE + SET v_id_permutation := v_id_permutation_tmp; + END IF; + END IF; + END LOOP; + + CLOSE cur; + + RETURN v_id_permutation; +END // + +DELIMITER ; + +/* +SELECT fn_shop_get_id_product_permutation_from_variation_csv_list ( 1, '1:1' ) AS id_permutation; +SELECT fn_shop_get_id_product_permutation_from_variation_csv_list ( 3, '' ) AS id_permutation; +*/ + + +/* +-- Update the table using the function +UPDATE product_permutation_input +SET v_id_permutation = find_v_id_permutation(variation_csv) +WHERE v_id_permutation IS NULL; +*/ + +/* +select * from partsltd_prod.Shop_Variation + +DROP PROCEDURE IF EXISTS p_shop_get_id_product_permutation_from_variation_csv_list; + +DELIMITER // +CREATE PROCEDURE p_shop_get_id_product_permutation_from_variation_csv_list ( + IN a_guid BINARY(36) + , IN a_debug BIT +) +BEGIN + DECLARE done INT DEFAULT FALSE; + DECLARE v_id INT; + DECLARE v_row_id INT; + DECLARE v_variation_csv TEXT; + DECLARE v_id_permutation INT; + DECLARE v_time_start TIMESTAMP(6); + + -- Cursor to iterate through unprocessed rows + DECLARE cur CURSOR FOR + SELECT id, session_guid, row_id, variation_csv + FROM product_permutation_input + WHERE v_id_permutation IS NULL; + + DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; + + SET v_time_start := CURRENT_TIMESTAMP(6); + SET a_debug := IFNULL(a_debug, 0); + + IF a_debug = 1 THEN + SELECT + a_guid + , a_debug + ; + END IF; + + CALL p_validate_guid ( a_guid ); + + OPEN cur; + + read_loop: LOOP + FETCH cur INTO v_id, v_session_guid, v_row_id, v_variation_csv; + IF done THEN + LEAVE read_loop; + END IF; + + -- Find matching v_id_permutation + SET v_id_permutation = NULL; + + SELECT ppvl.v_id_permutation INTO v_id_permutation + FROM ( + SELECT + SUBSTRING_INDEX(SUBSTRING_INDEX(t.pair, ':', 1), ',', -1) AS id_variation_type, + SUBSTRING_INDEX(t.pair, ':', -1) AS id_variation + FROM ( + SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(v_variation_csv, ',', numbers.n), ',', -1) pair + FROM ( + SELECT 1 n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 -- add more if needed + ) numbers + WHERE CHAR_LENGTH(v_variation_csv) - CHAR_LENGTH(REPLACE(v_variation_csv, ',', '')) >= numbers.n - 1 + ) t + ) parsed + INNER JOIN product_permutation_variation_link ppvl + ON parsed.id_variation_type = ppvl.id_variation_type + AND parsed.id_variation = ppvl.id_variation + GROUP BY ppvl.v_id_permutation + HAVING COUNT(*) = (LENGTH(v_variation_csv) - LENGTH(REPLACE(v_variation_csv, ',', '')) + 1) + LIMIT 1; + + -- Update the v_id_permutation in the input table + UPDATE product_permutation_input + SET v_id_permutation = v_id_permutation + WHERE id = v_id; + + END LOOP; + + CLOSE cur; + + + IF EXISTS ( SELECT * FROM Shop_Get_Id_Product_Permutation_From_Variation_Csv_List_Temp WHERE GUID = a_guid LIMIT 1 ) THEN + IF EXISTS (SELECT * FROM tmp_Split_Split LIMIT 1) THEN + START TRANSACTION; + INSERT INTO Split_Key_Value_Pair_Csv_Temp ( + guid + , id + , key_column + , value_column + ) + SELECT + a_guid + , id + , key_column + , value_column + FROM tmp_Split_Split + ; + COMMIT; + END IF; + END IF; + + DROP TEMPORARY TABLE IF EXISTS tmp_Split_Input; + DROP TEMPORARY TABLE IF EXISTS tmp_Split_Split; + + IF a_debug = 1 THEN + CALL p_debug_timing_reporting ( v_time_start ); + END IF; +END // +DELIMITER ;; +*/ + +/* +CALL p_shop_get_id_product_permutation_from_variation_csv_list ( + 'nipsnipsnipsnipsnipsnipsnipsnipsnips' + , '1:100,2:200,3:300,4:400' # a_string + , 1 +); + +SELECT * +FROM Split_key_value_pair_csv_Temp +WHERE GUID = 'nipsnipsnipsnipsnipsnipsnipsnipsnips'; + +CALL p_clear_split_key_value_pair_csv_temp( 'nipsnipsnipsnipsnipsnipsnipsnipsnips' ); +*/ 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 21c21bf2..20443aff 100644 --- a/static/MySQL/7219_p_shop_get_many_stock_item.sql +++ b/static/MySQL/7219_p_shop_get_many_stock_item.sql @@ -622,6 +622,7 @@ BEGIN select * from tmp_Stock_Item; select * from tmp_Permutation; select * from tmp_Location_Storage; + select * from Shop_Storage_Location; select * from tmp_Plant_Storage; select * from tmp_Region_Storage; */ @@ -636,14 +637,19 @@ BEGIN P.id_category, t_SI.id_location_storage, t_PS.id_plant, - t_RS.id_region, + PLANT.id_address AS id_address_plant, + t_RS.id_region AS id_region_plant, + SL.code AS code_storage_location, + SL.name AS name_storage_location, + PLANT.code AS code_plant, + PLANT.name AS name_plant, SI.id_currency_cost, CURRENCY.symbol AS symbol_currency_cost, CURRENCY.code AS code_currency_cost, + SI.cost_local_VAT_excl, + SI.cost_local_VAT_incl, SI.date_purchased, SI.date_received, - SI.cost_local_VAT_incl, - SI.cost_local_VAT_excl, SI.is_sealed, SI.date_unsealed, SI.date_expiration, @@ -722,6 +728,7 @@ END // DELIMITER ;; +/* CALL p_shop_get_many_stock_item ( 1, # a_id_user 1, # a_get_all_product_permutation @@ -750,7 +757,6 @@ CALL p_shop_get_many_stock_item ( , 0 # a_debug ); -/* DROP TABLE IF EXISTS tmp_Msg_Error; diff --git a/static/MySQL/7220_p_shop_save_stock_item.sql b/static/MySQL/7220_p_shop_save_stock_item.sql new file mode 100644 index 00000000..97195ef2 --- /dev/null +++ b/static/MySQL/7220_p_shop_save_stock_item.sql @@ -0,0 +1,646 @@ + + +-- Clear previous proc +DROP PROCEDURE IF EXISTS p_shop_save_stock_item; + +DELIMITER // +CREATE PROCEDURE p_shop_save_stock_item ( + IN a_comment VARCHAR(500) + , IN a_guid BINARY(36) + , IN a_id_user INT + , IN a_debug BIT +) +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_time_start TIMESTAMP(6); + DECLARE v_time_expire DATETIME; + + 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 + , id_type INT NULL + , code VARCHAR(50) NOT NULL + , msg VARCHAR(4000) NOT NULL + ); + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + NULL + , @errno + , @text + ; + SELECT * + FROM tmp_Msg_Error; + DROP TABLE IF EXISTS tmp_Msg_Error; + END; + + SET v_time_start := CURRENT_TIMESTAMP(6); + SET v_time_expire := DATE_ADD(v_time_start, INTERVAL 1000 YEAR); + 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 TEMPORARY TABLE IF EXISTS tmp_Stock_Item; + DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error; + + CREATE TEMPORARY TABLE tmp_Stock_Item ( + id_stock INT NOT NULL + , id_category INT NULL + , id_product INT NOT NULL + , id_permutation INT NULL + , id_pairs_variations VARCHAR(4000) NULL + , has_variations BIT NULL + , date_purchased DATETIME NOT NULL + , date_received DATETIME NULL + , id_location_storage INT NOT NULL + , id_currency_cost INT NOT NULL + , cost_local_VAT_incl FLOAT NOT NULL + , cost_local_VAT_excl FLOAT NOT NULL + , is_sealed BIT NOT NULL + , date_unsealed DATETIME NULL + , date_expiration DATETIME NOT NULL + , is_consumed BIT NOT NULL + , date_consumed DATETIME NULL + , active BIT NOT NULL + , can_view BIT NULL + , can_edit BIT NULL + , can_admin BIT NULL + , name_error VARCHAR(1000) NULL + , is_new BIT NOT NULL + ); + + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Msg_Error ( + display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT + , id_type INT NULL + , code VARCHAR(50) NOT NULL + , msg VARCHAR(4000) NOT NULL + ); + + + -- Get data from Temp table + INSERT INTO tmp_Stock_Item ( + id_stock + -- , id_category + , id_product + , id_permutation + , id_pairs_variations + , has_variations + , date_purchased + , date_received + , id_location_storage + , id_currency_cost + , cost_local_VAT_incl + , cost_local_VAT_excl + , is_sealed + , date_unsealed + , date_expiration + , is_consumed + , date_consumed + , active + # , name_error + , is_new + ) + SELECT + SI_T.id_stock + -- , IFNULL(SI_T.id_category, P.id_category) AS id_category + , IFNULL(IFNULL(SI_T.id_product, PP.id_product), 0) AS id_product + , IFNULL(IFNULL(SI_T.id_permutation, SI.id_permutation), 0) AS id_permutation + , TRIM(IFNULL(SI_T.id_pairs_variations, '')) + , CASE WHEN TRIM(IFNULL(SI_T.id_pairs_variations, '')) = '' THEN 0 ELSE 1 END AS has_variations + , IFNULL(IFNULL(SI_T.date_purchased, SI.date_purchased), v_time_start) AS date_purchased + , IFNULL(SI_T.date_received, SI.date_received) AS date_received + , IFNULL(IFNULL(SI_T.id_location_storage, SI.id_location_storage), 0) AS id_location_storage + , IFNULL(IFNULL(SI_T.id_currency_cost, SI.id_currency_cost), 0) AS id_currency_cost + , IFNULL(SI_T.cost_local_VAT_incl, SI.cost_local_VAT_incl) AS cost_local_VAT_incl + , IFNULL(SI_T.cost_local_VAT_excl, SI.cost_local_VAT_excl) AS cost_local_VAT_excl + , IFNULL(IFNULL(SI_T.is_sealed, SI.is_sealed), 1) AS is_sealed + , IFNULL(SI_T.date_unsealed, SI.date_unsealed) AS date_unsealed + , IFNULL(IFNULL(SI_T.date_expiration, SI.date_expiration), v_time_expire) AS date_expiration + , IFNULL(IFNULL(SI_T.is_consumed, SI.is_consumed), 0) AS is_consumed + , IFNULL(SI_T.date_consumed, SI.date_consumed) AS date_consumed + , IFNULL(IFNULL(SI_T.active, SI.active), 1) AS active + # , fn_shop_get_product_permutation_name(SI_T.id_permutation) + , CASE WHEN IFNULL(SI_T.id_stock, 0) < 1 THEN 1 ELSE 0 END AS is_new + FROM partsltd_prod.Shop_Stock_Item_Temp SI_T + LEFT JOIN partsltd_prod.Shop_Stock_Item SI ON SI_T.id_stock = SI.id_stock + LEFT JOIN partsltd_prod.Shop_Product_Permutation PP ON SI_T.id_permutation = PP.id_permutation + -- LEFT JOIN Shop_Product P ON PP.id_product = P.id_product + WHERE SI_T.guid = a_guid + ; + + -- Missing Permutation IDs for setting new permutation for stock item + -- With variations + UPDATE tmp_Stock_Item t_SI + INNER JOIN partsltd_prod.Shop_Product P ON t_SI.id_product = P.id_product + SET t_SI.id_permutation = IFNULL(fn_shop_get_id_product_permutation_from_variation_csv_list ( t_SI.id_product, t_SI.id_pairs_variations ), 0) + WHERE 1=1 + AND t_SI.id_permutation = 0 + AND t_SI.has_variations = 1 + ; + -- Without variations + UPDATE tmp_Stock_Item t_SI + -- INNER JOIN Shop_Product P ON t_SI.id_product = P.id_product + INNER JOIN partsltd_prod.Shop_Product_Permutation PP ON t_SI.id_product = PP.id_product + SET t_SI.id_permutation = IFNULL(PP.id_permutation, 0) + WHERE 1=1 + AND t_SI.id_permutation = 0 + AND t_SI.has_variations = 0 + ; + + -- Add stock item error names + UPDATE tmp_Stock_Item t_SI + INNER JOIN partsltd_prod.Shop_Product P ON t_SI.id_product = P.id_product + INNER JOIN partsltd_prod.Shop_Product_Category PC ON P.id_category = PC.id_category + -- INNER JOIN Shop_Product_Permutation PP ON t_SI.id_product = PP.id_product + SET t_SI.name_error = CONCAT( + PC.name, + ' - ', + P.name, + ' - ', + CASE WHEN IFNULL(t_SI.id_permutation, 0) = 0 THEN '(No permutation)' ELSE fn_shop_get_product_permutation_name ( t_SI.id_permutation ) END + ) + ; + + IF a_debug = 1 THEN + sElect * from tmp_Stock_Item; + END IF; + + -- Validation + -- Missing mandatory fields + -- id_product + IF EXISTS (SELECT * FROM tmp_Stock_Item t_SI WHERE t_SI.id_product = 0 LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following stock item(s) do not have a product: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + WHERE t_SI.id_product = 0 + ; + END IF; + -- id_permutation + IF EXISTS ( + SELECT * + FROM tmp_Stock_Item t_SI + LEFT JOIN partsltd_prod.Shop_Product_Permutation PP ON t_SI.id_permutation = PP.id_permutation + WHERE 1=1 + AND ( + t_SI.id_permutation = 0 + OR PP.active = 0 + ) + LIMIT 1 + ) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('A valid permutation could not be found for the variations selected for the following stock item(s): ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + LEFT JOIN partsltd_prod.Shop_Product_Permutation PP ON t_SI.id_permutation = PP.id_permutation + WHERE 1=1 + AND ( + t_SI.id_permutation = 0 + OR PP.active = 0 + ) + ; + END IF; + -- date_purchased + IF EXISTS (SELECT * FROM tmp_Stock_Item t_SI WHERE ISNULL(t_SI.date_purchased) LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following stock item(s) do not have an purchase date: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + WHERE ISNULL(t_SI.date_purchased) + ; + END IF; + -- id_location_storage + IF EXISTS ( + SELECT * + FROM tmp_Stock_Item t_SI + INNER JOIN partsltd_prod.Shop_Storage_Location SL + ON t_SI.id_location_storage = SL.id_location + AND SL.active = 1 + WHERE ISNULL(SL.id_location) + LIMIT 1 + ) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following stock item(s) do not have a valid storage location: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + INNER JOIN partsltd_prod.Shop_Storage_Location SL + ON t_SI.id_location_storage = SL.id_location + AND SL.active = 1 + WHERE ISNULL(SL.id_location) + ; + END IF; + -- id_currency_cost + IF EXISTS ( + SELECT * + FROM tmp_Stock_Item t_SI + INNER JOIN partsltd_prod.Shop_Currency C + ON t_SI.id_currency_cost = C.id_currency + AND C.active = 1 + WHERE ISNULL(C.id_currency) + LIMIT 1 + ) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following stock item(s) do not have a valid cost currency: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + INNER JOIN partsltd_prod.Shop_Currency C + ON t_SI.id_currency_cost = C.id_currency + AND C.active = 1 + WHERE ISNULL(C.id_currency) + ; + END IF; + -- cost_local_VAT_excl + IF EXISTS ( + SELECT * + FROM tmp_Stock_Item t_SI + WHERE 1=1 + AND ( + ISNULL(t_SI.cost_local_VAT_excl) + OR t_SI.cost_local_VAT_excl < 0 + ) + LIMIT 1 + ) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following stock item(s) do not have a valid cost excluding VAT: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + WHERE 1=1 + AND ( + ISNULL(t_SI.cost_local_VAT_excl) + OR t_SI.cost_local_VAT_excl < 0 + ) + ; + END IF; + -- cost_local_VAT_incl + IF EXISTS ( + SELECT * + FROM tmp_Stock_Item t_SI + WHERE 1=1 + AND ( + ISNULL(t_SI.cost_local_VAT_incl) + OR t_SI.cost_local_VAT_incl < 0 + ) + LIMIT 1 + ) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following stock item(s) do not have a valid cost including VAT: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + WHERE 1=1 + AND ( + ISNULL(t_SI.cost_local_VAT_incl) + OR t_SI.cost_local_VAT_incl < t_SI.cost_local_VAT_excl + ) + ; + END IF; + -- date_received + IF EXISTS (SELECT * FROM tmp_Stock_Item t_SI WHERE NOT ISNULL(t_SI.date_received) AND t_SI.date_received < t_SI.date_purchased LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following stock item(s) do not have a valid received date: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + WHERE 1=1 + AND NOT ISNULL(t_SI.date_received) + AND t_SI.date_received < t_SI.date_purchased + ; + END IF; + -- date_unsealed + IF EXISTS (SELECT * FROM tmp_Stock_Item t_SI WHERE NOT ISNULL(t_SI.date_unsealed) AND t_SI.date_unsealed < t_SI.date_purchased LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following stock item(s) do not have a valid unsealed date: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + WHERE 1=1 + AND NOT ISNULL(t_SI.date_received) + AND t_SI.date_received < t_SI.date_purchased + ; + END IF; + -- date_expiration + IF EXISTS (SELECT * FROM tmp_Stock_Item t_SI WHERE NOT ISNULL(t_SI.date_expiration) AND t_SI.date_expiration < t_SI.date_purchased LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following stock item(s) do not have a valid expiration date: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + WHERE 1=1 + AND NOT ISNULL(t_SI.date_expiration) + AND t_SI.date_expiration < t_SI.date_purchased + ; + END IF; + -- date_consumed + IF EXISTS (SELECT * FROM tmp_Stock_Item t_SI WHERE NOT ISNULL(t_SI.date_consumed) AND t_SI.date_consumed < t_SI.date_purchased LIMIT 1) THEN + INSERT INTO tmp_Msg_Error ( + id_type + , code + , msg + ) + SELECT + v_id_type_error_bad_data + , v_code_type_error_bad_data + , CONCAT('The following stock item(s) do not have a valid consumed date: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + WHERE 1=1 + AND NOT ISNULL(t_SI.date_consumed) + AND t_SI.date_consumed < t_SI.date_purchased + ; + END IF; + + -- Permissions + SET v_ids_product_permission := ( SELECT GROUP_CONCAT(t_SI.id_product SEPARATOR ',') FROM tmp_Stock_Item t_SI ); + + 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_calc_user( + a_guid + , a_id_user + , FALSE -- a_get_inactive_users + , v_id_permission_product + , v_id_access_level_edit + , v_ids_product_permission + , 0 -- a_debug + ); + + UPDATE tmp_Stock_Item t_SI + INNER JOIN Shop_Product P ON t_SI.id_product = P.id_product + INNER JOIN Shop_Calc_User_Temp UE_T + ON P.id_product = UE_T.id_product + AND UE_T.GUID = a_guid + SET + t_SI.can_view = UE_T.can_view + , t_SI.can_edit = UE_T.can_edit + , t_SI.can_admin = UE_T.can_admin + ; + + CALL p_shop_clear_calc_user( + a_guid + , 0 -- a_debug + ); + + IF EXISTS (SELECT * FROM tmp_Stock_Item t_SI WHERE IFNULL(t_SI.can_edit, 0) = 0 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 stock item(s) do not have product edit permission: ', GROUP_CONCAT(IFNULL(t_SI.name_error, 'NULL') SEPARATOR ', ')) AS msg + FROM tmp_Stock_Item t_SI + WHERE IFNULL(t_SI.can_edit, 0) = 0 + ; + END IF; + END IF; + + 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(); + + -- select * from partsltd_prod.Shop_Stock_Item + UPDATE partsltd_prod.Shop_Stock_Item SI + INNER JOIN tmp_Stock_Item t_SI + ON SI.id_stock = t_SI.id_stock + SET + SI.id_permutation = t_SI.id_permutation + , SI.date_purchased = t_SI.date_purchased + , SI.date_received = t_SI.date_received + , SI.id_location_storage = t_SI.id_location_storage + , SI.id_currency_cost = t_SI.id_currency_cost + , SI.cost_local_VAT_excl = t_SI.cost_local_VAT_excl + , SI.cost_local_VAT_incl = t_SI.cost_local_VAT_incl + , SI.is_sealed = t_SI.is_sealed + , SI.date_unsealed = t_SI.date_unsealed + , SI.date_expiration = t_SI.date_expiration + , SI.is_consumed = t_SI.is_consumed + , SI.date_consumed = t_SI.date_consumed + , SI.active = t_SI.active + , SI.id_change_set = v_id_change_set + ; + END IF; + + INSERT INTO partsltd_prod.Shop_Stock_Item ( + id_permutation + , date_purchased + , date_received + , id_location_storage + , id_currency_cost + , cost_local_VAT_excl + , cost_local_VAT_incl + , is_sealed + , date_unsealed + , date_expiration + , is_consumed + , date_consumed + , active + , created_by + , created_on + ) + SELECT + t_SI.id_permutation + , t_SI.date_purchased + , t_SI.date_received + , t_SI.id_location_storage + , t_SI.id_currency_cost + , t_SI.cost_local_VAT_excl + , t_SI.cost_local_VAT_incl + , t_SI.is_sealed + , t_SI.date_unsealed + , t_SI.date_expiration + , t_SI.is_consumed + , t_SI.date_consumed + , t_SI.active + , a_id_user AS created_by + , v_time_start AS created_on + FROM tmp_Stock_Item t_SI + WHERE + is_new = 1 + AND active = 1 + ; + + DELETE FROM partsltd_prod.Shop_Stock_Item_Temp + WHERE GUID = a_guid; + + COMMIT; + END IF; + + SELECT * FROM tmp_Msg_Error; + + DROP TEMPORARY TABLE IF EXISTS tmp_Stock_Item; + 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/7220_p_shop_save_stock_item_test.sql b/static/MySQL/7220_p_shop_save_stock_item_test.sql new file mode 100644 index 00000000..99d0834d --- /dev/null +++ b/static/MySQL/7220_p_shop_save_stock_item_test.sql @@ -0,0 +1,101 @@ + + +-- Clear previous proc +DROP PROCEDURE IF EXISTS partsltd_prod.p_shop_save_stock_item_test; + + +DELIMITER // +CREATE PROCEDURE p_shop_save_stock_item_test () +BEGIN + + DECLARE v_guid BINARY(36); + DECLARE v_time_start TIMESTAMP(6); + + SET v_time_start := CURRENT_TIMESTAMP(6); + SET v_guid := 'nips'; + + SELECT * + FROM partsltd_prod.Shop_Stock_Item + ; + SELECT * + FROM partsltd_prod.Shop_Stock_Item_Temp + ; + + START TRANSACTION; + + INSERT INTO partsltd_prod.Shop_Stock_Item_Temp ( + id_stock + -- id_category + , id_product + , id_permutation + , id_pairs_variations + -- , has_variations + , date_purchased + , date_received + , id_location_storage + , id_currency_cost + , cost_local_VAT_excl + , cost_local_VAT_incl + , is_sealed + , date_unsealed + , date_expiration + , is_consumed + , date_consumed + , active + , guid + ) + VALUES ( + -1 -- id_stock + -- 1 -- id_category + , 4 -- id_product + , NULL -- id_permutation + , NULL -- id_pairs_variations + -- , FALSE -- 0 -- has_variations + , '2025-09-05 00:00' -- date_purchased + , NULL -- date_received + , 1 -- id_location_storage + , 1 -- id_currency_cost + , 10 -- cost_local_VAT_excl + , 12 -- cost_local_VAT_incl + , 1 -- is_sealed + , NULL -- date_unsealed + , NULL -- date_expiration + , FALSE -- 0 -- is_consumed + , NULL -- date_consumed + , 1 -- active + , v_guid + ); + + COMMIT; + + SELECT * + FROM partsltd_prod.Shop_Stock_Item_Temp + WHERE GUID = v_guid + ; + + CALL partsltd_prod.p_shop_save_Stock_Item ( + 'Test save Stock_Item' -- comment + , v_guid -- guid + , 1 -- id_user + , 0 -- debug + ); + + SELECT * + FROM partsltd_prod.Shop_Stock_Item + ; + SELECT * + FROM partsltd_prod.Shop_Stock_Item_Temp + ; + + CALL partsltd_prod.p_debug_timing_reporting ( v_time_start ); +END // +DELIMITER ;; + +CALL partsltd_prod.p_shop_save_stock_item_test (); + +DELETE FROM partsltd_prod.Shop_Stock_Item_Temp; + +/* +update shop_product p set p.has_variations = 0 where id_product = 4 +DROP TABLE IF EXISTS tmp_Msg_Error; +*/ \ No newline at end of file diff --git a/static/MySQL/7313_p_get_many_user.sql b/static/MySQL/7313_p_get_many_user.sql index 8b797b4d..27b730eb 100644 --- a/static/MySQL/7313_p_get_many_user.sql +++ b/static/MySQL/7313_p_get_many_user.sql @@ -1,7 +1,5 @@ - - -- Clear previous proc DROP PROCEDURE IF EXISTS p_get_many_user; @@ -15,48 +13,81 @@ CREATE PROCEDURE p_get_many_user ( , IN a_get_first_user_only BIT , IN a_ids_user LONGTEXT , IN a_ids_user_auth0 LONGTEXT + , IN a_debug BIT ) BEGIN + DECLARE v_id_access_level_admin INT; DECLARE v_id_access_level_view INT; DECLARE v_id_permission_store_admin INT; DECLARE v_id_permission_user INT; DECLARE v_id_permission_user_admin INT; + DECLARE v_ids_permission_required VARCHAR(4000); DECLARE v_now TIMESTAMP; DECLARE v_id_minimum INT; - DECLARE v_code_error_data VARCHAR(50); - DECLARE v_id_type_error_data INT; + DECLARE v_code_error_bad_data VARCHAR(50); + DECLARE v_id_type_error_bad_data INT; DECLARE v_has_filter_user BIT; + DECLARE v_has_filter_user_auth0 BIT; DECLARE v_guid BINARY(36); + DECLARE v_rank_max INT; + DECLARE v_time_start TIMESTAMP(6); + SET v_time_start := CURRENT_TIMESTAMP(6); SET v_guid := UUID(); - SET v_id_access_level_view := (SELECT id_access_level FROM Shop_Access_Level WHERE code = 'VIEW' LIMIT 1); - SET v_id_permission_store_admin := (SELECT id_permission FROM Shop_Permission WHERE code = 'STORE_ADMIN' LIMIT 1); - SET v_id_permission_user := (SELECT id_permission FROM Shop_Permission WHERE code = 'STORE_USER' LIMIT 1); - SET v_id_permission_user_admin := (SELECT id_permission FROM Shop_Permission WHERE code = 'STORE_USER_ADMIN' LIMIT 1); - SET v_code_error_data := (SELECT code FROM Shop_Msg_Error_Type WHERE code = 'BAD_DATA' LIMIT 1); - SET v_id_type_error_data := (SELECT id_type FROM Shop_Msg_Error_Type WHERE code = v_code_error_data LIMIT 1); + SET v_id_access_level_admin := (SELECT id_access_level FROM partsltd_prod.Shop_Access_Level WHERE code = 'ADMIN' LIMIT 1); + SET v_id_access_level_view := (SELECT id_access_level FROM partsltd_prod.Shop_Access_Level WHERE code = 'VIEW' LIMIT 1); + SET v_id_permission_store_admin := (SELECT id_permission FROM partsltd_prod.Shop_Permission WHERE code = 'STORE_ADMIN' LIMIT 1); + SET v_id_permission_user := (SELECT id_permission FROM partsltd_prod.Shop_Permission WHERE code = 'STORE_USER' LIMIT 1); + SET v_id_permission_user_admin := (SELECT id_permission FROM partsltd_prod.Shop_Permission WHERE code = 'STORE_USER_ADMIN' LIMIT 1); + SET v_code_error_bad_data := (SELECT code FROM partsltd_prod.Shop_Msg_Error_Type WHERE code = 'BAD_DATA' LIMIT 1); + SET v_id_type_error_bad_data := (SELECT id_type FROM partsltd_prod.Shop_Msg_Error_Type WHERE code = v_code_error_bad_data LIMIT 1); + SET v_ids_permission_required := CONCAT(v_id_permission_user, ',', v_id_permission_user_admin, ',', v_id_permission_store_admin); + SET a_get_all_user := IFNULL(a_get_all_user, 1); + SET a_get_inactive_user := IFNULL(a_get_inactive_user, 0); + SET a_get_first_user_only := IFNULL(a_get_first_user_only, 0); SET a_ids_user := TRIM(IFNULL(a_ids_user, '')); SET a_ids_user_auth0 := TRIM(IFNULL(a_ids_user_auth0, '')); + SET a_debug := IFNULL(a_debug, 0); + + IF a_debug = 1 THEN + SELECT + a_id_user + , a_id_user_auth0 + , a_get_all_user + , a_get_inactive_user + , a_get_first_user_only + , a_ids_user + , a_ids_user_auth0 + , a_debug + ; + END IF; DROP TEMPORARY TABLE IF EXISTS tmp_User; DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error; CREATE TEMPORARY TABLE tmp_User ( - id_user INT NOT NULL, - rank_user INT NULL + id_user INT NULL + , rank_user INT NULL + , can_admin_store BIT NULL + , can_admin_user BIT NULL ); CREATE TEMPORARY TABLE tmp_Msg_Error ( display_order INT NOT NULL PRIMARY KEY AUTO_INCREMENT, - guid BINARY(36) NOT NULL, + -- guid BINARY(36) NOT NULL, id_type INT NOT NULL, code VARCHAR(50) NOT NULL, msg VARCHAR(4000) NOT NULL ); + CREATE TEMPORARY TABLE IF NOT EXISTS tmp_Split ( + substring VARCHAR(4000) NOT NULL + , as_int INT NULL + ); + IF ISNULL(a_id_user) AND NOT ISNULL(a_id_user_auth0) THEN - SET a_id_user := (SELECT U.id_user FROM Shop_User U WHERE U.id_user_auth0 LIKE CONCAT('%', a_id_user_auth0, '%') LIMIT 1); + SET a_id_user := (SELECT U.id_user FROM partsltd_prod.Shop_User U WHERE U.id_user_auth0 = a_id_user_auth0 LIMIT 1); -- LIKE CONCAT('%', a_id_user_auth0, '%') LIMIT 1); END IF; IF ISNULL(a_id_user) THEN @@ -68,150 +99,352 @@ BEGIN ) VALUES ( v_guid, - v_id_type_error_data, - v_code_error_data, + v_id_type_error_bad_data, + v_code_error_bad_data, CONCAT('User ID required for authorisation.') ) ; END IF; - SET v_has_filter_user := CASE WHEN a_ids_user = '' AND a_ids_user_auth0= '' THEN 0 ELSE 1 END; + SET v_has_filter_user := CASE WHEN a_ids_user = '' THEN 0 ELSE 1 END; + SET v_has_filter_user_auth0 := CASE WHEN a_ids_user_auth0 = '' THEN 0 ELSE 1 END; - IF v_has_filter_user THEN - INSERT INTO tmp_User ( - id_user - -- , active - , rank_user - ) - SELECT - DISTINCT U.id_user - -- S.active - , RANK() OVER (ORDER BY id_user ASC) AS rank_user - FROM Shop_User U - WHERE 1=1 - AND ( - FIND_IN_SET(U.id_user, a_ids_user) > 0 - OR FIND_IN_SET(U.id_user_auth0, a_ids_user_auth0) > 0 - ) - AND ( - a_get_inactive_user - OR U.active - ) - /*Shop_Calc_User_Temp UE_T - WHERE 1=1 - AND UE_T.guid = v_guid - AND UE_T.active = 1 - */ + IF a_debug = 1 THEN + SELECT + v_has_filter_user + , v_has_filter_user_auth0 ; - - IF a_get_first_user_only THEN - DELETE t_U - FROM tmp_User t_U - WHERE t_U.rank_user > 1 - ; - END IF; END IF; - -- Permissions - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN - -- SELECT v_guid, a_id_user, false, v_id_permission_product, v_id_access_level_view, v_ids_permutation_permission; - -- select * from Shop_Calc_User_Temp; + -- User IDs + IF (NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) AND v_has_filter_user = 1) THEN + CALL partsltd_prod.p_split(v_guid, a_ids_user, ',', FALSE); - CALL p_shop_calc_user( - v_guid, -- guid - a_id_user, -- ids_user - FALSE, -- get_inactive_user - CONCAT(v_id_permission_user, ',', v_id_permission_user_admin, ',', v_id_permission_store_admin), -- ids_permission - v_id_access_level_view, -- ids_access_level - '' -- ids_product + DELETE FROM tmp_Split; + + INSERT INTO tmp_Split ( + substring + , as_int + ) + SELECT + substring + , CONVERT(substring, DECIMAL(10,0)) AS as_int + FROM partsltd_prod.Split_Temp + WHERE 1=1 + AND GUID = v_guid + AND NOT ISNULL(substring) + AND substring != '' + ; + + CALL partsltd_prod.p_clear_split_temp( v_guid ); + END IF; + + IF (NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) AND v_has_filter_user = 1) THEN + IF EXISTS ( + SELECT * + FROM tmp_Split t_S + LEFT JOIN partsltd_prod.Shop_User U ON t_S.as_int = U.id_user + WHERE + ISNULL(t_S.as_int) + OR ISNULL(U.id_user) + ) THEN + INSERT INTO tmp_Msg_Error ( + -- guid, + id_type, + code, + msg + ) + SELECT + -- v_guid, + v_id_type_error_bad_data, + v_code_error_bad_data, + CONCAT('Invalid or inactive User IDs: ', IFNULL(GROUP_CONCAT(t_S.substring SEPARATOR ', '), 'NULL')) + FROM tmp_Split t_S + LEFT JOIN partsltd_prod.Shop_User U ON t_S.as_int = U.id_user + WHERE + ISNULL(t_S.as_int) + OR ISNULL(U.id_user) + ; + ELSE + INSERT INTO tmp_User ( + id_user + , rank_user + ) + SELECT + U.id_user + , RANK() OVER (ORDER BY U.id_user DESC) AS rank_user + FROM tmp_Split t_S + RIGHT JOIN partsltd_prod.Shop_User U ON t_S.as_int = U.id_user + WHERE + ( + a_get_all_user = 1 + OR ( + v_has_filter_user = 1 + AND NOT ISNULL(t_S.as_int) + ) + ) + AND ( + a_get_inactive_user = 1 + OR U.active = 1 + ) + ; + END IF; + END IF; + + -- Auth0 User IDs + IF (NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) AND v_has_filter_user_auth0 = 1) THEN + CALL partsltd_prod.p_split(v_guid, a_ids_user_auth0, ',', FALSE); + + DELETE FROM tmp_Split; + + INSERT INTO tmp_Split ( + substring + ) + SELECT + substring + FROM partsltd_prod.Split_Temp + WHERE 1=1 + AND GUID = v_guid + AND NOT ISNULL(substring) + AND substring != '' + ; + + CALL partsltd_prod.p_clear_split_temp( v_guid ); + END IF; + + IF (NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) AND v_has_filter_user_auth0 = 1) THEN + IF EXISTS ( + SELECT * + FROM tmp_Split t_S + LEFT JOIN partsltd_prod.Shop_User U ON t_S.substring = U.id_user_auth0 + WHERE + ISNULL(t_S.substring) + OR ISNULL(U.id_user_auth0) + ) THEN + INSERT INTO tmp_Msg_Error ( + -- guid, + id_type, + code, + msg + ) + SELECT + -- v_guid, + v_id_type_error_bad_data, + v_code_error_bad_data, + CONCAT('Invalid or inactive Auth0 User IDs: ', IFNULL(GROUP_CONCAT(t_S.substring SEPARATOR ', '), 'NULL')) + FROM tmp_Split t_S + LEFT JOIN partsltd_prod.Shop_User U ON t_S.substring = U.id_user_auth0 + WHERE + ISNULL(t_S.substring) + OR ISNULL(U.id_user_auth0) + ; + ELSE + SET v_rank_max := IFNULL((SELECT rank_user FROM tmp_User ORDER BY rank_user DESC LIMIT 1), 0); + + INSERT INTO tmp_User ( + id_user + , rank_user + ) + SELECT + U.id_user + , v_rank_max + (RANK() OVER (ORDER BY U.id_user DESC)) AS rank_user + FROM tmp_Split t_S + RIGHT JOIN partsltd_prod.Shop_User U ON t_S.substring = U.id_user_auth0 + WHERE + ( + a_get_all_user = 1 + OR ( + v_has_filter_user_auth0 = 1 + AND NOT ISNULL(t_S.substring) + ) + ) + AND ( + a_get_inactive_user = 1 + OR U.active = 1 + ) + ; + END IF; + END IF; + + IF a_debug = 1 THEN + SELECT * FROM tmp_User; + END IF; + + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN + IF a_get_first_user_only THEN + DELETE t_U + FROM tmp_User t_U + WHERE t_U.rank_user > 1 + ; + END IF; + END IF; + + IF a_debug = 1 THEN + SELECT * FROM tmp_User; + END IF; + + -- Can admin store + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN + IF a_debug = 1 THEN + SELECT + v_guid -- guid + , a_id_user -- ids_user + , FALSE -- get_inactive_user + , v_id_permission_store_admin -- ids_permission + , v_id_access_level_admin -- ids_access_level + , '' -- ids_product + , 0 -- a_debug + ; + SELECT * FROM partsltd_prod.Shop_Calc_User_Temp; + END IF; + + CALL partsltd_prod.p_shop_calc_user( + v_guid -- guid + , a_id_user -- ids_user + , FALSE -- get_inactive_user + , v_id_permission_store_admin -- ids_permission + , v_id_access_level_admin -- ids_access_level + , '' -- ids_product + , 0 -- a_debug ); - -- select * from Shop_Calc_User_Temp; + IF a_debug = 1 THEN + SELECT * FROM partsltd_prod.Shop_Calc_User_Temp WHERE GUID = v_guid; + END IF; + + UPDATE tmp_User t_U + INNER JOIN partsltd_prod.Shop_Calc_User_Temp CUT + ON CUT.GUID = v_guid + AND t_U.id_user = CUT.id_user + SET t_U.can_admin_store = CUT.can_admin + ; + + CALL partsltd_prod.p_shop_clear_calc_user( v_guid, FALSE ); + END IF; + + -- Can admin user + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN + IF a_debug = 1 THEN + SELECT + v_guid -- guid + , a_id_user -- ids_user + , FALSE -- get_inactive_user + , v_id_permission_user_admin -- ids_permission + , v_id_access_level_admin -- ids_access_level + , '' -- ids_product + , 0 -- a_debug + ; + SELECT * FROM partsltd_prod.Shop_Calc_User_Temp; + END IF; + + CALL partsltd_prod.p_shop_calc_user( + v_guid -- guid + , a_id_user -- ids_user + , FALSE -- get_inactive_user + , v_id_permission_user_admin -- ids_permission + , v_id_access_level_admin -- ids_access_level + , '' -- ids_product + , 0 -- a_debug + ); + + IF a_debug = 1 THEN + SELECT * FROM partsltd_prod.Shop_Calc_User_Temp WHERE GUID = v_guid; + END IF; + + UPDATE tmp_User t_U + INNER JOIN partsltd_prod.Shop_Calc_User_Temp CUT + ON CUT.GUID = v_guid + AND t_U.id_user = CUT.id_user + SET t_U.can_admin_user = CUT.can_admin + ; + + CALL partsltd_prod.p_shop_clear_calc_user( v_guid, FALSE ); + END IF; + + -- Permissions + IF NOT EXISTS (SELECT * FROM tmp_Msg_Error LIMIT 1) THEN + IF a_debug = 1 THEN + SELECT + v_guid -- guid + , a_id_user -- ids_user + , FALSE -- get_inactive_user + , v_ids_permission_required -- ids_permission + , v_id_access_level_view -- ids_access_level + , '' -- ids_product + , 0 -- a_debug + ; + SELECT * FROM partsltd_prod.Shop_Calc_User_Temp; + END IF; + + CALL partsltd_prod.p_shop_calc_user( + v_guid -- guid + , a_id_user -- ids_user + , FALSE -- get_inactive_user + , v_ids_permission_required -- ids_permission + , v_id_access_level_view -- ids_access_level + , '' -- ids_product + , 0 -- a_debug + ); + + IF a_debug = 1 THEN + SELECT * FROM partsltd_prod.Shop_Calc_User_Temp WHERE GUID = v_guid; + END IF; IF NOT EXISTS ( SELECT can_view - FROM Shop_Calc_User_Temp UE_T + FROM partsltd_prod.Shop_Calc_User_Temp CUT WHERE 1=1 - AND UE_T.GUID = v_guid - AND UE_T.id_permission_required = v_id_permission_user + AND CUT.GUID = v_guid + AND can_view = 1 + -- AND FIND_IN_SET(v_ids_permission_required, CUT.id_permission_required) > 0 ) THEN INSERT INTO tmp_Msg_Error ( - guid, id_type, code, msg ) VALUES ( - v_guid, - v_id_type_error_data, - v_code_error_data, - CONCAT('You do not have view permissions for ', (SELECT name FROM Shop_Permission WHERE id_permission = v_id_permission_user LIMIT 1)) + v_id_type_error_bad_data, + v_code_error_bad_data, + -- CONCAT('You do not have view permissions for ', (SELECT name FROM partsltd_prod.Shop_Permission WHERE id_permission = v_id_permission_user LIMIT 1)) + -- CONCAT('You do not have view permissions for ', (SELECT GROUP_CONCAT(name SEPARATOR ', ') FROM partsltd_prod.Shop_Permission WHERE FIND_IN_SET(v_id_permission_user, id_permission) > 0)) + CONCAT('You do not have view permissions for ', (SELECT name FROM partsltd_prod.Shop_Permission P INNER JOIN partsltd_prod.Shop_Calc_User_Temp CUT ON P.id_permission = CUT.id_permission_required WHERE GUID = v_guid AND IFNULL(can_view, 0) = 0 LIMIT 1)) -- WHERE IFNULL(CUT.can_view, 0) = 0 ) ; + ELSE + -- INSERT INTO + SET a_debug := a_debug; END IF; + + CALL partsltd_prod.p_shop_clear_calc_user( v_guid, FALSE ); END IF; -- Returns - /* NULL record required for flask sql_alchemy to detect result set - IF EXISTS (SELECT * FROM tmp_Msg_Error WHERE GUID = v_guid) THEN + /* NULL record required for flask sql_alchemy to detect result set */ + IF EXISTS (SELECT * FROM tmp_Msg_Error) THEN DELETE FROM tmp_User; + INSERT INTO tmp_User ( id_user ) + VALUES ( NULL ); END IF; - */ - IF NOT EXISTS (SELECT * FROM tmp_Msg_Error WHERE GUID = v_guid) THEN - SELECT - U.id_user - , U.id_user_auth0 - , U.firstname - , U.surname - , U.email - , U.is_email_verified - , U.id_currency_default - , U.id_region_default - , U.is_included_VAT_default - , U.is_super_user - , UE_T_STORE.can_admin_store AS can_admin_store - , UE_T_USER.can_admin_user AS can_admin_user - FROM tmp_User t_U - INNER JOIN Shop_User U ON t_U.id_user = U.id_user - INNER JOIN ( - SELECT - id_user - , id_permission_required - , can_admin AS can_admin_store - FROM Shop_Calc_User_Temp UE_T_STORE - WHERE 1=1 - AND UE_T_STORE.guid = v_guid - AND UE_T_STORE.id_permission_required = v_id_permission_store_admin - ) UE_T_STORE ON t_U.id_user = UE_T_STORE.id_user - INNER JOIN ( - SELECT - id_user - , id_permission_required - , can_admin AS can_admin_user - FROM Shop_Calc_User_Temp UE_T_USER - WHERE 1=1 - AND UE_T_USER.guid = v_guid - AND UE_T_USER.id_permission_required = v_id_permission_user_admin - ) UE_T_USER ON t_U.id_user = UE_T_USER.id_user - ; - ELSE - SELECT - NULL AS id_user - , NULL AS id_user_auth0 - , NULL AS firstname - , NULL AS surname - , NULL AS email - , NULL AS is_email_verified - , NULL AS id_currency_default - , NULL AS id_region_default - , NULL AS is_included_VAT_default - , NULL AS is_super_user - , NULL AS can_admin_store - , NULL AS can_admin_user - ; - END IF; + + SELECT + U.id_user + , U.id_user_auth0 + , U.firstname + , U.surname + , U.email + , U.is_email_verified + , U.id_currency_default + , U.id_region_default + , U.is_included_VAT_default + , U.is_super_user + , t_U.can_admin_store + , t_U.can_admin_user + FROM tmp_User t_U + INNER JOIN partsltd_prod.Shop_User U ON t_U.id_user = U.id_user + ; # Errors SELECT @@ -221,27 +454,33 @@ BEGIN MET.name, MET.description FROM tmp_Msg_Error t_ME - INNER JOIN Shop_Msg_Error_Type MET + INNER JOIN partsltd_prod.Shop_Msg_Error_Type MET ON t_ME.id_type = MET.id_type - WHERE guid = v_guid ; + IF a_debug = 1 THEN + SELECT * FROM tmp_User; + END IF; + -- Clean up DROP TEMPORARY TABLE IF EXISTS tmp_User; DROP TEMPORARY TABLE IF EXISTS tmp_Msg_Error; /* - DELETE FROM Shop_Calc_User_Temp + DELETE FROM partsltd_prod.Shop_Calc_User_Temp WHERE GUID = v_guid; */ - CALL p_shop_clear_calc_user(v_guid); + + IF a_debug = 1 THEN + CALL partsltd_prod.p_debug_timing_reporting ( v_time_start ); + END IF; END // DELIMITER ;; - /* + CALL p_get_many_user ( NULL # a_id_user , 'auth0|6582b95c895d09a70ba10fef' # a_id_user_auth0 @@ -249,13 +488,15 @@ CALL p_get_many_user ( , 0 # a_get_inactive_user , 0 # a_get_first_user_only , NULL # a_ids_user - , 'auth0|6582b95c895d09a70ba10fef' # a_ids_user_auth0 # ' -- + , 'auth0|6582b95c895d09a70ba10fef' # a_ids_user_auth0 + , 1 -- a_debug ); -select * from Shop_Calc_User_Temp; -delete from Shop_Calc_User_Temp; + +select * FROM partsltd_prod.Shop_Calc_User_Temp; +delete FROM partsltd_prod.Shop_Calc_User_Temp; SELECT * -FROM SHOP_USER; +FROM partsltd_prod.Shop_USER; CALL p_get_many_user( NULL -- :a_id_user, diff --git a/static/MySQL/9000_populate.sql b/static/MySQL/9000_populate.sql index c4e1836c..7953450c 100644 --- a/static/MySQL/9000_populate.sql +++ b/static/MySQL/9000_populate.sql @@ -86,6 +86,14 @@ VALUES ; */ +# Addresses +INSERT INTO Shop_Address ( + id_region, postcode, address_line_1, address_line_2, city, county +) +VALUES ( + 1, 'CV22 6DN', '53 Alfred Green Close', '', 'Rugby', 'Warwickshire' +); + # Plants INSERT INTO Shop_Plant ( code, name, id_address, id_user_manager @@ -552,7 +560,10 @@ VALUES (4, 'SALES_AND_PURCHASING', 'Sales and Purchasing'), (5, 'MANUFACTURING', 'Manufacturing') ; - +/* +select * from Shop_Permission +select * from Shop_Role_Permission_Link +*/ # Permissions INSERT INTO Shop_Permission ( display_order, code, name, id_permission_group, id_access_level_required @@ -627,8 +638,8 @@ VALUES (1, 1) ; -# Addresses -INSERT INTO Shop_Address ( +# User Addresses +INSERT INTO Shop_User_Address ( id_user, id_region, name_full, phone_number, postcode, address_line_1, address_line_2, city, county ) SELECT U.id_user, 1, CONCAT(U.firstname, ' ', U.surname), '07375 571430', 'CV22 6DN', '53 Alfred Green Close', '', 'Rugby', 'Warwickshire' @@ -697,7 +708,7 @@ INSERT INTO Shop_Supplier ( , id_currency ) VALUES - ('Malt Kiln Farm Shop', NULL, NULL, 2, '01788 832640', NULL, 'farmshop@maltkilnfarmshop.co.uk', 'https://www.maltkilnfarmshop.co.uk/', 1) + ('Malt Kiln Farm Shop', NULL, NULL, 1, '01788 832640', NULL, 'farmshop@maltkilnfarmshop.co.uk', 'https://www.maltkilnfarmshop.co.uk/', 1) ; /* diff --git a/static/MySQL/9010_anal.sql b/static/MySQL/9010_anal.sql index d9277844..65229fa0 100644 --- a/static/MySQL/9010_anal.sql +++ b/static/MySQL/9010_anal.sql @@ -1,6 +1,6 @@ - +/* SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES @@ -24,4 +24,7 @@ FROM WHERE TABLE_SCHEMA = 'PARTS' -- AND TABLE_NAME = 'your_table_name' -; \ No newline at end of file +; + +*/ + diff --git a/static/MySQL/temp.txt b/static/MySQL/temp.txt index b26ac673..d9b0aa72 100644 --- a/static/MySQL/temp.txt +++ b/static/MySQL/temp.txt @@ -2,6 +2,7 @@ 1000_tbl_Shop_Product_Change_Set.sql 1000_tbl_Split_Temp.sql 1001_tbl_Shop_User_Change_Set.sql +1001_tbl_Split_Key_Value_Pair_Csv_Temp.sql 1002_tbl_Shop_Sales_And_Purchasing_Change_Set.sql 1003_tbl_Shop_Access_Level.sql 1004_tbl_Shop_Access_Level_Audit.sql @@ -18,7 +19,9 @@ 1103_tbl_Shop_Region_Branch.sql 1104_tbl_Shop_Region_Branch_Audit.sql 1105_tbl_Shop_Region_Branch_Temp.sql +1106_tbl_Shop_Address.sql 1106_tbl_Shop_Plant.sql +1107_tbl_Shop_Address_Audit.sql 1107_tbl_Shop_Plant_Audit.sql 1108_tbl_Shop_Plant_Temp.sql 1109_tbl_Shop_Storage_Location.sql @@ -67,9 +70,7 @@ 1233_tbl_Shop_Discount.sql 1234_tbl_Shop_Discount_Audit.sql 1236_tbl_Shop_Discount_Region_Currency_Link.sql -1236_tbl_Shop_Product_Currency_Region_Link.sql 1237_tbl_Shop_Discount_Region_Currency_Link_Audit.sql -1237_tbl_Shop_Product_Currency_Region_Link_Audit.sql 1300_tbl_Shop_Permission_Group.sql 1301_tbl_Shop_Permission_Group_Audit.sql 1303_tbl_Shop_Permission.sql @@ -82,8 +83,8 @@ 1313_tbl_Shop_User_Audit.sql 1315_tbl_Shop_User_Role_Link.sql 1316_tbl_Shop_User_Role_Link_Audit.sql -1318_tbl_Shop_Address.sql -1319_tbl_Shop_Address_Audit.sql +1318_tbl_Shop_User_Address.sql +1319_tbl_Shop_User_Address_Audit.sql 1321_tbl_Shop_User_Basket.sql 1322_tbl_Shop_User_Basket_Audit.sql 1397_tbl_Shop_Order_Status.sql @@ -118,6 +119,7 @@ 3014_tri_Shop_Image_Type.sql 3100_tri_Shop_Region.sql 3103_tri_Shop_Region_Branch.sql +3106_tri_Shop_Address.sql 3109_tri_Shop_Storage_Location.sql 3115_tri_Shop_Currency.sql 3118_tri_Shop_Tax_Or_Surcharge.sql @@ -140,7 +142,7 @@ 3309_tri_Shop_Role_Permission_Link.sql 3312_tri_Shop_User.sql 3315_tri_Shop_User_Role_Link.sql -3318_tri_Shop_Address.sql +3318_tri_Shop_User_Address.sql 3321_tri_Shop_User_Basket.sql 3324_tri_Shop_User_Order_Status.sql 3400_tri_Shop_Supplier.sql @@ -157,24 +159,31 @@ 6000_p_split.sql 6001_p_clear_split_temp.sql 6001_p_validate_guid.sql +6003_p_split_key_value_pair_csv.sql +6004_p_clear_split_key_value_pair_csv_temp.sql 6206_fn_shop_get_product_permutation_name.sql 6500_p_shop_calc_user.sql 6501_p_shop_clear_calc_user.sql 7003_p_shop_get_many_access_level.sql 7101_p_shop_get_many_region.sql +7106_p_shop_get_many_plant.sql +7109_p_shop_get_many_storage_location.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 7202_p_shop_clear_calc_product_permutation.sql 7203_p_shop_save_product.sql +7203_p_shop_save_product_test.sql 7204_p_shop_calc_product_permutation.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_fn_shop_get_id_product_permutation_from_variation_csv_list.sql 7210_p_shop_get_many_product_variation.sql 7219_p_shop_get_many_stock_item.sql +7220_p_shop_save_stock_item.sql +7220_p_shop_save_stock_item_test.sql 7221_p_get_many_shop_product_price_and_discount_and_delivery_option.sql 7223_p_shop_get_many_stripe_price_new.sql 7312_p_shop_save_user.sql @@ -193,4 +202,3 @@ 9000_populate.sql 9001_view.sql 9010_anal.sql -DEPRECATED diff --git a/static/css/components/table.css b/static/css/components/table.css index 89830f09..73544f5d 100644 --- a/static/css/components/table.css +++ b/static/css/components/table.css @@ -33,3 +33,15 @@ tr { visibility: hidden; } */ + +table textarea { + width: 95% !important; +} + +table select { + width: 100% !important; +} + +table input { + width: 90% !important; +} \ No newline at end of file diff --git a/static/css/pages/store/product_permutations.css b/static/css/pages/store/product_permutations.css index 8a5e45a4..7c345c82 100644 --- a/static/css/pages/store/product_permutations.css +++ b/static/css/pages/store/product_permutations.css @@ -107,17 +107,6 @@ min-width: 6vh; } -textarea { - width: 95% !important; -} - -select { - width: 100% !important; -} - -input { - width: 90% !important; -} td > input, td > select, td > textarea, .container-input > input, .container-input > select, .container-input > textarea { border: 2px solid var(--c_purple); diff --git a/static/css/pages/store/stock_items.css b/static/css/pages/store/stock_items.css index 295792a0..3f980784 100644 --- a/static/css/pages/store/stock_items.css +++ b/static/css/pages/store/stock_items.css @@ -4,36 +4,82 @@ th, td { } - -.category { - width: 12%; +#tableMain { + max-width: 90vw; } -.product { - width: 12%; +#tableMain thead tr th.category, #tableMain tbody tr td.category { + width: 8vh; + min-width: 8vh; } -.variations { - width: 12%; -} -.currency { - width: 12%; -} -.cost-local-VAT-incl { - width: 10%; -} -.date-puchased, .date-received, .date-unsealed, .date-expiration, .date-consumed { - width: 6%; -} -.storage-location { - width: 12%; -} -.active { - width: 5%; +#tableMain thead tr th.product, #tableMain tbody tr td.product, +#tableMain thead tr th.storage_location, #tableMain tbody tr td.storage_location { + width: 10vh; + min-width: 10vh; } -.row-new { - visibility: hidden; +#tableMain thead tr th.product_variations.collapsed, #tableMain tbody tr td.product_variations.collapsed { + width: 10vh; + min-width: 10vh; + display: table-cell !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; } -textarea, select, input { - width: 100% !important; +#tableMain thead tr th.id_currency_cost.collapsed, #tableMain tbody tr td.id_currency_cost.collapsed { + width: 9vh; + min-width: 9vh; } +#tableMain thead tr th.id_currency_cost, #tableMain tbody tr td.id_currency_cost { + width: 11vh; + min-width: 11vh; +} + +#tableMain thead tr th.cost_local_vat_excl, #tableMain tbody tr td.cost_local_vat_excl, +#tableMain thead tr th.cost_local_vat_incl, #tableMain tbody tr td.cost_local_vat_incl { + width: 9vh; + min-width: 9vh; +} + +#tableMain thead tr th.storage-location.collapsed, #tableMain tbody tr td.storage-location.collapsed { + width: 10vh; + min-width: 10vh; + display: table-cell !important; +} +#tableMain thead tr th.storage-location, #tableMain tbody tr td.storage-location { + width: 20vh; + min-width: 20vh; +} +#tableMain tbody tr td.storage-location table thead tr th, #tableMain tbody tr td.storage-location table tbody tr td { + width: 8vh; + min-width: 8vh; +} +#tableMain tbody tr td.storage-location table thead tr th:last-of-type, #tableMain tbody tr td.storage-location table tbody tr td:last-of-type { + width: 4vh; + min-width: 4vh; +} + +#tableMain thead tr th.active, #tableMain tbody tr td.active, +#tableMain thead tr th.is_sealed, #tableMain tbody tr td.is_sealed, +#tableMain thead tr th.is_consumed, #tableMain tbody tr td.is_consumed { + width: 6vh; + min-width: 6vh; +} + +#tableMain thead tr th.date_purchased, #tableMain tbody tr td.date_purchased, +#tableMain thead tr th.date_received, #tableMain tbody tr td.date_received, +#tableMain thead tr th.date_unsealed, #tableMain tbody tr td.date_unsealed, +#tableMain thead tr th.date_expiration, #tableMain tbody tr td.date_expiration, +#tableMain thead tr th.date_consumed, #tableMain tbody tr td.date_consumed { + width: 17vh; + min-width: 17vh; +} \ No newline at end of file diff --git a/static/dist/css/main.bundle.css b/static/dist/css/main.bundle.css index c229ab4c..05b86a66 100644 --- a/static/dist/css/main.bundle.css +++ b/static/dist/css/main.bundle.css @@ -644,6 +644,17 @@ tr { } */ +table textarea { + width: 95% !important; +} + +table select { + width: 100% !important; +} + +table input { + width: 90% !important; +} button.collapsed { diff --git a/static/dist/css/store_product_permutations.bundle.css b/static/dist/css/store_product_permutations.bundle.css index f5aac066..ff0283be 100644 --- a/static/dist/css/store_product_permutations.bundle.css +++ b/static/dist/css/store_product_permutations.bundle.css @@ -160,17 +160,6 @@ min-width: 6vh; } -textarea { - width: 95% !important; -} - -select { - width: 100% !important; -} - -input { - width: 90% !important; -} td > input, td > select, td > textarea, .container-input > input, .container-input > select, .container-input > textarea { border: 2px solid var(--c_purple); diff --git a/static/dist/css/store_stock_items.bundle.css b/static/dist/css/store_stock_items.bundle.css index 99a06b67..8ca65b65 100644 --- a/static/dist/css/store_stock_items.bundle.css +++ b/static/dist/css/store_stock_items.bundle.css @@ -57,37 +57,82 @@ th, td { } - -.category { - width: 12%; +#tableMain { + max-width: 90vw; } -.product { - width: 12%; +#tableMain thead tr th.category, #tableMain tbody tr td.category { + width: 8vh; + min-width: 8vh; } -.variations { - width: 12%; -} -.currency { - width: 12%; -} -.cost-local-VAT-incl { - width: 10%; -} -.date-puchased, .date-received, .date-unsealed, .date-expiration, .date-consumed { - width: 6%; -} -.storage-location { - width: 12%; -} -.active { - width: 5%; +#tableMain thead tr th.product, #tableMain tbody tr td.product, +#tableMain thead tr th.storage_location, #tableMain tbody tr td.storage_location { + width: 10vh; + min-width: 10vh; } -.row-new { - visibility: hidden; +#tableMain thead tr th.product_variations.collapsed, #tableMain tbody tr td.product_variations.collapsed { + width: 10vh; + min-width: 10vh; + display: table-cell !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; } -textarea, select, input { - width: 100% !important; +#tableMain thead tr th.id_currency_cost.collapsed, #tableMain tbody tr td.id_currency_cost.collapsed { + width: 9vh; + min-width: 9vh; +} +#tableMain thead tr th.id_currency_cost, #tableMain tbody tr td.id_currency_cost { + width: 11vh; + min-width: 11vh; } +#tableMain thead tr th.cost_local_vat_excl, #tableMain tbody tr td.cost_local_vat_excl, +#tableMain thead tr th.cost_local_vat_incl, #tableMain tbody tr td.cost_local_vat_incl { + width: 9vh; + min-width: 9vh; +} + +#tableMain thead tr th.storage-location.collapsed, #tableMain tbody tr td.storage-location.collapsed { + width: 10vh; + min-width: 10vh; + display: table-cell !important; +} +#tableMain thead tr th.storage-location, #tableMain tbody tr td.storage-location { + width: 20vh; + min-width: 20vh; +} +#tableMain tbody tr td.storage-location table thead tr th, #tableMain tbody tr td.storage-location table tbody tr td { + width: 8vh; + min-width: 8vh; +} +#tableMain tbody tr td.storage-location table thead tr th:last-of-type, #tableMain tbody tr td.storage-location table tbody tr td:last-of-type { + width: 4vh; + min-width: 4vh; +} + +#tableMain thead tr th.active, #tableMain tbody tr td.active, +#tableMain thead tr th.is_sealed, #tableMain tbody tr td.is_sealed, +#tableMain thead tr th.is_consumed, #tableMain tbody tr td.is_consumed { + width: 6vh; + min-width: 6vh; +} + +#tableMain thead tr th.date_purchased, #tableMain tbody tr td.date_purchased, +#tableMain thead tr th.date_received, #tableMain tbody tr td.date_received, +#tableMain thead tr th.date_unsealed, #tableMain tbody tr td.date_unsealed, +#tableMain thead tr th.date_expiration, #tableMain tbody tr td.date_expiration, +#tableMain thead tr th.date_consumed, #tableMain tbody tr td.date_consumed { + width: 17vh; + min-width: 17vh; +} diff --git a/static/dist/js/main.bundle.js b/static/dist/js/main.bundle.js index fe0503a7..b6ca1f58 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],u=a.completion;if("root"===a.tryLoc)return o("end");if(a.tryLoc<=this.prev){var l=n.call(a,"catchLoc"),c=n.call(a,"finallyLoc");if(l&&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),F(r),v}},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;F(r)}return o}}throw Error("illegal catch attempt")},delegateYield:function(t,r,n){return this.delegate={iterator:q(t),resultName:r,nextLoc:n},"next"===this.method&&(this.arg=e),v}},t}function b(e,t,r,n,o,i,a){try{var u=e[i](a),l=u.value}catch(e){return void r(e)}u.done?t(l):Promise.resolve(l).then(n,o)}function k(e){return function(){var t=this,r=arguments;return new Promise((function(n,o){var i=e.apply(t,r);function a(e){b(i,n,o,a,u,"next",e)}function u(e){b(i,n,o,a,u,"throw",e)}a(void 0)}))}}function P(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),u={method:n,headers:{"Content-Type":"application/json","X-CSRFToken":e.getCsrfToken()}},!o||"POST"!==n&&"PUT"!==n&&"PATCH"!==n||(u.body=JSON.stringify(o)),console.log("API request:",n,a,o),t.prev=7,t.next=10,fetch(a,u);case 10:if((l=t.sent).ok){t.next=13;break}throw new Error("HTTP error! status: ".concat(l.status));case 13:return t.next=15,l.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 d.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:(p=k(m().mark((function t(){var r;return m().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 p.apply(this,arguments)})},{key:"getCategories",value:(y=k(m().mark((function t(){return m().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 y.apply(this,arguments)})},{key:"getCategoriesByFilters",value:(f=k(m().mark((function t(r){return m().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 f.apply(this,arguments)})},{key:"saveCategories",value:(s=k(m().mark((function t(r,n,o){var i;return m().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return(i={})[flagFormFilters]=l.convertForm2JSON(n),i[flagProductCategory]=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 s.apply(this,arguments)})},{key:"getProducts",value:(c=k(m().mark((function t(){return m().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,e.request(hashGetStoreProduct);case 2:return t.abrupt("return",t.sent);case 3:case"end":return t.stop()}}),t)}))),function(){return c.apply(this,arguments)})},{key:"getProductsByFilters",value:(u=k(m().mark((function t(r){return m().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:e.goToHash(hashPageStoreProducts,r);case 1:case"end":return t.stop()}}),t)}))),function(e){return u.apply(this,arguments)})},{key:"saveProducts",value:(a=k(m().mark((function t(r,n,o){var i;return m().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return(i={})[flagFormFilters]=l.convertForm2JSON(n),i[flagProduct]=r,i[flagComment]=o,t.next=6,e.request(hashSaveStoreProduct,"POST",i);case 6:return t.abrupt("return",t.sent);case 7:case"end":return t.stop()}}),t)}))),function(e,t,r){return a.apply(this,arguments)})},{key:"getProductPermutations",value:(i=k(m().mark((function t(){return m().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,e.request(hashGetStoreProductPermutation);case 2:return t.abrupt("return",t.sent);case 3:case"end":return t.stop()}}),t)}))),function(){return i.apply(this,arguments)})},{key:"getProductPermutationsByFilters",value:(o=k(m().mark((function t(r){return m().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:e.goToHash(hashPageStoreProductPermutations,r);case 1:case"end":return t.stop()}}),t)}))),function(e){return o.apply(this,arguments)})},{key:"saveProductPermutations",value:(n=k(m().mark((function t(r,n,o){var i;return m().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return(i={})[flagFormFilters]=l.convertForm2JSON(n),i[flagProductPermutation]=r,i[flagComment]=o,t.next=6,e.request(hashSaveStoreProductPermutation,"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&&P(t,r),Object.defineProperty(t,"prototype",{writable:!1}),t;var t,r,n,o,i,a,u,c,s,f,y,p,d}();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;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]=getElementValueCurrent(r.querySelector("#"+keyInfoIdentical)),n)t==idOverlayInfoBilling&&e[keyForm][keyInfoIdentical]?e[keyForm][n[o]]=getElementValueCurrent((void 0).querySelector("#"+n[o])):e[keyForm][n[o]]=getElementValueCurrent(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),y.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(){y.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=getElementValueCurrent(n.querySelector("#"+t[o]))}))}))}},{key:"leave",value:function(){!function(e,t,r){var n=Ke(We(e.prototype),"leave",r);return"function"==typeof n?function(e){return n.apply(r,e)}:n}(t,0,this)([])}}])}(F);function Ze(e){return Ze="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},Ze(e)}function et(e,t){for(var r=0;r3&&void 0!==arguments[3]?arguments[3]:null;return{text:e[t],value:e[r],selected:e[r]==n}}},{key:"getOptionJsonFromObjectJson",value:function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=t[flagNameAttrOptionText],o=t[flagNameAttrOptionValue];return console.log({objectJson:t,keyText:n,keyValue:o}),e.getOptionJsonFromObjectJsonAndKeys(t,n,o,r)}}])}();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 pt(e,t){for(var r=0;r1&&void 0!==arguments[1]&&arguments[1];if(arguments.length>0&&void 0!==arguments[0]&&arguments[0]){var o=this.getLocalStoragePage()[flagFormFilters],i=this.getFormFilters(),a=l.convertForm2JSON(i);n.areEqualDicts(o,a)||this.callFilterTableContent(o)}else Et(t,"sharedInitialize",this,3)([]),this.hookupFilters(),this.hookupButtonsAddSaveCancel(),this.hookupTableMain(),T.hookup((function(){r?e.saveRecordsTableDirtySinglePageApp():e.saveRecordsTableDirty()}))}},{key:"hookupFilters",value:function(){if(this.constructor===t)throw new Error("Subclass of TableBasePage must implement method hookupFilters().")}},{key:"sharedHookupFilters",value:function(){this.hookupButtonApplyFilters()}},{key:"hookupFilterActive",value:function(){this.hookupFilter(flagActive)}},{key:"hookupFilter",value:function(e){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:function(e,r){return t.isDirtyFilter(r)},n=idFormFilters+" ."+e;this.hookupEventHandler("change",n,r)}},{key:"hookupFilterIsNotEmpty",value:function(){this.hookupFilter(flagIsNotEmpty)}},{key:"hookupButtonApplyFilters",value:function(){var e=this;this.hookupEventHandler("click",idButtonApplyFilters,(function(t,r){t.stopPropagation(),e.getAndLoadFilteredTableContent()}))}},{key:"getAndLoadFilteredTableContent",value:function(){var e=this.getFormFilters(),t=l.convertForm2JSON(e);this.leave(),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:"getAndLoadFilteredTableContentSinglePageApp",value:function(){var e=this,t=this.getFormFilters(),r=l.convertForm2JSON(t);this.callFilterTableContent(r).then((function(t){console.log("Table data received:",t),e.callbackLoadTableContent(t)})).catch((function(e){return console.error("Error:",e)}))}},{key:"hookupButtonsAddSaveCancel",value:function(){this.hookupButtonAddRowTable(),this.hookupButtonSave(),this.hookupButtonCancel(),this.toggleShowButtonsSaveCancel(!1)}},{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("Records saved!"),console.log("Data received:",t),e.getAndLoadFilteredTableContent()):(console.log("error: ",t[flagMessage]),bt.show(t[flagMessage]))})).catch((function(e){return console.error("Error:",e)}))}else bt.show("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:"saveRecordsTableDirtySinglePageApp",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("Records saved!"),console.log("Data received:",t),e.callbackLoadTableContent(t)):(console.log("error: ",t[flagMessage]),bt.show(t[flagMessage]))})).catch((function(e){return console.error("Error:",e)}))}else bt.show("No records to save")}},{key:"hookupButtonCancel",value:function(){y.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;this.hookupEventHandler("click",idFormFilters+" button."+flagAdd,(function(t,r){t.stopPropagation();var n=document.querySelector(idTableMain+" tbody"),o=_rowBlank.cloneNode(!0);o.classList.remove(flagInitialised),o.querySelectorAll("."+flagInitialised).forEach((function(e){e.classList.remove(flagInitialised)})),e.initialiseRowNew(o),n.appendChild(o),e.hookupTableMain()}))}},{key:"initialiseRowNew",value:function(e){throw new Error("Subclass of TableBasePage must implement method initialiseRowNew().")}},{key:"hookupTableMain",value:function(){var e=this;if(this.constructor===t)throw new Error("Must implement hookupTableMain() method.");null==_rowBlank&&y.initialiseEventHandler(idTableMain,flagInitialised,(function(t){e.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=idTableMain+" tbody tr td."+flagDisplayOrder+" input."+flagSlider+"."+flagDisplayOrder;this.hookupChangeHandlerTableCells(e)}},{key:"hookupChangeHandlerTableCells",value:function(e){var t=this,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:function(e,r){t.handleChangeElementCellTable(e,r)};y.initialiseEventHandler(e,flagInitialised,(function(e){e.addEventListener("change",(function(t){r(t,e)})),t.handleChangeElementCellTable(null,e)}))}},{key:"handleChangeElementCellTable",value:function(e,t){var r=l.getRowFromElement(t),n=l.getCellFromElement(t),o=l.hasDirtyChildrenContainer(r),i=t.classList.contains(flagDirty),a=l.updateAndCheckIsElementDirty(t);if(a!=i){l.handleDirtyElement(n,a);var u=l.hasDirtyChildrenContainer(r);if(u!=o){l.handleDirtyElement(r,u);var c=this.getTableRecords(!0).length>0;this.toggleShowButtonsSaveCancel(c)}}}},{key:"hookupChangeHandlerTableCellsWhenNotCollapsed",value:function(e){var t=this,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:function(e,r){r.classList.contains(flagCollapsed)||t.handleChangeElementCellTable(e,r)};this.hookupEventHandler("change",e,r)}},{key:"hookupTextareasCodeTable",value:function(){this.hookupChangeHandlerTableCells(idTableMain+" tbody tr td."+flagCode+" textarea")}},{key:"hookupTextareasNameTable",value:function(){this.hookupChangeHandlerTableCells(idTableMain+" tbody tr td."+flagName+" textarea")}},{key:"hookupTextareasDescriptionTable",value:function(){this.hookupChangeHandlerTableCells(idTableMain+" tbody tr td."+flagDescription+" textarea")}},{key:"hookupInputsActiveTable",value:function(){this.hookupChangeHandlerTableCells(idTableMain+" tbody tr td."+flagActive+' input[type="checkbox"]')}},{key:"hookupTdsAccessLevel",value:function(){var e=idTableMain+" tbody td."+flagAccessLevel;this.hookupTableCellDdlPreviews(e,ht.getListFromDict(accessLevels))}},{key:"hookupTableCellDdlPreviews",value:function(e,t){var r=this,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(e,t){r.hookupTableCellDdls(e,t)};this.hookupEventHandler("click",e,(function(o,i){r.handleClickTableCellDdlPreview(o,i,t,e,(function(e,t){n(e,t)}))}))}},{key:"hookupTableCellDdls",value:function(e){var t=this;this.hookupEventHandler("change",e,(function(e,r){t.handleChangeTableCellDdl(e,r)}))}},{key:"handleClickTableCellDdlPreview",value:function(e,t,r,n){var o=this,i=arguments.length>4&&void 0!==arguments[4]?arguments[4]:function(e,t){o.hookupTableCellDdls(e,t)};if(!t.querySelector("select")){console.log("click table cell ddl preview");var a=t.cloneNode(!0);t.parentNode.replaceChild(a,t);var u=a.getAttribute(attrValueCurrent);a.innerHTML="";var c,s,f=document.createElement("select");l.setElementValuesCurrentAndPrevious(f,l.getElementAttributeValueCurrent(a)),console.log({optionObjectList:r,cellSelector:n}),r.forEach((function(e){c=ft.getOptionJsonFromObjectJson(e,u),s=l.createOption(c),f.appendChild(s)})),a.appendChild(f),i(n+" select")}}},{key:"handleChangeTableCellDdl",value:function(e,t){var r=l.getRowFromElement(t),n=l.getCellFromElement(t);console.log("td: ",n);var o=l.hasDirtyChildrenContainer(r),i=t.classList.contains(flagDirty),a=l.updateAndCheckIsElementDirty(t);if(console.log("isDirtyElement: ",a),console.log("wasDirtyElement: ",i),a!=i){l.handleDirtyElement(n,a);var u=t.options[t.selectedIndex];l.setElementAttributeValueCurrent(n,u.value);var c=l.hasDirtyChildrenContainer(r);if(console.log("isNowDirtyRow: ",c),console.log("wasDirtyRow: ",o),c!=o){l.handleDirtyElement(r,c);var s=this.getTableRecords(!0),f=s.length>0;console.log("dirty records:",s),console.log("existsDirtyRecord:",f),this.toggleShowButtonsSaveCancel(f)}}}},{key:"hookupTableCellDDlPreviewsWhenNotCollapsed",value:function(e,t){var r=this,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(e,t){r.hookupTableCellDdls(e,t)};this.hookupEventHandler("click",e,(function(o,i){var a=i.querySelector("div");a&&!a.classList.contains(flagCollapsed)&&r.handleClickTableCellDdlPreview(o,i,t,e,(function(e,t){n(e,t)}))}))}},{key:"leave",value:function(){if(this.constructor===t)throw new Error("Must implement leave() method.");Et(t,"leave",this,3)([]);var e=this.getFormFilters(),r={};r[flagFormFilters]=l.convertForm2JSON(e),this.setLocalStoragePage(r)}},{key:"toggleColumnHasClassnameFlag",value:function(e,t,r){var n=this.getTableMain(),o=n.querySelector("th."+e),i=o.classList.contains(r);if(t!=i){var a=n.querySelectorAll("td."+e);l.toggleElementHasClassnameFlag(o,t,r),a.forEach((function(e){l.toggleElementHasClassnameFlag(e,t,r)}))}}}],[{key:"isDirtyFilter",value:function(e){var t=l.updateAndCheckIsElementDirty(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}}])}(F);function It(e){return It="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},It(e)}function Ft(e,t){var r="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!r){if(Array.isArray(e)||(r=function(e,t){if(e){if("string"==typeof e)return Lt(e,t);var r={}.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?Lt(e,t):void 0}}(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,o=function(){};return{s:o,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,u=!1;return{s:function(){r=r.call(e)},n:function(){var e=r.next();return a=e.done,e},e:function(e){u=!0,i=e},f:function(){try{a||null==r.return||r.return()}finally{if(u)throw i}}}}function Lt(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r",e))})),t.addEventListener("change",(function(e){loadPermutations()}))}));var r=document.querySelectorAll(idFilterIsOutOfStock);y.initialiseEventHandler(r,flagInitialised,(function(){r.addEventListener("change",(function(e){loadPermutations()}))}));var n=document.querySelectorAll(idFilterQuantityMin);y.initialiseEventHandler(n,flagInitialised,(function(){n.addEventListener("change",(function(e){loadPermutations()}))}));var o=document.querySelectorAll(idFilterQuantityMax);y.initialiseEventHandler(o,flagInitialised,(function(){o.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(),$.each(e.data,(function(e,o){r=_rowBlank.cloneNode(!0),(r=document.querySelectorAll(r)).classList.remove(flagRowNew),console.log("applying data row: ",o),r.querySelector("td."+flagProductCategory+" select").val(o[attrIdProductCategory]),n=r.querySelector("td."+flagProduct+" select"),listProducts.forEach((function(e){e[attrIdProductCategory]==o[attrIdProductCategory]&&n.appendChild(document.createElement("