@mj-biz-apps/orders-core-entities-server 5.35.0 → 5.36.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 (76) hide show
  1. package/dist/AccountingBridge.d.ts +6 -7
  2. package/dist/AccountingBridge.d.ts.map +1 -1
  3. package/dist/AccountingBridge.js +6 -7
  4. package/dist/AccountingBridge.js.map +1 -1
  5. package/dist/AdvanceOrderStateOperation.d.ts +5 -5
  6. package/dist/AdvanceOrderStateOperation.js +5 -5
  7. package/dist/BaseInvoiceRail.d.ts +9 -0
  8. package/dist/BaseInvoiceRail.d.ts.map +1 -1
  9. package/dist/BaseInvoiceRail.js +8 -0
  10. package/dist/BaseInvoiceRail.js.map +1 -1
  11. package/dist/BasePaymentProvider.d.ts +7 -0
  12. package/dist/BasePaymentProvider.d.ts.map +1 -1
  13. package/dist/BasePaymentProvider.js.map +1 -1
  14. package/dist/BillComInvoiceRail.d.ts +5 -0
  15. package/dist/BillComInvoiceRail.d.ts.map +1 -1
  16. package/dist/BillComInvoiceRail.js +12 -3
  17. package/dist/BillComInvoiceRail.js.map +1 -1
  18. package/dist/CheckoutPublishableKey.d.ts +69 -0
  19. package/dist/CheckoutPublishableKey.d.ts.map +1 -0
  20. package/dist/CheckoutPublishableKey.js +122 -0
  21. package/dist/CheckoutPublishableKey.js.map +1 -0
  22. package/dist/CheckoutSessionService.d.ts +10 -1
  23. package/dist/CheckoutSessionService.d.ts.map +1 -1
  24. package/dist/CheckoutSessionService.js +26 -5
  25. package/dist/CheckoutSessionService.js.map +1 -1
  26. package/dist/ConcessionApprovalTask.d.ts +4 -0
  27. package/dist/ConcessionApprovalTask.d.ts.map +1 -1
  28. package/dist/ConcessionApprovalTask.js +8 -8
  29. package/dist/ConcessionApprovalTask.js.map +1 -1
  30. package/dist/CreateOrderFromProviderPaymentOperation.d.ts.map +1 -1
  31. package/dist/CreateOrderFromProviderPaymentOperation.js +2 -1
  32. package/dist/CreateOrderFromProviderPaymentOperation.js.map +1 -1
  33. package/dist/ExternalInvoiceBehavior.d.ts +6 -0
  34. package/dist/ExternalInvoiceBehavior.d.ts.map +1 -1
  35. package/dist/ExternalInvoiceBehavior.js +7 -0
  36. package/dist/ExternalInvoiceBehavior.js.map +1 -1
  37. package/dist/IssueExternalInvoiceOperation.d.ts.map +1 -1
  38. package/dist/IssueExternalInvoiceOperation.js +25 -3
  39. package/dist/IssueExternalInvoiceOperation.js.map +1 -1
  40. package/dist/OrderEntityServer.d.ts +26 -0
  41. package/dist/OrderEntityServer.d.ts.map +1 -1
  42. package/dist/OrderEntityServer.js +122 -8
  43. package/dist/OrderEntityServer.js.map +1 -1
  44. package/dist/OrderReview.d.ts +72 -0
  45. package/dist/OrderReview.d.ts.map +1 -0
  46. package/dist/OrderReview.js +611 -0
  47. package/dist/OrderReview.js.map +1 -0
  48. package/dist/OrdersSettings.d.ts +58 -0
  49. package/dist/OrdersSettings.d.ts.map +1 -1
  50. package/dist/OrdersSettings.js +111 -0
  51. package/dist/OrdersSettings.js.map +1 -1
  52. package/dist/PaymentProviderResolver.d.ts +10 -2
  53. package/dist/PaymentProviderResolver.d.ts.map +1 -1
  54. package/dist/PaymentProviderResolver.js +16 -5
  55. package/dist/PaymentProviderResolver.js.map +1 -1
  56. package/dist/ProductPriceEntityServer.d.ts +2 -2
  57. package/dist/ProductPriceEntityServer.d.ts.map +1 -1
  58. package/dist/ProductPriceEntityServer.js +3 -3
  59. package/dist/ProductPriceEntityServer.js.map +1 -1
  60. package/dist/RefundAuthority.d.ts +75 -0
  61. package/dist/RefundAuthority.d.ts.map +1 -0
  62. package/dist/RefundAuthority.js +155 -0
  63. package/dist/RefundAuthority.js.map +1 -0
  64. package/dist/RefundPaymentOperation.d.ts +2 -0
  65. package/dist/RefundPaymentOperation.d.ts.map +1 -1
  66. package/dist/RefundPaymentOperation.js +15 -0
  67. package/dist/RefundPaymentOperation.js.map +1 -1
  68. package/dist/SystemOrderOrigin.d.ts +40 -0
  69. package/dist/SystemOrderOrigin.d.ts.map +1 -0
  70. package/dist/SystemOrderOrigin.js +30 -0
  71. package/dist/SystemOrderOrigin.js.map +1 -0
  72. package/dist/index.d.ts +3 -1
  73. package/dist/index.d.ts.map +1 -1
  74. package/dist/index.js +3 -2
  75. package/dist/index.js.map +1 -1
  76. package/package.json +22 -22
