erp-core/docs/03-requerimientos/RF-catalogs/RF-CATALOG-004.md

8.0 KiB

RF-CATALOG-004: Unidades de Medida (UoM)

Identificacion

Campo Valor
ID RF-CATALOG-004
Modulo MGN-005 Catalogs
Titulo Unidades de Medida (UoM)
Prioridad Media
Estado Draft
Fecha 2025-12-05

Descripcion

El sistema debe permitir gestionar unidades de medida agrupadas por categorias, con factores de conversion entre unidades de la misma categoria.

Referencia Odoo:

  • uom.category (addons/uom/models/uom_uom.py)
  • uom.uom (mismo archivo)

Arquitectura

Por Tenant

A diferencia de paises y monedas, las unidades de medida son por tenant:

core_catalogs.uom_categories (tenant_id UUID NOT NULL)
core_catalogs.uom (tenant_id UUID NOT NULL)

Rationale: Cada tenant puede necesitar unidades personalizadas segun su industria.


Requisitos Funcionales

RF-CATALOG-004.1: Categorias de UoM

Las unidades se agrupan en categorias. Solo se pueden convertir unidades de la misma categoria.

Campo Tipo Descripcion
id UUID Identificador unico
tenant_id FK Tenant propietario
name string Nombre de categoria
is_active boolean Disponible para uso

Categorias por defecto (seed):

Categoria Descripcion
Unit Unidades discretas (piezas, docenas)
Weight Peso (kg, g, lb, oz)
Volume Volumen (L, mL, gal)
Length Longitud (m, cm, ft, in)
Time Tiempo (hora, dia, semana)
Area Area (m2, ha, acre)

RF-CATALOG-004.2: Unidades de Medida

Campo Tipo Descripcion
id UUID Identificador unico
tenant_id FK Tenant propietario
category_id FK Categoria de UoM
name string Nombre de unidad
uom_type enum reference/bigger/smaller
factor decimal Factor de conversion
rounding decimal Precision de redondeo
is_active boolean Disponible para uso

RF-CATALOG-004.3: Tipos de Unidad

Cada categoria tiene exactamente UNA unidad de referencia:

Tipo Descripcion Factor
reference Unidad base de la categoria 1.0
bigger Mayor que la referencia < 1.0
smaller Menor que la referencia > 1.0

Ejemplo categoria "Weight":

Unidad Tipo Factor Equivalencia
kg reference 1.0 1 kg = 1 kg
g smaller 1000 1 kg = 1000 g
lb bigger 0.453592 1 lb = 0.453592 kg
oz smaller 35.274 1 kg = 35.274 oz

RF-CATALOG-004.4: Conversion de Unidades

El sistema debe proporcionar funciones de conversion:

// Convertir cantidad de una unidad a otra
convertUom(
  quantity: number,
  fromUom: UUID,
  toUom: UUID
): number

// Redondear segun unidad
roundUom(quantity: number, uom: UUID): number

Formula de conversion:

quantity_to = quantity_from * (factor_from / factor_to)

Validacion: Solo se permite conversion entre unidades de la misma categoria.

RF-CATALOG-004.5: Constraints de Categoria

Constraint Descripcion
Una referencia Exactamente 1 unidad reference por categoria
Factor referencia = 1 La unidad reference debe tener factor = 1.0
Factor > 0 El factor de conversion debe ser positivo

RF-CATALOG-004.6: Unidades Protegidas

Algunas unidades del seed no deben modificarse:

-- Unidades protegidas
is_protected BOOLEAN DEFAULT false
Unidad Categoria Protegida Razon
pcs Unit Si Referencia universal
kg Weight Si SI standard
L Volume Si SI standard
m Length Si SI standard
hr Time Si Referencia de tiempo

Operaciones CRUD

Listar Categorias

GET /api/v1/catalogs/uom-categories

Response:
{
  "data": [
    { "id": "uuid", "name": "Unit", "uomCount": 3 },
    { "id": "uuid", "name": "Weight", "uomCount": 5 },
    ...
  ]
}

Listar Unidades por Categoria

GET /api/v1/catalogs/uom?categoryId=uuid-weight

