feat(POS-010): completed feature
This commit is contained in:
@@ -640,4 +640,48 @@ export async function registerPosRoutes(app: FastifyInstance, deps: PosRouteDeps
|
||||
return reply.send(result.rows[0]);
|
||||
});
|
||||
|
||||
|
||||
// ── POS-010: Discount validation ──────────────────────────────────────────
|
||||
|
||||
app.post('/pos/discounts/validate', {
|
||||
schema: {
|
||||
tags: ['POS Terminal'],
|
||||
summary: 'Validate discount before applying',
|
||||
body: {
|
||||
type: 'object',
|
||||
required: ['unitPriceCents', 'discountCents'],
|
||||
properties: {
|
||||
unitPriceCents: { type: 'integer', minimum: 0 },
|
||||
discountCents: { type: 'integer', minimum: 0 },
|
||||
discountPercent: { type: 'number', minimum: 0, maximum: 100 },
|
||||
role: { type: 'string', enum: ['admin', 'pos_manager', 'pos_cashier'] },
|
||||
},
|
||||
},
|
||||
response: { 401: errorSchema, 403: errorSchema },
|
||||
} as FastifySchema,
|
||||
}, async (request, reply) => {
|
||||
const user = await authenticate(request);
|
||||
requireAnyRole(user, ['admin', 'pos_manager', 'pos_cashier'] as ReadonlyArray<Role>);
|
||||
const body = (request.body ?? {}) as { unitPriceCents?: number; discountCents?: number; discountPercent?: number; role?: string };
|
||||
const unitPriceCents = body.unitPriceCents ?? 0;
|
||||
const discountCents = body.discountCents ?? 0;
|
||||
const discountPercent = body.discountPercent ?? (unitPriceCents > 0 ? (discountCents / unitPriceCents) * 100 : 0);
|
||||
|
||||
// Cashiers capped at 50% per item
|
||||
const maxPercent = user.role === 'pos_manager' || user.role === 'admin' ? 100 : 50;
|
||||
if (discountPercent > maxPercent) {
|
||||
throw new AppError(403, 'DISCOUNT_EXCEEDED', `Discount ${discountPercent.toFixed(0)}% exceeds max ${maxPercent}% for role`);
|
||||
}
|
||||
if (discountCents > unitPriceCents) {
|
||||
throw new AppError(400, 'INVALID_DISCOUNT', 'Discount cannot exceed unit price');
|
||||
}
|
||||
return reply.send({
|
||||
valid: true,
|
||||
maxPercent,
|
||||
appliedPercent: discountPercent,
|
||||
appliedCents: discountCents,
|
||||
finalPriceCents: unitPriceCents - discountCents,
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user