diff --git a/.dockerignore b/.dockerignore index a0ae8ea..ecf5f17 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1 +1,3 @@ web/node_modules +web1/node_modules +migrations \ No newline at end of file diff --git a/app/api/v1/invoice/invoice.py b/app/api/v1/invoice/invoice.py index 0dc9603..684ad12 100644 --- a/app/api/v1/invoice/invoice.py +++ b/app/api/v1/invoice/invoice.py @@ -124,13 +124,24 @@ async def upload_payment_receipt(id: int, data: PaymentReceiptCreate): return Success(data=detail, msg="上传成功") -@invoice_router.get("/headers", summary="发票抬头列表", response_model=BasicResponse[list[InvoiceHeaderOut]], dependencies=[DependAuth, DependPermission]) -async def get_invoice_headers(app_user_id: Optional[int] = Query(None)): +@invoice_router.get("/headers", summary="发票抬头列表", response_model=PageResponse[InvoiceHeaderOut], dependencies=[DependAuth, DependPermission]) +async def get_invoice_headers( + app_user_id: Optional[int] = Query(None, description="按App用户ID过滤"), + user_id: Optional[int] = Query(None, description="按App用户ID过滤(兼容参数)"), + page: int = Query(1, ge=1), + page_size: int = Query(10, ge=1, le=100), +): """ - 管理端抬头列表(管理员token):允许按 app_user_id 过滤;为空则返回全部。 + 管理端抬头列表(管理员token):支持按 App 用户过滤与分页。 """ - headers = await invoice_controller.get_headers(user_id=app_user_id) - return Success(data=headers, msg="获取成功") + uid = app_user_id if app_user_id is not None else user_id + qs = InvoiceHeader.all() + if uid is not None: + qs = qs.filter(app_user_id=uid) + total = await qs.count() + rows = await qs.order_by("-created_at").offset((page - 1) * page_size).limit(page_size) + items = [InvoiceHeaderOut.model_validate(r) for r in rows] + return SuccessExtra(data=[i.model_dump() for i in items], total=total, page=page, page_size=page_size, msg="获取成功") @invoice_router.get("/headers/{id}", summary="发票抬头详情", response_model=BasicResponse[InvoiceHeaderOut], dependencies=[DependAuth, DependPermission]) diff --git a/app/api/v1/valuations/valuations.py b/app/api/v1/valuations/valuations.py index cf2ffc5..5c06654 100644 --- a/app/api/v1/valuations/valuations.py +++ b/app/api/v1/valuations/valuations.py @@ -90,7 +90,7 @@ async def get_valuation_report(valuation_id: int): @valuations_router.put("/{valuation_id}", summary="更新估值评估", response_model=BasicResponse[ValuationAssessmentOut]) async def update_valuation(valuation_id: int, data: ValuationAssessmentUpdate): """更新估值评估记录""" - result = await valuation_controller.update(valuation_id, data) + result = await valuation_controller.update1(valuation_id, data) if not result: raise HTTPException(status_code=404, detail="估值评估记录不存在") import json diff --git a/app/controllers/invoice.py b/app/controllers/invoice.py index f4251ef..f7b1f7b 100644 --- a/app/controllers/invoice.py +++ b/app/controllers/invoice.py @@ -85,6 +85,17 @@ class InvoiceController(CRUDBase[Invoice, InvoiceCreate, InvoiceUpdate]): if header.app_user_id is not None: await InvoiceHeader.filter(app_user_id=header.app_user_id).exclude(id=header.id).update(is_default=False) await header.update_from_dict(update_data).save() + # 同步引用该抬头的发票基本信息 + sync_fields = { + "company_name": header.company_name, + "tax_number": header.tax_number, + "register_address": header.register_address, + "register_phone": header.register_phone, + "bank_name": header.bank_name, + "bank_account": header.bank_account, + "email": header.email, + } + await Invoice.filter(header_id=header.id).update(**sync_fields) return InvoiceHeaderOut.model_validate(header) async def list(self, page: int = 1, page_size: int = 10, **filters) -> InvoiceList: diff --git a/app/controllers/valuation.py b/app/controllers/valuation.py index 2a640ad..037ac4d 100644 --- a/app/controllers/valuation.py +++ b/app/controllers/valuation.py @@ -491,7 +491,7 @@ class ValuationController: await valuation.update_from_dict(update_data) await valuation.save() from datetime import datetime - valuation.status = update_data.get("status", "pending") + valuation.status ="pending" if not getattr(valuation, "audited_at", None): valuation.audited_at = datetime.now() await valuation.save() @@ -499,6 +499,28 @@ class ValuationController: out = ValuationAssessmentOut.model_validate(valuation) return await self._attach_user_phone(out) + async def update1(self, valuation_id: int, data: ValuationAssessmentUpdate) -> Optional[ValuationAssessmentOut]: + """更新估值评估""" + valuation = await self.model.filter(id=valuation_id, is_active=True).first() + if not valuation: + return None + + update_data = data.model_dump(exclude_unset=True) + if update_data: + if 'certificate_url' in update_data and update_data.get('certificate_url'): + from datetime import datetime + update_data['audited_at'] = datetime.now() + await valuation.update_from_dict(update_data) + await valuation.save() + from datetime import datetime + valuation.status ="success" + if not getattr(valuation, "audited_at", None): + valuation.audited_at = datetime.now() + await valuation.save() + + out = ValuationAssessmentOut.model_validate(valuation) + return await self._attach_user_phone(out) + async def delete(self, valuation_id: int) -> bool: """软删除估值评估""" valuation = await self.model.filter(id=valuation_id, is_active=True).first() diff --git a/app/schemas/invoice.py b/app/schemas/invoice.py index ee5d376..2367bdc 100644 --- a/app/schemas/invoice.py +++ b/app/schemas/invoice.py @@ -12,6 +12,13 @@ class InvoiceHeaderCreate(BaseModel): email: EmailStr is_default: Optional[bool] = False + @field_validator('register_address', 'register_phone', 'bank_name', 'bank_account', mode='before') + @classmethod + def _empty_to_none(cls, v): + if isinstance(v, str) and v.strip() == "": + return None + return v + class InvoiceHeaderOut(BaseModel): id: int @@ -22,7 +29,7 @@ class InvoiceHeaderOut(BaseModel): register_phone: str bank_name: str bank_account: str - email: EmailStr + email: Optional[str] = None class Config: from_attributes = True is_default: Optional[bool] = False