From e908279f24c81478675d0a8429645ea1e632b811 Mon Sep 17 00:00:00 2001 From: JochemVH1 Date: Wed, 3 Jul 2024 12:01:31 +0200 Subject: [PATCH 1/2] invoiceModel: adjusted invoice model to set config as property in constructor adjusted setClient function to pass config and date to getInvoiceDateFunction invoice-date-strategy: add parameter to getInvoice to receive date of invoice adjusted endofmonth function to handling new logic with given date invoiceModel.spec.ts: add test for testing new endofmonth functionallity => in hindsight this might have been more logically as seperate spec file --- .../components/invoice/models/InvoiceModel.ts | 4 +- .../invoice/models/invoice-date-strategy.ts | 25 ++++---- .../invoice/spec/InvoiceModel.spec.ts | 58 +++++++++++++++++++ 3 files changed, 76 insertions(+), 11 deletions(-) diff --git a/frontend/src/components/invoice/models/InvoiceModel.ts b/frontend/src/components/invoice/models/InvoiceModel.ts index 40521597..f1fb46c7 100644 --- a/frontend/src/components/invoice/models/InvoiceModel.ts +++ b/frontend/src/components/invoice/models/InvoiceModel.ts @@ -55,6 +55,7 @@ export default class InvoiceModel implements IAttachment { lines: InvoiceLine[] = []; money: InvoiceMoney; note: string; + config: ConfigModel; get isNew(): boolean { return this._id === undefined; @@ -79,6 +80,7 @@ export default class InvoiceModel implements IAttachment { this._lines = obj.lines || config.defaultInvoiceLines || []; this.audit = obj.audit; + this.config = config; } getType(): 'quotation' | 'invoice' { @@ -102,7 +104,7 @@ export default class InvoiceModel implements IAttachment { /** Some weird stuff happening here that EditInvoice probably depends on */ setClient(client: undefined | ClientModel): InvoiceModel { this.client = client as ClientModel; - this.date = getInvoiceDate(client); + this.date = getInvoiceDate(client, this.config, this.date); if (client && client.defaultInvoiceLines.length) { this._lines = client.defaultInvoiceLines.map(x => ({...x})); diff --git a/frontend/src/components/invoice/models/invoice-date-strategy.ts b/frontend/src/components/invoice/models/invoice-date-strategy.ts index 88bc3b50..79416b38 100644 --- a/frontend/src/components/invoice/models/invoice-date-strategy.ts +++ b/frontend/src/components/invoice/models/invoice-date-strategy.ts @@ -8,25 +8,30 @@ export const invoiceDateStrategies = ['prev-month-last-day', 'today']; export const today = (): moment.Moment => moment().startOf('day'); -const endOfMonth = (): moment.Moment => { - if (moment().date() > 28) { - return today(); +const endOfMonth = (date?: moment.Moment): moment.Moment => { + const dateToCheck:moment.Moment = date || moment(); + const endOfMonthStartDay:number = 1; + const endOfMonthEndDay:number = 21; + const currentDay:number = dateToCheck.date(); + + //checking on format to skip any time inequality + if(dateToCheck.format('YYYY-MM-DD') === dateToCheck.endOf('month').format('YYYY-MM-DD')){ + return dateToCheck + }else if(currentDay >= endOfMonthStartDay && currentDay <= endOfMonthEndDay){ + return dateToCheck.subtract(1, 'months').endOf('month'); + }else{ + return dateToCheck.startOf('month') } - - // ATTN: The following returns something like: "Thu Apr 30 2020 23:59:59 GMT+0200" - // (which should probably be cleaned up at some point) - const lastDayPrevMonth = moment().subtract(1, 'months').endOf('month'); - return lastDayPrevMonth; }; -export const getInvoiceDate = (client?: ClientModel, config?: ConfigModel): moment.Moment => { +export const getInvoiceDate = (client?: ClientModel, config?: ConfigModel, date?: moment.Moment): moment.Moment => { const strategy = (client && client.defaultInvoiceDateStrategy) || (config && config.defaultInvoiceDateStrategy); switch (strategy) { case 'prev-month-last-day': - return endOfMonth(); + return endOfMonth(date); case 'today': default: return today(); diff --git a/frontend/src/components/invoice/spec/InvoiceModel.spec.ts b/frontend/src/components/invoice/spec/InvoiceModel.spec.ts index a6383932..7441b6d9 100644 --- a/frontend/src/components/invoice/spec/InvoiceModel.spec.ts +++ b/frontend/src/components/invoice/spec/InvoiceModel.spec.ts @@ -208,3 +208,61 @@ describe('Switch between days and hours', () => { expect(vm.lines[0].amount).toBe(10); }); }); + +describe('Invoice date for last of month config', () => { + it('Should be 31 may when date is 10 june', () => { + const vm = createViewModel(); + vm.date = moment('2024-06-10'); + vm.setClient(undefined); + + expect(vm.date.format('YYYY-MM-DD')).toBe('2024-05-31') + }) + + it('Should be 31 december when date is 10 januari', () => { + const vm = createViewModel(); + vm.date = moment('2024-01-10'); + vm.setClient(undefined); + + expect(vm.date.format('YYYY-MM-DD')).toBe('2023-12-31') + }) + + it('Should be 30 june month when date is 30 june', () => { + const vm = createViewModel(); + vm.date = moment('2024-06-30'); + vm.setClient(undefined); + + expect(vm.date.format('YYYY-MM-DD')).toBe('2024-06-30') + }) + + it('Should be 29 februari month when date is 29 februari', () => { + const vm = createViewModel(); + vm.date = moment('2024-02-29'); + vm.setClient(undefined); + + expect(vm.date.format('YYYY-MM-DD')).toBe('2024-02-29') + }) + + it('Should be 31 januari month when date is 31 januari', () => { + const vm = createViewModel(); + vm.date = moment('2024-01-31'); + vm.setClient(undefined); + + expect(vm.date.format('YYYY-MM-DD')).toBe('2024-01-31') + }) + + it('Should be 1 june month when date is 22 june', () => { + const vm = createViewModel(); + vm.date = moment('2024-06-22'); + vm.setClient(undefined); + + expect(vm.date.format('YYYY-MM-DD')).toBe('2024-06-01') + }) + + it('Should be 1 januari month when date is 22 januari', () => { + const vm = createViewModel(); + vm.date = moment('2024-01-22'); + vm.setClient(undefined); + + expect(vm.date.format('YYYY-MM-DD')).toBe('2024-01-01') + }) +}) From c41302a7c86eac33c546c6051c43c9946a4f58c0 Mon Sep 17 00:00:00 2001 From: JochemVH1 Date: Wed, 3 Jul 2024 14:33:55 +0200 Subject: [PATCH 2/2] Added new strategy to models.ts Added translations for new strategy Added new case for new strategy and reverted old logic in invoice-date-strategy.ts fixed tests to use new strategy --- .../invoice/models/invoice-date-strategy.ts | 21 ++++++++++++++----- .../invoice/spec/InvoiceModel.spec.ts | 9 +++++++- frontend/src/models.ts | 2 +- frontend/src/trans.en.ts | 1 + frontend/src/trans.nl.ts | 1 + 5 files changed, 27 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/invoice/models/invoice-date-strategy.ts b/frontend/src/components/invoice/models/invoice-date-strategy.ts index 79416b38..1fab6ec4 100644 --- a/frontend/src/components/invoice/models/invoice-date-strategy.ts +++ b/frontend/src/components/invoice/models/invoice-date-strategy.ts @@ -2,13 +2,24 @@ import moment from 'moment'; import {ClientModel} from '../../client/models/ClientModels'; import {ConfigModel} from '../../config/models/ConfigModel'; -export const invoiceDateStrategies = ['prev-month-last-day', 'today']; +export const invoiceDateStrategies = ['new-month-from-22th', 'prev-month-last-day', 'today']; export const today = (): moment.Moment => moment().startOf('day'); -const endOfMonth = (date?: moment.Moment): moment.Moment => { +const endOfMonth = (): moment.Moment => { + if (moment().date() > 28) { + return today(); + } + + // ATTN: The following returns something like: "Thu Apr 30 2020 23:59:59 GMT+0200" + // (which should probably be cleaned up at some point) + const lastDayPrevMonth = moment().subtract(1, 'months').endOf('month'); + return lastDayPrevMonth; +}; + +const newMonthFromThe22th = (date?: moment.Moment): moment.Moment => { const dateToCheck:moment.Moment = date || moment(); const endOfMonthStartDay:number = 1; const endOfMonthEndDay:number = 21; @@ -24,14 +35,14 @@ const endOfMonth = (date?: moment.Moment): moment.Moment => { } }; - - export const getInvoiceDate = (client?: ClientModel, config?: ConfigModel, date?: moment.Moment): moment.Moment => { const strategy = (client && client.defaultInvoiceDateStrategy) || (config && config.defaultInvoiceDateStrategy); switch (strategy) { case 'prev-month-last-day': - return endOfMonth(date); + return endOfMonth(); + case 'new-month-from-22th': + return newMonthFromThe22th(date) case 'today': default: return today(); diff --git a/frontend/src/components/invoice/spec/InvoiceModel.spec.ts b/frontend/src/components/invoice/spec/InvoiceModel.spec.ts index 7441b6d9..c6e25620 100644 --- a/frontend/src/components/invoice/spec/InvoiceModel.spec.ts +++ b/frontend/src/components/invoice/spec/InvoiceModel.spec.ts @@ -209,10 +209,11 @@ describe('Switch between days and hours', () => { }); }); -describe('Invoice date for last of month config', () => { +describe('Invoice date new month from the 22th', () => { it('Should be 31 may when date is 10 june', () => { const vm = createViewModel(); vm.date = moment('2024-06-10'); + vm.config.defaultInvoiceDateStrategy = 'new-month-from-22th'; vm.setClient(undefined); expect(vm.date.format('YYYY-MM-DD')).toBe('2024-05-31') @@ -221,6 +222,7 @@ describe('Invoice date for last of month config', () => { it('Should be 31 december when date is 10 januari', () => { const vm = createViewModel(); vm.date = moment('2024-01-10'); + vm.config.defaultInvoiceDateStrategy = 'new-month-from-22th'; vm.setClient(undefined); expect(vm.date.format('YYYY-MM-DD')).toBe('2023-12-31') @@ -229,6 +231,7 @@ describe('Invoice date for last of month config', () => { it('Should be 30 june month when date is 30 june', () => { const vm = createViewModel(); vm.date = moment('2024-06-30'); + vm.config.defaultInvoiceDateStrategy = 'new-month-from-22th'; vm.setClient(undefined); expect(vm.date.format('YYYY-MM-DD')).toBe('2024-06-30') @@ -237,6 +240,7 @@ describe('Invoice date for last of month config', () => { it('Should be 29 februari month when date is 29 februari', () => { const vm = createViewModel(); vm.date = moment('2024-02-29'); + vm.config.defaultInvoiceDateStrategy = 'new-month-from-22th'; vm.setClient(undefined); expect(vm.date.format('YYYY-MM-DD')).toBe('2024-02-29') @@ -245,6 +249,7 @@ describe('Invoice date for last of month config', () => { it('Should be 31 januari month when date is 31 januari', () => { const vm = createViewModel(); vm.date = moment('2024-01-31'); + vm.config.defaultInvoiceDateStrategy = 'new-month-from-22th'; vm.setClient(undefined); expect(vm.date.format('YYYY-MM-DD')).toBe('2024-01-31') @@ -253,6 +258,7 @@ describe('Invoice date for last of month config', () => { it('Should be 1 june month when date is 22 june', () => { const vm = createViewModel(); vm.date = moment('2024-06-22'); + vm.config.defaultInvoiceDateStrategy = 'new-month-from-22th'; vm.setClient(undefined); expect(vm.date.format('YYYY-MM-DD')).toBe('2024-06-01') @@ -261,6 +267,7 @@ describe('Invoice date for last of month config', () => { it('Should be 1 januari month when date is 22 januari', () => { const vm = createViewModel(); vm.date = moment('2024-01-22'); + vm.config.defaultInvoiceDateStrategy = 'new-month-from-22th'; vm.setClient(undefined); expect(vm.date.format('YYYY-MM-DD')).toBe('2024-01-01') diff --git a/frontend/src/models.ts b/frontend/src/models.ts index 6cf8af2c..556c4f39 100644 --- a/frontend/src/models.ts +++ b/frontend/src/models.ts @@ -4,7 +4,7 @@ import {StandardComponents} from './components/controls/form-controls/lib/Compon import {ConsultantListFilters, ClientListFilters, InvoiceListFilters, ProjectListFilters, ProjectMonthListFilters, UsersListFilters, RolesListFilters} from './components/controls/table/table-models'; -export type InvoiceDateStrategy = 'prev-month-last-day' | 'today'; +export type InvoiceDateStrategy = 'new-month-from-22th' | 'prev-month-last-day' | 'today'; export type ChildrenType = React.ReactNode | JSX.Element[]; diff --git a/frontend/src/trans.en.ts b/frontend/src/trans.en.ts index 9563e063..aa7e680c 100644 --- a/frontend/src/trans.en.ts +++ b/frontend/src/trans.en.ts @@ -285,6 +285,7 @@ export const trans = { dateStrategies: { 'prev-month-last-day': 'Last day last month', today: 'Today', + 'new-month-from-22th': 'New month from the 22th' }, hours: 'Total hours', days: 'Days', diff --git a/frontend/src/trans.nl.ts b/frontend/src/trans.nl.ts index 8b50e083..1bdd387a 100644 --- a/frontend/src/trans.nl.ts +++ b/frontend/src/trans.nl.ts @@ -285,6 +285,7 @@ export const trans = { dateStrategies: { 'prev-month-last-day': 'Laatste dag vorige maand', today: 'Vandaag', + 'new-month-from-22th': 'Nieuwe maand vanaf de 22ste' }, hours: 'Totaal uren', days: 'Dagen',