@bisondesk/core-sdk 1.0.402 → 1.0.404
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/types/crm.d.ts +14 -0
- package/lib/types/crm.d.ts.map +1 -1
- package/lib/types/crm.js +7 -0
- package/lib/types/crm.js.map +1 -1
- package/lib/types/offers.d.ts +45 -3
- package/lib/types/offers.d.ts.map +1 -1
- package/lib/types/offers.js +1 -0
- package/lib/types/offers.js.map +1 -1
- package/lib/types/vehicles.d.ts +18 -6
- package/lib/types/vehicles.d.ts.map +1 -1
- package/lib/types/vehicles.js +9 -0
- package/lib/types/vehicles.js.map +1 -1
- package/lib/utils/vehicles.d.ts +2 -0
- package/lib/utils/vehicles.d.ts.map +1 -1
- package/lib/utils/vehicles.js +32 -5
- package/lib/utils/vehicles.js.map +1 -1
- package/lib/utils/vehicles.test.d.ts +2 -0
- package/lib/utils/vehicles.test.d.ts.map +1 -0
- package/lib/utils/vehicles.test.js +40 -0
- package/lib/utils/vehicles.test.js.map +1 -0
- package/package.json +1 -1
- package/src/types/crm.ts +17 -0
- package/src/types/offers.ts +55 -2
- package/src/types/vehicles.ts +22 -5
- package/src/utils/vehicles.test.ts +48 -0
- package/src/utils/vehicles.ts +43 -6
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vehicles.js","sourceRoot":"/","sources":["utils/vehicles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"vehicles.js","sourceRoot":"/","sources":["utils/vehicles.ts"],"names":[],"mappings":"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","sourcesContent":["import { Categories } from '../constants.js';\nimport { VehicleExternalInfo } from '../types/vehicles.js';\nimport { XError } from '@bisondesk/commons-sdk/errors';\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\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 make: string;\n category: string;\n modelName?: string;\n modelTypeName?: string;\n bodywork?: string;\n}): string => {\n if (category === Categories.Trailer || category === Categories.SemiTrailer) {\n return [make, modelName, 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]{2}\\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 baseNumber = match[1];\n const counter = match[2];\n const counterNumber = convertLettersToNumber(counter);\n const nextCounterNumber = counterNumber + 1;\n const nextCounter = convertNumberToLetters(nextCounterNumber);\n return `${baseNumber}${nextCounter}`;\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vehicles.test.d.ts","sourceRoot":"/","sources":["utils/vehicles.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { convertLettersToNumber, convertNumberToLetters, getNextRelatedStockNumber, } from './vehicles.js';
|
|
2
|
+
import { XError } from '@bisondesk/commons-sdk/errors';
|
|
3
|
+
describe('stock number utils', () => {
|
|
4
|
+
describe('convertNumberToLetters', () => {
|
|
5
|
+
it('should convert numbers to letters correctly', () => {
|
|
6
|
+
expect(convertNumberToLetters(0)).toBe('');
|
|
7
|
+
expect(convertNumberToLetters(1)).toBe('A');
|
|
8
|
+
expect(convertNumberToLetters(2)).toBe('B');
|
|
9
|
+
expect(convertNumberToLetters(26)).toBe('Z');
|
|
10
|
+
expect(convertNumberToLetters(27)).toBe('AA');
|
|
11
|
+
expect(convertNumberToLetters(52)).toBe('AZ');
|
|
12
|
+
});
|
|
13
|
+
it('should return an empty string for numbers less than 1', () => {
|
|
14
|
+
expect(convertNumberToLetters(0)).toBe('');
|
|
15
|
+
expect(convertNumberToLetters(-1)).toBe('');
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
describe('convertLettersToNumber', () => {
|
|
19
|
+
it('should convert letters to numbers correctly', () => {
|
|
20
|
+
expect(convertLettersToNumber('')).toBe(0);
|
|
21
|
+
expect(convertLettersToNumber('A')).toBe(1);
|
|
22
|
+
expect(convertLettersToNumber('Z')).toBe(26);
|
|
23
|
+
expect(convertLettersToNumber('AA')).toBe(27);
|
|
24
|
+
expect(convertLettersToNumber('AZ')).toBe(52);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
describe('getNextRelatedStockNumber', () => {
|
|
28
|
+
it('should get the next related stock number correctly', () => {
|
|
29
|
+
expect(getNextRelatedStockNumber('AB12345')).toBe('AB12345A');
|
|
30
|
+
expect(getNextRelatedStockNumber('AB12345A')).toBe('AB12345B');
|
|
31
|
+
expect(getNextRelatedStockNumber('AB12345Z')).toBe('AB12345AA');
|
|
32
|
+
expect(getNextRelatedStockNumber('AB12345AZ')).toBe('AB12345BA');
|
|
33
|
+
});
|
|
34
|
+
it('should throw an error for invalid stock numbers', () => {
|
|
35
|
+
expect(() => getNextRelatedStockNumber('12345')).toThrow(XError);
|
|
36
|
+
expect(() => getNextRelatedStockNumber('AB12345PPP')).toThrow(XError);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
//# sourceMappingURL=vehicles.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vehicles.test.js","sourceRoot":"/","sources":["utils/vehicles.test.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n convertLettersToNumber,\n convertNumberToLetters,\n getNextRelatedStockNumber,\n} from './vehicles.js';\nimport { XError } from '@bisondesk/commons-sdk/errors';\n\ndescribe('stock number utils', () => {\n describe('convertNumberToLetters', () => {\n it('should convert numbers to letters correctly', () => {\n expect(convertNumberToLetters(0)).toBe('');\n expect(convertNumberToLetters(1)).toBe('A');\n expect(convertNumberToLetters(2)).toBe('B');\n expect(convertNumberToLetters(26)).toBe('Z');\n expect(convertNumberToLetters(27)).toBe('AA');\n expect(convertNumberToLetters(52)).toBe('AZ');\n });\n\n it('should return an empty string for numbers less than 1', () => {\n expect(convertNumberToLetters(0)).toBe('');\n expect(convertNumberToLetters(-1)).toBe('');\n });\n });\n\n describe('convertLettersToNumber', () => {\n it('should convert letters to numbers correctly', () => {\n expect(convertLettersToNumber('')).toBe(0);\n expect(convertLettersToNumber('A')).toBe(1);\n expect(convertLettersToNumber('Z')).toBe(26);\n expect(convertLettersToNumber('AA')).toBe(27);\n expect(convertLettersToNumber('AZ')).toBe(52);\n });\n });\n\n describe('getNextRelatedStockNumber', () => {\n it('should get the next related stock number correctly', () => {\n expect(getNextRelatedStockNumber('AB12345')).toBe('AB12345A');\n expect(getNextRelatedStockNumber('AB12345A')).toBe('AB12345B');\n expect(getNextRelatedStockNumber('AB12345Z')).toBe('AB12345AA');\n expect(getNextRelatedStockNumber('AB12345AZ')).toBe('AB12345BA');\n });\n\n it('should throw an error for invalid stock numbers', () => {\n expect(() => getNextRelatedStockNumber('12345')).toThrow(XError);\n expect(() => getNextRelatedStockNumber('AB12345PPP')).toThrow(XError);\n });\n });\n});\n"]}
|
package/package.json
CHANGED
package/src/types/crm.ts
CHANGED
|
@@ -129,6 +129,22 @@ export type CrmPublicSearchDefinitions = {
|
|
|
129
129
|
searchContact: PublicSearchDefinition;
|
|
130
130
|
};
|
|
131
131
|
|
|
132
|
+
export enum MarketingChannel {
|
|
133
|
+
Email = 'email',
|
|
134
|
+
Whatsapp = 'whatsapp',
|
|
135
|
+
Sms = 'sms',
|
|
136
|
+
Phone = 'phone',
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export type MarketingPreferenceEntry = {
|
|
140
|
+
optedOut: boolean;
|
|
141
|
+
updatedAt: string;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export type MarketingPreferences = {
|
|
145
|
+
[channel in MarketingChannel]?: MarketingPreferenceEntry;
|
|
146
|
+
};
|
|
147
|
+
|
|
132
148
|
type BaseContact = {
|
|
133
149
|
accountManager?: string;
|
|
134
150
|
countryCode?: string;
|
|
@@ -141,6 +157,7 @@ type BaseContact = {
|
|
|
141
157
|
organizationId?: string;
|
|
142
158
|
/** will not be filled if organizationId is present */
|
|
143
159
|
orgName?: string;
|
|
160
|
+
marketingPreferences?: MarketingPreferences;
|
|
144
161
|
};
|
|
145
162
|
|
|
146
163
|
export type NewContact = BaseContact & {
|
package/src/types/offers.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
import { DistributiveOmit, Document, NextList } from '@bisondesk/commons-sdk/types';
|
|
1
|
+
import { DistributiveOmit, Document, LocationValue, NextList } from '@bisondesk/commons-sdk/types';
|
|
2
2
|
import { BusinessEntityIds, WarningHints } from '../constants.js';
|
|
3
3
|
import { Contact, Organization } from './crm.js';
|
|
4
4
|
import { Insights, InsightsComparableSpecs } from './insights.js';
|
|
5
5
|
import { BaseSearchRequest } from './search.js';
|
|
6
6
|
import { DataRecord, ReferenceData } from './utils.js';
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
SearchVehicle,
|
|
9
|
+
VehicleExternalInfo,
|
|
10
|
+
VehicleInternalInfo,
|
|
11
|
+
VehiclePurchaseDealStatus,
|
|
12
|
+
VehiclePurchaseDeliveryType,
|
|
13
|
+
} from './vehicles.js';
|
|
8
14
|
|
|
9
15
|
export enum OfferActions {
|
|
10
16
|
CREATE_BID = 'create_bid',
|
|
@@ -21,6 +27,7 @@ export enum OfferActions {
|
|
|
21
27
|
ACCEPT_NEGOTIATION = 'accept_negotiation',
|
|
22
28
|
UNDO_ACCEPT_NEGOTIATION = 'undo_accept_negotiation',
|
|
23
29
|
SET_SUPPLIER_VEHICLE = 'set_supplier_vehicle',
|
|
30
|
+
CAN_PURCHASE = 'can_purchase',
|
|
24
31
|
}
|
|
25
32
|
|
|
26
33
|
export enum OfferBidActions {
|
|
@@ -77,6 +84,7 @@ type BaseOffer = {
|
|
|
77
84
|
organizationId?: string;
|
|
78
85
|
|
|
79
86
|
supplierNotes?: string; // Optional notes from the supplier
|
|
87
|
+
description: { remarks?: string; technicalRemarks?: string };
|
|
80
88
|
};
|
|
81
89
|
|
|
82
90
|
export type NewOffer = BaseOffer & {
|
|
@@ -133,6 +141,7 @@ export type OfferUpdate = {
|
|
|
133
141
|
|
|
134
142
|
finalValuation?: string | null;
|
|
135
143
|
agreed?: boolean;
|
|
144
|
+
description?: { remarks?: string; technicalRemarks?: string };
|
|
136
145
|
};
|
|
137
146
|
|
|
138
147
|
type OfferWarningActionLink = {
|
|
@@ -163,6 +172,7 @@ export type OfferMetadata = {
|
|
|
163
172
|
export type OfferBff = {
|
|
164
173
|
offer: DataRecord<Offer, OfferMetadata>;
|
|
165
174
|
bids: DataRecord<OfferBid>[];
|
|
175
|
+
vehicles: SearchVehicle[];
|
|
166
176
|
customer?: {
|
|
167
177
|
contact: DataRecord<Contact>;
|
|
168
178
|
org?: DataRecord<Organization>;
|
|
@@ -270,3 +280,46 @@ export type KanbanOffersNextList = Omit<
|
|
|
270
280
|
> & {
|
|
271
281
|
nextTokens?: Record<string, string | undefined>;
|
|
272
282
|
};
|
|
283
|
+
|
|
284
|
+
/********
|
|
285
|
+
* Vehicle Purchase
|
|
286
|
+
*/
|
|
287
|
+
|
|
288
|
+
export type OfferPurchase = {
|
|
289
|
+
offerId: string;
|
|
290
|
+
vin: string;
|
|
291
|
+
supplierStockNumber?: string;
|
|
292
|
+
|
|
293
|
+
deal: {
|
|
294
|
+
description: {
|
|
295
|
+
technicalRemarks: string;
|
|
296
|
+
};
|
|
297
|
+
dealStatus:
|
|
298
|
+
| VehiclePurchaseDealStatus.PurchaseEvaluation
|
|
299
|
+
| VehiclePurchaseDealStatus.PurchaseAgreed
|
|
300
|
+
| VehiclePurchaseDealStatus.Marketing;
|
|
301
|
+
costs: {
|
|
302
|
+
purchase: string;
|
|
303
|
+
purchaseVatPercentage: string;
|
|
304
|
+
internalGarage?: string;
|
|
305
|
+
externalGarage?: string;
|
|
306
|
+
internalTransport?: string;
|
|
307
|
+
externalTransport?: string;
|
|
308
|
+
other?: string;
|
|
309
|
+
commission?: string;
|
|
310
|
+
};
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
logistics: {
|
|
314
|
+
vehicleRole: VehicleInternalInfo['role'];
|
|
315
|
+
availabilityDate: string;
|
|
316
|
+
deliveryType?: VehiclePurchaseDeliveryType;
|
|
317
|
+
pickupAddress?: LocationValue;
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
salesPrices?: {
|
|
321
|
+
internet?: string;
|
|
322
|
+
premium?: string;
|
|
323
|
+
minimum?: string;
|
|
324
|
+
};
|
|
325
|
+
};
|
package/src/types/vehicles.ts
CHANGED
|
@@ -9,6 +9,14 @@ import {
|
|
|
9
9
|
} from '@bisondesk/commons-sdk/types';
|
|
10
10
|
import { OpportunityReservation } from './reservations.js';
|
|
11
11
|
|
|
12
|
+
export enum VehicleRoles {
|
|
13
|
+
SALE = 'SALE',
|
|
14
|
+
OWN_USE = 'OWN_USE',
|
|
15
|
+
RENTAL = 'RENTAL',
|
|
16
|
+
BUILD = 'BUILD',
|
|
17
|
+
UNKNOWN = 'UNKNOWN',
|
|
18
|
+
}
|
|
19
|
+
|
|
12
20
|
type BaseVehicleEvent = {
|
|
13
21
|
id: string;
|
|
14
22
|
actionAt: string;
|
|
@@ -73,8 +81,8 @@ export type NewVehicleRequest = {
|
|
|
73
81
|
technicalRemarks?: string;
|
|
74
82
|
};
|
|
75
83
|
logistics: {
|
|
76
|
-
parking
|
|
77
|
-
deliveryType
|
|
84
|
+
parking?: string;
|
|
85
|
+
deliveryType?: VehiclePurchaseDeliveryType;
|
|
78
86
|
pickupAddress?: LocationValue;
|
|
79
87
|
checkedInAt?: string;
|
|
80
88
|
checkedInBy?: string;
|
|
@@ -95,13 +103,15 @@ export type NewVehicleRequest = {
|
|
|
95
103
|
};
|
|
96
104
|
vinList?: string;
|
|
97
105
|
deal: {
|
|
106
|
+
offerId?: string;
|
|
98
107
|
stockNumber?: string;
|
|
99
108
|
contactId: string;
|
|
100
109
|
orgId: string;
|
|
101
110
|
purchasedBy: string;
|
|
102
111
|
dealStatus:
|
|
103
112
|
| VehiclePurchaseDealStatus.PurchaseEvaluation
|
|
104
|
-
| VehiclePurchaseDealStatus.PurchaseAgreed
|
|
113
|
+
| VehiclePurchaseDealStatus.PurchaseAgreed
|
|
114
|
+
| VehiclePurchaseDealStatus.Marketing;
|
|
105
115
|
costs: {
|
|
106
116
|
purchase: string;
|
|
107
117
|
purchaseVatPercentage: string;
|
|
@@ -114,7 +124,7 @@ export type NewVehicleRequest = {
|
|
|
114
124
|
};
|
|
115
125
|
logistics: {
|
|
116
126
|
availableDate: string;
|
|
117
|
-
vehicleRole:
|
|
127
|
+
vehicleRole: VehicleRoles;
|
|
118
128
|
};
|
|
119
129
|
};
|
|
120
130
|
};
|
|
@@ -257,6 +267,8 @@ export type VehicleInternalInfo = {
|
|
|
257
267
|
stockNumber: string;
|
|
258
268
|
branch: string;
|
|
259
269
|
|
|
270
|
+
offerId?: string;
|
|
271
|
+
|
|
260
272
|
/**
|
|
261
273
|
* This ID is used to link different vehicle objects that represent the same real world asset.
|
|
262
274
|
* Ideally the chassis number could be used, but in some cases it is not available yet.
|
|
@@ -267,7 +279,7 @@ export type VehicleInternalInfo = {
|
|
|
267
279
|
pictures: AttachmentValue[];
|
|
268
280
|
engineeringDocs: Document[];
|
|
269
281
|
pricing: VehiclePricing;
|
|
270
|
-
role:
|
|
282
|
+
role: VehicleRoles;
|
|
271
283
|
status: VehicleStatus;
|
|
272
284
|
updatedAt: string;
|
|
273
285
|
/* use this property to store additional terms that you want the vehicle to be found with when doing a full text search */
|
|
@@ -517,6 +529,7 @@ export enum VehiclePurchaseDealStatus {
|
|
|
517
529
|
FirstPaymentSent = 'FIRST_PAYMENT_SENT',
|
|
518
530
|
FullPaymentAllowed = 'FULL_PAYMENT_ALLOWED',
|
|
519
531
|
FullPaymentSent = 'FULL_PAYMENT_SENT',
|
|
532
|
+
Marketing = 'MARKETING',
|
|
520
533
|
}
|
|
521
534
|
|
|
522
535
|
export enum VehiclePurchaseLogisticsStatus {
|
|
@@ -600,8 +613,12 @@ export type VehiclePurchase = {
|
|
|
600
613
|
|
|
601
614
|
arrivedAt?: string;
|
|
602
615
|
arrivedBy?: string;
|
|
616
|
+
|
|
603
617
|
checkedInAt?: string;
|
|
604
618
|
checkedInBy?: string;
|
|
619
|
+
|
|
620
|
+
marketingStartedAt?: string;
|
|
621
|
+
marketingStartedBy?: string;
|
|
605
622
|
};
|
|
606
623
|
|
|
607
624
|
deal: {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {
|
|
2
|
+
convertLettersToNumber,
|
|
3
|
+
convertNumberToLetters,
|
|
4
|
+
getNextRelatedStockNumber,
|
|
5
|
+
} from './vehicles.js';
|
|
6
|
+
import { XError } from '@bisondesk/commons-sdk/errors';
|
|
7
|
+
|
|
8
|
+
describe('stock number utils', () => {
|
|
9
|
+
describe('convertNumberToLetters', () => {
|
|
10
|
+
it('should convert numbers to letters correctly', () => {
|
|
11
|
+
expect(convertNumberToLetters(0)).toBe('');
|
|
12
|
+
expect(convertNumberToLetters(1)).toBe('A');
|
|
13
|
+
expect(convertNumberToLetters(2)).toBe('B');
|
|
14
|
+
expect(convertNumberToLetters(26)).toBe('Z');
|
|
15
|
+
expect(convertNumberToLetters(27)).toBe('AA');
|
|
16
|
+
expect(convertNumberToLetters(52)).toBe('AZ');
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should return an empty string for numbers less than 1', () => {
|
|
20
|
+
expect(convertNumberToLetters(0)).toBe('');
|
|
21
|
+
expect(convertNumberToLetters(-1)).toBe('');
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe('convertLettersToNumber', () => {
|
|
26
|
+
it('should convert letters to numbers correctly', () => {
|
|
27
|
+
expect(convertLettersToNumber('')).toBe(0);
|
|
28
|
+
expect(convertLettersToNumber('A')).toBe(1);
|
|
29
|
+
expect(convertLettersToNumber('Z')).toBe(26);
|
|
30
|
+
expect(convertLettersToNumber('AA')).toBe(27);
|
|
31
|
+
expect(convertLettersToNumber('AZ')).toBe(52);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
describe('getNextRelatedStockNumber', () => {
|
|
36
|
+
it('should get the next related stock number correctly', () => {
|
|
37
|
+
expect(getNextRelatedStockNumber('AB12345')).toBe('AB12345A');
|
|
38
|
+
expect(getNextRelatedStockNumber('AB12345A')).toBe('AB12345B');
|
|
39
|
+
expect(getNextRelatedStockNumber('AB12345Z')).toBe('AB12345AA');
|
|
40
|
+
expect(getNextRelatedStockNumber('AB12345AZ')).toBe('AB12345BA');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should throw an error for invalid stock numbers', () => {
|
|
44
|
+
expect(() => getNextRelatedStockNumber('12345')).toThrow(XError);
|
|
45
|
+
expect(() => getNextRelatedStockNumber('AB12345PPP')).toThrow(XError);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
});
|
package/src/utils/vehicles.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Categories } from '../constants.js';
|
|
2
2
|
import { VehicleExternalInfo } from '../types/vehicles.js';
|
|
3
|
+
import { XError } from '@bisondesk/commons-sdk/errors';
|
|
3
4
|
|
|
4
5
|
export const extractCustomFeatures = (vehicle: VehicleExternalInfo): string[] => {
|
|
5
6
|
const features: {
|
|
@@ -62,17 +63,53 @@ export const getInternalTitle = ({
|
|
|
62
63
|
.trim();
|
|
63
64
|
};
|
|
64
65
|
|
|
65
|
-
|
|
66
|
+
const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
67
|
+
|
|
68
|
+
// example: 1 -> A, 2 -> B, 26 -> Z, 27 -> AA, 28 -> AB, 52 -> AZ, 53 -> BA, 54 -> BB, 702 -> ZZ
|
|
66
69
|
export const convertNumberToLetters = (num: number): string => {
|
|
67
|
-
const
|
|
68
|
-
const lettersLength = letters.length;
|
|
70
|
+
const lettersLength = ALPHABET.length;
|
|
69
71
|
|
|
70
72
|
if (num < 1) {
|
|
71
73
|
return '';
|
|
72
74
|
}
|
|
73
75
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
let remainder = num % lettersLength;
|
|
77
|
+
let quotient = Math.floor(num / lettersLength);
|
|
78
|
+
|
|
79
|
+
// If remainder is 0, it means we should map it to 'Z' and reduce the quotient by 1
|
|
80
|
+
if (remainder === 0) {
|
|
81
|
+
remainder = lettersLength;
|
|
82
|
+
quotient -= 1;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return convertNumberToLetters(quotient) + ALPHABET.charAt(remainder - 1);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// example: A -> 1, B -> 2, Z -> 26, AA -> 27, AB -> 28, AZ -> 52, BA -> 53, BB -> 54, ZZ -> 702
|
|
89
|
+
export const convertLettersToNumber = (letters: string): number => {
|
|
90
|
+
const base = ALPHABET.length;
|
|
91
|
+
|
|
92
|
+
let result = 0;
|
|
93
|
+
|
|
94
|
+
for (let i = 0; i < letters.length; i++) {
|
|
95
|
+
const charValue = ALPHABET.indexOf(letters[i]) + 1;
|
|
96
|
+
result = result * base + charValue;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return result;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export const getNextRelatedStockNumber = (stockNumber: string): string => {
|
|
103
|
+
const counterPattern = /^([A-Z]{2}\d{5})([A-Z]{0,2})$/;
|
|
104
|
+
const match = stockNumber.match(counterPattern);
|
|
105
|
+
if (match == null) {
|
|
106
|
+
throw new XError('core-sdk.vehicles.bad-stock-number', { stockNumber });
|
|
107
|
+
}
|
|
76
108
|
|
|
77
|
-
|
|
109
|
+
const baseNumber = match[1];
|
|
110
|
+
const counter = match[2];
|
|
111
|
+
const counterNumber = convertLettersToNumber(counter);
|
|
112
|
+
const nextCounterNumber = counterNumber + 1;
|
|
113
|
+
const nextCounter = convertNumberToLetters(nextCounterNumber);
|
|
114
|
+
return `${baseNumber}${nextCounter}`;
|
|
78
115
|
};
|