Fix in Requests + in Report part

This commit is contained in:
2024-11-14 19:19:48 +03:00
parent 7d939ef1e4
commit 19d5ce088e
18 changed files with 222 additions and 54 deletions

View File

@@ -1,21 +1,67 @@
from flask import request, Blueprint, render_template
from flask import request, Blueprint, render_template, session, url_for
from checker import check_auth
from os import path
from .report_model import sales_report, make_report
import json
with open(path.join(path.dirname(__file__), 'reports.json')) as f:
report_list = json.load(f)
report_bp = Blueprint('report_bp', __name__, template_folder='templates')
@report_bp.route('/', methods=['GET', 'POST'])
@report_bp.route('/menu')
@check_auth
def menu():
if request.method == 'GET':
return render_template('report_menu.html', options=report_list)
@report_bp.route('/quaterly', methods=['GET', 'POST'])
return render_template('report_menu.html')
@report_bp.route('/create', methods=['GET', 'POST'])
@check_auth
def quaterly():
def create():
if request.method == 'GET':
return render_template('quaterly.html')
return render_template('report_basic.html',
write=True,
title='Создание отчета',
items = report_list)
else:
data = dict(month=request.form.get('month'), year=request.form.get('year'))
id = request.form.get('category')
with open(path.join(path.dirname(__file__), f'access/{id}.json')) as f:
report_access = json.load(f)
if session['role'] in report_access['write']:
proc_name = report_access['procedure']
ready_report = make_report(data, proc_name)
if ready_report.status:
return render_template("OK.html")
else:
return render_template("error.html", error_message=ready_report.error_message)
else:
return render_template("error.html", error_message='Недостаточно прав для создания данного отчета!')
@report_bp.route('/view', methods=['GET', 'POST'])
@check_auth
def view():
if request.method == 'GET':
return render_template('report_basic.html',
write=False,
title='Просмотр отчета',
items = report_list)
else:
data = dict(month=request.form.get('month'), year=request.form.get('year'))
id = request.form.get('category')
with open(path.join(path.dirname(__file__), f'access/{id}.json')) as f:
report_access = json.load(f)
if session['role'] in report_access['read']:
ready_report = sales_report(data, report_access['view'])
if ready_report.status:
title= f'{report_access["title"]} за {data["month"]}-{data["year"]}'
return render_template("output.html", items=ready_report.result,
header=title,
link = url_for('report_bp.menu'))
else:
return render_template("error.html", error_message=ready_report.error_message)
else:
return render_template("error.html", error_message='Недосточно прав для чтения данного отчета!')

7
App/Report/access/1.json Normal file
View File

@@ -0,0 +1,7 @@
{
"title" : "Отчет о продажах",
"write" : ["Менеджер"],
"read" : ["Управляющий"],
"view" : "view_report",
"procedure" : "generate_report"
}

View File

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

View File

View File

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

23
App/Report/db/work.py Normal file
View File

@@ -0,0 +1,23 @@
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 procedure(db_config, name, args: tuple):
with DBContextManager(db_config) as cursor:
if cursor is None:
raise ValueError("Cursor not created")
else:
cursor.callproc(name, args)
result = cursor.fetchall()[0]
schema = cursor.description[0]
lst = dict(zip(schema, result))
return lst

View File

@@ -1,3 +1,3 @@
[
{"name": "Квартальный отчет передвижений заготовок", "url": "report_bp.quaterly"}
{"id": 1, "name": "Покупки за месяц", "json_file": "access/sales.json"}
]

View File

@@ -0,0 +1,4 @@
SELECT EXISTS (
SELECT 1 FROM reports
WHERE month = $month AND year = $year
) AS exist;

View File

@@ -1,11 +0,0 @@
SELECT sellers.name AS 'Поставщик',
w.date_of_delivery AS 'Дата поставки',
SUM(wl.count) AS 'Общее количество заготовок',
SUM(wl.price) AS 'Общая стоимость поставленных заготовок'
FROM waybill w
JOIN waybill_lines wl USING(waybill_id)
JOIN workpiece USING(work_id)
JOIN sellers USING(sel_id)
WHERE workpiece.material = '${material}'
AND (w.date_of_delivery BETWEEN '${date_from}' AND '${date_to}')
GROUP BY sellers.name, w.date_of_delivery;

View File

@@ -0,0 +1,5 @@
SELECT name_of_product AS 'Наименование',
count_of_bought AS 'Количество',
sum AS 'Общая стоимость'
FROM reports
WHERE month = '$month' AND year = '$year';

View File

