@feedmepos/mf-order-setting 0.0.88 → 0.0.89

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/{DisplaySystemView-BiKFL6UY.js → DisplaySystemView-BA-5JObJ.js} +1 -1
  2. package/dist/{KioskDevicesView-DQPue13D.js → KioskDevicesView-CgdnW9N9.js} +1 -1
  3. package/dist/{KioskDevicesView.vue_vue_type_script_setup_true_lang-BAe1eQvx.js → KioskDevicesView.vue_vue_type_script_setup_true_lang-C9X9ziUm.js} +3 -3
  4. package/dist/KioskSettingView-CVck01e7.js +860 -0
  5. package/dist/{KioskView-BfTNsmN1.js → KioskView-DKY2QEh5.js} +54 -48
  6. package/dist/{OrderSettingsView-CowX8_oN.js → OrderSettingsView-CEPIZmHA.js} +774 -768
  7. package/dist/{app-DgZSoUgk.js → app-C9nnuR9O.js} +206 -190
  8. package/dist/app.js +1 -1
  9. package/dist/frontend/mf-order/src/app.d.ts +16 -0
  10. package/dist/frontend/mf-order/src/main.d.ts +16 -0
  11. package/dist/frontend/mf-order/src/modules/order-setting/kiosk/interface.d.ts +2 -0
  12. package/dist/frontend/mf-order/src/stores/order-setting/index.d.ts +6 -0
  13. package/dist/frontend/mf-order/tsconfig.app.tsbuildinfo +1 -1
  14. package/dist/{index-CGJIcLNE.js → index-BaC_Douy.js} +2 -2
  15. package/dist/{index-CWm0u6lo.js → index-DGAU5Dhc.js} +1 -1
  16. package/dist/{index-DzmXxFJu.js → index-Gk7389CW.js} +1 -1
  17. package/dist/{order.dto-DQWf-RVV.js → order.dto-CfCfBJYu.js} +43 -6
  18. package/dist/package/entity/food-court/food-court.dto.d.ts +51 -121
  19. package/dist/package/entity/incoming-order/incoming-order-to-bill.dto.d.ts +10 -0
  20. package/dist/package/entity/kiosk/kiosk.do.d.ts +16 -16
  21. package/dist/package/entity/kiosk/kiosk.dto.d.ts +19 -19
  22. package/dist/package/entity/order/order-item/order-item.dto.d.ts +20 -0
  23. package/dist/package/entity/order/order.do.d.ts +19 -3
  24. package/dist/package/entity/order/order.dto.d.ts +107 -91
  25. package/dist/package/entity/order/order.enum.d.ts +1 -1
  26. package/dist/package/entity/order-setting/kiosk/kiosk.do.d.ts +3 -0
  27. package/dist/package/entity/order-setting/kiosk/kiosk.dto.d.ts +6 -0
  28. package/dist/package/entity/order-setting/order-setting.do.d.ts +5 -0
  29. package/dist/package/entity/order-setting/order-setting.dto.d.ts +13 -0
  30. package/dist/package/entity/queue/queue.dto.d.ts +23 -36
  31. package/dist/package/entity/restaurant/restaurant.dto.d.ts +10 -15
  32. package/dist/package/entity/websocket/websocket.dto.d.ts +12 -0
  33. package/package.json +1 -1
  34. package/src/locales/en-US.json +4 -0
  35. package/src/locales/ja-JP.json +4 -0
  36. package/src/locales/th-TH.json +4 -0
  37. package/src/locales/zh-CN.json +4 -0
  38. package/src/modules/order-setting/kiosk/interface.ts +10 -0
  39. package/src/stores/order-setting/mapper.spec.ts +21 -0
  40. package/src/stores/order-setting/mapper.ts +8 -2
  41. package/src/views/kiosk/settings/KioskSettingView.vue +37 -0
  42. package/src/views/order-settings/delivery/delivery.spec.ts +23 -3
  43. package/src/views/order-settings/delivery/delivery.ts +4 -0
  44. package/dist/KioskSettingView-M3pBFSwt.js +0 -839
@@ -384,6 +384,10 @@
384
384
  "osVersion": "OS Version",
385
385
  "otaChannel": "OTA channel",
386
386
  "otaChannelHint": "Optional. Leave blank to use the default OTA feed.",
387
+ "minWeighGrams": "Minimum weight",
388
+ "minWeighGramsLabel": "Minimum weight (g)",
389
+ "minWeighGramsPlaceholder": "No minimum",
390
+ "minWeighGramsHint": "For items sold by weight. The kiosk will not sell a lighter portion. Leave empty for no minimum (any weight above 0 g, like POS).",
387
391
  "other": "Other",
