feat: add release controls and 09:00 collection
This commit is contained in:
137
lib/distribution-release-service.ts
Normal file
137
lib/distribution-release-service.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
type ReleasableDistribution = {
|
||||
id: string;
|
||||
task_id: string;
|
||||
content_id: string;
|
||||
content_title: string;
|
||||
partner_id: string;
|
||||
partner_name: string;
|
||||
claim_id: string | null;
|
||||
delegation_bundle_id: string | null;
|
||||
publish_url: string | null;
|
||||
};
|
||||
|
||||
export class DistributionReleaseError extends Error {
|
||||
readonly status: number;
|
||||
|
||||
constructor(message: string, status: number) {
|
||||
super(message);
|
||||
this.name = "DistributionReleaseError";
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
|
||||
export function distributionReleaseBlockReason(input: {
|
||||
publishUrl?: string | null;
|
||||
resultSubmittedAt?: string | null;
|
||||
}) {
|
||||
if (input.publishUrl) return "已回填发布链接的笔记不能释放";
|
||||
if (input.resultSubmittedAt) return "已提交结果截图的任务不能释放";
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function releaseUnfinishedDistribution(
|
||||
db: D1Database,
|
||||
distributionId: string,
|
||||
) {
|
||||
if (!distributionId) {
|
||||
throw new DistributionReleaseError("请选择需要释放的领取记录", 400);
|
||||
}
|
||||
|
||||
const distribution = await db
|
||||
.prepare(
|
||||
`SELECT
|
||||
d.id,
|
||||
d.task_id,
|
||||
d.content_id,
|
||||
c.title AS content_title,
|
||||
d.partner_id,
|
||||
p.name AS partner_name,
|
||||
d.claim_id,
|
||||
d.delegation_bundle_id,
|
||||
d.publish_url
|
||||
FROM distributions d
|
||||
JOIN contents c ON c.id = d.content_id
|
||||
JOIN partners p ON p.id = d.partner_id
|
||||
WHERE d.id = ?`,
|
||||
)
|
||||
.bind(distributionId)
|
||||
.first<ReleasableDistribution>();
|
||||
|
||||
if (!distribution) {
|
||||
throw new DistributionReleaseError("领取记录不存在或已被释放", 404);
|
||||
}
|
||||
const blocked = distributionReleaseBlockReason({
|
||||
publishUrl: distribution.publish_url,
|
||||
});
|
||||
if (blocked) throw new DistributionReleaseError(blocked, 409);
|
||||
|
||||
const statements: D1PreparedStatement[] = [
|
||||
db
|
||||
.prepare("DELETE FROM collection_runs WHERE distribution_id = ?")
|
||||
.bind(distribution.id),
|
||||
db.prepare("DELETE FROM distributions WHERE id = ?").bind(distribution.id),
|
||||
db
|
||||
.prepare("UPDATE contents SET status = 'available' WHERE id = ?")
|
||||
.bind(distribution.content_id),
|
||||
db
|
||||
.prepare(
|
||||
`UPDATE tasks
|
||||
SET claimed_quantity = MAX(claimed_quantity - 1, 0)
|
||||
WHERE id = ?`,
|
||||
)
|
||||
.bind(distribution.task_id),
|
||||
db
|
||||
.prepare(
|
||||
`UPDATE partners
|
||||
SET claimed_total = MAX(claimed_total - 1, 0)
|
||||
WHERE id = ?`,
|
||||
)
|
||||
.bind(distribution.partner_id),
|
||||
];
|
||||
|
||||
if (distribution.delegation_bundle_id) {
|
||||
statements.push(
|
||||
db
|
||||
.prepare(
|
||||
`UPDATE delegation_bundles
|
||||
SET quantity = MAX(quantity - 1, 0),
|
||||
status = CASE WHEN quantity <= 1 THEN 'revoked' ELSE status END,
|
||||
revoked_at = CASE WHEN quantity <= 1 THEN CURRENT_TIMESTAMP ELSE revoked_at END,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ?`,
|
||||
)
|
||||
.bind(distribution.delegation_bundle_id),
|
||||
);
|
||||
}
|
||||
|
||||
if (distribution.claim_id) {
|
||||
statements.push(
|
||||
db
|
||||
.prepare(
|
||||
`UPDATE claims
|
||||
SET quantity = MAX(quantity - 1, 0)
|
||||
WHERE id = ?`,
|
||||
)
|
||||
.bind(distribution.claim_id),
|
||||
db
|
||||
.prepare(
|
||||
`DELETE FROM claims
|
||||
WHERE id = ?
|
||||
AND quantity <= 0
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM distributions WHERE claim_id = ?
|
||||
)`,
|
||||
)
|
||||
.bind(distribution.claim_id, distribution.claim_id),
|
||||
);
|
||||
}
|
||||
|
||||
await db.batch(statements);
|
||||
return {
|
||||
distributionId: distribution.id,
|
||||
taskId: distribution.task_id,
|
||||
contentId: distribution.content_id,
|
||||
contentTitle: distribution.content_title,
|
||||
partnerName: distribution.partner_name,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user