File size: 3,591 Bytes
422b73d
 
 
 
2041c17
 
 
 
 
 
 
 
422b73d
389ef0e
1c7eff7
422b73d
2b10760
422b73d
 
 
2041c17
422b73d
 
 
 
2041c17
422b73d
389ef0e
422b73d
 
 
deb7f2a
422b73d
 
 
 
 
 
 
 
 
 
 
 
2b10760
 
 
422b73d
 
 
 
 
 
 
 
 
2041c17
422b73d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2041c17
422b73d
 
 
 
2041c17
422b73d
 
 
 
2041c17
389ef0e
 
 
422b73d
 
 
 
 
 
 
 
2041c17
422b73d
 
 
 
 
 
2041c17
422b73d
 
 
2041c17
 
378503c
2041c17
422b73d
 
 
2041c17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2b10760
2041c17
 
 
68a1f99
389ef0e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import {
  DataTypes,
  Model,
  CreationOptional,
  ValidationErrorItem,
  Op,
  ValidationError,
} from "sequelize";
import { sequelize } from "./index";
import { InvoiceInterface } from "../shared/interfaces/invoice.interface";
import User from "./users";
import InvoiceDetail from "./invoicedetail";

class Invoice extends Model<InvoiceInterface> implements InvoiceInterface {
  declare id?: number;
  declare reference_number: string;
  declare invoice_number: string;
  declare vendor_name: string;
  declare invoice_date: Date;
  declare total: number;
  declare amount_paid: number;
  declare due_date?: Date;
  declare term?: string;
  declare description?: string;
  declare payment_status?: string;
  declare pw_work_order_id?: number;
  declare pw_vendor_id?: number;
  declare filename?: string;
  declare pdf_url?: string;
  declare status: string;
  declare uploaded_by: number;
  declare InvoiceDetails: InvoiceDetail[];
}

Invoice.init(
  {
    id: {
      type: DataTypes.INTEGER,
      autoIncrement: true,
      primaryKey: true,
    },
    reference_number: {
      type: DataTypes.STRING(100),
    },
    invoice_number: {
      type: DataTypes.STRING(100),
    },
    vendor_name: {
      type: DataTypes.STRING(255),
    },
    invoice_date: {
      type: DataTypes.DATE,
    },
    total: {
      type: DataTypes.DECIMAL(10, 2),
    },
    amount_paid: {
      type: DataTypes.DECIMAL(10, 2),
    },
    due_date: {
      type: DataTypes.DATE,
      allowNull: true,
    },
    term: {
      type: DataTypes.STRING(50),
      allowNull: true,
    },
    description: {
      type: DataTypes.TEXT,
      allowNull: true,
    },
    payment_status: {
      type: DataTypes.STRING(50),
      defaultValue: "pending",
    },
    pw_work_order_id: {
      type: DataTypes.INTEGER,
      allowNull: true,
    },
    pw_vendor_id: {
      type: DataTypes.INTEGER,
      allowNull: true,
    },
    filename: {
      type: DataTypes.STRING(255),
      allowNull: false,
    },
    pdf_url: {
      type: DataTypes.STRING(255),
      allowNull: true,
    },
    status: {
      type: DataTypes.STRING(50),
      allowNull: false,
    },
    uploaded_by: {
      type: DataTypes.INTEGER,
      allowNull: false,
    },
  },
  {
    sequelize,
    tableName: "invoices",
    underscored: true,
    freezeTableName: true,
    timestamps: true,
    createdAt: "created_at",
    updatedAt: "updated_at",
    paranoid: true,
    deletedAt: "deleted_at",
  }
);

Invoice.belongsTo(User, { foreignKey: "uploaded_by", as: "uploadedBy" });
Invoice.hasMany(InvoiceDetail, { foreignKey: "invoice_id" });

const validateInvoice = async (invoice: Invoice) => {
  const existingInvoice = await Invoice.findOne({
    where: {
      reference_number: invoice.reference_number,
      status: { [Op.ne]: "archived" },
      id: { [Op.ne]: invoice.id },
    },
  });

  const validationErrorItems: ValidationErrorItem[] = [];

  if (existingInvoice) {
    validationErrorItems.push(
      new ValidationErrorItem(
        "Invoice with the same reference number already exists; archive it before adding another.",
        "unique violation",
        "reference_number",
        invoice.reference_number,
        invoice,
        "isUnique",
        "reference_number",
        []
      )
    );
  }

  if (validationErrorItems.length > 0) {
    throw new ValidationError("Validation Error", validationErrorItems);
  }
};

Invoice.addHook("beforeCreate", validateInvoice);
Invoice.addHook("beforeUpdate", validateInvoice);
Invoice.addHook("beforeSave", validateInvoice);

export default Invoice;