Spaces:
Runtime error
Runtime error
Bansari Akhani commited on
Commit ·
389ef0e
1
Parent(s): adca714
invoice list apis
Browse files- package.json +2 -0
- src/app.ts +10 -3
- src/controllers/invoice/invoice.controller.ts +132 -52
- src/db/migrations/20240711110620-create-invoice-table.js +7 -7
- src/db/migrations/20240715065820-create-invoice-detail.js +2 -2
- src/models/invoice.ts +9 -7
- src/routes/invoice.routes.ts +18 -0
- src/routes/{index.ts → propertyware.routes.ts} +9 -14
- src/shared/interfaces/invoice.interface.ts +5 -4
- src/shared/services/invoice.service.ts +0 -2
- yarn.lock +23 -4
package.json
CHANGED
|
@@ -8,6 +8,7 @@
|
|
| 8 |
"aws-sdk": "^2.1659.0",
|
| 9 |
"axios": "^1.7.2",
|
| 10 |
"babel-register": "^6.26.0",
|
|
|
|
| 11 |
"bcryptjs": "^2.4.3",
|
| 12 |
"dotenv": "^16.4.5",
|
| 13 |
"express": "^4.19.2",
|
|
@@ -20,6 +21,7 @@
|
|
| 20 |
"sequelize-typescript": "^2.1.6"
|
| 21 |
},
|
| 22 |
"devDependencies": {
|
|
|
|
| 23 |
"@types/bcryptjs": "^2",
|
| 24 |
"@types/dotenv": "^8.2.0",
|
| 25 |
"@types/express": "^4.17.21",
|
|
|
|
| 8 |
"aws-sdk": "^2.1659.0",
|
| 9 |
"axios": "^1.7.2",
|
| 10 |
"babel-register": "^6.26.0",
|
| 11 |
+
"cors": "^2.8.5",
|
| 12 |
"bcryptjs": "^2.4.3",
|
| 13 |
"dotenv": "^16.4.5",
|
| 14 |
"express": "^4.19.2",
|
|
|
|
| 21 |
"sequelize-typescript": "^2.1.6"
|
| 22 |
},
|
| 23 |
"devDependencies": {
|
| 24 |
+
"@types/cors": "^2",
|
| 25 |
"@types/bcryptjs": "^2",
|
| 26 |
"@types/dotenv": "^8.2.0",
|
| 27 |
"@types/express": "^4.17.21",
|
src/app.ts
CHANGED
|
@@ -1,18 +1,25 @@
|
|
| 1 |
import express from 'express';
|
|
|
|
| 2 |
|
| 3 |
-
import
|
|
|
|
| 4 |
import userRouter from './routes/users';
|
| 5 |
|
| 6 |
const app = express();
|
|
|
|
| 7 |
const port = 3000;
|
| 8 |
app.use(express.json());
|
| 9 |
|
| 10 |
-
app.
|
|
|
|
|
|
|
| 11 |
res.send('Service is healthy!');
|
| 12 |
});
|
| 13 |
|
|
|
|
|
|
|
|
|
|
| 14 |
app.use('/api/users/', userRouter)
|
| 15 |
-
app.use("/api/", router);
|
| 16 |
|
| 17 |
try {
|
| 18 |
app.listen(port, () => {
|
|
|
|
| 1 |
import express from 'express';
|
| 2 |
+
import cors from 'cors';
|
| 3 |
|
| 4 |
+
import invoiceRouter from './routes/invoice.routes';
|
| 5 |
+
import pwRouter from './routes/propertyware.routes';
|
| 6 |
import userRouter from './routes/users';
|
| 7 |
|
| 8 |
const app = express();
|
| 9 |
+
|
| 10 |
const port = 3000;
|
| 11 |
app.use(express.json());
|
| 12 |
|
| 13 |
+
app.use(cors());
|
| 14 |
+
|
| 15 |
+
app.get('/', (_, res) => {
|
| 16 |
res.send('Service is healthy!');
|
| 17 |
});
|
| 18 |
|
| 19 |
+
|
| 20 |
+
app.use("/api/pw", pwRouter);
|
| 21 |
+
app.use('/api/invoices', invoiceRouter);
|
| 22 |
app.use('/api/users/', userRouter)
|
|
|
|
| 23 |
|
| 24 |
try {
|
| 25 |
app.listen(port, () => {
|
src/controllers/invoice/invoice.controller.ts
CHANGED
|
@@ -1,58 +1,138 @@
|
|
| 1 |
-
import { Request, Response } from
|
| 2 |
|
| 3 |
// import Invoice from '../../models/invoice';
|
| 4 |
-
import { uploadInvoice } from
|
| 5 |
-
import { parseInvoice } from
|
| 6 |
-
import FormData from
|
| 7 |
-
import Invoice from
|
|
|
|
|
|
|
| 8 |
|
| 9 |
export const createInvoice = async (req: Request, res: Response) => {
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { Request, Response } from "express";
|
| 2 |
|
| 3 |
// import Invoice from '../../models/invoice';
|
| 4 |
+
import { uploadInvoice } from "../../shared/services/invoice.service";
|
| 5 |
+
import { parseInvoice } from "../../shared/services/ai.service";
|
| 6 |
+
import FormData from "form-data";
|
| 7 |
+
import Invoice from "../../models/invoice";
|
| 8 |
+
import InvoiceDetail from "../../models/invoicedetail";
|
| 9 |
+
import User from "../../models/users";
|
| 10 |
|
| 11 |
export const createInvoice = async (req: Request, res: Response) => {
|
| 12 |
+
const files = req.files as Express.Multer.File[];
|
| 13 |
+
|
| 14 |
+
if (files?.length) {
|
| 15 |
+
try {
|
| 16 |
+
const uploadPromises = uploadInvoice(files);
|
| 17 |
+
const uploadResults = await Promise.all(uploadPromises);
|
| 18 |
+
|
| 19 |
+
const createInvoicePromises = files.map(async (file, index) => {
|
| 20 |
+
const formData = new FormData();
|
| 21 |
+
formData.append("file", file.buffer, file.originalname);
|
| 22 |
+
|
| 23 |
+
// Send the file URLs to the AI service API for parsing
|
| 24 |
+
const aiServiceResponse = await parseInvoice(formData);
|
| 25 |
+
const aiServiceData = aiServiceResponse[0];
|
| 26 |
+
|
| 27 |
+
const totalAmount = aiServiceData.billSplits.reduce(
|
| 28 |
+
(total: number, split: { amount: number }) => total + split.amount,
|
| 29 |
+
0
|
| 30 |
+
);
|
| 31 |
+
const invoiceDate = new Date(aiServiceData.billDate);
|
| 32 |
+
const dueDate = new Date(aiServiceData.dueDate);
|
| 33 |
+
let invoiceRecord = {
|
| 34 |
+
reference_number: aiServiceData.refNo,
|
| 35 |
+
vendor_name: aiServiceData.vendor,
|
| 36 |
+
pw_vendor_id: aiServiceData.vendor,
|
| 37 |
+
invoice_date: invoiceDate,
|
| 38 |
+
due_date: dueDate,
|
| 39 |
+
total: totalAmount,
|
| 40 |
+
description: aiServiceData.description,
|
| 41 |
+
status: "Pending",
|
| 42 |
+
amount_paid: 0,
|
| 43 |
+
filename: file.originalname,
|
| 44 |
+
pdf_url: uploadResults[index].Location,
|
| 45 |
+
uploaded_by: 1, // TODO : replace with logged in user when user module is implemented
|
| 46 |
+
};
|
| 47 |
+
|
| 48 |
+
const result = await Invoice.create(invoiceRecord);
|
| 49 |
+
|
| 50 |
+
// Create Invoice Details
|
| 51 |
+
const invoiceDetails = aiServiceData.billSplits.map(
|
| 52 |
+
(details: {
|
| 53 |
+
portfolio: any;
|
| 54 |
+
building: any;
|
| 55 |
+
unit: any;
|
| 56 |
+
glAccount: any;
|
| 57 |
+
amount: any;
|
| 58 |
+
description: any;
|
| 59 |
+
}) => ({
|
| 60 |
+
invoice_id: result.id,
|
| 61 |
+
pw_portfolio_id: details.portfolio,
|
| 62 |
+
pw_building_id: details.building,
|
| 63 |
+
pw_unit_id: details.unit,
|
| 64 |
+
pw_gl_account_id: details.glAccount,
|
| 65 |
+
amount: details.amount,
|
| 66 |
+
description: details.description,
|
| 67 |
+
})
|
| 68 |
+
);
|
| 69 |
+
|
| 70 |
+
await InvoiceDetail.bulkCreate(invoiceDetails);
|
| 71 |
+
});
|
| 72 |
+
|
| 73 |
+
await Promise.all(createInvoicePromises);
|
| 74 |
+
|
| 75 |
+
res.status(201).json({ message: "Invoices created successfully" });
|
| 76 |
+
} catch (error) {
|
| 77 |
+
console.error(error);
|
| 78 |
+
res.status(500).json({ message: "Error creating invoices", error });
|
| 79 |
}
|
| 80 |
+
} else {
|
| 81 |
+
res.status(400).json({ message: "No files uploaded" });
|
| 82 |
+
}
|
| 83 |
+
};
|
| 84 |
+
|
| 85 |
+
// Get All Invoices
|
| 86 |
+
export const getAllInvoices = async (req: Request, res: Response): Promise<Response> => {
|
| 87 |
+
try {
|
| 88 |
+
const invoices = await Invoice.findAll({
|
| 89 |
+
include: [
|
| 90 |
+
{ model: User, as: 'uploadedBy' }
|
| 91 |
+
]
|
| 92 |
+
});
|
| 93 |
+
|
| 94 |
+
if (invoices.length === 0) {
|
| 95 |
+
return res.status(404).json({ error: "No invoices found" });
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
return res.status(200).json(invoices);
|
| 99 |
+
} catch (error) {
|
| 100 |
+
console.error("Error fetching invoices:", error);
|
| 101 |
+
return res.status(500).json({ error: "Error fetching invoices" });
|
| 102 |
+
}
|
| 103 |
+
};
|
| 104 |
+
|
| 105 |
+
export const getInvoiceById = async (req: Request, res: Response): Promise<Response> => {
|
| 106 |
+
try {
|
| 107 |
+
const { id } = req.params;
|
| 108 |
+
const invoice = await Invoice.findByPk(id);
|
| 109 |
+
|
| 110 |
+
if (!invoice) {
|
| 111 |
+
return res.status(404).json({ error: "Invoice not found" });
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
return res.status(200).json(invoice);
|
| 115 |
+
} catch (error) {
|
| 116 |
+
console.error("Error fetching invoice:", error);
|
| 117 |
+
return res.status(500).json({ error: "Error fetching invoice details" });
|
| 118 |
+
}
|
| 119 |
+
};
|
| 120 |
+
|
| 121 |
+
// Delete an invoice
|
| 122 |
+
export const deleteInvoice = async (req: Request, res: Response): Promise<Response> => {
|
| 123 |
+
try {
|
| 124 |
+
const { id } = req.params;
|
| 125 |
+
const invoice = await Invoice.findByPk(id);
|
| 126 |
+
|
| 127 |
+
if (!invoice) {
|
| 128 |
+
return res.status(404).json({ error: "Invoice not found" });
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
await invoice.destroy();
|
| 132 |
|
| 133 |
+
return res.status(204).send();
|
| 134 |
+
} catch (error) {
|
| 135 |
+
console.error("Error deleting invoice:", error);
|
| 136 |
+
return res.status(500).json({ error: "Internal server error" });
|
| 137 |
+
}
|
| 138 |
+
};
|
src/db/migrations/20240711110620-create-invoice-table.js
CHANGED
|
@@ -10,20 +10,16 @@ module.exports = {
|
|
| 10 |
type: Sequelize.INTEGER
|
| 11 |
},
|
| 12 |
reference_number: {
|
| 13 |
-
allowNull: false,
|
| 14 |
type: Sequelize.STRING(100),
|
| 15 |
unique: true
|
| 16 |
},
|
| 17 |
vendor_name: {
|
| 18 |
-
allowNull: false,
|
| 19 |
type: Sequelize.STRING(255)
|
| 20 |
},
|
| 21 |
invoice_date: {
|
| 22 |
-
allowNull: false,
|
| 23 |
type: Sequelize.DATE
|
| 24 |
},
|
| 25 |
total: {
|
| 26 |
-
allowNull: false,
|
| 27 |
type: Sequelize.DECIMAL(10, 2)
|
| 28 |
},
|
| 29 |
amount_paid: {
|
|
@@ -45,10 +41,14 @@ module.exports = {
|
|
| 45 |
defaultValue: 'pending'
|
| 46 |
},
|
| 47 |
pw_work_order_id: {
|
| 48 |
-
type: Sequelize.
|
| 49 |
},
|
| 50 |
pw_vendor_id: {
|
| 51 |
-
type: Sequelize.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
},
|
| 53 |
pdf_url: {
|
| 54 |
type: Sequelize.STRING(255)
|
|
@@ -73,4 +73,4 @@ module.exports = {
|
|
| 73 |
async down(queryInterface, Sequelize) {
|
| 74 |
await queryInterface.dropTable('invoices');
|
| 75 |
}
|
| 76 |
-
};
|
|
|
|
| 10 |
type: Sequelize.INTEGER
|
| 11 |
},
|
| 12 |
reference_number: {
|
|
|
|
| 13 |
type: Sequelize.STRING(100),
|
| 14 |
unique: true
|
| 15 |
},
|
| 16 |
vendor_name: {
|
|
|
|
| 17 |
type: Sequelize.STRING(255)
|
| 18 |
},
|
| 19 |
invoice_date: {
|
|
|
|
| 20 |
type: Sequelize.DATE
|
| 21 |
},
|
| 22 |
total: {
|
|
|
|
| 23 |
type: Sequelize.DECIMAL(10, 2)
|
| 24 |
},
|
| 25 |
amount_paid: {
|
|
|
|
| 41 |
defaultValue: 'pending'
|
| 42 |
},
|
| 43 |
pw_work_order_id: {
|
| 44 |
+
type: Sequelize.BIGINT
|
| 45 |
},
|
| 46 |
pw_vendor_id: {
|
| 47 |
+
type: Sequelize.BIGINT
|
| 48 |
+
},
|
| 49 |
+
filename:{
|
| 50 |
+
type: Sequelize.STRING(255),
|
| 51 |
+
allowNull: false,
|
| 52 |
},
|
| 53 |
pdf_url: {
|
| 54 |
type: Sequelize.STRING(255)
|
|
|
|
| 73 |
async down(queryInterface, Sequelize) {
|
| 74 |
await queryInterface.dropTable('invoices');
|
| 75 |
}
|
| 76 |
+
};
|
src/db/migrations/20240715065820-create-invoice-detail.js
CHANGED
|
@@ -28,7 +28,7 @@ module.exports = {
|
|
| 28 |
type: Sequelize.BIGINT,
|
| 29 |
},
|
| 30 |
pw_gl_account_id: {
|
| 31 |
-
type: Sequelize.
|
| 32 |
defaultValue: null,
|
| 33 |
},
|
| 34 |
amount: {
|
|
@@ -49,4 +49,4 @@ module.exports = {
|
|
| 49 |
async down(queryInterface, Sequelize) {
|
| 50 |
await queryInterface.dropTable('invoice_details');
|
| 51 |
}
|
| 52 |
-
};
|
|
|
|
| 28 |
type: Sequelize.BIGINT,
|
| 29 |
},
|
| 30 |
pw_gl_account_id: {
|
| 31 |
+
type: Sequelize.BIGINT,
|
| 32 |
defaultValue: null,
|
| 33 |
},
|
| 34 |
amount: {
|
|
|
|
| 49 |
async down(queryInterface, Sequelize) {
|
| 50 |
await queryInterface.dropTable('invoice_details');
|
| 51 |
}
|
| 52 |
+
};
|
src/models/invoice.ts
CHANGED
|
@@ -7,8 +7,9 @@ import {
|
|
| 7 |
} from 'sequelize';
|
| 8 |
import { sequelize } from './index';
|
| 9 |
import { InvoiceInterface } from '../shared/interfaces/invoice.interface';
|
|
|
|
| 10 |
|
| 11 |
-
class Invoice extends Model<
|
| 12 |
declare id?: CreationOptional<number>;
|
| 13 |
declare reference_number: string;
|
| 14 |
declare vendor_name: string;
|
|
@@ -21,6 +22,7 @@ class Invoice extends Model<InferAttributes<Invoice>, InferCreationAttributes<In
|
|
| 21 |
declare payment_status?: string;
|
| 22 |
declare pw_work_order_id?: number;
|
| 23 |
declare pw_vendor_id?: number;
|
|
|
|
| 24 |
declare pdf_url?: string;
|
| 25 |
declare status: string;
|
| 26 |
declare uploaded_by: number;
|
|
@@ -35,24 +37,19 @@ Invoice.init(
|
|
| 35 |
},
|
| 36 |
reference_number: {
|
| 37 |
type: DataTypes.STRING(100),
|
| 38 |
-
allowNull: false,
|
| 39 |
unique: true,
|
| 40 |
},
|
| 41 |
vendor_name: {
|
| 42 |
type: DataTypes.STRING(255),
|
| 43 |
-
allowNull: false,
|
| 44 |
},
|
| 45 |
invoice_date: {
|
| 46 |
type: DataTypes.DATE,
|
| 47 |
-
allowNull: false,
|
| 48 |
},
|
| 49 |
total: {
|
| 50 |
type: DataTypes.DECIMAL(10, 2),
|
| 51 |
-
allowNull: false,
|
| 52 |
},
|
| 53 |
amount_paid: {
|
| 54 |
type: DataTypes.DECIMAL(10, 2),
|
| 55 |
-
allowNull: false,
|
| 56 |
},
|
| 57 |
due_date: {
|
| 58 |
type: DataTypes.DATE,
|
|
@@ -78,6 +75,10 @@ Invoice.init(
|
|
| 78 |
type: DataTypes.INTEGER,
|
| 79 |
allowNull: true,
|
| 80 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
pdf_url: {
|
| 82 |
type: DataTypes.STRING(255),
|
| 83 |
allowNull: true,
|
|
@@ -102,5 +103,6 @@ Invoice.init(
|
|
| 102 |
}
|
| 103 |
);
|
| 104 |
|
|
|
|
| 105 |
|
| 106 |
-
export default Invoice;
|
|
|
|
| 7 |
} from 'sequelize';
|
| 8 |
import { sequelize } from './index';
|
| 9 |
import { InvoiceInterface } from '../shared/interfaces/invoice.interface';
|
| 10 |
+
import User from './users';
|
| 11 |
|
| 12 |
+
class Invoice extends Model<InvoiceInterface> implements InvoiceInterface {
|
| 13 |
declare id?: CreationOptional<number>;
|
| 14 |
declare reference_number: string;
|
| 15 |
declare vendor_name: string;
|
|
|
|
| 22 |
declare payment_status?: string;
|
| 23 |
declare pw_work_order_id?: number;
|
| 24 |
declare pw_vendor_id?: number;
|
| 25 |
+
declare filename?: string;
|
| 26 |
declare pdf_url?: string;
|
| 27 |
declare status: string;
|
| 28 |
declare uploaded_by: number;
|
|
|
|
| 37 |
},
|
| 38 |
reference_number: {
|
| 39 |
type: DataTypes.STRING(100),
|
|
|
|
| 40 |
unique: true,
|
| 41 |
},
|
| 42 |
vendor_name: {
|
| 43 |
type: DataTypes.STRING(255),
|
|
|
|
| 44 |
},
|
| 45 |
invoice_date: {
|
| 46 |
type: DataTypes.DATE,
|
|
|
|
| 47 |
},
|
| 48 |
total: {
|
| 49 |
type: DataTypes.DECIMAL(10, 2),
|
|
|
|
| 50 |
},
|
| 51 |
amount_paid: {
|
| 52 |
type: DataTypes.DECIMAL(10, 2),
|
|
|
|
| 53 |
},
|
| 54 |
due_date: {
|
| 55 |
type: DataTypes.DATE,
|
|
|
|
| 75 |
type: DataTypes.INTEGER,
|
| 76 |
allowNull: true,
|
| 77 |
},
|
| 78 |
+
filename:{
|
| 79 |
+
type: DataTypes.STRING(255),
|
| 80 |
+
allowNull: false,
|
| 81 |
+
},
|
| 82 |
pdf_url: {
|
| 83 |
type: DataTypes.STRING(255),
|
| 84 |
allowNull: true,
|
|
|
|
| 103 |
}
|
| 104 |
);
|
| 105 |
|
| 106 |
+
Invoice.belongsTo(User, { foreignKey: 'uploaded_by', as: 'uploadedBy' });
|
| 107 |
|
| 108 |
+
export default Invoice;
|
src/routes/invoice.routes.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import express from 'express';
|
| 2 |
+
import { multipleUpload } from '../middlewares/multer';
|
| 3 |
+
|
| 4 |
+
import {
|
| 5 |
+
createInvoice,
|
| 6 |
+
getAllInvoices,
|
| 7 |
+
getInvoiceById,
|
| 8 |
+
deleteInvoice,
|
| 9 |
+
} from '../controllers/invoice/invoice.controller';
|
| 10 |
+
|
| 11 |
+
const invoiceRouter = express.Router();
|
| 12 |
+
|
| 13 |
+
invoiceRouter.post("/", multipleUpload, createInvoice);
|
| 14 |
+
invoiceRouter.get('/', getAllInvoices);
|
| 15 |
+
invoiceRouter.get('/:id', getInvoiceById);
|
| 16 |
+
invoiceRouter.delete('/:id', deleteInvoice);
|
| 17 |
+
|
| 18 |
+
export default invoiceRouter;
|
src/routes/{index.ts → propertyware.routes.ts}
RENAMED
|
@@ -1,22 +1,17 @@
|
|
| 1 |
import express from "express";
|
| 2 |
-
import { multipleUpload } from '../middlewares/multer';
|
| 3 |
|
| 4 |
-
import {
|
| 5 |
import { fetchGLAccountsData } from "../controllers/propertyware/glAccounts.controller";
|
| 6 |
import { syncPortfolioData } from "../controllers/propertyware/portfolio.controller";
|
| 7 |
-
import { syncBuildingsData } from "../controllers/propertyware/buildings.controller";
|
| 8 |
import { syncUnitsData } from "../controllers/propertyware/units.controller";
|
| 9 |
-
import {
|
| 10 |
-
|
| 11 |
-
const router = express.Router();
|
| 12 |
-
|
| 13 |
-
router.get("/pw/glAccounts", fetchGLAccountsData);
|
| 14 |
-
router.get("/pw/vendors", fetchVendorsData);
|
| 15 |
-
router.get("/pw/syncPortfolio", syncPortfolioData);
|
| 16 |
-
router.get("/pw/syncBuildings", syncBuildingsData);
|
| 17 |
-
router.get("/pw/syncUnits", syncUnitsData);
|
| 18 |
|
| 19 |
-
|
| 20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
|
| 22 |
-
export default
|
|
|
|
| 1 |
import express from "express";
|
|
|
|
| 2 |
|
| 3 |
+
import { syncBuildingsData } from "../controllers/propertyware/buildings.controller";
|
| 4 |
import { fetchGLAccountsData } from "../controllers/propertyware/glAccounts.controller";
|
| 5 |
import { syncPortfolioData } from "../controllers/propertyware/portfolio.controller";
|
|
|
|
| 6 |
import { syncUnitsData } from "../controllers/propertyware/units.controller";
|
| 7 |
+
import { fetchVendorsData } from "../controllers/propertyware/vendors.controller";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
|
| 9 |
+
const pwRouter = express.Router();
|
| 10 |
|
| 11 |
+
pwRouter.get("/glAccounts", fetchGLAccountsData);
|
| 12 |
+
pwRouter.get("/vendors", fetchVendorsData);
|
| 13 |
+
pwRouter.get("/syncPortfolio", syncPortfolioData);
|
| 14 |
+
pwRouter.get("/syncBuildings", syncBuildingsData);
|
| 15 |
+
pwRouter.get("/syncUnits", syncUnitsData);
|
| 16 |
|
| 17 |
+
export default pwRouter;
|
src/shared/interfaces/invoice.interface.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
| 1 |
export interface InvoiceInterface {
|
| 2 |
id?: number;
|
| 3 |
-
reference_number: string;
|
| 4 |
-
vendor_name: string;
|
| 5 |
-
invoice_date: Date;
|
| 6 |
-
total: number;
|
| 7 |
amount_paid: number;
|
| 8 |
due_date?: Date;
|
| 9 |
term?: string;
|
|
@@ -11,6 +11,7 @@ export interface InvoiceInterface {
|
|
| 11 |
payment_status?: string;
|
| 12 |
pw_work_order_id?: number;
|
| 13 |
pw_vendor_id?: number;
|
|
|
|
| 14 |
pdf_url?: string;
|
| 15 |
status: string;
|
| 16 |
uploaded_by: number;
|
|
|
|
| 1 |
export interface InvoiceInterface {
|
| 2 |
id?: number;
|
| 3 |
+
reference_number?: string;
|
| 4 |
+
vendor_name?: string;
|
| 5 |
+
invoice_date?: Date;
|
| 6 |
+
total?: number;
|
| 7 |
amount_paid: number;
|
| 8 |
due_date?: Date;
|
| 9 |
term?: string;
|
|
|
|
| 11 |
payment_status?: string;
|
| 12 |
pw_work_order_id?: number;
|
| 13 |
pw_vendor_id?: number;
|
| 14 |
+
filename?: string;
|
| 15 |
pdf_url?: string;
|
| 16 |
status: string;
|
| 17 |
uploaded_by: number;
|
src/shared/services/invoice.service.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
| 1 |
import { s3 } from '../../middlewares/multer';
|
| 2 |
|
| 3 |
export const uploadInvoice = (files: Express.Multer.File[]) => {
|
| 4 |
-
console.log(files);
|
| 5 |
-
|
| 6 |
const uploadPromises = files.map(file => {
|
| 7 |
const params = {
|
| 8 |
Bucket: process.env.AWS_S3_BUCKET_NAME || '',
|
|
|
|
| 1 |
import { s3 } from '../../middlewares/multer';
|
| 2 |
|
| 3 |
export const uploadInvoice = (files: Express.Multer.File[]) => {
|
|
|
|
|
|
|
| 4 |
const uploadPromises = files.map(file => {
|
| 5 |
const params = {
|
| 6 |
Bucket: process.env.AWS_S3_BUCKET_NAME || '',
|
yarn.lock
CHANGED
|
@@ -1546,6 +1546,15 @@ __metadata:
|
|
| 1546 |
languageName: node
|
| 1547 |
linkType: hard
|
| 1548 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1549 |
"@types/debug@npm:^4.1.8":
|
| 1550 |
version: 4.1.12
|
| 1551 |
resolution: "@types/debug@npm:4.1.12"
|
|
@@ -2534,6 +2543,16 @@ __metadata:
|
|
| 2534 |
languageName: node
|
| 2535 |
linkType: hard
|
| 2536 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2537 |
"create-require@npm:^1.1.0":
|
| 2538 |
version: 1.1.1
|
| 2539 |
resolution: "create-require@npm:1.1.1"
|
|
@@ -3138,7 +3157,7 @@ __metadata:
|
|
| 3138 |
resolution: "fb-api@workspace:."
|
| 3139 |
dependencies:
|
| 3140 |
"@aws-sdk/client-s3": "npm:^3.614.0"
|
| 3141 |
-
"@types/
|
| 3142 |
"@types/dotenv": "npm:^8.2.0"
|
| 3143 |
"@types/express": "npm:^4.17.21"
|
| 3144 |
"@types/multer": "npm:^1"
|
|
@@ -3149,7 +3168,7 @@ __metadata:
|
|
| 3149 |
aws-sdk: "npm:^2.1659.0"
|
| 3150 |
axios: "npm:^1.7.2"
|
| 3151 |
babel-register: "npm:^6.26.0"
|
| 3152 |
-
|
| 3153 |
dotenv: "npm:^16.4.5"
|
| 3154 |
eslint: "npm:^9.7.0"
|
| 3155 |
eslint-config-prettier: "npm:^9.1.0"
|
|
@@ -4473,7 +4492,7 @@ __metadata:
|
|
| 4473 |
languageName: node
|
| 4474 |
linkType: hard
|
| 4475 |
|
| 4476 |
-
"object-assign@npm:^4.1.1":
|
| 4477 |
version: 4.1.1
|
| 4478 |
resolution: "object-assign@npm:4.1.1"
|
| 4479 |
checksum: 10c0/1f4df9945120325d041ccf7b86f31e8bcc14e73d29171e37a7903050e96b81323784ec59f93f102ec635bcf6fa8034ba3ea0a8c7e69fa202b87ae3b6cec5a414
|
|
@@ -5675,7 +5694,7 @@ __metadata:
|
|
| 5675 |
languageName: node
|
| 5676 |
linkType: hard
|
| 5677 |
|
| 5678 |
-
"vary@npm:~1.1.2":
|
| 5679 |
version: 1.1.2
|
| 5680 |
resolution: "vary@npm:1.1.2"
|
| 5681 |
checksum: 10c0/f15d588d79f3675135ba783c91a4083dcd290a2a5be9fcb6514220a1634e23df116847b1cc51f66bfb0644cf9353b2abb7815ae499bab06e46dd33c1a6bf1f4f
|
|
|
|
| 1546 |
languageName: node
|
| 1547 |
linkType: hard
|
| 1548 |
|
| 1549 |
+
"@types/cors@npm:^2":
|
| 1550 |
+
version: 2.8.17
|
| 1551 |
+
resolution: "@types/cors@npm:2.8.17"
|
| 1552 |
+
dependencies:
|
| 1553 |
+
"@types/node": "npm:*"
|
| 1554 |
+
checksum: 10c0/457364c28c89f3d9ed34800e1de5c6eaaf344d1bb39af122f013322a50bc606eb2aa6f63de4e41a7a08ba7ef454473926c94a830636723da45bf786df032696d
|
| 1555 |
+
languageName: node
|
| 1556 |
+
linkType: hard
|
| 1557 |
+
|
| 1558 |
"@types/debug@npm:^4.1.8":
|
| 1559 |
version: 4.1.12
|
| 1560 |
resolution: "@types/debug@npm:4.1.12"
|
|
|
|
| 2543 |
languageName: node
|
| 2544 |
linkType: hard
|
| 2545 |
|
| 2546 |
+
"cors@npm:^2.8.5":
|
| 2547 |
+
version: 2.8.5
|
| 2548 |
+
resolution: "cors@npm:2.8.5"
|
| 2549 |
+
dependencies:
|
| 2550 |
+
object-assign: "npm:^4"
|
| 2551 |
+
vary: "npm:^1"
|
| 2552 |
+
checksum: 10c0/373702b7999409922da80de4a61938aabba6929aea5b6fd9096fefb9e8342f626c0ebd7507b0e8b0b311380744cc985f27edebc0a26e0ddb784b54e1085de761
|
| 2553 |
+
languageName: node
|
| 2554 |
+
linkType: hard
|
| 2555 |
+
|
| 2556 |
"create-require@npm:^1.1.0":
|
| 2557 |
version: 1.1.1
|
| 2558 |
resolution: "create-require@npm:1.1.1"
|
|
|
|
| 3157 |
resolution: "fb-api@workspace:."
|
| 3158 |
dependencies:
|
| 3159 |
"@aws-sdk/client-s3": "npm:^3.614.0"
|
| 3160 |
+
"@types/cors": "npm:^2"
|
| 3161 |
"@types/dotenv": "npm:^8.2.0"
|
| 3162 |
"@types/express": "npm:^4.17.21"
|
| 3163 |
"@types/multer": "npm:^1"
|
|
|
|
| 3168 |
aws-sdk: "npm:^2.1659.0"
|
| 3169 |
axios: "npm:^1.7.2"
|
| 3170 |
babel-register: "npm:^6.26.0"
|
| 3171 |
+
cors: "npm:^2.8.5"
|
| 3172 |
dotenv: "npm:^16.4.5"
|
| 3173 |
eslint: "npm:^9.7.0"
|
| 3174 |
eslint-config-prettier: "npm:^9.1.0"
|
|
|
|
| 4492 |
languageName: node
|
| 4493 |
linkType: hard
|
| 4494 |
|
| 4495 |
+
"object-assign@npm:^4, object-assign@npm:^4.1.1":
|
| 4496 |
version: 4.1.1
|
| 4497 |
resolution: "object-assign@npm:4.1.1"
|
| 4498 |
checksum: 10c0/1f4df9945120325d041ccf7b86f31e8bcc14e73d29171e37a7903050e96b81323784ec59f93f102ec635bcf6fa8034ba3ea0a8c7e69fa202b87ae3b6cec5a414
|
|
|
|
| 5694 |
languageName: node
|
| 5695 |
linkType: hard
|
| 5696 |
|
| 5697 |
+
"vary@npm:^1, vary@npm:~1.1.2":
|
| 5698 |
version: 1.1.2
|
| 5699 |
resolution: "vary@npm:1.1.2"
|
| 5700 |
checksum: 10c0/f15d588d79f3675135ba783c91a4083dcd290a2a5be9fcb6514220a1634e23df116847b1cc51f66bfb0644cf9353b2abb7815ae499bab06e46dd33c1a6bf1f4f
|