feat(TICKET-LOGO): completed feature

This commit is contained in:
chattie
2026-08-25 06:35:39 +02:00
parent 419f47ec1c
commit 7639c1ff42
16 changed files with 324 additions and 12 deletions

View File

@@ -136,12 +136,13 @@ export async function registerPosRoutes(app: FastifyInstance, deps: PosRouteDeps
contactPhone: z.string().optional(),
receiptHeader: z.string().optional(),
receiptFooter: z.string().optional(),
logoUrl: z.string().url().max(500).optional(),
}),
request.body ?? {},
);
const result = await pool.query<{ id: string; name: string; slug: string; active: boolean }>(
`INSERT INTO pos_stores (name, slug, address, tax_id, contact_email, contact_phone, receipt_header, receipt_footer)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
`INSERT INTO pos_stores (name, slug, address, tax_id, contact_email, contact_phone, receipt_header, receipt_footer, logo_url)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
RETURNING id, name, slug, active`,
[
body.name,
@@ -152,6 +153,7 @@ export async function registerPosRoutes(app: FastifyInstance, deps: PosRouteDeps
body.contactPhone,
body.receiptHeader,
body.receiptFooter,
body.logoUrl ?? null,
],
);
return reply.code(201).send(result.rows[0]);
@@ -1268,6 +1270,7 @@ export async function registerPosRoutes(app: FastifyInstance, deps: PosRouteDeps
contactPhone: z.string().trim().max(64).optional(),
receiptHeader: z.string().trim().max(500).optional(),
receiptFooter: z.string().trim().max(1000).optional(),
logoUrl: z.string().url().max(500).optional(),
prefix: z
.string()
.trim()
@@ -1288,7 +1291,8 @@ export async function registerPosRoutes(app: FastifyInstance, deps: PosRouteDeps
tax_id = COALESCE($4, tax_id), contact_email = COALESCE($5, contact_email),
contact_phone = COALESCE($6, contact_phone),
receipt_header = COALESCE($7, receipt_header),
receipt_footer = COALESCE($8, receipt_footer), updated_at = now()
receipt_footer = COALESCE($8, receipt_footer),
logo_url = $9, updated_at = now()
WHERE id = $1 RETURNING id`,
[
body.storeId,
@@ -1299,6 +1303,7 @@ export async function registerPosRoutes(app: FastifyInstance, deps: PosRouteDeps
body.contactPhone,
body.receiptHeader,
body.receiptFooter,
body.logoUrl ?? null,
],
);
if (!store.rows[0]) throw new AppError(404, 'STORE_NOT_FOUND', 'No se encontró la tienda');

View File

@@ -37,6 +37,7 @@ interface ReceiptOrderRow {
terminal_name: string;
cashier_email: string;
return_policy: string | null;
logo_url: string | null;
}
interface ReceiptItemRow {
@@ -61,7 +62,7 @@ export async function buildPosReceipt(queryable: Queryable, orderId: string): Pr
o.total_cents, o.created_at, o.cash_session_id, o.terminal_id,
customer.email AS customer_email,
store.name AS store_name, store.address, store.tax_id, store.contact_email,
store.contact_phone, store.receipt_header, store.receipt_footer,
store.contact_phone, store.receipt_header, store.receipt_footer, store.logo_url,
terminal.name AS terminal_name, cashier.email AS cashier_email,
receipt_settings.return_policy
FROM orders_orders o
@@ -117,6 +118,7 @@ export async function buildPosReceipt(queryable: Queryable, orderId: string): Pr
email: order.contact_email,
phone: order.contact_phone,
},
logoUrl: order.logo_url,
terminal: { id: order.terminal_id, name: order.terminal_name },
cashier: order.cashier_email,
sessionId: order.cash_session_id,
@@ -231,6 +233,7 @@ export async function buildPosReturnReceipt(
orderId: original.orderId,
issuedAt: original.issuedAt,
company: original.company,
logoUrl: original.logoUrl,
terminal: original.terminal,
cashier: original.cashier,
sessionId: original.sessionId,

View File

@@ -93,6 +93,8 @@ export interface PosReceipt {
email: string | null;
phone: string | null;
};
/** URL del logo custom para el ticket. Si es null, usar /images/logo-main.png */
logoUrl: string | null;
terminal: { id: string; name: string };
cashier: string;
sessionId: string;