Просмотр исходного кода

feat(admin-ui): Improved refund dialog

Relates to #2393
Michael Bromley 2 лет назад
Родитель
Сommit
ccbf9ec7e8
29 измененных файлов с 618 добавлено и 365 удалено
  1. 55 55
      packages/admin-ui/i18n-coverage.json
  2. 1 1
      packages/admin-ui/src/lib/core/src/common/generated-types.ts
  3. 4 0
      packages/admin-ui/src/lib/core/src/data/definitions/order-definitions.ts
  4. 4 0
      packages/admin-ui/src/lib/core/src/shared/components/currency-input/currency-input.component.scss
  5. 33 24
      packages/admin-ui/src/lib/order/src/components/order-detail/order-detail.component.ts
  6. 23 0
      packages/admin-ui/src/lib/order/src/components/order-table/order-table.component.html
  7. 216 154
      packages/admin-ui/src/lib/order/src/components/refund-order-dialog/refund-order-dialog.component.html
  8. 38 16
      packages/admin-ui/src/lib/order/src/components/refund-order-dialog/refund-order-dialog.component.scss
  9. 129 68
      packages/admin-ui/src/lib/order/src/components/refund-order-dialog/refund-order-dialog.component.ts
  10. 0 6
      packages/admin-ui/src/lib/order/src/order.routes.ts
  11. 6 2
      packages/admin-ui/src/lib/static/i18n-messages/ar.json
  12. 6 2
      packages/admin-ui/src/lib/static/i18n-messages/cs.json
  13. 6 2
      packages/admin-ui/src/lib/static/i18n-messages/de.json
  14. 6 2
      packages/admin-ui/src/lib/static/i18n-messages/en.json
  15. 6 2
      packages/admin-ui/src/lib/static/i18n-messages/es.json
  16. 6 2
      packages/admin-ui/src/lib/static/i18n-messages/fa.json
  17. 6 2
      packages/admin-ui/src/lib/static/i18n-messages/fr.json
  18. 6 2
      packages/admin-ui/src/lib/static/i18n-messages/he.json
  19. 6 2
      packages/admin-ui/src/lib/static/i18n-messages/hr.json
  20. 6 2
      packages/admin-ui/src/lib/static/i18n-messages/it.json
  21. 7 4
      packages/admin-ui/src/lib/static/i18n-messages/nb.json
  22. 6 2
      packages/admin-ui/src/lib/static/i18n-messages/ne.json
  23. 6 2
      packages/admin-ui/src/lib/static/i18n-messages/pl.json
  24. 6 3
      packages/admin-ui/src/lib/static/i18n-messages/pt_BR.json
  25. 6 2
      packages/admin-ui/src/lib/static/i18n-messages/pt_PT.json
  26. 6 2
      packages/admin-ui/src/lib/static/i18n-messages/ru.json
  27. 6 2
      packages/admin-ui/src/lib/static/i18n-messages/uk.json
  28. 6 2
      packages/admin-ui/src/lib/static/i18n-messages/zh_Hans.json
  29. 6 2
      packages/admin-ui/src/lib/static/i18n-messages/zh_Hant.json

+ 55 - 55
packages/admin-ui/i18n-coverage.json

@@ -1,101 +1,101 @@
 {
-  "generatedOn": "2024-01-02T15:08:18.987Z",
-  "lastCommit": "ea8c1798376626a904b61bdb1a4bf4fe1de953ee",
+  "generatedOn": "2024-01-17T15:22:24.662Z",
+  "lastCommit": "5263c2d4e66ca1a87a9f1d36c53f6f8fc2ae48dc",
   "translationStatus": {
     "ar": {
-      "tokenCount": 761,
-      "translatedCount": 761,
-      "percentage": 100
+      "tokenCount": 764,
+      "translatedCount": 759,
+      "percentage": 99
     },
     "cs": {
-      "tokenCount": 761,
-      "translatedCount": 571,
+      "tokenCount": 764,
+      "translatedCount": 570,
       "percentage": 75
     },
     "de": {
-      "tokenCount": 761,
-      "translatedCount": 761,
-      "percentage": 100
+      "tokenCount": 764,
+      "translatedCount": 759,
+      "percentage": 99
     },
     "en": {
-      "tokenCount": 761,
-      "translatedCount": 761,
+      "tokenCount": 764,
+      "translatedCount": 763,
       "percentage": 100
     },
     "es": {
-      "tokenCount": 761,
-      "translatedCount": 761,
-      "percentage": 100
+      "tokenCount": 764,
+      "translatedCount": 759,
+      "percentage": 99
     },
     "fa": {
-      "tokenCount": 761,
-      "translatedCount": 761,
-      "percentage": 100
+      "tokenCount": 764,
+      "translatedCount": 759,
+      "percentage": 99
     },
     "fr": {
-      "tokenCount": 761,
-      "translatedCount": 758,
-      "percentage": 100
+      "tokenCount": 764,
+      "translatedCount": 756,
+      "percentage": 99
     },
     "he": {
-      "tokenCount": 761,
-      "translatedCount": 761,
-      "percentage": 100
+      "tokenCount": 764,
+      "translatedCount": 759,
+      "percentage": 99
     },
     "hr": {
-      "tokenCount": 761,
-      "translatedCount": 760,
-      "percentage": 100
+      "tokenCount": 764,
+      "translatedCount": 758,
+      "percentage": 99
     },
     "it": {
-      "tokenCount": 761,
-      "translatedCount": 761,
-      "percentage": 100
+      "tokenCount": 764,
+      "translatedCount": 759,
+      "percentage": 99
     },
     "nb": {
-      "tokenCount": 761,
-      "translatedCount": 759,
-      "percentage": 100
+      "tokenCount": 764,
+      "translatedCount": 756,
+      "percentage": 99
     },
     "ne": {
-      "tokenCount": 761,
-      "translatedCount": 750,
-      "percentage": 99
+      "tokenCount": 764,
+      "translatedCount": 748,
+      "percentage": 98
     },
     "pl": {
-      "tokenCount": 761,
-      "translatedCount": 400,
-      "percentage": 53
+      "tokenCount": 764,
+      "translatedCount": 398,
+      "percentage": 52
     },
     "pt_BR": {
-      "tokenCount": 761,
-      "translatedCount": 760,
-      "percentage": 100
+      "tokenCount": 764,
+      "translatedCount": 758,
+      "percentage": 99
     },
     "pt_PT": {
-      "tokenCount": 761,
-      "translatedCount": 609,
-      "percentage": 80
+      "tokenCount": 764,
+      "translatedCount": 606,
+      "percentage": 79
     },
     "ru": {
-      "tokenCount": 761,
-      "translatedCount": 761,
-      "percentage": 100
+      "tokenCount": 764,
+      "translatedCount": 759,
+      "percentage": 99
     },
     "uk": {
-      "tokenCount": 761,
-      "translatedCount": 596,
+      "tokenCount": 764,
+      "translatedCount": 594,
       "percentage": 78
     },
     "zh_Hans": {
-      "tokenCount": 761,
-      "translatedCount": 541,
+      "tokenCount": 764,
+      "translatedCount": 539,
       "percentage": 71
     },
     "zh_Hant": {
-      "tokenCount": 761,
-      "translatedCount": 387,
-      "percentage": 51
+      "tokenCount": 764,
+      "translatedCount": 385,
+      "percentage": 50
     }
   }
 }

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
packages/admin-ui/src/lib/core/src/common/generated-types.ts


+ 4 - 0
packages/admin-ui/src/lib/core/src/data/definitions/order-definitions.ts

