Merge branch 'Debug' of ParkSuMin/Cursovaya into main

This commit is contained in:
2024-12-06 14:15:46 +00:00
committed by Gogs
46 changed files with 189 additions and 316 deletions

View File

@@ -1,4 +1,4 @@
from flask import request, Blueprint, render_template, session, current_app, redirect, url_for
from flask import Blueprint, render_template, redirect, url_for, request, session
from .auth_model import auth_model
auth_bp = Blueprint('auth_bp', __name__, template_folder='templates')

View File

@@ -1,6 +1,8 @@
from dataclasses import dataclass
from .db.select import select_list
from .db.sql_provider import SQLProvider
from Database.work import select_list
from Database.sql_provider import SQLProvider
from flask import current_app
import os
@@ -12,8 +14,10 @@ class InfoRespronse:
status: bool
def auth_model(input_data) -> InfoRespronse:
db_config = current_app.config['db_config']
_sql = sql_provider.get('auth.sql', input_data)
user = select_list(current_app.config['db_config'], _sql)
user = select_list(db_config, _sql)
if user is None:
return InfoRespronse((),
error_message = 'Ошибка при подключении к БД',

View File

@@ -1,12 +0,0 @@
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

View File

@@ -1,13 +0,0 @@
.
├── auth_model.py - реализация модели авторизации
├── db
│   ├── DBconnect.py - коннектор к СУБД
│   ├── __init__.py - файл для инициализации db как модуль
│   ├── select.py - файл для выполнения select-запросов к СУБД
│   └── sql_provider.py - SQL-провайдер для формирования запроса к СУБД
├── __init__.py - файл для инициализации Auth как модуль
├── sql
│   └── auth.sql - sql-запрос, проверяющий наличие пользователя в СУБД
└── templates
└── auth.html - шаблон для страницы авторизации

View File

@@ -13,7 +13,8 @@ class DBContextManager:
port=self.db_config['port'],
user=self.db_config['user'],
password=self.db_config['password'],
db=self.db_config['db']
db=self.db_config['db'],
charset=self.db_config['charset']
)
self.cursor = self.connection.cursor()
return self.cursor

View File

@@ -11,7 +11,7 @@ def select_list(db_config, sql) -> list:
lst = [dict(zip(schema, row)) for row in result]
return lst
def procedure(db_config, name, args: tuple):
def procedure(db_config, name, args: tuple) -> list:
with DBContextManager(db_config) as cursor:
if cursor is None:
raise ValueError("Cursor not created")
@@ -21,3 +21,7 @@ def procedure(db_config, name, args: tuple):
schema = cursor.description[0]
lst = dict(zip(schema, result))
return lst
def transaction(cursor, sql):
cursor.execute(sql)
return True

View File

@@ -5,10 +5,10 @@ from datetime import date
from .report_model import view_report_model, create_report_model
import json
with open(path.join(path.dirname(__file__), 'reports.json')) as f:
with open(path.join(path.dirname(__file__), 'reports.json'), encoding='utf-8') as f:
report_list = json.load(f)
report_bp = Blueprint('report_bp', __name__, template_folder='templates')
report_bp = Blueprint('report_bp', __name__, template_folder='templates', static_folder='static')
@report_bp.route('/menu')
@check_auth

View File

@@ -1,34 +0,0 @@
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

View File

@@ -1,14 +0,0 @@
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)

View File

@@ -1,16 +0,0 @@
.
├── db
│   ├── DBconnect.py - коннектор к СУБД
│   ├── __init__.py - файл для инициализации db как модуль
│   ├── sql_provider.py - SQL-провайдер для формирования запроса к СУБД
│   └── work.py - файл для выполнения select и call запросов
├── __init__.py - файл для инициализации Report как модуль
├── report_model.py - реализация модели варианта работы с отчётами
├── reports.json - файл с информацией о вариантах отчётов
├── sql 
│   ├── sellers_report.sql - sql-запрос для просмотра отчёта о поставках поставщиков
│   └── workpiece_report.sql - sql-запрос для просмотра отчёта о поставках заготовок
└── templates
├── OK.html - шаблон для вывода информации об успешном добавлении отчета в БД
├── report_basic.html - шаблон для ввода параметров просмотра/создания отчёта
└── report_menu.html - шаблон для выбора просмотра/создания отчёта

View File

