feat(api): add M5 coverage controls and frontend spec
This commit is contained in:
@@ -44,6 +44,30 @@ async function ensureActorUser(client, actor) {
|
||||
);
|
||||
}
|
||||
|
||||
async function ensureStaffNotBlockedByBusiness(client, { tenantId, businessId, staffId }) {
|
||||
const blocked = await client.query(
|
||||
`
|
||||
SELECT id, reason, issue_flags
|
||||
FROM staff_blocks
|
||||
WHERE tenant_id = $1
|
||||
AND business_id = $2
|
||||
AND staff_id = $3
|
||||
LIMIT 1
|
||||
`,
|
||||
[tenantId, businessId, staffId]
|
||||
);
|
||||
|
||||
if (blocked.rowCount > 0) {
|
||||
throw new AppError('STAFF_BLOCKED', 'Staff is blocked from future shift assignments for this business', 409, {
|
||||
businessId,
|
||||
staffId,
|
||||
blockId: blocked.rows[0].id,
|
||||
reason: blocked.rows[0].reason || null,
|
||||
issueFlags: Array.isArray(blocked.rows[0].issue_flags) ? blocked.rows[0].issue_flags : [],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function insertDomainEvent(client, {
|
||||
tenantId,
|
||||
aggregateType,
|
||||
@@ -986,6 +1010,11 @@ export async function assignStaffToShift(actor, payload) {
|
||||
}
|
||||
|
||||
const workforce = await requireWorkforce(client, payload.tenantId, payload.workforceId);
|
||||
await ensureStaffNotBlockedByBusiness(client, {
|
||||
tenantId: shift.tenant_id,
|
||||
businessId: shift.business_id,
|
||||
staffId: workforce.staff_id,
|
||||
});
|
||||
let application = null;
|
||||
if (payload.applicationId) {
|
||||
application = await requireApplication(client, payload.tenantId, payload.applicationId);
|
||||
|
||||
Reference in New Issue
Block a user