3c19b7dd97
新增 StorePackage 与变更审核流,覆盖总部直存、合伙/门店提审、C 端展示与套餐异议工单;同步 PRD/开发文档与 REQ 索引。 Co-authored-by: Cursor <cursoragent@cursor.com>
50 lines
1.6 KiB
TypeScript
50 lines
1.6 KiB
TypeScript
import type { StorePackageItemDto } from '@dukang/shared-types';
|
|
import { STORE_PACKAGE_MAX_COUNT } from '@dukang/shared-types';
|
|
|
|
export type PackageFormItem = StorePackageItemDto;
|
|
|
|
export function emptyPackage(index = 0): PackageFormItem {
|
|
return {
|
|
name: '',
|
|
price: '',
|
|
dishes: '',
|
|
usableTime: '',
|
|
otherNotes: '',
|
|
sortOrder: index,
|
|
};
|
|
}
|
|
|
|
export function normalizePackageFormItems(raw: PackageFormItem[]): PackageFormItem[] {
|
|
return raw
|
|
.map((item, index) => ({
|
|
name: item.name.trim(),
|
|
price: item.price.trim(),
|
|
dishes: item.dishes.trim(),
|
|
usableTime: item.usableTime?.trim() || '',
|
|
otherNotes: item.otherNotes?.trim() || '',
|
|
sortOrder: index,
|
|
}))
|
|
.filter((item) => item.name || item.price || item.dishes || item.usableTime || item.otherNotes);
|
|
}
|
|
|
|
export function validatePackageFormItems(items: PackageFormItem[]): string | null {
|
|
const filled = normalizePackageFormItems(items);
|
|
if (filled.length > STORE_PACKAGE_MAX_COUNT) {
|
|
return `套餐最多 ${STORE_PACKAGE_MAX_COUNT} 条`;
|
|
}
|
|
for (let i = 0; i < filled.length; i++) {
|
|
const item = filled[i];
|
|
if (!item.name) return `第 ${i + 1} 条套餐名称不能为空`;
|
|
const price = Number(item.price);
|
|
if (!Number.isFinite(price) || price < 0) return `第 ${i + 1} 条套餐价格须为非负数字`;
|
|
if (!item.dishes) return `第 ${i + 1} 条套餐菜品不能为空`;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
export function formatPackagePrice(price: string | number) {
|
|
const n = typeof price === 'number' ? price : Number(price);
|
|
if (!Number.isFinite(n)) return String(price);
|
|
return n % 1 === 0 ? String(n) : n.toFixed(2);
|
|
}
|