Cálculo de Precios — Tabla ArticuloPrecios

Motor unificado de precios. Reemplaza V1 (DBVenta1..10) y V2 (ArticuloPrecio) con multi-moneda, redondeo per-fila y guardrails.

v1.0 Productivo 2026-05-02 Técnico + Operativo 12 min AY-076
Menú Ayuda

Enviarle este manual a un usuario

El enlace abre solo este manual, sin el menú del sistema. El usuario no necesita clave ni entrar a FactuPOS: se ve en cualquier navegador y en el celular.

El WhatsApp sale del número de Soporte Real y el correo de info@soportereal.com. Con Compartir desde este teléfono sale de su propio WhatsApp y elige el contacto de su lista, sin escribir el número.

Vista general

El motor unificado de precios dbo.ArticuloPrecios reemplaza los dos modelos legacy (V1 con DBVenta1..10 en Articulos, y V2 con la tabla ArticuloPrecio) por una sola tabla con:

Precios por artículo
Dinámicos (1..n)
No limitado a 10
Multi-moneda
Por precio
CRC + USD + EUR (TC venta)
Redondeo
Per-fila
Sin red. / 2 dec / 1 dec / Ent / × 5/10/100
Guardrails
POS
Desc.Max + Util.Mínima

Tabla y campos

