@bisondesk/core-sdk 1.0.675 → 1.0.677
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/exchange-rates.d.ts +3 -0
- package/lib/apis/exchange-rates.d.ts.map +1 -1
- package/lib/apis/exchange-rates.js +29 -0
- package/lib/apis/exchange-rates.js.map +1 -1
- package/lib/constants.d.ts +1 -0
- package/lib/constants.d.ts.map +1 -1
- package/lib/constants.js +1 -0
- package/lib/constants.js.map +1 -1
- package/lib/types/intercompany-payments.d.ts.map +1 -1
- package/lib/types/intercompany-payments.js.map +1 -1
- package/lib/types/offers.d.ts +2 -1
- package/lib/types/offers.d.ts.map +1 -1
- package/lib/types/offers.js.map +1 -1
- package/lib/types/opportunities.d.ts +9 -0
- package/lib/types/opportunities.d.ts.map +1 -1
- package/lib/types/opportunities.js.map +1 -1
- package/lib/types/opportunity-payments.d.ts +9 -0
- package/lib/types/opportunity-payments.d.ts.map +1 -1
- package/lib/types/opportunity-payments.js.map +1 -1
- package/lib/types/quote-settings.d.ts +1 -0
- package/lib/types/quote-settings.d.ts.map +1 -1
- package/lib/types/quote-settings.js.map +1 -1
- package/lib/types/quotes.d.ts +1 -0
- package/lib/types/quotes.d.ts.map +1 -1
- package/lib/types/quotes.js.map +1 -1
- package/lib/types/tenants.d.ts +2 -0
- package/lib/types/tenants.d.ts.map +1 -1
- package/lib/types/tenants.js.map +1 -1
- package/lib/types/vehicle-purchase-payments.d.ts +8 -1
- package/lib/types/vehicle-purchase-payments.d.ts.map +1 -1
- package/lib/types/vehicle-purchase-payments.js.map +1 -1
- package/lib/types/vehicles.d.ts +7 -0
- package/lib/types/vehicles.d.ts.map +1 -1
- package/lib/types/vehicles.js.map +1 -1
- package/lib/utils/opportunity-payments.d.ts +3 -0
- package/lib/utils/opportunity-payments.d.ts.map +1 -0
- package/lib/utils/opportunity-payments.js +5 -0
- package/lib/utils/opportunity-payments.js.map +1 -0
- package/lib/utils/opportunity-payments.test.d.ts +2 -0
- package/lib/utils/opportunity-payments.test.d.ts.map +1 -0
- package/lib/utils/opportunity-payments.test.js +23 -0
- package/lib/utils/opportunity-payments.test.js.map +1 -0
- package/lib/utils/tenants.d.ts +4 -0
- package/lib/utils/tenants.d.ts.map +1 -1
- package/lib/utils/tenants.js +8 -0
- package/lib/utils/tenants.js.map +1 -1
- package/lib/utils/tenants.test.js +44 -1
- package/lib/utils/tenants.test.js.map +1 -1
- package/package.json +1 -1
- package/src/apis/exchange-rates.ts +49 -0
- package/src/constants.ts +2 -0
- package/src/types/intercompany-payments.ts +4 -3
- package/src/types/offers.ts +2 -0
- package/src/types/opportunities.ts +16 -0
- package/src/types/opportunity-payments.ts +23 -0
- package/src/types/quote-settings.ts +2 -0
- package/src/types/quotes.ts +2 -0
- package/src/types/tenants.ts +12 -0
- package/src/types/vehicle-purchase-payments.ts +16 -1
- package/src/types/vehicles.ts +15 -1
- package/src/utils/opportunity-payments.test.ts +31 -0
- package/src/utils/opportunity-payments.ts +15 -0
- package/src/utils/tenants.test.ts +60 -2
- package/src/utils/tenants.ts +28 -0
- package/tsconfig.tsbuildinfo +1 -1
package/src/types/offers.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
SearchVehicle,
|
|
10
10
|
VehicleExternalInfo,
|
|
11
11
|
VehicleInternalInfo,
|
|
12
|
+
VehiclePurchaseDealForeign,
|
|
12
13
|
VehiclePurchaseDealStatus,
|
|
13
14
|
VehiclePurchaseDeliveryType,
|
|
14
15
|
} from './vehicles.js';
|
|
@@ -330,6 +331,7 @@ export type OfferPurchase = {
|
|
|
330
331
|
| VehiclePurchaseDealStatus.Marketing;
|
|
331
332
|
costs: {
|
|
332
333
|
purchase: string;
|
|
334
|
+
foreign?: VehiclePurchaseDealForeign;
|
|
333
335
|
purchaseVatPercentage: string;
|
|
334
336
|
internalGarage?: string;
|
|
335
337
|
externalGarage?: string;
|
|
@@ -251,8 +251,23 @@ export type OpportunityUpdate = {
|
|
|
251
251
|
};
|
|
252
252
|
|
|
253
253
|
export type OpportunityPaymentSummary = {
|
|
254
|
+
/** Branch currency. */
|
|
254
255
|
total: string;
|
|
256
|
+
/** Sum of `amount` over the payments, in branch currency. */
|
|
255
257
|
paid: string;
|
|
258
|
+
/**
|
|
259
|
+
* The same pair in the quote's alternative currency, present when the branch can be paid in it.
|
|
260
|
+
* `paid` sums the payments that arrived in that currency.
|
|
261
|
+
*/
|
|
262
|
+
foreign?: {
|
|
263
|
+
total: string;
|
|
264
|
+
paid: string;
|
|
265
|
+
currencyCode: string;
|
|
266
|
+
exchangeRate: string;
|
|
267
|
+
};
|
|
268
|
+
/** Fully paid when either currency reaches its total. */
|
|
269
|
+
status: OpportunityPaymentStatus;
|
|
270
|
+
percentagePaid: string;
|
|
256
271
|
entries: DataRecord<OpportunityPayment>[];
|
|
257
272
|
};
|
|
258
273
|
|
|
@@ -604,6 +619,7 @@ export type HpLeasingContractRequest = {
|
|
|
604
619
|
vanCourier: boolean;
|
|
605
620
|
startDate: number;
|
|
606
621
|
opportunityContractId: string;
|
|
622
|
+
maxKmPerYear?: number;
|
|
607
623
|
data: {
|
|
608
624
|
leasingParameter: {
|
|
609
625
|
allRisksPercentage: number;
|
|
@@ -7,8 +7,27 @@ export enum OpportunityPaymentActions {
|
|
|
7
7
|
|
|
8
8
|
export const OPPORTUNITY_PAYMENT_NOTIFICATION_ORIGIN = 'opportunity-payment-notification';
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* The money as it arrived, when it arrived in the quote's alternative currency. `amount` then
|
|
12
|
+
* holds its value in branch currency: `foreign.amount × foreign.exchangeRate`.
|
|
13
|
+
*/
|
|
14
|
+
export type OpportunityPaymentForeign = {
|
|
15
|
+
amount: string;
|
|
16
|
+
currencyCode: string;
|
|
17
|
+
/** Branch currency units per 1 unit of `currencyCode`, the quote's rate. */
|
|
18
|
+
exchangeRate: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/** What a user sends for a payment in another currency. The backend takes the rate from the quote
|
|
22
|
+
* and derives `amount`. */
|
|
23
|
+
export type OpportunityPaymentForeignRequest = Pick<
|
|
24
|
+
OpportunityPaymentForeign,
|
|
25
|
+
'amount' | 'currencyCode'
|
|
26
|
+
>;
|
|
27
|
+
|
|
10
28
|
type BaseOpportunityPayment = {
|
|
11
29
|
opportunityId: string;
|
|
30
|
+
/** Branch currency. */
|
|
12
31
|
amount: string;
|
|
13
32
|
description?: string;
|
|
14
33
|
vehicleId: string;
|
|
@@ -24,6 +43,7 @@ export type NewOpportunityPayment = BaseOpportunityPayment & {
|
|
|
24
43
|
deletedAt?: undefined;
|
|
25
44
|
deletedBy?: undefined;
|
|
26
45
|
paidAt: string;
|
|
46
|
+
foreign?: OpportunityPaymentForeignRequest;
|
|
27
47
|
};
|
|
28
48
|
|
|
29
49
|
export type OpportunityPayment = BaseOpportunityPayment & {
|
|
@@ -35,11 +55,14 @@ export type OpportunityPayment = BaseOpportunityPayment & {
|
|
|
35
55
|
deletedAt?: string;
|
|
36
56
|
deletedBy?: string;
|
|
37
57
|
paidAt?: string;
|
|
58
|
+
foreign?: OpportunityPaymentForeign;
|
|
38
59
|
};
|
|
39
60
|
|
|
40
61
|
export type OpportunityPaymentUpdate = {
|
|
41
62
|
description?: string;
|
|
42
63
|
amount?: string;
|
|
64
|
+
/** `null` turns the payment back into a branch currency payment. */
|
|
65
|
+
foreign?: OpportunityPaymentForeignRequest | null;
|
|
43
66
|
paidAt?: string;
|
|
44
67
|
};
|
|
45
68
|
|
|
@@ -91,6 +91,8 @@ export type LeasingQuoteParams<P extends CountrySpecificQuoteParams = CountrySpe
|
|
|
91
91
|
leasingDuration: number;
|
|
92
92
|
leasingDepositPercentage: string;
|
|
93
93
|
leasingResidualValuePercentage: string;
|
|
94
|
+
/** Seeds `leasing.maxKmPerYear` on new quotes. */
|
|
95
|
+
maxKmPerYear?: number;
|
|
94
96
|
};
|
|
95
97
|
costs: {
|
|
96
98
|
bankDepositPercentage: string;
|
package/src/types/quotes.ts
CHANGED
|
@@ -91,6 +91,8 @@ export type LeasingCalculatorInput = BaseQuoteCalculatorInput & {
|
|
|
91
91
|
interestRate: string;
|
|
92
92
|
duration: number;
|
|
93
93
|
contractStartDate: string;
|
|
94
|
+
/** Mileage cap the contract allows per year, in km. Printed on the quote and the contract. */
|
|
95
|
+
maxKmPerYear?: number;
|
|
94
96
|
};
|
|
95
97
|
bank: {
|
|
96
98
|
interestRate: string;
|
package/src/types/tenants.ts
CHANGED
|
@@ -148,6 +148,12 @@ export type Branch = {
|
|
|
148
148
|
exactAccounting?: boolean;
|
|
149
149
|
accounting?: AccountingProvider;
|
|
150
150
|
currency: string;
|
|
151
|
+
/**
|
|
152
|
+
* The currencies money moves in at this branch, its own `currency` included. Customer payments,
|
|
153
|
+
* purchase prices, supplier invoice drafts and Exact bookings are supported in these currencies
|
|
154
|
+
* only. Absent = the branch's own `currency` only. Set by script.
|
|
155
|
+
*/
|
|
156
|
+
paymentCurrencies?: [string, ...string[]];
|
|
151
157
|
adminNumberPrefix: string;
|
|
152
158
|
stockNumberPrefix: string;
|
|
153
159
|
vatNumber: string;
|
|
@@ -156,6 +162,12 @@ export type Branch = {
|
|
|
156
162
|
standard: string; //percentage value (e.g. 21)
|
|
157
163
|
};
|
|
158
164
|
location: LocationValue;
|
|
165
|
+
/**
|
|
166
|
+
* The parking (a `location` picklist value) this branch's vehicles go to when their purchase
|
|
167
|
+
* names none. Vehicle entry offers it as the stock destination, and the transport ITR prints
|
|
168
|
+
* it as the park. Absent = the ITR prints the branch's own address.
|
|
169
|
+
*/
|
|
170
|
+
defaultParking?: string;
|
|
159
171
|
|
|
160
172
|
storecoveExternalId?: number;
|
|
161
173
|
// true if the branch is for a company where VAT is due when the invoice
|
|
@@ -4,18 +4,33 @@ import { SearchVehicle } from './vehicles.js';
|
|
|
4
4
|
export const VEHICLE_PURCHASE_PAYMENT_ALLOWED_NOTIFICATION_ORIGIN =
|
|
5
5
|
'vehicle-purchase-payment-allowed-notification';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* A payment on a purchase priced in another currency is authorized and paid in that currency.
|
|
9
|
+
* `amount` then holds its value in branch currency: `foreign.amount × foreign.exchangeRate`.
|
|
10
|
+
*/
|
|
11
|
+
export type VehiclePurchasePaymentForeign = {
|
|
12
|
+
amount: string;
|
|
13
|
+
currencyCode: string;
|
|
14
|
+
/** Branch currency units per 1 unit of `currencyCode`, the purchase's rate. */
|
|
15
|
+
exchangeRate: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
7
18
|
export type NewVehiclePurchasePayment = {
|
|
8
19
|
vehicleId: string;
|
|
20
|
+
/** Branch currency. Derived from `foreign` when the purchase is priced in another currency. */
|
|
9
21
|
amount: string;
|
|
22
|
+
/** The backend takes the rate from the purchase. */
|
|
23
|
+
foreign?: Pick<VehiclePurchasePaymentForeign, 'amount' | 'currencyCode'>;
|
|
10
24
|
description?: string;
|
|
11
25
|
paidAt?: string;
|
|
12
26
|
paidBy?: string;
|
|
13
27
|
};
|
|
14
28
|
|
|
15
|
-
export type VehiclePurchasePayment = NewVehiclePurchasePayment & {
|
|
29
|
+
export type VehiclePurchasePayment = Omit<NewVehiclePurchasePayment, 'foreign'> & {
|
|
16
30
|
id: string;
|
|
17
31
|
createdBy: string;
|
|
18
32
|
createdAt: string;
|
|
33
|
+
foreign?: VehiclePurchasePaymentForeign;
|
|
19
34
|
};
|
|
20
35
|
|
|
21
36
|
export type VehiclePurchasePaymentBff = {
|
package/src/types/vehicles.ts
CHANGED
|
@@ -170,6 +170,7 @@ export type NewVehicleRequest = {
|
|
|
170
170
|
dealStatus: VehiclePurchaseDealStatus;
|
|
171
171
|
costs: {
|
|
172
172
|
purchase: string;
|
|
173
|
+
foreign?: VehiclePurchaseDealForeign;
|
|
173
174
|
purchaseVatPercentage: string;
|
|
174
175
|
commission?: string;
|
|
175
176
|
externalTransport?: string;
|
|
@@ -811,6 +812,18 @@ export type VehiclePriceUpdateResponse =
|
|
|
811
812
|
errors: VehiclePriceUpdateError[];
|
|
812
813
|
};
|
|
813
814
|
|
|
815
|
+
/**
|
|
816
|
+
* The price the supplier asked, in the supplier's currency: one of the payment currencies of the
|
|
817
|
+
* vehicle's branch. The purchase's `deal.purchase` is then `purchase × exchangeRate`, and payments
|
|
818
|
+
* are authorized in `currencyCode`.
|
|
819
|
+
*/
|
|
820
|
+
export type VehiclePurchaseDealForeign = {
|
|
821
|
+
purchase: string; // exclusive VAT
|
|
822
|
+
currencyCode: string;
|
|
823
|
+
/** Branch currency units per 1 unit of `currencyCode`. */
|
|
824
|
+
exchangeRate: string;
|
|
825
|
+
};
|
|
826
|
+
|
|
814
827
|
export type VehiclePurchase = {
|
|
815
828
|
organizationId: string;
|
|
816
829
|
contactId: string;
|
|
@@ -851,7 +864,8 @@ export type VehiclePurchase = {
|
|
|
851
864
|
readyToDeliver?: boolean;
|
|
852
865
|
|
|
853
866
|
purchaseVatRate?: string;
|
|
854
|
-
purchase?: string; // exclusive VAT
|
|
867
|
+
purchase?: string; // exclusive VAT; derived from `foreign` when present
|
|
868
|
+
foreign?: VehiclePurchaseDealForeign;
|
|
855
869
|
|
|
856
870
|
bonus?: string; // sometimes manufacturers pay us a bonus when we reach a target
|
|
857
871
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { OpportunityPayment } from '../types/opportunity-payments.js';
|
|
2
|
+
import { isPaidInAlternativeCurrency } from './opportunity-payments.js';
|
|
3
|
+
|
|
4
|
+
const dollarPayment: Pick<OpportunityPayment, 'foreign' | 'deletedAt'> = {
|
|
5
|
+
foreign: { amount: '30000', currencyCode: 'USD', exchangeRate: '0.861804' },
|
|
6
|
+
};
|
|
7
|
+
const euroPayment: Pick<OpportunityPayment, 'foreign' | 'deletedAt'> = {};
|
|
8
|
+
|
|
9
|
+
describe('isPaidInAlternativeCurrency', () => {
|
|
10
|
+
it('shows the alternative currency before any payment arrived', () => {
|
|
11
|
+
expect(isPaidInAlternativeCurrency('USD', [])).toBe(true);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('shows the alternative currency while every payment arrived in it', () => {
|
|
15
|
+
expect(isPaidInAlternativeCurrency('USD', [dollarPayment, dollarPayment])).toBe(true);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('switches to branch currency once one payment arrived in branch currency', () => {
|
|
19
|
+
expect(isPaidInAlternativeCurrency('USD', [dollarPayment, euroPayment])).toBe(false);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('leaves deleted payments out', () => {
|
|
23
|
+
expect(
|
|
24
|
+
isPaidInAlternativeCurrency('USD', [dollarPayment, { deletedAt: '2026-09-30T10:00:00Z' }]),
|
|
25
|
+
).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('shows branch currency when the quote has no alternative currency', () => {
|
|
29
|
+
expect(isPaidInAlternativeCurrency(undefined, [dollarPayment])).toBe(false);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { OpportunityPayment } from '../types/opportunity-payments.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Whether a deal's payments are shown in the quote's alternative currency: every payment so far
|
|
5
|
+
* arrived in it. One payment in branch currency switches the deal to branch currency, because
|
|
6
|
+
* only the branch currency amounts then add up to the whole.
|
|
7
|
+
*/
|
|
8
|
+
export const isPaidInAlternativeCurrency = (
|
|
9
|
+
alternativeCurrency: string | undefined,
|
|
10
|
+
payments: Pick<OpportunityPayment, 'foreign' | 'deletedAt'>[],
|
|
11
|
+
): boolean =>
|
|
12
|
+
alternativeCurrency != null &&
|
|
13
|
+
payments
|
|
14
|
+
.filter((payment) => payment.deletedAt == null)
|
|
15
|
+
.every((payment) => payment.foreign?.currencyCode === alternativeCurrency);
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
import { Branch } from '../types/tenants.js';
|
|
2
|
-
import {
|
|
1
|
+
import { Branch, Tenant } from '../types/tenants.js';
|
|
2
|
+
import {
|
|
3
|
+
areBranchesQuoteCompatible,
|
|
4
|
+
getBranchAskingVies,
|
|
5
|
+
getBranchPaymentCurrencies,
|
|
6
|
+
hasForeignPaymentCurrency,
|
|
7
|
+
isForeignPaymentCurrency,
|
|
8
|
+
} from './tenants.js';
|
|
3
9
|
|
|
4
10
|
const createBranch = (override?: Partial<Branch>): Branch => ({
|
|
5
11
|
id: 'TTC',
|
|
@@ -45,3 +51,55 @@ describe('areBranchesQuoteCompatible', () => {
|
|
|
45
51
|
expect(areBranchesQuoteCompatible(implicit, explicit)).toBe(true);
|
|
46
52
|
});
|
|
47
53
|
});
|
|
54
|
+
|
|
55
|
+
describe('getBranchAskingVies', () => {
|
|
56
|
+
const bolivia = createBranch({ id: 'BO', country: 'bo', vatNumber: '387032026' });
|
|
57
|
+
const belgium = createBranch({ id: 'BE', country: 'be', vatNumber: 'BE0405567886' });
|
|
58
|
+
const france = createBranch({ id: 'FR', country: 'fr', vatNumber: 'FR10821739638' });
|
|
59
|
+
const tenantOf = (branches: Branch[]) => ({ branches }) as Tenant;
|
|
60
|
+
|
|
61
|
+
test.each([
|
|
62
|
+
['the European branch the check is made for', 'FR', 'FR'],
|
|
63
|
+
['the first European branch when no branch is given', undefined, 'BE'],
|
|
64
|
+
['the first European branch when the given branch is outside the EU', 'BO', 'BE'],
|
|
65
|
+
['the first European branch when the given branch is unknown', 'GONE', 'BE'],
|
|
66
|
+
])('picks %s', (_label, branchId, expected) => {
|
|
67
|
+
expect(getBranchAskingVies(tenantOf([bolivia, belgium, france]), branchId)?.id).toBe(expected);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test('asks anonymously for a tenant without a European branch', () => {
|
|
71
|
+
expect(getBranchAskingVies(tenantOf([bolivia]), 'BO')).toBeUndefined();
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
describe('payment currencies of a branch', () => {
|
|
76
|
+
const southAmerica = createBranch({
|
|
77
|
+
id: 'HPA South America',
|
|
78
|
+
paymentCurrencies: ['EUR', 'USD'],
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test('a branch without a list is paid in its own currency only', () => {
|
|
82
|
+
expect(getBranchPaymentCurrencies(createBranch())).toEqual(['EUR']);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('a branch with a list is paid in the currencies it lists', () => {
|
|
86
|
+
expect(getBranchPaymentCurrencies(southAmerica)).toEqual(['EUR', 'USD']);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test.each([
|
|
90
|
+
['a listed currency other than its own', 'USD', true],
|
|
91
|
+
['its own currency', 'EUR', false],
|
|
92
|
+
['a currency it does not list', 'BOB', false],
|
|
93
|
+
])('%s is a foreign payment currency: %s', (_label, currencyCode, expected) => {
|
|
94
|
+
expect(isForeignPaymentCurrency(southAmerica, currencyCode)).toBe(expected);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test('a branch without a list has no foreign payment currency', () => {
|
|
98
|
+
expect(isForeignPaymentCurrency(createBranch(), 'USD')).toBe(false);
|
|
99
|
+
expect(hasForeignPaymentCurrency(createBranch())).toBe(false);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test('a branch listing another currency has a foreign payment currency', () => {
|
|
103
|
+
expect(hasForeignPaymentCurrency(southAmerica)).toBe(true);
|
|
104
|
+
});
|
|
105
|
+
});
|
package/src/utils/tenants.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { XError } from '@bisondesk/commons-sdk/errors';
|
|
2
|
+
import { isEUCountry } from '@bisondesk/commons-sdk/locations';
|
|
2
3
|
import { first } from 'lodash-es';
|
|
3
4
|
import { Branch, Tenant } from '../types/tenants.js';
|
|
4
5
|
|
|
@@ -13,6 +14,33 @@ export const getBranch = (tenant: Tenant, branchId: string): Branch => {
|
|
|
13
14
|
|
|
14
15
|
export const getDefaultBranch = (tenant: Tenant): Branch => first(tenant.branches)!;
|
|
15
16
|
|
|
17
|
+
/**
|
|
18
|
+
* The branch whose VAT number VIES records as the requester of a VAT check, which earns a
|
|
19
|
+
* consultation number: the branch the check is made for when it is European, else the tenant's
|
|
20
|
+
* first European branch. A tenant without a European branch asks VIES anonymously.
|
|
21
|
+
*/
|
|
22
|
+
export const getBranchAskingVies = (tenant: Tenant, branchId?: string): Branch | undefined => {
|
|
23
|
+
const europeanBranches = tenant.branches.filter((branch) => isEUCountry(branch.country));
|
|
24
|
+
return europeanBranches.find((branch) => branch.id === branchId) ?? europeanBranches.at(0);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** The currencies money moves in at the branch, its own currency included. */
|
|
28
|
+
export const getBranchPaymentCurrencies = (branch: Branch): string[] =>
|
|
29
|
+
branch.paymentCurrencies ?? [branch.currency];
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Whether the branch can be paid, price a purchase or receive a supplier invoice in a currency
|
|
33
|
+
* other than its own. Its own currency is never a foreign one.
|
|
34
|
+
*/
|
|
35
|
+
export const isForeignPaymentCurrency = (branch: Branch, currencyCode: string): boolean =>
|
|
36
|
+
currencyCode !== branch.currency && getBranchPaymentCurrencies(branch).includes(currencyCode);
|
|
37
|
+
|
|
38
|
+
/** Whether the branch lists any payment currency other than its own. */
|
|
39
|
+
export const hasForeignPaymentCurrency = (branch: Branch): boolean =>
|
|
40
|
+
getBranchPaymentCurrencies(branch).some((currencyCode) =>
|
|
41
|
+
isForeignPaymentCurrency(branch, currencyCode),
|
|
42
|
+
);
|
|
43
|
+
|
|
16
44
|
/** The source invoices the end customer directly; this branch collects payment and earns
|
|
17
45
|
* commission (see {@link Branch.dropshipping}). */
|
|
18
46
|
export const isDropshippingBranch = (branch: Branch): boolean => branch.dropshipping === true;
|