erp-retail/orchestration/planes/fase-2-analisis-modulos/ANALISIS-RT-009-ecommerce.md

14 KiB

ANALISIS MODULO RT-009: E-COMMERCE

Fecha: 2025-12-18 Fase: 2 - Analisis por Modulo Modulo: RT-009 E-commerce Herencia: 20% Story Points: 55 Prioridad: P2


1. DESCRIPCION GENERAL

1.1 Proposito

Tienda online integrada con inventario, carrito de compras, checkout, pasarelas de pago y opciones de entrega.

1.2 Funcionalidades Principales

Funcionalidad Descripcion Criticidad
Catalogo online Navegacion y busqueda Alta
Carrito Persistente Alta
Checkout Flujo completo Critica
Pagos Multiples pasarelas Critica
Envio Multiples opciones Alta
Pedidos Gestion backoffice Alta

2. HERENCIA DEL CORE

2.1 Componentes Heredados (20%)

Componente Core % Uso Accion
inventory.products 100% HEREDAR
sales.pricelists 100% HEREDAR
core.partners 100% HEREDAR

2.2 Servicios a Heredar

import { ProductsService } from '@erp-core/inventory';
import { PricelistsService } from '@erp-core/sales';
import { PartnersService } from '@erp-core/core';

3. COMPONENTES NUEVOS

3.1 Entidades (TypeORM)

// 1. EcommerceOrder - Pedido online
@Entity('ecommerce_orders', { schema: 'retail' })
export class EcommerceOrder {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column('uuid')
  tenantId: string;

  @Column()
  orderNumber: string;

  @ManyToOne(() => Partner)
  customer: Partner;

  @Column({ type: 'enum', enum: EcommerceOrderStatus })
  status: EcommerceOrderStatus;
  // pending, paid, preparing, shipped, ready_pickup, delivered, cancelled

  @Column({ type: 'timestamptz' })
  orderDate: Date;

  // Totales
  @Column({ type: 'decimal', precision: 12, scale: 2 })
  subtotal: number;

  @Column({ type: 'decimal', precision: 12, scale: 2, default: 0 })
  discountAmount: number;

  @Column({ type: 'decimal', precision: 12, scale: 2 })
  shippingCost: number;

  @Column({ type: 'decimal', precision: 12, scale: 2 })
  taxAmount: number;

  @Column({ type: 'decimal', precision: 12, scale: 2 })
  total: number;

  // Pago
  @Column({ type: 'enum', enum: PaymentStatus })
  paymentStatus: PaymentStatus;

  @Column({ nullable: true })
  paymentMethod: string;

  @Column({ nullable: true })
  paymentReference: string;

  // Entrega
  @Column({ type: 'enum', enum: DeliveryMethod })
  deliveryMethod: DeliveryMethod;  // shipping, pickup

  @ManyToOne(() => Branch, { nullable: true })
  pickupBranch: Branch;  // Si es pickup

  @Column({ type: 'jsonb', nullable: true })
  shippingAddress: Address;

  @Column({ nullable: true })
  trackingNumber: string;

  @OneToMany(() => EcommerceOrderLine, line => line.order)
  lines: EcommerceOrderLine[];

  @Column({ nullable: true })
  notes: string;
}

// 2. EcommerceOrderLine
@Entity('ecommerce_order_lines', { schema: 'retail' })
export class EcommerceOrderLine {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @ManyToOne(() => EcommerceOrder)
  order: EcommerceOrder;

  @ManyToOne(() => Product)
  product: Product;

  @Column()
  productName: string;

  @Column({ type: 'decimal', precision: 12, scale: 4 })
  quantity: number;

  @Column({ type: 'decimal', precision: 12, scale: 2 })
  unitPrice: number;

  @Column({ type: 'decimal', precision: 12, scale: 2 })
  total: number;
}

// 3. Cart - Carrito (session-based)
@Entity('carts', { schema: 'retail' })
export class Cart {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column('uuid')
  tenantId: string;

  @ManyToOne(() => Partner, { nullable: true })
  customer: Partner;  // null si guest

  @Column({ nullable: true })
  sessionId: string;  // Para guests

  @OneToMany(() => CartItem, item => item.cart)
  items: CartItem[];

  @Column({ type: 'decimal', precision: 12, scale: 2, default: 0 })
  subtotal: number;

  @Column({ type: 'timestamptz' })
  createdAt: Date;

  @Column({ type: 'timestamptz' })
  updatedAt: Date;

  @Column({ type: 'timestamptz', nullable: true })
  expiresAt: Date;
}

// 4. CartItem
@Entity('cart_items', { schema: 'retail' })
export class CartItem {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @ManyToOne(() => Cart)
  cart: Cart;

  @ManyToOne(() => Product)
  product: Product;

  @Column({ type: 'decimal', precision: 12, scale: 4 })
  quantity: number;

  @Column({ type: 'decimal', precision: 12, scale: 2 })
  unitPrice: number;

  @Column({ type: 'decimal', precision: 12, scale: 2 })
  total: number;
}

