@bisondesk/core-sdk 1.0.667 → 1.0.668
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/types/vehicles.d.ts +85 -1
- package/lib/types/vehicles.d.ts.map +1 -1
- package/lib/types/vehicles.js +35 -0
- package/lib/types/vehicles.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 +4 -0
- package/lib/utils/tenants.js.map +1 -1
- package/lib/utils/tenants.test.d.ts +2 -0
- package/lib/utils/tenants.test.d.ts.map +1 -0
- package/lib/utils/tenants.test.js +39 -0
- package/lib/utils/tenants.test.js.map +1 -0
- package/package.json +1 -1
- package/src/types/vehicles.ts +105 -0
- package/src/utils/tenants.test.ts +47 -0
- package/src/utils/tenants.ts +11 -0
- package/tsconfig.tsbuildinfo +1 -1
package/src/types/vehicles.ts
CHANGED
|
@@ -338,6 +338,15 @@ export type RelatedVehicle = {
|
|
|
338
338
|
stockNumber: string;
|
|
339
339
|
};
|
|
340
340
|
|
|
341
|
+
export type VehicleBranchHistoryEntry = {
|
|
342
|
+
branch: string;
|
|
343
|
+
stockNumber: string;
|
|
344
|
+
administrativeNumber?: string;
|
|
345
|
+
changedAt: string;
|
|
346
|
+
changedBy: string;
|
|
347
|
+
reason?: string;
|
|
348
|
+
};
|
|
349
|
+
|
|
341
350
|
export type VehicleInternalInfo = {
|
|
342
351
|
createdAt: string;
|
|
343
352
|
description: {
|
|
@@ -355,6 +364,11 @@ export type VehicleInternalInfo = {
|
|
|
355
364
|
licensePlate: string;
|
|
356
365
|
changedAt: string;
|
|
357
366
|
}[];
|
|
367
|
+
/**
|
|
368
|
+
* One entry per branch the vehicle has left, oldest first. Records the identity it carried
|
|
369
|
+
* there (stock and administrative numbers are redrawn on a move) and who moved it.
|
|
370
|
+
*/
|
|
371
|
+
branchHistory?: VehicleBranchHistoryEntry[];
|
|
358
372
|
|
|
359
373
|
/**
|
|
360
374
|
* This ID is used to link different vehicle objects that represent the same real world asset.
|
|
@@ -890,8 +904,99 @@ export enum VehicleActions {
|
|
|
890
904
|
ViewPurchase = 'view_purchase',
|
|
891
905
|
ViewPriceHistory = 'view_price_history',
|
|
892
906
|
DeleteVehicle = 'delete_vehicle',
|
|
907
|
+
ChangeBranch = 'change_branch',
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
export type VehicleBranchChangeRequest = {
|
|
911
|
+
branch: string;
|
|
912
|
+
reason?: string;
|
|
913
|
+
/** Required when the preview carries a warning that needs acknowledgement. */
|
|
914
|
+
acknowledged?: boolean;
|
|
915
|
+
};
|
|
916
|
+
|
|
917
|
+
export enum VehicleBranchChangeBlockerCode {
|
|
918
|
+
SameBranch = 'same_branch',
|
|
919
|
+
VehicleDeleted = 'vehicle_deleted',
|
|
920
|
+
CurrencyMismatch = 'currency_mismatch',
|
|
921
|
+
FinanceDocumentsExist = 'finance_documents_exist',
|
|
922
|
+
PurchasePaymentsExist = 'purchase_payments_exist',
|
|
923
|
+
DealCommitted = 'deal_committed',
|
|
924
|
+
VehicleSold = 'vehicle_sold',
|
|
925
|
+
LeasingContractExists = 'leasing_contract_exists',
|
|
926
|
+
RelatedVehicles = 'related_vehicles',
|
|
927
|
+
InternalDealQuote = 'internal_deal_quote',
|
|
928
|
+
IntercompanyLinkLive = 'intercompany_link_live',
|
|
929
|
+
HyperdmsOrganisationChange = 'hyperdms_organisation_change',
|
|
930
|
+
StockNumberTaken = 'stock_number_taken',
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
export enum VehicleBranchChangeWarningCode {
|
|
934
|
+
DealsLoseQuotes = 'deals_lose_quotes',
|
|
935
|
+
DealPaymentsExist = 'deal_payments_exist',
|
|
936
|
+
OpenTransports = 'open_transports',
|
|
937
|
+
CopiesWithdrawn = 'copies_withdrawn',
|
|
938
|
+
CopiesCreated = 'copies_created',
|
|
939
|
+
TargetWithoutAccounting = 'target_without_accounting',
|
|
940
|
+
TargetWithoutStorecove = 'target_without_storecove',
|
|
893
941
|
}
|
|
894
942
|
|
|
943
|
+
export type VehicleBranchChangeBlocker = {
|
|
944
|
+
code: VehicleBranchChangeBlockerCode;
|
|
945
|
+
data?: Record<string, unknown>;
|
|
946
|
+
};
|
|
947
|
+
|
|
948
|
+
export type VehicleBranchChangeWarning = {
|
|
949
|
+
code: VehicleBranchChangeWarningCode;
|
|
950
|
+
/** The write refuses unless the request says `acknowledged: true`. */
|
|
951
|
+
requiresAcknowledgement: boolean;
|
|
952
|
+
data?: Record<string, unknown>;
|
|
953
|
+
};
|
|
954
|
+
|
|
955
|
+
export enum VehicleBranchChangeDealOutcome {
|
|
956
|
+
/** Branches are quote-compatible: the deal and its quotes move together. */
|
|
957
|
+
FollowsWithQuotes = 'follows_with_quotes',
|
|
958
|
+
/** The deal moves; its quotes stay archived on the old branch and it needs a new one. */
|
|
959
|
+
FollowsNeedsRequote = 'follows_needs_requote',
|
|
960
|
+
AlreadyOnTarget = 'already_on_target',
|
|
961
|
+
StaysClosed = 'stays_closed',
|
|
962
|
+
/** In Preparation or later: contracts and paperwork exist, so this deal blocks the move. */
|
|
963
|
+
Committed = 'committed',
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
export type VehicleBranchChangeDealImpact = {
|
|
967
|
+
opportunityId: string;
|
|
968
|
+
status: string;
|
|
969
|
+
branch: string;
|
|
970
|
+
outcome: VehicleBranchChangeDealOutcome;
|
|
971
|
+
hasActiveQuote: boolean;
|
|
972
|
+
paymentsCount: number;
|
|
973
|
+
};
|
|
974
|
+
|
|
975
|
+
export type VehicleBranchChangeIdentity = {
|
|
976
|
+
branch: string;
|
|
977
|
+
stockNumber: string;
|
|
978
|
+
administrativeNumber?: string;
|
|
979
|
+
};
|
|
980
|
+
|
|
981
|
+
export type VehicleBranchChangePreview = {
|
|
982
|
+
from: VehicleBranchChangeIdentity;
|
|
983
|
+
/** The administrative number is only known once drawn, so the preview leaves it out. */
|
|
984
|
+
to: Omit<VehicleBranchChangeIdentity, 'administrativeNumber'>;
|
|
985
|
+
blockers: VehicleBranchChangeBlocker[];
|
|
986
|
+
warnings: VehicleBranchChangeWarning[];
|
|
987
|
+
/** Counts of the records that follow are not reported: the warnings above already name them. */
|
|
988
|
+
impact: { deals: VehicleBranchChangeDealImpact[] };
|
|
989
|
+
};
|
|
990
|
+
|
|
991
|
+
export type VehicleBranchChangeResult = {
|
|
992
|
+
vehicle: Vehicle;
|
|
993
|
+
from: VehicleBranchChangeIdentity;
|
|
994
|
+
to: VehicleBranchChangeIdentity;
|
|
995
|
+
deals: VehicleBranchChangeDealImpact[];
|
|
996
|
+
/** Repair steps that failed after the vehicle moved; running the move again retries them. */
|
|
997
|
+
failedSteps: string[];
|
|
998
|
+
};
|
|
999
|
+
|
|
895
1000
|
export enum PurchaseActions {
|
|
896
1001
|
ViewDeal = 'view_deal',
|
|
897
1002
|
ViewSupplierOrganization = 'view_supplier_organization',
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Branch } from '../types/tenants.js';
|
|
2
|
+
import { areBranchesQuoteCompatible } from './tenants.js';
|
|
3
|
+
|
|
4
|
+
const createBranch = (override?: Partial<Branch>): Branch => ({
|
|
5
|
+
id: 'TTC',
|
|
6
|
+
name: 'TTC Belgium',
|
|
7
|
+
country: 'be',
|
|
8
|
+
language: 'nl',
|
|
9
|
+
currency: 'EUR',
|
|
10
|
+
adminNumberPrefix: 'AT',
|
|
11
|
+
stockNumberPrefix: 'TC',
|
|
12
|
+
vatNumber: 'BE0123456789',
|
|
13
|
+
vatRates: { standard: '21' },
|
|
14
|
+
location: { country: 'be' },
|
|
15
|
+
...override,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe('areBranchesQuoteCompatible', () => {
|
|
19
|
+
it('accepts two branches that agree on country, currency, vat rate and quote mode', () => {
|
|
20
|
+
const a = createBranch();
|
|
21
|
+
const b = createBranch({ id: 'TTC2', name: 'TTC Antwerp', stockNumberPrefix: 'TA' });
|
|
22
|
+
|
|
23
|
+
expect(areBranchesQuoteCompatible(a, b)).toBe(true);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('is true for a branch compared with itself', () => {
|
|
27
|
+
const branch = createBranch();
|
|
28
|
+
|
|
29
|
+
expect(areBranchesQuoteCompatible(branch, branch)).toBe(true);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it.each([
|
|
33
|
+
['country', { country: 'fr' }],
|
|
34
|
+
['currency', { currency: 'USD' }],
|
|
35
|
+
['vat rate', { vatRates: { standard: '20' } }],
|
|
36
|
+
['external quote mode', { externalQuote: true }],
|
|
37
|
+
])('rejects branches that differ in %s', (_label, override) => {
|
|
38
|
+
expect(areBranchesQuoteCompatible(createBranch(), createBranch(override))).toBe(false);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('treats a missing externalQuote as false rather than as a difference', () => {
|
|
42
|
+
const implicit = createBranch();
|
|
43
|
+
const explicit = createBranch({ externalQuote: false });
|
|
44
|
+
|
|
45
|
+
expect(areBranchesQuoteCompatible(implicit, explicit)).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
});
|
package/src/utils/tenants.ts
CHANGED
|
@@ -21,3 +21,14 @@ export const getBranchStandardVatRate = (tenant: Tenant, branchId: string): stri
|
|
|
21
21
|
const branch: Branch = getBranch(tenant, branchId);
|
|
22
22
|
return branch.vatRates.standard;
|
|
23
23
|
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Whether a quote computed for one branch is still right for the other. A quote's VAT regime,
|
|
27
|
+
* currency, calculator strategy and conditions all come from these four fields, so when they
|
|
28
|
+
* agree the quote can move with its deal; otherwise the deal needs a new one.
|
|
29
|
+
*/
|
|
30
|
+
export const areBranchesQuoteCompatible = (a: Branch, b: Branch): boolean =>
|
|
31
|
+
a.country === b.country &&
|
|
32
|
+
a.currency === b.currency &&
|
|
33
|
+
a.vatRates.standard === b.vatRates.standard &&
|
|
34
|
+
(a.externalQuote ?? false) === (b.externalQuote ?? false);
|