Response:
{
  "data": [
    {
      "id": "uuid",
      "name": "kg",
      "uomType": "reference",
      "factor": 1.0,
      "rounding": 0.001
    },
    {
      "id": "uuid",
      "name": "g",
      "uomType": "smaller",
      "factor": 1000,
      "rounding": 1
    }
  ]
}

Crear Unidad

POST /api/v1/catalogs/uom
{
  "categoryId": "uuid-weight",
  "name": "Tonelada",
  "uomType": "bigger",
  "factor": 0.001,  // 1 ton = 0.001 kg^-1 = 1000 kg
  "rounding": 0.001
}

Convertir Cantidad

GET /api/v1/catalogs/uom/convert?from=uuid-kg&to=uuid-lb&quantity=10

Response:
{
  "from": { "uom": "kg", "quantity": 10 },
  "to": { "uom": "lb", "quantity": 22.0462 },
  "factor": 2.20462
}

Data Seed

Categoria: Unit

Nombre Tipo Factor Rounding
pcs (Pieces) reference 1 1
dozen bigger 0.0833 1
pair bigger 0.5 1

Categoria: Weight

Nombre Tipo Factor Rounding
kg reference 1 0.001
g smaller 1000 1
lb bigger 0.453592 0.01
oz smaller 35.274 0.01
ton bigger 0.001 0.001

Categoria: Volume

Nombre Tipo Factor Rounding
L reference 1 0.001
mL smaller 1000 1
gal (US) bigger 0.264172 0.001
m3 bigger 0.001 0.001

Categoria: Length

Nombre Tipo Factor Rounding
m reference 1 0.001
cm smaller 100 1
ft bigger 0.3048 0.01
in smaller 39.3701 0.1

Categoria: Time

Nombre Tipo Factor Rounding
hour reference 1 0.01
day bigger 0.0417 0.01
week bigger 0.00595 0.01

Reglas de Negocio

ID Regla Severidad
BR-001 Una unidad reference por categoria Error
BR-002 Reference factor = 1.0 Error
BR-003 Factor > 0 Error
BR-004 Solo convertir misma categoria Error
BR-005 No eliminar unidad con productos Error
BR-006 No modificar unidades protegidas Error

Casos de Prueba

ID Escenario Resultado Esperado
TC-001 Crear categoria nueva Categoria creada
TC-002 Crear unidad reference Factor = 1.0 validado
TC-003 Crear segunda reference Error: ya existe
TC-004 Convertir kg a lb 10 kg = 22.0462 lb
TC-005 Convertir kg a L (diferente categoria) Error
TC-006 Redondear 10.12345 kg (rounding=0.001) 10.123
TC-007 Eliminar unidad con productos Error

Criterios de Aceptacion

  • Categorias CRUD funcional
  • Unidades CRUD funcional
  • Constraint de una reference
  • Conversion dentro de categoria
  • Redondeo segun precision
  • Seed de unidades comunes
  • Proteccion de unidades base

Notas Tecnicas

Funcion de Conversion SQL

CREATE OR REPLACE FUNCTION core_catalogs.convert_uom(
    p_quantity DECIMAL,
    p_from_uom UUID,
    p_to_uom UUID
) RETURNS DECIMAL AS $$
DECLARE
    v_from_factor DECIMAL;
    v_to_factor DECIMAL;
    v_from_category UUID;
    v_to_category UUID;
BEGIN
    -- Obtener datos de origen
    SELECT factor, category_id INTO v_from_factor, v_from_category
    FROM core_catalogs.uom WHERE id = p_from_uom;

    -- Obtener datos de destino
    SELECT factor, category_id INTO v_to_factor, v_to_category
    FROM core_catalogs.uom WHERE id = p_to_uom;

    -- Validar misma categoria
    IF v_from_category != v_to_category THEN
        RAISE EXCEPTION 'Cannot convert between different UoM categories';
    END IF;

    -- Convertir
    RETURN p_quantity * (v_from_factor / v_to_factor);
END;
$$ LANGUAGE plpgsql STABLE;

Historial

Version Fecha Autor Cambios
1.0 2025-12-05 System Creacion inicial