Browse Source

feat(admin-ui): Implement manual refund settlement

Relates to #121
Michael Bromley 6 years ago
parent
commit
66006a11c5
19 changed files with 210 additions and 26 deletions
  1. 0 3
      admin-ui/src/app/common/base-detail.component.ts
  2. 22 3
      admin-ui/src/app/common/generated-types.ts
  3. 24 7
      admin-ui/src/app/data/definitions/order-definitions.ts
  4. 9 0
      admin-ui/src/app/data/providers/order-data.service.ts
  5. 1 1
      admin-ui/src/app/order/components/cancel-order-dialog/cancel-order-dialog.component.html
  6. 1 1
      admin-ui/src/app/order/components/line-refunds/line-refunds.component.html
  7. 7 2
      admin-ui/src/app/order/components/order-detail/order-detail.component.html
  8. 32 0
      admin-ui/src/app/order/components/order-detail/order-detail.component.ts
  9. 18 7
      admin-ui/src/app/order/components/order-payment-detail/order-payment-detail.component.html
  10. 5 0
      admin-ui/src/app/order/components/order-payment-detail/order-payment-detail.component.scss
  11. 1 0
      admin-ui/src/app/order/components/order-payment-detail/order-payment-detail.component.ts
  12. 4 0
      admin-ui/src/app/order/components/refund-state-label/refund-state-label.component.html
  13. 3 0
      admin-ui/src/app/order/components/refund-state-label/refund-state-label.component.scss
  14. 22 0
      admin-ui/src/app/order/components/refund-state-label/refund-state-label.component.ts
  15. 15 0
      admin-ui/src/app/order/components/settle-refund-dialog/settle-refund-dialog.component.html
  16. 8 0
      admin-ui/src/app/order/components/settle-refund-dialog/settle-refund-dialog.component.scss
  17. 24 0
      admin-ui/src/app/order/components/settle-refund-dialog/settle-refund-dialog.component.ts
  18. 10 1
      admin-ui/src/app/order/order.module.ts
  19. 4 1
      admin-ui/src/i18n-messages/en.json

+ 0 - 3
admin-ui/src/app/common/base-detail.component.ts

