feat: repair-POS integration, receipt formats, manager overrides, price adjustments
- Add thermal/full-page receipt format toggle (per-device, localStorage) - Full-page receipt uses clean invoice layout matching repair PDF style - Settings page reorganized into tabbed sections (Store, Locations, Modules, Receipt, POS Security, Advanced) - Manager override system: configurable PIN prompt for void, refund, discount, cash in/out - Discount threshold setting: require manager approval above X% - Consumable product type: tracked for internal job costing, excluded from POS search, receipts, and customer-facing totals - Repair line item dialog: product picker dropdown for parts/consumables from inventory - Repair → POS checkout: load ready-for-pickup tickets into repair_payment transactions with proper tax categories (labor=service, parts=goods) - Transaction completion auto-updates repair ticket status to picked_up - POS Repairs dialog with Pickup and New Intake tabs, customer account lookup - Inline price adjustment on cart items: % off, $ off, or set price with live preview - Order-level discount button with same three input modes - Backend: migration 0043 (consumable enum + is_consumable flag), createFromRepairTicket service, ready-for-pickup endpoint - Fix: backend dev script uses --env-file for turbo compatibility Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,8 @@ interface POSUser {
|
||||
role: string
|
||||
}
|
||||
|
||||
type ReceiptFormat = 'thermal' | 'full'
|
||||
|
||||
interface POSState {
|
||||
currentTransactionId: string | null
|
||||
locationId: string | null
|
||||
@@ -20,6 +22,7 @@ interface POSState {
|
||||
accountName: string | null
|
||||
accountPhone: string | null
|
||||
accountEmail: string | null
|
||||
receiptFormat: ReceiptFormat
|
||||
setTransaction: (id: string | null) => void
|
||||
setLocation: (id: string) => void
|
||||
setDrawerSession: (id: string | null) => void
|
||||
@@ -28,9 +31,17 @@ interface POSState {
|
||||
touchActivity: () => void
|
||||
setAccount: (id: string, name: string, phone?: string | null, email?: string | null) => void
|
||||
clearAccount: () => void
|
||||
setReceiptFormat: (format: ReceiptFormat) => void
|
||||
reset: () => void
|
||||
}
|
||||
|
||||
const RECEIPT_FORMAT_KEY = 'pos_receipt_format'
|
||||
|
||||
function getStoredReceiptFormat(): ReceiptFormat {
|
||||
const stored = localStorage.getItem(RECEIPT_FORMAT_KEY)
|
||||
return stored === 'full' ? 'full' : 'thermal'
|
||||
}
|
||||
|
||||
export const usePOSStore = create<POSState>((set) => ({
|
||||
currentTransactionId: null,
|
||||
locationId: null,
|
||||
@@ -43,6 +54,7 @@ export const usePOSStore = create<POSState>((set) => ({
|
||||
accountName: null,
|
||||
accountPhone: null,
|
||||
accountEmail: null,
|
||||
receiptFormat: getStoredReceiptFormat(),
|
||||
setTransaction: (id) => set({ currentTransactionId: id }),
|
||||
setLocation: (id) => set({ locationId: id }),
|
||||
setDrawerSession: (id) => set({ drawerSessionId: id }),
|
||||
@@ -51,5 +63,6 @@ export const usePOSStore = create<POSState>((set) => ({
|
||||
touchActivity: () => set({ lastActivity: Date.now() }),
|
||||
setAccount: (id, name, phone, email) => set({ accountId: id, accountName: name, accountPhone: phone ?? null, accountEmail: email ?? null }),
|
||||
clearAccount: () => set({ accountId: null, accountName: null, accountPhone: null, accountEmail: null }),
|
||||
setReceiptFormat: (format) => { localStorage.setItem(RECEIPT_FORMAT_KEY, format); set({ receiptFormat: format }) },
|
||||
reset: () => set({ currentTransactionId: null, accountId: null, accountName: null, accountPhone: null, accountEmail: null }),
|
||||
}))
|
||||
|
||||
Reference in New Issue
Block a user