Skip to content

Commit 55fccb4

Browse files
author
Gerald Baulig
committed
fix(taxes): apply tax on commercial
1 parent aed5aaf commit 55fccb4

File tree

3 files changed

+183
-119
lines changed

3 files changed

+183
-119
lines changed

src/service.ts

+14-118
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ import {
101101
DeleteRequest,
102102
Filter_ValueType,
103103
ReadRequest,
104+
Resource,
105+
ResourceResponse,
104106
} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/resource_base.js';
105107
import {
106108
OperationStatus,
@@ -118,61 +120,7 @@ import {
118120
VAT
119121
} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/amount.js';
120122
import { Subject } from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/auth.js';
121-
122-
export type BigVAT = {
123-
tax_id: string;
124-
vat: BigNumber;
125-
};
126-
127-
export type BigAmount = {
128-
currency_id: string;
129-
gross: BigNumber;
130-
net: BigNumber;
131-
vats: VAT[];
132-
};
133-
134-
export type RatioedTax = Tax & {
135-
tax_ratio?: number;
136-
};
137-
138-
export const toObjectMap = <T extends object>(items: any[]) => items.reduce(
139-
(a, b) => {
140-
a[b.id ?? b.payload?.id] = b;
141-
return a;
142-
},
143-
{} as T
144-
) ?? {};
145-
146-
export type OrderMap = { [key: string]: OrderResponse };
147-
export type ProductMap = { [key: string]: ProductResponse };
148-
export type FulfillmentMap = { [key: string]: FulfillmentResponse[] };
149-
export type RatioedTaxMap = { [key: string]: RatioedTax };
150-
export type CustomerMap = { [key: string]: CustomerResponse };
151-
export type CurrencyMap = { [key: string]: CurrencyResponse };
152-
export type ShopMap = { [key: string]: ShopResponse };
153-
export type OrganizationMap = { [key: string]: OrganizationResponse };
154-
export type ContactPointMap = { [key: string]: ContactPointResponse };
155-
export type AddressMap = { [key: string]: AddressResponse };
156-
export type CountryMap = { [key: string]: CountryResponse };
157-
export type FulfillmentSolutionMap = { [key: string]: FulfillmentSolutionResponse };
158-
export type PositionMap = { [key: string]: Position };
159-
export type StatusMap = { [key: string]: Status };
160-
export type OperationStatusMap = { [key: string]: OperationStatus };
161-
export type VATMap = { [key: string]: VAT };
162-
export type ProductNature = PhysicalProduct & VirtualProduct & ServiceProduct;
163-
export type ProductVariant = PhysicalVariant & VirtualVariant & ServiceVariant;
164-
export type CRUDClient = Client<ProductServiceDefinition>
165-
| Client<TaxServiceDefinition>
166-
| Client<CustomerServiceDefinition>
167-
| Client<ShopServiceDefinition>
168-
| Client<OrganizationServiceDefinition>
169-
| Client<ContactPointServiceDefinition>
170-
| Client<AddressServiceDefinition>
171-
| Client<CountryServiceDefinition>
172-
| Client<FulfillmentServiceDefinition>
173-
| Client<FulfillmentProductServiceDefinition>
174-
| Client<CurrencyServiceDefinition>
175-
| Client<InvoiceServiceDefinition>;
123+
import { AddressMap, BigAmount, BigVAT, ContactPointMap, CountryMap, CRUDClient, CurrencyMap, CustomerMap, DefaultUrns, FulfillmentMap, FulfillmentSolutionMap, OrderMap, OrganizationMap, PositionMap, ProductMap, ProductNature, ProductVariant, RatioedTax, RatioedTaxMap, ShopMap, toObjectMap, VATMap } from './utils.js';
176124

177125
const CREATE_FULFILLMENT = 'createFulfillment';
178126

@@ -200,39 +148,7 @@ export class OrderingService
200148
};
201149
}
202150

