mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Merged PR 1977: #5390 Reward Checkout Action Card - Collect Request
#5390 Reward Checkout Action Card - Collect Request
This commit is contained in:
committed by
Lorenz Hilpert
parent
bcb412e48d
commit
7376846894
@@ -37,6 +37,7 @@ export { Gender } from './models/gender';
|
|||||||
export { DateRangeDTO } from './models/date-range-dto';
|
export { DateRangeDTO } from './models/date-range-dto';
|
||||||
export { PaymentType } from './models/payment-type';
|
export { PaymentType } from './models/payment-type';
|
||||||
export { PaymentStatus } from './models/payment-status';
|
export { PaymentStatus } from './models/payment-status';
|
||||||
|
export { LoyaltyDTO } from './models/loyalty-dto';
|
||||||
export { QueryTokenDTO } from './models/query-token-dto';
|
export { QueryTokenDTO } from './models/query-token-dto';
|
||||||
export { ListResponseArgsOfOrderItemListItemDTO } from './models/list-response-args-of-order-item-list-item-dto';
|
export { ListResponseArgsOfOrderItemListItemDTO } from './models/list-response-args-of-order-item-list-item-dto';
|
||||||
export { ResponseArgsOfIEnumerableOfOrderItemListItemDTO } from './models/response-args-of-ienumerable-of-order-item-list-item-dto';
|
export { ResponseArgsOfIEnumerableOfOrderItemListItemDTO } from './models/response-args-of-ienumerable-of-order-item-list-item-dto';
|
||||||
@@ -130,7 +131,6 @@ export { Price } from './models/price';
|
|||||||
export { ShippingTarget } from './models/shipping-target';
|
export { ShippingTarget } from './models/shipping-target';
|
||||||
export { EntityDTOBaseOfShopItemDTOAndIShopItem } from './models/entity-dtobase-of-shop-item-dtoand-ishop-item';
|
export { EntityDTOBaseOfShopItemDTOAndIShopItem } from './models/entity-dtobase-of-shop-item-dtoand-ishop-item';
|
||||||
export { CampaignDTO } from './models/campaign-dto';
|
export { CampaignDTO } from './models/campaign-dto';
|
||||||
export { LoyaltyDTO } from './models/loyalty-dto';
|
|
||||||
export { EntityDTOBaseOfOrderItemDTOAndIOrderItem } from './models/entity-dtobase-of-order-item-dtoand-iorder-item';
|
export { EntityDTOBaseOfOrderItemDTOAndIOrderItem } from './models/entity-dtobase-of-order-item-dtoand-iorder-item';
|
||||||
export { EntityDTOContainerOfSupplierDTO } from './models/entity-dtocontainer-of-supplier-dto';
|
export { EntityDTOContainerOfSupplierDTO } from './models/entity-dtocontainer-of-supplier-dto';
|
||||||
export { SupplierDTO } from './models/supplier-dto';
|
export { SupplierDTO } from './models/supplier-dto';
|
||||||
@@ -207,6 +207,8 @@ export { EntityDTOContainerOfOrderItemSubsetTransitionDTO } from './models/entit
|
|||||||
export { OrderItemSubsetTransitionDTO } from './models/order-item-subset-transition-dto';
|
export { OrderItemSubsetTransitionDTO } from './models/order-item-subset-transition-dto';
|
||||||
export { EntityDTOBaseOfOrderItemSubsetTransitionDTOAndIOrderItemStatusTransition } from './models/entity-dtobase-of-order-item-subset-transition-dtoand-iorder-item-status-transition';
|
export { EntityDTOBaseOfOrderItemSubsetTransitionDTOAndIOrderItemStatusTransition } from './models/entity-dtobase-of-order-item-subset-transition-dtoand-iorder-item-status-transition';
|
||||||
export { EntityDTOBaseOfOrderItemSubsetTaskDTOAndIOrderItemStatusTask } from './models/entity-dtobase-of-order-item-subset-task-dtoand-iorder-item-status-task';
|
export { EntityDTOBaseOfOrderItemSubsetTaskDTOAndIOrderItemStatusTask } from './models/entity-dtobase-of-order-item-subset-task-dtoand-iorder-item-status-task';
|
||||||
|
export { LoyaltyCollectValues } from './models/loyalty-collect-values';
|
||||||
|
export { LoyaltyCollectType } from './models/loyalty-collect-type';
|
||||||
export { ResponseArgsOfBoolean } from './models/response-args-of-boolean';
|
export { ResponseArgsOfBoolean } from './models/response-args-of-boolean';
|
||||||
export { ResponseArgsOfOrderItemDTO } from './models/response-args-of-order-item-dto';
|
export { ResponseArgsOfOrderItemDTO } from './models/response-args-of-order-item-dto';
|
||||||
export { ResponseArgsOfIEnumerableOfOrderItemDTO } from './models/response-args-of-ienumerable-of-order-item-dto';
|
export { ResponseArgsOfIEnumerableOfOrderItemDTO } from './models/response-args-of-ienumerable-of-order-item-dto';
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
import { EntityDTOBaseOfDisplayOrderItemDTOAndIOrderItem } from './entity-dtobase-of-display-order-item-dtoand-iorder-item';
|
import { EntityDTOBaseOfDisplayOrderItemDTOAndIOrderItem } from './entity-dtobase-of-display-order-item-dtoand-iorder-item';
|
||||||
|
import { LoyaltyDTO } from './loyalty-dto';
|
||||||
import { DisplayOrderDTO } from './display-order-dto';
|
import { DisplayOrderDTO } from './display-order-dto';
|
||||||
import { PriceDTO } from './price-dto';
|
import { PriceDTO } from './price-dto';
|
||||||
import { ProductDTO } from './product-dto';
|
import { ProductDTO } from './product-dto';
|
||||||
@@ -23,6 +24,11 @@ export interface DisplayOrderItemDTO extends EntityDTOBaseOfDisplayOrderItemDTOA
|
|||||||
*/
|
*/
|
||||||
features?: {[key: string]: string};
|
features?: {[key: string]: string};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loylty
|
||||||
|
*/
|
||||||
|
loyalty?: LoyaltyDTO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bestellung
|
* Bestellung
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
/* tslint:disable */
|
||||||
|
export type LoyaltyCollectType = 0 | 1 | 2;
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
/* tslint:disable */
|
||||||
|
import { LoyaltyCollectType } from './loyalty-collect-type';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loyalty collect values
|
||||||
|
*/
|
||||||
|
export interface LoyaltyCollectValues {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collect Type
|
||||||
|
*/
|
||||||
|
collectType: LoyaltyCollectType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quantity (optional, default null)
|
||||||
|
*/
|
||||||
|
quantity?: number;
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import { EnvironmentChannel } from './environment-channel';
|
|||||||
import { CRUDA } from './cruda';
|
import { CRUDA } from './cruda';
|
||||||
import { DateRangeDTO } from './date-range-dto';
|
import { DateRangeDTO } from './date-range-dto';
|
||||||
import { Gender } from './gender';
|
import { Gender } from './gender';
|
||||||
|
import { LoyaltyDTO } from './loyalty-dto';
|
||||||
import { OrderType } from './order-type';
|
import { OrderType } from './order-type';
|
||||||
import { PaymentStatus } from './payment-status';
|
import { PaymentStatus } from './payment-status';
|
||||||
import { PaymentType } from './payment-type';
|
import { PaymentType } from './payment-type';
|
||||||
@@ -102,6 +103,11 @@ export interface OrderItemListItemDTO {
|
|||||||
*/
|
*/
|
||||||
lastName?: string;
|
lastName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loylty
|
||||||
|
*/
|
||||||
|
loyalty?: LoyaltyDTO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bestellfiliale
|
* Bestellfiliale
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,12 +1,19 @@
|
|||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
import { EntityReferenceDTO } from './entity-reference-dto';
|
import { EntityReferenceDTO } from './entity-reference-dto';
|
||||||
|
import { KeyValueDTOOfStringAndString } from './key-value-dtoof-string-and-string';
|
||||||
import { CRUDA } from './cruda';
|
import { CRUDA } from './cruda';
|
||||||
import { PriceDTO } from './price-dto';
|
import { PriceDTO } from './price-dto';
|
||||||
|
import { LoyaltyDTO } from './loyalty-dto';
|
||||||
import { ProductDTO } from './product-dto';
|
import { ProductDTO } from './product-dto';
|
||||||
import { PromotionDTO } from './promotion-dto';
|
import { PromotionDTO } from './promotion-dto';
|
||||||
import { QuantityDTO } from './quantity-dto';
|
import { QuantityDTO } from './quantity-dto';
|
||||||
import { ReceiptListItemDTO } from './receipt-list-item-dto';
|
import { ReceiptListItemDTO } from './receipt-list-item-dto';
|
||||||
export interface ReceiptItemListItemDTO extends EntityReferenceDTO{
|
export interface ReceiptItemListItemDTO extends EntityReferenceDTO{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mögliche Aktionen
|
||||||
|
*/
|
||||||
|
actions?: Array<KeyValueDTOOfStringAndString>;
|
||||||
buyerComment?: string;
|
buyerComment?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -19,6 +26,11 @@ export interface ReceiptItemListItemDTO extends EntityReferenceDTO{
|
|||||||
*/
|
*/
|
||||||
discountedPrice?: PriceDTO;
|
discountedPrice?: PriceDTO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zusätzliche Markierungen
|
||||||
|
*/
|
||||||
|
features?: {[key: string]: string};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PK
|
* PK
|
||||||
*/
|
*/
|
||||||
@@ -35,6 +47,11 @@ export interface ReceiptItemListItemDTO extends EntityReferenceDTO{
|
|||||||
*/
|
*/
|
||||||
lineNumber?: number;
|
lineNumber?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loyalty
|
||||||
|
*/
|
||||||
|
loyalty?: LoyaltyDTO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bestellnummer
|
* Bestellnummer
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import { ResponseArgsOfQuerySettingsDTO } from '../models/response-args-of-query
|
|||||||
import { ResponseArgsOfIEnumerableOfAutocompleteDTO } from '../models/response-args-of-ienumerable-of-autocomplete-dto';
|
import { ResponseArgsOfIEnumerableOfAutocompleteDTO } from '../models/response-args-of-ienumerable-of-autocomplete-dto';
|
||||||
import { AutocompleteTokenDTO } from '../models/autocomplete-token-dto';
|
import { AutocompleteTokenDTO } from '../models/autocomplete-token-dto';
|
||||||
import { ListResponseArgsOfDBHOrderItemListItemDTO } from '../models/list-response-args-of-dbhorder-item-list-item-dto';
|
import { ListResponseArgsOfDBHOrderItemListItemDTO } from '../models/list-response-args-of-dbhorder-item-list-item-dto';
|
||||||
|
import { ResponseArgsOfIEnumerableOfDBHOrderItemListItemDTO } from '../models/response-args-of-ienumerable-of-dbhorder-item-list-item-dto';
|
||||||
|
import { LoyaltyCollectValues } from '../models/loyalty-collect-values';
|
||||||
import { ListResponseArgsOfOrderItemListItemDTO } from '../models/list-response-args-of-order-item-list-item-dto';
|
import { ListResponseArgsOfOrderItemListItemDTO } from '../models/list-response-args-of-order-item-list-item-dto';
|
||||||
import { ResponseArgsOfIEnumerableOfOrderItemDTO } from '../models/response-args-of-ienumerable-of-order-item-dto';
|
import { ResponseArgsOfIEnumerableOfOrderItemDTO } from '../models/response-args-of-ienumerable-of-order-item-dto';
|
||||||
import { OrderItemDTO } from '../models/order-item-dto';
|
import { OrderItemDTO } from '../models/order-item-dto';
|
||||||
@@ -54,6 +56,7 @@ class OrderService extends __BaseService {
|
|||||||
static readonly OrderKundenbestellungenSettingsPath = '/kundenbestellungen/s/settings';
|
static readonly OrderKundenbestellungenSettingsPath = '/kundenbestellungen/s/settings';
|
||||||
static readonly OrderKundenbestellungenAutocompletePath = '/kundenbestellungen/s/complete';
|
static readonly OrderKundenbestellungenAutocompletePath = '/kundenbestellungen/s/complete';
|
||||||
static readonly OrderKundenbestellungenPath = '/kundenbestellungen/s';
|
static readonly OrderKundenbestellungenPath = '/kundenbestellungen/s';
|
||||||
|
static readonly OrderLoyaltyCollectPath = '/order/{orderId}/orderitem/{orderItemId}/orderitemsubset/{orderItemSubsetId}/loyaltycollect';
|
||||||
static readonly OrderQueryOrderItemPath = '/order/item/s';
|
static readonly OrderQueryOrderItemPath = '/order/item/s';
|
||||||
static readonly OrderQueryOrderItemAutocompletePath = '/order/item/s/complete';
|
static readonly OrderQueryOrderItemAutocompletePath = '/order/item/s/complete';
|
||||||
static readonly OrderGetOrderItemPath = '/order/orderitem/{orderItemId}';
|
static readonly OrderGetOrderItemPath = '/order/orderitem/{orderItemId}';
|
||||||
@@ -636,6 +639,63 @@ class OrderService extends __BaseService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ausgabe order Storno von Prämienbestellposten
|
||||||
|
* Falls die Menge/Stückzahl kleiner der ursprünglichen Menge/Stückzahl ist, wird eine neue Bestellpostenteilmenge erzeugt.
|
||||||
|
* @param params The `OrderService.OrderLoyaltyCollectParams` containing the following parameters:
|
||||||
|
*
|
||||||
|
* - `orderItemSubsetId`: PK Bestellpostenteilmenge
|
||||||
|
*
|
||||||
|
* - `orderItemId`: PK Bestellposten
|
||||||
|
*
|
||||||
|
* - `orderId`: PK Bestellung
|
||||||
|
*
|
||||||
|
* - `data`: Daten zur Änderung des Bearbeitungsstatus
|
||||||
|
*/
|
||||||
|
OrderLoyaltyCollectResponse(params: OrderService.OrderLoyaltyCollectParams): __Observable<__StrictHttpResponse<ResponseArgsOfIEnumerableOfDBHOrderItemListItemDTO>> {
|
||||||
|
let __params = this.newParams();
|
||||||
|
let __headers = new HttpHeaders();
|
||||||
|
let __body: any = null;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
__body = params.data;
|
||||||
|
let req = new HttpRequest<any>(
|
||||||
|
'POST',
|
||||||
|
this.rootUrl + `/order/${encodeURIComponent(String(params.orderId))}/orderitem/${encodeURIComponent(String(params.orderItemId))}/orderitemsubset/${encodeURIComponent(String(params.orderItemSubsetId))}/loyaltycollect`,
|
||||||
|
__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<ResponseArgsOfIEnumerableOfDBHOrderItemListItemDTO>;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Ausgabe order Storno von Prämienbestellposten
|
||||||
|
* Falls die Menge/Stückzahl kleiner der ursprünglichen Menge/Stückzahl ist, wird eine neue Bestellpostenteilmenge erzeugt.
|
||||||
|
* @param params The `OrderService.OrderLoyaltyCollectParams` containing the following parameters:
|
||||||
|
*
|
||||||
|
* - `orderItemSubsetId`: PK Bestellpostenteilmenge
|
||||||
|
*
|
||||||
|
* - `orderItemId`: PK Bestellposten
|
||||||
|
*
|
||||||
|
* - `orderId`: PK Bestellung
|
||||||
|
*
|
||||||
|
* - `data`: Daten zur Änderung des Bearbeitungsstatus
|
||||||
|
*/
|
||||||
|
OrderLoyaltyCollect(params: OrderService.OrderLoyaltyCollectParams): __Observable<ResponseArgsOfIEnumerableOfDBHOrderItemListItemDTO> {
|
||||||
|
return this.OrderLoyaltyCollectResponse(params).pipe(
|
||||||
|
__map(_r => _r.body as ResponseArgsOfIEnumerableOfDBHOrderItemListItemDTO)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Suche nach Bestellposten
|
* Suche nach Bestellposten
|
||||||
* @param queryToken Suchkriterien
|
* @param queryToken Suchkriterien
|
||||||
@@ -1671,6 +1731,32 @@ module OrderService {
|
|||||||
buyerNumber?: null | string;
|
buyerNumber?: null | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameters for OrderLoyaltyCollect
|
||||||
|
*/
|
||||||
|
export interface OrderLoyaltyCollectParams {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PK Bestellpostenteilmenge
|
||||||
|
*/
|
||||||
|
orderItemSubsetId: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PK Bestellposten
|
||||||
|
*/
|
||||||
|
orderItemId: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PK Bestellung
|
||||||
|
*/
|
||||||
|
orderId: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Daten zur Änderung des Bearbeitungsstatus
|
||||||
|
*/
|
||||||
|
data: LoyaltyCollectValues;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parameters for OrderUpdateOrderItem
|
* Parameters for OrderUpdateOrderItem
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -236,6 +236,7 @@ class ReceiptService extends __BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Aufgabe auf erledigt setzen
|
||||||
* @param taskId undefined
|
* @param taskId undefined
|
||||||
*/
|
*/
|
||||||
ReceiptReceiptItemTaskCompletedResponse(taskId: number): __Observable<__StrictHttpResponse<ResponseArgsOfReceiptItemTaskListItemDTO>> {
|
ReceiptReceiptItemTaskCompletedResponse(taskId: number): __Observable<__StrictHttpResponse<ResponseArgsOfReceiptItemTaskListItemDTO>> {
|
||||||
@@ -261,6 +262,7 @@ class ReceiptService extends __BaseService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* Aufgabe auf erledigt setzen
|
||||||
* @param taskId undefined
|
* @param taskId undefined
|
||||||
*/
|
*/
|
||||||
ReceiptReceiptItemTaskCompleted(taskId: number): __Observable<ResponseArgsOfReceiptItemTaskListItemDTO> {
|
ReceiptReceiptItemTaskCompleted(taskId: number): __Observable<ResponseArgsOfReceiptItemTaskListItemDTO> {
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
.confirmation-list-item-done {
|
||||||
|
@apply bg-transparent p-0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
<div
|
||||||
|
class="w-[24.5rem] h-full p-4 flex flex-col gap-4 rounded-lg bg-isa-secondary-100"
|
||||||
|
[class.confirmation-list-item-done]="item().status !== 1"
|
||||||
|
>
|
||||||
|
@if (!isComplete()) {
|
||||||
|
<div
|
||||||
|
data-what="confirmation-message"
|
||||||
|
data-which="confirmation-comment"
|
||||||
|
class="isa-text-body-2-bold"
|
||||||
|
>
|
||||||
|
Bitte buchen Sie die Prämie aus dem Abholfach aus oder wählen Sie eine
|
||||||
|
andere Aktion.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-row justify-between items-center">
|
||||||
|
<ui-dropdown
|
||||||
|
class="h-8 border-none pl-0 hover:bg-transparent"
|
||||||
|
[value]="selectedAction()"
|
||||||
|
(valueChange)="setDropdownAction($event)"
|
||||||
|
>
|
||||||
|
<ui-dropdown-option [value]="LoyaltyCollectType.Collect"
|
||||||
|
>Prämie ausbuchen</ui-dropdown-option
|
||||||
|
>
|
||||||
|
<ui-dropdown-option [value]="LoyaltyCollectType.OutOfStock"
|
||||||
|
>Nicht gefunden</ui-dropdown-option
|
||||||
|
>
|
||||||
|
<ui-dropdown-option [value]="LoyaltyCollectType.Cancel"
|
||||||
|
>Stornieren</ui-dropdown-option
|
||||||
|
>
|
||||||
|
</ui-dropdown>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="flex items-center gap-2 self-end"
|
||||||
|
type="button"
|
||||||
|
uiButton
|
||||||
|
color="primary"
|
||||||
|
size="small"
|
||||||
|
(click)="onCollect()"
|
||||||
|
data-what="button"
|
||||||
|
data-which="complete"
|
||||||
|
>
|
||||||
|
<ng-icon name="isaActionCheck" uiButtonIcon></ng-icon>
|
||||||
|
Abschließen
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
} @else {
|
||||||
|
<div
|
||||||
|
data-what="done-message"
|
||||||
|
data-which="done-comment"
|
||||||
|
class="isa-text-body-2-bold"
|
||||||
|
>
|
||||||
|
Artikel wurde Storniert und Lesepunkte gut geschrieben.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span
|
||||||
|
class="flex items-center gap-2 self-end text-isa-accent-green isa-text-body-2-bold"
|
||||||
|
>
|
||||||
|
<ng-icon name="isaActionCheck"></ng-icon>
|
||||||
|
Abgeschlossen
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -1,13 +1,111 @@
|
|||||||
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
|
import {
|
||||||
import { DisplayOrderItem } from '@isa/oms/data-access';
|
ChangeDetectionStrategy,
|
||||||
|
Component,
|
||||||
|
input,
|
||||||
|
inject,
|
||||||
|
computed,
|
||||||
|
signal,
|
||||||
|
effect,
|
||||||
|
} from '@angular/core';
|
||||||
|
import { isaActionCheck } from '@isa/icons';
|
||||||
|
import {
|
||||||
|
DisplayOrderItem,
|
||||||
|
OrderRewardCollectFacade,
|
||||||
|
LoyaltyCollectType,
|
||||||
|
OrderItemSubsetResource,
|
||||||
|
getProcessingStatusCompleted,
|
||||||
|
} from '@isa/oms/data-access';
|
||||||
|
import { ButtonComponent } from '@isa/ui/buttons';
|
||||||
|
import { NgIcon } from '@ng-icons/core';
|
||||||
|
import { provideIcons } from '@ng-icons/core';
|
||||||
|
import { OrderConfiramtionStore } from '../../../reward-order-confirmation.store';
|
||||||
|
import {
|
||||||
|
DropdownButtonComponent,
|
||||||
|
DropdownOptionComponent,
|
||||||
|
} from '@isa/ui/input-controls';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'checkout-confirmation-list-item-action-card',
|
selector: 'checkout-confirmation-list-item-action-card',
|
||||||
templateUrl: './confirmation-list-item-action-card.component.html',
|
templateUrl: './confirmation-list-item-action-card.component.html',
|
||||||
styleUrls: ['./confirmation-list-item-action-card.component.css'],
|
styleUrls: ['./confirmation-list-item-action-card.component.css'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
imports: [],
|
imports: [
|
||||||
|
NgIcon,
|
||||||
|
ButtonComponent,
|
||||||
|
DropdownButtonComponent,
|
||||||
|
DropdownOptionComponent,
|
||||||
|
],
|
||||||
|
providers: [provideIcons({ isaActionCheck }), OrderItemSubsetResource],
|
||||||
})
|
})
|
||||||
export class ConfirmationListItemActionCardComponent {
|
export class ConfirmationListItemActionCardComponent {
|
||||||
|
LoyaltyCollectType = LoyaltyCollectType;
|
||||||
|
#orderRewardCollectFacade = inject(OrderRewardCollectFacade);
|
||||||
|
#store = inject(OrderConfiramtionStore);
|
||||||
|
#orderItemSubsetResource = inject(OrderItemSubsetResource);
|
||||||
|
|
||||||
item = input.required<DisplayOrderItem>();
|
item = input.required<DisplayOrderItem>();
|
||||||
|
|
||||||
|
orders = this.#store.orders;
|
||||||
|
|
||||||
|
getOrderIdBasedOnItem = computed(() => {
|
||||||
|
const item = this.item();
|
||||||
|
const orders = this.orders();
|
||||||
|
if (!orders) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const order = orders.find((order) =>
|
||||||
|
order.items?.some((orderItem) => orderItem.id === item.id),
|
||||||
|
);
|
||||||
|
return order?.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
orderItemSubsets = this.#orderItemSubsetResource.orderItemSubsets;
|
||||||
|
selectedAction = signal<LoyaltyCollectType>(LoyaltyCollectType.Collect);
|
||||||
|
isComplete = computed(() => {
|
||||||
|
const subsets = this.orderItemSubsets();
|
||||||
|
const statuses = subsets?.map((subset) => subset.processingStatus);
|
||||||
|
return getProcessingStatusCompleted(statuses);
|
||||||
|
});
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
effect(() => {
|
||||||
|
const item = this.item();
|
||||||
|
const orderItemSubsetIds = item.subsetItems
|
||||||
|
?.map((subset) => subset.id)
|
||||||
|
?.filter((id): id is number => id !== undefined);
|
||||||
|
|
||||||
|
if (orderItemSubsetIds?.length) {
|
||||||
|
this.#orderItemSubsetResource.loadOrderItemSubsets(orderItemSubsetIds);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setDropdownAction(value: LoyaltyCollectType) {
|
||||||
|
this.selectedAction.set(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
async onCollect() {
|
||||||
|
const item = this.item();
|
||||||
|
const orderId = this.getOrderIdBasedOnItem();
|
||||||
|
const orderItemId = item.id;
|
||||||
|
const collectType = this.selectedAction();
|
||||||
|
|
||||||
|
if (orderId && orderItemId) {
|
||||||
|
for (const subsetItem of item.subsetItems ?? []) {
|
||||||
|
const orderItemSubsetId = subsetItem.id;
|
||||||
|
const quantity = subsetItem.quantity;
|
||||||
|
|
||||||
|
if (orderItemSubsetId && !!quantity) {
|
||||||
|
await this.#orderRewardCollectFacade.collect({
|
||||||
|
orderId,
|
||||||
|
orderItemId,
|
||||||
|
orderItemSubsetId,
|
||||||
|
collectType,
|
||||||
|
quantity,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.#orderItemSubsetResource.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
:host {
|
:host {
|
||||||
@apply flex w-full items-start gap-6;
|
@apply flex w-full items-start gap-6;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import z from 'zod';
|
||||||
|
|
||||||
|
export const DateRangeSchema = z.object({
|
||||||
|
start: z.string().optional(),
|
||||||
|
end: z.string().optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type DateRange = z.infer<typeof DateRangeSchema>;
|
||||||
@@ -2,6 +2,7 @@ export * from './address.schema';
|
|||||||
export * from './addressee-with-reference.schema';
|
export * from './addressee-with-reference.schema';
|
||||||
export * from './buyer-type.schema';
|
export * from './buyer-type.schema';
|
||||||
export * from './communication-details.schema';
|
export * from './communication-details.schema';
|
||||||
|
export * from './date-range.schema';
|
||||||
export * from './entity-container.schema';
|
export * from './entity-container.schema';
|
||||||
export * from './entity-reference-container.schema';
|
export * from './entity-reference-container.schema';
|
||||||
export * from './entity-reference.schema';
|
export * from './entity-reference.schema';
|
||||||
|
|||||||
@@ -19,8 +19,9 @@ export * from './lib/errors';
|
|||||||
export * from './lib/questions';
|
export * from './lib/questions';
|
||||||
export * from './lib/models';
|
export * from './lib/models';
|
||||||
export * from './lib/facades';
|
export * from './lib/facades';
|
||||||
export * from './lib/helpers/return-process';
|
export * from './lib/helpers';
|
||||||
export * from './lib/schemas';
|
export * from './lib/schemas';
|
||||||
export * from './lib/services';
|
export * from './lib/services';
|
||||||
export * from './lib/operators';
|
export * from './lib/operators';
|
||||||
export * from './lib/stores';
|
export * from './lib/stores';
|
||||||
|
export * from './lib/resources';
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
export { OrderCreationFacade } from './order-creation.facade';
|
export { OrderCreationFacade } from './order-creation.facade';
|
||||||
|
export { OrderRewardCollectFacade } from './order-reward-collect.facade';
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
import { createServiceFactory, SpectatorService } from '@ngneat/spectator/jest';
|
||||||
|
import { OrderRewardCollectFacade } from './order-reward-collect.facade';
|
||||||
|
import { OrderRewardCollectService } from '../services';
|
||||||
|
import { DBHOrderItemListItemDTO } from '@generated/swagger/oms-api';
|
||||||
|
|
||||||
|
describe('OrderRewardCollectFacade', () => {
|
||||||
|
let spectator: SpectatorService<OrderRewardCollectFacade>;
|
||||||
|
const createService = createServiceFactory({
|
||||||
|
service: OrderRewardCollectFacade,
|
||||||
|
mocks: [OrderRewardCollectService],
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
spectator = createService();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('collect', () => {
|
||||||
|
it('should delegate to OrderRewardCollectService.collect', async () => {
|
||||||
|
// Arrange
|
||||||
|
const mockParams = {
|
||||||
|
orderId: 123,
|
||||||
|
orderItemId: 456,
|
||||||
|
orderItemSubsetId: 789,
|
||||||
|
collectType: 1 as const, // Valid LoyaltyCollectType.Collect
|
||||||
|
quantity: 2,
|
||||||
|
};
|
||||||
|
const mockResult: DBHOrderItemListItemDTO[] = [
|
||||||
|
{ orderItemType: 1 } as DBHOrderItemListItemDTO,
|
||||||
|
];
|
||||||
|
const rewardItemService = spectator.inject(OrderRewardCollectService);
|
||||||
|
(rewardItemService.collect as jest.Mock).mockResolvedValue(mockResult);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = await spectator.service.collect(mockParams);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toEqual(mockResult);
|
||||||
|
expect(rewardItemService.collect).toHaveBeenCalledWith({
|
||||||
|
orderId: mockParams.orderId,
|
||||||
|
orderItemId: mockParams.orderItemId,
|
||||||
|
orderItemSubsetId: mockParams.orderItemSubsetId,
|
||||||
|
collectType: mockParams.collectType,
|
||||||
|
quantity: mockParams.quantity,
|
||||||
|
});
|
||||||
|
expect(rewardItemService.collect).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should propagate errors from OrderRewardCollectService', async () => {
|
||||||
|
// Arrange
|
||||||
|
const mockParams = {
|
||||||
|
orderId: 123,
|
||||||
|
orderItemId: 456,
|
||||||
|
orderItemSubsetId: 789,
|
||||||
|
collectType: 1 as const, // Valid LoyaltyCollectType.Collect
|
||||||
|
quantity: 2,
|
||||||
|
};
|
||||||
|
const errorMessage = 'Failed to collect reward item';
|
||||||
|
const rewardItemService = spectator.inject(OrderRewardCollectService);
|
||||||
|
(rewardItemService.collect as jest.Mock).mockRejectedValue(
|
||||||
|
new Error(errorMessage),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
await expect(spectator.service.collect(mockParams)).rejects.toThrow(
|
||||||
|
errorMessage,
|
||||||
|
);
|
||||||
|
expect(rewardItemService.collect).toHaveBeenCalledWith({
|
||||||
|
orderId: mockParams.orderId,
|
||||||
|
orderItemId: mockParams.orderItemId,
|
||||||
|
orderItemSubsetId: mockParams.orderItemSubsetId,
|
||||||
|
collectType: mockParams.collectType,
|
||||||
|
quantity: mockParams.quantity,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getOrderItemSubset', () => {
|
||||||
|
it('should delegate to OrderRewardCollectService.fetchOrderItemSubset', async () => {
|
||||||
|
// Arrange
|
||||||
|
const mockParams = {
|
||||||
|
orderItemSubsetId: 789,
|
||||||
|
};
|
||||||
|
const mockResult = {
|
||||||
|
id: 789,
|
||||||
|
quantity: 2,
|
||||||
|
name: 'Test Subset',
|
||||||
|
};
|
||||||
|
const rewardItemService = spectator.inject(OrderRewardCollectService);
|
||||||
|
(rewardItemService.fetchOrderItemSubset as jest.Mock).mockResolvedValue(
|
||||||
|
mockResult,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = await spectator.service.getOrderItemSubset(mockParams);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toEqual(mockResult);
|
||||||
|
expect(rewardItemService.fetchOrderItemSubset).toHaveBeenCalledWith(
|
||||||
|
mockParams,
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
expect(rewardItemService.fetchOrderItemSubset).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { inject, Injectable } from '@angular/core';
|
||||||
|
import { OrderRewardCollectService } from '../services';
|
||||||
|
import {
|
||||||
|
FetchOrderItemSubsetSchemaInput,
|
||||||
|
OrderLoyaltyCollectInput,
|
||||||
|
} from '../schemas';
|
||||||
|
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class OrderRewardCollectFacade {
|
||||||
|
#orderRewardCollectService = inject(OrderRewardCollectService);
|
||||||
|
|
||||||
|
async collect(params: OrderLoyaltyCollectInput) {
|
||||||
|
return this.#orderRewardCollectService.collect(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getOrderItemSubset(
|
||||||
|
params: FetchOrderItemSubsetSchemaInput,
|
||||||
|
abortSignal?: AbortSignal,
|
||||||
|
) {
|
||||||
|
return this.#orderRewardCollectService.fetchOrderItemSubset(
|
||||||
|
params,
|
||||||
|
abortSignal,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
2
libs/oms/data-access/src/lib/helpers/index.ts
Normal file
2
libs/oms/data-access/src/lib/helpers/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export * from './return-process';
|
||||||
|
export * from './reward';
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
import { OrderItemProcessingStatusValue } from '../../schemas';
|
||||||
|
import { getProcessingStatusCompleted } from './get-processing-status-completed.helper';
|
||||||
|
|
||||||
|
describe('getProcessingStatusCompleted', () => {
|
||||||
|
it('should return true when all statuses are different from Bestellt (16)', () => {
|
||||||
|
// Arrange
|
||||||
|
const statuses = [
|
||||||
|
OrderItemProcessingStatusValue.Versendet, // 64
|
||||||
|
OrderItemProcessingStatusValue.Eingetroffen, // 128
|
||||||
|
OrderItemProcessingStatusValue.Abgeholt, // 256
|
||||||
|
];
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = getProcessingStatusCompleted(statuses);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true when statuses include various completed states', () => {
|
||||||
|
// Arrange
|
||||||
|
const statuses = [
|
||||||
|
OrderItemProcessingStatusValue.Zugestellt, // 4194304
|
||||||
|
OrderItemProcessingStatusValue.Abgeholt, // 256
|
||||||
|
OrderItemProcessingStatusValue.Versendet, // 64
|
||||||
|
];
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = getProcessingStatusCompleted(statuses);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false when at least one status is Bestellt (16)', () => {
|
||||||
|
// Arrange
|
||||||
|
const statuses = [
|
||||||
|
OrderItemProcessingStatusValue.Versendet, // 64
|
||||||
|
OrderItemProcessingStatusValue.Bestellt, // 16
|
||||||
|
OrderItemProcessingStatusValue.Abgeholt, // 256
|
||||||
|
];
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = getProcessingStatusCompleted(statuses);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false when all statuses are Bestellt (16)', () => {
|
||||||
|
// Arrange
|
||||||
|
const statuses = [
|
||||||
|
OrderItemProcessingStatusValue.Bestellt, // 16
|
||||||
|
OrderItemProcessingStatusValue.Bestellt, // 16
|
||||||
|
OrderItemProcessingStatusValue.Bestellt, // 16
|
||||||
|
];
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = getProcessingStatusCompleted(statuses);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false when array is empty', () => {
|
||||||
|
// Arrange
|
||||||
|
const statuses: number[] = [];
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = getProcessingStatusCompleted(statuses);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false when statuses is undefined', () => {
|
||||||
|
// Arrange
|
||||||
|
const statuses = undefined;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = getProcessingStatusCompleted(statuses);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true with single status different from Bestellt', () => {
|
||||||
|
// Arrange
|
||||||
|
const statuses = [OrderItemProcessingStatusValue.Abgeholt]; // 256
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = getProcessingStatusCompleted(statuses);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { OrderItemProcessingStatusValue } from '../../schemas';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if all processing statuses are completed (not in "Bestellt" state).
|
||||||
|
* Returns true if all statuses are different from "Bestellt" (16).
|
||||||
|
* Returns false if any status is still "Bestellt" (16) or if the array is empty/undefined.
|
||||||
|
*/
|
||||||
|
export const getProcessingStatusCompleted = (
|
||||||
|
statuses: number[] | undefined,
|
||||||
|
): boolean => {
|
||||||
|
if (!statuses || statuses.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return statuses.every(
|
||||||
|
(status) => status !== OrderItemProcessingStatusValue.Bestellt,
|
||||||
|
);
|
||||||
|
};
|
||||||
1
libs/oms/data-access/src/lib/helpers/reward/index.ts
Normal file
1
libs/oms/data-access/src/lib/helpers/reward/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './get-processing-status-completed.helper';
|
||||||
@@ -6,3 +6,4 @@ export * from './questions';
|
|||||||
export * from './schemas';
|
export * from './schemas';
|
||||||
export * from './services';
|
export * from './services';
|
||||||
export * from './stores';
|
export * from './stores';
|
||||||
|
export * from './resources';
|
||||||
|
|||||||
1
libs/oms/data-access/src/lib/resources/index.ts
Normal file
1
libs/oms/data-access/src/lib/resources/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './order-item-subset.resource';
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import { computed, inject, Injectable, resource, signal } from '@angular/core';
|
||||||
|
import { DisplayOrderItemSubset } from '../schemas';
|
||||||
|
import { OrderRewardCollectFacade } from '../facades';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class OrderItemSubsetResource {
|
||||||
|
#orderRewardCollectFacade = inject(OrderRewardCollectFacade);
|
||||||
|
|
||||||
|
#orderItemSubsetIds = signal<number[] | undefined>(undefined);
|
||||||
|
|
||||||
|
#orderItemSubsetsResource = resource({
|
||||||
|
params: computed(() => ({
|
||||||
|
orderItemSubsetIds: this.#orderItemSubsetIds(),
|
||||||
|
})),
|
||||||
|
loader: async ({
|
||||||
|
params,
|
||||||
|
abortSignal,
|
||||||
|
}): Promise<DisplayOrderItemSubset[]> => {
|
||||||
|
if (!params?.orderItemSubsetIds?.length) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const results: DisplayOrderItemSubset[] = [];
|
||||||
|
for (const id of params.orderItemSubsetIds) {
|
||||||
|
const result = await this.#orderRewardCollectFacade.getOrderItemSubset(
|
||||||
|
{ orderItemSubsetId: id },
|
||||||
|
abortSignal,
|
||||||
|
);
|
||||||
|
if (result) {
|
||||||
|
results.push(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
},
|
||||||
|
defaultValue: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
readonly orderItemSubsets = this.#orderItemSubsetsResource.value.asReadonly();
|
||||||
|
readonly loading = this.#orderItemSubsetsResource.isLoading;
|
||||||
|
readonly error = computed(
|
||||||
|
() => this.#orderItemSubsetsResource.error()?.message ?? null,
|
||||||
|
);
|
||||||
|
|
||||||
|
loadOrderItemSubsets(orderItemSubsetIds: number[] | undefined) {
|
||||||
|
this.#orderItemSubsetIds.set(orderItemSubsetIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh() {
|
||||||
|
this.#orderItemSubsetsResource.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import { EntitySchema, DateRangeSchema } from '@isa/common/data-access';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { OrderItemProcessingStatusValueSchema } from './order-item-processing-status-value.schema';
|
||||||
|
|
||||||
|
// Forward declaration for circular reference
|
||||||
|
export const DisplayOrderItemSubsetSchema = z
|
||||||
|
.object({
|
||||||
|
compartmentCode: z.string().describe('Compartment code').optional(),
|
||||||
|
compartmentInfo: z.string().describe('Compartment information').optional(),
|
||||||
|
compartmentStart: z.string().describe('Compartment start').optional(),
|
||||||
|
compartmentStop: z.string().describe('Compartment stop').optional(),
|
||||||
|
description: z.string().describe('Description text').optional(),
|
||||||
|
estimatedDelivery: DateRangeSchema.describe(
|
||||||
|
'Estimated delivery date range',
|
||||||
|
).optional(),
|
||||||
|
estimatedShippingDate: z
|
||||||
|
.string()
|
||||||
|
.describe('Estimated shipping date')
|
||||||
|
.optional(),
|
||||||
|
orderItem: z
|
||||||
|
.lazy(() => z.any())
|
||||||
|
.describe('Order item')
|
||||||
|
.optional(), // Circular reference to DisplayOrderItem
|
||||||
|
orderItemSubsetNumber: z
|
||||||
|
.string()
|
||||||
|
.describe('Order item subset number')
|
||||||
|
.optional(),
|
||||||
|
preferredPickUpDate: z
|
||||||
|
.string()
|
||||||
|
.describe('Preferred pick up date')
|
||||||
|
.optional(),
|
||||||
|
processingStatus:
|
||||||
|
OrderItemProcessingStatusValueSchema.describe('Processing status'),
|
||||||
|
processingStatusDate: z
|
||||||
|
.string()
|
||||||
|
.describe('Processing status date')
|
||||||
|
.optional(),
|
||||||
|
quantity: z.number().describe('Quantity').optional(),
|
||||||
|
specialComment: z.string().describe('Special comment').optional(),
|
||||||
|
ssc: z.string().describe('SSC code').optional(),
|
||||||
|
sscText: z.string().describe('SSC text').optional(),
|
||||||
|
supplierLabel: z.string().describe('Supplier label').optional(),
|
||||||
|
supplierName: z.string().describe('Supplier name').optional(),
|
||||||
|
supplyChannel: z.string().describe('Supply channel').optional(),
|
||||||
|
trackingNumber: z.string().describe('Tracking number').optional(),
|
||||||
|
})
|
||||||
|
.extend(EntitySchema.shape);
|
||||||
|
|
||||||
|
export type DisplayOrderItemSubset = z.infer<
|
||||||
|
typeof DisplayOrderItemSubsetSchema
|
||||||
|
>;
|
||||||
@@ -1,32 +1,33 @@
|
|||||||
import { EntitySchema, QuantityUnitTypeSchema } from '@isa/common/data-access';
|
import { EntitySchema, QuantityUnitTypeSchema } from '@isa/common/data-access';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { PriceSchema } from './price.schema';
|
import { PriceSchema } from './price.schema';
|
||||||
import { ProductSchema } from './product.schema';
|
import { ProductSchema } from './product.schema';
|
||||||
import { PromotionSchema } from './promotion.schema';
|
import { PromotionSchema } from './promotion.schema';
|
||||||
|
import { DisplayOrderItemSubsetSchema } from './display-order-item-subset.schema';
|
||||||
// Forward declaration for circular reference
|
|
||||||
export const DisplayOrderItemSchema = z
|
// Forward declaration for circular reference
|
||||||
.object({
|
export const DisplayOrderItemSchema = z
|
||||||
buyerComment: z.string().describe('Buyer comment').optional(),
|
.object({
|
||||||
description: z.string().describe('Description text').optional(),
|
buyerComment: z.string().describe('Buyer comment').optional(),
|
||||||
features: z.record(z.string().describe('Features'), z.string()).optional(),
|
description: z.string().describe('Description text').optional(),
|
||||||
order: z
|
features: z.record(z.string().describe('Features'), z.string()).optional(),
|
||||||
.lazy(() => z.any())
|
order: z
|
||||||
.describe('Order')
|
.lazy(() => z.any())
|
||||||
.optional(), // Circular reference to DisplayOrder
|
.describe('Order')
|
||||||
orderDate: z.string().describe('Order date').optional(),
|
.optional(), // Circular reference to DisplayOrder
|
||||||
orderItemNumber: z.string().describe('OrderItem number').optional(),
|
orderDate: z.string().describe('Order date').optional(),
|
||||||
price: PriceSchema.describe('Price information').optional(),
|
orderItemNumber: z.string().describe('OrderItem number').optional(),
|
||||||
product: ProductSchema.describe('Product').optional(),
|
price: PriceSchema.describe('Price information').optional(),
|
||||||
promotion: PromotionSchema.describe('Promotion information').optional(),
|
product: ProductSchema.describe('Product').optional(),
|
||||||
quantity: z.number().describe('Quantity').optional(),
|
promotion: PromotionSchema.describe('Promotion information').optional(),
|
||||||
quantityUnit: z.string().describe('Quantity unit').optional(),
|
quantity: z.number().describe('Quantity').optional(),
|
||||||
quantityUnitType: QuantityUnitTypeSchema.describe('QuantityUnit type'),
|
quantityUnit: z.string().describe('Quantity unit').optional(),
|
||||||
subsetItems: z
|
quantityUnitType: QuantityUnitTypeSchema.describe('QuantityUnit type'),
|
||||||
.array(z.lazy(() => z.any()))
|
subsetItems: z
|
||||||
.describe('Subset items')
|
.array(DisplayOrderItemSubsetSchema)
|
||||||
.optional(), // Circular reference to DisplayOrderItemSubset
|
.describe('Subset items')
|
||||||
})
|
.optional(),
|
||||||
.extend(EntitySchema.shape);
|
})
|
||||||
|
.extend(EntitySchema.shape);
|
||||||
export type DisplayOrderItem = z.infer<typeof DisplayOrderItemSchema>;
|
|
||||||
|
export type DisplayOrderItem = z.infer<typeof DisplayOrderItemSchema>;
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import z from 'zod';
|
||||||
|
|
||||||
|
export const FetchOrderItemSubsetSchema = z.object({
|
||||||
|
orderItemSubsetId: z.number(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type FetchOrderItemSubsetSchemaInput = z.infer<
|
||||||
|
typeof FetchOrderItemSubsetSchema
|
||||||
|
>;
|
||||||
@@ -17,3 +17,8 @@ export * from './return-receipt-values.schema';
|
|||||||
export * from './shipping-type.schema';
|
export * from './shipping-type.schema';
|
||||||
export * from './terms-of-delivery.schema';
|
export * from './terms-of-delivery.schema';
|
||||||
export * from './type-of-delivery.schema';
|
export * from './type-of-delivery.schema';
|
||||||
|
export * from './loyalty-collect-type.schema';
|
||||||
|
export * from './order-loyalty-collect.schema';
|
||||||
|
export * from './fetch-order-item-subset.schema';
|
||||||
|
export * from './display-order-item-subset.schema';
|
||||||
|
export * from './order-item-processing-status-value.schema';
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import z from 'zod';
|
||||||
|
|
||||||
|
export const LoyaltyCollectType = {
|
||||||
|
Collect: 0,
|
||||||
|
OutOfStock: 1,
|
||||||
|
Cancel: 2,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
const ALL_FLAGS = Object.values(LoyaltyCollectType).reduce<number>(
|
||||||
|
(a, b) => a | b,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
|
export const LoyaltyCollectTypeSchema = z
|
||||||
|
.nativeEnum(LoyaltyCollectType)
|
||||||
|
.refine((val) => (val & ALL_FLAGS) === val, {
|
||||||
|
message: 'Invalid loyalty collect type',
|
||||||
|
})
|
||||||
|
.describe('Loyalty collect type');
|
||||||
|
|
||||||
|
export type LoyaltyCollectType = z.infer<typeof LoyaltyCollectTypeSchema>;
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import z from 'zod';
|
||||||
|
|
||||||
|
export const OrderItemProcessingStatusValue = {
|
||||||
|
NotSet: 0,
|
||||||
|
NeuAngelegt1: 1,
|
||||||
|
NeuAngelegt2: 2,
|
||||||
|
NeuÜbernommen: 4,
|
||||||
|
Geparkt: 8,
|
||||||
|
Bestellt: 16,
|
||||||
|
VorbereitungVersand: 32,
|
||||||
|
Versendet: 64,
|
||||||
|
Eingetroffen: 128,
|
||||||
|
Abgeholt: 256,
|
||||||
|
StorniertKunde: 512,
|
||||||
|
Storniert: 1024,
|
||||||
|
StorniertLieferant: 2048,
|
||||||
|
NichtLieferbar: 4096,
|
||||||
|
Nachbestellt: 8192,
|
||||||
|
Zurückgegeben: 16384,
|
||||||
|
ZumDownloadVerfügbar: 32768,
|
||||||
|
Downloaded: 65536,
|
||||||
|
NichtAbgeholt: 131072,
|
||||||
|
AnsLagerNichtAbgeholt: 262144,
|
||||||
|
Angefragt: 524288,
|
||||||
|
WeitergeleitetIntern: 1048576,
|
||||||
|
Überfällig: 2097152,
|
||||||
|
Zugestellt: 4194304,
|
||||||
|
LieferantErmittelt: 8388608,
|
||||||
|
DerzeitNichtLieferbar: 16777216,
|
||||||
|
Reserviert: 33554432,
|
||||||
|
Zusammengestellt: 67108864,
|
||||||
|
Verpackt: 134217728,
|
||||||
|
Lieferschein: 268435456,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const OrderItemProcessingStatusValueSchema = z.number().refine(
|
||||||
|
(val) => {
|
||||||
|
// Validate that the value is a valid combination of flags
|
||||||
|
const allFlags = Object.values(
|
||||||
|
OrderItemProcessingStatusValue,
|
||||||
|
).reduce<number>((acc, flag) => acc | flag, 0);
|
||||||
|
return (val & allFlags) === val;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: 'Invalid order item processing status value',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
export type OrderItemProcessingStatusValue = z.infer<
|
||||||
|
typeof OrderItemProcessingStatusValueSchema
|
||||||
|
>;
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import z from 'zod';
|
||||||
|
import { LoyaltyCollectTypeSchema } from './loyalty-collect-type.schema';
|
||||||
|
|
||||||
|
export const OrderLoyaltyCollectSchema = z.object({
|
||||||
|
orderId: z.number(),
|
||||||
|
orderItemId: z.number(),
|
||||||
|
orderItemSubsetId: z.number(),
|
||||||
|
collectType: LoyaltyCollectTypeSchema,
|
||||||
|
quantity: z.number().int().nonnegative(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type OrderLoyaltyCollectInput = z.infer<
|
||||||
|
typeof OrderLoyaltyCollectSchema
|
||||||
|
>;
|
||||||
@@ -8,3 +8,4 @@ export * from './return-details.service';
|
|||||||
export * from './return-process.service';
|
export * from './return-process.service';
|
||||||
export * from './return-search.service';
|
export * from './return-search.service';
|
||||||
export * from './return-task-list.service';
|
export * from './return-task-list.service';
|
||||||
|
export * from './order-reward-collect.service';
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
import { createServiceFactory, SpectatorService } from '@ngneat/spectator/jest';
|
||||||
|
import { OrderRewardCollectService } from './order-reward-collect.service';
|
||||||
|
import {
|
||||||
|
OrderService,
|
||||||
|
DBHOrderItemListItemDTO,
|
||||||
|
} from '@generated/swagger/oms-api';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
|
||||||
|
describe('OrderRewardCollectService', () => {
|
||||||
|
let spectator: SpectatorService<OrderRewardCollectService>;
|
||||||
|
const createService = createServiceFactory({
|
||||||
|
service: OrderRewardCollectService,
|
||||||
|
mocks: [OrderService],
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
spectator = createService();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(spectator.service).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('collect', () => {
|
||||||
|
it('should collect reward item successfully', async () => {
|
||||||
|
// Arrange
|
||||||
|
const mockParams = {
|
||||||
|
orderId: 123,
|
||||||
|
orderItemId: 456,
|
||||||
|
orderItemSubsetId: 789,
|
||||||
|
collectType: 1 as const, // Valid LoyaltyCollectType.Collect
|
||||||
|
quantity: 2,
|
||||||
|
};
|
||||||
|
const mockResult: DBHOrderItemListItemDTO[] = [
|
||||||
|
{ orderItemType: 1 } as DBHOrderItemListItemDTO,
|
||||||
|
];
|
||||||
|
const mockResponse = { result: mockResult, error: false };
|
||||||
|
const orderService = spectator.inject(OrderService);
|
||||||
|
orderService.OrderLoyaltyCollect.mockReturnValue(of(mockResponse));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = await spectator.service.collect(mockParams);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toEqual(mockResult);
|
||||||
|
expect(orderService.OrderLoyaltyCollect).toHaveBeenCalledWith({
|
||||||
|
orderId: mockParams.orderId,
|
||||||
|
orderItemId: mockParams.orderItemId,
|
||||||
|
orderItemSubsetId: mockParams.orderItemSubsetId,
|
||||||
|
data: {
|
||||||
|
collectType: mockParams.collectType,
|
||||||
|
quantity: mockParams.quantity,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(orderService.OrderLoyaltyCollect).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error if API response contains error', async () => {
|
||||||
|
// Arrange
|
||||||
|
const mockParams = {
|
||||||
|
orderId: 123,
|
||||||
|
orderItemId: 456,
|
||||||
|
orderItemSubsetId: 789,
|
||||||
|
collectType: 1 as const, // Valid LoyaltyCollectType.Collect
|
||||||
|
quantity: 2,
|
||||||
|
};
|
||||||
|
const mockResponse = { error: true, result: undefined };
|
||||||
|
const orderService = spectator.inject(OrderService);
|
||||||
|
orderService.OrderLoyaltyCollect.mockReturnValue(of(mockResponse));
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
await expect(spectator.service.collect(mockParams)).rejects.toThrow();
|
||||||
|
expect(orderService.OrderLoyaltyCollect).toHaveBeenCalledWith({
|
||||||
|
orderId: mockParams.orderId,
|
||||||
|
orderItemId: mockParams.orderItemId,
|
||||||
|
orderItemSubsetId: mockParams.orderItemSubsetId,
|
||||||
|
data: {
|
||||||
|
collectType: mockParams.collectType,
|
||||||
|
quantity: mockParams.quantity,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('fetchOrderItemSubset', () => {
|
||||||
|
it('should fetch order item subset successfully', async () => {
|
||||||
|
// Arrange
|
||||||
|
const mockParams = {
|
||||||
|
orderItemSubsetId: 789,
|
||||||
|
};
|
||||||
|
const mockResult = {
|
||||||
|
id: 789,
|
||||||
|
quantity: 2,
|
||||||
|
name: 'Test Subset',
|
||||||
|
};
|
||||||
|
const mockResponse = { result: mockResult, error: false };
|
||||||
|
const orderService = spectator.inject(OrderService);
|
||||||
|
orderService.OrderGetOrderItemSubset.mockReturnValue(of(mockResponse));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const result = await spectator.service.fetchOrderItemSubset(mockParams);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(result).toEqual(mockResult);
|
||||||
|
expect(orderService.OrderGetOrderItemSubset).toHaveBeenCalledWith(
|
||||||
|
mockParams.orderItemSubsetId,
|
||||||
|
);
|
||||||
|
expect(orderService.OrderGetOrderItemSubset).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import { inject, Injectable } from '@angular/core';
|
||||||
|
import { OrderService } from '@generated/swagger/oms-api';
|
||||||
|
import { ResponseArgsError, takeUntilAborted } from '@isa/common/data-access';
|
||||||
|
import { logger } from '@isa/core/logging';
|
||||||
|
import { firstValueFrom } from 'rxjs';
|
||||||
|
import {
|
||||||
|
DisplayOrderItemSubset,
|
||||||
|
FetchOrderItemSubsetSchema,
|
||||||
|
FetchOrderItemSubsetSchemaInput,
|
||||||
|
OrderLoyaltyCollectInput,
|
||||||
|
OrderLoyaltyCollectSchema,
|
||||||
|
} from '../schemas';
|
||||||
|
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class OrderRewardCollectService {
|
||||||
|
#logger = logger(() => ({ service: 'OrderRewardCollectService' }));
|
||||||
|
#orderService = inject(OrderService);
|
||||||
|
|
||||||
|
async collect(params: OrderLoyaltyCollectInput) {
|
||||||
|
try {
|
||||||
|
params = OrderLoyaltyCollectSchema.parse(params);
|
||||||
|
} catch (error) {
|
||||||
|
this.#logger.error('Failed to parse schema', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
const req$ = this.#orderService.OrderLoyaltyCollect({
|
||||||
|
orderId: params.orderId,
|
||||||
|
orderItemId: params.orderItemId,
|
||||||
|
orderItemSubsetId: params.orderItemSubsetId,
|
||||||
|
data: {
|
||||||
|
collectType: params.collectType,
|
||||||
|
quantity: params.quantity,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const res = await firstValueFrom(req$);
|
||||||
|
|
||||||
|
if (res.error) {
|
||||||
|
const error = new ResponseArgsError(res);
|
||||||
|
this.#logger.error('Failed to collect reward item', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchOrderItemSubset(
|
||||||
|
params: FetchOrderItemSubsetSchemaInput,
|
||||||
|
abortSignal?: AbortSignal,
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
params = FetchOrderItemSubsetSchema.parse(params);
|
||||||
|
} catch (error) {
|
||||||
|
this.#logger.error('Failed to parse schema', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
let req$ = this.#orderService.OrderGetOrderItemSubset(
|
||||||
|
params.orderItemSubsetId,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (abortSignal) {
|
||||||
|
req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await firstValueFrom(req$);
|
||||||
|
|
||||||
|
if (res.error) {
|
||||||
|
const error = new ResponseArgsError(res);
|
||||||
|
this.#logger.error('Failed to fetch order item subset', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.result as DisplayOrderItemSubset;
|
||||||
|
}
|
||||||
|
}
|
||||||
567
package-lock.json
generated
567
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user