Compare commits

...

145 Commits

Author SHA1 Message Date
Lorenz Hilpert
6f9d4d9218 Merge branch 'release/4.0' 2025-07-23 16:35:08 +02:00
Lorenz Hilpert
e674378080 Merged PR 1883: fix(return-details): update email validation and improve error handling
fix(return-details): update email validation and improve error handling

Refs: #5211
2025-07-14 14:57:41 +00:00
Nino Righi
7c907645dc Merged PR 1880: hotfix(oms-data-access): initial implementation of OMS data access layer
hotfix(oms-data-access): initial implementation of OMS data access layer

Introduce the foundational OMS data access module, including service scaffolding and integration points for future API communication. This establishes a clear separation of concerns for order management system data retrieval and manipulation, following project architecture guidelines.

Ref: #5210
2025-07-10 11:32:42 +00:00
Nino Righi
6fee35c756 Merged PR 1872: fix(isa-app-moment-locale): correct locale initialization for date formatting
fix(isa-app-moment-locale): correct locale initialization for date formatting

Ensures proper setup of moment.js locale in the ISA app to provide accurate date and time formatting for users. Addresses issues with incorrect or inconsistent locale application.

Ref: #5188
2025-06-25 08:35:43 +00:00
Nino Righi
c15077aa86 Merged PR 1870: fix(oms-return-search): fix display and logic issues in return search results
fix(oms-return-search): fix display and logic issues in return search results

Resolve display inconsistencies and correct logic in the return search result component to improve user experience and maintain alignment with design and business requirements.

Ref: #5009
2025-06-23 21:23:27 +00:00
Nino Righi
f051a97e53 Merged PR 1871: fix(ui-dropdown): improve dropdown usability and conditional rendering
fix(ui-dropdown): improve dropdown usability and conditional rendering

Refines the logic for displaying quantity and product category dropdowns in the return details order group item controls. Ensures dropdowns are only shown when appropriate and maintains accessibility and user experience.

Ref: #5189
2025-06-23 15:32:56 +00:00
Nino Righi
1b26a44a37 Merged PR 1869: fix(oms-task-list-item): address styling and layout issues in return task lis...
fix(oms-task-list-item): address styling and layout issues in return task list item

Improves SCSS for the return task list item component to ensure consistent appearance and resolve layout inconsistencies. Enhances maintainability and visual alignment with design standards.

Ref: #5191
2025-06-23 15:25:34 +00:00
Nino Righi
80b2508708 Merged PR 1868: fix(oms-return-search): resolve issues in return search result item rendering
fix(oms-return-search): resolve issues in return search result item rendering

Corrects rendering logic and improves template structure for the return search result item component. Ensures compliance with Angular control flow best practices and enhances maintainability.

Ref: #5190
2025-06-23 15:24:26 +00:00
Nino
e9affd2359 fix(return-details): Small Layout Fix, Refs: #5171 2025-06-17 16:52:03 +02:00
Nino
8f8b9153b0 Merge branch 'develop' into release/4.0 2025-06-17 16:45:37 +02:00
Lorenz Hilpert
9a4121e2bf fix(return-details): correct storage key retrieval in ReturnDetailsStore 2025-06-16 10:53:58 +02:00
Nino Righi
636e405927 Merged PR 1865: feat(oms-data-access, oms-return-review, oms-return-summary): fix return receipt mapping and ensure process completion
feat(oms-data-access, oms-return-review, oms-return-summary): fix return receipt mapping and ensure process completion

Corrects the mapping of return receipts in the return process flow to ensure that the correct receipt IDs are used when printing and finalizing returns. Updates the `finishProcess` method to associate return receipts with the correct entities and ensures the store is updated after process completion. This resolves issues where printed receipts or review steps could reference incorrect or missing data.

Ref: #5120
2025-06-14 14:19:02 +00:00
Nino Righi
159afa9356 Merged PR 1864: feat(ui-tooltip): remove native title attribute from tooltip icon host
- feat(ui-tooltip): remove native title attribute from tooltip icon host

Refs: #5163
2025-06-14 14:18:21 +00:00
Nino Righi
2088fd3191 Merged PR 1863: feat(oms-return-details): improve layout and styling of order group item controls
- feat(oms-return-details): improve layout and styling of order group item controls

Ref: #5171
2025-06-13 13:56:15 +00:00
Nino Righi
6f80159281 Merged PR 1860: #5157 Return Input Ean Validation
- feat(oms-return-review): implement return review feature
- Merge branch 'develop' of https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend into develop
- Merge branch 'develop' of https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend into develop
- feat(oms-return-process, ui-input-controls): improve error feedback for EAN input and adjust text field container spacing

Refs: #5157
2025-06-13 13:55:32 +00:00
Lorenz Hilpert
50b7f21394 Merge branch 'develop' into release/4.0 2025-06-12 21:12:08 +02:00
Lorenz Hilpert
0134f8dbf5 fix(return-search): correct typo in tooltip content 2025-06-12 18:53:41 +02:00
Lorenz Hilpert
1429ca37c6 feat(return-product-info): add ProductRouterLinkDirective to tests 2025-06-12 18:50:52 +02:00
Nino Righi
f5f8a7ae18 Merged PR 1862: #5168
- feat(oms-data-access): fix return process entity validation in startProcess

Refs: #5168
2025-06-12 16:28:31 +00:00
Lorenz Hilpert
3cf05f04ef feat(shared-scanner): Moved to shared/scanner
feat(common-data-access): takeUnitl operators for keydown

Refs: #5062
2025-06-12 16:34:21 +02:00
Lorenz Hilpert
055cfb67d3 Merged PR 1861: feat(product-router-link): add shared product router link directive and builder
feat(product-router-link): add shared product router link directive and builder

Ref: #5111 #5169
2025-06-12 14:28:12 +00:00
Lorenz Hilpert
53d8abd615 Merged PR 1859: feat(print-button): implement reusable print button component with service in...
feat(print-button): implement reusable print button component with service integration

Ref: #5146
2025-06-12 14:00:09 +00:00
Nino Righi
7323c67ba6 Merged PR 1857: feat(oms-return-review): implement return review feature
feat(oms-return-review): implement return review feature

Introduce the initial implementation of the return review feature in the OMS module. This includes core logic, UI components, and integration with existing state management. The feature enables users to review return processes, view item details, and confirm actions as part of the return workflow.

Ref: #5120
2025-06-12 12:16:30 +00:00
Lorenz Hilpert
1617533412 Merged PR 1858: feat(scanner): add full-screen scanner styles and components
feat(scanner): add full-screen scanner styles and components

Implemented full-screen scanner styles in styles.scss.
Added ScannerButtonComponent to trigger barcode scanning.
Created ScannerComponent for rendering camera view and processing scans.
Updated ScannerService to handle scanning operations and configuration.
Enhanced README.md with detailed library features and usage examples.
Refactored return process components to utilize new scanner button.
Updated search bar input to integrate scanner functionality.
Added tests for new components and services, ensuring proper functionality.
Improved UI button styles for better integration with scanner features.
Ref:
#5123
DS // Scanner Overlay
QA
#5056
Retoure // Scan-Button lösen Suche aus
QA
#5147

Related work items: #5147
2025-06-12 11:56:06 +00:00
Nino Righi
b589dc21cd Merged PR 1856: #5144 #5141 #5099
- feat(oms-data-access, oms-return-details): add processed quantity helper and refactor item controls
- feat(ui-input-controls, oms-return-details): add disabled styling and logic for dropdowns
- feat(oms-return-details): improve dropdown accessibility and disabled state handling

Refs: #5144 #5141 #5099
2025-06-11 19:56:16 +00:00
Lorenz Hilpert
80fb65ffc4 Merged PR 1855: 5000 Retoure // Info -Tooltip zur Suchseite hinzufügen
Related work items: #5000
2025-06-11 15:08:54 +00:00
Lorenz Hilpert
dbe0328eb7 Merged PR 1854: refactor(searchbox): improve formatting and add showScannerButton getter
refactor(searchbox): improve formatting and add showScannerButton getter

Ref: #5001
2025-06-10 14:57:14 +00:00
Lorenz Hilpert
61ce9940c9 Merged PR 1853: feat(return-process): add getReceiptItemQuantity helper and related tests
feat(return-process): add getReceiptItemQuantity helper and related tests

Ref: #5156
2025-06-10 14:56:34 +00:00
Nino Righi
a37201ef33 Merged PR 1849: feat(libs-ui-item-rows): improve data value wrapping and label sizing
feat(libs-ui-item-rows): improve data value wrapping and label sizing

- Add `break-all` to `.ui-item-row-data-value` for better handling of long or unbroken content, ensuring values do not overflow their containers
- Use Tailwind's `min-w-[6.5rem]` utility for `.ui-item-row-data-label` and `.ui-item-row-data-label` in both `item-row-data` and `client-row` components, standardizing minimum label width and improving layout consistency

Ref: #5074
2025-06-10 14:43:13 +00:00
Nino Righi
9857d86bdf Merged PR 1850: feat(libs-shared-filter): improve date range equality for default filter inpu...
feat(libs-shared-filter): improve date range equality for default filter input detection

Enhance the isDefaultFilterInput method to compare DateRangeFilterInput values by parsing ISO date strings to Date objects before comparison. This ensures that date ranges are considered equal even if their string representations differ in precision (e.g., "2023-06-05T22:00:00Z" vs. "2023-06-05T22:00:00.000Z"). This change improves filter reset and default state detection reliability for date range filters.

Ref: #5142
2025-06-10 13:57:09 +00:00
Nino Righi
7283caab15 Merged PR 1852: feat(shared-filter,search-bar,search-main): add E2E data attributes for filte...
feat(shared-filter,search-bar,search-main): add E2E data attributes for filter and search UI

Add standardized `data-which` and `data-what` attributes to filter input buttons, search bar input, search bar button, and clear search icon components. This improves end-to-end testability and aligns with project conventions for robust, maintainable UI automation. Updates affect filter menu, input menu button, search bar input, and search bar clear components, as well as the return search main feature.

Ref: #5060
2025-06-10 13:16:15 +00:00
Lorenz Hilpert
3eb6981e3a Merged PR 1851: Retoure // Mehrere Belege in der Retouren-Detailansicht anzeigen
Related work items: #5002, #5148
2025-06-06 15:34:33 +00:00
Lorenz Hilpert
dd598d100c Merged PR 1848: feat(tooltip): add tooltip component and directive with customizable triggers
feat(tooltip): add tooltip component and directive with customizable triggers

Introduce a new tooltip library for Angular applications, featuring a
flexible tooltip component that supports various trigger events
(click, hover, focus) and customizable content. Includes necessary
styles, tests, and documentation for usage and configuration.

Ref: #4992
2025-06-06 11:13:07 +00:00
Nino Righi
405bf5b463 Merged PR 1847: fix(shared-filter): add mapFilterInputToRecord util and refactor query mapping
fix(shared-filter): add mapFilterInputToRecord util and refactor query mapping

Introduce mapFilterInputToRecord utility for consistent mapping of filter inputs to query parameter records. Refactor FilterService.query to use this utility for both filter and input groups, ensuring DRY code and improved maintainability.

Add unit tests for the new mapping function and update the mappings index export.

Ref: #5105, #5106, #5143
2025-06-05 17:14:05 +00:00
Nino Righi
b261273228 Merged PR 1841: feat(ui-input-controls, oms-return-process): introduce text field container,...
feat(ui-input-controls, oms-return-process): introduce text field container, clear, and errors components

- Add `ui-text-field-container`, `ui-text-field-clear`, and `ui-text-field-errors` as standalone components for improved text field composition and error handling.
- Update SCSS to include new styles for container, clear, and errors components, ensuring visual consistency and error highlighting.
- Refactor `ReturnProcessProductQuestionComponent` to use the new containerized text field structure, improving template clarity and error display.
- Update Storybook story for `TextField` to demonstrate new composition and error handling.
- Export new components from the input-controls public API for external usage.

Ref: #4989, #5058
2025-06-05 17:12:28 +00:00
Lorenz Hilpert
f5507a874c Merge branch 'develop' of ssh.dev.azure.com:v3/hugendubel/ISA/ISA-Frontend into develop 2025-06-05 18:49:39 +02:00
Lorenz Hilpert
4478e1ce21 hotfix(checkout): Chaning the Quantity in the cart used a wrink branch for "Rücklage"
- When chaning the quantity, the current destination branch will be used to update the quantity in the cart
2025-06-05 18:35:23 +02:00
Lorenz Hilpert
ade6b7f845 Merged PR 1846: Navigation for to Customer Details from external Systems
Related work items: #5149
2025-06-05 16:09:13 +00:00
Nino Righi
7743150652 Merged PR 1845: feat(shared-product-info): add shared product info module and initial impleme...
feat(shared-product-info): add shared product info module and initial implementation

Introduce a new shared module for product information, providing reusable components and services for displaying product details across the application. This module is designed for consistency and maintainability, following project guidelines for modularization and type safety.

Ref: #5065
2025-06-04 19:42:14 +00:00
Nino Righi
543de57190 Merged PR 1844: feat(oms-data-access, oms-shared-task-list): add Tolino return receipt print support and improve task action typing
feat(oms-data-access, oms-shared-task-list): add Tolino return receipt print support and improve task action typing

- Add `PrintTolinoReturnReceiptService` to `oms-data-access` for printing Tolino return receipts via office printers, including direct integration with the OMS print API.
- Extend `TaskActionType` to include `receiptItemId` for more precise task identification and action handling.
- Update `return-task-list-item` and `return-task-list` components in `oms-shared-task-list` to support the new Tolino print action, including UI and logic for triggering the print dialog.
- Refactor print-related service and test code to use the new print API signature and improve type safety.
- Add and update unit tests to cover new print flows and ensure correct integration.

Ref: #5121
2025-06-03 22:17:29 +00:00
Nino Righi
bcd3c800b1 Merged PR 1843: feat(libs-shared-filter): show selected filter count on filter button
feat(libs-shared-filter): show selected filter count on filter button

- Display the number of selected filters as a badge on the filter menu button when filters are active.
- Add `.has-selected-filter` styling for visual emphasis when filters are selected.
- Update FilterService to provide a computed `selectedFilterCount` property, counting non-default filter inputs.
- Remove direct icon rendering from the button; icon is now handled by the button component.
- Update tests to mock and assert the new selected filter count logic.

Ref: #5070
2025-06-03 22:15:06 +00:00
Nino Righi
bd7faeb1b5 Merged PR 1842: #5139 minor fix
#5139 minor fix
2025-06-03 22:14:30 +00:00
Lorenz Hilpert
a67375557d Merge branch 'develop' into release/4.0 2025-06-02 11:41:54 +02:00
Lorenz Hilpert
6e7c56fcb9 style(errors): standardize quotation marks in error exports 2025-05-28 21:32:41 +02:00
Lorenz Hilpert
e60d74573c Merged PR 1840: feat(ui-menu): add ui-menu component and related directives
feat(ui-menu): add ui-menu component and related directives

Ref: #5103
2025-05-28 14:06:16 +00:00
Nino Righi
2f04b56f71 Merged PR 1838: feat(oms-return-search): add unit tests for ReturnSearchResultItemComponent a...
feat(oms-return-search): add unit tests for ReturnSearchResultItemComponent and fix address fallback

- Add comprehensive Spectator-based unit tests for ReturnSearchResultItemComponent, covering all computed properties and edge cases.
- Fix address computed property to correctly fall back to shipping address when billing address is missing, ensuring robust display logic.

Ref: #5113
2025-05-26 19:19:14 +00:00
Nino Righi
6e8df1c4ab Merged PR 1839: feat(oms-return-process): apply flex layout to select question description
feat(oms-return-process): apply flex layout to select question description

Update the return-process-select-question component to use the 'flex-1' Tailwind utility class on the description container. This ensures proper flexbox alignment and consistent layout within the parent flex context.

Ref: #5057
2025-05-26 19:19:00 +00:00
Lorenz Hilpert
94e1d729a0 fix(shared/filter): handle setTimeout in FilterMenuButton test
Fix failing test in FilterMenuButtonComponent that checks if rollback is called
when the menu is closed with rollbackOnClose=true. The test was failing because
the component uses setTimeout to schedule the rollback call, but the test was
asserting immediately without waiting for the timeout to complete.

Changes made:
- Modified the test to use jest.useFakeTimers() to control JavaScript timers
- Added jest.runAllTimers() to ensure the setTimeout callback executes
- Added cleanup with jest.useRealTimers() to prevent test pollution
- Made the test function async to properly handle asynchronous behavior

This change ensures that the test properly validates the component's
asynchronous behavior and makes the test suite more reliable.
2025-05-26 21:17:46 +02:00
Lorenz Hilpert
0d202ab97c Merged PR 1837: Fix - Filter Reset und Filter Sync - Removed unused code, logger performance
refactor: improve code formatting and readability in provide-filter.ts and filter-menu components

fix: delay filter rollback on close in FilterMenuButtonComponent

fix: update filter clear button text and method calls in filter-menu.component.html

chore: update package-lock.json to remove unnecessary dev flags and add new dependencies

Ref: #5125, #5076
2025-05-26 15:02:43 +00:00
Nino Righi
c322020c3f Merged PR 1835: feat(oms-data-access, oms-return-summary): unify return details mapping and serialization
Commit 8949c691: feat(oms-data-access, oms-return-summary): unify return details mapping and serialization

- Refactor `returnReceiptValuesMapping` to use `serializeReturnDetails` instead of `returnDetailsMapping` for the `returnDetails` field, ensuring consistent serialization of return details across the OMS data access layer.
- Move the string mapping logic for return details into a dedicated helper (`serializeReturnDetails`), and update all usages and tests accordingly.
- Update `ReturnSummaryItemComponent` to use the new `returnDetailsMapping` helper for rendering human-readable return details in the summary UI.
- Add and update comprehensive unit tests for both helpers and the mapping logic to ensure correct handling of edge cases and maintainability.

Ref: #5124
2025-05-26 14:00:21 +00:00
Nino Righi
bbcf84d357 Merged PR 1836: fix(oms-return-details): use 24-hour format for receipt and order dates
fix(oms-return-details): use 24-hour format for receipt and order dates

Update date formatting in return-details-order-group-data.component.html to use
'HH:mm' (24-hour format) instead of 'hh:mm' (12-hour format) for both receipt
and order dates. This ensures consistency with German locale expectations and
improves clarity for users.

Ref: #5040
2025-05-26 13:59:23 +00:00
Nino Righi
1ddc0a2767 Merged PR 1833: fix(oms-data-access, oms-return-details): remove obsolete 'Software' product...
fix(oms-data-access, oms-return-details): remove obsolete 'Software' product category and related logic

- Removed the 'Software' entry from the ProductCategory constant and its type in `constants.ts`.
- Removed all references to ProductCategory.Software in the category-question registry and eligibility logic.
- Updated the return-details-order-group-item-controls component template to ensure the product category dropdown and checkbox are only rendered when the item is returnable, improving UI consistency and preventing controls from appearing for non-returnable items.
- Added/extended unit tests to verify correct rendering and logic for canReturnReceiptItem and selectability.

This change ensures that only supported product categories are handled in the return process and that UI controls are displayed appropriately based on item eligibility.

Ref: #5100
2025-05-26 08:53:33 +00:00
Nino Righi
1ad6c41c25 Merged PR 1834: fix(oms-return-search): add missing name attribute to mobile sort button
fix(oms-return-search): add missing name attribute to mobile sort button

Adds the `name="isaActionSort"` attribute to the mobile sort button in the return search result component template. This ensures consistent accessibility and testability across platforms, aligning with project standards for semantic markup and E2E test selectors.

Ref: #5110
2025-05-26 08:52:03 +00:00
Nino
72bdf59b05 #5116 Quick Fix 2025-05-23 10:07:51 +02:00
Lorenz Hilpert
0a4eb9bb1c refactor(form-control): improve structure and formatting of component 2025-05-22 19:24:55 +02:00
Lorenz Hilpert
7c9839d93a refactor(scan): improve structure of init method and format code 2025-05-22 19:13:28 +02:00
Lorenz Hilpert
cfb8fb17d6 Merge branch 'develop' of ssh.dev.azure.com:v3/hugendubel/ISA/ISA-Frontend into develop 2025-05-22 19:07:31 +02:00
Lorenz Hilpert
cdd27aeeb0 refactor(print): update print dialog component to use new listbox directives
test(print): add unit tests for PrintService and PrintReceiptsService

feat(print): modify PrintService methods to return promises instead of observables

refactor(oms): rename return-print-receipts.service to print-receipts.service and update references

chore(ui): remove deprecated ui-list library and integrate listbox components

style(ui): add styles for listbox and listbox items

test(ui): implement unit tests for listbox directives

docs(ui): update README and remove unused files related to ui-list
2025-05-22 19:07:00 +02:00
Nino
2e3029daa2 feat(oms-return-details): extract item controls into dedicated component
Refactor the order group item controls into a separate component for improved maintainability and reusability. The new ReturnDetailsOrderGroupItemControlsComponent encapsulates dropdown and checkbox functionality that was previously embedded within the parent component.

This change improves code organization by applying the Single Responsibility Principle, making each component more focused and easier to test. Updated tests ensure proper functionality is maintained after extraction.

Ref: #5116
2025-05-22 17:30:35 +02:00
Nino
ec109f89ef Merge branch 'develop' of https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend into develop 2025-05-22 12:38:51 +02:00
Nino
f11567dd82 feat(oms-data-access): implement dynamic question flow for Tolino returns
Add conditional question flow logic for Tolino device returns based on previous answers.
The implementation creates a dedicated helper for Tolino questions that dynamically
determines the next question based on device power status and defect status.

This allows for a more tailored return process experience where:
- If device powers on and has no defects, show return reason
- If device doesn't power on and has no defects, ask about damage
- Otherwise check if case is damaged

Ref: #4944
2025-05-22 12:38:34 +02:00
Lorenz Hilpert
4bbdb870f8 Merge branch 'feature/5047-5053-Design-und-Funktionsweise-Drucker-Dialog' into develop 2025-05-21 21:11:22 +02:00
Lorenz Hilpert
d9e9e39998 feat: remove uncompleted tasks dialog and replace with confirmation dialog
- Deleted uncompleted tasks dialog component files (HTML, SCSS, TS).
- Updated UncompletedTasksGuard to use new ConfirmationDialogComponent.
- Added ConfirmationDialogComponent for user confirmation with customizable messages.
- Updated dialog component templates to include data attributes for easier testing.
- Removed obsolete unit tests for ReturnReviewComponent and ReturnTaskListComponent.
- Updated unit tests for ReturnSummaryComponent to reflect changes in return process handling.
2025-05-21 20:58:03 +02:00
Lorenz Hilpert
896478b2fb Merge branch 'develop' into feature/5047-5053-Design-und-Funktionsweise-Drucker-Dialog 2025-05-21 14:39:05 +02:00
Lorenz Hilpert
d84bc276d5 chore: update dependencies and add new path mappings
- Updated @nx/js from 20.4.6 to 20.8.1
- Updated angular-eslint from 19.1.0 to 19.2.0
- Added path mapping for @isa/common/print in tsconfig.base.json
- Added path mapping for @isa/ui/dialog in tsconfig.base.json
- Added path mapping for @isa/ui/list in tsconfig.base.json
2025-05-21 14:38:24 +02:00
Nino
ca3433a4e1 feat(oms-return-unit-tests): update return process questions with German labels
This commit makes several important changes to the return process functionality:

- Updates ItemConditionAnswer values from English codes to German user-facing text
  (e.g., 'ovp' → 'Originalverpackt', 'damaged' → 'Geöffnet/Defekt')
- Updates ReturnReasonAnswer values to use German labels
  (e.g., 'dislike' → 'Gefällt nicht/Widerruf', 'wrong_item' → 'Fehllieferung')
- Updates YesNoAnswer values to use German text ('yes'/'no' → 'Ja'/'Nein')
- Updates PackageIncompleteAnswer values to use descriptive German text
- Corrects an expected depth value in unit test to match the current behavior
- Adds comments in test files that need to be re-enabled after the printReceiptsService
  is updated to not use the old ISA app through the legacy ModalService

These changes improve readability and make the return processing system
more consistent with the German UI labels.

Ref: #4944
2025-05-21 11:46:13 +02:00
Nino
d2b3d1bf18 feat(oms-data-access, oms-return-summary): implement returnDetails as object with type safety
This commit improves the handling of return details by:
- Changing returnDetails from string to a typed record object for better type safety
- Adding support for checklist question types in getReturnInfo
- Adding explicit mapping function (returnDetailsMapping) to format details for API
- Updating the return summary component to properly display structured return details
- Making internalActiveReturnProcessQuestions public to support nested questions
- Ensuring eligibility check functions receive proper question objects for validation
- Improving returnProcessQuestionKey naming to use more descriptive German names

Ref: #4944
2025-05-20 17:13:47 +02:00
Nino
08f8686791 Config Feature Url Anpassungen 2025-05-19 13:56:42 +02:00
Nino
4131255a1b feat(oms-return-details): add quantity change support for return items
This update introduces quantity selection and change handling for return items in the return details feature. The following enhancements were made:

