Skip to main content

RPApos Gateway — Entity Mapping

How each RPApos catalog entity is transformed and loaded into FlowPOS.

Document version: 1.0 · Last updated: 2026-05


Dependency graph

Hard prerequisites (auto-expanded in custom sync):

flowchart TD
moneda[moneda]
uom[unidad_medida]
plu_g[plu_grupo]
sku_g[sku_grupo]
prod_g[produccion_grupo]
bodega[bodega]
proveedor[proveedor]
area[area]
persona[persona]
sku[sku]
plu[plu]
usuario[usuario]
mesa[mesa]
batch[batch_maestro]

plu_option_g[plu_option_group]
plu_option_i[plu_option_item]
plu_option_a[plu_option_group_assignment]

plu_g --> plu
uom --> plu
sku_g --> sku
uom --> sku
bodega --> area
area --> mesa
plu --> batch
sku --> batch
uom --> batch
plu --> plu_option_i
plu_option_g --> plu_option_i
plu --> plu_option_a
plu_option_g --> plu_option_a

Canonical execution order is fixed in RPAPOS_CATALOG_ENTITIES (packages/global/enums/rpapos.enums.ts).


Summary table

EntityRPApos APISinkImport type / pathPrimary FlowPOS tables
monedaMonedaRestSinkcurrency, business_currency
unidad_medidaUnidadMedidaRestSinkunit_of_measure, business_unit_of_measure
plu_grupoPLU/GrupoHandlerSinkcategorycategory
sku_grupoProducto/GrupoHandlerSinkcategorycategory
produccion_grupoProduccion/GrupoHandlerSinkcategorycategory
bodegaBodegaHandlerSinklocationlocation, address fields
proveedorProveedorHandlerSinksuppliersupplier domain tables
areaareaRestSinkdining_area
personaPersonaRestSinkcustomer
skuSKUHandlerSinkproductproduct (is_raw_material=true)
pluPLU/MaestroHandlerSinkproductproduct (is_raw_material=false)
usuarioUsuarioHandlerSinkemployeeemployee
mesaper-area Mesa/{id}RestSinkdining_table
batch_maestroBatchMaestroRestSinkproduct_recipe
plu_option_groupSOAP Catalogo_4 Producto_GrupoRestSinkplu (optional)product_modifier_group
plu_option_itemSOAP Producto_Grupo_Detalle / Manager API viw_Producto_Grupo_Detalle_1 (+ viw_Producto_Atributo_1 for labels)RestSinkplu_option_group, plu (optional)product_modifier
plu_option_group_assignmentSOAP Producto_Grupo_Relacion / Manager API viw_Producto_Grupo_Relacion_1RestSinkplu, plu_option_groupproduct_modifier_group_assignment
precioPLU/Precio (REST) / viw_PLU_Precio_1Extract/archive only (no FlowPOS load yet)
plu_option_attributeviw_Producto_Atributo_1 (Manager API)Extract/archive only (destination table TBD)

Every successful row should also write rpapos_id_map for idempotent re-sync.

Full FlowPOS table index (catalog, orders, pricing, marketplace, RPApos source names): Menus & Modifier Groups — All related tables.


RestSink details

Moneda → currency

  • Match by currency_code globally; link to business via business_currency.

UnidadMedida → unit_of_measure

  • Match by name / RPApos name / abbreviation via findUomIdFirstMatch.
  • Link via business_unit_of_measure.

Area → dining_area

Location resolution priority:

  1. Planner targetLocationId
  2. rpapos_id_map for bodegalocation
  3. Oldest location created by import_type=location
  4. Oldest location for business

Upsert key: (location_id, name); updates location_id on re-sync when mapping changes.

Mesa → dining_table

  • Resolves area_id from rpapos_id_map (entity_type=area, external id from row).
  • Fallback: first dining area at target location (or business-wide).
  • Upsert: (area_id, table_number); id map keyed by RPA mesa external id.

Persona → customer

  • Upsert by customer_code within business.

BatchMaestro → product_recipe

  • Resolves parent PLU and ingredient SKU via rpapos_id_map (plu, sku).
  • Resolves UoM via id map or first business UoM.
  • Unique per (parent_product_id, ingredient_product_id).

PluOptionGroup → product_modifier_group

Source: SOAP Catalogo_4 pTabla=Producto_Grupo. Requires registered SOAP token.

  • Upsert keyed by rpapos_id_map(entity_type=plu_option_group, external_id=<group id>).
  • Wire PK is usually Producto_Grupo (not Id) on tenant DBs; legacy Id still accepted.
  • auto_prompt always false. IdTipoGrupo stored in raw blob only.