@@ -34,7 +34,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
34
34
  */
35
35
  import { BaseEntity, BaseEntityResult, BaseRemotableOperation, CompositeKey, EntitySaveOptions, LogError, LogStatus, Metadata, RunView, ValidationErrorInfo, ValidationErrorType, } from '@memberjunction/core';
36
36
  import { MJGlobal, RegisterClass, UUIDsEqual } from '@memberjunction/global';
37
- import { ADDRESS_SNAPSHOT_FIELDS, BuildAddressSnapshot, OrderHeaderEntity, OrderLineEntity, mjBizAppsOrdersEventOrderLineEntity, ToISODate, HostOrderConfirmVeto, ResolveOrderConfirmRefusal, RunAlongsideRefusal, } from '@mj-biz-apps/orders-entities';
37
+ import { ADDRESS_SNAPSHOT_FIELDS, BuildAddressSnapshot, OrderHeaderEntity, OrderLineEntity, mjBizAppsOrdersEventOrderLineEntity, ToISODate, IsEditable, REVIEWED_HEADER_FIELDS, REVIEWED_LINE_FIELDS, HostOrderConfirmVeto, ResolveOrderConfirmRefusal, RunAlongsideRefusal, } from '@mj-biz-apps/orders-entities';
38
38
  import { CalendarDayOrToday } from './calendar-day.js';
39
39
  import { ResolveLineParty } from './LineParty.js';
40
40
  import { BuildGLAccountResolver, EntityIDFor, LoadAccountingEngine, ResolverEntities } from './AccountingBridge.js';
@@ -53,6 +53,8 @@ import { RequireUUID, RequireUUIDs } from './sql-guards.js';
53
53
  import { ExplainMissingAttendees, LoadLinesWithAttendee, LoadProductsRequiringAttendees } from './AttendeeRequirement.js';
54
54
  import { FindUnapprovedConcessions } from './ConcessionGate.js';
55
55
  import { RaisePriceBelowEngineExceptions } from './PriceBelowEngineExceptions.js';
56
+ import { CheckOrderReviewAtConfirm, CheckOrderReviewOnChange } from './OrderReview.js';
57
+ import { IsSystemOriginWrite, OriginWriteRefusal } from './SystemOrderOrigin.js';
56
58
  import { DimensionDefaultResolver } from './DimensionDefaultResolver.js';
57
59
  import { DeriveLineDimensions } from './LineDimensionRules.js';
58
60
  import { MergeDerivedTags, MergeLineDimensions } from './LineDimensionMerge.js';
