@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.
Files changed (296) hide show
  1. package/dist/factories/GroupFactory.d.ts.map +1 -1
  2. package/dist/factories/GroupFactory.js +1 -1
  3. package/dist/factories/GroupFactory.js.map +1 -1
  4. package/dist/factories/OrganizationFactory.d.ts +2 -1
  5. package/dist/factories/OrganizationFactory.d.ts.map +1 -1
  6. package/dist/factories/OrganizationFactory.js +9 -1
  7. package/dist/factories/OrganizationFactory.js.map +1 -1
  8. package/dist/factories/RegistrationInvitationFactory.d.ts +15 -0
  9. package/dist/factories/RegistrationInvitationFactory.d.ts.map +1 -0
  10. package/dist/factories/RegistrationInvitationFactory.js +18 -0
  11. package/dist/factories/RegistrationInvitationFactory.js.map +1 -0
  12. package/dist/factories/STPackageFactory.js.map +1 -1
  13. package/dist/factories/UserFactory.d.ts.map +1 -1
  14. package/dist/factories/UserFactory.js +2 -2
  15. package/dist/factories/UserFactory.js.map +1 -1
  16. package/dist/factories/index.d.ts +1 -0
  17. package/dist/factories/index.d.ts.map +1 -1
  18. package/dist/factories/index.js +1 -0
  19. package/dist/factories/index.js.map +1 -1
  20. package/dist/helpers/EmailBuilder.d.ts.map +1 -1
  21. package/dist/helpers/EmailBuilder.js +8 -8
  22. package/dist/helpers/EmailBuilder.js.map +1 -1
  23. package/dist/helpers/Handlebars.d.ts.map +1 -1
  24. package/dist/helpers/Handlebars.js +10 -1
  25. package/dist/helpers/Handlebars.js.map +1 -1
  26. package/dist/helpers/InvoiceCounter.d.ts +24 -0
  27. package/dist/helpers/InvoiceCounter.d.ts.map +1 -0
  28. package/dist/helpers/InvoiceCounter.js +133 -0
  29. package/dist/helpers/InvoiceCounter.js.map +1 -0
  30. package/dist/index.d.ts +0 -1
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +0 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/migrations/1605262045-import-postcodes.d.ts.map +1 -1
  35. package/dist/migrations/1605262045-import-postcodes.js +58 -24
  36. package/dist/migrations/1605262045-import-postcodes.js.map +1 -1
  37. package/dist/migrations/1605262046-import-postcodes-nl.d.ts.map +1 -1
  38. package/dist/migrations/1605262046-import-postcodes-nl.js +54 -17
  39. package/dist/migrations/1605262046-import-postcodes-nl.js.map +1 -1
  40. package/dist/migrations/1719567881-organization-periodId.sql +2 -0
  41. package/dist/migrations/1719567882-groups-periodId.sql +2 -0
  42. package/dist/migrations/1720080975-convert-charset.d.ts +4 -0
  43. package/dist/migrations/1720080975-convert-charset.d.ts.map +1 -0
  44. package/dist/migrations/1720080975-convert-charset.js +26 -0
  45. package/dist/migrations/1720080975-convert-charset.js.map +1 -0
  46. package/dist/migrations/1720080976-convert-charset-leads.d.ts.map +1 -1
  47. package/dist/migrations/1720080976-convert-charset-leads.js +11 -10
  48. package/dist/migrations/1720080976-convert-charset-leads.js.map +1 -1
  49. package/dist/migrations/1721400546-users-memberId.sql +2 -0
  50. package/dist/migrations/1722269236-group-waitinglist-id.sql +2 -1
  51. package/dist/migrations/1722525785-balance-item-paying-organization-id.sql +2 -0
  52. package/dist/migrations/1722525787-depending-balance-item.sql +2 -0
  53. package/dist/migrations/1722963554-registration-group-price-and-options.sql +1 -1
  54. package/dist/migrations/1723652797-payments-paying-organization-id-fk.sql +2 -0
  55. package/dist/migrations/1733317908-added-missing-organization-fk-on-registrations.sql +2 -0
  56. package/dist/migrations/1733317910-paying-organization-id-fk.sql +2 -0
  57. package/dist/migrations/1733504881-negative-invoice-id.sql +6 -0
  58. package/dist/migrations/1733994455-balance-item-status-open.d.ts +4 -0
  59. package/dist/migrations/1733994455-balance-item-status-open.d.ts.map +1 -0
  60. package/dist/migrations/1733994455-balance-item-status-open.js +28 -0
  61. package/dist/migrations/1733994455-balance-item-status-open.js.map +1 -0
  62. package/dist/migrations/1763216320-bigint-balance-item-payments.sql +2 -0
  63. package/dist/migrations/1763216320-bigint-balance-items.sql +5 -0
  64. package/dist/migrations/1763216320-bigint-orders.sql +2 -0
  65. package/dist/migrations/1763216320-bigint-payments.sql +2 -0
  66. package/dist/migrations/1763216332-bigint-balance-item-price-total.sql +2 -0
  67. package/dist/migrations/1769087808-corrected-invoice-user-agent.sql +2 -0
  68. package/dist/migrations/1769087809-payments-invoice-id.sql +2 -0
  69. package/dist/migrations/1772033555-balance-item-package-id.sql +2 -0
  70. package/dist/migrations/1776873089-create-registration-invitations-table.sql +13 -0
  71. package/dist/migrations/1778657958-payments-create-mandate.sql +2 -0
  72. package/dist/migrations/1778657959-payments-mandate-id.sql +2 -0
  73. package/dist/migrations/1778796615-payments-reversing-payment-id.sql +5 -0
  74. package/dist/migrations/1778950642-price-invoiced.sql +2 -0
  75. package/dist/migrations/1779443446-transfer-fees.sql +3 -0
  76. package/dist/migrations/1779709174-used-register-code-balance-item-id.sql +5 -0
  77. package/dist/migrations/1779968328-payments-admin-user-id.sql +5 -0
  78. package/dist/migrations/1779970611-payments-refunded-amount.sql +2 -0
  79. package/dist/migrations/1779972640-balance-items-failed-at.sql +2 -0
  80. package/dist/migrations/1780328285-document-template-locked.sql +2 -0
  81. package/dist/migrations/1780328286-document-locked.sql +2 -0
  82. package/dist/migrations/1780412083-documents-set-locked.d.ts +4 -0
  83. package/dist/migrations/1780412083-documents-set-locked.d.ts.map +1 -0
  84. package/dist/migrations/1780412083-documents-set-locked.js +14 -0
  85. package/dist/migrations/1780412083-documents-set-locked.js.map +1 -0
  86. package/dist/migrations/1780928401-v1-groups-migration-data.d.ts +4 -0
  87. package/dist/migrations/1780928401-v1-groups-migration-data.d.ts.map +1 -0
  88. package/dist/migrations/1780928401-v1-groups-migration-data.js +44 -0
  89. package/dist/migrations/1780928401-v1-groups-migration-data.js.map +1 -0
  90. package/dist/models/BalanceItem.d.ts +14 -1
  91. package/dist/models/BalanceItem.d.ts.map +1 -1
  92. package/dist/models/BalanceItem.js +91 -41
  93. package/dist/models/BalanceItem.js.map +1 -1
  94. package/dist/models/CachedBalance.d.ts +6 -1
  95. package/dist/models/CachedBalance.d.ts.map +1 -1
  96. package/dist/models/CachedBalance.js +3 -2
  97. package/dist/models/CachedBalance.js.map +1 -1
  98. package/dist/models/Document.d.ts +4 -0
  99. package/dist/models/Document.d.ts.map +1 -1
  100. package/dist/models/Document.js +26 -3
  101. package/dist/models/Document.js.map +1 -1
  102. package/dist/models/DocumentTemplate.d.ts +4 -0
  103. package/dist/models/DocumentTemplate.d.ts.map +1 -1
  104. package/dist/models/DocumentTemplate.js +37 -1
  105. package/dist/models/DocumentTemplate.js.map +1 -1
  106. package/dist/models/Email.d.ts.map +1 -1
  107. package/dist/models/Email.js +1 -1
  108. package/dist/models/Email.js.map +1 -1
  109. package/dist/models/EmailVerificationCode.d.ts.map +1 -1
  110. package/dist/models/EmailVerificationCode.js +3 -13
  111. package/dist/models/EmailVerificationCode.js.map +1 -1
  112. package/dist/models/Event.d.ts +2 -1
  113. package/dist/models/Event.d.ts.map +1 -1
  114. package/dist/models/Event.js +3 -0
  115. package/dist/models/Event.js.map +1 -1
  116. package/dist/models/EventNotification.d.ts.map +1 -1
  117. package/dist/models/EventNotification.js +5 -5
  118. package/dist/models/EventNotification.js.map +1 -1
  119. package/dist/models/Group.d.ts +4 -0
  120. package/dist/models/Group.d.ts.map +1 -1
  121. package/dist/models/Group.js +17 -0
  122. package/dist/models/Group.js.map +1 -1
  123. package/dist/models/Invoice.d.ts +1 -0
  124. package/dist/models/Invoice.d.ts.map +1 -1
  125. package/dist/models/Invoice.js +8 -8
  126. package/dist/models/Invoice.js.map +1 -1
  127. package/dist/models/MemberPlatformMembership.d.ts.map +1 -1
  128. package/dist/models/MemberPlatformMembership.js +9 -0
  129. package/dist/models/MemberPlatformMembership.js.map +1 -1
  130. package/dist/models/MollieToken.d.ts +4 -8
  131. package/dist/models/MollieToken.d.ts.map +1 -1
  132. package/dist/models/MollieToken.js +37 -90
  133. package/dist/models/MollieToken.js.map +1 -1
  134. package/dist/models/Order.d.ts.map +1 -1
  135. package/dist/models/Order.js +1 -0
  136. package/dist/models/Order.js.map +1 -1
  137. package/dist/models/Organization.d.ts +30 -23
  138. package/dist/models/Organization.d.ts.map +1 -1
  139. package/dist/models/Organization.js +113 -61
  140. package/dist/models/Organization.js.map +1 -1
  141. package/dist/models/PasswordToken.d.ts +5 -1
  142. package/dist/models/PasswordToken.d.ts.map +1 -1
  143. package/dist/models/PasswordToken.js +18 -17
  144. package/dist/models/PasswordToken.js.map +1 -1
  145. package/dist/models/Payment.d.ts +35 -3
  146. package/dist/models/Payment.d.ts.map +1 -1
  147. package/dist/models/Payment.js +66 -3
  148. package/dist/models/Payment.js.map +1 -1
  149. package/dist/models/Registration.d.ts +1 -0
  150. package/dist/models/Registration.d.ts.map +1 -1
  151. package/dist/models/Registration.js +4 -3
  152. package/dist/models/Registration.js.map +1 -1
  153. package/dist/models/RegistrationInvitation.d.ts +14 -0
  154. package/dist/models/RegistrationInvitation.d.ts.map +1 -0
  155. package/dist/models/RegistrationInvitation.js +45 -0
  156. package/dist/models/RegistrationInvitation.js.map +1 -0
  157. package/dist/models/STCredit.d.ts +4 -0
  158. package/dist/models/STCredit.d.ts.map +1 -1
  159. package/dist/models/STCredit.js +28 -0
  160. package/dist/models/STCredit.js.map +1 -1
  161. package/dist/models/STInvoice.d.ts +7 -1
  162. package/dist/models/STInvoice.d.ts.map +1 -1
  163. package/dist/models/STInvoice.js +9 -0
  164. package/dist/models/STInvoice.js.map +1 -1
  165. package/dist/models/STPackage.d.ts +4 -0
  166. package/dist/models/STPackage.d.ts.map +1 -1
  167. package/dist/models/STPackage.js +12 -1
  168. package/dist/models/STPackage.js.map +1 -1
  169. package/dist/models/UsedRegisterCode.d.ts +9 -0
  170. package/dist/models/UsedRegisterCode.d.ts.map +1 -1
  171. package/dist/models/UsedRegisterCode.js +31 -0
  172. package/dist/models/UsedRegisterCode.js.map +1 -1
  173. package/dist/models/User.d.ts +1 -1
  174. package/dist/models/User.d.ts.map +1 -1
  175. package/dist/models/User.js +1 -1
  176. package/dist/models/User.js.map +1 -1
  177. package/dist/models/_relations.js +25 -0
  178. package/dist/models/_relations.js.map +1 -1
  179. package/dist/models/addresses/City.d.ts +4 -4
  180. package/dist/models/addresses/City.d.ts.map +1 -1
  181. package/dist/models/addresses/City.js +6 -6
  182. package/dist/models/addresses/City.js.map +1 -1
  183. package/dist/models/addresses/PostalCode.d.ts +2 -2
  184. package/dist/models/addresses/PostalCode.d.ts.map +1 -1
  185. package/dist/models/addresses/PostalCode.js +4 -3
  186. package/dist/models/addresses/PostalCode.js.map +1 -1
  187. package/dist/models/addresses/Street.d.ts +3 -3
  188. package/dist/models/addresses/Street.d.ts.map +1 -1
  189. package/dist/models/addresses/Street.js +4 -4
  190. package/dist/models/addresses/Street.js.map +1 -1
  191. package/dist/models/index.d.ts +2 -0
  192. package/dist/models/index.d.ts.map +1 -1
  193. package/dist/models/index.js +2 -0
  194. package/dist/models/index.js.map +1 -1
  195. package/dist/models/v1GroupMigrationData.d.ts +22 -0
  196. package/dist/models/v1GroupMigrationData.d.ts.map +1 -0
  197. package/dist/models/v1GroupMigrationData.js +48 -0
  198. package/dist/models/v1GroupMigrationData.js.map +1 -0
  199. package/package.json +41 -13
  200. package/src/factories/GroupFactory.ts +4 -6
  201. package/src/factories/OrganizationFactory.ts +12 -4
  202. package/src/factories/RegistrationInvitationFactory.ts +24 -0
  203. package/src/factories/STPackageFactory.ts +2 -2
  204. package/src/factories/UserFactory.ts +4 -5
  205. package/src/factories/index.ts +1 -0
  206. package/src/helpers/EmailBuilder.ts +19 -28
  207. package/src/helpers/Handlebars.ts +10 -1
  208. package/src/helpers/InvoiceCounter.test.ts +220 -0
  209. package/src/helpers/InvoiceCounter.ts +162 -0
  210. package/src/index.ts +0 -1
  211. package/src/migrations/1605262045-import-postcodes.ts +62 -25
  212. package/src/migrations/1605262046-import-postcodes-nl.ts +58 -17
  213. package/src/migrations/1719567881-organization-periodId.sql +2 -0
  214. package/src/migrations/1719567882-groups-periodId.sql +2 -0
  215. package/src/migrations/1720080975-convert-charset.ts +34 -0
  216. package/src/migrations/1720080976-convert-charset-leads.ts +16 -13
  217. package/src/migrations/1721400546-users-memberId.sql +2 -0
  218. package/src/migrations/1722269236-group-waitinglist-id.sql +2 -1
  219. package/src/migrations/1722525785-balance-item-paying-organization-id.sql +2 -0
  220. package/src/migrations/1722525787-depending-balance-item.sql +2 -0
  221. package/src/migrations/1722963554-registration-group-price-and-options.sql +1 -1
  222. package/src/migrations/1723652797-payments-paying-organization-id-fk.sql +2 -0
  223. package/src/migrations/1733317908-added-missing-organization-fk-on-registrations.sql +2 -0
  224. package/src/migrations/1733317910-paying-organization-id-fk.sql +2 -0
  225. package/src/migrations/1733504881-negative-invoice-id.sql +6 -0
  226. package/src/migrations/1733994455-balance-item-status-open.ts +30 -0
  227. package/src/migrations/1763216320-bigint-balance-item-payments.sql +2 -0
  228. package/src/migrations/1763216320-bigint-balance-items.sql +5 -0
  229. package/src/migrations/1763216320-bigint-orders.sql +2 -0
  230. package/src/migrations/1763216320-bigint-payments.sql +2 -0
  231. package/src/migrations/1763216332-bigint-balance-item-price-total.sql +2 -0
  232. package/src/migrations/1769087808-corrected-invoice-user-agent.sql +2 -0
  233. package/src/migrations/1769087809-payments-invoice-id.sql +2 -0
  234. package/src/migrations/1772033555-balance-item-package-id.sql +2 -0
  235. package/src/migrations/1776873089-create-registration-invitations-table.sql +13 -0
  236. package/src/migrations/1778657958-payments-create-mandate.sql +2 -0
  237. package/src/migrations/1778657959-payments-mandate-id.sql +2 -0
  238. package/src/migrations/1778796615-payments-reversing-payment-id.sql +5 -0
  239. package/src/migrations/1778950642-price-invoiced.sql +2 -0
  240. package/src/migrations/1779443446-transfer-fees.sql +3 -0
  241. package/src/migrations/1779709174-used-register-code-balance-item-id.sql +5 -0
  242. package/src/migrations/1779968328-payments-admin-user-id.sql +5 -0
  243. package/src/migrations/1779970611-payments-refunded-amount.sql +2 -0
  244. package/src/migrations/1779972640-balance-items-failed-at.sql +2 -0
  245. package/src/migrations/1780328285-document-template-locked.sql +2 -0
  246. package/src/migrations/1780328286-document-locked.sql +2 -0
  247. package/src/migrations/1780412083-documents-set-locked.ts +18 -0
  248. package/src/migrations/1780928401-v1-groups-migration-data.ts +50 -0
  249. package/src/models/BalanceItem.ts +98 -43
  250. package/src/models/CachedBalance.test.ts +46 -46
  251. package/src/models/CachedBalance.ts +7 -7
  252. package/src/models/Document.ts +34 -13
  253. package/src/models/DocumentTemplate.ts +56 -17
  254. package/src/models/Email.test.ts +3 -3
  255. package/src/models/Email.ts +28 -49
  256. package/src/models/EmailVerificationCode.ts +8 -22
  257. package/src/models/Event.ts +6 -4
  258. package/src/models/EventNotification.ts +6 -6
  259. package/src/models/Group.ts +24 -3
  260. package/src/models/Invoice.ts +10 -9
  261. package/src/models/MemberPlatformMembership.test.ts +70 -0
  262. package/src/models/MemberPlatformMembership.ts +16 -12
  263. package/src/models/MollieToken.ts +42 -102
  264. package/src/models/Order.ts +14 -26
  265. package/src/models/Organization.ts +143 -86
  266. package/src/models/PasswordToken.ts +21 -21
  267. package/src/models/Payment.ts +61 -4
  268. package/src/models/Registration.ts +6 -5
  269. package/src/models/RegistrationInvitation.ts +40 -0
  270. package/src/models/STCredit.ts +32 -0
  271. package/src/models/STInvoice.ts +11 -5
  272. package/src/models/STPackage.ts +19 -14
  273. package/src/models/UsedRegisterCode.ts +34 -0
  274. package/src/models/User.ts +6 -7
  275. package/src/models/_relations.ts +29 -0
  276. package/src/models/addresses/City.ts +8 -6
  277. package/src/models/addresses/PostalCode.test.ts +1 -0
  278. package/src/models/addresses/PostalCode.ts +5 -3
  279. package/src/models/addresses/Street.ts +6 -4
  280. package/src/models/index.ts +3 -0
  281. package/src/models/v1GroupMigrationData.ts +43 -0
  282. package/dist/helpers/MemberMerger.d.ts +0 -14
  283. package/dist/helpers/MemberMerger.d.ts.map +0 -1
  284. package/dist/helpers/MemberMerger.js +0 -364
  285. package/dist/helpers/MemberMerger.js.map +0 -1
  286. package/dist/migrations/1720080975-convert-charset.sql +0 -85
  287. package/dist/migrations/1723202126-member-number-index.sql +0 -2
  288. package/dist/models/OneTimeToken.d.ts +0 -38
  289. package/dist/models/OneTimeToken.d.ts.map +0 -1
  290. package/dist/models/OneTimeToken.js +0 -125
  291. package/dist/models/OneTimeToken.js.map +0 -1
  292. package/src/helpers/MemberMerger.test.ts +0 -782
  293. package/src/helpers/MemberMerger.ts +0 -577
  294. package/src/migrations/1720080975-convert-charset.sql +0 -85
  295. package/src/migrations/1723202126-member-number-index.sql +0 -2
  296. package/src/models/OneTimeToken.ts +0 -133
