Skip to content
This repository was archived by the owner on May 6, 2022. It is now read-only.

Commit 6d7045d

Browse files
authored
Merge pull request #107 from Tolfix/dev
v3.3
2 parents c96fcec + a9ef08f commit 6d7045d

13 files changed

+179
-110
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cpg-api",
3-
"version": "v3.2",
3+
"version": "v3.3",
44
"description": "Central Payment Gateway",
55
"main": "./build/Main.js",
66
"dependencies": {

src/Admin/Commands/Cron.prompt.ts

+10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { cron_chargeStripePayment, cron_notifyInvoices, cron_notifyLateInvoicePaid } from "../../Cron/Methods/Invoices.cron.methods";
2+
import { cron_createNewInvoicesFromOrders } from "../../Cron/Methods/Orders.cron.methods";
23
import Logger from "../../Lib/Logger";
34

45
export default
@@ -22,6 +23,10 @@ export default
2223
{
2324
name: 'Invoice late notify',
2425
value: 'run_late_invoice_notify',
26+
},
27+
{
28+
name: "Create invoice from order",
29+
value: 'run_create_invoice_from_order',
2530
}
2631
],
2732
}
@@ -43,6 +48,11 @@ export default
4348
Logger.info('Running Invoice late notify');
4449
cron_notifyLateInvoicePaid()
4550
}
51+
if(crons.includes('run_create_invoice_from_order'))
52+
{
53+
Logger.info('Running Create invoice from order');
54+
cron_createNewInvoicesFromOrders();
55+
}
4656
return true;
4757
}
4858
}

src/Admin/Commands/Invoices.prompt.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,10 @@ export default
166166
}
167167

168168
invoice.paid = true;
169-
169+
invoice.dates.date_paid = getDate();
170+
invoice.markModified('dates');
170171
await invoice.save();
172+
mainEvent.emit("invoice_paid", invoice);
171173
Logger.info(`Invoice with id ${invoiceId} marked as paid`);
172174
break;
173175
}

src/Admin/Commands/Orders.prompt.ts

+21-10
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import mainEvent from "../../Events/Main.event";
1313
import { sendEmail } from "../../Email/Send";
1414
import NewOrderCreated from "../../Email/Templates/Orders/NewOrderCreated";
1515
import { Company_Name } from "../../Config";
16+
import { createInvoiceFromOrder } from "../../Lib/Orders/newInvoice";
17+
import { sendInvoiceEmail } from "../../Lib/Invoices/SendEmail";
1618

1719
export default
1820
{
@@ -91,7 +93,7 @@ export default
9193
name: 'currency',
9294
type: 'search-list',
9395
message: 'Enter the currency',
94-
choices: currencyCodes
96+
choices: [...currencyCodes, "Customer Currency"]
9597
},
9698
{
9799
name: 'products',
@@ -178,18 +180,25 @@ export default
178180
}
179181
});
180182