PluOptionItem → product_modifier

Source: SOAP Catalogo_4 pTabla=Producto_Grupo_Detalle, or Manager API viw_Producto_Grupo_Detalle_1 when credentials are present.

  • Upsert keyed by rpapos_id_map(entity_type=plu_option_item, external_id=<detail id>).
  • Wire PK is usually Producto_Grupo_Detalle; group FK is Producto_Grupo (legacy Id / Id_Grupo still accepted).
  • modifier_group_id resolved via id map (plu_option_group, Producto_Grupo value) — hard fail if id_map empty.
  • linked_product_id resolved via id map (plu, Codigo_PLU, or numeric Producto) — soft fail (NULL) with warning if unresolved.
  • Detail rows often have no label column. Manager API: orchestrator joins viw_Producto_Atributo_1 on Producto_Atributo to copy Descripcion and Codigo_PLU onto each detalle row before transform. Without that join, names fall back to linked PLU product name, then to "{group} — opción {orden}".
  • When linked_product_id is set, quantity_per_modifier is forced to 1 (check constraint).

viw_Producto_Grupo_Relacion_1 is not modifier items — it only links sellable PLUs to modifier groups (product_modifier_group_assignment). Option labels always come from detalle + attribute master (or linked PLU name).

PluOptionGroupAssignment → product_modifier_group_assignment

Source: SOAP Catalogo_4 pTabla=Producto_Grupo_Relacion. Requires registered SOAP token. No REST equivalent.

  • product_id resolved via id map (plu, Codigo_PLU / Id_PLU) — hard fail if missing.
  • modifier_group_id resolved via id map (plu_option_group, Producto_Grupo / Id_Grupo) — hard fail if missing.
  • Unique constraint: (product_id, modifier_group_id).
  • Pre-extraction guard: if plu id_map is empty for the business, run fails with PLU_IDMAP_EMPTY.

HandlerSink details

Uses the same handlers as CSV import (apps/backend/src/data-import/application/handlers/).

Product (PLU / SKU)

  • PLU: sellable product; category and UoM resolved by name; optional category id map when PLU_Grupo_Nombre missing on wire.
  • SKU: raw material flag; orchestrator may pre-create categories from SKU_Grupo_Nombre before handler runs.

Category groups

plu_grupo, sku_grupo, produccion_grupo all map to import type category with different transformer field mappings.

Bodega → location

Creates FlowPOS locations/warehouses; id map enables later dining area placement.

Usuario → employee

Employee import handler; may reference locations by name.

Proveedor → supplier

Standard supplier handler.


Metadata on rows

Transformers attach __rpapos (and related fields) for id mapping:

{
name: "Product name",
sku: "PLU-001",
__rpapos: {
externalId: "12345",
entityType: "plu"
}
}

IdMapWriterService reads this after sink success to populate rpapos_id_map.


Product images (PLU only)

Optional post-sync step (not a catalog entity type). Matching uses rpapos_id_map where entity_type = plu and external_id equals RPApos Codigo_PLU from SOAP Producto_U_M. Images are stored on product.image_url (GCS). Does not create new products — PLU must be imported first (or use a prior id map for images-only runs).


Quick start vs full catalog

EntityQuick startEverything
moneda
unidad_medida
plu_grupo
sku_grupo
produccion_grupo
bodega
proveedor
area
persona
sku
plu
usuario
mesa
batch_maestro
plu_option_group
plu_option_item
plu_option_group_assignment

Transformers (source)

EntityTransformer file
monedamoneda.transformer.ts
unidad_medidaunidad-medida.transformer.ts
plu_grupoplu-grupo.transformer.ts
sku_gruposku-grupo.transformer.ts
produccion_grupoproduccion-grupo.transformer.ts
bodegabodega.transformer.ts
proveedorproveedor.transformer.ts
areaarea.transformer.ts
personapersona-cliente.transformer.ts
skusku.transformer.ts
pluplu.transformer.ts
usuariousuario.transformer.ts
mesamesa.transformer.ts
batch_maestrobatch-maestro.transformer.ts
plu_option_groupplu-option-group.transformer.ts
plu_option_itemplu-option-item.transformer.ts
plu_option_group_assignmentplu-option-group-assignment.transformer.ts

Payload types: apps/backend/src/rpapos/domain/types/rpapos-payloads.types.ts