from flask import Flask, render_template, request, redirect, url_for, flash from database import db import os import re from datetime import datetime app = Flask(__name__) app.config['SECRET_KEY'] = 'your-secret-key-2026' # Функция валидации телефона def validate_phone(phone): phone_clean = re.sub(r'[^\d+]', '', phone) if phone_clean.startswith('+7') and len(phone_clean) == 12: return True elif phone_clean.startswith('8') and len(phone_clean) == 11: return True elif len(phone_clean) == 10 and phone_clean.isdigit(): return True elif len(phone_clean) == 11 and phone_clean.isdigit(): return True return False def format_phone(phone): phone_clean = re.sub(r'[^\d+]', '', phone) if phone_clean.startswith('+7') and len(phone_clean) == 12: return f"+7 ({phone_clean[2:5]}) {phone_clean[5:8]}-{phone_clean[8:10]}-{phone_clean[10:12]}" elif phone_clean.startswith('8') and len(phone_clean) == 11: return f"+7 ({phone_clean[1:4]}) {phone_clean[4:7]}-{phone_clean[7:9]}-{phone_clean[9:11]}" elif len(phone_clean) == 10: return f"+7 ({phone_clean[0:3]}) {phone_clean[3:6]}-{phone_clean[6:8]}-{phone_clean[8:10]}" elif len(phone_clean) == 11: return f"+7 ({phone_clean[1:4]}) {phone_clean[4:7]}-{phone_clean[7:9]}-{phone_clean[9:11]}" return phone # Функция расчета коэффициента срока годности def get_expiry_coefficient(expiry_date): """ Расчет коэффициента скидки в зависимости от срока годности < 30 дней -> 50% скидка 30-90 дней -> 30% скидка 90-180 дней -> 15% скидка > 180 дней -> 0% скидка """ if not expiry_date: return 0 try: # Преобразуем строку в дату (формат дд.мм.гггг) expiry = datetime.strptime(expiry_date, '%d.%m.%Y') today = datetime.now() days_until_expiry = (expiry - today).days if days_until_expiry < 0: return 100 # Просрочен - 100% скидка (не продаем) elif days_until_expiry < 30: return 50 # 50% скидка elif days_until_expiry < 90: return 30 # 30% скидка elif days_until_expiry < 180: return 15 # 15% скидка else: return 0 except: return 0 # Функция расчета итоговой цены с учетом скидки и срока годности def calculate_final_price(price, quantity, expiry_date, quantity_discount_percent=0): """ Расчет итоговой цены: 1. Базовая сумма = цена * количество 2. Скидка по сроку годности 3. Скидка по количеству """ total = price * quantity # Скидка по сроку годности expiry_discount_percent = get_expiry_coefficient(expiry_date) expiry_discount_amount = total * expiry_discount_percent / 100 # Скидка по количеству quantity_discount_amount = total * quantity_discount_percent / 100 # Общая скидка total_discount = expiry_discount_amount + quantity_discount_amount final_total = total - total_discount return { 'total': total, 'expiry_discount_percent': expiry_discount_percent, 'expiry_discount_amount': expiry_discount_amount, 'quantity_discount_percent': quantity_discount_percent, 'quantity_discount_amount': quantity_discount_amount, 'total_discount': total_discount, 'final_total': final_total } # ============ ГЛАВНАЯ ============ @app.route('/') def index(): products = db.get_products() total_items = sum(p.get('stock_quantity', 0) for p in products) total_value = sum(p.get('stock_quantity', 0) * p.get('selling_price', 0) for p in products) return render_template('index.html', total_items=total_items, total_value=total_value) # ============ ТОВАРЫ ============ @app.route('/products', methods=['GET', 'POST']) def products(): if request.method == 'POST': product = { 'name': request.form.get('name'), 'manufacturer': request.form.get('manufacturer'), 'product_type': request.form.get('product_type'), 'purchase_price': float(request.form.get('purchase_price', 0)), 'selling_price': float(request.form.get('selling_price', 0)), 'expiry_date': request.form.get('expiry_date', ''), 'stock_quantity': int(request.form.get('stock_quantity', 0)) } db.save_product(product) flash('Товар добавлен', 'success') return redirect(url_for('products')) products = db.get_products() categories = db.get_categories() return render_template('products.html', products=products, categories=categories) @app.route('/products/delete/') def delete_product(product_id): db.delete_product(product_id) flash('Товар удален', 'warning') return redirect(url_for('products')) @app.route('/products/edit/', methods=['GET', 'POST']) def edit_product(product_id): product = db.get_product_by_id(product_id) if not product: flash('Товар не найден', 'danger') return redirect(url_for('products')) if request.method == 'POST': updated_data = { 'name': request.form.get('name'), 'manufacturer': request.form.get('manufacturer'), 'product_type': request.form.get('product_type'), 'purchase_price': float(request.form.get('purchase_price', 0)), 'selling_price': float(request.form.get('selling_price', 0)), 'expiry_date': request.form.get('expiry_date', ''), 'stock_quantity': int(request.form.get('stock_quantity', 0)) } db.update_product(product_id, updated_data) flash('Товар обновлен', 'success') return redirect(url_for('products')) return render_template('edit_product.html', product=product) # ============ ПОСТАВЩИКИ ============ @app.route('/suppliers', methods=['GET', 'POST']) def suppliers(): if request.method == 'POST': name = request.form.get('name') contact = request.form.get('contact') phone = request.form.get('phone') if phone and not validate_phone(phone): flash('Неверный формат телефона', 'danger') suppliers = db.get_suppliers() return render_template('suppliers.html', suppliers=suppliers) supplier = { 'name': name, 'contact': contact, 'phone': format_phone(phone) if phone else '' } db.save_supplier(supplier) flash('Поставщик добавлен', 'success') return redirect(url_for('suppliers')) suppliers = db.get_suppliers() return render_template('suppliers.html', suppliers=suppliers) @app.route('/suppliers/edit/', methods=['GET', 'POST']) def edit_supplier(supplier_id): supplier = db.get_supplier_by_id(supplier_id) if not supplier: flash('Поставщик не найден', 'danger') return redirect(url_for('suppliers')) if request.method == 'POST': name = request.form.get('name') contact = request.form.get('contact') phone = request.form.get('phone') if phone and not validate_phone(phone): flash('Неверный формат телефона', 'danger') return render_template('edit_supplier.html', supplier=supplier) updated_data = { 'name': name, 'contact': contact, 'phone': format_phone(phone) if phone else '' } db.update_supplier(supplier_id, updated_data) flash('Поставщик обновлен', 'success') return redirect(url_for('suppliers')) return render_template('edit_supplier.html', supplier=supplier) @app.route('/supplier/orders/') def supplier_orders(supplier_id): supplier = db.get_supplier_by_id(supplier_id) if not supplier: flash('Поставщик не найден', 'danger') return redirect(url_for('suppliers')) all_orders = db.get_incoming_orders() supplier_orders = [o for o in all_orders if o.get('supplier_id') == supplier_id] total_sum = sum(o.get('total', 0) for o in supplier_orders) total_items = sum(o.get('quantity', 0) for o in supplier_orders) return render_template('supplier_orders.html', supplier=supplier, orders=supplier_orders, total_sum=total_sum, total_items=total_items) # ============ ПОСТУПЛЕНИЕ ТОВАРА (С УЧЕТОМ СРОКА ГОДНОСТИ) ============ @app.route('/incoming', methods=['GET', 'POST']) def incoming(): if request.method == 'POST': product_id = int(request.form.get('product_id')) supplier_id = int(request.form.get('supplier_id')) quantity = int(request.form.get('quantity')) purchase_price = float(request.form.get('purchase_price')) product = db.get_product_by_id(product_id) supplier = db.get_supplier_by_id(supplier_id) if product and supplier: # Получаем срок годности товара expiry_date = product.get('expiry_date', '') # Рассчитываем коэффициенты expiry_discount_percent = get_expiry_coefficient(expiry_date) # Базовая сумма total = quantity * purchase_price # Скидка по сроку годности discount_amount = total * expiry_discount_percent / 100 final_total = total - discount_amount incoming_order = { 'supplier_id': supplier_id, 'supplier_name': supplier['name'], 'product_id': product_id, 'product_name': product['name'], 'expiry_date': expiry_date, 'quantity': quantity, 'purchase_price': purchase_price, 'total': total, 'expiry_discount_percent': expiry_discount_percent, 'discount_amount': discount_amount, 'final_total': final_total } db.save_incoming_order(incoming_order) db.update_stock(product_id, quantity) if expiry_discount_percent > 0: flash(f'Товар "{product["name"]}" поступил на склад. Применена скидка {expiry_discount_percent}% по сроку годности!', 'success') else: flash(f'Товар "{product["name"]}" поступил на склад в количестве {quantity} шт.', 'success') else: flash('Ошибка при оформлении поступления', 'danger') return redirect(url_for('incoming')) products = db.get_products() suppliers = db.get_suppliers() return render_template('incoming.html', products=products, suppliers=suppliers) # ============ ПРИХОДНЫЕ НАКЛАДНЫЕ ============ @app.route('/incoming-orders') def incoming_orders(): sort_by = request.args.get('sort', 'date') order = request.args.get('order', 'desc') orders = db.get_incoming_orders(sort_by=sort_by, order=order) return render_template('incoming_orders.html', orders=orders, sort_by=sort_by, order=order) # ============ ЗАПУСК ============ if __name__ == '__main__': app.run(debug=True)