50 lines
2.6 KiB
Markdown
50 lines
2.6 KiB
Markdown
# Implementer evidence — CLUB-003
|
|
|
|
## Resumen
|
|
Implementé la integración del Club en el TPV: resolución de socio por código, acumulación de cashback en ledger idempotente y campos de respuesta en venta POS.
|
|
|
|
## Qué se añadió
|
|
|
|
### 1) Endpoint de resolución de socio
|
|
- `GET /club/resolve?memberCode=MDV-XXXXXXXX` en `project/src/modules/club/api/club.routes.ts`
|
|
- Método `resolveByCode` en `ClubService`
|
|
- Método `findMemberByCode` en `PgClubRepository` (solo socios activos)
|
|
|
|
### 2) Integración de cashback en venta POS
|
|
- `PosSaleInput` ahora acepta `clubMemberId?: string` (domain type)
|
|
- `PosSaleResult` ahora devuelve `clubEarnedCents` y `clubMemberCode`
|
|
- `CreatePosSaleUseCase`:
|
|
- Al completar una venta (orderState === 'COMPLETED'), si hay `clubMemberId`:
|
|
- Consulta `club_enabled` y `club_cashback_bps` de `store_settings`
|
|
- Calcula `cashbackCents = round(totalCents * cashbackBps / 10_000)`
|
|
- Inserta transacción de ledger idempotente con `idempotency_key = club-earn-${orderId}` dentro de la misma transacción DB que la venta
|
|
- Si la insercción falla, continúa sin bloquear la venta (fail-safe)
|
|
- `loadResult` recupera el `clubEarnedCents` del ledger al recargar una venta por idempotency key
|
|
- `receive-rest-payment.ts` devuelve `clubEarnedCents: 0` (pagos adicionales no re-acumulan cashback)
|
|
|
|
### 3) API del TPV
|
|
- El body de `POST /pos/sales` acepta `clubMemberId` con validación UUID
|
|
- La respuesta de venta incluye `clubEarnedCents` y `clubMemberCode`
|
|
|
|
### 4) Tipos frontend
|
|
- `PosSaleResponse` en `apps/pos/src/types/checkout.ts` incluye `clubEarnedCents` y `clubMemberCode`
|
|
|
|
## Decisiones técnicas
|
|
- El cashback se acumula **solo cuando la venta pasa a COMPLETED**, no en ventas PENDING.
|
|
- Si la escritura de ledger falla, la venta sigue adelante (fail-safe).
|
|
- El idempotency key del ledger incluye el `orderId` (`club-earn-${orderId}`), garantizando una única acumulación por venta.
|
|
- El `loadResult` recupera el cashback del ledger para mantener consistencia en respuestas por idempotency.
|
|
|
|
## Validación ejecutada
|
|
- `cd project && npm run typecheck` ✅
|
|
- `cd project && npm run build` ✅
|
|
- `cd project/apps/pos && npm run build` ✅
|
|
- `./scripts/verify.sh` ✅
|
|
- `cd project && npx vitest run src/modules/pos/tests/payment-allocation.test.ts` ✅
|
|
- `cd project && npx vitest run src/modules/club/tests/` ✅
|
|
- `git diff --check` ✅
|
|
|
|
## Riesgos / siguiente paso
|
|
- CLUB-004 debe implementar el flujo de devolución TPV que revierte el cashback acumulado cuando se reintegran artículos.
|
|
- El frontend TPV (interfaz de búsqueda de socio Club) queda pendiente de implementar en la UI del terminal; los campos del endpoint ya están listos.
|