203-
private readonly urns = {
204-
instanceType: 'urn:restorecommerce:acs:model:order:Order',
205-
disableFulfillment: 'urn:restorecommerce:order:preferences:disableFulfillment',
206-
disableInvoice: 'urn:restorecommerce:order:preferences:disableInvoice',
207-
entity: 'urn:restorecommerce:acs:names:model:entity',
208-
user: 'urn:restorecommerce:acs:model:user.User',
209-
model: 'urn:restorecommerce:acs:model',
210-
role: 'urn:restorecommerce:acs:names:role',
211-
roleScopingEntity: 'urn:restorecommerce:acs:names:roleScopingEntity',
212-
roleScopingInstance: 'urn:restorecommerce:acs:names:roleScopingInstance',
213-
unauthenticated_user: 'urn:restorecommerce:acs:names:unauthenticated-user',
214-
property: 'urn:restorecommerce:acs:names:model:property',
215-
ownerIndicatoryEntity: 'urn:restorecommerce:acs:names:ownerIndicatoryEntity',
216-
ownerInstance: 'urn:restorecommerce:acs:names:ownerInstance',
217-
orgScope: 'urn:restorecommerce:acs:model:organization.Organization',
218-
subjectID: 'urn:oasis:names:tc:xacml:1.0:subject:subject-id',
219-
resourceID: 'urn:oasis:names:tc:xacml:1.0:resource:resource-id',
220-
actionID: 'urn:oasis:names:tc:xacml:1.0:action:action-id',
221-
action: 'urn:restorecommerce:acs:names:action',
222-
operation: 'urn:restorecommerce:acs:names:operation',
223-
execute: 'urn:restorecommerce:acs:names:action:execute',
224-
permitOverrides: 'urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:permit-overrides',
225-
denyOverrides: 'urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:deny-overrides',
226-
create: 'urn:restorecommerce:acs:names:action:create',
227-
read: 'urn:restorecommerce:acs:names:action:read',
228-
modify: 'urn:restorecommerce:acs:names:action:modify',
229-
delete: 'urn:restorecommerce:acs:names:action:delete',
230-
organization: 'urn:restorecommerce:acs:model:organization.Organization',
231-
aclIndicatoryEntity: 'urn:restorecommerce:acs:names:aclIndicatoryEntity',
232-
aclInstance: 'urn:restorecommerce:acs:names:aclInstance',
233-
skipACL: 'urn:restorecommerce:acs:names:skipACL',
234-
maskedProperty: 'urn:restorecommerce:acs:names:obligation:maskedProperty',
235-
};
151+
private readonly urns = DefaultUrns;
236152