@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Успех</title>
<link href="/static/css/auth.css" type="text/css" rel="stylesheet">
<link href="/static/css/main.css" type="text/css" rel="stylesheet">
</head>
<body>
<h1>Успешно!</h1>
<p>Отчет успешно добавлен в базу данных!</p>
<a href="{{ url_for('index') }}"><button>На главную страницу</button></a>
<a href="{{ url_for('report_bp.menu') }}"><button>В меню отчетов</button></a>
</body>
</html>

View File

@@ -1,18 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Квартальный отчет</title>
<link href="/static/css/main.css" type="text/css" rel="stylesheet">
</head>
<body>
<div class="logout">
<a href="{{ url_for('logout') }}"><button>Выход</button></a>
</div>
<!-- Not implemented -->
<h1>Заглушка для квартального отчета</h1>
<div class="return">
<a href="{{ url_for('index') }}"><button>Главное меню</button></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,45 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ title }}</title>
<link href="/static/css/main.css" type="text/css" rel="stylesheet">
</head>
<body>
<div class="logout">
<a href="{{ url_for('logout') }}"><button>Выход</button></a>
</div>
<h1>{{ title }}</h1>
<form action="" method="post">
{% for item in items %}
<select name="category" required>
<option value="{{ item['id'] }}">{{ item['name'] }}</option>
</select>
{% endfor %}
<select name="month" required>
<option value="1">Январь</option>
<option value="2">Февраль</option>
<option value="3">Март</option>
<option value="4">Апрель</option>
<option value="5">Май</option>
<option value="6">Июнь</option>
<option value="7">Июль</option>
<option value="8">Август</option>
<option value="9">Сентябрь</option>
<option value="10">Октябрь</option>
<option value="11">Ноябрь</option>
<option value="12">Декабрь</option>
</select>
<input type="number" name="year" value="2024" min="1990" max="2100" required>
{% if write %}
<button type="submit" value="write">Создать</button>
{% else %}
<button type="submit" value="read">Просмотр</button>
{% endif %}
</form>
<div class="return">
<a href="{{ url_for('index') }}"><button>Главное меню</button></a>
</div>
</body>
</html>

View File

@@ -10,11 +10,10 @@
<a href="{{ url_for('logout') }}"><button>Выход</button></a>
</div>
<h1>Выберите вариант отчетов</h1>
<nav class="menu">
{% for point in options %}
<a href="{{ url_for(point['url']) }}"><button>{{ point['name'] }}</button></a>
{% endfor %}
</nav>
<div style="text-align: center; margin: 20px 0;">
<a href="{{ url_for('report_bp.create') }}"><button>Создать отчет</button></a>
<a href="{{ url_for('report_bp.view') }}"><button>Читать отчеты</button></a>
</div>
<div class="return">
<a href="{{ url_for('index') }}"><button>Главное меню</button></a>
</div>

View File

@@ -1,6 +1,6 @@
from dataclasses import dataclass
from db.select import select_list
from db.sql_provider import SQLProvider
from .db.select import select_list
from .db.sql_provider import SQLProvider
from flask import current_app
from os import path

View File

@@ -26,4 +26,6 @@ def index():
def logout():
session.clear()
return render_template('main_menu.html', ses=session)
app.run(port=5002, host='0.0.0.0')
if __name__ == '__main__':
app.run(port=5002, host='0.0.0.0')

View File

@@ -1,5 +1,11 @@
{
"Менеджер": ["auth_bp", "requests_bp"],
"Управляющий": ["auth_bp", "requests_bp", "report_bp"],
"Поставщик": ["auth_bp", "waybill_bp"]
}
"Менеджер": [
"requests_bp",
"report_bp"],
"Управляющий": [
"requests_bp",
"report_bp"],
"Поставщик": [
"waybill_bp"]
}

View File

@@ -11,18 +11,15 @@
<a href="{{ url_for('logout') }}"><button>Выход</button></a>
</div>
<h1>Здравствуйте, {{ ses['login'] }}!</h1>
<h2> Ваша роль: {{ ses['role'] }}</h2>
{% if ses['access_user'] == 'internal_users' %}
<h2> Ваша роль: {{ ses['role'] }}</h2>
<!-- Not implemented -->
<nav class="menu">
<a href="{{ url_for('requests_bp.requests') }}"><button>Запросы</button></a>
<a href="{{ url_for('report_bp.menu') }}"><button>Отчеты</button></a>
</nav>
{% else %}
<nav class="menu">
<!-- Not implemented -->
<a href="{{ url_for('waybill_bp.waybill') }}"><button>Новая накладная</button></a>
</nav>
<p>Not implemented</p>
{% endif %}
{% else %}
<div class="login">