@bisondesk/core-sdk 1.0.627 → 1.0.628
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/apis/opportunities.d.ts +2 -0
- package/lib/apis/opportunities.d.ts.map +1 -1
- package/lib/apis/opportunities.js +12 -0
- package/lib/apis/opportunities.js.map +1 -1
- package/lib/apis/opportunities.test.d.ts +2 -0
- package/lib/apis/opportunities.test.d.ts.map +1 -0
- package/lib/apis/opportunities.test.js +53 -0
- package/lib/apis/opportunities.test.js.map +1 -0
- package/lib/types/internet-opportunities.d.ts +1 -1
- package/lib/types/internet-opportunities.d.ts.map +1 -1
- package/lib/types/internet-opportunities.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.map +1 -1
- package/lib/utils/tenants.d.ts +1 -0
- package/lib/utils/tenants.d.ts.map +1 -1
- package/lib/utils/tenants.js +1 -0
- package/lib/utils/tenants.js.map +1 -1
- package/lib/utils/vehicles.d.ts +1 -0
- package/lib/utils/vehicles.d.ts.map +1 -1
- package/lib/utils/vehicles.js +1 -0
- package/lib/utils/vehicles.js.map +1 -1
- package/package.json +1 -1
- package/src/apis/opportunities.test.ts +68 -0
- package/src/apis/opportunities.ts +14 -0
- package/src/types/internet-opportunities.ts +1 -1
- package/src/types/tenants.ts +4 -0
- package/src/utils/tenants.ts +4 -0
- package/src/utils/vehicles.ts +10 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/src/types/activities.js +0 -13
- package/src/types/activities.js.map +0 -1
- package/src/types/comparables.js +0 -2
- package/src/types/comparables.js.map +0 -1
- package/src/types/crm.js +0 -58
- package/src/types/crm.js.map +0 -1
- package/src/types/dashboard.js +0 -2
- package/src/types/dashboard.js.map +0 -1
- package/src/types/definitions.js +0 -2
- package/src/types/definitions.js.map +0 -1
- package/src/types/fields.js +0 -2
- package/src/types/fields.js.map +0 -1
- package/src/types/insights.js +0 -2
- package/src/types/insights.js.map +0 -1
- package/src/types/interests.js +0 -6
- package/src/types/interests.js.map +0 -1
- package/src/types/internal-events.js +0 -18
- package/src/types/internal-events.js.map +0 -1
- package/src/types/internet-opportunities.js +0 -2
- package/src/types/internet-opportunities.js.map +0 -1
- package/src/types/internet-vehicles.js +0 -2
- package/src/types/internet-vehicles.js.map +0 -1
- package/src/types/leasing-administration.js +0 -2
- package/src/types/leasing-administration.js.map +0 -1
- package/src/types/leasing-debtors.js +0 -2
- package/src/types/leasing-debtors.js.map +0 -1
- package/src/types/leasing-search.js +0 -2
- package/src/types/leasing-search.js.map +0 -1
- package/src/types/leasing-settings.js +0 -7
- package/src/types/leasing-settings.js.map +0 -1
- package/src/types/leasing.js +0 -38
- package/src/types/leasing.js.map +0 -1
- package/src/types/marketing.js +0 -35
- package/src/types/marketing.js.map +0 -1
- package/src/types/offers.js +0 -56
- package/src/types/opportunities.js +0 -107
- package/src/types/opportunities.js.map +0 -1
- package/src/types/payments.js +0 -7
- package/src/types/picklists.js +0 -2
- package/src/types/picklists.js.map +0 -1
- package/src/types/quotes.js +0 -42
- package/src/types/recently-viewed.js +0 -2
- package/src/types/recently-viewed.js.map +0 -1
- package/src/types/reservations.js +0 -5
- package/src/types/reservations.js.map +0 -1
- package/src/types/roi-ratings.js +0 -5
- package/src/types/roi-ratings.js.map +0 -1
- package/src/types/saved-filters.js +0 -9
- package/src/types/saved-filters.js.map +0 -1
- package/src/types/search.js +0 -2
- package/src/types/search.js.map +0 -1
- package/src/types/settings.js +0 -2
- package/src/types/settings.js.map +0 -1
- package/src/types/templates.js +0 -2
- package/src/types/templates.js.map +0 -1
- package/src/types/tenants.js +0 -21
- package/src/types/tenants.js.map +0 -1
- package/src/types/user-performance.js +0 -7
- package/src/types/user-performance.js.map +0 -1
- package/src/types/utils.js +0 -2
- package/src/types/validation.js +0 -2
- package/src/types/validation.js.map +0 -1
- package/src/types/vehicle-sales.js +0 -6
- package/src/types/vehicle-sales.js.map +0 -1
- package/src/types/vehicles.js +0 -98
- package/src/types/vehicles.js.map +0 -1
- package/src/utils/leasing.js +0 -6
- package/src/utils/leasing.js.map +0 -1
- package/src/utils/opportunities.js +0 -48
- package/src/utils/opportunities.js.map +0 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { InternetOpportunityEvent } from '../types/internet-opportunities.js';
|
|
1
2
|
import { Bid, ListOpportunitiesFilters, NewBid, NewOpportunity, Opportunity, OpportunityBFF, OpportunityUpdate } from '../types/opportunities.js';
|
|
2
3
|
import { LeasingQuoteParams } from '../types/quote-settings.js';
|
|
3
4
|
import { Quote } from '../types/quotes.js';
|
|
@@ -7,6 +8,7 @@ export declare const getOpportunityById: (tenantId: string, opportunityId: strin
|
|
|
7
8
|
export declare const getOpportunityBff: (tenantId: string, opportunityId: string) => Promise<OpportunityBFF | undefined>;
|
|
8
9
|
export declare const updateOpportunity: (tenantId: string, opportunity: OpportunityUpdate, opportunityId: string) => Promise<OpportunityBFF | undefined>;
|
|
9
10
|
export declare const createOpportunity: (tenantId: string, opportunity: NewOpportunity) => Promise<Opportunity>;
|
|
11
|
+
export declare const createInternetOpportunity: (event: InternetOpportunityEvent) => Promise<void>;
|
|
10
12
|
export declare const createBid: (tenantId: string, bid: NewBid) => Promise<Bid>;
|
|
11
13
|
export declare const getLeasingQuoteParams: (tenantId: string, settingId: string) => Promise<LeasingQuoteParams | undefined>;
|
|
12
14
|
export declare const getQuoteById: (tenantId: string, quoteId: string) => Promise<Quote | undefined>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opportunities.d.ts","sourceRoot":"/","sources":["apis/opportunities.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,GAAG,EACH,wBAAwB,EACxB,MAAM,EACN,cAAc,EACd,WAAW,EACX,cAAc,EACd,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,eAAO,MAAM,iBAAiB,GAC5B,UAAU,MAAM,EAChB,gBAAe,wBAA6B,KAC3C,OAAO,CAAC,WAAW,EAAE,CAgBvB,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,UAAU,MAAM,EAChB,eAAe,MAAM,KACpB,OAAO,CAAC,WAAW,GAAG,SAAS,CAQjC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,UAAU,MAAM,EAChB,eAAe,MAAM,KACpB,OAAO,CAAC,cAAc,GAAG,SAAS,CAQpC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,UAAU,MAAM,EAChB,aAAa,iBAAiB,EAC9B,eAAe,MAAM,KACpB,OAAO,CAAC,cAAc,GAAG,SAAS,CAUpC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,UAAU,MAAM,EAChB,aAAa,cAAc,KAC1B,OAAO,CAAC,WAAW,CAoBrB,CAAC;AAKF,eAAO,MAAM,SAAS,GAAU,UAAU,MAAM,EAAE,KAAK,MAAM,KAAG,OAAO,CAAC,GAAG,CAiB1E,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,UAAU,MAAM,EAChB,WAAW,MAAM,KAChB,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAWxC,CAAC;AAKF,eAAO,MAAM,YAAY,GACvB,UAAU,MAAM,EAChB,SAAS,MAAM,KACd,OAAO,CAAC,KAAK,GAAG,SAAS,CAQ3B,CAAC;AAKF,eAAO,MAAM,yBAAyB,GACpC,UAAU,MAAM,EAChB,WAAW,MAAM,KAChB,OAAO,CAAC,sBAAsB,GAAG,SAAS,CAW5C,CAAC"}
|
|
1
|
+
{"version":3,"file":"opportunities.d.ts","sourceRoot":"/","sources":["apis/opportunities.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,OAAO,EACL,GAAG,EACH,wBAAwB,EACxB,MAAM,EACN,cAAc,EACd,WAAW,EACX,cAAc,EACd,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,eAAO,MAAM,iBAAiB,GAC5B,UAAU,MAAM,EAChB,gBAAe,wBAA6B,KAC3C,OAAO,CAAC,WAAW,EAAE,CAgBvB,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,UAAU,MAAM,EAChB,eAAe,MAAM,KACpB,OAAO,CAAC,WAAW,GAAG,SAAS,CAQjC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,UAAU,MAAM,EAChB,eAAe,MAAM,KACpB,OAAO,CAAC,cAAc,GAAG,SAAS,CAQpC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,UAAU,MAAM,EAChB,aAAa,iBAAiB,EAC9B,eAAe,MAAM,KACpB,OAAO,CAAC,cAAc,GAAG,SAAS,CAUpC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,UAAU,MAAM,EAChB,aAAa,cAAc,KAC1B,OAAO,CAAC,WAAW,CAoBrB,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAU,OAAO,wBAAwB,KAAG,OAAO,CAAC,IAAI,CAW7F,CAAC;AAKF,eAAO,MAAM,SAAS,GAAU,UAAU,MAAM,EAAE,KAAK,MAAM,KAAG,OAAO,CAAC,GAAG,CAiB1E,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,UAAU,MAAM,EAChB,WAAW,MAAM,KAChB,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAWxC,CAAC;AAKF,eAAO,MAAM,YAAY,GACvB,UAAU,MAAM,EAChB,SAAS,MAAM,KACd,OAAO,CAAC,KAAK,GAAG,SAAS,CAQ3B,CAAC;AAKF,eAAO,MAAM,yBAAyB,GACpC,UAAU,MAAM,EAChB,WAAW,MAAM,KAChB,OAAO,CAAC,sBAAsB,GAAG,SAAS,CAW5C,CAAC"}
|
|
@@ -58,6 +58,18 @@ export const createOpportunity = async (tenantId, opportunity) => {
|
|
|
58
58
|
}
|
|
59
59
|
return response;
|
|
60
60
|
};
|
|
61
|
+
export const createInternetOpportunity = async (event) => {
|
|
62
|
+
const auth = await getAdminAuth();
|
|
63
|
+
await fetchJson(`${process.env.CORE_API_ORIGIN}/api/opportunities/internet`, {
|
|
64
|
+
method: 'POST',
|
|
65
|
+
headers: cleanHeaders({
|
|
66
|
+
Authorization: auth,
|
|
67
|
+
[TENANT_ID_ADMIN_HEADER]: event.tenantId,
|
|
68
|
+
'Content-Type': 'application/json',
|
|
69
|
+
}),
|
|
70
|
+
body: JSON.stringify(event),
|
|
71
|
+
});
|
|
72
|
+
};
|
|
61
73
|
export const createBid = async (tenantId, bid) => {
|
|
62
74
|
const auth = await getAdminAuth();
|
|
63
75
|
const response = await fetchJson(`${process.env.CORE_API_ORIGIN}/api/bids`, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opportunities.js","sourceRoot":"/","sources":["apis/opportunities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"opportunities.js","sourceRoot":"/","sources":["apis/opportunities.ts"],"names":[],"mappings":"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","sourcesContent":["import { TENANT_ID_ADMIN_HEADER } from '@bisondesk/commons-sdk/constants';\nimport { cleanHeaders, fetchJson, getAdminAuth } from '@bisondesk/commons-sdk/fetch';\nimport { InternetOpportunityEvent } from '../types/internet-opportunities.js';\nimport {\n Bid,\n ListOpportunitiesFilters,\n NewBid,\n NewOpportunity,\n Opportunity,\n OpportunityBFF,\n OpportunityUpdate,\n} from '../types/opportunities.js';\nimport { LeasingQuoteParams } from '../types/quote-settings.js';\nimport { Quote } from '../types/quotes.js';\nimport { OpportunityReservation } from '../types/reservations.js';\n\nexport const listOpportunities = async (\n tenantId: string,\n filterOptions: ListOpportunitiesFilters = {},\n): Promise<Opportunity[]> => {\n const auth = await getAdminAuth();\n const result = await fetchJson<Opportunity[]>(\n `${process.env.CORE_API_ORIGIN}/api/opportunities/list`,\n {\n method: 'POST',\n headers: cleanHeaders({\n Authorization: auth,\n [TENANT_ID_ADMIN_HEADER]: tenantId,\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify(filterOptions),\n },\n );\n\n return result ?? [];\n};\n\nexport const getOpportunityById = async (\n tenantId: string,\n opportunityId: string,\n): Promise<Opportunity | undefined> => {\n const auth = await getAdminAuth();\n return fetchJson(`${process.env.CORE_API_ORIGIN}/api/opportunities/${opportunityId}`, {\n headers: cleanHeaders({\n Authorization: auth,\n [TENANT_ID_ADMIN_HEADER]: tenantId,\n }),\n });\n};\n\nexport const getOpportunityBff = async (\n tenantId: string,\n opportunityId: string,\n): Promise<OpportunityBFF | undefined> => {\n const auth = await getAdminAuth();\n return fetchJson(`${process.env.CORE_API_ORIGIN}/api/opportunities/${opportunityId}/bff`, {\n headers: cleanHeaders({\n Authorization: auth,\n [TENANT_ID_ADMIN_HEADER]: tenantId,\n }),\n });\n};\n\nexport const updateOpportunity = async (\n tenantId: string,\n opportunity: OpportunityUpdate,\n opportunityId: string,\n): Promise<OpportunityBFF | undefined> => {\n const auth = await getAdminAuth();\n return fetchJson(`${process.env.CORE_API_ORIGIN}/api/opportunities/${opportunityId}`, {\n method: 'PATCH',\n headers: cleanHeaders({\n Authorization: auth,\n [TENANT_ID_ADMIN_HEADER]: tenantId,\n }),\n body: JSON.stringify(opportunity),\n });\n};\n\nexport const createOpportunity = async (\n tenantId: string,\n opportunity: NewOpportunity,\n): Promise<Opportunity> => {\n const auth = await getAdminAuth();\n const response: Opportunity | undefined = await fetchJson(\n `${process.env.CORE_API_ORIGIN}/api/opportunities`,\n {\n method: 'POST',\n headers: cleanHeaders({\n Authorization: auth,\n [TENANT_ID_ADMIN_HEADER]: tenantId,\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify(opportunity),\n },\n );\n\n if (response == null) {\n throw new Error('Opportunity not created');\n }\n\n return response;\n};\n\nexport const createInternetOpportunity = async (event: InternetOpportunityEvent): Promise<void> => {\n const auth = await getAdminAuth();\n await fetchJson(`${process.env.CORE_API_ORIGIN}/api/opportunities/internet`, {\n method: 'POST',\n headers: cleanHeaders({\n Authorization: auth,\n [TENANT_ID_ADMIN_HEADER]: event.tenantId,\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify(event),\n });\n};\n\n//\n// Bids\n//\nexport const createBid = async (tenantId: string, bid: NewBid): Promise<Bid> => {\n const auth = await getAdminAuth();\n const response: Bid | undefined = await fetchJson(`${process.env.CORE_API_ORIGIN}/api/bids`, {\n method: 'POST',\n headers: cleanHeaders({\n Authorization: auth,\n [TENANT_ID_ADMIN_HEADER]: tenantId,\n 'Content-Type': 'application/json',\n }),\n body: JSON.stringify(bid),\n });\n\n if (response == null) {\n throw new Error('Bid not created');\n }\n\n return response;\n};\n\nexport const getLeasingQuoteParams = async (\n tenantId: string,\n settingId: string,\n): Promise<LeasingQuoteParams | undefined> => {\n const auth = await getAdminAuth();\n return fetchJson(\n `${process.env.CORE_API_ORIGIN}/api/leasing/administration/settings/quote-params/${settingId}`,\n {\n headers: cleanHeaders({\n Authorization: auth,\n [TENANT_ID_ADMIN_HEADER]: tenantId,\n }),\n },\n );\n};\n\n//\n// Quotes\n//\nexport const getQuoteById = async (\n tenantId: string,\n quoteId: string,\n): Promise<Quote | undefined> => {\n const auth = await getAdminAuth();\n return fetchJson(`${process.env.CORE_API_ORIGIN}/api/quotes/${quoteId}`, {\n headers: cleanHeaders({\n Authorization: auth,\n [TENANT_ID_ADMIN_HEADER]: tenantId,\n }),\n });\n};\n\n//\n// Vehicle Reservation\n//\nexport const getReservationByVehicleId = async (\n tenantId: string,\n vehicleId: string,\n): Promise<OpportunityReservation | undefined> => {\n const auth = await getAdminAuth();\n return fetchJson(\n `${process.env.CORE_API_ORIGIN}/api/opportunities/vehicle/${vehicleId}/reservation`,\n {\n headers: cleanHeaders({\n Authorization: auth,\n [TENANT_ID_ADMIN_HEADER]: tenantId,\n }),\n },\n );\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opportunities.test.d.ts","sourceRoot":"/","sources":["apis/opportunities.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { TENANT_ID_ADMIN_HEADER } from '@bisondesk/commons-sdk/constants';
|
|
2
|
+
import { XError } from '@bisondesk/commons-sdk/errors';
|
|
3
|
+
import { createInternetOpportunity } from './opportunities.js';
|
|
4
|
+
const ADMIN_KEY = 'test-admin-key';
|
|
5
|
+
const ORIGIN = 'https://core.example.com';
|
|
6
|
+
const event = {
|
|
7
|
+
tenantId: 'ttc',
|
|
8
|
+
branchId: 'ttc-nl',
|
|
9
|
+
name: 'John Doe',
|
|
10
|
+
phoneNumber: '+31612345678',
|
|
11
|
+
source: 'website',
|
|
12
|
+
};
|
|
13
|
+
const mockFetch = vi.fn();
|
|
14
|
+
const okResponse = () => ({
|
|
15
|
+
ok: true,
|
|
16
|
+
status: 202,
|
|
17
|
+
json: async () => ({ queued: true }),
|
|
18
|
+
});
|
|
19
|
+
const errorResponse = (status, statusText) => ({
|
|
20
|
+
ok: false,
|
|
21
|
+
status,
|
|
22
|
+
statusText,
|
|
23
|
+
text: async () => statusText,
|
|
24
|
+
});
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
vi.resetAllMocks();
|
|
27
|
+
vi.stubGlobal('fetch', mockFetch);
|
|
28
|
+
process.env.ADMIN_KEY = ADMIN_KEY;
|
|
29
|
+
process.env.CORE_API_ORIGIN = ORIGIN;
|
|
30
|
+
});
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
vi.unstubAllGlobals();
|
|
33
|
+
});
|
|
34
|
+
describe('createInternetOpportunity', () => {
|
|
35
|
+
test('POSTs to /api/opportunities/internet with admin auth + tenant headers and JSON body', async () => {
|
|
36
|
+
mockFetch.mockResolvedValueOnce(okResponse());
|
|
37
|
+
await createInternetOpportunity(event);
|
|
38
|
+
expect(mockFetch).toHaveBeenCalledTimes(1);
|
|
39
|
+
const [url, init] = mockFetch.mock.calls[0];
|
|
40
|
+
expect(url.toString()).toBe(`${ORIGIN}/api/opportunities/internet`);
|
|
41
|
+
expect(init.method).toBe('POST');
|
|
42
|
+
expect(init.body).toBe(JSON.stringify(event));
|
|
43
|
+
const headers = Object.fromEntries(init.headers);
|
|
44
|
+
expect(headers.Authorization).toBe(`AdminKey ${ADMIN_KEY}`);
|
|
45
|
+
expect(headers['Content-Type']).toBe('application/json');
|
|
46
|
+
expect(headers[TENANT_ID_ADMIN_HEADER]).toBe(event.tenantId);
|
|
47
|
+
});
|
|
48
|
+
test('throws XError when the response is a non-2xx', async () => {
|
|
49
|
+
mockFetch.mockResolvedValueOnce(errorResponse(500, 'Internal Server Error'));
|
|
50
|
+
await expect(createInternetOpportunity(event)).rejects.toBeInstanceOf(XError);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=opportunities.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opportunities.test.js","sourceRoot":"/","sources":["apis/opportunities.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { TENANT_ID_ADMIN_HEADER } from '@bisondesk/commons-sdk/constants';\nimport { XError } from '@bisondesk/commons-sdk/errors';\nimport { InternetOpportunityEvent } from '../types/internet-opportunities.js';\nimport { createInternetOpportunity } from './opportunities.js';\n\nconst ADMIN_KEY = 'test-admin-key';\nconst ORIGIN = 'https://core.example.com';\n\nconst event: InternetOpportunityEvent = {\n tenantId: 'ttc',\n branchId: 'ttc-nl',\n name: 'John Doe',\n phoneNumber: '+31612345678',\n source: 'website',\n};\n\nconst mockFetch = vi.fn();\n\nconst okResponse = (): Response =>\n ({\n ok: true,\n status: 202,\n json: async () => ({ queued: true }),\n }) as unknown as Response;\n\nconst errorResponse = (status: number, statusText: string): Response =>\n ({\n ok: false,\n status,\n statusText,\n text: async () => statusText,\n }) as unknown as Response;\n\nbeforeEach(() => {\n vi.resetAllMocks();\n vi.stubGlobal('fetch', mockFetch);\n process.env.ADMIN_KEY = ADMIN_KEY;\n process.env.CORE_API_ORIGIN = ORIGIN;\n});\n\nafterEach(() => {\n vi.unstubAllGlobals();\n});\n\ndescribe('createInternetOpportunity', () => {\n test('POSTs to /api/opportunities/internet with admin auth + tenant headers and JSON body', async () => {\n mockFetch.mockResolvedValueOnce(okResponse());\n\n await createInternetOpportunity(event);\n\n expect(mockFetch).toHaveBeenCalledTimes(1);\n const [url, init] = mockFetch.mock.calls[0];\n expect(url.toString()).toBe(`${ORIGIN}/api/opportunities/internet`);\n expect(init.method).toBe('POST');\n expect(init.body).toBe(JSON.stringify(event));\n\n const headers = Object.fromEntries(init.headers as [string, string][]);\n expect(headers.Authorization).toBe(`AdminKey ${ADMIN_KEY}`);\n expect(headers['Content-Type']).toBe('application/json');\n expect(headers[TENANT_ID_ADMIN_HEADER]).toBe(event.tenantId);\n });\n\n test('throws XError when the response is a non-2xx', async () => {\n mockFetch.mockResolvedValueOnce(errorResponse(500, 'Internal Server Error'));\n\n await expect(createInternetOpportunity(event)).rejects.toBeInstanceOf(XError);\n });\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internet-opportunities.d.ts","sourceRoot":"/","sources":["types/internet-opportunities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,KAAK,uBAAuB,GAAG;IAE7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"internet-opportunities.d.ts","sourceRoot":"/","sources":["types/internet-opportunities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,KAAK,uBAAuB,GAAG;IAE7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IAGtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,uBAAuB,GAAG;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,uBAAuB,GAAG;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,gBAAgB,CAAC;CAChC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internet-opportunities.js","sourceRoot":"/","sources":["types/internet-opportunities.ts"],"names":[],"mappings":"","sourcesContent":["import { PhoneNumberValue } from '@bisondesk/commons-sdk/types';\nimport { OpportunityType } from '../constants.js';\n\ntype BaseInternetOpportunity = {\n // ids\n tenantId: string;\n branchId: string;\n emailId
|
|
1
|
+
{"version":3,"file":"internet-opportunities.js","sourceRoot":"/","sources":["types/internet-opportunities.ts"],"names":[],"mappings":"","sourcesContent":["import { PhoneNumberValue } from '@bisondesk/commons-sdk/types';\nimport { OpportunityType } from '../constants.js';\n\ntype BaseInternetOpportunity = {\n // ids\n tenantId: string;\n branchId: string;\n emailId?: string;\n\n // raw data\n emailHtml?: string;\n emailSubject?: string;\n\n // extracted opportunity data\n bid?: number;\n countryCode?: string;\n email?: string;\n firstName?: string;\n language?: string;\n lastName?: string;\n message?: string;\n name: string;\n source: string;\n stockNumber?: string;\n type?: OpportunityType;\n vehicleBid?: string;\n};\n\nexport type InternetOpportunityEvent = BaseInternetOpportunity & {\n phoneNumber?: string;\n replyToEmail?: string;\n fromEmail?: string;\n};\n\nexport type InternetOpportunity = BaseInternetOpportunity & {\n platformEmail?: string;\n phoneNumber?: PhoneNumberValue;\n};\n"]}
|
package/lib/types/tenants.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenants.d.ts","sourceRoot":"/","sources":["types/tenants.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"tenants.d.ts","sourceRoot":"/","sources":["types/tenants.ts"],"names":[],"mappings":"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"}
|
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,YAsBX;AAtBD,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;IACf,8DAA8C,CAAA;IAC9C,uCAAuB,CAAA;IACvB,mCAAmB,CAAA;IACnB,uCAAuB,CAAA;AACzB,CAAC,EAtBW,YAAY,KAAZ,YAAY,QAsBvB;AAGD,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,WAAW,CAAU,CAAC","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 DeliveryConfirmation = 'delivery_confirmation',\n Transport = 'transport',\n Reports = 'reports',\n Prospects = 'prospects',\n}\n\n/** Report tabs a tenant can enable, in canonical order. */\nexport const REPORT_TAB_KEYS = ['sales', 'leasing', 'purchases'] as const;\n\nexport type ReportTabKey = (typeof REPORT_TAB_KEYS)[number];\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 /**\n * Reports page configuration. `tabs` lists the visible tabs in display order;\n * absent or empty means no reports are configured for the tenant (the page\n * shows a notice instead of tabs).\n */\n reports?: {\n tabs: ReportTabKey[];\n };\n test?: boolean;\n opportunities: {\n types: OpportunityType[];\n };\n /**\n * Reservation expiry for this tenant's OWN vehicles (ADR-0026): the truck's owner sets the\n * clock, wherever the deal runs — for a cross-tenant copy the chain origin's policy\n * applies, whatever opportunity type the tenant selling to the end customer uses.\n * Absent = the default\n * business-day tiers; the tier is still picked by the local customer org's\n * trustworthy/conglomerate flags.\n */\n reservationExpiry?: ReservationExpiryPolicy;\n crm?: {\n vatNumberRequiredForCompanies?: boolean;\n };\n accounting?: {\n costCenterPerLine?: boolean;\n };\n // E.164 Twilio caller ID used as a fallback when a user has no own number configured\n defaultTwilioPhoneNumber?: string;\n deliveryEmail?: string;\n};\n\nexport type ReservationExpiryPolicy =\n | { policy: 'disabled' }\n | { policy: 'days'; generic: number; trustworthy: number; conglomerate: number };\n\nexport type AccountingProvider = 'exact' | 'odoo';\n\nexport type Branch = {\n id: string;\n name: string;\n country: string;\n language: string;\n /* deprecated — use `accounting === 'exact'` instead. Kept until prod cutover. */\n exactAccounting?: boolean;\n accounting?: AccountingProvider;\n currency: string;\n adminNumberPrefix: string;\n stockNumberPrefix: string;\n vatNumber: string;\n contactPerson?: { firstName: string; lastName: string };\n vatRates: {\n standard: string; //percentage value (e.g. 21)\n };\n location: LocationValue;\n\n storecoveExternalId?: number;\n externalQuote?: boolean;\n hyperdmsId?: string;\n internalDealsEnabled?: boolean;\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"]}
|
|
1
|
+
{"version":3,"file":"tenants.js","sourceRoot":"/","sources":["types/tenants.ts"],"names":[],"mappings":"AAgBA,MAAM,CAAN,IAAY,YAsBX;AAtBD,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;IACf,8DAA8C,CAAA;IAC9C,uCAAuB,CAAA;IACvB,mCAAmB,CAAA;IACnB,uCAAuB,CAAA;AACzB,CAAC,EAtBW,YAAY,KAAZ,YAAY,QAsBvB;AAGD,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,WAAW,CAAU,CAAC","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 DeliveryConfirmation = 'delivery_confirmation',\n Transport = 'transport',\n Reports = 'reports',\n Prospects = 'prospects',\n}\n\n/** Report tabs a tenant can enable, in canonical order. */\nexport const REPORT_TAB_KEYS = ['sales', 'leasing', 'purchases'] as const;\n\nexport type ReportTabKey = (typeof REPORT_TAB_KEYS)[number];\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 /**\n * Reports page configuration. `tabs` lists the visible tabs in display order;\n * absent or empty means no reports are configured for the tenant (the page\n * shows a notice instead of tabs).\n */\n reports?: {\n tabs: ReportTabKey[];\n };\n test?: boolean;\n opportunities: {\n types: OpportunityType[];\n };\n /**\n * Reservation expiry for this tenant's OWN vehicles (ADR-0026): the truck's owner sets the\n * clock, wherever the deal runs — for a cross-tenant copy the chain origin's policy\n * applies, whatever opportunity type the tenant selling to the end customer uses.\n * Absent = the default\n * business-day tiers; the tier is still picked by the local customer org's\n * trustworthy/conglomerate flags.\n */\n reservationExpiry?: ReservationExpiryPolicy;\n crm?: {\n vatNumberRequiredForCompanies?: boolean;\n };\n accounting?: {\n costCenterPerLine?: boolean;\n };\n // E.164 Twilio caller ID used as a fallback when a user has no own number configured\n defaultTwilioPhoneNumber?: string;\n deliveryEmail?: string;\n};\n\nexport type ReservationExpiryPolicy =\n | { policy: 'disabled' }\n | { policy: 'days'; generic: number; trustworthy: number; conglomerate: number };\n\nexport type AccountingProvider = 'exact' | 'odoo';\n\nexport type Branch = {\n id: string;\n name: string;\n country: string;\n language: string;\n /* deprecated — use `accounting === 'exact'` instead. Kept until prod cutover. */\n exactAccounting?: boolean;\n accounting?: AccountingProvider;\n currency: string;\n adminNumberPrefix: string;\n stockNumberPrefix: string;\n vatNumber: string;\n contactPerson?: { firstName: string; lastName: string };\n vatRates: {\n standard: string; //percentage value (e.g. 21)\n };\n location: LocationValue;\n\n storecoveExternalId?: number;\n externalQuote?: boolean;\n hyperdmsId?: string;\n internalDealsEnabled?: boolean;\n /** The source invoices the end customer directly; this branch collects payment and earns\n * commission. Intercompany source opportunities for this branch's deals take the buyer\n * deal's own client instead of the branch counterparty org. */\n dropshipping?: boolean;\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"]}
|
package/lib/utils/tenants.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Branch, Tenant } from '../types/tenants.js';
|
|
2
2
|
export declare const getBranch: (tenant: Tenant, branchId: string) => Branch;
|
|
3
3
|
export declare const getDefaultBranch: (tenant: Tenant) => Branch;
|
|
4
|
+
export declare const isDropshippingBranch: (branch: Branch) => boolean;
|
|
4
5
|
export declare const getBranchStandardVatRate: (tenant: Tenant, branchId: string) => string;
|
|
5
6
|
//# sourceMappingURL=tenants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenants.d.ts","sourceRoot":"/","sources":["utils/tenants.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAErD,eAAO,MAAM,SAAS,GAAI,QAAQ,MAAM,EAAE,UAAU,MAAM,KAAG,MAO5D,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,KAAG,MAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"tenants.d.ts","sourceRoot":"/","sources":["utils/tenants.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAErD,eAAO,MAAM,SAAS,GAAI,QAAQ,MAAM,EAAE,UAAU,MAAM,KAAG,MAO5D,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,KAAG,MAAiC,CAAC;AAIpF,eAAO,MAAM,oBAAoB,GAAI,QAAQ,MAAM,KAAG,OAAuC,CAAC;AAE9F,eAAO,MAAM,wBAAwB,GAAI,QAAQ,MAAM,EAAE,UAAU,MAAM,KAAG,MAG3E,CAAC"}
|
package/lib/utils/tenants.js
CHANGED
|
@@ -8,6 +8,7 @@ export const getBranch = (tenant, branchId) => {
|
|
|
8
8
|
return branch;
|
|
9
9
|
};
|
|
10
10
|
export const getDefaultBranch = (tenant) => first(tenant.branches);
|
|
11
|
+
export const isDropshippingBranch = (branch) => branch.dropshipping === true;
|
|
11
12
|
export const getBranchStandardVatRate = (tenant, branchId) => {
|
|
12
13
|
const branch = getBranch(tenant, branchId);
|
|
13
14
|
return branch.vatRates.standard;
|
package/lib/utils/tenants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenants.js","sourceRoot":"/","sources":["utils/tenants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAGlC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,MAAc,EAAE,QAAgB,EAAU,EAAE;IACpE,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAc,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;IAChF,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,MAAM,CAAC,0BAA0B,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAAc,EAAU,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"tenants.js","sourceRoot":"/","sources":["utils/tenants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAGlC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,MAAc,EAAE,QAAgB,EAAU,EAAE;IACpE,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAc,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;IAChF,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,MAAM,CAAC,0BAA0B,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAAc,EAAU,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAE,CAAC;AAIpF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,MAAc,EAAW,EAAE,CAAC,MAAM,CAAC,YAAY,KAAK,IAAI,CAAC;AAE9F,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,MAAc,EAAE,QAAgB,EAAU,EAAE;IACnF,MAAM,MAAM,GAAW,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnD,OAAO,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;AAClC,CAAC,CAAC","sourcesContent":["import { XError } from '@bisondesk/commons-sdk/errors';\nimport { first } from 'lodash-es';\nimport { Branch, Tenant } from '../types/tenants.js';\n\nexport const getBranch = (tenant: Tenant, branchId: string): Branch => {\n const branch = tenant.branches.find((branch: Branch) => branch.id === branchId);\n if (branch == null) {\n throw new XError('tenants.branch-not-found', { tenantId: tenant.id, branchId });\n }\n\n return branch;\n};\n\nexport const getDefaultBranch = (tenant: Tenant): Branch => first(tenant.branches)!;\n\n/** The source invoices the end customer directly; this branch collects payment and earns\n * commission (see {@link Branch.dropshipping}). */\nexport const isDropshippingBranch = (branch: Branch): boolean => branch.dropshipping === true;\n\nexport const getBranchStandardVatRate = (tenant: Tenant, branchId: string): string => {\n const branch: Branch = getBranch(tenant, branchId);\n return branch.vatRates.standard;\n};\n"]}
|
package/lib/utils/vehicles.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export declare const getInternalTitle: ({ make, category, modelName, bodywork, m
|
|
|
13
13
|
}) => string;
|
|
14
14
|
export declare const convertNumberToLetters: (num: number) => string;
|
|
15
15
|
export declare const convertLettersToNumber: (letters: string) => number;
|
|
16
|
+
export declare const buildStockNumberPattern: (prefixPattern: string) => string;
|
|
16
17
|
export declare const getNextRelatedStockNumber: (stockNumber: string) => string;
|
|
17
18
|
export declare const getVehicleDescription: (external: VehicleExternalInfo, { showStockNumber, showAxleConfiguration, lang, }: {
|
|
18
19
|
showStockNumber?: boolean;
|
|
@@ -1 +1 @@
|
|
|
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;AAOnG,eAAO,MAAM,YAAY,GAAI,SAAS,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,KAAG,OAG1B,CAAC;AAEzC,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;
|
|
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;AAOnG,eAAO,MAAM,YAAY,GAAI,SAAS,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,KAAG,OAG1B,CAAC;AAEzC,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;AASF,eAAO,MAAM,uBAAuB,GAAI,eAAe,MAAM,KAAG,MACxB,CAAC;AAEzC,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"}
|
package/lib/utils/vehicles.js
CHANGED
|
@@ -88,6 +88,7 @@ export const convertLettersToNumber = (letters) => {
|
|
|
88
88
|
}
|
|
89
89
|
return result;
|
|
90
90
|
};
|
|
91
|
+
export const buildStockNumberPattern = (prefixPattern) => `(?:${prefixPattern})\\d{5}[A-Z]{0,2}`;
|
|
91
92
|
export const getNextRelatedStockNumber = (stockNumber) => {
|
|
92
93
|
const counterPattern = /^([A-Z]+\d{5})([A-Z]{0,2})$/;
|
|
93
94
|
const match = stockNumber.match(counterPattern);
|
|
@@ -1 +1 @@
|
|
|
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\n/**\n * A trailer or semi-trailer that has never been used — what the sales ladder calls a new\n * trailer, and the reason it has opportunity types of its own (`NEW_TRAILER`,\n * `NEW_TRAILER_NEW_PRODUCTION`) instead of going through plain sales.\n */\nexport const isNewTrailer = (vehicle: Pick<Vehicle, 'external'>): boolean =>\n [Categories.Trailer, Categories.SemiTrailer].includes(\n vehicle.external.general.category as Categories,\n ) && !vehicle.external.condition?.used;\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\n/**\n * A trailer or semi-trailer that has never been used — what the sales ladder calls a new\n * trailer, and the reason it has opportunity types of its own (`NEW_TRAILER`,\n * `NEW_TRAILER_NEW_PRODUCTION`) instead of going through plain sales.\n */\nexport const isNewTrailer = (vehicle: Pick<Vehicle, 'external'>): boolean =>\n [Categories.Trailer, Categories.SemiTrailer].includes(\n vehicle.external.general.category as Categories,\n ) && !vehicle.external.condition?.used;\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\n/**\n * Canonical stock-number shape: a branch prefix of 1 to 3 letters followed by exactly 5 digits\n * and up to 2 trailing counter letters (e.g. B49397AB, TC12345 — see\n * {@link getNextRelatedStockNumber}). Callers supply the prefix pattern (concrete branch\n * prefixes, or a policy like `[A-Z]{2}`) and wrap their own boundary/anchor policy around the\n * returned pattern.\n */\nexport const buildStockNumberPattern = (prefixPattern: string): string =>\n `(?:${prefixPattern})\\\\d{5}[A-Z]{0,2}`;\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
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { TENANT_ID_ADMIN_HEADER } from '@bisondesk/commons-sdk/constants';
|
|
2
|
+
import { XError } from '@bisondesk/commons-sdk/errors';
|
|
3
|
+
import { InternetOpportunityEvent } from '../types/internet-opportunities.js';
|
|
4
|
+
import { createInternetOpportunity } from './opportunities.js';
|
|
5
|
+
|
|
6
|
+
const ADMIN_KEY = 'test-admin-key';
|
|
7
|
+
const ORIGIN = 'https://core.example.com';
|
|
8
|
+
|
|
9
|
+
const event: InternetOpportunityEvent = {
|
|
10
|
+
tenantId: 'ttc',
|
|
11
|
+
branchId: 'ttc-nl',
|
|
12
|
+
name: 'John Doe',
|
|
13
|
+
phoneNumber: '+31612345678',
|
|
14
|
+
source: 'website',
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const mockFetch = vi.fn();
|
|
18
|
+
|
|
19
|
+
const okResponse = (): Response =>
|
|
20
|
+
({
|
|
21
|
+
ok: true,
|
|
22
|
+
status: 202,
|
|
23
|
+
json: async () => ({ queued: true }),
|
|
24
|
+
}) as unknown as Response;
|
|
25
|
+
|
|
26
|
+
const errorResponse = (status: number, statusText: string): Response =>
|
|
27
|
+
({
|
|
28
|
+
ok: false,
|
|
29
|
+
status,
|
|
30
|
+
statusText,
|
|
31
|
+
text: async () => statusText,
|
|
32
|
+
}) as unknown as Response;
|
|
33
|
+
|
|
34
|
+
beforeEach(() => {
|
|
35
|
+
vi.resetAllMocks();
|
|
36
|
+
vi.stubGlobal('fetch', mockFetch);
|
|
37
|
+
process.env.ADMIN_KEY = ADMIN_KEY;
|
|
38
|
+
process.env.CORE_API_ORIGIN = ORIGIN;
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
afterEach(() => {
|
|
42
|
+
vi.unstubAllGlobals();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe('createInternetOpportunity', () => {
|
|
46
|
+
test('POSTs to /api/opportunities/internet with admin auth + tenant headers and JSON body', async () => {
|
|
47
|
+
mockFetch.mockResolvedValueOnce(okResponse());
|
|
48
|
+
|
|
49
|
+
await createInternetOpportunity(event);
|
|
50
|
+
|
|
51
|
+
expect(mockFetch).toHaveBeenCalledTimes(1);
|
|
52
|
+
const [url, init] = mockFetch.mock.calls[0];
|
|
53
|
+
expect(url.toString()).toBe(`${ORIGIN}/api/opportunities/internet`);
|
|
54
|
+
expect(init.method).toBe('POST');
|
|
55
|
+
expect(init.body).toBe(JSON.stringify(event));
|
|
56
|
+
|
|
57
|
+
const headers = Object.fromEntries(init.headers as [string, string][]);
|
|
58
|
+
expect(headers.Authorization).toBe(`AdminKey ${ADMIN_KEY}`);
|
|
59
|
+
expect(headers['Content-Type']).toBe('application/json');
|
|
60
|
+
expect(headers[TENANT_ID_ADMIN_HEADER]).toBe(event.tenantId);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test('throws XError when the response is a non-2xx', async () => {
|
|
64
|
+
mockFetch.mockResolvedValueOnce(errorResponse(500, 'Internal Server Error'));
|
|
65
|
+
|
|
66
|
+
await expect(createInternetOpportunity(event)).rejects.toBeInstanceOf(XError);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { TENANT_ID_ADMIN_HEADER } from '@bisondesk/commons-sdk/constants';
|
|
2
2
|
import { cleanHeaders, fetchJson, getAdminAuth } from '@bisondesk/commons-sdk/fetch';
|
|
3
|
+
import { InternetOpportunityEvent } from '../types/internet-opportunities.js';
|
|
3
4
|
import {
|
|
4
5
|
Bid,
|
|
5
6
|
ListOpportunitiesFilters,
|
|
@@ -101,6 +102,19 @@ export const createOpportunity = async (
|
|
|
101
102
|
return response;
|
|
102
103
|
};
|
|
103
104
|
|
|
105
|
+
export const createInternetOpportunity = async (event: InternetOpportunityEvent): Promise<void> => {
|
|
106
|
+
const auth = await getAdminAuth();
|
|
107
|
+
await fetchJson(`${process.env.CORE_API_ORIGIN}/api/opportunities/internet`, {
|
|
108
|
+
method: 'POST',
|
|
109
|
+
headers: cleanHeaders({
|
|
110
|
+
Authorization: auth,
|
|
111
|
+
[TENANT_ID_ADMIN_HEADER]: event.tenantId,
|
|
112
|
+
'Content-Type': 'application/json',
|
|
113
|
+
}),
|
|
114
|
+
body: JSON.stringify(event),
|
|
115
|
+
});
|
|
116
|
+
};
|
|
117
|
+
|
|
104
118
|
//
|
|
105
119
|
// Bids
|
|
106
120
|
//
|
package/src/types/tenants.ts
CHANGED
|
@@ -116,6 +116,10 @@ export type Branch = {
|
|
|
116
116
|
externalQuote?: boolean;
|
|
117
117
|
hyperdmsId?: string;
|
|
118
118
|
internalDealsEnabled?: boolean;
|
|
119
|
+
/** The source invoices the end customer directly; this branch collects payment and earns
|
|
120
|
+
* commission. Intercompany source opportunities for this branch's deals take the buyer
|
|
121
|
+
* deal's own client instead of the branch counterparty org. */
|
|
122
|
+
dropshipping?: boolean;
|
|
119
123
|
};
|
|
120
124
|
|
|
121
125
|
export type HdmsVehiclesSync = {
|
package/src/utils/tenants.ts
CHANGED
|
@@ -13,6 +13,10 @@ export const getBranch = (tenant: Tenant, branchId: string): Branch => {
|
|
|
13
13
|
|
|
14
14
|
export const getDefaultBranch = (tenant: Tenant): Branch => first(tenant.branches)!;
|
|
15
15
|
|
|
16
|
+
/** The source invoices the end customer directly; this branch collects payment and earns
|
|
17
|
+
* commission (see {@link Branch.dropshipping}). */
|
|
18
|
+
export const isDropshippingBranch = (branch: Branch): boolean => branch.dropshipping === true;
|
|
19
|
+
|
|
16
20
|
export const getBranchStandardVatRate = (tenant: Tenant, branchId: string): string => {
|
|
17
21
|
const branch: Branch = getBranch(tenant, branchId);
|
|
18
22
|
return branch.vatRates.standard;
|
package/src/utils/vehicles.ts
CHANGED
|
@@ -165,6 +165,16 @@ export const convertLettersToNumber = (letters: string): number => {
|
|
|
165
165
|
return result;
|
|
166
166
|
};
|
|
167
167
|
|
|
168
|
+
/**
|
|
169
|
+
* Canonical stock-number shape: a branch prefix of 1 to 3 letters followed by exactly 5 digits
|
|
170
|
+
* and up to 2 trailing counter letters (e.g. B49397AB, TC12345 — see
|
|
171
|
+
* {@link getNextRelatedStockNumber}). Callers supply the prefix pattern (concrete branch
|
|
172
|
+
* prefixes, or a policy like `[A-Z]{2}`) and wrap their own boundary/anchor policy around the
|
|
173
|
+
* returned pattern.
|
|
174
|
+
*/
|
|
175
|
+
export const buildStockNumberPattern = (prefixPattern: string): string =>
|
|
176
|
+
`(?:${prefixPattern})\\d{5}[A-Z]{0,2}`;
|
|
177
|
+
|
|
168
178
|
export const getNextRelatedStockNumber = (stockNumber: string): string => {
|
|
169
179
|
const counterPattern = /^([A-Z]+\d{5})([A-Z]{0,2})$/;
|
|
170
180
|
const match = stockNumber.match(counterPattern);
|