@bisondesk/core-sdk 1.0.619 → 1.0.620

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.
@@ -0,0 +1,5 @@
1
+ import { ExchangeRate } from '../types/exchange-rates.js';
2
+ export declare const listExchangeRates: () => Promise<ExchangeRate[]>;
3
+ export declare const getExchangeRate: (fromCurrency: string, toCurrency: string) => Promise<ExchangeRate | undefined>;
4
+ export declare const getConversionRate: (fromCurrency: string, toCurrency: string) => Promise<number | undefined>;
5
+ //# sourceMappingURL=exchange-rates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exchange-rates.d.ts","sourceRoot":"/","sources":["apis/exchange-rates.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,eAAO,MAAM,iBAAiB,QAAa,OAAO,CAAC,YAAY,EAAE,CAehE,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,cAAc,MAAM,EACpB,YAAY,MAAM,KACjB,OAAO,CAAC,YAAY,GAAG,SAAS,CAqBlC,CAAC;AAQF,eAAO,MAAM,iBAAiB,GAC5B,cAAc,MAAM,EACpB,YAAY,MAAM,KACjB,OAAO,CAAC,MAAM,GAAG,SAAS,CAgB5B,CAAC"}
@@ -0,0 +1,49 @@
1
+ import { XError } from '@bisondesk/commons-sdk/errors';
2
+ import { getAdminAuth } from '@bisondesk/commons-sdk/fetch';
3
+ import fetch from 'node-fetch';
4
+ export const listExchangeRates = async () => {
5
+ const auth = await getAdminAuth();
6
+ const url = `${process.env.CORE_API_ORIGIN}/api/settings/exchange-rates`;
7
+ const response = await fetch(url, {
8
+ headers: {
9
+ Authorization: auth,
10
+ },
11
+ });
12
+ if (response.ok) {
13
+ return response.json();
14
+ }
15
+ const body = await response.text();
16
+ throw new XError(response.statusText, { url, body });
17
+ };
18
+ export const getExchangeRate = async (fromCurrency, toCurrency) => {
19
+ const auth = await getAdminAuth();
20
+ const url = `${process.env.CORE_API_ORIGIN}/api/settings/exchange-rates/${encodeURIComponent(fromCurrency)}/${encodeURIComponent(toCurrency)}`;
21
+ const response = await fetch(url, {
22
+ headers: {
23
+ Authorization: auth,
24
+ },
25
+ });
26
+ if (response.ok) {
27
+ return response.status === 200 ? response.json() : undefined;
28
+ }
29
+ if (response.status === 404) {
30
+ return undefined;
31
+ }
32
+ const body = await response.text();
33
+ throw new XError(response.statusText, { url, body, fromCurrency, toCurrency });
34
+ };
35
+ export const getConversionRate = async (fromCurrency, toCurrency) => {
36
+ if (fromCurrency === toCurrency) {
37
+ return 1;
38
+ }
39
+ const direct = await getExchangeRate(fromCurrency, toCurrency);
40
+ if (direct) {
41
+ return direct.rate;
42
+ }
43
+ const inverse = await getExchangeRate(toCurrency, fromCurrency);
44
+ if (inverse && inverse.rate > 0) {
45
+ return 1 / inverse.rate;
46
+ }
47
+ return undefined;
48
+ };
49
+ //# sourceMappingURL=exchange-rates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exchange-rates.js","sourceRoot":"/","sources":["apis/exchange-rates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,KAAmB,MAAM,YAAY,CAAC;AAG7C,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,IAA6B,EAAE;IACnE,MAAM,IAAI,GAAG,MAAM,YAAY,EAAE,CAAC;IAClC,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,8BAA8B,CAAC;IACzE,MAAM,QAAQ,GAAa,MAAM,KAAK,CAAC,GAAG,EAAE;QAC1C,OAAO,EAAE;YACP,aAAa,EAAE,IAAI;SACpB;KACF,CAAC,CAAC;IAEH,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;QAChB,OAAO,QAAQ,CAAC,IAAI,EAAS,CAAC;IAChC,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,MAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;AACvD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAClC,YAAoB,EACpB,UAAkB,EACiB,EAAE;IACrC,MAAM,IAAI,GAAG,MAAM,YAAY,EAAE,CAAC;IAClC,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,gCAAgC,kBAAkB,CAC1F,YAAY,CACb,IAAI,kBAAkB,CAAC,UAAU,CAAC,EAAE,CAAC;IACtC,MAAM,QAAQ,GAAa,MAAM,KAAK,CAAC,GAAG,EAAE;QAC1C,OAAO,EAAE;YACP,aAAa,EAAE,IAAI;SACpB;KACF,CAAC,CAAC;IAEH,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;QAChB,OAAO,QAAQ,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAE,QAAQ,CAAC,IAAI,EAAU,CAAC,CAAC,CAAC,SAAS,CAAC;IACxE,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,MAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,CAAC;AACjF,CAAC,CAAC;AAQF,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EACpC,YAAoB,EACpB,UAAkB,EACW,EAAE;IAC/B,IAAI,YAAY,KAAK,UAAU,EAAE,CAAC;QAChC,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IAC/D,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAChE,IAAI,OAAO,IAAI,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAC1B,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC","sourcesContent":["import { XError } from '@bisondesk/commons-sdk/errors';\nimport { getAdminAuth } from '@bisondesk/commons-sdk/fetch';\nimport fetch, { Response } from 'node-fetch';\nimport { ExchangeRate } from '../types/exchange-rates.js';\n\nexport const listExchangeRates = async (): Promise<ExchangeRate[]> => {\n const auth = await getAdminAuth();\n const url = `${process.env.CORE_API_ORIGIN}/api/settings/exchange-rates`;\n const response: Response = await fetch(url, {\n headers: {\n Authorization: auth,\n },\n });\n\n if (response.ok) {\n return response.json() as any;\n }\n\n const body = await response.text();\n throw new XError(response.statusText, { url, body });\n};\n\nexport const getExchangeRate = async (\n fromCurrency: string,\n toCurrency: string,\n): Promise<ExchangeRate | undefined> => {\n const auth = await getAdminAuth();\n const url = `${process.env.CORE_API_ORIGIN}/api/settings/exchange-rates/${encodeURIComponent(\n fromCurrency,\n )}/${encodeURIComponent(toCurrency)}`;\n const response: Response = await fetch(url, {\n headers: {\n Authorization: auth,\n },\n });\n\n if (response.ok) {\n return response.status === 200 ? (response.json() as any) : undefined;\n }\n\n if (response.status === 404) {\n return undefined;\n }\n\n const body = await response.text();\n throw new XError(response.statusText, { url, body, fromCurrency, toCurrency });\n};\n\n/**\n * Direction-agnostic conversion multiplier: how many units of `toCurrency`\n * equal 1 unit of `fromCurrency`. Tries a direct pair first, then falls back\n * to the inverse of the reverse pair (configured rows only need one direction\n * per pair). Returns `undefined` if neither is configured.\n */\nexport const getConversionRate = async (\n fromCurrency: string,\n toCurrency: string,\n): Promise<number | undefined> => {\n if (fromCurrency === toCurrency) {\n return 1;\n }\n\n const direct = await getExchangeRate(fromCurrency, toCurrency);\n if (direct) {\n return direct.rate;\n }\n\n const inverse = await getExchangeRate(toCurrency, fromCurrency);\n if (inverse && inverse.rate > 0) {\n return 1 / inverse.rate;\n }\n\n return undefined;\n};\n"]}
@@ -4,6 +4,7 @@ export declare enum VehicleTimelineEventType {
4
4
  Created = "CREATED",
5
5
  Purchased = "PURCHASED",
6
6
  Sold = "SOLD",
7
+ PurchaseEvaluationStarted = "PURCHASE_EVALUATION_STARTED",
7
8
  PurchaseAgreed = "PURCHASE_AGREED",
8
9
  PurchaseFirstPayment = "PURCHASE_FIRST_PAYMENT",
9
10
  PurchaseFullPayment = "PURCHASE_FULL_PAYMENT",
@@ -1 +1 @@
1
- {"version":3,"file":"vehicle-timeline.d.ts","sourceRoot":"/","sources":["types/vehicle-timeline.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vehicle-timeline.d.ts","sourceRoot":"/","sources":["types/vehicle-timeline.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@ export var VehicleTimelineEventType;
3
3
  VehicleTimelineEventType["Created"] = "CREATED";
4
4
  VehicleTimelineEventType["Purchased"] = "PURCHASED";
5
5
  VehicleTimelineEventType["Sold"] = "SOLD";
6
+ VehicleTimelineEventType["PurchaseEvaluationStarted"] = "PURCHASE_EVALUATION_STARTED";
6
7
  VehicleTimelineEventType["PurchaseAgreed"] = "PURCHASE_AGREED";
7
8
  VehicleTimelineEventType["PurchaseFirstPayment"] = "PURCHASE_FIRST_PAYMENT";
8
9
  VehicleTimelineEventType["PurchaseFullPayment"] = "PURCHASE_FULL_PAYMENT";
@@ -1 +1 @@
1
- {"version":3,"file":"vehicle-timeline.js","sourceRoot":"/","sources":["types/vehicle-timeline.ts"],"names":[],"mappings":"AAQA,MAAM,CAAN,IAAY,wBAyBX;AAzBD,WAAY,wBAAwB;IAClC,+CAAmB,CAAA;IACnB,mDAAuB,CAAA;IACvB,yCAAa,CAAA;IAEb,8DAAkC,CAAA;IAElC,2EAA+C,CAAA;IAE/C,yEAA6C,CAAA;IAE7C,gEAAoC,CAAA;IAEpC,qEAAyC,CAAA;IAEzC,mEAAuC,CAAA;IAEvC,iEAAqC,CAAA;IAErC,4DAAgC,CAAA;IAChC,8DAAkC,CAAA;IAElC,2EAA+C,CAAA;IAE/C,8DAAkC,CAAA;AACpC,CAAC,EAzBW,wBAAwB,KAAxB,wBAAwB,QAyBnC;AAED,MAAM,CAAN,IAAY,wBAIX;AAJD,WAAY,wBAAwB;IAClC,iDAAqB,CAAA;IACrB,iDAAqB,CAAA;IACrB,6CAAiB,CAAA;AACnB,CAAC,EAJW,wBAAwB,KAAxB,wBAAwB,QAInC;AAED,MAAM,CAAN,IAAY,yBAIX;AAJD,WAAY,yBAAyB;IACnC,6DAAgC,CAAA;IAChC,yDAA4B,CAAA;IAC5B,qDAAwB,CAAA;AAC1B,CAAC,EAJW,yBAAyB,KAAzB,yBAAyB,QAIpC","sourcesContent":["import { ReferenceData } from './utils.js';\nimport { VehicleRoles } from './vehicles.js';\n\n/**\n * The kind of milestone a timeline event represents. The frontend maps each\n * type to its own title, icon and tone (translated client-side); the backend\n * only emits the semantic type plus the data backing it.\n */\nexport enum VehicleTimelineEventType {\n Created = 'CREATED',\n Purchased = 'PURCHASED',\n Sold = 'SOLD',\n /** The purchase was agreed with the supplier (purchase deal progressed). */\n PurchaseAgreed = 'PURCHASE_AGREED',\n /** First payment sent to the supplier (purchase deal progressed). */\n PurchaseFirstPayment = 'PURCHASE_FIRST_PAYMENT',\n /** Full payment sent to the supplier (purchase deal progressed). */\n PurchaseFullPayment = 'PURCHASE_FULL_PAYMENT',\n /** The purchased vehicle arrived (purchase logistics). */\n PurchaseArrived = 'PURCHASE_ARRIVED',\n /** The purchased vehicle was checked in (purchase logistics). */\n PurchaseCheckedIn = 'PURCHASE_CHECKED_IN',\n /** First payment received from the customer (sale deal progressed). */\n SaleFirstPayment = 'SALE_FIRST_PAYMENT',\n /** Full payment received from the customer (sale deal progressed). */\n SaleFullPayment = 'SALE_FULL_PAYMENT',\n /** The sold vehicle was delivered to the customer (sale logistics). */\n SaleDelivered = 'SALE_DELIVERED',\n LeasingStarted = 'LEASING_STARTED',\n /** The leasing return process was started (contract entered leasing return). */\n LeasingReturnStarted = 'LEASING_RETURN_STARTED',\n /** The vehicle was retaken/recovered from the lessee. */\n VehicleRetaken = 'VEHICLE_RETAKEN',\n}\n\nexport enum VehicleTimelinePartyRole {\n Supplier = 'SUPPLIER',\n Customer = 'CUSTOMER',\n Debtor = 'DEBTOR',\n}\n\nexport enum VehicleTimelineAmountType {\n PurchasePrice = 'PURCHASE_PRICE',\n AskingPrice = 'ASKING_PRICE',\n SalePrice = 'SALE_PRICE',\n}\n\nexport type VehicleTimelineParty = {\n role: VehicleTimelinePartyRole;\n organizationId?: string;\n /** Pre-formatted display name, e.g. \"807576 · GABIANCA EXPRES SRL\". */\n name?: string;\n /** ISO country code used to render the small flag badge. */\n countryCode?: string;\n};\n\nexport type VehicleTimelineAmount = {\n type: VehicleTimelineAmountType;\n value: string;\n currency?: string;\n};\n\n/**\n * Leasing-contract details for a LEASING_STARTED event. The monthly/residual\n * figures come from the contract's current conditions and are absent for\n * contract sources that don't carry inline conditions (e.g. Bisondesk-origin).\n */\nexport type VehicleTimelineLeasing = {\n contractId: string;\n vehicleStockNumber?: string;\n startDate: string;\n endDate?: string;\n /** Headline monthly amount (total, excl. VAT). */\n monthly?: string;\n /** Leasing portion of the monthly amount. */\n monthlyLeasing?: string;\n /** Insurance + taxes + other portion of the monthly amount. */\n monthlyOther?: string;\n residual?: string;\n deposit?: string;\n durationInMonths?: number;\n saleAmount?: string;\n currency?: string;\n};\n\nexport type VehicleTimelineDocument<TDoc = unknown> = {\n doc: TDoc;\n paidAt?: string;\n};\n\nexport type VehicleTimelineRetake = {\n contractId: string;\n contractNumber?: string;\n /** Set on a retake when the vehicle was recovered as a total loss. */\n totalLoss?: boolean;\n};\n\nexport type VehicleTimelineEvent<TDoc = unknown> = {\n id: string;\n type: VehicleTimelineEventType;\n date?: string;\n party?: VehicleTimelineParty;\n /** User id of the person who drove the milestone (bought by / sold by / account manager). */\n personUserId?: string;\n assistedByUserId?: string;\n opportunityId?: string;\n /** Raw deal status of the underlying purchase/sale, rendered as a badge. */\n dealStatus?: string;\n /** Raw logistics status of the underlying purchase/sale, rendered as a badge. */\n logisticStatus?: string;\n amount?: VehicleTimelineAmount;\n leasing?: VehicleTimelineLeasing;\n /** Present on LEASING_RETURNED / VEHICLE_RETAKEN milestones. */\n retake?: VehicleTimelineRetake;\n /** Finance documents that belong to this milestone (nested in its card). */\n documents: VehicleTimelineDocument<TDoc>[];\n};\n\n/**\n * Why a non-original stock record exists in the chain. Mirrors the description\n * stored on the clone's `internal.relatedVehicles` entry pointing back to its\n * predecessor (e.g. \"Sale & lease-back …\", \"Retake …\").\n */\nexport type VehicleTimelineRelation = {\n description: string;\n fromVehicleId?: string;\n fromStockNumber?: string;\n};\n\nexport type VehicleTimelineVehicle = {\n id: string;\n stockNumber: string;\n administrativeNumber?: string;\n title: string;\n branch: string;\n role: VehicleRoles;\n deleted: boolean;\n createdAt: string;\n imageUrl?: string;\n /** Pre-built spec fragments, joined client-side with \" · \". */\n specs: string[];\n};\n\n/**\n * One stock record in the related-vehicles chain together with everything that\n * happened to it. Groups are ordered original-first; every group after the\n * first carries a `relation` describing the clone that created it.\n */\nexport type VehicleTimelineGroup<TDoc = unknown> = {\n vehicle: VehicleTimelineVehicle;\n /** True for the vehicle whose id was passed to the endpoint. */\n isRequested: boolean;\n relation?: VehicleTimelineRelation;\n events: VehicleTimelineEvent<TDoc>[];\n};\n\nexport type VehicleTimelineSummary = {\n stockRecords: number;\n saleCycles: number;\n daysHeld?: number;\n};\n\n/**\n * `TDoc` is generic because `core-sdk` cannot depend on `documents-sdk`\n * (it would be circular). The backend resolves it to `FinanceDocument`.\n */\nexport type VehicleTimeline<TDoc = unknown> = {\n requestedVehicleId: string;\n groups: VehicleTimelineGroup<TDoc>[];\n summary: VehicleTimelineSummary;\n meta?: ReferenceData;\n};\n"]}
1
+ {"version":3,"file":"vehicle-timeline.js","sourceRoot":"/","sources":["types/vehicle-timeline.ts"],"names":[],"mappings":"AAQA,MAAM,CAAN,IAAY,wBA2BX;AA3BD,WAAY,wBAAwB;IAClC,+CAAmB,CAAA;IACnB,mDAAuB,CAAA;IACvB,yCAAa,CAAA;IAEb,qFAAyD,CAAA;IAEzD,8DAAkC,CAAA;IAElC,2EAA+C,CAAA;IAE/C,yEAA6C,CAAA;IAE7C,gEAAoC,CAAA;IAEpC,qEAAyC,CAAA;IAEzC,mEAAuC,CAAA;IAEvC,iEAAqC,CAAA;IAErC,4DAAgC,CAAA;IAChC,8DAAkC,CAAA;IAElC,2EAA+C,CAAA;IAE/C,8DAAkC,CAAA;AACpC,CAAC,EA3BW,wBAAwB,KAAxB,wBAAwB,QA2BnC;AAED,MAAM,CAAN,IAAY,wBAIX;AAJD,WAAY,wBAAwB;IAClC,iDAAqB,CAAA;IACrB,iDAAqB,CAAA;IACrB,6CAAiB,CAAA;AACnB,CAAC,EAJW,wBAAwB,KAAxB,wBAAwB,QAInC;AAED,MAAM,CAAN,IAAY,yBAIX;AAJD,WAAY,yBAAyB;IACnC,6DAAgC,CAAA;IAChC,yDAA4B,CAAA;IAC5B,qDAAwB,CAAA;AAC1B,CAAC,EAJW,yBAAyB,KAAzB,yBAAyB,QAIpC","sourcesContent":["import { ReferenceData } from './utils.js';\nimport { VehicleRoles } from './vehicles.js';\n\n/**\n * The kind of milestone a timeline event represents. The frontend maps each\n * type to its own title, icon and tone (translated client-side); the backend\n * only emits the semantic type plus the data backing it.\n */\nexport enum VehicleTimelineEventType {\n Created = 'CREATED',\n Purchased = 'PURCHASED',\n Sold = 'SOLD',\n /** The vehicle entered purchase evaluation / consignation (purchase deal progressed). */\n PurchaseEvaluationStarted = 'PURCHASE_EVALUATION_STARTED',\n /** The purchase was agreed with the supplier (purchase deal progressed). */\n PurchaseAgreed = 'PURCHASE_AGREED',\n /** First payment sent to the supplier (purchase deal progressed). */\n PurchaseFirstPayment = 'PURCHASE_FIRST_PAYMENT',\n /** Full payment sent to the supplier (purchase deal progressed). */\n PurchaseFullPayment = 'PURCHASE_FULL_PAYMENT',\n /** The purchased vehicle arrived (purchase logistics). */\n PurchaseArrived = 'PURCHASE_ARRIVED',\n /** The purchased vehicle was checked in (purchase logistics). */\n PurchaseCheckedIn = 'PURCHASE_CHECKED_IN',\n /** First payment received from the customer (sale deal progressed). */\n SaleFirstPayment = 'SALE_FIRST_PAYMENT',\n /** Full payment received from the customer (sale deal progressed). */\n SaleFullPayment = 'SALE_FULL_PAYMENT',\n /** The sold vehicle was delivered to the customer (sale logistics). */\n SaleDelivered = 'SALE_DELIVERED',\n LeasingStarted = 'LEASING_STARTED',\n /** The leasing return process was started (contract entered leasing return). */\n LeasingReturnStarted = 'LEASING_RETURN_STARTED',\n /** The vehicle was retaken/recovered from the lessee. */\n VehicleRetaken = 'VEHICLE_RETAKEN',\n}\n\nexport enum VehicleTimelinePartyRole {\n Supplier = 'SUPPLIER',\n Customer = 'CUSTOMER',\n Debtor = 'DEBTOR',\n}\n\nexport enum VehicleTimelineAmountType {\n PurchasePrice = 'PURCHASE_PRICE',\n AskingPrice = 'ASKING_PRICE',\n SalePrice = 'SALE_PRICE',\n}\n\nexport type VehicleTimelineParty = {\n role: VehicleTimelinePartyRole;\n organizationId?: string;\n /** Pre-formatted display name, e.g. \"807576 · GABIANCA EXPRES SRL\". */\n name?: string;\n /** ISO country code used to render the small flag badge. */\n countryCode?: string;\n};\n\nexport type VehicleTimelineAmount = {\n type: VehicleTimelineAmountType;\n value: string;\n currency?: string;\n};\n\n/**\n * Leasing-contract details for a LEASING_STARTED event. The monthly/residual\n * figures come from the contract's current conditions and are absent for\n * contract sources that don't carry inline conditions (e.g. Bisondesk-origin).\n */\nexport type VehicleTimelineLeasing = {\n contractId: string;\n vehicleStockNumber?: string;\n startDate: string;\n endDate?: string;\n /** Headline monthly amount (total, excl. VAT). */\n monthly?: string;\n /** Leasing portion of the monthly amount. */\n monthlyLeasing?: string;\n /** Insurance + taxes + other portion of the monthly amount. */\n monthlyOther?: string;\n residual?: string;\n deposit?: string;\n durationInMonths?: number;\n saleAmount?: string;\n currency?: string;\n};\n\nexport type VehicleTimelineDocument<TDoc = unknown> = {\n doc: TDoc;\n paidAt?: string;\n};\n\nexport type VehicleTimelineRetake = {\n contractId: string;\n contractNumber?: string;\n /** Set on a retake when the vehicle was recovered as a total loss. */\n totalLoss?: boolean;\n};\n\nexport type VehicleTimelineEvent<TDoc = unknown> = {\n id: string;\n type: VehicleTimelineEventType;\n date?: string;\n party?: VehicleTimelineParty;\n /** User id of the person who drove the milestone (bought by / sold by / account manager). */\n personUserId?: string;\n assistedByUserId?: string;\n opportunityId?: string;\n /** Raw deal status of the underlying purchase/sale, rendered as a badge. */\n dealStatus?: string;\n /** Raw logistics status of the underlying purchase/sale, rendered as a badge. */\n logisticStatus?: string;\n amount?: VehicleTimelineAmount;\n leasing?: VehicleTimelineLeasing;\n /** Present on LEASING_RETURNED / VEHICLE_RETAKEN milestones. */\n retake?: VehicleTimelineRetake;\n /** Finance documents that belong to this milestone (nested in its card). */\n documents: VehicleTimelineDocument<TDoc>[];\n};\n\n/**\n * Why a non-original stock record exists in the chain. Mirrors the description\n * stored on the clone's `internal.relatedVehicles` entry pointing back to its\n * predecessor (e.g. \"Sale & lease-back …\", \"Retake …\").\n */\nexport type VehicleTimelineRelation = {\n description: string;\n fromVehicleId?: string;\n fromStockNumber?: string;\n};\n\nexport type VehicleTimelineVehicle = {\n id: string;\n stockNumber: string;\n administrativeNumber?: string;\n title: string;\n branch: string;\n role: VehicleRoles;\n deleted: boolean;\n createdAt: string;\n imageUrl?: string;\n /** Pre-built spec fragments, joined client-side with \" · \". */\n specs: string[];\n};\n\n/**\n * One stock record in the related-vehicles chain together with everything that\n * happened to it. Groups are ordered original-first; every group after the\n * first carries a `relation` describing the clone that created it.\n */\nexport type VehicleTimelineGroup<TDoc = unknown> = {\n vehicle: VehicleTimelineVehicle;\n /** True for the vehicle whose id was passed to the endpoint. */\n isRequested: boolean;\n relation?: VehicleTimelineRelation;\n events: VehicleTimelineEvent<TDoc>[];\n};\n\nexport type VehicleTimelineSummary = {\n stockRecords: number;\n saleCycles: number;\n daysHeld?: number;\n};\n\n/**\n * `TDoc` is generic because `core-sdk` cannot depend on `documents-sdk`\n * (it would be circular). The backend resolves it to `FinanceDocument`.\n */\nexport type VehicleTimeline<TDoc = unknown> = {\n requestedVehicleId: string;\n groups: VehicleTimelineGroup<TDoc>[];\n summary: VehicleTimelineSummary;\n meta?: ReferenceData;\n};\n"]}
@@ -1,4 +1,7 @@
1
- import { VehicleExternalInfo } from '../types/vehicles.js';
1
+ import { Vehicle, VehicleExternalInfo, VehiclePurchase } from '../types/vehicles.js';
2
+ export declare const isDealInMarketing: (purchase: VehiclePurchase | undefined) => boolean;
3
+ export declare const isSourceMastered: (vehicle: Pick<Vehicle, "original">, purchase: VehiclePurchase | undefined) => boolean;
4
+ export declare const isUnavailableFromSource: (vehicle: Pick<Vehicle, "original">, purchase: VehiclePurchase | undefined) => boolean;
2
5
  export declare const extractCustomFeatures: (vehicle: VehicleExternalInfo) => string[];
3
6
  export declare const getInternalTitle: ({ make, category, modelName, bodywork, modelTypeName, }: {
4
7
  category: string;
@@ -1 +1 @@
1
- {"version":3,"file":"vehicles.d.ts","sourceRoot":"/","sources":["utils/vehicles.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE3D,eAAO,MAAM,qBAAqB,GAAI,SAAS,mBAAmB,KAAG,MAAM,EAiD1E,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,yDAM9B;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,KAAG,MAcH,CAAC;AAKF,eAAO,MAAM,sBAAsB,GAAI,KAAK,MAAM,KAAG,MAiBpD,CAAC;AAGF,eAAO,MAAM,sBAAsB,GAAI,SAAS,MAAM,KAAG,MAWxD,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,aAAa,MAAM,KAAG,MAa/D,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,UAAU,mBAAmB,EAC7B,mDAIG;IACD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,WAyBF,CAAC"}
1
+ {"version":3,"file":"vehicles.d.ts","sourceRoot":"/","sources":["utils/vehicles.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,OAAO,EACP,mBAAmB,EACnB,eAAe,EAEhB,MAAM,sBAAsB,CAAC;AAO9B,eAAO,MAAM,iBAAiB,GAAI,UAAU,eAAe,GAAG,SAAS,KAAG,OACQ,CAAC;AASnF,eAAO,MAAM,gBAAgB,GAC3B,SAAS,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,EAClC,UAAU,eAAe,GAAG,SAAS,KACpC,OAAkE,CAAC;AAQtE,eAAO,MAAM,uBAAuB,GAClC,SAAS,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,EAClC,UAAU,eAAe,GAAG,SAAS,KACpC,OAC+F,CAAC;AAEnG,eAAO,MAAM,qBAAqB,GAAI,SAAS,mBAAmB,KAAG,MAAM,EAiD1E,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,yDAM9B;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,KAAG,MAcH,CAAC;AAKF,eAAO,MAAM,sBAAsB,GAAI,KAAK,MAAM,KAAG,MAiBpD,CAAC;AAGF,eAAO,MAAM,sBAAsB,GAAI,SAAS,MAAM,KAAG,MAWxD,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,aAAa,MAAM,KAAG,MAa/D,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,UAAU,mBAAmB,EAC7B,mDAIG;IACD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,WAyBF,CAAC"}
@@ -1,6 +1,10 @@
1
1
  import { XError } from '@bisondesk/commons-sdk/errors';
2
2
  import { joinWithSeparator } from '@bisondesk/commons-sdk/formatting';
3
3
  import { Categories } from '../constants.js';
4
+ import { VehiclePurchaseDealStatus, } from '../types/vehicles.js';
5
+ export const isDealInMarketing = (purchase) => purchase == null || purchase.deal.status === VehiclePurchaseDealStatus.Marketing;
6
+ export const isSourceMastered = (vehicle, purchase) => vehicle.original != null && isDealInMarketing(purchase);
7
+ export const isUnavailableFromSource = (vehicle, purchase) => isSourceMastered(vehicle, purchase) && (vehicle.original?.salesConditions?.unavailable ?? false);
4
8
  export const extractCustomFeatures = (vehicle) => {
5
9
  const features = [
6
10
  {
@@ -1 +1 @@
1
- {"version":3,"file":"vehicles.js","sourceRoot":"/","sources":["utils/vehicles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,OAA4B,EAAY,EAAE;IAC9E,MAAM,QAAQ,GAGR;QACJ;YACE,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,KAAK,EAAE,OAAO;YAC7D,eAAe,EAAE,OAAO;SACzB;QACD;YACE,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,QAAQ,EAAE,OAAO;YAChE,eAAe,EAAE,UAAU;SAC5B;QACD,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE;QAC1E;YACE,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,gBAAgB;YAC3D,eAAe,EAAE,kBAAkB;SACpC;QACD;YACE,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,kBAAkB;YAC7D,eAAe,EAAE,oBAAoB;SACtC;QACD;YACE,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO;YAClD,eAAe,EAAE,SAAS;SAC3B;QACD;YACE,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI;YAC/C,eAAe,EAAE,MAAM;SACxB;QACD;YACE,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,WAAW;YACtD,eAAe,EAAE,aAAa;SAC/B;QACD;YACE,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI;YAC/C,eAAe,EAAE,MAAM;SACxB;QACD;YACE,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CACpB,OAAO,CAAC,eAAe,EAAE,oBAAoB,EAAE,SAAS;gBACxD,OAAO,CAAC,eAAe,EAAE,oBAAoB,EAAE,QAAQ;YACzD,eAAe,EAAE,UAAU;SAC5B;KACF,CAAC;IAEF,OAAO,QAAQ;SACZ,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;SAChD,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;AAC/C,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,EAC/B,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,aAAa,GAOd,EAAU,EAAE;IACX,IAAI,QAAQ,KAAK,UAAU,CAAC,OAAO,IAAI,QAAQ,KAAK,UAAU,CAAC,WAAW,EAAE,CAAC;QAC3E,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,CAAC;aAC9C,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;aAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aACpB,IAAI,CAAC,GAAG,CAAC;aACT,IAAI,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,aAAa,CAAC;SACpC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;SAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,IAAI,CAAC,GAAG,CAAC;SACT,IAAI,EAAE,CAAC;AACZ,CAAC,CAAC;AAEF,MAAM,QAAQ,GAAG,4BAA4B,CAAC;AAG9C,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,GAAW,EAAU,EAAE;IAC5D,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC;IAEtC,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;QACZ,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,SAAS,GAAG,GAAG,GAAG,aAAa,CAAC;IACpC,IAAI,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,aAAa,CAAC,CAAC;IAG/C,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;QACpB,SAAS,GAAG,aAAa,CAAC;QAC1B,QAAQ,IAAI,CAAC,CAAC;IAChB,CAAC;IAED,OAAO,sBAAsB,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;AAC3E,CAAC,CAAC;AAGF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,OAAe,EAAU,EAAE;IAChE,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC;IAE7B,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACnD,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACrC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,WAAmB,EAAU,EAAE;IACvE,MAAM,cAAc,GAAG,6BAA6B,CAAC;IACrD,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAChD,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;QAClB,MAAM,IAAI,MAAM,CAAC,oCAAoC,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,MAAM,eAAe,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACjC,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAChC,MAAM,aAAa,GAAG,sBAAsB,CAAC,cAAc,CAAC,CAAC;IAC7D,MAAM,iBAAiB,GAAG,aAAa,GAAG,CAAC,CAAC;IAC5C,MAAM,kBAAkB,GAAG,sBAAsB,CAAC,iBAAiB,CAAC,CAAC;IACrE,OAAO,GAAG,eAAe,GAAG,kBAAkB,EAAE,CAAC;AACnD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,QAA6B,EAC7B,EACE,eAAe,GAAG,KAAK,EACvB,qBAAqB,GAAG,KAAK,EAC7B,IAAI,GAKL,EACD,EAAE;IACF,MAAM,UAAU,GAAG;QACjB,QAAQ,CAAC,cAAc,EAAE,UAAU,EAAE,QAAQ;QAC7C,QAAQ,CAAC,cAAc,EAAE,UAAU,EAAE,UAAU;KAChD;SACE,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;SAC1B,IAAI,CAAC,EAAE,CAAC,CAAC;IACZ,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;QAC1C,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,WAAW;KAClB,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,iBAAiB,CAAC;QAC7B,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;QACjE,QAAQ,CAAC,OAAO,EAAE,eAAe;QACjC,QAAQ,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,IAAI,IAAI;YACtC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;YACpD,CAAC,CAAC,SAAS;QACb,QAAQ,CAAC,UAAU,EAAE,SAAS,EAAE,QAAQ,IAAI,QAAQ,CAAC,UAAU,EAAE,SAAS,EAAE,KAAK;QACjF,UAAU;QACV,qBAAqB,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,SAAS;KAC9E,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC;AACd,CAAC,CAAC","sourcesContent":["import { XError } from '@bisondesk/commons-sdk/errors';\nimport { joinWithSeparator } from '@bisondesk/commons-sdk/formatting';\nimport { Categories } from '../constants.js';\nimport { VehicleExternalInfo } from '../types/vehicles.js';\n\nexport const extractCustomFeatures = (vehicle: VehicleExternalInfo): string[] => {\n const features: {\n getValue: (vehicle: VehicleExternalInfo) => any;\n picklistValueId: string;\n }[] = [\n {\n getValue: (vehicle) => vehicle.superstructure?.crane?.present,\n picklistValueId: 'crane',\n },\n {\n getValue: (vehicle) => vehicle.superstructure?.tailgate?.present,\n picklistValueId: 'tailgate',\n },\n { getValue: (vehicle) => vehicle.accessories.adr, picklistValueId: 'adr' },\n {\n getValue: (vehicle) => vehicle.accessories.retarderIntarder,\n picklistValueId: 'retarderIntarder',\n },\n {\n getValue: (vehicle) => vehicle.accessories.hydraulicTipperKit,\n picklistValueId: 'hydraulicTipperKit',\n },\n {\n getValue: (vehicle) => vehicle.accessories.lowDeck,\n picklistValueId: 'lowDeck',\n },\n {\n getValue: (vehicle) => vehicle.accessories.coil,\n picklistValueId: 'coil',\n },\n {\n getValue: (vehicle) => vehicle.accessories.doubleStock,\n picklistValueId: 'doubleStock',\n },\n {\n getValue: (vehicle) => vehicle.accessories.mega,\n picklistValueId: 'mega',\n },\n {\n getValue: (vehicle) =>\n vehicle.salesConditions?.manufacturerWarranty?.available ||\n vehicle.salesConditions?.manufacturerWarranty?.included,\n picklistValueId: 'warranty',\n },\n ];\n\n return features\n .filter((feature) => !!feature.getValue(vehicle))\n .map((feature) => feature.picklistValueId);\n};\n\nexport const getInternalTitle = ({\n make,\n category,\n modelName,\n bodywork,\n modelTypeName,\n}: {\n category: string;\n make?: string;\n modelName?: string;\n modelTypeName?: string;\n bodywork?: string;\n}): string => {\n if (category === Categories.Trailer || category === Categories.SemiTrailer) {\n return [make, modelName, modelTypeName, bodywork]\n .filter((v): v is string => !!v)\n .map((v) => v.trim())\n .join(' ')\n .trim();\n }\n\n return [make, modelName, modelTypeName]\n .filter((v): v is string => !!v)\n .map((v) => v.trim())\n .join(' ')\n .trim();\n};\n\nconst ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';\n\n// example: 1 -> A, 2 -> B, 26 -> Z, 27 -> AA, 28 -> AB, 52 -> AZ, 53 -> BA, 54 -> BB, 702 -> ZZ\nexport const convertNumberToLetters = (num: number): string => {\n const lettersLength = ALPHABET.length;\n\n if (num < 1) {\n return '';\n }\n\n let remainder = num % lettersLength;\n let quotient = Math.floor(num / lettersLength);\n\n // If remainder is 0, it means we should map it to 'Z' and reduce the quotient by 1\n if (remainder === 0) {\n remainder = lettersLength;\n quotient -= 1;\n }\n\n return convertNumberToLetters(quotient) + ALPHABET.charAt(remainder - 1);\n};\n\n// example: A -> 1, B -> 2, Z -> 26, AA -> 27, AB -> 28, AZ -> 52, BA -> 53, BB -> 54, ZZ -> 702\nexport const convertLettersToNumber = (letters: string): number => {\n const base = ALPHABET.length;\n\n let result = 0;\n\n for (let i = 0; i < letters.length; i++) {\n const charValue = ALPHABET.indexOf(letters[i]) + 1;\n result = result * base + charValue;\n }\n\n return result;\n};\n\nexport const getNextRelatedStockNumber = (stockNumber: string): string => {\n const counterPattern = /^([A-Z]+\\d{5})([A-Z]{0,2})$/;\n const match = stockNumber.match(counterPattern);\n if (match == null) {\n throw new XError('core-sdk.vehicles.bad-stock-number', { stockNumber });\n }\n\n const baseStockNumber = match[1];\n const counterLetters = match[2];\n const counterNumber = convertLettersToNumber(counterLetters);\n const nextCounterNumber = counterNumber + 1;\n const nextCounterLetters = convertNumberToLetters(nextCounterNumber);\n return `${baseStockNumber}${nextCounterLetters}`;\n};\n\nexport const getVehicleDescription = (\n external: VehicleExternalInfo,\n {\n showStockNumber = false,\n showAxleConfiguration = false,\n lang,\n }: {\n showStockNumber?: boolean;\n showAxleConfiguration?: boolean;\n lang?: string;\n },\n) => {\n const dimensions = [\n external.superstructure?.dimensions?.extended,\n external.superstructure?.dimensions?.heightened,\n ]\n .filter((value) => !!value)\n .join('');\n const kmFormatter = Intl.NumberFormat(lang, {\n style: 'unit',\n unit: 'kilometer',\n });\n\n const text = joinWithSeparator([\n showStockNumber ? external.identification.stockNumber : undefined,\n external.history?.advertisingYear,\n external.condition?.odometer?.km != null\n ? kmFormatter.format(external.condition.odometer.km)\n : undefined,\n external.powertrain?.emissions?.subclass ?? external.powertrain?.emissions?.class,\n dimensions,\n showAxleConfiguration ? external.powertrain?.axles?.configuration : undefined,\n ]);\n\n return text;\n};\n"]}
1
+ {"version":3,"file":"vehicles.js","sourceRoot":"/","sources":["utils/vehicles.ts"],"names":[],"mappings":"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","sourcesContent":["import { XError } from '@bisondesk/commons-sdk/errors';\nimport { joinWithSeparator } from '@bisondesk/commons-sdk/formatting';\nimport { Categories } from '../constants.js';\nimport {\n Vehicle,\n VehicleExternalInfo,\n VehiclePurchase,\n VehiclePurchaseDealStatus,\n} from '../types/vehicles.js';\n\n/**\n * The deal has not been committed: there is no purchase yet, or its deal is still in\n * `Marketing`. Copies are created in this state; it ends when the owner agrees to buy\n * (e.g. an ICO invoice moves the deal to PurchaseAgreed).\n */\nexport const isDealInMarketing = (purchase: VehiclePurchase | undefined): boolean =>\n purchase == null || purchase.deal.status === VehiclePurchaseDealStatus.Marketing;\n\n/**\n * A cross-tenant copy whose source still masters it: it has an `original` link and its deal is\n * still in Marketing ({@link isDealInMarketing}). While this holds, the next sync overwrites\n * `external` (specs, pictures, videos) and `salesConditions` from the source; once the deal\n * progresses, the vehicle is the owner's own stock and the sync hands off. Native vehicles are\n * never source-mastered.\n */\nexport const isSourceMastered = (\n vehicle: Pick<Vehicle, 'original'>,\n purchase: VehiclePurchase | undefined,\n): boolean => vehicle.original != null && isDealInMarketing(purchase);\n\n/**\n * A cross-tenant copy whose source is not sellable, as stamped on the last sync hop. Only\n * meaningful while the source still masters the copy ({@link isSourceMastered}): past Marketing\n * the vehicle is the owner's own stock, and a still-present flag is merely stale — the sync\n * clears it on the next source event — so it must be ignored.\n */\nexport const isUnavailableFromSource = (\n vehicle: Pick<Vehicle, 'original'>,\n purchase: VehiclePurchase | undefined,\n): boolean =>\n isSourceMastered(vehicle, purchase) && (vehicle.original?.salesConditions?.unavailable ?? false);\n\nexport const extractCustomFeatures = (vehicle: VehicleExternalInfo): string[] => {\n const features: {\n getValue: (vehicle: VehicleExternalInfo) => any;\n picklistValueId: string;\n }[] = [\n {\n getValue: (vehicle) => vehicle.superstructure?.crane?.present,\n picklistValueId: 'crane',\n },\n {\n getValue: (vehicle) => vehicle.superstructure?.tailgate?.present,\n picklistValueId: 'tailgate',\n },\n { getValue: (vehicle) => vehicle.accessories.adr, picklistValueId: 'adr' },\n {\n getValue: (vehicle) => vehicle.accessories.retarderIntarder,\n picklistValueId: 'retarderIntarder',\n },\n {\n getValue: (vehicle) => vehicle.accessories.hydraulicTipperKit,\n picklistValueId: 'hydraulicTipperKit',\n },\n {\n getValue: (vehicle) => vehicle.accessories.lowDeck,\n picklistValueId: 'lowDeck',\n },\n {\n getValue: (vehicle) => vehicle.accessories.coil,\n picklistValueId: 'coil',\n },\n {\n getValue: (vehicle) => vehicle.accessories.doubleStock,\n picklistValueId: 'doubleStock',\n },\n {\n getValue: (vehicle) => vehicle.accessories.mega,\n picklistValueId: 'mega',\n },\n {\n getValue: (vehicle) =>\n vehicle.salesConditions?.manufacturerWarranty?.available ||\n vehicle.salesConditions?.manufacturerWarranty?.included,\n picklistValueId: 'warranty',\n },\n ];\n\n return features\n .filter((feature) => !!feature.getValue(vehicle))\n .map((feature) => feature.picklistValueId);\n};\n\nexport const getInternalTitle = ({\n make,\n category,\n modelName,\n bodywork,\n modelTypeName,\n}: {\n category: string;\n make?: string;\n modelName?: string;\n modelTypeName?: string;\n bodywork?: string;\n}): string => {\n if (category === Categories.Trailer || category === Categories.SemiTrailer) {\n return [make, modelName, modelTypeName, bodywork]\n .filter((v): v is string => !!v)\n .map((v) => v.trim())\n .join(' ')\n .trim();\n }\n\n return [make, modelName, modelTypeName]\n .filter((v): v is string => !!v)\n .map((v) => v.trim())\n .join(' ')\n .trim();\n};\n\nconst ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';\n\n// example: 1 -> A, 2 -> B, 26 -> Z, 27 -> AA, 28 -> AB, 52 -> AZ, 53 -> BA, 54 -> BB, 702 -> ZZ\nexport const convertNumberToLetters = (num: number): string => {\n const lettersLength = ALPHABET.length;\n\n if (num < 1) {\n return '';\n }\n\n let remainder = num % lettersLength;\n let quotient = Math.floor(num / lettersLength);\n\n // If remainder is 0, it means we should map it to 'Z' and reduce the quotient by 1\n if (remainder === 0) {\n remainder = lettersLength;\n quotient -= 1;\n }\n\n return convertNumberToLetters(quotient) + ALPHABET.charAt(remainder - 1);\n};\n\n// example: A -> 1, B -> 2, Z -> 26, AA -> 27, AB -> 28, AZ -> 52, BA -> 53, BB -> 54, ZZ -> 702\nexport const convertLettersToNumber = (letters: string): number => {\n const base = ALPHABET.length;\n\n let result = 0;\n\n for (let i = 0; i < letters.length; i++) {\n const charValue = ALPHABET.indexOf(letters[i]) + 1;\n result = result * base + charValue;\n }\n\n return result;\n};\n\nexport const getNextRelatedStockNumber = (stockNumber: string): string => {\n const counterPattern = /^([A-Z]+\\d{5})([A-Z]{0,2})$/;\n const match = stockNumber.match(counterPattern);\n if (match == null) {\n throw new XError('core-sdk.vehicles.bad-stock-number', { stockNumber });\n }\n\n const baseStockNumber = match[1];\n const counterLetters = match[2];\n const counterNumber = convertLettersToNumber(counterLetters);\n const nextCounterNumber = counterNumber + 1;\n const nextCounterLetters = convertNumberToLetters(nextCounterNumber);\n return `${baseStockNumber}${nextCounterLetters}`;\n};\n\nexport const getVehicleDescription = (\n external: VehicleExternalInfo,\n {\n showStockNumber = false,\n showAxleConfiguration = false,\n lang,\n }: {\n showStockNumber?: boolean;\n showAxleConfiguration?: boolean;\n lang?: string;\n },\n) => {\n const dimensions = [\n external.superstructure?.dimensions?.extended,\n external.superstructure?.dimensions?.heightened,\n ]\n .filter((value) => !!value)\n .join('');\n const kmFormatter = Intl.NumberFormat(lang, {\n style: 'unit',\n unit: 'kilometer',\n });\n\n const text = joinWithSeparator([\n showStockNumber ? external.identification.stockNumber : undefined,\n external.history?.advertisingYear,\n external.condition?.odometer?.km != null\n ? kmFormatter.format(external.condition.odometer.km)\n : undefined,\n external.powertrain?.emissions?.subclass ?? external.powertrain?.emissions?.class,\n dimensions,\n showAxleConfiguration ? external.powertrain?.axles?.configuration : undefined,\n ]);\n\n return text;\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bisondesk/core-sdk",
3
- "version": "1.0.619",
3
+ "version": "1.0.620",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "author": "TheTruckCompany",
@@ -0,0 +1,74 @@
1
+ import { XError } from '@bisondesk/commons-sdk/errors';
2
+ import { getAdminAuth } from '@bisondesk/commons-sdk/fetch';
3
+ import fetch, { Response } from 'node-fetch';
4
+ import { ExchangeRate } from '../types/exchange-rates.js';
5
+
6
+ export const listExchangeRates = async (): Promise<ExchangeRate[]> => {
7
+ const auth = await getAdminAuth();
8
+ const url = `${process.env.CORE_API_ORIGIN}/api/settings/exchange-rates`;
9
+ const response: Response = await fetch(url, {
10
+ headers: {
11
+ Authorization: auth,
12
+ },
13
+ });
14
+
15
+ if (response.ok) {
16
+ return response.json() as any;
17
+ }
18
+
19
+ const body = await response.text();
20
+ throw new XError(response.statusText, { url, body });
21
+ };
22
+
23
+ export const getExchangeRate = async (
24
+ fromCurrency: string,
25
+ toCurrency: string,
26
+ ): Promise<ExchangeRate | undefined> => {
27
+ const auth = await getAdminAuth();
28
+ const url = `${process.env.CORE_API_ORIGIN}/api/settings/exchange-rates/${encodeURIComponent(
29
+ fromCurrency,
30
+ )}/${encodeURIComponent(toCurrency)}`;
31
+ const response: Response = await fetch(url, {
32
+ headers: {
33
+ Authorization: auth,
34
+ },
35
+ });
36
+
37
+ if (response.ok) {
38
+ return response.status === 200 ? (response.json() as any) : undefined;
39
+ }
40
+
41
+ if (response.status === 404) {
42
+ return undefined;
43
+ }
44
+
45
+ const body = await response.text();
46
+ throw new XError(response.statusText, { url, body, fromCurrency, toCurrency });
47
+ };
48
+
49
+ /**
50
+ * Direction-agnostic conversion multiplier: how many units of `toCurrency`
51
+ * equal 1 unit of `fromCurrency`. Tries a direct pair first, then falls back
52
+ * to the inverse of the reverse pair (configured rows only need one direction
53
+ * per pair). Returns `undefined` if neither is configured.
54
+ */
55
+ export const getConversionRate = async (
56
+ fromCurrency: string,
57
+ toCurrency: string,
58
+ ): Promise<number | undefined> => {
59
+ if (fromCurrency === toCurrency) {
60
+ return 1;
61
+ }
62
+
63
+ const direct = await getExchangeRate(fromCurrency, toCurrency);
64
+ if (direct) {
65
+ return direct.rate;
66
+ }
67
+
68
+ const inverse = await getExchangeRate(toCurrency, fromCurrency);
69
+ if (inverse && inverse.rate > 0) {
70
+ return 1 / inverse.rate;
71
+ }
72
+
73
+ return undefined;
74
+ };
@@ -10,6 +10,8 @@ export enum VehicleTimelineEventType {
10
10
  Created = 'CREATED',
11
11
  Purchased = 'PURCHASED',
12
12
  Sold = 'SOLD',
13
+ /** The vehicle entered purchase evaluation / consignation (purchase deal progressed). */
14
+ PurchaseEvaluationStarted = 'PURCHASE_EVALUATION_STARTED',
13
15
  /** The purchase was agreed with the supplier (purchase deal progressed). */
14
16
  PurchaseAgreed = 'PURCHASE_AGREED',
15
17
  /** First payment sent to the supplier (purchase deal progressed). */
@@ -1,7 +1,44 @@
1
1
  import { XError } from '@bisondesk/commons-sdk/errors';
2
2
  import { joinWithSeparator } from '@bisondesk/commons-sdk/formatting';
3
3
  import { Categories } from '../constants.js';
4
- import { VehicleExternalInfo } from '../types/vehicles.js';
4
+ import {
5
+ Vehicle,
6
+ VehicleExternalInfo,
7
+ VehiclePurchase,
8
+ VehiclePurchaseDealStatus,
9
+ } from '../types/vehicles.js';
10
+
11
+ /**
12
+ * The deal has not been committed: there is no purchase yet, or its deal is still in
13
+ * `Marketing`. Copies are created in this state; it ends when the owner agrees to buy
14
+ * (e.g. an ICO invoice moves the deal to PurchaseAgreed).
15
+ */
16
+ export const isDealInMarketing = (purchase: VehiclePurchase | undefined): boolean =>
17
+ purchase == null || purchase.deal.status === VehiclePurchaseDealStatus.Marketing;
18
+
19
+ /**
20
+ * A cross-tenant copy whose source still masters it: it has an `original` link and its deal is
21
+ * still in Marketing ({@link isDealInMarketing}). While this holds, the next sync overwrites
22
+ * `external` (specs, pictures, videos) and `salesConditions` from the source; once the deal
23
+ * progresses, the vehicle is the owner's own stock and the sync hands off. Native vehicles are
24
+ * never source-mastered.
25
+ */
26
+ export const isSourceMastered = (
27
+ vehicle: Pick<Vehicle, 'original'>,
28
+ purchase: VehiclePurchase | undefined,
29
+ ): boolean => vehicle.original != null && isDealInMarketing(purchase);
30
+
31
+ /**
32
+ * A cross-tenant copy whose source is not sellable, as stamped on the last sync hop. Only
33
+ * meaningful while the source still masters the copy ({@link isSourceMastered}): past Marketing
34
+ * the vehicle is the owner's own stock, and a still-present flag is merely stale — the sync
35
+ * clears it on the next source event — so it must be ignored.
36
+ */
37
+ export const isUnavailableFromSource = (
38
+ vehicle: Pick<Vehicle, 'original'>,
39
+ purchase: VehiclePurchase | undefined,
40
+ ): boolean =>
41
+ isSourceMastered(vehicle, purchase) && (vehicle.original?.salesConditions?.unavailable ?? false);
5
42
 
6
43
  export const extractCustomFeatures = (vehicle: VehicleExternalInfo): string[] => {
7
44
  const features: {