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

150 lines
5.4 KiB
Python
Executable file

"""
API endpoints برای گزارش‌های مالیاتی
"""
from __future__ import annotations
from fastapi import APIRouter, Request, Depends, Body
from typing import Dict, Any, Optional
from sqlalchemy.orm import Session
from sqlalchemy import func, and_
from app.core.responses import success_response, ApiError
from app.core.auth_dependency import get_current_user, AuthContext
from app.core.permissions import require_business_access, require_business_permission_dep
from app.core.moadian_plugin_dependency import ensure_moadian_plugin_active
from adapters.db.session import get_db
from adapters.db.models.document import Document
from adapters.api.v1.invoices import SUPPORTED_INVOICE_TYPES
router = APIRouter(prefix="/tax-reports", tags=["tax-reports"])
@router.post("/business/{business_id}/export")
@require_business_access("business_id")
def export_tax_report(
request: Request,
business_id: int,
body: Dict[str, Any] = Body(...),
ctx: AuthContext = Depends(get_current_user),
db: Session = Depends(get_db),
_: None = Depends(require_business_permission_dep("moadian", "export_reports")),
) -> Dict[str, Any]:
"""
Export گزارش ارسال‌های مالیاتی به Excel
Body:
- from_date: تاریخ شروع (اختیاری)
- to_date: تاریخ پایان (اختیاری)
- status: وضعیت (اختیاری)
- format: excel یا pdf (پیش‌فرض: excel)
"""
ensure_moadian_plugin_active(db, business_id)
from datetime import datetime
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment
from_date = body.get("from_date")
to_date = body.get("to_date")
status = body.get("status")
format_type = body.get("format", "excel")
from sqlalchemy import cast, Boolean
from sqlalchemy.dialects.postgresql import JSONB
_extra_info_jb = cast(Document.extra_info, JSONB)
query = db.query(Document).filter(
and_(
Document.business_id == business_id,
Document.document_type.in_(list(SUPPORTED_INVOICE_TYPES)),
cast(_extra_info_jb['tax_workspace'], Boolean) == True,
)
)
# فیلتر تاریخ
if from_date:
try:
from_dt = datetime.fromisoformat(from_date.replace('Z', '+00:00'))
query = query.filter(Document.date >= from_dt.date())
except Exception:
pass
if to_date:
try:
to_dt = datetime.fromisoformat(to_date.replace('Z', '+00:00'))
query = query.filter(Document.date <= to_dt.date())
except Exception:
pass
# فیلتر وضعیت
if status:
query = query.filter(
_extra_info_jb['tax_status'].astext == status
)
docs = query.order_by(Document.date.desc()).limit(10000).all()
if format_type == "excel":
# ایجاد Excel
wb = Workbook()
ws = wb.active
ws.title = "گزارش مالیاتی"
# Header
headers = [
"کد فاکتور",
"تاریخ",
"وضعیت",
"کد رهگیری",
"تاریخ ارسال",
"تاریخ آخرین استعلام",
"پیام خطا",
]
header_fill = PatternFill(start_color="366092", end_color="366092", fill_type="solid")
header_font = Font(bold=True, color="FFFFFF")
for col, header in enumerate(headers, 1):
cell = ws.cell(row=1, column=col, value=header)
cell.fill = header_fill
cell.font = header_font
cell.alignment = Alignment(horizontal="center", vertical="center")
# داده‌ها
for row, doc in enumerate(docs, 2):
extra = dict(doc.extra_info or {})
ws.cell(row=row, column=1, value=doc.code or "")
ws.cell(row=row, column=2, value=doc.date.isoformat() if doc.date else "")
ws.cell(row=row, column=3, value=extra.get("tax_status", ""))
ws.cell(row=row, column=4, value=extra.get("tax_tracking_code", ""))
ws.cell(row=row, column=5, value=extra.get("tax_last_send_at", ""))
ws.cell(row=row, column=6, value=extra.get("tax_last_inquiry_at", ""))
ws.cell(row=row, column=7, value=extra.get("tax_error_message", ""))
# تنظیم عرض ستون‌ها
ws.column_dimensions['A'].width = 15
ws.column_dimensions['B'].width = 12
ws.column_dimensions['C'].width = 15
ws.column_dimensions['D'].width = 20
ws.column_dimensions['E'].width = 20
ws.column_dimensions['F'].width = 20
ws.column_dimensions['G'].width = 30
# ذخیره در memory
from io import BytesIO
output = BytesIO()
wb.save(output)
output.seek(0)
from fastapi.responses import Response
return Response(
content=output.read(),
media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
headers={
"Content-Disposition": f'attachment; filename="tax_report_{business_id}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.xlsx"'
}
)
else:
raise ApiError("UNSUPPORTED_FORMAT", f"Format {format_type} is not supported", http_status=400)