# @isa/oms/feature/return-summary

A comprehensive Angular feature library for displaying and confirming return process summaries in the Order Management System (OMS). This library provides a review interface where users can inspect all items being returned, verify return details, and complete the return process with receipt printing.

## Overview

The Return Summary feature library is a critical component in the OMS return workflow. It displays all items selected for return in a given process, shows their return conditions and reasons, and provides a confirmation interface to complete the return and generate return receipts. The library integrates tightly with the return process state management and handles the final step before items are officially returned to inventory.

## Table of Contents

- [Features](#features)
- [Quick Start](#quick-start)
- [Core Concepts](#core-concepts)
- [API Reference](#api-reference)
- [Usage Examples](#usage-examples)
- [Routing and Navigation](#routing-and-navigation)
- [Component Architecture](#component-architecture)
- [State Management](#state-management)
- [Testing](#testing)
- [Best Practices](#best-practices)
- [Dependencies](#dependencies)

## Features

- **Return Process Summary** - Displays all items in a return process with complete details
- **Product Information Display** - Shows product names, images, and identification
- **Return Details Visualization** - Presents item condition, return reason, and customer comments
- **Eligibility Validation** - Verifies each item is eligible for return before processing
- **Process Completion** - Completes return process and generates return receipts
- **Receipt Printing** - Automatically triggers receipt printing after successful return
- **Navigation Integration** - Seamless routing to review screens after completion
- **Loading States** - Visual feedback during asynchronous operations
- **Error Handling** - Comprehensive error logging and user feedback
- **E2E Testing Support** - Full data-* attribute coverage for automated testing
- **Responsive Design** - Tailwind CSS-based layout with grid system
- **OnPush Change Detection** - Optimized performance with reactive signals

## Quick Start

### 1. Import Routes

```typescript
import { Routes } from '@angular/router';

export const routes: Routes = [
  {
    path: 'return/:tabId/summary',
    loadChildren: () =>
      import('@isa/oms/feature/return-summary').then(m => m.routes)
  }
];
```

### 2. Navigate to Summary

```typescript
import { Component, inject } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app-return-process',
  template: '...'
})
export class ReturnProcessComponent {
  #router = inject(Router);

  async goToSummary(tabId: number): Promise<void> {
    await this.#router.navigate(['/return', tabId, 'summary']);
  }
}
```

### 3. Process Completion Flow

The component automatically handles:
- Loading return process items from the store
- Displaying return details for each item
- Completing the return when user confirms
- Navigating to review screen after success

## Core Concepts

### Return Process Workflow

The return summary is the penultimate step in the return workflow:

1. **Return Search** - Find receipt and items to return
2. **Return Details Collection** - Gather item condition, reason, comments
3. **Return Summary** (This Library) - Review and confirm all details
4. **Return Review** - Display completed return receipts

### Return Process Data Structure

Each return process contains comprehensive information:

```typescript
interface ReturnProcess {
  id: number;                           // Unique return process ID
  processId: number;                    // Parent process ID (groups multiple returns)
  receiptId: number;                    // Original receipt ID
  receiptItem: ReceiptItem;             // Item being returned with product details
  receiptDate: string | undefined;      // Original purchase date
  answers: Record<string, unknown>;     // Return questionnaire answers
  productCategory: string;              // Product category (affects questions)
  quantity: number;                     // Quantity being returned
  returnReceipt?: Receipt;              // Generated return receipt (set after completion)
}
```

### Eligibility States

Items are validated for return eligibility:

```typescript
enum EligibleForReturnState {
  Eligible = 'eligible',              // Can be returned
  NotEligible = 'ineligible',         // Cannot be returned
  Conditional = 'conditional'         // May be returned with conditions
}

interface EligibleForReturn {
  state: EligibleForReturnState;
  reason?: string;                     // Explanation if not eligible
}
```

### Return Information Display

Return details are collected from the return process answers:

- **Item Condition** - Physical state of the item (e.g., "Unopened", "Used")
- **Return Reason** - Why the customer is returning (e.g., "Defective", "Wrong item")
- **Return Details** - Specific damage or issues (e.g., "Case damaged", "Missing accessories")
- **Other Product** - If wrong item was delivered, shows the received item's EAN
- **Comment** - Free-text customer explanation

## API Reference

### ReturnSummaryComponent

Main component for displaying the return summary and handling process completion.

#### Component Metadata

```typescript
@Component({
  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 })]
})
```

#### Properties

##### `processId: Signal<number>`

The active tab/process ID extracted from the route.

```typescript
const processId = this.processId();  // e.g., 42
```

##### `returnProcesses: Signal<ReturnProcess[]>`

Computed signal containing all return processes for the current processId.

```typescript
const items = this.returnProcesses();  // Array of ReturnProcess objects
console.log(`${items.length} items to return`);
```

##### `returnItemsAndPrintReciptStatus: WritableSignal<undefined | 'pending' | 'success' | 'error'>`

Tracks the current status of the return and print operation.

**States:**
- `undefined` - Initial state, no operation started
- `'pending'` - Operation in progress
- `'success'` - Operation completed successfully
- `'error'` - Operation failed

```typescript
const status = this.returnItemsAndPrintReciptStatus();
if (status === 'pending') {
  console.log('Processing return...');
}
```

##### `returnItemsAndPrintReciptStatusPending: Signal<boolean>`

Computed signal that returns true when the operation is pending.

```typescript
const isProcessing = this.returnItemsAndPrintReciptStatusPending();
// Used to disable buttons during processing
```

##### `location: Location`

Angular Location service for navigation (back button functionality).

```typescript
this.location.back();  // Navigate to previous page
```

#### Methods

##### `async returnItemsAndPrintRecipt(): Promise<void>`

Completes the return process, generates return receipts, and navigates to the review screen.

**Workflow:**
1. Checks if operation is already in progress (prevents double-submit)
2. Sets status to 'pending'
3. Calls `ReturnProcessService.completeReturnProcess()` with all return processes
4. Updates status based on success/failure
5. Stores completed receipts in `ReturnProcessStore`
6. Navigates to '../review' route on success
7. Logs errors if operation fails

**Example:**
```typescript
await component.returnItemsAndPrintRecipt();
// After successful completion:
// - Return receipts are created
// - State is updated with completed receipts
// - User is navigated to review screen
```

**Error Handling:**
- Logs warnings if called while already pending
- Logs errors with full context on failure
- Sets status to 'error' on exception
- Status remains visible to user (success button hidden, error stays pending)

### ReturnSummaryItemComponent

Displays a single return process item with product details and return information.

#### Component Metadata

```typescript
@Component({
  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'
  }
})
```

#### Inputs

##### `returnProcess: InputSignal<ReturnProcess>` (required)

The return process object containing all information about the item being returned.

```typescript
<oms-feature-return-summary-item
  [returnProcess]="returnProcessItem"
></oms-feature-return-summary-item>
```

##### `returnItemsAndPrintReciptPending: InputSignal<boolean>` (optional, default: false)

Whether the parent completion operation is in progress. Used to disable edit button during processing.

```typescript
<oms-feature-return-summary-item
  [returnProcess]="item"
  [returnItemsAndPrintReciptPending]="isPending()"
></oms-feature-return-summary-item>
```

#### Properties

##### `eligibleForReturn: Signal<EligibleForReturn | undefined>`

Computes the return eligibility for the current return process.

```typescript
const eligibility = this.eligibleForReturn();
if (eligibility?.state === EligibleForReturnState.NotEligible) {
  console.log(`Cannot return: ${eligibility.reason}`);
}
```

##### `returnInfos: Signal<string[]>`

Computes an array of human-readable return information strings.

**Includes:**
- Item condition (except for Tolino products)
- Return reason (except for Tolino products)
- Mapped return details (damage, missing items, etc.)
- Incorrect product delivered (shows EAN)
- Customer comments

**Special Handling:**
- Tolino products skip condition/reason display
- Duplicates are automatically removed
- Empty values are filtered out

```typescript
const infos = this.returnInfos();
// Example output:
// [
//   "Opened and used",
//   "Defective",
//   "Display damaged: Yes",
//   "Missing accessories: Power cable",
//   "Screen has scratches"
// ]
```

##### `location: Location`

Angular Location service for back navigation (edit button).

```typescript
this.location.back();  // Returns to return details screen
```

## Usage Examples

### Basic Implementation

```typescript
import { Routes } from '@angular/router';

export const returnRoutes: Routes = [
  {
    path: 'return/:tabId',
    children: [
      {
        path: 'summary',
        loadChildren: () =>
          import('@isa/oms/feature/return-summary').then(m => m.routes)
      }
    ]
  }
];
```

### Programmatic Navigation

```typescript
import { Component, inject } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app-return-workflow',
  template: `
    <button (click)="proceedToSummary()">Review Return</button>
  `
})
export class ReturnWorkflowComponent {
  #router = inject(Router);

  async proceedToSummary(): Promise<void> {
    // Navigate to summary for tab ID 42
    await this.#router.navigate(['/return', 42, 'summary']);
  }
}
```

### Handling Return Completion

```typescript
import { Component, inject, OnInit } from '@angular/core';
import { ReturnProcessStore } from '@isa/oms/data-access';
import { Router, ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-return-completion-handler',
  template: '...'
})
export class ReturnCompletionHandlerComponent implements OnInit {
  #returnStore = inject(ReturnProcessStore);
  #router = inject(Router);
  #route = inject(ActivatedRoute);

  ngOnInit(): void {
    // After completion, user is redirected to '../review'
    // which resolves to '/return/:tabId/review'

    // Access completed receipts from the store
    const completedReceipts = this.#returnStore.entities()
      .filter(p => p.returnReceipt !== undefined)
      .map(p => p.returnReceipt);

    console.log(`${completedReceipts.length} returns completed`);
  }
}
```

### Custom Navigation Flow

```typescript
import { Component, inject } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Location } from '@angular/common';

@Component({
  selector: 'app-custom-return-flow',
  template: `
    <oms-feature-return-summary></oms-feature-return-summary>
    <button (click)="cancelReturn()">Cancel</button>
  `
})
export class CustomReturnFlowComponent {
  #router = inject(Router);
  #route = inject(ActivatedRoute);
  #location = inject(Location);

  cancelReturn(): void {
    // Option 1: Navigate back
    this.#location.back();

    // Option 2: Navigate to specific route
    this.#router.navigate(['/return/search']);

    // Option 3: Navigate relative to current route
    this.#router.navigate(['../../search'], {
      relativeTo: this.#route
    });
  }
}
```

### Error Handling

```typescript
import { Component, inject, effect } from '@angular/core';
import { ReturnSummaryComponent } from '@isa/oms/feature/return-summary';
import { ToastService } from '@isa/ui/notifications';

@Component({
  selector: 'app-return-with-error-handling',
  template: `
    <oms-feature-return-summary></oms-feature-return-summary>
  `
})
export class ReturnWithErrorHandlingComponent {
  #toastService = inject(ToastService);
  returnSummary = inject(ReturnSummaryComponent);

  constructor() {
    // Monitor return status and show notifications
    effect(() => {
      const status = this.returnSummary.returnItemsAndPrintReciptStatus();

      if (status === 'success') {
        this.#toastService.success('Return completed successfully');
      } else if (status === 'error') {
        this.#toastService.error('Failed to complete return. Please try again.');
      }
    });
  }
}
```

### Accessing Return Process Data

```typescript
import { Component, inject, computed } from '@angular/core';
import { ReturnProcessStore } from '@isa/oms/data-access';
import { injectTabId } from '@isa/core/tabs';

@Component({
  selector: 'app-return-summary-analytics',
  template: '...'
})
export class ReturnSummaryAnalyticsComponent {
  #returnStore = inject(ReturnProcessStore);
  processId = injectTabId();

  // Get all returns for current process
  currentReturns = computed(() => {
    const pid = this.processId();
    return this.#returnStore.entities()
      .filter(p => p.processId === pid);
  });

  // Calculate total items being returned
  totalItems = computed(() => {
    return this.currentReturns()
      .reduce((sum, p) => sum + (p.quantity || 1), 0);
  });

  // Group by product category
  byCategory = computed(() => {
    const returns = this.currentReturns();
    return returns.reduce((acc, p) => {
      const category = p.productCategory || 'Unknown';
      acc[category] = (acc[category] || 0) + 1;
      return acc;
    }, {} as Record<string, number>);
  });
}
```

## Routing and Navigation

### Route Configuration

The library exports a `routes` constant that defines its routing structure:

```typescript
// libs/oms/feature/return-summary/src/lib/routes.ts
export const routes: Routes = [
  {
    path: '',
    component: ReturnSummaryComponent
  },
  {
    path: 'review',
    loadChildren: () =>
      import('@isa/oms/feature/return-review').then(feat => feat.routes)
  }
];
```

### Integration in Application

**Parent Route Setup:**

```typescript
// In app routing or OMS feature routing
const omsRoutes: Routes = [
  {
    path: 'return/:tabId',
    children: [
      {
        path: 'search',
        loadChildren: () => import('@isa/oms/feature/return-search')
          .then(m => m.routes)
      },
      {
        path: 'details',
        loadChildren: () => import('@isa/oms/feature/return-details')
          .then(m => m.routes)
      },
      {
        path: 'summary',
        loadChildren: () => import('@isa/oms/feature/return-summary')
          .then(m => m.routes)
      }
    ]
  }
];
```

### URL Structure

- **Summary View**: `/return/:tabId/summary`
  - Example: `/return/42/summary`

- **Review View** (after completion): `/return/:tabId/summary/review`
  - Example: `/return/42/summary/review`
  - Loads `@isa/oms/feature/return-review` lazily

### Navigation Flow

```
┌─────────────────┐
│ Return Search   │
│ /return/:id     │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ Return Details  │
│ /return/:id/... │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ Return Summary  │◄────── You are here
│ /return/:id/    │        (This Library)
│      summary    │
└────────┬────────┘
         │ (Complete Return)
         ▼
┌─────────────────┐
│ Return Review   │
│ /return/:id/    │
│  summary/review │
└─────────────────┘
```

### Back Navigation

Both components use Angular's `Location` service for back navigation:

```typescript
import { Location } from '@angular/common';

@Component({ ... })
class ReturnSummaryComponent {
  location = inject(Location);

  goBack(): void {
    this.location.back();  // Returns to previous page in history
  }
}
```

**Use Cases:**
- **Back Button** (ReturnSummaryComponent): Returns to return details collection screen
- **Edit Button** (ReturnSummaryItemComponent): Returns to edit specific item details

### Relative Navigation

The component uses relative navigation for the review route:

```typescript
await this.#router.navigate(['../', 'review'], {
  relativeTo: this.#activatedRoute
});

// From: /return/42/summary
// To:   /return/42/summary/review
```

## Component Architecture

### Component Hierarchy

```
ReturnSummaryComponent
├── Back Button (navigates to previous page)
├── Heading ("Zusammenfassung überprüfen")
├── Return Items Container
│   └── ReturnSummaryItemComponent (for each return process)
│       ├── ReturnProductInfoComponent (product display)
│       ├── Return Information List (conditions, reasons, etc.)
│       └── Edit Button (navigates back to edit)
└── Complete Button ("Artikel zurückgeben und drucken")
```

### Standalone Component Pattern

Both components use Angular's standalone component architecture:

```typescript
@Component({
  selector: 'oms-feature-return-summary',
  imports: [
    ReturnSummaryItemComponent,    // Child component
    ButtonComponent,               // UI library
    NgIcon                         // Icon library
  ],
  providers: [
    provideIcons({ isaActionChevronLeft })  // Icon registration
  ]
})
```

**Benefits:**
- No NgModule required
- Explicit dependency management
- Better tree-shaking
- Easier testing

### Change Detection Strategy

Both components use `OnPush` change detection for optimal performance:

```typescript
@Component({
  changeDetection: ChangeDetectionStrategy.OnPush
})
```

**Implications:**
- Components only re-render when:
  - Input signals change
  - Computed signals update
  - Async events trigger (button clicks)
- Better performance with large lists
- Requires reactive patterns (signals, observables)

### Styling Architecture

**Host Styling:**

```scss
// return-summary.component.scss
:host {
  @apply grid grid-flow-row gap-6 justify-stretch mt-6 relative;
}
```

**Item Styling:**

```scss
// return-summary-item.component.scss
:host {
  @apply grid grid-cols-[1fr,1fr,auto] p-6 text-isa-secondary-900 items-center;
}
```

**Layout Structure:**
- Summary uses vertical grid layout (grid-flow-row)
- Items use 3-column grid: [product info | return details | edit button]
- Tailwind utility classes for spacing and alignment
- ISA design system colors and typography

### E2E Testing Attributes

Complete data attribute coverage for automated testing:

**ReturnSummaryComponent:**
```html
<!-- Heading -->
<h1 data-what="heading" data-which="return-summary-title">

<!-- Container -->
<div data-what="container" data-which="return-items-list">

<!-- List Items -->
<oms-feature-return-summary-item
  data-what="list-item"
  data-which="return-process-item"
  [attr.data-item-id]="item.id"
  [attr.data-item-category]="item.productCategory">

<!-- Complete Button -->
<button data-what="button" data-which="return-and-print">
```

**ReturnSummaryItemComponent:**
```html
<!-- Host attributes (dynamic) -->
<component
  data-what="list-item"
  data-which="return-process-item"
  [attr.data-receipt-id]="returnProcess()?.receiptId"
  [attr.data-return-item-id]="returnProcess()?.returnItem?.id">

<!-- Return info list -->
<ul data-what="list" data-which="return-infos">
  <li data-what="list-item"
      data-which="return-info"
      [attr.data-return-info]="returnInfo"
      [attr.data-info-index]="$index">

<!-- Edit button -->
<button data-what="button" data-which="edit-return-item">
```

## State Management

### ReturnProcessStore Integration

The component relies on NgRx Signals-based state management:

```typescript
import { ReturnProcessStore } from '@isa/oms/data-access';

@Component({ ... })
class ReturnSummaryComponent {
  #returnProcessStore = inject(ReturnProcessStore);

  // Reactive query: filters entities by processId
  returnProcesses = computed<ReturnProcess[]>(() => {
    const processId = this.processId();
    return this.#returnProcessStore
      .entities()
      .filter(p => p.processId === processId);
  });
}
```

### Store Methods Used

**Reading State:**

```typescript
// Get all return process entities
this.#returnProcessStore.entities()  // Signal<ReturnProcess[]>
```

**Writing State:**

```typescript
// Mark processes as finished with generated receipts
this.#returnProcessStore.finishProcess(returnReceipts: Receipt[])
```

### Process Lifecycle

```
┌─────────────────────────────────────────────────────────┐
│ Store State: ReturnProcess[]                            │
├─────────────────────────────────────────────────────────┤
│ Initial State:                                          │
│   - Multiple ReturnProcess entities                     │
│   - Grouped by processId                                │
│   - Contains answers, receiptItem, productCategory      │
│   - returnReceipt is undefined                          │
└────────────────────┬────────────────────────────────────┘
                     │
                     │ User clicks "Complete Return"
                     ▼
┌─────────────────────────────────────────────────────────┐
│ ReturnProcessService.completeReturnProcess()            │
├─────────────────────────────────────────────────────────┤
│ - API call to OMS backend                               │
│ - Generates return receipts                             │
│ - Prints receipts                                       │
│ - Returns Receipt[] array                               │
└────────────────────┬────────────────────────────────────┘
                     │
                     │ Success: Receipt[] returned
                     ▼
┌─────────────────────────────────────────────────────────┐
│ Store.finishProcess(receipts)                           │
├─────────────────────────────────────────────────────────┤
│ Updates State:                                          │
│   - Matches receipts to ReturnProcess entities          │
│   - Sets returnReceipt property on each                 │
│   - Marks processes as completed                        │
└────────────────────┬────────────────────────────────────┘
                     │
                     │ Navigate to review
                     ▼
┌─────────────────────────────────────────────────────────┐
│ ReturnReview Screen                                     │
│ - Displays completed returnReceipts                     │
│ - Shows confirmation to user                            │
└─────────────────────────────────────────────────────────┘
```

### Tab ID Management

Uses `@isa/core/tabs` for process ID extraction:

```typescript
import { injectTabId } from '@isa/core/tabs';

@Component({ ... })
class ReturnSummaryComponent {
  // Automatically extracts tabId from route params
  processId = injectTabId();  // Signal<number>
}
```

**Benefits:**
- Centralized tab/process ID management
- Type-safe signal-based access
- Automatic route parameter tracking
- Consistent across OMS features

## Testing

The library uses **Jest** with **Spectator** for unit testing.

### Running Tests

```bash
# Run tests for this library
npx nx test oms-feature-return-summary --skip-nx-cache

# Run tests with coverage
npx nx test oms-feature-return-summary --code-coverage --skip-nx-cache

# Run tests in watch mode
npx nx test oms-feature-return-summary --watch
```

### Test Structure

The library includes comprehensive unit tests covering:

- **Component creation** - Verifies component instantiation
- **State filtering** - Tests processId-based filtering of return processes
- **Child component rendering** - Validates ReturnSummaryItemComponent is rendered correctly
- **Input binding** - Tests data flow to child components
- **E2E attributes** - Validates all data-* attributes are properly set
- **User interactions** - Tests button clicks and navigation
- **Return information** - Tests computed return details display
- **Eligibility checking** - Tests return eligibility validation
- **Navigation** - Tests back button and edit functionality

### Example Test: E2E Attributes

```typescript
it('should have proper E2E testing attributes', () => {
  // Arrange
  const mockReturnProcesses: ReturnProcess[] = [
    { id: 1, processId: 1, productCategory: 'Electronics' } as ReturnProcess,
    { id: 2, processId: 1, productCategory: 'Books' } as ReturnProcess
  ];

  jest.spyOn(spectator.component, 'returnProcesses')
    .mockReturnValue(mockReturnProcesses);

  // Act
  spectator.detectChanges();

  // Assert
  const heading = spectator.query('[data-what="heading"]');
  expect(heading).toHaveAttribute('data-which', 'return-summary-title');

  const listItems = spectator.queryAll('oms-feature-return-summary-item');
  expect(listItems[0]).toHaveAttribute('data-item-id', '1');
  expect(listItems[0]).toHaveAttribute('data-item-category', 'Electronics');
  expect(listItems[1]).toHaveAttribute('data-item-id', '2');
  expect(listItems[1]).toHaveAttribute('data-item-category', 'Books');

  const button = spectator.query('[data-which="return-and-print"]');
  expect(button).toBeTruthy();
});
```

### Example Test: Return Information Display

```typescript
it('should provide correct return information array', () => {
  // Arrange
  const mockReturnInfo = {
    itemCondition: 'Used',
    returnReason: 'Defective',
    returnDetails: { [ReturnProcessQuestionKey.CaseDamaged]: 'Yes' },
    otherProduct: { ean: '1234567890123' } as Product,
    comment: 'Screen has scratches'
  };

  jest.spyOn(returnProcessService, 'getReturnInfo')
    .mockReturnValue(mockReturnInfo);

  spectator.setInput('returnProcess', mockReturnProcess);
  spectator.detectChanges();

  // Act
  const actualInfos = spectator.component.returnInfos();

  // Assert
  expect(actualInfos).toEqual([
    'Used',
    'Defective',
    'Gehäuse beschädigt: Yes',
    'Geliefert wurde: 1234567890123',
    'Screen has scratches'
  ]);
});
```

### Mocking Strategy

**ReturnSummaryComponent Tests:**
```typescript
const createComponent = createComponentFactory({
  component: ReturnSummaryComponent,
  imports: [MockComponent(ReturnSummaryItemComponent)],
  mocks: [ReturnProcessStore, ReturnProcessService, ActivatedRoute, Router]
});
```

**ReturnSummaryItemComponent Tests:**
```typescript
const createComponent = createRoutingFactory({
  component: ReturnSummaryItemComponent,
  declarations: MockComponents(
    ReturnProductInfoComponent,
    NgIcon,
    IconButtonComponent
  ),
  providers: [
    MockProvider(ReturnProcessService, {
      getReturnInfo: jest.fn(),
      eligibleForReturn: jest.fn().mockReturnValue({ state: 'eligible' })
    }),
    MockProvider(Location, { back: jest.fn() })
  ]
});
```

### Coverage Requirements

The tests ensure coverage of:
- All public methods and properties
- All computed signals and their logic
- All user interaction handlers
- All conditional template rendering
- All E2E testing attributes
- All error scenarios

## Best Practices

### 1. Use Computed Signals for Derived State

```typescript
// ✅ Good: Reactive computed signal
returnProcesses = computed<ReturnProcess[]>(() => {
  const processId = this.processId();
  return this.#returnProcessStore
    .entities()
    .filter(p => p.processId === processId);
});

// ❌ Bad: Manual filtering in template
// {{ store.entities() | filterByProcessId: processId() }}
```

### 2. Prevent Double-Submit with Status Checking

```typescript
async returnItemsAndPrintRecipt() {
  // ✅ Good: Check if already processing
  if (this.returnItemsAndPrintReciptStatus() === 'pending') {
    this.#logger.warn('Return process already in progress');
    return;
  }

  try {
    this.returnItemsAndPrintReciptStatus.set('pending');
    // ... process return
  } catch (error) {
    this.returnItemsAndPrintReciptStatus.set('error');
  }
}

// ❌ Bad: No duplicate check, user can click multiple times
```

### 3. Comprehensive Error Logging

```typescript
// ✅ Good: Contextual error logging
this.#logger.error(
  'Error completing return process',
  error as Error,
  () => ({
    function: 'returnItemsAndPrintRecipt',
    processCount: this.returnProcesses().length,
    processId: this.processId()
  })
);

// ❌ Bad: Generic console.error
console.error('Error:', error);
```

### 4. Use E2E Attributes Consistently

```typescript
// ✅ Good: Complete E2E attribute coverage
<button
  data-what="button"
  data-which="return-and-print"
  [disabled]="returnItemsAndPrintReciptStatusPending()"
  (click)="returnItemsAndPrintRecipt()">

// ❌ Bad: Missing E2E attributes
<button
  [disabled]="isPending"
  (click)="submit()">
```

### 5. Disable UI During Async Operations

```typescript
// ✅ Good: Disable button during pending state
<button
  uiButton
  [disabled]="returnItemsAndPrintReciptStatusPending()"
  [pending]="returnItemsAndPrintReciptStatusPending()"
  (click)="returnItemsAndPrintRecipt()">

// ❌ Bad: No disabled state, allows multiple clicks
<button (click)="returnItemsAndPrintRecipt()">
```

### 6. Clean Return Info Display

```typescript
// ✅ Good: Remove duplicates and filter empty values
returnInfos = computed<string[]>(() => {
  const result: string[] = [];
  // ... collect info
  return Array.from(new Set(result));  // Remove duplicates
});

// ❌ Bad: Show duplicate info or empty entries
returnInfos = computed(() => {
  return [condition, reason, details];  // May have duplicates
});
```

### 7. Navigation After State Update

```typescript
// ✅ Good: Update store before navigation
this.#returnProcessStore.finishProcess(returnReceipts);
await this.#router.navigate(['../', 'review'], {
  relativeTo: this.#activatedRoute
});

// ❌ Bad: Navigate before state update
await this.#router.navigate(['../', 'review']);
this.#returnProcessStore.finishProcess(returnReceipts);
```

### 8. Conditional Rendering with Signals

```typescript
// ✅ Good: Use control flow syntax with signals
@if (returnItemsAndPrintReciptStatus() !== "success") {
  <button>Complete Return</button>
}

// ❌ Bad: Old *ngIf syntax (still works but less optimal)
<button *ngIf="status !== 'success'">Complete Return</button>
```

### 9. Product Category-Specific Logic

```typescript
// ✅ Good: Handle Tolino products specially
if (returnProcess.productCategory !== ProductCategory.Tolino) {
  if (itemCondition) result.push(itemCondition);
  if (returnReason) result.push(returnReason);
}

// ❌ Bad: Show all fields for all categories
result.push(itemCondition, returnReason);
```

### 10. Relative Route Navigation

```typescript
// ✅ Good: Relative navigation with ActivatedRoute
await this.#router.navigate(['../', 'review'], {
  relativeTo: this.#activatedRoute
});

// ❌ Bad: Hardcoded absolute paths
await this.#router.navigate(['/return/42/summary/review']);
```

## Dependencies

### Required Angular Libraries

- `@angular/core` (^20.1.2) - Angular framework with signals support
- `@angular/common` (^20.1.2) - Common Angular utilities (Location service)
- `@angular/router` (^20.1.2) - Routing and navigation

### ISA Internal Libraries

#### Core Libraries
- `@isa/core/tabs` - Tab/process ID management with `injectTabId()`
- `@isa/core/logging` - Centralized logging service

#### OMS Domain Libraries
- `@isa/oms/data-access` - Return process state management and services
  - `ReturnProcessStore` - NgRx Signals store
  - `ReturnProcessService` - Business logic service
  - `ReturnProcess` - Return process model
  - `EligibleForReturn`, `EligibleForReturnState` - Eligibility types
  - `ProductCategory` - Product categorization
  - `returnDetailsMapping` - Return details formatter

#### Shared Libraries
- `@isa/oms/shared/product-info` - Product information display component
- `@isa/ui/buttons` - Button and icon button components
- `@isa/icons` - Icon library (`isaActionChevronLeft`, `isaActionChevronRight`, `isaActionEdit`, `isaActionClose`)

### Third-Party Libraries

- `@ng-icons/core` - Icon component system with `NgIcon` and `provideIcons()`

### Path Alias

Import from: `@isa/oms/feature/return-summary`

### Peer Dependencies

This library expects the following to be available in the consuming application:

- Angular 20.1.2 or higher
- Tailwind CSS configured with ISA design tokens
- NgRx Signals (@ngrx/signals)
- Return process state properly initialized in ReturnProcessStore

## Architecture Notes

### Integration Points

**Upstream Dependencies:**
```
Return Details Collection
    ↓ (populates ReturnProcessStore)
Return Summary (This Library)
    ↓ (completes and stores receipts)
Return Review
```

**State Flow:**
```
ReturnProcessStore
    ↓ (entities filtered by processId)
ReturnSummaryComponent
    ↓ (passes individual processes)
ReturnSummaryItemComponent
    ↓ (displays product + return info)
User Confirmation
    ↓ (completion)
ReturnProcessService
    ↓ (API call + receipt generation)
Back to ReturnProcessStore
    ↓ (finishProcess updates)
Navigate to Review
```

### Design Patterns

1. **Presentation + Container Pattern**
   - `ReturnSummaryComponent` = Container (orchestrates flow)
   - `ReturnSummaryItemComponent` = Presentation (displays data)

2. **Signal-Based Reactivity**
   - All state management uses Angular signals
   - Computed signals for derived state
   - No manual subscription management needed

3. **Service Facade Pattern**
   - `ReturnProcessService` abstracts API complexity
   - Single method `completeReturnProcess()` handles entire flow

4. **Optimistic UI Updates**
   - Status signal immediately set to 'pending'
   - UI disables to prevent further interaction
   - Rollback on error (status set to 'error')

### Future Enhancements

Potential improvements identified:

1. **Undo Functionality** - Allow users to go back and modify before final confirmation
2. **Bulk Actions** - Select/deselect items for return in the summary
3. **Print Preview** - Show receipt preview before final confirmation
4. **Offline Support** - Queue returns when offline, sync when online
5. **Analytics Integration** - Track return patterns and reasons
6. **Accessibility Improvements** - Screen reader announcements for status changes
7. **Animation** - Smooth transitions between states
8. **Keyboard Shortcuts** - Quick navigation and confirmation via keyboard

### Known Considerations

1. **No Loading Skeleton** - Component shows empty state until data loads
2. **No Retry Mechanism** - Failed returns require manual retry (button click)
3. **Hard-Coded German Text** - Internationalization not implemented
4. **Navigation Dependency** - Assumes review route exists at '../review'
5. **Store Coupling** - Tightly coupled to ReturnProcessStore structure

## License

Internal ISA Frontend library - not for external distribution.