388
392
  "onlinePaxDialog": "Pax Dialog (Online Ordering)",
389
393
  "onlinePaxDialogSublabel": "Ask customers for the number of people when they order online. POS keeps its own pax dialog setting.",
@@ -171,6 +171,10 @@
171
171
  "deviceDetails": "デバイス詳細",
172
172
  "otaChannel": "OTAチャネル",
173
173
  "otaChannelHint": "任意。空欄の場合はデフォルトのOTAフィードを使用します。",
174
+ "minWeighGrams": "最低重量",
175
+ "minWeighGramsLabel": "最低重量(g)",
176
+ "minWeighGramsPlaceholder": "最低なし",
177
+ "minWeighGramsHint": "重量販売の商品が対象です。キオスクはこれより軽い量を販売しません。空欄の場合は最低なし(POS と同じく 0 g より重ければ可)。",
174
178
  "dineIn": "店内飲食",
175
179
  "dineInCanTakeaway": "テイクアウト許可",
176
180
  "driveThru": "ドライブスルー",
@@ -264,6 +264,10 @@
264
264
  "deviceDetails": "รายละเอียดอุปกรณ์",
265
265
  "otaChannel": "ช่อง OTA",
266
266
  "otaChannelHint": "ไม่บังคับ เว้นว่างเพื่อใช้ฟีด OTA เริ่มต้น",
267
+ "minWeighGrams": "น้ำหนักขั้นต่ำ",
268
+ "minWeighGramsLabel": "น้ำหนักขั้นต่ำ (กรัม)",
269
+ "minWeighGramsPlaceholder": "ไม่มีขั้นต่ำ",
270
+ "minWeighGramsHint": "สำหรับสินค้าที่ขายตามน้ำหนัก ตู้คีออสก์จะไม่ขายปริมาณที่เบากว่านี้ เว้นว่างไว้หากไม่ต้องการกำหนดขั้นต่ำ (มากกว่า 0 กรัม เหมือน POS)",
267
271
  "dineIn": "ทานที่ร้าน",
268
272
  "dineInCanTakeaway": "อนุญาตให้สั่งกลับบ้าน",
269
273
  "dineInRemarkEnabled": "หมายเหตุการสั่งอาหาร",
@@ -265,6 +265,10 @@
265
265
  "deviceDetails": "设备详情",
266
266
  "otaChannel": "OTA 渠道",
267
267
  "otaChannelHint": "可选。留空将使用默认的 OTA 源。",
268
+ "minWeighGrams": "最低重量",
269
+ "minWeighGramsLabel": "最低重量(克)",
270
+ "minWeighGramsPlaceholder": "不设最低",
271
+ "minWeighGramsHint": "适用于按重量出售的商品。自助点餐机不会出售低于此重量的份量。留空则不设最低(与 POS 相同,只要大于 0 克即可)。",
268
272
  "dineIn": "堂食",
269
273
  "dineInCanTakeaway": "允许外带",
270
274
  "driveThru": "得来速",
@@ -104,6 +104,11 @@ export interface MfKioskOrderSetting {
104
104
  // i.e. the kiosk shows every language it ships. Anything else is the exact
105
105
  // allowed set.
106
106
  languages: string[] | null,
107
+ // Smallest weight (whole grams) the kiosk may sell for an item sold by
108
+ // weight (KDI-5138). null = no minimum beyond "more than 0 g", like POS.
109
+ // Carried end-to-end like allowReject, or a save of any other kiosk field
110
+ // would delete it.
111
+ minWeighGrams: number | null,
107
112
  }
108
113
 
109
114
  export interface MfKioskOrderSettingMenuItemForm {
@@ -138,6 +143,11 @@ export interface MfKioskOrderSettingForm {
138
143
  // i.e. the kiosk shows every language it ships. Anything else is the exact
139
144
  // allowed set.
140
145
  languages: string[] | null,
146
+ // Smallest weight (whole grams) the kiosk may sell for an item sold by
147
+ // weight (KDI-5138). null = no minimum beyond "more than 0 g", like POS.
148
+ // Carried end-to-end like allowReject, or a save of any other kiosk field
149
+ // would delete it.
150
+ minWeighGrams: number | null,
141
151
  }
142
152
 
143
153
  export type KioskPickAtCounterSettingForm = MfKioskPickAtCounterSetting;
@@ -104,3 +104,24 @@ describe('kiosk allowReject round-trip (KDI-5089)', () => {
104
104
  expect(saved(form).allowReject).toBe(false)
105
105
  })
106
106
  })
