刘光辉
2 小时以前 06f314545ac3514d7ce28939920866ae8188d31c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="jnpf.dmsMapper.DmsApprovedBatchMapper">
<resultMap id="Batch" type="jnpf.dmsEntity.storage.approval.DmsApprovedBatch">
    <result column="id" property="id" typeHandler="jnpf.dmsDatabase.DmsUuidTypeHandler"/>
    <result column="tenant_id" property="tenantId"/>
    <result column="flow_id" property="flowId"/>
    <result column="task_id" property="taskId"/>
    <result column="audit_id" property="auditId"/>
    <result column="audit_type" property="auditType"/>
    <result column="source_digest" property="sourceDigest"/>
    <result column="approval_render_snapshot" property="approvalRenderSnapshot"/>
    <result column="actor_id" property="actorId"/>
    <result column="approved_at" property="approvedAt"/>
    <result column="scheduled_at" property="scheduledAt"/>
    <result column="effective_to" property="effectiveTo"/>
    <result column="activated_at" property="activatedAt"/>
    <result column="status" property="status"/>
    <result column="attempts" property="attempts"/>
    <result column="next_attempt_at" property="nextAttemptAt"/>
    <result column="lease_token" property="leaseToken"/>
    <result column="lease_until" property="leaseUntil"/>
    <result column="last_error" property="lastError"/>
</resultMap>
<resultMap id="Item" type="jnpf.dmsEntity.storage.approval.DmsApprovedItem">
    <result column="batch_id" property="batchId" typeHandler="jnpf.dmsDatabase.DmsUuidTypeHandler"/>
    <result column="tenant_id" property="tenantId"/>
    <result column="source_key" property="sourceKey"/>
    <result column="source_row_id" property="sourceRowId"/>
    <result column="change_type" property="changeType"/>
    <result column="file_id" property="fileId"/>
    <result column="business_version_id" property="businessVersionId"/>
    <result column="document_id" property="documentId" typeHandler="jnpf.dmsDatabase.DmsUuidTypeHandler"/>
    <result column="file_version_id" property="fileVersionId" typeHandler="jnpf.dmsDatabase.DmsUuidTypeHandler"/>
    <result column="base_file_version_id" property="baseFileVersionId" typeHandler="jnpf.dmsDatabase.DmsUuidTypeHandler"/>
    <result column="checksum_sha256" property="checksumSha256"/>
    <result column="storage_receipt" property="storageReceipt"/>
    <result column="read_access_scope" property="readAccessScope"/>
    <result column="shifou_shoukong" property="shifouShoukong"/>
