аптечный склад

This commit is contained in:
commit 211f5a942b
23 changed files with 1029 additions and 0 deletions

Binary file not shown.

Binary file not shown.

BIN
Resource/masterpol.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

196
app.py Normal file
View file

@ -0,0 +1,196 @@
from flask import Flask, render_template, request, redirect, url_for, flash
import sqlite3
from datetime import datetime, timedelta
app = Flask(__name__)
app.secret_key = 'apteka_secret'
def get_db():
conn = sqlite3.connect('pharmacy.db')
conn.row_factory = sqlite3.Row
return conn
def calculate_order_price(medicine_id, quantity):
"""Расчет стоимости заказа с учетом срока годности и сезона"""
conn = get_db()
medicine = conn.execute('''
SELECT price, expiration_date, season_coeff FROM medicines WHERE id = ?
''', (medicine_id,)).fetchone()
conn.close()
if not medicine:
return 0
base = medicine['price'] * quantity
date_str = medicine['expiration_date'][:10]
exp_date = datetime.strptime(date_str, '%Y-%m-%d').date()
days_left = (exp_date - datetime.now().date()).days
if days_left < 0:
exp_factor = 0.1
elif days_left < 30:
exp_factor = 0.7
elif days_left < 90:
exp_factor = 0.9
else:
exp_factor = 1.0
season_factor = medicine['season_coeff']
return round(base * exp_factor * season_factor, 2)
# ========== ГЛАВНАЯ ==========
@app.route('/')
def index():
conn = get_db()
medicines = conn.execute('''
SELECT m.*, c.name as category_name, man.name as manufacturer_name
FROM medicines m
LEFT JOIN categories c ON m.category_id = c.id
LEFT JOIN manufacturers man ON m.manufacturer_id = man.id
ORDER BY m.name
''').fetchall()
conn.close()
return render_template('index.html', medicines=medicines, calculate=calculate_order_price)
# ========== ПРОИЗВОДИТЕЛИ ==========
@app.route('/manufacturers')
def manufacturers():
conn = get_db()
mans = conn.execute('SELECT * FROM manufacturers ORDER BY name').fetchall()
conn.close()
return render_template('manufacturers.html', manufacturers=mans)
@app.route('/add_manufacturer', methods=['GET', 'POST'])
def add_manufacturer():
if request.method == 'POST':
name = request.form['name']
country = request.form.get('country', '')
phone = request.form.get('phone', '')
email = request.form.get('email', '')
conn = get_db()
conn.execute('''
INSERT INTO manufacturers (name, country, phone, email)
VALUES (?, ?, ?, ?)
''', (name, country, phone, email))
conn.commit()
conn.close()
flash('Производитель добавлен!', 'success')
return redirect(url_for('manufacturers'))
return render_template('add_manufacturer.html')
@app.route('/edit_manufacturer/<int:id>', methods=['GET', 'POST'])
def edit_manufacturer(id):
conn = get_db()
if request.method == 'POST':
name = request.form['name']
country = request.form.get('country', '')
phone = request.form.get('phone', '')
email = request.form.get('email', '')
conn.execute('''
UPDATE manufacturers
SET name=?, country=?, phone=?, email=?
WHERE id=?
''', (name, country, phone, email, id))
conn.commit()
conn.close()
flash('Производитель обновлен!', 'success')
return redirect(url_for('manufacturers'))
man = conn.execute('SELECT * FROM manufacturers WHERE id = ?', (id,)).fetchone()
conn.close()
return render_template('edit_manufacturer.html', manufacturer=man)
@app.route('/delete_manufacturer/<int:id>', methods=['POST'])
def delete_manufacturer(id):
conn = get_db()
conn.execute('DELETE FROM manufacturers WHERE id = ?', (id,))
conn.commit()
conn.close()
flash('Производитель удален!', 'success')
return redirect(url_for('manufacturers'))
# ========== КАТЕГОРИИ ==========
@app.route('/categories')
def categories():
conn = get_db()
cats = conn.execute('SELECT * FROM categories ORDER BY name').fetchall()
conn.close()
return render_template('categories.html', categories=cats)
@app.route('/add_category', methods=['GET', 'POST'])
def add_category():
if request.method == 'POST':
name = request.form['name']
description = request.form.get('description', '')
conn = get_db()
conn.execute('INSERT INTO categories (name, description) VALUES (?, ?)',
(name, description))
conn.commit()
conn.close()
flash('Категория добавлена!', 'success')
return redirect(url_for('categories'))
return render_template('add_category.html')
@app.route('/edit_category/<int:id>', methods=['GET', 'POST'])
def edit_category(id):
conn = get_db()
if request.method == 'POST':
name = request.form['name']
description = request.form.get('description', '')
conn.execute('UPDATE categories SET name=?, description=? WHERE id=?',
(name, description, id))
conn.commit()
conn.close()
flash('Категория обновлена!', 'success')
return redirect(url_for('categories'))
category = conn.execute('SELECT * FROM categories WHERE id = ?', (id,)).fetchone()
conn.close()
return render_template('edit_category.html', category=category)
@app.route('/delete_category/<int:id>', methods=['POST'])
def delete_category(id):
conn = get_db()
conn.execute('DELETE FROM categories WHERE id = ?', (id,))
conn.commit()
conn.close()
flash('Категория удалена!', 'success')
return redirect(url_for('categories'))
# ========== ЛЕКАРСТВА ==========
@app.route('/add_medicine', methods=['GET', 'POST'])
def add_medicine():
conn = get_db()
if request.method == 'POST':
name = request.form['name']
category_id = request.form['category_id']
manufacturer_id = request.form['manufacturer_id']
price = request.form['price']
expiration_date = request.form['expiration_date']
stock_quantity = request.form['stock_quantity']
season_coeff = request.form.get('season_coeff', 1.0)
conn.execute('''
INSERT INTO medicines (name, category_id, manufacturer_id, price, expiration_date, stock_quantity, season_coeff)
VALUES (?, ?, ?, ?, ?, ?, ?)
''', (name, category_id, manufacturer_id, price, expiration_date, stock_quantity, season_coeff))
conn.commit()
conn.close()
flash('Лекарство добавлено!', 'success')
return redirect(url_for('index'))
categories = conn.execute('SELECT * FROM categories').fetchall()
manufacturers = conn.execute('SELECT * FROM manufacturers').fetchall()
conn.close()
return render_template('add_medicine.html', categories=categories, manufacturers=manufacturers)
if __name__ == '__main__':
app.run(debug=True)

