@bisondesk/core-sdk 1.0.651 → 1.0.652

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 (129) hide show
  1. package/lib/apis/leasing.d.ts +1 -1
  2. package/lib/apis/leasing.d.ts.map +1 -1
  3. package/lib/apis/leasing.js +3 -2
  4. package/lib/apis/leasing.js.map +1 -1
  5. package/lib/types/quotes.d.ts +1 -0
  6. package/lib/types/quotes.d.ts.map +1 -1
  7. package/lib/types/quotes.js.map +1 -1
  8. package/lib/types/reports-arrivals.d.ts +67 -0
  9. package/lib/types/reports-arrivals.d.ts.map +1 -0
  10. package/lib/types/reports-arrivals.js +4 -0
  11. package/lib/types/reports-arrivals.js.map +1 -0
  12. package/lib/types/reports-sales.d.ts +7 -0
  13. package/lib/types/reports-sales.d.ts.map +1 -1
  14. package/lib/types/reports-sales.js.map +1 -1
  15. package/lib/types/templates.d.ts +22 -0
  16. package/lib/types/templates.d.ts.map +1 -1
  17. package/lib/types/templates.js.map +1 -1
  18. package/lib/types/tenants.d.ts +1 -1
  19. package/lib/types/tenants.d.ts.map +1 -1
  20. package/lib/types/tenants.js +1 -1
  21. package/lib/types/tenants.js.map +1 -1
  22. package/lib/types/transports.d.ts +5 -1
  23. package/lib/types/transports.d.ts.map +1 -1
  24. package/lib/types/transports.js +6 -0
  25. package/lib/types/transports.js.map +1 -1
  26. package/lib/utils/leasing.d.ts +1 -0
  27. package/lib/utils/leasing.d.ts.map +1 -1
  28. package/lib/utils/leasing.js +7 -1
  29. package/lib/utils/leasing.js.map +1 -1
  30. package/lib/utils/leasing.test.d.ts +2 -0
  31. package/lib/utils/leasing.test.d.ts.map +1 -0
  32. package/lib/utils/leasing.test.js +69 -0
  33. package/lib/utils/leasing.test.js.map +1 -0
  34. package/lib/utils/reports-arrivals.d.ts +3 -0
  35. package/lib/utils/reports-arrivals.d.ts.map +1 -0
  36. package/lib/utils/reports-arrivals.js +15 -0
  37. package/lib/utils/reports-arrivals.js.map +1 -0
  38. package/lib/utils/transports.d.ts +1 -0
  39. package/lib/utils/transports.d.ts.map +1 -1
  40. package/lib/utils/transports.js +3 -4
  41. package/lib/utils/transports.js.map +1 -1
  42. package/lib/utils/vehicles.d.ts +3 -1
  43. package/lib/utils/vehicles.d.ts.map +1 -1
  44. package/lib/utils/vehicles.js +6 -1
  45. package/lib/utils/vehicles.js.map +1 -1
  46. package/package.json +1 -1
  47. package/src/apis/leasing.ts +3 -1
  48. package/src/types/activities.js +13 -0
  49. package/src/types/activities.js.map +1 -0
  50. package/src/types/comparables.js +2 -0
  51. package/src/types/comparables.js.map +1 -0
  52. package/src/types/crm.js +58 -0
  53. package/src/types/crm.js.map +1 -0
  54. package/src/types/dashboard.js +2 -0
  55. package/src/types/dashboard.js.map +1 -0
  56. package/src/types/definitions.js +2 -0
  57. package/src/types/definitions.js.map +1 -0
  58. package/src/types/fields.js +2 -0
  59. package/src/types/fields.js.map +1 -0
  60. package/src/types/insights.js +2 -0
  61. package/src/types/insights.js.map +1 -0
  62. package/src/types/interests.js +6 -0
  63. package/src/types/interests.js.map +1 -0
  64. package/src/types/internal-events.js +18 -0
  65. package/src/types/internal-events.js.map +1 -0
  66. package/src/types/internet-opportunities.js +2 -0
  67. package/src/types/internet-opportunities.js.map +1 -0
  68. package/src/types/internet-vehicles.js +2 -0
  69. package/src/types/internet-vehicles.js.map +1 -0
  70. package/src/types/leasing-administration.js +2 -0
  71. package/src/types/leasing-administration.js.map +1 -0
  72. package/src/types/leasing-debtors.js +2 -0
  73. package/src/types/leasing-debtors.js.map +1 -0
  74. package/src/types/leasing-search.js +2 -0
  75. package/src/types/leasing-search.js.map +1 -0
  76. package/src/types/leasing-settings.js +7 -0
  77. package/src/types/leasing-settings.js.map +1 -0
  78. package/src/types/leasing.js +38 -0
  79. package/src/types/leasing.js.map +1 -0
  80. package/src/types/marketing.js +35 -0
  81. package/src/types/marketing.js.map +1 -0
  82. package/src/types/offers.js +56 -0
  83. package/src/types/opportunities.js +107 -0
  84. package/src/types/opportunities.js.map +1 -0
  85. package/src/types/payments.js +7 -0
  86. package/src/types/picklists.js +2 -0
  87. package/src/types/picklists.js.map +1 -0
  88. package/src/types/quotes.js +42 -0
  89. package/src/types/quotes.ts +1 -0
  90. package/src/types/recently-viewed.js +2 -0
  91. package/src/types/recently-viewed.js.map +1 -0
  92. package/src/types/reports-arrivals.ts +95 -0
  93. package/src/types/reports-sales.ts +13 -0
  94. package/src/types/reservations.js +5 -0
  95. package/src/types/reservations.js.map +1 -0
  96. package/src/types/roi-ratings.js +5 -0
  97. package/src/types/roi-ratings.js.map +1 -0
  98. package/src/types/saved-filters.js +9 -0
  99. package/src/types/saved-filters.js.map +1 -0
  100. package/src/types/search.js +2 -0
  101. package/src/types/search.js.map +1 -0
  102. package/src/types/settings.js +2 -0
  103. package/src/types/settings.js.map +1 -0
  104. package/src/types/templates.js +2 -0
  105. package/src/types/templates.js.map +1 -0
  106. package/src/types/templates.ts +27 -0
  107. package/src/types/tenants.js +21 -0
  108. package/src/types/tenants.js.map +1 -0
  109. package/src/types/tenants.ts +1 -1
  110. package/src/types/transports.ts +11 -1
  111. package/src/types/user-performance.js +7 -0
  112. package/src/types/user-performance.js.map +1 -0
  113. package/src/types/utils.js +2 -0
  114. package/src/types/validation.js +2 -0
  115. package/src/types/validation.js.map +1 -0
  116. package/src/types/vehicle-sales.js +6 -0
  117. package/src/types/vehicle-sales.js.map +1 -0
  118. package/src/types/vehicles.js +98 -0
  119. package/src/types/vehicles.js.map +1 -0
  120. package/src/utils/leasing.js +6 -0
  121. package/src/utils/leasing.js.map +1 -0
  122. package/src/utils/leasing.test.ts +79 -0
  123. package/src/utils/leasing.ts +22 -1
  124. package/src/utils/opportunities.js +48 -0
  125. package/src/utils/opportunities.js.map +1 -0
  126. package/src/utils/reports-arrivals.ts +19 -0
  127. package/src/utils/transports.ts +13 -7
  128. package/src/utils/vehicles.ts +10 -0
  129. package/tsconfig.tsbuildinfo +1 -1
