diff --git a/src/components/displays/department/pos/steps/mobile/PosDepartmentStepMobile2.vue b/src/components/displays/department/pos/steps/mobile/PosDepartmentStepMobile2.vue index 85810ca6..2fef6520 100644 --- a/src/components/displays/department/pos/steps/mobile/PosDepartmentStepMobile2.vue +++ b/src/components/displays/department/pos/steps/mobile/PosDepartmentStepMobile2.vue @@ -48,7 +48,12 @@ import { registerPosStepSaveBarrier, saveOrderMetadataField, } from "@/components/shop/POSDepartmentProcess.vue"; -import { createOrderItem, getOrderItems, removeOrderItem } from "@/components/shop/OrdersItems.vue"; +import { + AUDITED_ORDER_ITEM_PRODUCT_IDS, + createOrderItem, + getOrderItems, + removeOrderItem, +} from "@/components/shop/OrdersItems.vue"; import { syncMobileOrderItems } from "@/components/displays/department/pos/steps/mobile/utils/syncMobileOrderItems.js"; import { PosProduct } from "@/components/displays/department/pos/steps/mobile/objects/PosProduct.vue"; import PosDepartmentStepMobileButtonClearAll from "@/components/displays/department/pos/steps/mobile/elements/PosDepartmentStepMobileButtonClearAll.vue"; @@ -1035,6 +1040,7 @@ const productRequiresOrderItemNote = (product: any) => { return ( isEnabledFlag(product?.requires_note ?? product?.product?.requires_note) || + AUDITED_ORDER_ITEM_PRODUCT_IDS.has(getProductId(product)) || getProductId(product) === EXTRAORDINARY_CHEMISTRY_PRODUCT_ID || getProductName(product) === EXTRAORDINARY_CHEMISTRY_PRODUCT_NAME ); diff --git a/tests/e2e/pos-mobile-order-flow.spec.js b/tests/e2e/pos-mobile-order-flow.spec.js index 3229f3b8..e987db06 100644 --- a/tests/e2e/pos-mobile-order-flow.spec.js +++ b/tests/e2e/pos-mobile-order-flow.spec.js @@ -4213,6 +4213,94 @@ test.describe("POS mobile order flow", () => { await waitForStepReset(page); }); + test("prompts for a required reason note for audited add-on products that are not the chemistry product", async ({ + page, + }) => { + const orderId = 9416; + const baseFixture = createMobilePosFixture(); + const auditedProduct = { + id: 24, + name: "Højtryk - ekstra tid", + description: "Audited addon that requires a reason comment", + price: 95, + subscription_allowed: true, + category: 8, + piktogram: "24", + apply_category_discount: false, + requires_note: false, + is_wash: false, + display_in_booking_form: true, + order_priority: 6, + addons: [], + }; + const primaryProduct = { + ...fixtureProduct(53), + addons: [ + ...fixtureProduct(53).addons, + { + id: auditedProduct.id, + name: auditedProduct.name, + price: auditedProduct.price, + product: { ...auditedProduct }, + quantity: 1, + min: 0, + max: -1, + }, + ], + }; + const fixture = createMobilePosFixture({ + products: baseFixture.products + .map((product) => { + if (Number(product.id) !== 53) { + return product; + } + return primaryProduct; + }) + .concat(auditedProduct), + ordersById: { + [orderId]: buildRegularOrder(orderId), + }, + orderItemsByOrderId: { + [orderId]: [], + }, + }); + + await setupMobilePosPage(page, fixture, { + token: "mobile-product-24-note-token", + seedState: { + customerId: REGULAR_CUSTOMER_ID, + reg: "AB12345", + reference: "PRODUCT-24-NOTE", + primaryItem: primaryProduct, + vehicleType: 53, + lastOrderId: null, + }, + route: { + step: 2, + orderId, + customerId: REGULAR_CUSTOMER_ID, + }, + }); + + await expect(page.getByTestId("pos-mobile-step-2")).toBeVisible({ timeout: 10_000 }); + await expect(page.getByTestId("pos-mobile-addon-24-value")).toHaveText("1", { timeout: 10_000 }); + + await page.getByTestId("pos-mobile-next-step").click(); + await expect(page.locator('[data-testid="pos-mobile-popup"][data-popup-id="add_product_note"]')).toBeVisible({ + timeout: 10_000, + }); + await page.getByTestId("pos-mobile-product-note-input").fill("Højtryk bagpå venstre side"); + await page.getByTestId("pos-mobile-product-note-confirm").click(); + + await expect.poll(() => fixture.requestCounters.orderItemsPost, { timeout: 10_000 }).toBe(2); + await expect.poll(() => fixture.requestCounters.markAsCompleted, { timeout: 10_000 }).toBe(1); + const product24Create = fixture.requestLog.orderItemCreates.find((entry) => Number(entry.product_id) === 24); + expect(product24Create?.notes).toBe("Højtryk bagpå venstre side"); + expect(product24Create?.reason_code).toBe("customer_approved_extra_work"); + expect(product24Create?.reason_comment).toBe("Højtryk bagpå venstre side"); + await waitForStepReset(page); + }); + test("booking hydration applies booking items, reference, notes, and po", async ({ page }) => { const orderId = 9405; const fixture = createMobilePosFixture({ diff --git a/tests/e2e/support/mobilePos.js b/tests/e2e/support/mobilePos.js index bad5b82e..5d092279 100644 --- a/tests/e2e/support/mobilePos.js +++ b/tests/e2e/support/mobilePos.js @@ -11,6 +11,7 @@ export const CARD_CUSTOMER_ID = 999; export const WASH_CERTIFICATE_PRODUCT_ID = 41; const EXTRAORDINARY_CHEMISTRY_PRODUCT_ID = 27; const EXTRAORDINARY_CHEMISTRY_PRODUCT_NAME = "Ekstraordinær pr. 10 min inkl. kemi"; +const AUDITED_ORDER_ITEM_PRODUCT_IDS = new Set([21, 22, 24, 25, 26, 27]); export const MOBILE_PERMISSIONS = ["admin", "department_access_1"]; export const MOBILE_NEXT_STEP_COOLDOWN_MS = 2100; @@ -342,6 +343,7 @@ function productRequiresOrderItemNote(product) { const productId = Number(product?.product?.id ?? product?.product_id ?? product?.id ?? 0); return ( isEnabledFlag(product?.requires_note ?? product?.product?.requires_note) || + AUDITED_ORDER_ITEM_PRODUCT_IDS.has(productId) || productId === EXTRAORDINARY_CHEMISTRY_PRODUCT_ID || String(product?.product?.name ?? product?.name ?? "").trim() === EXTRAORDINARY_CHEMISTRY_PRODUCT_NAME );