56
create_tables.py Normal file
View file

@ -0,0 +1,56 @@
import sqlite3
conn = sqlite3.connect('pharmacy.db')
cursor = conn.cursor()
# Категории лекарств
cursor.execute('''
CREATE TABLE IF NOT EXISTS categories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
description TEXT
)
''')
# Производители
cursor.execute('''
CREATE TABLE IF NOT EXISTS manufacturers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
country TEXT,
phone TEXT,
email TEXT UNIQUE
)
''')
# Лекарства
cursor.execute('''
CREATE TABLE IF NOT EXISTS medicines (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
category_id INTEGER,
manufacturer_id INTEGER,
price REAL NOT NULL,
expiration_date DATE NOT NULL,
stock_quantity INTEGER DEFAULT 0,
season_coeff REAL DEFAULT 1.0,
FOREIGN KEY (category_id) REFERENCES categories(id),
FOREIGN KEY (manufacturer_id) REFERENCES manufacturers(id)
)
''')
# Заказы (для истории продаж)
cursor.execute('''
CREATE TABLE IF NOT EXISTS orders (
id INTEGER PRIMARY KEY AUTOINCREMENT,
medicine_id INTEGER,
quantity INTEGER NOT NULL,
order_date DATE NOT NULL,
total_price REAL,
FOREIGN KEY (medicine_id) REFERENCES medicines(id)
)
''')
print("✅ Таблицы созданы")
conn.commit()
conn.close()

39
load_data.py Normal file
View file

@ -0,0 +1,39 @@
import sqlite3
import pandas as pd
conn = sqlite3.connect('pharmacy.db')
cursor = conn.cursor()
# Загрузка категорий
print("📦 Загрузка категорий...")
df = pd.read_excel('Resource/categories_import.xlsx')
for _, row in df.iterrows():
cursor.execute('''
INSERT OR IGNORE INTO categories (id, name, description)
VALUES (?, ?, ?)
''', (row['ID'], row['CategoryName'], row['Description']))
# Загрузка производителей
print("🏭 Загрузка производителей...")
df = pd.read_excel('Resource/manufacturers_import.xlsx')
for _, row in df.iterrows():
cursor.execute('''
INSERT OR IGNORE INTO manufacturers (id, name, country, phone, email)
VALUES (?, ?, ?, ?, ?)
''', (row['ID'], row['ManufacturerName'], row['Country'], row['Phone'], row['Email']))
# Загрузка лекарств
print("💊 Загрузка лекарств...")
df = pd.read_excel('Resource/medicines_import.xlsx')
for _, row in df.iterrows():
cursor.execute('''
INSERT OR IGNORE INTO medicines
(id, name, category_id, manufacturer_id, price, expiration_date, stock_quantity, season_coeff)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
''', (row['ID'], row['MedicineName'], row['CategoryID'], row['ManufacturerID'],
row['Price'], row['ExpirationDate'], row['StockQty'], row['SeasonCoeff']))
conn.commit()
conn.close()
print("✅ Данные загружены!")
input("Нажми Enter для выхода...")