@@ -1,6 +1,8 @@
from dataclasses import dataclass
from .db.work import select_list, procedure
from .db.sql_provider import SQLProvider
from Database.work import select_list, procedure
from Database.sql_provider import SQLProvider
from flask import current_app, session
from os import path
@@ -12,7 +14,9 @@ class InfoRespronse:
status: bool
def check_report(input_data: dict) -> bool:
result = procedure(current_app.config['db_config'], 'check_report', tuple(input_data.values()))
db_config = current_app.config['db_config']
result = procedure(db_config, 'check_report', tuple(input_data.values()))
if result is None or result['exist'] == 0:
return False
return True
@@ -32,9 +36,10 @@ def view_report_model(request, report_list: dict) -> InfoRespronse:
error_message = 'Отчет не найден',
status=False)
db_config = current_app.config['db_config']
view_script = report_list[id]['data']['view']
_sql = sql_provider.get(f'{view_script}.sql', data)
result = select_list(current_app.config['db_config'], _sql)
result = select_list(db_config, _sql)
if result is None:
return InfoRespronse((),
error_message = 'Ошибка в подключении к базе данных. Свяжитесь с администратором',
@@ -60,9 +65,10 @@ def create_report_model(request, report_list: dict) -> InfoRespronse:
error_message = 'Отчет уже существует',
status=False)
db_config = current_app.config['db_config']
proc_name = report_list[id]['data']['procedure']
args = tuple(data.values())
result = procedure(current_app.config['db_config'], proc_name, args)
result = procedure(db_config, proc_name, args)
if result is None:
return InfoRespronse((),

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8">
<title>{{ title }}</title>
<link href="/static/css/main.css" type="text/css" rel="stylesheet">
<link href="/static/css/report.css" type="text/css" rel="stylesheet">
<link href="static/css/report.css" type="text/css" rel="stylesheet">
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet"
@@ -14,7 +14,7 @@
rel="stylesheet"
/>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="/static/js/check.js"></script>
<script src="static/js/check.js"></script>
</head>
<body class="p-3 m-0 border-0 bd-example m-0 border-0">
<div class="row flex-nowrap justify-content-between pb-5">

View File

@@ -29,7 +29,7 @@
<div class="col-12 d-flex justify-content-center">
<div class="btn-group py-5" role="group" aria-label="Basic example">
<a href="{{ url_for('report_bp.create') }}"><button type="button" class="btn btn-primary me-2">Создать отчет</button></a>
<a href="{{ url_for('report_bp.view') }}"><button type="button" class="btn btn-secondary">Читать отчеты</button></a>
<a href="{{ url_for('report_bp.view') }}"><button type="button" class="btn btn-primary">Читать отчеты</button></a>
</div>
</div>
</div>

View File

@@ -1,34 +0,0 @@
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

View File

@@ -1,12 +0,0 @@
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

View File

@@ -1,14 +0,0 @@
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)

View File

@@ -1,18 +0,0 @@
.
├── db
│   ├── DBconnect.py - коннектор к СУБД
│   ├── __init__.py - файл для инициализации db как модуль
│   ├── select.py - файл для выполнения select-запросов к СУБД
│   └── sql_provider.py - SQL-провайдер для формирования запроса к СУБД
├── __init__.py - файл для инициализации Requests как модуль
├── requests_model.py - реализация модели варианта работы с запросами
├── sql
│   ├── materials_names.sql - sql-запрос для получения списка материалоа заготовок
│   ├── sellers_names.sql - sql-запрос для получения списка поставщиков
│   ├── ship_seller.sql - sql-запрос для получения списка поставок поставщиком
│   └── sklad_material.sql - sql-запрос для получения списка заготовок на складе
├── templates
│   ├── sellers_ship.html - шаблон для формы передачи параметров для запроса всех поставок выбранного поставщика
│   ├── zagotovki.html - шаблон для формы передачи параметров для запроса количества заготовок на складе
│   └── zapros_menu.html - шаблон для выбора варианта отчёта
└── zapros_menu.json - файл с названиями запросов и их ссылками

View File