@@ -126,6 +126,8 @@ export const PAYMENT_WITH_REFUNDS_FRAGMENT = gql`
 export const ORDER_LINE_FRAGMENT = gql`
     fragment OrderLine on OrderLine {
         id
+        createdAt
+        updatedAt
         featuredAsset {
             preview
         }
@@ -211,6 +213,8 @@ export const ORDER_DETAIL_FRAGMENT = gql`
         shipping
         shippingWithTax
         shippingLines {
+            id
+            discountedPriceWithTax
             shippingMethod {
                 id
                 code

+ 4 - 0
packages/admin-ui/src/lib/core/src/shared/components/currency-input/currency-input.component.scss

@@ -1,6 +1,10 @@
 :host {
     padding: 0;
     border: none;
+    &.ng-invalid input[type='number'] {
+        color: var(--color-error-700);
+        border-color: var(--color-error-300);
+    }
 }
 
 input {

+ 33 - 24
packages/admin-ui/src/lib/order/src/components/order-detail/order-detail.component.ts

@@ -20,7 +20,7 @@ import {
 } from '@vendure/admin-ui/core';
 import { assertNever, summate } from '@vendure/common/lib/shared-utils';
 import { gql } from 'apollo-angular';
-import { EMPTY, Observable, of, Subject } from 'rxjs';
+import { EMPTY, forkJoin, Observable, of, Subject } from 'rxjs';
 import { map, mapTo, startWith, switchMap, take } from 'rxjs/operators';
 
 import { OrderTransitionService } from '../../providers/order-transition.service';
@@ -567,7 +567,12 @@ export class OrderDetailComponent
                                 switch (result.__typename) {
                                     case 'Order':
                                         this.refetchOrder(result).subscribe();
-                                        this.notificationService.success(_('order.cancelled-order-success'));
+                                        this.notificationService.success(
+                                            _('order.cancelled-order-items-success'),
+                                            {
+                                                count: summate(input.cancel.lines, 'quantity'),
+                                            },
+                                        );
                                         return input;
                                     case 'CancelActiveOrderError':
                                     case 'QuantityTooGreatError':
@@ -587,35 +592,39 @@ export class OrderDetailComponent
                     if (!input) {
                         return of(undefined);
                     }
-                    if (input.refund.lines.length) {
-                        return this.dataService.order
-                            .refundOrder(input.refund)
-                            .pipe(map(res => res.refundOrder));
+                    if (input.refunds.length) {
+                        return forkJoin(
+                            input.refunds.map(refund =>
+                                this.dataService.order.refundOrder(refund).pipe(map(res => res.refundOrder)),
+                            ),
+                        );
                     } else {
                         return [undefined];
                     }
                 }),
             )
-            .subscribe(result => {
-                if (result) {
-                    switch (result.__typename) {
-                        case 'Refund':
-                            this.refetchOrder(result).subscribe();
-                            if (result.state === 'Failed') {
-                                this.notificationService.error(_('order.refund-order-failed'));
-                            } else {
-                                this.notificationService.success(_('order.refund-order-success'));
-                            }
-                            break;
-                        case 'AlreadyRefundedError':
-                        case 'NothingToRefundError':
-                        case 'PaymentOrderMismatchError':
-                        case 'RefundOrderStateError':
-                        case 'RefundStateTransitionError':
-                            this.notificationService.error(result.message);
-                            break;
+            .subscribe(results => {
+                for (const result of results ?? []) {
+                    if (result) {
+                        switch (result.__typename) {
+                            case 'Refund':
+                                if (result.state === 'Failed') {
+                                    this.notificationService.error(_('order.refund-order-failed'));
+                                } else {
+                                    this.notificationService.success(_('order.refund-order-success'));
+                                }
+                                break;
+                            case 'AlreadyRefundedError':
+                            case 'NothingToRefundError':
+                            case 'PaymentOrderMismatchError':
+                            case 'RefundOrderStateError':
+                            case 'RefundStateTransitionError':
+                                this.notificationService.error(result.message);
+                                break;
+                        }
                     }
                 }
+                this.refetchOrder(results?.[0]).subscribe();
             });
     }
 

+ 23 - 0
packages/admin-ui/src/lib/order/src/components/order-table/order-table.component.html

@@ -1,4 +1,27 @@
 <vdr-order-data-table id="order-detail-list" [items]="order.lines" [order]="order">
+    <vdr-dt2-column id="id" [heading]="'common.id' | translate" [hiddenByDefault]="true">
+        <ng-template let-line="item">
+            {{ line.id }}
+        </ng-template>
+    </vdr-dt2-column>
+    <vdr-dt2-column
+            id="created-at"
+            [heading]="'common.created-at' | translate"
+            [hiddenByDefault]="true"
+    >
+        <ng-template let-line="item">
+            {{ line.createdAt | localeDate : 'short' }}
+        </ng-template>
+    </vdr-dt2-column>
+    <vdr-dt2-column
+            id="updated-at"
+            [heading]="'common.updated-at' | translate"
+            [hiddenByDefault]="true"
+    >
+        <ng-template let-line="item">
+            {{ line.updatedAt | localeDate : 'short' }}
+        </ng-template>
+    </vdr-dt2-column>
     <vdr-dt2-column [heading]="'common.image' | translate" id="image">
         <ng-template let-line="item">
             <div class="image-placeholder">

+ 216 - 154
packages/admin-ui/src/lib/order/src/components/refund-order-dialog/refund-order-dialog.component.html

@@ -1,81 +1,99 @@
 <ng-template vdrDialogTitle>{{ 'order.refund-and-cancel-order' | translate }}</ng-template>
 
 <div class="refund-wrapper">
-    <div class="order-table">
-        <table class="table">
-            <thead>
-                <tr>
-                    <th></th>
-                    <th>{{ 'order.product-name' | translate }}</th>
-                    <th>{{ 'order.product-sku' | translate }}</th>
-                    <th>{{ 'order.quantity' | translate }}</th>
-                    <th>{{ 'order.unit-price' | translate }}</th>
-                    <th>{{ 'order.prorated-unit-price' | translate }}</th>
-                    <th>{{ 'order.quantity' | translate }}</th>
-                    <th>{{ 'order.refund' | translate }}</th>
-                    <th>{{ 'order.cancel' | translate }}</th>
-                </tr>
-            </thead>
-            <tr *ngFor="let line of order.lines" class="order-line">
-                <td class="align-middle thumb">
-                    <img [src]="line.featuredAsset | assetPreview: 'tiny'" />
-                </td>
-                <td class="align-middle name">{{ line.productVariant.name }}</td>
-                <td class="align-middle sku">{{ line.productVariant.sku }}</td>
-                <td class="align-middle quantity">
-                    {{ line.quantity }}
-                    <vdr-line-refunds [line]="line" [payments]="order.payments"></vdr-line-refunds>
-                </td>
-                <td class="align-middle quantity">
-                    {{ line.unitPriceWithTax | localeCurrency: order.currencyCode }}
-                </td>
-                <td class="align-middle quantity">
-                    <div class="prorated-wrapper">
-                        {{ line.proratedUnitPriceWithTax | localeCurrency: order.currencyCode }}
-                        <ng-container *ngIf="line.discounts as discounts">
-                            <vdr-dropdown *ngIf="discounts.length">
-                                <div class="promotions-label" vdrDropdownTrigger>
-                                    <button class="icon-button"><clr-icon shape="info"></clr-icon></button>
-                                </div>
-                                <vdr-dropdown-menu>
-                                    <div class="line-promotion" *ngFor="let discount of discounts">
-                                        {{ discount.description }}
-                                        <div class="promotion-amount">
-                                            {{
-                                                discount.amount / 100 / line.quantity
-                                                    | number: '1.0-2'
-                                                    | currency: order.currencyCode
-                                            }}
-                                        </div>
-                                    </div>
-                                </vdr-dropdown-menu>
-                            </vdr-dropdown>
-                        </ng-container>
-                    </div>
-                </td>
-                <td class="align-middle quantity-col">
-                    <input
-                        *ngIf="lineCanBeRefundedOrCancelled(line)"
-                        [(ngModel)]="lineQuantities[line.id].quantity"
-                        type="number"
-                        [max]="line.quantity"
-                        min="0"
-                        (input)="handleZeroQuantity(lineQuantities[line.id])"
+    <vdr-data-table-2 id="refund-order" [items]="order.lines">
+        <!-- Here we define all the available columns -->
+        <vdr-dt2-column id="id" [heading]="'common.id' | translate" [hiddenByDefault]="true">
+            <ng-template let-line="item">
+                {{ line.id }}
+            </ng-template>
+        </vdr-dt2-column>
+        <vdr-dt2-column id="created-at" [heading]="'common.created-at' | translate" [hiddenByDefault]="true">
+            <ng-template let-line="item">
+                {{ line.createdAt | localeDate : 'short' }}
+            </ng-template>
+        </vdr-dt2-column>
+        <vdr-dt2-column id="updated-at" [heading]="'common.updated-at' | translate" [hiddenByDefault]="true">
+            <ng-template let-line="item">
+                {{ line.updatedAt | localeDate : 'short' }}
+            </ng-template>
+        </vdr-dt2-column>
+        <vdr-dt2-column [heading]="'common.image' | translate" id="image">
+            <ng-template let-line="item">
+                <div class="image-placeholder">
+                    <img
+                        *ngIf="line.featuredAsset as asset; else imagePlaceholder"
+                        [src]="asset | assetPreview : 'tiny'"
                     />
-                </td>
-                <td class="align-middle">
-                    <div class="cancel-checkbox-wrapper">
-                        <input
-                            type="checkbox"
-                            *ngIf="lineCanBeRefundedOrCancelled(line)"
-                            clrCheckbox
-                            [disabled]="0 === lineQuantities[line.id].quantity"
-                            [(ngModel)]="lineQuantities[line.id].refund"
-                        />
-                    </div>
-                </td>
-                <td class="align-middle">
-                    <div class="cancel-checkbox-wrapper">
+                    <ng-template #imagePlaceholder>
+                        <div class="placeholder">
+                            <clr-icon shape="image" size="48"></clr-icon>
+                        </div>
+                    </ng-template>
+                </div>
+            </ng-template>
+        </vdr-dt2-column>
+        <vdr-dt2-column id="product-name" [heading]="'order.product-name' | translate" [optional]="false">
+            <ng-template let-line="item">
+                {{ line.productVariant.name }}
+            </ng-template>
+        </vdr-dt2-column>
+        <vdr-dt2-column id="product-sku" [heading]="'order.product-sku' | translate">
+            <ng-template let-line="item">
+                {{ line.productVariant.sku }}
+            </ng-template>
+        </vdr-dt2-column>
+        <vdr-dt2-column id="unit-price" [heading]="'order.unit-price' | translate" [hiddenByDefault]="true">
+            <ng-template let-line="item">
+                {{ line.unitPriceWithTax | localeCurrency : order.currencyCode }}
+            </ng-template>
+        </vdr-dt2-column>
+        <vdr-dt2-column id="prorated-unit-price" [heading]="'order.prorated-unit-price' | translate">
+            <ng-template let-line="item">
+                {{ line.unitPriceWithTax | localeCurrency : order.currencyCode }}
+                <ng-container *ngIf="line.discounts as discounts">
+                    <vdr-dropdown *ngIf="discounts.length">
+                        <div class="promotions-label" vdrDropdownTrigger>
+                            <button class="icon-button"><clr-icon shape="info"></clr-icon></button>
+                        </div>
+                        <vdr-dropdown-menu>
+                            <div class="line-promotion" *ngFor="let discount of discounts">
+                                {{ discount.description }}
+                                <div class="promotion-amount">
+                                    {{
+                                        discount.amount / 100 / line.quantity
+                                            | number : '1.0-2'
+                                            | currency : order.currencyCode
+                                    }}
+                                </div>
+                            </div>
+                        </vdr-dropdown-menu>
+                    </vdr-dropdown>
+                </ng-container>
+            </ng-template>
+        </vdr-dt2-column>
+        <vdr-dt2-column id="quantity" [heading]="'order.quantity' | translate">
+            <ng-template let-line="item">
+                {{ line.quantity }}
+                <vdr-line-refunds [line]="line" [payments]="order.payments"></vdr-line-refunds>
+            </ng-template>
+        </vdr-dt2-column>
+        <vdr-dt2-column id="refund-quantity" [heading]="'order.refund' | translate" [optional]="false">
+            <ng-template let-line="item">
+                <input
+                    *ngIf="lineCanBeRefundedOrCancelled(line)"
+                    [ngModel]="lineQuantities[line.id].quantity"
+                    type="number"
+                    [max]="line.quantity"
+                    min="0"
+                    (ngModelChange)="onRefundQuantityChange(line.id, $event)"
+                />
+            </ng-template>
+        </vdr-dt2-column>
+        <vdr-dt2-column id="cancel" [heading]="'order.return-to-stock' | translate" [optional]="false">
+            <ng-template let-line="item">
+                <div class="cancel-checkbox-wrapper">
+                    <label class="flex center">
                         <input
                             type="checkbox"
                             *ngIf="lineCanBeRefundedOrCancelled(line)"
@@ -83,96 +101,140 @@
                             [disabled]="0 === lineQuantities[line.id].quantity"
                             [(ngModel)]="lineQuantities[line.id].cancel"
                         />
-                    </div>
-                </td>
-            </tr>
-        </table>
-    </div>
-    <div class="refund-details mt-4" [class.faded]="!isRefunding() && !isCancelling()">
-        <div>
-            <label class="clr-control-label">{{ 'order.refund-cancellation-reason' | translate }}</label>
-            <ng-select
-                [disabled]="!isRefunding() && !isCancelling()"
-                [items]="reasons"
-                bindLabel="name"
-                autofocus
-                [placeholder]="'order.refund-cancellation-reason-required' | translate"
-                bindValue="id"
-                [addTag]="true"
-                [(ngModel)]="reason"
-            ></ng-select>
-        </div>
-
-        <div>
-            <clr-select-container>
-                <label>{{ 'order.payment-to-refund' | translate }}</label>
-                <select clrSelect name="options" [(ngModel)]="selectedPayment" [disabled]="!isRefunding()">
-                    <option
-                        *ngFor="let payment of settledPayments"
-                        [ngValue]="payment"
-                        [disabled]="payment.state !== 'Settled'"
+                        <span class="ml-1">{{ 'order.return-to-stock' | translate }}</span></label
                     >
-                        #{{ payment.id }} {{ payment.method }}:
-                        {{ payment.amount | localeCurrency: order.currencyCode }}
-                    </option>
-                </select>
-            </clr-select-container>
-
-            <clr-checkbox-wrapper>
-                <input type="checkbox" clrCheckbox [(ngModel)]="refundShipping" [disabled]="!isRefunding()" />
-                <label>
-                    {{ 'order.refund-shipping' | translate }} ({{
-                        order.shippingWithTax | localeCurrency: order.currencyCode
-                    }})
-                </label>
-            </clr-checkbox-wrapper>
-            <clr-input-container>
-                <label>{{ 'order.refund-adjustment' | translate }}</label>
-                <vdr-currency-input
-                    clrInput
-                    [disabled]="!isRefunding()"
-                    [currencyCode]="order.currencyCode"
-                    [(ngModel)]="adjustment"
-                ></vdr-currency-input>
-            </clr-input-container>
-            <div class="totals" [class.disabled]="!isRefunding()">
-                <div class="order-total">
-                    {{ 'order.payment-amount' | translate }}:
-                    {{ selectedPayment.amount | localeCurrency: order.currencyCode }}
                 </div>
-                <div class="refund-total">
-                    {{ 'order.refund-total' | translate }}:
-                    {{ refundTotal | localeCurrency: order.currencyCode }}
+            </ng-template>
+        </vdr-dt2-column>
+    </vdr-data-table-2>
+
+    <div class="refund-details mt-4">
+        <div>
+            <vdr-card>
+                <label class="flex mb-2" *ngFor="let shippingLine of order.shippingLines">
+                    <input type="checkbox" clrCheckbox (change)="toggleShippingRefund(shippingLine.id)" />
+                    <div class="ml-1">
+                        {{ 'order.refund-shipping' | translate }}
+                        <span>{{ shippingLine.shippingMethod.name }}:</span>
+                        <span class="ml-1"
+                            >{{ shippingLine.discountedPriceWithTax | localeCurrency : order.currencyCode }}
+                        </span>
+                    </div></label
+                >
+                <vdr-form-field [label]="'order.refund-cancellation-reason' | translate" class="mb-2">
+                    <ng-select
+                        [items]="reasons"
+                        bindLabel="name"
+                        autofocus
+                        [placeholder]="'order.refund-cancellation-reason-required' | translate"
+                        bindValue="id"
+                        [addTag]="true"
+                        [(ngModel)]="reason"
+                    ></ng-select>
+                </vdr-form-field>
+                <vdr-form-field
+                    [label]="'order.refund-total' | translate"
+                    [readOnlyToggle]="true"
+                    (readOnlyToggleChange)="manuallySetRefundTotal = !$event"
+                >
+                    <vdr-currency-input
+                        [readonly]="!manuallySetRefundTotal"
+                        [currencyCode]="order.currencyCode"
+                        [(ngModel)]="refundTotal"
+                        (ngModelChange)="updateRefundTotal()"
+                    ></vdr-currency-input>
+                </vdr-form-field>
+            </vdr-card>
+        </div>
+        <div class="">
+            <vdr-card
+                [title]="'order.payment' | translate"
+                [class.selected]="payment.selected"
+                [class.unselected]="!payment.selected"
+                *ngFor="let payment of refundablePayments"
+            >
+                <ng-template vdrCardControls>
+                    <vdr-select-toggle
+                        size="small"
+                        [title]="'order.refund-this-payment' | translate"
+                        [label]="'order.refund-this-payment' | translate"
+                        [disabled]="refundablePayments.length === 1"
+                        [(selected)]="payment.selected"
+                        (selectedChange)="onPaymentSelected(payment, $event)"
+                    ></vdr-select-toggle>
+                </ng-template>
+                <div class="form-grid">
+                    <vdr-labeled-data [label]="'order.payment-method' | translate">
+                        {{ payment.method }}
+                    </vdr-labeled-data>
+                    <vdr-labeled-data [label]="'order.transaction-id' | translate">
+                        {{ payment.transactionId }}
+                    </vdr-labeled-data>
+                    <vdr-labeled-data [label]="'order.payment-amount' | translate">
+                        {{ payment.amount | localeCurrency : order.currencyCode }}
+                    </vdr-labeled-data>
+                    <vdr-labeled-data [label]="'order.refundable-amount' | translate">
+                        {{ payment.refundableAmount | localeCurrency : order.currencyCode }}
+                    </vdr-labeled-data>
                 </div>
-                <div class="refund-total-error" *ngIf="refundTotal < 0 || settledPaymentsTotal < refundTotal">
+                <vdr-form-field [label]="'order.refund-amount' | translate">
+                    <vdr-currency-input
+                        [readonly]="!payment.selected"
+                        [currencyCode]="order.currencyCode"
+                        [formControl]="payment.amountToRefundControl"
+                    ></vdr-currency-input>
+                </vdr-form-field>
+            </vdr-card>
+        </div>
+    </div>
+</div>
+
+<ng-template vdrDialogButtons>
+    <div>
+        <div class="errors">
+            <clr-alert
+                *ngIf="refundTotal < 0 || totalRefundableAmount < refundTotal"
+                [clrAlertType]="'danger'"
+                [clrAlertClosable]="false"
+            >
+                <clr-alert-item>
                     {{
                         'order.refund-total-error'
                             | translate
                                 : {
-                                      min: 0 | currency: order.currencyCode,
-                                      max: settledPaymentsTotal | localeCurrency: order.currencyCode
+                                      min: 0 | currency : order.currencyCode,
+                                      max: totalRefundableAmount | localeCurrency : order.currencyCode
                                   }
                     }}
-                </div>
-                <div class="refund-total-warning" *ngIf="selectedPayment.amount < refundTotal">
+                </clr-alert-item>
+            </clr-alert>
+            <clr-alert
+                *ngIf="amountToRefundTotal < refundTotal || refundTotal < amountToRefundTotal"
+                [clrAlertType]="'danger'"
+                [clrAlertClosable]="false"
+            >
+                <clr-alert-item>
                     {{ 'order.refund-total-warning' | translate }}
-                </div>
-            </div>
+                </clr-alert-item>
+            </clr-alert>
+            <clr-alert
+                *ngIf="amountToRefundTotal && !reason"
+                [clrAlertType]="'danger'"
+                [clrAlertClosable]="false"
+            >
+                <clr-alert-item>
+                    {{ 'order.refund-cancellation-reason-required' | translate }}
+                </clr-alert-item>
+            </clr-alert>
+        </div>
+        <div class="modal-buttons">
+            <button type="button" class="btn" (click)="cancel()">{{ 'common.cancel' | translate }}</button>
+            <button type="submit" (click)="select()" [disabled]="!canSubmit()" class="btn btn-primary">
+                {{
+                    'order.refund-with-amount'
+                        | translate : { amount: amountToRefundTotal | localeCurrency : order.currencyCode }
+                }}
+            </button>
         </div>
     </div>
-</div>
-
-<ng-template vdrDialogButtons>
-    <button type="button" class="btn" (click)="cancel()">{{ 'common.cancel' | translate }}</button>
-    <button type="submit" (click)="select()" [disabled]="!canSubmit()" class="btn btn-primary">
-        <ng-container *ngIf="isRefunding(); else cancelling">
-            {{
-                'order.refund-with-amount'
-                    | translate: { amount: refundTotal | localeCurrency: order.currencyCode }
-            }}
-        </ng-container>
-        <ng-template #cancelling>
-            {{ 'order.cancel-selected-items' | translate }}
-        </ng-template>
-    </button>
 </ng-template>

+ 38 - 16
packages/admin-ui/src/lib/order/src/components/refund-order-dialog/refund-order-dialog.component.scss

@@ -1,7 +1,9 @@
+@import 'variables';
 
 :host {
     height: 100%;
     display: flex;
+    flex-direction: column;
     min-height: 64vh;
 }
 .refund-wrapper {
@@ -18,6 +20,11 @@
         color: var(--color-grey-300);
     }
 }
+
+::ng-deep .refund-wrapper .table-wrapper {
+    max-width: initial !important;
+}
+
 .quantity-col {
     background-color: var(--color-warning-100);
 }
@@ -33,27 +40,31 @@ clr-checkbox-wrapper {
 }
 .refund-details {
     display: flex;
-    justify-content: space-between;
-    &.faded {
-        opacity: 0.5;
-    }
-}
-.totals {
-    margin-top: 48px;
-    .refund-total {
-        font-size: 18px;
+    flex-direction: column;
+    padding-bottom: var(--space-unit);
+    @media screen and (min-width: $breakpoint-medium) {
+        flex-direction: row;
     }
-    .refund-total-error {
-        color: var(--color-error-500);
+    gap: calc(var(--space-unit) * 2);
+    justify-content: space-between;
+    vdr-card.unselected {
+        opacity: 0.8;
     }
-    .refund-total-warning {
-        color: var(--color-warning-600);
-        max-width: 250px;
+    vdr-card.selected {
+        ::ng-deep .card-container {
+            //border-color: var(--color-success-300);
+        }
     }
-    &.disabled {
-        color: var(--color-grey-300);
+    > * {
+        flex: 1;
     }
 }
+.errors {
+    display: flex;
+    justify-content: flex-end;
+    gap: calc(var(--space-unit) * 2);
+    margin: calc(var(--space-unit) * 2) 0;
+}
 .prorated-wrapper {
     display: flex;
     justify-content: center;
@@ -67,3 +78,14 @@ clr-checkbox-wrapper {
         margin-inline-start: 12px;
     }
 }
+
+vdr-card.faded {
+    opacity: 0.8;
+}
+
+.modal-buttons {
+    display: flex;
+    justify-content: flex-end;
+    gap: 0.6rem;
+    gap: var(--clr-modal-footer-gap, 0.6rem);
+}

+ 129 - 68
packages/admin-ui/src/lib/order/src/components/refund-order-dialog/refund-order-dialog.component.ts

@@ -1,4 +1,5 @@
 import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
+import { FormControl, Validators } from '@angular/forms';
 import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
 import {
     CancelOrderInput,
@@ -12,8 +13,13 @@ import {
 } from '@vendure/admin-ui/core';
 import { summate } from '@vendure/common/lib/shared-utils';
 
-type SelectionLine = { quantity: number; refund: boolean; cancel: boolean };
+type SelectionLine = { quantity: number; cancel: boolean };
 type Payment = NonNullable<OrderDetailFragment['payments']>[number];
+type RefundablePayment = Payment & {
+    refundableAmount: number;
+    amountToRefundControl: FormControl<number>;
+    selected: boolean;
+};
 
 @Component({
     selector: 'vdr-refund-order-dialog',
@@ -22,47 +28,34 @@ type Payment = NonNullable<OrderDetailFragment['payments']>[number];
     changeDetection: ChangeDetectionStrategy.OnPush,
 })
 export class RefundOrderDialogComponent
-    implements OnInit, Dialog<{ cancel: CancelOrderInput; refund: RefundOrderInput }>
+    implements OnInit, Dialog<{ cancel: CancelOrderInput; refunds: RefundOrderInput[] }>
 {
     order: OrderDetailFragment;
-    resolveWith: (result?: { cancel: CancelOrderInput; refund: RefundOrderInput }) => void;
+    resolveWith: (result?: { cancel: CancelOrderInput; refunds: RefundOrderInput[] }) => void;
     reason: string;
-    settledPayments: Payment[];
-    selectedPayment: Payment;
     lineQuantities: { [lineId: string]: SelectionLine } = {};
-    refundShipping = false;
-    adjustment = 0;
+    refundablePayments: RefundablePayment[] = [];
+    refundShippingLineIds: string[] = [];
     reasons = getAppConfig().cancellationReasons ?? [
         _('order.refund-reason-customer-request'),
         _('order.refund-reason-not-available'),
     ];
+    manuallySetRefundTotal = false;
+    refundTotal = 0;
 
     constructor(private i18nService: I18nService) {
         this.reasons = this.reasons.map(r => this.i18nService.translate(r));
     }
 
-    get refundTotal(): number {
-        const itemTotal = this.order.lines.reduce((total, line) => {
-            const lineRef = this.lineQuantities[line.id];
-            const refundCount = (lineRef.refund && lineRef.quantity) || 0;
-            return total + line.proratedUnitPriceWithTax * refundCount;
-        }, 0);
-        return itemTotal + (this.refundShipping ? this.order.shippingWithTax : 0) + this.adjustment;
+    get totalRefundableAmount(): number {
+        return summate(this.refundablePayments, 'refundableAmount');
     }
 
-    get settledPaymentsTotal(): number {
-        return this.settledPayments
-            .map(payment => {
-                const paymentTotal = payment.amount;
-                const alreadyRefundedTotal = summate(
-                    payment.refunds.filter(r => r.state !== 'Failed') as Array<
-                        Required<Payment['refunds'][number]>
-                    >,
-                    'total',
-                );
-                return paymentTotal - alreadyRefundedTotal;
-            })
-            .reduce((sum, amount) => sum + amount, 0);
+    get amountToRefundTotal(): number {
+        return this.refundablePayments.reduce(
+            (total, payment) => total + payment.amountToRefundControl.value,
+            0,
+        );
     }
 
     lineCanBeRefundedOrCancelled(line: OrderDetailFragment['lines'][number]): boolean {
@@ -89,28 +82,104 @@ export class RefundOrderDialogComponent
                 ...result,
                 [line.id]: {
                     quantity: 0,
-                    refund: false,
+                    refund: true,
                     cancel: false,
                 },
             }),
             {},
         );
-        this.settledPayments = (this.order.payments || []).filter(p => p.state === 'Settled');
-        if (this.settledPayments.length) {
-            this.selectedPayment = this.settledPayments[0];
+        const settledPayments = (this.order.payments || []).filter(p => p.state === 'Settled');
+        this.refundablePayments = settledPayments.map((payment, index) => {
+            const refundableAmount =
+                payment.amount -
+                summate(
+                    payment.refunds.filter(r => r.state !== 'Failed'),
+                    'total',
+                );
+            return {
+                ...payment,
+                refundableAmount,
+                amountToRefundControl: new FormControl(0, {
+                    nonNullable: true,
+                    validators: [Validators.min(0), Validators.max(refundableAmount)],
+                }),
+                selected: index === 0,
+            };
+        });
+    }
+
+    updateRefundTotal() {
+        if (!this.manuallySetRefundTotal) {
+            const itemTotal = this.order.lines.reduce((total, line) => {
+                const lineRef = this.lineQuantities[line.id];
+                const refundCount = lineRef.quantity || 0;
+                return total + line.proratedUnitPriceWithTax * refundCount;
+            }, 0);
+            const shippingTotal = this.order.shippingLines.reduce((total, line) => {
+                if (this.refundShippingLineIds.includes(line.id)) {
+                    return total + line.discountedPriceWithTax;
+                } else {
+                    return total;
+                }
+            }, 0);
+            this.refundTotal = itemTotal + shippingTotal;
+        }
+
+        // allocate the refund total across the refundable payments
+        const refundablePayments = this.refundablePayments.filter(p => p.selected);
+        let refundsAllocated = 0;
+        for (const payment of refundablePayments) {
+            const amountToRefund = Math.min(payment.refundableAmount, this.refundTotal - refundsAllocated);
+            payment.amountToRefundControl.setValue(amountToRefund);
+            refundsAllocated += amountToRefund;
+        }
+    }
+
+    toggleShippingRefund(lineId: string) {
+        const index = this.refundShippingLineIds.indexOf(lineId);
+        if (index === -1) {
+            this.refundShippingLineIds.push(lineId);
+        } else {
+            this.refundShippingLineIds.splice(index, 1);
+        }
+        this.updateRefundTotal();
+    }
+
+    onRefundQuantityChange(orderLineId: string, quantity: number) {
+        this.manuallySetRefundTotal = false;
+        const selectionLine = this.lineQuantities[orderLineId];
+        if (selectionLine) {
+            const previousQuantity = selectionLine.quantity;
+            if (quantity === 0) {
+                selectionLine.cancel = false;
+            } else if (previousQuantity === 0 && quantity > 0) {
+                selectionLine.cancel = true;
+            }
+            selectionLine.quantity = quantity;
+            this.updateRefundTotal();
         }
     }
 
-    handleZeroQuantity(line?: SelectionLine) {
-        if (line?.quantity === 0) {
-            line.cancel = false;
-            line.refund = false;
+    onPaymentSelected(payment: RefundablePayment, selected: boolean) {
+        if (selected) {
+            const outstandingRefundAmount =
+                this.refundTotal -
+                this.refundablePayments
+                    .filter(p => p.id !== payment.id)
+                    .reduce((total, p) => total + p.amountToRefundControl.value, 0);
+            if (0 < outstandingRefundAmount) {
+                payment.amountToRefundControl.setValue(
+                    Math.min(outstandingRefundAmount, payment.refundableAmount),
+                );
+            }
+        } else {
+            payment.amountToRefundControl.setValue(0);
         }
     }
 
     isRefunding(): boolean {
         const result = Object.values(this.lineQuantities).reduce(
-            (isRefunding, line) => isRefunding || (0 < line.quantity && line.refund),
+            (isRefunding, line) => isRefunding || 0 < line.quantity,
             false,
         );
         return result;
@@ -125,41 +194,33 @@ export class RefundOrderDialogComponent
     }
 
     canSubmit(): boolean {
-        if (this.isRefunding()) {
-            return !!(
-                this.selectedPayment &&
-                this.reason &&
-                0 < this.refundTotal &&
-                this.refundTotal <= this.settledPaymentsTotal
-            );
-        } else if (this.isCancelling()) {
-            return !!this.reason;
-        }
-        return false;
+        return 0 < this.refundTotal && this.amountToRefundTotal === this.refundTotal && !!this.reason;
     }
 
     select() {
-        const payment = this.selectedPayment;
-        if (payment) {
-            const refundLines = this.getOrderLineInput(line => line.refund);
-            const cancelLines = this.getOrderLineInput(line => line.cancel);
-
-            this.resolveWith({
-                refund: {
-                    lines: refundLines,
-                    reason: this.reason,
-                    shipping: this.refundShipping ? this.order.shippingWithTax : 0,
-                    adjustment: this.adjustment,
-                    paymentId: payment.id,
-                },
-                cancel: {
-                    lines: cancelLines,
-                    orderId: this.order.id,
-                    reason: this.reason,
-                    cancelShipping: this.refundShipping,
-                },
-            });
-        }
+        const refundLines = this.getOrderLineInput(() => true);
+        const cancelLines = this.getOrderLineInput(line => line.cancel);
+
+        this.resolveWith({
+            refunds: this.refundablePayments
+                .filter(rp => rp.selected && 0 < rp.amountToRefundControl.value)
+                .map(payment => {
+                    return {
+                        lines: refundLines,
+                        reason: this.reason,
+                        paymentId: payment.id,
+                        amount: payment.amountToRefundControl.value,
+                        shipping: 0,
+                        adjustment: 0,
+                    };
+                }),
+            cancel: {
+                lines: cancelLines,
+                orderId: this.order.id,
+                reason: this.reason,
+                cancelShipping: this.refundShippingLineIds.length > 0,
+            },
+        });
     }
 
     cancel() {

+ 0 - 6
packages/admin-ui/src/lib/order/src/order.routes.ts

@@ -2,18 +2,12 @@ import { Route } from '@angular/router';
 import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
 import {
     BreadcrumbLabelLinkPair,
-    CanDeactivateDetailGuard,
-    detailBreadcrumb,
     OrderDetailFragment,
     PageComponent,
     PageService,
 } from '@vendure/admin-ui/core';
 import { map } from 'rxjs/operators';
-
-import { DraftOrderDetailComponent } from './components/draft-order-detail/draft-order-detail.component';
-import { OrderDetailComponent } from './components/order-detail/order-detail.component';
 import { OrderEditorComponent } from './components/order-editor/order-editor.component';
-import { OrderListComponent } from './components/order-list/order-list.component';
 import { OrderResolver } from './providers/routing/order-resolver';
 import { OrderGuard } from './providers/routing/order.guard';
 

+ 6 - 2
packages/admin-ui/src/lib/static/i18n-messages/ar.json

@@ -549,6 +549,7 @@
     "cancel-selected-items": "إلغاء العناصر المحددة",
     "cancel-specified-items": "إلغاء العناصر المحددة",
     "cancellation-reason": "سبب الإلغاء",
+    "cancelled-order-items-success": "تم إلغاء { count } { count, plural, one {عنصر} other {عناصر} } من الطلب",
     "cancelled-order-success": "الطلب الذي تم إلغاؤه بنجاح",
     "complete-draft-order": "إنهاء المسودة",
     "confirm-modifications": "تأكيد التعديلات",
@@ -631,7 +632,7 @@
     "prorated-unit-price": "سعر الوحدة المتناسق",
     "quantity": "كمية",
     "refund": "استرداد",
-    "refund-adjustment": "تعديل",
+    "refund-amount": "مبلغ الاسترداد",
     "refund-and-cancel-order": "استرداد وإلغاء الطلب",
     "refund-cancellation-reason": "سبب الاسترداد/الإلغاء",
     "refund-cancellation-reason-required": "الاسترداد/الإلغاء سبب مطلوب",
@@ -642,12 +643,15 @@
     "refund-reason-customer-request": "طلب العميل",
     "refund-reason-not-available": "غير متاح",
     "refund-shipping": "استرداد الشحن",
+    "refund-this-payment": "استرداد هذه الدفعة",
     "refund-total": "إجمالي استرداد الأموال",
     "refund-total-error": "يجب أن يكون إجمالي الاسترداد بين {min} و {max}",
-    "refund-total-warning": "إجمالي استرداد المبلغ يتجاوز مبلغ الدفع المحدد. سيتم رد المبلغ المتبقي من المدفوعات الأخرى.",
+    "refund-total-warning": "يرجى تحديد مبالغ الاسترداد التي تساوي إجمالي الاسترداد.",
     "refund-with-amount": "المبلغ المسترد}",
+    "refundable-amount": "المبلغ القابل للاسترداد",
     "refunded-count": "{count} {count , الجمع , واحد {item} آخر {العناصر}}",
     "removed-items": "العناصر التي تمت إزالتها",
+    "return-to-stock": "العودة إلى المخزون",
     "search-by-order-filters": "ابحث بالاسم / الكود / معرف المعاملة",
     "select-address": "حدد العنوان",
     "select-shipping-method": "إختر طريقة الشحن",

+ 6 - 2
packages/admin-ui/src/lib/static/i18n-messages/cs.json

@@ -549,6 +549,7 @@
     "cancel-selected-items": "Zrušit vybrané položky",
     "cancel-specified-items": "",
     "cancellation-reason": "Důvod zrušení",
+    "cancelled-order-items-success": "Storno { count } { count, plural, one {položka} other {položky} } z objednávky",
     "cancelled-order-success": "Objednávka úspěšně zrušena",
     "complete-draft-order": "",
     "confirm-modifications": "Potvrdit úpravy",
@@ -631,7 +632,7 @@
     "prorated-unit-price": "Poměrná jednotková cena",
     "quantity": "Množství",
     "refund": "Refundace",
-    "refund-adjustment": "Úprava",
+    "refund-amount": "Částka k vrácení",
     "refund-and-cancel-order": "Refundovat a zrušit objednávku",
     "refund-cancellation-reason": "Důvod refundace/zrušení",
     "refund-cancellation-reason-required": "Uvedení důvodu refundace/zrušení je povinné",
@@ -642,12 +643,15 @@
     "refund-reason-customer-request": "Požadavek zákazníka",
     "refund-reason-not-available": "Neuveden",
     "refund-shipping": "Refundovat poštovné",
+    "refund-this-payment": "Vrátit tuto platbu",
     "refund-total": "Refundovat celkem",
     "refund-total-error": "Částka refundace musí být mezi {min} a {max}",
-    "refund-total-warning": "",
+    "refund-total-warning": "Zadejte prosím částky k vrácení, které odpovídají celkové částce vrácení.",
     "refund-with-amount": "Refundovat {amount}",
+    "refundable-amount": "Částka k vrácení",
     "refunded-count": "{count} {count, plural, one {položka} other {položky}} refundovány",
     "removed-items": "Odebrané položky",
+    "return-to-stock": "Vrátit do skladu",
     "search-by-order-filters": "Hledat na základě kódu objednávky / Příjmení / ID transakce",
     "select-address": "",
     "select-shipping-method": "",

+ 6 - 2
packages/admin-ui/src/lib/static/i18n-messages/de.json

@@ -549,6 +549,7 @@
     "cancel-selected-items": "Auswahl aufheben",
     "cancel-specified-items": "Auswahl aufheben",
     "cancellation-reason": "Stornierungsgrund",
+    "cancelled-order-items-success": "Storniert { count } { count, plural, one {Artikel} other {Artikel} } aus der Bestellung",
     "cancelled-order-success": "Bestellung erfolgreich storniert",
     "complete-draft-order": "Bestellungsentwurf vervollständigen",
     "confirm-modifications": "Änderungen bestätigen",
@@ -631,7 +632,7 @@
     "prorated-unit-price": "Anteiliger Artikelpreis",
     "quantity": "Anzahl",
     "refund": "Rückzahlung",
-    "refund-adjustment": "Anpassung",
+    "refund-amount": "Rückerstattungsbetrag",
     "refund-and-cancel-order": "Rückzahlung & Stornierung der Bestellung",
     "refund-cancellation-reason": "Stornierungs-/Rückzahlungsgrund",
     "refund-cancellation-reason-required": "Stornierungs-/Rückzahlungsgrund ist erforderlich",
@@ -642,12 +643,15 @@
     "refund-reason-customer-request": "Kundenanfrage",
     "refund-reason-not-available": "Nicht verfügbar",
     "refund-shipping": "Versandkosten erstatten",
+    "refund-this-payment": "Diese Zahlung erstatten",
     "refund-total": "Rückzahlung gesamt",
     "refund-total-error": "Die Erstattungssumme muss zwischen {min} und {max} liegen",
-    "refund-total-warning": "Der Erstattungsbetrag übersteigt den ausgewählten Zahlungsbetrag. Der verbleibende Erstattungsbetrag wird aus den anderen Zahlungen erstattet.",
+    "refund-total-warning": "Bitte geben Sie Rückerstattungsbeträge an, die dem Gesamtbetrag entsprechen.",
     "refund-with-amount": "Rückzahlung {amount}",
+    "refundable-amount": "Rückerstattungsbetrag",
     "refunded-count": "{count} {count, plural, one {Artikel} other {Artikel}} erstattet",
     "removed-items": "Entfernte Artikel",
+    "return-to-stock": "Zurück zum Bestand",
     "search-by-order-filters": "Suche nach Name / Bestellnummer / Transaktions-ID",
     "select-address": "Adresse auswählen",
     "select-shipping-method": "Versandart auswählen",

+ 6 - 2
packages/admin-ui/src/lib/static/i18n-messages/en.json

@@ -549,6 +549,7 @@
     "cancel-selected-items": "Cancel selected items",
     "cancel-specified-items": "Cancel specified items",
     "cancellation-reason": "Cancellation reason",
+    "cancelled-order-items-success": "Cancelled { count } { count, plural, one {item} other {items} } from the order",
     "cancelled-order-success": "Successfully cancelled order",
     "complete-draft-order": "Complete draft",
     "confirm-modifications": "Confirm modifications",
@@ -631,7 +632,7 @@
     "prorated-unit-price": "Prorated unit price",
     "quantity": "Quantity",
     "refund": "Refund",
-    "refund-adjustment": "Adjustment",
+    "refund-amount": "Refund amount",
     "refund-and-cancel-order": "Refund & cancel order",
     "refund-cancellation-reason": "Refund/cancellation reason",
     "refund-cancellation-reason-required": "Refund/cancellation reason is required",
@@ -642,12 +643,15 @@
     "refund-reason-customer-request": "Customer request",
     "refund-reason-not-available": "Not available",
     "refund-shipping": "Refund shipping",
+    "refund-this-payment": "Refund this payment",
     "refund-total": "Refund total",
     "refund-total-error": "Refund total must be between {min} and {max}",
-    "refund-total-warning": "Refund total exceeds selected payment amount. The remaining refund amount will be refunded from the other payments.",
+    "refund-total-warning": "Please specify refund amounts that equal the refund total.",
     "refund-with-amount": "Refund {amount}",
+    "refundable-amount": "Refundable amount",
     "refunded-count": "{count} {count, plural, one {item} other {items}} refunded",
     "removed-items": "Removed items",
+    "return-to-stock": "Return to stock",
     "search-by-order-filters": "Search by name / code / transaction ID",
     "select-address": "Select address",
     "select-shipping-method": "Select shipping method",

+ 6 - 2
packages/admin-ui/src/lib/static/i18n-messages/es.json

@@ -549,6 +549,7 @@
     "cancel-selected-items": "Cancelar artículos seleccionados",
     "cancel-specified-items": "Cancelar artículos especificados",
     "cancellation-reason": "Motivo de la cancelación",
+    "cancelled-order-items-success": "Se cancelaron { count } { count, plural, one {ítem} other {ítems} } de la orden",
     "cancelled-order-success": "Pedido cancelado con éxito",
     "complete-draft-order": "Completar borrador de pedido",
     "confirm-modifications": "Confirmar modificaciones",
@@ -631,7 +632,7 @@
     "prorated-unit-price": "Precio unitario prorrateado",
     "quantity": "Cantidad",
     "refund": "Reembolso",
-    "refund-adjustment": "Ajuste",
+    "refund-amount": "Monto a reembolsar",
     "refund-and-cancel-order": "Cancelación y Reembolso de pedido",
     "refund-cancellation-reason": "Motivo de Cancelación/Reembolso",
     "refund-cancellation-reason-required": "Se requiere un motivo de Cancelación/Reembolso",
@@ -642,12 +643,15 @@
     "refund-reason-customer-request": "Solicitud de cliente",
     "refund-reason-not-available": "No disponible",
     "refund-shipping": "Reembolso de gastos de envío",
+    "refund-this-payment": "Reembolsar este pago",
     "refund-total": "Total de reembolso",
     "refund-total-error": "El total del reembolso debe estar entre {min} y {max}",
-    "refund-total-warning": "El total del reembolso supera el importe del pago seleccionado. El importe restante del reembolso se reembolsará de los otros pagos.",
+    "refund-total-warning": "Por favor, especifique montos de reembolso que igualen el total a reembolsar.",
     "refund-with-amount": "Reembolso {amount}",
+    "refundable-amount": "Monto reembolsable",
     "refunded-count": "{count} {count, plural, one {artículo} other {artículos}} {count, plural, one {reembolsado} other {reembolsados}}",
     "removed-items": "Artículos eliminados",
+    "return-to-stock": "Devolver al inventario",
     "search-by-order-filters": "Buscar por el código de pedido / apellido del cliente / ID de transacción",
     "select-address": "Seleccionar dirección",
     "select-shipping-method": "Seleccionar método de envío",

+ 6 - 2
packages/admin-ui/src/lib/static/i18n-messages/fa.json

@@ -549,6 +549,7 @@
     "cancel-selected-items": "لغو آیتم های انتخاب شده",
     "cancel-specified-items": "لغو آیتم های مشخص شده",
     "cancellation-reason": "دلیل لغو",
+    "cancelled-order-items-success": "لغو { count } { count, plural, one {مورد} other {موارد} } از سفارش",
     "cancelled-order-success": "سفارش با موفقیت لغو شد",
     "complete-draft-order": "تکمیل پیش نویس سفارش",
     "confirm-modifications": "تایید تغییرات سفارش",
@@ -631,7 +632,7 @@
     "prorated-unit-price": "تخصیص قیمت واحد",
     "quantity": "تعداد",
     "refund": "بازگشت وجه / استرداد",
-    "refund-adjustment": "تنظیم استرداد وجه",
+    "refund-amount": "مبلغ بازپرداخت",
     "refund-and-cancel-order": "استرداد وجه و لغو سفارش",
     "refund-cancellation-reason": "علت لغو یا استرداد سفارش",
     "refund-cancellation-reason-required": "علت لغو یا استرداد سفارش الزامی است",
@@ -642,12 +643,15 @@
     "refund-reason-customer-request": "درخواست مشتری",
     "refund-reason-not-available": "در دسترس نیست",
     "refund-shipping": "حمل و نقل استرداد وجه",
+    "refund-this-payment": "بازپرداخت این پرداخت",
     "refund-total": "کل مبلغ استرداد وجه",
     "refund-total-error": "کل مبلغ استرداد وجه باید بین {min} و {max} باشد",
-    "refund-total-warning": "کل مبلغ استرداد وجه از مبلغ پرداختی انتخابی بیشتر است. مبلغ باقیمانده استرداد از سایر پرداخت ها مسترد خواهد شد.",
+    "refund-total-warning": "لطفاً مقدارهای بازپرداخت را مشخص کنید که معادل کل بازپرداخت باشند.",
     "refund-with-amount": "استرداد وجه به میزان {amount}",
+    "refundable-amount": "مبلغ قابل بازپرداخت",
     "refunded-count": "تعداد {count} آیتم استرداد وجه شد",
     "removed-items": "آیتم های حذف شده",
+    "return-to-stock": "بازگشت به انبار",
     "search-by-order-filters": "جستجو براساس نام یا کد یا شناسه تراکنش",
     "select-address": "انتخاب آدرس",
     "select-shipping-method": "انتخاب شیوه حمل و نقل",

+ 6 - 2
packages/admin-ui/src/lib/static/i18n-messages/fr.json

@@ -549,6 +549,7 @@
     "cancel-selected-items": "Annuler les articles selectionnés",
     "cancel-specified-items": "Annuler les articles spécifiés",
     "cancellation-reason": "Raison de l'annulation",
+    "cancelled-order-items-success": "Annulation de { count } { count, plural, one {article} other {articles} } de la commande",
     "cancelled-order-success": "Commande annulée",
     "complete-draft-order": "Valider le brouillon",
     "confirm-modifications": "Confirmer les modifications",
@@ -631,7 +632,7 @@
     "prorated-unit-price": "A l'unité",
     "quantity": "Quantité",
     "refund": "Remboursement",
-    "refund-adjustment": "Ajustement",
+    "refund-amount": "Montant du remboursement",
     "refund-and-cancel-order": "Rembourser et annuler la commande",
     "refund-cancellation-reason": "Raison du remboursement/annulation",
     "refund-cancellation-reason-required": "Raison du remboursement/annulation requise",
@@ -642,12 +643,15 @@
     "refund-reason-customer-request": "Demande du client",
     "refund-reason-not-available": "Non disponible",
     "refund-shipping": "Rembourser la livraison",
+    "refund-this-payment": "Rembourser ce paiement",
     "refund-total": "Remboursement total",
     "refund-total-error": "Le remboursement total doit être entre {min} et {max}",
-    "refund-total-warning": "",
+    "refund-total-warning": "Veuillez spécifier des montants de remboursement équivalents au total du remboursement.",
     "refund-with-amount": "Rembourser {amount}",
+    "refundable-amount": "Montant remboursable",
     "refunded-count": "{count} {count, plural, one {article remboursé} other {articles remboursés}}",
     "removed-items": "Articles supprimés",
+    "return-to-stock": "Retourner au stock",
     "search-by-order-filters": "Rehercher par numéro de commande / nom du client / Numéro de transaction",
     "select-address": "Sélectionner adresse",
     "select-shipping-method": "Sélectionner méthode transport",

+ 6 - 2
packages/admin-ui/src/lib/static/i18n-messages/he.json

@@ -549,6 +549,7 @@
     "cancel-selected-items": "בטל פריטים שנבחרו",
     "cancel-specified-items": "בטל פריטים שצוינו",
     "cancellation-reason": "סיבת ביטול",
+    "cancelled-order-items-success": "בוטלו { count } { count, plural, one {פריט} other {פריטים} } מההזמנה",
     "cancelled-order-success": "ההזמנה בוטלה בהצלחה",
     "complete-draft-order": "השלם הזמנה טיוטה",
     "confirm-modifications": "אשר שינויים",
@@ -631,7 +632,7 @@
     "prorated-unit-price": "מחיר יחידת פרורטה",
     "quantity": "כמות",
     "refund": "החזר",
-    "refund-adjustment": "תיקון",
+    "refund-amount": "סכום החזר",
     "refund-and-cancel-order": "החזר וביטול הזמנה",
     "refund-cancellation-reason": "סיבת החזר/ביטול",
     "refund-cancellation-reason-required": "נדרשת סיבת החזר/ביטול",
@@ -642,12 +643,15 @@
     "refund-reason-customer-request": "בקשת הלקוח",
     "refund-reason-not-available": "לא זמין",
     "refund-shipping": "החזר משלוח",
+    "refund-this-payment": "החזר תשלום זה",
     "refund-total": "סך הכול להחזרה",
     "refund-total-error": "סך הכול להחזרה חייב להיות בין {min} לבין {max}",
-    "refund-total-warning": "סך הכול להחזרה עולה על סכום התשלומים שנבחר. סכום ההחזרה שנותר יוחזר מתשלומים אחרים.",
+    "refund-total-warning": "יש לציין סכומי החזר ששווים לסכום הכולל של ההחזר.",
     "refund-with-amount": "החזר {amount}",
+    "refundable-amount": "סכום החזר ניתן להחזר",
     "refunded-count": "{count} {count, plural, one {פריט} other {פריטים}} הוחזרו",
     "removed-items": "פריטים שהוסרו",
+    "return-to-stock": "החזר למלאי",
     "search-by-order-filters": "חיפוש לפי שם / קוד / מספר עסקה",
     "select-address": "בחר כתובת",
     "select-shipping-method": "בחר שיטת משלוח",

+ 6 - 2
packages/admin-ui/src/lib/static/i18n-messages/hr.json

@@ -549,6 +549,7 @@
     "cancel-selected-items": "Otkaži odabrane stavke",
     "cancel-specified-items": "Otkaži određene stavke",
     "cancellation-reason": "Razlog otkazivanja",
+    "cancelled-order-items-success": "Otkazano { count } { count, plural, one {stavka} other {stavki} } iz narudžbe",
     "cancelled-order-success": "Narudžba uspješno otkazana",
     "complete-draft-order": "Završi skicu",
     "confirm-modifications": "Potvrdi izmjene",
@@ -631,7 +632,7 @@
     "prorated-unit-price": "Proračunska cijena po komadu",
     "quantity": "Količina",
     "refund": "Povrat sredstava",
-    "refund-adjustment": "Prilagodba",
+    "refund-amount": "Iznos povrata",
     "refund-and-cancel-order": "Povrat sredstava i otkazivanje narudžbe",
     "refund-cancellation-reason": "Razlog povrata sredstava/otkazivanja",
     "refund-cancellation-reason-required": "Razlog povrata sredstava/otkazivanja je obavezan",
@@ -642,12 +643,15 @@
     "refund-reason-customer-request": "Zahtjev kupca",
     "refund-reason-not-available": "Nedostupno",
     "refund-shipping": "Povrat troškova dostave",
+    "refund-this-payment": "Povrat ove uplate",
     "refund-total": "Ukupan iznos povrata",
     "refund-total-error": "Ukupan iznos povrata mora biti između {min} i {max}",
-    "refund-total-warning": "Ukupan iznos povrata premašuje odabrani iznos plaćanja. Preostali iznos povrata bit će vraćen iz drugih plaćanja.",
+    "refund-total-warning": "Molimo navedite iznose povrata koji jednaki ukupnom iznosu povrata.",
     "refund-with-amount": "Povrat u iznosu od {amount}",
+    "refundable-amount": "Iznos koji se može vratiti",
     "refunded-count": "Povraćeno {count} {count, plural, one {stavka} other {stavki}}",
     "removed-items": "Uklonjene stavke",
+    "return-to-stock": "Vrati na zalihe",
     "search-by-order-filters": "Pretraga po imenu / kodu / ID transakcije",
     "select-address": "Odaberi adresu",
     "select-shipping-method": "Odaberi metodu dostave",

+ 6 - 2
packages/admin-ui/src/lib/static/i18n-messages/it.json

@@ -549,6 +549,7 @@
     "cancel-selected-items": "Cancella prodotti selezionati",
     "cancel-specified-items": "Cancella prodotti specifcati",
     "cancellation-reason": "Motivo dell'annullamento",
+    "cancelled-order-items-success": "Annullati { count } { count, plural, one {articolo} other {articoli} } dall'ordine",
     "cancelled-order-success": "Ordine cancellato con successo",
     "complete-draft-order": "Salva bozza",
     "confirm-modifications": "Conferma modifiche",
@@ -631,7 +632,7 @@
     "prorated-unit-price": "Prezzo unitario",
     "quantity": "Quantità",
     "refund": "Rimborso",
-    "refund-adjustment": "Aggiustamento",
+    "refund-amount": "Importo del rimborso",
     "refund-and-cancel-order": "Rimborsa & cancella ordine",
     "refund-cancellation-reason": "Motivo del rimborso/cancellazione",
     "refund-cancellation-reason-required": "Il motivo del rimborso/cancellazione è obbligatorio",
@@ -642,12 +643,15 @@
     "refund-reason-customer-request": "Richiesta del cliente",
     "refund-reason-not-available": "Non disponibile",
     "refund-shipping": "Rimborso spedizione",
+    "refund-this-payment": "Rimborsa questo pagamento",
     "refund-total": "Totale rimborso",
     "refund-total-error": "Il totale del rimborso deve essere compreso tra {min} e {max}",
-    "refund-total-warning": "Il rimborso totale eccede l'ammontare pagato. L'ammontare residuo verrà rimborsato tramite gli altri pagamenti effettuati",
+    "refund-total-warning": "Si prega di specificare importi di rimborso che equivalgano all'importo totale del rimborso.",
     "refund-with-amount": "Rimborsa {amount}",
+    "refundable-amount": "Importo rimborsabile",
     "refunded-count": "Hai rimborsato {count} {count, plural, one {prodotto} other {prodotti}}",
     "removed-items": "Prodotti rimossi",
+    "return-to-stock": "Ritorna allo stock",
     "search-by-order-filters": "Cerca per codice ordine / cognome cliente / ID transazione",
     "select-address": "Inserisci indirizzo",
     "select-shipping-method": "Seleziona il metodo di consegna",

+ 7 - 4
packages/admin-ui/src/lib/static/i18n-messages/nb.json

@@ -89,6 +89,7 @@
     "confirm-deletion-of-unused-variants-body": "Følgende produktvarianter er gjort foreldede på grunn av tillegg av nye alternativer. De vil bli slettet under opprettelsen av nye produktvarianter.",
     "confirm-deletion-of-unused-variants-title": "Slett foreldede produktvarianter?",
     "create-draft-order": "Opprett utkast til ordre",
+    "create-facet-value": "Kansellerte { count } { count, plural, one {vare} other {varer} } fra bestillingen",
     "create-new-collection": "Opprett ny samling",
     "create-new-facet": "Opprett ny fasett",
     "create-new-product": "Nytt produkt",
@@ -105,7 +106,6 @@
     "facet-values": "Fasettverdier",
     "facets": "Fasetter",
     "filter-by-name": "Filtrer etter navn",
-    "filter-by-sku": "Filtrer etter SKU",
     "filter-inheritance": "Filtrer arv",
     "filters": "Filtre",
     "inherit-filters-from-parent": "Arv filtre fra forelder",
@@ -478,7 +478,6 @@
   "error": {
     "403-forbidden": "Du har for øyeblikket ikke autorisasjon til å få tilgang til \"{ path }\". Enten mangler du tillatelser, eller økten din har utløpt.",
     "could-not-connect-to-server": "Kunne ikke koble til Vendure-serveren på { url }",
-    "facet-value-form-values-do-not-match": "Antallet verdier i facet-skjemaet samsvarer ikke med det faktiske antallet verdier",
     "health-check-failed": "Systemhelsesjekk mislyktes",
     "no-default-shipping-zone-set": "Denne kanalen har ingen standard fraktsone. Dette kan føre til feil ved beregning av fraktkostnader for bestillinger.",
     "no-default-tax-zone-set": "Denne kanalen har ingen standard skattesone, noe som vil føre til feil ved beregning av priser. Vennligst opprett eller velg en sone."
@@ -550,6 +549,7 @@
     "cancel-selected-items": "Avbryt valgte varer",
     "cancel-specified-items": "Avbryt spesifikke varer",
     "cancellation-reason": "Årsak til avbestilling",
+    "cancelled-order-items-success": "",
     "cancelled-order-success": "Ordren ble avlyst",
     "complete-draft-order": "Fullfør utkast",
     "confirm-modifications": "Bekreft endringer",
@@ -632,7 +632,7 @@
     "prorated-unit-price": "Fordelt enhetspris",
     "quantity": "Antall",
     "refund": "Refusjon",
-    "refund-adjustment": "Justering",
+    "refund-amount": "Refusjonsbeløp",
     "refund-and-cancel-order": "Refunder og kanseller ordren",
     "refund-cancellation-reason": "Årsak til refusjon/avbestilling",
     "refund-cancellation-reason-required": "Årsak til refusjon/avbestilling kreves",
@@ -643,12 +643,15 @@
     "refund-reason-customer-request": "Kundeønske",
     "refund-reason-not-available": "Ikke tilgjengelig",
     "refund-shipping": "Refusjon av frakt",
+    "refund-this-payment": "Refunder denne betalingen",
     "refund-total": "Total refusjon",
     "refund-total-error": "Total refusjon må være mellom {min} og {max}",
-    "refund-total-warning": "Total refusjon overstiger valgt beløp for betaling. Resten av refusjonsbeløpet vil bli refundert fra andre betalinger.",
+    "refund-total-warning": "Vennligst spesifiser refusjonsbeløp som tilsvarer total refusjon.",
     "refund-with-amount": "Refusjon av {amount}",
+    "refundable-amount": "Refunderbart beløp",
     "refunded-count": "{count} {count, plural, one {vare} other {varer}} refundert",
     "removed-items": "Fjernede varer",
+    "return-to-stock": "Returner til lager",
     "search-by-order-filters": "Søk etter navn / kode / transaksjons-ID",
     "select-address": "Velg adresse",
     "select-shipping-method": "Velg leveringsmetode",

+ 6 - 2
packages/admin-ui/src/lib/static/i18n-messages/ne.json

@@ -549,6 +549,7 @@
     "cancel-selected-items": "चयन गरिएका समानहरू रद्द गर्नुहोस्",
     "cancel-specified-items": "निर्दिष्ट समानहरू रद्द गर्नुहोस्",
     "cancellation-reason": "रद्द गर्ने कारण",
+    "cancelled-order-items-success": "आदेरी गरिएको { count } { count, plural, one {वस्तु} other {वस्तुहरू} } बाट आदेरी गरिएको",
     "cancelled-order-success": "ओर्दर सफलतापूर्वक रद्द गरियो",
     "complete-draft-order": "पूरा प्रारूप",
     "confirm-modifications": "संशोधनहरू पुष्टि गर्नुहोस्",
@@ -631,7 +632,7 @@
     "prorated-unit-price": "प्राप्त मूल्य यूनिट मूल्य",
     "quantity": "मात्रा",
     "refund": "वापसी",
-    "refund-adjustment": "सम्यक गर्दैछ",
+    "refund-amount": "वापसी रकम",
     "refund-and-cancel-order": "वापसी गर्दै र ओर्दर रद्द गर्दै",
     "refund-cancellation-reason": "वापसी/रद्द गर्दै कारण",
     "refund-cancellation-reason-required": "वापसी/रद्द गर्दै कारण आवश्यक छ",
@@ -642,12 +643,15 @@
     "refund-reason-customer-request": "ग्राहकको अनुरोध",
     "refund-reason-not-available": "उपलब्ध छैन",
     "refund-shipping": "पारिश्रमिक वापसी",
+    "refund-this-payment": "यो भुक्तानी वापसी गर",
     "refund-total": "कुल वापसी",
     "refund-total-error": "कुल वापसी {min} र {max} को बीचमा हुनुपर्छ",
-    "refund-total-warning": "कुल वापसी चयन गरिएको भुक्तानी रकमलाई माथि पुर्याइएको छैन। अरू भुक्तानीहरूबाट बाँकी वापसी रकम वापसी गरिनेछ।",
+    "refund-total-warning": "कृपया वापसी रकमहरूलाई जसले वापसी को जम्मा रकमसँग मेल खान्छ भने स्पष्ट गर्नुहोस्।",
     "refund-with-amount": "{amount} वापसी गर्नुहोस्",
+    "refundable-amount": "वापसी गर्न सकिने रकम",
     "refunded-count": "{count} {count, plural, one {समान} other {समानहरू}} वापसी गरियो",
     "removed-items": "हटाइएका समानहरू",
+    "return-to-stock": "बन्धुपत्रमा फर्क",
     "search-by-order-filters": "नाम / कोड / लेखा निम्ति खोज्नुहोस्",
     "select-address": "ठेगाना चयन गर्नुहोस्",
     "select-shipping-method": "ढुवानी तरिका चयन गर्नुहोस्",

+ 6 - 2
packages/admin-ui/src/lib/static/i18n-messages/pl.json

@@ -549,6 +549,7 @@
     "cancel-selected-items": "Anuluj zaznaczone",
     "cancel-specified-items": "",
     "cancellation-reason": "Powód anulowania",
+    "cancelled-order-items-success": "Anulowano { count } { count, plural, one {pozycję} other {pozycje} } z zamówienia",
     "cancelled-order-success": "Pomyślnie anulowano zamówienie",
     "complete-draft-order": "",
     "confirm-modifications": "",
@@ -631,7 +632,7 @@
     "prorated-unit-price": "",
     "quantity": "Ilość",
     "refund": "Zwrot",
-    "refund-adjustment": "Regulacja",
+    "refund-amount": "Kwota zwrotu",
     "refund-and-cancel-order": "Zwróć i anuluj zamówienie",
     "refund-cancellation-reason": "Powód zwrotu/anulowania",
     "refund-cancellation-reason-required": "Powód zwrotu/anulowania jest wymagany",
@@ -642,12 +643,15 @@
     "refund-reason-customer-request": "Prośba klienta",
     "refund-reason-not-available": "Niedostępny",
     "refund-shipping": "Wysyłka zwrotu",
+    "refund-this-payment": "Zwróć tę płatność",
     "refund-total": "Wartość zwrotu",
     "refund-total-error": "Wartość zwrotu musi być pomiędzy {min} i {max}",
-    "refund-total-warning": "",
+    "refund-total-warning": "Proszę podać kwoty zwrotu równe całkowitej kwocie zwrotu.",
     "refund-with-amount": "Zwróć {amount}",
+    "refundable-amount": "Kwota do zwrotu",
     "refunded-count": "{count} {count, plural, one {zamówienie} other {zamówień}} zwrócono",
     "removed-items": "",
+    "return-to-stock": "Powrót do magazynu",
     "search-by-order-filters": "Szukaj po numerze zamówienia / Nazwisko / Numer transakcji",
     "select-address": "",
     "select-shipping-method": "",

+ 6 - 3
packages/admin-ui/src/lib/static/i18n-messages/pt_BR.json

@@ -478,7 +478,6 @@
   "error": {
     "403-forbidden": "No momento, você não está autorizado a acessar \"{ path }\". Você não tem permissão ou sua sessão expirou.",
     "could-not-connect-to-server": "Não foi possível ao servidor Vendure no link { url }",
-    "facet-value-form-values-do-not-match": "O número de valores no formulário de etiqueta não corresponde ao número real de valores",
     "health-check-failed": "Falha na verificação de integridade do sistema",
     "no-default-shipping-zone-set": "Este canal não possui zona de entrega padrão. Isso pode causar erros ao calcular as despesas de envio do pedido.",
     "no-default-tax-zone-set": "Este canal não possui zona de imposto padrão, o que causará erros no cálculo de preços. Por favor, crie ou selecione uma zona."
@@ -550,6 +549,7 @@
     "cancel-selected-items": "Cancelar itens selecionados",
     "cancel-specified-items": "Cancelar itens específicos",
     "cancellation-reason": "Motivo do cancelamento",
+    "cancelled-order-items-success": "Itens da ordem cancelados { count } { count, plural, one {item} other {itens} }",
     "cancelled-order-success": "Pedido cancelado com sucesso",
     "complete-draft-order": "Completar rascunho",
     "confirm-modifications": "Confirmar modificações",
@@ -632,7 +632,7 @@
     "prorated-unit-price": "Diferença de preço",
     "quantity": "Quantidade",
     "refund": "Reembolso",
-    "refund-adjustment": "Ajuste",
+    "refund-amount": "Valor do reembolso",
     "refund-and-cancel-order": "Reembolso & cancelamento do pedido",
     "refund-cancellation-reason": "Motivo do reembolso/cancelamento",
     "refund-cancellation-reason-required": "O motivo do reembolso/cancelamento é obrigatório",
@@ -643,12 +643,15 @@
     "refund-reason-customer-request": "Solicitação do cliente",
     "refund-reason-not-available": "Não disponível",
     "refund-shipping": "Envio de reembolso",
+    "refund-this-payment": "Reembolsar este pagamento",
     "refund-total": "Total do reembolso",
     "refund-total-error": "Total do reembolso deve ser entre {min} e {max}",
-    "refund-total-warning": "O total do reembolso excede o valor do pagamento selecionado. O valor restante do reembolso será reembolsado dos outros pagamentos.",
+    "refund-total-warning": "Por favor, especifique os valores de reembolso que totalizam o valor total do reembolso.",
     "refund-with-amount": "Reembolso {amount}",
+    "refundable-amount": "Valor reembolsável",
     "refunded-count": "{count} {count, plural, one {item} other {items}} reembolsado",
     "removed-items": "Itens removidos",
+    "return-to-stock": "Devolver ao estoque",
     "search-by-order-filters": "Buscar por código do pedido / Sobrenome / Código ID da transação",
     "select-address": "Selecionar endereço",
     "select-shipping-method": "Selecionar método de envio",

+ 6 - 2
packages/admin-ui/src/lib/static/i18n-messages/pt_PT.json

@@ -549,6 +549,7 @@
     "cancel-selected-items": "Cancelar itens seleccionados",
     "cancel-specified-items": "",
     "cancellation-reason": "Motivo do cancelamento",
+    "cancelled-order-items-success": "Itens da encomenda cancelados { count } { count, plural, one {item} other {itens} }",
     "cancelled-order-success": "Encomenda cancelada com sucesso",
     "complete-draft-order": "",
     "confirm-modifications": "Confirmar modificações",
@@ -631,7 +632,7 @@
     "prorated-unit-price": "Diferença de preço",
     "quantity": "Quantidade",
     "refund": "Reembolso",
-    "refund-adjustment": "Ajuste",
+    "refund-amount": "Valor a reembolsar",
     "refund-and-cancel-order": "Reembolso e cancelamento da encomenda",
     "refund-cancellation-reason": "Motivo do reembolso/cancelamento",
     "refund-cancellation-reason-required": "O motivo do reembolso/cancelamento é obrigatório",
@@ -642,12 +643,15 @@
     "refund-reason-customer-request": "Solicitação do cliente",
     "refund-reason-not-available": "Não disponível",
     "refund-shipping": "Envio de reembolso",
+    "refund-this-payment": "Reembolsar este pagamento",
     "refund-total": "Total do reembolso",
     "refund-total-error": "Total do reembolso deve ser entre {min} e {max}",
-    "refund-total-warning": "O total do reembolso excede o valor do pagamento seleccionado. O valor excedido será descontado dos outros pagamentos.",
+    "refund-total-warning": "Por favor, especifique os valores de reembolso que totalizam o valor total a reembolsar.",
     "refund-with-amount": "Reembolso {amount}",
+    "refundable-amount": "Valor reembolsável",
     "refunded-count": "{count} {count, plural, one {item reembolsado} other {itens reembolsados}}",
     "removed-items": "Itens removidos",
+    "return-to-stock": "Devolver ao stock",
     "search-by-order-filters": "Pesqusiar pelo código da encomenda / apelido do cliente / ID da transação",
     "select-address": "",
     "select-shipping-method": "",

+ 6 - 2
packages/admin-ui/src/lib/static/i18n-messages/ru.json

@@ -549,6 +549,7 @@
     "cancel-selected-items": "Отменить выбранные позиции",
     "cancel-specified-items": "Отменить указанные позиции",
     "cancellation-reason": "Причина отмены",
+    "cancelled-order-items-success": "Отменено { count } { count, plural, one {позиция} other {позиции} } из заказа",
     "cancelled-order-success": "Успешно отмененный заказ",
     "complete-draft-order": "Завершить черновик заказа",
     "confirm-modifications": "Подтвердите изменения",
@@ -631,7 +632,7 @@
     "prorated-unit-price": "Пропорциональная цена за единицу",
     "quantity": "Количество",
     "refund": "Возврат",
-    "refund-adjustment": "Корректирование",
+    "refund-amount": "Сумма возврата",
     "refund-and-cancel-order": "Возврат и отмена заказа",
     "refund-cancellation-reason": "Причина возврата / отмены",
     "refund-cancellation-reason-required": "Укажите причину возврата / отмены",
@@ -642,12 +643,15 @@
     "refund-reason-customer-request": "Запрос клиента",
     "refund-reason-not-available": "Недоступен",
     "refund-shipping": "Возврат стоимости доставки",
+    "refund-this-payment": "Вернуть этот платеж",
     "refund-total": "Общая сумма возврата",
     "refund-total-error": "Общая сумма возврата должна быть в пределах {min} и {max}",
-    "refund-total-warning": "Общая сумма возврата превышает выбранную сумму платежа. Оставшаяся сумма возврата будет возвращена из других платежей.",
+    "refund-total-warning": "Пожалуйста, укажите суммы возврата, равные общей сумме возврата.",
     "refund-with-amount": "Возврат {amount}",
+    "refundable-amount": "Сумма к возврату",
     "refunded-count": "{count} {count, plural, one {позиция} other {позиций}} возвращен",
     "removed-items": "Удаленные позиции",
+    "return-to-stock": "Вернуть в наличие",
     "search-by-order-filters": "Поиск по фамилии клиента / коду заказа / ID транзакции",
     "select-address": "Выбрать адрес",
     "select-shipping-method": "Выбрать метод доставки",

+ 6 - 2
packages/admin-ui/src/lib/static/i18n-messages/uk.json

@@ -549,6 +549,7 @@
     "cancel-selected-items": "Скасувати вибрані позиції",
     "cancel-specified-items": "",
     "cancellation-reason": "Причина скасування",
+    "cancelled-order-items-success": "Скасовано { count } { count, plural, one {позицію} other {позицій} } замовлення",
     "cancelled-order-success": "Успішно скасоване замовлення",
     "complete-draft-order": "",
     "confirm-modifications": "Підтвердіть зміни",
@@ -631,7 +632,7 @@
     "prorated-unit-price": "Пропорційна ціна за одиницю",
     "quantity": "Кількість",
     "refund": "Повернення",
-    "refund-adjustment": "Коригування",
+    "refund-amount": "Сума повернення",
     "refund-and-cancel-order": "Повернення та скасування замовлення",
     "refund-cancellation-reason": "Причина повернення / скасування",
     "refund-cancellation-reason-required": "Вкажіть причину повернення / скасування",
@@ -642,12 +643,15 @@
     "refund-reason-customer-request": "Запит клієнта",
     "refund-reason-not-available": "Недоступний",
     "refund-shipping": "Повернення вартості доставки",
+    "refund-this-payment": "Повернути цей платіж",
     "refund-total": "Загальна сума повернення",
     "refund-total-error": "Загальна сума повернення повинна бути в межах {min} і {max}",
-    "refund-total-warning": "Загальна сума повернення перевищує обрану суму платежу. Решта суми повернення буде повернута з інших платежів.",
+    "refund-total-warning": "Будь ласка, вкажіть суми повернення, які дорівнюють загальній сумі повернення.",
     "refund-with-amount": "Повернення {amount}",
+    "refundable-amount": "Сума до повернення",
     "refunded-count": "{count} {count, plural, one {позиція} other {позицій}} повернено",
     "removed-items": "Видалені позиції",
+    "return-to-stock": "Повернутися на склад",
     "search-by-order-filters": "Пошук за коду замовлення / прізвищем клієнта / ID транзакції",
     "select-address": "",
     "select-shipping-method": "",

+ 6 - 2
packages/admin-ui/src/lib/static/i18n-messages/zh_Hans.json

@@ -549,6 +549,7 @@
     "cancel-selected-items": "取消已选",
     "cancel-specified-items": "",
     "cancellation-reason": "取消原因",
+    "cancelled-order-items-success": "从订单中取消 { count } { count, plural, one {项} other {项} }",
     "cancelled-order-success": "订单成功取消",
     "complete-draft-order": "",
     "confirm-modifications": "确认修改",
@@ -631,7 +632,7 @@
     "prorated-unit-price": "",
     "quantity": "数量",
     "refund": "退款",
-    "refund-adjustment": "退款调整",
+    "refund-amount": "退款金额",
     "refund-and-cancel-order": "退款|取消订单",
     "refund-cancellation-reason": "",
     "refund-cancellation-reason-required": "",
@@ -642,12 +643,15 @@
     "refund-reason-customer-request": "客户要求",
     "refund-reason-not-available": "无库存",
     "refund-shipping": "退运费",
+    "refund-this-payment": "退还此支付",
     "refund-total": "退款总计",
     "refund-total-error": "退款总计必须大于{min}并少于{max}之间",
-    "refund-total-warning": "",
+    "refund-total-warning": "请指定等于退款总额的退款金额。",
     "refund-with-amount": "退款金额{amount}",
+    "refundable-amount": "可退款金额",
     "refunded-count": "{count}个商品已退款",
     "removed-items": "",
+    "return-to-stock": "返回库存",
     "search-by-order-filters": "输入要搜索的订单编号 / 姓 / 交易ID ",
     "select-address": "",
     "select-shipping-method": "",

+ 6 - 2
packages/admin-ui/src/lib/static/i18n-messages/zh_Hant.json

@@ -549,6 +549,7 @@
     "cancel-selected-items": "取消已選",
     "cancel-specified-items": "",
     "cancellation-reason": "取消原因",
+    "cancelled-order-items-success": "已取消訂單中的 { count } { count, plural, one {項} other {項} }",
     "cancelled-order-success": "訂單取消成功",
     "complete-draft-order": "",
     "confirm-modifications": "",
@@ -631,7 +632,7 @@
     "prorated-unit-price": "",
     "quantity": "數量",
     "refund": "退款",
-    "refund-adjustment": "退款調整",
+    "refund-amount": "退款金額",
     "refund-and-cancel-order": "退款|取消訂單",
     "refund-cancellation-reason": "",
     "refund-cancellation-reason-required": "",
@@ -642,12 +643,15 @@
     "refund-reason-customer-request": "客户要求",
     "refund-reason-not-available": "無庫存",
     "refund-shipping": "退運費",
+    "refund-this-payment": "退款此付款",
     "refund-total": "退款總計",
     "refund-total-error": "退款總計必須大於{min}並少遊{max}之間",
-    "refund-total-warning": "",
+    "refund-total-warning": "請指定等於退款總額的退款金額。",
     "refund-with-amount": "退款金額{amount}",
+    "refundable-amount": "可退款金額",
     "refunded-count": "{count}個商品已退款",
     "removed-items": "",
+    "return-to-stock": "返回庫存",
     "search-by-order-filters": "輸入要搜索的訂單編號 / 姓 / 交易編號 ",
     "select-address": "",
     "select-shipping-method": "",

Некоторые файлы не были показаны из-за большого количества измененных файлов