progress in persons

This commit is contained in:
Hesabix 2025-09-28 20:36:44 +03:30
parent c31240846f
commit af7aac7657
3 changed files with 157 additions and 130 deletions

View file

@ -1,4 +1,4 @@
from fastapi import APIRouter, Depends, HTTPException, Query, Request, Body
from fastapi import APIRouter, Depends, HTTPException, Query, Request, Body, Form
from fastapi import UploadFile, File
from sqlalchemy.orm import Session
from typing import Dict, Any, List, Optional
@ -701,9 +701,9 @@ async def import_persons_excel(
business_id: int,
request: Request,
file: UploadFile = File(...),
dry_run: bool = Body(default=True),
match_by: str = Body(default="code"),
conflict_policy: str = Body(default="upsert"),
dry_run: str = Form(default="true"),
match_by: str = Form(default="code"),
conflict_policy: str = Form(default="upsert"),
auth_context: AuthContext = Depends(get_current_user),
db: Session = Depends(get_db),
):
@ -712,15 +712,39 @@ async def import_persons_excel(
import re
from openpyxl import load_workbook
from fastapi import HTTPException
import logging
logger = logging.getLogger(__name__)
try:
# Convert dry_run string to boolean
dry_run_bool = dry_run.lower() in ('true', '1', 'yes', 'on')
logger.info(f"Import request: business_id={business_id}, dry_run={dry_run_bool}, match_by={match_by}, conflict_policy={conflict_policy}")
logger.info(f"File info: filename={file.filename}, content_type={file.content_type}")
if not file.filename or not file.filename.lower().endswith('.xlsx'):
logger.error(f"Invalid file format: {file.filename}")
raise HTTPException(status_code=400, detail="فرمت فایل معتبر نیست. تنها xlsx پشتیبانی می‌شود")
content = await file.read()
logger.info(f"File content size: {len(content)} bytes")
# Check if content is empty or too small
if len(content) < 100:
logger.error(f"File too small: {len(content)} bytes")
raise HTTPException(status_code=400, detail="فایل خیلی کوچک است یا خالی است")
# Check if it's a valid Excel file by looking at the first few bytes
if not content.startswith(b'PK'):
logger.error("File does not start with PK signature (not a valid Excel file)")
raise HTTPException(status_code=400, detail="فرمت فایل معتبر نیست. فایل Excel معتبر نیست")
try:
wb = load_workbook(filename=io.BytesIO(content), data_only=True)
except Exception:
raise HTTPException(status_code=400, detail="امکان خواندن فایل وجود ندارد")
except Exception as e:
logger.error(f"Error loading workbook: {str(e)}")
raise HTTPException(status_code=400, detail=f"امکان خواندن فایل وجود ندارد: {str(e)}")
ws = wb.active
rows = list(ws.iter_rows(values_only=True))
@ -791,7 +815,7 @@ async def import_persons_excel(
updated = 0
skipped = 0
if not dry_run and valid_items:
if not dry_run_bool and valid_items:
# apply import with conflict policy
from adapters.db.models.person import Person
from sqlalchemy import and_
@ -835,7 +859,7 @@ async def import_persons_excel(
"inserted": inserted,
"updated": updated,
"skipped": skipped,
"dry_run": dry_run,
"dry_run": dry_run_bool,
}
return success_response(
@ -846,3 +870,6 @@ async def import_persons_excel(
request=request,
message="نتیجه ایمپورت اشخاص",
)
except Exception as e:
logger.error(f"Import error: {str(e)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"خطا در پردازش فایل: {str(e)}")

View file

@ -197,14 +197,6 @@ class _BusinessShellState extends State<BusinessShell> {
type: _MenuItemType.simple,
hasAddButton: true,
),
_MenuItem(
label: t.checks,
icon: Icons.receipt_long,
selectedIcon: Icons.receipt_long,
path: '/business/${widget.businessId}/checks',
type: _MenuItemType.simple,
hasAddButton: true,
),
],
),
_MenuItem(
@ -246,6 +238,14 @@ class _BusinessShellState extends State<BusinessShell> {
type: _MenuItemType.simple,
hasAddButton: true,
),
_MenuItem(
label: t.checks,
icon: Icons.receipt_long,
selectedIcon: Icons.receipt_long,
path: '/business/${widget.businessId}/checks',
type: _MenuItemType.simple,
hasAddButton: true,
),
_MenuItem(
label: t.documents,
icon: Icons.description,

View file

@ -127,7 +127,7 @@ class _PersonImportDialogState extends State<PersonImportDialog> {
});
final form = FormData.fromMap({
'file': MultipartFile.fromBytes(bytes, filename: filename),
'dry_run': dryRun,
'dry_run': dryRun.toString(),
'match_by': _matchBy,
'conflict_policy': _conflictPolicy,
});