feat(TICKET-LOGO): completed feature
This commit is contained in:
@@ -57,6 +57,7 @@ interface ReceiptSettings {
|
||||
contactPhone: string;
|
||||
receiptHeader: string;
|
||||
receiptFooter: string;
|
||||
logoUrl: string;
|
||||
prefix: string;
|
||||
nextNumber: number;
|
||||
padding: number;
|
||||
@@ -72,6 +73,7 @@ const emptyReceipt: ReceiptSettings = {
|
||||
contactPhone: '',
|
||||
receiptHeader: '',
|
||||
receiptFooter: '',
|
||||
logoUrl: '',
|
||||
prefix: 'TPV',
|
||||
nextNumber: 1,
|
||||
padding: 6,
|
||||
@@ -823,6 +825,12 @@ export default function PosAdminPage() {
|
||||
value={receipt.receiptFooter}
|
||||
onChange={(value) => setReceipt({ ...receipt, receiptFooter: value })}
|
||||
/>
|
||||
<Field
|
||||
label="URL del logo"
|
||||
value={receipt.logoUrl}
|
||||
onChange={(value) => setReceipt({ ...receipt, logoUrl: value })}
|
||||
placeholder="https://ejemplo.com/logo.png"
|
||||
/>
|
||||
<Field
|
||||
label="Prefijo de ticket"
|
||||
value={receipt.prefix}
|
||||
|
||||
@@ -72,7 +72,7 @@ export default function ReceiptModal({
|
||||
{/* Logo */}
|
||||
<div className="mb-3 flex justify-center">
|
||||
<img
|
||||
src="/images/logo-main.png"
|
||||
src={receipt.logoUrl ?? '/images/logo-main.png'}
|
||||
alt="Logo"
|
||||
className="h-16 object-contain print:h-12"
|
||||
/>
|
||||
|
||||
@@ -47,6 +47,7 @@ export interface PosReceipt {
|
||||
email: string | null;
|
||||
phone: string | null;
|
||||
};
|
||||
logoUrl: string | null;
|
||||
terminal: { id: string; name: string };
|
||||
cashier: string;
|
||||
sessionId: string;
|
||||
|
||||
18
project/migrations/063_pos_store_logo_url.js
Normal file
18
project/migrations/063_pos_store_logo_url.js
Normal file
@@ -0,0 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
exports.shorthands = undefined;
|
||||
|
||||
exports.up = (pgm) => {
|
||||
pgm.addColumns('pos_stores', {
|
||||
logo_url: {
|
||||
type: 'text',
|
||||
notNull: false,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
pgm.addCommentOnColumn('pos_stores', 'logo_url', 'URL del logo custom para tickets TPV. Si es null, se usa el logo default /images/logo-main.png');
|
||||
};
|
||||
|
||||
exports.down = (pgm) => {
|
||||
pgm.dropColumns('pos_stores', ['logo_url']);
|
||||
};
|
||||
@@ -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');
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user