- Added a quantity dropdown to each return item, allowing users to select the quantity to return (when more than one is available).
- Implemented the `changeQuantity` output in `ReturnDetailsOrderGroup
2025-05-16 17:27:01 +02:00
Nino
874453f74f feat(oms-data-access, oms-return-details, oms-return-process): improve canReturn logic and UX for return eligibility
- Refactored `ReturnCanReturnService` to use a type guard for input discrimination and improved error handling, removing logger side effects for stricter error propagation.
- Updated `ReturnDetailsService` to delegate canReturn checks to `ReturnCanReturnService` for category-based eligibility, ensuring type safety and code reuse.
- Enhanced `ReturnDetailsOrderGroupItemComponent`:
  - Added spinner feedback when canReturn is loading.
  - Used endpoint result for eligibility and message display, falling back to item actions if necessary.
  - Improved state management for dropdowns and selection, with robust error logging.
- Updated `ReturnDetailsOrderGroupComponent` to only allow selection of items with known categories and eligible for return.
- Improved `ReturnProcessItemComponent`:
  - Added loading spinner for canReturn backend checks.
  - Used endpoint result for eligibility and messaging.
  - Added robust error logging and effect-based async state management.
- Updated `ReturnProcessComponent` to check canReturn for all processes asynchronously, with error handling and correct signal updates.
- Improved templates to show loading indicators and correct eligibility messages based on backend and frontend checks.

Ref: #5088
2025-05-16 15:18:45 +02:00
Nino
8077fe949f Config Feature Print Update 2025-05-16 11:39:48 +02:00
Nino
39bdcd4da6 feat(oms-data-access, oms-return-process): extract canReturn logic to dedicated service and unify question helpers
- Move canReturn logic from ReturnProcessService and ReturnProcessItemComponent into a new ReturnCanReturnService for improved separation of concerns and testability.
- Add getReturnProcessQuestions and returnReceiptValuesMapping helpers to centralize question and payload mapping logic.
- Refactor ReturnProcessService to use new helpers and remove obsolete methods.
- Update ReturnProcessItemComponent and ReturnProcessComponent to use ReturnCanReturnService for backend eligibility checks.
- Ensure summary navigation is only enabled when all items are eligible for return both frontend and backend.
- Update public API exports for new helpers and service.

Ref: #5089, #5088
2025-05-15 17:49:42 +02:00
Nino
55b95e571c Fix Unit Test Error - Uncommented Unit Tests in Details because of multiple errors 2025-05-14 17:07:00 +02:00
Nino
4adf947b90 feat(oms-return-details, oms-return-process, oms-data-access): implement product category management
Add dropdown component for selecting product categories in the return details UI.
Move product category selection from return process to return details screen,
allowing users to set categories before starting the return process.

This change:
- Moves availableCategories method from ReturnProcessService to ReturnDetailsService
- Adds new updateProductCategoryForItem method to ReturnDetailsStore
- Updates the OrderGroupItem component with dropdown for category selection
- Removes the category dropdown from ReturnProcessQuestions component

Ref: #5089
2025-05-14 16:52:24 +02:00
Lorenz Hilpert
05e257b922 Merge branch 'develop' into release/4.0 2025-05-13 18:52:00 +02:00
Lorenz Hilpert
efdfa126e7 fix(config): update configMap mountPath for consistency across environments 2025-05-13 18:51:31 +02:00
Lorenz Hilpert
d7d61915fa Merge branch 'develop' into release/4.0 2025-05-13 18:36:09 +02:00
Nino
efd28bcc06 Merge branch 'develop' of https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend into develop 2025-05-13 16:45:30 +02:00
Nino
05986ab9f4 feat(oms-return-process, oms-return-details, oms-data-access): implement return process workflow
Add new components and services to support the end-to-end return process
workflow. This includes return creation, validation, item selection, and
submission features across the specified modules.

Ref: #4978
2025-05-13 16:44:53 +02:00
Lorenz Hilpert
6fc65c4158 fix(config): update configMap mountPath for consistency 2025-05-13 12:13:12 +02:00
Lorenz Hilpert
e3395c8772 ci: update artifact path for ISAClientConfigs 2025-05-13 11:51:35 +02:00
Lorenz Hilpert
ec67724b66 ci: update artifact path for ISAClientConfigs 2025-05-13 11:48:23 +02:00
Lorenz Hilpert
911187bc08 update(config): update url path for APIs Checkout, Crm, Oms 2025-05-13 10:53:55 +02:00
Lorenz Hilpert
9a55cd8642 Merge branch 'develop' of ssh.dev.azure.com:v3/hugendubel/ISA/ISA-Frontend into develop 2025-05-12 16:29:33 +02:00
Lorenz Hilpert
4815963565 fix(checkbox): ensure checkbox input dimensions are consistently applied
Ref: #5077
2025-05-12 16:28:56 +02:00
Nino
0d4e5c6bf9 Merge branch 'develop' of https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend into develop 2025-05-12 16:13:11 +02:00
Nino
e60f4db18a fix(oms-data-access): move category to top level in return receipt payload
Update ReturnReceiptValuesSchema to accept category as a direct property
instead of nested in receiptItem.data.features. Simplifies the schema by
removing the unnecessary ReceiptItemDataSchema and modifying how the
category is accessed in completeReturnProcess.

Ref: #5083
2025-05-12 16:11:20 +02:00
Lorenz Hilpert
b0de88301f Merge branch 'develop' of ssh.dev.azure.com:v3/hugendubel/ISA/ISA-Frontend into develop 2025-05-12 16:05:39 +02:00
Lorenz Hilpert
6868c6df75 refactor(return-details): reorganize button placement for better layout 2025-05-12 16:05:08 +02:00
Nino
f2ca829b36 OMS Api Update 2025-05-12 16:01:39 +02:00
Nino
190d0786e0 fix(oms-data-access): unify electronic and nonbook item condition labels
Harmonize electronic device and nonbook item condition labels to consistently
use "Geöffnet/Defekt" instead of "Geöffnet/Beschädigt" or "Beschädigt/Fehldruck".
Also remove redundant defect verification question for electronic devices since
the condition label already indicates this state.

Additionally, add product features to receipt item data in return receipts to
ensure proper product information is available for returns processing.

Ref: #5083
2025-05-12 15:10:47 +02:00
Nino
0ec1457ffc fix(oms-data-access): simplify return receipt values schema
Replace separate type extension with direct schema definition by adding
otherProduct field to the ReturnReceiptValuesSchema. This eliminates
redundant type definition and improves type safety by ensuring all
fields are properly validated through the Zod schema.

Ref: #5082
2025-05-12 14:32:59 +02:00
Nino
a978f94519 feat(oms-task-list): simplify filter logic
Simplify the task list filter logic by using a cleaner object literal approach
instead of nested properties. This improves readability and maintainability of
the filtering conditions.

Ref: #5072
2025-05-12 14:03:46 +02:00
Nino
71ee7ea842 fix(oms-data-access), fix(return-process), fix(return-summary): filter out ineligible items from return process submission
This commit makes several important changes to ensure only eligible items
are processed during return submission:

1. ReturnProcessService now filters out ineligible items before submission
2. Fixed canContinueToSummary logic to check if ANY item is eligible (not ALL)
3. Added conditional rendering to return-summary-item to display error state
   for ineligible items

These changes prevent system errors when attempting to process returns
that don't meet eligibility criteria while still allowing partial returns
when at least one item is eligible.

Ref: #5084
2025-05-12 13:43:49 +02:00
Nino
d0220b6246 Merge branch 'develop' into release/4.0 2025-05-09 17:26:47 +02:00
Nino
a8c5e8feb5 feat(oms-return-process): improve product search error handling and feedback
Enhance the ReturnProcessProductQuestion component with better error handling:
- Add proper display of "no product found" message when search returns no results
- Add validation feedback for invalid EAN inputs
- Refactor status handling from a simple boolean to a more descriptive object
- Remove unnecessary complete handler in favor of explicit state management

Ref: #4979
2025-05-09 17:25:37 +02:00
Nino
1b9e70141b feat(oms-data-access): implement return eligibility for electronic devices
Add new helper function isElektronischeGeraeteEligibleForReturn to determine
if electronic devices are eligible for returns based on item condition and
receipt date. Update ReturnProcessService to use this helper for electronic
device category.

This implementation checks if devices in original packaging with receipts
older than 100 days are not eligible for return.

Ref: #4978
2025-05-09 15:22:37 +02:00
Nino
bdc711926c feat(oms-return-details): improve boolean coercion for return eligibility check
Replace direct Boolean() casting with Angular's coerceBooleanProperty to ensure consistent
boolean type coercion when determining if items can be returned. This improves type safety
and provides more predictable behavior for string-based boolean values in item actions.

Ref: #5067
2025-05-09 14:28:51 +02:00
Nino
74531a7ddc Small Fix ElibigleItems 2025-05-09 14:12:25 +02:00
Nino
32336ba5b4 Update index file return data-access 2025-05-09 12:13:25 +02:00
Nino
1f26d5285b Merge branch 'develop' into release/4.0 2025-05-09 12:12:19 +02:00
Nino
202ceb0b22 Unit Test Quick Fix 2025-05-08 18:38:44 +02:00
Nino
693d1af51b feat(oms-data-access, oms-task-list): implement query token filtering for task lists
Add support for filter parameters when querying receipt item tasks, allowing
for more refined control over which tasks are displayed. Update the service,
store, and component to use this filtering capability.

- Modify ReturnTaskListService to accept queryToken parameter
- Update ReturnTaskListStore to pass the queryToken to the service
- Enhance ReturnTaskListComponent to construct appropriate filter based on appearance
- Fix spelling of "Non-Book" in ProductCategory constant

Ref: #5072
2025-05-08 18:07:59 +02:00
Nino
78880fb2f4 Swagger API Update 2025-05-08 17:59:50 +02:00
Nino
d887c4e8fe fix(oms-data-access), fix(oms-return-process): implement return eligibility logic for specific product types
Add helper functions to determine product return eligibility based on item condition
and defect status. Specifically implemented return logic for TonDatentraeger products
where damaged but non-defective items aren't eligible for return. Also added export
for the eligibility helper in the index file.

Update the ReturnProcessComponent to check eligibility status before allowing
continuation to summary, ensuring only eligible items proceed in the return workflow.

Ref: #5075
2025-05-08 17:45:58 +02:00
Nino
0fe71fe9d8 fix(oms-data-access), fix(return-process): handle unknown product category in return process
Add support for 'unknown' product category state in ReturnProcessService
and ReturnProcessQuestionsComponent to ensure proper handling of return
processes without a defined product category. This correctly returns
EligibleForReturnState.Unknown and displays the product category dropdown
when needed.

Ref: #5073 #4943
2025-05-08 16:09:01 +02:00
Nino
b4bb5ab979 fix(oms-data-access): make most DeliveredItem fields optional
Update ReturnProcessQuestionSchema for DeliveredItem to make contributors,
format, formatDetail, volume, and manufacturer fields optional instead of
required. This ensures compatibility with the actual data structure received
from the API and prevents validation errors for incomplete product data.

Ref: #5068
2025-05-07 17:11:17 +02:00
Nino
bd19ec8489 feat(oms-task-list): improve task filtering and sorting logic
- Filter completed tasks to show only those completed today in review view
- Sort task list to show open tasks before completed tasks
- Add date-fns functions (isSameDay, parseISO) to handle date comparison
- Refactor filtering logic for better readability and maintainability

Ref: #4942
2025-05-07 15:58:27 +02:00
Nino
2bbf3d3739 fix(oms-return): centralize name formatting logic
Extracted common name formatting code into a reusable utility function to ensure
consistent display of customer/organization names across return feature components.
This improves maintainability and ensures consistent presentation throughout the
application.

Ref: #5066
2025-05-07 12:30:16 +02:00
Nino
e49d084439 fix(oms-data-access): make catalogProductNumber optional in DeliveredItem schema
Make the catalogProductNumber field optional in the ReturnProcessQuestionSchema for DeliveredItem
to match actual API response data structure and prevent validation errors when processing items
without this field.

Ref: #5068
2025-05-07 12:12:01 +02:00
Nino
5f31842afa feat(oms-task-list, oms-data-access): rename and enhance return review components to task list
Rename and refactor return review components to task list throughout the codebase:
- Rename ReturnReviewService to ReturnTaskListService with improved error handling
- Rename ReturnReviewStore to ReturnTaskListStore and add logging
- Update TaskActionType interface with new updateTo and actions properties
- Enhance ReturnTaskListItemComponent to support dynamic task actions
- Update templates to use new action structure and naming

The refactoring improves code organization and readability while enhancing the
task list functionality with better action handling and error management.

Ref: #4942 #4973
2025-05-06 17:48:58 +02:00
Nino
81bb8ba72d feat(oms-return-review): add uncompleted tasks dialog and guard
Add dialog component to warn users when they attempt to leave the return review
process with uncompleted tasks. This includes:
- Creating UncompletedTasksDialogComponent with confirmation/cancellation options
- Implementing CanDeactivate guard to check for uncompleted tasks
- Adding guard to return review routes configuration

The dialog gives users the choice to either go back and complete tasks or
leave despite having uncompleted tasks.

Ref: #4976
2025-05-06 17:46:34 +02:00
Nino
68ea22f3d2 OMS Swagger API Update 2025-05-06 13:15:19 +02:00
Nino
7edbe11c65 feat(oms-task-list): implement task action types and specialized UI handling
Enhance the ReturnTaskListComponent and ReturnTaskListItemComponent to:
- Use properly typed TaskActionTypes enum (OK, NOK, PRINT, UNKNOWN) instead of string literals
- Add specialized UI components for different action types
- Implement conditional rendering for task actions based on type
- Improve styling for different task types
- Filter out completed tasks in main view

feat(oms-data-access): add Zod schema validation for return receipts

- Add ReturnReceiptValuesSchema for validation of API payloads
- Implement proper type safety for task action types
- Use schema validation in ReturnProcessService before API calls

Ref: #4942
2025-05-05 17:45:48 +02:00
Nino
82d991fcbc feat(shared-task-list), feat(return-search-main), feat(return-review): create shared task list component and refactor return views
Implement new shared task list component to replace duplicate task list functionality across the application.
Update return review and search views to use the new shared component.

- Create new @isa/oms/shared/task-list library
- Extract task list functionality from return review component
- Add task list to return search main view
- Handle task completion actions through the shared component
- Fix typo in return review success message

Ref: #4942, #4972, #4974
2025-04-30 17:34:24 +02:00
Nino
0d1a65ed4a feat(oms-data-access), feat(return-review): implement task completion in return review
Added updateTaskListItem method to ReturnReviewStore to handle updating
individual task list items. Implemented the UI logic to show/hide the
"Mark as done" button based on completion status and connected the
completeTask method to update the store with the returned result.

Ref: #4942
2025-04-30 14:56:34 +02:00
Nino
c98cbd73b1 feat(oms-data-acess), feat(return-review): implement return review functionality
Add new ReturnReview library with core components and service structure:
- Create ReturnReviewService and ReturnReviewStore for task management
- Extract PrintReceipts functionality into dedicated service
- Implement review page components with task listing and completion
- Add support for receipt item tasks data model
- Update error handling with consistent error types
- Add comprehensive JSDoc documentation throughout

The implementation provides the foundation for the return review workflow,
including task listing and completion functionality.

Ref: #4942
2025-04-29 17:49:11 +02:00
Nino
4c79f2d127 feat(generated-swagger-oms-api): update OMS Swagger API models and services
Add receipt item task-related models and interfaces to support return review
functionality. Add new fields to ReceiptDTO and update ReturnProcessService

Includes:
- New task list models for receipt items
- Receipt service endpoint updates
- Field additions to ReceiptDTO model

Ref: #4942
2025-04-29 14:12:01 +02:00
Nino
61d0030342 feat(return-review): create return review library and connect to routing
Initialize the return-review feature library with basic component structure
and connect it to the existing routing system in both return-process and
return-summary features. Update navigation in ReturnSummaryComponent to
redirect to the review page after successful return completion.

Ref: #4942
2025-04-29 14:05:11 +02:00
Nino
86ed379b38 Merge branch 'develop' of https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend into develop 2025-04-28 17:38:18 +02:00
Nino Righi
eba9cec16e Merged PR 1832: #4941 #5049 #5050
#4941 #5049 #5050
2025-04-28 15:36:03 +00:00
Nino
651c65edc7 Merge branch 'develop' of https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend into develop 2025-04-28 15:24:12 +02:00
Lorenz Hilpert
809a6e38b3 fix(tests): update initialization test to expect service to be truthy 2025-04-25 20:00:10 +02:00
Lorenz Hilpert
e1ce520711 test(return-process): update initialization test to expect service to be falsy 2025-04-25 19:54:17 +02:00
Lorenz Hilpert
81995e8863 chore(pre-push): remove pre-push test script 2025-04-25 19:53:22 +02:00
Lorenz Hilpert
ae89f1e2f8 chore: update devDependencies and add pretest script
- Added a pretest script to clean up test results using trash-cli.
- Updated @angular-devkit/build-angular from 19.2.6 to ^19.2.9.
- Updated @nx/angular from 20.4.6 to ^20.8.1.
2025-04-25 19:43:36 +02:00
Lorenz Hilpert
75c6170be4 ci: update pre-push hook to run tests instead of CI 2025-04-25 19:26:54 +02:00
Lorenz Hilpert
5db3521a0e feat(tests): add jest-junit reporter for Azure DevOps integration 2025-04-25 19:15:29 +02:00
Lorenz Hilpert
a48ff29051 style(guidelines): change function export style to arrow functions
Replace function declarations with arrow function expressions assigned to constants
for better testability when mocking functions during unit tests.

This makes the codebase more consistent and addresses issues with function mocking.
2025-04-25 17:09:40 +02:00
Lorenz Hilpert
337ef46acb Updated .gitignore and Dockerfile for improved build process.
- 🛠️ **Refactor**: Changed npm install command in Dockerfile for better script handling
- 🗑️ **Chore**: Removed junit.xml from repository
- 🎨 **Style**: Added junit.xml to .gitignore for cleaner project structure
- 🎨 **Style**: Ensured newline at end of file in .gitignore
2025-04-25 12:06:15 +02:00
Lorenz Hilpert
c0e8e69f9f Updated Jest preset to enhance coverage collection configuration.
- ⚙️ **Config**: Added additional files to coverage exclusion list
2025-04-25 11:11:07 +02:00
Lorenz Hilpert
2046212581 Updated CI configuration and Jest preset for improved coverage reporting.
- ⚙️ **Config**: Modified CI command to include coverage in package.json
- ⚙️ **Config**: Updated summary file location in azure-pipelines.yml
- ⚙️ **Config**: Enhanced Jest preset to configure coverage reporters
2025-04-25 10:59:14 +02:00
Lorenz Hilpert
57968bd061 Updated Node.js version in Dockerfile for improved compatibility.
- ⚙️ **Config**: Changed base image from node:18 to node:22
2025-04-25 10:44:13 +02:00
Lorenz Hilpert
22c0a7d5d9 feat(e2e): add data attributes for improved test stability
Add data-what and data-which attributes to key UI elements:
- Add back button attributes to return details and process components
- Add filter button attributes to the filter menu component
- Add sort button attributes for both desktop and mobile views
- Add result count element attributes for better selection
- Add attributes to search result items for identification
- Add attributes to loading spinners for state verification

These attributes improve E2E test stability by providing reliable selectors
that are not tied to styling or DOM structure changes.

Ref: #5052
2025-04-24 21:39:23 +02:00
Nino
fa5ad7a561 Instructions Update 2025-04-22 12:23:39 +02:00
Lorenz Hilpert
39d101d456 Enhanced logging functionality with improved context handling and documentation.
-  **Feature**: Added support for hierarchical logger context
- 🛠️ **Refactor**: Updated logging methods to use LoggerContext
- 📚 **Docs**: Improved documentation for logger methods and context
2025-04-16 15:35:52 +02:00
Lorenz Hilpert
c9b5af7282 Added error logging guidelines and best practices to code style documentation.
- 📚 **Docs**: Introduced error logging section with guidelines
-  **Feature**: Added context-aware logging examples
- 🛠️ **Refactor**: Improved structure for error handling practices
2025-04-16 14:12:26 +02:00
Lorenz Hilpert
2efc5c3b0d Enhanced logging library with new features and improved performance.
-  **Feature**: Added global context support for logging configuration
- 🛠️ **Refactor**: Improved error handling in logging service
- 🚀 **Performance**: Optimized log level checks and error resilience
- 📚 **Docs**: Updated README with detailed logging levels and usage examples
2025-04-16 14:07:56 +02:00
Lorenz Hilpert
e0edd7887e Merge branch 'feature/core-logger-lib' into develop 2025-04-16 13:20:27 +02:00
Lorenz Hilpert
d615efd806 refactor: remove validation functions and tests for return processes
- Deleted validation functions for electronic devices, nonbook items, and ton/datentraeger.
- Removed associated test files for these validations.
- Updated question definitions to use new constants for item conditions and return reasons.
- Refactored return process service to utilize schema validation instead of custom validators.
- Adjusted HTML templates to reflect changes in eligibility state handling.
2025-04-15 21:39:50 +02:00
Lorenz Hilpert
a608d77ab5 Enhanced Checkbox and Checklist components with detailed documentation.
-  **Feature**: Added customizable appearance options for CheckboxComponent
-  **Feature**: Implemented ChecklistComponent for managing groups of checkboxes
- 📚 **Docs**: Added comprehensive documentation for Checkbox and Checklist components
- 🧪 **Test**: Created unit tests for ChecklistValueDirective and ChecklistComponent
2025-04-15 18:38:55 +02:00
Lorenz Hilpert
93665cf35d Refactor FilterService and FilterMenuButtonComponent to remove logging. 2025-04-11 15:00:13 +02:00
Lorenz Hilpert
a766534b97 feat(logging): implement core logging library with structured logging service
- Added Core Logging library providing centralized logging functionality.
- Implemented LoggingService with multiple log levels and configurable sinks.
- Created ConsoleLogSink for logging to the browser console.
- Introduced LoggerApi for context-aware logging.
- Added support for custom sinks and logging configuration during app initialization.
- Enhanced FilterService and FilterMenuButtonComponent with logging capabilities.
- Updated ESLint and Jest configurations for the new logging library.
- Documented the logging library API and usage in README.
2025-04-11 14:58:34 +02:00
Michael Auer
be0bff0535 Cherry Pick: PR 1824: ISA-Frontend - Expliziter Pfad für Traefik IngressRoute
(cherry picked from commit c9b2762bbc)
2025-02-28 09:36:06 +01:00
Lorenz Hilpert
cb7391e66f Update version numbers in azure-pipelines.yml to 4.0 2025-02-10 10:43:23 +01:00
745 changed files with 25707 additions and 6139 deletions

View File

@@ -1,36 +1,86 @@
# Commit Message Instructions
# Commit Message Instructions (Conventional Commits)
Commit messages should follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/). This provides a standardized format for commit messages, making it easier to understand changes, automate changelog generation, and trigger build/publish processes.
## Format
Each commit message should follow this structure:
1. **Short Summary**: A brief summary of the changes (max 72 characters).
2. **List of Changes**: A detailed list of changes with icons to indicate the type of change.
---
### Example
The commit message structure is as follows:
```
Added a new module to handle user authentication, including login and registration.
<type>[optional scope]: <description>
- ✨ **Feature**: Implemented user login functionality
- 🐛 **Fix**: Resolved session timeout issue
- 🛠️ **Refactor**: Improved error handling in auth service
- 🧪 **Test**: Added unit tests for login component
[optional body]
[optional footer(s)]
```
---
## Icons for Change Types
### Components
- **Feature**: New features or functionality
- 🐛 **Fix**: Bug fixes
- 🛠️ **Refactor**: Code improvements without changing functionality
- 🧪 **Test**: Adding or updating tests
- 📚 **Docs**: Documentation updates
- 🗑️ **Chore**: Maintenance tasks (e.g., dependency updates)
- 🚀 **Performance**: Performance improvements
- 🎨 **Style**: Code style changes (e.g., formatting)
- 🔒 **Security**: Security-related changes
- ⚙️ **Config**: Configuration changes
1. **Type**: Indicates the kind of change introduced by the commit. Must be one of the allowed types (see below).
2. **Scope (Optional)**: A noun describing the section of the codebase affected by the change (e.g., `auth`, `ui`, `build`). Enclosed in parentheses.
3. **Description**: A concise summary of the change in the imperative, present tense (e.g., "add login feature", not "added login feature" or "adds login feature"). Starts with a lowercase letter and should not end with a period. Max 72 characters recommended for the entire header line (`<type>[optional scope]: <description>`).
4. **Body (Optional)**: A more detailed explanation of the changes. Use the imperative, present tense. Explain the _what_ and _why_ vs. _how_. Separate from the description by a blank line. Wrap lines at 72 characters.
5. **Footer(s) (Optional)**: Contains additional metadata. Common footers include:
- `BREAKING CHANGE:` followed by a description of the breaking change. A `!` can also be appended to the type/scope (`feat!:`) to indicate a breaking change.
- Issue references (e.g., `Refs: #123`, `Closes: #456`). Separate from the body by a blank line.
---
### Allowed Types
- **feat**: A new feature for the user.
- **fix**: A bug fix for the user.
- **build**: Changes that affect the build system or external dependencies (e.g., gulp, broccoli, npm).
- **chore**: Other changes that don't modify src or test files (e.g., updating dependencies, build tasks).
- **ci**: Changes to CI configuration files and scripts (e.g., Travis, Circle, BrowserStack, SauceLabs).
- **docs**: Documentation only changes.
- **perf**: A code change that improves performance.
- **refactor**: A code change that neither fixes a bug nor adds a feature.
- **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc).
- **test**: Adding missing tests or correcting existing tests.
---
### Examples
**Commit with description only:**
```
fix: correct minor typos in code
```
**Commit with scope:**
```
feat(lang): add polish language
```
**Commit with body and breaking change footer:**
```
refactor: drop support for Node 6
The new implementation relies on async/await and other features
introduced in Node 8+.
BREAKING CHANGE: refactor to use JavaScript features not available in Node 6.
```
**Commit with scope, body, and issue footer:**
```
docs(readme): improve installation instructions
Provide clearer steps for setting up the development environment.
Add links to prerequisite tools.
Closes: #12
```
**Commit with `!` for breaking change:**
```
feat(api)!: send an email to the customer when a product is shipped
```

View File

@@ -1,17 +1,21 @@
# Spark Instructions
# Mentor Instructions
## Introduction
You are Spark, a mentor designed to help me with coding, preview my work, and assist me in improving by pointing out areas for enhancement.
You are Mentor, an AI assistant focused on ensuring code quality, strict adherence to best practices, and development efficiency. **Your core function is to enforce the coding standards and guidelines established in this workspace.** Your goal is to help me produce professional, maintainable, and high-performing code.
## Tone and Personality
You are a mentor with a dual approach: when I make a mistake or my work needs improvement, you adopt a strict and technical tone to clearly explain whats wrong and how to fix it. In all other cases, you are casual and friendly, like a supportive coding buddy, keeping the vibe light and encouraging.
Maintain a professional, objective, and direct tone consistently:
- **Guideline Enforcement & Error Correction:** When code deviates from guidelines or contains errors, provide precise, technical feedback. Clearly state the issue, cite the relevant guideline or principle, and explain the required correction for optimal, maintainable results.
- **Technical Consultation:** In discussions about architecture, best practices, or complex coding inquiries, remain formal and analytical. Provide clear, well-reasoned explanations and recommendations grounded in industry standards and the project's specific guidelines.
## Behavioral Guidelines
- Focus on constructive feedback; avoid simply rewriting my code unless I ask for it.
- If my question or code is unclear, ask me for clarification or more details.
- Do not discourage me; always frame suggestions as opportunities for growth.
- Avoid giving generic answers—tailor your advice to my specific code or problem.
- Keep my preferences in mind: prioritize Type safety, follow Clean Code principles and emphasize good documentation.
- **Actionable Feedback:** Prioritize constructive, actionable feedback aimed at improving code quality, maintainability, and adherence to standards. Avoid rewriting code; focus on explaining the necessary changes and their rationale based on guidelines.
- **Strict Guideline Adherence:** Base _all_ feedback, suggestions, and explanations rigorously on the guidelines documented within this workspace. Cite specific rules and principles consistently.
- **Demand Clarity:** If a query or code snippet lacks sufficient detail for a thorough, professional analysis, request clarification.
- **Professional Framing:** Frame all feedback objectively, focusing on the technical aspects and the importance of meeting project standards for long-term success.
- **Context-Specific Expertise:** Provide specific, context-aware advice tailored to the code or problem, always within the framework of our established guidelines.
- **Enforce Standards:** Actively enforce project preferences for Type safety, Clean Code principles, and thorough documentation, as mandated by the workspace guidelines.

40
.github/instructions/nx.instructions.md vendored Normal file
View File

