feat(F-161): completed feature

This commit is contained in:
chattie
2026-08-22 18:13:37 +02:00
parent 83a44980c6
commit 9152b3a65e
15 changed files with 164 additions and 63 deletions

View File

@@ -342,7 +342,9 @@ export async function buildApp(deps: BuildAppDeps = {}): Promise<FastifyInstance
await app.register(async (instance) => {
await registerCheckoutRoutes(instance, {
pool: deps.pool as pg.Pool,
authenticate: combinedAuth,
// Checkout creates customer-owned orders. Do not use combinedAuth here:
// a coexisting backoffice cookie must never override the storefront user.
authenticate,
tracer: telemetry.tracer,
});
});

View File

@@ -25,6 +25,9 @@ const BASE_ORDER = {
total_cents: 1210,
tracking_number: null,
courier: null,
customer_name: null,
customer_phone: null,
phone: null,
created_at: new Date('2026-01-01T00:00:00Z'),
updated_at: new Date('2026-01-01T00:00:00Z'),
};
@@ -40,9 +43,28 @@ describe('PgOrderRepository.findById — F-153 customer email association', () =
expect(result!.email).toBe('customer@example.com');
const orderQuery = String(query.mock.calls[0]![0]);
expect(orderQuery).toContain('identity_users');
expect(orderQuery).toContain('users_profiles');
expect(orderQuery).toContain('COALESCE(o.customer_name, p.display_name)');
expect(orderQuery).toContain('u.email');
});
it('maps customer name and phone resolved by the read query', async () => {
const { pool } = mockPool({
...BASE_ORDER,
email: 'customer@example.com',
customer_name: 'Cliente Ejemplo',
customer_phone: '+34600000000',
phone: '+34600000000',
});
const repo = new PgOrderRepository(pool);
const result = await repo.findById('order-1');
expect(result?.customerName).toBe('Cliente Ejemplo');
expect(result?.customerPhone).toBe('+34600000000');
expect(result?.phone).toBe('+34600000000');
});
it('returns null email when the order has no linked identity_user', async () => {
const { pool } = mockPool({ ...BASE_ORDER, email: null });
const repo = new PgOrderRepository(pool);

View File

@@ -173,9 +173,13 @@ export class PgOrderRepository implements OrderRepository {
async findById(id: string): Promise<OrderView | undefined> {
const orderResult = await this.pool.query<OrderRow>(
`SELECT o.*, u.email, u.phone
`SELECT o.*, u.email,
COALESCE(o.customer_name, p.display_name) AS customer_name,
COALESCE(o.customer_phone, p.phone, u.phone) AS customer_phone,
COALESCE(u.phone, p.phone) AS phone
FROM orders_orders o
LEFT JOIN identity_users u ON u.id = o.user_id
LEFT JOIN users_profiles p ON p.user_id = o.user_id
WHERE o.id = $1`,
[id],
);
@@ -207,9 +211,13 @@ export class PgOrderRepository implements OrderRepository {
async findByIdAndUserId(id: string, userId: string): Promise<OrderView | undefined> {
const orderResult = await this.pool.query<OrderRow>(
`SELECT o.*, u.email, u.phone
`SELECT o.*, u.email,
COALESCE(o.customer_name, p.display_name) AS customer_name,
COALESCE(o.customer_phone, p.phone, u.phone) AS customer_phone,
COALESCE(u.phone, p.phone) AS phone
FROM orders_orders o
LEFT JOIN identity_users u ON u.id = o.user_id
LEFT JOIN users_profiles p ON p.user_id = o.user_id
WHERE o.id = $1 AND o.user_id = $2`,
[id, userId],
);
@@ -294,6 +302,8 @@ function toOrder(row: OrderRow): Order {
totalCents: row.total_cents,
trackingNumber: row.tracking_number,
courier: row.courier,
customerName: row.customer_name ?? null,
customerPhone: row.customer_phone ?? null,
createdAt: row.created_at,
updatedAt: row.updated_at,
};