Watch
1
0
Fork
You've already forked Seyyed_arc
0
forked from hesabix/arc
Seyyed_arc/hesabixAPI/adapters/api/v1/document_numbering.py

313 lines
9.7 KiB
Python
Executable file

from __future__ import annotations
from typing import List
from fastapi import APIRouter, Depends, Request, HTTPException, Path
from sqlalchemy.orm import Session
from sqlalchemy import and_
from adapters.db.session import get_db
from app.core.auth_dependency import get_current_user, AuthContext
from app.core.permissions import require_business_access_dep
from app.core.responses import success_response
from adapters.db.models.document_numbering import BusinessDocumentNumberingSetting
from adapters.api.v1.schemas import (
DocumentNumberingSettingRequest,
DocumentNumberingSettingResponse,
)
router = APIRouter(
prefix="/businesses/{business_id}/document-numbering-settings",
tags=["document-numbering"],
)
def _get_default_setting(document_type: str) -> dict:
"""
برگرداندن تنظیمات پیش‌فرض برای هر نوع سند
"""
defaults = {
"invoice_sales": {
"prefix": "INV",
"include_date": True,
"calendar_type": "gregorian",
"date_format": "YYYYMMDD",
},
"invoice_sales_return": {
"prefix": "INV-RET",
"include_date": True,
"calendar_type": "gregorian",
"date_format": "YYYYMMDD",
},
"invoice_purchase": {
"prefix": "INV-PUR",
"include_date": True,
"calendar_type": "gregorian",
"date_format": "YYYYMMDD",
},
"invoice_purchase_return": {
"prefix": "INV-PUR-RET",
"include_date": True,
"calendar_type": "gregorian",
"date_format": "YYYYMMDD",
},
"invoice_direct_consumption": {
"prefix": "INV-CON",
"include_date": True,
"calendar_type": "gregorian",
"date_format": "YYYYMMDD",
},
"invoice_production": {
"prefix": "INV-PROD",
"include_date": True,
"calendar_type": "gregorian",
"date_format": "YYYYMMDD",
},
"invoice_waste": {
"prefix": "INV-WASTE",
"include_date": True,
"calendar_type": "gregorian",
"date_format": "YYYYMMDD",
},
"receipt": {
"prefix": "RC",
"include_date": True,
"calendar_type": "gregorian",
"date_format": "YYYYMMDD",
},
"payment": {
"prefix": "PY",
"include_date": True,
"calendar_type": "gregorian",
"date_format": "YYYYMMDD",
},
"transfer": {
"prefix": "TR",
"include_date": True,
"calendar_type": "gregorian",
"date_format": "YYYYMMDD",
},
"expense": {
"prefix": "EXP",
"include_date": True,
"calendar_type": "gregorian",
"date_format": "YYYYMMDD",
},
"income": {
"prefix": "INC",
"include_date": True,
"calendar_type": "gregorian",
"date_format": "YYYYMMDD",
},
"crm_lead": {
"prefix": "L",
"include_date": True,
"calendar_type": "gregorian",
"date_format": "YYYYMMDD",
},
"crm_deal": {
"prefix": "D",
"include_date": True,
"calendar_type": "gregorian",
"date_format": "YYYYMMDD",
},
"crm_activity": {
"prefix": "A",
"include_date": True,
"calendar_type": "gregorian",
"date_format": "YYYYMMDD",
},
"warehouse_document": {
"prefix": "WH",
"include_date": True,
"calendar_type": "gregorian",
"date_format": "YYYYMMDD",
},
"warehouse_location": {
"prefix": "LOC",
"include_date": True,
"calendar_type": "gregorian",
"date_format": "YYYYMMDD",
},
}
default = defaults.get(
document_type,
{
"prefix": "DOC",
"include_date": True,
"calendar_type": "gregorian",
"date_format": "YYYYMMDD",
"separator": "-",
"start_number": 1,
"number_padding": 4,
"reset_period": "never",
},
)
return default
@router.get(
"",
summary="دریافت تمام تنظیمات شماره‌گذاری اسناد یک کسب و کار",
)
def get_document_numbering_settings(
request: Request,
business_id: int = Path(..., description="شناسه کسب و کار"),
_: None = Depends(require_business_access_dep),
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user),
) -> dict:
"""
دریافت تمام تنظیمات شماره‌گذاری اسناد یک کسب و کار
"""
if not ctx.has_business_permission("settings", "join"):
raise HTTPException(status_code=403, detail="دسترسی غیرمجاز")
settings = (
db.query(BusinessDocumentNumberingSetting)
.filter(BusinessDocumentNumberingSetting.business_id == business_id)
.all()
)
return success_response(
[DocumentNumberingSettingResponse.from_orm(s).dict() for s in settings], request
)
@router.get(
"/{document_type}",
summary="دریافت تنظیمات شماره‌گذاری برای یک نوع سند خاص",
)
def get_document_numbering_setting(
request: Request,
business_id: int = Path(..., description="شناسه کسب و کار"),
document_type: str = Path(..., description="نوع سند"),
_: None = Depends(require_business_access_dep),
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user),
) -> dict:
"""
دریافت تنظیمات شماره‌گذاری برای یک نوع سند خاص
"""
if not ctx.has_business_permission("settings", "join"):
raise HTTPException(status_code=403, detail="دسترسی غیرمجاز")
setting = (
db.query(BusinessDocumentNumberingSetting)
.filter(
and_(
BusinessDocumentNumberingSetting.business_id == business_id,
BusinessDocumentNumberingSetting.document_type == document_type,
)
)
.first()
)
if not setting:
# برگرداندن تنظیمات پیش‌فرض
default = _get_default_setting(document_type)
return success_response(default, request)
return success_response(
DocumentNumberingSettingResponse.from_orm(setting).dict(), request
)
@router.post(
"",
summary="ایجاد یا به‌روزرسانی تنظیمات شماره‌گذاری",
)
def create_or_update_document_numbering_setting(
request: Request,
business_id: int = Path(..., description="شناسه کسب و کار"),
data: DocumentNumberingSettingRequest = ...,
_: None = Depends(require_business_access_dep),
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user),
) -> dict:
"""
ایجاد یا به‌روزرسانی تنظیمات شماره‌گذاری
"""
if not ctx.has_business_permission("settings", "join"):
raise HTTPException(status_code=403, detail="دسترسی غیرمجاز")
from datetime import datetime
existing = (
db.query(BusinessDocumentNumberingSetting)
.filter(
and_(
BusinessDocumentNumberingSetting.business_id == business_id,
BusinessDocumentNumberingSetting.document_type == data.document_type,
)
)
.first()
)
if existing:
# به‌روزرسانی
for key, value in data.dict(exclude_unset=True).items():
setattr(existing, key, value)
existing.updated_at = datetime.utcnow()
db.commit()
db.refresh(existing)
return success_response(
DocumentNumberingSettingResponse.from_orm(existing).dict(),
request,
message="تنظیمات به‌روزرسانی شد",
)
else:
# ایجاد جدید
new_setting = BusinessDocumentNumberingSetting(
business_id=business_id, **data.dict()
)
db.add(new_setting)
db.commit()
db.refresh(new_setting)
return success_response(
DocumentNumberingSettingResponse.from_orm(new_setting).dict(),
request,
message="تنظیمات ایجاد شد",
)
@router.delete(
"/{document_type}",
summary="حذف تنظیمات شماره‌گذاری (بازگشت به پیش‌فرض)",
)
def delete_document_numbering_setting(
request: Request,
business_id: int = Path(..., description="شناسه کسب و کار"),
document_type: str = Path(..., description="نوع سند"),
_: None = Depends(require_business_access_dep),
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user),
) -> dict:
"""
حذف تنظیمات شماره‌گذاری (بازگشت به پیش‌فرض)
"""
if not ctx.has_business_permission("settings", "join"):
raise HTTPException(status_code=403, detail="دسترسی غیرمجاز")
setting = (
db.query(BusinessDocumentNumberingSetting)
.filter(
and_(
BusinessDocumentNumberingSetting.business_id == business_id,
BusinessDocumentNumberingSetting.document_type == document_type,
)
)
.first()
)
if setting:
db.delete(setting)
db.commit()
return success_response(
{"message": "تنظیمات حذف شد و به حالت پیش‌فرض بازگشت"}, request
)