Promociones reutilizables
Cómo el POS reutiliza el mismo id, cómo el cliente crea ventanas únicas en Brightmarket y qué hay que configurar para que los tickets diarios apunten a la última promoción.
Algunos POS reutilizan el mismo id de promoción cuando la campaña vuelve a estar vigente. Brightmarket exige externalId único por organización, así que cada ventana de fechas es una promoción distinta.
El SDK no inventa el sufijo ni detecta overlap. El cliente crea el externalId único al sincronizar promociones; los tickets siguen mandando el id del POS; el SDK resuelve el id vigente por fecha.
Flujo
POS IdPromo = 3813 (estable)
│
├─ primera carga → Brightmarket externalId = 3813
└─ reuso (nueva ventana) → 3813-20260301-20260315-14
↓
Ticket línea IdPromo = 3813 + fecha del ticket
↓
GET promotions/searchByDateAndStartsWithExternalId
↓
Ticket.promotionExternalIds = [id resuelto]Qué hace el SDK
- En
-promotions, escribe elexternalIdque ya viene en la fila o en el payload listo. No agrega fechas. - En
-tickets, si mapeásTICKET_FIELD_MAP.promo_id, junta los ids de línea, llamaresolve_promotion_external_id_for_datecon la fecha del ticket y envíapromotionExternalIds. - Ese helper llama
GET /promotions/searchByDateAndStartsWithExternalIdy usa el primer resultado.
Si tu sync de tickets es custom (no sync_tickets), llamá el mismo helper:
from brightmarket_data_sync.writers import resolve_promotion_external_id_for_date
external_id = resolve_promotion_external_id_for_date("3813", "2026-03-10")Qué tiene que hacer el cliente
1. Sufijo al crear promociones reutilizadas
En src/transforms/ (llamado desde el adapter antes de devolver filas), armá un externalId único por ventana. Patrón habitual:
{id}-{YYYYMMDD}-{YYYYMMDD}-{días}Ejemplo: 3813 del 2026-03-01 al 2026-03-15 → 3813-20260301-20260315-14.
Aplicá el mismo sufijo al name para poder distinguirlas en la UI.
- Primera carga / histórica: podés dejar el id original sin sufijo (
3813). - Reuso diario: siempre un id nuevo con sufijo. No reutilices el
externalIdanterior (la API rechaza duplicados).
El SDK no construye ese sufijo. Si devolvés el id crudo del POS en cada sync, el create falla o pisa la promoción original.
2. Tickets: mandá el id crudo del POS
No sufijes IdPromo en las líneas de ticket. El POS sigue enviando 3813. El SDK (o tu sync custom) resuelve el id Brightmarket vigente.
Mapeá la columna en constants:
TICKET_FIELD_MAP = {
# ...
"promo_id": "IdPromo",
}Sincronizá -promotions antes de -tickets, en la misma ventana de fechas.
3. Pedí el parámetro de organización en Brightmarket
Para que la búsqueda agrupe 3813 y 3813-… y devuelva la última ventana (startDate más reciente, luego id), Brightmarket debe tener REUSE_PROMOTIONS=true en Parámetros de esa organización.
Hasta que el flag esté en true, el endpoint sigue el LIKE por prefijo sin preferir la última ventana: los tickets diarios pueden quedar en la promoción original.
Esto lo configura Brightmarket (o un admin) en la org. No es una variable de entorno del cliente.
Histórico vs diario
| Carga | Promociones | Tickets |
|---|---|---|
| Histórica | Id original sin sufijo (y/o ventanas ya sufijadas) | El ticket usa el id resuelto para esa fecha. Si solo existe 3813 en esa ventana, queda asociado a 3813. |
| Diaria (script activo) | Nueva promoción con sufijo por ventana | Resolver siempre la última promoción cuyo externalId empieza con el id del ticket y cubre la fecha |
La creación/importación de tickets hace match exacto de promotionExternalIds. El resolve es el paso que convierte 3813 → 3813-20260301-20260315-14.
Checklist
- Transform de promociones en
src/transforms/(sufijo en name + externalId al reusar). TICKET_FIELD_MAP.promo_id(oresolve_promotion_external_id_for_dateen sync custom).- Orden: promociones → tickets.
REUSE_PROMOTIONS=trueen la organización que reutiliza ids.
Ejemplos de patrón: primera carga con el id original; reuso posterior con sufijo de fechas (sufijo al actualizar, o sufijo siempre que existan fechas de inicio y fin).