183+
const customer = await CustomerModel.findOne({
184+
id: customer_uid,
185+
});
186+
187+
if(!customer)
188+
throw new Error(`Fail to find customer with id: ${customer_uid}`);
189+
181190
const b_recurring = action2Result.billing_type === "recurring";
182191
const newOrder = await (new OrderModel({
183192
uid: idOrder(),
184193
invoices: [],
185-
currency,
194+
currency: currency === "Customer Currency" ? customer.currency : currency,
186195
customer_uid,
187196
dates: {
188197
createdAt: new Date(),
189198
last_recycle: b_recurring ? dateFormat.format(new Date(), "YYYY-MM-DD") : undefined,
190199
next_recycle: b_recurring ? dateFormat.format(nextRycleDate(new Date(), action2Result.billing_cycle), "YYYY-MM-DD") : undefined,
191200
},
192-
order_status: 'pending',
201+
order_status: 'active',
193202
payment_method,
194203
products: newProduct,
195204
billing_type: action2Result.billing_type,
@@ -200,13 +209,6 @@ export default
200209

201210
mainEvent.emit("order_created", newOrder);
202211

203-
const customer = await CustomerModel.findOne({
204-
id: customer_uid,
205-
});
206-
207-
if(!customer)
208-
throw new Error(`Fail to find customer with id: ${customer_uid}`);
209-
210212
await sendEmail({
211213
receiver: customer.personal.email,
212214
subject: `New order from ${await Company_Name() !== "" ? await Company_Name() : "CPG"} #${newOrder.id}`,
@@ -217,6 +219,15 @@ export default
217219

218220
Logger.info(newOrder);
219221

222+
// Creating new invoice
223+
const invoice = await createInvoiceFromOrder(newOrder);
224+
await sendInvoiceEmail(invoice, customer);
225+
226+
newOrder.invoices.push(invoice.id);
227+
await newOrder.save();
228+
229+
Logger.info(`Created new invoice:`, invoice);
230+
220231
break;
221232
}
222233

src/Cron/Methods/Invoices.cron.methods.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import GetText from "../../Translation/GetText";
66
import CustomerModel from "../../Database/Models/Customers/Customer.model";
77
import { sendInvoiceEmail, sendLateInvoiceEmail } from "../../Lib/Invoices/SendEmail";
88
import { ChargeCustomer } from "../../Payments/Stripe";
9-
import { InvoiceNotifiedReport } from "../../Email/Reports/InvoiceReport";
9+
import { InvoiceLateReport, InvoiceNotifiedReport } from "../../Email/Reports/InvoiceReport";
1010
import mainEvent from "../../Events/Main.event";
1111
import { getDate } from "../../Lib/Time";
1212

@@ -44,7 +44,7 @@ export function cron_notifyInvoices()
4444
for await(const invoice of invoices)
4545
{
4646
// Get customer
47-
const Customer = await CustomerModel.findOne({ id: invoice.customer_uid});
47+
const Customer = await CustomerModel.findOne({ id: invoice.customer_uid });
4848
if(!Customer)
4949
continue;
5050

@@ -143,9 +143,9 @@ export function cron_notifyLateInvoicePaid()
143143
const Customer = await CustomerModel.findOne({ id: invoice.customer_uid});
144144
if(!Customer)
145145
continue;
146-
147146
await sendLateInvoiceEmail(invoice, Customer);
148-
149147
}
148+
if(invoices.length > 0)
149+
await InvoiceLateReport(invoices);
150150
});
151151
}
+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { Default_Language, d_Days } from "../../Config";
2+
import OrderModel from "../../Database/Models/Orders.model";
3+
import Logger from "../../Lib/Logger";
4+
import GetText from "../../Translation/GetText";
5+
import dateFormat from "date-and-time";
6+
import nextRecycleDate from "../../Lib/Dates/DateCycle";
7+
import { createInvoiceFromOrder } from "../../Lib/Orders/newInvoice";
8+
import { InvoiceCreatedReport } from "../../Email/Reports/InvoiceReport";
9+
10+
// Logger.info(`Checking orders..`);
11+
export function cron_createNewInvoicesFromOrders()
12+
{
13+
Logger.info(GetText(Default_Language).cron.txt_Orders_Checking);
14+
// Check if the order needs to create a new invoice if order.dates.next_recycle is withing 14 days
15+
OrderModel.find({
16+
order_status: "active",
17+
// order_status: {
18+
// $not: /fraud|cancelled|draft|refunded/g
19+
// }
20+
}).then(async orders =>
21+
{
22+
const newInvoices = [];
23+
// orders.forEach(async order => {
24+
for await(const order of orders)
25+
{
26+
Logger.info(GetText(Default_Language).cron.txt_Order_Checking(order.id));
27+
// Logger.info(`Checking order ${order.id}`);
28+
// Check if order.order_status is not "cancelled" or "fraud"
29+
if(order.dates.next_recycle)
30+
if(dateFormat.parse(order.dates.next_recycle, "YYYY-MM-DD").getTime() - new Date().getTime() <= d_Days * 24 * 60 * 60 * 1000)
31+
{
32+
const temptNextRecycle = order.dates.next_recycle;
33+
order.dates.last_recycle = temptNextRecycle;
34+
// Update order.dates.next_recycle
35+
order.dates.next_recycle = dateFormat.format(nextRecycleDate(
36+
dateFormat.parse(temptNextRecycle, "YYYY-MM-DD"), order.billing_cycle ?? "monthly")
37+
, "YYYY-MM-DD");
38+
// Create a new invoice
39+
const newInvoice = await createInvoiceFromOrder(order);
40+
newInvoices.push(newInvoice);
41+
42+
// Save the invoice in order.invoices array
43+
order.invoices.push(newInvoice.id);
44+
45+
// mark order updated in dates
46+
order.markModified("dates");
47+
order.markModified("invoices");
48+
// Save the order
49+
await order.save();
50+
}
51+
if(newInvoices.length > 0)
52+
await InvoiceCreatedReport(newInvoices);
53+
}
54+
});
55+
}

src/Cron/Orders.cron.ts

+2-53
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,11 @@
11
import { CronJob } from "cron";
2-
import OrderModel from "../Database/Models/Orders.model";
3-
import Logger from "../Lib/Logger";
4-
import dateFormat from "date-and-time";
5-
import { createInvoiceFromOrder } from "../Lib/Orders/newInvoice";
6-
import nextRecycleDate from "../Lib/Dates/DateCycle";
7-
import { Default_Language, d_Days } from "../Config";
8-
import { InvoiceCreatedReport } from "../Email/Reports/InvoiceReport";
9-
import GetText from "../Translation/GetText";
2+
import { cron_createNewInvoicesFromOrders } from "./Methods/Orders.cron.methods";
103

114
export = function Cron_Orders()
125
{
136
// Every hour
147
new CronJob("0 12 * * *", () =>
158
{
16-
Logger.info(GetText(Default_Language).cron.txt_Orders_Checking);
17-
// Logger.info(`Checking orders..`);
18-
19-
// Check if the order needs to create a new invoice if order.dates.next_recycle is withing 14 days
20-
OrderModel.find({
21-
order_status: "active",
22-
// order_status: {
23-
// $not: /fraud|cancelled|draft|refunded/g
24-
// }
25-
}).then(async orders =>
26-
{
27-
const newInvoices = [];
28-
// orders.forEach(async order => {
29-
for await(const order of orders)
30-
{
31-
Logger.info(GetText(Default_Language).cron.txt_Order_Checking(order.id));
32-
// Logger.info(`Checking order ${order.id}`);
33-
// Check if order.order_status is not "cancelled" or "fraud"
34-
if(order.dates.next_recycle)
35-
if(dateFormat.parse(order.dates.next_recycle, "YYYY-MM-DD").getTime() - new Date().getTime() <= d_Days * 24 * 60 * 60 * 1000)
36-
{
37-
const temptNextRecycle = order.dates.next_recycle;
38-
order.dates.last_recycle = temptNextRecycle;
39-
// Update order.dates.next_recycle
40-
order.dates.next_recycle = dateFormat.format(nextRecycleDate(
41-
dateFormat.parse(temptNextRecycle, "YYYY-MM-DD"), order.billing_cycle ?? "monthly")
42-
, "YYYY-MM-DD");
43-
// Create a new invoice
44-
const newInvoice = await createInvoiceFromOrder(order);
45-
newInvoices.push(newInvoice);
46-
47-
// Save the invoice in order.invoices array
48-
order.invoices.push(newInvoice.id);
49-
50-
// mark order updated in dates
51-
order.markModified("dates");
52-
order.markModified("invoices");
53-
// Save the order
54-
await order.save();
55-
}
56-
if(newInvoices.length > 0)
57-
await InvoiceCreatedReport(newInvoices);
58-
}
59-
});
60-
9+
cron_createNewInvoicesFromOrders();
6110
}, null, true, "Europe/Stockholm");
6211
}

src/Email/Reports/InvoiceReport.ts

+44-36
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,79 @@
11
import { GetSMTPEmails } from "../../Config";
22
import { IInvoice } from "@interface/Invoice.interface";
33
import { SendEmail } from "../Send";
4+
import UseStyles from "../Templates/General/UseStyles";
5+
import { stripIndent } from "common-tags";
46

57
export const InvoiceNotifiedReport = async (invoices: IInvoice[]) =>
68
{
7-
GetSMTPEmails().then((emails) =>
9+
GetSMTPEmails().then(async (emails) =>
810
{
9-
for(const email of emails)
11+
for await(const email of emails)
1012
{
1113
SendEmail(email, "Invoice(s) Notified", {
1214
isHTML: true,
13-
body: `
14-
<h1>Invoice(s) Notified</h1>
15-
<p>
16-
${invoices.length} invoices have been notified.
17-
</p>
18-
<p>
19-
The following invoices have been notified:
20-
${invoices.map((invoice) => `<br><strong>${invoice.id}</strong>`).join("")}
21-
</p>
22-
`
15+
body: await UseStyles(stripIndent`
16+
<div>
17+
<h1>Invoice(s) Notified</h1>
18+
<p>
19+
${invoices.length} invoices have been notified.
20+
</p>
21+
<p>
22+
The following invoices have been notified:
23+
${invoices.map((invoice) => `<br><strong>${invoice.id}</strong>`).join("")}
24+
</p>
25+
</div>
26+
`)
2327
});
2428
}
2529
})
2630
};
2731

2832
export const InvoiceLateReport = async (invoices: IInvoice[]) =>
2933
{
30-
GetSMTPEmails().then((emails) =>
34+
GetSMTPEmails().then(async (emails) =>
3135
{
32-
for(const email of emails)
36+
for await(const email of emails)
3337
{
3438
SendEmail(email, "Invoice(s) Late Reminder", {
3539
isHTML: true,
36-
body: `
37-
<h1>Invoice(s) Reminded</h1>
38-
<p>
39-
${invoices.length} invoices have been reminded.
40-
</p>
41-
<p>
42-
The following invoices have been reminded:
43-
${invoices.map((invoice) => `<br><strong>${invoice.id}</strong>`).join("")}
44-
</p>
45-
`
40+
body: await UseStyles(stripIndent`
41+
<div>
42+
<h1>Invoice(s) Reminded</h1>
43+
<p>
44+
${invoices.length} invoices have been reminded.
45+
</p>
46+
<p>
47+
The following invoices have been reminded:
48+
${invoices.map((invoice) => `<br><strong>${invoice.id}</strong>`).join("")}
49+
</p>
50+
</div>
51+
`)
4652
});
4753
}
4854
})
4955
};
5056

5157
export const InvoiceCreatedReport = async (invoices: IInvoice[]) =>
5258
{
53-
GetSMTPEmails().then((emails) =>
59+
GetSMTPEmails().then(async (emails) =>
5460
{
55-
for(const email of emails)
61+
for await(const email of emails)
5662
{
5763
SendEmail(email, "Invoice(s) Created", {
5864
isHTML: true,
59-
body: `
60-
<h1>Invoice(s) Created</h1>
61-
<p>
62-
${invoices.length} invoices have been created.
63-
</p>
64-
<p>
65-
The following invoices have been created:
66-
${invoices.map((invoice) => `<br><strong>${invoice.id}</strong>`).join("")}
67-
</p>
68-
`
65+
body: await UseStyles(stripIndent`
66+
<div>
67+
<h1>Invoice(s) Created</h1>
68+
<p>
69+
${invoices.length} invoices have been created.
70+
</p>
71+
<p>
72+
The following invoices have been created:
73+
${invoices.map((invoice) => `<br><strong>${invoice.id}</strong>`).join("")}
74+
</p>
75+
</div>
76+
`)
6977
});
7078
}
7179
})

0 commit comments

Comments
 (0)