// 5. ShippingRate
@Entity('shipping_rates', { schema: 'retail' })
export class ShippingRate {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column('uuid')
  tenantId: string;

  @Column()
  name: string;  // "Envio estandar", "Express"

  @Column()
  carrier: string;  // "Fedex", "DHL", "Estafeta"

  @Column({ type: 'decimal', precision: 12, scale: 2 })
  baseRate: number;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  freeShippingMinimum: number;

  @Column({ type: 'int', nullable: true })
  estimatedDays: number;

  @Column({ type: 'boolean', default: true })
  isActive: boolean;
}

3.2 Servicios Backend

Servicio Metodos Principales
CatalogService search(), getByCategory(), getProduct()
CartService create(), addItem(), updateItem(), removeItem(), clear()
CheckoutService validate(), calculateTotals(), processPayment()
PaymentGatewayService createPayment(), capture(), refund()
ShippingService calculateRates(), createShipment(), track()
EcommerceOrderService create(), updateStatus(), getByCustomer()

3.3 Controladores

// API Publica (Storefront)
@Controller('store')
export class StorefrontController {
  // Catalogo
  @Get('products')
  getProducts(@Query() filters: CatalogFilters): Promise<PaginatedProducts>;

  @Get('products/:id')
  getProduct(@Param('id') id: string): Promise<ProductDetail>;

  @Get('products/search')
  searchProducts(@Query('q') query: string): Promise<Product[]>;

  @Get('categories')
  getCategories(): Promise<Category[]>;

  // Carrito
  @Get('cart')
  getCart(): Promise<Cart>;

  @Post('cart/items')
  addToCart(@Body() dto: AddToCartDto): Promise<Cart>;

  @Put('cart/items/:id')
  updateCartItem(@Param('id') id: string, @Body() dto: UpdateCartDto): Promise<Cart>;

  @Delete('cart/items/:id')
  removeFromCart(@Param('id') id: string): Promise<Cart>;

  // Checkout
  @Post('checkout/validate')
  validateCheckout(@Body() dto: CheckoutDto): Promise<CheckoutValidation>;

  @Get('checkout/shipping-rates')
  getShippingRates(@Query() dto: ShippingQuery): Promise<ShippingRate[]>;

  @Post('checkout/complete')
  completeCheckout(@Body() dto: CompleteCheckoutDto): Promise<EcommerceOrder>;

  // Pagos
  @Post('payments/create')
  createPayment(@Body() dto: PaymentDto): Promise<PaymentIntent>;

  @Post('payments/webhook')
  handleWebhook(@Body() payload: any): Promise<void>;

  // Pedidos (autenticado)
  @Get('orders')
  @UseGuards(AuthGuard)
  getMyOrders(): Promise<EcommerceOrder[]>;

  @Get('orders/:id')
  @UseGuards(AuthGuard)
  getOrder(@Param('id') id: string): Promise<EcommerceOrder>;
}

// API Backoffice
@Controller('ecommerce')
export class EcommerceController {
  // Gestion de pedidos
  @Get('orders')
  getOrders(@Query() filters: OrderFilters): Promise<PaginatedOrders>;

  @Put('orders/:id/status')
  updateStatus(@Param('id') id: string, @Body() dto: StatusDto): Promise<EcommerceOrder>;

  @Post('orders/:id/ship')
  markAsShipped(@Param('id') id: string, @Body() dto: ShipDto): Promise<EcommerceOrder>;

  // Configuracion
  @Get('shipping-rates')
  getShippingRates(): Promise<ShippingRate[]>;

  @Post('shipping-rates')
  createShippingRate(@Body() dto: CreateRateDto): Promise<ShippingRate>;
}

4. INTEGRACIONES EXTERNAS

4.1 Pasarelas de Pago

interface PaymentGateway {
  name: string;
  createPayment(order: EcommerceOrder): Promise<PaymentIntent>;
  capturePayment(paymentId: string): Promise<PaymentResult>;
  refund(paymentId: string, amount: number): Promise<RefundResult>;
}

// Implementaciones
class StripeGateway implements PaymentGateway { ... }
class ConektaGateway implements PaymentGateway { ... }
class MercadoPagoGateway implements PaymentGateway { ... }

4.2 Proveedores de Envio

interface ShippingProvider {
  name: string;
  calculateRate(origin: Address, destination: Address, weight: number): Promise<ShippingQuote>;
  createShipment(order: EcommerceOrder): Promise<Shipment>;
  getTracking(trackingNumber: string): Promise<TrackingInfo>;
}

// Implementaciones
class FedexProvider implements ShippingProvider { ... }
class DHLProvider implements ShippingProvider { ... }
class EstafetaProvider implements ShippingProvider { ... }

5. FLUJOS DE NEGOCIO

5.1 Flujo de Compra

1. Cliente navega catalogo
      ↓
2. Agrega productos al carrito
      ↓
3. Revisa carrito
      ↓
4. Inicia checkout
      ↓
