@stamhoofd/models 2.120.6 → 2.122.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/factories/GroupFactory.d.ts.map +1 -1
- package/dist/factories/GroupFactory.js +1 -1
- package/dist/factories/GroupFactory.js.map +1 -1
- package/dist/factories/OrganizationFactory.d.ts +2 -1
- package/dist/factories/OrganizationFactory.d.ts.map +1 -1
- package/dist/factories/OrganizationFactory.js +9 -1
- package/dist/factories/OrganizationFactory.js.map +1 -1
- package/dist/factories/RegistrationInvitationFactory.d.ts +15 -0
- package/dist/factories/RegistrationInvitationFactory.d.ts.map +1 -0
- package/dist/factories/RegistrationInvitationFactory.js +18 -0
- package/dist/factories/RegistrationInvitationFactory.js.map +1 -0
- package/dist/factories/STPackageFactory.js.map +1 -1
- package/dist/factories/UserFactory.d.ts.map +1 -1
- package/dist/factories/UserFactory.js +2 -2
- package/dist/factories/UserFactory.js.map +1 -1
- package/dist/factories/index.d.ts +1 -0
- package/dist/factories/index.d.ts.map +1 -1
- package/dist/factories/index.js +1 -0
- package/dist/factories/index.js.map +1 -1
- package/dist/helpers/EmailBuilder.d.ts.map +1 -1
- package/dist/helpers/EmailBuilder.js +8 -8
- package/dist/helpers/EmailBuilder.js.map +1 -1
- package/dist/helpers/Handlebars.d.ts.map +1 -1
- package/dist/helpers/Handlebars.js +10 -1
- package/dist/helpers/Handlebars.js.map +1 -1
- package/dist/helpers/InvoiceCounter.d.ts +24 -0
- package/dist/helpers/InvoiceCounter.d.ts.map +1 -0
- package/dist/helpers/InvoiceCounter.js +133 -0
- package/dist/helpers/InvoiceCounter.js.map +1 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/migrations/1605262045-import-postcodes.d.ts.map +1 -1
- package/dist/migrations/1605262045-import-postcodes.js +58 -24
- package/dist/migrations/1605262045-import-postcodes.js.map +1 -1
- package/dist/migrations/1605262046-import-postcodes-nl.d.ts.map +1 -1
- package/dist/migrations/1605262046-import-postcodes-nl.js +54 -17
- package/dist/migrations/1605262046-import-postcodes-nl.js.map +1 -1
- package/dist/migrations/1719567881-organization-periodId.sql +2 -0
- package/dist/migrations/1719567882-groups-periodId.sql +2 -0
- package/dist/migrations/1720080975-convert-charset.d.ts +4 -0
- package/dist/migrations/1720080975-convert-charset.d.ts.map +1 -0
- package/dist/migrations/1720080975-convert-charset.js +26 -0
- package/dist/migrations/1720080975-convert-charset.js.map +1 -0
- package/dist/migrations/1720080976-convert-charset-leads.d.ts.map +1 -1
- package/dist/migrations/1720080976-convert-charset-leads.js +11 -10
- package/dist/migrations/1720080976-convert-charset-leads.js.map +1 -1
- package/dist/migrations/1721400546-users-memberId.sql +2 -0
- package/dist/migrations/1722269236-group-waitinglist-id.sql +2 -1
- package/dist/migrations/1722525785-balance-item-paying-organization-id.sql +2 -0
- package/dist/migrations/1722525787-depending-balance-item.sql +2 -0
- package/dist/migrations/1722963554-registration-group-price-and-options.sql +1 -1
- package/dist/migrations/1723652797-payments-paying-organization-id-fk.sql +2 -0
- package/dist/migrations/1733317908-added-missing-organization-fk-on-registrations.sql +2 -0
- package/dist/migrations/1733317910-paying-organization-id-fk.sql +2 -0
- package/dist/migrations/1733504881-negative-invoice-id.sql +6 -0
- package/dist/migrations/1733994455-balance-item-status-open.d.ts +4 -0
- package/dist/migrations/1733994455-balance-item-status-open.d.ts.map +1 -0
- package/dist/migrations/1733994455-balance-item-status-open.js +28 -0
- package/dist/migrations/1733994455-balance-item-status-open.js.map +1 -0
- package/dist/migrations/1763216320-bigint-balance-item-payments.sql +2 -0
- package/dist/migrations/1763216320-bigint-balance-items.sql +5 -0
- package/dist/migrations/1763216320-bigint-orders.sql +2 -0
- package/dist/migrations/1763216320-bigint-payments.sql +2 -0
- package/dist/migrations/1763216332-bigint-balance-item-price-total.sql +2 -0
- package/dist/migrations/1769087808-corrected-invoice-user-agent.sql +2 -0
- package/dist/migrations/1769087809-payments-invoice-id.sql +2 -0
- package/dist/migrations/1772033555-balance-item-package-id.sql +2 -0
- package/dist/migrations/1776873089-create-registration-invitations-table.sql +13 -0
- package/dist/migrations/1778657958-payments-create-mandate.sql +2 -0
- package/dist/migrations/1778657959-payments-mandate-id.sql +2 -0
- package/dist/migrations/1778796615-payments-reversing-payment-id.sql +5 -0
- package/dist/migrations/1778950642-price-invoiced.sql +2 -0
- package/dist/migrations/1779443446-transfer-fees.sql +3 -0
- package/dist/migrations/1779709174-used-register-code-balance-item-id.sql +5 -0
- package/dist/migrations/1779968328-payments-admin-user-id.sql +5 -0
- package/dist/migrations/1779970611-payments-refunded-amount.sql +2 -0
- package/dist/migrations/1779972640-balance-items-failed-at.sql +2 -0
- package/dist/migrations/1780328285-document-template-locked.sql +2 -0
- package/dist/migrations/1780328286-document-locked.sql +2 -0
- package/dist/migrations/1780412083-documents-set-locked.d.ts +4 -0
- package/dist/migrations/1780412083-documents-set-locked.d.ts.map +1 -0
- package/dist/migrations/1780412083-documents-set-locked.js +14 -0
- package/dist/migrations/1780412083-documents-set-locked.js.map +1 -0
- package/dist/migrations/1780928401-v1-groups-migration-data.d.ts +4 -0
- package/dist/migrations/1780928401-v1-groups-migration-data.d.ts.map +1 -0
- package/dist/migrations/1780928401-v1-groups-migration-data.js +44 -0
- package/dist/migrations/1780928401-v1-groups-migration-data.js.map +1 -0
- package/dist/models/BalanceItem.d.ts +14 -1
- package/dist/models/BalanceItem.d.ts.map +1 -1
- package/dist/models/BalanceItem.js +91 -41
- package/dist/models/BalanceItem.js.map +1 -1
- package/dist/models/CachedBalance.d.ts +6 -1
- package/dist/models/CachedBalance.d.ts.map +1 -1
- package/dist/models/CachedBalance.js +3 -2
- package/dist/models/CachedBalance.js.map +1 -1
- package/dist/models/Document.d.ts +4 -0
- package/dist/models/Document.d.ts.map +1 -1
- package/dist/models/Document.js +26 -3
- package/dist/models/Document.js.map +1 -1
- package/dist/models/DocumentTemplate.d.ts +4 -0
- package/dist/models/DocumentTemplate.d.ts.map +1 -1
- package/dist/models/DocumentTemplate.js +37 -1
- package/dist/models/DocumentTemplate.js.map +1 -1
- package/dist/models/Email.d.ts.map +1 -1
- package/dist/models/Email.js +1 -1
- package/dist/models/Email.js.map +1 -1
- package/dist/models/EmailVerificationCode.d.ts.map +1 -1
- package/dist/models/EmailVerificationCode.js +3 -13
- package/dist/models/EmailVerificationCode.js.map +1 -1
- package/dist/models/Event.d.ts +2 -1
- package/dist/models/Event.d.ts.map +1 -1
- package/dist/models/Event.js +3 -0
- package/dist/models/Event.js.map +1 -1
- package/dist/models/EventNotification.d.ts.map +1 -1
- package/dist/models/EventNotification.js +5 -5
- package/dist/models/EventNotification.js.map +1 -1
- package/dist/models/Group.d.ts +4 -0
- package/dist/models/Group.d.ts.map +1 -1
- package/dist/models/Group.js +17 -0
- package/dist/models/Group.js.map +1 -1
- package/dist/models/Invoice.d.ts +1 -0
- package/dist/models/Invoice.d.ts.map +1 -1
- package/dist/models/Invoice.js +8 -8
- package/dist/models/Invoice.js.map +1 -1
- package/dist/models/MemberPlatformMembership.d.ts.map +1 -1
- package/dist/models/MemberPlatformMembership.js +9 -0
- package/dist/models/MemberPlatformMembership.js.map +1 -1
- package/dist/models/MollieToken.d.ts +4 -8
- package/dist/models/MollieToken.d.ts.map +1 -1
- package/dist/models/MollieToken.js +37 -90
- package/dist/models/MollieToken.js.map +1 -1
- package/dist/models/Order.d.ts.map +1 -1
- package/dist/models/Order.js +1 -0
- package/dist/models/Order.js.map +1 -1
- package/dist/models/Organization.d.ts +30 -23
- package/dist/models/Organization.d.ts.map +1 -1
- package/dist/models/Organization.js +113 -61
- package/dist/models/Organization.js.map +1 -1
- package/dist/models/PasswordToken.d.ts +5 -1
- package/dist/models/PasswordToken.d.ts.map +1 -1
- package/dist/models/PasswordToken.js +18 -17
- package/dist/models/PasswordToken.js.map +1 -1
- package/dist/models/Payment.d.ts +35 -3
- package/dist/models/Payment.d.ts.map +1 -1
- package/dist/models/Payment.js +66 -3
- package/dist/models/Payment.js.map +1 -1
- package/dist/models/Registration.d.ts +1 -0
- package/dist/models/Registration.d.ts.map +1 -1
- package/dist/models/Registration.js +4 -3
- package/dist/models/Registration.js.map +1 -1
- package/dist/models/RegistrationInvitation.d.ts +14 -0
- package/dist/models/RegistrationInvitation.d.ts.map +1 -0
- package/dist/models/RegistrationInvitation.js +45 -0
- package/dist/models/RegistrationInvitation.js.map +1 -0
- package/dist/models/STCredit.d.ts +4 -0
- package/dist/models/STCredit.d.ts.map +1 -1
- package/dist/models/STCredit.js +28 -0
- package/dist/models/STCredit.js.map +1 -1
- package/dist/models/STInvoice.d.ts +7 -1
- package/dist/models/STInvoice.d.ts.map +1 -1
- package/dist/models/STInvoice.js +9 -0
- package/dist/models/STInvoice.js.map +1 -1
- package/dist/models/STPackage.d.ts +4 -0
- package/dist/models/STPackage.d.ts.map +1 -1
- package/dist/models/STPackage.js +12 -1
- package/dist/models/STPackage.js.map +1 -1
- package/dist/models/UsedRegisterCode.d.ts +9 -0
- package/dist/models/UsedRegisterCode.d.ts.map +1 -1
- package/dist/models/UsedRegisterCode.js +31 -0
- package/dist/models/UsedRegisterCode.js.map +1 -1
- package/dist/models/User.d.ts +1 -1
- package/dist/models/User.d.ts.map +1 -1
- package/dist/models/User.js +1 -1
- package/dist/models/User.js.map +1 -1
- package/dist/models/_relations.js +25 -0
- package/dist/models/_relations.js.map +1 -1
- package/dist/models/addresses/City.d.ts +4 -4
- package/dist/models/addresses/City.d.ts.map +1 -1
- package/dist/models/addresses/City.js +6 -6
- package/dist/models/addresses/City.js.map +1 -1
- package/dist/models/addresses/PostalCode.d.ts +2 -2
- package/dist/models/addresses/PostalCode.d.ts.map +1 -1
- package/dist/models/addresses/PostalCode.js +4 -3
- package/dist/models/addresses/PostalCode.js.map +1 -1
- package/dist/models/addresses/Street.d.ts +3 -3
- package/dist/models/addresses/Street.d.ts.map +1 -1
- package/dist/models/addresses/Street.js +4 -4
- package/dist/models/addresses/Street.js.map +1 -1
- package/dist/models/index.d.ts +2 -0
- package/dist/models/index.d.ts.map +1 -1
- package/dist/models/index.js +2 -0
- package/dist/models/index.js.map +1 -1
- package/dist/models/v1GroupMigrationData.d.ts +22 -0
- package/dist/models/v1GroupMigrationData.d.ts.map +1 -0
- package/dist/models/v1GroupMigrationData.js +48 -0
- package/dist/models/v1GroupMigrationData.js.map +1 -0
- package/package.json +41 -13
- package/src/factories/GroupFactory.ts +4 -6
- package/src/factories/OrganizationFactory.ts +12 -4
- package/src/factories/RegistrationInvitationFactory.ts +24 -0
- package/src/factories/STPackageFactory.ts +2 -2
- package/src/factories/UserFactory.ts +4 -5
- package/src/factories/index.ts +1 -0
- package/src/helpers/EmailBuilder.ts +19 -28
- package/src/helpers/Handlebars.ts +10 -1
- package/src/helpers/InvoiceCounter.test.ts +220 -0
- package/src/helpers/InvoiceCounter.ts +162 -0
- package/src/index.ts +0 -1
- package/src/migrations/1605262045-import-postcodes.ts +62 -25
- package/src/migrations/1605262046-import-postcodes-nl.ts +58 -17
- package/src/migrations/1719567881-organization-periodId.sql +2 -0
- package/src/migrations/1719567882-groups-periodId.sql +2 -0
- package/src/migrations/1720080975-convert-charset.ts +34 -0
- package/src/migrations/1720080976-convert-charset-leads.ts +16 -13
- package/src/migrations/1721400546-users-memberId.sql +2 -0
- package/src/migrations/1722269236-group-waitinglist-id.sql +2 -1
- package/src/migrations/1722525785-balance-item-paying-organization-id.sql +2 -0
- package/src/migrations/1722525787-depending-balance-item.sql +2 -0
- package/src/migrations/1722963554-registration-group-price-and-options.sql +1 -1
- package/src/migrations/1723652797-payments-paying-organization-id-fk.sql +2 -0
- package/src/migrations/1733317908-added-missing-organization-fk-on-registrations.sql +2 -0
- package/src/migrations/1733317910-paying-organization-id-fk.sql +2 -0
- package/src/migrations/1733504881-negative-invoice-id.sql +6 -0
- package/src/migrations/1733994455-balance-item-status-open.ts +30 -0
- package/src/migrations/1763216320-bigint-balance-item-payments.sql +2 -0
- package/src/migrations/1763216320-bigint-balance-items.sql +5 -0
- package/src/migrations/1763216320-bigint-orders.sql +2 -0
- package/src/migrations/1763216320-bigint-payments.sql +2 -0
- package/src/migrations/1763216332-bigint-balance-item-price-total.sql +2 -0
- package/src/migrations/1769087808-corrected-invoice-user-agent.sql +2 -0
- package/src/migrations/1769087809-payments-invoice-id.sql +2 -0
- package/src/migrations/1772033555-balance-item-package-id.sql +2 -0
- package/src/migrations/1776873089-create-registration-invitations-table.sql +13 -0
- package/src/migrations/1778657958-payments-create-mandate.sql +2 -0
- package/src/migrations/1778657959-payments-mandate-id.sql +2 -0
- package/src/migrations/1778796615-payments-reversing-payment-id.sql +5 -0
- package/src/migrations/1778950642-price-invoiced.sql +2 -0
- package/src/migrations/1779443446-transfer-fees.sql +3 -0
- package/src/migrations/1779709174-used-register-code-balance-item-id.sql +5 -0
- package/src/migrations/1779968328-payments-admin-user-id.sql +5 -0
- package/src/migrations/1779970611-payments-refunded-amount.sql +2 -0
- package/src/migrations/1779972640-balance-items-failed-at.sql +2 -0
- package/src/migrations/1780328285-document-template-locked.sql +2 -0
- package/src/migrations/1780328286-document-locked.sql +2 -0
- package/src/migrations/1780412083-documents-set-locked.ts +18 -0
- package/src/migrations/1780928401-v1-groups-migration-data.ts +50 -0
- package/src/models/BalanceItem.ts +98 -43
- package/src/models/CachedBalance.test.ts +46 -46
- package/src/models/CachedBalance.ts +7 -7
- package/src/models/Document.ts +34 -13
- package/src/models/DocumentTemplate.ts +56 -17
- package/src/models/Email.test.ts +3 -3
- package/src/models/Email.ts +28 -49
- package/src/models/EmailVerificationCode.ts +8 -22
- package/src/models/Event.ts +6 -4
- package/src/models/EventNotification.ts +6 -6
- package/src/models/Group.ts +24 -3
- package/src/models/Invoice.ts +10 -9
- package/src/models/MemberPlatformMembership.test.ts +70 -0
- package/src/models/MemberPlatformMembership.ts +16 -12
- package/src/models/MollieToken.ts +42 -102
- package/src/models/Order.ts +14 -26
- package/src/models/Organization.ts +143 -86
- package/src/models/PasswordToken.ts +21 -21
- package/src/models/Payment.ts +61 -4
- package/src/models/Registration.ts +6 -5
- package/src/models/RegistrationInvitation.ts +40 -0
- package/src/models/STCredit.ts +32 -0
- package/src/models/STInvoice.ts +11 -5
- package/src/models/STPackage.ts +19 -14
- package/src/models/UsedRegisterCode.ts +34 -0
- package/src/models/User.ts +6 -7
- package/src/models/_relations.ts +29 -0
- package/src/models/addresses/City.ts +8 -6
- package/src/models/addresses/PostalCode.test.ts +1 -0
- package/src/models/addresses/PostalCode.ts +5 -3
- package/src/models/addresses/Street.ts +6 -4
- package/src/models/index.ts +3 -0
- package/src/models/v1GroupMigrationData.ts +43 -0
- package/dist/helpers/MemberMerger.d.ts +0 -14
- package/dist/helpers/MemberMerger.d.ts.map +0 -1
- package/dist/helpers/MemberMerger.js +0 -364
- package/dist/helpers/MemberMerger.js.map +0 -1
- package/dist/migrations/1720080975-convert-charset.sql +0 -85
- package/dist/migrations/1723202126-member-number-index.sql +0 -2
- package/dist/models/OneTimeToken.d.ts +0 -38
- package/dist/models/OneTimeToken.d.ts.map +0 -1
- package/dist/models/OneTimeToken.js +0 -125
- package/dist/models/OneTimeToken.js.map +0 -1
- package/src/helpers/MemberMerger.test.ts +0 -782
- package/src/helpers/MemberMerger.ts +0 -577
- package/src/migrations/1720080975-convert-charset.sql +0 -85
- package/src/migrations/1723202126-member-number-index.sql +0 -2
- package/src/models/OneTimeToken.ts +0 -133
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { QueueHandler } from '@stamhoofd/queues';
|
|
2
|
+
|
|
3
|
+
import type { OrganizationInvoiceSettings } from '@stamhoofd/structures/OrganizationInvoiceSettings.js';
|
|
4
|
+
import { Formatter } from '@stamhoofd/utility';
|
|
5
|
+
import type { DateTime } from 'luxon';
|
|
6
|
+
import { Invoice } from '../models/Invoice.js';
|
|
7
|
+
|
|
8
|
+
export class InvoiceCounter {
|
|
9
|
+
static numberCache: Map<string, {lastNumber: number, date: Date}> = new Map();
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
private static getNextResetDate(last: DateTime, resetMonth: number): DateTime {
|
|
13
|
+
const candidate = last.set({ month: resetMonth, day: 1 }).startOf('day');
|
|
14
|
+
return candidate > last ? candidate : candidate.plus({ years: 1 }).startOf('day');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static shouldStartNewSeries(settings: OrganizationInvoiceSettings, lastInvoiceDate: Date, invoiceDate: Date) {
|
|
18
|
+
if (settings.resetMonth === null) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const last = Formatter.luxon(lastInvoiceDate);
|
|
23
|
+
const current = Formatter.luxon(invoiceDate);
|
|
24
|
+
|
|
25
|
+
return current >= this.getNextResetDate(last, settings.resetMonth)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* XXX-123 -> 123
|
|
30
|
+
* YYY-0001 -> 1
|
|
31
|
+
*
|
|
32
|
+
* if prefix is enabled:
|
|
33
|
+
* 2025001 -> 1
|
|
34
|
+
* STA-2025001 -> 1
|
|
35
|
+
*/
|
|
36
|
+
static parseNumber(settings: OrganizationInvoiceSettings, str: string) {
|
|
37
|
+
str = str.replace(/\D+/g, '-').replace(/^-+/, '').replace(/-+$/, '');
|
|
38
|
+
// Remove prefixes and possibly year
|
|
39
|
+
const splitted = str.split('-');
|
|
40
|
+
|
|
41
|
+
let last = splitted[splitted.length - 1];
|
|
42
|
+
|
|
43
|
+
const stripYear = settings.prefixYear
|
|
44
|
+
|
|
45
|
+
if (last.length) {
|
|
46
|
+
if (stripYear) {
|
|
47
|
+
if (last.length <= 4) {
|
|
48
|
+
console.error('Could not parse invoice number from string ' + str + ' (could not trim year prefix)')
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
last = last.substring(4)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const int = parseInt(last);
|
|
55
|
+
if (int !== 0 && !isNaN(int) && isFinite(int)) {
|
|
56
|
+
return int;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
console.error('Could not parse invoice number from string ' + str)
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static formatNumber(settings: OrganizationInvoiceSettings, int: number, invoicedAt: Date) {
|
|
65
|
+
let str = int.toFixed(0).padStart(settings.padZeroLength, '0')
|
|
66
|
+
|
|
67
|
+
if (settings.prefixYear) {
|
|
68
|
+
const year = Formatter.luxon(invoicedAt).year
|
|
69
|
+
str = year + str;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (settings.fixedPrefix) {
|
|
73
|
+
if (!settings.fixedPrefix.match(/\D$/)) {
|
|
74
|
+
// Need seperation character
|
|
75
|
+
str = settings.fixedPrefix.replace(/-$/, '') + '-' + str;
|
|
76
|
+
} else {
|
|
77
|
+
str = settings.fixedPrefix + str;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return str;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
static async assignNextNumber(invoice: Invoice, settings: OrganizationInvoiceSettings): Promise<void> {
|
|
85
|
+
const organizationId = invoice.organizationId
|
|
86
|
+
return await QueueHandler.schedule('invoice/numbers-' + organizationId, async () => {
|
|
87
|
+
// Invoice date should be inside the queue to ensure it is chronologically generated
|
|
88
|
+
const invoicedAt = new Date();
|
|
89
|
+
|
|
90
|
+
const c = this.numberCache.get(organizationId);
|
|
91
|
+
if (c !== undefined) {
|
|
92
|
+
const lastNumber = c.lastNumber
|
|
93
|
+
|
|
94
|
+
// check date
|
|
95
|
+
if (!this.shouldStartNewSeries(settings, c.date, invoicedAt)) {
|
|
96
|
+
// Set and save.
|
|
97
|
+
// we do this here because it assures we'll not increase the next number if the save fails
|
|
98
|
+
invoice.number = this.formatNumber(settings, lastNumber + 1, invoicedAt);
|
|
99
|
+
invoice.invoicedAt = invoicedAt;
|
|
100
|
+
await invoice.save()
|
|
101
|
+
|
|
102
|
+
// If save succeeds, increase cache:
|
|
103
|
+
this.numberCache.set(organizationId, {
|
|
104
|
+
lastNumber: lastNumber + 1,
|
|
105
|
+
date: new Date(invoicedAt)
|
|
106
|
+
});
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const lastInvoice = await Invoice.select()
|
|
112
|
+
.where('organizationId', organizationId)
|
|
113
|
+
.where('number', '!=', null)
|
|
114
|
+
.where('invoicedAt', '!=', null)
|
|
115
|
+
.orderBy('invoicedAt', 'DESC')
|
|
116
|
+
.first(false);
|
|
117
|
+
|
|
118
|
+
if (lastInvoice && lastInvoice.number && lastInvoice.invoicedAt) {
|
|
119
|
+
// check date
|
|
120
|
+
if (!this.shouldStartNewSeries(settings, lastInvoice.invoicedAt, invoicedAt)) {
|
|
121
|
+
const lastNumber = this.parseNumber(settings, lastInvoice.number)
|
|
122
|
+
|
|
123
|
+
if (lastNumber) {
|
|
124
|
+
invoice.number = this.formatNumber(settings, lastNumber + 1, invoicedAt);
|
|
125
|
+
invoice.invoicedAt = invoicedAt;
|
|
126
|
+
await invoice.save()
|
|
127
|
+
|
|
128
|
+
this.numberCache.set(organizationId, {
|
|
129
|
+
lastNumber: lastNumber + 1,
|
|
130
|
+
date: new Date(invoicedAt)
|
|
131
|
+
});
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Start new
|
|
138
|
+
invoice.number = this.formatNumber(settings, 1, invoicedAt);
|
|
139
|
+
invoice.invoicedAt = invoicedAt;
|
|
140
|
+
await invoice.save()
|
|
141
|
+
|
|
142
|
+
this.numberCache.set(organizationId, {
|
|
143
|
+
lastNumber: 1,
|
|
144
|
+
date: new Date(invoicedAt)
|
|
145
|
+
});
|
|
146
|
+
return;
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
static async resetNumbers(organizationId: string): Promise<void> {
|
|
151
|
+
// Prevent race conditions: create a queue
|
|
152
|
+
// The queue can only run one at a time for the same webshop (so multiple webshops at the same time are allowed)
|
|
153
|
+
return await QueueHandler.schedule('invoice/numbers-' + organizationId, async () => {
|
|
154
|
+
this.numberCache.delete(organizationId);
|
|
155
|
+
return Promise.resolve();
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
static clearAll() {
|
|
160
|
+
this.numberCache.clear();
|
|
161
|
+
}
|
|
162
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { column, Migration } from '@simonbackx/simple-database';
|
|
1
|
+
import { column, Database, Migration } from '@simonbackx/simple-database';
|
|
2
2
|
import { QueryableModel } from '@stamhoofd/sql';
|
|
3
3
|
import { Country } from '@stamhoofd/types/Country';
|
|
4
4
|
import { StringCompare } from '@stamhoofd/utility';
|
|
5
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
5
6
|
import { City } from '../models/addresses/City.js';
|
|
6
7
|
import { PostalCode } from '../models/addresses/PostalCode.js';
|
|
7
8
|
import { Province } from '../models/addresses/Province.js';
|
|
@@ -33,16 +34,17 @@ export class Gemeente extends QueryableModel {
|
|
|
33
34
|
city!: City;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
function getProvince(name: string, provinces: Province[], provinceRows: string[][]): Province {
|
|
37
38
|
const p = provinces.find(p => StringCompare.typoCount(p.name, name) < 2 && p.country == Country.Belgium);
|
|
38
39
|
if (p) {
|
|
39
40
|
return p;
|
|
40
41
|
}
|
|
41
42
|
const province = new Province();
|
|
43
|
+
province.id = uuidv4();
|
|
42
44
|
province.country = Country.Belgium;
|
|
43
45
|
province.name = name.trim();
|
|
44
|
-
await province.save();
|
|
45
46
|
provinces.push(province);
|
|
47
|
+
provinceRows.push([province.id, province.name, province.country]);
|
|
46
48
|
return province;
|
|
47
49
|
}
|
|
48
50
|
|
|
@@ -54,42 +56,38 @@ export default new Migration(async () => {
|
|
|
54
56
|
// Loop all gemeenten
|
|
55
57
|
const provinces = await Province.all();
|
|
56
58
|
const gemeenten = await Gemeente.all();
|
|
57
|
-
const
|
|
59
|
+
const citiesByNameAndProvince = new Map<string, City>();
|
|
60
|
+
const provinceRows: string[][] = [];
|
|
61
|
+
const cityRows: unknown[][] = [];
|
|
62
|
+
const postalCodeRows: string[][] = [];
|
|
63
|
+
const parentCityUpdates = new Map<string, string>();
|
|
58
64
|
|
|
59
65
|
for (const gemeente of gemeenten) {
|
|
60
|
-
const province =
|
|
66
|
+
const province = getProvince(gemeente.provincie, provinces, provinceRows);
|
|
61
67
|
|
|
62
68
|
// Some cities have the same name
|
|
63
|
-
const found =
|
|
69
|
+
const found = citiesByNameAndProvince.get(cityKey(gemeente.gemeente, province.id));
|
|
64
70
|
|
|
65
71
|
if (!found) {
|
|
66
72
|
// Create the city
|
|
67
73
|
const city = new City();
|
|
74
|
+
city.id = uuidv4();
|
|
68
75
|
city.name = gemeente.gemeente.trim();
|
|
69
76
|
city.country = Country.Belgium;
|
|
70
77
|
city.provinceId = province.id;
|
|
71
|
-
|
|
72
|
-
await city.save();
|
|
78
|
+
cityRows.push([city.id, city.name, city.provinceId, city.parentCityId, city.country]);
|
|
73
79
|
|
|
74
80
|
// Also add postal code already
|
|
75
|
-
|
|
76
|
-
postalCode.postalCode = gemeente.postcode;
|
|
77
|
-
postalCode.cityId = city.id;
|
|
78
|
-
postalCode.country = Country.Belgium;
|
|
79
|
-
await postalCode.save();
|
|
81
|
+
postalCodeRows.push([uuidv4(), gemeente.postcode, city.id, Country.Belgium]);
|
|
80
82
|
|
|
81
83
|
gemeente.city = city;
|
|
82
|
-
|
|
84
|
+
citiesByNameAndProvince.set(cityKey(city.name, city.provinceId), city);
|
|
83
85
|
}
|
|
84
86
|
else {
|
|
85
87
|
gemeente.city = found;
|
|
86
88
|
|
|
87
89
|
// Also add postal code already
|
|
88
|
-
|
|
89
|
-
postalCode.postalCode = gemeente.postcode;
|
|
90
|
-
postalCode.cityId = found.id;
|
|
91
|
-
postalCode.country = Country.Belgium;
|
|
92
|
-
await postalCode.save();
|
|
90
|
+
postalCodeRows.push([uuidv4(), gemeente.postcode, found.id, Country.Belgium]);
|
|
93
91
|
}
|
|
94
92
|
}
|
|
95
93
|
|
|
@@ -98,28 +96,67 @@ export default new Migration(async () => {
|
|
|
98
96
|
continue;
|
|
99
97
|
}
|
|
100
98
|
|
|
101
|
-
const hoofd =
|
|
99
|
+
const hoofd = citiesByNameAndProvince.get(cityKey(gemeente.hoofdgemeente, gemeente.city.provinceId));
|
|
102
100
|
if (!hoofd) {
|
|
103
101
|
// Create the city
|
|
104
102
|
const city = new City();
|
|
103
|
+
city.id = uuidv4();
|
|
105
104
|
city.name = gemeente.hoofdgemeente.trim();
|
|
106
105
|
city.country = Country.Belgium;
|
|
107
106
|
|
|
108
|
-
const province =
|
|
107
|
+
const province = getProvince(gemeente.provincie, provinces, provinceRows);
|
|
109
108
|
city.provinceId = province.id;
|
|
110
|
-
|
|
109
|
+
cityRows.push([city.id, city.name, city.provinceId, city.parentCityId, city.country]);
|
|
111
110
|
|
|
112
|
-
|
|
111
|
+
citiesByNameAndProvince.set(cityKey(city.name, city.provinceId), city);
|
|
113
112
|
// do not create a postal code here, these don't have one
|
|
114
113
|
|
|
115
114
|
// console.log('Assigning ' + gemeente.gemeente + ' to ' + city.name);
|
|
116
115
|
gemeente.city.parentCityId = city.id;
|
|
117
|
-
|
|
116
|
+
parentCityUpdates.set(gemeente.city.id, city.id);
|
|
118
117
|
}
|
|
119
118
|
else {
|
|
120
119
|
// console.log('Assigning ' + gemeente.gemeente + ' to ' + hoofd.name);
|
|
121
120
|
gemeente.city.parentCityId = hoofd.id;
|
|
122
|
-
|
|
121
|
+
parentCityUpdates.set(gemeente.city.id, hoofd.id);
|
|
123
122
|
}
|
|
124
123
|
}
|
|
124
|
+
|
|
125
|
+
await insertRows(Province.table, ['id', 'name', 'country'], provinceRows);
|
|
126
|
+
await insertRows(City.table, ['id', 'name', 'provinceId', 'parentCityId', 'country'], cityRows);
|
|
127
|
+
await insertRows(PostalCode.table, ['id', 'postalCode', 'cityId', 'country'], postalCodeRows);
|
|
128
|
+
await updateParentCityIds([...parentCityUpdates.entries()]);
|
|
125
129
|
});
|
|
130
|
+
function cityKey(name: string, provinceId: string): string {
|
|
131
|
+
return `${name.trim()}\0${provinceId}`;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async function insertRows(table: string, columns: string[], rows: unknown[][]): Promise<void> {
|
|
135
|
+
for (const chunk of chunks(rows, 1000)) {
|
|
136
|
+
if (chunk.length === 0) {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
await Database.insert(`INSERT INTO \`${table}\` (${columns.map(column => `\`${column}\``).join(', ')}) VALUES ?`, [chunk]);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async function updateParentCityIds(rows: string[][]): Promise<void> {
|
|
144
|
+
for (const chunk of chunks(rows, 1000)) {
|
|
145
|
+
if (chunk.length === 0) {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
const cases = chunk.map(() => 'WHEN ? THEN ?').join(' ');
|
|
149
|
+
await Database.statement(`UPDATE \`${City.table}\` SET \`parentCityId\` = CASE \`id\` ${cases} END WHERE \`id\` IN (?)`, [
|
|
150
|
+
...chunk.flatMap(([cityId, parentCityId]) => [cityId, parentCityId]),
|
|
151
|
+
chunk.map(([cityId]) => cityId),
|
|
152
|
+
]);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function chunks<T>(values: T[], size: number): T[][] {
|
|
157
|
+
const result: T[][] = [];
|
|
158
|
+
for (let index = 0; index < values.length; index += size) {
|
|
159
|
+
result.push(values.slice(index, index + size));
|
|
160
|
+
}
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
@@ -1,39 +1,42 @@
|
|
|
1
|
-
import { Migration } from '@simonbackx/simple-database';
|
|
1
|
+
import { Database, Migration } from '@simonbackx/simple-database';
|
|
2
2
|
import { Country } from '@stamhoofd/types/Country';
|
|
3
3
|
import { StringCompare } from '@stamhoofd/utility';
|
|
4
4
|
import fs from 'fs';
|
|
5
5
|
import readline from 'readline';
|
|
6
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
6
7
|
|
|
7
8
|
import { City } from '../models/addresses/City.js';
|
|
8
9
|
import { PostalCode } from '../models/addresses/PostalCode.js';
|
|
9
10
|
import { Province } from '../models/addresses/Province.js';
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
function getProvince(name: string, provinces: Province[], provinceRows: string[][]): Province {
|
|
12
13
|
const p = provinces.find(p => StringCompare.typoCount(p.name, name) == 0 && p.country == Country.Netherlands);
|
|
13
14
|
if (p) {
|
|
14
15
|
return p;
|
|
15
16
|
}
|
|
16
17
|
const province = new Province();
|
|
18
|
+
province.id = uuidv4();
|
|
17
19
|
province.country = Country.Netherlands;
|
|
18
20
|
province.name = name;
|
|
19
|
-
await province.save();
|
|
20
21
|
|
|
21
22
|
provinces.push(province);
|
|
23
|
+
provinceRows.push([province.id, province.name, province.country]);
|
|
22
24
|
return province;
|
|
23
25
|
}
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
const p =
|
|
27
|
+
function getCity(name: string, provinceId: string, citiesByName: Map<string, City>, cityRows: unknown[][]): City {
|
|
28
|
+
const p = citiesByName.get(normalizeCityName(name));
|
|
27
29
|
if (p) {
|
|
28
30
|
return p;
|
|
29
31
|
}
|
|
30
32
|
const city = new City();
|
|
33
|
+
city.id = uuidv4();
|
|
31
34
|
city.name = name;
|
|
32
35
|
city.country = Country.Netherlands;
|
|
33
36
|
city.provinceId = provinceId;
|
|
34
|
-
|
|
37
|
+
cityRows.push([city.id, city.name, city.provinceId, city.parentCityId, city.country]);
|
|
35
38
|
|
|
36
|
-
|
|
39
|
+
citiesByName.set(normalizeCityName(city.name), city);
|
|
37
40
|
return city;
|
|
38
41
|
}
|
|
39
42
|
|
|
@@ -52,11 +55,15 @@ export default new Migration(async () => {
|
|
|
52
55
|
});
|
|
53
56
|
|
|
54
57
|
const allProvinces = await Province.where({ country: Country.Netherlands });
|
|
58
|
+
const provinceRows: string[][] = [];
|
|
59
|
+
const cityRows: unknown[][] = [];
|
|
60
|
+
const postalCodeRows: string[][] = [];
|
|
61
|
+
const parentCityUpdates: string[][] = [];
|
|
55
62
|
|
|
56
63
|
for (const p of provinces) {
|
|
57
64
|
// console.log(p.name);
|
|
58
65
|
|
|
59
|
-
const province =
|
|
66
|
+
const province = getProvince(p.name.trim(), allProvinces, provinceRows);
|
|
60
67
|
|
|
61
68
|
// const cities = await fs.readFile(p.path, { encoding: "utf-8" });
|
|
62
69
|
|
|
@@ -64,7 +71,7 @@ export default new Migration(async () => {
|
|
|
64
71
|
input: fs.createReadStream(p.path, { encoding: 'utf-8' }),
|
|
65
72
|
});
|
|
66
73
|
|
|
67
|
-
const
|
|
74
|
+
const citiesByName = new Map<string, City>();
|
|
68
75
|
|
|
69
76
|
for await (const line of lineReader) {
|
|
70
77
|
const splitted = line.split('\t');
|
|
@@ -77,19 +84,53 @@ export default new Migration(async () => {
|
|
|
77
84
|
const plaats = splitted[2].trim();
|
|
78
85
|
|
|
79
86
|
// Check plaats and gemeente
|
|
80
|
-
const city =
|
|
81
|
-
const city2 =
|
|
87
|
+
const city = getCity(plaats, province.id, citiesByName, cityRows);
|
|
88
|
+
const city2 = getCity(gemeente, province.id, citiesByName, cityRows); // might be the same as city
|
|
82
89
|
if (city2.id !== city.id && city.parentCityId === null) {
|
|
83
90
|
city.parentCityId = city2.id;
|
|
84
|
-
|
|
91
|
+
parentCityUpdates.push([city.id, city2.id]);
|
|
85
92
|
}
|
|
86
93
|
|
|
87
94
|
// Also add postal code already
|
|
88
|
-
|
|
89
|
-
postalCode.postalCode = postcode;
|
|
90
|
-
postalCode.cityId = city.id;
|
|
91
|
-
postalCode.country = Country.Netherlands;
|
|
92
|
-
await postalCode.save();
|
|
95
|
+
postalCodeRows.push([uuidv4(), postcode, city.id, Country.Netherlands]);
|
|
93
96
|
}
|
|
94
97
|
}
|
|
98
|
+
|
|
99
|
+
await insertRows(Province.table, ['id', 'name', 'country'], provinceRows);
|
|
100
|
+
await insertRows(City.table, ['id', 'name', 'provinceId', 'parentCityId', 'country'], cityRows);
|
|
101
|
+
await insertRows(PostalCode.table, ['id', 'postalCode', 'cityId', 'country'], postalCodeRows);
|
|
102
|
+
await updateParentCityIds(parentCityUpdates);
|
|
95
103
|
});
|
|
104
|
+
function normalizeCityName(name: string): string {
|
|
105
|
+
return name.normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase().replace(/\s+/, ' ').trim();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async function insertRows(table: string, columns: string[], rows: unknown[][]): Promise<void> {
|
|
109
|
+
for (const chunk of chunks(rows, 1000)) {
|
|
110
|
+
if (chunk.length === 0) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
await Database.insert(`INSERT INTO \`${table}\` (${columns.map(column => `\`${column}\``).join(', ')}) VALUES ?`, [chunk]);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async function updateParentCityIds(rows: string[][]): Promise<void> {
|
|
118
|
+
for (const chunk of chunks(rows, 1000)) {
|
|
119
|
+
if (chunk.length === 0) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
const cases = chunk.map(() => 'WHEN ? THEN ?').join(' ');
|
|
123
|
+
await Database.statement(`UPDATE \`${City.table}\` SET \`parentCityId\` = CASE \`id\` ${cases} END WHERE \`id\` IN (?)`, [
|
|
124
|
+
...chunk.flatMap(([cityId, parentCityId]) => [cityId, parentCityId]),
|
|
125
|
+
chunk.map(([cityId]) => cityId),
|
|
126
|
+
]);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function chunks<T>(values: T[], size: number): T[][] {
|
|
131
|
+
const result: T[][] = [];
|
|
132
|
+
for (let index = 0; index < values.length; index += size) {
|
|
133
|
+
result.push(values.slice(index, index + size));
|
|
134
|
+
}
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
+
SET FOREIGN_KEY_CHECKS=0;
|
|
1
2
|
ALTER TABLE `organizations` ADD COLUMN `periodId` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL;
|
|
2
3
|
ALTER TABLE `organizations` ADD FOREIGN KEY (`periodId`) REFERENCES `registration_periods` (`id`) ON UPDATE CASCADE ON DELETE RESTRICT;
|
|
4
|
+
SET FOREIGN_KEY_CHECKS=1;
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
+
SET FOREIGN_KEY_CHECKS=0;
|
|
1
2
|
ALTER TABLE `groups` ADD COLUMN `periodId` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL;
|
|
2
3
|
ALTER TABLE `groups` ADD FOREIGN KEY (`periodId`) REFERENCES `registration_periods` (`id`) ON UPDATE CASCADE ON DELETE RESTRICT;
|
|
4
|
+
SET FOREIGN_KEY_CHECKS=1;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Database, Migration } from '@simonbackx/simple-database';
|
|
2
|
+
import { LoggingTools } from '@stamhoofd/utility';
|
|
3
|
+
|
|
4
|
+
export default new Migration(async () => {
|
|
5
|
+
process.stdout.write('\n');
|
|
6
|
+
|
|
7
|
+
if (STAMHOOFD.userMode === 'platform' && (STAMHOOFD.environment === 'production' || STAMHOOFD.environment === 'staging')) {
|
|
8
|
+
console.log('Skipped convert charset for userMode platform in production.');
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const tables = ['_members_users', 'balance_item_payments', 'balance_items', 'buckaroo_payments', 'cities', 'document_templates', 'documents', 'email_templates', 'email_verification_codes', 'groups', 'images', 'members', 'migrations', 'mollie_payments', 'mollie_tokens', 'organization_registration_periods', 'organizations', 'password_tokens', 'payconiq_payments', 'payments', 'platform', 'postal_codes', 'provinces', 'register_codes', 'registration_periods', 'registrations', 'stamhoofd_credits', 'stamhoofd_invoices', 'stamhoofd_packages', 'stamhoofd_pending_invoices', 'streets', 'stripe_accounts', 'stripe_checkout_sessions', 'stripe_payment_intents', 'tokens', 'used_register_codes', 'users', 'webshop_discount_codes', 'webshop_orders', 'webshop_tickets', 'webshops'];
|
|
13
|
+
|
|
14
|
+
const progressLogger = LoggingTools.createProgressLogger(tables.length, { tag: 'convert tables charset' });
|
|
15
|
+
|
|
16
|
+
for (const table of tables) {
|
|
17
|
+
await convertTable(table);
|
|
18
|
+
progressLogger.update();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
console.log('Start set database charset.');
|
|
22
|
+
await Database.statement('ALTER DATABASE CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
async function convertTable(name: string): Promise<void> {
|
|
26
|
+
await Database.beginTransaction(async () => {
|
|
27
|
+
await Database.statement('set foreign_key_checks=0;');
|
|
28
|
+
|
|
29
|
+
console.log('Start converting charset of table: ' + name);
|
|
30
|
+
await Database.statement('ALTER TABLE `' + name + '` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;');
|
|
31
|
+
|
|
32
|
+
await Database.statement('set foreign_key_checks=1;');
|
|
33
|
+
});
|
|
34
|
+
}
|
|
@@ -3,14 +3,14 @@ import { Database, Migration } from '@simonbackx/simple-database';
|
|
|
3
3
|
/**
|
|
4
4
|
* If the charset of the leads table is not converted this results
|
|
5
5
|
* in foreign keys constraint errors in other migrations.
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
7
|
* todo: will we keep the leads table after the migration?
|
|
8
8
|
*/
|
|
9
9
|
export default new Migration(async () => {
|
|
10
10
|
process.stdout.write('\n');
|
|
11
11
|
|
|
12
|
-
if (STAMHOOFD.userMode === 'platform') {
|
|
13
|
-
console.log('Skipped update leads charset for userMode platform.')
|
|
12
|
+
if (STAMHOOFD.userMode === 'platform' && (STAMHOOFD.environment === 'production' || STAMHOOFD.environment === 'staging')) {
|
|
13
|
+
console.log('Skipped update leads charset for userMode platform in production.');
|
|
14
14
|
return Promise.resolve();
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -18,15 +18,7 @@ export default new Migration(async () => {
|
|
|
18
18
|
console.log('Has leads table: ' + hasTable);
|
|
19
19
|
|
|
20
20
|
if (hasTable) {
|
|
21
|
-
|
|
22
|
-
'set foreign_key_checks=0;',
|
|
23
|
-
'ALTER TABLE `leads` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;',
|
|
24
|
-
'ALTER TABLE `leads` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;',
|
|
25
|
-
'set foreign_key_checks=1;'
|
|
26
|
-
].join('');
|
|
27
|
-
|
|
28
|
-
console.log('Start updating charset of leads table.');
|
|
29
|
-
await Database.statement(sqlStatement);
|
|
21
|
+
await convertTable('leads');
|
|
30
22
|
}
|
|
31
23
|
|
|
32
24
|
return Promise.resolve();
|
|
@@ -40,7 +32,7 @@ async function tableExists(tableName: string): Promise<boolean> {
|
|
|
40
32
|
WHERE table_schema = DATABASE()
|
|
41
33
|
AND table_name = ?
|
|
42
34
|
`,
|
|
43
|
-
[tableName]
|
|
35
|
+
[tableName],
|
|
44
36
|
);
|
|
45
37
|
|
|
46
38
|
const count = rows[0]['']['count'];
|
|
@@ -51,3 +43,14 @@ async function tableExists(tableName: string): Promise<boolean> {
|
|
|
51
43
|
|
|
52
44
|
return count > 0;
|
|
53
45
|
}
|
|
46
|
+
|
|
47
|
+
async function convertTable(name: string): Promise<void> {
|
|
48
|
+
await Database.beginTransaction(async () => {
|
|
49
|
+
await Database.statement('set foreign_key_checks=0;');
|
|
50
|
+
|
|
51
|
+
console.log('Start converting charset of table: ' + name);
|
|
52
|
+
await Database.statement('ALTER TABLE `' + name + '` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;');
|
|
53
|
+
|
|
54
|
+
await Database.statement('set foreign_key_checks=1;');
|
|
55
|
+
});
|
|
56
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
+
SET FOREIGN_KEY_CHECKS=0;
|
|
1
2
|
ALTER TABLE `groups`
|
|
2
3
|
ADD COLUMN `waitingListId` varchar(36) NULL AFTER `defaultAgeGroupId`;
|
|
3
|
-
|
|
4
4
|
ALTER TABLE `groups` ADD FOREIGN KEY (`waitingListId`) REFERENCES `groups` (`id`) ON UPDATE CASCADE ON DELETE SET NULL;
|
|
5
|
+
SET FOREIGN_KEY_CHECKS=1;
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
+
SET FOREIGN_KEY_CHECKS=0;
|
|
1
2
|
ALTER TABLE `balance_items` ADD COLUMN `payingOrganizationId` varchar(36) NULL;
|
|
2
3
|
ALTER TABLE `balance_items` ADD FOREIGN KEY (`payingOrganizationId`) REFERENCES `organizations` (`id`) ON UPDATE CASCADE ON DELETE SET NULL;
|
|
4
|
+
SET FOREIGN_KEY_CHECKS=1;
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
+
SET FOREIGN_KEY_CHECKS=0;
|
|
1
2
|
ALTER TABLE `balance_items` ADD COLUMN `dependingBalanceItemId` varchar(36) NULL;
|
|
2
3
|
ALTER TABLE `balance_items` ADD FOREIGN KEY (`dependingBalanceItemId`) REFERENCES `balance_items` (`id`) ON UPDATE CASCADE ON DELETE SET NULL;
|
|
4
|
+
SET FOREIGN_KEY_CHECKS=1;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
ALTER TABLE `registrations`
|
|
2
2
|
ADD COLUMN `options` json NOT NULL DEFAULT ('{"value": [], "version": 0}') AFTER `price`,
|
|
3
|
-
ADD COLUMN `groupPrice` json NOT NULL DEFAULT ('{"value": {"id": "unknown", "name": "
|
|
3
|
+
ADD COLUMN `groupPrice` json NOT NULL DEFAULT ('{"value": {"id": "unknown", "name": "Standaardtarief", "price": {"price": 0, "reducedPrice": null}}, "version": 0}') AFTER `price`;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Database, Migration } from '@simonbackx/simple-database';
|
|
2
|
+
import { BalanceItemStatus } from '@stamhoofd/structures';
|
|
3
|
+
|
|
4
|
+
export default new Migration(async () => {
|
|
5
|
+
if (STAMHOOFD.environment === 'test') {
|
|
6
|
+
console.log('skipped in tests');
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const query = `
|
|
11
|
+
UPDATE
|
|
12
|
+
balance_items
|
|
13
|
+
SET status = ?
|
|
14
|
+
WHERE status IN (?)`;
|
|
15
|
+
await Database.update(query, [
|
|
16
|
+
BalanceItemStatus.Due,
|
|
17
|
+
['Paid', 'Pending'],
|
|
18
|
+
]);
|
|
19
|
+
|
|
20
|
+
const q2 = `
|
|
21
|
+
UPDATE
|
|
22
|
+
balance_items
|
|
23
|
+
SET status = ?,
|
|
24
|
+
amount = coalesce(nullif(ROUND(coalesce(pricePaid / nullif(unitPrice, 0), 0)), 0), 1)
|
|
25
|
+
WHERE amount = 0 AND status = ?`;
|
|
26
|
+
await Database.update(q2, [
|
|
27
|
+
BalanceItemStatus.Canceled,
|
|
28
|
+
BalanceItemStatus.Due,
|
|
29
|
+
]);
|
|
30
|
+
});
|