package dto // CreateRefundRequest 创建退款申请请求 type CreateRefundRequest struct { OrderID uint `json:"order_id" validate:"required" required:"true" description:"关联订单ID"` ActualReceivedAmount *int64 `json:"actual_received_amount" validate:"omitempty" description:"已废弃:实收金额由系统从原成功支付记录或订单实际收款派生并冻结,提交人填写无效"` Method string `json:"method" validate:"required,oneof=original_route customer_account asset_wallet agent_wallet" required:"true" description:"退款方式 (original_route:原路退款, customer_account:客户收款信息退款, asset_wallet:退回资产钱包, agent_wallet:退回代理主钱包)"` CustomerAccountInfo string `json:"customer_account_info" validate:"omitempty,max=1000" maxLength:"1000" description:"客户收款信息,仅客户收款信息退款方式必填,不得复用公司线下收款方式字典"` RequestedRefundAmount int64 `json:"requested_refund_amount" validate:"required,min=1" required:"true" minimum:"1" description:"申请退款金额(分)"` RefundVoucherKey []string `json:"refund_voucher_key" validate:"omitempty,max=5,dive,max=500" maxItems:"5" description:"退款凭证对象存储file_key列表(最多5个,仅客户收款信息退款方式必填,通过/storage/upload-url上传图片后获得)"` RefundReason string `json:"refund_reason" validate:"required,max=1000" required:"true" maxLength:"1000" description:"退款原因(必填,去除首尾空白后不得为空)"` // Remark 是申请人备注,随本次提交冻结进当次审批尝试快照;与审批备注(详情响应中的 remark)语义不同。 Remark *string `json:"remark" validate:"omitempty,max=500" maxLength:"500" description:"申请人备注(可选,随本次提交冻结进审批尝试快照,不改变审批备注)"` PackageUsageID *uint `json:"package_usage_id" validate:"omitempty" description:"关联套餐使用记录ID(可选)"` } // RefundIDRequest 退款申请ID路径参数 type RefundIDRequest struct { ID uint `path:"id" description:"退款申请ID" required:"true"` } // RejectRefundRequest 拒绝退款申请请求 type RejectRefundRequest struct { ID uint `json:"-" params:"id" path:"id" validate:"required" description:"退款申请ID"` RejectReason string `json:"reject_reason" validate:"required,max=500" required:"true" maxLength:"500" description:"拒绝原因(必填)"` } // ResubmitRefundRequest 重新提交退款申请请求 // 退款单被退回后,可修改部分字段后重新提交 type ResubmitRefundRequest struct { ID uint `json:"-" params:"id" path:"id" validate:"required" description:"退款申请ID"` ActualReceivedAmount *int64 `json:"actual_received_amount" validate:"omitempty,min=1" minimum:"1" description:"已废弃:实收金额由系统从原成功支付记录或订单实际收款派生并冻结,提交人填写无效"` Method *string `json:"method" validate:"omitempty,oneof=original_route customer_account asset_wallet agent_wallet" description:"退款方式 (original_route:原路退款, customer_account:客户收款信息退款, asset_wallet:退回资产钱包, agent_wallet:退回代理主钱包),不填沿用原有方式"` CustomerAccountInfo *string `json:"customer_account_info" validate:"omitempty,max=1000" maxLength:"1000" description:"客户收款信息,仅客户收款信息退款方式必填,不得复用公司线下收款方式字典"` RequestedRefundAmount *int64 `json:"requested_refund_amount" validate:"omitempty,min=1" minimum:"1" description:"申请退款金额(分)"` RefundVoucherKey *[]string `json:"refund_voucher_key" validate:"omitempty,max=5,dive,max=500" maxItems:"5" description:"退款凭证对象存储file_key列表(重新提交时可替换;客户收款信息退款方式必填,最多5个)"` RefundReason *string `json:"refund_reason" validate:"omitempty,max=1000" maxLength:"1000" description:"退款原因(不填沿用原有原因;重提时去除首尾空白后不得为空)"` // Remark 是本次重提的申请人备注,随本次尝试冻结;不填沿用该退款单最近一次尝试的备注。 Remark *string `json:"remark" validate:"omitempty,max=500" maxLength:"500" description:"申请人备注(可选,随本次重提冻结进新的审批尝试快照,历史尝试备注不被改写)"` } // ApproveRefundRequest 审批通过退款申请请求 type ApproveRefundRequest struct { ID uint `json:"-" params:"id" path:"id" validate:"required" description:"退款申请ID"` ApprovedRefundAmount *int64 `json:"approved_refund_amount" validate:"omitempty,min=1" minimum:"1" description:"审批实际退款金额(分),不填则使用申请金额"` Remark string `json:"remark" validate:"omitempty,max=500" maxLength:"500" description:"审批备注"` } // ReturnRefundRequest 退回退款申请请求 type ReturnRefundRequest struct { ID uint `json:"-" params:"id" path:"id" validate:"required" description:"退款申请ID"` Remark string `json:"remark" validate:"omitempty,max=500" maxLength:"500" description:"退回备注"` } // RefundListRequest 退款申请列表查询请求 type RefundListRequest struct { Page int `json:"page" query:"page" validate:"omitempty,min=1" minimum:"1" description:"页码(默认1)"` PageSize int `json:"page_size" query:"page_size" validate:"omitempty,min=1,max=100" minimum:"1" maximum:"100" description:"每页数量(默认20,最大100)"` Status *int `json:"status" query:"status" validate:"omitempty,min=1,max=6" minimum:"1" maximum:"6" description:"状态 (1:待审批, 2:已通过, 3:已拒绝, 4:已退回, 5:原路退款处理中, 6:原路退款失败)"` OrderID *uint `json:"order_id" query:"order_id" validate:"omitempty" description:"关联订单ID"` ShopID *uint `json:"shop_id" query:"shop_id" validate:"omitempty" description:"店铺ID"` AssetIdentifier string `json:"asset_identifier" query:"asset_identifier" validate:"omitempty,max=100" maxLength:"100" description:"资产标识精确检索(ICCID 或 设备虚拟号,非空时精确匹配)"` } // RefundResponse 退款申请详情响应 type RefundResponse struct { ID uint `json:"id" description:"退款申请ID"` RefundNo string `json:"refund_no" description:"退款单号"` OrderID uint `json:"order_id" description:"关联订单ID"` OrderNo string `json:"order_no" description:"订单号"` AssetIdentifier string `json:"asset_identifier,omitempty" description:"下单时资产的标识符快照(卡为 ICCID,设备优先使用 VirtualNo,缺失时使用 IMEI)"` AssetType string `json:"asset_type,omitempty" description:"资产类型 (card:单卡, device:设备)"` IotCardID *uint `json:"iot_card_id,omitempty" description:"IoT卡ID"` DeviceID *uint `json:"device_id,omitempty" description:"设备ID"` PackageUsageID *uint `json:"package_usage_id,omitempty" description:"关联套餐使用记录ID"` // 当前退款套餐用量:按冻结套餐使用记录 → 订单主套餐 → 订单任一套餐的优先级解析, // 只用于展示、查询与导出,不参与退款金额校验、套餐失效或佣金回溯。 RefundPackageUsedMB int64 `json:"refund_package_used_mb" description:"当前退款套餐已用量(MB,真实流量;解析不到套餐时为0)"` RefundPackageTotalMB int64 `json:"refund_package_total_mb" description:"当前退款套餐总量(MB,真实流量;解析不到套餐时为0)"` ShopID *uint `json:"shop_id,omitempty" description:"店铺ID"` ShopName string `json:"shop_name,omitempty" description:"店铺名称"` ActualReceivedAmount int64 `json:"actual_received_amount" description:"实收金额(分)"` RequestedRefundAmount int64 `json:"requested_refund_amount" description:"申请退款金额(分)"` ApprovedRefundAmount *int64 `json:"approved_refund_amount,omitempty" description:"审批实际退款金额(分)"` RefundVoucherKey []string `json:"refund_voucher_key" description:"退款凭证对象存储file_key列表(最多5个)"` RefundReason string `json:"refund_reason" description:"退款原因"` Status int `json:"status" description:"状态 (1:待审批, 2:已通过, 3:已拒绝, 4:已退回, 5:原路退款处理中, 6:原路退款失败)"` StatusName string `json:"status_name" description:"状态名称(中文)"` Method string `json:"method" description:"退款方式 (original_route:原路退款, customer_account:客户收款信息退款, asset_wallet:退回资产钱包, agent_wallet:退回代理主钱包),空表示未接入方式的存量申请"` MethodName string `json:"method_name" description:"退款方式中文名称"` FrozenActualReceivedAmount int64 `json:"frozen_actual_received_amount" description:"系统派生并冻结的权威实收金额(分),作为可退金额上限"` CustomerAccountInfo string `json:"customer_account_info" description:"客户收款信息自由文本快照,仅客户收款信息退款方式有值"` ChannelRefundStatus int `json:"channel_refund_status" description:"渠道原路退款状态 (0:未发起, 1:处理中, 2:已成功, 3:已失败),0 表示未发起渠道退款或不适用该退款方式"` ChannelRefundStatusName string `json:"channel_refund_status_name" description:"渠道原路退款状态中文名称"` ChannelRefundNo string `json:"channel_refund_no" description:"渠道退款流水号,渠道明确成功或失败后回填"` ChannelRefundRequestNo string `json:"channel_refund_request_no" description:"渠道退款请求号快照,用于幂等与对账"` ChannelRefundAmount int64 `json:"channel_refund_amount" description:"提交渠道的退款金额快照(分)"` ChannelRefundedAt string `json:"channel_refunded_at,omitempty" description:"渠道明确退款成功时间"` // 结算标识:前两项是冻结的来源支付事实,第三项是财务补录的线下处理流水号,语义互不相同。 SourcePaymentNo string `json:"source_payment_no" description:"冻结的来源支付单号,取创建申请时的原成功支付记录;线下订单无线上支付记录时为空字符串"` OriginalChannelTradeNo string `json:"original_channel_trade_no" description:"冻结的原支付渠道交易流水号,取创建申请时的原成功支付记录;线下订单无线上支付记录时为空字符串"` OfflineSettlementNo string `json:"offline_settlement_no" description:"线下退款处理流水号或凭证编号,由授权账号补录或更正;与渠道退款流水号语义不同"` OfflineSettledAt string `json:"offline_settled_at,omitempty" description:"线下退款处理流水号最近一次登记或更正时间"` OfflineSettledBy uint `json:"offline_settled_by" description:"线下退款处理流水号最近一次登记或更正的操作账号ID,0 表示未登记"` FailureReason string `json:"failure_reason" description:"结构化失败分类稳定编码 (channel_rejected:渠道明确拒绝, credential_invalid:渠道凭证失效, insufficient_balance:渠道余额不足, timeout_unknown:超时或结果未知, approval_rejected:企业微信驳回或关闭, revoked_after_approved:企业微信通过后撤销, payment_fact_invalid:本地原支付事实不可用),空表示无失败"` FailureReasonName string `json:"failure_reason_name" description:"失败分类中文名称"` FailureMessage string `json:"failure_message" description:"失败安全摘要,供人工排查;不含渠道凭证等敏感内容"` AnomalyFlag int `json:"anomaly_flag" description:"异常标记 (0:无异常, 1:有异常,需人工处理)"` AnomalyReason string `json:"anomaly_reason" description:"异常原因说明,无异常时为空"` LatestAttemptID uint `json:"latest_attempt_id" description:"最新审批尝试记录ID,仅用于展示"` LatestApprovalInstanceID uint `json:"latest_approval_instance_id" description:"最新通用审批实例ID,仅用于展示"` Attempts []RefundAttemptResponse `json:"attempts" description:"审批尝试记录,按提交顺序排列,历史材料不被覆盖;无尝试记录时为空数组"` ProcessorID *uint `json:"processor_id,omitempty" description:"审批人ID"` ProcessedAt string `json:"processed_at,omitempty" description:"审批时间"` RejectReason string `json:"reject_reason,omitempty" description:"拒绝原因"` Remark string `json:"remark,omitempty" description:"审批备注"` CommissionDeducted bool `json:"commission_deducted" description:"佣金是否已回扣"` AssetReset bool `json:"asset_reset" description:"退款后资产处理是否完成"` SubmitterID uint `json:"submitter_id" description:"提交人账号ID"` SubmitterName string `json:"submitter_name" description:"提交人账号名称"` ApprovalInstanceID *uint `json:"approval_instance_id,omitempty" description:"通用审批实例ID"` ApprovalProvider string `json:"approval_provider,omitempty" description:"审批渠道,企业微信为wecom"` ApprovalStatus *int `json:"approval_status,omitempty" description:"审批状态 (0:提交中, 1:审批中, 2:已通过, 3:已拒绝, 4:已撤销, 5:通过后撤销, 6:已删除, 7:提交失败, 8:提交结果未知)"` ApprovalStatusName string `json:"approval_status_name,omitempty" description:"审批状态名称(中文)"` Creator uint `json:"creator" description:"创建人ID"` Updater uint `json:"updater" description:"更新人ID"` CreatedAt string `json:"created_at" description:"创建时间"` UpdatedAt string `json:"updated_at" description:"更新时间"` } // RefundListResponse 退款申请列表分页响应 type RefundListResponse struct { Items []RefundResponse `json:"items" description:"退款申请列表"` Total int64 `json:"total" description:"总记录数"` Page int `json:"page" description:"当前页码"` Size int `json:"size" description:"每页数量"` } // RefundAttemptResponse 退款审批尝试响应,材料为本次提交的冻结快照。 type RefundAttemptResponse struct { ID uint `json:"id" description:"审批尝试记录ID,同时是通用审批业务ID"` AttemptNo int `json:"attempt_no" description:"第几次提交,从 1 递增"` Method string `json:"method" description:"本次冻结的退款方式 (original_route:原路退款, customer_account:客户收款信息退款, asset_wallet:退回资产钱包, agent_wallet:退回代理主钱包)"` MethodName string `json:"method_name" description:"本次冻结的退款方式中文名称"` RefundAmount int64 `json:"refund_amount" description:"本次提交冻结的申请退款金额(分)"` FrozenActualReceivedAmount int64 `json:"frozen_actual_received_amount" description:"本次提交冻结的权威实收金额(分)"` RefundReason string `json:"refund_reason" description:"本次提交的退款原因"` Remark string `json:"remark" description:"本次提交冻结的申请人备注快照,未填写时为空;与审批备注(详情响应中的 remark)不是同一字段"` CustomerAccountInfo string `json:"customer_account_info" description:"本次冻结的客户收款信息快照,非客户收款信息退款方式为空"` CustomerVoucherKey []string `json:"customer_voucher_key" description:"客户收款凭证对象存储file_key列表,仅返回对象键引用"` ChannelRefundRequestNo string `json:"channel_refund_request_no" description:"本次提交使用的渠道退款请求号快照,用于幂等与对账"` SubmittedByAccountID uint `json:"submitted_by_account_id" description:"本次实际提交账号ID"` ApprovalInstanceID uint `json:"approval_instance_id" description:"本次尝试关联的通用审批实例ID,0 表示未关联"` ApprovalStatus *int `json:"approval_status,omitempty" description:"通用审批实例状态 (0:提交中, 1:审批中, 2:已通过, 3:已拒绝, 4:已撤销, 5:通过后撤销, 6:已删除, 7:提交失败, 8:提交结果未知)"` ApprovalStatusName string `json:"approval_status_name" description:"通用审批实例状态中文名称"` CreatedAt string `json:"created_at" description:"创建时间"` } // RefundOrderOptionsRequest 按来源订单查询可选退款方式请求。 type RefundOrderOptionsRequest struct { OrderID uint `json:"order_id" query:"order_id" validate:"required,min=1" required:"true" minimum:"1" description:"来源订单ID"` } // RefundMethodOptionResponse 描述一种可选退款方式及其当前可用性。 type RefundMethodOptionResponse struct { Method string `json:"method" description:"退款方式 (original_route:原路退款, customer_account:客户收款信息退款, asset_wallet:退回资产钱包, agent_wallet:退回代理主钱包)"` MethodName string `json:"method_name" description:"退款方式中文名称"` Available bool `json:"available" description:"该方式当前是否可用"` Unavailable string `json:"unavailable_reason" description:"不可用原因;可用时为空字符串"` } // RefundCapabilityResponse 是原路退款能力校验结果投影。 type RefundCapabilityResponse struct { Available bool `json:"available" description:"原路退款能力校验是否通过(凭证完整性、服务商类型与渠道可退时限)"` Unavailable string `json:"unavailable_reason" description:"不通过原因;通过时为空字符串"` } // RefundOrderOptionsResponse 按来源订单查询可选退款方式响应。 type RefundOrderOptionsResponse struct { OrderID uint `json:"order_id" description:"来源订单ID"` OrderNo string `json:"order_no" description:"来源订单号"` OrderPaymentType string `json:"order_payment_type" description:"来源订单支付方式 (wechat:微信, alipay:支付宝, wallet:钱包, offline:后台线下)"` Methods []RefundMethodOptionResponse `json:"methods" description:"可选退款方式集合,含每种方式的可用性与不可用原因;判定事实缺失时为空数组"` MerchantID *uint `json:"merchant_id,omitempty" description:"原收款商户ID,无实际收款商户时为空"` MerchantName string `json:"merchant_name" description:"原收款商户名称快照,无实际收款商户时为空字符串"` OriginalChannelTradeNo string `json:"original_channel_trade_no" description:"原支付渠道交易流水号,无线上支付记录时为空字符串"` RefundCapability RefundCapabilityResponse `json:"refund_capability" description:"原路退款能力校验结果"` // UnavailableReason 在判定所需事实缺失(如无原成功支付记录或订单支付方式不支持退款)时说明原因, // 使调用方得到不可用原因而不是请求失败。 UnavailableReason string `json:"unavailable_reason" description:"整体判定不可用时的原因,可用时为空字符串"` } // OfflineSettlementRequest 登记或更正线下退款处理流水号请求。 type OfflineSettlementRequest struct { ID uint `json:"-" params:"id" path:"id" validate:"required" description:"退款申请ID"` // OfflineSettlementNo 记录财务实际执行的线下退款处理流水号或凭证编号;重复提交即更正,历史值由审计留存。 OfflineSettlementNo string `json:"offline_settlement_no" validate:"required,max=128" required:"true" maxLength:"128" description:"线下退款处理流水号或凭证编号(必填,去除首尾空白后不得为空)"` }