@@ -1,6 +1,8 @@
from dataclasses import dataclass
from .db.select import select_list
from .db.sql_provider import SQLProvider
from Database.work import select_list
from Database.sql_provider import SQLProvider
from flask import current_app
from os import path
@@ -12,8 +14,10 @@ class InfoRespronse:
status: bool
def sellers_names() -> InfoRespronse:
db_config = current_app.config['db_config']
_sql = sql_provider.get('sellers_names.sql', {})
result = select_list(current_app.config['db_config'], _sql)
result = select_list(db_config, _sql)
if result is None:
return InfoRespronse((),
error_message = 'Ошибка в подключении к базе данных. Свяжитесь с администратором',
@@ -21,8 +25,10 @@ def sellers_names() -> InfoRespronse:
return InfoRespronse(result, error_message='', status=True)
def materials_names() -> InfoRespronse:
db_config = current_app.config['db_config']
_sql = sql_provider.get('materials_names.sql', {})
result = select_list(current_app.config['db_config'], _sql)
result = select_list(db_config, _sql)
if result is None:
return InfoRespronse((),
error_message = 'Ошибка в подключении к базе данных. Свяжитесь с администратором',
@@ -30,9 +36,11 @@ def materials_names() -> InfoRespronse:
return InfoRespronse(result, error_message='', status=True)
def sklad(request) -> InfoRespronse:
db_config = current_app.config['db_config']
material = dict(request.form)
_sql = sql_provider.get('sklad_material.sql', material)
result = select_list(current_app.config['db_config'], _sql)
result = select_list(db_config, _sql)
if result is None:
return InfoRespronse((),
error_message = 'Ошибка в подключении к базе данных. Свяжитесь с администратором',
@@ -41,9 +49,11 @@ def sklad(request) -> InfoRespronse:
def materials_per_seller(request) -> InfoRespronse:
db_config = current_app.config['db_config']
seller = dict(request.form)
_sql = sql_provider.get('ship_seller.sql', seller)
result = select_list(current_app.config['db_config'], _sql)
result = select_list(db_config, _sql)
if result is None:
return InfoRespronse((),
error_message = 'Ошибка в подключении к базе данных. Свяжитесь с администратором',

View File

@@ -1,7 +1,7 @@
from flask import request, Blueprint, render_template, session, redirect, url_for
from flask import Blueprint, render_template, redirect, url_for, session, request
from checker import check_auth
from .model import index_waybill, form_waybill, clear, button_click, transaction_order_model
from datetime import date
from datetime import datetime
waybill_bp = Blueprint('waybill_bp', __name__, template_folder='templates', static_folder='static')
@@ -37,7 +37,7 @@ def save_order():
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")
current_date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
result = transaction_order_model(user_id, current_date)
if result.status:

View File

@@ -1,34 +0,0 @@
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

View File

@@ -1,14 +0,0 @@
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)

View File

@@ -1,16 +0,0 @@
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
def transaction(cursor, sql):
cursor.execute(sql)
return True

View File

@@ -1,11 +1,11 @@
from .db.sql_provider import SQLProvider
from .db.work import select_list, transaction
from .db.DBconnect import DBContextManager
from Database.sql_provider import SQLProvider
from Database.work import select_list
from Database.DBconnect import DBContextManager
from flask import current_app, session
from dataclasses import dataclass
from datetime import date
from .cache.wrapper import fetch_from_cache
from cache.wrapper import fetch_from_cache
import os
@dataclass
@@ -21,11 +21,15 @@ def clear():
session.pop('waybill')
def form_waybill() -> list:
db_config = current_app.config['db_config']
cache_config = current_app.config['cache_config']
current_waybill = session.get('waybill',{})
waybill = []
for k,v in current_waybill.items():
_sql = sql_provider.get('one_good.sql', dict(work_id=k))
product = select_list(current_app.config['db_config'], _sql)[0]
cache_select = fetch_from_cache(f'product_{k}', cache_config)(select_list)
product = cache_select(db_config, _sql)[0]
product['amount'] = v
waybill.append(product)
return waybill
@@ -37,6 +41,8 @@ def index_waybill() -> list:
cache_select = fetch_from_cache('items_cached', cache_config)(select_list)
_sql = sql_provider.get('goods.sql', {})
products = cache_select(db_config, _sql)
if products == None:
return []
return products
@@ -72,13 +78,6 @@ def button_click(request):
print(session['waybill'])
session.modified = True
# elif request.form.get('product_display_plus'):
# # increasing count in waybill
# 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
@@ -101,20 +100,17 @@ def transaction_order_model(user_id: int, current_date: date):
with DBContextManager(db_config) as cursor:
data = dict(e_user_id=user_id, e_order_date=current_date, e_total=total)
_sql = sql_provider.get('create_order.sql', data)
try:
_sql = sql_provider.get('create_order.sql', data)
cursor.execute(_sql)
except:
return InfoRespronse((), error_message="Заказ не был создан", status=False)
order_id = cursor.lastrowid
for key, value in waybill.items():
_sql = sql_provider.get('insert_order_line.sql',
dict(e_order_id = order_id,
e_price = 0,
e_prod_id = int(key),
e_amount = int(value)))
try:
cursor.execute(_sql)
except:
return InfoRespronse((), error_message="Заказ не был создан", status=False)

View File

@@ -0,0 +1 @@
SELECT price FROM workpiece WHERE work_id = $e_prod_id

View File

@@ -1 +1 @@
SELECT work_id, name, price, material, count FROM workpiece
SELECT work_id, name, price, material, count, weight FROM workpiece

View File

@@ -1,2 +1 @@
INSERT INTO `waybill_lines` VALUES ($e_order_id, $e_prod_id,
(SELECT price FROM workpiece WHERE work_id = $e_prod_id), $e_amount);
INSERT INTO `waybill_lines` VALUES ($e_order_id, $e_prod_id, $e_price, $e_amount);

View File

@@ -4,6 +4,8 @@
<div class="card-body">
<h6 class="card-title">{{ item['name'] }}</h6>
<p class="card-text">Цена: {{ item['price'] }} ₽</p>
<p class="card-text">Материал: {{ item['material'] }}</p>
<p class="card-text">Вес: {{ item['weight'] }} г</p>
{% if show_amount %}
<span>Количество: {{item['amount']}}</span><br>
<form method="POST" action="">

13
App/auth.txt Normal file
View File

@@ -0,0 +1,13 @@
.
├── Database
│   ├── DBconnect.py - коннектор к СУБД
│   ├── __init__.py
│   ├── sql_provider.py - SQL-провайдер для формирования запроса к СУБД
│   └── work.py - файл для выполнения запросов к СУБД
└── Auth
   ├── auth_model.py - реализация модели авторизации
   ├── __init__.py
   ├── sql
   │   └── auth.sql - sql-запрос, проверяющий наличие пользователя в СУБД
   └── templates
   └── auth.html - шаблон для страницы авторизации

View File

@@ -1,17 +1,16 @@
from functools import wraps
from Waybill.cache import RedisCache
from . import RedisCache
def fetch_from_cache(cache_name: str, cache_config: dict):
cache_conn = RedisCache(cache_config['redis'])
ttl = cache_config['ttl']
"""
It checks if a cached value exists for a given cache_name.
If a cached value exists, it returns the cached value.
If no cached value exists, it calls the original function f with the provided arguments, caches the result, and then returns the result.
"""
def decorator(f):
# как оно работает
# лезем в кэш и смотрим, есть ли там что-то
# если есть, то возвращаем кэшированную информацию
# если нет, то запускаем декорируемую функцию
# достаём оттуда информацию
# заносим её в кэш
# возвращаем кэшированную информацию
@wraps(f)
def wrapper(*args, **kwargs):
cached_value = cache_conn.get_value(cache_name)

View File

@@ -3,5 +3,6 @@
"port": 3306,
"user": "manager",
"password": "ilikepizza",
"db": "sklad"
"db": "sklad",
"charset": "utf8"
}

View File

@@ -1,16 +0,0 @@
.
├── app.py - основное приложение
├── checker.py - декораторы
├── data
│   ├── config.json - конфигурация для подключения к СУБД
│   └── db_access.json - доступ пользователей к вариантам использования ИС
├── static
│   └── css - стили для страниц
│   ├── auth.css
│   ├── main.css
│   └── output.css
└── templates
├── error.html - универсальный шаблон для ошибок
├── main_menu.html - шаблон главного меню
└── output.html - универсальный шаблон для вывода результатов

19
App/main.txt Normal file
View File

@@ -0,0 +1,19 @@
.
├── app.py - основное приложение
├── checker.py - декораторы
├── data
│   ├── config.json - конфигурация для подключения к СУБД
│   ├── db_access.json - доступ пользователей к вариантам использования ИС
│   └── redis_config.json - конфигурация для подключения к Redis
├── Database
│   ├── DBconnect.py - коннектор к СУБД
│   ├── __init__.py
│   ├── sql_provider.py - SQL-провайдер для формирования запроса к СУБД
│   └── work.py - файл для выполнения запросов к СУБД
├── static
│   └── css - стили для страниц
│   └── main.css
└── templates - стандартные шаблоны для страниц
   ├── error.html - шаблон для ошибок
   ├── main_menu.html - шаблон главного меню
   └── output.html - шаблон для вывода результатов в формате таблицы

22
App/report.txt Normal file
View File

@@ -0,0 +1,22 @@
.
├── Database
│   ├── DBconnect.py - коннектор к СУБД
│   ├── __init__.py
│   ├── sql_provider.py - SQL-провайдер для формирования запроса к СУБД
│   └── work.py - файл для выполнения запросов к СУБД
└── Report
   ├── __init__.py
   ├── report_model.py - реализация модели работы с отчётами
   ├── reports.json - файл с информацией о вариантах отчётов
   ├── sql
   │   ├── sellers_report.sql - sql-запрос для просмотра отчёта о поставках поставщиков
   │ └── workpiece_report.sql - sql-запрос для просмотра отчёта о поставках заготовок
   ├── static
   │   ├── css - стили страниц
   │   │   └── report.css
   │   └── js
   │   └── check.js - проверка периода формирования отчёта
   └── templates
   ├── OK.html - шаблон для вывода информации об успешном добавлении отчета в БД
├── report_basic.html - шаблон для ввода параметров просмотра/создания отчёта
└── report_menu.html - шаблон для выбора просмотра/создания отчёта

19
App/requests.txt Normal file
View File

@@ -0,0 +1,19 @@
.
├── Database
│   ├── DBconnect.py - коннектор к СУБД
│   ├── __init__.py
│   ├── sql_provider.py - SQL-провайдер для формирования запроса к СУБД
│   └── work.py - файл для выполнения запросов к СУБД
└── Requests
   ├── __init__.py
   ├── requests_model.py - реализация модели работы с запросами
   ├── sql
    │   ├── materials_names.sql - sql-запрос для получения списка материалов заготовок
   │   ├── sellers_names.sql - sql-запрос для получения списка поставщиков
   │   ├── ship_seller.sql - sql-запрос для получения списка поставок поставщиком
   │   └── sklad_material.sql - sql-запрос для получения списка заготовок на складе
   ├── templates
   │   ├── sellers_ship.html - шаблон для формы передачи параметров для запроса всех поставок выбранного поставщика
│   ├── zagotovki.html - шаблон для формы передачи параметров для запроса количества заготовок на складе
│   └── zapros_menu.html - шаблон для выбора варианта отчёта
   └── zapros_menu.json - файл с названиями запросов и их ссылками

View File

@@ -1,5 +0,0 @@
form[name="auth"] input[type="submit"] {
display: block;
margin: 10px auto;
background-color: #f2c464;
}

View File

@@ -33,8 +33,11 @@
</div>
</div>
</header>
{% if 'role' in ses and ses['access_user'] == 'internal_users'%}
<h1 class="justify-content-center">Ваша роль: {{ ses['role'] }}</h1>
{% endif %}
<main class="flex-shrink-0">
<div class="d-flex gap-2 justify-content-center py-5">
<div class="d-flex gap-2 justify-content-center py-3">
{% if 'role' not in ses %}
<div class="text-center">
<h2 class="fs-2 text-body-emphasis mb-4">Для доступа к функциям системы необходимо авторизоваться</h2>

25
App/waybill.txt Normal file
View File

@@ -0,0 +1,25 @@
.
├── cache - модуль для кэширования данных
│ ├── __init__.py
│ └── wrapper.py - файл с функцией-обёрткой для кэширования функций
├── Database
│   ├── DBconnect.py - коннектор к СУБД
│   ├── __init__.py
│   ├── sql_provider.py - SQL-провайдер для формирования запроса к СУБД
│   └── work.py - файл для выполнения запросов к СУБД
└── Waybill
├── __init__.py
├── model.py - реализация модели оформления накладной
├── sql
│ ├── create_order.sql - SQL запрос на создание накладной
│ ├── goods.sql - SQL запрос на получение списка заготовок
│ ├── insert_order_line.sql - SQL запрос на добавление позиции в накладную
│ └── one_good.sql - SQL запрос на получение информации о заготовке
├── static
│ └── css - стили страниц
│ └── waybill.css
└── templates
├── card.html - шаблон для отображения карточки заготовки
├── order_finish.html - шаблон для страницы о завершении оформления накладной
└── waybill.html - шаблон для страницы формированиянакладной

1
cache_delete.sh Executable file
View File

@@ -0,0 +1 @@
find . -type d -name "__pycache__" -exec rm -rf {} +