@@ -0,0 +1,40 @@
---
applyTo: '**'
---
// This file is automatically generated by Nx Console
You are in an nx workspace using Nx 21.2.1 and npm as the package manager.
You have access to the Nx MCP server and the tools it provides. Use them. Follow these guidelines in order to best help the user:
# General Guidelines
- When answering questions, use the nx_workspace tool first to gain an understanding of the workspace architecture
- For questions around nx configuration, best practices or if you're unsure, use the nx_docs tool to get relevant, up-to-date docs!! Always use this instead of assuming things about nx configuration
- If the user needs help with an Nx configuration or project graph error, use the 'nx_workspace' tool to get any errors
- To help answer questions about the workspace structure or simply help with demonstrating how tasks depend on each other, use the 'nx_visualize_graph' tool
# Generation Guidelines
If the user wants to generate something, use the following flow:
- learn about the nx workspace and any specifics the user needs by using the 'nx_workspace' tool and the 'nx_project_details' tool if applicable
- get the available generators using the 'nx_generators' tool
- decide which generator to use. If no generators seem relevant, check the 'nx_available_plugins' tool to see if the user could install a plugin to help them
- get generator details using the 'nx_generator_schema' tool
- you may use the 'nx_docs' tool to learn more about a specific generator or technology if you're unsure
- decide which options to provide in order to best complete the user's request. Don't make any assumptions and keep the options minimalistic
- open the generator UI using the 'nx_open_generate_ui' tool
- wait for the user to finish the generator
- read the generator log file using the 'nx_read_generator_log' tool
- use the information provided in the log file to answer the user's question or continue with what they were doing
# Running Tasks Guidelines
If the user wants help with tasks or commands (which include keywords like "test", "build", "lint", or other similar actions), use the following flow:
- Use the 'nx_current_running_tasks_details' tool to get the list of tasks (this can include tasks that were completed, stopped or failed).
- If there are any tasks, ask the user if they would like help with a specific task then use the 'nx_current_running_task_output' tool to get the terminal output for that task/command
- Use the terminal output from 'nx_current_running_task_output' to see what's wrong and help the user fix their problem. Use the appropriate tools if necessary
- If the user would like to rerun the task or command, always use `nx run <taskId>` to rerun in the terminal. This will ensure that the task will run in the nx context and will be run the same way it originally executed
- If the task was marked as "continuous" do not offer to rerun the task. This task is already running and the user can see the output in the terminal. You can use 'nx_current_running_task_output' to get the output of the task to verify the output.

View File

@@ -36,8 +36,9 @@ When conducting a code review, follow these steps to ensure a thorough and const
## Additional Informations
- Treat missing tests and JSDocs as warnings
- Tread missing unit test as warnings
- Missing tests and JSDocs are minor issues
- Missing unit test are minor issues
- Missing End-to-End (E2E) Testing Attributes (`data-what`, `data-which`) are warnings
### Review Template

View File

