Files
xenia-pos-local/local_backend/models/waste.py
bonamin 9cfbde0e3e feat: Phase 2H — void/waste log
Backend:
- New model: WasteLog (waste_log table) — product, quantity (float), reason, reason_notes,
  unit_cost_snapshot (copied at log time from product's effective cost), total_cost (stored),
  logged_by, business_day_id
- Cost snapshot: same logic as Phase 2A — breakdown sum first, fallback to cost_simple, null if neither
- New router /api/waste/:
  - GET / — list entries (?business_day_id= or ?from=&to=), ordered by logged_at desc
  - POST / — log waste; snapshots cost; attaches to open business day automatically
  - DELETE /{id} — manager only; only allowed within the same open business day
  - GET /summary — totals by reason + by product for a period
- product_performance report: waste_qty + waste_cost added per product from the same period;
  products with only waste (no sales) also included
- Migration: CREATE TABLE IF NOT EXISTS waste_log

Frontend:
- WastePage (/waste): fast log form (product picker, quantity, reason chips, notes);
  today's entries list below (scoped to active business day); cost shown per entry;
  delete button for today's entries; history section behind toggle with date-range picker
- ProductPerformance report: Απόβλητα column showing waste_qty + cost in amber
- Sidebar: Trash2 icon for Αποβλήτα (after Καρτέλες)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 03:19:33 +03:00

27 lines
1.2 KiB
Python

from sqlalchemy import Column, Integer, String, Float, DateTime, ForeignKey, Text
from sqlalchemy.orm import relationship
from datetime import datetime, timezone
from database import Base
def _utcnow():
return datetime.now(timezone.utc)
class WasteLog(Base):
__tablename__ = "waste_log"
id = Column(Integer, primary_key=True, index=True)
product_id = Column(Integer, ForeignKey("products.id"), nullable=False)
quantity = Column(Float, nullable=False) # supports decimals
unit_cost_snapshot = Column(Float, nullable=True) # product's effective cost at log time
total_cost = Column(Float, nullable=True) # unit_cost_snapshot * quantity
reason = Column(String, nullable=False) # kitchen_error|dropped|expired|other
reason_notes = Column(Text, nullable=True)
logged_by_id = Column(Integer, ForeignKey("users.id"), nullable=False)
business_day_id = Column(Integer, ForeignKey("business_days.id"), nullable=True)
logged_at = Column(DateTime(timezone=True), default=_utcnow)
product = relationship("Product", foreign_keys=[product_id])
logged_by = relationship("User", foreign_keys=[logged_by_id])