feat: customer lookup from POS with order history and item search

- Customer dialog in cart panel: search accounts by name, phone, email, account #
- Selected customer shown with name, phone, email in cart header
- accountId passed when creating transactions
- Order history view: tap a transaction to expand and see line items
- Item search in history (e.g. "strings") — filters orders containing that item
- Backend: add accountId and itemSearch filters to transaction list endpoint
- itemSearch uses EXISTS subquery on line item descriptions (ILIKE)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
ryan
2026-04-04 21:07:24 +00:00
parent 24b2b8c292
commit 31d80b5b9d
7 changed files with 310 additions and 5 deletions

View File

@@ -27,6 +27,8 @@ export const transactionRoutes: FastifyPluginAsync = async (app) => {
status: query.status,
transactionType: query.transactionType,
locationId: query.locationId,
accountId: query.accountId,
itemSearch: query.itemSearch,
}
const result = await TransactionService.list(app.db, params, filters)

View File

@@ -390,12 +390,20 @@ export const TransactionService = {
status?: string
transactionType?: string
locationId?: string
accountId?: string
itemSearch?: string
}) {
const conditions: ReturnType<typeof eq>[] = []
if (params.q) {
conditions.push(buildSearchCondition(params.q, [transactions.transactionNumber])!)
}
if (filters?.itemSearch) {
const term = `%${filters.itemSearch}%`
conditions.push(
sql`EXISTS (SELECT 1 FROM ${transactionLineItems} WHERE ${transactionLineItems.transactionId} = ${transactions.id} AND ${transactionLineItems.description} ILIKE ${term})`
)
}
if (filters?.status) {
conditions.push(eq(transactions.status, filters.status as any))
}
@@ -405,6 +413,9 @@ export const TransactionService = {
if (filters?.locationId) {
conditions.push(eq(transactions.locationId, filters.locationId))
}
if (filters?.accountId) {
conditions.push(eq(transactions.accountId, filters.accountId))
}
const where = conditions.length === 0 ? undefined : conditions.length === 1 ? conditions[0] : and(...conditions)