@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.
- package/dist/{DisplaySystemView-BiKFL6UY.js → DisplaySystemView-BA-5JObJ.js} +1 -1
- package/dist/{KioskDevicesView-DQPue13D.js → KioskDevicesView-CgdnW9N9.js} +1 -1
- package/dist/{KioskDevicesView.vue_vue_type_script_setup_true_lang-BAe1eQvx.js → KioskDevicesView.vue_vue_type_script_setup_true_lang-C9X9ziUm.js} +3 -3
- package/dist/KioskSettingView-CVck01e7.js +860 -0
- package/dist/{KioskView-BfTNsmN1.js → KioskView-DKY2QEh5.js} +54 -48
- package/dist/{OrderSettingsView-CowX8_oN.js → OrderSettingsView-CEPIZmHA.js} +774 -768
- package/dist/{app-DgZSoUgk.js → app-C9nnuR9O.js} +206 -190
- package/dist/app.js +1 -1
- package/dist/frontend/mf-order/src/app.d.ts +16 -0
- package/dist/frontend/mf-order/src/main.d.ts +16 -0
- package/dist/frontend/mf-order/src/modules/order-setting/kiosk/interface.d.ts +2 -0
- package/dist/frontend/mf-order/src/stores/order-setting/index.d.ts +6 -0
- package/dist/frontend/mf-order/tsconfig.app.tsbuildinfo +1 -1
- package/dist/{index-CGJIcLNE.js → index-BaC_Douy.js} +2 -2
- package/dist/{index-CWm0u6lo.js → index-DGAU5Dhc.js} +1 -1
- package/dist/{index-DzmXxFJu.js → index-Gk7389CW.js} +1 -1
- package/dist/{order.dto-DQWf-RVV.js → order.dto-CfCfBJYu.js} +43 -6
- package/dist/package/entity/food-court/food-court.dto.d.ts +51 -121
- package/dist/package/entity/incoming-order/incoming-order-to-bill.dto.d.ts +10 -0
- package/dist/package/entity/kiosk/kiosk.do.d.ts +16 -16
- package/dist/package/entity/kiosk/kiosk.dto.d.ts +19 -19
- package/dist/package/entity/order/order-item/order-item.dto.d.ts +20 -0
- package/dist/package/entity/order/order.do.d.ts +19 -3
- package/dist/package/entity/order/order.dto.d.ts +107 -91
- package/dist/package/entity/order/order.enum.d.ts +1 -1
- package/dist/package/entity/order-setting/kiosk/kiosk.do.d.ts +3 -0
- package/dist/package/entity/order-setting/kiosk/kiosk.dto.d.ts +6 -0
- package/dist/package/entity/order-setting/order-setting.do.d.ts +5 -0
- package/dist/package/entity/order-setting/order-setting.dto.d.ts +13 -0
- package/dist/package/entity/queue/queue.dto.d.ts +23 -36
- package/dist/package/entity/restaurant/restaurant.dto.d.ts +10 -15
- package/dist/package/entity/websocket/websocket.dto.d.ts +12 -0
- package/package.json +1 -1
- package/src/locales/en-US.json +4 -0
- package/src/locales/ja-JP.json +4 -0
- package/src/locales/th-TH.json +4 -0
- package/src/locales/zh-CN.json +4 -0
- package/src/modules/order-setting/kiosk/interface.ts +10 -0
- package/src/stores/order-setting/mapper.spec.ts +21 -0
- package/src/stores/order-setting/mapper.ts +8 -2
- package/src/views/kiosk/settings/KioskSettingView.vue +37 -0
- package/src/views/order-settings/delivery/delivery.spec.ts +23 -3
- package/src/views/order-settings/delivery/delivery.ts +4 -0
- package/dist/KioskSettingView-M3pBFSwt.js +0 -839
package/src/locales/en-US.json
CHANGED
|
@@ -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.",
|
package/src/locales/ja-JP.json
CHANGED
|
@@ -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": "ドライブスルー",
|
package/src/locales/th-TH.json
CHANGED
|
@@ -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": "หมายเหตุการสั่งอาหาร",
|
package/src/locales/zh-CN.json
CHANGED
|
@@ -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;
|
|
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
|
}
|