diff --git a/src/app/core/layout/store-layout/store-layout.component.html b/src/app/core/layout/store-layout/store-layout.component.html index 96036aa..204c82d 100644 --- a/src/app/core/layout/store-layout/store-layout.component.html +++ b/src/app/core/layout/store-layout/store-layout.component.html @@ -29,6 +29,7 @@ [subtotal]="cartSubtotal()" [discount]="cartDiscount()" [total]="cartTotal()" + [readonly]="!cartEditingEnabled()" [backgroundColor]="'#ffffff'" (closed)="isCartOpen.set(false)" > diff --git a/src/app/core/layout/store-layout/store-layout.component.spec.ts b/src/app/core/layout/store-layout/store-layout.component.spec.ts index 190f689..1b6758d 100644 --- a/src/app/core/layout/store-layout/store-layout.component.spec.ts +++ b/src/app/core/layout/store-layout/store-layout.component.spec.ts @@ -645,4 +645,35 @@ describe('StoreLayoutComponent', () => { expect(cartItem.componentInstance.quantityDisabled()).toBe(false); expect(buyButton).toBeDefined(); }); + + it('hides quantity selectors when the tenant disables cart editing', () => { + tenantState.set({ ...tenant, cart_editing_enabled: false }); + cartState.set({ + id: 1, + tenant_codigo: tenant.codigo, + status: 'active', + subtotal: '100.00', + items: [ + { + id: 1, + cantidad: 1, + precio_unitario: '100.00', + catalog_item_id: 1, + variant_id: null, + nombre: 'Producto', + imagen: null, + variant: null, + }, + ], + }); + + const fixture = TestBed.createComponent(StoreLayoutComponent); + fixture.detectChanges(); + (fixture.componentInstance as any).isCartOpen.set(true); + fixture.detectChanges(); + + const cartItem = fixture.debugElement.query(By.css('app-cart-item')); + expect(cartItem.componentInstance.readonly()).toBe(true); + expect(cartItem.nativeElement.querySelector('app-quantity-selector')).toBeNull(); + }); }); diff --git a/src/app/core/layout/store-layout/store-layout.component.ts b/src/app/core/layout/store-layout/store-layout.component.ts index 87f919e..47d17e6 100644 --- a/src/app/core/layout/store-layout/store-layout.component.ts +++ b/src/app/core/layout/store-layout/store-layout.component.ts @@ -36,6 +36,9 @@ export class StoreLayoutComponent implements OnInit { protected readonly isCartOpen = signal(false); protected readonly isCreatingPurchase = signal(false); protected readonly displayCart = computed(() => this.tenant()?.display_cart ?? true); + protected readonly cartEditingEnabled = computed( + () => this.tenant()?.cart_editing_enabled ?? true, + ); protected readonly cartSubtotal = computed(() => { const cart = this.cartService.cart(); diff --git a/src/app/core/services/tenant.interface.ts b/src/app/core/services/tenant.interface.ts index 34c6f33..40eb77f 100644 --- a/src/app/core/services/tenant.interface.ts +++ b/src/app/core/services/tenant.interface.ts @@ -126,6 +126,7 @@ export interface Tenant { display_categories?: boolean; display_seach_bar?: boolean; display_cart?: boolean; + cart_editing_enabled?: boolean; social_media?: SocialMedia[]; menues?: Menu[]; categories: Category[]; diff --git a/src/app/features/store/pages/checkout-page/checkout-page.component.html b/src/app/features/store/pages/checkout-page/checkout-page.component.html index f062cd9..33a2c30 100644 --- a/src/app/features/store/pages/checkout-page/checkout-page.component.html +++ b/src/app/features/store/pages/checkout-page/checkout-page.component.html @@ -58,6 +58,7 @@ [subtotal]="cartSubtotal()" [discount]="cartDiscount()" [total]="cartTotal()" + [readonly]="!cartEditingEnabled()" [allowEditing]=" createdPurchase()?.status === 'created' || createdPurchase()?.status === 'pending_payment' " diff --git a/src/app/features/store/pages/checkout-page/checkout-page.component.spec.ts b/src/app/features/store/pages/checkout-page/checkout-page.component.spec.ts index c3f71b7..737c0c0 100644 --- a/src/app/features/store/pages/checkout-page/checkout-page.component.spec.ts +++ b/src/app/features/store/pages/checkout-page/checkout-page.component.spec.ts @@ -33,6 +33,7 @@ describe('CheckoutPageComponent payment validation', () => { let routerStub: { navigate: ReturnType }; let routeQueryParamMap: ReturnType; let authUserState: ReturnType; + let tenantState: ReturnType>; beforeAll(() => { try { @@ -88,6 +89,7 @@ describe('CheckoutPageComponent payment validation', () => { routerStub = { navigate: vi.fn() }; routeQueryParamMap = convertToParamMap({}); authUserState = signal(null); + tenantState = signal({ codigo: 'tenant-test' }); await TestBed.configureTestingModule({ imports: [CheckoutPageComponent], @@ -95,7 +97,7 @@ describe('CheckoutPageComponent payment validation', () => { { provide: CheckoutService, useValue: checkoutServiceStub }, { provide: CatalogService, useValue: { getCatalogItem: vi.fn() } }, { provide: CartService, useValue: cartServiceStub }, - { provide: TenantService, useValue: { tenant: signal({ codigo: 'tenant-test' }) } }, + { provide: TenantService, useValue: { tenant: tenantState } }, { provide: AuthService, useValue: { user: authUserState } }, { provide: ActivatedRoute, @@ -366,11 +368,7 @@ describe('CheckoutPageComponent payment validation', () => { expect(component.checkoutStepIndex()).toBe(1); expect(component.selectedPaymentMethod()).toBe('qr'); - expect(checkoutServiceStub.generatePaymentIntent).toHaveBeenCalledWith( - 'tenant-test', - 25, - 'qr', - ); + expect(checkoutServiceStub.generatePaymentIntent).toHaveBeenCalledWith('tenant-test', 25, 'qr'); expect(component.qrData()).toBe('qr-value'); expect(component.qrPaymentStatus()).toBe('waiting'); }); @@ -472,6 +470,17 @@ describe('CheckoutPageComponent payment validation', () => { expect(component.isEditingItems()).toBe(false); }); + it('does not allow item editing when the tenant disables cart editing', async () => { + tenantState.set({ codigo: 'tenant-test', cart_editing_enabled: false }); + const { component } = createComponent(); + + await component.onEditingItemsChange(true); + + expect(component.cartEditingEnabled()).toBe(false); + expect(component.isEditingItems()).toBe(false); + expect(checkoutServiceStub.prepareItemEditing).not.toHaveBeenCalled(); + }); + it('updates customer data on the existing purchase before payment', async () => { const updatedPurchase = { id: 25, diff --git a/src/app/features/store/pages/checkout-page/checkout-page.component.ts b/src/app/features/store/pages/checkout-page/checkout-page.component.ts index 6db657f..ca75da9 100644 --- a/src/app/features/store/pages/checkout-page/checkout-page.component.ts +++ b/src/app/features/store/pages/checkout-page/checkout-page.component.ts @@ -79,6 +79,9 @@ export class CheckoutPageComponent implements OnInit, OnDestroy { protected readonly createdPurchase = signal(null); protected readonly isLoadingPurchase = signal(true); protected readonly checkoutStepIndex = signal(0); + protected readonly cartEditingEnabled = computed( + () => this.tenantService.tenant()?.cart_editing_enabled ?? true, + ); protected readonly cartSubtotal = computed(() => { const purchase = this.createdPurchase(); @@ -179,6 +182,10 @@ export class CheckoutPageComponent implements OnInit, OnDestroy { return; } + if (editing && !this.cartEditingEnabled()) { + return; + } + if (!editing) { this.isEditingItems.set(false); @@ -224,7 +231,14 @@ export class CheckoutPageComponent implements OnInit, OnDestroy { const purchaseId = this.createdPurchaseId(); const itemId = event.item.cartItemId; - if (!tenant || !purchaseId || !itemId || this.isUpdatingItem() || !this.isEditingItems()) { + if ( + !this.cartEditingEnabled() || + !tenant || + !purchaseId || + !itemId || + this.isUpdatingItem() || + !this.isEditingItems() + ) { return; }