Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(payments-plugin): Add multi-currency support for Braintree #3223

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
## <small>3.0.6 (2024-11-15)</small>


#### Fixes

* **admin-ui** Fix collection product filter dark theme (#3172) ([9f4eb9e](https://github.com/vendure-ecommerce/vendure/commit/9f4eb9e)), closes [#3172](https://github.com/vendure-ecommerce/vendure/issues/3172)
* **admin-ui** Fix incorrect type when dealing with numeric value in list (#3094) ([76d66c6](https://github.com/vendure-ecommerce/vendure/commit/76d66c6)), closes [#3094](https://github.com/vendure-ecommerce/vendure/issues/3094) [#3093](https://github.com/vendure-ecommerce/vendure/issues/3093)
* **admin-ui** Fix variant detail quick-jump component (#3189) ([478989e](https://github.com/vendure-ecommerce/vendure/commit/478989e)), closes [#3189](https://github.com/vendure-ecommerce/vendure/issues/3189)
* **admin-ui** Make registerPageTab work on 'order-list' location (#3187) ([61d808b](https://github.com/vendure-ecommerce/vendure/commit/61d808b)), closes [#3187](https://github.com/vendure-ecommerce/vendure/issues/3187)
* **admin-ui** Refund order dialog is showing the wrong field for prorated unit price (#3151) ([3777555](https://github.com/vendure-ecommerce/vendure/commit/3777555)), closes [#3151](https://github.com/vendure-ecommerce/vendure/issues/3151)
* **admin-ui** Swedish translation adjustments (#3174) ([a21f129](https://github.com/vendure-ecommerce/vendure/commit/a21f129)), closes [#3174](https://github.com/vendure-ecommerce/vendure/issues/3174)
* **common** Allow null on idsAreEqual function (#3171) ([7bba907](https://github.com/vendure-ecommerce/vendure/commit/7bba907)), closes [#3171](https://github.com/vendure-ecommerce/vendure/issues/3171)
* **core** Added deprecation notices to the old refund input fields (#3119) ([7324bb3](https://github.com/vendure-ecommerce/vendure/commit/7324bb3)), closes [#3119](https://github.com/vendure-ecommerce/vendure/issues/3119)
* **core** Disallow deletion of default channel (#3181) ([2ed3211](https://github.com/vendure-ecommerce/vendure/commit/2ed3211)), closes [#3181](https://github.com/vendure-ecommerce/vendure/issues/3181)
* **core** Fix error on internal Administrator customFields (#3159) ([e03b7f0](https://github.com/vendure-ecommerce/vendure/commit/e03b7f0)), closes [#3159](https://github.com/vendure-ecommerce/vendure/issues/3159)
* **core** Fix merging order with conflicting products using UseGuestStrategy (#3155) ([f0607aa](https://github.com/vendure-ecommerce/vendure/commit/f0607aa)), closes [#3155](https://github.com/vendure-ecommerce/vendure/issues/3155)
* **core** Fix returning stale data in Role Update Event (#3154) ([71f85d2](https://github.com/vendure-ecommerce/vendure/commit/71f85d2)), closes [#3154](https://github.com/vendure-ecommerce/vendure/issues/3154)
* **payments-plugin** Check for eligibility of Mollie method (#3200) ([a12dedc](https://github.com/vendure-ecommerce/vendure/commit/a12dedc)), closes [#3200](https://github.com/vendure-ecommerce/vendure/issues/3200)
* **payments-plugin** prevent false positive logging (#3195) ([961297d](https://github.com/vendure-ecommerce/vendure/commit/961297d)), closes [#3195](https://github.com/vendure-ecommerce/vendure/issues/3195)
* **testing** Make test client's `fileUploadMutation` work for more input variable shapes (#3188) ([a8938f4](https://github.com/vendure-ecommerce/vendure/commit/a8938f4)), closes [#3188](https://github.com/vendure-ecommerce/vendure/issues/3188)

## <small>3.0.5 (2024-10-15)</small>


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ A component for selecting product variants via an autocomplete-style select inpu

```HTML
<vdr-product-variant-selector
(productSelected)="selectResult($event)"></vdr-product-selector>
(productSelected)="selectResult($event)"></vdr-product-variant-selector>
```

```ts title="Signature"
Expand Down
6 changes: 4 additions & 2 deletions lerna.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
{
"packages": ["packages/*"],
"packages": [
"packages/*"
],
"version": "3.1.0-next.3",
"npmClient": "npm",
"command": {
"version": {
"push": false
}
}
}
}
26 changes: 25 additions & 1 deletion license/signatures/version1/cla.json
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,30 @@
"created_at": "2024-10-31T08:42:52Z",
"repoId": 136938012,
"pullRequestNo": 3174
},
{
"name": "kkerti",
"id": 47832952,
"comment_id": 2458191015,
"created_at": "2024-11-05T21:33:05Z",
"repoId": 136938012,
"pullRequestNo": 3187
},
{
"name": "shingoaoyama1",
"id": 17615101,
"comment_id": 2459213307,
"created_at": "2024-11-06T10:15:37Z",
"repoId": 136938012,
"pullRequestNo": 3192
},
{
"name": "agoransson",
"id": 487002,
"comment_id": 2466157456,
"created_at": "2024-11-09T10:08:00Z",
"repoId": 136938012,
"pullRequestNo": 3205
}
]
}
}
2 changes: 1 addition & 1 deletion packages/admin-ui-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@
"express-rate-limit": "^7.4.0",
"fs-extra": "^11.2.0"
}
}
}
2 changes: 1 addition & 1 deletion packages/admin-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,4 @@
"rimraf": "^5.0.5",
"typescript": "5.3.3"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,17 @@ export class ProductVariantQuickJumpComponent implements OnInit {
@Input() productId: string;
selectedVariantId: string | undefined;
variants$: Observable<NonNullable<GetProductVariantsQuickJumpQuery['product']>['variants']>;
constructor(private dataService: DataService, private router: Router) {}
constructor(
private dataService: DataService,
private router: Router,
) {}

ngOnInit() {
this.variants$ = this.dataService
.query(GetProductVariantsQuickJumpDocument, {
id: this.productId,
})
.mapSingle(data => data.product?.variants ?? []);
.mapStream(data => data.product?.variants ?? []);
}

searchFn = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { DataService } from '../../../data/providers/data.service';
* @example
* ```HTML
* <vdr-product-variant-selector
* (productSelected)="selectResult($event)"></vdr-product-selector>
* (productSelected)="selectResult($event)"></vdr-product-variant-selector>
* ```
*
* @docsCategory components
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,12 @@ export class DynamicFormInputComponent
if (this.listItems) {
for (const item of this.listItems) {
if (item.componentRef) {
const { value } = item.control;
const { type } = item.componentRef.instance.config || {};
// fix a bug where the list item of string turns into number which lead to unexpected behavior
if (typeof value === 'number' && type === 'string') {
item.control.setValue(item.control.value.toString(), { emitEvent: false });
}
this.updateBindings(changes, item.componentRef);
}
}
Expand Down Expand Up @@ -280,7 +286,7 @@ export class DynamicFormInputComponent
({
id: this.listId++,
control: new UntypedFormControl(getConfigArgValue(value)),
} as InputListItem),
}) as InputListItem,
);
this.renderList$.next();
}
Expand Down
1 change: 0 additions & 1 deletion packages/admin-ui/src/lib/order/src/order.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export const createRoutes = (pageService: PageService): Route[] => [
{
path: '',
component: PageComponent,
pathMatch: 'full',
data: {
locationId: 'order-list',
breadcrumb: _('breadcrumb.orders'),
Expand Down
2 changes: 1 addition & 1 deletion packages/asset-server-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@
"fs-extra": "^11.2.0",
"sharp": "~0.33.2"
}
}
}
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@
"@vendure/core": "3.1.0-next.3",
"typescript": "5.3.3"
}
}
}
2 changes: 1 addition & 1 deletion packages/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@
"rimraf": "^5.0.5",
"typescript": "5.3.3"
}
}
}
20 changes: 20 additions & 0 deletions packages/core/e2e/channel.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,26 @@ describe('Channels', () => {
expect(product!.channels.map(c => c.id)).toEqual(['T_1']);
});

it('Fail to delete the default channel', async () => {
await adminClient.asSuperAdmin();

const defaultChannelId = (
await adminClient.query<Codegen.GetChannelsQuery, Codegen.GetChannelsQueryVariables>(GET_CHANNELS)
).channels.items.find(channel => channel.code === DEFAULT_CHANNEL_CODE)?.id;

expect(defaultChannelId).not.toBeUndefined();

const mutation = await adminClient.query<
Codegen.DeleteChannelMutation,
Codegen.DeleteChannelMutationVariables
>(DELETE_CHANNEL, { id: defaultChannelId! });

expect(mutation.deleteChannel).toEqual({
result: DeletionResult.NOT_DELETED,
message: 'The default Channel cannot be deleted',
});
});

describe('currencyCode support', () => {
beforeAll(async () => {
await adminClient.asSuperAdmin();
Expand Down
19 changes: 19 additions & 0 deletions packages/core/e2e/order-merge.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,25 @@ describe('Order merging', () => {
).toEqual([{ productVariantId: 'T_5', quantity: 3 }]);
});

it('UseGuestStrategy with conflicting lines', async () => {
const result = await testMerge({
strategy: new UseGuestStrategy(),
customerEmailAddress: customers[8].emailAddress,
existingOrderLines: [
{ productVariantId: 'T_7', quantity: 1 },
{ productVariantId: 'T_8', quantity: 1 },
],
guestOrderLines: [{ productVariantId: 'T_8', quantity: 3 }],
});

expect(
(result?.lines || []).sort(sortById).map(line => ({
productVariantId: line.productVariant.id,
quantity: line.quantity,
})),
).toEqual([{ productVariantId: 'T_8', quantity: 3 }]);
});

it('UseGuestIfExistingEmptyStrategy with empty existing', async () => {
const result = await testMerge({
strategy: new UseGuestIfExistingEmptyStrategy(),
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,4 @@
"sqlite3": "^5.1.7",
"typescript": "5.3.3"
}
}
}
22 changes: 10 additions & 12 deletions packages/core/src/api/schema/admin-api/order.api.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -111,14 +111,12 @@ input CancelOrderInput {
}

input RefundOrderInput {
lines: [OrderLineInput!]!
shipping: Money!
adjustment: Money!
lines: [OrderLineInput!] @deprecated(reason: "Use the `amount` field instead")
shipping: Money @deprecated(reason: "Use the `amount` field instead")
adjustment: Money @deprecated(reason: "Use the `amount` field instead")
"""
If an amount is specified, this value will be used to create a Refund rather than calculating the
amount automatically. This was added in v2.2 and will be the preferred way to specify the refund
amount in the future. The `lines`, `shipping` and `adjustment` fields will likely be removed in a future
version.
The amount to be refunded to this particular payment. This was introduced in v2.2.0 as the preferred way to specify the refund amount.
Can be as much as the total amount of the payment minus the sum of all previous refunds.
"""
amount: Money
paymentId: ID!
Expand Down Expand Up @@ -410,28 +408,28 @@ type ManualPaymentStateError implements ErrorResult {

union TransitionOrderToStateResult = Order | OrderStateTransitionError
union SettlePaymentResult =
Payment
| Payment
| SettlePaymentError
| PaymentStateTransitionError
| OrderStateTransitionError
union CancelPaymentResult = Payment | CancelPaymentError | PaymentStateTransitionError
union AddFulfillmentToOrderResult =
Fulfillment
| Fulfillment
| EmptyOrderLineSelectionError
| ItemsAlreadyFulfilledError
| InsufficientStockOnHandError
| InvalidFulfillmentHandlerError
| FulfillmentStateTransitionError
| CreateFulfillmentError
union CancelOrderResult =
Order
| Order
| EmptyOrderLineSelectionError
| QuantityTooGreatError
| MultipleOrderError
| CancelActiveOrderError
| OrderStateTransitionError
union RefundOrderResult =
Refund
| Refund
| QuantityTooGreatError
| NothingToRefundError
| OrderStateTransitionError
Expand All @@ -445,7 +443,7 @@ union SettleRefundResult = Refund | RefundStateTransitionError
union TransitionFulfillmentToStateResult = Fulfillment | FulfillmentStateTransitionError
union TransitionPaymentToStateResult = Payment | PaymentStateTransitionError
union ModifyOrderResult =
Order
| Order
| NoChangesSpecifiedError
| OrderModificationStateError
| PaymentMethodMissingError
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/messages/de.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"error": {
"cannot-delete-role": "Die Rolle \"{ roleCode }\" kann nicht gelöscht werden",
"cannot-delete-default-channel": "Der Standardkanal kann nicht gelöscht werden",
"cannot-locate-customer-for-user": "Es konnte kein Kunde für den Nutzer gefunden werden",
"cannot-modify-role": "Die Rolle \"{ roleCode }\" kann nicht geändert werden",
"cannot-create-sales-for-active-order": "Es kann kein Sale für eine aktive Bestellung erstellt werden",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"available-currency-codes-must-include-default": "availableCurrencyCodes must include the defaultCurrencyCode ({ defaultCurrencyCode })",
"cannot-delete-role": "The role \"{ roleCode }\" cannot be deleted",
"cannot-delete-sole-superadmin": "The sole SuperAdmin cannot be deleted",
"cannot-delete-default-channel": "The default Channel cannot be deleted",
"cannot-locate-customer-for-user": "Cannot locate a Customer for the user",
"cannot-modify-role": "The role \"{ roleCode }\" cannot be modified",
"cannot-move-collection-into-self": "Cannot move a Collection into itself",
Expand Down
6 changes: 6 additions & 0 deletions packages/core/src/service/services/channel.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,12 @@ export class ChannelService {

async delete(ctx: RequestContext, id: ID): Promise<DeletionResponse> {
const channel = await this.connection.getEntityOrThrow(ctx, Channel, id);
if (channel.code === DEFAULT_CHANNEL_CODE)
return {
result: DeletionResult.NOT_DELETED,
message: ctx.translate('error.cannot-delete-default-channel'),
};

const deletedChannel = new Channel(channel);
await this.connection.getRepository(ctx, Session).delete({ activeChannelId: id });
await this.connection.getRepository(ctx, Channel).delete(id);
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/service/services/order.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1763,6 +1763,11 @@ export class OrderService {
const result = await this.addItemsToOrder(ctx, orderId, linesToInsert);
order = result.order;
}
if (order && linesToInsert) {
const orderId = order.id;
const result = await this.addItemsToOrder(ctx, orderId, linesToInsert);
order = result.order;
}
if (order && linesToModify) {
const orderId = order.id;
const result = await this.adjustOrderLines(ctx, orderId, linesToModify);
Expand Down
11 changes: 6 additions & 5 deletions packages/core/src/service/services/role.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,19 +267,20 @@ export class RoleService {
input.permissions,
);
}
const updatedRole = patchEntity(role, {
patchEntity(role, {
code: input.code,
description: input.description,
permissions: input.permissions
? unique([Permission.Authenticated, ...input.permissions])
: undefined,
});
if (targetChannels) {
updatedRole.channels = targetChannels;
role.channels = targetChannels;
}
await this.connection.getRepository(ctx, Role).save(updatedRole, { reload: false });
await this.eventBus.publish(new RoleEvent(ctx, role, 'updated', input));
return await assertFound(this.findOne(ctx, role.id));
await this.connection.getRepository(ctx, Role).save(role, { reload: false });
const updatedRole = await assertFound(this.findOne(ctx, role.id));
await this.eventBus.publish(new RoleEvent(ctx, updatedRole, 'updated', input));
return updatedRole;
}

async delete(ctx: RequestContext, id: ID): Promise<DeletionResponse> {
Expand Down
2 changes: 1 addition & 1 deletion packages/create/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@
"semver": "^7.5.4",
"tcp-port-used": "^1.0.2"
}
}
}
1 change: 1 addition & 0 deletions packages/dev-server/dev-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ export const devConfig: VendureConfig = {
changeEmailAddressUrl: 'http://localhost:4201/change-email-address',
},
}),

AdminUiPlugin.init({
route: 'admin',
port: 5001,
Expand Down
Loading