107
+
108
+ describe('kiosk minWeighGrams round-trip (KDI-5138)', () => {
109
+ it('reads a stored minimum back onto the form', () => {
110
+ expect(toKioskForm({ minWeighGrams: 20 }).minWeighGrams).toBe(20)
111
+ })
112
+
113
+ it('reads an unset minimum as null', () => {
114
+ expect(toKioskForm({}).minWeighGrams).toBeNull()
115
+ })
116
+
117
+ it('writes a set minimum and omits a cleared one', () => {
118
+ expect(saved({ ...defaultKioskOrderSetting, minWeighGrams: 20 }).minWeighGrams).toBe(20)
119
+ expect(saved({ ...defaultKioskOrderSetting, minWeighGrams: null }).minWeighGrams).toBeUndefined()
120
+ })
121
+
122
+ it('survives a save of an unrelated kiosk field', () => {
123
+ const form = toKioskForm({ minWeighGrams: 50, canTakeaway: true })
124
+ form.takeaway.enabled = false
125
+ expect(saved(form).minWeighGrams).toBe(50)
126
+ })
127
+ })
@@ -85,7 +85,8 @@ export const defaultKioskOrderSetting: MfKioskOrderSettingForm = {
85
85
  autoCloseBill: null,
86
86
  printReceiptAfterClose: null,
87
87
  allowReject: null,
88
- languages: null
88
+ languages: null,
89
+ minWeighGrams: null
89
90
  }
90
91
 
91
92
  export const defaultSubmitOrderInstruction: MfKioskSubmitOrderInstruction = {
@@ -160,7 +161,9 @@ const toKiosk = (
160
161
  allowReject: kioskOrderSettings?.allowReject ?? null,
161
162
  // Stored [] means the same thing as unset ("all languages"), so collapse it
162
163
  // to null here — the form only ever has to reason about null vs a real set.
163
- languages: kioskOrderSettings?.languages?.length ? [...kioskOrderSettings.languages] : null
164
+ languages: kioskOrderSettings?.languages?.length ? [...kioskOrderSettings.languages] : null,
165
+ // KDI-5138. Read back so a save of any other kiosk field keeps it.
166
+ minWeighGrams: kioskOrderSettings?.minWeighGrams ?? null
164
167
  }
165
168
  }
166
169
 
