diff --git a/apps/backend/src/domain/work-order-acceptance-evidence.test.ts b/apps/backend/src/domain/work-order-acceptance-evidence.test.ts new file mode 100644 index 00000000..7645a878 --- /dev/null +++ b/apps/backend/src/domain/work-order-acceptance-evidence.test.ts @@ -0,0 +1,31 @@ +import assert from 'node:assert/strict' +import test from 'node:test' +import { hasAcceptanceEvidence } from './work-order-acceptance-evidence.js' + +const VIDEO = { url: 'https://example.com/worker-acceptance-video/a.mp4', durationSeconds: 12 } + +test('验收证据:只有图片算有证据', () => { + assert.equal(hasAcceptanceEvidence({ imageUrls: ['https://example.com/a.jpg'] }), true) +}) + +test('验收证据:只有视频也算有证据(视频视同图片)', () => { + assert.equal(hasAcceptanceEvidence({ imageUrls: [], video: VIDEO }), true) +}) + +test('验收证据:图片与视频都有算有证据', () => { + assert.equal( + hasAcceptanceEvidence({ imageUrls: ['https://example.com/a.jpg'], video: VIDEO }), + true, + ) +}) + +test('验收证据:图片视频都没有则没有证据', () => { + assert.equal(hasAcceptanceEvidence({ imageUrls: [], video: null }), false) + assert.equal(hasAcceptanceEvidence({}), false) + assert.equal(hasAcceptanceEvidence({ imageUrls: undefined, video: undefined }), false) +}) + +test('验收证据:兼容非数组的 imageUrls(脏数据按无图片处理)', () => { + assert.equal(hasAcceptanceEvidence({ imageUrls: null, video: VIDEO }), true) + assert.equal(hasAcceptanceEvidence({ imageUrls: null, video: null }), false) +}) diff --git a/apps/backend/src/domain/work-order-acceptance-evidence.ts b/apps/backend/src/domain/work-order-acceptance-evidence.ts new file mode 100644 index 00000000..d8d2bbb7 --- /dev/null +++ b/apps/backend/src/domain/work-order-acceptance-evidence.ts @@ -0,0 +1,15 @@ +/** + * 验收证据口径:验收图片与验收视频至少上传一个。 + * + * 口径(已确认):有视频时视同有图片,其它逻辑完全按「已上传图片」走—— + * 打手端提交/保存验收的必填校验、VIP 免审核的 `evidenceStatus` / `evidenceDueAt` + * 判定都复用这个函数,避免整单与拼单份额两处口径漂移。 + */ +export function hasAcceptanceEvidence(input: { + imageUrls?: readonly unknown[] | null + video?: unknown +}): boolean { + const imageUrls = input.imageUrls + const imageCount = Array.isArray(imageUrls) ? imageUrls.length : 0 + return imageCount > 0 || Boolean(input.video) +}