feat: add cash rounding, POS test suite, and fix test harness port cleanup
- Add Swedish rounding (nearest nickel) for cash payments at locations with cash_rounding enabled - Add rounding_adjustment column to transactions, cash_rounding to locations - Add POS schema to database plugin for relational query support - Complete/void routes now return full transaction with line items via getById - Test harness killPort falls back to fuser when lsof unavailable (fixes stale process bug) - Add 35-test POS API suite covering discounts, drawer, transactions, tax, rounding, e2e flow - Add unit tests for tax service and POS Zod schemas Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -231,10 +231,26 @@ export const TransactionService = {
|
||||
if (!txn) throw new NotFoundError('Transaction')
|
||||
if (txn.status !== 'pending') throw new ConflictError('Transaction is not pending')
|
||||
|
||||
// Validate cash payment
|
||||
// Validate cash payment (with optional nickel rounding)
|
||||
let changeGiven: string | undefined
|
||||
let roundingAdjustment = 0
|
||||
if (input.paymentMethod === 'cash') {
|
||||
const total = parseFloat(txn.total)
|
||||
let total = parseFloat(txn.total)
|
||||
|
||||
// Apply Swedish rounding if location has cash_rounding enabled
|
||||
if (txn.locationId) {
|
||||
const [loc] = await db
|
||||
.select({ cashRounding: locations.cashRounding })
|
||||
.from(locations)
|
||||
.where(eq(locations.id, txn.locationId))
|
||||
.limit(1)
|
||||
if (loc?.cashRounding) {
|
||||
const rounded = TaxService.roundToNickel(total)
|
||||
roundingAdjustment = Math.round((rounded - total) * 100) / 100
|
||||
total = rounded
|
||||
}
|
||||
}
|
||||
|
||||
if (!input.amountTendered || input.amountTendered < total) {
|
||||
throw new ValidationError('Amount tendered must be >= transaction total for cash payments')
|
||||
}
|
||||
@@ -273,13 +289,13 @@ export const TransactionService = {
|
||||
paymentMethod: input.paymentMethod,
|
||||
amountTendered: input.amountTendered?.toString(),
|
||||
changeGiven,
|
||||
roundingAdjustment: roundingAdjustment.toString(),
|
||||
checkNumber: input.checkNumber,
|
||||
completedAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
})
|
||||
.where(eq(transactions.id, transactionId))
|
||||
.returning()
|
||||
|
||||
return completed
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user