agmission/Development/server/controllers/log_payment.js

107 lines
3.8 KiB
JavaScript

'use strict';
const { AppParamError, AppError } = require('../helpers/app_error'),
{ Errors, UserTypes } = require('../helpers/constants'),
{ toFixedNumberString } = require('../helpers/utils'),
mongoose = require('mongoose'),
mongoUtil = require('../helpers/mongo'),
env = require('../helpers/env'),
{ Invoice, LogPayment } = require('../model'),
ObjectId = require('mongodb').ObjectId;
async function getLogPayments_get(req, res) {
const invoiceId = req?.query?.invoiceId;
const puid = req.userInfo?.puid;
const invoice = await Invoice.findOne({ _id: invoiceId, byPuid: puid });
if (!invoice) AppParamError.throw(Errors.INVOICE_NOT_FOUND);
const userId = req.uid;
const option = { invoice: invoice };
const isClientRole = req.ut === UserTypes.CLIENT;
if (isClientRole) option['client'] = userId;
const logPayments = await LogPayment.find(option).populate({ path: 'client', select: 'name email address phone' }).populate({ path: 'createdBy', select: 'name email address phone' });
res.json(logPayments);
}
async function insertLogPayment(logPaymentBody, puid, createdBy, session) {
const invoiceId = logPaymentBody?.invoiceId;
const clientId = logPaymentBody?.clientId;
const amount = logPaymentBody?.amount;
const invoice = await Invoice.findOne({ 'clients.billTo': clientId, _id: invoiceId, byPuid: puid });
if (!invoice) AppParamError.throw(Errors.INVOICE_NOT_FOUND);
// update invoice
const client = invoice?.clients?.find((client) => client?.billTo == clientId);
const amountPaid = client?.amountPaid ? Number(client?.amountPaid) + Number(amount) : Number(amount);
const totalExcludingTax = Number(client?.subTotal) * (1 - Number(client?.discount) / 100);
const total = toFixedNumberString(totalExcludingTax + totalExcludingTax * (Number(client?.taxRate) / 100));
const amountDue = Number(total) - amountPaid;
if (env.INV_OVERPAID_THRESHOLD && amountPaid > (Number(total) * (1 + (env.INV_OVERPAID_THRESHOLD * 1E-2)))) AppError.create(Errors.CLIENT_OVER_PAID);
client.amountPaid = toFixedNumberString(amountPaid);
client.amountDue = toFixedNumberString(amountDue);
const createdLogPayment = new LogPayment({ ...logPaymentBody, invoice: invoiceId, client: clientId, amount: toFixedNumberString(amount), amountDue: toFixedNumberString(amountDue), createdBy });
const logPayment = await createdLogPayment.save({ session });
await invoice.save({ session });
return logPayment;
}
async function createLogPayment_post(req, res) {
const logPaymentBody = req?.body;
const puid = req.userInfo?.puid;
if (!puid || !ObjectId.isValid(puid)) AppParamError.throw(Errors.INVALID_PUID);
const createdBy = req.uid;
if (!createdBy) AppParamError.throw(Errors.INVALID_CREATED_BY_USER_ID);
let logPayment;
await mongoUtil.runInTransaction(async (session) => {
logPayment = await insertLogPayment(logPaymentBody, puid, createdBy, session);
});
res.json(logPayment);
}
async function createLogPayments_post(req, res) {
const logPayments = [];
const logPaymentsBody = req.body;
const puid = req.userInfo?.puid;
if (!puid || !ObjectId.isValid(puid)) AppParamError.throw(Errors.INVALID_PUID);
const createdBy = req.uid;
if (!createdBy) AppParamError.throw(Errors.INVALID_CREATED_BY_USER_ID);
const session = await mongoose.startSession({ readPreference: { mode: "primary" } });
try {
session && session.startTransaction();
for (const logPayment of logPaymentsBody) {
const newLogPayment = await insertLogPayment(logPayment, puid, createdBy, session);
logPayments.push(newLogPayment);
}
session && await mongoUtil.commitWithRetry(session);
} catch (err) {
session && session.abortTransaction();
throw error;
} finally {
session && session.endSession();
}
res.json(logPayments);
}
module.exports = {
getLogPayments_get, createLogPayment_post, createLogPayments_post,
};