@@ -1,3 +1,5 @@
1
+ import type { EmailContent, EmailRequest } from '@bisondesk/commons-sdk/messages';
2
+
1
3
  export type TemplateContent = {
2
4
  subject: string;
3
5
  content: {
@@ -35,3 +37,28 @@ export type UpdateTemplateInfoRequest = {
35
37
  name: string;
36
38
  tags?: any;
37
39
  };
40
+
41
+ export type CodeEmailTemplateInfo = Pick<TemplateInfo, 'id' | 'name' | 'countries'> & {
42
+ format: 'react-email';
43
+ };
44
+
45
+ export type TemplateCatalogueEntry = (TemplateInfo & { format: 'html' }) | CodeEmailTemplateInfo;
46
+
47
+ export type TemplateEmailRequest<T extends Record<string, unknown> = Record<string, unknown>> =
48
+ Omit<EmailRequest, 'subject' | 'body'> & {
49
+ templateId: string;
50
+ country: string;
51
+ fallbackCountry?: string;
52
+ data: T;
53
+ subject?: string;
54
+ };
55
+
56
+ export type EmailTemplatePreviewRequest = {
57
+ data?: Record<string, unknown>;
58
+ subject?: string;
59
+ };
60
+
61
+ export type EmailTemplatePreview = {
62
+ content: EmailContent;
63
+ data: Record<string, unknown>;
64
+ };
@@ -0,0 +1,21 @@
1
+ export var TenantModule;
2
+ (function (TenantModule) {
3
+ TenantModule["Administration"] = "administration";
4
+ TenantModule["App"] = "app";
5
+ TenantModule["CRM"] = "crm";
6
+ TenantModule["Docs"] = "docs";
7
+ TenantModule["Leads"] = "leads";
8
+ TenantModule["Leasing"] = "leasing";
9
+ TenantModule["Marketing"] = "marketing";
10
+ TenantModule["Insights"] = "insights";
11
+ TenantModule["Opportunities"] = "opportunities";
12
+ TenantModule["Offers"] = "offers";
13
+ TenantModule["VehiclesMasterData"] = "vehicles_master_data";
14
+ TenantModule["Vehicles"] = "vehicles";
15
+ TenantModule["Tasks"] = "tasks";
16
+ TenantModule["TrackAndTrace"] = "track_and_trace";
17
+ TenantModule["Bootstrap"] = "bootstrap";
18
+ TenantModule["WhatsappNotifications"] = "whatsapp_notifications";
19
+ TenantModule["Hexon"] = "hexon";
20
+ })(TenantModule || (TenantModule = {}));
21
+ //# sourceMappingURL=tenants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenants.js","sourceRoot":"","sources":["tenants.ts"],"names":[],"mappings":"AAgBA,MAAM,CAAN,IAAY,YAkBX;AAlBD,WAAY,YAAY;IACtB,iDAAiC,CAAA;IACjC,2BAAW,CAAA;IACX,2BAAW,CAAA;IACX,6BAAa,CAAA;IACb,+BAAe,CAAA;IACf,mCAAmB,CAAA;IACnB,uCAAuB,CAAA;IACvB,qCAAqB,CAAA;IACrB,+CAA+B,CAAA;IAC/B,iCAAiB,CAAA;IACjB,2DAA2C,CAAA;IAC3C,qCAAqB,CAAA;IACrB,+BAAe,CAAA;IACf,iDAAiC,CAAA;IACjC,uCAAuB,CAAA;IACvB,gEAAgD,CAAA;IAChD,+BAAe,CAAA;AACjB,CAAC,EAlBW,YAAY,KAAZ,YAAY,QAkBvB"}
@@ -68,7 +68,7 @@ export enum TenantModule {
68
68
  }
69
69
 
70
70
  /** Report tabs a tenant can enable, in canonical order. */
71
- export const REPORT_TAB_KEYS = ['sales', 'leasing', 'purchases'] as const;
71
+ export const REPORT_TAB_KEYS = ['sales', 'leasing', 'purchases', 'arrivals'] as const;
72
72
 
73
73
  export type ReportTabKey = (typeof REPORT_TAB_KEYS)[number];
74
74
 
@@ -14,9 +14,18 @@ import { Vehicle, VehiclePurchase } from './vehicles.js';
14
14
 
15
15
  export enum TransportType {
16
16
  PurchasePickUp = 'PURCHASE_PICK_UP',
17
+ PurchaseDropOff = 'PURCHASE_DROP_OFF',
17
18
  SaleDelivery = 'SALE_DELIVERY',
18
19
  }
19
20
 
21
+ /** Both inbound journeys, whoever drives them. Mirrors the purchase's own delivery type. */
22
+ export type TransportPurchaseType = TransportType.PurchasePickUp | TransportType.PurchaseDropOff;
23
+
24
+ export const TransportPurchaseTypes: TransportPurchaseType[] = [
25
+ TransportType.PurchasePickUp,
26
+ TransportType.PurchaseDropOff,
27
+ ];
28
+
20
29
  export enum TransportStatus {
21
30
  Todo = 'TODO',
22
31
  Planning = 'PLANNING',
@@ -127,7 +136,7 @@ export type Transport = {
127
136
  updatedBy: string;
128
137
  } & (
129
138
  | {
130
- type: TransportType.PurchasePickUp;
139
+ type: TransportPurchaseType;
131
140
  delivery: TransportPurchaseDeliveryType;
132
141
  }
133
142
  | {
@@ -204,6 +213,7 @@ export type TransportUpdateEvent = BaseTransportEvent & {
204
213
  export type TransportEvent = BaseEvent & (TransportCreateEvent | TransportUpdateEvent);
205
214
 
206
215
  export enum TransportPaymentStatus {
216
+ PaymentNotNeeded = 'payment_not_needed',
207
217
  NoPayment = 'no_payment',
208
218
  PartialPaymentReceived = 'partial_payment_received',
209
219
  FullPaymentReceived = 'full_payment_received',
@@ -0,0 +1,7 @@
1
+ export var CommissionGrade;
2
+ (function (CommissionGrade) {
3
+ CommissionGrade["TooLow"] = "tooLow";
4
+ CommissionGrade["Low"] = "low";
5
+ CommissionGrade["OnTarget"] = "onTarget";
6
+ })(CommissionGrade || (CommissionGrade = {}));
7
+ //# sourceMappingURL=user-performance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-performance.js","sourceRoot":"","sources":["user-performance.ts"],"names":[],"mappings":"AAsCA,MAAM,CAAN,IAAY,eAIX;AAJD,WAAY,eAAe;IACzB,oCAAiB,CAAA;IACjB,8BAAW,CAAA;IACX,wCAAqB,CAAA;AACvB,CAAC,EAJW,eAAe,KAAf,eAAe,QAI1B"}
@@ -0,0 +1,2 @@
1
+ export * from '@bisondesk/commons-sdk/utils';
2
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["validation.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ export var VehicleSaleInfoActions;
2
+ (function (VehicleSaleInfoActions) {
3
+ VehicleSaleInfoActions["VIEW_COSTS"] = "canSeeCosts";
4
+ VehicleSaleInfoActions["VIEW_CUSTOMER"] = "canSeeCustomer";
5
+ })(VehicleSaleInfoActions || (VehicleSaleInfoActions = {}));
6
+ //# sourceMappingURL=vehicle-sales.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vehicle-sales.js","sourceRoot":"","sources":["vehicle-sales.ts"],"names":[],"mappings":"AAOA,MAAM,CAAN,IAAY,sBAGX;AAHD,WAAY,sBAAsB;IAChC,oDAA0B,CAAA;IAC1B,0DAAgC,CAAA;AAClC,CAAC,EAHW,sBAAsB,KAAtB,sBAAsB,QAGjC"}
@@ -0,0 +1,98 @@
1
+ export var VehicleRoles;
2
+ (function (VehicleRoles) {
3
+ VehicleRoles["SALE"] = "SALE";
4
+ VehicleRoles["OWN_USE"] = "OWN_USE";
5
+ VehicleRoles["RENTAL"] = "RENTAL";
6
+ VehicleRoles["BUILD"] = "BUILD";
7
+ VehicleRoles["UNKNOWN"] = "UNKNOWN";
8
+ VehicleRoles["BANK_FINANCE"] = "BANK_FINANCE";
9
+ })(VehicleRoles || (VehicleRoles = {}));
10
+ export var VehicleFuelType;
11
+ (function (VehicleFuelType) {
12
+ VehicleFuelType["Petrol"] = "PETROL";
13
+ VehicleFuelType["Diesel"] = "DIESEL";
14
+ VehicleFuelType["LPG"] = "LPG";
15
+ VehicleFuelType["LPG_G3"] = "LPG_G3";
16
+ VehicleFuelType["Electric"] = "ELECTRIC";
17
+ VehicleFuelType["CNG"] = "CNG";
18
+ VehicleFuelType["Hydrogen"] = "HYDROGEN";
19
+ VehicleFuelType["BioEthanol"] = "BIO_ETHANOL";
20
+ VehicleFuelType["BioDiesel"] = "BIO_DIESEL";
21
+ VehicleFuelType["E85"] = "E85";
22
+ VehicleFuelType["HCNG"] = "HCNG";
23
+ VehicleFuelType["LPG_Petrol"] = "LPG_PETROL";
24
+ VehicleFuelType["LPG_Diesel"] = "LPG_DIESEL";
25
+ VehicleFuelType["LPG_G3_Petrol"] = "LPG_G3_PETROL";
26
+ VehicleFuelType["LPG_G3_Diesel"] = "LPG_G3_DIESEL";
27
+ VehicleFuelType["Electric_Diesel"] = "ELECTRIC_DIESEL";
28
+ VehicleFuelType["Electric_Petrol"] = "ELECTRIC_PETROL";
29
+ VehicleFuelType["Hybrid"] = "HYBRID";
30
+ VehicleFuelType["Other"] = "OTHER";
31
+ })(VehicleFuelType || (VehicleFuelType = {}));
32
+ export var VehicleTachoTypes;
33
+ (function (VehicleTachoTypes) {
34
+ VehicleTachoTypes["Analog"] = "ANALOG";
35
+ VehicleTachoTypes["Digital"] = "DIGITAL";
36
+ VehicleTachoTypes["SmartTacho1"] = "SMART_TACHO_1";
37
+ VehicleTachoTypes["SmartTacho2"] = "SMART_TACHO_2";
38
+ })(VehicleTachoTypes || (VehicleTachoTypes = {}));
39
+ export var SearchVehicleSaleDealStatus;
40
+ (function (SearchVehicleSaleDealStatus) {
41
+ SearchVehicleSaleDealStatus["NotSold"] = "NOT_SOLD";
42
+ SearchVehicleSaleDealStatus["Reserved"] = "RESERVED";
43
+ SearchVehicleSaleDealStatus["Sold"] = "SOLD";
44
+ })(SearchVehicleSaleDealStatus || (SearchVehicleSaleDealStatus = {}));
45
+ export var VehiclePurchaseDealStatus;
46
+ (function (VehiclePurchaseDealStatus) {
47
+ VehiclePurchaseDealStatus["Marketing"] = "MARKETING";
48
+ VehiclePurchaseDealStatus["PurchaseEvaluation"] = "PURCHASE_EVALUATION";
49
+ VehiclePurchaseDealStatus["PurchaseAgreed"] = "PURCHASE_AGREED";
50
+ VehiclePurchaseDealStatus["FirstPaymentAllowed"] = "FIRST_PAYMENT_ALLOWED";
51
+ VehiclePurchaseDealStatus["FirstPaymentSent"] = "FIRST_PAYMENT_SENT";
52
+ VehiclePurchaseDealStatus["FullPaymentAllowed"] = "FULL_PAYMENT_ALLOWED";
53
+ VehiclePurchaseDealStatus["FullPaymentSent"] = "FULL_PAYMENT_SENT";
54
+ })(VehiclePurchaseDealStatus || (VehiclePurchaseDealStatus = {}));
55
+ export var VehiclePurchaseLogisticsStatus;
56
+ (function (VehiclePurchaseLogisticsStatus) {
57
+ VehiclePurchaseLogisticsStatus["AtOrigin"] = "AT_ORIGIN";
58
+ VehiclePurchaseLogisticsStatus["Arrived"] = "ARRIVED";
59
+ VehiclePurchaseLogisticsStatus["CheckedIn"] = "CHECKED_IN";
60
+ })(VehiclePurchaseLogisticsStatus || (VehiclePurchaseLogisticsStatus = {}));
61
+ export var VehiclePurchaseDeliveryType;
62
+ (function (VehiclePurchaseDeliveryType) {
63
+ VehiclePurchaseDeliveryType["PickUp"] = "PICK_UP";
64
+ VehiclePurchaseDeliveryType["DropOff"] = "DROP_OFF";
65
+ })(VehiclePurchaseDeliveryType || (VehiclePurchaseDeliveryType = {}));
66
+ export var VehicleActions;
67
+ (function (VehicleActions) {
68
+ VehicleActions["EditAdminDocs"] = "edit_admin_docs";
69
+ VehicleActions["EditEngineeringDocs"] = "edit_engineering_docs";
70
+ VehicleActions["EditMarketing"] = "edit_marketing";
71
+ VehicleActions["EditMedia"] = "edit_media";
72
+ VehicleActions["EditPictures"] = "edit_pictures";
73
+ VehicleActions["EditPrices"] = "edit_prices";
74
+ VehicleActions["EditPurchaseDeal"] = "edit_purchase_deal";
75
+ VehicleActions["EditPurchaseLogistics"] = "edit_purchase_logistics";
76
+ VehicleActions["EditSpecs"] = "edit_specs";
77
+ VehicleActions["EditVideos"] = "edit_videos";
78
+ VehicleActions["ViewLeads"] = "view_leads";
79
+ VehicleActions["ViewSimilarOnline"] = "view_similar_online";
80
+ VehicleActions["ViewPurchase"] = "view_purchase";
81
+ VehicleActions["ViewPriceHistory"] = "view_price_history";
82
+ VehicleActions["DeleteVehicle"] = "delete_vehicle";
83
+ })(VehicleActions || (VehicleActions = {}));
84
+ export var PurchaseActions;
85
+ (function (PurchaseActions) {
86
+ PurchaseActions["ViewDeal"] = "view_deal";
87
+ PurchaseActions["ViewSupplierOrganization"] = "view_supplier_organization";
88
+ PurchaseActions["ViewContact"] = "view_contact";
89
+ PurchaseActions["ViewLegalAddress"] = "view_legal_address";
90
+ PurchaseActions["ViewPickupAddress"] = "view_pickup_address";
91
+ PurchaseActions["ViewEstimatedCosts"] = "view_estimated_costs";
92
+ PurchaseActions["ViewFinanceDocuments"] = "view_finance_documents";
93
+ PurchaseActions["AddPayment"] = "add_payment";
94
+ PurchaseActions["EditPayment"] = "edit_payment";
95
+ PurchaseActions["MarkPaymentDone"] = "mark_payment_done";
96
+ PurchaseActions["AddRemarks"] = "add_remarks";
97
+ })(PurchaseActions || (PurchaseActions = {}));
98
+ //# sourceMappingURL=vehicles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vehicles.js","sourceRoot":"","sources":["vehicles.ts"],"names":[],"mappings":"AAgBA,MAAM,CAAN,IAAY,YAOX;AAPD,WAAY,YAAY;IACtB,6BAAa,CAAA;IACb,mCAAmB,CAAA;IACnB,iCAAiB,CAAA;IACjB,+BAAe,CAAA;IACf,mCAAmB,CAAA;IACnB,6CAA6B,CAAA;AAC/B,CAAC,EAPW,YAAY,KAAZ,YAAY,QAOvB;AAED,MAAM,CAAN,IAAY,eAoBX;AApBD,WAAY,eAAe;IACzB,oCAAiB,CAAA;IACjB,oCAAiB,CAAA;IACjB,8BAAW,CAAA;IACX,oCAAiB,CAAA;IACjB,wCAAqB,CAAA;IACrB,8BAAW,CAAA;IACX,wCAAqB,CAAA;IACrB,6CAA0B,CAAA;IAC1B,2CAAwB,CAAA;IACxB,8BAAW,CAAA;IACX,gCAAa,CAAA;IACb,4CAAyB,CAAA;IACzB,4CAAyB,CAAA;IACzB,kDAA+B,CAAA;IAC/B,kDAA+B,CAAA;IAC/B,sDAAmC,CAAA;IACnC,sDAAmC,CAAA;IACnC,oCAAiB,CAAA;IACjB,kCAAe,CAAA;AACjB,CAAC,EApBW,eAAe,KAAf,eAAe,QAoB1B;AAED,MAAM,CAAN,IAAY,iBAKX;AALD,WAAY,iBAAiB;IAC3B,sCAAiB,CAAA;IACjB,wCAAmB,CAAA;IACnB,kDAA6B,CAAA;IAC7B,kDAA6B,CAAA;AAC/B,CAAC,EALW,iBAAiB,KAAjB,iBAAiB,QAK5B;AAiLD,MAAM,CAAN,IAAY,2BAIX;AAJD,WAAY,2BAA2B;IACrC,mDAAoB,CAAA;IACpB,oDAAqB,CAAA;IACrB,4CAAa,CAAA;AACf,CAAC,EAJW,2BAA2B,KAA3B,2BAA2B,QAItC;AAwWD,MAAM,CAAN,IAAY,yBAQX;AARD,WAAY,yBAAyB;IACnC,oDAAuB,CAAA;IACvB,uEAA0C,CAAA;IAC1C,+DAAkC,CAAA;IAClC,0EAA6C,CAAA;IAC7C,oEAAuC,CAAA;IACvC,wEAA2C,CAAA;IAC3C,kEAAqC,CAAA;AACvC,CAAC,EARW,yBAAyB,KAAzB,yBAAyB,QAQpC;AAED,MAAM,CAAN,IAAY,8BAIX;AAJD,WAAY,8BAA8B;IACxC,wDAAsB,CAAA;IACtB,qDAAmB,CAAA;IACnB,0DAAwB,CAAA;AAC1B,CAAC,EAJW,8BAA8B,KAA9B,8BAA8B,QAIzC;AAED,MAAM,CAAN,IAAY,2BAGX;AAHD,WAAY,2BAA2B;IACrC,iDAAkB,CAAA;IAClB,mDAAoB,CAAA;AACtB,CAAC,EAHW,2BAA2B,KAA3B,2BAA2B,QAGtC;AAwGD,MAAM,CAAN,IAAY,cAgBX;AAhBD,WAAY,cAAc;IACxB,mDAAiC,CAAA;IACjC,+DAA6C,CAAA;IAC7C,kDAAgC,CAAA;IAChC,0CAAwB,CAAA;IACxB,gDAA8B,CAAA;IAC9B,4CAA0B,CAAA;IAC1B,yDAAuC,CAAA;IACvC,mEAAiD,CAAA;IACjD,0CAAwB,CAAA;IACxB,4CAA0B,CAAA;IAC1B,0CAAwB,CAAA;IACxB,2DAAyC,CAAA;IACzC,gDAA8B,CAAA;IAC9B,yDAAuC,CAAA;IACvC,kDAAgC,CAAA;AAClC,CAAC,EAhBW,cAAc,KAAd,cAAc,QAgBzB;AAED,MAAM,CAAN,IAAY,eAYX;AAZD,WAAY,eAAe;IACzB,yCAAsB,CAAA;IACtB,0EAAuD,CAAA;IACvD,+CAA4B,CAAA;IAC5B,0DAAuC,CAAA;IACvC,4DAAyC,CAAA;IACzC,8DAA2C,CAAA;IAC3C,kEAA+C,CAAA;IAC/C,6CAA0B,CAAA;IAC1B,+CAA4B,CAAA;IAC5B,wDAAqC,CAAA;IACrC,6CAA0B,CAAA;AAC5B,CAAC,EAZW,eAAe,KAAf,eAAe,QAY1B"}
@@ -0,0 +1,6 @@
1
+ import { UTCDate } from '@date-fns/utc';
2
+ import { format } from 'date-fns';
3
+ import { last, map, sortBy, uniqBy } from 'lodash-es';
4
+ export const sortContractClients = (clients) => sortBy(map(uniqBy(clients, (c) => c.takeoverId), (c) => ({ ...c, since: format(new UTCDate(c.since), 'yyyy-MM-dd') })), (cli) => cli.since, (cli) => (cli.takeoverId ? parseInt(cli.takeoverId.replace(/[^0-9]/g, '')) : 0));
5
+ export const getDealRef = ({ conditions, opportunities, }) => last(conditions) ?? last(opportunities);
6
+ //# sourceMappingURL=leasing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"leasing.js","sourceRoot":"","sources":["leasing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAStD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,OAAgC,EAA2B,EAAE,CAC/F,MAAM,CACJ,GAAG,CACD,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,EACpC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC,CACrE,EACD,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,EAClB,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAChF,CAAC;AAEJ,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EACzB,UAAU,EACV,aAAa,GACyC,EAAkC,EAAE,CAC1F,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,aAAa,CAAE,CAAC"}
@@ -0,0 +1,79 @@
1
+ import { ConditionsRef, OpportunityRef } from '../types/leasing.js';
2
+ import { getDealRefAsOf } from './leasing.js';
3
+
4
+ const makeOpportunityRef = (overrides: Partial<OpportunityRef> = {}): OpportunityRef => ({
5
+ id: 'opp',
6
+ createdAt: '2025-01-01',
7
+ quoteId: 'q',
8
+ depositAmount: '0',
9
+ durationInMonths: 24,
10
+ saleAmount: '0',
11
+ interestRate: '0',
12
+ residualAmount: '0',
13
+ leasingMonthlyAmount: '0',
14
+ otherMonthlyAmounts: '0',
15
+ totalMonthlyAmount: '0',
16
+ ...overrides,
17
+ });
18
+
19
+ const makeConditionsRef = (overrides: Partial<ConditionsRef> = {}): ConditionsRef => ({
20
+ id: 'cond',
21
+ validSince: '2025-01-01',
22
+ depositAmount: '0',
23
+ durationInMonths: 24,
24
+ saleAmount: '0',
25
+ interestRate: '0',
26
+ residualAmount: '0',
27
+ leasingMonthlyAmount: '0',
28
+ otherMonthlyAmounts: '0',
29
+ totalMonthlyAmount: '0',
30
+ ...overrides,
31
+ });
32
+
33
+ describe('getDealRefAsOf', () => {
34
+ test('picks the opportunity snapshot in force when the invoice was issued (the failing case)', () => {
35
+ const original = makeOpportunityRef({
36
+ id: 'original',
37
+ createdAt: '2025-06-19T09:20:28.019Z',
38
+ insuranceAmount: '196',
39
+ otherMonthlyAmounts: '213',
40
+ totalMonthlyAmount: '1423',
41
+ });
42
+ const renegotiated = makeOpportunityRef({
43
+ id: 'renegotiated',
44
+ createdAt: '2026-01-01',
45
+ insuranceAmount: '211.65',
46
+ otherMonthlyAmounts: '228.65',
47
+ totalMonthlyAmount: '1438.65',
48
+ });
49
+ const contract = { conditions: undefined, opportunities: [original, renegotiated] };
50
+
51
+ expect(getDealRefAsOf(contract, '2025-11-01').id).toBe('original');
52
+ expect(getDealRefAsOf(contract, '2026-02-01').id).toBe('renegotiated');
53
+ });
54
+
55
+ test('picks the conditions snapshot in force by validSince', () => {
56
+ const first = makeConditionsRef({ id: 'first', validSince: '2024-01-01' });
57
+ const second = makeConditionsRef({ id: 'second', validSince: '2025-01-01' });
58
+ const contract = { conditions: [first, second], opportunities: undefined };
59
+
60
+ expect(getDealRefAsOf(contract, '2024-06-01').id).toBe('first');
61
+ expect(getDealRefAsOf(contract, '2025-06-01').id).toBe('second');
62
+ });
63
+
64
+ test('is inclusive of a snapshot effective on the same day as the invoice', () => {
65
+ const before = makeConditionsRef({ id: 'before', validSince: '2024-01-01' });
66
+ const sameDay = makeConditionsRef({ id: 'sameDay', validSince: '2025-05-10' });
67
+ const contract = { conditions: [before, sameDay], opportunities: undefined };
68
+
69
+ expect(getDealRefAsOf(contract, '2025-05-10').id).toBe('sameDay');
70
+ });
71
+
72
+ test('falls back to the earliest snapshot when the date predates all of them', () => {
73
+ const first = makeConditionsRef({ id: 'first', validSince: '2025-01-01' });
74
+ const second = makeConditionsRef({ id: 'second', validSince: '2026-01-01' });
75
+ const contract = { conditions: [first, second], opportunities: undefined };
76
+
77
+ expect(getDealRefAsOf(contract, '2024-01-01').id).toBe('first');
78
+ });
79
+ });
@@ -1,7 +1,7 @@
1
1
  import { UTCDate } from '@date-fns/utc';
2
2
  import { format } from 'date-fns';
3
3
  import { Decimal } from 'decimal.js';
4
- import { last, map, sortBy, uniqBy } from 'lodash-es';
4
+ import { first, last, map, sortBy, uniqBy } from 'lodash-es';
5
5
  import {
6
6
  ConditionsRef,
7
7
  LeasingContract,
@@ -30,6 +30,27 @@ export const getDealRef = ({
30
30
  }: Pick<LeasingContract, 'conditions' | 'opportunities'>): ConditionsRef | OpportunityRef =>
31
31
  last(conditions) ?? last(opportunities)!;
32
32
 
33
+ const refEffectiveFrom = (ref: ConditionsRef | OpportunityRef): string =>
34
+ 'validSince' in ref ? ref.validSince : ref.createdAt;
35
+
36
+ /**
37
+ * Picks the conditions snapshot that was in force on a given date, rather than the latest one.
38
+ *
39
+ * A contract keeps its conditions/opportunities snapshots oldest first, each with an effective
40
+ * date. This returns the most recent snapshot effective on or before `asOfDate` — the terms a
41
+ * document issued on that date was billed under. Dates are compared by day, so the mix of
42
+ * date-only `validSince` and datetime `createdAt` strings behaves consistently. When `asOfDate`
43
+ * predates every snapshot, it falls back to the earliest one.
44
+ */
45
+ export const getDealRefAsOf = (
46
+ { conditions, opportunities }: Pick<LeasingContract, 'conditions' | 'opportunities'>,
47
+ asOfDate: string,
48
+ ): ConditionsRef | OpportunityRef => {
49
+ const refs: (ConditionsRef | OpportunityRef)[] = conditions ?? opportunities ?? [];
50
+ const inForce = refs.filter((ref) => refEffectiveFrom(ref).slice(0, 10) <= asOfDate.slice(0, 10));
51
+ return last(inForce) ?? first(refs) ?? last(refs)!;
52
+ };
53
+
33
54
  export const getItemClientPercentage = (value: LeasingItemsPaymentSplit): Decimal => {
34
55
  switch (value) {
35
56
  case LeasingItemsPaymentSplit.Company:
@@ -0,0 +1,48 @@
1
+ import { OpportunityStatus, OpportunityStatusOrder } from '../types/opportunities.js';
2
+ const compareOpportunityStatus = (input) => {
3
+ const { currentStatus, referenceStatus } = input;
4
+ const currentStatusIdx = OpportunityStatusOrder.indexOf(currentStatus);
5
+ const referenceStatusIdx = OpportunityStatusOrder.indexOf(referenceStatus);
6
+ return {
7
+ currentStatusIdx,
8
+ referenceStatusIdx,
9
+ };
10
+ };
11
+ export const getPreviousStatus = (currentStatus) => {
12
+ const currentIndex = OpportunityStatusOrder.indexOf(currentStatus);
13
+ if (currentIndex === 0) {
14
+ return;
15
+ }
16
+ return OpportunityStatusOrder[currentIndex - 1];
17
+ };
18
+ export const getNextStatus = (status) => {
19
+ const statusIndex = OpportunityStatusOrder.indexOf(status);
20
+ if (statusIndex >= OpportunityStatusOrder.length - 1) {
21
+ return;
22
+ }
23
+ return OpportunityStatusOrder[statusIndex + 1];
24
+ };
25
+ export const isSameOrAfterReferenceOpportunityStatus = (input) => {
26
+ const { currentStatusIdx, referenceStatusIdx } = compareOpportunityStatus(input);
27
+ return currentStatusIdx >= referenceStatusIdx;
28
+ };
29
+ export const isAfterReferenceOpportunityStatus = (input) => {
30
+ const { currentStatusIdx, referenceStatusIdx } = compareOpportunityStatus(input);
31
+ return currentStatusIdx > referenceStatusIdx;
32
+ };
33
+ export const isSameOrBeforeReferenceOpportunityStatus = (input) => {
34
+ const { currentStatusIdx, referenceStatusIdx } = compareOpportunityStatus(input);
35
+ return currentStatusIdx <= referenceStatusIdx;
36
+ };
37
+ export const isBeforeReferenceOpportunityStatus = (input) => {
38
+ const { currentStatusIdx, referenceStatusIdx } = compareOpportunityStatus(input);
39
+ return currentStatusIdx < referenceStatusIdx;
40
+ };
41
+ export const isOpportunityLost = (input) => input.lostAt != null;
42
+ export const getOpportunityReservedStatus = () => [
43
+ OpportunityStatus.REVIEW,
44
+ OpportunityStatus.PREPARATION,
45
+ OpportunityStatus.DELIVERY,
46
+ ];
47
+ export const isOpportunityReserved = (input) => getOpportunityReservedStatus().includes(input.status);
48
+ //# sourceMappingURL=opportunities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opportunities.js","sourceRoot":"","sources":["opportunities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAOnG,MAAM,wBAAwB,GAAG,CAAC,KAAmB,EAAE,EAAE;IACvD,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,GAAG,KAAK,CAAC;IAEjD,MAAM,gBAAgB,GAAG,sBAAsB,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IACvE,MAAM,kBAAkB,GAAG,sBAAsB,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAE3E,OAAO;QACL,gBAAgB;QAChB,kBAAkB;KACnB,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,aAAgC,EACD,EAAE;IACjC,MAAM,YAAY,GAAG,sBAAsB,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IACnE,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO;IACT,CAAC;IACD,OAAO,sBAAsB,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC;AAClD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,MAAyB,EAAiC,EAAE;IACxF,MAAM,WAAW,GAAG,sBAAsB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3D,IAAI,WAAW,IAAI,sBAAsB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrD,OAAO;IACT,CAAC;IACD,OAAO,sBAAsB,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,uCAAuC,GAAG,CAAC,KAAmB,EAAW,EAAE;IACtF,MAAM,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;IAEjF,OAAO,gBAAgB,IAAI,kBAAkB,CAAC;AAChD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC,KAAmB,EAAW,EAAE;IAChF,MAAM,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;IAEjF,OAAO,gBAAgB,GAAG,kBAAkB,CAAC;AAC/C,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,wCAAwC,GAAG,CAAC,KAAmB,EAAW,EAAE;IACvF,MAAM,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;IAEjF,OAAO,gBAAgB,IAAI,kBAAkB,CAAC;AAChD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,KAAmB,EAAW,EAAE;IACjF,MAAM,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;IAEjF,OAAO,gBAAgB,GAAG,kBAAkB,CAAC;AAC/C,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAkB,EAAW,EAAE,CAAC,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC;AAEvF,MAAM,CAAC,MAAM,4BAA4B,GAAG,GAAwB,EAAE,CAAC;IACrE,iBAAiB,CAAC,MAAM;IACxB,iBAAiB,CAAC,WAAW;IAC7B,iBAAiB,CAAC,QAAQ;CAC3B,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,KAAkB,EAAW,EAAE,CACnE,4BAA4B,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { ExpectedArrivalRow } from '../types/reports-arrivals.js';
2
+ import { TransportType } from '../types/transports.js';
3
+
4
+ /** Pick up and drop off come from the transport; direct-to-client deliveries stay separate. */
5
+ export const getArrivalDeliveryType = (
6
+ row: ExpectedArrivalRow,
7
+ ): 'pickUp' | 'dropOff' | 'direct' | undefined => {
8
+ if (row.readyToDeliver) {
9
+ return 'direct';
10
+ }
11
+ switch (row.transport?.type) {
12
+ case TransportType.PurchasePickUp:
13
+ return 'pickUp';
14
+ case TransportType.PurchaseDropOff:
15
+ return 'dropOff';
16
+ default:
17
+ return undefined;
18
+ }
19
+ };
@@ -1,10 +1,20 @@
1
1
  import { Opportunity } from '../types/opportunities.js';
2
2
  import { SearchTransport, Transport, TransportType } from '../types/transports.js';
3
- import { VehiclePurchase, VehiclePurchaseLogisticsStatus } from '../types/vehicles.js';
3
+ import { VehiclePurchase } from '../types/vehicles.js';
4
+ import { hasPurchaseArrived } from './vehicles.js';
5
+
6
+ /**
7
+ * Which side of the trade the transport serves. Both purchase types answer yes: a pick-up we drive
8
+ * and a drop-off the supplier drives differ only in who is behind the wheel, and every rule that
9
+ * asks this question — what it costs, whose money moved, which papers it needs — is the same for
10
+ * both.
11
+ */
12
+ export const isPurchaseTransport = (transport: Transport): boolean =>
13
+ transport.type !== TransportType.SaleDelivery;
4
14
 
5
15
  /**
6
16
  * A transport is finished when the journey it describes has demonstrably happened: the customer has
7
- * the vehicle for a sale delivery, the vehicle is on our park for a purchase pick-up. From then on
17
+ * the vehicle for a sale delivery, the vehicle is on our park for a purchase. From then on
8
18
  * the record is history and the server refuses edits to it.
9
19
  *
10
20
  * Not the same thing as the transport's own `doneAt`. Delivery can be declared on the opportunity
@@ -22,11 +32,7 @@ export const isTransportCompleted = (
22
32
  return context.opportunity?.deliveredAt != null;
23
33
  }
24
34
 
25
- const status = context.purchase?.logistics.status;
26
- return (
27
- status === VehiclePurchaseLogisticsStatus.Arrived ||
28
- status === VehiclePurchaseLogisticsStatus.CheckedIn
29
- );
35
+ return context.purchase != null && hasPurchaseArrived(context.purchase);
30
36
  };
31
37
 
32
38
  /** The same question asked of a search document, which already carries both sides. */
@@ -6,8 +6,18 @@ import {
6
6
  VehicleExternalInfo,
7
7
  VehiclePurchase,
8
8
  VehiclePurchaseDealStatus,
9
+ VehiclePurchaseLogisticsStatus,
9
10
  } from '../types/vehicles.js';
10
11
 
12
+ /** The logistics statuses at which the purchased vehicle is on our park. */
13
+ export const PURCHASE_ARRIVED_STATUSES: readonly VehiclePurchaseLogisticsStatus[] = [
14
+ VehiclePurchaseLogisticsStatus.Arrived,
15
+ VehiclePurchaseLogisticsStatus.CheckedIn,
16
+ ];
17
+
18
+ export const hasPurchaseArrived = (purchase: Pick<VehiclePurchase, 'logistics'>): boolean =>
19
+ PURCHASE_ARRIVED_STATUSES.includes(purchase.logistics.status);
20
+
11
21
  /**
12
22
  * The deal has not been committed: there is no purchase yet, or its deal is still in
13
23
  * `Marketing`. Copies are created in this state; it ends when the owner agrees to buy