CREATE TABLE dbo.ArticuloPrecios (
    Id               INT IDENTITY(1,1) NOT NULL UNIQUE,
    ArticuloCodigo   VARCHAR(15)   NOT NULL,
    NumeroPrecio     INT           NOT NULL,                        -- 1..n dinámico
    MonedaCodigo     VARCHAR(3)    NOT NULL DEFAULT 'CRC',    -- por precio
    Costo            DECIMAL(18,4) NOT NULL DEFAULT 0,        -- en MonedaCodigo
    Margen           DECIMAL(9,4)  NOT NULL DEFAULT 0,        -- % ANCLA del usuario
    Precio           DECIMAL(19,5) NOT NULL DEFAULT 0,        -- sin IVA, 5 decimales (#2465)
    MargenSobre      VARCHAR(5)    NOT NULL DEFAULT 'COSTO',  -- 'COSTO'|'VENTA'
    PrecioAuto       BIT           NOT NULL DEFAULT 1,        -- 1=auto, 0=manual
    DescuentoFijo    DECIMAL(9,4)  NOT NULL DEFAULT 0,
    DescuentoMaximo  DECIMAL(9,4)  NOT NULL DEFAULT 0,
    UtilidadMinima   DECIMAL(9,4)  NOT NULL DEFAULT 0,
    RedondeoPrecio   DECIMAL(10,4) NOT NULL DEFAULT 0.01,     -- step redondeo Neto
    PRIMARY KEY CLUSTERED (ArticuloCodigo, NumeroPrecio)
);

Conceptos clave

1. Margen es ANCLA del usuario

Regla de oro: el campo Margen guardado en BD es la "intención" del usuario y solo cambia cuando el usuario lo edita explícitamente. Cualquier otra operación — cambio de Costo, edición de Precio, redondeo, conversión de moneda, etc. — NO toca Margen.

2. Costo en moneda del precio

Articulos.DBCosto vive en la moneda del artículo (Articulos.Cod_TipoMoneda). En cada fila ArticuloPrecios.Costo se guarda el costo convertido a la moneda de esa fila, usando TipoCambioVenta de dbo.TipoCambio.

3. RedondeoPrecio per-fila

Cada fila guarda su propio RedondeoPrecio (step) — distinto para CRC (típico × 100) que para USD (típico 0.01).

4. Tipo de precio: A, M, E o C

Cada nivel tiene su tipo, guardado como letra en PrecioAuto (los niveles viejos pueden tener todavía 1/0, que valen A/M). Decide qué pasa con el precio cuando cambia el costo (ver Tipo de precio):

TipoColumnasPrecio en pantallaAl cambiar Costo
A AutomáticoPrecioAuto='A' (o '1')readonlyEl Precio se recalcula desde el Margen (sube o baja)
M ManualPrecioAuto='M' (o '0')editableEl Precio no se toca; lo que se mueve es el margen real
E EspecialPrecioAuto='E'editableCosto sube → el Precio sube · costo baja → el Precio no baja
C CompuestoPrecioAuto='C'editable (recalcula el Margen)Costo baja → el Precio no baja · costo sube → el Precio solo sube si el margen real cae bajo el Margen, y justo hasta él

Cambio de Costo — flujo completo

Cuando el usuario edita uno de los 4 costos (Propio / Promedio / Último / Bruto) en el formulario y presiona Enter o el botón ✓:

  1. JS guardarCostoArticulo() arma FormData con los 4 costos + el origen seleccionado y POST a api_guardarCostoArticulo.php.
  2. Endpoint Fase 1 (granular): compara cada uno de los 5 campos (4 costos + origen) con la BD; UPDATE solo los que cambiaron. DBCosto (Propio) solo se actualiza si origen = 0.
  3. Endpoint deriva dbCostoFinal según el origen activo:
    • 0 → costoPropio
    • 1 → costoPromedio
    • 2 → costoUltimo
    • 3 → costoBruto
  4. Endpoint Fase 2 (propagación): si DBCosto efectivamente cambió, llama a la función articulo_precios_actualizar_costo($pdo, $cod, $dbCostoFinal, $moneda).
  5. La función itera todas las filas de ArticuloPrecios del artículo y aplica las 3 fases internas (ver siguiente sección).

Fases internas de articulo_precios_actualizar_costo

UPDATE Articulos SET DBCosto, Cod_TipoMoneda
    ↓ por cada fila ArticuloPrecios:

FASE 1 — Convertir Costo a moneda de la fila
    Si MonedaCodigo == moneda del artículo: Costo = DBCosto
    Si difiere: convertir vía TipoCambioVenta (TC más reciente <= hoy)
    Si TC no disponible: aviso, salta esta fila

FASE 2 — Precio según el TIPO del nivel (Margen NO se toca)
    A → Precio = articulo_precios_calcular_precio(Costo, Margen, MargenSobre)
    M → Precio queda igual (se mueve el margen real)
    E → costo bajó: Precio queda igual
        costo subió: Precio = max(Precio + (CostoNuevo − CostoAntes),
                                  calcular_precio(CostoNuevo, Margen, MargenSobre))

FASE 3 — Redondear Neto al step de la fila
    Neto = Precio × (1 + IVA / 100)
    NetoRound = ceil(Neto / RedondeoPrecio) × RedondeoPrecio
    Si NetoRound != Neto:
        exacto = NetoRound / (1 + IVA / 100)
        Precio = floor(exacto × 10000) / 10000   // truncar (no round)

Cambio de Precio — flujo completo

El usuario tiene varias formas equivalentes de modificar el precio de una fila desde el editor de artículos:

AcciónTriggerBackend recibe
Edita Margenblur / Enter{ Margen: X }
Edita Precio (en Manual)blur / Enter{ Precio: X }
Edita Ganancia (en Manual)blur / Enter{ Precio: Costo + Gan }
Edita Precio+IVA (Manual)blur / Enter{ Precio: Neto / (1+IVA) }
Toggle Auto/Manualchange{ PrecioAuto: 0|1 }
Doble-clic en Monchange select{ MonedaCodigo: 'X' }
Cambio de Redondeochange select{ RedondeoPrecio: X }
Click en # abre modal MAP-001botón Guardartodos los campos del modal

Todas terminan llamando a guardarPrecioArticulo(numero, cambios) en JS, que hace POST a api_guardarPrecioArticulo.php y este invoca la función articulo_precios_actualizar_precio.

Fases internas de articulo_precios_actualizar_precio

SELECT fila actual de ArticuloPrecios
    ↓
Aplicar $cambios sobre copia
    ↓
Validaciones (descuentos 0..100, fijo<=max, util>=0, margen>=0)
    ↓

FASE 1 — Convertir Costo según la moneda
    Si MonedaCodigo cambió:
        Lee Articulos.DBCosto + Cod_TipoMoneda + Param 249 (nacional)
        Costo nuevo = convertir_costo(DBCosto, monedaArt → monedaNueva)
        Si TC no disponible: throw error
    Si no cambió: Costo se mantiene

FASE 2 — Recalcular según QUÉ editó el usuario
    Si user mandó 'margen':       Precio = f(Costo, Margen, MargenSobre)
    Si user mandó 'precio':       NO toca Margen (queda como ancla)
                                  Validación: precio < costo → throw
    Si user no mandó ninguno:     no recalcula nada

FASE 3 — Redondear Neto al step (RedondeoPrecio)
    Igual que en actualizar_costo (ceil + floor con truncate)
    Margen NUNCA se toca acá
    ↓
UPDATE ArticuloPrecios + INSERT BitacoraSistema

Redondeo del Neto per-fila

El RedondeoPrecio de cada fila define el "paso" al cual se redondea el Precio + IVA (no el Precio sin IVA). El signo del valor indica el sentido:

  • Positivo (5, 10, 100, 1000…) → redondea el Neto hacia ARRIBA (ceil) al múltiplo.
  • Negativo (-5, -10, -100, -1000…) → redondea el Neto hacia ABAJO (floor) al múltiplo de abs(step).
  • 0 → «Sin redondeo» (primera opción de la lista, #2465): no se aplica ningún redondeo; el precio sin IVA queda tal como se escribió o calculó, con hasta 5 decimales, y el neto es el que sale de él.
  • 0.01 (positivo) → «↑ 2 decimales»: el Neto sube al céntimo; el Precio sin IVA se ajusta para que el neto quede en céntimos exactos (caso default de un nivel nuevo).
StepEtiqueta UIComportamientoCaso típico
0Sin redondeoNo redondea nada: el precio queda como está (hasta 5 decimales)Precio sin IVA exacto (#2465)
0.01 / -0.01↑ 2 dec / ↓ 2 decNeto al céntimo hacia arriba / hacia abajo0.01 = default de un nivel nuevo
0.10 / -0.10↑ 1 dec / ↓ 1 decAl 0.10 más cercano hacia arriba / hacia abajoUSD "precio bonito"
1 / -1↑ Ent / ↓ EntAl entero hacia arriba / hacia abajoUSD enteros / CRC truncado
5 / -5↑ × 5 / ↓ × 5Múltiplos de 5 (arriba / abajo)CRC menor
10 / -10↑ × 10 / ↓ × 10Múltiplos de 10 (arriba / abajo)CRC retail
25 / -25↑ × 25 / ↓ × 25Múltiplos de 25 (arriba / abajo)CRC retail
50 / -50↑ × 50 / ↓ × 50Múltiplos de 50 (arriba / abajo)CRC retail
100 / -100↑ × 100 / ↓ × 100Múltiplos de 100 (arriba / abajo)CRC mayoreo
500 / -500↑ × 500 / ↓ × 500Múltiplos de 500 (arriba / abajo)CRC mayoreo
1000 / -1000↑ × 1000 / ↓ × 1000Múltiplos de 1000 (arriba / abajo)CRC mayoreo grande

Editor de artículo — UI

Layout principal

┌─ Costos y Precios (col-middle) ─────────────────────────────┐
│  [Propio ●][Promedio][Último][Bruto] [✓ Guardar]            │ ← edita costo
│   327.33    320.00    327.33   330.00                       │
├─────────────────────────────────────────────────────────────┤
│  📊 Tabla ArticuloPrecios   11 filas  ☐MON ☐COSTO  [+ AGR]  │
├─────────────────────────────────────────────────────────────┤
│  # [Mon] [Costo]  PRECIO    MARGEN          GAN.   PRECIO+IVA│
│  1                411.5044  [25.72][25.00]  84.17  465.00    │
│  ─                                                            │
│   ▓ verde Auto                                                │
│  2                429.2035  [31.12][30.00]  101.87 485.00    │
│  ─                                                            │
│   ▓ ámbar Manual                                              │
└─────────────────────────────────────────────────────────────┘

Columnas visibles por default

#, Precio, Margen (con Margen Real al lado), Ganancia, Precio+IVA. Adicionalmente con toggle: Mon y Costo.

Columnas siempre ocultas (en modal)

Sobre, Desc.Fijo, Desc.Max, Util.Min. Estos campos se editan vía el modal MAP-001 (lápiz de la fila o doble clic).

Tipo: la columna Tipo tiene un combo por nivel con M-Manual, A-Automático, E-Especial y C-Compuesto; el color dice cuál rige (verde A, gris M, naranja E, celeste C). Al escoger otro se guarda de una vez. Ver Tipo de precio.

Inline editing

  • Margen: editable siempre (ancla del usuario)
  • Precio: editable en Manual, Especial y Compuesto (readonly solo en Auto). En Compuesto, escribir el precio recalcula el margen del dueño desde ese precio (ya redondeado) y desde ahí rige la subida por costo.
  • Ganancia: editable solo en Manual (al editar, recalcula Precio = Costo + Ganancia)
  • Precio+IVA: editable solo en Manual (al editar, recalcula Precio = Neto / (1+IVA))
  • Mon: doble-clic abre select inline

Indicador visual de modo

Debajo del badge # aparece una barra de 2px:

  • verde = AUTO
  • ámbar = MANUAL

Alertas visuales

  • Margen = 0 → input rojo pulsante
  • Margen negativo (no permitido) → bloqueado en backend
  • Precio < Costo → input rojo + tooltip
  • Precio = 0 en Manual → input rojo

Tipo de precio: A, M, E (Especial) y C (Compuesto)

Cada nivel de precio (P1, P2…) tiene un tipo, que decide qué pasa con el precio cuando cambia el costo, ya sea porque se aplicó una compra, porque se cambió el costo en la ficha o desde Cambios globales:

  • A = Automático: el costo sube o baja y el precio lo sigue; el margen no se toca.
  • M = Manual: el precio no se toca; lo que cambia es el margen real.
  • E = Especial: si el costo sube, el precio sube solo; si el costo baja, el precio no baja: la empresa se queda con la diferencia y solo cambia el margen real. El margen que puso el dueño no cambia.
  • C = Compuesto (Especial/Auto): si el costo baja, el precio no baja (como en E). Si el costo sube, el precio se queda mientras el margen real siga igual o por encima del margen del dueño; solo cuando el margen real va a quedar por debajo, el precio sube justo lo necesario para volver al margen del dueño. Es más conservador que el E: no mueve el precio al público por subidas pequeñas que el margen real puede absorber.

¿Cuánto sube el precio en el tipo E?

Sube lo mismo que subió el costo base (DBCosto, que sale del origen marcado: Propio, Promedio, Último o Bruto), pero nunca queda por debajo del margen del dueño. Se compara el costo base de antes con el nuevo; si se cambia el origen y el costo base sube, también cuenta.

PasoCostoPrecioPor qué
Inicio (margen del dueño 50 %)100150
Compra más barata80150el costo bajó: el precio se queda
Vuelve a subir90160subió 10 → el precio sube 10

El piso del margen del dueño: si el precio estaba justo en su margen (costo 100, precio 150) y el costo sube a 120, sumar la diferencia daría 170, que es menos del 50 % sobre 120. En ese caso se usa el margen del dueño: 180. Siempre se toma el mayor de los dos.

Si el nivel tiene redondeo, el precio nuevo se redondea igual que siempre.

¿Cuándo y cuánto sube el precio en el tipo C?

Se usa el mismo costo base que en el E (DBCosto del origen marcado, comparando el de antes con el nuevo). Ejemplo con margen del dueño 40 % sobre costo:

PasoCostoPrecioMargen realPor qué
Inicio2.0003.00050 %
Compra más barata1.6003.00087,5 %el costo bajó: el precio se queda
Sube un poco2.1003.00042,9 %sigue por encima del 40 %: el precio no se mueve
Sube mucho2.5003.50040 %con 3.000 quedaría en 20 %: sube justo hasta el 40 %
Vuelve a bajar2.3003.50052,2 %el costo bajó: el precio se queda

Diferencia con el E: en el paso «sube un poco» el E habría subido el precio lo mismo que el costo; el C lo deja quieto porque el margen real todavía alcanza.

Si se reescribe el margen del dueño en un nivel C, el precio se recalcula desde el costo actual con el margen nuevo, igual que en el A: es como empezar de cero con el nuevo límite de margen. Si sube el margen, el precio sube; si lo baja, el precio también baja. Ejemplo: costo 2.600, precio 3.640 y usted escribe 30 % → el precio queda en 3.380 (2.600 × 1,30). Si no toca el margen, nada cambia.

Si se escribe el precio a mano en un nivel C (precio sin IVA o neto), el margen del dueño pasa a ser el de ese precio (calculado sobre el precio ya redondeado) y la dinámica del C sigue igual con ese margen nuevo. Ejemplo: costo 2.000, precio 3.000, margen 40 %; usted escribe 3.200 → el margen queda en 60 %. Si después el costo sube a 2.100, con 3.200 el margen real quedaría en 52,4 % (bajo el 60 %), así que el precio sube a 3.360. Si el costo baja, el precio se queda. Un precio por debajo del costo se rechaza. Los precios que ya existían no se tocaron con este cambio: siguen igual hasta que un cambio de costo, un margen nuevo o un precio escrito los mueva.

Si el nivel tiene redondeo, el precio nuevo se redondea igual que siempre.

Si se revierte la compra

Cuando se revierte una compra que había subido el precio de un nivel E o C, ese precio vuelve al que tenía antes de la compra (esa compra no cuenta). Si después de la compra alguien cambió el precio —a mano u otra compra—, no se toca y la reversa lo avisa en su detalle.

Cómo se escoge

  • IN-002 (ficha del artículo): combo de la columna Tipo en la lista de precios. En el celular, el mismo combo en la cabecera de cada nivel.
  • MAP-001 / agregar nivel: selector Modo con A, M, E y C.
  • Cambios globales (MX-010): tarjetas Modo de venta (todos los niveles) y Modo de venta (Auto / Manual / Especial / Compuesto) (un nivel).
  • Nuevo artículo desde la compra (MCO-003): cuadro Tipo de precio por nivel, una casilla por nivel que se recuerda (ver Compras).
  • Análisis de precios de la compra (CO-020): se ve como Especial o Compuesto y se cambia en su modal. En un nivel C el precio también se puede escribir ahí: recalcula el margen del dueño.

En el tipo E se puede escribir el precio o el margen a mano igual que en Manual. En el tipo C, como en el A, solo se escribe el margen.

Filtro, Excel y sucursales

  • En IN-002, Más filtros → Modo precio tiene las opciones Especial y Compuesto (sobre el nivel elegido en Precio).
  • El Excel de IN-002 trae la columna Tipo precio (Pn) con Auto, Manual, Especial o Compuesto.
  • El tipo viaja a las sucursales al guardar, desde Cambios globales y en la sincronización masiva (CF-SART). Una sucursal que todavía no tenga esta actualización recibe el nivel E o C como Manual (su precio no baja).
  • Si la empresa todavía no tiene la actualización, E-Especial y C-Compuesto aparecen como «no disponible» y no se pueden escoger.

Descuento por caja

Es un porcentaje por nivel de precio que la factura aplica sola a las cajas enteras de un artículo que se vende por empaque. Típico de supermercados y farmacias: la cerveza por unidad a ₡1.300, y si lleva el six-pack completo, 10 % menos.

  • Solo aparece en el modal MAP-001 si el artículo tiene Unidades x medida mayor que 1. Con 1, la opción no se ofrece.
  • Cada nivel tiene el suyo: P1 puede tener 10 % y P2 0 % (en P2 no hay descuento por caja).
  • Debajo de los descuentos se ve el Neto caja: lo que cuesta la caja completa, con IVA, ya con el descuento fijo + el de caja.
  • En la factura (FactuDesk) solo cubre cajas enteras: con cajas de 6, si lleva 8 el descuento va sobre 6 y las otras 2 van a precio normal. Detalle en el manual de FactuDesk.

Candado de utilidad mínima

Si el nivel tiene Util. mínima, el modal no deja guardar cuando alguno de los descuentos dejaría el precio por debajo de ella: el descuento fijo, el descuento máximo o el fijo + el de caja (los dos se suman en la factura). Aparece un aviso en rojo que dice cuál es, y el botón Guardar queda gris hasta que se baje ese descuento o la utilidad mínima. Se calcula igual que en la factura: utilidad sobre el costo, (Precio con descuento − Costo) ÷ Costo × 100.

Ejemplo: costo ₡1.000, precio ₡1.300 (30 % de utilidad), utilidad mínima 20 %. Un descuento de 5 % deja 23,5 % → se puede. Uno de 10 % deja 17 % → no se puede guardar.

Para muchos artículos a la vez (MX-010)

En el listado de IN-002 seleccione los artículos (o todo el filtro) → Config → Cambios globales → Precios por nivel → Descuento x caja: elija el nivel, escriba el % y presione Establecer desc. x caja. Solo se aplica a los que se venden por empaque (Uds x Med mayor que 1); a los demás no se les toca nada. Al terminar sale un resumen, por ejemplo:

«De los 100 artículos filtrados, se aplicó a 23 que se venden en cajas y unidades; 4 quedan por debajo de la utilidad mínima. ¿Desea verlos?»

Si responde que sí, el listado se queda con su mismo filtro pero muestra los que hay que revisar (el punto rojo de Margen/Costo, a la par de Buscar, + Se venden x paq. de Más filtros: así no se cuelan artículos por unidad; el rojo trae además los que quedan bajo el costo, así que pueden salir más de los contados), para revisarlos uno por uno o volver a aplicar un % más bajo. En los cambios globales el descuento se aplica igual aunque rompa la utilidad mínima: por eso el resumen lo cuenta; en la factura, esos artículos no reciben la parte de caja mientras la rompan (salvo permiso 006).

Sucursales (empresas sincronizadas)

Si la empresa sincroniza su catálogo con otras sucursales, el descuento por caja viaja igual que los demás descuentos: al guardar en el modal MAP-001 o en IN-002, al aplicarlo desde Cambios globales y en la sincronización masiva (CF-SART), cada sucursal queda con el mismo % en el mismo nivel. La sucursal tiene que estar al día con las actualizaciones del sistema; si todavía no tiene el descuento por caja, el resto de los precios se sincroniza normal y ese dato se omite.

Ejemplos numéricos

Ejemplo 1 — Cambio de costo en CRC

Artículo en CRC, IVA 13%, varias filas con distinto step.

Acción: usuario cambia DbCostoUltimo de 320 a 327.33 (origen = Último).

PMargenStepPrecio recalcNeto pre-redondeoNeto redondeadoPrecio final
1255409.16462.35465.00411.5044
2305425.53480.85485.00429.2035
5355441.90499.35500.00442.4778
7300.01425.53480.85480.86425.5398
9301425.53480.85481.00425.6637
11 (USD)500.101.071.211.301.1504

Ejemplo 2 — Bug histórico del round → ceil

Step 5, IVA 13%, usuario tipea Neto = 450
Si usáramos round() half-up:
  450 / 1.13 = 398.230088...
  round(398.230088, 4) = 398.2301  ↑ (5to dec = 8, sube)
  398.2301 × 1.13 = 450.000013      ↑ pasa de 450
  ceil(450.000013 / 5) × 5 = 455  ❌

Con floor() (truncar):
  floor(398.230088 × 10000) / 10000 = 398.2300  ↓
  398.2300 × 1.13 = 449.999          ↓ debajo de 450
  ceil(449.999 / 5) × 5 = 450  ✓

API / Funciones

Funciones backend (/functions/shared/articulos/articulo_precios.php)

FunciónPropósito
articulo_precios_actualizar_costo($pdo, $cod, $costo, $moneda)Cambia DBCosto + propaga a TODAS las filas
articulo_precios_actualizar_precio($pdo, $cod, $numero, $cambios)Edita una fila (P_n) con cualquier subset de campos
articulo_precios_crear_fila($pdo, $cod, $numero?, $cambios)Crea P_n nuevo (auto-asigna max+1 si null)
articulo_precios_eliminar_fila($pdo, $cod, $numero)Borra P_n
articulo_precios_calcular_precio($costo, $margen, $sobre)Helper puro (sin DB) — fórmula
articulo_precios_calcular_margen($costo, $precio, $sobre)Helper puro (sin DB) — fórmula inversa

Endpoints HTTP

EndpointPOST body
api_guardarCostoArticulo.phpCod_Articulo + 4 costos + DbArticuloOrigenCosto
api_guardarPrecioArticulo.phpCod_Articulo + NumeroPrecio + cualquier subset
api_crearPrecioArticulo.phpCod_Articulo + opciones
api_eliminarPrecioArticulo.phpCod_Articulo + NumeroPrecio

JS (articulos_crear.js)

  • guardarCostoArticulo() — disparado por click ✓ o Enter en input de costo
  • guardarPrecioArticulo(numero, cambios) — wrapper genérico
  • renderArticuloPrecios(rows) — re-pinta la tabla
  • articulo_precios_calc_real_margen(costo, precio, sobre) — helper puro JS para Margen virtual

Bitácora

Cada función registra entradas en dbo.BitacoraSistema:

Articulos.DBCosto | art ABC100 | costo 1000 CRC → 1200 CRC | filas afectadas 7/10
ArticuloPrecios | art ABC100 P3 | costo 1000→1200, precio 1300→1560
Costo Fase 2 | art ABC100 | DBCosto 250→331.85 | origen=Bruto (3) — DBCosto sincroniza
ArticuloPrecios CREATE | art ABC100 P11 | Mon=USD, Costo=2.4, Margen=30, Precio=3.12
ArticuloPrecios DELETE | art ABC100 P8 | Mon=CRC, Precio=375

Preguntas frecuentes