- 审批核心在实例进入提交失败的同一事务内写 submission_failed 决策投递与终态事件,消费入口单独放行 - 核销(4)、退款(7)、扫码注册(3)、资料资格(4)、线下充值(7)、佣金提现(5)新增“审批提交失败”终态并释放预占/冻结 - 三处恢复入口不再重放提交失败;退款关闭类终态按审批尝试定位退款单(M13) - 核销列表与详情批量返回审批提交状态;筛选、字段说明、状态名称、退款导出加入新状态 - 迁移 000239 放宽五张业务表状态约束与决策投递取值约束(测试库已执行 up/down/up) - OpenSpec Change fix-approval-submission-failure-terminal:18/26,测试部署后端到端验证与存量补数据待完成
72 lines
3.0 KiB
Go
72 lines
3.0 KiB
Go
package employeecollection
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
approvalapp "github.com/break/junhong_cmp_fiber/internal/application/approval"
|
|
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
|
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
|
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
|
)
|
|
|
|
// applicationSubmissionRow 是核销申请最新审批实例的提交事实。
|
|
type applicationSubmissionRow struct {
|
|
InstanceID uint `gorm:"column:instance_id"`
|
|
InstanceStatus int `gorm:"column:instance_status"`
|
|
SubmissionStatus int `gorm:"column:submission_status"`
|
|
LastError string `gorm:"column:last_error"`
|
|
LastRecoveryAt *time.Time `gorm:"column:last_recovery_at"`
|
|
}
|
|
|
|
// fillApplicationSubmission 按最新审批实例一次批量读取企微审批上下文,填充提交状态、脱敏摘要、可恢复与最近恢复时间。
|
|
// 无审批实例或无企微上下文的申请保持零值。
|
|
func (q *ApplicationQuery) fillApplicationSubmission(ctx context.Context, responses []*dto.EmployeeCollectionApplicationResponse) error {
|
|
instanceIDs := make([]uint, 0, len(responses))
|
|
for _, response := range responses {
|
|
if response != nil && response.LatestApprovalInstanceID != 0 {
|
|
instanceIDs = append(instanceIDs, response.LatestApprovalInstanceID)
|
|
}
|
|
}
|
|
if len(instanceIDs) == 0 {
|
|
return nil
|
|
}
|
|
var rows []applicationSubmissionRow
|
|
if err := q.db.WithContext(ctx).Raw(
|
|
`SELECT ai.id AS instance_id, ai.status AS instance_status,
|
|
COALESCE(wc.submission_status, 0) AS submission_status,
|
|
COALESCE(wc.last_error, '') AS last_error, wc.last_recovery_at
|
|
FROM tb_approval_instance ai
|
|
LEFT JOIN tb_wecom_approval_context wc ON wc.approval_instance_id = ai.id
|
|
WHERE ai.id IN ?`, instanceIDs).Scan(&rows).Error; err != nil {
|
|
return errors.Wrap(errors.CodeDatabaseError, err, "批量查询核销申请审批提交状态失败")
|
|
}
|
|
byInstance := make(map[uint]applicationSubmissionRow, len(rows))
|
|
for _, row := range rows {
|
|
byInstance[row.InstanceID] = row
|
|
}
|
|
for _, response := range responses {
|
|
if response == nil {
|
|
continue
|
|
}
|
|
row, ok := byInstance[response.LatestApprovalInstanceID]
|
|
if !ok {
|
|
continue
|
|
}
|
|
response.ApprovalSubmissionStatus = row.SubmissionStatus
|
|
response.ApprovalSubmissionName = constants.GetWeComSubmissionStatusName(row.SubmissionStatus)
|
|
if row.SubmissionStatus == constants.WeComSubmissionStatusFailed {
|
|
response.ApprovalFailureSummary = approvalapp.SubmissionFailureReason(row.LastError)
|
|
}
|
|
// 提交失败为终态不可恢复;只有审批中的申请且实例仍在提交中、审批中或结果未知时可恢复。
|
|
response.Recoverable = response.Status == constants.EmployeeCollectionApplicationStatusPending &&
|
|
(row.InstanceStatus == constants.ApprovalStatusSubmitting ||
|
|
row.InstanceStatus == constants.ApprovalStatusPending ||
|
|
row.InstanceStatus == constants.ApprovalStatusSubmissionUnknown)
|
|
if row.LastRecoveryAt != nil {
|
|
response.LastRecoveryAt = row.LastRecoveryAt.UTC().Format(time.RFC3339)
|
|
}
|
|
}
|
|
return nil
|
|
}
|