Reorganiza repo como fuente de la verdad + propuesta v1.0 con emisión de facturas
- Estructura nueva: README maestro, bitacora/ (REGISTRO, PENDIENTES, plantillas), propuesta/, fuentes/; material superado a _archivado/ - Propuesta v1.0: MVP BIND-first con emisión asistida MXN/USD (dry-run + confirmación, timbra PAC de BIND), 112-136 h / $67,200-$81,600 + IVA, stack .NET 10 + EF Core + Angular 21 + PostgreSQL 17 sobre Azure - Bitácora: historial de correos + 2 llamadas (incl. revisión 4-jun) y pendientes - Prototipo y diagrama actualizados a v1.0; precios de Azure verificados - Archivo ajeno (proyecto EOS) retirado del repo Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,261 @@
|
||||
/**
|
||||
* Datos sintéticos que imitan lo que BIND devolvería para una cuenta
|
||||
* del tamaño de Balam (45 colaboradores + 5 freelancers, ~50 facturas/mes).
|
||||
*
|
||||
* Nada de esto es información real de Balam. Solo cumple con la *forma*
|
||||
* del payload para que el cliente y los handlers se validen.
|
||||
*/
|
||||
|
||||
import type {
|
||||
Activity,
|
||||
Customer,
|
||||
Invoice,
|
||||
InvoiceLine,
|
||||
Payment,
|
||||
Product,
|
||||
} from "../../client/types.js";
|
||||
|
||||
export const customers: Customer[] = [
|
||||
{
|
||||
ID: "11111111-1111-1111-1111-111111111111",
|
||||
Code: "ACU-001",
|
||||
Name: "Acuntia México SA de CV",
|
||||
TaxId: "ACU010203AB1",
|
||||
Country: "MX",
|
||||
Email: "facturacion@acuntia.example",
|
||||
Currency: "MXN",
|
||||
PaymentTerms: 30,
|
||||
IsActive: true,
|
||||
CreatedAt: "2024-01-15T10:00:00Z",
|
||||
UpdatedAt: "2026-04-01T10:00:00Z",
|
||||
},
|
||||
{
|
||||
ID: "22222222-2222-2222-2222-222222222222",
|
||||
Code: "CLI-002",
|
||||
Name: "TechMex Innovaciones SAPI",
|
||||
TaxId: "TMI150301CD2",
|
||||
Country: "MX",
|
||||
Email: "ap@techmex.example",
|
||||
Currency: "MXN",
|
||||
PaymentTerms: 45,
|
||||
IsActive: true,
|
||||
CreatedAt: "2024-03-20T10:00:00Z",
|
||||
UpdatedAt: "2026-04-15T10:00:00Z",
|
||||
},
|
||||
{
|
||||
ID: "33333333-3333-3333-3333-333333333333",
|
||||
Code: "CLI-003",
|
||||
Name: "Norteamericana Logistics LLC",
|
||||
TaxId: "98-7654321",
|
||||
Country: "US",
|
||||
Email: "billing@norteam.example",
|
||||
Currency: "USD",
|
||||
PaymentTerms: 60,
|
||||
IsActive: true,
|
||||
CreatedAt: "2025-02-10T10:00:00Z",
|
||||
UpdatedAt: "2026-05-01T10:00:00Z",
|
||||
},
|
||||
{
|
||||
ID: "44444444-4444-4444-4444-444444444444",
|
||||
Code: "CLI-004",
|
||||
Name: "Distribuidora del Golfo SA",
|
||||
TaxId: "DGO180815EF3",
|
||||
Country: "MX",
|
||||
Email: "pagos@dgolfo.example",
|
||||
Currency: "MXN",
|
||||
PaymentTerms: 30,
|
||||
IsActive: true,
|
||||
CreatedAt: "2025-06-01T10:00:00Z",
|
||||
UpdatedAt: "2026-05-10T10:00:00Z",
|
||||
},
|
||||
{
|
||||
ID: "55555555-5555-5555-5555-555555555555",
|
||||
Code: "CLI-005",
|
||||
Name: "Servicios Estratégicos del Norte",
|
||||
TaxId: "SEN200401GH4",
|
||||
Country: "MX",
|
||||
Email: "tesoreria@sen.example",
|
||||
Currency: "MXN",
|
||||
PaymentTerms: 15,
|
||||
IsActive: false,
|
||||
CreatedAt: "2025-08-12T10:00:00Z",
|
||||
UpdatedAt: "2026-03-22T10:00:00Z",
|
||||
},
|
||||
];
|
||||
|
||||
export const products: Product[] = [
|
||||
{
|
||||
ID: "a1111111-1111-1111-1111-111111111111",
|
||||
Code: "SVC-CONSULT",
|
||||
Name: "Consultoría estratégica · hora",
|
||||
UnitPrice: 1800,
|
||||
Currency: "MXN",
|
||||
SatCode: "80101504",
|
||||
IsActive: true,
|
||||
},
|
||||
{
|
||||
ID: "a2222222-2222-2222-2222-222222222222",
|
||||
Code: "SVC-RECRUIT",
|
||||
Name: "Búsqueda de talento ejecutivo",
|
||||
UnitPrice: 45000,
|
||||
Currency: "MXN",
|
||||
SatCode: "80111501",
|
||||
IsActive: true,
|
||||
},
|
||||
];
|
||||
|
||||
function line(product: Product, qty: number, taxRate: number): InvoiceLine {
|
||||
const subtotal = round2(qty * product.UnitPrice);
|
||||
const total = round2(subtotal * (1 + taxRate));
|
||||
return {
|
||||
ProductID: product.ID,
|
||||
Description: product.Name,
|
||||
Quantity: qty,
|
||||
UnitPrice: product.UnitPrice,
|
||||
TaxRate: taxRate,
|
||||
Subtotal: subtotal,
|
||||
Total: total,
|
||||
};
|
||||
}
|
||||
|
||||
export const invoices: Invoice[] = [
|
||||
// 1) Pagada
|
||||
{
|
||||
ID: "f0000001-0000-0000-0000-000000000001",
|
||||
Folio: "0001",
|
||||
Serie: "A",
|
||||
UUID: "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAA0001",
|
||||
CustomerID: customers[1]!.ID,
|
||||
IssueDate: "2026-03-01T10:00:00Z",
|
||||
DueDate: "2026-04-15T10:00:00Z",
|
||||
Currency: "MXN",
|
||||
ExchangeRate: null,
|
||||
Subtotal: 90000,
|
||||
Taxes: 14400,
|
||||
Total: 104400,
|
||||
Balance: 0,
|
||||
Status: "paid",
|
||||
Lines: [line(products[1]!, 2, 0.16)],
|
||||
XmlUrl: "https://api.bind.com.mx/api/Invoices/f0000001/xml",
|
||||
PdfUrl: "https://api.bind.com.mx/api/Invoices/f0000001/pdf",
|
||||
},
|
||||
// 2) Vigente
|
||||
{
|
||||
ID: "f0000002-0000-0000-0000-000000000002",
|
||||
Folio: "0002",
|
||||
Serie: "A",
|
||||
UUID: "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAA0002",
|
||||
CustomerID: customers[3]!.ID,
|
||||
IssueDate: "2026-05-10T10:00:00Z",
|
||||
DueDate: "2026-06-09T10:00:00Z",
|
||||
Currency: "MXN",
|
||||
ExchangeRate: null,
|
||||
Subtotal: 36000,
|
||||
Taxes: 5760,
|
||||
Total: 41760,
|
||||
Balance: 41760,
|
||||
Status: "issued",
|
||||
Lines: [line(products[0]!, 20, 0.16)],
|
||||
XmlUrl: null,
|
||||
PdfUrl: null,
|
||||
},
|
||||
// 3) Vencida — caso cobranza
|
||||
{
|
||||
ID: "f0000003-0000-0000-0000-000000000003",
|
||||
Folio: "0003",
|
||||
Serie: "A",
|
||||
UUID: "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAA0003",
|
||||
CustomerID: customers[1]!.ID,
|
||||
IssueDate: "2026-02-15T10:00:00Z",
|
||||
DueDate: "2026-04-01T10:00:00Z",
|
||||
Currency: "MXN",
|
||||
ExchangeRate: null,
|
||||
Subtotal: 18000,
|
||||
Taxes: 2880,
|
||||
Total: 20880,
|
||||
Balance: 20880,
|
||||
Status: "overdue",
|
||||
Lines: [line(products[0]!, 10, 0.16)],
|
||||
XmlUrl: null,
|
||||
PdfUrl: null,
|
||||
},
|
||||
// 4) USD a cliente Texas — sin IVA (exportación)
|
||||
{
|
||||
ID: "f0000004-0000-0000-0000-000000000004",
|
||||
Folio: "0004",
|
||||
Serie: "A",
|
||||
UUID: "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAA0004",
|
||||
CustomerID: customers[2]!.ID,
|
||||
IssueDate: "2026-05-20T10:00:00Z",
|
||||
DueDate: "2026-07-19T10:00:00Z",
|
||||
Currency: "USD",
|
||||
ExchangeRate: 17.85,
|
||||
Subtotal: 12500,
|
||||
Taxes: 0,
|
||||
Total: 12500,
|
||||
Balance: 12500,
|
||||
Status: "issued",
|
||||
Lines: [
|
||||
{
|
||||
ProductID: products[1]!.ID,
|
||||
Description: products[1]!.Name,
|
||||
Quantity: 1,
|
||||
UnitPrice: 12500,
|
||||
TaxRate: 0,
|
||||
Subtotal: 12500,
|
||||
Total: 12500,
|
||||
},
|
||||
],
|
||||
XmlUrl: null,
|
||||
PdfUrl: null,
|
||||
},
|
||||
// 5) Cliente estratégico — ACUNTIA (no debe recibir recordatorio auto)
|
||||
{
|
||||
ID: "f0000005-0000-0000-0000-000000000005",
|
||||
Folio: "0005",
|
||||
Serie: "A",
|
||||
UUID: "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAA0005",
|
||||
CustomerID: customers[0]!.ID,
|
||||
IssueDate: "2026-04-20T10:00:00Z",
|
||||
DueDate: "2026-05-20T10:00:00Z",
|
||||
Currency: "MXN",
|
||||
ExchangeRate: null,
|
||||
Subtotal: 54000,
|
||||
Taxes: 8640,
|
||||
Total: 62640,
|
||||
Balance: 62640,
|
||||
Status: "overdue",
|
||||
Lines: [line(products[0]!, 30, 0.16)],
|
||||
XmlUrl: null,
|
||||
PdfUrl: null,
|
||||
},
|
||||
];
|
||||
|
||||
export const payments: Payment[] = [
|
||||
{
|
||||
ID: "p0000001-0000-0000-0000-000000000001",
|
||||
InvoiceID: invoices[0]!.ID,
|
||||
PaymentDate: "2026-04-10T10:00:00Z",
|
||||
Amount: 104400,
|
||||
Currency: "MXN",
|
||||
Method: "transfer",
|
||||
Reference: "SPEI 7XX9-2026-04-10",
|
||||
},
|
||||
];
|
||||
|
||||
export const activities: Activity[] = [
|
||||
{
|
||||
ID: "ac000001-0000-0000-0000-000000000001",
|
||||
CustomerID: customers[1]!.ID,
|
||||
InvoiceID: invoices[2]!.ID,
|
||||
Type: "reminder",
|
||||
Subject: "Recordatorio enviado a TechMex (vencida 30 días)",
|
||||
Notes: "Plantilla cobranza-vencida-30d",
|
||||
CreatedAt: "2026-04-05T16:00:00Z",
|
||||
CreatedBy: "balam-collections-bot",
|
||||
},
|
||||
];
|
||||
|
||||
function round2(n: number): number {
|
||||
return Math.round(n * 100) / 100;
|
||||
}
|
||||
Reference in New Issue
Block a user