@@ -1,10 +1,12 @@
# Testing Instructions
## Framework and Tools
- Use **Jest** as the testing framework.
- For unit tests, utilize **Spectator** to simplify Angular component testing.
## Guidelines
1. **Error Case Testing**: Ensure all edge cases and error scenarios are thoroughly tested.
2. **Arrange-Act-Assert Pattern**: Follow the Arrange-Act-Assert pattern for structuring your tests:
- **Arrange**: Set up the testing environment and initialize required variables.
@@ -12,12 +14,14 @@
- **Assert**: Verify the expected outcomes.
## Best Practices
- Write clear and descriptive test names.
- Ensure tests are isolated and do not depend on each other.
- Mock external dependencies to avoid side effects.
- Aim for high code coverage without compromising test quality.
## Example Test Structure
```typescript
// Example using Jest and Spectator
import { createComponentFactory, Spectator } from '@ngneat/spectator';
@@ -57,5 +61,6 @@ describe('MyComponent', () => {
```
## Additional Resources
- [Jest Documentation](https://jestjs.io/docs/getting-started)
- [Spectator Documentation](https://ngneat.github.io/spectator/)
- [Spectator Documentation](https://ngneat.github.io/spectator/)

6
.gitignore vendored
View File

@@ -1,6 +1,7 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
.matomo
junit.xml
# compiled output
/dist
@@ -60,4 +61,7 @@ libs/swagger/src/lib/*
.angular
storybook-static
storybook-static
.cursor\rules\nx-rules.mdc
.github\instructions\nx.instructions.md

View File

@@ -1 +0,0 @@
npm run ci

19
.vscode/settings.json vendored
View File

@@ -19,7 +19,10 @@
"exportall.config.folderListener": [
"/libs/oms/data-access/src/lib/models",
"/libs/oms/data-access/src/lib/schemas",
"/libs/catalogue/data-access/src/lib/models"
"/libs/catalogue/data-access/src/lib/models",
"/libs/common/data-access/src/lib/models",
"/libs/common/data-access/src/lib/error",
"/libs/oms/data-access/src/lib/errors/return-process"
],
"github.copilot.chat.commitMessageGeneration.instructions": [
{
@@ -28,13 +31,7 @@
],
"github.copilot.chat.codeGeneration.instructions": [
{
"file": ".github/copilot-instructions.md"
},
{
"file": ".github/review-instructions.md"
},
{
"file": ".github/testing-instructions.md"
"file": ".vscode/llms/angular.txt"
},
{
"file": "docs/tech-stack.md"
@@ -53,9 +50,6 @@
}
],
"github.copilot.chat.testGeneration.instructions": [
{
"file": ".github/copilot-instructions.md"
},
{
"file": ".github/testing-instructions.md"
},
@@ -92,4 +86,7 @@
"file": "docs/guidelines/testing.md"
}
],
"nxConsole.generateAiAgentRules": true,
"chat.mcp.enabled": true,
"chat.mcp.discovery.enabled": true
}

View File

@@ -1,5 +1,5 @@
#stage 1
FROM node:18 as base
FROM node:22 as base
ARG IS_PRODUCTION=false
ARG SEMVERSION=1.0.0
ARG BuildUniqueID
@@ -8,7 +8,7 @@ WORKDIR /app
COPY . .
RUN umask 0022
RUN npm version ${SEMVERSION}
RUN npm install --always-auth=false
RUN npm install --foreground-scripts
RUN if [ "${IS_PRODUCTION}" = "true" ] ; then npm run-script build-prod ; else npm run-script build ; fi
# stage final

View File

@@ -1,5 +1,9 @@
import { inject, Injectable } from '@angular/core';
import { PromptModalData, UiModalService, UiPromptModalComponent } from '@ui/modal';
import {
PromptModalData,
UiModalService,
UiPromptModalComponent,
} from '@ui/modal';
import { Observable } from 'rxjs';
import { ScanAdapter } from './scan-adapter';
import { Config } from '@core/config';
@@ -14,9 +18,14 @@ export class DevScanAdapter implements ScanAdapter {
private _config = inject(Config);
async init(): Promise<boolean> {
return new Promise((resolve, reject) => {
resolve(coerceBooleanProperty(this._config.get('dev-scanner')));
});
const enabled = localStorage.getItem('dev_scan_adapter_enabled') === 'true';
if (enabled) {
return new Promise((resolve, reject) => {
resolve(coerceBooleanProperty(this._config.get('dev-scanner')));
});
}
return false;
}
scan(): Observable<string> {
@@ -25,7 +34,8 @@ export class DevScanAdapter implements ScanAdapter {
content: UiPromptModalComponent,
title: 'Scannen',
data: {
message: 'Diese Eingabemaske dient nur zu Entwicklungs und Testzwecken.',
message:
'Diese Eingabemaske dient nur zu Entwicklungs und Testzwecken.',
placeholder: 'Scan Code',
confirmText: 'weiter',
cancelText: 'abbrechen',

View File

@@ -27,7 +27,10 @@ export class ScanditScanAdapter implements ScanAdapter {
) {}
async init(): Promise<boolean> {
if (this._environmentService.isTablet()) {
const enabled =
localStorage.getItem('scandit_scan_adapter_enabled') === 'true';
if (enabled || this._environmentService.isTablet()) {
try {
await configure({
licenseKey: this._config.get('licence.scandit'),
@@ -88,7 +91,11 @@ export class ScanditScanAdapter implements ScanAdapter {
createOverlay() {
const overlay = this._overlay.create({
positionStrategy: this._overlay.position().global().centerHorizontally().centerVertically(),
positionStrategy: this._overlay
.position()
.global()
.centerHorizontally()
.centerVertically(),
hasBackdrop: true,
});

View File

@@ -1,4 +1,8 @@
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import {
HTTP_INTERCEPTORS,
provideHttpClient,
withInterceptorsFromDi,
} from '@angular/common/http';
import {
ErrorHandler,
Injector,
@@ -24,7 +28,10 @@ import { environment } from '../environments/environment';
import { AppSwaggerModule } from './app-swagger.module';
import { AppDomainModule } from './app-domain.module';
import { UiModalModule } from '@ui/modal';
import { NotificationsHubModule, NOTIFICATIONS_HUB_OPTIONS } from '@hub/notifications';
import {
NotificationsHubModule,
NOTIFICATIONS_HUB_OPTIONS,
} from '@hub/notifications';
import { SignalRHubOptions } from '@core/signalr';
import { CoreBreadcrumbModule } from '@core/breadcrumb';
import { UiCommonModule } from '@ui/common';
@@ -36,7 +43,11 @@ import { HttpErrorInterceptor } from './interceptors';
import { CoreLoggerModule, LOG_PROVIDER } from '@core/logger';
import { IsaLogProvider } from './providers';
import { IsaErrorHandler } from './providers/isa.error-handler';
import { ScanAdapterModule, ScanAdapterService, ScanditScanAdapterModule } from '@adapter/scan';
import {
ScanAdapterModule,
ScanAdapterService,
ScanditScanAdapterModule,
} from '@adapter/scan';
import { RootStateService } from './store/root-state.service';
import * as Commands from './commands';
import { PreviewComponent } from './preview';
@@ -45,11 +56,22 @@ import { ShellModule } from '@shared/shell';
import { MainComponent } from './main.component';
import { IconModule } from '@shared/components/icon';
import { NgIconsModule } from '@ng-icons/core';
import { matClose, matWifi, matWifiOff } from '@ng-icons/material-icons/baseline';
import {
matClose,
matWifi,
matWifiOff,
} from '@ng-icons/material-icons/baseline';
import { NetworkStatusService } from './services/network-status.service';
import { firstValueFrom } from 'rxjs';
import { provideMatomo } from 'ngx-matomo-client';
import { withRouter, withRouteData } from 'ngx-matomo-client';
import {
provideLogging,
withLogLevel,
LogLevel,
withSink,
ConsoleLogSink,
} from '@isa/core/logging';
registerLocaleData(localeDe, localeDeExtra);
registerLocaleData(localeDe, 'de', localeDeExtra);
@@ -103,7 +125,13 @@ export function _appInitializerFactory(config: Config, injector: Injector) {
'⚡<br><br><b>Fehler bei der Initialisierung</b><br><br>Bitte prüfen Sie die Netzwerkverbindung (WLAN).<br><br>';
const reload = document.createElement('button');
reload.classList.add('bg-brand', 'text-white', 'p-2', 'rounded', 'cursor-pointer');
reload.classList.add(
'bg-brand',
'text-white',
'p-2',
'rounded',
'cursor-pointer',
);
reload.innerHTML = 'App neu laden';
reload.onclick = () => window.location.reload();
statusElement.appendChild(reload);
@@ -167,7 +195,10 @@ export function _notificationsHubOptionsFactory(
],
providers: [
provideAppInitializer(() => {
const initializerFn = _appInitializerFactory(inject(Config), inject(Injector));
const initializerFn = _appInitializerFactory(
inject(Config),
inject(Injector),
);
return initializerFn();
}),
{
@@ -196,6 +227,7 @@ export function _notificationsHubOptionsFactory(
withRouter(),
withRouteData(),
),
provideLogging(withLogLevel(LogLevel.Debug), withSink(ConsoleLogSink)),
],
})
export class AppModule {}

View File

@@ -1,12 +1,22 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
import { ApplicationProcess, ApplicationService } from '@core/application';
import { DomainCheckoutService } from '@domain/checkout';
import { CustomerSearchNavigation } from '@shared/services/navigation';
import { first } from 'rxjs/operators';
import { Injectable } from "@angular/core";
import {
ActivatedRouteSnapshot,
Router,
RouterStateSnapshot,
} from "@angular/router";
import { ApplicationProcess, ApplicationService } from "@core/application";
import { DomainCheckoutService } from "@domain/checkout";
import { logger } from "@isa/core/logging";
import { CustomerSearchNavigation } from "@shared/services/navigation";
import { first } from "rxjs/operators";
@Injectable({ providedIn: 'root' })
@Injectable({ providedIn: "root" })
export class CanActivateCustomerGuard {
#logger = logger(() => ({
context: "CanActivateCustomerGuard",
tags: ["guard", "customer", "navigation"],
}));
constructor(
private readonly _applicationService: ApplicationService,
private readonly _checkoutService: DomainCheckoutService,
@@ -14,36 +24,77 @@ export class CanActivateCustomerGuard {
private readonly _navigation: CustomerSearchNavigation,
) {}
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
let lastActivatedProcessId = (
async canActivate(
route: ActivatedRouteSnapshot,
{ url }: RouterStateSnapshot,
) {
if (url.startsWith("/kunde/customer/search/")) {
const processId = Date.now(); // Generate a new process ID
// Extract parts before and after the pattern
const parts = url.split("/kunde/customer/");
if (parts.length === 2) {
const prefix = parts[0] + "/kunde/";
const suffix = "customer/" + parts[1];
// Construct the new URL with process ID inserted
const newUrl = `${prefix}${processId}/${suffix}`;
this.#logger.info("Redirecting to URL with process ID", () => ({
originalUrl: url,
newUrl,
processId,
}));
// Navigate to the new URL and prevent original navigation
this._router.navigateByUrl(newUrl);
return false;
}
}
const processes = await this._applicationService
.getProcesses$("customer")
.pipe(first())
.toPromise();
const lastActivatedProcessId = (
await this._applicationService
.getLastActivatedProcessWithSectionAndType$('customer', 'cart')
.getLastActivatedProcessWithSectionAndType$("customer", "cart")
.pipe(first())
.toPromise()
)?.id;
const lastActivatedCartCheckoutProcessId = (
await this._applicationService
.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout')
.getLastActivatedProcessWithSectionAndType$("customer", "cart-checkout")
.pipe(first())
.toPromise()
)?.id;
const lastActivatedGoodsOutProcessId = (
await this._applicationService
.getLastActivatedProcessWithSectionAndType$('customer', 'goods-out')
.getLastActivatedProcessWithSectionAndType$("customer", "goods-out")
.pipe(first())
.toPromise()
)?.id;
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();
const activatedProcessId = await this._applicationService
.getActivatedProcessId$()
.pipe(first())
.toPromise();
// Darf nur reinkommen wenn der aktuell aktive Tab ein Bestellabschluss Tab ist
if (!!lastActivatedCartCheckoutProcessId && lastActivatedCartCheckoutProcessId === activatedProcessId) {
await this.fromCartCheckoutProcess(processes, lastActivatedCartCheckoutProcessId);
if (
!!lastActivatedCartCheckoutProcessId &&
lastActivatedCartCheckoutProcessId === activatedProcessId
) {
await this.fromCartCheckoutProcess(
processes,
lastActivatedCartCheckoutProcessId,
);
return false;
} else if (!!lastActivatedGoodsOutProcessId && lastActivatedGoodsOutProcessId === activatedProcessId) {
} else if (
!!lastActivatedGoodsOutProcessId &&
lastActivatedGoodsOutProcessId === activatedProcessId
) {
await this.fromGoodsOutProcess(processes, lastActivatedGoodsOutProcessId);
return false;
}
@@ -68,25 +119,28 @@ export class CanActivateCustomerGuard {
const newProcessId = Date.now();
await this._applicationService.createProcess({
id: newProcessId,
type: 'cart',
section: 'customer',
name: `Vorgang ${this.processNumber(processes.filter((process) => process.type === 'cart'))}`,
type: "cart",
section: "customer",
name: `Vorgang ${this.processNumber(processes.filter((process) => process.type === "cart"))}`,
});
await this.navigateToDefaultRoute(newProcessId);
}
// Bei offener Bestellbestätigung und Klick auf Footer Kundensuche
async fromCartCheckoutProcess(processes: ApplicationProcess[], processId: number) {
async fromCartCheckoutProcess(
processes: ApplicationProcess[],
processId: number,
) {
// Um alle Checkout Daten zu resetten die mit dem Prozess assoziiert sind
this._checkoutService.removeProcess({ processId });
// Ändere type cart-checkout zu cart
this._applicationService.patchProcess(processId, {
id: processId,
type: 'cart',
section: 'customer',
name: `Vorgang ${this.processNumber(processes.filter((process) => process.type === 'cart'))}`,
type: "cart",
section: "customer",
name: `Vorgang ${this.processNumber(processes.filter((process) => process.type === "cart"))}`,
data: {},
});
@@ -95,22 +149,31 @@ export class CanActivateCustomerGuard {
}
// Bei offener Warenausgabe und Klick auf Footer Kundensuche
async fromGoodsOutProcess(processes: ApplicationProcess[], processId: number) {
const buyer = await this._checkoutService.getBuyer({ processId }).pipe(first()).toPromise();
const customerFeatures = await this._checkoutService.getCustomerFeatures({ processId }).pipe(first()).toPromise();
async fromGoodsOutProcess(
processes: ApplicationProcess[],
processId: number,
) {
const buyer = await this._checkoutService
.getBuyer({ processId })
.pipe(first())
.toPromise();
const customerFeatures = await this._checkoutService
.getCustomerFeatures({ processId })
.pipe(first())
.toPromise();
const name = buyer
? customerFeatures?.b2b
? buyer.organisation?.name
? buyer.organisation?.name
: buyer.lastName
: buyer.lastName
: `Vorgang ${this.processNumber(processes.filter((process) => process.type === 'cart'))}`;
: `Vorgang ${this.processNumber(processes.filter((process) => process.type === "cart"))}`;
// Ändere type goods-out zu cart
this._applicationService.patchProcess(processId, {
id: processId,
type: 'cart',
section: 'customer',
type: "cart",
section: "customer",
name,
});
@@ -119,12 +182,20 @@ export class CanActivateCustomerGuard {
}
processNumber(processes: ApplicationProcess[]) {
const processNumbers = processes?.map((process) => Number(process?.name?.replace(/\D/g, '')));
return !!processNumbers && processNumbers.length > 0 ? this.findMissingNumber(processNumbers) : 1;
const processNumbers = processes?.map((process) =>
Number(process?.name?.replace(/\D/g, "")),
);
return !!processNumbers && processNumbers.length > 0
? this.findMissingNumber(processNumbers)
: 1;
}
findMissingNumber(processNumbers: number[]) {
for (let missingNumber = 1; missingNumber < Math.max(...processNumbers); missingNumber++) {
for (
let missingNumber = 1;
missingNumber < Math.max(...processNumbers);
missingNumber++
) {
if (!processNumbers.find((number) => number === missingNumber)) {
return missingNumber;
}

View File

@@ -1,11 +1,16 @@
import { HttpErrorResponse } from '@angular/common/http';
import { ErrorHandler, Injectable } from '@angular/core';
import { AuthService } from '@core/auth';
import { DialogModel, UiDialogModalComponent, UiErrorModalComponent, UiModalService } from '@ui/modal';
import { IsaLogProvider } from './isa.log-provider';
import { LogLevel } from '@core/logger';
import { HttpErrorResponse } from "@angular/common/http";
import { ErrorHandler, Injectable } from "@angular/core";
import { AuthService } from "@core/auth";
import {
DialogModel,
UiDialogModalComponent,
UiErrorModalComponent,
UiModalService,
} from "@ui/modal";
import { IsaLogProvider } from "./isa.log-provider";
import { LogLevel } from "@core/logger";
@Injectable({ providedIn: 'root' })
@Injectable({ providedIn: "root" })
export class IsaErrorHandler implements ErrorHandler {
constructor(
private _modal: UiModalService,
@@ -17,7 +22,7 @@ export class IsaErrorHandler implements ErrorHandler {
console.error(error);
// Bei Klick auf Abbrechen auf der Login Seite erneut zur Login Seite weiterleiten
if (error?.type === 'token_error') {
if (error?.type === "token_error") {
this._authService.login();
return;
}
@@ -26,11 +31,14 @@ export class IsaErrorHandler implements ErrorHandler {
await this._modal
.open({
content: UiDialogModalComponent,
title: 'Sitzung abgelaufen',
title: "Sitzung abgelaufen",
data: {
handleCommand: false,
content: 'Sie waren zu lange nicht in der ISA aktiv. Bitte melden Sie sich erneut an',
actions: [{ command: 'CLOSE', selected: true, label: 'Erneut anmelden' }],
content:
"Sie waren zu lange nicht in der ISA aktiv. Bitte melden Sie sich erneut an",
actions: [
{ command: "CLOSE", selected: true, label: "Erneut anmelden" },
],
} as DialogModel,
})
.afterClosed$.toPromise();
@@ -39,7 +47,11 @@ export class IsaErrorHandler implements ErrorHandler {
return;
}
this._isaLogProvider.log(LogLevel.ERROR, 'Client Error', error);
try {
this._isaLogProvider.log(LogLevel.ERROR, "Client Error", error);
} catch (logError) {
console.error("Error logging to IsaLogProvider:", logError);
}
// this._modal.open({
// content: UiErrorModalComponent,

View File

@@ -1,28 +1,36 @@
import { Injectable, Injector } from '@angular/core';
import { LogLevel, LogProvider } from '@core/logger';
import { UserStateService } from '@generated/swagger/isa-api';
import { environment } from '../../environments/environment';
import { Injectable } from "@angular/core";
import { LogLevel, LogProvider } from "@core/logger";
import { UserStateService } from "@generated/swagger/isa-api";
import { environment } from "../../environments/environment";
@Injectable({ providedIn: 'root' })
@Injectable({ providedIn: "root" })
export class IsaLogProvider implements LogProvider {
static InfoService: UserStateService | undefined;
constructor() {}
log(logLevel: LogLevel, message: string, error: Error, ...optionalParams: any[]): void {
if (!environment.production && (logLevel === LogLevel.WARN || logLevel === LogLevel.ERROR)) {
IsaLogProvider.InfoService?.UserStateSaveLog({
logType: logLevel,
message: message,
content: JSON.stringify({
error: error?.name,
message: error?.message,
stack: error?.stack,
data: optionalParams,
}),
})
.toPromise()
.catch(() => {});
log(
logLevel: LogLevel,
message: string,
error: Error,
...optionalParams: any[]
): void {
try {
if (
!environment.production &&
(logLevel === LogLevel.WARN || logLevel === LogLevel.ERROR)
) {
IsaLogProvider.InfoService?.UserStateSaveLog({
logType: logLevel,
message: message,
content: JSON.stringify({
error: error?.name,
message: error?.message,
stack: error?.stack,
data: optionalParams,
}),
}).toPromise();
}
} catch (error) {
console.error("Error logging to InfoService:", error);
}
}
}

View File

@@ -1,86 +1,85 @@
{
"title": "ISA - Feature",
"silentRefresh": {
"interval": 300000
},
"@cdn/product-image": {
"url": "https://produktbilder.paragon-data.net"
},
"@core/auth": {
"issuer": "https://sso-test.paragon-data.de",
"clientId": "hug-isa",
"responseType": "id_token token",
"oidc": true,
"scope": "openid profile cmf_user isa-isa-webapi isa-checkout-webapi isa-cat-webapi isa-ava-webapi isa-crm-webapi isa-review-webapi isa-kpi-webapi isa-oms-webapi isa-nbo-webapi isa-print-webapi eis-service isa-inv-webapi isa-wws-webapi"
},
"@core/logger": {
"logLevel": "debug"
},
"@domain/checkout": {
"olaExpiration": "5m"
},
"@swagger/isa": {
"rootUrl": "https://isa-test.paragon-data.net/isa/v1"
},
"@swagger/cat": {
"rootUrl": "https://isa-test.paragon-data.net/catsearch/v6"
},
"@swagger/av": {
"rootUrl": "https://isa-test.paragon-data.net/ava/v6"
},
"@swagger/checkout": {
"rootUrl": "https://isa-test.paragon-data.net/checkout/v6"
},
"@swagger/crm": {
"rootUrl": "https://isa-test.paragon-data.net/crm/v6"
},
"@swagger/oms": {
"rootUrl": "https://isa-test.paragon-data.net/oms/v6"
},
"@swagger/print": {
"rootUrl": "https://isa-test.paragon-data.net/print/v1"
},
"@swagger/eis": {
"rootUrl": "https://filialinformationsystem-test.paragon-systems.de/eiswebapi/v1"
},
"@swagger/remi": {
"rootUrl": "https://isa-test.paragon-data.net/inv/v6"
},
"@swagger/wws": {
"rootUrl": "https://isa-test.paragon-data.net/wws/v1"
},
"hubs": {
"notifications": {
"url": "https://isa-test.paragon-data.net/isa/v1/rt",
"enableAutomaticReconnect": false,
"httpOptions": {
"transport": 1,
"logMessageContent": true,
"skipNegotiation": true
}
}
},
"process": {
"ids": {
"goodsOut": 1000,
"goodsIn": 2000,
"taskCalendar": 3000,
"remission": 4000,
"packageInspection": 5000,
"assortment": 6000,
"pickupShelf": 7000
}
},
"checkForUpdates": 3600000,
"licence": {
"scandit": "Ae8F2Wx2RMq5Lvn7UUAlWzVFZTt2+ubMAF8XtDpmPlNkBeG/LWs1M7AbgDW0LQqYLnszClEENaEHS56/6Ts2vrJ1Ux03CXUjK3jUvZpF5OchXR1CpnmpepJ6WxPCd7LMVHUGG1BbwPLDTFjP3y8uT0caTSmmGrYQWAs4CZcEF+ZBabP0z7vfm+hCZF/ebj9qqCJZcW8nH/n19hohshllzYBjFXjh87P2lIh1s6yZS3OaQWWXo/o0AKdxx7T6CVyR0/G5zq6uYJWf6rs3euUBEhpzOZHbHZK86Lvy2AVBEyVkkcttlDW1J2fA4l1W1JV/Xibz8AQV6kG482EpGF42KEoK48paZgX3e1AQsqUtmqzw294dcP4zMVstnw5/WrwKKi/5E/nOOJT2txYP1ZufIjPrwNFsqTlv7xCQlHjMzFGYwT816yD5qLRLbwOtjrkUPXNZLZ06T4upvWwJDmm8XgdeoDqMjHdcO4lwji1bl9EiIYJ/2qnsk9yZ2FqSaHzn4cbiL0f5u2HFlNAP0GUujGRlthGhHi6o4dFU+WAxKsFMKVt+SfoQUazNKHFVQgiAklTIZxIc/HUVzRvOLMxf+wFDerraBtcqGJg+g/5mrWYqeDBGhCBHtKiYf6244IJ4afzNTiH1/30SJcRzXwbEa3A7q1fJTx9/nLTOfVPrJKBQs7f/OQs2dA7LDCel8mzXdbjvsNQaeU5+iCIAq6zbTNKy1xT8wwj+VZrQmtNJs+qeznD+u29nCM24h8xCmRpvNPo4/Mww/lrTNrrNwLBSn1pMIwsH7yS9hH0v0oNAM3A6bVtk1D9qEkbyw+xZa+MZGpMP0D0CdcsqHalPcm5r/Ik="
},
"gender": {
"0": "Keine Anrede",
"1": "Enby",
"2": "Herr",
"4": "Frau"
},
"@shared/icon": "/assets/icons.json"
}
"title": "ISA - Feature",
"silentRefresh": {
"interval": 300000
},
"@cdn/product-image": {
"url": "https://produktbilder.paragon-data.net"
},
"@core/auth": {
"issuer": "https://sso-test.paragon-data.de",
"clientId": "hug-isa",
"responseType": "id_token token",
"oidc": true,
"scope": "openid profile cmf_user isa-isa-webapi isa-checkout-webapi isa-cat-webapi isa-ava-webapi isa-crm-webapi isa-review-webapi isa-kpi-webapi isa-oms-webapi isa-nbo-webapi isa-print-webapi eis-service isa-inv-webapi isa-wws-webapi"
},
"@core/logger": {
"logLevel": "debug"
},
"@domain/checkout": {
"olaExpiration": "5m"
},
"@swagger/isa": {
"rootUrl": "https://isa-feature.paragon-data.net/isa/v1"
},
"@swagger/cat": {
"rootUrl": "https://isa-test.paragon-data.net/catsearch/v6"
},
"@swagger/av": {
"rootUrl": "https://isa-test.paragon-data.net/ava/v6"
},
"@swagger/checkout": {
"rootUrl": "https://isa-feature.paragon-data.net/checkout/v6"
},
"@swagger/crm": {
"rootUrl": "https://isa-feature.paragon-data.net/crm/v6"
},
"@swagger/oms": {
"rootUrl": "https://isa-feature.paragon-data.net/oms/v6"
},
"@swagger/print": {
"rootUrl": "https://isa-feature.paragon-data.net/print/v1"
},
"@swagger/eis": {
"rootUrl": "https://filialinformationsystem-test.paragon-systems.de/eiswebapi/v1"
},
"@swagger/remi": {
"rootUrl": "https://isa-feature.paragon-data.net/inv/v6"
},
"@swagger/wws": {
"rootUrl": "https://isa-test.paragon-data.net/wws/v1"
},
"hubs": {
"notifications": {
"url": "https://isa-feature.paragon-data.net/isa/v1/rt",
"enableAutomaticReconnect": false,
"httpOptions": {
"transport": 1,
"logMessageContent": true,
"skipNegotiation": true
}
}
},
"process": {
"ids": {
"goodsOut": 1000,
"goodsIn": 2000,
"taskCalendar": 3000,
"remission": 4000,
"packageInspection": 5000,
"assortment": 6000,
"pickupShelf": 7000
}
},
"checkForUpdates": 3600000,
"licence": {
"scandit": "Ae8F2Wx2RMq5Lvn7UUAlWzVFZTt2+ubMAF8XtDpmPlNkBeG/LWs1M7AbgDW0LQqYLnszClEENaEHS56/6Ts2vrJ1Ux03CXUjK3jUvZpF5OchXR1CpnmpepJ6WxPCd7LMVHUGG1BbwPLDTFjP3y8uT0caTSmmGrYQWAs4CZcEF+ZBabP0z7vfm+hCZF/ebj9qqCJZcW8nH/n19hohshllzYBjFXjh87P2lIh1s6yZS3OaQWWXo/o0AKdxx7T6CVyR0/G5zq6uYJWf6rs3euUBEhpzOZHbHZK86Lvy2AVBEyVkkcttlDW1J2fA4l1W1JV/Xibz8AQV6kG482EpGF42KEoK48paZgX3e1AQsqUtmqzw294dcP4zMVstnw5/WrwKKi/5E/nOOJT2txYP1ZufIjPrwNFsqTlv7xCQlHjMzFGYwT816yD5qLRLbwOtjrkUPXNZLZ06T4upvWwJDmm8XgdeoDqMjHdcO4lwji1bl9EiIYJ/2qnsk9yZ2FqSaHzn4cbiL0f5u2HFlNAP0GUujGRlthGhHi6o4dFU+WAxKsFMKVt+SfoQUazNKHFVQgiAklTIZxIc/HUVzRvOLMxf+wFDerraBtcqGJg+g/5mrWYqeDBGhCBHtKiYf6244IJ4afzNTiH1/30SJcRzXwbEa3A7q1fJTx9/nLTOfVPrJKBQs7f/OQs2dA7LDCel8mzXdbjvsNQaeU5+iCIAq6zbTNKy1xT8wwj+VZrQmtNJs+qeznD+u29nCM24h8xCmRpvNPo4/Mww/lrTNrrNwLBSn1pMIwsH7yS9hH0v0oNAM3A6bVtk1D9qEkbyw+xZa+MZGpMP0D0CdcsqHalPcm5r/Ik="
},
"gender": {
"0": "Keine Anrede",
"1": "Enby",
"2": "Herr",
"4": "Frau"
},
"@shared/icon": "/assets/icons.json"
}

View File

@@ -1,13 +1,18 @@
import { coerceArray } from '@angular/cdk/coercion';
import { inject, Injectable } from '@angular/core';
import { Config } from '@core/config';
import { isNullOrUndefined } from '@utils/common';
import { AuthConfig, OAuthService } from 'angular-oauth2-oidc';
import { JwksValidationHandler } from 'angular-oauth2-oidc-jwks';
import { BehaviorSubject } from 'rxjs';
import { coerceArray } from "@angular/cdk/coercion";
import { inject, Injectable } from "@angular/core";
import { Config } from "@core/config";
import { isNullOrUndefined } from "@utils/common";
import { AuthConfig, OAuthService } from "angular-oauth2-oidc";
import { JwksValidationHandler } from "angular-oauth2-oidc-jwks";
import { BehaviorSubject } from "rxjs";
/**
* Storage key for the URL to redirect to after login
*/
const REDIRECT_URL_KEY = "auth_redirect_url";
@Injectable({
providedIn: 'root',
providedIn: "root",
})
export class AuthService {
private readonly _initialized = new BehaviorSubject<boolean>(false);
@@ -16,28 +21,39 @@ export class AuthService {
}
private _authConfig: AuthConfig;
constructor(
private _config: Config,
private readonly _oAuthService: OAuthService,
) {
this._oAuthService.events?.subscribe((event) => {
if (event.type === 'token_received') {
console.log('SSO Token Expiration:', new Date(this._oAuthService.getAccessTokenExpiration()));
if (event.type === "token_received") {
console.log(
"SSO Token Expiration:",
new Date(this._oAuthService.getAccessTokenExpiration()),
);
// Handle redirect after successful authentication
setTimeout(() => {
const redirectUrl = this._getAndClearRedirectUrl();
if (redirectUrl) {
window.location.href = redirectUrl;
}
}, 100);
}
});
}
async init() {
if (this._initialized.getValue()) {
throw new Error('AuthService is already initialized');
throw new Error("AuthService is already initialized");
}
this._authConfig = this._config.get('@core/auth');
this._authConfig = this._config.get("@core/auth");
this._authConfig.redirectUri = window.location.origin;
this._authConfig.silentRefreshRedirectUri = window.location.origin + '/silent-refresh.html';
this._authConfig.silentRefreshRedirectUri =
window.location.origin + "/silent-refresh.html";
this._authConfig.useSilentRefresh = true;
this._oAuthService.configure(this._authConfig);
@@ -55,12 +71,18 @@ export class AuthService {
}
isIdTokenValid() {
console.log('ID Token Expiration:', new Date(this._oAuthService.getIdTokenExpiration()));
console.log(
"ID Token Expiration:",
new Date(this._oAuthService.getIdTokenExpiration()),
);
return this._oAuthService.hasValidIdToken();
}
isAccessTokenValid() {
console.log('ACCESS Token Expiration:', new Date(this._oAuthService.getAccessTokenExpiration()));
console.log(
"ACCESS Token Expiration:",
new Date(this._oAuthService.getAccessTokenExpiration()),
);
return this._oAuthService.hasValidAccessToken();
}
@@ -85,14 +107,31 @@ export class AuthService {
if (isNullOrUndefined(token)) {
return null;
}
const base64Url = token.split('.')[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
const base64Url = token.split(".")[1];
const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
const encoded = window.atob(base64);
return JSON.parse(encoded);
}
/**
* Saves the URL to redirect to after successful login
*/
_saveRedirectUrl(): void {
localStorage.setItem(REDIRECT_URL_KEY, window.location.href);
}
/**
* Gets and clears the saved redirect URL
*/
_getAndClearRedirectUrl(): string | null {
const url = localStorage.getItem(REDIRECT_URL_KEY);
localStorage.removeItem(REDIRECT_URL_KEY);
return url;
}
login() {
this._saveRedirectUrl();
this._oAuthService.initLoginFlow();
}
@@ -109,7 +148,7 @@ export class AuthService {
hasRole(role: string | string[]) {
const roles = coerceArray(role);
const userRoles = this.getClaimByKey('role');
const userRoles = this.getClaimByKey("role");
if (isNullOrUndefined(userRoles)) {
return false;
@@ -120,7 +159,10 @@ export class AuthService {
async refresh() {
try {
if (this._authConfig.responseType.includes('code') && this._authConfig.scope.includes('offline_access')) {
if (
this._authConfig.responseType.includes("code") &&
this._authConfig.scope.includes("offline_access")
) {
await this._oAuthService.refreshToken();
} else {
await this._oAuthService.silentRefresh();

View File

@@ -1,5 +1,4 @@
import { Injectable } from '@angular/core';
import { LogLevel } from './log-level';
import { LogLevel } from "./log-level";
export interface LogProvider {
log(logLevel: LogLevel, message: string, ...optionalParams: any[]): void;

View File

@@ -1,5 +1,9 @@
import { Injectable } from '@angular/core';
import { ArticleDTO, DisplayInfoDTO, EISPublicDocumentService } from '@generated/swagger/eis-api';
import {
ArticleDTO,
DisplayInfoDTO,
EISPublicDocumentService,
} from '@generated/swagger/eis-api';
import {
CatalogPrintService,
CheckoutPrintService,
@@ -42,7 +46,9 @@ export class DomainPrinterService {
map((response: any) => {
if (response.error && response.error.status === 503) {
return {
error: response.message ? response.message : 'Das Backend ist derzeit nicht erreichbar',
error: response.message
? response.message
: 'Das Backend ist derzeit nicht erreichbar',
};
}
if (response.error && response.error.name === 'TimeoutError') {
@@ -77,7 +83,9 @@ export class DomainPrinterService {
map((response: any) => {
if (response.error && response.error.status === 503) {
return {
error: response.message ? response.message : 'Das Backend ist derzeit nicht erreichbar',
error: response.message
? response.message
: 'Das Backend ist derzeit nicht erreichbar',
};
}
if (response.error && response.error.name === 'TimeoutError') {
@@ -112,7 +120,9 @@ export class DomainPrinterService {
map((response: any) => {
if (response.error && response.error.status === 503) {
return {
error: response.message ? response.message : 'Das Backend ist derzeit nicht erreichbar',
error: response.message
? response.message
: 'Das Backend ist derzeit nicht erreichbar',
};
}
if (response.error && response.error.name === 'TimeoutError') {
@@ -141,28 +151,61 @@ export class DomainPrinterService {
);
}
printOrder({ orderIds, printer }: { orderIds: number[]; printer: string }): Observable<ResponseArgs> {
printOrder({
orderIds,
printer,
}: {
orderIds: number[];
printer: string;
}): Observable<ResponseArgs> {
const params = <any>{
printer: printer,
data: orderIds,
};
return this.oMSPrintService.OMSPrintAbholscheinById(params).pipe(timeout(20000));
return this.oMSPrintService
.OMSPrintAbholscheinById(params)
.pipe(timeout(20000));
}
printShippingNote({ receipts, printer }: { receipts: number[]; printer: string }) {
printShippingNote({
receipts,
printer,
}: {
receipts: number[];
printer: string;
}) {
return this.oMSPrintService.OMSPrintLieferschein({
printer,
data: receipts,
});
}
printCompartmentLabel({ orderItemSubsetIds, printer }: { orderItemSubsetIds: number[]; printer: string }) {
printCompartmentLabel({
orderItemSubsetIds,
printer,
}: {
orderItemSubsetIds: number[];
printer: string;
}) {
return this.oMSPrintService.OMSPrintAbholfachetikett({
printer,
data: orderItemSubsetIds,
});
}
printReturnReceipt({
receiptIds,
printer,
}: {
receiptIds: number[];
printer: string;
}) {
return this.oMSPrintService.OMSPrintReturnReceipt({
printer,
data: receiptIds,
});
}
printKubiAgb({ p4mCode, printer }: { p4mCode: string; printer: string }) {
return this._loyaltyCardPrintService.LoyaltyCardPrintPrintLoyaltyCardAGB({
printer,
@@ -170,20 +213,36 @@ export class DomainPrinterService {
});
}
printProduct({ item, printer }: { item: ItemDTO; printer: string }): Observable<ResponseArgs> {
printProduct({
item,
printer,
}: {
item: ItemDTO;
printer: string;
}): Observable<ResponseArgs> {
const params = <PrintRequestOfIEnumerableOfItemDTO>{
printer: printer,
data: [item],
};
return this.catalogPrintService.CatalogPrintArtikelDetail(params).pipe(timeout(20000));
return this.catalogPrintService
.CatalogPrintArtikelDetail(params)
.pipe(timeout(20000));
}
printCart({ cartId, printer }: { cartId: number; printer: string }): Observable<ResponseArgs> {
printCart({
cartId,
printer,
}: {
cartId: number;
printer: string;
}): Observable<ResponseArgs> {
const params = <any>{
printer: printer,
data: cartId,
};
return this.checkoutPrintService.CheckoutPrintWarenkorbById(params).pipe(timeout(20000));
return this.checkoutPrintService
.CheckoutPrintWarenkorbById(params)
.pipe(timeout(20000));
}
async printGoodsInLabel(subsetItemIds: number[]): Promise<ResponseArgs> {
@@ -223,7 +282,9 @@ export class DomainPrinterService {
printProductListItemsResponse(
payload: DocumentPayloadOfIEnumerableOfProductListItemDTO,
): Observable<ResponseArgsOfString> {
return this._productListService.ProductListProductListItemPdfAsBase64(payload);
return this._productListService.ProductListProductListItemPdfAsBase64(
payload,
);
}
printProductListItems({

View File

@@ -1,21 +1,22 @@
import { enableProdMode, isDevMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { CONFIG_DATA } from '@isa/core/config';
import { setDefaultOptions } from 'date-fns';
import { de } from 'date-fns/locale';
import * as moment from 'moment';
import { enableProdMode, isDevMode } from "@angular/core";
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
import { CONFIG_DATA } from "@isa/core/config";
import { setDefaultOptions } from "date-fns";
import { de } from "date-fns/locale";
import * as moment from "moment";
import "moment/locale/de";
setDefaultOptions({ locale: de });
moment.locale('de');
moment.locale("de");
import { AppModule } from './app/app.module';
import { AppModule } from "./app/app.module";
if (!isDevMode()) {
enableProdMode();
}
async function bootstrap() {
const configRes = await fetch('/config/config.json');
const configRes = await fetch("/config/config.json");
const config = await configRes.json();

View File

@@ -9,37 +9,53 @@ import {
AfterViewInit,
TrackByFunction,
inject,
} from '@angular/core';
import { Router } from '@angular/router';
import { ApplicationService } from '@core/application';
import { DomainAvailabilityService } from '@domain/availability';
import { DomainCheckoutService } from '@domain/checkout';
import { AvailabilityDTO, BranchDTO, DestinationDTO, ShoppingCartItemDTO } from '@generated/swagger/checkout-api';
import { UiMessageModalComponent, UiModalService } from '@ui/modal';
import { PrintModalData, PrintModalComponent } from '@modal/printer';
import { delay, first, map, switchMap, takeUntil, tap } from 'rxjs/operators';
import { Subject, NEVER, combineLatest, BehaviorSubject, Subscription } from 'rxjs';
import { DomainCatalogService } from '@domain/catalog';
import { BreadcrumbService } from '@core/breadcrumb';
import { DomainPrinterService } from '@domain/printer';
import { CheckoutDummyComponent } from '../checkout-dummy/checkout-dummy.component';
import { CheckoutDummyData } from '../checkout-dummy/checkout-dummy-data';
import { PurchaseOptionsModalService } from '@modal/purchase-options';
import { CheckoutNavigationService, ProductCatalogNavigationService } from '@shared/services/navigation';
import { EnvironmentService } from '@core/environment';
import { CheckoutReviewStore } from './checkout-review.store';
import { ToasterService } from '@shared/shell';
import { ShoppingCartItemComponent } from './shopping-cart-item/shopping-cart-item.component';
import { CustomerSearchNavigation } from '@shared/services/navigation';
} from "@angular/core";
import { Router } from "@angular/router";
import { ApplicationService } from "@core/application";
import { DomainAvailabilityService } from "@domain/availability";
import { DomainCheckoutService } from "@domain/checkout";
import {
AvailabilityDTO,
BranchDTO,
DestinationDTO,
ShoppingCartItemDTO,
} from "@generated/swagger/checkout-api";
import { UiMessageModalComponent, UiModalService } from "@ui/modal";
import { PrintModalData, PrintModalComponent } from "@modal/printer";
import { delay, first, map, switchMap, takeUntil, tap } from "rxjs/operators";
import {
Subject,
NEVER,
combineLatest,
BehaviorSubject,
Subscription,
} from "rxjs";
import { DomainCatalogService } from "@domain/catalog";
import { BreadcrumbService } from "@core/breadcrumb";
import { DomainPrinterService } from "@domain/printer";
import { CheckoutDummyComponent } from "../checkout-dummy/checkout-dummy.component";
import { CheckoutDummyData } from "../checkout-dummy/checkout-dummy-data";
import { PurchaseOptionsModalService } from "@modal/purchase-options";
import {
CheckoutNavigationService,
ProductCatalogNavigationService,
} from "@shared/services/navigation";
import { EnvironmentService } from "@core/environment";
import { CheckoutReviewStore } from "./checkout-review.store";
import { ToasterService } from "@shared/shell";
import { ShoppingCartItemComponent } from "./shopping-cart-item/shopping-cart-item.component";
import { CustomerSearchNavigation } from "@shared/services/navigation";
@Component({
selector: 'page-checkout-review',
templateUrl: 'checkout-review.component.html',
styleUrls: ['checkout-review.component.scss'],
selector: "page-checkout-review",
templateUrl: "checkout-review.component.html",
styleUrls: ["checkout-review.component.scss"],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false,
})
export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit {
export class CheckoutReviewComponent
implements OnInit, OnDestroy, AfterViewInit
{
private _onDestroy$ = new Subject<void>();
private _customerSearchNavigation = inject(CustomerSearchNavigation);
@@ -57,7 +73,9 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
shoppingCartItemsWithoutOrderType$ = this._store.shoppingCartItems$.pipe(
takeUntil(this._store.orderCompleted),
map((items) => items?.filter((item) => item?.features?.orderType === undefined)),
map((items) =>
items?.filter((item) => item?.features?.orderType === undefined),
),
);
trackByGroupedItems: TrackByFunction<{
@@ -71,11 +89,11 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
map((items) =>
items.reduce(
(grouped, item) => {
let index = grouped.findIndex((g) =>
item?.availability?.supplyChannel === 'MANUALLY'
? g?.orderType === 'Dummy'
: item?.features?.orderType === 'DIG-Versand'
? g?.orderType === 'Versand'
const index = grouped.findIndex((g) =>
item?.availability?.supplyChannel === "MANUALLY"
? g?.orderType === "Dummy"
: item?.features?.orderType === "DIG-Versand"
? g?.orderType === "Versand"
: g?.orderType === item?.features?.orderType,
);
@@ -83,10 +101,10 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
if (!group) {
group = {
orderType:
item?.availability?.supplyChannel === 'MANUALLY'
? 'Dummy'
: item?.features?.orderType === 'DIG-Versand'
? 'Versand'
item?.availability?.supplyChannel === "MANUALLY"
? "Dummy"
: item?.features?.orderType === "DIG-Versand"
? "Versand"
: item?.features?.orderType,
destination: item?.destination?.data,
items: [],
@@ -95,7 +113,8 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
group.items = [...group.items, item]?.sort(
(a, b) =>
a.destination?.data?.targetBranch?.id - b.destination?.data?.targetBranch?.id ||
a.destination?.data?.targetBranch?.id -
b.destination?.data?.targetBranch?.id ||
a.product?.name.localeCompare(b.product?.name),
);
@@ -105,9 +124,19 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
grouped.push(group);
}
return [...grouped].sort((a, b) => (a?.orderType === undefined ? -1 : b?.orderType === undefined ? 1 : 0));
return [...grouped].sort((a, b) =>
a?.orderType === undefined
? -1
: b?.orderType === undefined
? 1
: 0,
);
},
[] as { orderType: string; destination: DestinationDTO; items: ShoppingCartItemDTO[] }[],
[] as {
orderType: string;
destination: DestinationDTO;
items: ShoppingCartItemDTO[];
}[],
),
),
);
@@ -138,7 +167,14 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
.getPromotionPoints({
items,
})
.pipe(map((response) => Object.values(response.result).reduce((sum, points) => sum + points, 0)));
.pipe(
map((response) =>
Object.values(response.result).reduce(
(sum, points) => sum + points,
0,
),
),
);
} else {
return NEVER;
}
@@ -147,20 +183,25 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
customerFeatures$ = this._store.customerFeatures$;
checkNotificationChannelControl$ = this._store.checkNotificationChannelControl$;
checkNotificationChannelControl$ =
this._store.checkNotificationChannelControl$;
showQuantityControlSpinnerItemId: number;
quantityError$ = new BehaviorSubject<{ [key: string]: string }>({});
primaryCtaLabel$ = combineLatest([this.payer$, this.buyer$, this.shoppingCartItemsWithoutOrderType$]).pipe(
primaryCtaLabel$ = combineLatest([
this.payer$,
this.buyer$,
this.shoppingCartItemsWithoutOrderType$,
]).pipe(
map(([payer, buyer, shoppingCartItemsWithoutOrderType]) => {
if (shoppingCartItemsWithoutOrderType?.length > 0) {
return 'Kaufoptionen';
return "Kaufoptionen";
}
if (!(payer || buyer)) {
return 'Weiter';
return "Weiter";
}
return 'Bestellen';
return "Bestellen";
}),
);
@@ -181,12 +222,16 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
checkoutIsInValid$ = this.applicationService.activatedProcessId$.pipe(
takeUntil(this._onDestroy$),
switchMap((processId) => this.domainCheckoutService.checkoutIsValid({ processId })),
switchMap((processId) =>
this.domainCheckoutService.checkoutIsValid({ processId }),
),
map((valid) => !valid),
);
get productSearchBasePath() {
return this._productNavigationService.getArticleSearchBasePath(this.applicationService.activatedProcessId).path;
return this._productNavigationService.getArticleSearchBasePath(
this.applicationService.activatedProcessId,
).path;
}
get isDesktop$() {
@@ -219,14 +264,16 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
) {}
async ngOnInit() {
this.applicationService.activatedProcessId$.pipe(takeUntil(this._onDestroy$)).subscribe((_) => {
this._store.loadShoppingCart();
});
this.applicationService.activatedProcessId$
.pipe(takeUntil(this._onDestroy$))
.subscribe((_) => {
this._store.loadShoppingCart();
});
await this.removeBreadcrumbs();
await this.updateBreadcrumb();
window['Checkout'] = {
window["Checkout"] = {
refreshAvailabilities: this.refreshAvailabilities.bind(this),
};
}
@@ -267,13 +314,16 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
group: { items: ShoppingCartItemDTO[] },
i: number,
) {
return i === 0 ? false : targetBranch.id !== group.items[i - 1].destination?.data?.targetBranch?.data.id;
return i === 0
? false
: targetBranch.id !==
group.items[i - 1].destination?.data?.targetBranch?.data.id;
}
async refreshAvailabilities() {
this.checkingOla$.next(true);
for (let itemComp of this._shoppingCartItems.toArray()) {
for (const itemComp of this._shoppingCartItems.toArray()) {
await itemComp.refreshAvailability();
await new Promise((resolve) => setTimeout(resolve, 100));
}
@@ -283,16 +333,22 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
async updateBreadcrumb() {
await this.breadcrumb.addOrUpdateBreadcrumbIfNotExists({
key: this.applicationService.activatedProcessId,
name: 'Warenkorb',
path: this._navigationService.getCheckoutReviewPath(this.applicationService.activatedProcessId).path,
tags: ['checkout', 'cart'],
section: 'customer',
name: "Warenkorb",
path: this._navigationService.getCheckoutReviewPath(
this.applicationService.activatedProcessId,
).path,
tags: ["checkout", "cart"],
section: "customer",
});
}
async removeBreadcrumbs() {
const checkoutDummyCrumbs = await this.breadcrumb
.getBreadcrumbsByKeyAndTags$(this.applicationService.activatedProcessId, ['checkout', 'cart', 'dummy'])
.getBreadcrumbsByKeyAndTags$(this.applicationService.activatedProcessId, [
"checkout",
"cart",
"dummy",
])
.pipe(first())
.toPromise();
checkoutDummyCrumbs.forEach(async (crumb) => {
@@ -304,32 +360,49 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
this._store.notificationsControl = undefined;
}
openDummyModal({ data, changeDataFromCart = false }: { data?: CheckoutDummyData; changeDataFromCart?: boolean }) {
openDummyModal({
data,
changeDataFromCart = false,
}: {
data?: CheckoutDummyData;
changeDataFromCart?: boolean;
}) {
this.uiModal.open({
content: CheckoutDummyComponent,
data: { ...data, changeDataFromCart },
});
}
changeDummyItem({ shoppingCartItem }: { shoppingCartItem: ShoppingCartItemDTO }) {
changeDummyItem({
shoppingCartItem,
}: {
shoppingCartItem: ShoppingCartItemDTO;
}) {
this.openDummyModal({ data: shoppingCartItem, changeDataFromCart: true });
}
async changeItem({ shoppingCartItem }: { shoppingCartItem: ShoppingCartItemDTO }) {
async changeItem({
shoppingCartItem,
}: {
shoppingCartItem: ShoppingCartItemDTO;
}) {
this._purchaseOptionsModalService.open({
processId: this.applicationService.activatedProcessId,
items: [shoppingCartItem],
type: 'update',
type: "update",
});
}
async openPrintModal() {
let shoppingCart = await this.shoppingCart$.pipe(first()).toPromise();
const shoppingCart = await this.shoppingCart$.pipe(first()).toPromise();
this.uiModal.open({
content: PrintModalComponent,
data: {
printerType: 'Label',
print: (printer) => this.domainPrinterService.printCart({ cartId: shoppingCart.id, printer }).toPromise(),
printerType: "Label",
print: (printer) =>
this.domainPrinterService
.printCart({ cartId: shoppingCart.id, printer })
.toPromise(),
} as PrintModalData,
config: {
panelClass: [],
@@ -351,7 +424,8 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
this.loadingOnQuantityChangeById$.next(shoppingCartItem.id);
const shoppingCartItemPrice = shoppingCartItem?.availability?.price?.value?.value;
const shoppingCartItemPrice =
shoppingCartItem?.availability?.price?.value?.value;
const orderType = shoppingCartItem?.features?.orderType;
let availability: AvailabilityDTO;
@@ -360,7 +434,7 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
if (orderType) {
switch (orderType) {
case 'Rücklage':
case "Rücklage":
availability = await this.availabilityService
.getTakeAwayAvailability({
item: {
@@ -369,12 +443,13 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
price: shoppingCartItem.availability.price,
},
quantity,
branch,
})
.toPromise();
// this.setQuantityError(shoppingCartItem, availability, availability?.inStock < quantity);
break;
case 'Abholung':
case "Abholung":
availability = await this.availabilityService
.getPickUpAvailability({
branch,
@@ -388,7 +463,7 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
.pipe(map((av) => av[0]))
.toPromise();
break;
case 'Versand':
case "Versand":
availability = await this.availabilityService
.getDeliveryAvailability({
item: {
@@ -400,7 +475,7 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
})
.toPromise();
break;
case 'DIG-Versand':
case "DIG-Versand":
availability = await this.availabilityService
.getDigDeliveryAvailability({
item: {
@@ -412,7 +487,7 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
})
.toPromise();
break;
case 'B2B-Versand':
case "B2B-Versand":
availability = await this.availabilityService
.getB2bDeliveryAvailability({
item: {
@@ -424,7 +499,7 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
})
.toPromise();
break;
case 'Download':
case "Download":
availability = await this.availabilityService
.getDownloadAvailability({
item: {
@@ -463,7 +538,11 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
shoppingCartItemId: shoppingCartItem.id,
update: {
quantity,
availability: this.compareDeliveryAndCatalogPrice(updateAvailability, orderType, shoppingCartItemPrice),
availability: this.compareDeliveryAndCatalogPrice(
updateAvailability,
orderType,
shoppingCartItemPrice,
),
},
})
.toPromise();
@@ -483,8 +562,15 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
}
// Bei unbekannten Kunden und DIG Bestellung findet ein Vergleich der Preise statt
compareDeliveryAndCatalogPrice(availability: AvailabilityDTO, orderType: string, shoppingCartItemPrice: number) {
if (['Versand', 'DIG-Versand'].includes(orderType) && shoppingCartItemPrice < availability?.price?.value?.value) {
compareDeliveryAndCatalogPrice(
availability: AvailabilityDTO,
orderType: string,
shoppingCartItemPrice: number,
) {
if (
["Versand", "DIG-Versand"].includes(orderType) &&
shoppingCartItemPrice < availability?.price?.value?.value
) {
return {
...availability,
price: {
@@ -507,7 +593,10 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
.pipe(
first(),
switchMap((customerFeatures) => {
return this.domainCheckoutService.canSetCustomer({ processId, customerFeatures });
return this.domainCheckoutService.canSetCustomer({
processId,
customerFeatures,
});
}),
)
.toPromise();
@@ -524,24 +613,31 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
this._purchaseOptionsModalService.open({
processId: this.applicationService.activatedProcessId,
items: shoppingCartItems,
type: 'update',
type: "update",
});
}
async changeAddress() {
const processId = this.applicationService.activatedProcessId;
const customer = await this.domainCheckoutService.getBuyer({ processId }).pipe(first()).toPromise();
const customer = await this.domainCheckoutService
.getBuyer({ processId })
.pipe(first())
.toPromise();
if (!customer) {
this.navigateToCustomerSearch(processId);
return;
}
const customerId = customer.source;
const nav = this._customerSearchNavigation.detailsRoute({ processId, customerId });
const nav = this._customerSearchNavigation.detailsRoute({
processId,
customerId,
});
this.router.navigate(nav.path);
}
async order() {
const shoppingCartItemsWithoutOrderType = await this.shoppingCartItemsWithoutOrderType$.pipe(first()).toPromise();
const shoppingCartItemsWithoutOrderType =
await this.shoppingCartItemsWithoutOrderType$.pipe(first()).toPromise();
if (shoppingCartItemsWithoutOrderType?.length > 0) {
this.showPurchasingListModal(shoppingCartItemsWithoutOrderType);
@@ -549,7 +645,10 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
}
const processId = this.applicationService.activatedProcessId;
const customer = await this.domainCheckoutService.getBuyer({ processId }).pipe(first()).toPromise();
const customer = await this.domainCheckoutService
.getBuyer({ processId })
.pipe(first())
.toPromise();
if (!customer) {
this.navigateToCustomerSearch(processId);
} else {
@@ -557,33 +656,42 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
this.showOrderButtonSpinner = true;
// Ticket #3287 Um nur E-Mail und SMS Benachrichtigungen zu setzen und um alle anderen Benachrichtigungskanäle wie z.B. Brief zu deaktivieren
await this._store.onNotificationChange();
const orders = await this.domainCheckoutService.completeCheckout({ processId }).toPromise();
const orderIds = orders.map((order) => order.id).join(',');
const orders = await this.domainCheckoutService
.completeCheckout({ processId })
.toPromise();
const orderIds = orders.map((order) => order.id).join(",");
this._store.orderCompleted.next();
await this.patchProcess(processId);
await this._navigationService.getCheckoutSummaryPath({ processId, orderIds }).navigate();
await this._navigationService
.getCheckoutSummaryPath({ processId, orderIds })
.navigate();
} catch (error) {
const response = error?.error;
let message: string = response?.message ?? '';
let message: string = response?.message ?? "";
if (response?.invalidProperties && Object.values(response?.invalidProperties)?.length) {
message += `\n${Object.values(response.invalidProperties).join('\n')}`;
if (
response?.invalidProperties &&
Object.values(response?.invalidProperties)?.length
) {
message += `\n${Object.values(response.invalidProperties).join("\n")}`;
}
if (message?.length) {
this.uiModal.open({
content: UiMessageModalComponent,
title: 'Hinweis',
title: "Hinweis",
data: { message: message.trim() },
});
} else if (error) {
this.uiModal.error('Fehler beim abschließen der Bestellung', error);
this.uiModal.error("Fehler beim abschließen der Bestellung", error);
}
if (error.status === 409) {
this._store.orderCompleted.next();
await this.patchProcess(processId);
await this._navigationService.getCheckoutSummaryPath({ processId }).navigate();
await this._navigationService
.getCheckoutSummaryPath({ processId })
.navigate();
}
} finally {
this.showOrderButtonSpinner = false;
@@ -593,11 +701,14 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
}
async patchProcess(processId: number) {
const process = await this.applicationService.getProcessById$(processId).pipe(first()).toPromise();
const process = await this.applicationService
.getProcessById$(processId)
.pipe(first())
.toPromise();
if (process) {
this.applicationService.patchProcess(process.id, {
name: `${process.name} Bestellbestätigung`,
type: 'cart-checkout',
type: "cart-checkout",
});
}
}

View File

@@ -3,11 +3,11 @@ import {
ChangeDetectionStrategy,
Input,
ContentChild,
ElementRef,
ViewEncapsulation,
ChangeDetectorRef,
OnDestroy,
AfterContentInit,
inject,
} from '@angular/core';
import { NgControl } from '@angular/forms';
import { EmptyControl } from './empty-control';
@@ -22,7 +22,7 @@ import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';
styleUrls: ['form-control.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
host: { class: 'shared-form-control' },
host: { 'class': 'shared-form-control', '[attr.label]': 'label' },
imports: [FirstErrorPipe],
})
export class FormControlComponent implements OnDestroy, AfterContentInit {
@@ -32,6 +32,8 @@ export class FormControlComponent implements OnDestroy, AfterContentInit {
@ContentChild(NgControl, { static: true })
controlDirective: NgControl;
private _cdr = inject(ChangeDetectorRef);
get control() {
return this.controlDirective.control;
}
@@ -39,7 +41,10 @@ export class FormControlComponent implements OnDestroy, AfterContentInit {
required = false;
get displayLabel() {
return (this.label ?? this.control?.['name'] ?? '') + (this.required && this._hasRequiredMark ? '*' : '');
return (
(this.label ?? this.control?.['name'] ?? '') +
(this.required && this._hasRequiredMark ? '*' : '')
);
}
private _onDestroy$ = new Subject<void>();
@@ -50,17 +55,14 @@ export class FormControlComponent implements OnDestroy, AfterContentInit {
this._hasRequiredMark = coerceBooleanProperty(value);
}
constructor(
private _elementRef: ElementRef,
private _cdr: ChangeDetectorRef,
) {}
ngAfterContentInit() {
this.checkValidator();
this.control.statusChanges.pipe(takeUntil(this._onDestroy$)).subscribe(() => {
this.checkValidator();
this._cdr.markForCheck();
});
this.control.statusChanges
.pipe(takeUntil(this._onDestroy$))
.subscribe(() => {
this.checkValidator();
this._cdr.markForCheck();
});
}
ngOnDestroy() {
@@ -73,6 +75,4 @@ export class FormControlComponent implements OnDestroy, AfterContentInit {
this.required = !!errors?.required;
}
clickLabel() {}
}

View File

@@ -12,14 +12,24 @@
(focus)="clearHint(); focused.emit(true)"
(blur)="focused.emit(false)"
(keyup)="onKeyup($event)"
(keyup.enter)="tracker.trackEvent({ action: 'keyup enter', name: 'search' })"
(keyup.enter)="
tracker.trackEvent({ action: 'keyup enter', name: 'search' })
"
matomoTracker
#tracker="matomo"
matomoCategory="searchbox"
/>
<div *ngIf="showHint" class="searchbox-hint" (click)="focus()">{{ hint }}</div>
<div *ngIf="showHint" class="searchbox-hint" (click)="focus()">
{{ hint }}
</div>
</div>
<button (click)="clear(); focus()" tabindex="-1" *ngIf="input.value" class="searchbox-clear-btn" type="button">
<button
(click)="clear(); focus()"
tabindex="-1"
*ngIf="input.value"
class="searchbox-clear-btn"
type="button"
>
<shared-icon icon="close" [size]="32"></shared-icon>
</button>
<ng-container *ngIf="!loading">
@@ -27,7 +37,7 @@
tabindex="0"
class="searchbox-search-btn"
type="button"
*ngIf="!canScan"
*ngIf="!showScannerButton"
(click)="emitSearch()"
[disabled]="completeValue !== query"
matomoClickAction="click"
@@ -40,7 +50,7 @@
tabindex="0"
class="searchbox-scan-btn"
type="button"
*ngIf="canScan"
*ngIf="showScannerButton"
(click)="startScan()"
matomoClickAction="open"
matomoClickCategory="searchbox"

View File

@@ -31,7 +31,11 @@ import { EnvironmentService } from '@core/environment';
templateUrl: 'searchbox.component.html',
styleUrls: ['searchbox.component.scss'],
providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SearchboxComponent), multi: true },
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => SearchboxComponent),
multi: true,
},
],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false,
@@ -54,10 +58,10 @@ export class SearchboxComponent
autocomplete: UiAutocompleteComponent;
@Input()
focusAfterViewInit: boolean = true;
focusAfterViewInit = true;
@Input()
placeholder: string = '';
placeholder = '';
private _query = '';
@@ -90,7 +94,7 @@ export class SearchboxComponent
scanner = false;
@Input()
hint: string = '';
hint = '';
@Input()
autocompleteValueSelector: (item: any) => string = (item: any) => item;
@@ -113,6 +117,10 @@ export class SearchboxComponent
return this.#env.isMobileDevice() && this.scanAdapterService?.isReady();
}
get showScannerButton() {
return this.canScan && !this.query;
}
get canClear() {
return !!this.query;
}
@@ -123,9 +131,9 @@ export class SearchboxComponent
subscriptions = new Subscription();
onChange = (_: any) => {};
onChange?: (_: any) => void;
onTouched = () => {};
onTouched?: () => void;
constructor(
private cdr: ChangeDetectorRef,
@@ -186,12 +194,12 @@ export class SearchboxComponent
}
}
setQuery(query: string, emitEvent: boolean = true, complete?: boolean) {
setQuery(query: string, emitEvent = true, complete?: boolean) {
this._query = query;
if (emitEvent) {
this.queryChange.emit(query);
this.onChange(query);
this.onTouched();
this.onChange?.(query);
this.onTouched?.();
}
if (complete) {
this.completeValue = query;
@@ -227,7 +235,9 @@ export class SearchboxComponent
handleArrowUpDownEvent(event: KeyboardEvent) {
this.autocomplete?.handleKeyboardEvent(event);
if (this.autocomplete?.activeItem) {
const query = this.autocompleteValueSelector(this.autocomplete.activeItem.item);
const query = this.autocompleteValueSelector(
this.autocomplete.activeItem.item,
);
this.setQuery(query, false, false);
}
}

View File

@@ -5,6 +5,31 @@
@import "./scss/components";
/* Scanner Fullscreen Styles */
.full-screen-scanner {
max-width: 100vw !important;
max-height: 100vh !important;
width: 100vw !important;
height: 100vh !important;
.scanner-component {
width: 100%;
height: 100%;
}
}
/* Override CDK overlay container styles for scanner */
.cdk-overlay-container {
.full-screen-scanner {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: 0;
}
}
@import "./scss/root";
@import "./scss/customer";
@import "./scss/branch";

View File

@@ -1,4 +1,7 @@
@use '../../../libs/ui/buttons/src/buttons.scss';
@use '../../../libs/ui/datepicker/src/datepicker.scss';
@use '../../../libs/ui/dialog/src/dialog.scss';
@use '../../../libs/ui/input-controls/src/input-controls.scss';
@use '../../../libs/ui/menu/src/menu.scss';
@use '../../../libs/ui/progress-bar/src/lib/progress-bar.scss';
@use '../../../libs/ui/tooltip/src/tooltip.scss';

View File

@@ -1,5 +1,14 @@
import { argsToTemplate, type Meta, type StoryObj, moduleMetadata } from '@storybook/angular';
import { IconButtonColor, IconButtonSize, IconButtonComponent } from '@isa/ui/buttons';
import {
argsToTemplate,
type Meta,
type StoryObj,
moduleMetadata,
} from '@storybook/angular';
import {
IconButtonColor,
IconButtonSize,
IconButtonComponent,
} from '@isa/ui/buttons';
import { IsaIcons } from '@isa/icons';
import { NgIconComponent, provideIcons } from '@ng-icons/core';
@@ -28,7 +37,12 @@ const meta: Meta<UiIconButtonComponentInputs> = {
},
color: {
control: { type: 'select' },
options: ['brand', 'primary', 'secondary', 'tertiary'] as IconButtonColor[],
options: [
'brand',
'primary',
'secondary',
'tertiary',
] as IconButtonColor[],
description: 'Color style of the button',
},
size: {
@@ -54,8 +68,8 @@ const meta: Meta<UiIconButtonComponentInputs> = {
},
render: (args) => ({
props: args,
template: `<button uiIconButton ${argsToTemplate(args, { exclude: ['icon'] })} >
<ng-icon name="${args.icon}"></ng-icon>
template: `<button uiIconButton name="${args.icon}" ${argsToTemplate(args, { exclude: ['icon'] })} >
</button>`,
}),
};

View File

@@ -0,0 +1,49 @@
import { Component, Input } from '@angular/core';
import { ButtonComponent } from '@isa/ui/buttons';
import { ExpandableDirectives } from '@isa/ui/expandable';
import { argsToTemplate, type Meta, type StoryObj } from '@storybook/angular';
@Component({
selector: 'app-expandable-directives',
template: `
<div uiExpandable [(uiExpandable)]="isExpanded" class="border border-black">
<button uiButton uiExpandableTrigger>Toggle</button>
<div class="bg-red-200" *uiExpanded>Expanded Content</div>
<div class="bg-blue-200" *uiCollapsed>Collapsed Content</div>
</div>
`,
standalone: true,
imports: [ExpandableDirectives, ButtonComponent],
})
class ExpandableDirectivesComponent {
@Input()
isExpanded = false;
}
const meta: Meta<ExpandableDirectivesComponent> = {
title: 'ui/expandable/Expandable',
component: ExpandableDirectivesComponent,
argTypes: {
isExpanded: {
control: 'boolean',
description: 'Controls the expanded state of the section',
table: {
defaultValue: { summary: 'false' },
},
},
},
args: {
isExpanded: false,
},
render: (args) => ({
props: args,
template: `<app-expandable-directives ${argsToTemplate(args)}></app-expandable-directives>`,
}),
};
export default meta;
type Story = StoryObj<ExpandableDirectivesComponent>;
export const Default: Story = {
args: {},
};

View File

@@ -0,0 +1,110 @@
import { FormsModule, ReactiveFormsModule, FormControl } from '@angular/forms';
import {
StoryObj,
Meta,
moduleMetadata,
applicationConfig,
} from '@storybook/angular';
import {
ChecklistComponent,
ChecklistValueDirective,
CheckboxComponent,
CheckboxAppearance,
} from '@isa/ui/input-controls';
import { provideAnimations } from '@angular/platform-browser/animations';
import { importProvidersFrom } from '@angular/core';
interface ChecklistStoryProps {
values: string[];
options: string[];
disabled: boolean;
appearance: CheckboxAppearance;
}
const meta: Meta<ChecklistStoryProps> = {
title: 'ui/input-controls/Checklist',
component: ChecklistComponent,
decorators: [
moduleMetadata({
imports: [
FormsModule,
ReactiveFormsModule,
CheckboxComponent,
ChecklistValueDirective,
],
}),
applicationConfig({
providers: [
importProvidersFrom(FormsModule, ReactiveFormsModule),
provideAnimations(),
],
}),
],
argTypes: {
values: {
control: 'object',
description: 'Array of pre-selected values',
},
options: {
control: 'object',
description: 'Available options for the checklist',
},
disabled: {
control: 'boolean',
description: 'Whether the checklist is disabled',
},
appearance: {
control: 'select',
options: Object.values(CheckboxAppearance),
description: 'The appearance style of the checkboxes',
},
},
args: {
values: ['Option 1', 'Option 3'],
options: ['Option 1', 'Option 2', 'Option 3', 'Option 4'],
disabled: false,
appearance: CheckboxAppearance.Checkbox,
},
render: (args) => ({
props: {
...args,
selectedValues: [...args.values],
},
template: `
<div class="p-4">
<h3 class="mb-2 font-medium">Selected values: {{ selectedValues | json }}</h3>
<ui-checklist [(ngModel)]="selectedValues" [disabled]="disabled">
<label *ngFor="let option of options" class="ui-checkbox-label flex items-center gap-2">
<ui-checkbox [appearance]="appearance">
<input type="checkbox" [uiChecklistValue]="option" />
</ui-checkbox>
{{ option }}
</label>
</ui-checklist>
</div>
`,
}),
parameters: {
docs: {
description: {
component: `
The Checklist component manages a group of checkboxes as a form control.
It can be used with both template-driven and reactive forms.
`,
},
},
},
};
export default meta;
type Story = StoryObj<ChecklistStoryProps>;
// Basic example with ngModel
export const Default: Story = {};
// Example with bullet appearance
export const BulletAppearance: Story = {
args: {
appearance: CheckboxAppearance.Bullet,
},
};

View File

@@ -1,24 +1,72 @@
import { type Meta, type StoryObj } from '@storybook/angular';
import { TextFieldComponent } from '@isa/ui/input-controls';
import { moduleMetadata, type Meta, type StoryObj } from '@storybook/angular';
import {
TextFieldClearComponent,
TextFieldComponent,
TextFieldContainerComponent,
TextFieldErrorsComponent,
} from '@isa/ui/input-controls';
const meta: Meta<TextFieldComponent> = {
interface TextFieldStoryProps {
showClear: boolean;
showError1: boolean;
showError2: boolean;
errorText1: string;
errorText2: string;
}
const meta: Meta<TextFieldStoryProps> = {
component: TextFieldComponent,
title: 'ui/input-controls/TextField',
argTypes: {},
argTypes: {
showClear: { control: 'boolean', name: 'Show Clear Button' },
showError1: { control: 'boolean', name: 'Show Error 1' },
showError2: { control: 'boolean', name: 'Show Error 2' },
errorText1: { control: 'text', name: 'Error 1 Text' },
errorText2: { control: 'text', name: 'Error 2 Text' },
},
args: {
showClear: true,
showError1: false,
showError2: false,
errorText1: 'Eingabe ungültig',
errorText2: 'Error Beispiel 2',
},
decorators: [
moduleMetadata({
imports: [
TextFieldClearComponent,
TextFieldContainerComponent,
TextFieldErrorsComponent,
],
}),
],
render: (args) => ({
props: args,
template: `
<ui-text-field-container>
<ui-text-field>
<input type="text" placeholder="Enter your name" />
<input type="text" placeholder="Enter your name" />
<ui-text-field-clear *ngIf="showClear"></ui-text-field-clear>
</ui-text-field>
<ui-text-field-errors>
<span *ngIf="showError1">{{ errorText1 }}</span>
<span *ngIf="showError2">{{ errorText2 }}</span>
</ui-text-field-errors>
</ui-text-field-container>
`,
}),
};
export default meta;
type Story = StoryObj<TextFieldComponent>;
type Story = StoryObj<TextFieldStoryProps>;
export const Default: Story = {
args: {},
args: {
showClear: true,
showError1: false,
showError2: false,
errorText1: 'Eingabe ungültig',
errorText2: 'Error Beispiel 2',
},
};

View File

@@ -1,9 +1,13 @@
import { type Meta, type StoryObj, moduleMetadata } from '@storybook/angular';
import { ClientRowComponent, ClientRowImports, ItemRowDataImports } from '@isa/ui/item-rows';
import { type Meta, type StoryObj, moduleMetadata } from "@storybook/angular";
import {
ClientRowComponent,
ClientRowImports,
ItemRowDataImports,
} from "@isa/ui/item-rows";
const meta: Meta<ClientRowComponent> = {
component: ClientRowComponent,
title: 'ui/item-rows/ClientRow',
title: "ui/item-rows/ClientRow",
decorators: [
moduleMetadata({
imports: [ClientRowImports, ItemRowDataImports],
@@ -21,25 +25,25 @@ const meta: Meta<ClientRowComponent> = {
<ui-item-row-data-row>
<ui-item-row-data-label>Belegdatum</ui-item-row-data-label>
<ui-item-row-data-value>
<span class="isa-text-body-2-bold">
<span class="isa-text-body-2-bold">
01.11.2024
</span>
</ui-item-row-data-value>
</ui-item-row-data-row>
<ui-item-row-data-row>
<ui-item-row-data-label>Rechnugsnr.</ui-item-row-data-label>
<ui-item-row-data-label>Beleg-Nr.</ui-item-row-data-label>
<ui-item-row-data-value>
<span class="isa-text-body-2-bold">
<span class="isa-text-body-2-bold">
1234567890
</span>
</ui-item-row-data-value>
</ui-item-row-data-row>
<ui-item-row-data-row>
<ui-item-row-data-label >Vorgangs-ID</ui-item-row-data-label>
<ui-item-row-data-value >
<span class="isa-text-body-2-bold">
640175214390060/0
</span>
<ui-item-row-data-value >
<span class="isa-text-body-2-bold">
640175214390060/0
</span>
</ui-item-row-data-value>
</ui-item-row-data-row>
</ui-item-row-data>

View File

@@ -8,8 +8,6 @@ import {
UiSearchBarClearComponent,
UiSearchBarComponent,
} from '@isa/ui/search-bar';
import { NgIconComponent, provideIcons } from '@ng-icons/core';
import { isaActionSearch } from '@isa/icons';
import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { IconButtonComponent } from '@isa/ui/buttons';
@@ -29,11 +27,9 @@ const meta: Meta<UiSearchBarComponentInputs> = {
imports: [
IconButtonComponent,
UiSearchBarClearComponent,
NgIconComponent,
FormsModule,
ReactiveFormsModule,
],
providers: [provideIcons({ isaActionSearch })],
}),
],
title: 'ui/search-bar/SearchBar',
@@ -62,10 +58,10 @@ const meta: Meta<UiSearchBarComponentInputs> = {
if (args.appearance === 'main') {
button =
'<button type="submit" uiIconButton color="brand"><ng-icon name="isaActionSearch"></ng-icon></button>';
'<button type="submit" uiIconButton name="isaActionSearch" color="brand"></button>';
} else if (args.appearance === 'results') {
button =
'<button type="submit" uiIconButton prefix color="neutral"><ng-icon name="isaActionSearch"></ng-icon></button>';
'<button type="submit" uiIconButton prefix name="isaActionSearch" color="neutral"></button>';
}
return {

View File

@@ -0,0 +1,39 @@
import { type Meta, type StoryObj, argsToTemplate } from '@storybook/angular';
import { TooltipDirective } from '@isa/ui/tooltip';
const meta: Meta<TooltipDirective> = {
title: 'UI/Tooltip',
component: TooltipDirective,
argTypes: {
title: { control: 'text' },
content: { control: 'text' },
triggerOn: {
control: 'multi-select',
options: ['click', 'hover', 'focus'],
},
},
args: {
title: 'Tooltip Title',
content: 'This is the tooltip content.',
triggerOn: ['click', 'hover', 'focus'],
},
render: (args) => ({
props: args,
template: `
<button uiTooltip ${argsToTemplate(args)} >
Hover or click me
</button>
`,
}),
};
export default meta;
type Story = StoryObj<TooltipDirective>;
export const Default: Story = {
args: {
title: 'Default Tooltip',
content: 'This is the default tooltip content.',
triggerOn: ['hover', 'click'],
},
};

View File

@@ -9,10 +9,10 @@ trigger:
variables:
# Major Version einstellen
- name: 'Major'
value: '3'
value: '4'
# Minor Version einstellen
- name: 'Minor'
value: '4'
value: '0'
- name: 'Patch'
value: "$[counter(format('{0}.{1}', variables['Major'], variables['Minor']),0)]"
- name: 'BuildUniqueID'
@@ -20,7 +20,6 @@ variables:
- group: 'GithubCMF'
jobs:
- job: unittests
displayName: Unit Tests
pool:
@@ -55,17 +54,17 @@ jobs:
- task: PublishTestResults@2
displayName: Publish Test results
inputs:
testResultsFiles: '**/TESTS*.xml'
testResultsFiles: '**/TESTS-*.xml'
searchFolder: $(Build.StagingDirectory)/testresults
testResultsFormat: JUnit
mergeTestResults: false
failTaskOnFailedTests: true
condition: always()
- task: PublishCodeCoverageResults@1
- task: PublishCodeCoverageResults@2
displayName: Publish code Coverage
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: $(Build.StagingDirectory)/coverage/**/cobertura.xml
summaryFileLocation: $(Build.StagingDirectory)/coverage/**/cobertura-coverage.xml
pathToSources: $(Build.SourcesDirectory)
condition: always()
- bash: |
@@ -96,7 +95,6 @@ jobs:
$(Build.BuildNumber)-$(Build.SourceVersion)
$(DockerTagSourceBranch)
steps:
- task: npmAuthenticate@0
displayName: 'npm auth'
inputs:
@@ -158,7 +156,7 @@ jobs:
- Agent.OS -equals Linux
- docker
condition: or(eq(variables['Build.SourceBranch'], 'refs/heads/integration'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), startsWith(variables['Build.SourceBranch'], 'refs/heads/hotfix/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'))
variables:
variables:
- name: DockerTagSourceBranch
value: $[replace(variables['Build.SourceBranch'], '/', '_')]
- name: 'DockerTag'
@@ -195,7 +193,6 @@ jobs:
repository: 'isa/ui'
command: 'push'
tags: '$(DockerTag)'
- task: PublishBuildArtifacts@1
displayName: 'Artefakt veröffentlichen: HelmValues'

View File

@@ -200,6 +200,7 @@ This section extends the core code style principles with Angular-specific and ad
- **File Organization**: Structure files according to features and follow the recommended folder structure.
- **Control Flow**: Use modern control flow syntax (@if, @for) instead of structural directives (*ngIf, *ngFor).
- **Signals**: Prefer signals over RxJS for simpler state management within components.
- **Standalone by Default**: Components and directives are standalone by default. The `standalone: true` flag is unnecessary. Only specify `standalone: false` when a component or directive explicitly needs to be part of an NgModule.
### TypeScript Enhancements
@@ -309,6 +310,7 @@ This section extends the core code style principles with Angular-specific and ad
- **Functions and Methods**:
- Always export functions as arrow function expressions (const) instead of function declarations
- Use arrow functions for callbacks and class methods
- Explicitly type parameters and return values
- Keep functions pure when possible
@@ -322,16 +324,21 @@ This section extends the core code style principles with Angular-specific and ad
* @param id - The user's unique identifier
* @param includeDetails - Whether to include additional user details
*/
const getUser = (id: string, includeDetails = false): Promise<User> => {
export const getUser = (id: string, includeDetails = false): Promise<User> => {
// ...implementation
};
// Bad
function getUser(id) {
export function getUser(id) {
// ...implementation
}
```
// Reason for using arrow function expressions:
// 1. More consistent with modern JavaScript practices
// 2. Easier to mock in unit tests
// 3. Avoids 'this' binding issues
- **Generics**:
- Use meaningful type parameter names (e.g., `T` for type, `K` for key)
- Constrain generic types when possible using `extends`
@@ -487,6 +494,203 @@ function getUser(id) {
}
```
## Error Logging
Proper error logging is critical for diagnosing issues in production applications. Always use the `@isa/core/logging` module for logging throughout the application.
### Basic Logging Guidelines
- Always use the appropriate log level for the situation:
- `trace` - For fine-grained debugging information
- `debug` - For development-time debugging information
- `info` - For general runtime information
- `warn` - For potential issues that don't interrupt operation
- `error` - For errors that affect functionality
### Setting Up Logging
Use the logger factory function to create loggers in your components and services:
```typescript
import { logger } from '@isa/core/logging';
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
})
export class ExampleComponent implements OnInit {
// Create a private logger instance
#logger = logger();
constructor(private userService: UserService) {}
ngOnInit(): void {
this.#logger.info('Component initialized');
}
}
```
### Context-Aware Logging
Always provide relevant context when logging:
```typescript
// Good - With detailed context
this.#logger.error(
'Failed to load user data',
error,
{ userId: '123', attempt: 2, source: 'UserProfileComponent' }
);
// Bad - No context for troubleshooting
this.#logger.error('Failed to load user data');
```
### Component and Service Level Context
Use the `provideLoggerContext` to set component-level context:
```typescript
@Component({
selector: 'app-user-profile',
templateUrl: './user-profile.component.html',
providers: [
provideLoggerContext({
component: 'UserProfile',
section: 'Account'
})
]
})
export class UserProfileComponent {
#logger = logger();
// All logs from this component will include the context
updateProfile(): void {
this.#logger.info('Updating user profile');
// Log output will include { component: 'UserProfile', section: 'Account' }
}
}
```
### Error Handling Best Practices
1. **Always log the original Error object**:
```typescript
// Good - Includes the original error with stack trace
try {
// risky operation
} catch (error) {
this.#logger.error('Operation failed', error, { context: 'additional data' });
}
// Bad - Loses the stack trace and error details
try {
// risky operation
} catch (error) {
this.#logger.error(`Operation failed: ${error}`);
}
```
2. **Structure error handling with contextual information**:
```typescript
saveData(data: UserData): void {
this.userService.save(data).pipe(
catchError((error) => {
this.#logger.error(
'Failed to save user data',
error,
{
userId: data.id,
dataSize: JSON.stringify(data).length,
operation: 'saveData'
}
);
// Handle the error appropriately
return throwError(() => new Error('Failed to save data'));
})
).subscribe();
}
```
3. **Use log levels appropriately**:
```typescript
// Debug information during development
this.#logger.debug('Processing data batch', { batchSize: items.length });
// General information during runtime
this.#logger.info('User logged in', { userId: user.id });
// Potential issues that don't break functionality
this.#logger.warn('API response slow', { responseTime: '2500ms', endpoint: '/users' });
// Errors that affect functionality
this.#logger.error('Payment processing failed', error, { orderId: order.id });
```
4. **In RxJS operators, use tap for logging**:
```typescript
return this.http.get<User[]>('/api/users').pipe(
tap({
next: (users) => this.#logger.info('Users loaded', { count: users.length }),
error: (error) => this.#logger.error('Failed to load users', error)
}),
catchError((error) => {
this.#logger.error('Error in users API call', error, { retry: true });
return this.fallbackUserService.getUsers();
})
);
```
5. **Log lifecycle events when relevant**:
```typescript
export class ImportantComponent implements OnInit, OnDestroy {
#logger = logger();
ngOnInit(): void {
this.#logger.debug('Component initialized');
}
ngOnDestroy(): void {
this.#logger.debug('Component destroyed');
}
}
```
### Performance Considerations
- Avoid expensive operations in log messages in production:
```typescript
// Bad - Performs expensive operation even if debug level is disabled
this.#logger.debug('Data state:', JSON.stringify(this.largeDataObject));
// Good - Only performs expensive operation if needed
if (isDevMode()) {
this.#logger.debug('Data state:', { data: this.largeDataObject });
}
```
- Consider log level in production environments:
```typescript
// In app.config.ts
export const appConfig: ApplicationConfig = {
providers: [
// Other providers...
provideLogging(
withLogLevel(isDevMode() ? LogLevel.Debug : LogLevel.Warn),
withSink(ConsoleLogSink)
)
]
};
```
## Project-Specific Preferences
- **Frameworks**: Follow best practices for Nx, Angular, date-fns, Ngrx, RxJs and Zod.

View File

File diff suppressed because it is too large Load Diff

View File

@@ -225,6 +225,7 @@ export { PaymentInfoDTO } from './models/payment-info-dto';
export { EntityDTOContainerOfReceiptItemDTO } from './models/entity-dtocontainer-of-receipt-item-dto';
export { ReceiptItemDTO } from './models/receipt-item-dto';
export { EntityReferenceTypeDTO } from './models/entity-reference-type-dto';
export { ReferencedInOtherReceiptDTO } from './models/referenced-in-other-receipt-dto';
export { EntityDTOBaseOfReceiptItemDTOAndIReceiptItem } from './models/entity-dtobase-of-receipt-item-dtoand-ireceipt-item';
export { ShippingAddressDTO2 } from './models/shipping-address-dto2';
export { EntityDTOBaseOfReceiptDTOAndIReceipt } from './models/entity-dtobase-of-receipt-dtoand-ireceipt';
@@ -236,17 +237,22 @@ export { OrderItemStatusValuesDTO } from './models/order-item-status-values-dto'
export { ResponseArgsOfPayerDTO } from './models/response-args-of-payer-dto';
export { ResponseArgsOfShippingAddressDTO } from './models/response-args-of-shipping-address-dto';
export { ResponseArgsOfReceiptDTO } from './models/response-args-of-receipt-dto';
export { ReturnReceiptValuesDTO } from './models/return-receipt-values-dto';
export { ResponseArgsOfReceiptItemTaskListItemDTO } from './models/response-args-of-receipt-item-task-list-item-dto';
export { ReceiptItemTaskListItemDTO } from './models/receipt-item-task-list-item-dto';
export { ResponseArgsOfIEnumerableOfReceiptDTO } from './models/response-args-of-ienumerable-of-receipt-dto';
export { GenerateCollectiveReceiptsArgs } from './models/generate-collective-receipts-args';
export { ResponseArgsOfIEnumerableOfString } from './models/response-args-of-ienumerable-of-string';
export { DateRange } from './models/date-range';
export { ResponseArgsOfString } from './models/response-args-of-string';
export { ListResponseArgsOfReceiptItemTaskListItemDTO } from './models/list-response-args-of-receipt-item-task-list-item-dto';
export { ResponseArgsOfIEnumerableOfReceiptItemTaskListItemDTO } from './models/response-args-of-ienumerable-of-receipt-item-task-list-item-dto';
export { ListResponseArgsOfReceiptListItemDTO } from './models/list-response-args-of-receipt-list-item-dto';
export { ResponseArgsOfIEnumerableOfReceiptListItemDTO } from './models/response-args-of-ienumerable-of-receipt-list-item-dto';
export { ReceiptListItemDTO } from './models/receipt-list-item-dto';
export { ListResponseArgsOfReceiptItemListItemDTO } from './models/list-response-args-of-receipt-item-list-item-dto';
export { ResponseArgsOfIEnumerableOfReceiptItemListItemDTO } from './models/response-args-of-ienumerable-of-receipt-item-list-item-dto';
export { ReceiptItemListItemDTO } from './models/receipt-item-list-item-dto';
export { ReturnReceiptValuesDTO } from './models/return-receipt-values-dto';
export { ResponseArgsOfIEnumerableOfValueTupleOfLongAndReceiptTypeAndEntityDTOContainerOfReceiptDTO } from './models/response-args-of-ienumerable-of-value-tuple-of-long-and-receipt-type-and-entity-dtocontainer-of-receipt-dto';
export { ValueTupleOfLongAndReceiptTypeAndEntityDTOContainerOfReceiptDTO } from './models/value-tuple-of-long-and-receipt-type-and-entity-dtocontainer-of-receipt-dto';
export { ReceiptOrderItemSubsetReferenceValues } from './models/receipt-order-item-subset-reference-values';

View File

@@ -0,0 +1,24 @@
/* tslint:disable */
import { ResponseArgsOfIEnumerableOfReceiptItemTaskListItemDTO } from './response-args-of-ienumerable-of-receipt-item-task-list-item-dto';
export interface ListResponseArgsOfReceiptItemTaskListItemDTO extends ResponseArgsOfIEnumerableOfReceiptItemTaskListItemDTO{
/**
* Completed
*/
completed?: boolean;
/**
* Hits
*/
hits?: number;
/**
* Skip
*/
skip?: number;
/**
* Take
*/
take?: number;
}

View File

@@ -2,9 +2,11 @@
import { EntityDTOBaseOfReceiptDTOAndIReceipt } from './entity-dtobase-of-receipt-dtoand-ireceipt';
import { PayerDTO2 } from './payer-dto2';
import { BuyerDTO } from './buyer-dto';
import { EntityDTOContainerOfBranchDTO } from './entity-dtocontainer-of-branch-dto';
import { KeyValueDTOOfStringAndString } from './key-value-dtoof-string-and-string';
import { EntityDTOContainerOfReceiptItemDTO } from './entity-dtocontainer-of-receipt-item-dto';
import { EntityDTOContainerOfLabelDTO } from './entity-dtocontainer-of-label-dto';
import { LinkedRecordDTO } from './linked-record-dto';
import { EntityDTOContainerOfOrderDTO } from './entity-dtocontainer-of-order-dto';
import { EntityDTOContainerOfPaymentDTO } from './entity-dtocontainer-of-payment-dto';
import { PaymentInfoDTO } from './payment-info-dto';
@@ -36,6 +38,11 @@ export interface ReceiptDTO extends EntityDTOBaseOfReceiptDTOAndIReceipt{
*/
chargePostage?: boolean;
/**
* Label
*/
createdInBranch?: EntityDTOContainerOfBranchDTO;
/**
* Dateinamen (Separator: ";") der Belegdateien
*/
@@ -51,6 +58,11 @@ export interface ReceiptDTO extends EntityDTOBaseOfReceiptDTOAndIReceipt{
*/
label?: EntityDTOContainerOfLabelDTO;
/**
* Verknüpfte Datensätze (readonly)
*/
linkedRecords?: Array<LinkedRecordDTO>;
/**
* Bestellung
*/

View File

@@ -15,6 +15,7 @@ import { PromotionDTO } from './promotion-dto';
import { QuantityDTO } from './quantity-dto';
import { EntityDTOContainerOfReceiptDTO } from './entity-dtocontainer-of-receipt-dto';
import { EntityDTOReferenceContainer } from './entity-dtoreference-container';
import { ReferencedInOtherReceiptDTO } from './referenced-in-other-receipt-dto';
import { EntityDTOContainerOfSupplierDTO } from './entity-dtocontainer-of-supplier-dto';
export interface ReceiptItemDTO extends EntityDTOBaseOfReceiptItemDTOAndIReceiptItem{
_Parent?: EntityDTOContainerOfReceiptItemDTO;
@@ -221,6 +222,12 @@ export interface ReceiptItemDTO extends EntityDTOBaseOfReceiptItemDTOAndIReceipt
*/
referencedEntity?: EntityDTOReferenceContainer;
/**
* Referenced in other receipts / Referenziert in anderen Belegen
* readonly
*/
referencedInOtherReceipts?: Array<ReferencedInOtherReceiptDTO>;
/**
* Referenz zu anderem Posten
* z.B. Lieferscheinposition => Rechnungsposition

View File

@@ -0,0 +1,127 @@
/* tslint:disable */
import { KeyValueDTOOfStringAndString } from './key-value-dtoof-string-and-string';
import { AddresseeDTO } from './addressee-dto';
import { ProductDTO } from './product-dto';
import { EntityDTOContainerOfReceiptDTO } from './entity-dtocontainer-of-receipt-dto';
import { EntityDTOContainerOfReceiptItemDTO } from './entity-dtocontainer-of-receipt-item-dto';
/**
* Bestellpostenstatus-Aufgabe
*/
export interface ReceiptItemTaskListItemDTO {
/**
* Mögliche Aktionen
*/
actions?: Array<KeyValueDTOOfStringAndString>;
/**
* Rechnung
*/
billing?: AddresseeDTO;
/**
* Auftraggeber
*/
buyer?: AddresseeDTO;
/**
* Annulliert
*/
canceled?: string;
/**
* Abgeschlossen
*/
completed?: string;
/**
* Aufgabentyp Detail
*/
description?: string;
/**
* Zusätzliche Markierungen
*/
features?: {[key: string]: string};
/**
* Details
*/
handlingDetails?: string;
/**
* Reason / Grund
*/
handlingReason?: string;
/**
* Task ID
*/
id?: number;
/**
* Item condition / Artikelzustand
*/
itemCondition?: string;
/**
* Aufgabentyp
*/
name?: string;
/**
* Task PId
*/
pId?: string;
/**
* Auftraggeber-Nr
*/
payerNumber?: string;
/**
* Anmerkung zur Verarbeitung
*/
processingComment?: string;
/**
* Referenz (UId) des verarbeinden Systems
*/
processingReference?: string;
/**
* Artikel-/Produktdaten
*/
product?: ProductDTO;
/**
* Bestellung
*/
receipt?: EntityDTOContainerOfReceiptDTO;
/**
* Bestellposten
*/
receiptItem?: EntityDTOContainerOfReceiptItemDTO;
/**
* Belegnummer
*/
receiptNumber?: string;
/**
* Lieferung
*/
shipping?: AddresseeDTO;
/**
* Task date
*/
taskDate?: string;
/**
* Typ
*/
type?: string;
}

View File

@@ -0,0 +1,23 @@
/* tslint:disable */
import { ReceiptType } from './receipt-type';
/**
* Referenced in other receipt / Referenziert in anderem Beleg
*/
export interface ReferencedInOtherReceiptDTO {
/**
* Quantity / Menge
*/
quantity: number;
/**
* Receipt number / Belegnummer
*/
receiptNumber?: string;
/**
* Receipt type / Belegart
*/
receiptType: ReceiptType;
}

View File

@@ -0,0 +1,10 @@
/* tslint:disable */
import { ResponseArgs } from './response-args';
import { ReceiptItemTaskListItemDTO } from './receipt-item-task-list-item-dto';
export interface ResponseArgsOfIEnumerableOfReceiptItemTaskListItemDTO extends ResponseArgs{
/**
* Wert
*/
result?: Array<ReceiptItemTaskListItemDTO>;
}

View File

@@ -0,0 +1,10 @@
/* tslint:disable */
import { ResponseArgs } from './response-args';
import { ReceiptItemTaskListItemDTO } from './receipt-item-task-list-item-dto';
export interface ResponseArgsOfReceiptItemTaskListItemDTO extends ResponseArgs{
/**
* Wert
*/
result?: ReceiptItemTaskListItemDTO;
}

View File

@@ -0,0 +1,9 @@
/* tslint:disable */
import { ResponseArgs } from './response-args';
export interface ResponseArgsOfString extends ResponseArgs{
/**
* Wert
*/
result?: string;
}

View File

@@ -7,6 +7,11 @@ import { EntityDTOContainerOfReceiptItemDTO } from './entity-dtocontainer-of-rec
*/
export interface ReturnReceiptValuesDTO {
/**
* Category / Artikelkategorie
*/
category?: string;
/**
* Comment / Anmerkung
*/

View File

@@ -9,14 +9,18 @@ import { map as __map, filter as __filter } from 'rxjs/operators';
import { ResponseArgsOfQuerySettingsDTO } from '../models/response-args-of-query-settings-dto';
import { ResponseArgsOfReceiptDTO } from '../models/response-args-of-receipt-dto';
import { ResponseArgsOfBoolean } from '../models/response-args-of-boolean';
import { ReturnReceiptValuesDTO } from '../models/return-receipt-values-dto';
import { ResponseArgsOfReceiptItemTaskListItemDTO } from '../models/response-args-of-receipt-item-task-list-item-dto';
import { ResponseArgsOfIEnumerableOfReceiptDTO } from '../models/response-args-of-ienumerable-of-receipt-dto';
import { GenerateCollectiveReceiptsArgs } from '../models/generate-collective-receipts-args';
import { ResponseArgsOfIEnumerableOfString } from '../models/response-args-of-ienumerable-of-string';
import { DateRange } from '../models/date-range';
import { ListResponseArgsOfReceiptListItemDTO } from '../models/list-response-args-of-receipt-list-item-dto';
import { ResponseArgsOfString } from '../models/response-args-of-string';
import { ListResponseArgsOfReceiptItemTaskListItemDTO } from '../models/list-response-args-of-receipt-item-task-list-item-dto';
import { QueryTokenDTO } from '../models/query-token-dto';
import { ListResponseArgsOfReceiptListItemDTO } from '../models/list-response-args-of-receipt-list-item-dto';
import { ListResponseArgsOfReceiptItemListItemDTO } from '../models/list-response-args-of-receipt-item-list-item-dto';
import { ReturnReceiptValuesDTO } from '../models/return-receipt-values-dto';
import { ResponseArgsOfIEnumerableOfValueTupleOfLongAndReceiptTypeAndEntityDTOContainerOfReceiptDTO } from '../models/response-args-of-ienumerable-of-value-tuple-of-long-and-receipt-type-and-entity-dtocontainer-of-receipt-dto';
import { ReceiptOrderItemSubsetReferenceValues } from '../models/receipt-order-item-subset-reference-values';
@Injectable({
@@ -25,8 +29,13 @@ import { ReceiptOrderItemSubsetReferenceValues } from '../models/receipt-order-i
class ReceiptService extends __BaseService {
static readonly ReceiptQueryReceiptSettingsPath = '/receipt/s/settings';
static readonly ReceiptGetReceiptPath = '/receipt/{receiptId}';
static readonly ReceiptCanReturnPath = '/receipt/item/can-return';
static readonly ReceiptSetReceiptItemTaskToOKPath = '/receipt/item/task/{taskId}/ok';
static readonly ReceiptSetReceiptItemTaskToNOKPath = '/receipt/item/task/{taskId}/nok';
static readonly ReceiptGenerateCollectiveReceiptsPath = '/receipt/collectivereceipts';
static readonly ReceiptGenerateCollectiveReceiptsSimulationSummaryPath = '/receipt/collectivereceipts/simulationsummary';
static readonly ReceiptPostRuecknahmebelegPath = '/ruecknahmebeleg/{receiptId}';
static readonly ReceiptQueryReceiptItemTasksPath = '/receipt/item/task/s';
static readonly ReceiptQueryReceiptPath = '/receipt/s';
static readonly ReceiptQueryReceiptItemPath = '/receipt/item/s';
static readonly ReceiptCreateShippingNotePath = '/receipt/shippingnote/fromorder';
@@ -34,6 +43,7 @@ class ReceiptService extends __BaseService {
static readonly ReceiptCreateInvoicePath = '/receipt/invoice/fromorder';
static readonly ReceiptCreateInvoice2Path = '/receipt/invoice/fromitems';
static readonly ReceiptCreateReturnReceiptPath = '/receipt/return-receipt';
static readonly ReceiptReceiptItemTaskCompletedPath = '/receipt/item/task/{taskId}/completed';
static readonly ReceiptGetReceiptsByOrderItemSubsetPath = '/order/orderitem/orderitemsubset/receipts';
constructor(
@@ -119,6 +129,114 @@ class ReceiptService extends __BaseService {
);
}
/**
* Prüfen, ob eine Rückgabe möglich ist
* @param item undefined
*/
ReceiptCanReturnResponse(item: ReturnReceiptValuesDTO): __Observable<__StrictHttpResponse<ResponseArgsOfBoolean>> {
let __params = this.newParams();
let __headers = new HttpHeaders();
let __body: any = null;
__body = item;
let req = new HttpRequest<any>(
'POST',
this.rootUrl + `/receipt/item/can-return`,
__body,
{
headers: __headers,
params: __params,
responseType: 'json'
});
return this.http.request<any>(req).pipe(
__filter(_r => _r instanceof HttpResponse),
__map((_r) => {
return _r as __StrictHttpResponse<ResponseArgsOfBoolean>;
})
);
}
/**
* Prüfen, ob eine Rückgabe möglich ist
* @param item undefined
*/
ReceiptCanReturn(item: ReturnReceiptValuesDTO): __Observable<ResponseArgsOfBoolean> {
return this.ReceiptCanReturnResponse(item).pipe(
__map(_r => _r.body as ResponseArgsOfBoolean)
);
}
/**
* Aufgabe in eine "OK"-Aufgabe ändern
* @param taskId undefined
*/
ReceiptSetReceiptItemTaskToOKResponse(taskId: number): __Observable<__StrictHttpResponse<ResponseArgsOfReceiptItemTaskListItemDTO>> {
let __params = this.newParams();
let __headers = new HttpHeaders();
let __body: any = null;
let req = new HttpRequest<any>(
'PATCH',
this.rootUrl + `/receipt/item/task/${encodeURIComponent(String(taskId))}/ok`,
__body,
{
headers: __headers,
params: __params,
responseType: 'json'
});
return this.http.request<any>(req).pipe(
__filter(_r => _r instanceof HttpResponse),
__map((_r) => {
return _r as __StrictHttpResponse<ResponseArgsOfReceiptItemTaskListItemDTO>;
})
);
}
/**
* Aufgabe in eine "OK"-Aufgabe ändern
* @param taskId undefined
*/
ReceiptSetReceiptItemTaskToOK(taskId: number): __Observable<ResponseArgsOfReceiptItemTaskListItemDTO> {
return this.ReceiptSetReceiptItemTaskToOKResponse(taskId).pipe(
__map(_r => _r.body as ResponseArgsOfReceiptItemTaskListItemDTO)
);
}
/**
* Aufgabe in eine "NOK"-Aufgabe ändern
* @param taskId undefined
*/
ReceiptSetReceiptItemTaskToNOKResponse(taskId: number): __Observable<__StrictHttpResponse<ResponseArgsOfReceiptItemTaskListItemDTO>> {
let __params = this.newParams();
let __headers = new HttpHeaders();
let __body: any = null;
let req = new HttpRequest<any>(
'PATCH',
this.rootUrl + `/receipt/item/task/${encodeURIComponent(String(taskId))}/nok`,
__body,
{
headers: __headers,
params: __params,
responseType: 'json'
});
return this.http.request<any>(req).pipe(
__filter(_r => _r instanceof HttpResponse),
__map((_r) => {
return _r as __StrictHttpResponse<ResponseArgsOfReceiptItemTaskListItemDTO>;
})
);
}
/**
* Aufgabe in eine "NOK"-Aufgabe ändern
* @param taskId undefined
*/
ReceiptSetReceiptItemTaskToNOK(taskId: number): __Observable<ResponseArgsOfReceiptItemTaskListItemDTO> {
return this.ReceiptSetReceiptItemTaskToNOKResponse(taskId).pipe(
__map(_r => _r.body as ResponseArgsOfReceiptItemTaskListItemDTO)
);
}
/**
* Sammelrechnungen erstellen
* @param payload undefined
@@ -191,6 +309,74 @@ class ReceiptService extends __BaseService {
);
}
/**
* @param receiptId undefined
*/
ReceiptPostRuecknahmebelegResponse(receiptId: number): __Observable<__StrictHttpResponse<ResponseArgsOfString>> {
let __params = this.newParams();
let __headers = new HttpHeaders();
let __body: any = null;
let req = new HttpRequest<any>(
'POST',
this.rootUrl + `/ruecknahmebeleg/${encodeURIComponent(String(receiptId))}`,
__body,
{
headers: __headers,
params: __params,
responseType: 'json'
});
return this.http.request<any>(req).pipe(
__filter(_r => _r instanceof HttpResponse),
__map((_r) => {
return _r as __StrictHttpResponse<ResponseArgsOfString>;
})
);
}
/**
* @param receiptId undefined
*/
ReceiptPostRuecknahmebeleg(receiptId: number): __Observable<ResponseArgsOfString> {
return this.ReceiptPostRuecknahmebelegResponse(receiptId).pipe(
__map(_r => _r.body as ResponseArgsOfString)
);
}
/**
* @param queryToken undefined
*/
ReceiptQueryReceiptItemTasksResponse(queryToken: QueryTokenDTO): __Observable<__StrictHttpResponse<ListResponseArgsOfReceiptItemTaskListItemDTO>> {
let __params = this.newParams();
let __headers = new HttpHeaders();
let __body: any = null;
__body = queryToken;
let req = new HttpRequest<any>(
'POST',
this.rootUrl + `/receipt/item/task/s`,
__body,
{
headers: __headers,
params: __params,
responseType: 'json'
});
return this.http.request<any>(req).pipe(
__filter(_r => _r instanceof HttpResponse),
__map((_r) => {
return _r as __StrictHttpResponse<ListResponseArgsOfReceiptItemTaskListItemDTO>;
})
);
}
/**
* @param queryToken undefined
*/
ReceiptQueryReceiptItemTasks(queryToken: QueryTokenDTO): __Observable<ListResponseArgsOfReceiptItemTaskListItemDTO> {
return this.ReceiptQueryReceiptItemTasksResponse(queryToken).pipe(
__map(_r => _r.body as ListResponseArgsOfReceiptItemTaskListItemDTO)
);
}
/**
* Belege
* @param params The `ReceiptService.ReceiptQueryReceiptParams` containing the following parameters:
@@ -531,6 +717,42 @@ class ReceiptService extends __BaseService {
);
}
/**
* Aufgabe auf erledigt setzen
* @param taskId undefined
*/
ReceiptReceiptItemTaskCompletedResponse(taskId: number): __Observable<__StrictHttpResponse<ResponseArgsOfReceiptItemTaskListItemDTO>> {
let __params = this.newParams();
let __headers = new HttpHeaders();
let __body: any = null;
let req = new HttpRequest<any>(
'PATCH',
this.rootUrl + `/receipt/item/task/${encodeURIComponent(String(taskId))}/completed`,
__body,
{
headers: __headers,
params: __params,
responseType: 'json'
});
return this.http.request<any>(req).pipe(
__filter(_r => _r instanceof HttpResponse),
__map((_r) => {
return _r as __StrictHttpResponse<ResponseArgsOfReceiptItemTaskListItemDTO>;
})
);
}
/**
* Aufgabe auf erledigt setzen
* @param taskId undefined
*/
ReceiptReceiptItemTaskCompleted(taskId: number): __Observable<ResponseArgsOfReceiptItemTaskListItemDTO> {
return this.ReceiptReceiptItemTaskCompletedResponse(taskId).pipe(
__map(_r => _r.body as ResponseArgsOfReceiptItemTaskListItemDTO)
);
}
/**
* Zugeordnete Belege
* @param params The `ReceiptService.ReceiptGetReceiptsByOrderItemSubsetParams` containing the following parameters:

View File

@@ -31,8 +31,9 @@ const PARAMETER_CODEC = new ParameterCodec();
export class BaseService {
constructor(
protected config: PrintConfiguration,
protected http: HttpClient,
) {}
protected http: HttpClient
) {
}
private _rootUrl: string = '';
@@ -56,7 +57,7 @@ export class BaseService {
*/
protected newParams(): HttpParams {
return new HttpParams({
encoder: PARAMETER_CODEC,
encoder: PARAMETER_CODEC
});
}
}

View File

@@ -1,5 +1,8 @@
export { ResponseArgs } from './models/response-args';
export { IPublicUserInfo } from './models/ipublic-user-info';
export { DialogOfString } from './models/dialog-of-string';
export { DialogSettings } from './models/dialog-settings';
export { DialogContentType } from './models/dialog-content-type';
export { KeyValueDTOOfStringAndString } from './models/key-value-dtoof-string-and-string';
export { ProblemDetails } from './models/problem-details';
export { PrintRequestOfIEnumerableOfItemDTO } from './models/print-request-of-ienumerable-of-item-dto';
export { ItemDTO } from './models/item-dto';
@@ -8,6 +11,7 @@ export { ProductDTO } from './models/product-dto';
export { SizeOfString } from './models/size-of-string';
export { WeightOfAvoirdupois } from './models/weight-of-avoirdupois';
export { Avoirdupois } from './models/avoirdupois';
export { TouchedBase } from './models/touched-base';
export { SpecDTO } from './models/spec-dto';
export { TextDTO } from './models/text-dto';
export { ImageDTO } from './models/image-dto';
@@ -23,7 +27,7 @@ export { ShelfInfoDTO } from './models/shelf-info-dto';
export { ReviewDTO } from './models/review-dto';
export { EntityDTO } from './models/entity-dto';
export { EntityStatus } from './models/entity-status';
export { TouchedBase } from './models/touched-base';
export { CRUDA } from './models/cruda';
export { PaperKind } from './models/paper-kind';
export { PrintRequest } from './models/print-request';
export { PrintRequestOfLong } from './models/print-request-of-long';
@@ -41,37 +45,31 @@ export { Gender } from './models/gender';
export { OrganisationNamesDTO } from './models/organisation-names-dto';
export { EntityDTOContainerOfTenantDTO } from './models/entity-dtocontainer-of-tenant-dto';
export { TenantDTO } from './models/tenant-dto';
export { ReadOnlyEntityDTOOfTenantDTOAndIReadOnlyTenant } from './models/read-only-entity-dtoof-tenant-dtoand-iread-only-tenant';
export { EntityDTOBaseOfTenantDTOAndITenant } from './models/entity-dtobase-of-tenant-dtoand-itenant';
export { EntityDTOBase } from './models/entity-dtobase';
export { EntityDTOReferenceContainer } from './models/entity-dtoreference-container';
export { ExternalReferenceDTO } from './models/external-reference-dto';
export { EntityDTOOfContributorDTOAndIContributor } from './models/entity-dtoof-contributor-dtoand-icontributor';
export { ReadOnlyEntityDTOOfContributorDTOAndIContributor } from './models/read-only-entity-dtoof-contributor-dtoand-icontributor';
export { EntityDTOBaseOfContributorDTOAndIContributor } from './models/entity-dtobase-of-contributor-dtoand-icontributor';
export { EntityDTOContainerOfCompanyDTO } from './models/entity-dtocontainer-of-company-dto';
export { CompanyDTO } from './models/company-dto';
export { AddressDTO } from './models/address-dto';
export { GeoLocation } from './models/geo-location';
export { EntityDTOOfCompanyDTOAndICompany } from './models/entity-dtoof-company-dtoand-icompany';
export { ReadOnlyEntityDTOOfCompanyDTOAndICompany } from './models/read-only-entity-dtoof-company-dtoand-icompany';
export { EntityDTOBaseOfCompanyDTOAndICompany } from './models/entity-dtobase-of-company-dtoand-icompany';
export { EntityDTOContainerOfCategoryDTO } from './models/entity-dtocontainer-of-category-dto';
export { CategoryDTO } from './models/category-dto';
export { EntityDTOOfCategoryDTOAndICategory } from './models/entity-dtoof-category-dtoand-icategory';
export { ReadOnlyEntityDTOOfCategoryDTOAndICategory } from './models/read-only-entity-dtoof-category-dtoand-icategory';
export { EntityDTOContainerOfFileDTO } from './models/entity-dtocontainer-of-file-dto';
export { FileDTO } from './models/file-dto';
export { EntityDTOOfFileDTOAndIFile } from './models/entity-dtoof-file-dtoand-ifile';
export { ReadOnlyEntityDTOOfFileDTOAndIFile } from './models/read-only-entity-dtoof-file-dtoand-ifile';
export { EntityDTOBaseOfFileDTOAndIFile } from './models/entity-dtobase-of-file-dtoand-ifile';
export { EntityDTOContainerOfTextDTO } from './models/entity-dtocontainer-of-text-dto';
export { TextDTO2 } from './models/text-dto2';
export { EntityDTOOfTextDTOAndIText } from './models/entity-dtoof-text-dtoand-itext';
export { ReadOnlyEntityDTOOfTextDTOAndIText } from './models/read-only-entity-dtoof-text-dtoand-itext';
export { EntityDTOBaseOfTextDTOAndIText } from './models/entity-dtobase-of-text-dtoand-itext';
export { EntityDTOContainerOfComponentsDTO } from './models/entity-dtocontainer-of-components-dto';
export { ComponentsDTO } from './models/components-dto';
export { ComponentItemDTO } from './models/component-item-dto';
export { QuantityUnitType } from './models/quantity-unit-type';
export { ComponentItemDisplayType } from './models/component-item-display-type';
export { SetType } from './models/set-type';
export { EntityDTOOfComponentsDTOAndIComponents } from './models/entity-dtoof-components-dtoand-icomponents';
export { ReadOnlyEntityDTOOfComponentsDTOAndIComponents } from './models/read-only-entity-dtoof-components-dtoand-icomponents';
export { EntityDTOBaseOfComponentsDTOAndIComponents } from './models/entity-dtobase-of-components-dtoand-icomponents';
export { ItemLabelDTO } from './models/item-label-dto';
export { FoodDTO } from './models/food-dto';
export { FoodLabel } from './models/food-label';
@@ -81,24 +79,22 @@ export { NutritionFactsDTO } from './models/nutrition-facts-dto';
export { Rezeptmasz } from './models/rezeptmasz';
export { NutritionFactDTO } from './models/nutrition-fact-dto';
export { NutritionFactType } from './models/nutrition-fact-type';
export { EntityDTOOfItemDTOAndIItem } from './models/entity-dtoof-item-dtoand-iitem';
export { ReadOnlyEntityDTOOfItemDTOAndIItem } from './models/read-only-entity-dtoof-item-dtoand-iitem';
export { EntityDTOBaseOfItemDTOAndIItem } from './models/entity-dtobase-of-item-dtoand-iitem';
export { ImageDTO2 } from './models/image-dto2';
export { UrlDTO } from './models/url-dto';
export { AvailabilityDTO2 } from './models/availability-dto2';
export { DateRangeDTO } from './models/date-range-dto';
export { EntityDTOContainerOfSupplierDTO } from './models/entity-dtocontainer-of-supplier-dto';
export { SupplierDTO } from './models/supplier-dto';
export { SupplierType } from './models/supplier-type';
export { EntityDTOOfSupplierDTOAndISupplier } from './models/entity-dtoof-supplier-dtoand-isupplier';
export { ReadOnlyEntityDTOOfSupplierDTOAndISupplier } from './models/read-only-entity-dtoof-supplier-dtoand-isupplier';
export { EntityDTOBaseOfSupplierDTOAndISupplier } from './models/entity-dtobase-of-supplier-dtoand-isupplier';
export { EntityDTOContainerOfLogisticianDTO } from './models/entity-dtocontainer-of-logistician-dto';
export { LogisticianDTO } from './models/logistician-dto';
export { EntityDTOOfLogisticianDTOAndILogistician } from './models/entity-dtoof-logistician-dtoand-ilogistician';
export { ReadOnlyEntityDTOOfLogisticianDTOAndILogistician } from './models/read-only-entity-dtoof-logistician-dtoand-ilogistician';
export { EntityDTOBaseOfLogisticianDTOAndILogistician } from './models/entity-dtobase-of-logistician-dtoand-ilogistician';
export { ShippingDTO } from './models/shipping-dto';
export { ShippingType } from './models/shipping-type';
export { TypeOfDelivery } from './models/type-of-delivery';
export { ReadOnlyEntityDTOOfShopItemDTOAndIShopItem } from './models/read-only-entity-dtoof-shop-item-dtoand-ishop-item';
export { EntityDTOBaseOfShopItemDTOAndIShopItem } from './models/entity-dtobase-of-shop-item-dtoand-ishop-item';
export { EntityDTOContainerOfShoppingCartItemDTO } from './models/entity-dtocontainer-of-shopping-cart-item-dto';
export { ShoppingCartItemStatus } from './models/shopping-cart-item-status';
export { OrderItemType } from './models/order-item-type';
@@ -108,23 +104,20 @@ export { EntityDTOContainerOfBranchDTO } from './models/entity-dtocontainer-of-b
export { BranchDTO } from './models/branch-dto';
export { EntityDTOContainerOfLabelDTO } from './models/entity-dtocontainer-of-label-dto';
export { LabelDTO } from './models/label-dto';
export { ReadOnlyEntityDTOOfLabelDTOAndIReadOnlyLabel } from './models/read-only-entity-dtoof-label-dtoand-iread-only-label';
export { Address } from './models/address';
export { EntityDTOBaseOfLabelDTOAndILabel } from './models/entity-dtobase-of-label-dtoand-ilabel';
export { BranchType } from './models/branch-type';
export { ReadOnlyEntityDTOOfBranchDTOAndIReadOnlyBranch } from './models/read-only-entity-dtoof-branch-dtoand-iread-only-branch';
export { EntityDTOBaseOfBranchDTOAndIBranch } from './models/entity-dtobase-of-branch-dtoand-ibranch';
export { EntityDTOContainerOfCurrencyDTO } from './models/entity-dtocontainer-of-currency-dto';
export { CurrencyDTO } from './models/currency-dto';
export { EntityDTOOfCurrencyDTOAndICurrency } from './models/entity-dtoof-currency-dtoand-icurrency';
export { ReadOnlyEntityDTOOfCurrencyDTOAndICurrency } from './models/read-only-entity-dtoof-currency-dtoand-icurrency';
export { EntityDTOBaseOfCurrencyDTOAndICurrency } from './models/entity-dtobase-of-currency-dtoand-icurrency';
export { EntityDTOContainerOfCountryDTO } from './models/entity-dtocontainer-of-country-dto';
export { CountryDTO } from './models/country-dto';
export { ReadOnlyEntityDTOOfCountryDTOAndIReadOnlyCountry } from './models/read-only-entity-dtoof-country-dtoand-iread-only-country';
export { EntityDTOBaseOfCountryDTOAndICountry } from './models/entity-dtobase-of-country-dtoand-icountry';
export { PaymentType } from './models/payment-type';
export { ShippingTarget } from './models/shipping-target';
export { CountryTargetDTO } from './models/country-target-dto';
export { BranchTargetDTO } from './models/branch-target-dto';
export { EntityDTOOfShopDTOAndIShop } from './models/entity-dtoof-shop-dtoand-ishop';
export { ReadOnlyEntityDTOOfShopDTOAndIShop } from './models/read-only-entity-dtoof-shop-dtoand-ishop';
export { EntityDTOBaseOfShopDTOAndIShop } from './models/entity-dtobase-of-shop-dtoand-ishop';
export { EntityDTOContainerOfDestinationDTO } from './models/entity-dtocontainer-of-destination-dto';
export { DestinationDTO } from './models/destination-dto';
export { EntityDTOContainerOfCheckoutDTO } from './models/entity-dtocontainer-of-checkout-dto';
@@ -132,6 +125,8 @@ export { CheckoutDTO } from './models/checkout-dto';
export { UserAccountDTO } from './models/user-account-dto';
export { BuyerDTO } from './models/buyer-dto';
export { BuyerType } from './models/buyer-type';
export { BuyerStatus } from './models/buyer-status';
export { AddresseeWithReferenceDTO } from './models/addressee-with-reference-dto';
export { CommunicationDetailsDTO } from './models/communication-details-dto';
export { OrganisationDTO } from './models/organisation-dto';
export { EntityReferenceDTO } from './models/entity-reference-dto';
@@ -143,27 +138,25 @@ export { CheckoutDeliveryDTO } from './models/checkout-delivery-dto';
export { TermsOfDeliveryDTO } from './models/terms-of-delivery-dto';
export { EntityDTOContainerOfCheckoutItemDTO } from './models/entity-dtocontainer-of-checkout-item-dto';
export { CheckoutItemDTO } from './models/checkout-item-dto';
export { ReadOnlyEntityDTOOfCheckoutItemDTOAndICheckoutItem } from './models/read-only-entity-dtoof-checkout-item-dtoand-icheckout-item';
export { EntityDTOBaseOfCheckoutItemDTOAndICheckoutItem } from './models/entity-dtobase-of-checkout-item-dtoand-icheckout-item';
export { DisplayItemDTO } from './models/display-item-dto';
export { PromotionDTO } from './models/promotion-dto';
export { ReadOnlyEntityDTOOfCheckoutDeliveryDTOAndICheckoutDelivery } from './models/read-only-entity-dtoof-checkout-delivery-dtoand-icheckout-delivery';
export { EntityDTOBaseOfCheckoutDeliveryDTOAndICheckoutDelivery } from './models/entity-dtobase-of-checkout-delivery-dtoand-icheckout-delivery';
export { NotificationChannel } from './models/notification-channel';
export { SelectionDTOOfShippingTarget } from './models/selection-dtoof-shipping-target';
export { PaymentDTO } from './models/payment-dto';
export { SelectionDTOOfPaymentType } from './models/selection-dtoof-payment-type';
export { EntityDTOContainerOfVoucherDTO } from './models/entity-dtocontainer-of-voucher-dto';
export { VoucherDTO } from './models/voucher-dto';
export { ReadOnlyEntityDTOOfVoucherDTOAndIReadOnlyVoucher } from './models/read-only-entity-dtoof-voucher-dtoand-iread-only-voucher';
export { EntityDTOBaseOfVoucherDTOAndIVoucher } from './models/entity-dtobase-of-voucher-dtoand-ivoucher';
export { EntityDTOContainerOfCouponDTO } from './models/entity-dtocontainer-of-coupon-dto';
export { CouponDTO } from './models/coupon-dto';
export { CouponType } from './models/coupon-type';
export { ReadOnlyEntityDTOOfCouponDTOAndICoupon } from './models/read-only-entity-dtoof-coupon-dtoand-icoupon';
export { KeyValueDTOOfStringAndString } from './models/key-value-dtoof-string-and-string';
export { ReadOnlyEntityDTOOfCheckoutDTOAndICheckout } from './models/read-only-entity-dtoof-checkout-dtoand-icheckout';
export { EntityDTOBaseOfCouponDTOAndICoupon } from './models/entity-dtobase-of-coupon-dtoand-icoupon';
export { EntityDTOBaseOfCheckoutDTOAndICheckout } from './models/entity-dtobase-of-checkout-dtoand-icheckout';
export { ShippingAddressDTO } from './models/shipping-address-dto';
export { EntityDTOOfDestinationDTOAndIDestination } from './models/entity-dtoof-destination-dtoand-idestination';
export { ReadOnlyEntityDTOOfDestinationDTOAndIDestination } from './models/read-only-entity-dtoof-destination-dtoand-idestination';
export { ReadOnlyEntityDTOOfShoppingCartItemDTOAndIShoppingCartItem } from './models/read-only-entity-dtoof-shopping-cart-item-dtoand-ishopping-cart-item';
export { EntityDTOBaseOfDestinationDTOAndIDestination } from './models/entity-dtobase-of-destination-dtoand-idestination';
export { EntityDTOBaseOfShoppingCartItemDTOAndIShoppingCartItem } from './models/entity-dtobase-of-shopping-cart-item-dtoand-ishopping-cart-item';
export { PrintRequestOfString } from './models/print-request-of-string';
export { PrintRequestOfIEnumerableOfLong } from './models/print-request-of-ienumerable-of-long';
export { PrintRequestOfIEnumerableOfDisplayOrderDTO } from './models/print-request-of-ienumerable-of-display-order-dto';
@@ -171,19 +164,19 @@ export { DisplayOrderDTO } from './models/display-order-dto';
export { OrderType } from './models/order-type';
export { EnvironmentChannel } from './models/environment-channel';
export { DisplayBranchDTO } from './models/display-branch-dto';
export { ReadOnlyEntityDTOOfDisplayBranchDTOAndIReadOnlyBranch } from './models/read-only-entity-dtoof-display-branch-dtoand-iread-only-branch';
export { EntityDTOBaseOfDisplayBranchDTOAndIBranch } from './models/entity-dtobase-of-display-branch-dtoand-ibranch';
export { DisplayOrderItemDTO } from './models/display-order-item-dto';
export { DisplayOrderItemSubsetDTO } from './models/display-order-item-subset-dto';
export { OrderItemProcessingStatusValue } from './models/order-item-processing-status-value';
export { ReadOnlyEntityDTOOfDisplayOrderItemSubsetDTOAndIOrderItemStatus } from './models/read-only-entity-dtoof-display-order-item-subset-dtoand-iorder-item-status';
export { ReadOnlyEntityDTOOfDisplayOrderItemDTOAndIOrderItem } from './models/read-only-entity-dtoof-display-order-item-dtoand-iorder-item';
export { EntityDTOBaseOfDisplayOrderItemSubsetDTOAndIOrderItemStatus } from './models/entity-dtobase-of-display-order-item-subset-dtoand-iorder-item-status';
export { EntityDTOBaseOfDisplayOrderItemDTOAndIOrderItem } from './models/entity-dtobase-of-display-order-item-dtoand-iorder-item';
export { DisplayAddresseeDTO } from './models/display-addressee-dto';
export { DisplayLogisticianDTO } from './models/display-logistician-dto';
export { ReadOnlyEntityDTOOfDisplayLogisticianDTOAndILogistician } from './models/read-only-entity-dtoof-display-logistician-dtoand-ilogistician';
export { EntityDTOBaseOfDisplayLogisticianDTOAndILogistician } from './models/entity-dtobase-of-display-logistician-dtoand-ilogistician';
export { DisplayOrderPaymentDTO } from './models/display-order-payment-dto';
export { ReadOnlyEntityDTOOfDisplayOrderPaymentDTOAndIReadOnlyPayment } from './models/read-only-entity-dtoof-display-order-payment-dtoand-iread-only-payment';
export { TermsOfDeliveryDTO2 } from './models/terms-of-delivery-dto2';
export { ReadOnlyEntityDTOOfDisplayOrderDTOAndIOrder } from './models/read-only-entity-dtoof-display-order-dtoand-iorder';
export { EntityDTOBaseOfDisplayOrderPaymentDTOAndIReadOnlyPayment } from './models/entity-dtobase-of-display-order-payment-dtoand-iread-only-payment';
export { LinkedRecordDTO } from './models/linked-record-dto';
export { EntityDTOBaseOfDisplayOrderDTOAndIOrder } from './models/entity-dtobase-of-display-order-dtoand-iorder';
export { PrintRequestOfIEnumerableOfPriceQRCodeDTO } from './models/print-request-of-ienumerable-of-price-qrcode-dto';
export { PriceQRCodeDTO } from './models/price-qrcode-dto';
export { ResponseArgsOfIEnumerableOfString } from './models/response-args-of-ienumerable-of-string';

View File

@@ -1,6 +1,7 @@
/* tslint:disable */
import { TouchedBase } from './touched-base';
import { GeoLocation } from './geo-location';
export interface AddressDTO {
export interface AddressDTO extends TouchedBase{
apartment?: string;
careOf?: string;
city?: string;

View File

@@ -1,17 +0,0 @@
/* tslint:disable */
import { GeoLocation } from './geo-location';
export interface Address {
apartment?: string;
careOf?: string;
city?: string;
country?: string;
district?: string;
geoLocation?: GeoLocation;
info?: string;
po?: string;
region?: string;
state?: string;
street?: string;
streetNumber?: string;
zipCode?: string;
}

View File

@@ -0,0 +1,16 @@
/* tslint:disable */
import { EntityReferenceDTO } from './entity-reference-dto';
import { AddressDTO } from './address-dto';
import { CommunicationDetailsDTO } from './communication-details-dto';
import { Gender } from './gender';
import { OrganisationDTO } from './organisation-dto';
export interface AddresseeWithReferenceDTO extends EntityReferenceDTO{
address?: AddressDTO;
communicationDetails?: CommunicationDetailsDTO;
firstName?: string;
gender?: Gender;
lastName?: string;
locale?: string;
organisation?: OrganisationDTO;
title?: string;
}

View File

@@ -1,43 +1,2 @@
/* tslint:disable */
export type AllergeneType =
| 0
| 1
| 2
| 4
| 6
| 8
| 16
| 32
| 64
| 128
| 256
| 512
| 1024
| 1536
| 2048
| 6144
| 10240
| 18432
| 34816
| 67584
| 133120
| 264192
| 526336
| 1048576
| 3145728
| 5242880
| 9437184
| 17825792
| 34603008
| 68157440
| 135266304
| 268435456
| 805306368
| 1342177280
| 2415919104
| 4563402752
| 8858370048
| 17448304640
| 34628173824
| 68987912192
| 137438953472;
export type AllergeneType = 0 | 1 | 2 | 4 | 6 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 1536 | 2048 | 6144 | 10240 | 18432 | 34816 | 67584 | 133120 | 264192 | 526336 | 1048576 | 3145728 | 5242880 | 9437184 | 17825792 | 34603008 | 68157440 | 135266304 | 268435456 | 805306368 | 1342177280 | 2415919104 | 4563402752 | 8858370048 | 17448304640 | 34628173824 | 68987912192 | 137438953472;

View File

@@ -7,6 +7,7 @@ import { AvailabilityType } from './availability-type';
* Verfügbarkeit
*/
export interface AvailabilityDTO {
/**
* Voraussichtliches Lieferdatum
*/

View File

@@ -1,14 +1,18 @@
/* tslint:disable */
import { TouchedBase } from './touched-base';
import { AvailabilityType } from './availability-type';
import { DateRangeDTO } from './date-range-dto';
import { EntityDTOContainerOfLogisticianDTO } from './entity-dtocontainer-of-logistician-dto';
import { PriceDTO } from './price-dto';
import { EntityDTOContainerOfShopItemDTO } from './entity-dtocontainer-of-shop-item-dto';
import { EntityDTOContainerOfSupplierDTO } from './entity-dtocontainer-of-supplier-dto';
export interface AvailabilityDTO2 {
availabilityType: AvailabilityType;
export interface AvailabilityDTO2 extends TouchedBase{
availabilityType?: AvailabilityType;
estimatedDelivery?: DateRangeDTO;
estimatedShippingDate?: string;
inStock?: number;
isPrebooked?: boolean;
lastRequest?: string;
logistician?: EntityDTOContainerOfLogisticianDTO;
price?: PriceDTO;
requestReference?: string;
@@ -20,4 +24,5 @@ export interface AvailabilityDTO2 {
supplierProductNumber?: string;
supplierSSC?: string;
supplierSSCText?: string;
supplyChannel?: string;
}

View File

@@ -1,2 +1,2 @@
/* tslint:disable */
export type AvailabilityType = 0 | 1 | 2 | 32 | 256 | 512 | 1024 | 2048 | 4096 | 8192 | 16384;
export type AvailabilityType = 0 | 1 | 2 | 32 | 256 | 512 | 1024 | 2048 | 4096 | 8192 | 16384;

View File

@@ -1,2 +1,2 @@
/* tslint:disable */
export type Avoirdupois = 0 | 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096;
export type Avoirdupois = 0 | 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096;

View File

@@ -1,12 +1,13 @@
/* tslint:disable */
import { ReadOnlyEntityDTOOfBranchDTOAndIReadOnlyBranch } from './read-only-entity-dtoof-branch-dtoand-iread-only-branch';
import { Address } from './address';
import { EntityDTOBaseOfBranchDTOAndIBranch } from './entity-dtobase-of-branch-dtoand-ibranch';
import { AddressDTO } from './address-dto';
import { BranchType } from './branch-type';
import { EntityDTOContainerOfLabelDTO } from './entity-dtocontainer-of-label-dto';
export interface BranchDTO extends ReadOnlyEntityDTOOfBranchDTOAndIReadOnlyBranch {
address?: Address;
import { EntityDTOContainerOfBranchDTO } from './entity-dtocontainer-of-branch-dto';
export interface BranchDTO extends EntityDTOBaseOfBranchDTOAndIBranch{
address?: AddressDTO;
branchNumber?: string;
branchType: BranchType;
branchType?: BranchType;
isDefault?: string;
isOnline?: boolean;
isOrderingEnabled?: boolean;
@@ -14,6 +15,6 @@ export interface BranchDTO extends ReadOnlyEntityDTOOfBranchDTOAndIReadOnlyBranc
key?: string;
label?: EntityDTOContainerOfLabelDTO;
name?: string;
parent?: number;
parent?: EntityDTOContainerOfBranchDTO;
shortName?: string;
}

View File

@@ -1,6 +1,7 @@
/* tslint:disable */
import { TouchedBase } from './touched-base';
import { EntityDTOContainerOfBranchDTO } from './entity-dtocontainer-of-branch-dto';
export interface BranchTargetDTO {
export interface BranchTargetDTO extends TouchedBase{
isDefault?: string;
start?: string;
stop?: string;

View File

@@ -1,2 +1,2 @@
/* tslint:disable */
export type BranchType = 0 | 1 | 2 | 4 | 8 | 16;
export type BranchType = 0 | 1 | 2 | 4 | 8 | 16;

View File

@@ -1,21 +1,11 @@
/* tslint:disable */
import { EntityReferenceDTO } from './entity-reference-dto';
import { AddressDTO } from './address-dto';
import { AddresseeWithReferenceDTO } from './addressee-with-reference-dto';
import { BuyerStatus } from './buyer-status';
import { BuyerType } from './buyer-type';
import { CommunicationDetailsDTO } from './communication-details-dto';
import { Gender } from './gender';
import { OrganisationDTO } from './organisation-dto';
export interface BuyerDTO extends EntityReferenceDTO {
address?: AddressDTO;
export interface BuyerDTO extends AddresseeWithReferenceDTO{
buyerNumber?: string;
buyerType: BuyerType;
communicationDetails?: CommunicationDetailsDTO;
buyerStatus?: BuyerStatus;
buyerType?: BuyerType;
dateOfBirth?: string;
firstName?: string;
gender: Gender;
isTemporaryAccount?: boolean;
lastName?: string;
locale?: string;
organisation?: OrganisationDTO;
title?: string;
}

View File

@@ -0,0 +1,2 @@
/* tslint:disable */
export type BuyerStatus = 0 | 1 | 2 | 4 | 8 | 16;

View File

@@ -1,2 +1,2 @@
/* tslint:disable */
export type BuyerType = 0 | 1 | 2 | 4 | 8 | 16;
export type BuyerType = 0 | 1 | 2 | 4 | 8 | 16;

View File

@@ -1,8 +1,8 @@
/* tslint:disable */
import { EntityDTOOfCategoryDTOAndICategory } from './entity-dtoof-category-dtoand-icategory';
import { EntityDTOBase } from './entity-dtobase';
import { EntityDTOContainerOfCategoryDTO } from './entity-dtocontainer-of-category-dto';
import { EntityDTOContainerOfTenantDTO } from './entity-dtocontainer-of-tenant-dto';
export interface CategoryDTO extends EntityDTOOfCategoryDTOAndICategory {
export interface CategoryDTO extends EntityDTOBase{
key?: string;
name?: string;
parent?: EntityDTOContainerOfCategoryDTO;

View File

@@ -1,12 +1,12 @@
/* tslint:disable */
import { ReadOnlyEntityDTOOfCheckoutDeliveryDTOAndICheckoutDelivery } from './read-only-entity-dtoof-checkout-delivery-dtoand-icheckout-delivery';
import { EntityDTOBaseOfCheckoutDeliveryDTOAndICheckoutDelivery } from './entity-dtobase-of-checkout-delivery-dtoand-icheckout-delivery';
import { EntityDTOContainerOfCheckoutDTO } from './entity-dtocontainer-of-checkout-dto';
import { EntityDTOContainerOfDestinationDTO } from './entity-dtocontainer-of-destination-dto';
import { PriceValueDTO } from './price-value-dto';
import { DisplayItemDTO } from './display-item-dto';
import { EntityDTOContainerOfCheckoutItemDTO } from './entity-dtocontainer-of-checkout-item-dto';
import { TermsOfDeliveryDTO } from './terms-of-delivery-dto';
export interface CheckoutDeliveryDTO extends ReadOnlyEntityDTOOfCheckoutDeliveryDTOAndICheckoutDelivery {
export interface CheckoutDeliveryDTO extends EntityDTOBaseOfCheckoutDeliveryDTOAndICheckoutDelivery{
checkout?: EntityDTOContainerOfCheckoutDTO;
destination?: EntityDTOContainerOfDestinationDTO;
discount?: PriceValueDTO;

View File

@@ -1,5 +1,5 @@
/* tslint:disable */
import { ReadOnlyEntityDTOOfCheckoutDTOAndICheckout } from './read-only-entity-dtoof-checkout-dtoand-icheckout';
import { EntityDTOBaseOfCheckoutDTOAndICheckout } from './entity-dtobase-of-checkout-dtoand-icheckout';
import { KeyValueDTOOfStringAndString } from './key-value-dtoof-string-and-string';
import { SelectionDTOOfShippingTarget } from './selection-dtoof-shipping-target';
import { BuyerDTO } from './buyer-dto';
@@ -11,7 +11,7 @@ import { EntityDTOContainerOfBranchDTO } from './entity-dtocontainer-of-branch-d
import { PayerDTO } from './payer-dto';
import { PaymentDTO } from './payment-dto';
import { UserAccountDTO } from './user-account-dto';
export interface CheckoutDTO extends ReadOnlyEntityDTOOfCheckoutDTOAndICheckout {
export interface CheckoutDTO extends EntityDTOBaseOfCheckoutDTOAndICheckout{
agreements?: Array<KeyValueDTOOfStringAndString>;
availableShippingTargets?: Array<SelectionDTOOfShippingTarget>;
buyer?: BuyerDTO;
@@ -20,7 +20,7 @@ export interface CheckoutDTO extends ReadOnlyEntityDTOOfCheckoutDTOAndICheckout
destinations?: Array<EntityDTOContainerOfDestinationDTO>;
items?: Array<EntityDTOContainerOfCheckoutItemDTO>;
label?: string;
notificationChannels: NotificationChannel;
notificationChannels?: NotificationChannel;
orderBranch?: EntityDTOContainerOfBranchDTO;
payer?: PayerDTO;
payment?: PaymentDTO;

View File

@@ -1,10 +1,10 @@
/* tslint:disable */
import { ReadOnlyEntityDTOOfCheckoutItemDTOAndICheckoutItem } from './read-only-entity-dtoof-checkout-item-dtoand-icheckout-item';
import { EntityDTOBaseOfCheckoutItemDTOAndICheckoutItem } from './entity-dtobase-of-checkout-item-dtoand-icheckout-item';
import { EntityDTOContainerOfShoppingCartItemDTO } from './entity-dtocontainer-of-shopping-cart-item-dto';
import { EntityDTOContainerOfCheckoutDTO } from './entity-dtocontainer-of-checkout-dto';
import { EntityDTOContainerOfCheckoutDeliveryDTO } from './entity-dtocontainer-of-checkout-delivery-dto';
import { PriceValueDTO } from './price-value-dto';
export interface CheckoutItemDTO extends ReadOnlyEntityDTOOfCheckoutItemDTOAndICheckoutItem {
export interface CheckoutItemDTO extends EntityDTOBaseOfCheckoutItemDTOAndICheckoutItem{
accessories?: Array<EntityDTOContainerOfShoppingCartItemDTO>;
checkout?: EntityDTOContainerOfCheckoutDTO;
delivery?: EntityDTOContainerOfCheckoutDeliveryDTO;

View File

@@ -1,5 +1,6 @@
/* tslint:disable */
export interface CommunicationDetailsDTO {
import { TouchedBase } from './touched-base';
export interface CommunicationDetailsDTO extends TouchedBase{
email?: string;
fax?: string;
mobile?: string;

View File

@@ -1,9 +1,10 @@
/* tslint:disable */
import { EntityDTOOfCompanyDTOAndICompany } from './entity-dtoof-company-dtoand-icompany';
import { EntityDTOBaseOfCompanyDTOAndICompany } from './entity-dtobase-of-company-dtoand-icompany';
import { AddressDTO } from './address-dto';
import { EntityDTOContainerOfCompanyDTO } from './entity-dtocontainer-of-company-dto';
export interface CompanyDTO extends EntityDTOOfCompanyDTOAndICompany {
export interface CompanyDTO extends EntityDTOBaseOfCompanyDTOAndICompany{
address?: AddressDTO;
companyNumber?: string;
costUnit?: string;
department?: string;
gln?: string;

View File

@@ -1,2 +1,2 @@
/* tslint:disable */
export type ComponentItemDisplayType = 0 | 1 | 2;
export type ComponentItemDisplayType = 0 | 1 | 2;

View File

@@ -1,16 +1,18 @@
/* tslint:disable */
import { TouchedBase } from './touched-base';
import { EntityDTOContainerOfCategoryDTO } from './entity-dtocontainer-of-category-dto';
import { ComponentItemDisplayType } from './component-item-display-type';
import { EntityDTOContainerOfItemDTO } from './entity-dtocontainer-of-item-dto';
import { QuantityUnitType } from './quantity-unit-type';
export interface ComponentItemDTO {
export interface ComponentItemDTO extends TouchedBase{
category?: EntityDTOContainerOfCategoryDTO;
description?: string;
displayType: ComponentItemDisplayType;
displayType?: ComponentItemDisplayType;
item?: EntityDTOContainerOfItemDTO;
name?: string;
quantityMax?: number;
quantityUnitType: QuantityUnitType;
quantityMin?: number;
quantityUnitType?: QuantityUnitType;
required?: boolean;
start?: string;
stop?: string;

View File

@@ -1,14 +1,14 @@
/* tslint:disable */
import { EntityDTOOfComponentsDTOAndIComponents } from './entity-dtoof-components-dtoand-icomponents';
import { EntityDTOBaseOfComponentsDTOAndIComponents } from './entity-dtobase-of-components-dtoand-icomponents';
import { ComponentItemDTO } from './component-item-dto';
import { QuantityUnitType } from './quantity-unit-type';
import { SetType } from './set-type';
export interface ComponentsDTO extends EntityDTOOfComponentsDTOAndIComponents {
export interface ComponentsDTO extends EntityDTOBaseOfComponentsDTOAndIComponents{
items?: Array<ComponentItemDTO>;
overallQuantityMax?: number;
overallQuantityMin?: number;
quantityUnitType: QuantityUnitType;
quantityUnitType?: QuantityUnitType;
referenceQuantity?: number;
type: SetType;
type?: SetType;
unit?: string;
}

View File

@@ -1,9 +1,9 @@
/* tslint:disable */
import { EntityDTOOfContributorDTOAndIContributor } from './entity-dtoof-contributor-dtoand-icontributor';
import { EntityDTOBaseOfContributorDTOAndIContributor } from './entity-dtobase-of-contributor-dtoand-icontributor';
import { OrganisationNamesDTO } from './organisation-names-dto';
import { PersonNamesDTO } from './person-names-dto';
import { EntityDTOContainerOfTenantDTO } from './entity-dtocontainer-of-tenant-dto';
export interface ContributorDTO extends EntityDTOOfContributorDTOAndIContributor {
export interface ContributorDTO extends EntityDTOBaseOfContributorDTOAndIContributor{
friendlyName?: string;
organisation?: OrganisationNamesDTO;
person?: PersonNamesDTO;

View File

@@ -1,6 +1,7 @@
/* tslint:disable */
import { TouchedBase } from './touched-base';
import { EntityDTOContainerOfContributorDTO } from './entity-dtocontainer-of-contributor-dto';
export interface ContributorHelperDTO {
export interface ContributorHelperDTO extends TouchedBase{
contributor?: EntityDTOContainerOfContributorDTO;
type?: string;
}

View File

@@ -1,6 +1,6 @@
/* tslint:disable */
import { ReadOnlyEntityDTOOfCountryDTOAndIReadOnlyCountry } from './read-only-entity-dtoof-country-dtoand-iread-only-country';
export interface CountryDTO extends ReadOnlyEntityDTOOfCountryDTOAndIReadOnlyCountry {
import { EntityDTOBaseOfCountryDTOAndICountry } from './entity-dtobase-of-country-dtoand-icountry';
export interface CountryDTO extends EntityDTOBaseOfCountryDTOAndICountry{
isDefault?: string;
isO3166_A_3?: string;
name?: string;

View File

@@ -1,6 +1,7 @@
/* tslint:disable */
import { TouchedBase } from './touched-base';
import { EntityDTOContainerOfCountryDTO } from './entity-dtocontainer-of-country-dto';
export interface CountryTargetDTO {
export interface CountryTargetDTO extends TouchedBase{
isDefault?: string;
start?: string;
stop?: string;

View File

@@ -1,8 +1,8 @@
/* tslint:disable */
import { ReadOnlyEntityDTOOfCouponDTOAndICoupon } from './read-only-entity-dtoof-coupon-dtoand-icoupon';
import { EntityDTOBaseOfCouponDTOAndICoupon } from './entity-dtobase-of-coupon-dtoand-icoupon';
import { CouponType } from './coupon-type';
import { PriceValueDTO } from './price-value-dto';
export interface CouponDTO extends ReadOnlyEntityDTOOfCouponDTOAndICoupon {
export interface CouponDTO extends EntityDTOBaseOfCouponDTOAndICoupon{
code?: string;
couponType: CouponType;
discount?: number;

View File

@@ -1,2 +1,2 @@
/* tslint:disable */
export type CouponType = 0 | 1 | 2 | 4 | 8;
export type CouponType = 0 | 1 | 2 | 4 | 8;

View File

@@ -0,0 +1,2 @@
/* tslint:disable */
export type CRUDA = 0 | 1 | 2 | 4 | 8 | 16;

View File

@@ -1,6 +1,6 @@
/* tslint:disable */
import { EntityDTOOfCurrencyDTOAndICurrency } from './entity-dtoof-currency-dtoand-icurrency';
export interface CurrencyDTO extends EntityDTOOfCurrencyDTOAndICurrency {
import { EntityDTOBaseOfCurrencyDTOAndICurrency } from './entity-dtobase-of-currency-dtoand-icurrency';
export interface CurrencyDTO extends EntityDTOBaseOfCurrencyDTOAndICurrency{
isO4217?: string;
name?: string;
number?: number;

View File

@@ -0,0 +1,6 @@
/* tslint:disable */
import { TouchedBase } from './touched-base';
export interface DateRangeDTO extends TouchedBase{
start?: string;
stop?: string;
}

View File

@@ -1,20 +1,2 @@
/* tslint:disable */
export type DeclarableFoodAdditives =
| 0
| 1
| 2
| 4
| 8
| 16
| 32
| 64
| 128
| 256
| 512
| 1024
| 2048
| 4096
| 8192
| 16384
| 32768
| 65536;
export type DeclarableFoodAdditives = 0 | 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096 | 8192 | 16384 | 32768 | 65536;

View File

@@ -1,11 +1,11 @@
/* tslint:disable */
import { EntityDTOOfDestinationDTOAndIDestination } from './entity-dtoof-destination-dtoand-idestination';
import { EntityDTOBaseOfDestinationDTOAndIDestination } from './entity-dtobase-of-destination-dtoand-idestination';
import { EntityDTOContainerOfCheckoutDTO } from './entity-dtocontainer-of-checkout-dto';
import { EntityDTOContainerOfLogisticianDTO } from './entity-dtocontainer-of-logistician-dto';
import { ShippingAddressDTO } from './shipping-address-dto';
import { ShippingTarget } from './shipping-target';
import { EntityDTOContainerOfBranchDTO } from './entity-dtocontainer-of-branch-dto';
export interface DestinationDTO extends EntityDTOOfDestinationDTOAndIDestination {
export interface DestinationDTO extends EntityDTOBaseOfDestinationDTOAndIDestination{
checkout?: EntityDTOContainerOfCheckoutDTO;
logistician?: EntityDTOContainerOfLogisticianDTO;
shippingAddress?: ShippingAddressDTO;

View File

@@ -0,0 +1,2 @@
/* tslint:disable */
export type DialogContentType = 0 | 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128;

View File

@@ -0,0 +1,16 @@
/* tslint:disable */
import { KeyValueDTOOfStringAndString } from './key-value-dtoof-string-and-string';
import { DialogContentType } from './dialog-content-type';
import { DialogSettings } from './dialog-settings';
export interface DialogOfString {
actions?: Array<KeyValueDTOOfStringAndString>;
actionsRequired?: number;
area?: string;
content?: string;
contentType: DialogContentType;
description?: string;
displayTimeout?: number;
settings: DialogSettings;
subtitle?: string;
title?: string;
}

View File

@@ -0,0 +1,2 @@
/* tslint:disable */
export type DialogSettings = 0 | 1 | 2 | 4;

View File

@@ -1,8 +1,8 @@
/* tslint:disable */
import { ReadOnlyEntityDTOOfDisplayBranchDTOAndIReadOnlyBranch } from './read-only-entity-dtoof-display-branch-dtoand-iread-only-branch';
import { EntityDTOBaseOfDisplayBranchDTOAndIBranch } from './entity-dtobase-of-display-branch-dtoand-ibranch';
import { AddressDTO } from './address-dto';
import { CommunicationDetailsDTO } from './communication-details-dto';
export interface DisplayBranchDTO extends ReadOnlyEntityDTOOfDisplayBranchDTOAndIReadOnlyBranch {
export interface DisplayBranchDTO extends EntityDTOBaseOfDisplayBranchDTOAndIBranch{
address?: AddressDTO;
branchNumber?: string;
communicationDetails?: CommunicationDetailsDTO;

View File

@@ -1,6 +1,6 @@
/* tslint:disable */
import { ReadOnlyEntityDTOOfDisplayLogisticianDTOAndILogistician } from './read-only-entity-dtoof-display-logistician-dtoand-ilogistician';
export interface DisplayLogisticianDTO extends ReadOnlyEntityDTOOfDisplayLogisticianDTOAndILogistician {
import { EntityDTOBaseOfDisplayLogisticianDTOAndILogistician } from './entity-dtobase-of-display-logistician-dtoand-ilogistician';
export interface DisplayLogisticianDTO extends EntityDTOBaseOfDisplayLogisticianDTOAndILogistician{
gln?: string;
logisticianNumber?: string;
name?: string;

View File

@@ -1,16 +1,19 @@
/* tslint:disable */
import { ReadOnlyEntityDTOOfDisplayOrderDTOAndIOrder } from './read-only-entity-dtoof-display-order-dtoand-iorder';
import { EntityDTOBaseOfDisplayOrderDTOAndIOrder } from './entity-dtobase-of-display-order-dtoand-iorder';
import { KeyValueDTOOfStringAndString } from './key-value-dtoof-string-and-string';
import { DisplayAddresseeDTO } from './display-addressee-dto';
import { BuyerType } from './buyer-type';
import { EnvironmentChannel } from './environment-channel';
import { DisplayOrderItemDTO } from './display-order-item-dto';
import { LinkedRecordDTO } from './linked-record-dto';
import { DisplayLogisticianDTO } from './display-logistician-dto';
import { NotificationChannel } from './notification-channel';
import { DisplayBranchDTO } from './display-branch-dto';
import { OrderType } from './order-type';
import { DisplayOrderPaymentDTO } from './display-order-payment-dto';
import { TermsOfDeliveryDTO2 } from './terms-of-delivery-dto2';
export interface DisplayOrderDTO extends ReadOnlyEntityDTOOfDisplayOrderDTOAndIOrder {
import { TermsOfDeliveryDTO } from './terms-of-delivery-dto';
export interface DisplayOrderDTO extends EntityDTOBaseOfDisplayOrderDTOAndIOrder{
actions?: Array<KeyValueDTOOfStringAndString>;
buyer?: DisplayAddresseeDTO;
buyerComment?: string;
buyerIsGuestAccount?: boolean;
@@ -18,9 +21,10 @@ export interface DisplayOrderDTO extends ReadOnlyEntityDTOOfDisplayOrderDTOAndIO
buyerType?: BuyerType;
clientChannel?: EnvironmentChannel;
completedDate?: string;
features?: { [key: string]: string };
features?: {[key: string]: string};
items?: Array<DisplayOrderItemDTO>;
itemsCount?: number;
linkedRecords?: Array<LinkedRecordDTO>;
logistician?: DisplayLogisticianDTO;
notificationChannels?: NotificationChannel;
orderBranch?: DisplayBranchDTO;
@@ -35,5 +39,5 @@ export interface DisplayOrderDTO extends ReadOnlyEntityDTOOfDisplayOrderDTOAndIO
payment?: DisplayOrderPaymentDTO;
shippingAddress?: DisplayAddresseeDTO;
targetBranch?: DisplayBranchDTO;
termsOfDelivery?: TermsOfDeliveryDTO2;
termsOfDelivery?: TermsOfDeliveryDTO;
}

View File

@@ -1,15 +1,15 @@
/* tslint:disable */
import { ReadOnlyEntityDTOOfDisplayOrderItemDTOAndIOrderItem } from './read-only-entity-dtoof-display-order-item-dtoand-iorder-item';
import { EntityDTOBaseOfDisplayOrderItemDTOAndIOrderItem } from './entity-dtobase-of-display-order-item-dtoand-iorder-item';
import { DisplayOrderDTO } from './display-order-dto';
import { PriceDTO } from './price-dto';
import { ProductDTO } from './product-dto';
import { PromotionDTO } from './promotion-dto';
import { QuantityUnitType } from './quantity-unit-type';
import { DisplayOrderItemSubsetDTO } from './display-order-item-subset-dto';
export interface DisplayOrderItemDTO extends ReadOnlyEntityDTOOfDisplayOrderItemDTOAndIOrderItem {
export interface DisplayOrderItemDTO extends EntityDTOBaseOfDisplayOrderItemDTOAndIOrderItem{
buyerComment?: string;
description?: string;
features?: { [key: string]: string };
features?: {[key: string]: string};
order?: DisplayOrderDTO;
orderDate?: string;
orderItemNumber?: string;

View File

@@ -1,16 +1,19 @@
/* tslint:disable */
import { ReadOnlyEntityDTOOfDisplayOrderItemSubsetDTOAndIOrderItemStatus } from './read-only-entity-dtoof-display-order-item-subset-dtoand-iorder-item-status';
import { EntityDTOBaseOfDisplayOrderItemSubsetDTOAndIOrderItemStatus } from './entity-dtobase-of-display-order-item-subset-dtoand-iorder-item-status';
import { DateRangeDTO } from './date-range-dto';
import { DisplayOrderItemDTO } from './display-order-item-dto';
import { OrderItemProcessingStatusValue } from './order-item-processing-status-value';
export interface DisplayOrderItemSubsetDTO extends ReadOnlyEntityDTOOfDisplayOrderItemSubsetDTOAndIOrderItemStatus {
export interface DisplayOrderItemSubsetDTO extends EntityDTOBaseOfDisplayOrderItemSubsetDTOAndIOrderItemStatus{
compartmentCode?: string;
compartmentInfo?: string;
compartmentStart?: string;
compartmentStop?: string;
description?: string;
estimatedDelivery?: DateRangeDTO;
estimatedShippingDate?: string;
orderItem?: DisplayOrderItemDTO;
orderItemSubsetNumber?: string;
preferredPickUpDate?: string;
processingStatus: OrderItemProcessingStatusValue;
processingStatusDate?: string;
quantity?: number;
@@ -19,5 +22,6 @@ export interface DisplayOrderItemSubsetDTO extends ReadOnlyEntityDTOOfDisplayOrd
sscText?: string;
supplierLabel?: string;
supplierName?: string;
supplyChannel?: string;
trackingNumber?: string;
}

View File

@@ -1,7 +1,7 @@
/* tslint:disable */
import { ReadOnlyEntityDTOOfDisplayOrderPaymentDTOAndIReadOnlyPayment } from './read-only-entity-dtoof-display-order-payment-dtoand-iread-only-payment';
import { EntityDTOBaseOfDisplayOrderPaymentDTOAndIReadOnlyPayment } from './entity-dtobase-of-display-order-payment-dtoand-iread-only-payment';
import { PaymentType } from './payment-type';
export interface DisplayOrderPaymentDTO extends ReadOnlyEntityDTOOfDisplayOrderPaymentDTOAndIReadOnlyPayment {
export interface DisplayOrderPaymentDTO extends EntityDTOBaseOfDisplayOrderPaymentDTOAndIReadOnlyPayment{
cancelled?: string;
completed?: string;
currency?: string;

View File

@@ -1,11 +1,14 @@
/* tslint:disable */
import { TouchedBase } from './touched-base';
import { CRUDA } from './cruda';
import { EntityStatus } from './entity-status';
export interface EntityDTO extends TouchedBase {
export interface EntityDTO extends TouchedBase{
changed?: string;
created?: string;
cruda?: CRUDA;
id?: number;
pId?: string;
status?: EntityStatus;
uId?: string;
version?: number;
}

View File

@@ -0,0 +1,4 @@
/* tslint:disable */
import { EntityDTOBase } from './entity-dtobase';
export interface EntityDTOBaseOfBranchDTOAndIBranch extends EntityDTOBase{
}

View File

@@ -0,0 +1,4 @@
/* tslint:disable */
import { EntityDTOBase } from './entity-dtobase';
export interface EntityDTOBaseOfCheckoutDeliveryDTOAndICheckoutDelivery extends EntityDTOBase{
}

View File

@@ -0,0 +1,4 @@
/* tslint:disable */
import { EntityDTOBase } from './entity-dtobase';
export interface EntityDTOBaseOfCheckoutDTOAndICheckout extends EntityDTOBase{
}

View File

@@ -0,0 +1,4 @@
/* tslint:disable */
import { EntityDTOBase } from './entity-dtobase';
export interface EntityDTOBaseOfCheckoutItemDTOAndICheckoutItem extends EntityDTOBase{
}

View File

@@ -0,0 +1,4 @@
/* tslint:disable */
import { EntityDTOBase } from './entity-dtobase';
export interface EntityDTOBaseOfCompanyDTOAndICompany extends EntityDTOBase{
}

View File

@@ -0,0 +1,4 @@
/* tslint:disable */
import { EntityDTOBase } from './entity-dtobase';
export interface EntityDTOBaseOfComponentsDTOAndIComponents extends EntityDTOBase{
}

View File

@@ -0,0 +1,4 @@
/* tslint:disable */
import { EntityDTOBase } from './entity-dtobase';
export interface EntityDTOBaseOfContributorDTOAndIContributor extends EntityDTOBase{
}

Some files were not shown because too many files have changed in this diff Show More