</resultMap>
    <sql id="BatchColumns">id, tenant_id, flow_id, task_id, audit_id, audit_type, source_digest, approval_render_snapshot::text AS approval_render_snapshot, actor_id, approved_at, scheduled_at, effective_to, activated_at, status, attempts, next_attempt_at, lease_token, lease_until, last_error</sql>
    <sql id="ItemColumns">batch_id, tenant_id, source_key, source_row_id, change_type, file_id, business_version_id, document_id, file_version_id, base_file_version_id, checksum_sha256, storage_receipt::text AS storage_receipt, shifou_shoukong, read_access_scope::text AS read_access_scope</sql>
    <select id="nextUuidV7" resultType="java.lang.String" useCache="false" flushCache="true">SELECT CAST(uuidv7() AS text)</select>
    <select id="find" resultMap="Batch">
        SELECT <include refid="BatchColumns"/> FROM public.dms_approved_file_batches
        WHERE tenant_id = #{tenantId} AND task_id = #{taskId} AND audit_type = #{auditType}
    </select>
    <select id="lock" resultMap="Batch">
        SELECT <include refid="BatchColumns"/> FROM public.dms_approved_file_batches
        WHERE tenant_id = #{tenantId} AND id = #{id,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler} FOR UPDATE
    </select>
    <select id="items" resultMap="Item">
        SELECT <include refid="ItemColumns"/> FROM public.dms_approved_file_items
        WHERE tenant_id = #{tenantId} AND batch_id = #{batchId,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler} ORDER BY source_key
    </select>
    <select id="item" resultMap="Item">
        SELECT <include refid="ItemColumns"/> FROM public.dms_approved_file_items
        WHERE tenant_id = #{tenantId} AND source_key = #{sourceKey}
    </select>
    <select id="due" resultMap="Batch">
        SELECT <include refid="BatchColumns"/> FROM public.dms_approved_file_batches
        WHERE audit_type IN ('xinzeng_shenhe','xiuding_shenhe','wailai_wenjian_xinzeng_shenhe') AND status = 'WAITING' AND scheduled_at &lt;= CURRENT_TIMESTAMP ORDER BY scheduled_at, id LIMIT 100
    </select>
    <insert id="insertBatch">INSERT INTO public.dms_approved_file_batches (id, tenant_id, flow_id, task_id, audit_id, audit_type, source_digest, approval_render_snapshot, actor_id, approved_at, scheduled_at, effective_to, activated_at, status) VALUES (#{id,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler}, #{tenantId}, #{flowId}, #{taskId}, #{auditId}, #{auditType}, #{sourceDigest}, CAST(#{approvalRenderSnapshot,jdbcType=VARCHAR} AS jsonb), #{actorId}, #{approvedAt}, #{scheduledAt}, #{effectiveTo}, #{activatedAt}, #{status})</insert>
    <insert id="insertItem">
        INSERT INTO public.dms_approved_file_items
            (batch_id, tenant_id, source_key, source_row_id, change_type, file_id, business_version_id,
             document_id, file_version_id, base_file_version_id, checksum_sha256, shifou_shoukong, read_access_scope)
        VALUES (#{batchId,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler}, #{tenantId},
                #{sourceKey}, #{sourceRowId}, #{changeType}, #{fileId}, #{businessVersionId},
                #{documentId,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler},
                #{fileVersionId,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler},
                #{baseFileVersionId,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler},
                #{checksumSha256}, #{shifouShoukong}, COALESCE(CAST(#{readAccessScope,jdbcType=VARCHAR} AS jsonb), '[]'::jsonb))
    </insert>
    <update id="repairReservation">
        UPDATE public.dms_approved_file_items i
        SET document_id=#{item.documentId,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler},
            file_version_id=#{item.fileVersionId,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler}
        WHERE i.tenant_id=#{item.tenantId} AND i.batch_id=#{item.batchId,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler}
          AND i.source_key=#{item.sourceKey} AND i.checksum_sha256 IS NULL
          AND i.document_id=#{oldDocumentId,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler}
          AND i.file_version_id=#{oldVersionId,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler}
          AND EXISTS (SELECT 1 FROM public.dms_approved_file_batches b WHERE b.tenant_id=i.tenant_id AND b.id=i.batch_id AND b.status='REGISTERING')
    </update>
    <update id="storePhysicalReceipt">
        UPDATE public.dms_approved_file_items i SET storage_receipt=CAST(#{receipt} AS jsonb)
        WHERE i.tenant_id=#{tenantId} AND i.batch_id=#{batchId,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler}
          AND i.source_key=#{sourceKey} AND i.storage_receipt IS NULL
          AND EXISTS (SELECT 1 FROM public.dms_approved_file_batches b
              WHERE b.tenant_id=i.tenant_id AND b.id=i.batch_id AND b.status='REGISTERING'
                AND b.lease_token=#{token} AND b.lease_until &gt; CURRENT_TIMESTAMP)
    </update>
    <update id="registered">
        UPDATE public.dms_approved_file_batches SET status = 'WAITING'
        WHERE tenant_id = #{tenantId} AND id = #{id,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler} AND status = 'REGISTERING'
    </update>
    <update id="storeChecksum">
        UPDATE public.dms_approved_file_items SET checksum_sha256 = #{checksum}
        WHERE tenant_id = #{tenantId} AND batch_id = #{batchId,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler} AND source_key = #{sourceKey}
          AND checksum_sha256 IS NULL
    </update>
    <update id="activate">
        UPDATE public.dms_approved_file_batches SET status = 'EFFECTIVE', activated_at = CURRENT_TIMESTAMP
        WHERE tenant_id = #{tenantId} AND id = #{id,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler} AND status IN ('WAITING','FAILED') AND scheduled_at &lt;= CURRENT_TIMESTAMP
    </update>
    <update id="applied">
        UPDATE public.dms_approved_file_batches SET status = 'APPLIED'
        WHERE tenant_id = #{tenantId} AND id = #{id,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler} AND status = 'EFFECTIVE'
    </update>
    <update id="fail">
        UPDATE public.dms_approved_file_batches SET status = 'FAILED'
        WHERE tenant_id = #{tenantId} AND id = #{id,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler} AND status = 'WAITING'
    </update>
    <!-- Only native new/revision approvals without a settled version are recovered. -->
    <insert id="discover">
        INSERT INTO public.dms_approved_file_batches
            (id,tenant_id,flow_id,task_id,audit_id,audit_type,actor_id,approved_at,status)
        SELECT gen_random_uuid(), a.tenant_id, a.flow_id, a.task_id, a.audit_id, a.audit_type,
               COALESCE(NULLIF(t.f_last_modify_user_id,''),t.f_creator_user_id), t.f_end_time, 'PREPARING'
        FROM (
            SELECT f_tenant_id tenant_id,f_flow_id flow_id,f_flow_task_id task_id,f_id audit_id,'xinzeng_shenhe' audit_type
            FROM public.dms_wenjian_xinzeng_shenhe
            WHERE f_flow_state=2 AND f_delete_mark IS NULL AND shengxiao_wenjian_banben_id IS NULL AND banben_shengxiao_shijian IS NULL
            UNION ALL
            SELECT f_tenant_id,f_flow_id,f_flow_task_id,f_id,'xiuding_shenhe'
            FROM public.dms_wenjian_xiuding_shenhe
            WHERE f_flow_state=2 AND f_delete_mark IS NULL AND shengxiao_wenjian_banben_id IS NULL AND banben_shengxiao_shijian IS NULL
            UNION ALL
            SELECT f_tenant_id,f_flow_id,f_flow_task_id,f_id,'wailai_wenjian_xinzeng_shenhe'
            FROM public.dms_wailai_wenjian_xinzeng_shenhe
            WHERE f_flow_state=2 AND f_delete_mark IS NULL AND shengxiao_wenjian_banben_id IS NULL
              AND banben_shengxiao_shijian IS NULL AND wenjian_id IS NULL
              AND NULLIF(btrim(biz_files),'') IS NOT NULL
              AND NULLIF(btrim(banbenhao),'') IS NOT NULL
              AND NULLIF(btrim(wenjian_mulu_id),'') IS NOT NULL
        ) a JOIN public.workflow_task t ON t.f_tenant_id=a.tenant_id AND t.f_id=a.task_id
            AND (t.f_flow_id=a.flow_id OR t.f_template_id=a.flow_id)
        WHERE t.f_status=2 AND t.f_end_time IS NOT NULL AND t.f_delete_mark IS NULL
          AND COALESCE(NULLIF(t.f_last_modify_user_id,''),NULLIF(t.f_creator_user_id,'')) IS NOT NULL
          AND NOT EXISTS (SELECT 1 FROM public.dms_approved_file_batches b
              WHERE b.tenant_id=a.tenant_id AND b.task_id=a.task_id AND b.audit_type=a.audit_type)
        ORDER BY t.f_end_time, a.task_id LIMIT 100
        ON CONFLICT (tenant_id,task_id,audit_type) DO NOTHING
    </insert>
    <insert id="enqueue">
        INSERT INTO public.dms_approved_file_batches
            (id,tenant_id,flow_id,task_id,audit_id,audit_type,actor_id,approved_at,status)
        VALUES (#{id,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler},#{tenantId},#{flowId},#{taskId},#{auditId},#{auditType},#{actorId},#{approvedAt},'PREPARING')
        ON CONFLICT (tenant_id,task_id,audit_type) DO NOTHING
    </insert>
    <update id="refreshSchedule">
        UPDATE public.dms_approved_file_batches SET scheduled_at=#{scheduledAt}, effective_to=#{effectiveTo}
        WHERE tenant_id=#{tenantId} AND id=#{id,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler}
          AND status='REGISTERING' AND source_digest=#{sourceDigest}
    </update>
    <update id="prepared">
        UPDATE public.dms_approved_file_batches SET source_digest=#{sourceDigest}, scheduled_at=#{scheduledAt},
            effective_to=#{effectiveTo}, audit_id=#{auditId},
            approval_render_snapshot=CAST(#{approvalRenderSnapshot,jdbcType=VARCHAR} AS jsonb), status='REGISTERING'
        WHERE tenant_id=#{tenantId} AND id=#{id,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler} AND status='PREPARING'
    </update>
    <sql id="RetryEligible">
        status &lt;&gt; 'APPLIED'
        <if test="retryBackoffEnabled">AND next_attempt_at &lt;= CURRENT_TIMESTAMP</if>
        AND (lease_until IS NULL OR lease_until &lt;= CURRENT_TIMESTAMP)
        AND (status &lt;&gt; 'WAITING' OR scheduled_at &lt;= CURRENT_TIMESTAMP)
    </sql>
    <select id="retryCandidates" resultMap="Batch">
        SELECT <include refid="BatchColumns"/> FROM public.dms_approved_file_batches
        WHERE <include refid="RetryEligible"/>
        <if test="!includeDisable">AND audit_type IN ('xinzeng_shenhe','xiuding_shenhe','wailai_wenjian_xinzeng_shenhe')</if>
        ORDER BY next_attempt_at, id LIMIT 100
    </select>
    <update id="claim">
        UPDATE public.dms_approved_file_batches
        SET lease_token=#{token}, lease_until=CURRENT_TIMESTAMP + INTERVAL '10 minutes', attempts=attempts+1
        WHERE tenant_id=#{tenantId} AND id=#{id,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler} AND <include refid="RetryEligible"/>
    </update>
    <update id="finish">
        UPDATE public.dms_approved_file_batches SET lease_token=NULL,lease_until=NULL,
            last_error=#{error,jdbcType=VARCHAR},
            attempts=CASE WHEN #{error,jdbcType=VARCHAR} IS NULL THEN 0 ELSE attempts END,
            next_attempt_at=CASE WHEN #{error,jdbcType=VARCHAR} IS NULL AND status='WAITING' THEN scheduled_at
                ELSE CURRENT_TIMESTAMP + (#{delay} * INTERVAL '1 second') END
        WHERE tenant_id=#{tenantId} AND id=#{id,jdbcType=OTHER,typeHandler=jnpf.dmsDatabase.DmsUuidTypeHandler} AND lease_token=#{token}
    </update>
</mapper>