@@ -436,12 +438,25 @@ let OrderEntityServer = class OrderEntityServer extends OrderHeaderEntity {
436
438
  // has now found three times.
437
439
  if (!this.passesStatusTransition())
438
440
  return false;
441
+ // ORIGIN IS SET BY THE PROCESS THAT CREATES THE ORDER, never by the person saving it. Order
442
+ // review exempts the system origins (golive #320 §5), so a writable Origin was a way round it.
443
+ if (!this.passesOriginGuard())
444
+ return false;
445
+ // A CHANGE THAT SENDS THE ORDER TO REVIEW (golive #320 §5) is read before the party defaults
446
+ // below fill anything in, so it sees only what the caller changed. It raises the review before
447
+ // the write: a spare task for a save that then fails is the safe side of the trade.
448
+ if (!(await this.passesOrderReviewOnChange()))
449
+ return false;
439
450
  await this.ApplySavePartyDefaults();
440
451
  const booking = this.willBookOnThisSave();
441
452
  // NO CONFIRM AHEAD OF A CONCESSION'S APPROVAL. Checked before anything is priced or booked,
442
453
  // for the same reason as the status move above: a refused confirm must change nothing.
443
454
  if (booking && !(await this.passesConcessionGate()))
444
455
  return false;
456
+ // NO CONFIRM AHEAD OF AN ORDER REVIEW (golive #320 §5), once concessions are decided, so the
457
+ // reviewer sees the order as it will book. Off until a host switches a trigger on.
458
+ if (booking && !(await this.passesOrderReviewGate()))
459
+ return false;
445
460
  // ORDINARY PATH — no booking, and no line work to do.
446
461
  //
447
462
  // The test is DIRTINESS, not emptiness. It used to read `this._lines.length === 0`, which
@@ -939,7 +954,112 @@ let OrderEntityServer = class OrderEntityServer extends OrderHeaderEntity {
939
954
  const user = this.ContextCurrentUser;
940
955
  if (!user)
941
956
  return true;
942
- const lines = this.Lines.Items.map((line) => ({
957
+ const lines = this.concessionLineFacts();
958
+ const problems = await FindUnapprovedConcessions(this.IsSaved ? this.ID : null, lines, true, this.ProviderToUse, user);
959
+ if (problems.length === 0)
960
+ return true;
961
+ this.RegisterResultHistoryEntry(this.buildFailureResult(new Error(`Order ${this.OrderNumber ?? ''} cannot be confirmed yet: ${problems.join('; ')}. A concession ` +
962
+ `must be approved before the customer is committed to it.`)));
963
+ return false;
964
+ }
965
+ /**
966
+ * Refuse a write of `Origin` that no system process made (./SystemOrderOrigin.ts). Applies with or
967
+ * without review switched on: an Origin written while review was off would be trusted once it is on.
968
+ */
969
+ passesOriginGuard() {
970
+ const stored = this.GetFieldByName('Origin')?.OldValue;
971
+ const refusal = OriginWriteRefusal({
972
+ IsSaved: this.IsSaved,
973
+ Origin: this.Origin ?? null,
974
+ StoredOrigin: typeof stored === 'string' ? stored : null,
975
+ MarkedBySystem: IsSystemOriginWrite(this),
976
+ });
977
+ if (!refusal)
978
+ return true;
979
+ this.RegisterResultHistoryEntry(this.buildFailureResult(new Error(refusal)));
980
+ return false;
981
+ }
982
+ /**
983
+ * Refuse the confirm while the order's review is outstanding, and send an order that hit a review
984
+ * trigger with no review to one (golive #320 §5). Like the concession gate, a refusal refuses the
985
+ * whole save, not only the move to Confirmed: nothing else the save carried is written either. A
986
+ * save with no context user is not reviewed: there is nobody to route the review as, and the
987
+ * processes that save without one are not direct entry.
988
+ */
989
+ async passesOrderReviewGate() {
990
+ const user = this.ContextCurrentUser;
991
+ if (!user)
992
+ return true;
993
+ const refusal = await CheckOrderReviewAtConfirm(this.reviewOrderInput(), {
994
+ Provider: this.ProviderToUse,
995
+ User: user,
996
+ });
997
+ if (!refusal)
998
+ return true;
999
+ this.RegisterResultHistoryEntry(this.buildFailureResult(new Error(refusal)));
1000
+ return false;
1001
+ }
1002
+ /**
1003
+ * A save of an unconfirmed order that changes its bill-to, company, prices or service dates sends a
1004
+ * deal-created or already-reviewed order (back) to review, and an edit to a renewal's carried-forward
1005
+ * price sends any order there (golive #320 §5). Refuses the save only when such a review could not be
1006
+ * raised.
1007
+ */
1008
+ async passesOrderReviewOnChange() {
1009
+ const user = this.ContextCurrentUser;
1010
+ if (!user || !this.IsSaved)
1011
+ return true;
1012
+ const savedStatus = String(this.GetFieldByName('Status')?.OldValue ?? this.Status ?? '');
1013
+ if (!IsEditable(savedStatus))
1014
+ return true;
1015
+ const change = {
1016
+ HeaderFieldsChanged: REVIEWED_HEADER_FIELDS.filter((f) => this.GetFieldByName(f)?.Dirty === true),
1017
+ // A renewal line still at the price the renewal pass wrote is not a hand edit (golive #304).
1018
+ LinesChanged: this.Lines.Items.filter((line) => line.IsSaved && !this.isUneditedRenewalPrice(line))
1019
+ .map((line) => ({
1020
+ LineNumber: line.LineNumber ?? null,
1021
+ Fields: REVIEWED_LINE_FIELDS.filter((f) => line.GetFieldByName(f)?.Dirty === true),
1022
+ RenewsSubscriptionID: line.RenewsSubscriptionID ?? null,
1023
+ }))
1024
+ .filter((line) => line.Fields.length > 0),
1025
+ LinesAdded: this.Lines.Items.filter((line) => !line.IsSaved && !line.ParentOrderLineID && !line.ReversesOrderLineID).length,
1026
+ LinesRemoved: this.Lines.Removed.filter((line) => line.IsSaved).length,
1027
+ };
1028
+ if (change.HeaderFieldsChanged.length === 0 && change.LinesChanged.length === 0 && change.LinesAdded === 0 && change.LinesRemoved === 0) {
1029
+ return true;
1030
+ }
1031
+ const refusal = await CheckOrderReviewOnChange(this.reviewOrderInput(), change, {
1032
+ Provider: this.ProviderToUse,
1033
+ User: user,
1034
+ });
1035
+ if (!refusal)
1036
+ return true;
1037
+ this.RegisterResultHistoryEntry(this.buildFailureResult(new Error(refusal)));
1038
+ return false;
1039
+ }
1040
+ /** The order as the review reads it (golive #320 §5). */
1041
+ reviewOrderInput() {
1042
+ const items = this.Lines.Items;
1043
+ return {
1044
+ OrderHeaderID: this.IsSaved ? this.ID : null,
1045
+ OrderNumber: this.OrderNumber ?? null,
1046
+ Origin: this.Origin ?? null,
1047
+ ReversesOrderHeaderID: this.ReversesOrderHeaderID ?? null,
1048
+ Lines: this.concessionLineFacts().map((facts, i) => ({
1049
+ ...facts,
1050
+ ServicePeriodStart: ToISODate(items[i].ServicePeriodStart),
1051
+ ServicePeriodEnd: ToISODate(items[i].ServicePeriodEnd),
1052
+ RenewalPriceEdited: this.isEditedRenewalPrice(items[i]),
1053
+ })),
1054
+ };
1055
+ }
1056
+ /** True for a line the renewal pass priced in this object whose price has since been changed. */
1057
+ isEditedRenewalPrice(line) {
1058
+ return this._renewalPricedLines.has(line) && !this.isUneditedRenewalPrice(line);
1059
+ }
1060
+ /** The lines in memory as the concession gate and the order review read them, in `Lines.Items` order. */
1061
+ concessionLineFacts() {
1062
+ return this.Lines.Items.map((line) => ({
943
1063
  ID: line.IsSaved ? line.ID : null,
944
1064
  LineNumber: line.LineNumber ?? null,
945
1065
  ParentOrderLineID: line.ParentOrderLineID ?? null,
@@ -956,12 +1076,6 @@ let OrderEntityServer = class OrderEntityServer extends OrderHeaderEntity {
956
1076
  (line.IsSaved || line.GetFieldByName('UnitPrice')?.Dirty === true || (line.UnitPrice ?? 0) > 0),
957
1077
  LineTotalNet: line.IsRollupParent ? 0 : this.pendingLineNet(line),
958
1078
  }));
959
- const problems = await FindUnapprovedConcessions(this.IsSaved ? this.ID : null, lines, true, this.ProviderToUse, user);
960
- if (problems.length === 0)
961
- return true;
962
- this.RegisterResultHistoryEntry(this.buildFailureResult(new Error(`Order ${this.OrderNumber ?? ''} cannot be confirmed yet: ${problems.join('; ')}. A concession ` +
963
- `must be approved before the customer is committed to it.`)));
964
- return false;
965
1079
  }
966
1080
  /**
967
1081
  * Record every line of this booking that is priced below its engine price with no Approved