From d708baf2dd42abced7eb4948bbb91926b3d4d22c Mon Sep 17 00:00:00 2001 From: Anton Kamalov Date: Sat, 30 Nov 2024 22:16:43 +0300 Subject: [PATCH 01/12] =?UTF-8?q?=D0=A4=D0=BE=D0=BD=20=D1=81=D1=82=D1=80?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D1=86=D1=8B=20=D0=B0=D0=B2=D1=82=D0=BE=D1=80?= =?UTF-8?q?=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/Auth/templates/auth.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/App/Auth/templates/auth.html b/App/Auth/templates/auth.html index 986bdaa..f5f4cb8 100644 --- a/App/Auth/templates/auth.html +++ b/App/Auth/templates/auth.html @@ -1,5 +1,5 @@ - + From 988d8fe00639a978ba5fd38fc0b244c183440598 Mon Sep 17 00:00:00 2001 From: Anton Kamalov Date: Sun, 1 Dec 2024 17:57:16 +0300 Subject: [PATCH 02/12] =?UTF-8?q?=D0=9E=D1=81=D0=BD=D0=BE=D0=B2=D0=B0=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D0=BE=D1=84=D0=BE=D1=80=D0=BC=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=BD=D0=B0=D0=BA=D0=BB=D0=B0=D0=B4=D0=BD?= =?UTF-8?q?=D1=8B=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/Waybill/__init__.py | 7 ++- App/Waybill/db/DBconnect.py | 34 ++++++++++++ App/Waybill/db/__init__.py | 0 App/Waybill/db/sql_provider.py | 14 +++++ App/Waybill/db/work.py | 12 +++++ App/Waybill/{waybill_model.py => model.py} | 8 +-- App/Waybill/sql/goods.sql | 1 + App/Waybill/templates/card.html | 27 ++++++++++ App/Waybill/templates/waybill.html | 63 ++++++++++------------ App/static/css/waybill.css | 42 +-------------- 10 files changed, 128 insertions(+), 80 deletions(-) create mode 100644 App/Waybill/db/DBconnect.py create mode 100644 App/Waybill/db/__init__.py create mode 100644 App/Waybill/db/sql_provider.py create mode 100644 App/Waybill/db/work.py rename App/Waybill/{waybill_model.py => model.py} (77%) create mode 100644 App/Waybill/sql/goods.sql create mode 100644 App/Waybill/templates/card.html diff --git a/App/Waybill/__init__.py b/App/Waybill/__init__.py index 66fdc1b..78dd921 100644 --- a/App/Waybill/__init__.py +++ b/App/Waybill/__init__.py @@ -1,11 +1,16 @@ from flask import request, Blueprint, render_template, session, current_app, redirect, url_for from checker import check_auth +from .model import waybill_model waybill_bp = Blueprint('waybill_bp', __name__, template_folder='templates') @waybill_bp.route('/', methods=['GET', 'POST']) @check_auth def waybill(): if request.method == 'GET': - return render_template('waybill.html') + pack = waybill_model() + if pack.status: + return render_template('waybill.html', items=pack.result) + else: + return render_template('error.html', error_message=pack.error_message) print(request.form) return 'OK' \ No newline at end of file diff --git a/App/Waybill/db/DBconnect.py b/App/Waybill/db/DBconnect.py new file mode 100644 index 0000000..b335654 --- /dev/null +++ b/App/Waybill/db/DBconnect.py @@ -0,0 +1,34 @@ +import pymysql +from pymysql.err import * +class DBContextManager: + def __init__(self, db_config : dict): + self.db_config = db_config + self.connection = None + self.cursor = None + + def __enter__(self): + try: + self.connection = pymysql.connect( + host=self.db_config['host'], + port=self.db_config['port'], + user=self.db_config['user'], + password=self.db_config['password'], + db=self.db_config['db'] + ) + self.cursor = self.connection.cursor() + return self.cursor + except (OperationalError, KeyError) as err: + print(err.args) + return None + + def __exit__(self, exc_type, exc_val, exc_tb): + if self.connection and self.cursor: + if exc_type: + print(exc_type, '\n', exc_val) + self.connection.rollback() + else: + self.connection.commit() + self.cursor.close() + self.connection.close() + return True + \ No newline at end of file diff --git a/App/Waybill/db/__init__.py b/App/Waybill/db/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/App/Waybill/db/sql_provider.py b/App/Waybill/db/sql_provider.py new file mode 100644 index 0000000..a3a1855 --- /dev/null +++ b/App/Waybill/db/sql_provider.py @@ -0,0 +1,14 @@ +import os +from string import Template + +class SQLProvider: + def __init__(self, file_path): + self.scripts = {} + for file in os.listdir(file_path): + _sql = open(f'{file_path}/{file}').read() + self.scripts[file] = Template(_sql) + + def get(self, name, params) -> dict: + if name not in self.scripts: + raise ValueError(f'SQL template {name} not found') + return self.scripts[name].substitute(**params) \ No newline at end of file diff --git a/App/Waybill/db/work.py b/App/Waybill/db/work.py new file mode 100644 index 0000000..22cc3e7 --- /dev/null +++ b/App/Waybill/db/work.py @@ -0,0 +1,12 @@ +from .DBconnect import DBContextManager + +def select_list(db_config, sql) -> list: + with DBContextManager(db_config) as cursor: + if cursor is None: + raise ValueError("Cursor not created") + else: + cursor.execute(sql) + result = cursor.fetchall() + schema = [item[0] for item in cursor.description] + lst = [dict(zip(schema, row)) for row in result] + return lst \ No newline at end of file diff --git a/App/Waybill/waybill_model.py b/App/Waybill/model.py similarity index 77% rename from App/Waybill/waybill_model.py rename to App/Waybill/model.py index 2928f24..d63f599 100644 --- a/App/Waybill/waybill_model.py +++ b/App/Waybill/model.py @@ -1,5 +1,5 @@ -from Database.sql_provider import SQLProvider -from Database.select import select_list +from .db.sql_provider import SQLProvider +from .db.work import select_list from flask import current_app from dataclasses import dataclass import os @@ -13,8 +13,8 @@ class InfoRespronse: sql_provider = SQLProvider(os.path.join(os.path.dirname(__file__), 'sql')) -def waybill_model(input_data) -> InfoRespronse: - _sql = sql_provider.get('waybill.sql', input_data) +def waybill_model() -> InfoRespronse: + _sql = sql_provider.get('goods.sql', {}) result = select_list(current_app.config['db_config'], _sql) if result is None: return InfoRespronse((), diff --git a/App/Waybill/sql/goods.sql b/App/Waybill/sql/goods.sql new file mode 100644 index 0000000..feec29a --- /dev/null +++ b/App/Waybill/sql/goods.sql @@ -0,0 +1 @@ +SELECT work_id, name, price, material, count FROM workpiece diff --git a/App/Waybill/templates/card.html b/App/Waybill/templates/card.html new file mode 100644 index 0000000..a687103 --- /dev/null +++ b/App/Waybill/templates/card.html @@ -0,0 +1,27 @@ +{% macro render_item(item, show_amount = False, show_form = False) %} + +
+
+
{{ item['name'] }}
+

Цена: {{ item['price'] }} ₽

+ {% if show_amount %} + Количество: {{item['count']}}
+
+ + + + +
+ {% endif %} + {% if show_form %} +
+ + +
+ {% endif %} +
+
+ +{% endmacro %} \ No newline at end of file diff --git a/App/Waybill/templates/waybill.html b/App/Waybill/templates/waybill.html index 529270f..a52256f 100644 --- a/App/Waybill/templates/waybill.html +++ b/App/Waybill/templates/waybill.html @@ -1,48 +1,41 @@ +{% import 'card.html' as card %} - + - Авторизация + Оформление накладной + + + -

Заглушка для примера составления накладной

-
-
- -
- Фото товара -

Название товара 1

-

Цена: 500 руб.

-

Количество: 10 шт.

-
- +
+
+ +
+

Список товаров

+
+ {% for item in items %} +
+ {{ card.render_item(item, show_form = True, show_amount = False) }} +
+ {% endfor %}
-
- Фото товара -

Название товара 2

-

Цена: 1200 руб.

-

Количество: 5 шт.

-
- -
-
-
- Фото товара -

Название товара 3

-

Цена: 800 руб.

-

Количество: 7 шт.

-
- + + +
+

Корзина

+
    +
  • Корзина пуста
  • +
+
+
Итог: 0
-
- - -
- +
- \ No newline at end of file + diff --git a/App/static/css/waybill.css b/App/static/css/waybill.css index 048abb5..b7d39da 100644 --- a/App/static/css/waybill.css +++ b/App/static/css/waybill.css @@ -1,48 +1,10 @@ -.container { - display: flex; - flex-wrap: wrap; - gap: 20px; - padding: 20px; - justify-content: center; -} .card { background: #fff; border: 1px solid #ddd; + color: black; border-radius: 10px; width: 250px; padding: 15px; + margin-bottom: 15px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); -} -.card img { - width: 100%; - height: 150px; - object-fit: cover; - border-radius: 5px; -} -.card h3 { - margin: 10px 0; - font-size: 18px; -} -.price { - font-weight: bold; - color: #28a745; -} -.quantity { - margin: 10px 0; - font-weight: bold; - color: #007bff; -} -.input-container { - margin: 10px 0; -} -.input-container input { - width: 80%; - padding: 8px; - font-size: 14px; - border: 1px solid #ddd; - border-radius: 5px; -} -.button-container { - text-align: center; - margin: 20px 0; } \ No newline at end of file From b3f856b401e7876bb92ebda02bbb37b504e4ff09 Mon Sep 17 00:00:00 2001 From: Anton Kamalov Date: Sun, 1 Dec 2024 20:16:56 +0300 Subject: [PATCH 03/12] =?UTF-8?q?=D0=9F=D0=BE=D1=8F=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D1=81=D1=83=D1=89=D0=BD=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D0=B8=20=D0=BD=D0=B0=D0=BA=D0=BB=D0=B0=D0=B4=D0=BD=D0=BE=D0=B9?= =?UTF-8?q?=20+=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BD=D0=BE=D1=81=20waybill.css?= =?UTF-8?q?=20=D0=B2=20=D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD=D1=83?= =?UTF-8?q?=D1=8E=20=D0=BF=D0=B0=D0=BF=D0=BA=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/Waybill/__init__.py | 26 ++++++++++++++++-------- App/Waybill/model.py | 7 +++++-- App/{ => Waybill}/static/css/waybill.css | 0 App/Waybill/templates/card.html | 2 +- App/Waybill/templates/waybill.html | 25 ++++++++++++----------- App/static/css/output.css | 14 ------------- 6 files changed, 36 insertions(+), 38 deletions(-) rename App/{ => Waybill}/static/css/waybill.css (100%) delete mode 100644 App/static/css/output.css diff --git a/App/Waybill/__init__.py b/App/Waybill/__init__.py index 78dd921..0c69085 100644 --- a/App/Waybill/__init__.py +++ b/App/Waybill/__init__.py @@ -1,16 +1,24 @@ from flask import request, Blueprint, render_template, session, current_app, redirect, url_for from checker import check_auth -from .model import waybill_model -waybill_bp = Blueprint('waybill_bp', __name__, template_folder='templates') +from .model import workpiece_list, clear +waybill_bp = Blueprint('waybill_bp', __name__, template_folder='templates', static_folder='static') -@waybill_bp.route('/', methods=['GET', 'POST']) +@waybill_bp.route('/', methods=['GET']) @check_auth +def index(): + lst = workpiece_list() + if lst.status: + return render_template('waybill.html', items=lst.result) + else: + return render_template('error.html', error_message=lst.error_message) + +@waybill_bp.route('/clear', methods=['GET']) +@check_auth +def clear_basket(): + clear() + return redirect(url_for('waybill_bp.index')) + +@waybill_bp.route('/', methods=['POST']) def waybill(): - if request.method == 'GET': - pack = waybill_model() - if pack.status: - return render_template('waybill.html', items=pack.result) - else: - return render_template('error.html', error_message=pack.error_message) print(request.form) return 'OK' \ No newline at end of file diff --git a/App/Waybill/model.py b/App/Waybill/model.py index d63f599..a1eda22 100644 --- a/App/Waybill/model.py +++ b/App/Waybill/model.py @@ -1,6 +1,6 @@ from .db.sql_provider import SQLProvider from .db.work import select_list -from flask import current_app +from flask import current_app, session from dataclasses import dataclass import os @@ -12,8 +12,11 @@ class InfoRespronse: sql_provider = SQLProvider(os.path.join(os.path.dirname(__file__), 'sql')) +def clear(): + if session.get('basket',{}): + session.pop('basket') -def waybill_model() -> InfoRespronse: +def workpiece_list() -> InfoRespronse: _sql = sql_provider.get('goods.sql', {}) result = select_list(current_app.config['db_config'], _sql) if result is None: diff --git a/App/static/css/waybill.css b/App/Waybill/static/css/waybill.css similarity index 100% rename from App/static/css/waybill.css rename to App/Waybill/static/css/waybill.css diff --git a/App/Waybill/templates/card.html b/App/Waybill/templates/card.html index a687103..2963232 100644 --- a/App/Waybill/templates/card.html +++ b/App/Waybill/templates/card.html @@ -9,7 +9,7 @@
diff --git a/App/Waybill/templates/waybill.html b/App/Waybill/templates/waybill.html index a52256f..937ec17 100644 --- a/App/Waybill/templates/waybill.html +++ b/App/Waybill/templates/waybill.html @@ -5,17 +5,16 @@ Оформление накладной - + -
- +
-

Список товаров

+

Список заготовок

{% for item in items %}
@@ -25,15 +24,17 @@
- +
-

Корзина

-
    -
  • Корзина пуста
  • -
-
-
Итог: 0
-
+

Накладная

+ {% if basket %} + {% for item in basket %} + {{ components.render_item(item, show_form = False, show_amount = True) }} + {% endfor %} + + {% else %} + Ваша накладная пуста + {% endif %}
diff --git a/App/static/css/output.css b/App/static/css/output.css deleted file mode 100644 index e91e70a..0000000 --- a/App/static/css/output.css +++ /dev/null @@ -1,14 +0,0 @@ -table { - border: 1px solid black; - border-collapse: collapse; - background: white; - margin: 0 auto; -} -th { - background-color: #d3d3d3; -} -th, td { - border: 1px solid black; - padding: 5px; - text-align: center; -} From b58fcc7d0e1e46d4921c6243624ae9cca877b738 Mon Sep 17 00:00:00 2001 From: Anton Kamalov Date: Sun, 1 Dec 2024 20:41:02 +0300 Subject: [PATCH 04/12] =?UTF-8?q?=D0=9A=D1=8D=D1=88=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D1=81=D0=BF=D0=B8=D1=81=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=B7=D0=B0=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/Waybill/cache/__init__.py | 42 ++++++++++++++ App/Waybill/cache/wrapper.py | 26 +++++++++ App/Waybill/model.py | 102 +++++++++++++++++++++++++++++++++- App/app.py | 3 +- App/data/redis_config.json | 8 +++ 5 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 App/Waybill/cache/__init__.py create mode 100644 App/Waybill/cache/wrapper.py create mode 100644 App/data/redis_config.json diff --git a/App/Waybill/cache/__init__.py b/App/Waybill/cache/__init__.py new file mode 100644 index 0000000..d902592 --- /dev/null +++ b/App/Waybill/cache/__init__.py @@ -0,0 +1,42 @@ +import json +from redis import Redis, ConnectionError, DataError + +class RedisCache: + def __init__(self, config: dict): + self.config = config + self.conn = self._connect() + + def _connect(self): + try: + conn = Redis(**self.config) + return conn + except DataError as err: + print(err) + return None + + def set_value(self, name: str, value_dict: dict, ttl: int): + try: + value_js = json.dumps(value_dict) + self.conn.set(name=name, value=value_js) + if ttl > 0: + self.conn.expire(name, ttl) + return True + except ConnectionError as err: + print(err) + return False + + def get_value(self, name: str): + try: + value_js = self.conn.get(name) + except: + return None + value_js = self.conn.get(name) + if value_js: + value_dict = json.loads(value_js) + return value_dict + else: + return None + + def __exit__(self, exc_type, exc_val, exc_tb): + self.conn.close() + return True \ No newline at end of file diff --git a/App/Waybill/cache/wrapper.py b/App/Waybill/cache/wrapper.py new file mode 100644 index 0000000..ff38803 --- /dev/null +++ b/App/Waybill/cache/wrapper.py @@ -0,0 +1,26 @@ +from functools import wraps +from Waybill.cache import RedisCache + +def fetch_from_cache(cache_name: str, cache_config: dict): + cache_conn = RedisCache(cache_config['redis']) + ttl = cache_config['ttl'] + def decorator(f): + # как оно работает + # лезем в кэш и смотрим, есть ли там что-то + # если есть, то возвращаем кэшированную информацию + # если нет, то запускаем декорируемую функцию + # достаём оттуда информацию + # заносим её в кэш + # возвращаем кэшированную информацию + @wraps(f) + def wrapper(*args, **kwargs): + cached_value = cache_conn.get_value(cache_name) + print("cached_value=", cached_value) + if cached_value: + return cached_value + response = f(*args, **kwargs) + print("response=", response) + cache_conn.set_value(cache_name,response,ttl) + return response + return wrapper + return decorator \ No newline at end of file diff --git a/App/Waybill/model.py b/App/Waybill/model.py index a1eda22..eddd553 100644 --- a/App/Waybill/model.py +++ b/App/Waybill/model.py @@ -1,7 +1,11 @@ from .db.sql_provider import SQLProvider from .db.work import select_list +from db.DBconnect import DBContextManager + from flask import current_app, session from dataclasses import dataclass +from datetime import date +from .cache.wrapper import fetch_from_cache import os @dataclass @@ -23,4 +27,100 @@ def workpiece_list() -> InfoRespronse: return InfoRespronse((), error_message = 'Ошибка в подключении к базе данных. Свяжитесь с администратором', status=False) - return InfoRespronse(result, error_message='', status=True) \ No newline at end of file + return InfoRespronse(result, error_message='', status=True) + +def form_basket() -> list: + current_basket = session.get('basket',{}) + basket = [] + for k,v in current_basket.items(): + _sql = sql_provider.get('one_good.sql', dict(prod_id=k)) + product = select_list(current_app.config['db_config'], _sql)[0] + product['amount'] = v + basket.append(product) + return basket + +def index_basket() -> list: + db_config = current_app.config['db_config'] + cache_config = current_app.config['cache_config'] + + cache_select = fetch_from_cache('items_cached', cache_config)(select_list) + _sql = sql_provider.get('all_goods.sql', {}) + products = cache_select(db_config, _sql) + + return products + +def button_click(request): + db_config = current_app.config['db_config'] + data = dict(prod_id=int(request.form['product_display'])) + + _sql = sql_provider.get('one_good.sql', data) + result = select_list(db_config, _sql) + if result == None: + return False + + product = result[0] + + if request.form.get('buy'): + if 'basket' not in session: + session['basket'] = dict() + + if str(product['prod_id']) in session['basket']: + pr_id = product['prod_id'] + amount = int(session['basket'][str(pr_id)]) + session['basket'][str(pr_id)] = str(amount+1) + session.modified = True + else: + print("NEW PRODUCT") + pr_id = product['prod_id'] + session['basket'][str(pr_id)] = '1' + print(session['basket']) + session.modified = True + + elif request.form.get('product_display_plus'): + # increasing count in basket + + amount = int(session['basket'][str(product['prod_id'])]) + session['basket'][str(product['prod_id'])] = str(amount + 1) + session.modified = True + + elif request.form.get('product_display_minus'): + # decreasing count in basket + + amount = int(session['basket'][str(product['prod_id'])]) + if amount == 1: + session['basket'].pop(str(product['prod_id'])) + else: + session['basket'][str(product['prod_id'])] = str(amount-1) + session.modified = True + return True + +def transaction_order_model(user_id: int, current_date: date): + + db_config = current_app.config['db_config'] + basket = session.get('basket',{}) + + # Чтобы всё это шло как одна транзакция + with DBContextManager(db_config) as cursor: + + data = dict(e_user_id=user_id, e_order_date=current_date) + + _sql = sql_provider.get('create_order.sql', data) + try: + cursor.execute(_sql) + except: + return InfoRespronse(tuple(), error_message="Заказ не был создан", status=False) + + order_id = cursor.lastrowid + for key, value in basket.items(): + _sql = sql_provider.get('insert_order_line.sql', + dict(e_order_id = order_id, + e_prod_id = int(key), + e_amount = int(value))) + try: + cursor.execute(_sql) + except: + return InfoRespronse(tuple(), error_message="Заказ не был создан", status=False) + + result = tuple([order_id]) + clear() + return InfoRespronse(result, error_message="", status=True) \ No newline at end of file diff --git a/App/app.py b/App/app.py index cd4ad61..fe5e3d3 100644 --- a/App/app.py +++ b/App/app.py @@ -10,7 +10,8 @@ app.secret_key = 'suplex' app.config.update( db_config=json.load(open(os.path.join(os.path.dirname(__file__), 'data/config.json'))), - db_access=json.load(open(os.path.join(os.path.dirname(__file__), 'data/db_access.json'))) + db_access=json.load(open(os.path.join(os.path.dirname(__file__), 'data/db_access.json'))), + cache_config=json.load(open(os.path.join(os.path.dirname(__file__), 'data/redis_config.json'))) ) app.register_blueprint(requests_bp, url_prefix='/requests') diff --git a/App/data/redis_config.json b/App/data/redis_config.json new file mode 100644 index 0000000..c334cca --- /dev/null +++ b/App/data/redis_config.json @@ -0,0 +1,8 @@ +{ + "redis": { + "host" :"127.0.0.1", + "port": 6379, + "db" : 0 + }, + "ttl": 60 +} \ No newline at end of file From 0d2a5ff959ee6abe527cfae0494142b0caab3f91 Mon Sep 17 00:00:00 2001 From: Anton Kamalov Date: Sun, 1 Dec 2024 20:44:34 +0300 Subject: [PATCH 05/12] basket -> waybill --- App/Waybill/__init__.py | 2 +- App/Waybill/model.py | 52 +++++++++++++++--------------- App/Waybill/templates/waybill.html | 6 ++-- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/App/Waybill/__init__.py b/App/Waybill/__init__.py index 0c69085..c1f5588 100644 --- a/App/Waybill/__init__.py +++ b/App/Waybill/__init__.py @@ -14,7 +14,7 @@ def index(): @waybill_bp.route('/clear', methods=['GET']) @check_auth -def clear_basket(): +def clear_waybill(): clear() return redirect(url_for('waybill_bp.index')) diff --git a/App/Waybill/model.py b/App/Waybill/model.py index eddd553..02657d1 100644 --- a/App/Waybill/model.py +++ b/App/Waybill/model.py @@ -17,8 +17,8 @@ class InfoRespronse: sql_provider = SQLProvider(os.path.join(os.path.dirname(__file__), 'sql')) def clear(): - if session.get('basket',{}): - session.pop('basket') + if session.get('waybill',{}): + session.pop('waybill') def workpiece_list() -> InfoRespronse: _sql = sql_provider.get('goods.sql', {}) @@ -29,17 +29,17 @@ def workpiece_list() -> InfoRespronse: status=False) return InfoRespronse(result, error_message='', status=True) -def form_basket() -> list: - current_basket = session.get('basket',{}) - basket = [] - for k,v in current_basket.items(): +def form_waybill() -> list: + current_waybill = session.get('waybill',{}) + waybill = [] + for k,v in current_waybill.items(): _sql = sql_provider.get('one_good.sql', dict(prod_id=k)) product = select_list(current_app.config['db_config'], _sql)[0] product['amount'] = v - basket.append(product) - return basket + waybill.append(product) + return waybill -def index_basket() -> list: +def index_waybill() -> list: db_config = current_app.config['db_config'] cache_config = current_app.config['cache_config'] @@ -61,43 +61,43 @@ def button_click(request): product = result[0] if request.form.get('buy'): - if 'basket' not in session: - session['basket'] = dict() + if 'waybill' not in session: + session['waybill'] = dict() - if str(product['prod_id']) in session['basket']: + if str(product['prod_id']) in session['waybill']: pr_id = product['prod_id'] - amount = int(session['basket'][str(pr_id)]) - session['basket'][str(pr_id)] = str(amount+1) + amount = int(session['waybill'][str(pr_id)]) + session['waybill'][str(pr_id)] = str(amount+1) session.modified = True else: - print("NEW PRODUCT") + print("NEW WORKPIECE") pr_id = product['prod_id'] - session['basket'][str(pr_id)] = '1' - print(session['basket']) + session['waybill'][str(pr_id)] = '1' + print(session['waybill']) session.modified = True elif request.form.get('product_display_plus'): - # increasing count in basket + # increasing count in waybill - amount = int(session['basket'][str(product['prod_id'])]) - session['basket'][str(product['prod_id'])] = str(amount + 1) + amount = int(session['waybill'][str(product['prod_id'])]) + session['waybill'][str(product['prod_id'])] = str(amount + 1) session.modified = True elif request.form.get('product_display_minus'): - # decreasing count in basket + # decreasing count in waybill - amount = int(session['basket'][str(product['prod_id'])]) + amount = int(session['waybill'][str(product['prod_id'])]) if amount == 1: - session['basket'].pop(str(product['prod_id'])) + session['waybill'].pop(str(product['prod_id'])) else: - session['basket'][str(product['prod_id'])] = str(amount-1) + session['waybill'][str(product['prod_id'])] = str(amount-1) session.modified = True return True def transaction_order_model(user_id: int, current_date: date): db_config = current_app.config['db_config'] - basket = session.get('basket',{}) + waybill = session.get('waybill',{}) # Чтобы всё это шло как одна транзакция with DBContextManager(db_config) as cursor: @@ -111,7 +111,7 @@ def transaction_order_model(user_id: int, current_date: date): return InfoRespronse(tuple(), error_message="Заказ не был создан", status=False) order_id = cursor.lastrowid - for key, value in basket.items(): + for key, value in waybill.items(): _sql = sql_provider.get('insert_order_line.sql', dict(e_order_id = order_id, e_prod_id = int(key), diff --git a/App/Waybill/templates/waybill.html b/App/Waybill/templates/waybill.html index 937ec17..1f30fb4 100644 --- a/App/Waybill/templates/waybill.html +++ b/App/Waybill/templates/waybill.html @@ -27,11 +27,11 @@

Накладная

- {% if basket %} - {% for item in basket %} + {% if waybill %} + {% for item in waybill %} {{ components.render_item(item, show_form = False, show_amount = True) }} {% endfor %} - + {% else %} Ваша накладная пуста {% endif %} From 453801f2e9459ebe0d6e9d27d5c62c730f51e2ba Mon Sep 17 00:00:00 2001 From: Anton Kamalov Date: Tue, 3 Dec 2024 17:44:23 +0300 Subject: [PATCH 06/12] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D1=81=D0=BE=D0=B4=D0=B5=D1=80=D0=B6=D0=B8?= =?UTF-8?q?=D0=BC=D0=BE=D0=B3=D0=BE=20=D1=81=D0=B5=D1=81=D1=81=D0=B8=D0=B8?= =?UTF-8?q?=20=D0=BF=D1=80=D0=B8=20=D0=B0=D0=B2=D1=82=D0=BE=D1=80=D0=B8?= =?UTF-8?q?=D0=B7=D0=B0=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/Auth/__init__.py | 1 + App/Auth/sql/auth.sql | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/App/Auth/__init__.py b/App/Auth/__init__.py index 3e426da..402607f 100644 --- a/App/Auth/__init__.py +++ b/App/Auth/__init__.py @@ -12,6 +12,7 @@ def auth(): auth_data = auth_model(data) if auth_data.status: session.update({ + 'user_id': auth_data.result[0]['user_ID'], 'login': auth_data.result[0]['login'], 'access_user': data['access'], 'role': auth_data.result[0]['user_role'], diff --git a/App/Auth/sql/auth.sql b/App/Auth/sql/auth.sql index 4fb90bf..56c956a 100644 --- a/App/Auth/sql/auth.sql +++ b/App/Auth/sql/auth.sql @@ -1,4 +1,4 @@ -SELECT login, user_role FROM $access +SELECT user_ID, login, user_role FROM $access WHERE login = '$login' AND password = '$password' LIMIT 1; \ No newline at end of file From ee6a2f9756fda80cb78115544bb3d85099ca6b08 Mon Sep 17 00:00:00 2001 From: Anton Kamalov Date: Tue, 3 Dec 2024 17:46:41 +0300 Subject: [PATCH 07/12] =?UTF-8?q?=D0=9E=D1=81=D0=BD=D0=BE=D0=B2=D0=BD?= =?UTF-8?q?=D0=BE=D0=B9=20=D0=B1=D0=B8=D0=B7=D0=BD=D0=B5=D1=81-=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D1=86=D0=B5=D1=81=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Оформление накладных --- App/Waybill/__init__.py | 44 ++++++++++++++++----- App/Waybill/db/work.py | 6 ++- App/Waybill/model.py | 56 +++++++++++++-------------- App/Waybill/sql/create_order.sql | 1 + App/Waybill/sql/goods.sql | 2 +- App/Waybill/sql/insert_order_line.sql | 2 + App/Waybill/sql/one_good.sql | 3 ++ App/Waybill/templates/card.html | 9 ++--- App/Waybill/templates/waybill.html | 2 +- 9 files changed, 77 insertions(+), 48 deletions(-) create mode 100644 App/Waybill/sql/create_order.sql create mode 100644 App/Waybill/sql/insert_order_line.sql create mode 100644 App/Waybill/sql/one_good.sql diff --git a/App/Waybill/__init__.py b/App/Waybill/__init__.py index c1f5588..d3abfd5 100644 --- a/App/Waybill/__init__.py +++ b/App/Waybill/__init__.py @@ -1,16 +1,28 @@ -from flask import request, Blueprint, render_template, session, current_app, redirect, url_for +from flask import request, Blueprint, render_template, session, redirect, url_for from checker import check_auth -from .model import workpiece_list, clear +from .model import index_waybill, form_waybill, clear, button_click, transaction_order_model +from datetime import date + waybill_bp = Blueprint('waybill_bp', __name__, template_folder='templates', static_folder='static') @waybill_bp.route('/', methods=['GET']) @check_auth def index(): - lst = workpiece_list() - if lst.status: - return render_template('waybill.html', items=lst.result) + lst = index_waybill() + if lst is not None: + waybill = form_waybill() + return render_template('waybill.html', items=lst, waybill=waybill) else: - return render_template('error.html', error_message=lst.error_message) + return render_template('error.html', error_message="Ошибка в подключении к СУБД") + +@waybill_bp.route('/', methods=['POST']) +@check_auth +def waybill_main(): + status = button_click(request) + if status: + return redirect(url_for('waybill_bp.index')) + else: + return render_template("error.html", error_message="Товар не был добавлен в корзину") @waybill_bp.route('/clear', methods=['GET']) @check_auth @@ -18,7 +30,19 @@ def clear_waybill(): clear() return redirect(url_for('waybill_bp.index')) -@waybill_bp.route('/', methods=['POST']) -def waybill(): - print(request.form) - return 'OK' \ No newline at end of file +@waybill_bp.route('/save_order') +@check_auth +def save_order(): + if not session.get('waybill',{}): + return redirect(url_for('waybill_bp.index')) + + user_id = session.get('user_id',"") + current_date = date.today().strftime("%Y-%m-%d") + ' ' + date.today().strftime("%H:%M:%S") + + result = transaction_order_model(user_id, current_date) + if result.status: + print("Order success") + return "OK" + # return render_template("order_finish.html", order_id = result.result[0]) + else: + return render_template("error.html", error_message=result.error_message) \ No newline at end of file diff --git a/App/Waybill/db/work.py b/App/Waybill/db/work.py index 22cc3e7..5a7f039 100644 --- a/App/Waybill/db/work.py +++ b/App/Waybill/db/work.py @@ -9,4 +9,8 @@ def select_list(db_config, sql) -> list: result = cursor.fetchall() schema = [item[0] for item in cursor.description] lst = [dict(zip(schema, row)) for row in result] - return lst \ No newline at end of file + return lst + +def transaction(cursor, sql): + cursor.execute(sql) + return True \ No newline at end of file diff --git a/App/Waybill/model.py b/App/Waybill/model.py index 02657d1..01162b1 100644 --- a/App/Waybill/model.py +++ b/App/Waybill/model.py @@ -1,6 +1,6 @@ from .db.sql_provider import SQLProvider -from .db.work import select_list -from db.DBconnect import DBContextManager +from .db.work import select_list, transaction +from .db.DBconnect import DBContextManager from flask import current_app, session from dataclasses import dataclass @@ -20,20 +20,11 @@ def clear(): if session.get('waybill',{}): session.pop('waybill') -def workpiece_list() -> InfoRespronse: - _sql = sql_provider.get('goods.sql', {}) - result = select_list(current_app.config['db_config'], _sql) - if result is None: - return InfoRespronse((), - error_message = 'Ошибка в подключении к базе данных. Свяжитесь с администратором', - status=False) - return InfoRespronse(result, error_message='', status=True) - def form_waybill() -> list: current_waybill = session.get('waybill',{}) waybill = [] for k,v in current_waybill.items(): - _sql = sql_provider.get('one_good.sql', dict(prod_id=k)) + _sql = sql_provider.get('one_good.sql', dict(work_id=k)) product = select_list(current_app.config['db_config'], _sql)[0] product['amount'] = v waybill.append(product) @@ -44,14 +35,14 @@ def index_waybill() -> list: cache_config = current_app.config['cache_config'] cache_select = fetch_from_cache('items_cached', cache_config)(select_list) - _sql = sql_provider.get('all_goods.sql', {}) + _sql = sql_provider.get('goods.sql', {}) products = cache_select(db_config, _sql) return products def button_click(request): db_config = current_app.config['db_config'] - data = dict(prod_id=int(request.form['product_display'])) + data = dict(work_id=int(request.form['product_display'])) _sql = sql_provider.get('one_good.sql', data) result = select_list(db_config, _sql) @@ -60,37 +51,43 @@ def button_click(request): product = result[0] - if request.form.get('buy'): + if request.form.get('add'): if 'waybill' not in session: session['waybill'] = dict() + session['total'] = '0' - if str(product['prod_id']) in session['waybill']: - pr_id = product['prod_id'] + if str(product['work_id']) in session['waybill']: + pr_id = product['work_id'] + price = product['price'] amount = int(session['waybill'][str(pr_id)]) session['waybill'][str(pr_id)] = str(amount+1) + session['total'] = str(int(session['total']) + price) session.modified = True else: print("NEW WORKPIECE") - pr_id = product['prod_id'] + pr_id = product['work_id'] + price = product['price'] session['waybill'][str(pr_id)] = '1' + session['total'] = str(int(session['total']) + price) print(session['waybill']) session.modified = True - elif request.form.get('product_display_plus'): - # increasing count in waybill + # elif request.form.get('product_display_plus'): + # # increasing count in waybill - amount = int(session['waybill'][str(product['prod_id'])]) - session['waybill'][str(product['prod_id'])] = str(amount + 1) - session.modified = True + # amount = int(session['waybill'][str(product['work_id'])]) + # session['waybill'][str(product['work_id'])] = str(amount + 1) + # session.modified = True elif request.form.get('product_display_minus'): # decreasing count in waybill - amount = int(session['waybill'][str(product['prod_id'])]) + amount = int(session['waybill'][str(product['work_id'])]) if amount == 1: - session['waybill'].pop(str(product['prod_id'])) + session['waybill'].pop(str(product['work_id'])) else: - session['waybill'][str(product['prod_id'])] = str(amount-1) + session['waybill'][str(product['work_id'])] = str(amount-1) + session['total'] = str(int(session['total']) - product['price']) session.modified = True return True @@ -98,17 +95,18 @@ def transaction_order_model(user_id: int, current_date: date): db_config = current_app.config['db_config'] waybill = session.get('waybill',{}) + total = session.get('total', 0) # Чтобы всё это шло как одна транзакция with DBContextManager(db_config) as cursor: - data = dict(e_user_id=user_id, e_order_date=current_date) + data = dict(e_user_id=user_id, e_order_date=current_date, e_total=total) _sql = sql_provider.get('create_order.sql', data) try: cursor.execute(_sql) except: - return InfoRespronse(tuple(), error_message="Заказ не был создан", status=False) + return InfoRespronse((), error_message="Заказ не был создан", status=False) order_id = cursor.lastrowid for key, value in waybill.items(): @@ -119,7 +117,7 @@ def transaction_order_model(user_id: int, current_date: date): try: cursor.execute(_sql) except: - return InfoRespronse(tuple(), error_message="Заказ не был создан", status=False) + return InfoRespronse((), error_message="Заказ не был создан", status=False) result = tuple([order_id]) clear() diff --git a/App/Waybill/sql/create_order.sql b/App/Waybill/sql/create_order.sql new file mode 100644 index 0000000..0b5e11c --- /dev/null +++ b/App/Waybill/sql/create_order.sql @@ -0,0 +1 @@ +INSERT INTO `waybill` (`user_id`,`waybill_date`, `total`) VALUES ($e_user_id, '$e_order_date', $e_total); \ No newline at end of file diff --git a/App/Waybill/sql/goods.sql b/App/Waybill/sql/goods.sql index feec29a..9a18e9b 100644 --- a/App/Waybill/sql/goods.sql +++ b/App/Waybill/sql/goods.sql @@ -1 +1 @@ -SELECT work_id, name, price, material, count FROM workpiece +SELECT work_id, name, price, material, count FROM workpiece \ No newline at end of file diff --git a/App/Waybill/sql/insert_order_line.sql b/App/Waybill/sql/insert_order_line.sql new file mode 100644 index 0000000..26091a8 --- /dev/null +++ b/App/Waybill/sql/insert_order_line.sql @@ -0,0 +1,2 @@ +INSERT INTO `waybill_lines` VALUES ($e_order_id, $e_prod_id, +(SELECT price FROM workpiece WHERE work_id = $e_prod_id), $e_amount); \ No newline at end of file diff --git a/App/Waybill/sql/one_good.sql b/App/Waybill/sql/one_good.sql new file mode 100644 index 0000000..d81e194 --- /dev/null +++ b/App/Waybill/sql/one_good.sql @@ -0,0 +1,3 @@ +SELECT `work_id`, `name`, `price`, `weight` +FROM `workpiece` +WHERE `work_id` = $work_id; \ No newline at end of file diff --git a/App/Waybill/templates/card.html b/App/Waybill/templates/card.html index 2963232..b6248d6 100644 --- a/App/Waybill/templates/card.html +++ b/App/Waybill/templates/card.html @@ -5,20 +5,17 @@
{{ item['name'] }}

Цена: {{ item['price'] }} ₽

{% if show_amount %} - Количество: {{item['count']}}
+ Количество: {{item['amount']}}
- - + {% endif %} {% if show_form %}
- +
{% endif %}
diff --git a/App/Waybill/templates/waybill.html b/App/Waybill/templates/waybill.html index 1f30fb4..937ed2e 100644 --- a/App/Waybill/templates/waybill.html +++ b/App/Waybill/templates/waybill.html @@ -29,7 +29,7 @@

Накладная

{% if waybill %} {% for item in waybill %} - {{ components.render_item(item, show_form = False, show_amount = True) }} + {{ card.render_item(item, show_form = False, show_amount = True) }} {% endfor %} {% else %} From 07d4b6c9c5acf506414f4efe4d103422b78b442f Mon Sep 17 00:00:00 2001 From: Anton Kamalov Date: Tue, 3 Dec 2024 17:54:58 +0300 Subject: [PATCH 08/12] =?UTF-8?q?=D0=94=D0=BE=D1=81=D1=82=D1=83=D0=BF=20?= =?UTF-8?q?=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D1=89=D0=B8=D0=BA=D1=83=20?= =?UTF-8?q?=D0=BA=20=D0=BE=D1=84=D0=BE=D1=80=D0=BC=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8E=20=D0=BD=D0=B0=D0=BA=D0=BB=D0=B0=D0=B4=D0=BD=D0=BE=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/templates/main_menu.html | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/App/templates/main_menu.html b/App/templates/main_menu.html index 8fd8fc8..fa2a4ec 100644 --- a/App/templates/main_menu.html +++ b/App/templates/main_menu.html @@ -35,8 +35,8 @@
- {% if ses['access_user'] == 'internal_users' %}
+ {% if ses['access_user'] == 'internal_users' %}
+

Новая накладная

+ + + + {% endif %}
- \ No newline at end of file From 15cbb35dc5eb287771daa253a0d4e3810d9a117b Mon Sep 17 00:00:00 2001 From: Artur Date: Wed, 4 Dec 2024 01:06:59 +0300 Subject: [PATCH 09/12] =?UTF-8?q?=D0=90=D0=BA=D1=82=D1=83=D0=B0=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D1=8B=D0=B5=20=D0=BA=D0=BE=D0=BD=D1=84=D0=B8=D0=B3?= =?UTF-8?q?=D1=83=D1=80=D0=B0=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/data/config.json | 2 +- App/data/redis_config.json | 2 +- requirements.txt | Bin 49 -> 130 bytes 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/App/data/config.json b/App/data/config.json index 75428e2..8b7b193 100644 --- a/App/data/config.json +++ b/App/data/config.json @@ -1,5 +1,5 @@ { - "host": "localhost", + "host": "89.46.42.74", "port": 3306, "user": "manager", "password": "ilikepizza", diff --git a/App/data/redis_config.json b/App/data/redis_config.json index c334cca..2739ead 100644 --- a/App/data/redis_config.json +++ b/App/data/redis_config.json @@ -1,6 +1,6 @@ { "redis": { - "host" :"127.0.0.1", + "host" :"89.46.42.74", "port": 6379, "db" : 0 }, diff --git a/requirements.txt b/requirements.txt index 56846341ce2e20067a2ee9905a6b2baaceac943c..4e407bfe1d0af66f30bb7a23e15ebc7b833d1661 100644 GIT binary patch literal 130 zcmY+6!3sc76hzNj`4!=@w6&th7YHGWu<`R4&q}wc>7LHqSHs51%E3afUaJrKB)SNL nhp!l198zZSoypQaE9B%#MM-9PAn(iTZgjMavft%cEVSDX?~xPO literal 49 ycmYc;sw^nUPcKR=$f&fnH8IvR&@<+8%SkNGwzY+D0xEqgg9CkRZ4LE+kP85gI1VrX From 9ffa099cd0d7f1196833515668c3e4220789fcc9 Mon Sep 17 00:00:00 2001 From: Artur Date: Wed, 4 Dec 2024 01:32:47 +0300 Subject: [PATCH 10/12] =?UTF-8?q?=D0=A1=D1=82=D1=80=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=87=D0=BA=D0=B0=20=D0=B7=D0=B0=D0=B2=D0=B5=D1=80=D1=88=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=BE=D1=84=D0=BE=D1=80=D0=BC=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=BD=D0=B0=D0=BA=D0=BB=D0=B0=D0=B4=D0=BD?= =?UTF-8?q?=D0=BE=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/Waybill/__init__.py | 3 +-- App/Waybill/templates/order_finish.html | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 App/Waybill/templates/order_finish.html diff --git a/App/Waybill/__init__.py b/App/Waybill/__init__.py index d3abfd5..55276bc 100644 --- a/App/Waybill/__init__.py +++ b/App/Waybill/__init__.py @@ -42,7 +42,6 @@ def save_order(): result = transaction_order_model(user_id, current_date) if result.status: print("Order success") - return "OK" - # return render_template("order_finish.html", order_id = result.result[0]) + return render_template("order_finish.html", order_id = result.result[0]) else: return render_template("error.html", error_message=result.error_message) \ No newline at end of file diff --git a/App/Waybill/templates/order_finish.html b/App/Waybill/templates/order_finish.html new file mode 100644 index 0000000..dd7b64f --- /dev/null +++ b/App/Waybill/templates/order_finish.html @@ -0,0 +1,20 @@ + + + + + Накладная оформлена + + + + +
+
+

Накладная оформлена

+

Номер вашей накладной: {{ order_id }}

+ +
+
+ + From 55a4e0db48cfbbae09817ed0da4b855bf2e66546 Mon Sep 17 00:00:00 2001 From: Artur Date: Wed, 4 Dec 2024 01:33:31 +0300 Subject: [PATCH 11/12] =?UTF-8?q?=D0=9E=D1=84=D0=BE=D1=80=D0=BC=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B3=D0=BB=D0=B0=D0=B2=D0=BD=D0=BE?= =?UTF-8?q?=D0=B3=D0=BE=20=D0=BC=D0=B5=D0=BD=D0=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/templates/main_menu.html | 40 +++++++++++++----------------------- 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/App/templates/main_menu.html b/App/templates/main_menu.html index fa2a4ec..473c62e 100644 --- a/App/templates/main_menu.html +++ b/App/templates/main_menu.html @@ -35,19 +35,27 @@
+ {% if 'role' not in ses %} +
+

Для доступа к функциям системы необходимо авторизоваться

+
+ {% endif %} + {% if 'role' in ses and ses['access_user'] == 'external_users' %} +
+

Новая накладная

+ + + +
+ {% endif %} + {% if 'role' in ses and ses['access_user'] == 'internal_users' %}
- {% if ses['access_user'] == 'internal_users' %}

Запросы

- @@ -57,32 +65,12 @@ >

Отчёты

-
- {% else %} -
-
-
-

Новая накладная

- - - - {% endif %}
From 392ba2161f1bd9b57d0f5b3e6cf71ace7987053e Mon Sep 17 00:00:00 2001 From: Anton Kamalov Date: Wed, 4 Dec 2024 01:37:49 +0300 Subject: [PATCH 12/12] =?UTF-8?q?=D0=92=D0=BE=D0=B7=D0=B2=D1=80=D0=B0?= =?UTF-8?q?=D1=89=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B2=20=D0=B3=D0=BB=D0=B0?= =?UTF-8?q?=D0=B2=D0=BD=D0=BE=D0=B5=20=D0=BC=D0=B5=D0=BD=D1=8E=20=D0=BF?= =?UTF-8?q?=D1=80=D0=B8=20=D0=BE=D1=84=D0=BE=D1=80=D0=BC=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B8=20=D0=BD=D0=B0=D0=BA=D0=BB=D0=B0=D0=B4=D0=BD=D0=BE?= =?UTF-8?q?=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/Waybill/templates/waybill.html | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/App/Waybill/templates/waybill.html b/App/Waybill/templates/waybill.html index 937ed2e..9b0603a 100644 --- a/App/Waybill/templates/waybill.html +++ b/App/Waybill/templates/waybill.html @@ -24,16 +24,22 @@
- +

Накладная

{% if waybill %} {% for item in waybill %} {{ card.render_item(item, show_form = False, show_amount = True) }} {% endfor %} - + {% else %} Ваша накладная пуста + {% endif %}