From a3a653cfdf8e4607882e42fa61310d631f94b0a3 Mon Sep 17 00:00:00 2001 From: panda jacobs Date: Thu, 5 May 2022 23:33:59 +0200 Subject: [PATCH 1/9] add reporting route with get all unpaid invoices --- src/controllers/reporting.ts | 17 +++++++++++++++++ src/routes/reporting.ts | 7 +++++++ src/server.ts | 15 +++------------ src/services/reporting.ts | 10 ++++++++++ src/utils/mysql.connector.ts | 4 ++-- 5 files changed, 39 insertions(+), 14 deletions(-) create mode 100644 src/controllers/reporting.ts create mode 100644 src/routes/reporting.ts create mode 100644 src/services/reporting.ts diff --git a/src/controllers/reporting.ts b/src/controllers/reporting.ts new file mode 100644 index 0000000..a2168a4 --- /dev/null +++ b/src/controllers/reporting.ts @@ -0,0 +1,17 @@ +import {Request, RequestHandler, Response} from 'express'; +import { getAllUnpaidInvoices } from "../services/reporting"; + +export const getUnpaidInvoices: RequestHandler = async (req: Request, res: Response) => { + try { + const invoice = await getAllUnpaidInvoices(); + + res.status(200).json({ + invoice + }); + } catch (error) { + console.log(error); + res.status(500).json({ + message: 'There was an error when fetching estimations' + }); + } +}; diff --git a/src/routes/reporting.ts b/src/routes/reporting.ts new file mode 100644 index 0000000..4e1d011 --- /dev/null +++ b/src/routes/reporting.ts @@ -0,0 +1,7 @@ +import express from "express"; +import { getUnpaidInvoices } from "../controllers/reporting"; + +const reportingRoutes = express.Router(); +reportingRoutes.get('/reporting/tariffs', getUnpaidInvoices); + +export = reportingRoutes; diff --git a/src/server.ts b/src/server.ts index deca38c..4216495 100644 --- a/src/server.ts +++ b/src/server.ts @@ -18,24 +18,14 @@ import * as DBConnector from './utils/mysql.connector'; import authRoutes from './routes/auth-routes'; import testRoutes from './routes/test-routes'; import bodyParser from 'body-parser'; - import cors from 'cors'; - import dotenv from 'dotenv'; -import { Env } from './utils/env'; +import reportingRoutes from './routes/reporting'; if (process.env.NODE_ENV == null || process.env.NODE_ENV === 'development') { dotenv.config(); } -try { - Env.validateMandatoryKeys(); -} catch (err) { - console.error('.env not properly configured: ', err); - process.exit(-1); -} - - const router: Express = express(); /** Middleware for CORS */ @@ -82,7 +72,8 @@ router.use('/api/', planningRoutes, tariffRoutes, supplierRoutes, - ticketRoutes + ticketRoutes, + reportingRoutes ); /** Error handling */ diff --git a/src/services/reporting.ts b/src/services/reporting.ts new file mode 100644 index 0000000..cadbee0 --- /dev/null +++ b/src/services/reporting.ts @@ -0,0 +1,10 @@ +import { Invoice } from "../classes/invoice"; +import { execute } from "../utils/mysql.connector"; + +//TODO change name to be more descriptive gets all unpaided invoices that are late +export const getAllUnpaidInvoices = async () => { + console.log(new Date().toISOString()); + + let invoices = execute<{rows: Invoice[]}>('SELECT * FROM invoices WHERE "DueDate" <= $1;', [new Date().toISOString()]); + return (await invoices).rows; +}; diff --git a/src/utils/mysql.connector.ts b/src/utils/mysql.connector.ts index c42f900..4caefce 100644 --- a/src/utils/mysql.connector.ts +++ b/src/utils/mysql.connector.ts @@ -7,7 +7,7 @@ export function init() { const credentials = { user: "ad", host: "10.97.0.10", - database: "ADWEBSITE", + database: "TestADwebsite", password: "Ad2022%", port: 5432, }; @@ -47,4 +47,4 @@ export const execute = (query: string, params: any[]): Promise => { console.error('[mysql.connector][execute][Error]: ', error); throw new Error('failed to execute MySQL query'); } -} \ No newline at end of file +} From db288be400dd99c59cb267391639713b7b323d01 Mon Sep 17 00:00:00 2001 From: panda jacobs Date: Thu, 12 May 2022 00:01:34 +0200 Subject: [PATCH 2/9] move invoice from reporting to invoice, add routes --- src/classes/invoice.ts | 16 +++++++++++++--- src/controllers/invoice-controller.ts | 24 ++++++++++++++++++++++++ src/controllers/reporting.ts | 17 ----------------- src/routes/invoice-routes.ts | 3 ++- src/routes/reporting.ts | 7 ------- src/server.ts | 2 -- src/services/invoice-service.ts | 19 +++++++++++++++++-- src/services/reporting.ts | 10 ---------- 8 files changed, 56 insertions(+), 42 deletions(-) delete mode 100644 src/controllers/reporting.ts delete mode 100644 src/routes/reporting.ts delete mode 100644 src/services/reporting.ts diff --git a/src/classes/invoice.ts b/src/classes/invoice.ts index 1d0d6a0..f2c2eb1 100644 --- a/src/classes/invoice.ts +++ b/src/classes/invoice.ts @@ -6,15 +6,25 @@ export interface Invoice { SupplierID: number, Date: Date, DueDate: Date, - Status: number, + Statusid: InvoiceStatus, GasAmount: number, ElectricityType: number, Price: number, Tax: number, - StartDate: Date, - EndDate: Date + StartDate: Date, //? + EndDate: Date, //? } +//move to db table? +export enum InvoiceStatus { + sent, + paid, + overdue, + void, + writeOff, + draft + } + export const invoiceSchema = Joi.object({ InvoiceID: Joi.number().integer().min(0).required(), CustomerID: Joi.number().integer().min(0).required(), diff --git a/src/controllers/invoice-controller.ts b/src/controllers/invoice-controller.ts index be3f9eb..162c8de 100644 --- a/src/controllers/invoice-controller.ts +++ b/src/controllers/invoice-controller.ts @@ -82,3 +82,27 @@ export const deleteInvoiceById: RequestHandler = async (req: Request, res: Respo }); } }; + +//TODO add authentication +export const getOverdueInvoices: RequestHandler = async (req: Request, res: Response) => { + console.log("before 1"); + + try { + console.log("before 2"); + + const invoice = await invoiceService.getOverdueInvoices(); + console.log("before 3"); + + res.status(200).json({ + invoice + }); + } catch (error) { + console.log(); + + console.log(error); + res.status(500).json({ + message: 'There was an error when fetching estimations' + }); + } +}; + diff --git a/src/controllers/reporting.ts b/src/controllers/reporting.ts deleted file mode 100644 index a2168a4..0000000 --- a/src/controllers/reporting.ts +++ /dev/null @@ -1,17 +0,0 @@ -import {Request, RequestHandler, Response} from 'express'; -import { getAllUnpaidInvoices } from "../services/reporting"; - -export const getUnpaidInvoices: RequestHandler = async (req: Request, res: Response) => { - try { - const invoice = await getAllUnpaidInvoices(); - - res.status(200).json({ - invoice - }); - } catch (error) { - console.log(error); - res.status(500).json({ - message: 'There was an error when fetching estimations' - }); - } -}; diff --git a/src/routes/invoice-routes.ts b/src/routes/invoice-routes.ts index 9fc3f26..3f65cde 100644 --- a/src/routes/invoice-routes.ts +++ b/src/routes/invoice-routes.ts @@ -4,9 +4,10 @@ import * as invoiceController from '../controllers/invoice-controller'; const router = express.Router(); router.get('/invoices', invoiceController.getAllInvoices); -router.get('/invoices/:id', invoiceController.getInvoiceById); router.put('/invoices', invoiceController.updateInvoice); router.delete('/invoices/:id', invoiceController.deleteInvoiceById); +router.get('/invoices/overdue', invoiceController.getOverdueInvoices); router.post('/invoices', invoiceController.addInvoice); +router.get('/invoices/:id', invoiceController.getInvoiceById); export = router; diff --git a/src/routes/reporting.ts b/src/routes/reporting.ts deleted file mode 100644 index 4e1d011..0000000 --- a/src/routes/reporting.ts +++ /dev/null @@ -1,7 +0,0 @@ -import express from "express"; -import { getUnpaidInvoices } from "../controllers/reporting"; - -const reportingRoutes = express.Router(); -reportingRoutes.get('/reporting/tariffs', getUnpaidInvoices); - -export = reportingRoutes; diff --git a/src/server.ts b/src/server.ts index 4216495..9ae56a7 100644 --- a/src/server.ts +++ b/src/server.ts @@ -20,7 +20,6 @@ import testRoutes from './routes/test-routes'; import bodyParser from 'body-parser'; import cors from 'cors'; import dotenv from 'dotenv'; -import reportingRoutes from './routes/reporting'; if (process.env.NODE_ENV == null || process.env.NODE_ENV === 'development') { dotenv.config(); @@ -73,7 +72,6 @@ router.use('/api/', tariffRoutes, supplierRoutes, ticketRoutes, - reportingRoutes ); /** Error handling */ diff --git a/src/services/invoice-service.ts b/src/services/invoice-service.ts index d815ca0..58aa276 100644 --- a/src/services/invoice-service.ts +++ b/src/services/invoice-service.ts @@ -1,5 +1,5 @@ import {execute} from "../utils/mysql.connector"; -import {Invoice} from "../classes/invoice"; +import {Invoice, InvoiceStatus} from "../classes/invoice"; import {invoiceQueries} from "../queries/invoice-queries"; export const getAllInvoices = async () => { @@ -27,7 +27,7 @@ export const updateInvoice = async (invoice: Invoice) => { invoice.SupplierID, invoice.Date, invoice.DueDate, - invoice.Status, + invoice.Statusid, invoice.GasAmount, invoice.ElectricityType, invoice.Price, @@ -43,3 +43,18 @@ export const deleteInvoiceById = async (id: Invoice['InvoiceID']) => { const result = await execute<{ rowCount: number }>(invoiceQueries.deleteInvoiceById, [id]); return result.rowCount > 0; }; + +export const getOverdueInvoices = async () => { + console.log("start"); + const invoicesSql = await execute<{rows: Invoice[]}>('SELECT * FROM invoices WHERE "DueDate" <= $1;', [new Date().toISOString()]).catch(e => console.log("catch", e)); + console.log("overdue: 2"); + if(!invoicesSql) + return undefined + console.log(invoicesSql); + const invoices = invoicesSql.rows; + console.log("overdue: 3"); + //this gives all the overdue invoices even if status id isn't InvoiceStatus.overdue + invoices.forEach(e => e.Statusid = InvoiceStatus.overdue) + return invoices; +}; + diff --git a/src/services/reporting.ts b/src/services/reporting.ts deleted file mode 100644 index cadbee0..0000000 --- a/src/services/reporting.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Invoice } from "../classes/invoice"; -import { execute } from "../utils/mysql.connector"; - -//TODO change name to be more descriptive gets all unpaided invoices that are late -export const getAllUnpaidInvoices = async () => { - console.log(new Date().toISOString()); - - let invoices = execute<{rows: Invoice[]}>('SELECT * FROM invoices WHERE "DueDate" <= $1;', [new Date().toISOString()]); - return (await invoices).rows; -}; From 930ff7d1323e5a8b98f6bdaddf7cd31d536722af Mon Sep 17 00:00:00 2001 From: "LAPTOP-3BHD5BUF\\panda" Date: Thu, 12 May 2022 11:40:43 +0200 Subject: [PATCH 3/9] check invoices at interval --- src/app.ts | 2 ++ src/services/invoice-service.ts | 18 ++++++++++++------ src/utils/mysql.connector.ts | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/app.ts b/src/app.ts index 5b41cfa..c96fc0f 100644 --- a/src/app.ts +++ b/src/app.ts @@ -2,6 +2,7 @@ import dotenv from 'dotenv'; import { httpServer } from './server' import { MailService } from './services/mail-service' import { Env } from './utils/env'; +import { setOverdue, startIntervalsOverdue } from './services/invoice-service'; if (process.env.NODE_ENV == null || process.env.NODE_ENV === 'develepmont') { dotenv.config(); @@ -17,6 +18,7 @@ try { (async () => { const PORT: any = process.env.PORT ?? 6060; httpServer.listen(PORT, () => console.log(`The server is running on http://localhost:${PORT}`)); + startIntervalsOverdue(); /*try{ const ms = new MailService(); ms.testEmail() diff --git a/src/services/invoice-service.ts b/src/services/invoice-service.ts index 58aa276..6616a1e 100644 --- a/src/services/invoice-service.ts +++ b/src/services/invoice-service.ts @@ -1,6 +1,7 @@ import {execute} from "../utils/mysql.connector"; import {Invoice, InvoiceStatus} from "../classes/invoice"; import {invoiceQueries} from "../queries/invoice-queries"; +import { setInterval } from "timers"; export const getAllInvoices = async () => { let invoices = execute<{rows: Invoice[]}>(invoiceQueries.getAllInvoices, []); @@ -46,15 +47,20 @@ export const deleteInvoiceById = async (id: Invoice['InvoiceID']) => { export const getOverdueInvoices = async () => { console.log("start"); - const invoicesSql = await execute<{rows: Invoice[]}>('SELECT * FROM invoices WHERE "DueDate" <= $1;', [new Date().toISOString()]).catch(e => console.log("catch", e)); + const query = 'SELECT * FROM invoices WHERE "statusid" == $1;' + const invoicesSql = await execute<{rows: Invoice[]}>(query, [InvoiceStatus.overdue]).catch(e => console.log("catch", e)); console.log("overdue: 2"); if(!invoicesSql) return undefined - console.log(invoicesSql); - const invoices = invoicesSql.rows; - console.log("overdue: 3"); //this gives all the overdue invoices even if status id isn't InvoiceStatus.overdue - invoices.forEach(e => e.Statusid = InvoiceStatus.overdue) - return invoices; + return invoicesSql.rows; }; +export async function setOverdue() { + const query = `UPDATE "invoices" SET "Statusid" = ${InvoiceStatus.overdue} WHERE "Statusid" = ${InvoiceStatus.sent} AND "DueDate" <= '${new Date().toISOString()}'` //AND // "DueDate" <= ${new Date().toISOString() + const invoicesSql = await execute(query); +} + +export async function startIntervalsOverdue() { + setInterval(setOverdue, 1000); +} diff --git a/src/utils/mysql.connector.ts b/src/utils/mysql.connector.ts index 4caefce..3d15f6e 100644 --- a/src/utils/mysql.connector.ts +++ b/src/utils/mysql.connector.ts @@ -30,7 +30,7 @@ export function end() { } -export const execute = (query: string, params: any[]): Promise => { +export const execute = (query: string, params: any[] = []): Promise => { try { if (!pool) throw new Error('Pool was not created. Ensure pool is created when running the app.'); From 88311a99054b86bd505b8041061c44c2abf3c2f8 Mon Sep 17 00:00:00 2001 From: "LAPTOP-3BHD5BUF\\panda" Date: Thu, 12 May 2022 12:19:38 +0200 Subject: [PATCH 4/9] fix get over due with status --- src/services/invoice-service.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/services/invoice-service.ts b/src/services/invoice-service.ts index 6616a1e..6824182 100644 --- a/src/services/invoice-service.ts +++ b/src/services/invoice-service.ts @@ -47,12 +47,15 @@ export const deleteInvoiceById = async (id: Invoice['InvoiceID']) => { export const getOverdueInvoices = async () => { console.log("start"); - const query = 'SELECT * FROM invoices WHERE "statusid" == $1;' + const query = 'SELECT * FROM invoices WHERE "Statusid" = $1;' const invoicesSql = await execute<{rows: Invoice[]}>(query, [InvoiceStatus.overdue]).catch(e => console.log("catch", e)); + console.log("overdue: 2"); if(!invoicesSql) return undefined //this gives all the overdue invoices even if status id isn't InvoiceStatus.overdue + console.log(invoicesSql.rows); + return invoicesSql.rows; }; From 03a2eb0f5ea6765d1f14b7354677477358f1f0c6 Mon Sep 17 00:00:00 2001 From: panda jacobs Date: Wed, 18 May 2022 02:36:15 +0200 Subject: [PATCH 5/9] remove logging --- src/controllers/invoice-controller.ts | 9 ++------- src/services/invoice-service.ts | 14 +++++--------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/controllers/invoice-controller.ts b/src/controllers/invoice-controller.ts index 162c8de..19e5bfe 100644 --- a/src/controllers/invoice-controller.ts +++ b/src/controllers/invoice-controller.ts @@ -91,17 +91,12 @@ export const getOverdueInvoices: RequestHandler = async (req: Request, res: Resp console.log("before 2"); const invoice = await invoiceService.getOverdueInvoices(); - console.log("before 3"); - - res.status(200).json({ - invoice - }); + res.status(200).json(invoice); } catch (error) { - console.log(); console.log(error); res.status(500).json({ - message: 'There was an error when fetching estimations' + message: 'There was an error when fetching overdue invoices' }); } }; diff --git a/src/services/invoice-service.ts b/src/services/invoice-service.ts index 58aa276..2ff782f 100644 --- a/src/services/invoice-service.ts +++ b/src/services/invoice-service.ts @@ -44,17 +44,13 @@ export const deleteInvoiceById = async (id: Invoice['InvoiceID']) => { return result.rowCount > 0; }; +//this gives all the overdue invoices even if status id isn't InvoiceStatus.overdue export const getOverdueInvoices = async () => { - console.log("start"); - const invoicesSql = await execute<{rows: Invoice[]}>('SELECT * FROM invoices WHERE "DueDate" <= $1;', [new Date().toISOString()]).catch(e => console.log("catch", e)); - console.log("overdue: 2"); + const query = 'SELECT * FROM invoices WHERE "DueDate" <= $1;'; + const invoicesSql = await execute<{rows: Invoice[]}>(query, [new Date().toISOString()]) + .catch(e => console.log("overdue invoices error: ", e)); if(!invoicesSql) return undefined - console.log(invoicesSql); - const invoices = invoicesSql.rows; - console.log("overdue: 3"); - //this gives all the overdue invoices even if status id isn't InvoiceStatus.overdue - invoices.forEach(e => e.Statusid = InvoiceStatus.overdue) - return invoices; + return invoicesSql.rows; }; From 1fd1d3a94b4c60fe83f077982c31ee396ef5de6a Mon Sep 17 00:00:00 2001 From: panda jacobs Date: Wed, 18 May 2022 06:28:40 +0200 Subject: [PATCH 6/9] use overdue status instead of date --- src/classes/invoice.ts | 5 ++--- src/services/invoice-service.ts | 5 +++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/classes/invoice.ts b/src/classes/invoice.ts index f2c2eb1..1b2b578 100644 --- a/src/classes/invoice.ts +++ b/src/classes/invoice.ts @@ -20,9 +20,8 @@ export enum InvoiceStatus { sent, paid, overdue, - void, - writeOff, - draft + generated, + notGenerated } export const invoiceSchema = Joi.object({ diff --git a/src/services/invoice-service.ts b/src/services/invoice-service.ts index 2bf4aa0..be58b22 100644 --- a/src/services/invoice-service.ts +++ b/src/services/invoice-service.ts @@ -47,11 +47,12 @@ export const deleteInvoiceById = async (id: Invoice['InvoiceID']) => { //this gives all the overdue invoices even if status id isn't InvoiceStatus.overdue export const getOverdueInvoices = async () => { - const query = 'SELECT * FROM invoices WHERE "DueDate" <= $1;'; - const invoicesSql = await execute<{rows: Invoice[]}>(query, [new Date().toISOString()]) + const query = `SELECT * FROM invoices WHERE "Statusid" = $1;`; + const invoicesSql = await execute<{rows: Invoice[]}>(query, [ InvoiceStatus.overdue]) .catch(e => console.log("overdue invoices error: ", e)); if(!invoicesSql) return undefined + console.log(invoicesSql.rows.length) return invoicesSql.rows; }; From 3747a2018ac9d211047f0cbf3fa5f36ae45f42d6 Mon Sep 17 00:00:00 2001 From: panda jacobs Date: Wed, 18 May 2022 19:29:36 +0200 Subject: [PATCH 7/9] send mail on overdue invoice --- src/services/invoice-service.ts | 29 +++++++-- src/services/mail-service.ts | 107 ++++++++++++++++++++------------ 2 files changed, 89 insertions(+), 47 deletions(-) diff --git a/src/services/invoice-service.ts b/src/services/invoice-service.ts index be58b22..39fe0f1 100644 --- a/src/services/invoice-service.ts +++ b/src/services/invoice-service.ts @@ -2,6 +2,9 @@ import {execute} from "../utils/mysql.connector"; import {Invoice, InvoiceStatus} from "../classes/invoice"; import {invoiceQueries} from "../queries/invoice-queries"; import { setInterval } from "timers"; +import { MailService } from "./mail-service"; +import { mkdirSync } from "fs"; +import Mail from "nodemailer/lib/mailer"; export const getAllInvoices = async () => { let invoices = execute<{rows: Invoice[]}>(invoiceQueries.getAllInvoices, []); @@ -49,18 +52,32 @@ export const deleteInvoiceById = async (id: Invoice['InvoiceID']) => { export const getOverdueInvoices = async () => { const query = `SELECT * FROM invoices WHERE "Statusid" = $1;`; const invoicesSql = await execute<{rows: Invoice[]}>(query, [ InvoiceStatus.overdue]) - .catch(e => console.log("overdue invoices error: ", e)); + .catch(e => console.log("overdue invoices error: ", e)); if(!invoicesSql) - return undefined - console.log(invoicesSql.rows.length) + return undefined + console.log(invoicesSql.rows.length) + const overdues = await getOverdueInvoices() + const ms = new MailService(); + overdues?.forEach(o => { + ms.overdueInvoice(o) + }) return invoicesSql.rows; }; +//TODO use scheduler (invoice branch) export async function setOverdue() { - const query = `UPDATE "invoices" SET "Statusid" = ${InvoiceStatus.overdue} WHERE "Statusid" = ${InvoiceStatus.sent} AND "DueDate" <= '${new Date().toISOString()}'` //AND // "DueDate" <= ${new Date().toISOString() - const invoicesSql = await execute(query); + console.log("set overdue"); + + const querySelect = `select * from "invoices" WHERE "Statusid" = ${InvoiceStatus.sent} AND "DueDate" <= '${new Date().toISOString()}'`; + const queryUpdate = `UPDATE "invoices" SET "Statusid" = ${InvoiceStatus.overdue} WHERE "Statusid" = ${InvoiceStatus.sent} AND "DueDate" <= '${new Date().toISOString()}'` + const invoices = await execute<{rows: Invoice[]}>(querySelect); + execute(queryUpdate).catch(e => console.log(e)); + const ms = new MailService(); + + invoices.rows.forEach(o => ms.overdueInvoice(o)); + //new } export async function startIntervalsOverdue() { - setInterval(setOverdue, 1000); + setInterval(setOverdue, 10000); } diff --git a/src/services/mail-service.ts b/src/services/mail-service.ts index d1114ea..4f63c9f 100644 --- a/src/services/mail-service.ts +++ b/src/services/mail-service.ts @@ -9,7 +9,7 @@ export class MailService { private transport: Transporter; private hostEmail: string; private from : string; - + private endMail = `Best regards,\n${mailConfig.company}`; //supposed to be gotten from the data base private customer: Customer = { @@ -18,7 +18,7 @@ export class MailService { lastName: "rohan48", email: "AD0830686@PE2022.com" }; - + constructor() { this.checkEnv() this.hostEmail = process.env.MAILSERVER_U + "@" + mailConfig.domain; @@ -28,49 +28,48 @@ export class MailService { //console.log(this.transport); this.verify() }; - - - + + + private checkEnv() { if (!process.env.MAILSERVER_P) - throw new Error("Please define MAILSERVER_U in your env file"); - + throw new Error("Please define MAILSERVER_U in your env file"); + if (!process.env.MAILSERVER_U) throw new Error("Please define MAILSERVER_P in your env file"); - } - - private createTrans() { - //using https://ethereal.email includes authentication, testing - //mailserver doesn't have authentication (no TLS) - return createTransport({ - from: this.from, - host: mailConfig.host, - port: mailConfig.port, - auth: { - user: this.hostEmail, - pass: process.env.MAILSERVER_P - }, - //logger: true, - //transactionLog: true, - secure: false, - requireTLS: false - }) - } - - private async verify(): Promise { - if (!(await this.transport.verify())) + } + + private createTrans() { + //using https://ethereal.email includes authentication, testing + //mailserver doesn't have authentication (no TLS) + return createTransport({ + from: this.from, + host: mailConfig.host, + port: mailConfig.port, + auth: { + user: this.hostEmail, + pass: process.env.MAILSERVER_P + }, + //logger: true, + //transactionLog: true, + secure: false, + requireTLS: false + }) + } + + private async verify(): Promise { + if (!(await this.transport.verify())) throw new Error("transport in mailService isn't valid"); - } - - public sendInvoice(invoice: Invoice): SentMessageInfo { - //info from db - //TODO Get customer data from db - const title = `Dear ${this.customer.firstName} ${this.customer.lastName}`; - const body = [ - `your invoice ${invoice.InvoiceID} of ${invoice.Price} is due at ${invoice.DueDate.toDateString()} Please pay this as soon as possible.`, + } + + public sendInvoice(invoice: Invoice): SentMessageInfo { + //TODO Get customer data from db + const title = `Dear ${this.customer.firstName} ${this.customer.lastName}`; + const body = [ + `your invoice ${invoice.InvoiceID} of ${invoice.Price} is due at ${invoice.DueDate.toDateString()} Please pay this as soon as possible.`, "if you wish to see more details and/or pay please visit this link" ]; - + return this.transport.sendMail({ from: this.from, to: this.customer.email, @@ -79,7 +78,7 @@ export class MailService { html: this.htmlFormat(title, body), }).catch((e) => { Logger.error(e); }) } - + public sendWorkOrder(/*employee: Employee | User*/): SentMessageInfo{ const employee = this.customer; //info from db @@ -97,7 +96,7 @@ export class MailService { html: this.htmlFormat(title, body), }).catch((e) => { Logger.error(e); }); } - + public sendAppointment(/*appointment: Appointment*/): SentMessageInfo{ const Customer = this.customer; //info from db @@ -116,6 +115,30 @@ export class MailService { }).catch((e) => { Logger.error(e); }); } + overdueInvoice(o: Invoice) : SentMessageInfo{ + const Customer = this.customer; + //info from db + const title = `Dear ${Customer.firstName} ${Customer.lastName}`; + const body = [ + `Your invoice ${o.InvoiceID} is overdue`, + `Please pay the invoice at this link.`, + `
`, + `Invoice: ${o.InvoiceID}`, + `date: ${o.Date}`, + `price: ${o.Price}`, + ]; + + console.log(o); + + return this.transport.sendMail({ + from: this.from, + to: this.customer.email, + subject: `Work order`, + text: this.textFormat(title, body), + html: this.htmlFormat(title, body), + }).catch((e) => { Logger.error(e); }); + } + textFormat(title: string, body: string[]): string { let text = title; for (const b of body) { @@ -124,7 +147,7 @@ export class MailService { text += "\n\n" + this.endMail; return text; } - + htmlFormat(title: string, body: string[]): string { let text = "

" + title + "

"; for (const b of body) { @@ -134,5 +157,7 @@ export class MailService { text += "

" + this.endMail.replace("\n", "
") + "

"; return text; } + + }; From bcceecb540b3391a0c7d3b86e1c9fa79e2b5489c Mon Sep 17 00:00:00 2001 From: panda jacobs Date: Wed, 18 May 2022 20:36:36 +0200 Subject: [PATCH 8/9] change object accessors from main --- src/services/invoice-service.ts | 8 +++----- src/services/mail-service.ts | 12 ++++++------ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/services/invoice-service.ts b/src/services/invoice-service.ts index 243a26b..e7c98cd 100644 --- a/src/services/invoice-service.ts +++ b/src/services/invoice-service.ts @@ -84,7 +84,7 @@ export const getInvoiceByUserId = async (id: Invoice['invoice_id']) => { //this gives all the overdue invoices even if status id isn't InvoiceStatus.overdue export const getOverdueInvoices = async () => { - const query = `SELECT * FROM invoices WHERE "Statusid" = $1;`; + const query = `SELECT * FROM invoices WHERE "status_id" = $1;`; const invoicesSql = await execute<{ rows: Invoice[] }>(query, [InvoiceStatus.overdue]) .catch(e => console.log("overdue invoices error: ", e)); if (!invoicesSql) @@ -100,10 +100,8 @@ export const getOverdueInvoices = async () => { //TODO use scheduler (invoice branch) export async function setOverdue() { - console.log("set overdue"); - - const querySelect = `select * from "invoices" WHERE "Statusid" = $1 AND "DueDate" <= $2`; - const queryUpdate = `UPDATE "invoices" SET "Statusid" = $1 WHERE "Statusid" = $2 AND "DueDate" <= $3` + const querySelect = `select * from "invoices" WHERE "status_id" = $1 AND "due_date" <= $2`; + const queryUpdate = `UPDATE "invoices" SET "status_id" = $1 WHERE "status_id" = $2 AND "due_date" <= $3` const invoices = await execute<{ rows: Invoice[] }>(querySelect, [InvoiceStatus.sent, new Date().toISOString()]); execute(queryUpdate, [InvoiceStatus.overdue,InvoiceStatus.sent, new Date().toISOString()]).catch(e => console.log(e)); const ms = new MailService(); diff --git a/src/services/mail-service.ts b/src/services/mail-service.ts index 4f63c9f..8c57f64 100644 --- a/src/services/mail-service.ts +++ b/src/services/mail-service.ts @@ -66,14 +66,14 @@ export class MailService { //TODO Get customer data from db const title = `Dear ${this.customer.firstName} ${this.customer.lastName}`; const body = [ - `your invoice ${invoice.InvoiceID} of ${invoice.Price} is due at ${invoice.DueDate.toDateString()} Please pay this as soon as possible.`, + `your invoice ${invoice.invoice_id} of ${invoice.price} is due at ${invoice.due_date.toDateString()} Please pay this as soon as possible.`, "if you wish to see more details and/or pay please visit this link" ]; return this.transport.sendMail({ from: this.from, to: this.customer.email, - subject: `Invoice: ${invoice.InvoiceID}`, + subject: `Invoice: ${invoice.invoice_id}`, text: this.textFormat(title, body), html: this.htmlFormat(title, body), }).catch((e) => { Logger.error(e); }) @@ -120,12 +120,12 @@ export class MailService { //info from db const title = `Dear ${Customer.firstName} ${Customer.lastName}`; const body = [ - `Your invoice ${o.InvoiceID} is overdue`, + `Your invoice ${o.invoice_id} is overdue`, `Please pay the invoice at this link.`, `
`, - `Invoice: ${o.InvoiceID}`, - `date: ${o.Date}`, - `price: ${o.Price}`, + `Invoice: ${o.invoice_id}`, + `date: ${o.creation_date}`, + `price: ${o.price}`, ]; console.log(o); From 90b6e7226765aca82f4b8eea146ad61248dcb317 Mon Sep 17 00:00:00 2001 From: panda jacobs Date: Sun, 22 May 2022 05:10:47 +0200 Subject: [PATCH 9/9] fix: typo + rm logs + mv route top avoid id route --- src/controllers/invoice-controller.ts | 6 +----- src/routes/invoice-routes.ts | 2 +- src/routes/invoice.ts | 12 ------------ src/services/invoice-service.ts | 19 ++++++++----------- src/services/mail-service.ts | 2 +- 5 files changed, 11 insertions(+), 30 deletions(-) delete mode 100644 src/routes/invoice.ts diff --git a/src/controllers/invoice-controller.ts b/src/controllers/invoice-controller.ts index e288d20..8f92bd8 100644 --- a/src/controllers/invoice-controller.ts +++ b/src/controllers/invoice-controller.ts @@ -146,12 +146,8 @@ export const getInvoiceByUserId: RequestHandler = async (req: Request, res: Resp }; //TODO add authentication -export const getOverdueInvoices: RequestHandler = async (req: Request, res: Response) => { - console.log("before 1"); - +export const getOverdueInvoices: RequestHandler = async (req: Request, res: Response) => { try { - console.log("before 2"); - const invoice = await invoiceService.getOverdueInvoices(); res.status(200).json(invoice); } catch (error) { diff --git a/src/routes/invoice-routes.ts b/src/routes/invoice-routes.ts index 3667d98..14b3461 100644 --- a/src/routes/invoice-routes.ts +++ b/src/routes/invoice-routes.ts @@ -5,6 +5,7 @@ import { UserRole } from '../models/userrole'; const router = express.Router(); +router.get('/overdue', auth.authenticate([UserRole.ACCOUNTANT, UserRole.ADMIN]), invoiceController.getOverdueInvoices); router.get('/', auth.authenticate([UserRole.ADMIN, UserRole.ACCOUNTANT]), invoiceController.getAllInvoices); router.get('/:id/pdf', invoiceController.getInvoicePdfById); router.get('/:id', auth.authenticate([UserRole.ADMIN, UserRole.ACCOUNTANT]), invoiceController.getInvoiceById); @@ -12,6 +13,5 @@ router.get('/user/:id/', invoiceController.getInvoiceByUserId); router.post('/', auth.authenticate([UserRole.ADMIN, UserRole.ACCOUNTANT]), invoiceController.addInvoice); router.put('/', auth.authenticate([UserRole.ADMIN, UserRole.ACCOUNTANT]), invoiceController.updateInvoice); router.delete('/:id', auth.authenticate([UserRole.ADMIN]), invoiceController.deleteInvoiceById); -router.get('/overdue', auth.authenticate([UserRole.ACCOUNTANT, UserRole.ADMIN]), invoiceController.getOverdueInvoices); export = router; diff --git a/src/routes/invoice.ts b/src/routes/invoice.ts deleted file mode 100644 index e20ca5d..0000000 --- a/src/routes/invoice.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** source/routes/invoices.ts */ -import express from 'express'; -import controller from '../controller/invoice'; -const router = express.Router(); - -router.get('/invoices', controller.getInvoices); -router.get('/invoices/:id', controller.getInvoice); -router.put('/invoices', controller.updateInvoice); -router.delete('/invoices/:id', controller.deleteInvoice); -router.post('/invoices', controller.addInvoice); - -export = router; \ No newline at end of file diff --git a/src/services/invoice-service.ts b/src/services/invoice-service.ts index e7c98cd..bc79797 100644 --- a/src/services/invoice-service.ts +++ b/src/services/invoice-service.ts @@ -84,17 +84,13 @@ export const getInvoiceByUserId = async (id: Invoice['invoice_id']) => { //this gives all the overdue invoices even if status id isn't InvoiceStatus.overdue export const getOverdueInvoices = async () => { - const query = `SELECT * FROM invoices WHERE "status_id" = $1;`; + const query = `SELECT * FROM invoices WHERE status_id = $1;`; const invoicesSql = await execute<{ rows: Invoice[] }>(query, [InvoiceStatus.overdue]) .catch(e => console.log("overdue invoices error: ", e)); - if (!invoicesSql) + + if (!invoicesSql || !invoicesSql.rows) return undefined console.log(invoicesSql.rows.length) - const overdues = await getOverdueInvoices() - const ms = new MailService(); - overdues?.forEach(o => { - ms.overdueInvoice(o) - }) return invoicesSql.rows; }; @@ -102,12 +98,13 @@ export const getOverdueInvoices = async () => { export async function setOverdue() { const querySelect = `select * from "invoices" WHERE "status_id" = $1 AND "due_date" <= $2`; const queryUpdate = `UPDATE "invoices" SET "status_id" = $1 WHERE "status_id" = $2 AND "due_date" <= $3` - const invoices = await execute<{ rows: Invoice[] }>(querySelect, [InvoiceStatus.sent, new Date().toISOString()]); + const invoicesSql = await execute<{ rows: Invoice[] }>(querySelect, [InvoiceStatus.sent, new Date().toISOString()]); + if(!invoicesSql) + return undefined execute(queryUpdate, [InvoiceStatus.overdue,InvoiceStatus.sent, new Date().toISOString()]).catch(e => console.log(e)); + const ms = new MailService(); - - invoices.rows.forEach(o => ms.overdueInvoice(o)); - //new + invoicesSql.rows.forEach(o => ms.overdueInvoice(o)); } export async function startIntervalsOverdue() { diff --git a/src/services/mail-service.ts b/src/services/mail-service.ts index 8c57f64..2c4e6e6 100644 --- a/src/services/mail-service.ts +++ b/src/services/mail-service.ts @@ -133,7 +133,7 @@ export class MailService { return this.transport.sendMail({ from: this.from, to: this.customer.email, - subject: `Work order`, + subject: `Invoice: ${o.invoice_id}`, text: this.textFormat(title, body), html: this.htmlFormat(title, body), }).catch((e) => { Logger.error(e); });