@@ -27,9 +27,6 @@ export abstract class BaseDetailComponent<Entity extends { id: string; updatedAt
     init() {
         this.entity$ = this.route.data.pipe(
             switchMap(data => data.entity as Observable<Entity>),
-            distinctUntilChanged((a, b) => {
-                return a.id === b.id && a.updatedAt === b.updatedAt;
-            }),
             tap(entity => (this.id = entity.id)),
             shareReplay(1),
         );

+ 22 - 3
admin-ui/src/app/common/generated-types.ts

@@ -3483,13 +3483,15 @@ export type GetFacetWithValuesQuery = ({ __typename?: 'Query' } & { facet: Maybe
 
 export type AdjustmentFragment = ({ __typename?: 'Adjustment' } & Pick<Adjustment, 'adjustmentSource' | 'amount' | 'description' | 'type'>);
 
+export type RefundFragment = ({ __typename?: 'Refund' } & Pick<Refund, 'id' | 'state' | 'items' | 'shipping' | 'adjustment' | 'transactionId' | 'paymentId'>);
+
 export type ShippingAddressFragment = ({ __typename?: 'OrderAddress' } & Pick<OrderAddress, 'fullName' | 'company' | 'streetLine1' | 'streetLine2' | 'city' | 'province' | 'postalCode' | 'country' | 'phoneNumber'>);
 
 export type OrderFragment = ({ __typename?: 'Order' } & Pick<Order, 'id' | 'createdAt' | 'updatedAt' | 'code' | 'state' | 'total' | 'currencyCode'> & { customer: Maybe<({ __typename?: 'Customer' } & Pick<Customer, 'id' | 'firstName' | 'lastName'>)> });
 
 export type FulfillmentFragment = ({ __typename?: 'Fulfillment' } & Pick<Fulfillment, 'id' | 'createdAt' | 'updatedAt' | 'method' | 'trackingCode'>);
 
-export type OrderWithLinesFragment = ({ __typename?: 'Order' } & Pick<Order, 'id' | 'createdAt' | 'updatedAt' | 'code' | 'state' | 'active' | 'subTotal' | 'subTotalBeforeTax' | 'totalBeforeTax' | 'currencyCode' | 'shipping' | 'total'> & { customer: Maybe<({ __typename?: 'Customer' } & Pick<Customer, 'id' | 'firstName' | 'lastName'>)>, lines: Array<({ __typename?: 'OrderLine' } & Pick<OrderLine, 'id' | 'unitPrice' | 'unitPriceWithTax' | 'quantity' | 'totalPrice'> & { featuredAsset: Maybe<({ __typename?: 'Asset' } & Pick<Asset, 'preview'>)>, productVariant: ({ __typename?: 'ProductVariant' } & Pick<ProductVariant, 'id' | 'name' | 'sku'>), items: Array<({ __typename?: 'OrderItem' } & Pick<OrderItem, 'id' | 'unitPrice' | 'unitPriceIncludesTax' | 'unitPriceWithTax' | 'taxRate' | 'refundId' | 'cancelled'> & { fulfillment: Maybe<({ __typename?: 'Fulfillment' } & FulfillmentFragment)> })> })>, adjustments: Array<({ __typename?: 'Adjustment' } & AdjustmentFragment)>, shippingMethod: Maybe<({ __typename?: 'ShippingMethod' } & Pick<ShippingMethod, 'id' | 'code' | 'description'>)>, shippingAddress: Maybe<({ __typename?: 'OrderAddress' } & ShippingAddressFragment)>, payments: Maybe<Array<({ __typename?: 'Payment' } & Pick<Payment, 'id' | 'createdAt' | 'transactionId' | 'amount' | 'method' | 'state' | 'metadata'> & { refunds: Array<({ __typename?: 'Refund' } & Pick<Refund, 'id' | 'createdAt' | 'state' | 'items' | 'adjustment' | 'total' | 'paymentId' | 'method'> & { orderItems: Array<({ __typename?: 'OrderItem' } & Pick<OrderItem, 'id'>)> })> })>>, fulfillments: Maybe<Array<({ __typename?: 'Fulfillment' } & FulfillmentFragment)>> });
+export type OrderWithLinesFragment = ({ __typename?: 'Order' } & Pick<Order, 'id' | 'createdAt' | 'updatedAt' | 'code' | 'state' | 'active' | 'subTotal' | 'subTotalBeforeTax' | 'totalBeforeTax' | 'currencyCode' | 'shipping' | 'total'> & { customer: Maybe<({ __typename?: 'Customer' } & Pick<Customer, 'id' | 'firstName' | 'lastName'>)>, lines: Array<({ __typename?: 'OrderLine' } & Pick<OrderLine, 'id' | 'unitPrice' | 'unitPriceWithTax' | 'quantity' | 'totalPrice'> & { featuredAsset: Maybe<({ __typename?: 'Asset' } & Pick<Asset, 'preview'>)>, productVariant: ({ __typename?: 'ProductVariant' } & Pick<ProductVariant, 'id' | 'name' | 'sku'>), items: Array<({ __typename?: 'OrderItem' } & Pick<OrderItem, 'id' | 'unitPrice' | 'unitPriceIncludesTax' | 'unitPriceWithTax' | 'taxRate' | 'refundId' | 'cancelled'> & { fulfillment: Maybe<({ __typename?: 'Fulfillment' } & FulfillmentFragment)> })> })>, adjustments: Array<({ __typename?: 'Adjustment' } & AdjustmentFragment)>, shippingMethod: Maybe<({ __typename?: 'ShippingMethod' } & Pick<ShippingMethod, 'id' | 'code' | 'description'>)>, shippingAddress: Maybe<({ __typename?: 'OrderAddress' } & ShippingAddressFragment)>, payments: Maybe<Array<({ __typename?: 'Payment' } & Pick<Payment, 'id' | 'createdAt' | 'transactionId' | 'amount' | 'method' | 'state' | 'metadata'> & { refunds: Array<({ __typename?: 'Refund' } & Pick<Refund, 'id' | 'createdAt' | 'state' | 'items' | 'adjustment' | 'total' | 'paymentId' | 'transactionId' | 'method'> & { orderItems: Array<({ __typename?: 'OrderItem' } & Pick<OrderItem, 'id'>)> })> })>>, fulfillments: Maybe<Array<({ __typename?: 'Fulfillment' } & FulfillmentFragment)>> });
 
 export type GetOrderListQueryVariables = {
   options?: Maybe<OrderListOptions>
@@ -3531,7 +3533,14 @@ export type RefundOrderMutationVariables = {
 };
 
 
-export type RefundOrderMutation = ({ __typename?: 'Mutation' } & { refundOrder: ({ __typename?: 'Refund' } & Pick<Refund, 'id' | 'state' | 'items' | 'shipping' | 'adjustment' | 'transactionId' | 'paymentId'>) });
+export type RefundOrderMutation = ({ __typename?: 'Mutation' } & { refundOrder: ({ __typename?: 'Refund' } & RefundFragment) });
+
+export type SettleRefundMutationVariables = {
+  input: SettleRefundInput
+};
+
+
+export type SettleRefundMutation = ({ __typename?: 'Mutation' } & { settleRefund: ({ __typename?: 'Refund' } & RefundFragment) });
 
 export type AssetFragment = ({ __typename?: 'Asset' } & Pick<Asset, 'id' | 'createdAt' | 'name' | 'fileSize' | 'mimeType' | 'type' | 'preview' | 'source'>);
 
@@ -4265,6 +4274,10 @@ export namespace Adjustment {
   export type Fragment = AdjustmentFragment;
 }
 
+export namespace Refund {
+  export type Fragment = RefundFragment;
+}
+
 export namespace ShippingAddress {
   export type Fragment = ShippingAddressFragment;
 }
@@ -4329,7 +4342,13 @@ export namespace CancelOrder {
 export namespace RefundOrder {
   export type Variables = RefundOrderMutationVariables;
   export type Mutation = RefundOrderMutation;
-  export type RefundOrder = RefundOrderMutation['refundOrder'];
+  export type RefundOrder = RefundFragment;
+}
+
+export namespace SettleRefund {
+  export type Variables = SettleRefundMutationVariables;
+  export type Mutation = SettleRefundMutation;
+  export type SettleRefund = RefundFragment;
 }
 
 export namespace Asset {

+ 24 - 7
admin-ui/src/app/data/definitions/order-definitions.ts

@@ -9,6 +9,18 @@ export const ADJUSTMENT_FRAGMENT = gql`
     }
 `;
 
+export const REFUND_FRAGMENT = gql`
+    fragment Refund on Refund {
+        id
+        state
+        items
+        shipping
+        adjustment
+        transactionId
+        paymentId
+    }
+`;
+
 export const SHIPPING_ADDRESS_FRAGMENT = gql`
     fragment ShippingAddress on OrderAddress {
         fullName
@@ -122,6 +134,7 @@ export const ORDER_WITH_LINES_FRAGMENT = gql`
                 adjustment
                 total
                 paymentId
+                transactionId
                 method
                 orderItems {
                     id
@@ -193,13 +206,17 @@ export const CANCEL_ORDER = gql`
 export const REFUND_ORDER = gql`
     mutation RefundOrder($input: RefundOrderInput!) {
         refundOrder(input: $input) {
-            id
-            state
-            items
-            shipping
-            adjustment
-            transactionId
-            paymentId
+            ...Refund
+        }
+    }
+    ${REFUND_FRAGMENT}
+`;
+
+export const SETTLE_REFUND = gql`
+    mutation SettleRefund($input: SettleRefundInput!) {
+        settleRefund(input: $input) {
+            ...Refund
         }
     }
+    ${REFUND_FRAGMENT}
 `;

+ 9 - 0
admin-ui/src/app/data/providers/order-data.service.ts

@@ -8,6 +8,8 @@ import {
     RefundOrder,
     RefundOrderInput,
     SettlePayment,
+    SettleRefund,
+    SettleRefundInput,
 } from '../../common/generated-types';
 import {
     CANCEL_ORDER,
@@ -16,6 +18,7 @@ import {
     GET_ORDERS_LIST,
     REFUND_ORDER,
     SETTLE_PAYMENT,
+    SETTLE_REFUND,
 } from '../definitions/order-definitions';
 
 import { BaseDataService } from './base-data.service';
@@ -62,4 +65,10 @@ export class OrderDataService {
             input,
         });
     }
+
+    settleRefund(input: SettleRefundInput, orderId: string) {
+        return this.baseDataService.mutate<SettleRefund.Mutation, SettleRefund.Variables>(SETTLE_REFUND, {
+            input,
+        });
+    }
 }

+ 1 - 1
admin-ui/src/app/order/components/cancel-order-dialog/cancel-order-dialog.component.html

@@ -60,6 +60,6 @@
         [disabled]="!reason || selectionCount === 0"
         class="btn btn-primary"
     >
-        {{ 'order.cancel' | translate }}
+        {{ 'order.cancel-selected-items' | translate }}
     </button>
 </ng-template>

+ 1 - 1
admin-ui/src/app/order/components/line-refunds/line-refunds.component.html

@@ -1,3 +1,3 @@
 <span *ngIf="getRefundedCount()" [title]="'order.refunded-count' | translate: { count: getRefundedCount() }">
-    <clr-icon shape="asterisk" class="is-solid"></clr-icon>
+    <clr-icon shape="redo" class="is-solid" dir="down"></clr-icon>
 </span>

+ 7 - 2
admin-ui/src/app/order/components/order-detail/order-detail.component.html

@@ -26,11 +26,14 @@
                     type="button"
                     class="btn"
                     vdrDropdownItem
-                    *ngIf="!order.active"
+                    *ngIf="!order.active && order.state !== 'Cancelled'"
                     (click)="cancelOrRefund(order)"
                 >
                     <clr-icon shape="error-standard" class="is-error"></clr-icon>
-                    {{ 'order.refund-and-cancel-order' | translate }}
+                    <ng-container *ngIf="order.state !== 'PaymentAuthorized'; else cancelOnly">
+                        {{ 'order.refund-and-cancel-order' | translate }}
+                    </ng-container>
+                    <ng-template #cancelOnly>{{ 'order.cancel-order' | translate }}</ng-template>
                 </button>
             </vdr-dropdown-menu>
         </vdr-dropdown>
@@ -121,6 +124,8 @@
                     *ngFor="let payment of order.payments"
                     [currencyCode]="order.currencyCode"
                     [payment]="payment"
+                    (settlePayment)="settlePayment($event)"
+                    (settleRefund)="settleRefund($event)"
                 ></vdr-order-payment-detail>
             </ng-container>
             <ng-container *ngIf="order.fulfillments && order.fulfillments.length">

+ 32 - 0
admin-ui/src/app/order/components/order-detail/order-detail.component.ts

@@ -15,6 +15,7 @@ import { ModalService } from '../../../shared/providers/modal/modal.service';
 import { CancelOrderDialogComponent } from '../cancel-order-dialog/cancel-order-dialog.component';
 import { FulfillOrderDialogComponent } from '../fulfill-order-dialog/fulfill-order-dialog.component';
 import { RefundOrderDialogComponent } from '../refund-order-dialog/refund-order-dialog.component';
+import { SettleRefundDialogComponent } from '../settle-refund-dialog/settle-refund-dialog.component';
 
 @Component({
     selector: 'vdr-order-detail',
@@ -103,6 +104,37 @@ export class OrderDetailComponent extends BaseDetailComponent<OrderWithLines.Fra
         }
     }
 
+    settleRefund(refund: OrderWithLines.Refunds) {
+        this.modalService
+            .fromComponent(SettleRefundDialogComponent, {
+                size: 'md',
+                locals: {
+                    refund,
+                },
+            })
+            .pipe(
+                switchMap(transactionId => {
+                    if (transactionId) {
+                        return this.dataService.order.settleRefund(
+                            {
+                                transactionId,
+                                id: refund.id,
+                            },
+                            this.id,
+                        );
+                    } else {
+                        return of(undefined);
+                    }
+                }),
+                // switchMap(result => this.refetchOrder(result)),
+            )
+            .subscribe(result => {
+                if (result) {
+                    this.notificationService.success(_('order.settle-refund-success'));
+                }
+            });
+    }
+
     private cancelOrder(order: OrderWithLines.Fragment) {
         this.modalService
             .fromComponent(CancelOrderDialogComponent, {

+ 18 - 7
admin-ui/src/app/order/components/order-payment-detail/order-payment-detail.component.html

@@ -25,7 +25,12 @@
         </vdr-labeled-data>
     </div>
     <ng-container *ngFor="let refund of payment.refunds">
-        <div class="card-header">{{ 'order.refund' | translate }} #{{ refund.id }}</div>
+        <div class="card-header payment-header">
+            <clr-icon shape="redo" class="refund-icon" dir="down"></clr-icon>
+            {{ 'order.refund' | translate }} #{{ refund.id }}
+            <div class="clr-flex-fill"></div>
+            <vdr-refund-state-label [state]="refund.state"></vdr-refund-state-label>
+        </div>
         <div class="card-block">
             <vdr-labeled-data [label]="'common.created-at' | translate">
                 {{ refund.createdAt | date: 'medium' }}
@@ -33,13 +38,19 @@
             <vdr-labeled-data [label]="'order.refund-total' | translate">
                 {{ refund.total / 100 | currency: currencyCode }}
             </vdr-labeled-data>
+            <vdr-labeled-data [label]="'order.transaction-id' | translate" *ngIf="refund.transactionId">
+                {{ refund.transactionId }}
+            </vdr-labeled-data>
         </div>
-    </ng-container>
-    <div class="card-footer">
-        <ng-container *ngIf="payment.state === 'Authorized'">
-            <button class="btn btn-sm btn-primary" (click)="settlePayment.emit(payment)">
-                {{ 'order.settle-payment' | translate }}
+        <div class="card-footer" *ngIf="refund.state === 'Pending'">
+            <button class="btn btn-sm btn-primary" (click)="settleRefund.emit(refund)">
+                {{ 'order.settle-refund' | translate }}
             </button>
-        </ng-container>
+        </div>
+    </ng-container>
+    <div class="card-footer" *ngIf="payment.state === 'Authorized'">
+        <button class="btn btn-sm btn-primary" (click)="settlePayment.emit(payment)">
+            {{ 'order.settle-payment' | translate }}
+        </button>
     </div>
 </div>

+ 5 - 0
admin-ui/src/app/order/components/order-payment-detail/order-payment-detail.component.scss

@@ -12,3 +12,8 @@ ul.payment-metadata {
 .metadata-prop {
     color: $color-grey-500;
 }
+
+.refund-icon {
+    margin-right: 6px;
+    color: $color-grey-400;
+}

+ 1 - 0
admin-ui/src/app/order/components/order-payment-detail/order-payment-detail.component.ts

@@ -13,6 +13,7 @@ export class OrderPaymentDetailComponent {
     @Input() payment: OrderWithLines.Payments;
     @Input() currencyCode: CurrencyCode;
     @Output() settlePayment = new EventEmitter<OrderWithLines.Payments>();
+    @Output() settleRefund = new EventEmitter<OrderWithLines.Refunds>();
 
     getPaymentMetadata(payment: OrderWithLines.Payments) {
         return Object.entries(payment.metadata);

+ 4 - 0
admin-ui/src/app/order/components/refund-state-label/refund-state-label.component.html

@@ -0,0 +1,4 @@
+<vdr-chip [title]="'order.payment-state' | translate" [colorType]="chipColorType">
+    <clr-icon shape="check-circle" *ngIf="state === 'Settled'"></clr-icon>
+    {{ state }}
+</vdr-chip>

+ 3 - 0
admin-ui/src/app/order/components/refund-state-label/refund-state-label.component.scss

@@ -0,0 +1,3 @@
+:host {
+    font-size: 14px;
+}

+ 22 - 0
admin-ui/src/app/order/components/refund-state-label/refund-state-label.component.ts

@@ -0,0 +1,22 @@
+import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
+
+@Component({
+    selector: 'vdr-refund-state-label',
+    templateUrl: './refund-state-label.component.html',
+    styleUrls: ['./refund-state-label.component.scss'],
+    changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class RefundStateLabelComponent {
+    @Input() state: string;
+
+    get chipColorType() {
+        switch (this.state) {
+            case 'Pending':
+                return 'warning';
+            case 'Settled':
+                return 'success';
+            case 'Failed':
+                return 'error';
+        }
+    }
+}

+ 15 - 0
admin-ui/src/app/order/components/settle-refund-dialog/settle-refund-dialog.component.html

@@ -0,0 +1,15 @@
+<ng-template vdrDialogTitle>{{ 'order.settle-refund' | translate }}</ng-template>
+<p class="instruction">
+    {{ 'order.settle-refund-manual-instructions' | translate: { method: refund.method } }}
+</p>
+<clr-input-container>
+    <label>{{ 'order.transaction-id' | translate }}</label>
+    <input clrInput name="transactionId" [(ngModel)]="transactionId" />
+</clr-input-container>
+
+<ng-template vdrDialogButtons>
+    <button type="button" class="btn" (click)="cancel()">{{ 'common.cancel' | translate }}</button>
+    <button type="submit" (click)="submit()" [disabled]="!transactionId" class="btn btn-primary">
+        {{ 'order.settle-refund' | translate }}
+    </button>
+</ng-template>

+ 8 - 0
admin-ui/src/app/order/components/settle-refund-dialog/settle-refund-dialog.component.scss

@@ -0,0 +1,8 @@
+:host {
+    padding-bottom: 32px;
+}
+
+.instruction {
+    margin-top: 0;
+    margin-bottom: 24px;
+}

+ 24 - 0
admin-ui/src/app/order/components/settle-refund-dialog/settle-refund-dialog.component.ts

@@ -0,0 +1,24 @@
+import { ChangeDetectionStrategy, Component } from '@angular/core';
+
+import { OrderWithLines } from '../../../common/generated-types';
+import { Dialog } from '../../../shared/providers/modal/modal.service';
+
+@Component({
+    selector: 'vdr-settle-refund-dialog',
+    templateUrl: './settle-refund-dialog.component.html',
+    styleUrls: ['./settle-refund-dialog.component.scss'],
+    changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class SettleRefundDialogComponent implements Dialog<string> {
+    resolveWith: (result?: string) => void;
+    transactionId = '';
+    refund: OrderWithLines.Refunds;
+
+    submit() {
+        this.resolveWith(this.transactionId);
+    }
+
+    cancel() {
+        this.resolveWith();
+    }
+}

+ 10 - 1
admin-ui/src/app/order/order.module.ts

@@ -12,6 +12,8 @@ import { OrderListComponent } from './components/order-list/order-list.component
 import { OrderPaymentDetailComponent } from './components/order-payment-detail/order-payment-detail.component';
 import { PaymentStateLabelComponent } from './components/payment-state-label/payment-state-label.component';
 import { RefundOrderDialogComponent } from './components/refund-order-dialog/refund-order-dialog.component';
+import { RefundStateLabelComponent } from './components/refund-state-label/refund-state-label.component';
+import { SettleRefundDialogComponent } from './components/settle-refund-dialog/settle-refund-dialog.component';
 import { orderRoutes } from './order.routes';
 import { OrderResolver } from './providers/routing/order-resolver';
 
@@ -27,8 +29,15 @@ import { OrderResolver } from './providers/routing/order-resolver';
         PaymentStateLabelComponent,
         LineRefundsComponent,
         OrderPaymentDetailComponent,
+        RefundStateLabelComponent,
+        SettleRefundDialogComponent,
+    ],
+    entryComponents: [
+        FulfillOrderDialogComponent,
+        RefundOrderDialogComponent,
+        CancelOrderDialogComponent,
+        SettleRefundDialogComponent,
     ],
-    entryComponents: [FulfillOrderDialogComponent, RefundOrderDialogComponent, CancelOrderDialogComponent],
     providers: [OrderResolver],
 })
 export class OrderModule {}

+ 4 - 1
admin-ui/src/i18n-messages/en.json

@@ -410,6 +410,7 @@
     "cancel-order": "Cancel Order",
     "cancel-reason-customer-request": "Customer request",
     "cancel-reason-not-available": "Not available",
+    "cancel-selected-items": "Cancel selected items",
     "cancellation-reason": "Cancellation reason",
     "cancelled-order-success": "Successfully cancelled order",
     "create-fulfillment": "Create fulfillment",
@@ -444,11 +445,13 @@
     "refund-total-error": "Refund total must be between {min} and {max}",
     "refund-with-amount": "Refund {amount}",
     "refunded-count": "{count} {count, plural, one {item} other {items}} refunded",
-    "refunds": "Refunds",
     "return-to-stock": "Return to stock",
     "settle-payment": "Settle payment",
     "settle-payment-error": "Could not settle payment",
     "settle-payment-success": "Sucessfully settled payment",
+    "settle-refund": "Settle refund",
+    "settle-refund-manual-instructions": "After manually refunding via your payment provider ({method}), enter the transaction ID here.",
+    "settle-refund-success": "Successfully settled refund",
     "shipping": "Shipping",
     "shipping-address": "Shipping address",
     "shipping-method": "Shipping method",