ET-SALES-BACKEND
Especificacion Tecnica Backend - Modulo Ventas
METADATOS
| Campo |
Valor |
| Modulo |
MGN-011 |
| Version |
1.0.0 |
| Fecha |
2026-01-10 |
| Estado |
Documentado |
| Autor |
Claude Code |
1. SERVICIOS
1.1 CustomerGroupsService
Ubicacion: backend/src/modules/sales/customer-groups.service.ts
| Metodo |
Parametros |
Retorno |
Descripcion |
findAll |
tenantId: string, filters: CustomerGroupFilters |
Promise<{ data: CustomerGroup[]; total: number }> |
Lista grupos de clientes con paginacion y busqueda |
findById |
id: string, tenantId: string |
Promise<CustomerGroup> |
Obtiene grupo por ID con sus miembros |
create |
dto: CreateCustomerGroupDto, tenantId: string, userId: string |
Promise<CustomerGroup> |
Crea nuevo grupo de clientes |
update |
id: string, dto: UpdateCustomerGroupDto, tenantId: string |
Promise<CustomerGroup> |
Actualiza grupo existente |
delete |
id: string, tenantId: string |
Promise<void> |
Elimina grupo (solo si no tiene miembros) |
addMember |
groupId: string, partnerId: string, tenantId: string |
Promise<CustomerGroupMember> |
Agrega cliente al grupo |
removeMember |
groupId: string, memberId: string, tenantId: string |
Promise<void> |
Elimina cliente del grupo |
1.2 SalesTeamsService
Ubicacion: backend/src/modules/sales/sales-teams.service.ts
| Metodo |
Parametros |
Retorno |
Descripcion |
findAll |
tenantId: string, filters: SalesTeamFilters |
Promise<{ data: SalesTeam[]; total: number }> |
Lista equipos de ventas con filtros |
findById |
id: string, tenantId: string |
Promise<SalesTeam> |
Obtiene equipo por ID con miembros |
create |
dto: CreateSalesTeamDto, tenantId: string, userId: string |
Promise<SalesTeam> |
Crea nuevo equipo de ventas |
update |
id: string, dto: UpdateSalesTeamDto, tenantId: string, userId: string |
Promise<SalesTeam> |
Actualiza equipo existente |
addMember |
teamId: string, userId: string, role: string, tenantId: string |
Promise<SalesTeamMember> |
Agrega usuario al equipo |
removeMember |
teamId: string, memberId: string, tenantId: string |
Promise<void> |
Elimina usuario del equipo |
1.3 PricelistsService
Ubicacion: backend/src/modules/sales/pricelists.service.ts
| Metodo |
Parametros |
Retorno |
Descripcion |
findAll |
tenantId: string, filters: PricelistFilters |
Promise<{ data: Pricelist[]; total: number }> |
Lista listas de precios |
findById |
id: string, tenantId: string |
Promise<Pricelist> |
Obtiene lista de precios con items |
create |
dto: CreatePricelistDto, tenantId: string, userId: string |
Promise<Pricelist> |
Crea nueva lista de precios |
update |
id: string, dto: UpdatePricelistDto, tenantId: string, userId: string |
Promise<Pricelist> |
Actualiza lista de precios |
addItem |
pricelistId: string, dto: CreatePricelistItemDto, tenantId: string, userId: string |
Promise<PricelistItem> |
Agrega item a lista de precios |
removeItem |
pricelistId: string, itemId: string, tenantId: string |
Promise<void> |
Elimina item de lista de precios |
getProductPrice |
productId: string, pricelistId: string, quantity: number |
Promise<number | null> |
Obtiene precio de producto segun lista y cantidad |
Ubicacion: backend/src/modules/sales/orders.service.ts
| Metodo |
Parametros |
Retorno |
Descripcion |
findAll |
tenantId: string, filters: SalesOrderFilters |
Promise<{ data: SalesOrder[]; total: number }> |
Lista ordenes de venta con filtros avanzados |
findById |
id: string, tenantId: string |
Promise<SalesOrder> |
Obtiene orden por ID con lineas |
create |
dto: CreateSalesOrderDto, tenantId: string, userId: string |
Promise<SalesOrder> |
Crea nueva orden de venta |
update |
id: string, dto: UpdateSalesOrderDto, tenantId: string, userId: string |
Promise<SalesOrder> |
Actualiza orden (solo en estado draft) |
delete |
id: string, tenantId: string |
Promise<void> |
Elimina orden (solo en estado draft) |
addLine |
orderId: string, dto: CreateSalesOrderLineDto, tenantId: string, userId: string |
Promise<SalesOrderLine> |
Agrega linea a orden |
updateLine |
orderId: string, lineId: string, dto: UpdateSalesOrderLineDto, tenantId: string |
Promise<SalesOrderLine> |
Actualiza linea de orden |
removeLine |
orderId: string, lineId: string, tenantId: string |
Promise<void> |
Elimina linea de orden |
confirm |
id: string, tenantId: string, userId: string |
Promise<SalesOrder> |
Confirma orden (draft -> sent) |
cancel |
id: string, tenantId: string, userId: string |
Promise<SalesOrder> |
Cancela orden |
createInvoice |
id: string, tenantId: string, userId: string |
Promise<{ orderId: string; invoiceId: string }> |
Genera factura desde orden |
1.5 QuotationsService
Ubicacion: backend/src/modules/sales/quotations.service.ts
| Metodo |
Parametros |
Retorno |
Descripcion |
findAll |
tenantId: string, filters: QuotationFilters |
Promise<{ data: Quotation[]; total: number }> |
Lista cotizaciones con filtros |
findById |
id: string, tenantId: string |
Promise<Quotation> |
Obtiene cotizacion por ID con lineas |
create |
dto: CreateQuotationDto, tenantId: string, userId: string |
Promise<Quotation> |
Crea nueva cotizacion |
update |
id: string, dto: UpdateQuotationDto, tenantId: string, userId: string |
Promise<Quotation> |
Actualiza cotizacion (solo en draft) |
delete |
id: string, tenantId: string |
Promise<void> |
Elimina cotizacion (solo en draft) |
addLine |
quotationId: string, dto: CreateQuotationLineDto, tenantId: string, userId: string |
Promise<QuotationLine> |
Agrega linea a cotizacion |
updateLine |
quotationId: string, lineId: string, dto: UpdateQuotationLineDto, tenantId: string |
Promise<QuotationLine> |
Actualiza linea de cotizacion |
removeLine |
quotationId: string, lineId: string, tenantId: string |
Promise<void> |
Elimina linea de cotizacion |
send |
id: string, tenantId: string, userId: string |
Promise<Quotation> |
Envia cotizacion al cliente (email) |
confirm |
id: string, tenantId: string, userId: string |
Promise<{ quotation: Quotation; orderId: string }> |
Confirma cotizacion y crea orden de venta |
cancel |
id: string, tenantId: string, userId: string |
Promise<Quotation> |
Cancela cotizacion |
2. ENTIDADES
2.1 CustomerGroup
Schema: sales.customer_groups
| Columna |
Tipo |
Nullable |
Descripcion |
id |
UUID |
NO |
Identificador unico |
tenant_id |
UUID |
NO |
Tenant (multi-tenancy) |
name |
VARCHAR(255) |
NO |
Nombre del grupo |
description |
TEXT |
SI |
Descripcion |
discount_percentage |
DECIMAL |
NO |
Porcentaje de descuento (default: 0) |
created_by |
UUID |
SI |
Usuario que creo |
created_at |
TIMESTAMP |
NO |
Fecha de creacion |
2.2 CustomerGroupMember
Schema: sales.customer_group_members
| Columna |
Tipo |
Nullable |
Descripcion |
id |
UUID |
NO |
Identificador unico |
customer_group_id |
UUID |
NO |
FK a customer_groups |
partner_id |
UUID |
NO |
FK a core.partners |
joined_at |
TIMESTAMP |
NO |
Fecha de union |
2.3 SalesTeam
Schema: sales.sales_teams
| Columna |
Tipo |
Nullable |
Descripcion |
id |
UUID |
NO |
Identificador unico |
tenant_id |
UUID |
NO |
Tenant |
company_id |
UUID |
NO |
FK a auth.companies |
name |
VARCHAR(255) |
NO |
Nombre del equipo |
code |
VARCHAR(50) |
SI |
Codigo unico por empresa |
team_leader_id |
UUID |
SI |
FK a auth.users (lider) |
target_monthly |
DECIMAL |
SI |
Meta mensual |
target_annual |
DECIMAL |
SI |
Meta anual |
active |
BOOLEAN |
NO |
Estado activo (default: true) |
created_by |
UUID |
SI |
Usuario que creo |
created_at |
TIMESTAMP |
NO |
Fecha de creacion |
updated_by |
UUID |
SI |
Usuario que actualizo |
updated_at |
TIMESTAMP |
SI |
Fecha de actualizacion |
2.4 SalesTeamMember
Schema: sales.sales_team_members
| Columna |
Tipo |
Nullable |
Descripcion |
id |
UUID |
NO |
Identificador unico |
sales_team_id |
UUID |
NO |
FK a sales_teams |
user_id |
UUID |
NO |
FK a auth.users |
role |
VARCHAR(100) |
SI |
Rol en el equipo |
joined_at |
TIMESTAMP |
NO |
Fecha de union |
2.5 Pricelist
Schema: sales.pricelists
| Columna |
Tipo |
Nullable |
Descripcion |
id |
UUID |
NO |
Identificador unico |
tenant_id |
UUID |
NO |
Tenant |
company_id |
UUID |
SI |
FK a auth.companies |
name |
VARCHAR(255) |
NO |
Nombre de la lista |
currency_id |
UUID |
NO |
FK a core.currencies |
active |
BOOLEAN |
NO |
Estado activo (default: true) |
created_by |
UUID |
SI |
Usuario que creo |
created_at |
TIMESTAMP |
NO |
Fecha de creacion |
updated_by |
UUID |
SI |
Usuario que actualizo |
updated_at |
TIMESTAMP |
SI |
Fecha de actualizacion |
2.6 PricelistItem
Schema: sales.pricelist_items
| Columna |
Tipo |
Nullable |
Descripcion |
id |
UUID |
NO |
Identificador unico |
pricelist_id |
UUID |
NO |
FK a pricelists |
product_id |
UUID |
SI |
FK a inventory.products |
product_category_id |
UUID |
SI |
FK a core.product_categories |
price |
DECIMAL |
NO |
Precio |
min_quantity |
INTEGER |
NO |
Cantidad minima (default: 1) |
valid_from |
DATE |
SI |
Fecha inicio validez |
valid_to |
DATE |
SI |
Fecha fin validez |
active |
BOOLEAN |
NO |
Estado activo (default: true) |
created_by |
UUID |
SI |
Usuario que creo |
2.7 SalesOrder
Schema: sales.sales_orders
| Columna |
Tipo |
Nullable |
Descripcion |
id |
UUID |
NO |
Identificador unico |
tenant_id |
UUID |
NO |
Tenant |
company_id |
UUID |
NO |
FK a auth.companies |
name |
VARCHAR(50) |
NO |
Numero de orden (SO-XXXXXX) |
client_order_ref |
VARCHAR(100) |
SI |
Referencia del cliente |
partner_id |
UUID |
NO |
FK a core.partners |
order_date |
DATE |
NO |
Fecha de orden |
validity_date |
DATE |
SI |
Fecha de validez |
commitment_date |
DATE |
SI |
Fecha de compromiso |
currency_id |
UUID |
NO |
FK a core.currencies |
pricelist_id |
UUID |
SI |
FK a pricelists |
payment_term_id |
UUID |
SI |
FK a financial.payment_terms |
user_id |
UUID |
SI |
FK a auth.users (vendedor) |
sales_team_id |
UUID |
SI |
FK a sales_teams |
amount_untaxed |
DECIMAL |
NO |
Subtotal sin impuestos |
amount_tax |
DECIMAL |
NO |
Total impuestos |
amount_total |
DECIMAL |
NO |
Total |
status |
ENUM |
NO |
draft, sent, sale, done, cancelled |
invoice_status |
ENUM |
NO |
pending, partial, invoiced |
delivery_status |
ENUM |
NO |
pending, partial, delivered |
invoice_policy |
ENUM |
NO |
order, delivery |
picking_id |
UUID |
SI |
FK a inventory.pickings |
notes |
TEXT |
SI |
Notas internas |
terms_conditions |
TEXT |
SI |
Terminos y condiciones |
created_by |
UUID |
SI |
Usuario que creo |
created_at |
TIMESTAMP |
NO |
Fecha de creacion |
confirmed_at |
TIMESTAMP |
SI |
Fecha de confirmacion |
confirmed_by |
UUID |
SI |
Usuario que confirmo |
cancelled_at |
TIMESTAMP |
SI |
Fecha de cancelacion |
cancelled_by |
UUID |
SI |
Usuario que cancelo |
updated_by |
UUID |
SI |
Usuario que actualizo |
updated_at |
TIMESTAMP |
SI |
Fecha de actualizacion |
2.8 SalesOrderLine
Schema: sales.sales_order_lines
| Columna |
Tipo |
Nullable |
Descripcion |
id |
UUID |
NO |
Identificador unico |
order_id |
UUID |
NO |
FK a sales_orders |
tenant_id |
UUID |
NO |
Tenant |
product_id |
UUID |
NO |
FK a inventory.products |
description |
TEXT |
NO |
Descripcion |
quantity |
DECIMAL |
NO |
Cantidad |
qty_delivered |
DECIMAL |
NO |
Cantidad entregada |
qty_invoiced |
DECIMAL |
NO |
Cantidad facturada |
uom_id |
UUID |
NO |
FK a core.uom |
price_unit |
DECIMAL |
NO |
Precio unitario |
discount |
DECIMAL |
NO |
Porcentaje descuento |
tax_ids |
UUID[] |
NO |
Array de FK a financial.taxes |
amount_untaxed |
DECIMAL |
NO |
Subtotal sin impuestos |
amount_tax |
DECIMAL |
NO |
Total impuestos |
amount_total |
DECIMAL |
NO |
Total |
analytic_account_id |
UUID |
SI |
FK a financial.analytic_accounts |
created_at |
TIMESTAMP |
NO |
Fecha de creacion |
updated_at |
TIMESTAMP |
SI |
Fecha de actualizacion |
2.9 Quotation
Schema: sales.quotations
| Columna |
Tipo |
Nullable |
Descripcion |
id |
UUID |
NO |
Identificador unico |
tenant_id |
UUID |
NO |
Tenant |
company_id |
UUID |
NO |
FK a auth.companies |
name |
VARCHAR(50) |
NO |
Numero de cotizacion (QUO-XXXXXX) |
partner_id |
UUID |
NO |
FK a core.partners |
quotation_date |
DATE |
NO |
Fecha de cotizacion |
validity_date |
DATE |
NO |
Fecha de validez |
currency_id |
UUID |
NO |
FK a core.currencies |
pricelist_id |
UUID |
SI |
FK a pricelists |
user_id |
UUID |
SI |
FK a auth.users (vendedor) |
sales_team_id |
UUID |
SI |
FK a sales_teams |
amount_untaxed |
DECIMAL |
NO |
Subtotal sin impuestos |
amount_tax |
DECIMAL |
NO |
Total impuestos |
amount_total |
DECIMAL |
NO |
Total |
status |
ENUM |
NO |
draft, sent, confirmed, cancelled, expired |
sale_order_id |
UUID |
SI |
FK a sales_orders (orden generada) |
notes |
TEXT |
SI |
Notas internas |
terms_conditions |
TEXT |
SI |
Terminos y condiciones |
created_by |
UUID |
SI |
Usuario que creo |
created_at |
TIMESTAMP |
NO |
Fecha de creacion |
updated_by |
UUID |
SI |
Usuario que actualizo |
updated_at |
TIMESTAMP |
SI |
Fecha de actualizacion |
2.10 QuotationLine
Schema: sales.quotation_lines
| Columna |
Tipo |
Nullable |
Descripcion |
id |
UUID |
NO |
Identificador unico |
quotation_id |
UUID |
NO |
FK a quotations |
tenant_id |
UUID |
NO |
Tenant |
product_id |
UUID |
SI |
FK a inventory.products |
description |
TEXT |
NO |
Descripcion |
quantity |
DECIMAL |
NO |
Cantidad |
uom_id |
UUID |
NO |
FK a core.uom |
price_unit |
DECIMAL |
NO |
Precio unitario |
discount |
DECIMAL |
NO |
Porcentaje descuento |
tax_ids |
UUID[] |
NO |
Array de FK a financial.taxes |
amount_untaxed |
DECIMAL |
NO |
Subtotal sin impuestos |
amount_tax |
DECIMAL |
NO |
Total impuestos |
amount_total |
DECIMAL |
NO |
Total |
created_at |
TIMESTAMP |
NO |
Fecha de creacion |
3. DTOs
3.1 CustomerGroups DTOs
interface CreateCustomerGroupDto {
name: string; // Requerido, max 255
description?: string; // Opcional
discount_percentage?: number; // 0-100, default: 0
}
interface UpdateCustomerGroupDto {
name?: string; // max 255
description?: string | null;
discount_percentage?: number; // 0-100
}
interface CustomerGroupFilters {
search?: string;
page?: number; // default: 1
limit?: number; // default: 20, max: 100
}
3.2 SalesTeams DTOs
interface CreateSalesTeamDto {
company_id: string; // UUID, requerido
name: string; // Requerido, max 255
code?: string; // max 50
team_leader_id?: string; // UUID
target_monthly?: number; // > 0
target_annual?: number; // > 0
}
interface UpdateSalesTeamDto {
name?: string;
code?: string;
team_leader_id?: string | null;
target_monthly?: number | null;
target_annual?: number | null;
active?: boolean;
}
interface SalesTeamFilters {
company_id?: string;
active?: boolean;
page?: number;
limit?: number;
}
3.3 Pricelists DTOs
interface CreatePricelistDto {
company_id?: string; // UUID
name: string; // Requerido, max 255
currency_id: string; // UUID, requerido
}
interface UpdatePricelistDto {
name?: string;
currency_id?: string;
active?: boolean;
}
interface CreatePricelistItemDto {
product_id?: string; // UUID (uno de product_id o product_category_id)
product_category_id?: string; // UUID
price: number; // >= 0
min_quantity?: number; // > 0, default: 1
valid_from?: string; // ISO date
valid_to?: string; // ISO date
}
interface PricelistFilters {
company_id?: string;
active?: boolean;
page?: number;
limit?: number;
}
3.4 Orders DTOs
interface CreateSalesOrderDto {
company_id: string; // UUID, requerido
partner_id: string; // UUID, requerido
client_order_ref?: string; // max 100
order_date?: string; // ISO date
validity_date?: string; // ISO date
commitment_date?: string; // ISO date
currency_id: string; // UUID, requerido
pricelist_id?: string; // UUID
payment_term_id?: string; // UUID
sales_team_id?: string; // UUID
invoice_policy?: 'order' | 'delivery'; // default: 'order'
notes?: string;
terms_conditions?: string;
}
interface UpdateSalesOrderDto {
partner_id?: string;
client_order_ref?: string | null;
order_date?: string;
validity_date?: string | null;
commitment_date?: string | null;
currency_id?: string;
pricelist_id?: string | null;
payment_term_id?: string | null;
sales_team_id?: string | null;
invoice_policy?: 'order' | 'delivery';
notes?: string | null;
terms_conditions?: string | null;
}
interface CreateSalesOrderLineDto {
product_id: string; // UUID, requerido
description: string; // Requerido
quantity: number; // > 0
uom_id: string; // UUID, requerido
price_unit: number; // >= 0
discount?: number; // 0-100, default: 0
tax_ids?: string[]; // UUID[]
analytic_account_id?: string; // UUID
}
interface UpdateSalesOrderLineDto {
description?: string;
quantity?: number;
uom_id?: string;
price_unit?: number;
discount?: number;
tax_ids?: string[];
analytic_account_id?: string | null;
}
interface SalesOrderFilters {
company_id?: string;
partner_id?: string;
status?: 'draft' | 'sent' | 'sale' | 'done' | 'cancelled';
invoice_status?: 'pending' | 'partial' | 'invoiced';
delivery_status?: 'pending' | 'partial' | 'delivered';
date_from?: string;
date_to?: string;
search?: string;
page?: number;
limit?: number;
}
3.5 Quotations DTOs
interface CreateQuotationDto {
company_id: string; // UUID, requerido
partner_id: string; // UUID, requerido
quotation_date?: string; // ISO date
validity_date: string; // ISO date, requerido
currency_id: string; // UUID, requerido
pricelist_id?: string; // UUID
sales_team_id?: string; // UUID
notes?: string;
terms_conditions?: string;
}
interface UpdateQuotationDto {
partner_id?: string;
quotation_date?: string;
validity_date?: string;
currency_id?: string;
pricelist_id?: string | null;
sales_team_id?: string | null;
notes?: string | null;
terms_conditions?: string | null;
}
interface CreateQuotationLineDto {
product_id?: string; // UUID
description: string; // Requerido
quantity: number; // > 0
uom_id: string; // UUID, requerido
price_unit: number; // >= 0
discount?: number; // 0-100, default: 0
tax_ids?: string[]; // UUID[]
}
interface UpdateQuotationLineDto {
description?: string;
quantity?: number;
uom_id?: string;
price_unit?: number;
discount?: number;
tax_ids?: string[];
}
interface QuotationFilters {
company_id?: string;
partner_id?: string;
status?: 'draft' | 'sent' | 'confirmed' | 'cancelled' | 'expired';
date_from?: string;
date_to?: string;
search?: string;
page?: number;
limit?: number;
}
4. ENDPOINTS
4.1 Customer Groups
| Metodo |
Endpoint |
Descripcion |
| GET |
/api/sales/customer-groups |
Listar grupos de clientes |
| GET |
/api/sales/customer-groups/:id |
Obtener grupo por ID |
| POST |
/api/sales/customer-groups |
Crear grupo de clientes |
| PATCH |
/api/sales/customer-groups/:id |
Actualizar grupo |
| DELETE |
/api/sales/customer-groups/:id |
Eliminar grupo |
| POST |
/api/sales/customer-groups/:id/members |
Agregar miembro |
| DELETE |
/api/sales/customer-groups/:id/members/:memberId |
Eliminar miembro |
4.2 Sales Teams
| Metodo |
Endpoint |
Descripcion |
| GET |
/api/sales/teams |
Listar equipos de ventas |
| GET |
/api/sales/teams/:id |
Obtener equipo por ID |
| POST |
/api/sales/teams |
Crear equipo de ventas |
| PATCH |
/api/sales/teams/:id |
Actualizar equipo |
| POST |
/api/sales/teams/:id/members |
Agregar miembro |
| DELETE |
/api/sales/teams/:id/members/:memberId |
Eliminar miembro |
4.3 Pricelists
| Metodo |
Endpoint |
Descripcion |
| GET |
/api/sales/pricelists |
Listar listas de precios |
| GET |
/api/sales/pricelists/:id |
Obtener lista por ID |
| POST |
/api/sales/pricelists |
Crear lista de precios |
| PATCH |
/api/sales/pricelists/:id |
Actualizar lista |
| POST |
/api/sales/pricelists/:id/items |
Agregar item |
| DELETE |
/api/sales/pricelists/:id/items/:itemId |
Eliminar item |
4.4 Sales Orders
| Metodo |
Endpoint |
Descripcion |
| GET |
/api/sales/orders |
Listar ordenes de venta |
| GET |
/api/sales/orders/:id |
Obtener orden por ID |
| POST |
/api/sales/orders |
Crear orden de venta |
| PATCH |
/api/sales/orders/:id |
Actualizar orden |
| DELETE |
/api/sales/orders/:id |
Eliminar orden |
| POST |
/api/sales/orders/:id/lines |
Agregar linea |
| PATCH |
/api/sales/orders/:id/lines/:lineId |
Actualizar linea |
| DELETE |
/api/sales/orders/:id/lines/:lineId |
Eliminar linea |
| POST |
/api/sales/orders/:id/confirm |
Confirmar orden |
| POST |
/api/sales/orders/:id/cancel |
Cancelar orden |
| POST |
/api/sales/orders/:id/invoice |
Crear factura |
4.5 Quotations
| Metodo |
Endpoint |
Descripcion |
| GET |
/api/sales/quotations |
Listar cotizaciones |
| GET |
/api/sales/quotations/:id |
Obtener cotizacion por ID |
| POST |
/api/sales/quotations |
Crear cotizacion |
| PATCH |
/api/sales/quotations/:id |
Actualizar cotizacion |
| DELETE |
/api/sales/quotations/:id |
Eliminar cotizacion |
| POST |
/api/sales/quotations/:id/lines |
Agregar linea |
| PATCH |
/api/sales/quotations/:id/lines/:lineId |
Actualizar linea |
| DELETE |
/api/sales/quotations/:id/lines/:lineId |
Eliminar linea |
| POST |
/api/sales/quotations/:id/send |
Enviar cotizacion |
| POST |
/api/sales/quotations/:id/confirm |
Confirmar y crear orden |
| POST |
/api/sales/quotations/:id/cancel |
Cancelar cotizacion |
5. TESTS
5.1 Estado de Tests
| Servicio |
Archivo |
Estado |
| CustomerGroupsService |
__tests__/customer-groups.service.spec.ts |
Implementado |
| SalesTeamsService |
__tests__/sales-teams.service.spec.ts |
Implementado |
| PricelistsService |
__tests__/pricelists.service.spec.ts |
Implementado |
| OrdersService |
__tests__/orders.service.spec.ts |
Implementado |
| QuotationsService |
__tests__/quotations.service.spec.ts |
Implementado |
5.2 Cobertura
Todos los servicios cuentan con tests unitarios que cubren:
- CRUD basico
- Validaciones de negocio
- Manejo de errores
- Flujos de estado (confirmar, cancelar, etc.)
6. DEPENDENCIAS
6.1 Modulos Internos
| Modulo |
Uso |
auth |
Usuarios, empresas, autenticacion |
core |
Partners, currencies, UoM, product_categories, sequences |
inventory |
Products |
financial |
Taxes (calculo impuestos), invoices, payment_terms, analytic_accounts |
6.2 Servicios Externos
| Servicio |
Uso |
taxesService |
Calculo de impuestos en lineas de orden/cotizacion |
sequencesService |
Generacion de numeros de secuencia (SO-XXXXXX) |
emailService |
Envio de cotizaciones por email |
6.3 Dependencias de Base de Datos
sales.customer_groups
└── core.partners (via customer_group_members)
sales.sales_teams
├── auth.companies
└── auth.users (team_leader, members)
sales.pricelists
├── auth.companies
├── core.currencies
├── inventory.products (items)
└── core.product_categories (items)
sales.sales_orders
├── auth.companies
├── core.partners
├── core.currencies
├── sales.pricelists
├── sales.sales_teams
├── auth.users
├── financial.payment_terms
├── inventory.products (lines)
├── core.uom (lines)
└── financial.taxes (lines)
sales.quotations
├── (mismas dependencias que sales_orders)
└── sales.sales_orders (sale_order_id)
7. FLUJOS DE NEGOCIO
7.1 Flujo de Cotizacion
draft -> sent -> confirmed -> [crea sales_order]
-> cancelled
-> expired
7.2 Flujo de Orden de Venta
draft -> sent -> sale -> done
-> cancelled
invoice_status: pending -> partial -> invoiced
delivery_status: pending -> partial -> delivered
7.3 Reglas de Negocio
- Ordenes/Cotizaciones: Solo se pueden editar/eliminar en estado
draft
- Grupos de clientes: No se pueden eliminar si tienen miembros
- Equipos de ventas: Codigo unico por empresa
- Listas de precios: Nombre unico por tenant
- Facturacion: Segun
invoice_policy (order: al confirmar, delivery: al entregar)
- Impuestos: Calculados automaticamente usando
taxesService
8. VALIDACIONES
8.1 Validaciones con Zod
Todas las validaciones de entrada se realizan usando Zod en el controlador:
- Tipos de datos
- Campos requeridos
- Rangos (min, max)
- Formatos (UUID, email, fechas)
- Valores permitidos (enums)
8.2 Validaciones de Negocio
Las validaciones de negocio se realizan en los servicios:
- Unicidad de nombres/codigos
- Estados validos para operaciones
- Existencia de entidades relacionadas
- Restricciones de eliminacion