Watch
1
0
Fork
You've already forked Seyyed_arc
0
forked from hesabix/arc
Seyyed_arc/hesabixAPI/adapters/api/v1/received_loan_facilities.py
2026-05-14 01:30:20 +03:30

197 lines
7 KiB
Python
Executable file

from __future__ import annotations
from typing import Any, Dict
from fastapi import APIRouter, Body, Depends, Request
from sqlalchemy.orm import Session
from adapters.db.models.received_loan_facility import ReceivedLoanFacility
from adapters.db.session import get_db
from adapters.api.v1.schemas import QueryInfo
from app.core.auth_dependency import AuthContext, get_current_user
from app.core.permissions import (
require_business_access,
require_business_permission_dep,
require_business_permission_by_entity_dep,
)
from app.core.responses import ApiError, format_datetime_fields, success_response
from app.services.received_loan_facility_service import (
create_facility,
delete_facility,
delete_loan_payment,
get_facility_by_id,
list_facilities,
record_payment,
regenerate_schedule,
update_facility,
)
router = APIRouter(prefix="/loan-facilities", tags=["تسهیلات دریافتی"])
@router.post(
"/businesses/{business_id}/query",
summary="فهرست تسهیلات دریافتی",
)
@require_business_access("business_id")
def list_facilities_endpoint(
request: Request,
business_id: int,
query_info: QueryInfo,
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user),
_: None = Depends(require_business_permission_dep("loan_facilities", "view")),
):
qd = {
"take": query_info.take,
"skip": query_info.skip,
"search": query_info.search or "",
"sort_desc": getattr(query_info, "sort_desc", True),
}
res = list_facilities(db, business_id, qd)
return success_response(data=res, request=request, message="LOAN_FACILITIES_LISTED")
@router.post(
"/businesses/{business_id}/create",
summary="ایجاد قرارداد تسهیلات (پیش‌نویس)",
)
@require_business_access("business_id")
def create_facility_endpoint(
request: Request,
business_id: int,
body: Dict[str, Any] = Body(...),
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user),
_: None = Depends(require_business_permission_dep("loan_facilities", "add")),
):
payload = dict(body or {})
user_id = ctx.get_user_id()
if not user_id:
raise ApiError("UNAUTHORIZED", "User required", http_status=401)
created = create_facility(db, business_id, user_id, payload)
return success_response(data=format_datetime_fields(created, request), request=request, message="LOAN_FACILITY_CREATED")
@router.get(
"/{facility_id}",
summary="جزئیات تسهیلات با اقساط",
)
def get_facility_endpoint(
request: Request,
facility_id: int,
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user),
_: None = Depends(require_business_permission_by_entity_dep("loan_facilities", "view", ReceivedLoanFacility, "facility_id")),
):
row = get_facility_by_id(db, facility_id, with_installments=True)
if not row:
raise ApiError("LOAN_FACILITY_NOT_FOUND", "Facility not found", http_status=404)
return success_response(data=format_datetime_fields(row, request), request=request, message="LOAN_FACILITY_FETCHED")
@router.patch(
"/{facility_id}",
summary="به‌روزرسانی قرارداد",
)
def update_facility_endpoint(
request: Request,
facility_id: int,
body: Dict[str, Any] = Body(...),
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user),
_: None = Depends(require_business_permission_by_entity_dep("loan_facilities", "edit", ReceivedLoanFacility, "facility_id")),
):
updated = update_facility(db, facility_id, dict(body or {}))
if updated is None:
raise ApiError("LOAN_FACILITY_NOT_FOUND", "Facility not found", http_status=404)
return success_response(data=format_datetime_fields(updated, request), request=request, message="LOAN_FACILITY_UPDATED")
@router.delete(
"/{facility_id}",
summary="حذف قرارداد تسهیلات در صورت مجاز بودن حسابداری",
)
def delete_facility_endpoint(
request: Request,
facility_id: int,
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user),
_: None = Depends(require_business_permission_by_entity_dep("loan_facilities", "delete", ReceivedLoanFacility, "facility_id")),
):
obj = db.get(ReceivedLoanFacility, facility_id)
if obj is None:
raise ApiError("LOAN_FACILITY_NOT_FOUND", "Facility not found", http_status=404)
business_id = obj.business_id
ok = delete_facility(db, facility_id, business_id)
if not ok:
raise ApiError("LOAN_FACILITY_NOT_FOUND", "Facility not found", http_status=404)
return success_response(data={"deleted": True}, request=request, message="LOAN_FACILITY_DELETED")
@router.post(
"/{facility_id}/schedule",
summary="تولید یا بازسازی جدول اقساط",
)
def schedule_facility_endpoint(
request: Request,
facility_id: int,
body: Dict[str, Any] = Body(default={}),
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user),
_: None = Depends(require_business_permission_by_entity_dep("loan_facilities", "edit", ReceivedLoanFacility, "facility_id")),
):
payload = dict(body or {})
uid = ctx.get_user_id()
if not uid:
raise ApiError("UNAUTHORIZED", "User required", http_status=401)
row = regenerate_schedule(db, facility_id, payload, int(uid))
return success_response(data=format_datetime_fields(row, request), request=request, message="LOAN_FACILITY_SCHEDULED")
@router.post(
"/businesses/{business_id}/facilities/{facility_id}/installments/{installment_id}/payments",
summary="ثبت پرداخت قسط",
)
@require_business_access("business_id")
def pay_installment_endpoint(
request: Request,
business_id: int,
facility_id: int,
installment_id: int,
body: Dict[str, Any] = Body(...),
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user),
_: None = Depends(require_business_permission_dep("loan_facilities", "edit")),
):
f = db.get(ReceivedLoanFacility, facility_id)
if not f or f.business_id != business_id:
raise ApiError("LOAN_FACILITY_NOT_FOUND", "Facility not found", http_status=404)
user_id = ctx.get_user_id()
if not user_id:
raise ApiError("UNAUTHORIZED", "User required", http_status=401)
res = record_payment(db, business_id, user_id, facility_id, installment_id, dict(body or {}))
return success_response(data=format_datetime_fields(res, request), request=request, message="LOAN_PAYMENT_RECORDED")
@router.delete(
"/businesses/{business_id}/facilities/{facility_id}/installments/{installment_id}/payments/{payment_id}",
summary="حذف پرداخت قسط و سند حسابداری مرتبط",
)
@require_business_access("business_id")
def delete_installment_payment_endpoint(
request: Request,
business_id: int,
facility_id: int,
installment_id: int,
payment_id: int,
db: Session = Depends(get_db),
_ctx: AuthContext = Depends(get_current_user),
_: None = Depends(require_business_permission_dep("loan_facilities", "edit")),
):
f = db.get(ReceivedLoanFacility, facility_id)
if not f or f.business_id != business_id:
raise ApiError("LOAN_FACILITY_NOT_FOUND", "Facility not found", http_status=404)
res = delete_loan_payment(db, business_id, facility_id, installment_id, payment_id)
return success_response(data=format_datetime_fields(res, request), request=request, message="LOAN_PAYMENT_DELETED")