| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- """
- app/crud.py
- ───────────
- Data-access layer: pure SQLAlchemy CRUD functions for every domain entity.
- All functions are intentionally thin — they do no business logic beyond
- the DB operation itself.
- """
- from __future__ import annotations
- from typing import List, Optional
- from sqlalchemy.orm import Session
- from app.models import (
- Client, ClientCreate, ClientUpdate,
- EmailTemplate, TemplateCreate, TemplateUpdate,
- Invoice, InvoiceCreate, InvoiceUpdate,
- NotificationLog,
- )
- # ═══════════════════════════════════════════════════════════════════════════════
- # Clients
- # ═══════════════════════════════════════════════════════════════════════════════
- def get_clients(db: Session, skip: int = 0, limit: int = 500) -> List[Client]:
- return db.query(Client).offset(skip).limit(limit).all()
- def get_client(db: Session, client_id: int) -> Optional[Client]:
- return db.query(Client).filter(Client.id == client_id).first()
- def create_client(db: Session, data: ClientCreate) -> Client:
- obj = Client(**data.model_dump())
- db.add(obj)
- db.commit()
- db.refresh(obj)
- return obj
- def update_client(db: Session, client_id: int, data: ClientUpdate) -> Optional[Client]:
- obj = get_client(db, client_id)
- if not obj:
- return None
- for field, value in data.model_dump().items():
- setattr(obj, field, value)
- db.commit()
- db.refresh(obj)
- return obj
- def delete_client(db: Session, client_id: int) -> bool:
- obj = get_client(db, client_id)
- if not obj:
- return False
- db.delete(obj)
- db.commit()
- return True
- # ═══════════════════════════════════════════════════════════════════════════════
- # Email Templates
- # ═══════════════════════════════════════════════════════════════════════════════
- def get_templates(db: Session, skip: int = 0, limit: int = 500) -> List[EmailTemplate]:
- return db.query(EmailTemplate).offset(skip).limit(limit).all()
- def get_template(db: Session, template_id: int) -> Optional[EmailTemplate]:
- return db.query(EmailTemplate).filter(EmailTemplate.id == template_id).first()
- def create_template(db: Session, data: TemplateCreate) -> EmailTemplate:
- obj = EmailTemplate(**data.model_dump())
- db.add(obj)
- db.commit()
- db.refresh(obj)
- return obj
- def update_template(db: Session, template_id: int, data: TemplateUpdate) -> Optional[EmailTemplate]:
- obj = get_template(db, template_id)
- if not obj:
- return None
- for field, value in data.model_dump().items():
- setattr(obj, field, value)
- db.commit()
- db.refresh(obj)
- return obj
- def delete_template(db: Session, template_id: int) -> bool:
- obj = get_template(db, template_id)
- if not obj:
- return False
- db.delete(obj)
- db.commit()
- return True
- # ═══════════════════════════════════════════════════════════════════════════════
- # Invoices
- # ═══════════════════════════════════════════════════════════════════════════════
- def get_invoices(db: Session, skip: int = 0, limit: int = 500) -> List[Invoice]:
- return db.query(Invoice).offset(skip).limit(limit).all()
- def get_invoice(db: Session, invoice_id: int) -> Optional[Invoice]:
- return db.query(Invoice).filter(Invoice.id == invoice_id).first()
- def create_invoice(db: Session, data: InvoiceCreate) -> Invoice:
- obj = Invoice(**data.model_dump())
- db.add(obj)
- db.commit()
- db.refresh(obj)
- return obj
- def update_invoice(db: Session, invoice_id: int, data: InvoiceUpdate) -> Optional[Invoice]:
- obj = get_invoice(db, invoice_id)
- if not obj:
- return None
- for field, value in data.model_dump().items():
- setattr(obj, field, value)
- db.commit()
- db.refresh(obj)
- return obj
- def delete_invoice(db: Session, invoice_id: int) -> bool:
- obj = get_invoice(db, invoice_id)
- if not obj:
- return False
- db.delete(obj)
- db.commit()
- return True
- # ═══════════════════════════════════════════════════════════════════════════════
- # Notification Logs
- # ═══════════════════════════════════════════════════════════════════════════════
- def get_notification_logs(
- db: Session, skip: int = 0, limit: int = 500
- ) -> List[NotificationLog]:
- return (
- db.query(NotificationLog)
- .order_by(NotificationLog.sent_at.desc())
- .offset(skip)
- .limit(limit)
- .all()
- )
- def create_notification_log(
- db: Session,
- invoice_id: int,
- status: str,
- context: Optional[dict] = None,
- error_message: Optional[str] = None,
- ) -> NotificationLog:
- obj = NotificationLog(
- invoice_id=invoice_id,
- status=status,
- context=context or {},
- error_message=error_message,
- )
- db.add(obj)
- db.commit()
- db.refresh(obj)
- return obj
- def update_notification_status(
- db: Session,
- log_id: int,
- status: str,
- error_message: Optional[str] = None,
- ) -> Optional[NotificationLog]:
- obj = db.query(NotificationLog).filter(NotificationLog.id == log_id).first()
- if not obj:
- return None
- obj.status = status
- if error_message is not None:
- obj.error_message = error_message
- db.commit()
- db.refresh(obj)
- return obj
|