| Current Path : /proc/thread-self/root/home/deltalab/PMS/partner-manager-backend/services/ |
| Current File : //proc/thread-self/root/home/deltalab/PMS/partner-manager-backend/services/billing.js |
/* eslint-disable new-cap */
/* eslint-disable no-await-in-loop */
/* eslint-disable no-use-before-define */
/**
* Billing service
* Builds up invoices and billings to be inserted in the DB
*/
const { invoiceModel, royaltyModel, warehouseCostModel } = require('../models/mongoose/invoice');
const { partnerModel } = require('../models/mongoose/partner');
const { orderModel } = require('../models/mongoose/order');
const { subscriptionPlanModel } = require('../models/mongoose/subscription-plan');
const { indacoModuleModel } = require('../models/mongoose/indaco-module');
const { warehouseModel } = require('../models/mongoose/warehouse');
const { warehouseJournalModel } = require('../models/mongoose/warehouse-journal');
async function createInvoice(invoicePId, startDate, endDate) {
const invoice = new invoiceModel();
// Filling the common fields
invoice.partnerId = invoicePId;
invoice.startDate = startDate;
invoice.endDate = endDate;
// Find the partner's financial details
const partner = await partnerModel.findById(invoicePId);
if (!partner) {
return { error: 'No partner with the specified Id found' };
}
invoice.companyName = partner.companyName;
invoice.companyAddress = partner.address;
invoice.partnerVatNumber = partner.vatNumber;
// Fill in the INDACO
invoice.indacoCompanyName = 'INDACO SpA';
invoice.indacoVatNumber = 'Some VAT number';
invoice.indacoAddress = 'Via Kufstein 5, Trento';
// Fetch and fill all the orders for the specified partner
const query = {};
query.partnerId = invoicePId;
query.fullyPaid = true;
query.createdAt = {
$gte: startDate,
$lt: endDate,
};
const orders = await orderModel.find(query);
invoice.orders = orders;
// Fetch the subscription plan and calculate the costs
const partnerPlan = await subscriptionPlanModel.findById(partner.subscriptionPlanId);
const subscriptionModules = await indacoModuleModel.find({ '_id': { $in: partnerPlan.indacoModulesIds } });
subscriptionModules.forEach((module) => {
invoice.services.push(module);
});
// Calculate all the royalties for the orders based on the plan
orders.forEach((order) => {
const royalty = new royaltyModel();
royalty.orderId = order.omsgid;
royalty.royaltyAmount = (order.totalPriceSet.amount.valueOf() * partnerPlan.royaltyRate.valueOf()) / 100;
royalty.currency = order.totalPriceSet.currencyCode;
invoice.royalties.push(royalty);
});
const sharedWarehouses = await warehouseModel.find({ isShared: true });
for (let i = 0; i < sharedWarehouses.length; i++) {
for (let j = 0; j < sharedWarehouses[i].assignments.length; j++) {
if (sharedWarehouses[i].assignments[j].partnerId === invoicePId) {
invoice.warehouseCosts.push(await generateWarehouseInboundCost(sharedWarehouses[i].assignments[j], sharedWarehouses[i], invoicePId, startDate, endDate));
invoice.warehouseCosts.push(await generateWarehouseStorageCost(sharedWarehouses[i].assignments[j], sharedWarehouses[i]));
invoice.warehouseCosts.push(await generateWarehouseOrderCost(sharedWarehouses[i].assignments[j], sharedWarehouses[i], startDate, endDate));
}
}
}
return invoice;
}
async function generateWarehouseInboundCost(assignment, warehouse, partnerId, startDate, endDate) {
const journalEntries = await warehouseJournalModel.find({
$and: [
{ partnerId },
{ $or: [{ reason: 'INITIAL' }, { reason: 'INCREASE' }] },
{ date: { $gt: startDate } },
{ date: { $lt: endDate } },
{ warehouseId: warehouse._id },
{ refrigerated: assignment.refrigerated },
],
});
const warehouseInboundCost = new warehouseCostModel();
warehouseInboundCost.costObject = 'INBOUND';
warehouseInboundCost.warehouseId = warehouse._id;
warehouseInboundCost.warehouseName = warehouse.name;
warehouseInboundCost.rate = assignment.inboundRate;
warehouseInboundCost.total = warehouseInboundCost.rate * journalEntries.length;
warehouseInboundCost.currency = 'EUR';
return warehouseInboundCost;
}
async function generateWarehouseStorageCost(assignment, warehouse) {
const warehouseStorageCost = new warehouseCostModel();
warehouseStorageCost.costObject = 'STORAGE';
warehouseStorageCost.warehouseId = warehouse._id;
warehouseStorageCost.warehouseName = warehouse.name;
warehouseStorageCost.rate = assignment.storageRate;
warehouseStorageCost.total = warehouseStorageCost.rate * assignment.minimumStorage;
warehouseStorageCost.currency = 'EUR';
return warehouseStorageCost;
}
async function generateWarehouseOrderCost(assignment, warehouse, startDate, endDate) {
const journalEntries = await warehouseJournalModel.find({
$and: [
{ partnerId: assignment.partnerId },
{ reason: 'ORDER' },
{ date: { $gt: startDate } },
{ date: { $lt: endDate } },
{ warehouseId: warehouse._id },
{ refrigerated: assignment.refrigerated },
],
});
const warehouseOrderCost = new warehouseCostModel();
warehouseOrderCost.costObject = 'ORDER';
warehouseOrderCost.warehouseId = warehouse._id;
warehouseOrderCost.warehouseName = warehouse.name;
warehouseOrderCost.rate = assignment.orderRate;
warehouseOrderCost.total = warehouseOrderCost.rate * journalEntries.length;
warehouseOrderCost.currency = 'EUR';
return warehouseOrderCost;
}
async function fetchInvoicesPeriod(partnerId, startDate, endDate) {
const query = {};
query.partnerId = partnerId;
query.createdAt = {
$gte: startDate,
$lt: endDate,
};
const invoices = await invoiceModel.find(query);
return invoices;
}
module.exports = {
createInvoice,
fetchInvoicesPeriod,
};