from datetime import datetime from decimal import Decimal from typing import List, Optional from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator class BankcardExtInfoSchema(BaseModel): """银行卡信息""" # account_type|收款账户类型 # 【描述】收款账户类型。 1:对公(在金融机构开设的公司账户),如果银行卡为对公,必须传递省市支行信息或者联行号 # 2:对私(在金融机构开设的个人账户) account_type: str = Field(description="收款账户类型: 1/2。对公: 1,对私: 2") # inst_name|机构名称 # 【描述】当收款账户为对公账户时,机构名称必填;当收款账户为对私账户时,机构名称可为空。 inst_name: Optional[str] = Field(default=None, description="机构名称") # 【描述】银行所在省份 inst_province: Optional[str] = Field(default=None, description="银行所在省份") # inst_city|收款银行所在市 # 【描述】收款银行所在市 inst_city: Optional[str] = Field(default=None, description="收款银行所在市") # inst_branch_name|收款银行所属支行 # 【描述】收款银行所属支行 inst_branch_name: Optional[str] = Field(default=None, description="收款银行所属支行") # bank_code|银行支行联行号 # 【描述】银行支行联行号 bank_code: Optional[str] = Field(default=None, description="银行支行联行号") @field_validator("account_type") def validate_account_type(cls, v: str) -> str: if v not in ["1", "2"]: raise ValueError(f"account_type 必须是 {['1', '2']}") return v @model_validator(mode='after') def validate_inst_name(self) -> 'BankcardExtInfoSchema': """验证对公账户时inst_name必填""" if self.account_type == "1" and self.inst_name is None: raise ValueError("当 account_type 是 1 时,inst_name 必填") return self class PayeeInfoSchema(BaseModel): """收款方信息""" identity_type: str = Field(description="收款方类型: ALIPAY_ACCOUNT/BANK_CARD/BOOK") name: str = Field(description="收款方真实姓名") identity: str = Field(description="收款方唯一标识") bankcard_ext_info: Optional[BankcardExtInfoSchema] = Field(default=None, description="银行卡信息") @field_validator("identity_type") def validate_identity_type(cls, v: str) -> str: if v == "alipay": return "ALIPAY_ACCOUNT" elif v == "bank": return "BANK_CARD" elif v == "book": return "BOOK" else: raise ValueError(f"identity_type must be one of {['alipay', 'bank', 'book']}") @model_validator(mode='after') def validate_bankcard_ext_info(self) -> 'PayeeInfoSchema': """验证银行卡类型时bankcard_ext_info必填""" if self.identity_type == "BANK_CARD" and self.bankcard_ext_info is None: raise ValueError("当 identity_type 是银行卡时,bankcard_ext_info 必填") return self class AccountAuthorizeApplySchema(BaseModel): """申请转账授权签约请求""" enterprise_id: str = Field(description="企业ID") class AccountAuthorizeCallbackSchema(BaseModel): """转账授权回调通知请求""" enterprise_id: str = Field(description="企业ID") status: str = Field(description="协议状态: NORMAL") sign_time: str = Field(description="签约时间") class AccountCreateSchema(BaseModel): """开通资金专户请求""" enterprise_id: str = Field(description="企业ID") account_type: Optional[str] = Field(default="ALL", description="账户类型: INCOME/DISBURSE/ALL") scene: Optional[str] = Field(default="B2B_TRANS", description="场景类型: ENT_CREDIT/B2B_TRANS") account_book_id: Optional[str] = Field(default=None, description="资金专户号") remark: Optional[str] = Field(default=None, description="备注") class AccountDepositSchema(BaseModel): """资金专户充值请求""" enterprise_id: str = Field(description="企业ID") account_book_id: str = Field(description="资金专户号") amount: Decimal = Field(max_digits=10, decimal_places=2, gt=0, description="充值金额") out_biz_no: Optional[str] = Field(default=None, description="外部订单号") remark: Optional[str] = Field(default=None, description="充值备注") class AccountTransferSchema(BaseModel): """资金专户转账请求""" enterprise_id: str = Field(description="企业ID") account_book_id: Optional[str] = Field(default=None, description="付款方资金专户号") out_biz_no: Optional[str] = Field(default=None, description="商家侧订单号") # 转账总金额,单位为元,精确到小数点后两位 amount: Decimal = Field(max_digits=10, decimal_places=2, gt=0, description="转账金额") order_title: Optional[str] = Field(default=None, description="转账标题") remark: Optional[str] = Field(default=None, description="转账备注") payee_info: PayeeInfoSchema = Field(description="收款方信息") employee_id: Optional[str] = Field(default=None, description="员工ID") priority: Optional[str] = Field(default="NORMAL", description="优先级: HIGH/NORMAL/LOW") ext_info: Optional[dict] = Field(default=None, description="扩展信息") @model_validator(mode="after") def validate_ext_info(self): if self.ext_info and not isinstance(self.ext_info, dict): raise ValueError("ext_info 需要是字典类型") return self class AccountWithdrawSchema(BaseModel): """资金专户提现请求""" enterprise_id: str = Field(description="企业ID") account_book_id: str = Field(description="资金专户号") amount: Decimal = Field(max_digits=10, decimal_places=2, gt=0, description="提现金额") out_biz_no: str = Field(description="商家侧订单号") class ReceiptApplySchema(BaseModel): """申请资金回单请求""" enterprise_id: str = Field(description="企业ID") order_no: str = Field(description="支付宝转账单号") class AccountQuerySchema(BaseModel): """资金专户查询请求""" enterprise_id: str = Field(description="企业ID") class AccountOutSchema(BaseModel): """资金专户响应模型""" model_config = ConfigDict(from_attributes=True) id: int = Field(description="主键ID") enterprise_id: Optional[str] = Field(default=None, description="所属企业ID") account_book_id: Optional[str] = Field(default=None, description="资金专户号") account_name: Optional[str] = Field(default=None, description="专户名称") scene: str = Field(description="场景类型") sign_status: str = Field(description="授权状态") sign_time: Optional[datetime] = Field(default=None, description="授权时间") status: str = Field(description="专户状态") created_time: datetime = Field(description="创建时间") updated_time: datetime = Field(description="更新时间") class AccountAuthorizeApplyOutSchema(BaseModel): """申请转账授权响应""" sign_url: Optional[str] = Field(description="签约链接") class AccountDepositOutSchema(BaseModel): """充值响应""" url: Optional[str] = Field(description="充值确认页面URL") class AccountTransferOutSchema(BaseModel): """转账响应""" status: Optional[str] = Field(description="转账状态,SUCCESS:成功(对转账到银行卡的单据, 该状态可能变为退票[REFUND]); FAIL:失败; DEALING:处理中(转账到支付宝账户不涉及); REFUND:退票(转账到支付宝账户不涉及)") order_no: Optional[str] = Field(default=None, description="支付宝转账单号") fund_order_id: Optional[str] = Field(default=None, description="宝支付资金流水号") class AccountTransferBatchSchema(BaseModel): """批量资金专户转账请求""" transfers: List[AccountTransferSchema] = Field( description="转账列表" ) callback_url: Optional[str] = Field( default=None, description="转账结果回调URL" ) class AccountTransferBatchOutSchema(BaseModel): """批量转账响应""" batch_id: str = Field(description="批次ID") status: str = Field(description="状态: PENDING/PROCESSING/COMPLETED") total: int = Field(description="总笔数") processed: int = Field(description="已处理笔数") success: int = Field(description="成功笔数") failed: int = Field(description="失败笔数") class TransferResultSchema(BaseModel): """单笔转账结果""" out_biz_no: str = Field(description="商家侧订单号") status: str = Field(description="状态: SUCCESS/FAIL") order_no: Optional[str] = Field(default=None, description="支付宝转账单号") error_msg: Optional[str] = Field(default=None, description="错误信息") class TransferTaskSchema(BaseModel): """转账任务""" task_id: str = Field(description="任务ID") enterprise_id: str = Field(description="企业ID") account_book_id: str = Field(description="资金专户号") out_biz_no: str = Field(description="商家侧订单号") amount: Decimal = Field(max_digits=10, decimal_places=2, gt=0, description="转账金额") order_title: str = Field(description="转账标题") payee_info: PayeeInfoSchema = Field(description="收款方信息") priority: str = Field(default="NORMAL", description="优先级: HIGH/NORMAL/LOW") status: str = Field(default="PENDING", description="状态: PENDING/PROCESSING/SUCCESS/FAILED/RETRYING") retries: int = Field(default=0, description="重试次数") created_at: str = Field(description="创建时间") class TransferTaskOutSchema(BaseModel): """转账任务响应""" task_id: str = Field(description="任务ID") status: str = Field(description="任务状态") enterprise_id: str = Field(description="企业ID") out_biz_no: str = Field(description="商家侧订单号") amount: Decimal = Field(max_digits=10, decimal_places=2, gt=0, description="转账金额") priority: str = Field(description="优先级") created_at: str = Field(description="创建时间") class TransferQueueStatusSchema(BaseModel): """队列状态""" enterprise_id: str = Field(description="企业ID") pending_count: int = Field(description="待处理任务数") processing_count: int = Field(description="处理中任务数") completed_count: int = Field(description="已完成任务数") high_priority_count: int = Field(description="高优先级任务数") normal_priority_count: int = Field(description="普通优先级任务数") low_priority_count: int = Field(description="低优先级任务数") class TransferOutSchema(BaseModel): """转账记录响应""" model_config = ConfigDict(from_attributes=True) # id: int = Field(description="主键ID") enterprise_id: Optional[str] = Field(default=None, description="所属企业ID") out_biz_no: Optional[str] = Field(default=None, description="商家侧订单号") account_book_id: Optional[str] = Field(default=None, description="付款方资金专户号") amount: Decimal = Field(max_digits=10, decimal_places=2, gt=0, description="转账金额") order_title: Optional[str] = Field(default=None, description="转账标题") payee_info: Optional[dict] = Field(default=None, description="收款方信息") status: str = Field(description="转账状态") order_no: Optional[str] = Field(default=None, description="支付宝转账单号") error_code: Optional[str] = Field(default=None, description="错误码") error_msg: Optional[str] = Field(default=None, description="错误信息") ext_info: Optional[dict] = Field(default=None, description="扩展信息") created_time: datetime = Field(description="创建时间") class TransferListOutSchema(BaseModel): """转账记录列表响应""" model_config = ConfigDict(from_attributes=True) id: int = Field(description="主键ID") out_biz_no: Optional[str] = Field(default=None, description="商家侧订单号") account_book_id: Optional[str] = Field(default=None, description="付款方资金专户号") amount: Optional[float] = Field(default=None, description="转账金额") order_title: Optional[str] = Field(default=None, description="转账标题") status: str = Field(description="转账状态") order_no: Optional[str] = Field(default=None, description="支付宝转账单号") fund_order_id: Optional[str] = Field(default=None, description="宝支付资金流水号") payee_info: Optional[dict] = Field(default=None, description="收款方信息") created_time: datetime = Field(description="创建时间") class DepositOutSchema(BaseModel): """充值记录响应""" model_config = ConfigDict(from_attributes=True) id: int = Field(description="主键ID") enterprise_id: Optional[str] = Field(default=None, description="所属企业ID") out_biz_no: Optional[str] = Field(default=None, description="商家侧订单号") account_book_id: Optional[str] = Field(default=None, description="资金专户号") amount: Optional[float] = Field(default=None, description="充值金额") deposit_url: Optional[str] = Field(default=None, description="充值确认页面URL") status: str = Field(description="充值状态") created_time: datetime = Field(description="创建时间") class WithdrawOutSchema(BaseModel): """提现记录响应""" model_config = ConfigDict(from_attributes=True) id: int = Field(description="主键ID") enterprise_id: Optional[str] = Field(default=None, description="所属企业ID") out_biz_no: Optional[str] = Field(default=None, description="商家侧订单号") account_book_id: Optional[str] = Field(default=None, description="资金专户号") amount: Optional[Decimal] = Field(default=None, description="提现金额") status: str = Field(description="提现状态") order_no: Optional[str] = Field(default=None, description="支付宝提现单号") error_code: Optional[str] = Field(default=None, description="错误码") error_msg: Optional[str] = Field(default=None, description="错误信息") created_time: datetime = Field(description="创建时间") class ReceiptApplyOutSchema(BaseModel): """申请回单响应""" model_config = ConfigDict(from_attributes=True) file_id: str = Field(description="文件申请号") class ReceiptQueryOutSchema(BaseModel): """查询回单响应""" model_config = ConfigDict(from_attributes=True) file_id: str = Field(description="文件申请号") status: str = Field(description="处理状态: INIT/PROCESS/SUCCESS/FAIL") download_url: Optional[str] = Field(default=None, description="下载链接") error_message: Optional[str] = Field(default=None, description="错误信息") class AccountOperationOutSchema(BaseModel): """资金专户操作响应""" model_config = ConfigDict(from_attributes=True) enterprise_id: Optional[str] = Field(default=None, description="企业ID") account_book_id: Optional[str] = Field(default=None, description="资金专户号") class ConsumeDetailQuerySchema(BaseModel): """账单详情查询请求""" pay_no: str = Field(..., description="支付宝账单号") enterprise_id: Optional[str] = Field(default=None, description="企业ID(2.0接口签约企业必填)") ant_shop_id: Optional[str] = Field(default=None, description="蚂蚁门店ID(商户服务商必填)") query_options: Optional[List[str]] = Field( default=None, description="查询选项: Refund(关联退款账单)/Order(关联订单)/Ticket(关联票据)" ) class EcConsumeInfoSchema(BaseModel): """账单信息子属性""" model_config = ConfigDict(from_attributes=True) account_id: str = Field(description="共同账户ID") pay_no: str = Field(description="交易流水号") consume_type: str = Field(description="账单类型: CONSUME(消费账单)/REFUND(退款账单)/TRANSFER(转账账单)") gmt_biz_create: str = Field(description="账单创建时间,格式:yyyy-MM-dd HH:mm:ss") consume_biz_type: str = Field(description="账单业务类型: EC_PAY(因公支付)/EC_CLLCT(因公收款)") consume_amount: str = Field(description="账单金额,单位:元") order_complete_label: str = Field(description="订单完结标识: 0(未完结)/1(已完结)") refund_status: str = Field(description="退款状态: INIT(未退款)/REFUND_PART(部分退款)/REFUND_FULL(全额退款)") refund_amount: str = Field(description="退款金额,单位:元") peer_payer_card_name: str = Field(description="实际出资人名称") user_id: Optional[str] = Field(default=None, description="员工支付宝UID") open_id: Optional[str] = Field(default=None, description="员工open_id") enterprise_id: str = Field(description="企业ID") employee_id: str = Field(description="员工ID") enterprise_name: Optional[str] = Field(default=None, description="企业名称") employee_name: Optional[str] = Field(default=None, description="员工名称") consume_scene_code: Optional[str] = Field(default=None, description="消费场景编码") consume_type_sub_category: Optional[str] = Field(default=None, description="消费类型子类") consume_title: Optional[str] = Field(default=None, description="账单标题") gmt_pay: Optional[str] = Field(default=None, description="账单支付时间") gmt_refund: Optional[str] = Field(default=None, description="退款时间") pay_amount: Optional[str] = Field(default=None, description="用户实际支付金额") invoice_amount: Optional[str] = Field(default=None, description="用户实际承担金额") peer_pay_amount: Optional[str] = Field(default=None, description="企业代付金额") subsidy_amount: Optional[str] = Field(default=None, description="补贴金额") ext_infos: Optional[dict] = Field(default=None, description="扩展信息") class ConsumeDetailOutSchema(BaseModel): """账单详情查询响应""" model_config = ConfigDict(from_attributes=True) consume_info: EcConsumeInfoSchema = Field(description="账单信息")