Merged PR 1901: hotfix(return-summary): disable navigation during return processing

hotfix(return-summary): disable navigation during return processing

Replace Router navigation with Location.back() for better UX and add
disabled states to prevent user actions during pending operations.

Changes:
- Replace navigateBack() method with direct Location.back() calls
- Add returnItemsAndPrintReciptPending input to ReturnSummaryItemComponent
- Disable edit and back buttons when return operation is pending
- Update parent component to pass pending state to child components
- Fix template binding to use computed pending status signal

This prevents users from navigating away during critical return
operations and provides consistent disabled states across the UI.

Ref: #5257
This commit is contained in:
Nino Righi
2025-07-31 16:41:59 +00:00
committed by Andreas Schickinger
parent e674378080
commit 0addf392b6
6 changed files with 168 additions and 153 deletions

View File

@@ -35,6 +35,7 @@
name="isaActionEdit"
data-what="button"
data-which="edit-return-item"
(click)="navigateBack()"
[disabled]="returnItemsAndPrintReciptPending()"
(click)="location.back()"
></ui-icon-button>
</div>

View File

@@ -1,16 +1,16 @@
import { createRoutingFactory, Spectator } from '@ngneat/spectator/jest';
import { ReturnSummaryItemComponent } from './return-summary-item.component';
import { MockComponents, MockProvider } from 'ng-mocks';
import { ReturnProductInfoComponent } from '@isa/oms/shared/product-info';
import { createRoutingFactory, Spectator } from "@ngneat/spectator/jest";
import { ReturnSummaryItemComponent } from "./return-summary-item.component";
import { MockComponents, MockProvider } from "ng-mocks";
import { ReturnProductInfoComponent } from "@isa/oms/shared/product-info";
import {
Product,
ReturnProcess,
ReturnProcessQuestionKey,
ReturnProcessService,
} from '@isa/oms/data-access';
import { NgIcon } from '@ng-icons/core';
import { IconButtonComponent } from '@isa/ui/buttons';
import { Router } from '@angular/router';
} from "@isa/oms/data-access";
import { NgIcon } from "@ng-icons/core";
import { IconButtonComponent } from "@isa/ui/buttons";
import { Location } from "@angular/common";
/**
* Creates a mock ReturnProcess with default values that can be overridden
@@ -21,20 +21,20 @@ function createMockReturnProcess(
return {
id: 1,
processId: 1,
productCategory: 'Electronics',
productCategory: "Electronics",
answers: {},
receiptId: 123,
receiptItem: {
id: 321,
product: {
name: 'Test Product',
name: "Test Product",
},
},
...partial,
} as ReturnProcess;
}
describe('ReturnSummaryItemComponent', () => {
describe("ReturnSummaryItemComponent", () => {
let spectator: Spectator<ReturnSummaryItemComponent>;
let returnProcessService: jest.Mocked<ReturnProcessService>;
@@ -48,7 +48,10 @@ describe('ReturnSummaryItemComponent', () => {
providers: [
MockProvider(ReturnProcessService, {
getReturnInfo: jest.fn(),
eligibleForReturn: jest.fn().mockReturnValue({ state: 'eligible' }),
eligibleForReturn: jest.fn().mockReturnValue({ state: "eligible" }),
}),
MockProvider(Location, {
back: jest.fn(),
}),
],
shallow: true,
@@ -64,38 +67,38 @@ describe('ReturnSummaryItemComponent', () => {
spectator.detectChanges();
});
describe('Component Creation', () => {
it('should create the component', () => {
describe("Component Creation", () => {
it("should create the component", () => {
expect(spectator.component).toBeTruthy();
});
});
describe('Return Information Display', () => {
describe("Return Information Display", () => {
const mockReturnInfo = {
itemCondition: 'itemCondition',
returnDetails: { [ReturnProcessQuestionKey.CaseDamaged]: 'no' },
returnReason: 'returnReason',
itemCondition: "itemCondition",
returnDetails: { [ReturnProcessQuestionKey.CaseDamaged]: "no" },
returnReason: "returnReason",
otherProduct: {
ean: 'ean',
ean: "ean",
} as Product,
comment: 'comment',
comment: "comment",
};
beforeEach(() => {
jest
.spyOn(returnProcessService, 'getReturnInfo')
.spyOn(returnProcessService, "getReturnInfo")
.mockReturnValue(mockReturnInfo);
spectator.setInput('returnProcess', createMockReturnProcess({ id: 2 }));
spectator.setInput("returnProcess", createMockReturnProcess({ id: 2 }));
spectator.detectChanges();
});
it('should provide correct return information array', () => {
it("should provide correct return information array", () => {
// Arrange
const expectedInfos = [
'itemCondition',
'returnReason',
'Gehäuse beschädigt: no',
'Geliefert wurde: ean',
'comment',
"itemCondition",
"returnReason",
"Gehäuse beschädigt: no",
"Geliefert wurde: ean",
"comment",
];
// Act
@@ -105,14 +108,14 @@ describe('ReturnSummaryItemComponent', () => {
expect(actualInfos).toEqual(expectedInfos);
expect(actualInfos.length).toBe(5);
});
it('should render return info items with correct content', () => {
it("should render return info items with correct content", () => {
// Arrange
const expectedInfos = [
'itemCondition',
'returnReason',
'Gehäuse beschädigt: no',
'Geliefert wurde: ean',
'comment',
"itemCondition",
"returnReason",
"Gehäuse beschädigt: no",
"Geliefert wurde: ean",
"comment",
];
// Act
@@ -125,14 +128,14 @@ describe('ReturnSummaryItemComponent', () => {
expect(listItems.length).toBe(expectedInfos.length);
listItems.forEach((item, index) => {
expect(item).toHaveText(expectedInfos[index]);
expect(item).toHaveAttribute('data-info-index', index.toString());
expect(item).toHaveAttribute("data-info-index", index.toString());
});
});
it('should handle undefined return info gracefully', () => {
it("should handle undefined return info gracefully", () => {
// Arrange
returnProcessService.getReturnInfo.mockReturnValue(undefined);
spectator.setInput('returnProcess', createMockReturnProcess({ id: 3 }));
spectator.setInput("returnProcess", createMockReturnProcess({ id: 3 }));
spectator.detectChanges();
// Act
@@ -146,26 +149,26 @@ describe('ReturnSummaryItemComponent', () => {
expect(listItems.length).toBe(0);
});
describe('returnDetails mapping', () => {
it('should map multiple returnDetails keys to correct info strings', () => {
describe("returnDetails mapping", () => {
it("should map multiple returnDetails keys to correct info strings", () => {
const expected = [
'itemCondition',
'returnReason',
'Gehäuse beschädigt: Ja',
'Display beschädigt: Nein',
'Geliefert wurde: ean',
'comment',
"itemCondition",
"returnReason",
"Gehäuse beschädigt: Ja",
"Display beschädigt: Nein",
"Geliefert wurde: ean",
"comment",
];
// Arrange
const details = {
[ReturnProcessQuestionKey.CaseDamaged]: 'Ja',
[ReturnProcessQuestionKey.DisplayDamaged]: 'Nein',
[ReturnProcessQuestionKey.CaseDamaged]: "Ja",
[ReturnProcessQuestionKey.DisplayDamaged]: "Nein",
};
returnProcessService.getReturnInfo.mockReturnValue({
...mockReturnInfo,
returnDetails: details,
});
spectator.setInput('returnProcess', createMockReturnProcess({ id: 4 }));
spectator.setInput("returnProcess", createMockReturnProcess({ id: 4 }));
spectator.detectChanges();
// Act
@@ -173,31 +176,31 @@ describe('ReturnSummaryItemComponent', () => {
expect(infos).toEqual(expected);
});
it('should not include returnDetails if empty', () => {
it("should not include returnDetails if empty", () => {
// Arrange
returnProcessService.getReturnInfo.mockReturnValue({
...mockReturnInfo,
returnDetails: {},
});
spectator.setInput('returnProcess', createMockReturnProcess({ id: 5 }));
spectator.setInput("returnProcess", createMockReturnProcess({ id: 5 }));
spectator.detectChanges();
// Act
const infos = spectator.component.returnInfos();
// Assert
expect(infos.some((info) => info.includes('Gehäuse beschädigt'))).toBe(
expect(infos.some((info) => info.includes("Gehäuse beschädigt"))).toBe(
false,
);
expect(infos.some((info) => info.includes('Zubehör fehlt'))).toBe(
expect(infos.some((info) => info.includes("Zubehör fehlt"))).toBe(
false,
);
});
});
});
describe('Navigation', () => {
it('should render edit button with correct attributes', () => {
describe("Navigation", () => {
it("should render edit button with correct attributes", () => {
// Assert
const editButton = spectator.query(
'[data-what="button"][data-which="edit-return-item"]',
@@ -205,7 +208,7 @@ describe('ReturnSummaryItemComponent', () => {
expect(editButton).toExist();
});
it('should navigate back when edit button is clicked', () => {
it("should navigate back when edit button is clicked", () => {
// Arrange
const editButton = spectator.query(
'[data-what="button"][data-which="edit-return-item"]',
@@ -217,25 +220,20 @@ describe('ReturnSummaryItemComponent', () => {
}
// Assert
expect(spectator.inject(Router).navigate).toHaveBeenCalledWith(
['..'],
expect.objectContaining({
relativeTo: expect.anything(),
}),
);
expect(spectator.inject(Location).back).toHaveBeenCalled();
});
});
it('should render the product info component', () => {
it("should render the product info component", () => {
const productInfo = spectator.query(ReturnProductInfoComponent);
expect(productInfo).toExist();
});
it('should compute eligibility state as eligible', () => {
it("should compute eligibility state as eligible", () => {
(returnProcessService.eligibleForReturn as jest.Mock).mockReturnValue({
state: 'eligible',
state: "eligible",
});
spectator.detectChanges();
expect(spectator.component.eligibleForReturn()?.state).toBe('eligible');
expect(spectator.component.eligibleForReturn()?.state).toBe("eligible");
});
});

View File

@@ -4,13 +4,13 @@ import {
computed,
inject,
input,
} from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
} from "@angular/core";
import { Location } from "@angular/common";
import {
isaActionChevronRight,
isaActionClose,
isaActionEdit,
} from '@isa/icons';
} from "@isa/icons";
import {
EligibleForReturn,
EligibleForReturnState,
@@ -18,10 +18,10 @@ import {
ReturnProcessService,
ProductCategory,
returnDetailsMapping,
} from '@isa/oms/data-access';
import { ReturnProductInfoComponent } from '@isa/oms/shared/product-info';
import { IconButtonComponent } from '@isa/ui/buttons';
import { NgIcon, provideIcons } from '@ng-icons/core';
} from "@isa/oms/data-access";
import { ReturnProductInfoComponent } from "@isa/oms/shared/product-info";
import { IconButtonComponent } from "@isa/ui/buttons";
import { NgIcon, provideIcons } from "@ng-icons/core";
/**
* Displays a single item in the return process summary, showing product details
@@ -47,30 +47,34 @@ import { NgIcon, provideIcons } from '@ng-icons/core';
* ```
*/
@Component({
selector: 'oms-feature-return-summary-item',
templateUrl: './return-summary-item.component.html',
styleUrls: ['./return-summary-item.component.scss'],
selector: "oms-feature-return-summary-item",
templateUrl: "./return-summary-item.component.html",
styleUrls: ["./return-summary-item.component.scss"],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [ReturnProductInfoComponent, NgIcon, IconButtonComponent],
providers: [
provideIcons({ isaActionChevronRight, isaActionEdit, isaActionClose }),
],
host: {
'data-what': 'list-item',
'data-which': 'return-process-item',
'[attr.data-receipt-id]': 'returnProcess()?.receiptId',
'[attr.data-return-item-id]': 'returnProcess()?.returnItem?.id',
"data-what": "list-item",
"data-which": "return-process-item",
"[attr.data-receipt-id]": "returnProcess()?.receiptId",
"[attr.data-return-item-id]": "returnProcess()?.returnItem?.id",
},
})
export class ReturnSummaryItemComponent {
EligibleForReturnState = EligibleForReturnState;
#returnProcessService = inject(ReturnProcessService);
#router = inject(Router);
#activatedRoute = inject(ActivatedRoute);
/** Angular Location service for navigation */
location = inject(Location);
/** The return process object containing all information about the return */
returnProcess = input.required<ReturnProcess>();
/** The status of the return items and print receipt operation */
returnItemsAndPrintReciptPending = input<boolean>(false);
/**
* Computes whether the current return process is eligible for return.
*
@@ -149,8 +153,4 @@ export class ReturnSummaryItemComponent {
// remove duplicates
return Array.from(new Set(result));
});
navigateBack() {
this.#router.navigate(['..'], { relativeTo: this.#activatedRoute });
}
}

View File

@@ -3,6 +3,7 @@
color="tertiary"
size="small"
class="px-[0.875rem] py-1 min-w-0 bg-white gap-1 absolute top-0 left-0"
[disabled]="returnItemsAndPrintReciptStatusPending()"
(click)="location.back()"
>
<ng-icon name="isaActionChevronLeft" size="1.5rem" class="-ml-2"></ng-icon>
@@ -28,19 +29,22 @@
data-which="return-process-item"
[attr.data-item-id]="item.id"
[attr.data-item-category]="item.productCategory"
[returnItemsAndPrintReciptPending]="
returnItemsAndPrintReciptStatusPending()
"
></oms-feature-return-summary-item>
}
</div>
<div class="mt-6 text-center">
@if (returnItemsAndPrintReciptStatus() !== 'success') {
@if (returnItemsAndPrintReciptStatus() !== "success") {
<button
type="button"
size="large"
uiButton
color="brand"
(click)="returnItemsAndPrintRecipt()"
[pending]="returnItemsAndPrintReciptStatus() === 'pending'"
[disabled]="returnItemsAndPrintReciptStatus() === 'pending'"
[pending]="returnItemsAndPrintReciptStatusPending()"
[disabled]="returnItemsAndPrintReciptStatusPending()"
data-what="button"
data-which="return-and-print"
>

View File

@@ -1,30 +1,30 @@
import { createComponentFactory, Spectator } from '@ngneat/spectator/jest';
import { MockComponent } from 'ng-mocks';
import { ReturnSummaryComponent } from './return-summary.component';
import { createComponentFactory, Spectator } from "@ngneat/spectator/jest";
import { MockComponent } from "ng-mocks";
import { ReturnSummaryComponent } from "./return-summary.component";
import {
ReturnProcess,
ReturnProcessService,
ReturnProcessStore,
} from '@isa/oms/data-access';
import { ReturnSummaryItemComponent } from './return-summary-item/return-summary-item.component';
import { ActivatedRoute, Router } from '@angular/router';
} from "@isa/oms/data-access";
import { ReturnSummaryItemComponent } from "./return-summary-item/return-summary-item.component";
import { ActivatedRoute, Router } from "@angular/router";
jest.mock('@isa/core/process', () => ({
jest.mock("@isa/core/process", () => ({
injectActivatedProcessId: () => jest.fn(() => 1),
}));
const MOCK_RETURN_PROCESSES: ReturnProcess[] = [
{ id: 1, processId: 1, productCategory: 'Electronics' } as ReturnProcess,
{ id: 2, processId: 1, productCategory: 'Books' } as ReturnProcess,
{ id: 3, processId: 2, productCategory: 'Clothing' } as ReturnProcess,
{ id: 4, processId: 2, productCategory: 'Home Goods' } as ReturnProcess,
{ id: 5, processId: 3, productCategory: 'Electronics' } as ReturnProcess,
{ id: 6, processId: 3, productCategory: 'Toys' } as ReturnProcess,
{ id: 7, processId: 4, productCategory: 'Books' } as ReturnProcess,
{ id: 8, processId: 4, productCategory: 'Garden' } as ReturnProcess,
{ id: 1, processId: 1, productCategory: "Electronics" } as ReturnProcess,
{ id: 2, processId: 1, productCategory: "Books" } as ReturnProcess,
{ id: 3, processId: 2, productCategory: "Clothing" } as ReturnProcess,
{ id: 4, processId: 2, productCategory: "Home Goods" } as ReturnProcess,
{ id: 5, processId: 3, productCategory: "Electronics" } as ReturnProcess,
{ id: 6, processId: 3, productCategory: "Toys" } as ReturnProcess,
{ id: 7, processId: 4, productCategory: "Books" } as ReturnProcess,
{ id: 8, processId: 4, productCategory: "Garden" } as ReturnProcess,
];
describe('ReturnSummaryComponent', () => {
describe("ReturnSummaryComponent", () => {
let spectator: Spectator<ReturnSummaryComponent>;
// Use createComponentFactory for standalone components
const createComponent = createComponentFactory({
@@ -47,17 +47,17 @@ describe('ReturnSummaryComponent', () => {
});
});
it('should create the component', () => {
it("should create the component", () => {
// Assert: Check if the component instance was created successfully
expect(spectator.component).toBeTruthy();
});
it('should have a defined processId', () => {
it("should have a defined processId", () => {
// Assert: Check if the processId is defined
expect(spectator.component.processId()).toBeTruthy();
});
it('should have two return processes', () => {
it("should have two return processes", () => {
// Arrange:
const mockReturnProcesses: ReturnProcess[] = [
MOCK_RETURN_PROCESSES[0],
@@ -72,14 +72,14 @@ describe('ReturnSummaryComponent', () => {
expect(returnProcesses).toEqual(mockReturnProcesses);
});
it('should render the return summary item component', () => {
it("should render the return summary item component", () => {
// Arrange:
const mockReturnProcesses: ReturnProcess[] = [
MOCK_RETURN_PROCESSES[0],
MOCK_RETURN_PROCESSES[1],
];
jest
.spyOn(spectator.component, 'returnProcesses')
.spyOn(spectator.component, "returnProcesses")
.mockReturnValue(mockReturnProcesses);
// Act: Trigger change detection
@@ -91,14 +91,14 @@ describe('ReturnSummaryComponent', () => {
expect(returnSummaryItems.length).toBe(mockReturnProcesses.length);
});
it('should set the returnProcess input correctly', () => {
it("should set the returnProcess input correctly", () => {
// Arrange:
const mockReturnProcesses: ReturnProcess[] = [
MOCK_RETURN_PROCESSES[0],
MOCK_RETURN_PROCESSES[1],
];
jest
.spyOn(spectator.component, 'returnProcesses')
.spyOn(spectator.component, "returnProcesses")
.mockReturnValue(mockReturnProcesses);
// Act: Trigger change detection
@@ -110,7 +110,7 @@ describe('ReturnSummaryComponent', () => {
expect(returnSummaryItems[1].returnProcess).toEqual(mockReturnProcesses[1]);
});
it('should have proper E2E testing attributes', () => {
it("should have proper E2E testing attributes", () => {
// Arrange
const mockReturnProcesses: ReturnProcess[] = [
MOCK_RETURN_PROCESSES[0], // id: 1, processId: 1, category: 'Electronics'
@@ -118,7 +118,7 @@ describe('ReturnSummaryComponent', () => {
];
jest
.spyOn(spectator.component, 'returnProcesses')
.spyOn(spectator.component, "returnProcesses")
.mockReturnValue(mockReturnProcesses);
// Act
@@ -128,57 +128,57 @@ describe('ReturnSummaryComponent', () => {
// Check heading attributes
const heading = spectator.query('[data-what="heading"]');
expect(heading).toBeTruthy();
expect(heading).toHaveAttribute('data-which', 'return-summary-title');
expect(heading).toHaveAttribute("data-which", "return-summary-title");
// Check container attributes
const container = spectator.query('[data-what="container"]');
expect(container).toBeTruthy();
expect(container).toHaveAttribute('data-which', 'return-items-list');
expect(container).toHaveAttribute("data-which", "return-items-list");
// Check list item attributes
const listItems = spectator.queryAll('oms-feature-return-summary-item');
const listItems = spectator.queryAll("oms-feature-return-summary-item");
expect(listItems.length).toBe(mockReturnProcesses.length);
// Check attributes for the first item
expect(listItems[0]).toHaveAttribute('data-what', 'list-item');
expect(listItems[0]).toHaveAttribute('data-which', 'return-process-item');
expect(listItems[0]).toHaveAttribute("data-what", "list-item");
expect(listItems[0]).toHaveAttribute("data-which", "return-process-item");
expect(listItems[0]).toHaveAttribute(
'data-item-id',
"data-item-id",
`${mockReturnProcesses[0].id}`,
);
expect(listItems[0]).toHaveAttribute(
'data-item-category',
"data-item-category",
mockReturnProcesses[0].productCategory,
);
// Check attributes for the second item
expect(listItems[1]).toHaveAttribute('data-what', 'list-item');
expect(listItems[1]).toHaveAttribute('data-which', 'return-process-item');
expect(listItems[1]).toHaveAttribute("data-what", "list-item");
expect(listItems[1]).toHaveAttribute("data-which", "return-process-item");
expect(listItems[1]).toHaveAttribute(
'data-item-id',
"data-item-id",
`${mockReturnProcesses[1].id}`,
);
expect(listItems[1]).toHaveAttribute(
'data-item-category',
"data-item-category",
`${mockReturnProcesses[1].productCategory}`,
);
expect(listItems[1]).toHaveAttribute(
'data-item-category',
"data-item-category",
mockReturnProcesses[1].productCategory,
);
// Check button attributes
const button = spectator.query('[data-what="button"]');
expect(button).toBeTruthy();
expect(button).toHaveAttribute('data-which', 'return-and-print');
expect(button).toHaveAttribute("data-which", "return-and-print");
});
it('should call returnItemsAndPrintRecipt when button is clicked', () => {
it("should call returnItemsAndPrintRecipt when button is clicked", () => {
// Arrange: Spy on the returnItemsAndPrintRecipt method
const returnItemsAndPrintReciptSpy = jest.spyOn(
spectator.component,
'returnItemsAndPrintRecipt',
"returnItemsAndPrintRecipt",
);
// Act: Trigger button click

View File

@@ -4,20 +4,20 @@ import {
computed,
inject,
signal,
} from '@angular/core';
import { ReturnSummaryItemComponent } from './return-summary-item/return-summary-item.component';
import { injectActivatedProcessId } from '@isa/core/process';
} from "@angular/core";
import { ReturnSummaryItemComponent } from "./return-summary-item/return-summary-item.component";
import { injectActivatedProcessId } from "@isa/core/process";
import {
ReturnProcess,
ReturnProcessService,
ReturnProcessStore,
} from '@isa/oms/data-access';
import { ButtonComponent } from '@isa/ui/buttons';
import { NgIcon, provideIcons } from '@ng-icons/core';
import { Location } from '@angular/common';
import { isaActionChevronLeft } from '@isa/icons';
import { logger } from '@isa/core/logging';
import { ActivatedRoute, Router } from '@angular/router';
} from "@isa/oms/data-access";
import { ButtonComponent } from "@isa/ui/buttons";
import { NgIcon, provideIcons } from "@ng-icons/core";
import { Location } from "@angular/common";
import { isaActionChevronLeft } from "@isa/icons";
import { logger } from "@isa/core/logging";
import { ActivatedRoute, Router } from "@angular/router";
/**
* Main component for the return summary feature. Displays a list of items being returned
@@ -35,9 +35,9 @@ import { ActivatedRoute, Router } from '@angular/router';
* ```
*/
@Component({
selector: 'oms-feature-return-summary',
templateUrl: './return-summary.component.html',
styleUrls: ['./return-summary.component.scss'],
selector: "oms-feature-return-summary",
templateUrl: "./return-summary.component.html",
styleUrls: ["./return-summary.component.scss"],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [ReturnSummaryItemComponent, ButtonComponent, NgIcon],
providers: [provideIcons({ isaActionChevronLeft })],
@@ -74,9 +74,21 @@ export class ReturnSummaryComponent {
* - 'error': Operation failed
*/
returnItemsAndPrintReciptStatus = signal<
undefined | 'pending' | 'success' | 'error'
undefined | "pending" | "success" | "error"
>(undefined);
/**
* Computed signal to determine if the return items and print receipt operation is pending.
*
* This signal checks the current status of the returnItemsAndPrintReciptStatus signal
* and returns true if the status is 'pending', otherwise false.
*
* @returns {boolean} True if the operation is pending, false otherwise
*/
returnItemsAndPrintReciptStatusPending = computed(() => {
return this.returnItemsAndPrintReciptStatus() === "pending";
});
/**
* Handles the return and print process for multiple items.
*
@@ -93,35 +105,35 @@ export class ReturnSummaryComponent {
* @returns {Promise<void>}
*/
async returnItemsAndPrintRecipt() {
if (this.returnItemsAndPrintReciptStatus() === 'pending') {
this.#logger.warn('Return process already in progress', () => ({
function: 'returnItemsAndPrintRecipt',
if (this.returnItemsAndPrintReciptStatus() === "pending") {
this.#logger.warn("Return process already in progress", () => ({
function: "returnItemsAndPrintRecipt",
}));
return;
}
try {
this.returnItemsAndPrintReciptStatus.set('pending');
this.returnItemsAndPrintReciptStatus.set("pending");
const returnReceipts =
await this.#returnProcessService.completeReturnProcess(
this.returnProcesses(),
);
this.#logger.info('Return receipts created', () => ({
this.#logger.info("Return receipts created", () => ({
count: returnReceipts.length,
}));
this.returnItemsAndPrintReciptStatus.set('success');
this.returnItemsAndPrintReciptStatus.set("success");
this.#returnProcessStore.finishProcess(returnReceipts);
await this.#router.navigate(['../', 'review'], {
await this.#router.navigate(["../", "review"], {
relativeTo: this.#activatedRoute,
});
} catch (error) {
this.#logger.error('Error completing return process', error, () => ({
function: 'returnItemsAndPrintRecipt',
this.#logger.error("Error completing return process", error, () => ({
function: "returnItemsAndPrintRecipt",
}));
this.returnItemsAndPrintReciptStatus.set('error');
this.returnItemsAndPrintReciptStatus.set("error");
}
}
}