@bisondesk/core-sdk 1.0.493 → 1.0.495
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/constants.d.ts +2 -0
- package/lib/constants.d.ts.map +1 -1
- package/lib/constants.js +2 -0
- package/lib/constants.js.map +1 -1
- package/lib/types/comparables.d.ts +2 -0
- package/lib/types/comparables.d.ts.map +1 -1
- package/lib/types/comparables.js.map +1 -1
- package/lib/types/crm.d.ts +8 -0
- package/lib/types/crm.d.ts.map +1 -1
- package/lib/types/crm.js.map +1 -1
- package/lib/types/interests.d.ts +8 -0
- package/lib/types/interests.d.ts.map +1 -1
- package/lib/types/interests.js +2 -0
- package/lib/types/interests.js.map +1 -1
- package/lib/types/leasing-search.d.ts +1 -0
- package/lib/types/leasing-search.d.ts.map +1 -1
- package/lib/types/leasing-search.js.map +1 -1
- package/lib/types/marketing-emails.d.ts +57 -0
- package/lib/types/marketing-emails.d.ts.map +1 -0
- package/lib/types/marketing-emails.js +2 -0
- package/lib/types/marketing-emails.js.map +1 -0
- package/lib/types/marketing.d.ts +0 -1
- package/lib/types/marketing.d.ts.map +1 -1
- package/lib/types/marketing.js +0 -1
- package/lib/types/marketing.js.map +1 -1
- package/lib/types/tenants.d.ts +1 -0
- package/lib/types/tenants.d.ts.map +1 -1
- package/lib/types/tenants.js +1 -0
- package/lib/types/tenants.js.map +1 -1
- package/lib/utils/interests.d.ts +4 -0
- package/lib/utils/interests.d.ts.map +1 -0
- package/lib/utils/interests.js +110 -0
- package/lib/utils/interests.js.map +1 -0
- package/package.json +1 -1
- package/src/constants.ts +2 -0
- package/src/types/comparables.ts +2 -0
- package/src/types/crm.ts +11 -0
- package/src/types/interests.ts +14 -0
- package/src/types/leasing-search.ts +1 -0
- package/src/types/marketing-emails.ts +67 -0
- package/src/types/marketing.ts +1 -1
- package/src/types/tenants.ts +1 -0
- package/src/utils/interests.ts +150 -0
- package/tsconfig.tsbuildinfo +1 -1
package/lib/types/tenants.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenants.d.ts","sourceRoot":"/","sources":["types/tenants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAClF,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,MAAM,YAAY,GAAG;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;CAInC,CAAC;AAEF,oBAAY,YAAY;IACtB,cAAc,mBAAmB;IACjC,GAAG,QAAQ;IACX,GAAG,QAAQ;IACX,IAAI,SAAS;IACb,KAAK,UAAU;IACf,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,aAAa,kBAAkB;IAC/B,MAAM,WAAW;IACjB,kBAAkB,yBAAyB;IAC3C,QAAQ,aAAa;IACrB,KAAK,UAAU;IACf,aAAa,oBAAoB;IACjC,SAAS,cAAc;IACvB,qBAAqB,2BAA2B;IAChD,KAAK,UAAU;CAChB;AAED,MAAM,MAAM,MAAM,GAAG,YAAY,GAAG;IAClC,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,SAAS,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IAGvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,QAAQ,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;IAChC,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,aAAa,EAAE;QACb,KAAK,EAAE,eAAe,EAAE,CAAC;KAC1B,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE;QACR,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,QAAQ,EAAE,aAAa,CAAC;IAExB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC3C,OAAO,EAAE,WAAW,GAAG,SAAS,CAAC;IACjC,aAAa,EAAE,gBAAgB,GAAG,SAAS,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC"}
|
|
1
|
+
{"version":3,"file":"tenants.d.ts","sourceRoot":"/","sources":["types/tenants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAClF,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,MAAM,YAAY,GAAG;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;CAInC,CAAC;AAEF,oBAAY,YAAY;IACtB,cAAc,mBAAmB;IACjC,GAAG,QAAQ;IACX,GAAG,QAAQ;IACX,IAAI,SAAS;IACb,KAAK,UAAU;IACf,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,QAAQ,aAAa;IACrB,aAAa,kBAAkB;IAC/B,MAAM,WAAW;IACjB,kBAAkB,yBAAyB;IAC3C,QAAQ,aAAa;IACrB,KAAK,UAAU;IACf,aAAa,oBAAoB;IACjC,SAAS,cAAc;IACvB,qBAAqB,2BAA2B;IAChD,KAAK,UAAU;CAChB;AAED,MAAM,MAAM,MAAM,GAAG,YAAY,GAAG;IAClC,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,SAAS,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IAGvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,QAAQ,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;IAChC,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,aAAa,EAAE;QACb,KAAK,EAAE,eAAe,EAAE,CAAC;KAC1B,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE;QACR,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,QAAQ,EAAE,aAAa,CAAC;IAExB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC3C,OAAO,EAAE,WAAW,GAAG,SAAS,CAAC;IACjC,aAAa,EAAE,gBAAgB,GAAG,SAAS,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC"}
|
package/lib/types/tenants.js
CHANGED
|
@@ -6,6 +6,7 @@ export var TenantModule;
|
|
|
6
6
|
TenantModule["Docs"] = "docs";
|
|
7
7
|
TenantModule["Leads"] = "leads";
|
|
8
8
|
TenantModule["Leasing"] = "leasing";
|
|
9
|
+
TenantModule["Marketing"] = "marketing";
|
|
9
10
|
TenantModule["Insights"] = "insights";
|
|
10
11
|
TenantModule["Opportunities"] = "opportunities";
|
|
11
12
|
TenantModule["Offers"] = "offers";
|
package/lib/types/tenants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenants.js","sourceRoot":"/","sources":["types/tenants.ts"],"names":[],"mappings":"AAgBA,MAAM,CAAN,IAAY,
|
|
1
|
+
{"version":3,"file":"tenants.js","sourceRoot":"/","sources":["types/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","sourcesContent":["import { CognitoInfo, LocationValue, Region } from '@bisondesk/commons-sdk/types';\nimport { OpportunityType } from '../constants.js';\n\nexport type PublicTenant = {\n defaultCountry: string;\n defaultCurrency: string;\n defaultLanguage: string;\n id: string; // the id is provided on creation bc we assume tenants will be created by someone on the team\n name: string;\n region: Region;\n subdomains: [string, ...string[]];\n\n // Pay attention to what information is added here since\n // the tenant can be obtained without authentication\n};\n\nexport enum TenantModule {\n Administration = 'administration',\n App = 'app',\n CRM = 'crm',\n Docs = 'docs',\n Leads = 'leads',\n Leasing = 'leasing',\n Marketing = 'marketing',\n Insights = 'insights',\n Opportunities = 'opportunities',\n Offers = 'offers',\n VehiclesMasterData = 'vehicles_master_data',\n Vehicles = 'vehicles',\n Tasks = 'tasks',\n TrackAndTrace = 'track_and_trace',\n Bootstrap = 'bootstrap',\n WhatsappNotifications = 'whatsapp_notifications',\n Hexon = 'hexon',\n}\n\nexport type Tenant = PublicTenant & {\n cognito?: CognitoInfo;\n languages: [string, ...string[]];\n conglomerate?: string;\n emailDomain: string;\n hyperdmsIds?: string[];\n hyperportalId?: string;\n\n /* deprecated */\n exactAccounting?: boolean;\n\n branches: [Branch, ...Branch[]];\n modules: TenantModule[];\n test?: boolean;\n opportunities: {\n types: OpportunityType[];\n };\n};\n\nexport type Branch = {\n id: string;\n name: string;\n country: string;\n language: string;\n exactAccounting?: boolean;\n currency: string;\n adminNumberPrefix: string;\n stockNumberPrefix: string;\n vatNumber?: string;\n vatRates: {\n standard: string; //percentage value (e.g. 21)\n };\n location: LocationValue;\n\n storecoveExternalId?: number;\n};\n\nexport type HdmsVehiclesSync = {\n active: boolean;\n};\n\nexport type HdmsCrmSync = {\n active: boolean;\n};\n\nexport type HdmsDocumentSync = {\n active: boolean;\n};\n\nexport type TenantSyncSettings = {\n tenantId: string;\n hdmsVehicles: HdmsVehiclesSync | undefined;\n hdmsCrm: HdmsCrmSync | undefined;\n hdmsDocuments: HdmsDocumentSync | undefined;\n};\n\nexport type WhatsappStateResponse = {\n enabled: boolean;\n};\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Interest } from '../types/interests.js';
|
|
2
|
+
import { VehicleExternalInfo } from '../types/vehicles.js';
|
|
3
|
+
export declare const mapVehicleToInterest: (userId: string, vehicleExternalInfo: VehicleExternalInfo, referenceDate?: Date) => Interest;
|
|
4
|
+
//# sourceMappingURL=interests.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interests.d.ts","sourceRoot":"/","sources":["utils/interests.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE3D,eAAO,MAAM,oBAAoB,WACvB,MAAM,uBACO,mBAAmB,kBACzB,IAAI,KAClB,QAyCF,CAAC"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { isoString } from '@bisondesk/commons-sdk/date-utils';
|
|
2
|
+
import { generateId } from '@bisondesk/commons-sdk/ids';
|
|
3
|
+
import { UTCDate } from '@date-fns/utc';
|
|
4
|
+
import { first, range, uniq } from 'lodash-es';
|
|
5
|
+
import { KM_ROUNDING, MAX_AGE, MAX_KM, MAX_PRICE, PRICE_ROUNDING } from '../constants.js';
|
|
6
|
+
export const mapVehicleToInterest = (userId, vehicleExternalInfo, referenceDate = new UTCDate()) => {
|
|
7
|
+
return {
|
|
8
|
+
id: generateId(),
|
|
9
|
+
createdAt: isoString(),
|
|
10
|
+
createdBy: userId,
|
|
11
|
+
modifiedAt: isoString(),
|
|
12
|
+
modifiedBy: userId,
|
|
13
|
+
bodystyle: vehicleExternalInfo.general.bodystyle,
|
|
14
|
+
cabins: toCabins(toArray(vehicleExternalInfo.body?.cabin?.type)),
|
|
15
|
+
category: vehicleExternalInfo.general.category,
|
|
16
|
+
retarderIntarder: vehicleExternalInfo.accessories.retarderIntarder ? true : undefined,
|
|
17
|
+
adr: vehicleExternalInfo.accessories.adr,
|
|
18
|
+
damaged: vehicleExternalInfo.condition?.damaged ?? false,
|
|
19
|
+
extended: toArray(vehicleExternalInfo.superstructure?.dimensions?.extended),
|
|
20
|
+
heightened: toArray(vehicleExternalInfo.superstructure?.dimensions?.heightened),
|
|
21
|
+
used: vehicleExternalInfo.condition?.used,
|
|
22
|
+
crane: vehicleExternalInfo.superstructure?.crane?.present,
|
|
23
|
+
tailgate: vehicleExternalInfo.superstructure?.tailgate?.present,
|
|
24
|
+
axleConfigurations: toArray(vehicleExternalInfo.powertrain?.axles?.configuration),
|
|
25
|
+
suspensions: toSuspensions(toArray(vehicleExternalInfo.powertrain?.axles?.suspension)),
|
|
26
|
+
transmissions: toTransmissions(toArray(vehicleExternalInfo.powertrain?.transmission?.type)),
|
|
27
|
+
euronorms: toEuronorms(vehicleExternalInfo),
|
|
28
|
+
kilometers: vehicleExternalInfo.condition?.used
|
|
29
|
+
? toRound(KM_ROUNDING, vehicleExternalInfo.condition?.odometer?.km, MAX_KM)
|
|
30
|
+
: undefined,
|
|
31
|
+
horsepower: toMinHorsepower(vehicleExternalInfo, -0.1),
|
|
32
|
+
versions: vehicleExternalInfo.general.make != null
|
|
33
|
+
? [
|
|
34
|
+
{
|
|
35
|
+
make: vehicleExternalInfo.general.make,
|
|
36
|
+
models: toArray(vehicleExternalInfo.general.model),
|
|
37
|
+
},
|
|
38
|
+
]
|
|
39
|
+
: undefined,
|
|
40
|
+
price: toMaxPrice(vehicleExternalInfo.salesConditions.price),
|
|
41
|
+
age: vehicleExternalInfo.condition?.used
|
|
42
|
+
? toAge(referenceDate, vehicleExternalInfo.history?.advertisingYear)
|
|
43
|
+
: undefined,
|
|
44
|
+
autoGenerated: true,
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
const isHeavyVehicle = (vehicleExternalInfo) => ['Tractor Head', 'Truck'].includes(vehicleExternalInfo.general.category);
|
|
48
|
+
const toCabins = (values) => {
|
|
49
|
+
if (values == null || values.length === 0) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (values.some((v) => v.startsWith('Sleep'))) {
|
|
53
|
+
return uniq([...values, 'Sleep / Medium', 'Sleep / Large']);
|
|
54
|
+
}
|
|
55
|
+
return values;
|
|
56
|
+
};
|
|
57
|
+
const toSuspensions = (values) => {
|
|
58
|
+
if (values == null || values.length === 0) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (values.includes('Air/Steel')) {
|
|
62
|
+
return uniq([...values, 'Air']);
|
|
63
|
+
}
|
|
64
|
+
return values;
|
|
65
|
+
};
|
|
66
|
+
const toTransmissions = (values) => {
|
|
67
|
+
if (values == null || values.length === 0) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (values.includes('Manual')) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (values.includes('Semi-Automatic')) {
|
|
74
|
+
return uniq([...values, 'Automatic']);
|
|
75
|
+
}
|
|
76
|
+
return values;
|
|
77
|
+
};
|
|
78
|
+
const toEuronorms = (vehicleExternalInfo) => {
|
|
79
|
+
const values = toArray(vehicleExternalInfo.powertrain?.emissions?.class);
|
|
80
|
+
if (values == null || values.length === 0 || !isHeavyVehicle(vehicleExternalInfo)) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const minEuronorm = 5;
|
|
84
|
+
const maxEuronorm = 6;
|
|
85
|
+
const lowestEuronorm = first(values.map((v) => Number(v.charAt(v.length - 1))).sort());
|
|
86
|
+
if (lowestEuronorm < minEuronorm) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
return range(lowestEuronorm, maxEuronorm + 1).map((r) => `Euro ${r}`);
|
|
90
|
+
};
|
|
91
|
+
const toAge = (referenceDate, year) => {
|
|
92
|
+
if (year == null) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (year > referenceDate.getUTCFullYear()) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
return toRound(1, referenceDate.getUTCFullYear() - year, MAX_AGE);
|
|
99
|
+
};
|
|
100
|
+
const toMaxPrice = (value) => value != null ? toRound(PRICE_ROUNDING, Number(value) * 1.15, MAX_PRICE) : undefined;
|
|
101
|
+
const toMinHorsepower = (vehicleExternalInfo, shiftRatio) => {
|
|
102
|
+
const hasHorsepower = vehicleExternalInfo.powertrain?.engine?.power?.hp != null;
|
|
103
|
+
const isHorsepowerImportant = isHeavyVehicle(vehicleExternalInfo);
|
|
104
|
+
if (hasHorsepower && isHorsepowerImportant) {
|
|
105
|
+
return toRound(5, vehicleExternalInfo.powertrain.engine.power.hp * (1 + shiftRatio));
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
const toRound = (r, value, max = Infinity) => value != null ? Math.min(Math.ceil(Number(value) / r) * r, max) : undefined;
|
|
109
|
+
const toArray = (value) => (value ? [value] : []);
|
|
110
|
+
//# sourceMappingURL=interests.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interests.js","sourceRoot":"/","sources":["utils/interests.ts"],"names":[],"mappings":"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","sourcesContent":["import { isoString } from '@bisondesk/commons-sdk/date-utils';\nimport { generateId } from '@bisondesk/commons-sdk/ids';\nimport { UTCDate } from '@date-fns/utc';\nimport { first, range, uniq } from 'lodash-es';\nimport { KM_ROUNDING, MAX_AGE, MAX_KM, MAX_PRICE, PRICE_ROUNDING } from '../constants.js';\nimport { Interest } from '../types/interests.js';\nimport { VehicleExternalInfo } from '../types/vehicles.js';\n\nexport const mapVehicleToInterest = (\n userId: string,\n vehicleExternalInfo: VehicleExternalInfo,\n referenceDate: Date = new UTCDate()\n): Interest => {\n return {\n id: generateId(),\n createdAt: isoString(),\n createdBy: userId,\n modifiedAt: isoString(),\n modifiedBy: userId,\n bodystyle: vehicleExternalInfo.general.bodystyle,\n cabins: toCabins(toArray(vehicleExternalInfo.body?.cabin?.type)),\n category: vehicleExternalInfo.general.category,\n retarderIntarder: vehicleExternalInfo.accessories.retarderIntarder ? true : undefined,\n adr: vehicleExternalInfo.accessories.adr,\n damaged: vehicleExternalInfo.condition?.damaged ?? false,\n extended: toArray(vehicleExternalInfo.superstructure?.dimensions?.extended),\n heightened: toArray(vehicleExternalInfo.superstructure?.dimensions?.heightened),\n used: vehicleExternalInfo.condition?.used,\n crane: vehicleExternalInfo.superstructure?.crane?.present,\n tailgate: vehicleExternalInfo.superstructure?.tailgate?.present,\n axleConfigurations: toArray(vehicleExternalInfo.powertrain?.axles?.configuration),\n suspensions: toSuspensions(toArray(vehicleExternalInfo.powertrain?.axles?.suspension)),\n transmissions: toTransmissions(toArray(vehicleExternalInfo.powertrain?.transmission?.type)),\n euronorms: toEuronorms(vehicleExternalInfo),\n kilometers: vehicleExternalInfo.condition?.used\n ? toRound(KM_ROUNDING, vehicleExternalInfo.condition?.odometer?.km, MAX_KM)\n : undefined,\n horsepower: toMinHorsepower(vehicleExternalInfo, -0.1),\n versions:\n vehicleExternalInfo.general.make != null\n ? [\n {\n make: vehicleExternalInfo.general.make,\n models: toArray(vehicleExternalInfo.general.model),\n },\n ]\n : undefined,\n price: toMaxPrice(vehicleExternalInfo.salesConditions.price),\n age: vehicleExternalInfo.condition?.used\n ? toAge(referenceDate, vehicleExternalInfo.history?.advertisingYear)\n : undefined,\n autoGenerated: true,\n };\n};\n\nconst isHeavyVehicle = (vehicleExternalInfo: VehicleExternalInfo) =>\n ['Tractor Head', 'Truck'].includes(vehicleExternalInfo.general.category);\n\nconst toCabins = (values: string[] | undefined): string[] | undefined => {\n if (values == null || values.length === 0) {\n return;\n }\n\n if (values.some((v) => v.startsWith('Sleep'))) {\n // If it allows sleep, then add the two largest sleep options as well\n return uniq([...values, 'Sleep / Medium', 'Sleep / Large']);\n }\n\n return values;\n};\n\nconst toSuspensions = (values: string[] | undefined): string[] | undefined => {\n if (values == null || values.length === 0) {\n return;\n }\n\n if (values.includes('Air/Steel')) {\n // If it allows some axles with air suspension, then allow all\n return uniq([...values, 'Air']);\n }\n\n return values;\n};\n\nconst toTransmissions = (values: string[] | undefined): string[] | undefined => {\n if (values == null || values.length === 0) {\n return;\n }\n\n if (values.includes('Manual')) {\n // ignore transmission restriction\n return;\n }\n\n if (values.includes('Semi-Automatic')) {\n // also consider values that are better\n return uniq([...values, 'Automatic']);\n }\n\n return values;\n};\n\nconst toEuronorms = (vehicleExternalInfo: VehicleExternalInfo): string[] | undefined => {\n const values = toArray(vehicleExternalInfo.powertrain?.emissions?.class);\n if (values == null || values.length === 0 || !isHeavyVehicle(vehicleExternalInfo)) {\n return;\n }\n\n const minEuronorm = 5;\n const maxEuronorm = 6;\n\n const lowestEuronorm = first(values.map((v) => Number(v.charAt(v.length - 1))).sort())!;\n if (lowestEuronorm < minEuronorm) {\n return; // ignore Euronorm restriction\n }\n\n return range(lowestEuronorm, maxEuronorm + 1).map((r) => `Euro ${r}`);\n};\n\nconst toAge = (referenceDate: Date, year?: number) => {\n if (year == null) {\n return;\n }\n\n if (year > referenceDate.getUTCFullYear()) {\n return;\n }\n\n return toRound(1, referenceDate.getUTCFullYear() - year, MAX_AGE);\n};\n\nconst toMaxPrice = (value?: number | string) =>\n value != null ? toRound(PRICE_ROUNDING, Number(value) * 1.15, MAX_PRICE) : undefined;\n\nconst toMinHorsepower = (\n vehicleExternalInfo: VehicleExternalInfo,\n shiftRatio: number\n): number | undefined => {\n const hasHorsepower = vehicleExternalInfo.powertrain?.engine?.power?.hp != null;\n const isHorsepowerImportant = isHeavyVehicle(vehicleExternalInfo);\n\n if (hasHorsepower && isHorsepowerImportant) {\n return toRound(5, vehicleExternalInfo.powertrain!.engine!.power!.hp! * (1 + shiftRatio));\n }\n};\n\nconst toRound = (r: number, value?: number | string, max: number = Infinity) =>\n value != null ? Math.min(Math.ceil(Number(value) / r) * r, max) : undefined;\n\nconst toArray = (value?: string): string[] => (value ? [value] : []);\n"]}
|
package/package.json
CHANGED
package/src/constants.ts
CHANGED
|
@@ -7,6 +7,8 @@ export { BusinessEntityIds } from '@bisondesk/commons-sdk/constants';
|
|
|
7
7
|
//
|
|
8
8
|
export const APP_LANGUAGES_PICKLIST_ID = 'appLanguages';
|
|
9
9
|
export const CLIENT_LANGUAGES_PICKLIST_ID = 'clientLanguages';
|
|
10
|
+
export const CRM_CONTACT_TAGS_PICKLIST_ID = 'crmContactTags';
|
|
11
|
+
export const CRM_ORG_TAGS_PICKLIST_ID = 'crmOrganizationTags';
|
|
10
12
|
export const TIMEZONES_PICKLIST_ID = 'timezones';
|
|
11
13
|
export const COUNTRIES_PICKLIST_ID = 'countries';
|
|
12
14
|
export const VEHICLE_MAIN_FEATURES_PICKLIST_ID = 'vehicleMainFeatures';
|
package/src/types/comparables.ts
CHANGED
package/src/types/crm.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
SearchPermissions,
|
|
6
6
|
} from '@bisondesk/commons-sdk/types';
|
|
7
7
|
import { PublicSearchDefinition } from './definitions.js';
|
|
8
|
+
import { Interest } from './interests.js';
|
|
8
9
|
import { BaseEvent } from './internal-events.js';
|
|
9
10
|
import { ReferenceData } from './utils.js';
|
|
10
11
|
|
|
@@ -109,6 +110,8 @@ type BaseOrganization = {
|
|
|
109
110
|
trustworthy?: boolean;
|
|
110
111
|
// meta
|
|
111
112
|
slbPartner?: boolean;
|
|
113
|
+
|
|
114
|
+
tags?: string[]; // custom tags for the organization
|
|
112
115
|
};
|
|
113
116
|
|
|
114
117
|
export type NewOrganization = BaseOrganization & {
|
|
@@ -165,6 +168,8 @@ export type SearchOrganization = {
|
|
|
165
168
|
lastActivityAt: string | undefined; // last activity at this organization
|
|
166
169
|
lastActivityBy: string | undefined; // user that did the last activity at this organization
|
|
167
170
|
engagementTypes: OrgEngagementType[] | undefined; // types of engagements this organization has in the tenant
|
|
171
|
+
|
|
172
|
+
accountManagers: string[]; // dynamically determined account managers for this organization
|
|
168
173
|
};
|
|
169
174
|
};
|
|
170
175
|
|
|
@@ -177,6 +182,10 @@ export type InputSearchOrganization = SearchOrganization & {
|
|
|
177
182
|
export type SearchContact = {
|
|
178
183
|
contact: Contact;
|
|
179
184
|
org?: Organization;
|
|
185
|
+
interests?: Interest[];
|
|
186
|
+
custom: {
|
|
187
|
+
accountManagers: string[]; // dynamically determined account managers for this contact
|
|
188
|
+
};
|
|
180
189
|
};
|
|
181
190
|
|
|
182
191
|
export type InputSearchContact = SearchContact & {
|
|
@@ -229,6 +238,8 @@ type BaseContact = {
|
|
|
229
238
|
disabledAt?: string;
|
|
230
239
|
disabledBy?: string;
|
|
231
240
|
disabledReason?: string;
|
|
241
|
+
|
|
242
|
+
tags?: string[]; // custom tags for the contact
|
|
232
243
|
};
|
|
233
244
|
|
|
234
245
|
export type NewContact = BaseContact & {
|
package/src/types/interests.ts
CHANGED
|
@@ -23,6 +23,14 @@ export interface OpportunityInterest extends Interest {
|
|
|
23
23
|
organizationId?: string;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
export interface ContactInterest extends Interest {
|
|
27
|
+
contactId: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface OrganizationInterest extends Interest {
|
|
31
|
+
organizationId: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
26
34
|
export interface HdmsInterest extends Interest {
|
|
27
35
|
hdmsSaleId: string;
|
|
28
36
|
}
|
|
@@ -30,6 +38,12 @@ export interface HdmsInterest extends Interest {
|
|
|
30
38
|
export const isOpportunityInterest = (interest: Interest): interest is OpportunityInterest =>
|
|
31
39
|
'opportunityId' in interest;
|
|
32
40
|
|
|
41
|
+
export const isContactInterest = (interest: Interest): interest is ContactInterest =>
|
|
42
|
+
'contactId' in interest && !isOpportunityInterest(interest);
|
|
43
|
+
|
|
44
|
+
export const isOrganizationInterest = (interest: Interest): interest is OrganizationInterest =>
|
|
45
|
+
'organizationId' in interest && !isOpportunityInterest(interest) && !isContactInterest(interest);
|
|
46
|
+
|
|
33
47
|
export type LeadUpdate =
|
|
34
48
|
| {
|
|
35
49
|
dismissed: true;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { EmailDestination } from '@bisondesk/commons-sdk/messages';
|
|
2
|
+
import { AttachmentValue, NextRequest } from '@bisondesk/commons-sdk/types';
|
|
3
|
+
import { SearchRequest } from './search.js';
|
|
4
|
+
|
|
5
|
+
export type CampaignSearchRequest = {
|
|
6
|
+
fullText?: string;
|
|
7
|
+
query: NonNullable<SearchRequest['query']>;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type MarketingEmailCampaign = {
|
|
11
|
+
id: string;
|
|
12
|
+
createdAt: string;
|
|
13
|
+
createdBy: string;
|
|
14
|
+
name: string;
|
|
15
|
+
|
|
16
|
+
vehicleIds: string[];
|
|
17
|
+
subject: string;
|
|
18
|
+
message: string;
|
|
19
|
+
pictures?: AttachmentValue[];
|
|
20
|
+
|
|
21
|
+
targets: {
|
|
22
|
+
emails?: EmailDestination[];
|
|
23
|
+
queries?: CampaignSearchRequest[];
|
|
24
|
+
leads?: boolean;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
runAt?: string;
|
|
28
|
+
// determined on the moment of sending by merging all the targets
|
|
29
|
+
fullEmailList?: string[];
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type MarketingCampaignSentEmail = {
|
|
33
|
+
campaignId: string;
|
|
34
|
+
contactId?: string;
|
|
35
|
+
email: string;
|
|
36
|
+
runAt: string;
|
|
37
|
+
|
|
38
|
+
sentAt?: string;
|
|
39
|
+
deliveredAt?: string;
|
|
40
|
+
bouncedAt?: string;
|
|
41
|
+
complaintAt?: string;
|
|
42
|
+
openedAt?: string;
|
|
43
|
+
clickedAt?: string;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export type MarketingCampaignEmailEvent = {
|
|
47
|
+
tenantId: string;
|
|
48
|
+
campaignId: string;
|
|
49
|
+
email: string;
|
|
50
|
+
runAt: string;
|
|
51
|
+
contactId?: string;
|
|
52
|
+
name?: string;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export type MarketingCampaignStatistics = {
|
|
56
|
+
totalEmails: number;
|
|
57
|
+
successfulDeliveries: number;
|
|
58
|
+
bouncedEmails: number;
|
|
59
|
+
sentEmails: number;
|
|
60
|
+
complaints: number;
|
|
61
|
+
openedEmails: number;
|
|
62
|
+
clickedEmails: number;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export type SentEmailsSearchRequest = NextRequest & {
|
|
66
|
+
fullText?: string;
|
|
67
|
+
};
|
package/src/types/marketing.ts
CHANGED
|
@@ -7,7 +7,7 @@ export enum MarketingPlatform {
|
|
|
7
7
|
machineryplanet = 'machineryplanet',
|
|
8
8
|
machinetrack = 'machinetrack',
|
|
9
9
|
marktnet = 'marktnet',
|
|
10
|
-
mobile = 'mobile',
|
|
10
|
+
// mobile = 'mobile',
|
|
11
11
|
truck1st = 'truck1st', // Truck1.eu
|
|
12
12
|
trucks = 'trucks', //Trucks.nl
|
|
13
13
|
truckscout = 'truckscout24',
|
package/src/types/tenants.ts
CHANGED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { isoString } from '@bisondesk/commons-sdk/date-utils';
|
|
2
|
+
import { generateId } from '@bisondesk/commons-sdk/ids';
|
|
3
|
+
import { UTCDate } from '@date-fns/utc';
|
|
4
|
+
import { first, range, uniq } from 'lodash-es';
|
|
5
|
+
import { KM_ROUNDING, MAX_AGE, MAX_KM, MAX_PRICE, PRICE_ROUNDING } from '../constants.js';
|
|
6
|
+
import { Interest } from '../types/interests.js';
|
|
7
|
+
import { VehicleExternalInfo } from '../types/vehicles.js';
|
|
8
|
+
|
|
9
|
+
export const mapVehicleToInterest = (
|
|
10
|
+
userId: string,
|
|
11
|
+
vehicleExternalInfo: VehicleExternalInfo,
|
|
12
|
+
referenceDate: Date = new UTCDate()
|
|
13
|
+
): Interest => {
|
|
14
|
+
return {
|
|
15
|
+
id: generateId(),
|
|
16
|
+
createdAt: isoString(),
|
|
17
|
+
createdBy: userId,
|
|
18
|
+
modifiedAt: isoString(),
|
|
19
|
+
modifiedBy: userId,
|
|
20
|
+
bodystyle: vehicleExternalInfo.general.bodystyle,
|
|
21
|
+
cabins: toCabins(toArray(vehicleExternalInfo.body?.cabin?.type)),
|
|
22
|
+
category: vehicleExternalInfo.general.category,
|
|
23
|
+
retarderIntarder: vehicleExternalInfo.accessories.retarderIntarder ? true : undefined,
|
|
24
|
+
adr: vehicleExternalInfo.accessories.adr,
|
|
25
|
+
damaged: vehicleExternalInfo.condition?.damaged ?? false,
|
|
26
|
+
extended: toArray(vehicleExternalInfo.superstructure?.dimensions?.extended),
|
|
27
|
+
heightened: toArray(vehicleExternalInfo.superstructure?.dimensions?.heightened),
|
|
28
|
+
used: vehicleExternalInfo.condition?.used,
|
|
29
|
+
crane: vehicleExternalInfo.superstructure?.crane?.present,
|
|
30
|
+
tailgate: vehicleExternalInfo.superstructure?.tailgate?.present,
|
|
31
|
+
axleConfigurations: toArray(vehicleExternalInfo.powertrain?.axles?.configuration),
|
|
32
|
+
suspensions: toSuspensions(toArray(vehicleExternalInfo.powertrain?.axles?.suspension)),
|
|
33
|
+
transmissions: toTransmissions(toArray(vehicleExternalInfo.powertrain?.transmission?.type)),
|
|
34
|
+
euronorms: toEuronorms(vehicleExternalInfo),
|
|
35
|
+
kilometers: vehicleExternalInfo.condition?.used
|
|
36
|
+
? toRound(KM_ROUNDING, vehicleExternalInfo.condition?.odometer?.km, MAX_KM)
|
|
37
|
+
: undefined,
|
|
38
|
+
horsepower: toMinHorsepower(vehicleExternalInfo, -0.1),
|
|
39
|
+
versions:
|
|
40
|
+
vehicleExternalInfo.general.make != null
|
|
41
|
+
? [
|
|
42
|
+
{
|
|
43
|
+
make: vehicleExternalInfo.general.make,
|
|
44
|
+
models: toArray(vehicleExternalInfo.general.model),
|
|
45
|
+
},
|
|
46
|
+
]
|
|
47
|
+
: undefined,
|
|
48
|
+
price: toMaxPrice(vehicleExternalInfo.salesConditions.price),
|
|
49
|
+
age: vehicleExternalInfo.condition?.used
|
|
50
|
+
? toAge(referenceDate, vehicleExternalInfo.history?.advertisingYear)
|
|
51
|
+
: undefined,
|
|
52
|
+
autoGenerated: true,
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const isHeavyVehicle = (vehicleExternalInfo: VehicleExternalInfo) =>
|
|
57
|
+
['Tractor Head', 'Truck'].includes(vehicleExternalInfo.general.category);
|
|
58
|
+
|
|
59
|
+
const toCabins = (values: string[] | undefined): string[] | undefined => {
|
|
60
|
+
if (values == null || values.length === 0) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (values.some((v) => v.startsWith('Sleep'))) {
|
|
65
|
+
// If it allows sleep, then add the two largest sleep options as well
|
|
66
|
+
return uniq([...values, 'Sleep / Medium', 'Sleep / Large']);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return values;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const toSuspensions = (values: string[] | undefined): string[] | undefined => {
|
|
73
|
+
if (values == null || values.length === 0) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (values.includes('Air/Steel')) {
|
|
78
|
+
// If it allows some axles with air suspension, then allow all
|
|
79
|
+
return uniq([...values, 'Air']);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return values;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const toTransmissions = (values: string[] | undefined): string[] | undefined => {
|
|
86
|
+
if (values == null || values.length === 0) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (values.includes('Manual')) {
|
|
91
|
+
// ignore transmission restriction
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (values.includes('Semi-Automatic')) {
|
|
96
|
+
// also consider values that are better
|
|
97
|
+
return uniq([...values, 'Automatic']);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return values;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const toEuronorms = (vehicleExternalInfo: VehicleExternalInfo): string[] | undefined => {
|
|
104
|
+
const values = toArray(vehicleExternalInfo.powertrain?.emissions?.class);
|
|
105
|
+
if (values == null || values.length === 0 || !isHeavyVehicle(vehicleExternalInfo)) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const minEuronorm = 5;
|
|
110
|
+
const maxEuronorm = 6;
|
|
111
|
+
|
|
112
|
+
const lowestEuronorm = first(values.map((v) => Number(v.charAt(v.length - 1))).sort())!;
|
|
113
|
+
if (lowestEuronorm < minEuronorm) {
|
|
114
|
+
return; // ignore Euronorm restriction
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return range(lowestEuronorm, maxEuronorm + 1).map((r) => `Euro ${r}`);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const toAge = (referenceDate: Date, year?: number) => {
|
|
121
|
+
if (year == null) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (year > referenceDate.getUTCFullYear()) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return toRound(1, referenceDate.getUTCFullYear() - year, MAX_AGE);
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const toMaxPrice = (value?: number | string) =>
|
|
133
|
+
value != null ? toRound(PRICE_ROUNDING, Number(value) * 1.15, MAX_PRICE) : undefined;
|
|
134
|
+
|
|
135
|
+
const toMinHorsepower = (
|
|
136
|
+
vehicleExternalInfo: VehicleExternalInfo,
|
|
137
|
+
shiftRatio: number
|
|
138
|
+
): number | undefined => {
|
|
139
|
+
const hasHorsepower = vehicleExternalInfo.powertrain?.engine?.power?.hp != null;
|
|
140
|
+
const isHorsepowerImportant = isHeavyVehicle(vehicleExternalInfo);
|
|
141
|
+
|
|
142
|
+
if (hasHorsepower && isHorsepowerImportant) {
|
|
143
|
+
return toRound(5, vehicleExternalInfo.powertrain!.engine!.power!.hp! * (1 + shiftRatio));
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const toRound = (r: number, value?: number | string, max: number = Infinity) =>
|
|
148
|
+
value != null ? Math.min(Math.ceil(Number(value) / r) * r, max) : undefined;
|
|
149
|
+
|
|
150
|
+
const toArray = (value?: string): string[] => (value ? [value] : []);
|