import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, Model, NonAttribute, Sequelize, } from "sequelize"; import { CustomerInvoiceItemCreationAttributes, CustomerInvoiceItemModel, } from "./customer-invoice-item.model"; import { CustomerModel } from "@erp/customers/api"; import { CustomerInvoiceTaxCreationAttributes, CustomerInvoiceTaxModel, } from "./customer-invoice-tax.model"; export type CustomerInvoiceCreationAttributes = InferCreationAttributes< CustomerInvoiceModel, { omit: "items" | "taxes" | "current_customer" } > & { items?: CustomerInvoiceItemCreationAttributes[]; taxes?: CustomerInvoiceTaxCreationAttributes[]; }; export class CustomerInvoiceModel extends Model< InferAttributes, InferCreationAttributes > { // Version // declare version: CreationOptional; declare id: string; declare company_id: string; declare is_proforma: boolean; declare status: string; declare series: CreationOptional; declare invoice_number: CreationOptional; declare invoice_date: CreationOptional; declare operation_date: CreationOptional; declare language_code: CreationOptional; declare currency_code: CreationOptional; declare reference: CreationOptional; declare description: CreationOptional; declare notes: CreationOptional; // Método de pago declare payment_method_id: CreationOptional; declare payment_method_description: CreationOptional; // Subtotal declare subtotal_amount_value: number; declare subtotal_amount_scale: number; // Discount percentage declare discount_percentage_value: number; declare discount_percentage_scale: number; // Discount amount declare discount_amount_value: number; declare discount_amount_scale: number; // Taxable amount (base imponible) declare taxable_amount_value: number; declare taxable_amount_scale: number; // Total taxes amount / taxes total declare taxes_amount_value: number; declare taxes_amount_scale: number; // Total declare total_amount_value: number; declare total_amount_scale: number; // Customer declare customer_id: string; declare customer_tin: CreationOptional; declare customer_name: CreationOptional; declare customer_street: CreationOptional; declare customer_street2: CreationOptional; declare customer_city: CreationOptional; declare customer_province: CreationOptional; declare customer_postal_code: CreationOptional; declare customer_country: CreationOptional; // Relaciones declare items: NonAttribute; declare taxes: NonAttribute; declare current_customer: NonAttribute; static associate(database: Sequelize) { const { CustomerInvoiceModel, CustomerInvoiceItemModel, CustomerModel, CustomerInvoiceTaxModel, VerifactuRecordModel, } = database.models; CustomerInvoiceModel.belongsTo(CustomerModel, { as: "current_customer", foreignKey: "customer_id", constraints: false, }); CustomerInvoiceModel.hasMany(CustomerInvoiceItemModel, { as: "items", foreignKey: "invoice_id", sourceKey: "id", constraints: true, onDelete: "CASCADE", onUpdate: "CASCADE", }); CustomerInvoiceModel.hasMany(CustomerInvoiceTaxModel, { as: "taxes", foreignKey: "invoice_id", sourceKey: "id", constraints: true, onDelete: "CASCADE", onUpdate: "CASCADE", }); } static hooks(database: Sequelize) {} } export default (database: Sequelize) => { CustomerInvoiceModel.init( { /*version: { type: DataTypes.INTEGER.UNSIGNED, allowNull: false, defaultValue: 0, },*/ id: { type: DataTypes.UUID, primaryKey: true, }, company_id: { type: DataTypes.UUID, allowNull: false, }, is_proforma: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: true, }, status: { type: new DataTypes.STRING(), allowNull: false, defaultValue: "draft", }, series: { type: new DataTypes.STRING(), allowNull: true, defaultValue: null, }, invoice_number: { type: new DataTypes.STRING(), allowNull: true, defaultValue: null, }, invoice_date: { type: new DataTypes.DATEONLY(), allowNull: false, }, operation_date: { type: new DataTypes.DATEONLY(), allowNull: true, defaultValue: null, }, language_code: { type: DataTypes.STRING(2), allowNull: false, defaultValue: "es", }, currency_code: { type: new DataTypes.STRING(3), allowNull: false, defaultValue: "EUR", }, reference: { type: new DataTypes.STRING(), allowNull: true, defaultValue: null, }, description: { type: new DataTypes.STRING(), allowNull: true, defaultValue: null, }, notes: { type: new DataTypes.TEXT(), allowNull: true, defaultValue: null, }, payment_method_id: { type: DataTypes.UUID, allowNull: true, defaultValue: null, }, payment_method_description: { type: new DataTypes.STRING(), allowNull: true, defaultValue: null, }, subtotal_amount_value: { type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes allowNull: false, defaultValue: 0, }, subtotal_amount_scale: { type: new DataTypes.SMALLINT(), allowNull: false, defaultValue: 2, }, discount_percentage_value: { type: new DataTypes.SMALLINT(), allowNull: false, defaultValue: 0, }, discount_percentage_scale: { type: new DataTypes.SMALLINT(), allowNull: false, defaultValue: 2, }, discount_amount_value: { type: new DataTypes.BIGINT(), allowNull: false, defaultValue: 0, }, discount_amount_scale: { type: new DataTypes.SMALLINT(), allowNull: false, defaultValue: 2, }, taxable_amount_value: { type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes allowNull: false, defaultValue: 0, }, taxable_amount_scale: { type: new DataTypes.SMALLINT(), allowNull: false, defaultValue: 2, }, taxes_amount_value: { type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes allowNull: false, defaultValue: 0, }, taxes_amount_scale: { type: new DataTypes.SMALLINT(), allowNull: false, defaultValue: 2, }, total_amount_value: { type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes allowNull: false, defaultValue: 0, }, total_amount_scale: { type: new DataTypes.SMALLINT(), allowNull: false, defaultValue: 2, }, customer_id: { type: DataTypes.UUID, allowNull: false, }, customer_tin: { type: DataTypes.STRING, allowNull: true, defaultValue: null, }, customer_name: { type: DataTypes.STRING, allowNull: true, defaultValue: null, }, customer_street: { type: DataTypes.STRING, allowNull: true, defaultValue: null, }, customer_street2: { type: DataTypes.STRING, allowNull: true, defaultValue: null, }, customer_city: { type: DataTypes.STRING, allowNull: true, defaultValue: null, }, customer_province: { type: DataTypes.STRING, allowNull: true, defaultValue: null, }, customer_postal_code: { type: DataTypes.STRING, allowNull: true, defaultValue: null, }, customer_country: { type: DataTypes.STRING, allowNull: true, defaultValue: null, }, }, { sequelize: database, tableName: "customer_invoices", underscored: true, paranoid: true, // softs deletes timestamps: true, createdAt: "created_at", updatedAt: "updated_at", deletedAt: "deleted_at", indexes: [ { name: "idx_invoices_company_date", fields: ["company_id", "deleted_at", { name: "invoice_date", order: "DESC" }], }, { name: "idx_invoice_date", fields: ["invoice_date"] }, // <- para ordenación { name: "idx_company_idx", fields: ["id", "company_id"], unique: true }, // <- para consulta get { name: "ft_customer_invoice", type: "FULLTEXT", fields: ["invoice_number", "reference", "description"], }, ], whereMergeStrategy: "and", // <- cómo tratar el merge de un scope defaultScope: {}, scopes: {}, /*hooks: { // Incrementa la versión en cada update exitoso (OCC). beforeUpdate: (instance) => { const current = instance.get("version") as number; instance.set("version", current + 1); }, },*/ } ); return CustomerInvoiceModel; };