@@ -263,6 +266,9 @@ const toOrderKioskSettingsDto = (
263
266
  // Omit rather than send [] when the merchant restricts nothing, so the
264
267
  // saved document stays free of a field that means "all languages" anyway.
265
268
  languages: kioskSetting.languages?.length ? kioskSetting.languages : undefined,
269
+ // Omitted when unset: the backend $sets the whole kiosk subdocument, so a
270
+ // cleared minimum is removed instead of being stored as null.
271
+ minWeighGrams: kioskSetting.minWeighGrams ?? undefined,
266
272
  paymentSetting: createPaymentSettings(kioskSetting.paymentSetting),
267
273
  takeaway: kioskSetting.takeaway.submitOrderInstruction
268
274
  ? {
@@ -303,6 +303,24 @@
303
303
  </div>
304
304
  </div>
305
305
 
306
+ <!-- Weighing scale: minimum weight (KDI-5138) -->
307
+ <div class="flex flex-col gap-2">
308
+ <span class="fm-typo-en-title-sm-600">{{ t('order.minWeighGrams') }}</span>
309
+ <div class="w-11/12">
310
+ <FmStepperField
311
+ v-model="minWeighGrams"
312
+ class="max-w-[240px]"
313
+ :label="t('order.minWeighGramsLabel')"
314
+ :min="1"
315
+ :max="MAX_MIN_WEIGH_GRAMS"
316
+ :placeholder="t('order.minWeighGramsPlaceholder')"
317
+ />
318
+ <span class="fm-typo-en-body-sm-400 text-fm-color-typo-secondary">{{
319
+ t('order.minWeighGramsHint')
320
+ }}</span>
321
+ </div>
322
+ </div>
323
+
306
324
  <!-- Display Pax Dialog Section -->
307
325
  <div class="flex flex-col gap-2">
308
326
  <span class="fm-typo-en-title-sm-600">{{ t('order.displayPaxDialogTitle') }}</span>
@@ -496,6 +514,14 @@ const validKioskOrderSetting = computed<MfKioskOrderSetting | null>(() => {
496
514
  // render. Saving it would also be a no-op, since [] round-trips as null.
497
515
  if (f.languages != null && f.languages.length === 0) return null
498
516
 
517
+ // A minimum weight must be a whole number of grams, at least 1 (KDI-5138).
518
+ if (
519
+ f.minWeighGrams != null &&
520
+ (!Number.isInteger(f.minWeighGrams) || f.minWeighGrams < 1 || f.minWeighGrams > MAX_MIN_WEIGH_GRAMS)
521
+ ) {
522
+ return null
523
+ }
524
+
499
525
  // Validate payment settings
500
526
  const payment = f.paymentSetting
501
527
  if (payment?.paymentTypes?.includes(F_ORDER_PAYMENT_TYPE.enum.ePayment)) {
@@ -596,6 +622,17 @@ function removeCoverImage(orientation: CoverOrientation, index: number) {
596
622
  setCoverImages(orientation, next)
597
623
  }
598
624
 
625
+ // Minimum sellable weight for sold-by-weight items, in whole grams (KDI-5138).
626
+ // Empty = no minimum (more than 0 g, like POS). 100 kg is far above any kiosk scale.
627
+ const MAX_MIN_WEIGH_GRAMS = 100000
628
+ const minWeighGrams = computed<number | null>({
629
+ get: () => kioskOrderSettingForm.value.minWeighGrams ?? null,
630
+ set: (grams) => {
631
+ kioskOrderSettingForm.value.minWeighGrams =
632
+ typeof grams === 'number' && Number.isFinite(grams) && grams >= 1 ? Math.trunc(grams) : null
633
+ }
634
+ })
635
+
599
636
  const coverIntervalSeconds = computed<number | null>({
600
637
  get: () => readIntervalSeconds(kioskOrderSettingForm.value),
601
638
  set: (seconds) => {
@@ -1,9 +1,9 @@
1
- import { F_DELIVERY_TYPE } from '@feedmepos/core/entity'
1
+ import { F_COUNTRY, F_DELIVERY_TYPE } from '@feedmepos/core/entity'
2
2
  import { describe, expect, it, vi } from 'vitest'
3
- import { AUTO_INTEGRATION_CLIENT, isHiddenDeliveryKey } from './delivery'
3
+ import { AUTO_INTEGRATION_CLIENT, isHiddenDeliveryKey, useDelivery } from './delivery'
4
4
 
5
5
  // delivery.ts pulls in @feedmepos/mf-common for useCoreStore, whose dist bundle
6
- // crashes under vitest; isHiddenDeliveryKey never touches it, so stub it out.
6
+ // crashes under vitest; the functions under test never touch it, so stub it out.
7
7
  vi.mock('@feedmepos/mf-common', () => ({ useCoreStore: () => ({}) }))
8
8
 
9
9
  describe('isHiddenDeliveryKey', () => {
@@ -32,3 +32,23 @@ describe('isHiddenDeliveryKey', () => {
32
32
  }
33
33
  })
34
34
  })
35
+
36
+ describe('isIntegratedPlatformSupported', () => {
37
+ const { isIntegratedPlatformSupported } = useDelivery()
38
+
39
+ it('offers external delivery in the UK (GB)', () => {
40
+ expect(isIntegratedPlatformSupported(AUTO_INTEGRATION_CLIENT.external, F_COUNTRY.enum.GB)).toBe(
41
+ true
42
+ )
43
+ })
44
+
45
+ it('offers no other integrated platform in the UK (GB)', () => {
46
+ const others = Object.values(AUTO_INTEGRATION_CLIENT).filter(
47
+ (key) => key !== AUTO_INTEGRATION_CLIENT.external
48
+ )
49
+
50
+ for (const key of others) {
51
+ expect(isIntegratedPlatformSupported(key, F_COUNTRY.enum.GB)).toBe(false)
52
+ }
53
+ })
54
+ })
@@ -124,6 +124,7 @@ export function useDelivery() {
124
124
  AUTO_INTEGRATION_CLIENT.gofood,
125
125
  AUTO_INTEGRATION_CLIENT.external
126
126
  ]
127
+ const gbSupported = [AUTO_INTEGRATION_CLIENT.external]
127
128
 
128
129
  let supportedPlatforms: AUTO_INTEGRATION_CLIENT[] = []
129
130
  switch (country) {
@@ -142,6 +143,9 @@ export function useDelivery() {
142
143
  case F_COUNTRY.enum.ID:
143
144
  supportedPlatforms = idSupported
144
145
  break
146
+ case F_COUNTRY.enum.GB:
147
+ supportedPlatforms = gbSupported
148
+ break
145
149
  default:
146
150
  break
147
151
  }