import { type CreationOptional, DataTypes, type InferAttributes, type InferCreationAttributes, Model, type NonAttribute, type Sequelize, } from "sequelize"; import type { CustomerInvoiceModel } from "./customer-invoice.model"; export type CustomerInvoiceItemCreationAttributes = InferCreationAttributes< CustomerInvoiceItemModel, { omit: "invoice" } >; export class CustomerInvoiceItemModel extends Model< InferAttributes, InferCreationAttributes > { declare item_id: string; declare invoice_id: string; declare position: number; declare description: CreationOptional; declare quantity_value: CreationOptional; declare quantity_scale: number; declare unit_amount_value: CreationOptional; declare unit_amount_scale: number; // Subtotal declare subtotal_amount_value: CreationOptional; declare subtotal_amount_scale: number; // Discount percentage declare discount_percentage_value: CreationOptional; declare discount_percentage_scale: number; // Discount amount declare discount_amount_value: CreationOptional; declare discount_amount_scale: number; // Taxable amount (base imponible) declare taxable_amount_value: CreationOptional; declare taxable_amount_scale: number; // Código de impuestos // IVA percentage declare iva_code: CreationOptional; declare iva_percentage_value: CreationOptional; declare iva_percentage_scale: number; // IVA amount declare iva_amount_value: CreationOptional; declare iva_amount_scale: number; // Recargo de equivalencia percentage declare rec_code: CreationOptional; declare rec_percentage_value: CreationOptional; declare rec_percentage_scale: number; // Recargo de equivalencia amount declare rec_amount_value: CreationOptional; declare rec_amount_scale: number; // Retention percentage declare retention_code: CreationOptional; declare retention_percentage_value: CreationOptional; declare retention_percentage_scale: number; // Retention amount declare retention_amount_value: CreationOptional; declare retention_amount_scale: number; // Total taxes amount / taxes total declare taxes_amount_value: CreationOptional; declare taxes_amount_scale: number; // Total declare total_amount_value: CreationOptional; declare total_amount_scale: number; // Relaciones declare invoice: NonAttribute; static associate(database: Sequelize) { const models = database.models; const requiredModels = ["CustomerInvoiceModel", "CustomerInvoiceItemModel"]; // Comprobamos que los modelos existan for (const name of requiredModels) { if (!models[name]) { throw new Error(`[CustomerInvoiceItemModel.associate] Missing model: ${name}`); } } const { CustomerInvoiceModel, CustomerInvoiceItemModel } = models; CustomerInvoiceItemModel.belongsTo(CustomerInvoiceModel, { as: "invoice", targetKey: "id", foreignKey: "invoice_id", onDelete: "CASCADE", onUpdate: "CASCADE", }); } } export default (database: Sequelize) => { CustomerInvoiceItemModel.init( { item_id: { type: DataTypes.UUID, primaryKey: true, }, invoice_id: { type: DataTypes.UUID, allowNull: false, }, position: { type: new DataTypes.MEDIUMINT().UNSIGNED, autoIncrement: false, allowNull: false, }, description: { type: new DataTypes.TEXT(), allowNull: true, defaultValue: null, }, quantity_value: { type: new DataTypes.BIGINT(), allowNull: true, defaultValue: null, }, quantity_scale: { type: new DataTypes.SMALLINT(), allowNull: false, defaultValue: 2, }, unit_amount_value: { type: new DataTypes.BIGINT(), allowNull: true, defaultValue: null, }, unit_amount_scale: { type: new DataTypes.SMALLINT(), allowNull: false, defaultValue: 4, }, subtotal_amount_value: { type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes allowNull: true, defaultValue: null, }, subtotal_amount_scale: { type: new DataTypes.SMALLINT(), allowNull: false, defaultValue: 4, }, discount_percentage_value: { type: new DataTypes.SMALLINT(), allowNull: true, defaultValue: null, }, discount_percentage_scale: { type: new DataTypes.SMALLINT(), allowNull: false, defaultValue: 2, }, discount_amount_value: { type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes allowNull: true, defaultValue: null, }, discount_amount_scale: { type: new DataTypes.SMALLINT(), allowNull: false, defaultValue: 4, }, taxable_amount_value: { type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes allowNull: true, defaultValue: null, }, taxable_amount_scale: { type: new DataTypes.SMALLINT(), allowNull: false, defaultValue: 4, }, // IVA % iva_code: { type: DataTypes.STRING(40), allowNull: true, defaultValue: null, }, iva_percentage_value: { type: DataTypes.SMALLINT, allowNull: true, defaultValue: null, }, iva_percentage_scale: { type: DataTypes.SMALLINT, allowNull: false, defaultValue: 2, }, iva_amount_value: { type: DataTypes.BIGINT, allowNull: true, defaultValue: null, }, iva_amount_scale: { type: DataTypes.SMALLINT, allowNull: false, defaultValue: 4, }, // REC % rec_code: { type: DataTypes.STRING(40), allowNull: true, defaultValue: null, }, rec_percentage_value: { type: DataTypes.SMALLINT, allowNull: true, defaultValue: null, }, rec_percentage_scale: { type: DataTypes.SMALLINT, allowNull: false, defaultValue: 2, }, rec_amount_value: { type: DataTypes.BIGINT, allowNull: true, defaultValue: null, }, rec_amount_scale: { type: DataTypes.SMALLINT, allowNull: false, defaultValue: 4, }, // Retención % retention_code: { type: DataTypes.STRING(40), allowNull: true, defaultValue: null, }, retention_percentage_value: { type: DataTypes.SMALLINT, allowNull: true, defaultValue: null, }, retention_percentage_scale: { type: DataTypes.SMALLINT, allowNull: false, defaultValue: 2, }, retention_amount_value: { type: DataTypes.BIGINT, allowNull: true, defaultValue: null, }, retention_amount_scale: { type: DataTypes.SMALLINT, allowNull: false, defaultValue: 4, }, taxes_amount_value: { type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes allowNull: true, defaultValue: null, }, taxes_amount_scale: { type: new DataTypes.SMALLINT(), allowNull: false, defaultValue: 4, }, total_amount_value: { type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes allowNull: true, defaultValue: null, }, total_amount_scale: { type: new DataTypes.SMALLINT(), allowNull: false, defaultValue: 4, }, }, { sequelize: database, modelName: "CustomerInvoiceItemModel", tableName: "customer_invoice_items", underscored: true, indexes: [{ fields: ["invoice_id"] }, { fields: ["invoice_id", "position"] }], whereMergeStrategy: "and", // <- cómo tratar el merge de un scope defaultScope: { order: [["position", "ASC"]], }, scopes: {}, } ); return CustomerInvoiceItemModel; };