Bansari Akhani commited on
Commit
3a65c87
·
1 Parent(s): fa3491c

cetae audit logs on invoice update and sync to pw

Browse files
src/controllers/invoice/invoice.controller.ts CHANGED
@@ -10,9 +10,8 @@ import { FindOptions, Op } from "sequelize";
10
  import PwPortfolio from "../../models/pwPortfolio";
11
  import PwBuilding from "../../models/pwBuildings";
12
  import PwUnit from "../../models/pwUnits";
13
- import { fetchGLAccountById } from "../../shared/services/propertyware.service";
14
- import { formatDate } from "../../utils/dataUtils";
15
  import { logger } from '../../utils/logger';
 
16
 
17
 
18
  export const createInvoice = async (req: Request, res: Response) => {
@@ -24,7 +23,7 @@ export const createInvoice = async (req: Request, res: Response) => {
24
 
25
  try {
26
  const uploadResults = await uploadInvoice(files);
27
-
28
  res.status(201).json({ message: "Files uploaded successfully, processing invoices in the background" });
29
 
30
  // Process the rest of the operations in the background
@@ -133,7 +132,7 @@ const buildInvoiceWhereClause = (filter: Record<string, any>): any => {
133
  }
134
 
135
  if (filter.reference_number) {
136
- whereClause.reference_number = { [Op.like]: `%${filter.reference_number}%` };
137
  }
138
 
139
  if (filter.invoice_date) {
@@ -191,16 +190,16 @@ export const getAllInvoices = async (req: Request, res: Response): Promise<Respo
191
  const filter = req.query.filter as Record<string, any>;
192
 
193
  const allowedSortColumns = [
194
- 'id',
195
- 'invoice_date',
196
- 'total',
197
- 'amount_paid',
198
- 'due_date',
199
- 'pw_work_order_id',
200
- 'pw_vendor_id',
201
- 'uploaded_by',
202
- 'created_at'
203
- ];
204
 
205
  const whereClause = buildInvoiceWhereClause(filter);
206
 
@@ -221,7 +220,8 @@ export const getAllInvoices = async (req: Request, res: Response): Promise<Respo
221
  }
222
 
223
  const [invoices, totalInvoices] = await Promise.all([
224
- Invoice.findAll({...options,
 
225
  include: [
226
  { model: User,
227
  as: 'uploadedBy',
@@ -250,38 +250,52 @@ export const getAllInvoices = async (req: Request, res: Response): Promise<Respo
250
  }
251
  };
252
 
253
-
254
-
255
  export const getInvoiceById = async (req: Request, res: Response): Promise<Response> => {
256
  try {
257
  const { id } = req.params;
258
- const invoice = await Invoice.findOne({ where : {id: id}, include: [
259
- { model: InvoiceDetail }
260
- ]});
 
 
261
 
262
  if (!invoice) {
263
  return res.status(404).json({ error: "Invoice not found" });
264
  }
265
-
266
  const invoiceDetailsPromises = invoice.InvoiceDetails.map(async (invoiceDetails) => {
267
-
268
  return {
269
  amount: invoiceDetails.amount,
270
  expenseAccount: invoiceDetails.pw_gl_account_id,
271
- location: {portfolioId : invoiceDetails.pw_portfolio_id, buildingId: invoiceDetails.pw_building_id, unitId: invoiceDetails.pw_unit_id},
272
  description: invoiceDetails.description || ''
273
  };
274
  });
275
-
276
  const billSplit = await Promise.all(invoiceDetailsPromises);
277
-
278
- return res.status(200).json({invoice: invoice.dataValues, billSplit : billSplit });
279
  } catch (error) {
280
  logger.error("Error fetching invoice:", error);
281
  return res.status(500).json({ error: "Error fetching invoice details" });
282
  }
283
  };
284
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
285
 
286
  export const updateInvoice = async (req: Request, res: Response): Promise<Response> => {
287
  const { id } = req.params;
@@ -313,8 +327,18 @@ export const updateInvoice = async (req: Request, res: Response): Promise<Respon
313
  uploaded_by: invoice.uploaded_by,
314
  };
315
 
 
316
  const invoiceUpdate = await existingInvoice.update(updatedInvoiceData);
317
 
 
 
 
 
 
 
 
 
 
318
  // Delete existing InvoiceDetails
319
  await InvoiceDetail.destroy({ where: { invoice_id: id } });
320
 
 
10
  import PwPortfolio from "../../models/pwPortfolio";
11
  import PwBuilding from "../../models/pwBuildings";
12
  import PwUnit from "../../models/pwUnits";
 
 
13
  import { logger } from '../../utils/logger';
14
+ import AuditLog from "../../models/auditLogs";
15
 
16
 
17
  export const createInvoice = async (req: Request, res: Response) => {
 
23
 
24
  try {
25
  const uploadResults = await uploadInvoice(files);
26
+
27
  res.status(201).json({ message: "Files uploaded successfully, processing invoices in the background" });
28
 
29
  // Process the rest of the operations in the background
 
132
  }
133
 
134
  if (filter.reference_number) {
135
+ whereClause.reference_number = { [Op.like]: `%${filter.reference_number}%` };
136
  }
137
 
138
  if (filter.invoice_date) {
 
190
  const filter = req.query.filter as Record<string, any>;
191
 
192
  const allowedSortColumns = [
193
+ 'id',
194
+ 'invoice_date',
195
+ 'total',
196
+ 'amount_paid',
197
+ 'due_date',
198
+ 'pw_work_order_id',
199
+ 'pw_vendor_id',
200
+ 'uploaded_by',
201
+ 'created_at'
202
+ ];
203
 
204
  const whereClause = buildInvoiceWhereClause(filter);
205
 
 
220
  }
221
 
222
  const [invoices, totalInvoices] = await Promise.all([
223
+ Invoice.findAll({
224
+ ...options,
225
  include: [
226
  { model: User,
227
  as: 'uploadedBy',
 
250
  }
251
  };
252
 
 
 
253
  export const getInvoiceById = async (req: Request, res: Response): Promise<Response> => {
254
  try {
255
  const { id } = req.params;
256
+ const invoice = await Invoice.findOne({
257
+ where: { id: id }, include: [
258
+ { model: InvoiceDetail }
259
+ ]
260
+ });
261
 
262
  if (!invoice) {
263
  return res.status(404).json({ error: "Invoice not found" });
264
  }
265
+
266
  const invoiceDetailsPromises = invoice.InvoiceDetails.map(async (invoiceDetails) => {
267
+
268
  return {
269
  amount: invoiceDetails.amount,
270
  expenseAccount: invoiceDetails.pw_gl_account_id,
271
+ location: { portfolioId: invoiceDetails.pw_portfolio_id, buildingId: invoiceDetails.pw_building_id, unitId: invoiceDetails.pw_unit_id },
272
  description: invoiceDetails.description || ''
273
  };
274
  });
275
+
276
  const billSplit = await Promise.all(invoiceDetailsPromises);
277
+
278
+ return res.status(200).json({ invoice: invoice.dataValues, billSplit: billSplit });
279
  } catch (error) {
280
  logger.error("Error fetching invoice:", error);
281
  return res.status(500).json({ error: "Error fetching invoice details" });
282
  }
283
  };
284
 
285
+ function getUpdatedFields(original: any, updated: any): string {
286
+ const changes: string[] = [];
287
+ const skipKeys = ['InvoiceDetails', 'created_at', 'updated_at','deleted_at'];
288
+ for (const key in original) {
289
+ if (skipKeys.includes(key))
290
+ continue;
291
+ console.log(original[key] !== updated[key], key, original[key], updated[key] );
292
+ if (original[key] !== updated[key]) {
293
+ changes.push(`${key}: ${original[key]} -> ${updated[key]}`);
294
+ }
295
+ }
296
+ return changes.join(', ');
297
+ }
298
+
299
 
300
  export const updateInvoice = async (req: Request, res: Response): Promise<Response> => {
301
  const { id } = req.params;
 
327
  uploaded_by: invoice.uploaded_by,
328
  };
329
 
330
+ const originalInvoiceData = { ...existingInvoice.dataValues };
331
  const invoiceUpdate = await existingInvoice.update(updatedInvoiceData);
332
 
333
+ const updatedFields = getUpdatedFields(originalInvoiceData, invoiceUpdate.dataValues);
334
+ const auditLogData = {
335
+ invoice_id: invoice.id,
336
+ action_by: 1, // replace with the actual user ID performing the action
337
+ action: 'Update Invoice',
338
+ details: updatedFields
339
+ };
340
+
341
+ await AuditLog.create(auditLogData);
342
  // Delete existing InvoiceDetails
343
  await InvoiceDetail.destroy({ where: { invoice_id: id } });
344
 
src/controllers/propertyware/bills.controller.ts CHANGED
@@ -24,7 +24,7 @@ export const syncInvoices = async (req: Request, res: Response) => {
24
  // Map the invoices to the bill request format
25
  invoices.forEach(async (invoice) => {
26
  const bill = {
27
- billDate: formatDate(invoice.invoice_date), // FIXME: format invoice date
28
  billSplits: invoice.InvoiceDetails.map(detail => ({
29
  amount: detail.amount as number,
30
  glAccountID: detail.pw_gl_account_id,
@@ -34,24 +34,22 @@ export const syncInvoices = async (req: Request, res: Response) => {
34
  paid: false,
35
  unitID: detail.pw_unit_id
36
  })),
37
- dueDate: invoice.due_date ? formatDate(invoice.due_date) : null, // FIXME: format due date
38
  vendorID: invoice.pw_vendor_id?.toString(),
39
  billNumber: invoice.invoice_number,
40
  comments: invoice.description,
41
  refNo: invoice.reference_number,
42
  terms: invoice.term,
43
- workOrderID: invoice.pw_work_order_id, // FIXME: check if work order id is valid from pwoprtyware workorders
44
  };
45
  try {
46
  const response = await createBill(bill);
47
  console.log(response.id);
48
 
49
  // add audit log for Update Invoice
50
- // add entry to error log
51
- const auditLogData = { invoice_id: invoice.id as number, action_by: 1, action: 'Invoice sync to PW', details: `sync Successfull. PW invoice id : ${response.id}`};
52
- await AuditLog.create(auditLogData);
53
 
54
- // add audit log
 
55
 
56
  logger.info(`Bill for invoice ${bill.refNo} synced successfully`);
57
  } catch (error) {
 
24
  // Map the invoices to the bill request format
25
  invoices.forEach(async (invoice) => {
26
  const bill = {
27
+ billDate: formatDate(invoice.invoice_date),
28
  billSplits: invoice.InvoiceDetails.map(detail => ({
29
  amount: detail.amount as number,
30
  glAccountID: detail.pw_gl_account_id,
 
34
  paid: false,
35
  unitID: detail.pw_unit_id
36
  })),
37
+ dueDate: invoice.due_date ? formatDate(invoice.due_date) : null,
38
  vendorID: invoice.pw_vendor_id?.toString(),
39
  billNumber: invoice.invoice_number,
40
  comments: invoice.description,
41
  refNo: invoice.reference_number,
42
  terms: invoice.term,
43
+ workOrderID: null, // FIXME: check if work order id is valid from pwoprtyware workorders
44
  };
45
  try {
46
  const response = await createBill(bill);
47
  console.log(response.id);
48
 
49
  // add audit log for Update Invoice
 
 
 
50
 
51
+ const auditLogData = { invoice_id: invoice.id as number, action_by: 1, action: 'Invoice sync to PW', details: `Bill for invoice ${bill.refNo} synced successfully. PW invoice id : ${response.id}`};
52
+ await AuditLog.create(auditLogData);
53
 
54
  logger.info(`Bill for invoice ${bill.refNo} synced successfully`);
55
  } catch (error) {