progress in persons
This commit is contained in:
parent
c31240846f
commit
af7aac7657
|
|
@ -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)}")
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue