fix(pos): redesign quick products admin search and save flow

This commit is contained in:
Deploy
2026-08-26 07:43:13 +02:00
parent 290ced173b
commit cf3c906ed2
15 changed files with 358 additions and 75 deletions

View File

@@ -261,22 +261,60 @@ export async function registerPosRoutes(app: FastifyInstance, deps: PosRouteDeps
{
schema: {
tags: ['POS Admin'],
summary: 'List products available for TPV touch configuration',
summary: 'Search products available for TPV touch configuration',
querystring: {
type: 'object',
properties: {
q: { type: 'string', minLength: 1, maxLength: 120 },
limit: { type: 'integer', minimum: 1, maximum: 40, default: 12 },
variantIds: { type: 'string' },
},
},
response: { 401: errorSchema, 403: errorSchema },
} as FastifySchema,
},
async (request, reply) => {
const user = await authenticate(request);
requireRole(user, 'admin');
const result = await pool.query(
`SELECT v.id AS "variantId", p.id AS "productId", p.name, v.sku, v.ean,
COALESCE(pp.offer_cents, pp.net_unit_amount_cents, 0) AS "priceCents"
FROM catalog_product_variants v
JOIN catalog_products p ON p.id = v.product_id
LEFT JOIN pricing_variant_prices pp ON pp.variant_id = v.id AND pp.currency = 'EUR'
WHERE p.state = 'active'
ORDER BY p.name, v.sku`,
const query = parseJson(
z.object({
q: z.string().trim().min(1).max(120).optional(),
limit: z.coerce.number().int().min(1).max(40).default(12),
variantIds: z.string().optional(),
}),
request.query ?? {},
);
const variantIds = (query.variantIds ?? '')
.split(',')
.map((value) => value.trim())
.filter(Boolean);
if (variantIds.some((value) => !storeIdSchema.safeParse(value).success)) {
throw new AppError(400, 'INVALID_VARIANT_ID', 'Algún producto rápido no es válido');
}
const result = variantIds.length > 0
? await pool.query(
`SELECT v.id AS "variantId", p.id AS "productId", p.name, v.sku, v.ean,
COALESCE(pp.offer_cents, pp.net_unit_amount_cents, 0) AS "priceCents"
FROM catalog_product_variants v
JOIN catalog_products p ON p.id = v.product_id
LEFT JOIN pricing_variant_prices pp ON pp.variant_id = v.id AND pp.currency = 'EUR'
WHERE p.state = 'active' AND v.id = ANY($1::uuid[])
ORDER BY p.name, v.sku`,
[variantIds],
)
: await pool.query(
`SELECT v.id AS "variantId", p.id AS "productId", p.name, v.sku, v.ean,
COALESCE(pp.offer_cents, pp.net_unit_amount_cents, 0) AS "priceCents"
FROM catalog_product_variants v
JOIN catalog_products p ON p.id = v.product_id
LEFT JOIN pricing_variant_prices pp ON pp.variant_id = v.id AND pp.currency = 'EUR'
WHERE p.state = 'active'
AND ($1::text IS NULL OR p.name ILIKE $1 OR v.sku ILIKE $1 OR COALESCE(v.ean, '') ILIKE $1)
ORDER BY p.name, v.sku
LIMIT $2`,
[query.q ? `%${query.q}%` : null, query.limit],
);
return reply.send({ items: result.rows });
},
);