237153
private readonly status_codes = {
238154
OK: {
@@ -334,16 +250,6 @@ export class OrderingService
334250
billing: 'billing',
335251
};
336252

337-
get ApiKey(): Subject {
338-
const apiKey = this.cfg.get('authentication:apiKey');
339-
return apiKey
340-
? {
341-
id: 'apiKey',
342-
token: apiKey,
343-
}
344-
: undefined;
345-
}
346-
347253
get entityName() {
348254
return this.name;
349255
}
@@ -641,13 +547,7 @@ export class OrderingService
641547
).then(
642548
response => {
643549
if (response.operation_status?.code === 200) {
644-
return response?.items?.reduce(
645-
(a, b) => {
646-
a[b.payload.id] = b as OrderResponse;
647-
return a;
648-
},
649-
{} as OrderMap
650-
) ?? {};
550+
return toObjectMap(response.items);
651551
}
652552
else {
653553
throw response.operation_status;
@@ -851,12 +751,7 @@ export class OrderingService
851751
);
852752
}
853753
else {
854-
return response.items!.reduce(
855-
(a, b) => {
856-
a[b.payload.id] = b;
857-
return a;
858-
}, {} as ProductMap
859-
);
754+
return toObjectMap(response.items);
860755
}
861756
}
862757
);
@@ -1405,7 +1300,6 @@ export class OrderingService
14051300
const vats = taxes.filter(
14061301
t => (
14071302
t.country_id === country?.id &&
1408-
order.customer_type === CustomerType.PRIVATE &&
14091303
country?.economic_areas?.some(
14101304
ea => billing_country?.payload?.economic_areas?.includes(ea)
14111305
) && (
@@ -1853,10 +1747,10 @@ export class OrderingService
18531747
items: orders.items?.map(item => ({
18541748
order_id: item.payload.id,
18551749
})),
1856-
subject: this.fulfillment_tech_user ?? this.ApiKey ?? request.subject,
1750+
subject: this.fulfillment_tech_user ?? request.subject,
18571751
},
18581752
context,
1859-
toObjectMap<OrderMap>(orders.items),
1753+
toObjectMap(orders.items),
18601754
).then(
18611755
r => {
18621756
r.items?.forEach(
@@ -2328,7 +2222,7 @@ export class OrderingService
23282222
{
23292223
items: valids.map(item => item.payload),
23302224
total_count: valids.length,
2331-
subject: this.fulfillment_tech_user ?? this.ApiKey ?? request.subject,
2225+
subject: this.fulfillment_tech_user ?? request.subject,
23322226
},
23332227
context
23342228
).then(
@@ -2407,7 +2301,7 @@ export class OrderingService
24072301
{
24082302
items: valids.map(item => item.payload),
24092303
total_count: valids.length,
2410-
subject: this.fulfillment_tech_user ?? this.ApiKey ?? request.subject,
2304+
subject: this.fulfillment_tech_user ?? request.subject,
24112305
},
24122306
context
24132307
).then(
@@ -2801,14 +2695,16 @@ export class OrderingService
28012695
proto => proto.payload!
28022696
);
28032697

2804-
const response = await this.invoice_service!.render(
2698+
const action = this.invoice_service.create;
2699+
const response = await action(
28052700
{
28062701
items: valids,
28072702
total_count: valids.length,
2808-
subject: this.invoice_tech_user ?? this.ApiKey ?? request.subject,
2703+
subject: this.invoice_tech_user ?? request.subject,
28092704
},
28102705
context
28112706
);
2707+
28122708

28132709
return {
28142710
items: [

src/utils.ts

+168
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import { BigNumber } from 'bignumber.js';
2+
import {
3+
Client,
4+
} from '@restorecommerce/grpc-client';
5+
import {
6+
OrderResponse,
7+
} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/order.js';
8+
import {
9+
PhysicalProduct,
10+
PhysicalVariant,
11+
ProductResponse,
12+
ProductServiceDefinition,
13+
ServiceProduct,
14+
ServiceVariant,
15+
VirtualProduct,
16+
VirtualVariant
17+
} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/product.js';
18+
import {
19+
TaxServiceDefinition, Tax
20+
} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/tax.js';
21+
import {
22+
CustomerServiceDefinition, CustomerResponse, CustomerType,
23+
} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/customer.js';
24+
import {
25+
ShopServiceDefinition, ShopResponse
26+
} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/shop.js';
27+
import {
28+
OrganizationResponse, OrganizationServiceDefinition
29+
} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/organization.js';
30+
import {
31+
ContactPointServiceDefinition, ContactPointResponse
32+
} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/contact_point.js';
33+
import {
34+
CurrencyServiceDefinition, CurrencyResponse
35+
} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/currency.js';
36+
import {
37+
AddressServiceDefinition, AddressResponse
38+
} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/address.js';
39+
import {
40+
CountryServiceDefinition, CountryResponse
41+
} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/country.js';
42+
import {
43+
FulfillmentServiceDefinition,
44+
FulfillmentResponse,
45+
} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/fulfillment.js';
46+
import {
47+
FulfillmentProductServiceDefinition,
48+
FulfillmentSolutionResponse,
49+
} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/fulfillment_product.js';
50+
import {
51+
Resource,
52+
ResourceResponse,
53+
} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/resource_base.js';
54+
import {
55+
OperationStatus,
56+
Status,
57+
} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/status.js';
58+
import {
59+
Position,
60+
InvoiceServiceDefinition
61+
} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/invoice.js';
62+
import {
63+
VAT
64+
} from '@restorecommerce/rc-grpc-clients/dist/generated-server/io/restorecommerce/amount.js';
65+
66+
export type BigVAT = {
67+
tax_id: string;
68+
vat: BigNumber;
69+
};
70+
71+
export type BigAmount = {
72+
currency_id: string;
73+
gross: BigNumber;
74+
net: BigNumber;
75+
vats: VAT[];
76+
};
77+
78+
export type RatioedTax = Tax & {
79+
tax_ratio?: number;
80+
};
81+
82+
export type Entity = Resource & ResourceResponse;
83+
export type ObjectMap<T extends Entity> = { [key: string]: T };
84+
export type OrderMap = ObjectMap<OrderResponse>;
85+
export type ProductMap = ObjectMap<ProductResponse>;
86+
export type RatioedTaxMap = ObjectMap<RatioedTax>;
87+
export type CustomerMap = ObjectMap<CustomerResponse>;
88+
export type CurrencyMap = ObjectMap<CurrencyResponse>;
89+
export type ShopMap = ObjectMap<ShopResponse>;
90+
export type OrganizationMap = ObjectMap<OrganizationResponse>;
91+
export type ContactPointMap = ObjectMap<ContactPointResponse>;
92+
export type AddressMap = ObjectMap<AddressResponse>;
93+
export type CountryMap = ObjectMap<CountryResponse>;
94+
export type PositionMap = ObjectMap<Position>;
95+
export type StatusMap = ObjectMap<Status>;
96+
97+
export type FulfillmentMap = { [key: string]: FulfillmentResponse[] };
98+
export type FulfillmentSolutionMap = { [key: string]: FulfillmentSolutionResponse };
99+
export type OperationStatusMap = { [key: string]: OperationStatus };
100+
export type VATMap = { [key: string]: VAT };
101+
export type ProductNature = PhysicalProduct & VirtualProduct & ServiceProduct;
102+
export type ProductVariant = PhysicalVariant & VirtualVariant & ServiceVariant;
103+
export type CRUDClient = Client<ProductServiceDefinition>
104+
| Client<TaxServiceDefinition>
105+
| Client<CustomerServiceDefinition>
106+
| Client<ShopServiceDefinition>
107+
| Client<OrganizationServiceDefinition>
108+
| Client<ContactPointServiceDefinition>
109+
| Client<AddressServiceDefinition>
110+
| Client<CountryServiceDefinition>
111+
| Client<FulfillmentServiceDefinition>
112+
| Client<FulfillmentProductServiceDefinition>
113+
| Client<CurrencyServiceDefinition>
114+
| Client<InvoiceServiceDefinition>;
115+
116+
117+
export const toObjectMap = <T extends Entity>(items: T[]): ObjectMap<T> => items.reduce(
118+
(a, b) => {
119+
a[b.id ?? b.payload?.id] = b;
120+
return a;
121+
},
122+
{} as ObjectMap<T>
123+
) ?? {};
124+
125+
export const DefaultUrns = {
126+
instanceType: 'urn:restorecommerce:acs:model:order:Order',
127+
ownerIndicatoryEntity: 'urn:restorecommerce:acs:names:ownerIndicatoryEntity',
128+
ownerInstance: 'urn:restorecommerce:acs:names:ownerInstance',
129+
organization: 'urn:restorecommerce:acs:model:organization.Organization',
130+
user: 'urn:restorecommerce:acs:model:user.User',
131+
132+
shop_fulfillment_create_enabled: 'urn:restorecommerce:shop:setting:order:create:fulfillment:enabled',
133+
shop_fulfillment_submit_enabled: 'urn:restorecommerce:shop:setting:order:submit:fulfillment:enabled',
134+
shop_invoice_create_enabled: 'urn:restorecommerce:shop:setting:order:create:invoice:enabled',
135+
shop_invoice_render_enabled: 'urn:restorecommerce:shop:setting:order:render:invoice:enabled',
136+
shop_invoice_send_enabled: 'urn:restorecommerce:shop:setting:order:send:invoice:enabled',
137+
138+
139+
/*
140+
disableFulfillment: 'urn:restorecommerce:order:preferences:disableFulfillment',
141+
disableInvoice: 'urn:restorecommerce:order:preferences:disableInvoice',
142+
entity: 'urn:restorecommerce:acs:names:model:entity',
143+
model: 'urn:restorecommerce:acs:model',
144+
role: 'urn:restorecommerce:acs:names:role',
145+
roleScopingEntity: 'urn:restorecommerce:acs:names:roleScopingEntity',
146+
roleScopingInstance: 'urn:restorecommerce:acs:names:roleScopingInstance',
147+
unauthenticated_user: 'urn:restorecommerce:acs:names:unauthenticated-user',
148+
property: 'urn:restorecommerce:acs:names:model:property',
149+
orgScope: 'urn:restorecommerce:acs:model:organization.Organization',
150+
subjectID: 'urn:oasis:names:tc:xacml:1.0:subject:subject-id',
151+
resourceID: 'urn:oasis:names:tc:xacml:1.0:resource:resource-id',
152+
actionID: 'urn:oasis:names:tc:xacml:1.0:action:action-id',
153+
action: 'urn:restorecommerce:acs:names:action',
154+
operation: 'urn:restorecommerce:acs:names:operation',
155+
execute: 'urn:restorecommerce:acs:names:action:execute',
156+
permitOverrides: 'urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:permit-overrides',
157+
denyOverrides: 'urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:deny-overrides',
158+
create: 'urn:restorecommerce:acs:names:action:create',
159+
read: 'urn:restorecommerce:acs:names:action:read',
160+
modify: 'urn:restorecommerce:acs:names:action:modify',
161+
delete: 'urn:restorecommerce:acs:names:action:delete',
162+
aclIndicatoryEntity: 'urn:restorecommerce:acs:names:aclIndicatoryEntity',
163+
aclInstance: 'urn:restorecommerce:acs:names:aclInstance',
164+
skipACL: 'urn:restorecommerce:acs:names:skipACL',
165+
maskedProperty: 'urn:restorecommerce:acs:names:obligation:maskedProperty',
166+
*/
167+
};
168+
export type KnownUrns = typeof DefaultUrns;

test/utils.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export async function mockServices(configs: { [key: string]: any }) {
4444
}
4545

4646
if (!rules[name]) {
47-
throw `No mocking rules for ${name} in mocks.ts!`
47+
throw new Error(`No mocking rules for ${name} in mocks.ts!`)
4848
}
4949

5050
return await new GrpcMockServer(

0 commit comments

Comments
 (0)