Files
plantillas-proyectos/frontend/src/lib/api/dashboard/a76/invoices.ts
AlexeerCT fbb24f2cd3 Refactor invoice financials to change iva_factor type from string to numeric
- Updated the `iva_factor` field in the `InvoiceFinancials` model to use a numeric type with precision and scale.
- Adjusted related frontend components and API interfaces to reflect the new numeric type for `iva_factor`.
- Enhanced Alembic migration scripts to accommodate the schema changes, ensuring proper index management and data type conversions.

These changes improve data integrity and consistency for financial calculations in invoices.
2026-03-23 09:48:33 -05:00

545 lines
16 KiB
TypeScript

/**
* API Client para Facturas (Invoices)
* Gestiona las operaciones CRUD para facturas y sus relaciones
*/
import { api } from '$lib/api';
export type OperationType = 'imp' | 'exp';
export type TransportType = 'none' | 'transport' | 'box' | 'licence plates' | 'truck' | 'vessel' | 'rail barge' | 'container' | 'airplane' | 'gondola' | 'flatbed';
// --- Interfaces ---
export interface InvoiceComplianceMx {
invoice_id?: number;
pedimento_id?: number | null;
pedimento_r1?: number | null;
pedimento_k1?: number | null;
remesa?: number | null;
// Pedimento relationship data (when joined)
pedimento?: {
pedimento_number?: string;
pedimento_code?: string;
customs_office?: string;
license?: string;
year?: string;
} | null;
aduana?: string | null;
port_of_entry?: string | null;
destination?: string | null;
manifest_number?: string | null;
provider_header?: string | null;
provider_id?: number | null;
sold_to_header?: string | null;
sold_to_id?: number | null;
shipped_to_header?: string | null;
shipped_to_id?: number | null;
shipped_by_header?: string | null;
shipped_by_id?: number | null;
customs_broker_id?: number | null;
customs_broker_us_id?: number | null;
broker_invoice_num?: string | null;
broker_invoice_date?: string | null;
is_mixed?: boolean | null;
waste_type?: string | null;
scrap_type?: string | null;
appendix_17?: number | null;
is_regime_change?: boolean | null;
which_exchange_rate?: string | null;
value_method?: string | null;
act_value?: string | null;
is_pedimento_pending?: boolean | null;
is_owner_of_goods?: string | null;
generate_balances?: string | null;
was_reviewed_by_company?: boolean | null;
edocument?: string | null;
code_signature?: string | null;
electronic_signature?: string | null;
certificate_number?: string | null;
niu_number?: string | null;
bill_of_lading_count?: string | null;
addendum_vu?: string | null;
origin_destination_cove?: string | null;
vucem_operation_num?: string | null;
customs_person_line?: number | null;
contingency_mode?: boolean | null;
enclosure?: string | null;
guide_type_to_identify?: string | null;
location?: string | null;
dot_code?: string | null;
subdivision?: string | null;
acts_as?: string | null;
movement_type?: string | null;
office_document?: string | null;
reason_export?: string | null;
signature_key?: string | null;
sem_id?: number | null;
rule_3121_parties_ii?: boolean | null;
}
export interface InvoiceFinancials {
id?: number;
invoice_id?: number;
currency?: string | null;
currency_type?: string | null;
exchange_rate?: number | null;
exchange_rate_mm?: number | null;
value_mn?: number | null;
value_me?: number | null;
value_mc?: number | null;
customs_value_mn?: number | null;
customs_value_me?: number | null;
raw_material_value_mn?: number | null;
raw_material_value_me?: number | null;
aggregate_value_mn?: number | null;
aggregate_value_me?: number | null;
aggregate_value_mc?: number | null;
mexican_value_mn?: number | null;
mexican_value_me?: number | null;
mexican_value_mc?: number | null;
national_packaging_mn?: number | null;
national_packaging_me?: number | null;
national_packaging_mc?: number | null;
freight?: number | null;
insurance?: number | null;
insurance_value?: number | null;
packaging?: number | null;
other_increments?: number | null;
other_deductibles?: number | null;
total_increments_mn?: number | null;
total_increments_me?: number | null;
iva_mn?: number | null;
iva_me?: number | null;
iva_mc?: number | null;
iva_factor?: number | null;
tax_value_me?: number | null;
seal_value_2500?: boolean | null;
total_quantity?: number | null;
gross_weight?: number | null;
net_weight?: number | null;
bundle_count?: number | null;
weight_factor?: number | null;
}
export interface InvoiceLogistics {
id?: number;
invoice_id?: number;
carrier_id?: string | null;
transport_id?: string | null;
transport_us_id?: string | null;
transport_type?: TransportType | null;
transport_num?: string | null;
transport_mode?: string | null;
driver_name?: string | null;
is_rail?: string | null;
rail_id?: string | null;
vehicle_num?: string | null;
license_plate?: string | null;
license_plate_complete?: string | null;
trailer_num?: string | null;
seal_number?: string | null;
guide_number?: string | null;
bill_number?: string | null;
reference_number?: string | null;
shipment_number?: string | null;
incoterm?: string | null;
identifier_1?: string | null;
complement_1?: string | null;
identifier_2?: string | null;
complement_2?: string | null;
weight_type?: string | null;
container_types?: string | null;
vehicle_data?: string | null;
origin_location?: string | null;
destination_location?: string | null;
transport_itinerary?: string | null;
destination_goods?: string | null;
entry_exit_date?: string | null;
delivery_date?: string | null;
delivered_status?: string | null;
received_by?: string | null;
payment_date?: string | null;
payment_receipt_num?: string | null;
is_ctm_process?: string | null;
is_subdivision?: boolean | null;
acts_as_cd?: boolean | null;
equipment_reviewed?: boolean | null;
pedimento_arrived?: boolean | null;
green_light_mx?: boolean | null;
green_light_us?: boolean | null;
red_light_mx?: boolean | null;
red_light_us?: boolean | null;
}
export interface InvoiceSalesDetails {
id?: number;
invoice_id?: number;
line_number: number;
sales_order?: string | null;
colors_description?: string | null;
square_color_code?: string | null;
line_bundles?: number | null;
}
export interface InvoiceCollections {
id?: number;
invoice_id?: number;
concept?: string | null;
is_collected?: number | null;
collection_date?: string | null;
amount?: number | null;
collector_user?: string | null;
}
export interface Invoice {
id: number;
tenant_id: number;
company_id: number;
system?: string | null;
operation_type?: OperationType | null;
invoice_type?: string | null;
document_type?: string | null;
invoice_number?: string | null;
project_number?: string | null;
purchase_order?: string | null;
related_doc_id?: number | null;
alternate_invoice?: string | null;
invoice_ref?: string | null;
proforma_number?: string | null;
invoice_date?: string | null;
capture_date: string;
emission_date?: string | null;
status?: "pending" | "processed" | "reversed" | boolean | null;
processed_date?: string | null;
who_processed?: string | null;
capture_user?: string | null;
traffic_light_status?: string | null;
process_log?: string | null;
status_rec?: number | null;
status_rep?: string | null;
observation_es?: string | null;
observation_en?: string | null;
comments_status?: string | null;
vu_observations?: string | null;
cfdi_uuid?: string | null;
path_pdf?: string | null;
path_xml?: string | null;
subcompany?: string | null;
party_count?: number | null;
generate_id?: boolean | null;
generate_desc_parties?: string | null;
apply_manual_discount?: boolean | null;
is_bulk?: boolean | null;
download_substance?: boolean | null;
download_class?: boolean | null;
download_def?: boolean | null;
total_items?: number | null;
payment_terms?: string | null;
handling_fees?: number | null;
option_iv18?: string | null;
enajenation_goods?: boolean | null;
compliance_mx?: InvoiceComplianceMx | null;
financials?: InvoiceFinancials | null;
logistics?: InvoiceLogistics | null;
details?: InvoiceSalesDetails[];
collections?: InvoiceCollections[];
// Client-side only properties
is_selected?: boolean;
}
export interface InvoiceListResponse {
items: Invoice[];
total: number;
page: number;
page_size: number;
}
export interface CreateInvoiceData {
system: string;
operation_type: OperationType;
invoice_type: string;
document_type: string;
invoice_number: string;
project_number?: string | null;
purchase_order?: string | null;
related_doc_id?: number | null;
alternate_invoice?: string | null;
invoice_ref?: string | null;
proforma_number?: string | null;
invoice_date?: string | null;
emission_date?: string | null;
status?: "pending" | "processed" | "reversed" | boolean | null;
processed_date?: string | null;
who_processed?: string | null;
capture_user?: string | null;
traffic_light_status?: string | null;
process_log?: string | null;
status_rec?: number | null;
status_rep?: string | null;
observation_es?: string | null;
observation_en?: string | null;
comments_status?: string | null;
vu_observations?: string | null;
cfdi_uuid?: string | null;
path_pdf?: string | null;
path_xml?: string | null;
subcompany?: string | null;
party_count?: number | null;
generate_id?: boolean | null;
generate_desc_parties?: string | null;
apply_manual_discount?: boolean | null;
is_bulk?: boolean | null;
download_substance?: boolean | null;
download_class?: boolean | null;
download_def?: boolean | null;
payment_terms?: string | null;
handling_fees?: number | null;
option_iv18?: string | null;
enajenation_goods?: boolean | null;
compliance_mx?: Omit<InvoiceComplianceMx, 'invoice_id'> | null;
financials?: Omit<InvoiceFinancials, 'id' | 'invoice_id'> | null;
logistics?: Omit<InvoiceLogistics, 'id' | 'invoice_id'> | null;
details?: Omit<InvoiceSalesDetails, 'id' | 'invoice_id'>[] | null;
collections?: Omit<InvoiceCollections, 'id' | 'invoice_id'>[] | null;
}
export interface UpdateInvoiceData {
id: number; // Required by backend
operation_type?: OperationType | null;
invoice_type?: string | null;
document_type?: string | null;
invoice_number?: string | null;
project_number?: string | null;
purchase_order?: string | null;
related_doc_id?: number | null;
invoice_date?: string | null;
traffic_light_status?: string | null;
process_log?: string | null;
observation_es?: string | null;
observation_en?: string | null;
comments_status?: string | null;
cfdi_uuid?: string | null;
path_pdf?: string | null;
path_xml?: string | null;
status?: "pending" | "processed" | "reversed" | boolean | null;
compliance_mx?: Partial<InvoiceComplianceMx> | null;
financials?: Partial<InvoiceFinancials> | null;
logistics?: Partial<InvoiceLogistics>[] | null;
details?: Partial<InvoiceSalesDetails>[] | null;
collections?: Partial<InvoiceCollections>[] | null;
}
/**
* API para Facturas
*/
export const invoicesApi = {
/**
* Lista todas las facturas con paginación
*/
list: (companyId: number, page = 1, pageSize = 50, filters?: Record<string, any>) => {
const params = new URLSearchParams({
company_id: companyId.toString(),
page: page.toString(),
page_size: pageSize.toString()
});
// Agregar filtros si existen
if (filters) {
Object.entries(filters).forEach(([key, value]) => {
if (value !== null && value !== undefined && value !== '') {
params.append(key, String(value));
}
});
}
return api.get<InvoiceListResponse>(`/v1/a76/invoices/?${params.toString()}`);
},
/**
* Obtiene una factura por ID
*/
get: (invoiceId: number, companyId: number) => {
const params = new URLSearchParams({
company_id: companyId.toString()
});
return api.get<Invoice>(`/v1/a76/invoices/${invoiceId}?${params.toString()}`);
},
/**
* Crea una nueva factura
*/
create: (companyId: number, data: CreateInvoiceData) => {
const params = new URLSearchParams({
company_id: companyId.toString()
});
return api.post<Invoice>(`/v1/a76/invoices/?${params.toString()}`, data);
},
/**
* Actualiza una factura existente
*/
update: (invoiceId: number, companyId: number, data: UpdateInvoiceData) => {
const params = new URLSearchParams({
company_id: companyId.toString()
});
return api.put<Invoice>(`/v1/a76/invoices/${invoiceId}/?${params.toString()}`, data);
},
/**
* Elimina una factura
*/
delete: (invoiceId: number, companyId: number) => {
const params = new URLSearchParams({
company_id: companyId.toString()
});
return api.delete(`/v1/a76/invoices/${invoiceId}?${params.toString()}`);
},
/**
* Obtiene datos para la creación de una factura (catálogos consolidados)
*/
getCreationData: (companyId: number) => {
const params = new URLSearchParams({
company_id: companyId.toString()
});
return api.get<any>(`/v1/a76/invoices/creation-data?${params.toString()}`);
},
/**
* Obtiene datos para la edición de una factura (catálogos consolidados + factura)
*/
getEditionData: (invoiceId: number, companyId: number) => {
const params = new URLSearchParams({
company_id: companyId.toString()
});
return api.get<any>(`/v1/a76/invoices/${invoiceId}/edition-data?${params.toString()}`);
},
// --- Nested Resources ---
/**
* Logística de factura
*/
logistics: {
list: (invoiceId: number, companyId: number) => {
const params = new URLSearchParams({
company_id: companyId.toString()
});
return api.get<InvoiceLogistics[]>(`/v1/a76/invoices/${invoiceId}/logistics/?${params.toString()}`);
},
create: (invoiceId: number, companyId: number, data: Omit<InvoiceLogistics, 'id' | 'invoice_id'>) => {
const params = new URLSearchParams({
company_id: companyId.toString()
});
return api.post<InvoiceLogistics>(`/v1/a76/invoices/${invoiceId}/logistics/?${params.toString()}`, data);
},
delete: (invoiceId: number, logisticsId: number, companyId: number) => {
const params = new URLSearchParams({
company_id: companyId.toString()
});
return api.delete(`/v1/a76/invoices/${invoiceId}/logistics/${logisticsId}/?${params.toString()}`);
}
},
/**
* Detalles de venta de factura
*/
details: {
list: (invoiceId: number, companyId: number) => {
const params = new URLSearchParams({
company_id: companyId.toString()
});
return api.get<InvoiceSalesDetails[]>(`/v1/a76/invoices/${invoiceId}/details/?${params.toString()}`);
},
create: (invoiceId: number, companyId: number, data: Omit<InvoiceSalesDetails, 'id' | 'invoice_id'>) => {
const params = new URLSearchParams({
company_id: companyId.toString()
});
return api.post<InvoiceSalesDetails>(`/v1/a76/invoices/${invoiceId}/details/?${params.toString()}`, data);
},
delete: (invoiceId: number, detailId: number, companyId: number) => {
const params = new URLSearchParams({
company_id: companyId.toString()
});
return api.delete(`/v1/a76/invoices/${invoiceId}/details/${detailId}/?${params.toString()}`);
}
},
/**
* Cobranzas de factura
*/
collections: {
list: (invoiceId: number, companyId: number) => {
const params = new URLSearchParams({
company_id: companyId.toString()
});
return api.get<InvoiceCollections[]>(`/v1/a76/invoices/${invoiceId}/collections/?${params.toString()}`);
},
create: (invoiceId: number, companyId: number, data: Omit<InvoiceCollections, 'id' | 'invoice_id'>) => {
const params = new URLSearchParams({
company_id: companyId.toString()
});
return api.post<InvoiceCollections>(`/v1/a76/invoices/${invoiceId}/collections/?${params.toString()}`, data);
},
delete: (invoiceId: number, collectionId: number, companyId: number) => {
const params = new URLSearchParams({
company_id: companyId.toString()
});
return api.delete(`/v1/a76/invoices/${invoiceId}/collections/${collectionId}/?${params.toString()}`);
}
},
processInvoice: (invoiceId: number, companyId: number) => {
const params = new URLSearchParams({
company_id: companyId.toString()
});
return api.post<{ task_id: string }>(
`/v1/a76/invoices/${invoiceId}/process?${params.toString()}`,
{}
);
},
getProcessStatus: (taskId: string) => {
return api.get<{
state: 'PROCESSING' | 'SUCCESS' | 'FAILURE';
info?: { current: number; status: string };
result?: {
status: 'success' | 'validation_error' | 'error';
invoice_id?: number;
message?: string;
errors?: Array<{ field: string; message: string; code?: string; solution?: string[] }>;
sql_errors?: Array<{ consecutive: number; error: string }>;
};
}>(`/v1/a76/invoices/process/${taskId}/status`);
},
revertInvoice: (invoiceId: number, companyId: number) => {
const params = new URLSearchParams({
company_id: companyId.toString()
});
return api.post<{ task_id: string }>(
`/v1/a76/invoices/${invoiceId}/revert?${params.toString()}`,
{}
);
},
getRevertStatus: (taskId: string) => {
return api.get<{
state: 'PROCESSING' | 'SUCCESS' | 'FAILURE';
info?: { current: number; status: string };
result?: {
status: 'success' | 'validation_error' | 'error';
invoice_id?: number;
message?: string;
errors?: Array<{ field: string; message: string; code?: string; solution?: string[] }>;
sql_errors?: Array<{ consecutive: number; error: string }>;
};
}>(`/v1/a76/invoices/revert/${taskId}/status`);
}
};