BIN
pharmacy.db Normal file

Binary file not shown.

319
static/css/style.css Normal file
View file

@ -0,0 +1,319 @@
/* Подключаем шрифт Segoe UI */
@import url('https://fonts.googleapis.com/css2?family=Segoe+UI:wght@300;400;600;700&display=swap');
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #F4E8D3;
margin: 0;
padding: 0;
}
.main-container {
background-color: #ffffff;
min-height: 100vh;
padding: 20px;
}
.header {
background: linear-gradient(135deg, #67BA80 0%, #4CAF50 100%);
padding: 20px;
border-radius: 10px;
margin-bottom: 30px;
color: white;
}
.logo-container {
display: flex;
align-items: center;
gap: 20px;
}
.logo {
height: 60px;
width: auto;
object-fit: contain;
}
.header-title {
font-size: 2.2em;
font-weight: 700;
margin: 0;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.page-title {
color: #2c3e50;
font-weight: 600;
}
.partner-card {
border: 2px solid #67BA80;
border-radius: 12px;
padding: 20px;
margin-bottom: 20px;
background: #ffffff;
box-shadow: 0 4px 12px rgba(103, 186, 128, 0.15);
}
.partner-header {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2px solid #e9ecef;
padding-bottom: 15px;
margin-bottom: 15px;
}
.partner-name-line {
display: flex;
align-items: center;
gap: 12px;
flex-wrap: wrap;
}
.partner-type {
font-size: 1.3em;
font-weight: 600;
color: #6c757d;
background: #f8f9fa;
padding: 6px 14px;
border-radius: 20px;
}
.partner-name {
font-size: 1.4em;
font-weight: 700;
color: #2c3e50;
margin: 0;
}
.divider {
color: #dee2e6;
font-weight: bold;
font-size: 1.4em;
}
.discount-info {
display: flex;
align-items: center;
gap: 15px;
}
.discount-badge {
font-size: 1.1em;
padding: 8px 16px;
border-radius: 25px;
background-color: #67BA80;
color: white;
}
.sales-amount {
font-size: 1em;
color: #6c757d;
font-weight: 500;
}
.partner-info-row {
margin-bottom: 0;
padding: 6px 0;
line-height: 1.4;
}
.partner-label {
font-weight: 600;
color: #495057;
min-width: 100px;
display: inline-block;
font-size: 1em;
}
.partner-value {
font-size: 1em;
color: #2c3e50;
}
.partner-buttons-container {
display: flex;
gap: 12px;
justify-content: flex-start;
margin-top: 20px;
padding-top: 15px;
border-top: 2px solid #e9ecef;
}
.btn-action {
padding: 10px 20px;
font-size: 0.95em;
display: flex;
align-items: center;
gap: 8px;
min-width: 180px;
justify-content: center;
border: none;
border-radius: 8px;
font-weight: 600;
transition: all 0.3s ease;
}
.btn-edit {
background-color: #67BA80;
color: white;
}
.btn-add {
background-color: #6c757d;
color: white;
}
.btn-history {
background-color: #495057;
color: white;
}
.btn-action:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
color: white;
}
.btn-new-partner {
background-color: #67BA80;
color: white;
border: none;
padding: 12px 24px;
font-weight: 600;
border-radius: 8px;
}
.btn-new-partner:hover {
background-color: #5aa870;
color: white;
}
.rating-badge {
font-size: 0.9em;
padding: 6px 12px;
border-radius: 15px;
}
.alert {
border-radius: 10px;
border: none;
}
.partner-info-row:last-child {
margin-bottom: 10px;
}
.volume-info {
background-color: #f8f9fa;
padding: 8px 12px;
border-radius: 6px;
margin-top: 10px;
}
.volume-label {
font-weight: 600;
color: #495057;
}
.volume-value {
color: #2c3e50;
font-weight: 500;
}
/* Стили для страницы истории продаж */
/* Стили для таблицы продаж */
.table-responsive {
border-radius: 8px;
overflow: hidden;
}
.table {
margin-bottom: 0;
}
.table th {
background-color: #67BA80;
color: white;
font-weight: 600;
padding: 12px;
text-align: center;
}
.table td {
padding: 10px;
text-align: center;
vertical-align: middle;
}
.table-striped tbody tr:nth-of-type(odd) {
background-color: rgba(103, 186, 128, 0.05);
}
.table-striped tbody tr:hover {
background-color: rgba(103, 186, 128, 0.1);
}
.table tfoot {
background-color: #e8f5e8;
font-weight: 600;
}
.table tfoot td {
border-top: 2px solid #67BA80;
}
.text-end {
text-align: right !important;
}
/* Адаптивность для таблицы */
@media (max-width: 768px) {
.table-responsive {
font-size: 0.9em;
}
.table th, .table td {
padding: 6px;
}
}
/* Кастомные кнопки под цветовую схему */
.btn-custom-primary {
background-color: #67BA80;
color: white;
border: none;
padding: 10px 20px;
font-weight: 600;
border-radius: 8px;
transition: all 0.3s ease;
}
.btn-custom-primary:hover {
background-color: #5aa870;
color: white;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(103, 186, 128, 0.3);
}
.btn-custom-edit {
background-color: #6c757d;
color: white;
border: none;
padding: 5px 10px;
border-radius: 5px;
}
.btn-custom-edit:hover {
background-color: #5a6268;
color: white;
}
/* Таблицы */
.table th {
background-color: #67BA80;
color: white;
font-weight: 600;
}
/* Бейджи популярности */
.badge.bg-success {
background-color: #67BA80 !important;
}

37
static/js/script.js Normal file
View file

@ -0,0 +1,37 @@
document.addEventListener('DOMContentLoaded', function() {
// Кнопка нового партнера
const newPartnerBtn = document.querySelector('.btn-new-partner');
if (newPartnerBtn) {
newPartnerBtn.addEventListener('click', function() {
// Переход на страницу добавления партнера
window.location.href = '/add_partner';
});
}
// Кнопка "Редактирование"
document.querySelectorAll('.btn-edit').forEach(btn => {
btn.addEventListener('click', function() {
const partnerId = this.getAttribute('data-partner-id');
// Переход на страницу редактирования
window.location.href = `/edit_partner/${partnerId}`;
});
});
// Кнопка "Добавление продажи"
document.querySelectorAll('.btn-add').forEach(btn => {
btn.addEventListener('click', function() {
const partnerId = this.getAttribute('data-partner-id');
// Переход на страницу добавления продажи
window.location.href = `/add_sale/${partnerId}`;
});
});
// Кнопка "История реализации"
document.querySelectorAll('.btn-history').forEach(btn => {
btn.addEventListener('click', function() {
const partnerId = this.getAttribute('data-partner-id');
// Переход на страницу истории реализации
window.location.href = `/sales_history/${partnerId}`;
});
});
});

BIN
static/masterpol.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 B

View file

@ -0,0 +1,18 @@
{% extends "base.html" %}
{% block content %}
<h2>Добавить категорию</h2>
<form method="POST">
<div class="mb-3">
<label>Название категории</label>
<input type="text" name="name" class="form-control" required>
</div>
<div class="mb-3">
<label>Описание</label>
<textarea name="description" class="form-control" rows="3"></textarea>
</div>
<button type="submit" class="btn btn-primary">Добавить</button>
<a href="{{ url_for('categories') }}" class="btn btn-secondary">Отмена</a>
</form>
{% endblock %}

View file

@ -0,0 +1,26 @@
{% extends "base.html" %}
{% block content %}
<h2>Добавить производителя</h2>
<form method="POST">
<div class="mb-3">
<label>Название компании</label>
<input type="text" name="name" class="form-control" required>
</div>
<div class="mb-3">
<label>Страна</label>
<input type="text" name="country" class="form-control">
</div>
<div class="mb-3">
<label>Телефон</label>
<input type="text" name="phone" class="form-control">
</div>
<div class="mb-3">
<label>Email</label>
<input type="email" name="email" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Добавить</button>
<a href="{{ url_for('manufacturers') }}" class="btn btn-secondary">Отмена</a>
</form>
{% endblock %}

View file

@ -0,0 +1,45 @@
{% extends "base.html" %}
{% block content %}
<h2>Добавить лекарство</h2>
<form method="POST">
<div class="mb-3">
<label>Название</label>
<input type="text" name="name" class="form-control" required>
</div>
<div class="mb-3">
<label>Категория</label>
<select name="category_id" class="form-control" required>
{% for c in categories %}
<option value="{{ c.id }}">{{ c.name }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label>Производитель</label>
<select name="manufacturer_id" class="form-control" required>
{% for m in manufacturers %}
<option value="{{ m.id }}">{{ m.name }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label>Цена</label>
<input type="number" step="0.01" name="price" class="form-control" required>
</div>
<div class="mb-3">
<label>Срок годности (ГГГГ-ММ-ДД)</label>
<input type="date" name="expiration_date" class="form-control" required>
</div>
<div class="mb-3">
<label>Количество на складе</label>
<input type="number" name="stock_quantity" class="form-control" required>
</div>
<div class="mb-3">
<label>Сезонный коэффициент</label>
<input type="number" step="0.1" name="season_coeff" class="form-control" value="1.0">
</div>
<button type="submit" class="btn btn-primary">Добавить</button>
<a href="/" class="btn btn-secondary">Отмена</a>
</form>
{% endblock %}

69
templates/base.html Normal file
View file

@ -0,0 +1,69 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}Аптечный склад{% endblock %}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body {
font-family: Arial, sans-serif;
background-color: #FFFFFF;
}
.navbar {
background-color: #E6F2FF !important;
}
.btn-primary {
background-color: #0066CC !important;
border-color: #0066CC !important;
}
.btn-primary:hover {
background-color: #0052a3 !important;
}
.card-header {
background-color: #E6F2FF !important;
}
footer {
background-color: #E6F2FF;
padding: 10px 0;
margin-top: 30px;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg">
<div class="container">
<a class="navbar-brand" href="/">
<img src="{{ url_for('static', filename='masterpol.png') }}" alt="Logo" height="40">
Аптечный склад
</a>
<div>
<a href="/" class="btn btn-outline-primary">Лекарства</a>
<a href="/manufacturers" class="btn btn-outline-primary">Производители</a>
<a href="/categories" class="btn btn-outline-primary">Категории</a>
</div>
</div>
</nav>
<div class="container mt-4">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ 'danger' if category == 'error' else 'success' }} alert-dismissible">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</div>
<footer class="text-center">
<p>Аптечный склад © 2026</p>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

30
templates/categories.html Normal file
View file

@ -0,0 +1,30 @@
{% extends "base.html" %}
{% block content %}
<h2>Категории лекарств</h2>
<a href="/add_category" class="btn btn-primary mb-3">Добавить категорию</a>
<table class="table table-striped">
<thead>
<tr>
<th>Название</th>
<th>Описание</th>
<th>Действия</th>
</tr>
</thead>
<tbody>
{% for c in categories %}
<tr>
<td>{{ c.name }}</td>
<td>{{ c.description or '-' }}</td>
<td>
<a href="/edit_category/{{ c.id }}" class="btn btn-sm btn-primary">✏️</a>
<form action="/delete_category/{{ c.id }}" method="POST" style="display:inline;">
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Удалить?')">🗑️</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

View file

@ -0,0 +1,6 @@
<div class="header">
<div class="logo-container">
<img src="{{ url_for('static', filename='masterpol.png') }}" alt="MasterPol" class="logo">
<h1 class="header-title">Управление партнерами</h1>
</div>
</div>

View file

@ -0,0 +1,73 @@
<div class="col-12">
<div class="partner-card">
<!-- Первая строка: Тип | Наименование и Скидка -->
<div class="partner-header">
<div class="partner-name-line">
<span class="partner-type">
{% if partner.partner_type_name %}
{{ partner.partner_type_name }}
{% else %}
Тип не указан
{% endif %}
</span>
<span class="divider">|</span>
<span class="partner-name">{{ partner.name }}</span>
</div>
<div class="discount-info">
<span class="discount-badge">
Скидка {{ partner.discount_percent }}%
</span>
<span class="sales-amount">
{{ partner.total_quantity }} ед.
</span>
</div>
</div>
<!-- Информация о партнере -->
<div class="partner-info-row">
<span class="partner-label">Директор:</span>
<span class="partner-value">{{ partner.director or 'Не указан' }}</span>
</div>
<div class="partner-info-row">
<span class="partner-label">Телефон:</span>
<span class="partner-value">
{% if partner.phone %}
{{ partner.phone }}
{% else %}
Не указан
{% endif %}
</span>
</div>
<div class="partner-info-row">
<span class="partner-label">Рейтинг:</span>
<span class="partner-value">
<span class="badge rating-badge bg-{{ 'success' if partner.rating >= 4 else 'warning' if partner.rating >= 3 else 'danger' }}">
{{ partner.rating }}
</span>
</span>
</div>
<div class="partner-info-row">
<span class="partner-label">Объем продаж:</span>
<span class="partner-value">
{{ "%.2f"|format(partner.total_sales) }} руб.
</span>
</div>
<!-- Кнопки действий внизу -->
<div class="partner-buttons-container">
<button class="btn btn-action btn-edit" data-partner-id="{{ partner.id }}">
<i class="fas fa-edit"></i> Редактирование
</button>
<button class="btn btn-action btn-add" data-partner-id="{{ partner.id }}">
<i class="fas fa-plus-circle"></i> Добавление продажи
</button>
<button class="btn btn-action btn-history" data-partner-id="{{ partner.id }}">
<i class="fas fa-history"></i> История реализации
</button>
</div>
</div>
</div>

View file

@ -0,0 +1,18 @@
{% extends "base.html" %}
{% block content %}
<h2>Редактировать категорию</h2>
<form method="POST">
<div class="mb-3">
<label>Название категории</label>
<input type="text" name="name" class="form-control" value="{{ category.name }}" required>
</div>
<div class="mb-3">
<label>Описание</label>
<textarea name="description" class="form-control" rows="3">{{ category.description or '' }}</textarea>
</div>
<button type="submit" class="btn btn-primary">Сохранить</button>
<a href="{{ url_for('categories') }}" class="btn btn-secondary">Отмена</a>
</form>
{% endblock %}

View file

@ -0,0 +1,26 @@
{% extends "base.html" %}
{% block content %}
<h2>Редактировать производителя</h2>
<form method="POST">
<div class="mb-3">
<label>Название компании</label>
<input type="text" name="name" class="form-control" value="{{ manufacturer.name }}" required>
</div>
<div class="mb-3">
<label>Страна</label>
<input type="text" name="country" class="form-control" value="{{ manufacturer.country or '' }}">
</div>
<div class="mb-3">
<label>Телефон</label>
<input type="text" name="phone" class="form-control" value="{{ manufacturer.phone or '' }}">
</div>
<div class="mb-3">
<label>Email</label>
<input type="email" name="email" class="form-control" value="{{ manufacturer.email or '' }}">
</div>
<button type="submit" class="btn btn-primary">Сохранить</button>
<a href="{{ url_for('manufacturers') }}" class="btn btn-secondary">Отмена</a>
</form>
{% endblock %}

37
templates/index.html Normal file
View file

@ -0,0 +1,37 @@
{% extends "base.html" %}
{% block content %}
<h2>Список лекарств</h2>
<a href="/add_medicine" class="btn btn-primary mb-3">Добавить лекарство</a>
<table class="table table-striped">
<thead>
<tr>
<th>Название</th>
<th>Категория</th>
<th>Производитель</th>
<th>Цена</th>
<th>Срок годности</th>
<th>В наличии</th>
<th>Тест заказа (10 шт)</th>
</tr>
</thead>
<tbody>
{% for m in medicines %}
<tr>
<td>{{ m.name }}</td>
<td>{{ m.category_name }}</td>
<td>{{ m.manufacturer_name }}</td>
<td>{{ m.price }} ₽</td>
<td>{{ m.expiration_date }}</td>
<td>{{ m.stock_quantity }}</td>
<td>
{% set total = calculate(m.id, 10) %}
<strong>{{ total }} ₽</strong>
<small>(с учетом скидок)</small>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

View file

@ -0,0 +1,34 @@
{% extends "base.html" %}
{% block content %}
<h2>Производители</h2>
<a href="/add_manufacturer" class="btn btn-primary mb-3">Добавить производителя</a>
<table class="table table-striped">
<thead>
<tr>
<th>Название</th>
<th>Страна</th>
<th>Телефон</th>
<th>Email</th>
<th>Действия</th>
</tr>
</thead>
<tbody>
{% for m in manufacturers %}
<tr>
<td>{{ m.name }}</td>
<td>{{ m.country or '-' }}</td>
<td>{{ m.phone or '-' }}</td>
<td>{{ m.email or '-' }}</td>
<td>
<a href="/edit_manufacturer/{{ m.id }}" class="btn btn-sm btn-primary">✏️</a>
<form action="/delete_manufacturer/{{ m.id }}" method="POST" style="display:inline;">
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Удалить?')">🗑️</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}