@@ -1,5 +1,5 @@
1
- import { BalanceItemStatus } from '../../../../../shared/structures/dist/BalanceItem.js';
2
- import { ReceivableBalanceType } from '../../../../../shared/structures/dist/ReceivableBalance.js';
1
+ import { BalanceItemStatus } from '@stamhoofd/structures/BalanceItem.js';
2
+ import { ReceivableBalanceType } from '@stamhoofd/structures/ReceivableBalance.js';
3
3
  import { MemberFactory } from '../factories/MemberFactory.js';
4
4
  import { OrganizationFactory } from '../factories/OrganizationFactory.js';
5
5
  import { UserFactory } from '../factories/UserFactory.js';
@@ -21,19 +21,19 @@ describe('CachedBalance', () => {
21
21
 
22
22
  test('Balances for members are summed', async () => {
23
23
  const organization = await new OrganizationFactory({}).create();
24
- const member = await new MemberFactory({organization}).create();
24
+ const member = await new MemberFactory({ organization }).create();
25
25
 
26
26
  const balanceA = new BalanceItem();
27
- balanceA.dueAt = null
27
+ balanceA.dueAt = null;
28
28
  balanceA.quantity = 2;
29
29
  balanceA.unitPrice = 1_00;
30
30
  balanceA.memberId = member.id;
31
31
  balanceA.organizationId = organization.id;
32
- balanceA.status = BalanceItemStatus.Due
32
+ balanceA.status = BalanceItemStatus.Due;
33
33
  await balanceA.save();
34
34
 
35
35
  // Update cached balance for user.
36
- await CachedBalance.updateForMembers(organization.id, [member.id])
36
+ await CachedBalance.updateForMembers(organization.id, [member.id]);
37
37
  const cached = await CachedBalance.getForObjects([member.id], organization.id, ReceivableBalanceType.member);
38
38
  expect(cached).toHaveLength(1);
39
39
  expect(cached[0].amountOpen).toBe(2_00);
@@ -44,7 +44,7 @@ describe('CachedBalance', () => {
44
44
 
45
45
  test('Balances less than 7 days in the future are summed', async () => {
46
46
  const organization = await new OrganizationFactory({}).create();
47
- const member = await new MemberFactory({organization}).create();
47
+ const member = await new MemberFactory({ organization }).create();
48
48
 
49
49
  const balanceA = new BalanceItem();
50
50
  balanceA.dueAt = new Date(now.getTime() + 1000 * 60 * 60 * 24 * 6); // 6 days later
@@ -52,11 +52,11 @@ describe('CachedBalance', () => {
52
52
  balanceA.unitPrice = 1_00;
53
53
  balanceA.memberId = member.id;
54
54
  balanceA.organizationId = organization.id;
55
- balanceA.status = BalanceItemStatus.Due
55
+ balanceA.status = BalanceItemStatus.Due;
56
56
  await balanceA.save();
57
57
 
58
58
  // Update cached balance for user.
59
- await CachedBalance.updateForMembers(organization.id, [member.id])
59
+ await CachedBalance.updateForMembers(organization.id, [member.id]);
60
60
  const cached = await CachedBalance.getForObjects([member.id], organization.id, ReceivableBalanceType.member);
61
61
  expect(cached).toHaveLength(1);
62
62
  expect(cached[0].amountOpen).toBe(1_00);
@@ -67,7 +67,7 @@ describe('CachedBalance', () => {
67
67
 
68
68
  test('Balances more than 7 days in the future are not summed', async () => {
69
69
  const organization = await new OrganizationFactory({}).create();
70
- const member = await new MemberFactory({organization}).create();
70
+ const member = await new MemberFactory({ organization }).create();
71
71
 
72
72
  const balanceA = new BalanceItem();
73
73
  balanceA.dueAt = new Date(now.getTime() + 1000 * 60 * 60 * 24 * 8); // 8 days later
@@ -75,11 +75,11 @@ describe('CachedBalance', () => {
75
75
  balanceA.unitPrice = 1_00;
76
76
  balanceA.memberId = member.id;
77
77
  balanceA.organizationId = organization.id;
78
- balanceA.status = BalanceItemStatus.Due
78
+ balanceA.status = BalanceItemStatus.Due;
79
79
  await balanceA.save();
80
80
 
81
81
  // Update cached balance for user.
82
- await CachedBalance.updateForMembers(organization.id, [member.id])
82
+ await CachedBalance.updateForMembers(organization.id, [member.id]);
83
83
  const cached = await CachedBalance.getForObjects([member.id], organization.id, ReceivableBalanceType.member);
84
84
  expect(cached).toHaveLength(1);
85
85
  expect(cached[0].amountOpen).toBe(0);
@@ -90,7 +90,7 @@ describe('CachedBalance', () => {
90
90
 
91
91
  test('Paid balances more than 7 days in the future are summed', async () => {
92
92
  const organization = await new OrganizationFactory({}).create();
93
- const member = await new MemberFactory({organization}).create();
93
+ const member = await new MemberFactory({ organization }).create();
94
94
 
95
95
  const balanceA = new BalanceItem();
96
96
  balanceA.dueAt = new Date(now.getTime() + 1000 * 60 * 60 * 24 * 8); // 8 days later
@@ -98,12 +98,12 @@ describe('CachedBalance', () => {
98
98
  balanceA.unitPrice = 1_00;
99
99
  balanceA.memberId = member.id;
100
100
  balanceA.organizationId = organization.id;
101
- balanceA.status = BalanceItemStatus.Due
101
+ balanceA.status = BalanceItemStatus.Due;
102
102
  balanceA.pricePaid = 2_00;
103
103
  await balanceA.save();
104
104
 
105
105
  // Update cached balance for user.
106
- await CachedBalance.updateForMembers(organization.id, [member.id])
106
+ await CachedBalance.updateForMembers(organization.id, [member.id]);
107
107
  const cached = await CachedBalance.getForObjects([member.id], organization.id, ReceivableBalanceType.member);
108
108
  expect(cached).toHaveLength(1);
109
109
  expect(cached[0].amountOpen).toBe(0);
@@ -112,9 +112,9 @@ describe('CachedBalance', () => {
112
112
  expect(cached[0].nextDueAt).toEqual(null);
113
113
  });
114
114
 
115
- test('Paid balances more than 7 days in the future are summed and due at is still set if only partially paid', async () => {
115
+ test('Paid balances more than 7 days in the future are summed and due at is still set if only partially paid', async () => {
116
116
  const organization = await new OrganizationFactory({}).create();
117
- const member = await new MemberFactory({organization}).create();
117
+ const member = await new MemberFactory({ organization }).create();
118
118
 
119
119
  const balanceA = new BalanceItem();
120
120
  balanceA.dueAt = new Date(now.getTime() + 1000 * 60 * 60 * 24 * 8); // 8 days later
@@ -122,12 +122,12 @@ describe('CachedBalance', () => {
122
122
  balanceA.unitPrice = 1_00;
123
123
  balanceA.memberId = member.id;
124
124
  balanceA.organizationId = organization.id;
125
- balanceA.status = BalanceItemStatus.Due
125
+ balanceA.status = BalanceItemStatus.Due;
126
126
  balanceA.pricePaid = 1_00;
127
127
  await balanceA.save();
128
128
 
129
129
  // Update cached balance for user.
130
- await CachedBalance.updateForMembers(organization.id, [member.id])
130
+ await CachedBalance.updateForMembers(organization.id, [member.id]);
131
131
  const cached = await CachedBalance.getForObjects([member.id], organization.id, ReceivableBalanceType.member);
132
132
  expect(cached).toHaveLength(1);
133
133
  expect(cached[0].amountOpen).toBe(0);
@@ -138,7 +138,7 @@ describe('CachedBalance', () => {
138
138
 
139
139
  test('Canceled items are not summed', async () => {
140
140
  const organization = await new OrganizationFactory({}).create();
141
- const member = await new MemberFactory({organization}).create();
141
+ const member = await new MemberFactory({ organization }).create();
142
142
 
143
143
  const balanceA = new BalanceItem();
144
144
  balanceA.dueAt = null;
@@ -146,11 +146,11 @@ describe('CachedBalance', () => {
146
146
  balanceA.unitPrice = 1_00;
147
147
  balanceA.memberId = member.id;
148
148
  balanceA.organizationId = organization.id;
149
- balanceA.status = BalanceItemStatus.Canceled
149
+ balanceA.status = BalanceItemStatus.Canceled;
150
150
  await balanceA.save();
151
151
 
152
152
  // Update cached balance for user.
153
- await CachedBalance.updateForMembers(organization.id, [member.id])
153
+ await CachedBalance.updateForMembers(organization.id, [member.id]);
154
154
  const cached = await CachedBalance.getForObjects([member.id], organization.id, ReceivableBalanceType.member);
155
155
  expect(cached).toHaveLength(1);
156
156
  expect(cached[0].amountOpen).toBe(0);
@@ -160,7 +160,7 @@ describe('CachedBalance', () => {
160
160
 
161
161
  test('Hidden items are not summed', async () => {
162
162
  const organization = await new OrganizationFactory({}).create();
163
- const member = await new MemberFactory({organization}).create();
163
+ const member = await new MemberFactory({ organization }).create();
164
164
 
165
165
  const balanceA = new BalanceItem();
166
166
  balanceA.dueAt = null;
@@ -168,11 +168,11 @@ describe('CachedBalance', () => {
168
168
  balanceA.unitPrice = 1_00;
169
169
  balanceA.memberId = member.id;
170
170
  balanceA.organizationId = organization.id;
171
- balanceA.status = BalanceItemStatus.Hidden
171
+ balanceA.status = BalanceItemStatus.Hidden;
172
172
  await balanceA.save();
173
173
 
174
174
  // Update cached balance for user.
175
- await CachedBalance.updateForMembers(organization.id, [member.id])
175
+ await CachedBalance.updateForMembers(organization.id, [member.id]);
176
176
  const cached = await CachedBalance.getForObjects([member.id], organization.id, ReceivableBalanceType.member);
177
177
  expect(cached).toHaveLength(1);
178
178
  expect(cached[0].amountOpen).toBe(0);
@@ -183,8 +183,8 @@ describe('CachedBalance', () => {
183
183
  describe('nextDueAt for users with members', () => {
184
184
  test('Two balance items in the future are merged if less than 7 days in the future', async () => {
185
185
  const organization = await new OrganizationFactory({}).create();
186
- const member = await new MemberFactory({organization}).create();
187
- const user = await new UserFactory({organization}).create();
186
+ const member = await new MemberFactory({ organization }).create();
187
+ const user = await new UserFactory({ organization }).create();
188
188
 
189
189
  // Link member with user
190
190
  await Member.users.reverse('members').link(user, [member]);
@@ -195,7 +195,7 @@ describe('CachedBalance', () => {
195
195
  balanceA.unitPrice = 1_00;
196
196
  balanceA.memberId = member.id;
197
197
  balanceA.organizationId = organization.id;
198
- balanceA.status = BalanceItemStatus.Due
198
+ balanceA.status = BalanceItemStatus.Due;
199
199
  await balanceA.save();
200
200
 
201
201
  const balanceB = new BalanceItem();
@@ -204,12 +204,12 @@ describe('CachedBalance', () => {
204
204
  balanceB.unitPrice = 1_00;
205
205
  balanceB.userId = user.id;
206
206
  balanceB.organizationId = organization.id;
207
- balanceB.status = BalanceItemStatus.Due
207
+ balanceB.status = BalanceItemStatus.Due;
208
208
  await balanceB.save();
209
209
 
210
210
  // Update cached balance for user.
211
- await CachedBalance.updateForMembers(organization.id, [member.id])
212
- await CachedBalance.updateForUsers(organization.id, [user.id])
211
+ await CachedBalance.updateForMembers(organization.id, [member.id]);
212
+ await CachedBalance.updateForUsers(organization.id, [user.id]);
213
213
  {
214
214
  const cached = await CachedBalance.getForObjects([user.id], organization.id, ReceivableBalanceType.user);
215
215
  expect(cached).toHaveLength(1);
@@ -231,8 +231,8 @@ describe('CachedBalance', () => {
231
231
 
232
232
  test('[Regression] Two balance items more than 7 days in the future set correct nextDueAt', async () => {
233
233
  const organization = await new OrganizationFactory({}).create();
234
- const member = await new MemberFactory({organization}).create();
235
- const user = await new UserFactory({organization}).create();
234
+ const member = await new MemberFactory({ organization }).create();
235
+ const user = await new UserFactory({ organization }).create();
236
236
 
237
237
  // Link member with user
238
238
  await Member.users.reverse('members').link(user, [member]);
@@ -243,7 +243,7 @@ describe('CachedBalance', () => {
243
243
  balanceA.unitPrice = 1_00;
244
244
  balanceA.memberId = member.id;
245
245
  balanceA.organizationId = organization.id;
246
- balanceA.status = BalanceItemStatus.Due
246
+ balanceA.status = BalanceItemStatus.Due;
247
247
  await balanceA.save();
248
248
 
249
249
  const balanceB = new BalanceItem();
@@ -252,12 +252,12 @@ describe('CachedBalance', () => {
252
252
  balanceB.unitPrice = 1_00;
253
253
  balanceB.userId = user.id;
254
254
  balanceB.organizationId = organization.id;
255
- balanceB.status = BalanceItemStatus.Due
255
+ balanceB.status = BalanceItemStatus.Due;
256
256
  await balanceB.save();
257
257
 
258
258
  // Update cached balance for user.
259
- await CachedBalance.updateForMembers(organization.id, [member.id])
260
- await CachedBalance.updateForUsers(organization.id, [user.id])
259
+ await CachedBalance.updateForMembers(organization.id, [member.id]);
260
+ await CachedBalance.updateForUsers(organization.id, [user.id]);
261
261
  {
262
262
  const cached = await CachedBalance.getForObjects([user.id], organization.id, ReceivableBalanceType.user);
263
263
  expect(cached).toHaveLength(1);
@@ -278,9 +278,9 @@ describe('CachedBalance', () => {
278
278
 
279
279
  // Advance time with one day, balanceA is now less than 7 days in the future and should be included in the cached balance.
280
280
  // nextDueAt should be different and set to balanceB.dueAt
281
- vitest.setSystemTime(new Date(now.getTime() + 1000 * 60 * 60 * 24 * 1))
282
- await CachedBalance.updateForMembers(organization.id, [member.id])
283
- await CachedBalance.updateForUsers(organization.id, [user.id])
281
+ vitest.setSystemTime(new Date(now.getTime() + 1000 * 60 * 60 * 24 * 1));
282
+ await CachedBalance.updateForMembers(organization.id, [member.id]);
283
+ await CachedBalance.updateForUsers(organization.id, [user.id]);
284
284
  const cachedAfter = await CachedBalance.getForObjects([user.id], organization.id, ReceivableBalanceType.user);
285
285
  expect(cachedAfter).toHaveLength(1);
286
286
  expect(cachedAfter[0].amountOpen).toBe(1_00);
@@ -291,8 +291,8 @@ describe('CachedBalance', () => {
291
291
 
292
292
  test('Two balance items more than 7 days in the future that are partially paid are summed correctly', async () => {
293
293
  const organization = await new OrganizationFactory({}).create();
294
- const member = await new MemberFactory({organization}).create();
295
- const user = await new UserFactory({organization}).create();
294
+ const member = await new MemberFactory({ organization }).create();
295
+ const user = await new UserFactory({ organization }).create();
296
296
 
297
297
  // Link member with user
298
298
  await Member.users.reverse('members').link(user, [member]);
@@ -304,7 +304,7 @@ describe('CachedBalance', () => {
304
304
  balanceA.memberId = member.id;
305
305
  balanceA.organizationId = organization.id;
306
306
  balanceA.pricePaid = 50;
307
- balanceA.status = BalanceItemStatus.Due
307
+ balanceA.status = BalanceItemStatus.Due;
308
308
  await balanceA.save();
309
309
 
310
310
  const balanceB = new BalanceItem();
@@ -314,12 +314,12 @@ describe('CachedBalance', () => {
314
314
  balanceB.userId = user.id;
315
315
  balanceB.organizationId = organization.id;
316
316
  balanceB.pricePaid = 50;
317
- balanceB.status = BalanceItemStatus.Due
317
+ balanceB.status = BalanceItemStatus.Due;
318
318
  await balanceB.save();
319
319
 
320
320
  // Update cached balance for user.
321
- await CachedBalance.updateForMembers(organization.id, [member.id])
322
- await CachedBalance.updateForUsers(organization.id, [user.id])
321
+ await CachedBalance.updateForMembers(organization.id, [member.id]);
322
+ await CachedBalance.updateForUsers(organization.id, [user.id]);
323
323
  const cached = await CachedBalance.getForObjects([user.id], organization.id, ReceivableBalanceType.user);
324
324
  expect(cached).toHaveLength(1);
325
325
  expect(cached[0].amountOpen).toBe(0);
@@ -1,11 +1,11 @@
1
1
  import { column } from '@simonbackx/simple-database';
2
- import type { SQLWhere} from '@stamhoofd/sql';
2
+ import type { SQLWhere } from '@stamhoofd/sql';
3
3
  import { QueryableModel, SQL, SQLAlias, SQLMin, SQLSelectAs, SQLSum, SQLWhereSign } from '@stamhoofd/sql';
4
4
  import { BalanceItemStatus, BalanceItem as BalanceItemStruct, ReceivableBalanceType } from '@stamhoofd/structures';
5
+ import { Formatter } from '@stamhoofd/utility';
5
6
  import { v4 as uuidv4 } from 'uuid';
6
7
  import { BalanceItem } from './BalanceItem.js';
7
8
  import { MemberUser } from './MemberUser.js';
8
- import { Formatter } from '@stamhoofd/utility';
9
9
 
10
10
  /**
11
11
  * Keeps track of how much a member/user owes or needs to be reimbursed.
@@ -328,8 +328,7 @@ export class CachedBalance extends QueryableModel {
328
328
 
329
329
  result[1].amountPending += amountPending;
330
330
  result[1].amountPaid += amountPaid;
331
- }
332
- else {
331
+ } else {
333
332
  results.push([objectId, { amountPaid, amountOpen: 0, amountPending, nextDueAt: amountOpen !== 0 ? dueAt : null }]);
334
333
  }
335
334
  }
@@ -407,10 +406,12 @@ export class CachedBalance extends QueryableModel {
407
406
 
408
407
  static async updateForOrganizations(organizationId: string, organizationIds: string[]) {
409
408
  if (organizationIds.length === 0) {
410
- return;
409
+ return [];
411
410
  }
412
411
  const results = await this.fetchForObjects(organizationId, organizationIds, 'payingOrganizationId');
413
412
  await this.setForResults(organizationId, results, ReceivableBalanceType.organization);
413
+
414
+ return results;
414
415
  }
415
416
 
416
417
  static async updateForMembers(organizationId: string, memberIds: string[]) {
@@ -462,8 +463,7 @@ export class CachedBalance extends QueryableModel {
462
463
  if (memberCachedBalance.nextDueAt && (!result[1].nextDueAt || memberCachedBalance.nextDueAt < result[1].nextDueAt)) {
463
464
  result[1].nextDueAt = memberCachedBalance.nextDueAt;
464
465
  }
465
- }
466
- else {
466
+ } else {
467
467
  // Not possible
468
468
  throw new Error('User not found in results');
469
469
  }
@@ -3,6 +3,7 @@ import { DocumentData, DocumentStatus, Document as DocumentStruct, Platform, Ver
3
3
  import { Formatter } from '@stamhoofd/utility';
4
4
  import { v4 as uuidv4 } from 'uuid';
5
5
 
6
+ import { SimpleError } from '@simonbackx/simple-errors';
6
7
  import { QueryableModel } from '@stamhoofd/sql';
7
8
  import { render } from '../helpers/Handlebars.js';
8
9
  import type { Member, MemberWithRegistrations, RegistrationWithMember } from './Member.js';
@@ -38,6 +39,9 @@ export class Document extends QueryableModel {
38
39
  @column({ type: 'string' })
39
40
  status = DocumentStatus.Draft;
40
41
 
42
+ @column({ type: 'boolean' })
43
+ isLocked = false;
44
+
41
45
  /**
42
46
  * Assigned when exporting the document
43
47
  */
@@ -63,6 +67,18 @@ export class Document extends QueryableModel {
63
67
  })
64
68
  updatedAt: Date;
65
69
 
70
+ override save(options?: Parameters<QueryableModel['save']>[0] & { forceSave?: boolean }): Promise<boolean> {
71
+ if (!options?.forceSave && this.isLocked) {
72
+ throw new SimpleError({
73
+ code: 'locked',
74
+ message: 'Document is locked',
75
+ human: $t(`%1Uc`),
76
+ });
77
+ }
78
+
79
+ return super.save(options);
80
+ }
81
+
66
82
  getStructure() {
67
83
  return DocumentStruct.create(this);
68
84
  }
@@ -84,6 +100,7 @@ export class Document extends QueryableModel {
84
100
  };
85
101
  const platformLogo = Platform.shared.config.logoDocuments ?? Platform.shared.config.horizontalLogo ?? Platform.shared.config.squareLogo;
86
102
  const organizationLogo = organization.meta.horizontalLogo ?? organization.meta.squareLogo;
103
+ const logo = organizationLogo || platformLogo;
87
104
 
88
105
  if (organizationLogo) {
89
106
  data['organization'] = {
@@ -98,6 +115,10 @@ export class Document extends QueryableModel {
98
115
  };
99
116
  }
100
117
 
118
+ if (logo) {
119
+ data['logo'] = logo.encode({ version: Version }) ?? null;
120
+ }
121
+
101
122
  for (const field of this.data.fieldAnswers.values()) {
102
123
  const keys = field.settings.id.split('.');
103
124
  let current = data;
@@ -121,6 +142,11 @@ export class Document extends QueryableModel {
121
142
  }
122
143
 
123
144
  async updateData(): Promise<void> {
145
+ if (this.isLocked) {
146
+ console.log('Document is locked, skipping update');
147
+ return;
148
+ }
149
+
124
150
  const DocumentTemplate = (await import('./DocumentTemplate.js')).DocumentTemplate;
125
151
  const template = await DocumentTemplate.getByID(this.templateId);
126
152
  if (!template) {
@@ -165,8 +191,7 @@ export class Document extends QueryableModel {
165
191
  await this.updateForRegistrations(loadedMember.registrations.filter(r => r.registeredAt && r.deactivatedAt === null && r.organizationId === organizationId).map(r => r.id), organizationId);
166
192
  }
167
193
  }
168
- }
169
- catch (e) {
194
+ } catch (e) {
170
195
  console.error(e);
171
196
  }
172
197
  }
@@ -176,13 +201,12 @@ export class Document extends QueryableModel {
176
201
  console.log('Updating documents for registration', registration.id);
177
202
 
178
203
  const DocumentTemplate = (await import('./DocumentTemplate.js')).DocumentTemplate;
179
- const templates = await DocumentTemplate.where({ updatesEnabled: 1, organizationId: registration.organizationId });
204
+ const templates = await DocumentTemplate.where({ updatesEnabled: 1, isLocked: 0, organizationId: registration.organizationId });
180
205
 
181
206
  for (const template of templates) {
182
207
  await template.updateForRegistration(registration);
183
208
  }
184
- }
185
- catch (e) {
209
+ } catch (e) {
186
210
  console.error(e);
187
211
  }
188
212
  }
@@ -208,7 +232,7 @@ export class Document extends QueryableModel {
208
232
  console.log('Updating documents for updateForRegistrations', registrationIds, organizationId);
209
233
 
210
234
  const DocumentTemplate = (await import('./DocumentTemplate.js')).DocumentTemplate;
211
- const templates = await DocumentTemplate.where({ updatesEnabled: 1, organizationId });
235
+ const templates = await DocumentTemplate.where({ updatesEnabled: 1, isLocked: 0, organizationId });
212
236
 
213
237
  if (templates.length) {
214
238
  const Member = (await import('./Member.js')).Member;
@@ -219,8 +243,7 @@ export class Document extends QueryableModel {
219
243
  await template.updateForRegistrations(loadedRegistrations);
220
244
  }
221
245
  }
222
- }
223
- catch (e) {
246
+ } catch (e) {
224
247
  console.error(e);
225
248
  }
226
249
  }
@@ -230,7 +253,7 @@ export class Document extends QueryableModel {
230
253
  console.log('Updating documents for group', groupId);
231
254
 
232
255
  const DocumentTemplate = (await import('./DocumentTemplate.js')).DocumentTemplate;
233
- const templates = await DocumentTemplate.where({ updatesEnabled: 1, organizationId });
256
+ const templates = await DocumentTemplate.where({ updatesEnabled: 1, isLocked: 0, organizationId });
234
257
 
235
258
  if (templates.length) {
236
259
  const Member = (await import('./Member.js')).Member;
@@ -240,8 +263,7 @@ export class Document extends QueryableModel {
240
263
  await template.updateForRegistrations(registrations);
241
264
  }
242
265
  }
243
- }
244
- catch (e) {
266
+ } catch (e) {
245
267
  console.error(e);
246
268
  }
247
269
  }
@@ -263,8 +285,7 @@ export class Document extends QueryableModel {
263
285
  const context = this.buildContext(organization);
264
286
  const renderedHtml = await render(htmlTemplate, context);
265
287
  return renderedHtml;
266
- }
267
- catch (e) {
288
+ } catch (e) {
268
289
  console.error('Failed to render document html', e);
269
290
  return null;
270
291
  }
@@ -1,7 +1,7 @@
1
1
  import { column } from '@simonbackx/simple-database';
2
2
  import { isSimpleError, isSimpleErrors, SimpleError } from '@simonbackx/simple-errors';
3
3
  import { QueueHandler } from '@stamhoofd/queues';
4
- import type { Parent, RecordAnswer} from '@stamhoofd/structures';
4
+ import type { Parent, RecordAnswer } from '@stamhoofd/structures';
5
5
  import { BalanceItemStatus, DocumentData, DocumentPrivateSettings, DocumentSettings, DocumentStatus, DocumentTemplatePrivate, GroupType, NationalRegisterNumberOptOut, RecordAddressAnswer, RecordAnswerDecoder, RecordDateAnswer, RecordPriceAnswer, RecordSettings, RecordTextAnswer, RecordType } from '@stamhoofd/structures';
6
6
  import { Formatter, Sorter } from '@stamhoofd/utility';
7
7
  import { v4 as uuidv4 } from 'uuid';
@@ -37,6 +37,9 @@ export class DocumentTemplate extends QueryableModel {
37
37
  @column({ type: 'string' })
38
38
  status = DocumentStatus.Draft;
39
39
 
40
+ @column({ type: 'boolean' })
41
+ isLocked = false;
42
+
40
43
  @column({ type: 'boolean' })
41
44
  updatesEnabled = true;
42
45
 
@@ -87,6 +90,18 @@ export class DocumentTemplate extends QueryableModel {
87
90
  })
88
91
  updatedAt: Date;
89
92
 
93
+ override save(options?: Parameters<QueryableModel['save']>[0] & { forceSave?: boolean }): Promise<boolean> {
94
+ if (!options?.forceSave && this.isLocked) {
95
+ throw new SimpleError({
96
+ code: 'locked',
97
+ message: 'Document template is locked',
98
+ human: $t(`%1Uc`),
99
+ });
100
+ }
101
+
102
+ return super.save(options);
103
+ }
104
+
90
105
  getPrivateStructure() {
91
106
  return DocumentTemplatePrivate.create(this);
92
107
  }
@@ -363,8 +378,7 @@ export class DocumentTemplate extends QueryableModel {
363
378
  found = true;
364
379
  fieldAnswers.set(field.id, clone);
365
380
  break;
366
- }
367
- else {
381
+ } else {
368
382
  console.warn('Found type mismatch for default data: ' + linkedToMemberAnswerSettingsId + ' - ' + field.id);
369
383
  }
370
384
  }
@@ -412,8 +426,7 @@ export class DocumentTemplate extends QueryableModel {
412
426
  for (const answer of fieldAnswers.values()) {
413
427
  try {
414
428
  answer.validate();
415
- }
416
- catch (e) {
429
+ } catch (e) {
417
430
  missingData = true;
418
431
 
419
432
  console.log('Missing data because of validation error', e, answer, answer.settings);
@@ -453,6 +466,14 @@ export class DocumentTemplate extends QueryableModel {
453
466
  }
454
467
 
455
468
  async updateForRegistration(registration: RegistrationWithMember, existingDocuments?: Document[]): Promise<Document[]> {
469
+ if (this.isLocked) {
470
+ throw new SimpleError({
471
+ code: 'locked',
472
+ message: 'Document template is locked',
473
+ human: $t(`%1Uc`),
474
+ });
475
+ }
476
+
456
477
  existingDocuments = existingDocuments !== undefined ? existingDocuments : await Document.where({ templateId: this.id, registrationId: registration.id }, { limit: 5 });
457
478
 
458
479
  if (!this.checkRegistrationIncluded(registration)) {
@@ -549,8 +570,7 @@ export class DocumentTemplate extends QueryableModel {
549
570
  if (age > this.settings.maxAge) {
550
571
  return false;
551
572
  }
552
- }
553
- else {
573
+ } else {
554
574
  console.warn('Missing registration.startDate in fieldAnswers when checking maxAge');
555
575
  }
556
576
  }
@@ -581,11 +601,20 @@ export class DocumentTemplate extends QueryableModel {
581
601
  async buildAll({ generateNumbers = false } = {}) {
582
602
  QueueHandler.abort('documents-build-all/' + this.id);
583
603
  return await QueueHandler.schedule('documents-build-all/' + this.id, async ({ abort }) => {
604
+ if (this.isLocked) {
605
+ return await Document.where({ templateId: this.id });
606
+ }
607
+
584
608
  if (!this.updatesEnabled) {
585
609
  // Check status
586
610
  const documents = await Document.where({ templateId: this.id });
587
611
  for (const document of documents) {
588
612
  abort.throwIfAborted();
613
+
614
+ if (document.isLocked) {
615
+ continue;
616
+ }
617
+
589
618
  await this.updateAnswers(document); // Only update global data
590
619
  if (document.status === DocumentStatus.Draft || document.status === DocumentStatus.Published) {
591
620
  document.status = this.status;
@@ -597,6 +626,11 @@ export class DocumentTemplate extends QueryableModel {
597
626
  if (generateNumbers) {
598
627
  for (const document of documents) {
599
628
  abort.throwIfAborted();
629
+
630
+ if (document.isLocked) {
631
+ continue;
632
+ }
633
+
600
634
  if (document.number === null && document.status === DocumentStatus.Published) {
601
635
  document.number = this.nextNumberForDocuments(documents);
602
636
  await document.save();
@@ -627,11 +661,15 @@ export class DocumentTemplate extends QueryableModel {
627
661
  const documents = await Document.where({ templateId: this.id });
628
662
  for (const document of documents) {
629
663
  abort.throwIfAborted();
664
+
665
+ if (document.isLocked) {
666
+ continue;
667
+ }
668
+
630
669
  if (!documentSet.has(document.id)) {
631
670
  if (document.number === null) {
632
671
  await document.delete();
633
- }
634
- else {
672
+ } else {
635
673
  document.status = DocumentStatus.Deleted;
636
674
  await document.save();
637
675
  }
@@ -644,6 +682,11 @@ export class DocumentTemplate extends QueryableModel {
644
682
  if (generateNumbers) {
645
683
  for (const document of allDocuments) {
646
684
  abort.throwIfAborted();
685
+
686
+ if (document.isLocked) {
687
+ continue;
688
+ }
689
+
647
690
  if (document.number === null && document.status === DocumentStatus.Published) {
648
691
  document.number = this.nextNumberForDocuments(allDocuments);
649
692
  await document.save();
@@ -733,8 +776,7 @@ export class DocumentTemplate extends QueryableModel {
733
776
  const context = await this.buildContext(organization);
734
777
  const renderedHtml = await render(this.privateSettings.templateDefinition.xmlExport, context);
735
778
  return renderedHtml;
736
- }
737
- catch (e) {
779
+ } catch (e) {
738
780
  if (isSimpleError(e) || isSimpleErrors(e)) {
739
781
  throw e;
740
782
  }
@@ -753,8 +795,7 @@ export class DocumentTemplate extends QueryableModel {
753
795
  answer.settings = field;
754
796
  try {
755
797
  answer.validate();
756
- }
757
- catch (e) {
798
+ } catch (e) {
758
799
  // Invalid
759
800
  return false;
760
801
  }
@@ -774,8 +815,7 @@ export class DocumentTemplate extends QueryableModel {
774
815
  if (!existing.isReviewedAfter(addAnswer)) {
775
816
  newAnswers.set(addAnswer.settings.id, addAnswer);
776
817
  }
777
- }
778
- else {
818
+ } else {
779
819
  newAnswers.set(addAnswer.settings.id, addAnswer);
780
820
  }
781
821
  }
@@ -786,8 +826,7 @@ export class DocumentTemplate extends QueryableModel {
786
826
  if (document.status !== DocumentStatus.Deleted) {
787
827
  if (!complete) {
788
828
  document.status = DocumentStatus.MissingData;
789
- }
790
- else {
829
+ } else {
791
830
  if (document.status === DocumentStatus.MissingData) {
792
831
  document.status = this.status;
793
832
  }