5. Login/registro (o guest)
      ↓
6. Selecciona direccion de envio
      ↓
7. Selecciona metodo de envio
      ↓
8. Ve resumen con totales
      ↓
9. Selecciona metodo de pago
      ↓
10. Procesa pago
      ↓
11. Confirmacion de pedido
      ↓
12. Email de confirmacion

5.2 Flujo de Gestion de Pedido

1. Pedido creado (PENDING)
      ↓
2. Pago confirmado (PAID)
      ↓
3. Preparando (PREPARING)
   - Reservar stock
   - Imprimir etiqueta
      ↓
4. Enviado (SHIPPED) o Listo para recoger (READY_PICKUP)
   - Tracking disponible
      ↓
5. Entregado (DELIVERED)
      ↓
6. Fin (o cancelado en cualquier punto)

6. TABLAS DDL

6.1 Tablas Nuevas

-- Pedidos
CREATE TABLE retail.ecommerce_orders (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
  order_number VARCHAR(20) NOT NULL,
  customer_id UUID NOT NULL REFERENCES core.partners(id),
  status VARCHAR(20) NOT NULL DEFAULT 'pending',
  order_date TIMESTAMPTZ NOT NULL DEFAULT NOW(),

  subtotal DECIMAL(12,2) NOT NULL,
  discount_amount DECIMAL(12,2) DEFAULT 0,
  shipping_cost DECIMAL(12,2) NOT NULL DEFAULT 0,
  tax_amount DECIMAL(12,2) NOT NULL DEFAULT 0,
  total DECIMAL(12,2) NOT NULL,

  payment_status VARCHAR(20),
  payment_method VARCHAR(50),
  payment_reference VARCHAR(100),

  delivery_method VARCHAR(20) NOT NULL,
  pickup_branch_id UUID REFERENCES retail.branches(id),
  shipping_address JSONB,
  tracking_number VARCHAR(50),

  notes TEXT,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ,

  UNIQUE(tenant_id, order_number)
);

-- Lineas
CREATE TABLE retail.ecommerce_order_lines (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
  order_id UUID NOT NULL REFERENCES retail.ecommerce_orders(id) ON DELETE CASCADE,
  product_id UUID NOT NULL REFERENCES inventory.products(id),
  product_name VARCHAR(255) NOT NULL,
  quantity DECIMAL(12,4) NOT NULL,
  unit_price DECIMAL(12,2) NOT NULL,
  total DECIMAL(12,2) NOT NULL
);

-- Carritos
CREATE TABLE retail.carts (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
  customer_id UUID REFERENCES core.partners(id),
  session_id VARCHAR(100),
  subtotal DECIMAL(12,2) DEFAULT 0,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ,
  expires_at TIMESTAMPTZ
);

CREATE TABLE retail.cart_items (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
  cart_id UUID NOT NULL REFERENCES retail.carts(id) ON DELETE CASCADE,
  product_id UUID NOT NULL REFERENCES inventory.products(id),
  quantity DECIMAL(12,4) NOT NULL,
  unit_price DECIMAL(12,2) NOT NULL,
  total DECIMAL(12,2) NOT NULL
);

-- Tarifas de envio
CREATE TABLE retail.shipping_rates (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
  name VARCHAR(100) NOT NULL,
  carrier VARCHAR(50) NOT NULL,
  base_rate DECIMAL(12,2) NOT NULL,
  free_shipping_minimum DECIMAL(12,2),
  estimated_days INT,
  is_active BOOLEAN DEFAULT TRUE,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

7. DEPENDENCIAS

7.1 Dependencias de Retail

Modulo Tipo
RT-001 Fundamentos Prerequisito
RT-003 Inventario Stock
RT-005 Clientes Clientes y puntos
RT-006 Precios Precios online

7.2 Dependencias Externas

Servicio Proposito
Stripe/Conekta Pagos
Fedex/DHL Envios
SendGrid Emails

7.3 Bloquea a

Modulo Razon
RT-010 Facturacion Facturas de pedidos

8. CRITERIOS DE ACEPTACION

8.1 Storefront

  • Navegar catalogo
  • Buscar productos
  • Ver detalle de producto
  • Stock en tiempo real
  • Agregar al carrito
  • Carrito persistente
  • Checkout como guest o registrado
  • Multiples metodos de pago
  • Envio o pickup
  • Confirmacion por email

8.2 Backoffice

  • Ver pedidos
  • Actualizar estado
  • Generar etiqueta envio
  • Registrar tracking
  • Cancelar pedido

9. ESTIMACION DETALLADA

Componente SP Backend SP Frontend Total
Entities + Migrations 5 - 5
CatalogService 3 - 3
CartService 5 - 5
CheckoutService 5 - 5
PaymentGatewayService 8 - 8
ShippingService 5 - 5
OrderService 5 - 5
Storefront UI - 13 13
Backoffice UI - 6 6
TOTAL 36 19 55

Estado: ANALISIS COMPLETO Bloqueado por: RT-001, RT-003, RT-005, RT-006