@posx/core 5.5.504 → 5.5.506

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.
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":["CalcType","err : any","VISCII_TABLE: { [key: string]: number }","bytes: number[]","timeoutId: number","intervalId: number","lines: string[]","wrapped: string[]","http: AxiosInstance","db: Dexie","options: IServiceOptions","ipAddress: NetworkInfo","fileName: string","dotIndex: number","stringHelpers: StringHelpers","result: boolean","conditions: Array<{prop: string, value: any}>","comparisonHelpers: ComparisonHelpers","stringHelpers","comparisonHelpers","http: AxiosInstance","db: Dexie","options: IServiceOptions","helpers","LINE_OPTIONS_DEFAULT: LineOptions","http: AxiosInstance","db: Dexie","options: IServiceOptions","adjustmentCents: number","res : CustomResponse<IInvoice>","options: CreateInvoiceOptions","res: CustomResponse<any>","options: UpdateInvoiceOptions","options: CancelInvoiceOptions","options: CheckInvoiceOptions","options: SwitchInvoiceOptions","options: PayInvoiceOptions","receiptPrintJob: IPrintJob","kioskPrintJob: IPrintJob","options: DirectPayInvoiceOptions","options: VoidInvoiceOptions","printer: IPrinter","printJobs: IPrintJob[]","printerUidsKey: string","lines: IInvoiceLine[]","printerUidsSet: Set<string>","slicedInvoices: IInvoice[]","http: AxiosInstance","db: Dexie","options: IServiceOptions","uuidv4","items: IItem[]","fileName: string","dotIndex: number","newModifierCategories: ICoreCategory[]","newModifiers: ICoreItem[]","updatedItems: IItem[]","paymentMethods: IPaymentMethod[]","paymentMethod: PaymentMethod","methodsToUpdate: IPaymentMethod[]","payment","itemsToUpdate: T[]","data: CustomResponse<AppReport>","tills: Till[]","categories: ICategory[]","newModifier: TItemCoreSalesSummary","countryCodeToCodepage: { [key: string]: Codepages }","options: IServiceOptions","win: any","e: any","rows: IExportRow[]","price: number | undefined","stock: number | undefined","is_internal: boolean | undefined","min_order: number | undefined","max_order: number | undefined","sequence: number | undefined","values: string[]","categories: ICategory[]","products: IItem[]","currentCategory: ICategory | null","currentProduct: IItem | null","currentModifierCategory: ICoreCategory | null","currentComboGroup: IComboGroup | null","errors: ValidationError[]","template: unknown"],"sources":["../src/types/wyo.customer.type.ts","../src/types/wyo.coupon.type.ts","../src/types/abstract.type.ts","../src/types/misc.type.ts","../src/types/shift.type.ts","../src/types/section.type.ts","../src/types/role.type.ts","../src/types/product.type.ts","../src/libs/electron.socket.ts","../src/libs/viscii.encoding.ts","../src/libs/escpos.printer.ts","../src/utils/misc.utils.ts","../src/types/printer.type.ts","../src/types/payment.type.ts","../src/types/note.type.ts","../src/types/invoice.type.ts","../src/types/employee.type.ts","../src/types/config.type.ts","../src/types/request.type.ts","../src/libs/FindOptions.ts","../src/services/abstract.service.ts","../src/types/report.type.ts","../src/services/printer.service.ts","../src/services/misc.service.ts","../src/helpers/string.helpers.ts","../src/helpers/comparison.helpers.ts","../src/helpers/helpers.register.ts","../src/types/ods.type.ts","../src/services/ods.service.ts","../src/services/invoice.service.ts","../src/services/app.service.ts","../src/utils/http.utils.ts","../src/service.factory.ts","../src/utils/csv.utils.ts","../src/types/condition.type.ts","../src/types/merchant.type.ts","../src/types/storage.type.ts","../src/types/menu.type.ts","../src/types/stock.type.ts","../src/utils/st.validate.ts"],"sourcesContent":["/* eslint-disable no-unused-vars */\n\nexport interface IAddress {\n /** Address line 1 */\n address1: string;\n /** Address line 2 */\n address2: string;\n /** Latitude coordinate */\n lat: string;\n /** Longitude coordinate */\n lng: string;\n /** Postal code */\n postcode: string;\n /** Note associated with the address */\n note: string;\n /** Indicates if the address is the default one */\n is_default: boolean;\n /** Name associated with the address */\n name: string;\n /** Salutation associated with the address */\n salute: string;\n /** Phone number associated with the address */\n phone_number: string;\n}\n\n/**\n * Class representing the Address model.\n */\nexport class Address implements IAddress {\n public address1 = \"\";\n public address2 = \"\";\n public lat = \"\";\n public lng = \"\";\n public postcode = \"\";\n public note = \"\";\n public is_default = false;\n public name = \"\";\n public salute = \"\";\n public phone_number = \"\";\n\n constructor() {\n }\n}\n\nexport interface IUser {\n id: number;\n /** Reference ID */\n ref_id: string;\n /** Image URL */\n image_url: string;\n /** Stripe Token */\n stripe_token: string;\n /** Stripe Customer ID */\n stripe_customer_id: string;\n /** User Name */\n username: string;\n /** Normalized User Name */\n normalized_username: string;\n /** Company */\n company: string;\n /** Identification Card */\n ic: string;\n /** Display Name */\n display_name: string;\n /** Full Name */\n full_name: string;\n /** Birth Date */\n birth_date: string;\n /** Gender */\n gender: string;\n /** Address */\n address: string;\n /** Postcode */\n postcode: string;\n /** Note */\n note: string;\n /** Language */\n language: string;\n /** Time Zone */\n time_zone: string;\n /** Created At */\n created_at: Date;\n /** Updated At */\n updated_at: Date;\n /** License IDs */\n license_ids: string;\n /** Security Stamp */\n security_stamp: string;\n /** Phone Number */\n phone_number: string;\n}\n\nexport class User implements IUser {\n public id = 0;\n public ref_id = \"\";\n public image_url = \"\";\n public stripe_token = \"\";\n public stripe_customer_id = \"\";\n public username = \"\";\n public normalized_username = \"\";\n public company = \"\";\n public ic = \"\";\n public display_name = \"\";\n public full_name = \"\";\n public birth_date = \"\";\n public gender = \"\";\n public address = \"\";\n public postcode = \"\";\n public note = \"\";\n public language = \"\";\n public time_zone = \"\";\n public created_at = new Date();\n public updated_at = new Date();\n public license_ids = \"\";\n public security_stamp = \"\";\n public phone_number = \"\";\n\n constructor() {\n }\n}\n\nexport interface ICustomer extends IUser {\n /** License ID */\n license_id: number;\n /** Credit */\n credit: number;\n /** Point */\n point: number;\n /** Transaction Total */\n transaction_total: number;\n /** Transaction Time */\n transaction_time: number;\n /** User Group ID */\n user_group_id: number;\n /** User Group Name */\n user_group_name: string;\n /** Group Expires At */\n group_expires_at: Date | null;\n /** Error */\n error: string;\n}\n\nexport class Customer extends User implements ICustomer {\n public license_id = 0;\n public credit = 0;\n public point = 0;\n public transaction_total = 0;\n public transaction_time = 0;\n public user_group_id = 0;\n public user_group_name = \"\";\n public group_expires_at: Date | null = null;\n public error = \"\";\n\n constructor() {\n super();\n }\n}\n","import { Employee } from './employee.type';\nenum ApplyingType {\n All = 1,\n Inclusive = 2,\n Exclusive = 3\n}\n\nenum CalcType {\n Flat = 1,\n Percent = 2,\n}\n\n\nexport interface IApplying<T> {\n applying_type: ApplyingType;\n applying_items: T[];\n}\n\nexport class Applying<T> implements IApplying<T> {\n public applying_type: ApplyingType = ApplyingType.Inclusive;\n public applying_items: T[] = [];\n}\n\nexport interface ICoupon {\n /** Coupon guid */\n guid: string;\n /** Promotion code which is used to look up the coupon */\n promo_code: string;\n /** If this coupon can be used for multiple stores */\n is_multi_stores?: boolean;\n /** Coupon primary name */\n name: string;\n /** Coupon alias */\n alias?: string;\n /** Coupon primary description */\n description?: string;\n /** Coupon alias description */\n description_alias?: string;\n /** Applying PLUs (Price Lookup Code) */\n applying_plus: IApplying<string>;\n /** Applying User Tags */\n applying_user_tags: IApplying<string>;\n /** Applying User Groups */\n applying_user_groups: IApplying<number>;\n /** Discount Calculation Type */\n discount_calc_type: CalcType;\n /** Flat discount amount */\n discount_amount?: number;\n /** Percent discount (e.g. 30% => 0.3) */\n discount_percent?: number;\n /** Expiring duration in day after coupon is purchased */\n duration?: number;\n /** How many of this coupon has been redeemed */\n usage_count: number;\n /** How many of this coupon can be redeemed within an invoice */\n usage_limit_per_invoice?: number;\n /** Only above a specified invoice total before this coupon can be redeemed */\n above_invoice_amount?: number;\n /** Only below a specified invoice total before this coupon can be redeemed */\n below_invoice_amount?: number;\n /** Can this coupon be used to offset delivery fee */\n is_delivery_free?: boolean;\n /** If this coupon can only be used individually without stacking other coupons together */\n is_individual_use?: boolean;\n /** The amount of points to redeem this coupon */\n price_in_points?: number;\n /** Styles of the coupon */\n styles?: Record<string, string>;\n /** When this coupon will be expired */\n expired_at?: Date;\n /** If auto generation is true, the coupon will be automatically generated for all applicable users */\n auto_gen?: boolean;\n /** If this coupon has been disabled for purchasing */\n can_sell?: boolean;\n /** If this coupon has been disabled for redemption */\n can_redeem?: boolean;\n}\n\nexport class Coupon implements ICoupon {\n public guid = \"\";\n public promo_code = \"\";\n public is_multi_stores = false;\n public name = \"\";\n public alias?: string;\n public description?: string;\n public description_alias?: string;\n public applying_plus: IApplying<string>;\n public applying_user_tags: IApplying<string>;\n public applying_user_groups: IApplying<number>;\n public discount_calc_type = CalcType.Flat;\n public discount_amount?: number;\n public discount_percent?: number;\n public duration = 30;\n public usage_count = 0;\n public usage_limit_per_invoice = 1;\n public above_invoice_amount?: number;\n public below_invoice_amount?: number;\n public is_delivery_free = false;\n public is_individual_use = true;\n public price_in_points?: number;\n public styles: Record<string, string> = {};\n public expired_at?: Date;\n public auto_gen = false;\n public can_sell = true;\n public can_redeem = true;\n\n constructor(couponToClone?: Coupon) {\n if (couponToClone) {\n this.guid = couponToClone.guid;\n this.promo_code = couponToClone.promo_code;\n this.is_multi_stores = couponToClone.is_multi_stores;\n this.name = couponToClone.name;\n this.alias = couponToClone.alias;\n this.description = couponToClone.description;\n this.description_alias = couponToClone.description_alias;\n this.applying_plus = couponToClone.applying_plus;\n this.applying_user_tags = couponToClone.applying_user_tags;\n this.applying_user_groups = couponToClone.applying_user_groups;\n this.discount_calc_type = couponToClone.discount_calc_type;\n this.discount_amount = couponToClone.discount_amount;\n this.discount_percent = couponToClone.discount_percent;\n this.duration = couponToClone.duration;\n this.usage_count = couponToClone.usage_count;\n this.usage_limit_per_invoice = couponToClone.usage_limit_per_invoice;\n this.above_invoice_amount = couponToClone.above_invoice_amount;\n this.below_invoice_amount = couponToClone.below_invoice_amount;\n this.is_delivery_free = couponToClone.is_delivery_free;\n this.is_individual_use = couponToClone.is_individual_use;\n this.price_in_points = couponToClone.price_in_points;\n this.styles = { ...couponToClone.styles };\n this.expired_at = couponToClone.expired_at;\n this.auto_gen = couponToClone.auto_gen;\n this.can_sell = couponToClone.can_sell;\n this.can_redeem = couponToClone.can_redeem;\n }\n }\n}\n\nexport interface ICouponUsage {\n invoice_uid : string;\n}\n\nexport class CouponUsage implements ICouponUsage {\n public invoice_uid = \"\";\n constructor(couponUsageToClone?: CouponUsage) {\n if (couponUsageToClone) {\n this.invoice_uid = couponUsageToClone.invoice_uid;\n }\n }\n}\n\nexport interface ICouponItemized {\n /** Coupon itemized guid */\n guid: string;\n /** A snapshot of coupon at the time of purchase */\n coupon: ICoupon;\n /** If this coupon can be used for multiple stores, default: false */\n is_multi_stores?: boolean;\n /** Coupon usage record if it is redeemed */\n usage: ICouponUsage;\n /** Employee unique id */\n employee_uid: string;\n /** Promotion code which is used to look up the coupon */\n promo_code: string;\n /** If coupons are expired */\n is_expired: boolean;\n /** If the coupons are fully redeemed */\n is_redeemed: boolean;\n /** If the coupon is generated instead of purchase */\n is_generated: boolean;\n}\n\nexport class CouponItemized implements ICouponItemized {\n public guid = \"\";\n public coupon = new Coupon(); // Assuming Coupon is another model class you have\n public is_multi_stores?: boolean = false;\n public usage = new CouponUsage(); // Assuming CouponUsage is another model class you have\n public employee_uid = \"\"; // Initialize with some default value if available\n public promo_code = \"\"; // Initialize with some default value if available\n public is_expired = false;\n public is_redeemed = false;\n public is_generated = false;\n\n constructor(itemized?: CouponItemized) {\n if (itemized) {\n this.guid = itemized.guid;\n this.coupon = new Coupon(itemized.coupon);\n this.is_multi_stores = itemized.is_multi_stores;\n this.usage = new CouponUsage(itemized.usage);\n this.employee_uid = itemized.employee_uid;\n this.promo_code = itemized.promo_code;\n this.is_expired = itemized.is_expired;\n this.is_redeemed = itemized.is_redeemed;\n this.is_generated = itemized.is_generated;\n }\n }\n}\n","/* eslint-disable @typescript-eslint/no-unused-vars */\nimport dayjs from 'dayjs';\n\nexport const transformer = {\n from(value: string) {\n return dayjs(value).format('YYYY-MM-DD HH:mm:ss');\n },\n to(value: string) {\n return value;\n },\n};\n\nexport interface IAppCoreModel {\n /**\n * primary unique id\n * @ignore\n */\n uid: string;\n /**\n * the date when the object is updated\n * @ignore\n */\n updated_at: Date;\n /**\n * the date when the object is created\n * @ignore\n */\n created_at: Date;\n /**\n * the date when the object is created\n * @ignore\n */\n created_at_timestamp: number;\n /**\n * the date when the object is deleted\n * @ignore\n */\n deleted_at: Date | null;\n /**\n * timestamp in milliseconds\n * @ignore\n */\n _timestamp: number;\n /**\n * Primary unique id in server 1,2,3,5\n * @ignore\n */\n id_in_server: number;\n}\n\n\n\nexport abstract class AppCoreModel implements IAppCoreModel {\n uid: string;\n // ** the date when the object is updated */\n updated_at = new Date();\n // ** the date when the object is created */\n created_at = new Date();\n /**\n * the date when the object is created\n */\n created_at_timestamp: number = new Date().getTime();\n // ** the date when the object is deleted */\n deleted_at = null\n // ** timestamp in milliseconds for data sync */\n _timestamp: number;\n // ** Primary unique id in server 1,2,3,5 */\n id_in_server: number;\n constructor() {}\n}\n\nexport interface IAppBaseModel extends IAppCoreModel {\n /** \n * name of the object \n */\n name: string;\n /** \n * Translations of the name \n */\n name_translations: Record<string, string>;\n}\n\n\nexport class AppBaseModel extends AppCoreModel implements IAppBaseModel {\n name: string;\n name_translations: Record<string, string> = {};\n constructor() {\n super();\n }\n}\nexport interface IAppExtraModel extends IAppBaseModel {\n /**\n * description of the object\n */\n description: string;\n /**\n * Translations of the description\n */\n description_translations: Record<string, string>;\n}\n\nexport class AppExtraModel extends AppBaseModel implements IAppExtraModel {\n description: string;\n description_translations = {};\n}\n\n\nexport type IAppCore = Omit<IAppCoreModel, \"id_in_server\" | \"_timestamp\">;\nexport type IAppBase = Omit<IAppBaseModel, \"id_in_server\" | \"_timestamp\"> ;\nexport type IAppExtra = Omit<IAppExtraModel, \"id_in_server\" | \"_timestamp\"> ;","export enum ModelPrefix {\n Merchant = 'mnt_',\n Section = 'sec_',\n SectionItem = 'sit_',\n Category = 'cat_',\n Subcategory = 'sat_',\n Item = 'itm_',\n ItemModifier = 'iod_',\n ItemModifierCategory = 'imc_',\n Config = 'cfg_',\n Device = 'dev_',\n Invoice = 'inv_',\n InvoiceLine = 'iln_',\n InvoiceCharge = 'ich_',\n Payment = 'pay_',\n Employee = 'emp_',\n Shift = 'shf_',\n Till = 'til_',\n ReportCategory = 'rpc_',\n Report = 'rpt_',\n AppReport = 'apr_',\n PaymentMethod = 'pmd_',\n PrintTemplate = 'ptl_',\n PrintJob = 'pjb_',\n Printer = 'prt_',\n InvoiceDiscount = 'ind_',\n EmployeeRole = 'emr_',\n OrderDisplaySystem = 'ods_',\n Charge = 'chr_',\n Price = 'prc_',\n ComboGroup = 'cbo_',\n Storage = 'sto_',\n Menu = 'men_',\n StockLog = 'stl_',\n}\n\nexport enum ModelType {\n Merchant = 'mnt',\n Section = 'sec',\n SectionItem = 'sit',\n Category = 'cat',\n Subcategory = 'sat',\n Item = 'itm',\n Config = 'cfg',\n Device = 'dev',\n Invoice = 'inv',\n}\n\nexport enum ServiceMode {\n LOCAL = 'local',\n CLOUD = 'cloud',\n}\n\nexport interface IServiceOptions {\n mode: ServiceMode;\n base_url: string;\n device_uid: string;\n merchant_uid: string;\n token: string;\n database: {\n version: number;\n name: string;\n };\n}\n\nexport class ServiceOptions implements IServiceOptions {\n mode: ServiceMode;\n base_url: string;\n device_uid: string;\n merchant_uid: string;\n token: string;\n database: {\n version: 1;\n name: '';\n };\n}\n\nexport enum MessageType {\n Data = 'DataMessage',\n Event = 'EventMessage',\n}\n\n/** Interface for push_data */\nexport interface IPushData {\n model: string;\n /** Push Data Content */\n data: string;\n\n has_many: boolean;\n\n type: MessageType;\n}\n\n/** Model for push_data */\nexport class PushData implements IPushData {\n public model = '';\n /** Push Data Content */\n public data = '';\n\n public has_many = false;\n\n public type = MessageType.Data;\n}\n\nexport class SystemError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'system_error';\n }\n}\n\nexport type CustomResponse<T> = {\n data: T;\n error: ErrorMsgs | string;\n error_code: number;\n};\n\nexport enum ErrorMsgs {\n outdatedInvoice = 'outdated invoice',\n outdatedSectionItem = 'outdated section item',\n outdatedSourceSectionItem = 'outdated source section item',\n outdatedTargetSectionItem = 'outdated target section item',\n}\n\n\nexport interface IFileUploadResponse {\n file_url: string;\n thumbnail_url: string;\n}\n\n","/* eslint-disable no-unused-vars */\n\nimport { AppCoreModel, IAppCoreModel } from './abstract.type';\nimport { ModelPrefix } from './misc.type';\nimport { nanoid } from 'nanoid';\n\n// Assuming OperationStatus is an enum in C# code, representing it as a TypeScript enum\nexport enum ShiftStatus {\n Open = 'opened', // example value\n Closed = 'closed', // example value\n // Add other statuses as needed\n}\n\nexport interface IShift extends IAppCoreModel {\n /** user uid */\n user_uid: string;\n /** shift started at */\n started_at: Date;\n /** shift closed at */\n ended_at: Date;\n /** amount declared by user */\n declared_amount: number;\n /** amount recorded by */\n drawer_amount: number;\n /** Operation Status */\n status: ShiftStatus;\n /** first invoice number */\n first_invoice_number: number;\n}\n\nexport class Shift extends AppCoreModel implements IShift {\n public user_uid = '';\n public started_at = new Date();\n public ended_at = new Date();\n public declared_amount = 0;\n public drawer_amount = 0;\n public first_invoice_number = 0;\n public status = ShiftStatus.Open; // Default to STATUS1 or whichever is appropriate\n public uid = ModelPrefix.Shift + nanoid();\n constructor() {\n super();\n }\n}\n\nexport enum TillType {\n OpenDeposit = 'open_deposit', // example value\n CashDeposit = 'cash_deposit', // example value\n CashIn = 'cash_in', // example value\n CashOut = 'cash_out', // example value\n CashInvoice = 'cash_invoice', // example value\n}\n\nexport interface ITill extends AppCoreModel{\n /** user uid */\n user_uid: string;\n /** operation history id */\n shift_uid: string;\n /** invoice uid */\n invoice_uid: string;\n /** Till Type */\n type: TillType;\n /** Amount */\n amount: number;\n /** Note */\n note: string;\n}\n\nexport class Till extends AppCoreModel implements ITill {\n public user_uid = \"\";\n public shift_uid = \"\";\n public invoice_uid = \"\";\n public type = TillType.CashDeposit;\n public amount = 0;\n public note = \"\";\n public uid = ModelPrefix.Till + nanoid();\n constructor() {\n super();\n }\n}\n","import { IAppModelSequence } from '../services/abstract.service';\nimport { AppBaseModel, IAppBaseModel } from './abstract.type';\nimport { ModelPrefix } from './misc.type';\nimport { nanoid } from 'nanoid';\n\nexport enum SectionItemStatus {\n CLOSED = 'closed',\n OPENED = 'opened',\n PAYMENT = 'payment',\n}\n\n// TableConfig Interface\nexport interface ISectionItem extends IAppBaseModel {\n /** List of printer ID order */\n printer_id_order_list: number[];\n order_printer_uids: string[];\n /** Receipt printer UID for this section item */\n receipt_printer_uid: string;\n /** Check printer UID for this section item */\n check_printer_uid: string;\n /** QR printer UID for this section item */\n qr_printer_uid: string;\n /** Total amount */\n total: number;\n /** Time duration */\n time: number;\n /** Number of persons */\n pax: number;\n /** Invoice created timestamp */\n invoice_created_at: Date | null;\n /** Number of child persons */\n child_pax: number;\n /** Number of baby persons */\n baby_pax: number;\n /** Invoice ID */\n invoice_uid: string;\n /** Section ID */\n section_uid: string;\n /** Table status */\n status: SectionItemStatus;\n /** Table size in X direction */\n size_x: number;\n /** Table size in Y direction */\n size_y: number;\n /** Table x axis */\n row: number;\n /** Table y axis */\n col: number;\n /** Flag for take out */\n is_take_out: boolean;\n /** Soup base quota */\n soup_base_quota: number;\n /** Soup base type */\n soup_base_type: number;\n meta: Record<string, any>;\n customer: Record<string, any>;\n}\n\nexport class SectionItem extends AppBaseModel implements ISectionItem {\n public printer_id_order_list: number[] = [];\n public order_printer_uids: string[] = [];\n public receipt_printer_uid = '';\n public check_printer_uid = '';\n public qr_printer_uid = '';\n public total = 0; \n\n public time = 0;\n\n public pax = 0;\n public invoice_created_at = new Date();\n\n public child_pax = 0;\n\n public baby_pax = 0;\n public uid = ModelPrefix.SectionItem + nanoid();\n public invoice_uid = '';\n public section_uid = '';\n\n public status = SectionItemStatus.CLOSED;\n\n public size_x = 0;\n\n public size_y = 0;\n\n public row = 0;\n\n public col = 0;\n public is_take_out = false;\n public soup_base_quota = 0;\n public soup_base_type = 0;\n public is_delete = false;\n public meta: Record<string, any> = {};\n public customer: Record<string, any> = {};\n constructor() {\n super();\n }\n}\n\nexport type ISection = IAppBaseModel & IAppModelSequence;\n\nexport class Section extends AppBaseModel implements ISection {\n public sequence = 0;\n public uid = ModelPrefix.Section + nanoid();\n constructor() {\n super();\n }\n}\n","import { nanoid } from 'nanoid';\nimport { AppBaseModel, IAppBaseModel } from './abstract.type';\nimport { ModelPrefix } from './misc.type';\n\nexport interface IEmployeeRole extends IAppBaseModel{\n permissions: string[];\n is_default : boolean;\n}\n\nexport class EmployeeRole extends AppBaseModel implements IEmployeeRole {\n public permissions: string[] = [];\n public is_default = false;\n public uid: string = ModelPrefix.EmployeeRole + nanoid();\n constructor() {\n super();\n }\n}\n","import { IAppModelSequence } from '../services/abstract.service';\nimport { AppCoreModel, AppExtraModel, IAppCoreModel, IAppExtraModel } from './abstract.type';\nimport { ModelPrefix } from './misc.type';\nimport { nanoid } from 'nanoid';\n\nexport type TStockChangeItem = {\n item_uid: string;\n quantity: number;\n}\n\nexport type TStockChange = TStockChangeItem & {\n modifiers: TStockChangeItem[];\n}\n\nexport class StockChange implements TStockChange {\n public item_uid = '';\n public quantity = 0;\n public modifiers: TStockChangeItem[] = [];\n constructor(item_uid: string) {\n this.item_uid = item_uid;\n this.quantity = 0;\n this.modifiers = [];\n }\n}\n\nexport interface IProductBase extends IAppExtraModel, IAppModelSequence {\n /**\n * color of the object\n */\n color: string;\n /**\n * icon of the object\n */\n icon: string;\n /**\n * meta data\n * @ignore\n */\n meta: Record<string, any>;\n /**\n * extra data\n * @ignore\n */\n etc: Record<string, any>;\n /**\n * assets of the product (for image, etc)\n * Predefined keys that can be used by the system\n */\n assets: ProductPartialAssets & Record<string, any>;\n /**\n * config of the product\n * Predefined keys that can be used by the system\n */\n config: ProductPartialConfig & Record<string, any>;\n\n /**\n * if the product is internal and displayed in the POS only\n */\n is_internal: boolean;\n}\n\n/**\n * Predefined asset keys that can be used in the product assets\n */\nexport type ProductPartialAssets = {\n /**\n * large image url for online order\n */\n online_order_large_image_url?: string;\n /**\n * large image thumbnail url for online order\n */\n online_order_large_image_thumbnail_url?: string;\n /**\n * large image file path for online order\n */\n online_order_large_image_file_path?: string;\n /**\n * small image url for online order\n */\n online_order_small_image_url?: string;\n /**\n * small image thumbnail url for online order\n */\n online_order_small_image_thumbnail_url?: string;\n /**\n * small image file path for online order\n */\n online_order_small_image_file_path?: string;\n};\n\n/**\n * Predefined config keys that can be used in the product configs\n */\nexport type ProductPartialConfig = {\n /**\n * display large image for online order, if false, small image will be displayed\n */\n online_order_display_large_image: boolean;\n};\n\nexport class ProductBase extends AppExtraModel implements IProductBase {\n public meta = {};\n public etc = {};\n public assets = {};\n public config = {\n online_order_display_large_image: false,\n };\n public is_internal = false;\n public color = '';\n public icon = '';\n public sequence = 0;\n constructor() {\n super();\n }\n}\n\nexport interface IVisibility {\n system: System;\n visible: boolean;\n sequence: number;\n}\n\nexport class Visibility implements IVisibility {\n public system = System.POS;\n public visible = false;\n public sequence = 0;\n constructor() {}\n}\n\nexport enum System {\n POS = 'pos',\n QrCodeOrder = 'qr_code_order',\n}\n\nexport interface ICoreCategory extends IProductBase {\n type: CategoryType;\n visibility: Array<Visibility>;\n\n /**\n * maximum order quantity before you can order\n */\n max_order: number;\n\n /**\n * minimum order quantity before you can order\n */\n min_order: number;\n\n /**\n * Indicates whether the category is delisted\n */\n is_delisted: boolean;\n}\n\nexport interface ICategory extends ICoreCategory {\n image_url: string;\n /**\n * image file path\n */\n image_file_path: string;\n /**\n *\n */\n image_thumbnail_url: string;\n /**\n * image thumbnail file path\n */\n image_thumbnail_file_path: string;\n /** if category has subcategory */\n has_subcategory: boolean;\n /** Printing sequence number */\n printing_sequence: number;\n /**\n * subcategories of the category\n */\n subcategories: Array<ISubcategory>;\n}\n\nexport enum CategoryType {\n Product = 'product',\n Modifier = 'modifier',\n}\n\nexport class CoreCategory extends ProductBase implements ICoreCategory {\n public type = CategoryType.Modifier;\n public visibility: Visibility[] = [];\n public uid = ModelPrefix.ItemModifierCategory + nanoid();\n public max_order = 0;\n public min_order = 0;\n public is_delisted = false;\n constructor() {\n super();\n }\n}\n\nexport class Category extends ProductBase implements ICategory {\n public image_url = '';\n public image_file_path = '';\n public image_thumbnail_url = '';\n public image_thumbnail_file_path = '';\n public has_subcategory = false;\n public name_translations: Record<string, string> = {};\n public visibility: Visibility[];\n public printing_sequence = 0;\n public type = CategoryType.Product;\n public is_delisted = false;\n public subcategories = [];\n public uid = ModelPrefix.Category + nanoid();\n public max_order = 0;\n public min_order = 0;\n constructor() {\n super();\n }\n}\n\nexport interface ISubcategory extends IProductBase {\n /** Category ID */\n category_uid: string;\n}\n\nexport class Subcategory extends ProductBase implements ISubcategory {\n public category_uid = '';\n public uid = ModelPrefix.Subcategory + nanoid();\n constructor() {\n super();\n }\n}\n\nexport enum ProductType {\n ByQuantity = 'by_quantity',\n ByWeight = 'by_weight',\n Service = 'service',\n Combo = 'combo',\n Modifier = 'modifier',\n Package = 'package',\n}\n\n/**\n * Interface for a core item, which extends the IProductBase interface.\n */\nexport interface ICoreItem extends IProductBase {\n /**\n * Rank of the item\n */\n // rank: number; // meta\n image_url: string;\n /**\n * image file path\n */\n image_file_path: string;\n /**\n * @ignore\n */\n image_thumbnail_url: string;\n /**\n * image thumbnail file path\n */\n image_thumbnail_file_path: string;\n /**\n * The SKU (stock keeping unit) of the item.\n */\n sku: string;\n /**\n * The type of product.\n */\n type: ProductType;\n /**\n * The visibility of the item.\n */\n visibility: Array<Visibility>;\n /**\n * The barcode of the item.\n */\n barcode: string;\n /**\n * The price of the item.\n */\n price: number;\n /**\n * The original price of the item.\n */\n original_price: number;\n /**\n * The price list of the item.\n */\n prices: Array<IPrice>;\n /**\n * The unique identifier of the category that the item belongs to.\n */\n category_uid: string;\n /**\n * The current stock level of the item.\n * @ignore\n */\n stock: number;\n /**\n * Whether or not the item is sold out.\n */\n is_sold_out: boolean;\n /**\n * Whether or not the item should be printed on the receipt.\n */\n print_on_receipt: boolean;\n /**\n * Whether or not the price of the item can be adjusted.\n */\n price_adjustable: boolean;\n /**\n * Recipe of the modifier\n */\n recipe: string;\n /** Whether remark is disabled for this item */\n is_remark_disabled: boolean;\n}\n\nexport class CoreItem extends ProductBase implements ICoreItem {\n public image_url = '';\n public image_file_path = '';\n public image_thumbnail_url = '';\n public image_thumbnail_file_path = '';\n public visibility: Visibility[] = [];\n public sku = '';\n public type = ProductType.Modifier;\n public barcode = '';\n public category_uid = '';\n public price = 0;\n public original_price = 0;\n public prices: Array<IPrice> = [];\n public stock = 1000;\n public print_on_receipt = true;\n public price_adjustable = false;\n public is_sold_out = false;\n public recipe = '';\n public is_remark_disabled = false;\n public uid = ModelPrefix.ItemModifier + nanoid();\n constructor() {\n super();\n }\n}\n\n/**\n * Items\n */\n\nexport interface IItem extends ICoreItem {\n /**\n * Codename of the item\n */\n codename: string;\n /**\n * Recipe of the item\n */\n recipe: string;\n /**\n * Credit value of the item\n */\n add_credit: number;\n /**\n * Subcategory ID of the item\n */\n subcategory_uid: string;\n /**\n * Unit of the item\n * @ignore\n */\n unit: number;\n /**\n * Number of items sold\n * @ignore\n */\n sold: number;\n /**\n * if editor will be opened by default when item is clicked\n */\n open_editor: boolean;\n /**\n * how many points will be used to purchase the item\n */\n minus_point: number;\n /**\n * Cost of the item\n */\n cost: number;\n /**\n * Indicates whether the item is discountable\n */\n discountable: boolean;\n /**\n * Printing sequence of the item\n * @ignore\n */\n printing_sequence: number;\n /**\n * Number of likes for the item\n * @ignore\n */\n likes: number;\n /**\n * Number of dislikes for the item\n * @ignore\n */\n dislikes: number;\n\n /**\n * if the item is recommended\n */\n recommended: boolean;\n /**\n * Indicates whether the item is tax exempt\n */\n is_tax_exempt: boolean;\n /**\n * Indicates whether the item is service charge exempt\n */\n is_service_charge_exempt: boolean;\n /**\n * Indicates whether the item is point reward exempt\n */\n is_point_reward_exempt: boolean;\n /**\n * Indicates whether the item is credit reward exempt\n */\n is_credit_reward_exempt: boolean;\n /**\n * Indicates whether the item is internal and displayed in the POS only\n */\n is_internal: boolean;\n /**\n * Indicates whether the item is delisted\n */\n is_delisted: boolean;\n /**\n * Modifier IDs of the item\n */\n modifiers?: Array<ICoreItem>;\n /**\n * Modifier Group IDs of the item\n */\n modifier_categories?: Array<ICoreCategory>;\n /**\n * Kitchen printer IDs of the item\n */\n kitchen_printers_uids: Array<string>;\n /**\n * Order printer IDs of the item\n */\n order_printers_uids: Array<string>;\n /**\n * Label printer IDs of the item\n */\n label_printers_uids: Array<string>;\n /**\n * if editor will be opened by default when item is clicked\n */\n open_editor_panel: boolean;\n /**\n * if price editor will be opened by default when item is clicked\n */\n open_price_editor: boolean;\n /**\n * Combo groups (only applicable when type is ProductType.Combo)\n */\n combo_groups: IComboGroup[];\n}\n\nexport class Item extends CoreItem implements IItem {\n public codename = '';\n public sku = '';\n public recipe = '';\n public barcode = '';\n public type: ProductType = ProductType.ByQuantity;\n public add_credit = 0;\n public category_uid = '';\n public subcategory_uid = '';\n public unit = 0;\n public stock = 0;\n public is_sold_out = false;\n public sold = 0;\n public print_on_receipt = true;\n public price = 0;\n public open_editor = true;\n public price_adjustable = false;\n public minus_point = 0;\n public cost = 0;\n public discountable = true;\n public printing_sequence = 0;\n public recommended = false;\n public likes = 0;\n public dislikes = 0;\n public is_tax_exempt = false;\n public is_service_charge_exempt = false;\n public is_point_reward_exempt = false;\n public is_credit_reward_exempt = false;\n public is_internal = false;\n public is_delisted = false;\n public uid = ModelPrefix.Item + nanoid();\n public modifiers?: Array<ICoreItem>;\n public modifier_categories?: Array<ICoreCategory>;\n public kitchen_printers_uids = [];\n public order_printers_uids = [];\n public label_printers_uids = [];\n public open_editor_panel = false;\n public open_price_editor = false;\n public combo_groups: IComboGroup[] = [];\n constructor() {\n super();\n // You can perform additional initialization here if needed\n }\n}\n\nexport interface IPrice extends IAppCoreModel {\n /** keys to look up the price */\n lookup_keys: Array<string | 'member_price'>;\n /** product uid*/\n product_uid: string;\n /** price of the item */\n amount: number;\n /** name of the price */\n name: string;\n /** name translations */\n name_translations: Record<string, string>;\n}\n\nexport class Price extends AppCoreModel implements IPrice {\n public lookup_keys = [];\n public product_uid = '';\n public uid = ModelPrefix.Price + nanoid();\n public amount = 0;\n public name = '';\n public name_translations: Record<string, string> = {};\n constructor() {\n super();\n }\n}\n\n/**\n * COMBO PRODUCT IMPLEMENTATION\n *\n * Combo products bundle multiple existing products together and sell them as a group,\n * usually at a discount. This implementation provides minimal impact on existing data structures.\n *\n * Usage:\n * 1. Create combo product with type = ProductType.Combo\n * 2. Define combo_groups array with component groups and available items\n * 3. Set combo discount (either amount or percentage)\n * 4. When adding to invoice, combo appears as single line with selections in combo_components\n *\n * Example:\n * ```\n * const combo: IItem = {\n * type: ProductType.Combo,\n * combo_groups: [\n * {\n * name: \"Choose your main\",\n * min_selections: 1,\n * max_selections: 1,\n * required: true,\n * items: [\n * { item_uid: 'burger_uid', is_default: true },\n * { item_uid: 'chicken_uid', price_override: 2.00 }\n * ]\n * },\n * {\n * name: \"Pick a side\",\n * min_selections: 1,\n * max_selections: 1,\n * required: true,\n * items: [\n * { item_uid: 'fries_uid', is_default: true },\n * { item_uid: 'onion_rings_uid', price_override: 1.50 }\n * ]\n * }\n * ],\n * combo_discount_percent: 15 // 15% discount\n * }\n * ```\n */\n\n/**\n * Interface for individual items within a combo group\n */\nexport interface IComboGroupItem extends IAppModelSequence {\n /** Item unique id */\n item_uid: string;\n /** Combo item */\n /** @deprecated */\n combo_item: IItem;\n /** Price of the item in combo */\n price: number;\n /** Meta data */\n meta: Record<string, unknown>;\n}\n\n/**\n * Interface for combo component groups (e.g., \"Main Course\", \"Side\", \"Drink\")\n */\nexport interface IComboGroup extends IAppModelSequence {\n /** Group unique id */\n uid: string;\n /** Group name (e.g., \"Choose your main\", \"Pick a side\") */\n name: string;\n /** Translations of the name */\n name_translations: Record<string, string>;\n /** Minimum selections required from this group */\n min_order: number;\n /** Maximum selections allowed from this group */\n max_order: number;\n /** Available items in this group */\n combo_items: IComboGroupItem[];\n /** Meta data */\n meta: Record<string, unknown>;\n}\n\nexport class ComboGroupItem implements IComboGroupItem {\n public item_uid = '';\n public combo_item = new Item();\n public price = 0;\n public sequence = 0;\n public meta: Record<string, unknown> = {};\n constructor() {}\n}\n\nexport class ComboGroup implements IComboGroup {\n public uid = ModelPrefix.ComboGroup + nanoid();\n public name = '';\n public name_translations: Record<string, string> = {};\n public min_order = 1;\n public max_order = 1;\n public combo_items: IComboGroupItem[] = [];\n public sequence = 0;\n public meta: Record<string, unknown> = {};\n constructor() {}\n}\n\n","\n\nexport class ElectronSocket {\n static State = { CLOSED: 0, OPENING: 1, OPENED: 2, CLOSING: 3 };\n\n private _state = ElectronSocket.State.CLOSED;\n private cleanup?: () => void;\n public onData: ((data: Uint8Array) => void) | null = null;\n public onClose: ((hadError: boolean) => void) | null = null;\n public onError: ((error: string) => void) | null = null;\n\n\n\n get state() {\n return this._state;\n }\n\n static electronSocket = null;\n static setWindow(win: { electronSocket: typeof window.electronSocket }) {\n ElectronSocket.electronSocket = win.electronSocket;\n }\n\n\n private setupListeners() {\n this.cleanup?.();\n this.cleanup = window.electronSocket.onEvent((payload: any) => {\n switch (payload.type) {\n case 'DataReceived':\n this.onData?.(new Uint8Array(payload.data));\n break;\n case 'Close':\n this._state = ElectronSocket.State.CLOSED;\n this.onClose?.(payload.hasError);\n this.cleanup?.();\n break;\n case 'Error':\n this.onError?.(payload.errorMessage);\n break;\n }\n });\n }\n\n async open(host: string, port: number, success?: () => void, error?: (errorMessage: string) => void): Promise<void> {\n try {\n if (this._state !== ElectronSocket.State.CLOSED) {\n error?.(`Invalid state: ${this._state}`);\n return;\n }\n this._state = ElectronSocket.State.OPENING;\n this.setupListeners();\n const result = await ElectronSocket.electronSocket.open(host, port);\n if (result) {\n this._state = ElectronSocket.State.OPENED;\n success?.();\n } else error?.(`Open failed`);\n } catch (err : any) {\n this._state = ElectronSocket.State.CLOSED;\n this.cleanup?.();\n error?.(`Open failed: ${err}`);\n }\n }\n\n async write(data: Uint8Array, success?: () => void, error?: (errorMessage: string) => void): Promise<void> {\n try {\n if (this._state !== ElectronSocket.State.OPENED) error?.('Socket not opened');\n const result = await ElectronSocket.electronSocket.write(Array.from(data));\n if (result) success?.();\n else error?.('Write failed');\n } catch (err : any) {\n error?.(`Write failed: ${err}`);\n }\n }\n\n async close(success?: () => void, error?: (errorMessage: string) => void): Promise<void> {\n if (this._state !== ElectronSocket.State.OPENED) {\n error?.(`Invalid state: ${this._state}`);\n return;\n }\n try {\n this._state = ElectronSocket.State.CLOSING;\n const result = await ElectronSocket.electronSocket.close();\n if (result) {\n this._state = ElectronSocket.State.CLOSED;\n this.cleanup?.();\n success?.();\n } else error?.('Close socket failed');\n } catch (err : any) {\n this._state = ElectronSocket.State.CLOSED;\n this.cleanup?.();\n error?.(`Close socket failed: ${err}`);\n }\n }\n}\n","// VISCII codepage identifier\nexport const VISCII_CODEPAGE = '69';\n\n// Check if codepage is VISCII\nexport function isVISCIICodepage(codepage: string | undefined): boolean {\n return codepage === VISCII_CODEPAGE;\n}\n\n// VISCII encoding table based on RFC 1456 (extracted from iconv-lite)\nconst VISCII_TABLE: { [key: string]: number } = {\n // Control character range (0x02-0x1F)\n 'Ẳ': 0x02, 'Ẵ': 0x05, 'Ẫ': 0x06, 'Ỷ': 0x14, 'Ỹ': 0x19, 'Ỵ': 0x1E,\n\n // Extended character range (0x80-0xFF)\n 'Ạ': 0x80, 'Ắ': 0x81, 'Ằ': 0x82, 'Ặ': 0x83, 'Ấ': 0x84, 'Ầ': 0x85, 'Ẩ': 0x86, 'Ậ': 0x87,\n 'Ẽ': 0x88, 'Ẹ': 0x89, 'Ế': 0x8A, 'Ề': 0x8B, 'Ể': 0x8C, 'Ễ': 0x8D, 'Ệ': 0x8E,\n 'Ố': 0x8F, 'Ồ': 0x90, 'Ổ': 0x91, 'Ỗ': 0x92, 'Ộ': 0x93,\n 'Ợ': 0x94, 'Ớ': 0x95, 'Ờ': 0x96, 'Ở': 0x97,\n 'Ị': 0x98, 'Ỏ': 0x99, 'Ọ': 0x9A, 'Ỉ': 0x9B, 'Ủ': 0x9C, 'Ũ': 0x9D, 'Ụ': 0x9E, 'Ỳ': 0x9F,\n\n 'Õ': 0xA0,\n 'ắ': 0xA1, 'ằ': 0xA2, 'ặ': 0xA3, 'ấ': 0xA4, 'ầ': 0xA5, 'ẩ': 0xA6, 'ậ': 0xA7,\n 'ẽ': 0xA8, 'ẹ': 0xA9, 'ế': 0xAA, 'ề': 0xAB, 'ể': 0xAC, 'ễ': 0xAD, 'ệ': 0xAE,\n 'ố': 0xAF, 'ồ': 0xB0, 'ổ': 0xB1, 'ỗ': 0xB2,\n 'Ỡ': 0xB3, 'Ơ': 0xB4, 'ộ': 0xB5, 'ờ': 0xB6, 'ở': 0xB7,\n 'ị': 0xB8, 'Ự': 0xB9, 'Ứ': 0xBA, 'Ừ': 0xBB, 'Ử': 0xBC, 'ơ': 0xBD, 'ớ': 0xBE, 'Ư': 0xBF,\n\n 'À': 0xC0, 'Á': 0xC1, 'Â': 0xC2, 'Ã': 0xC3, 'Ả': 0xC4, 'Ă': 0xC5, 'ẳ': 0xC6, 'ẵ': 0xC7,\n 'È': 0xC8, 'É': 0xC9, 'Ê': 0xCA, 'Ẻ': 0xCB, 'Ì': 0xCC, 'Í': 0xCD, 'Ĩ': 0xCE, 'ỳ': 0xCF,\n\n 'Đ': 0xD0, 'ứ': 0xD1, 'Ò': 0xD2, 'Ó': 0xD3, 'Ô': 0xD4, 'ạ': 0xD5, 'ỷ': 0xD6, 'ừ': 0xD7, 'ử': 0xD8,\n 'Ù': 0xD9, 'Ú': 0xDA, 'ỹ': 0xDB, 'ỵ': 0xDC, 'Ý': 0xDD, 'ỡ': 0xDE, 'ư': 0xDF,\n\n 'à': 0xE0, 'á': 0xE1, 'â': 0xE2, 'ã': 0xE3, 'ả': 0xE4, 'ă': 0xE5, 'ữ': 0xE6, 'ẫ': 0xE7,\n 'è': 0xE8, 'é': 0xE9, 'ê': 0xEA, 'ẻ': 0xEB, 'ì': 0xEC, 'í': 0xED, 'ĩ': 0xEE, 'ỉ': 0xEF,\n\n 'đ': 0xF0, 'ự': 0xF1, 'ò': 0xF2, 'ó': 0xF3, 'ô': 0xF4, 'õ': 0xF5, 'ỏ': 0xF6, 'ọ': 0xF7,\n 'ụ': 0xF8, 'ù': 0xF9, 'ú': 0xFA, 'ũ': 0xFB, 'ủ': 0xFC, 'ý': 0xFD, 'ợ': 0xFE, 'Ữ': 0xFF,\n};\n\n// Convert UTF-8 Vietnamese text to VISCII bytes\nexport function utf8ToVISCII(text: string, fallback = 0x3F): Uint8Array {\n const bytes: number[] = [];\n for (const ch of text) {\n if (VISCII_TABLE[ch] !== undefined) bytes.push(VISCII_TABLE[ch]);\n else {\n const code = ch.charCodeAt(0);\n if (code <= 0x7F) bytes.push(code);\n else bytes.push(fallback);\n }\n }\n return Uint8Array.from(bytes);\n}\n","import EscPosEncoder from 'esc-pos-encoder-ionic';\nimport wcwidth from 'wcwidth';\nimport { ElectronSocket } from './electron.socket';\nimport { isVISCIICodepage, utf8ToVISCII } from './viscii.encoding';\n// eslint-disable-next-line no-var\ndeclare let Socket: any;\n\n// if (typeof process !== 'undefined' && process.versions && process.versions.electron) {\n// Socket = require('./renderer.js');\n// }\n\nfunction getSocket(): any { return typeof Socket === 'undefined' ? new ElectronSocket() : new Socket(); }\n\n/**\n * Represents an ESC/POS printer.\n */\nexport interface IEscPosPrinter {\n /**\n * Prints the content to the printer.\n * @returns A promise that resolves to true if the printing is successful, otherwise false.\n */\n testPrint(template: IPrintCommand): Promise<boolean>;\n\n /**\n * Connects to the printer with the specified IP address and port number.\n * @param ip The IP address of the printer.\n * @param port The port number of the printer. Default is 9100.\n * @param timeout The connection timeout in milliseconds. Default is 5000ms.\n * @returns A promise that resolves to true if the connection is successful, otherwise false.\n */\n connect(ip: string, port?: number, timeout?: number): Promise<boolean>;\n\n /**\n * Writes the content to the printer.\n * @param resultByte The content to write to the printer.\n * @param timeout The write timeout in milliseconds. Default is 10000ms.\n * @returns A promise that resolves to true if the writing is successful, otherwise false.\n */\n write(resultByte: any, timeout?: number): Promise<boolean>;\n\n /**\n * Interprets the print command and returns the encoded byte array.\n * @param template The print command to interpret.\n * @returns A promise that resolves to the encoded byte array.\n */\n interpret(template: IPrintCommand): Promise<Uint8Array>;\n}\n\nexport class EscPosPrinter implements IEscPosPrinter {\n // static instance: EscPosPrinter;\n public socket: any;\n\n public constructor() {\n this.socket = getSocket();\n console.log('this.socket', JSON.stringify(this.socket));\n\n this.socket.onData = function (data: any) {\n console.log('event - receive: ', data);\n };\n\n this.socket.onClose = function (hasError: any) {\n console.log('event - socket closed');\n };\n\n this.socket.onError = function (errorMessage: any) {\n console.error('event - socket error:', errorMessage);\n // Additional code to handle socket error\n };\n }\n\n // public static getInstance(): IEscPosPrinter {\n // if (!EscPosPrinter.instance) {\n // EscPosPrinter.instance = new EscPosPrinter();\n // }\n // // Return the singleton instance.\n // return EscPosPrinter.instance;\n // }\n\n /**\n * Prints esc pos printer\n * @returns print\n */\n public async testPrint(template: IPrintCommand): Promise<boolean> {\n //console.log('before connect', this.socket);\n await this.connect('192.168.1.253');\n const result = await this.interpret(template);\n console.log('escpos commands:', JSON.stringify(result));\n const printResult = await this.write(result);\n await this.disconnect();\n //console.log('after close', this.socket)\n return printResult;\n }\n\n public async connect(ip: string, port = 9100, timeout = 5000): Promise<boolean> {\n return new Promise<boolean>((resolve, reject) => {\n const checkInterval = 100; // Check state every 100ms\n // eslint-disable-next-line prefer-const\n let timeoutId: number;\n // eslint-disable-next-line prefer-const\n let intervalId: number;\n // Function to clear all timers\n const clearTimers = () => {\n if (timeoutId) window.clearTimeout(timeoutId);\n if (intervalId) window.clearInterval(intervalId);\n };\n \n // State resolve\n intervalId = window.setInterval(() => {\n // Requirement 1: Wait for state == 2 (OPENED) before resolve\n if (this.socket.state === 2) {\n clearTimers();\n resolve(true);\n }\n }, checkInterval);\n \n // Timeout resolve\n timeoutId = window.setTimeout(() => {\n clearTimers();\n resolve(false);\n }, timeout);\n \n // open\n this.socket.open(\n ip,\n port,\n () => {\n // Don't resolve here, wait for state to change to OPENED in the interval check\n },\n (err: any) => {\n clearTimers();\n resolve(false);\n }\n );\n }).catch(async (err) => {\n return false;\n });\n }\n\n public async write(resultByte: any, timeout = 10000): Promise<boolean> {\n return new Promise<boolean>((resolve, reject) => {\n let timeoutId: number;\n this.socket.write(resultByte, () => {\n console.log('write success');\n clearTimeout(timeoutId); // Clear the timeout\n resolve(true);\n });\n\n timeoutId = window.setTimeout(() => {\n console.error('socket write timed out');\n resolve(false);\n }, timeout); // Timeout after specified milliseconds\n }).catch((err) => {\n console.error('socket write exception: ', err);\n return false;\n });\n }\n\n public async interpret(template: IPrintCommand): Promise<Uint8Array> {\n const encoder = new EscPosEncoder();\n const printing = encoder.initialize();\n if(template.codepage && !Object.values(Codepages).includes(template.codepage)) {\n const codepageNum = parseInt(template.codepage as string, 10);\n printing.raw([0x1F, 0x1B, 0x1F, 0xFF, codepageNum, 0x0A, 0x00]);\n }else if (template.codepage && Object.values(Codepages).includes(template.codepage)) {\n encoder.codepage(template.codepage);\n } else {\n encoder.codepage(Codepages.SimplifiedChinese);\n }\n\n for (const printItem of template.items) {\n if (!printItem) {\n throw new Error('Item is undefined or null');\n }\n\n switch (printItem.style) {\n case PrintStyle.Bold:\n printing.bold(true);\n break;\n case PrintStyle.Italic:\n printing.italic(true);\n break;\n case PrintStyle.Underline:\n printing.underline(true);\n break;\n default:\n printing.bold(false);\n printing.italic(false);\n printing.underline(false);\n break;\n }\n\n if (printItem.align) {\n printing.align(printItem.align);\n }\n\n switch (printItem.type) {\n case PrintType.Text:\n if (printItem.item?.text) {\n if (printItem.item.size === PrintSize.Custom && printItem.item.height && printItem.item.width) {\n if (printItem.item.width < 0 || printItem.item.width > 7 || printItem.item.height < 0 || printItem.item.height > 7) {\n throw new Error('font_width and font_height must be between 0 and 7');\n }\n const sizeValue = (printItem.item.height << 4) | printItem.item.width;\n printing.raw([0x1d, 0x21, sizeValue]);\n } else if (printItem.item.size) {\n printing.size(printItem.item.size);\n }\n if (isVISCIICodepage(template.codepage)) {\n const visciiBytes = utf8ToVISCII(printItem.item.text);\n printing.raw(Array.from(visciiBytes));\n } else {\n printing.text(printItem.item.text, printItem.item.line_width ?? 48);\n }\n if (printItem.item.size === PrintSize.Custom) printing.raw([0x1d, 0x21, 0x00]);\n }\n break;\n case PrintType.Table:\n //console.log('printItem.table', printItem.table);\n if (printItem.table) {\n if (printItem.table.size === PrintSize.Custom && printItem.table.height && printItem.table.width) {\n if (printItem.table.width < 0 || printItem.table.width > 7 || printItem.table.height < 0 || printItem.table.height > 7) {\n throw new Error('font_width and font_height must be between 0 and 7');\n }\n const sizeValue = (printItem.table.height << 4) | printItem.table.width;\n printing.raw([0x1d, 0x21, sizeValue]);\n } else if (printItem.table.size) {\n printing.size(printItem.table.size);\n }\n //console.log('printItem.table.items', printItem.table.items);\n const lines = this.formatTable(printItem.table.items, printItem.table.line_width ?? 48);\n //console.log('lines', lines);\n lines.forEach((line) => {\n if (isVISCIICodepage(template.codepage)) {\n const visciiBytes = utf8ToVISCII(line);\n printing.raw(Array.from(visciiBytes));\n } else {\n printing.text(line, printItem.table.line_width ?? 48);\n }\n printing.newline();\n });\n if (printItem.table.size === PrintSize.Custom) printing.raw([0x1d, 0x21, 0x00]);\n }\n break;\n case PrintType.Line:\n printing.line(printItem.item?.text?.repeat(48) ?? '-'.repeat(48), printItem.item?.line_width ?? 48);\n break;\n case PrintType.NewLine:\n printItem.repeat = printItem.repeat ?? 1;\n for (let i = 0; i < printItem.repeat; i++) printing.newline();\n break;\n case PrintType.Image:\n if (printItem.image) {\n const image = await this.base64ToImageBitmap(printItem.image.base64_data);\n printing.image(image, printItem.image.width, printItem.image.height, printItem.image.algorithm, printItem.image.threshold);\n }\n break;\n case PrintType.QRCode:\n if (printItem.qrcode) {\n printing.qrcode(printItem.qrcode.data, printItem.qrcode.model, printItem.qrcode.size, printItem.qrcode.errorlevel);\n }\n break;\n case PrintType.Barcode:\n if (printItem.barcode) {\n printing.barcode(printItem.barcode.data, printItem.barcode.symbology, printItem.barcode.height);\n }\n break;\n case PrintType.Cut:\n printing.cut(printItem.item?.text ?? 'full');\n break;\n case PrintType.Beeper:\n printing.beeper();\n break;\n case PrintType.OpenCashDrawer:\n printing.openCashDrawer();\n break;\n default:\n throw new Error(`Unsupported item type: ${printItem.type}`);\n }\n\n // if (printItem.codepage && printItem.codepage !== template.codepage) {\n // encoder.codepage(template.codepage);\n // }\n };\n\n return printing.encode();\n }\n\n private formatTable(items: IPrintTableRowItem[], lineWidth = 48): string[] {\n // Calculate each item's width\n const itemWidths = items.map((item) => Math.floor(lineWidth * (item.column_width / 100)));\n\n // Wrap item text if necessary\n const textMatrix = items.map((item, index) => this.wrapText(item.text, itemWidths[index]));\n\n // Create formatted lines\n const lines: string[] = [];\n const maxLines = Math.max(...textMatrix.map((wrappedText) => wrappedText.length));\n\n for (let i = 0; i < maxLines; i++) {\n let line = '';\n for (let j = 0; j < items.length; j++) {\n const text = textMatrix[j][i] || '';\n line += this.padEnd(text, itemWidths[j]);\n }\n lines.push(line);\n }\n\n return lines;\n }\n\n private padEnd(text: string, width: number): string {\n let currentWidth = Array.from(text).reduce((acc, char) => acc + wcwidth(char), 0);\n return text + ' '.repeat(Math.max(0, width - currentWidth));\n }\n\n private padStart(text: string, width: number): string {\n let currentWidth = Array.from(text).reduce((acc, char) => acc + wcwidth(char), 0);\n return ' '.repeat(Math.max(0, width - currentWidth)) + text;\n }\n\n // Function to wrap text\n // Function to wrap text\n private wrapText(leftItem: any, width: number): string[] {\n if (typeof leftItem !== 'string') {\n leftItem = leftItem.toString();\n }\n if (!leftItem) return ['']; // Return array with empty string instead of empty array\n const wrapped: string[] = [];\n let currentLine = '';\n let currentWidth = 0;\n \n for (const char of leftItem) {\n const charWidth = wcwidth(char);\n if (currentWidth + charWidth > width) {\n wrapped.push(currentLine);\n currentLine = '';\n currentWidth = 0;\n }\n currentLine += char;\n currentWidth += charWidth;\n }\n \n if (currentLine) {\n wrapped.push(currentLine);\n }\n \n return wrapped;\n }\n\n public async disconnect(): Promise<boolean> {\n try {\n await this.close();\n return true;\n } catch (err) {\n throw new Error(err);\n }\n }\n\n private close(timeout = 5000): Promise<void> {\n return new Promise((resolve, reject) => {\n const originalOnClose = this.socket.onClose;\n // eslint-disable-next-line prefer-const\n let timeoutId: number;\n this.socket.onClose = (hasError: any) => {\n clearTimeout(timeoutId);\n this.socket.onClose = originalOnClose;\n if (hasError) {\n reject(new Error(`Socket closed with error: ${hasError}`));\n } else {\n resolve();\n }\n if (typeof originalOnClose === 'function') {\n originalOnClose(hasError);\n }\n };\n const error = (err: any) => {\n clearTimeout(timeoutId);\n this.socket.onClose = originalOnClose;\n reject(err);\n };\n \n timeoutId = window.setTimeout(() => {\n this.socket.onClose = originalOnClose;\n reject(new Error('Socket close operation timed out'));\n }, timeout);\n \n this.socket.close(\n () => console.log('Close initiated successfully'),\n error\n );\n });\n }\n\n /**\n * base64转ImageBitmap,只进行基本转换,不进行缩放和居中处理\n * @param base64Data 图片base64\n */\n private async base64ToImageBitmap(base64Data: string): Promise<ImageBitmap> {\n const match = base64Data.match(/^data:(image\\/(?:jpeg|png));base64,(.+)$/i);\n if (!match) throw new Error('base64_data format is invalid or image type is not supported (only jpeg/png allowed)');\n const [ , mimeType, pureBase64 ] = match;\n const blob = new Blob([Uint8Array.from(atob(pureBase64), c => c.charCodeAt(0))], { type: mimeType });\n const imageBitmap = await createImageBitmap(blob);\n return imageBitmap;\n }\n}\n\nexport enum Codepages {\n English = 'cp437',\n Greek = 'cp737',\n WesternEurope = 'cp850',\n BalticRim = 'cp775',\n CentralEurope = 'cp852',\n Cyrillic = 'cp855',\n Turkish = 'cp857',\n MultilingualLatin1WithEuro = 'cp858',\n Portuguese = 'cp860',\n Icelandic = 'cp861',\n Hebrew = 'cp862',\n FrenchCanadian = 'cp863',\n Arabic = 'cp864',\n Nordic = 'cp865',\n Russian = 'cp866',\n ModernGreek = 'cp869',\n SimplifiedChinese = 'cp936',\n Korean = 'cp949',\n TraditionalChinese = 'cp950',\n WesternEuropeanLatin = 'cp1252',\n ArabicISO = 'iso88596',\n Japanese = 'shiftjis',\n CentralEuropeanLatinWindows = 'windows1250',\n CyrillicWindows = 'windows1251',\n WesternEuropeanLatinWindows = 'windows1252',\n GreekWindows = 'windows1253',\n TurkishWindows = 'windows1254',\n HebrewWindows = 'windows1255',\n ArabicWindows = 'windows1256',\n BalticWindows = 'windows1257',\n Vietnamese = 'windows1258',\n}\n\nexport enum PrintAlign {\n Left = 'left',\n Center = 'center',\n Right = 'right',\n}\n\nexport enum PrintStyle {\n Normal = 'normal',\n Bold = 'bold',\n Italic = 'italic',\n Underline = 'underline',\n}\n\nexport enum PrintSize {\n Custom = 'custom',\n Normal = 'normal',\n Small = 'small',\n}\n\nexport enum PrintType {\n Text = 'text',\n Table = 'table',\n Line = 'line',\n Image = 'image',\n QRCode = 'qrcode',\n NewLine = 'newline',\n Barcode = 'barcode',\n Cut = 'cut',\n Beeper = 'beeper',\n OpenCashDrawer = 'open_cash_drawer',\n}\n\nexport interface IPrintBarcode {\n data: string;\n symbology: 'upca' | 'upce' | 'ean13' | 'ean8' | 'coda39' | 'itf' | 'codabar';\n height: number;\n}\n\nexport interface IPrintQrcode {\n data: string;\n model: number;\n size: number;\n errorlevel: 'l' | 'm' | 'q' | 'h';\n}\n\nexport type IFontSize = {\n width?: number;\n height?: number;\n size: PrintSize;\n};\n\nexport type IPrintText = IFontSize & {\n text: string;\n line_width?: number;\n};\n\nexport type IPrintTableRowItem = {\n text: string;\n column_width: number;\n};\n\nexport type IPrintTable = IFontSize & {\n items: IPrintTableRowItem[];\n line_width?: number;\n};\n\nexport class PrintBarcode {\n data = '';\n symbology: 'upca' | 'upce' | 'ean13' | 'ean8' | 'coda39' | 'itf' | 'codabar' = 'ean13';\n height = 0;\n}\n\nexport class PrintQrcode {\n data = '';\n model = 2;\n size = 6;\n errorlevel: 'l' | 'm' | 'q' | 'h' = 'm';\n}\n\nexport type IPrintImage = {\n base64_data: string;\n width: number;\n height: number;\n algorithm: 'threshold' | 'bayer' | 'floydsteinberg' | 'atkinson';\n threshold: number;\n};\n\nexport class PrintImage implements IPrintImage {\n base64_data = '';\n width = 0;\n height = 0;\n algorithm: 'threshold' | 'bayer' | 'floydsteinberg' | 'atkinson' = 'threshold';\n threshold = 128;\n}\n\nexport type IPrintCommandLine = {\n item?: IPrintText;\n table?: IPrintTable;\n image?: IPrintImage;\n qrcode?: IPrintQrcode;\n barcode?: IPrintBarcode;\n align?: PrintAlign;\n style?: PrintStyle;\n type: PrintType;\n repeat?: number;\n codepage?: Codepages;\n};\n\nexport type IPrintCommand = {\n codepage: Codepages;\n items: IPrintCommandLine[];\n};\n\nexport enum EscPosCompatibility {\n 'SunmiPrinter',\n}\n\nexport class PrintCommand implements IPrintCommand {\n codepage: Codepages = Codepages.WesternEuropeanLatin;\n items: IPrintCommandLine[] = [];\n}\n","import dayjs from 'dayjs';\n\n// Format date with optional custom format, defaults to 'YYYY-MMM-DD HH:mm:ss'\nexport function humanizedData(date: Date, format?: string): string {\n return dayjs(date).format(format || 'YYYY-MMM-DD HH:mm:ss');\n}\n\nexport function normalizedDate(date: Date): string {\n const year = date.getFullYear();\n const month = (date.getMonth() + 1).toString().padStart(2, '0'); // Months are 0-indexed, so we add 1\n const day = date.getDate().toString().padStart(2, '0');\n const hours = date.getHours().toString().padStart(2, '0');\n const minutes = date.getMinutes().toString().padStart(2, '0');\n const seconds = date.getSeconds().toString().padStart(2, '0');\n\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;\n}","/* eslint-disable no-unused-vars */\nimport { IPrintCommand, PrintCommand, Codepages } from '../libs/escpos.printer';\nimport { AppBaseModel, IAppBaseModel, IAppCoreModel } from './abstract.type';\nimport { IConfig } from './config.type';\nimport { IInvoice } from './invoice.type';\nimport { ModelPrefix } from './misc.type';\nimport { nanoid } from 'nanoid';\nimport { humanizedData } from '../utils/misc.utils';\nimport { IReportData } from './report.type';\nimport { ISectionItem } from './section.type';\n\nexport interface IDevice extends IAppCoreModel {\n machine_name: string;\n connection_id: string;\n type: DeviceType;\n etc: DeviceEtc;\n}\n\nexport type DeviceEtc = {\n fomopay_terminal_id: string;\n hirector_public_key: string;\n hirector_private_key: string;\n yeahpay_app_id: string;\n yeahpay_device_sn: string;\n yeahpay_server_public_key: string;\n yeahpay_client_private_key: string;\n yeahpay_signature_key: string;\n yeahpay_async_url: string;\n yeahpay_print_copies?: number;\n sync_to_specific_cds: string;\n [key: string]: unknown;\n};\n\n\n\nexport type INode = IDevice;\n\nexport class Device extends AppBaseModel implements IDevice {\n public machine_name = '';\n public connection_id = '';\n public type = DeviceType.Client;\n public etc: DeviceEtc = {\n fomopay_terminal_id: '',\n hirector_public_key: '',\n hirector_private_key: '',\n yeahpay_app_id: '',\n yeahpay_device_sn: '',\n yeahpay_server_public_key: '',\n yeahpay_client_private_key: '',\n yeahpay_signature_key: '',\n yeahpay_async_url: '',\n sync_to_specific_cds: '',\n };\n constructor() {\n super();\n }\n}\n\nexport class Node extends AppBaseModel implements INode {\n type = DeviceType.Node;\n machine_name = '';\n connection_id = '';\n etc: DeviceEtc = {\n fomopay_terminal_id: '',\n hirector_public_key: '',\n hirector_private_key: '',\n yeahpay_app_id: '',\n yeahpay_device_sn: '',\n yeahpay_server_public_key: '',\n yeahpay_client_private_key: '',\n yeahpay_signature_key: '',\n yeahpay_async_url: '',\n sync_to_specific_cds: '',\n };\n constructor() {\n super();\n }\n}\n\nexport enum DeviceType {\n Client = 'client',\n Node = 'node',\n}\n\n// Defining the PrinterType enum, assuming it's defined in your C# code\nexport enum PrinterType {\n ReceiptPrinter = 'receipt_printer',\n CheckPrinter = 'check_printer',\n OrderPrinter = 'order_printer',\n KitchenPrinter = 'kitchen_printer',\n KioskPrinter = 'kiosk_printer',\n LabelPrinter = 'label_printer',\n QrCodePrinter = 'qr_code_printer',\n}\n\nexport interface INodePrinter {\n printer_name: string;\n status: string;\n port_name: string;\n error: string;\n}\n\nexport class NodePrinter implements INodePrinter {\n public printer_name = '';\n public status = '';\n public port_name = '';\n public error = '';\n}\n\nexport enum PrinterProtocols {\n ESCPOS = 'ESC/POS',\n TSPL = 'TSPL',\n}\n\nexport enum PrinterConnections {\n USB = 'USB',\n WINDOWS_DRIVER = 'WINDOWS_DRIVER',\n ETHERNET = 'ETHERNET',\n BLUETOOTH = 'BLUETOOTH',\n BUILTIN = 'BUILTIN'\n}\n\nexport type IPrintTemplateCore = {\n header: string;\n body: string;\n footer: string;\n commands: string;\n};\n\nexport class PrintTemplateCore implements IPrintTemplateCore {\n public header = '';\n public body = '';\n public footer = '';\n public commands = '';\n public type = PrinterType.ReceiptPrinter;\n constructor() {}\n}\n\nexport type IPrintTemplate = IPrintTemplateCore &\n IAppBaseModel & {\n printer_type: PrinterType;\n codepage?: Codepages;\n report_code_name: string;\n };\n\nexport class PrintTemplate extends AppBaseModel implements IPrintTemplate {\n public header = '';\n public body = '';\n public footer = '';\n public commands = '';\n public printer_type = PrinterType.ReceiptPrinter;\n public codepage?: Codepages;\n public uid = ModelPrefix.PrintTemplate + nanoid();\n public report_code_name = '';\n constructor() {\n super();\n }\n}\n\nexport enum PrintJobStatus {\n Queued = 'queued',\n Printed = 'printed',\n Failed = 'failed',\n Expired = 'expired'\n}\n\nexport interface IPrintJob extends IAppCoreModel {\n printer_name: string;\n /** Actual printer name using printer driver*/\n driver_printer_name: string;\n printer_ip: string;\n printer_uid: string;\n printer_type: PrinterType;\n protocol: PrinterProtocols;\n connection_type: PrinterConnections;\n data: IPrintCommand;\n commands: string;\n status: PrintJobStatus;\n retries: number;\n /** If true, only save the print job to the database, do not print */\n save_only: boolean;\n print_times: number;\n printed: number;\n /** Targeting which device to print */\n device_uid_to_print: string;\n /** Designated Table Sections */\n designated_table_section_uids: string[];\n /** Job ID */\n job_id: number;\n /** Print sequence order (lower number prints first) */\n print_sequence?: number;\n meta: Record<string, unknown>;\n /** USB device ID (runtime dynamic) */\n usb_device_id?: number;\n /** USB serial number for persistent device identification */\n usb_serial_number?: string;\n}\n\nexport class PrintJob extends AppBaseModel implements IPrintJob {\n public printer_name = '';\n public driver_printer_name = '';\n public printer_ip = '';\n public printer_uid = '';\n public printer_type = PrinterType.ReceiptPrinter;\n public protocol = PrinterProtocols.ESCPOS;\n public connection_type = PrinterConnections.ETHERNET;\n public data = new PrintCommand();\n public status = PrintJobStatus.Queued;\n public retries = 0;\n public commands = '';\n public uid = ModelPrefix.PrintJob + nanoid();\n public save_only = false;\n public print_times = 1;\n public printed = 0;\n public device_uid_to_print = '';\n public designated_table_section_uids = [];\n public job_id = 0;\n public print_sequence?: number;\n constructor(printer: IPrinter, printData: IPrintCommand, saveOnly = false, printTimes = 1) {\n super();\n this.driver_printer_name = printer.driver_printer_name;\n if(printer.protocol) this.protocol = printer.protocol;\n if(printer.connection_type) this.connection_type = printer.connection_type;\n this.printer_name = printer.name;\n this.printer_ip = printer.ip_address;\n if(printer.type) this.printer_type = printer.type;\n this.data = printData;\n this.printer_uid = printer.uid;\n this.save_only = saveOnly;\n this.print_times = printTimes;\n if(printer.print_sequence !== undefined) this.print_sequence = printer.print_sequence;\n }\n public meta: Record<string, unknown> = {};\n}\n\nexport enum PrinterStatus {\n Online = 'online',\n Offline = 'offline',\n}\n\nexport interface IPrinter extends IAppBaseModel {\n /** Printer terminal ID */\n device_uid: string;\n /** Printer type */\n type: PrinterType;\n /** If true, this printer is not the default for its type */\n is_not_default?: boolean;\n /** Actual printer name using printer driver*/\n driver_printer_name: string;\n /** Backup printer ID */\n fallback_printer_uid: number;\n /** Printer protocol */\n protocol: PrinterProtocols;\n /** Printer connection type */\n connection_type: PrinterConnections;\n /** Print template UID */\n print_template_uid?: string;\n /** Printer IP address */\n ip_address?: string;\n /** Printer status */\n status: PrinterStatus;\n /** if it is consolidated print or itemized print when it is kitchen printer */\n kitchen_itemized_print: boolean;\n /** Number of times to print */\n print_times: number;\n /** Number of retries */\n retries: number;\n /** Print sequence order (lower number prints first) */\n print_sequence?: number;\n /** USB serial number for persistent device identification */\n usb_serial_number?: string;\n}\n\nexport class Printer extends AppBaseModel implements IPrinter {\n public device_uid = '';\n public type = PrinterType.ReceiptPrinter;\n public is_not_default?: boolean = false;\n public driver_printer_name = '';\n public fallback_printer_uid = 0;\n public protocol = PrinterProtocols.ESCPOS;\n public connection_type = PrinterConnections.ETHERNET;\n public print_template_uid = '';\n public uid = ModelPrefix.Printer + nanoid();\n public ip_address = '';\n public status = PrinterStatus.Online;\n public kitchen_itemized_print = false;\n public print_times = 1;\n public retries = 1;\n constructor() {\n super();\n }\n}\n\nexport interface ITemplateData {\n config: IConfig;\n invoice: IInvoice;\n printer_name: string;\n printed_at: Date;\n normalized_printed_at: string;\n report_data: IReportData;\n meta: Record<string, any>;\n is_cancel?: boolean;\n}\n\nexport class TemplateData implements ITemplateData {\n public config = {} as IConfig;\n public invoice = {} as IInvoice;\n public report_data = {} as IReportData;\n public section_item = {} as ISectionItem;\n public printer_name = '';\n public printed_at = new Date();\n public normalized_printed_at = '';\n public meta: Record<string, any> = {};\n public is_cancel = false;\n constructor() {\n this.normalized_printed_at = humanizedData(this.printed_at);\n }\n}\n\nexport type IRenderPrintTemplateOptions = {\n printer_name: string;\n kitchen_itemized_print: boolean;\n is_cancel?: boolean;\n};\n\nexport class RenderPrintTemplateOptions implements IRenderPrintTemplateOptions {\n public printer_name = '';\n public kitchen_itemized_print = false;\n public is_cancel = false;\n}\n","import { AppBaseModel, AppCoreModel, IAppBaseModel, IAppCoreModel } from \"./abstract.type\";\nimport { ModelPrefix } from './misc.type';\nimport { nanoid } from 'nanoid';\nimport { IAppModelSequence } from '../services/abstract.service';\n\n/**\n * Payment Entity Interface\n */\nexport interface IPayment extends IAppCoreModel {\n /** Invoice ID */\n invoice_uid: string;\n /** Tender Amount\n * tender amount can be greater than invoice amount\n * So the payment amount is tender_amount - change_amount\n */\n tender_amount: number;\n /** Change Amount */\n change_amount: number;\n /** Payment Method ID */\n payment_method_uid: string;\n /** Payment Method Code */\n payment_method_code: string;\n /** Selected Payment Method */\n payment_method_name: string;\n /** Selected Payment Method */\n payment_method: IPaymentMethod;\n /** Payment Method History when payment method is changed */\n payment_method_history?: IPaymentMethodHistory;\n}\n\nexport class Payment extends AppCoreModel implements IPayment {\n public invoice_uid = \"\";\n public tender_amount = 0;\n public change_amount = 0;\n public payment_method_uid = \"\";\n public payment_method_code = \"\";\n public payment_method_name = \"\";\n public payment_method = new PaymentMethod();\n public payment_method_history: IPaymentMethodHistory;\n public uid = ModelPrefix.Payment + nanoid();\n public updated_at = new Date();\n constructor() {\n super();\n }\n}\n\n/**\n * Payment Method Entity Interface\n */\nexport interface IPaymentMethod extends IAppBaseModel, IAppModelSequence{\n /** Payment Currency ID */\n payment_currency_id: number;\n /** Currency Code */\n currency_code: string;\n /** Payment Method Code */\n currency_symbol: string;\n /** Payment Method Code */\n payment_method_code: string;\n /** Payment Name */\n name: string;\n /** Code Name */\n codename: string;\n /** Name Abbreviation */\n name_abbrev: string;\n /** Enable Drawer */\n enable_drawer: boolean;\n /** Enable Receipt */\n enable_receipt: boolean;\n /** Image URL */\n image_url: string;\n /** Custom Image URL */\n custom_image_url: string;\n /** Is Cash */\n is_cash: boolean;\n /** Is Integrated */\n is_integrated: boolean;\n /** Is Disabled */\n is_disabled: boolean;\n /** Type */\n type: number;\n /** API ID */\n api_id: string;\n /** API Key */\n api_key: string;\n /** Is Sales Exclusive */\n is_sales_exclusive: boolean;\n /** Requires invoice.minus_credit > 0 for validation */\n enable_credit_validation: boolean;\n /** Requires invoice.customer_id > 0 for validation */\n enable_customer_validation: boolean;\n /** Allow cancellation during payment process */\n is_cancellable: boolean;\n}\n\nexport interface IPaymentMethodHistory extends IPaymentMethod {\n changed_at: Date;\n changed_by: string;\n}\n\n\n\nexport class PaymentMethod extends AppBaseModel implements IPaymentMethod {\n public sequence = 0;\n public payment_currency_id = 0;\n public currency_code = \"\";\n public currency_symbol = \"$\";\n public payment_method_code = \"\";\n public name = \"\";\n public codename = \"\";\n public name_abbrev = \"\";\n public enable_drawer = false;\n public enable_receipt = false;\n public image_url = \"\";\n public custom_image_url = \"\";\n public is_cash = false;\n public is_integrated = false;\n public is_disabled = true;\n public type = 0;\n public api_id = \"\";\n public api_key = \"\";\n public is_sales_exclusive = false;\n public enable_credit_validation = false;\n public enable_customer_validation = false;\n public is_cancellable = false;\n public uid = ModelPrefix.PaymentMethod + nanoid();\n constructor() {\n super();\n }\n}\n\nexport class PaymentMethodHistory extends PaymentMethod {\n public changed_at = new Date();\n public changed_by = \"\";\n constructor() {\n super();\n }\n}\n\n/* eslint-disable no-unused-vars */\nexport interface IStandardPaymentMethod {\n /** Access Token */\n access_token: string | null;\n /** Base64 encoded image */\n image_base64: string | null;\n /** Error message */\n error: string | null;\n /** Currency code */\n currency_code: string | null;\n /** Payment method code */\n payment_method_code: string;\n /** Codename of the payment method */\n codename: string | null;\n /** Abbreviated name */\n name_abbrev: string | null;\n /** Full name */\n name: string;\n /** Flag to enable drawer */\n enable_drawer: boolean;\n /** Flag to enable receipt */\n enable_receipt: boolean;\n /** Image URL */\n image_url: string;\n /** Flag for cash payment */\n is_cash: boolean;\n /** Flag for integrated payment */\n is_integrated: boolean;\n /** Flag to disable the payment method */\n is_disabled: boolean;\n /** Type of payment method */\n type: number;\n /** API ID */\n api_id: string | null;\n /** API Key */\n api_key: string | null;\n /** Timestamp of creation */\n timestamp_create: number;\n /** Timestamp of last update */\n timestamp_update: number;\n\n toPaymentMethod(): PaymentMethod;\n}\n\nexport class StandardPaymentMethod implements IStandardPaymentMethod {\n public access_token = null;\n public image_base64 = null;\n public error = null;\n public currency_code = null;\n public payment_method_code = \"\";\n public codename = null;\n public name_abbrev = null;\n public name = \"\";\n public enable_drawer = false;\n public enable_receipt = true;\n public image_url = \"\";\n public is_cash = false;\n public is_integrated = false;\n public is_disabled = false;\n public type = 0;\n public api_id = null;\n public api_key = null;\n public timestamp_create = Date.now();\n public timestamp_update = Date.now();\n\n toPaymentMethod(): PaymentMethod {\n const paymentMethod = new PaymentMethod();\n\n // Mapping properties with the same name\n paymentMethod.currency_code = this.currency_code || '';\n paymentMethod.payment_method_code = this.payment_method_code || '';\n paymentMethod.codename = this.codename || '';\n paymentMethod.name = this.name || '';\n paymentMethod.name_abbrev = this.name_abbrev || '';\n paymentMethod.enable_drawer = this.enable_drawer;\n paymentMethod.enable_receipt = this.enable_receipt;\n paymentMethod.image_url = this.image_url || '';\n paymentMethod.is_cash = this.is_cash;\n paymentMethod.is_integrated = this.is_integrated;\n paymentMethod.is_disabled = this.is_disabled;\n paymentMethod.type = this.type;\n paymentMethod.api_id = this.api_id || '';\n paymentMethod.api_key = this.api_key || '';\n\n // Properties in IPaymentMethod not mapped:\n // - sequence\n // - payment_currency_id\n // - is_sales_exclusive\n // - (and all properties from IAppBaseModel)\n\n return paymentMethod;\n }\n\n constructor(init?: Partial<IPaymentMethod>) {\n if (init) {\n Object.assign(this, init);\n }\n }\n}\n\nexport type IChangePaymentMethodOption = {\n source_payment: IPayment;\n target_payment_method: IPaymentMethod;\n}\n\n/**\n * Payment sync status enum\n */\nexport enum PaymentStatus {\n STARTED = 'payment_started',\n COMPLETED = 'payment_completed',\n FAILED = 'payment_failed',\n CANCELLED = 'payment_cancelled'\n}\n","import { AppBaseModel, IAppBaseModel } from './abstract.type';\nimport { ModelType } from './misc.type';\n\nexport type INoteGroupEntity = IAppBaseModel;\n\nexport class NoteGroupEntity extends AppBaseModel implements INoteGroupEntity {\n constructor() {\n super();\n }\n}\n\nexport type INoteGroup = INoteGroupEntity;\n\nexport class NoteGroup extends NoteGroupEntity {\n constructor() {\n super();\n }\n}\n\nexport interface INoteEntity extends IAppBaseModel {\n /** Group ID */\n note_group_uid: string;\n /** Type of the Note */\n related_model: ModelType;\n /** Usage */\n usage: number;\n}\n\nexport class NoteEntity extends AppBaseModel implements INoteEntity {\n public note_group_uid = \"\";\n public related_model = ModelType.Invoice; // Assign a default value based on the NoteType enum\n public usage = 0;\n\n constructor() {\n super();\n }\n}\n\nexport type INote = INoteEntity;\n\nexport class Note extends NoteEntity {\n constructor() {\n super();\n }\n}\n\n","import { IAppCoreModel, AppCoreModel } from './abstract.type';\nimport { IPayment } from './payment.type';\nimport { CoreItem, type ICoreItem, type IItem, Item } from './product.type';\nimport { Address, Customer, IAddress, ICustomer } from './wyo.customer.type';\nimport { ModelPrefix } from './misc.type';\nimport { nanoid } from 'nanoid';\nimport { ISectionItem } from './section.type';\nimport { ITill } from './shift.type';\nimport { IPrintJob } from './printer.type';\nimport { Condition } from './condition.type';\n\nexport enum InvoiceType {\n DineIn = 'dine_in',\n TakeOut = 'take_out',\n Delivery = 'delivery',\n}\n\nexport enum OrderFlow {\n PayToOrder = 'pay_to_order',\n OrderFirstAndPayLater = 'order_first_and_pay_later',\n OnSelection = 'on_selection',\n}\n\n\n\nexport enum TaxMethod {\n Inclusive = 'inclusive',\n Exclusive = 'exclusive',\n}\n\nexport enum InvoiceStatus {\n Open = 'open',\n OnHold = 'on_hold',\n Paying = 'paying',\n Paid = 'paid',\n Void = 'void',\n PayAtCounter = 'pay_at_counter',\n}\n\nexport enum InvoiceAction {\n Calibration = 'calibration',\n Create = 'create',\n Update = 'update',\n Cancel = 'cancel',\n Hold = 'hold',\n PaymentAsync = 'payment_async',\n Check = 'check',\n Void = 'void',\n Switch = 'switch',\n Reprint = 'reprint',\n Display = 'display',\n Merge = 'merge',\n Calculate = 'calculate',\n Delivery = 'delivery',\n Payment = 'payment',\n ChangePayment = 'change_payment',\n AddCustomer = 'add_customer',\n VoidAndDuplicate = 'void_and_duplicate',\n Duplicate = 'duplicate',\n PayAtCounter = 'pay_at_counter',\n PayInvoice = 'pay_invoice',\n SettleOnlineDeliveryOrder = 'settle_online_delivery_order'\n}\n// Enum types can be defined based on actual values in C# code\nexport enum UomType {\n quantity = 'quantity',\n weight = 'weight',\n}\n\nexport enum CalcType {\n Flat = 'flat',\n Percent = 'percent',\n}\n\nexport enum CalcFlow {\n AfterSubtotal = 'after_subtotal',\n AfterServiceCharge = 'after_service_charge',\n AfterGrantTotal = 'after_grant_total',\n}\n\nexport enum DiscountType {\n Custom = 'custom',\n Voucher = 'voucher',\n Coupon = 'coupon',\n}\n\n/**\n * Interface for invoice charge items\n */\nexport interface IInvoiceCharge {\n /** Charge unique id */\n uid: string;\n /** Charge name */\n name: string;\n /** Charge amount */\n percentage: number;\n /** Charge amount */\n amount: number;\n /** Charge calculation flow */\n calc_flow: CalcFlow;\n}\n\nexport class InvoiceCharge implements IInvoiceCharge {\n public uid = ModelPrefix.InvoiceCharge + nanoid();\n public name = '';\n public percentage = 0;\n public amount = 0;\n public calc_flow = CalcFlow.AfterSubtotal;\n}\n\nexport interface IInvoiceActivity {\n /** Action */\n action: InvoiceAction;\n /** Action by */\n action_by: string;\n /** Device unique id */\n device_uid: string;\n /** Action at */\n action_at: Date;\n}\n\nexport class InvoiceActivity {\n public action = InvoiceAction.Create;\n public action_by = '';\n public device_uid = '';\n public action_at = new Date();\n}\n\nexport interface IDiscount {\n name?: string;\n name_translation?: Record<string, string>;\n uid: string;\n calc_type: CalcType;\n amount: number;\n percent: number;\n}\n\nexport interface ICharge {\n uid: string;\n name: string;\n percent: number;\n calc_flow: CalcFlow;\n trigger_condition: Condition | string;\n}\n\nexport class Charge implements ICharge {\n public uid = ModelPrefix.Charge + nanoid();\n public name = '';\n public percent = 0;\n public calc_flow = CalcFlow.AfterSubtotal;\n public trigger_condition = '';\n}\n\nexport interface IInvoiceDiscount extends IDiscount {\n /** Discount Type */\n type: DiscountType;\n /** Discount unique id */\n voucher_uid?: string;\n /** Applying item uids */\n applying_item_uids: string[];\n /** Discount unique id */\n coupon_uid?: string;\n /** Calculation flow */\n calc_flow: CalcFlow;\n percent_amount: number;\n}\n\nexport class InvoiceDiscount implements IInvoiceDiscount {\n public calc_type = CalcType.Flat;\n public amount = 0;\n public percent = 0;\n public percent_amount = 0;\n public type = DiscountType.Custom;\n public calc_flow = CalcFlow.AfterSubtotal;\n public applying_item_uids: string[] = [];\n public name = '';\n public name_translation = {};\n public voucher_uid = '';\n public coupon_uid = '';\n public uid = ModelPrefix.InvoiceDiscount + nanoid();\n}\n\nexport interface IInvoiceCoreLine {\n /** Item unique id */\n item_uid: string;\n /** The item being sold on the line item. */\n item: ICoreItem;\n /** Item unit price */\n price: number;\n /** Unit of measure (1:quantity | 2:weight) */\n unit_of_measure: UomType;\n /** Quantity if it is quantity, e.g. 5*/\n quantity: number;\n /** Whether it is sent to server, e.g. send = 3, it means 2 items are not sent to server*/\n /** item A, qty = 5 sent 3 => kitchen slip will show quantity 2 on item A */\n sent: number;\n /** Whether cancel slip is printed */\n is_cancel_printed: boolean;\n /** Whether it is selected */\n selected: boolean;\n /** Sales user uid for this line item */\n sales_user_uid: string;\n}\n\n/**\n * Represents a line item on an invoice.\n */\nexport interface IInvoiceLine extends IAppCoreModel, Omit<IInvoiceCoreLine, 'item'> {\n item: IItem;\n /** Invoice Line unique id */\n invoice_uid: string;\n /** Line discount calculation type */\n discount_calc_type: CalcType;\n /** The amount of discount applied to the line item. */\n discount_amount: number;\n /** The percentage of discount applied to the line item. */\n discount_percent: number;\n /** The subtotal for the line item. */\n subtotal: number;\n /** The subtotal for the line item before any discounts were applied. */\n subtotal_before_discount: number;\n /** The unit price of the item. */\n price: number;\n /** The point value of the item. */\n point: number;\n /** The subtotal for the line item in points. */\n point_subtotal: number;\n /** The unit of measurement for the item. */\n unit_of_measure: UomType;\n /** The quantity of the item being sold on the line item. */\n quantity: number;\n /** Any additional remarks for the line item. */\n remark: string;\n /** Whether the item size is up-sized. */\n up_size: boolean;\n /** Whether the line item is for take-out. If so, the service charge is not counted. */\n is_take_out: boolean;\n /** Whether the line item is a duplicate. */\n is_duplicate: boolean;\n /** The line item that this line item is duplicated from. */\n duplicated_from_uid: string;\n /** Whether the line item is a combo. */\n is_combo : boolean;\n /** Whether the line item is a combo item. */\n is_combo_item : boolean;\n /** Combo group unique id. */\n combo_group_uid : string;\n /** Combo line unique id. */\n combo_line_uid: string;\n /** Any modifiers applied to the line item. */\n modifiers: IInvoiceCoreLine[];\n /** Meta data for the line item */\n meta: Record<string, any>;\n}\n\nexport interface IInvoice extends IAppCoreModel {\n /** Invoice reference number which is used for look-up */\n ref_id: string;\n /** The number which will be printed on kitchen slip \n or receipt or display to call when order is ready */\n call_num: string;\n /** Table unique id */\n table_uid: string;\n /**\n * Table name\n */\n table_name: string;\n /** Invoice type */\n type: InvoiceType;\n //#region Pax\n /** Total number of people including adult, child and baby */\n pax: number;\n /** Number of Adult People */\n adult_pax: number;\n /** Number of Child People */\n child_pax: number;\n /** Number of Baby People */\n baby_pax: number;\n //#endregion\n /** Invoice subtotal */\n subtotal: number;\n /** Invoice point subtotal */\n point_subtotal: number;\n /** Invoice subtotal applicable to service charge */\n service_chargeable_subtotal: number;\n /** Invoice subtotal applicable to discount */\n discountable_subtotal: number;\n /** Invoice service charge */\n service_charge: number;\n /** Online delivery id */\n delivery_id: number;\n /** Online delivery charge */\n delivery_charge: number;\n /** Online delivery type */\n delivery_type: string;\n /** Online delivery driver */\n delivery_by: string;\n //#region Package\n /** If customer package is used in this invoice */\n // use_customer_package: boolean;\n /** Package deduction amount */\n // minus_package: number;\n //#endregion\n //#region Point\n /** If customer point is used in this invoice */\n use_customer_point: boolean;\n /** Add point */\n add_point: number;\n /** minus point */\n minus_point: number;\n /** rewarded point rate */\n rewarded_point_rate: number;\n /** Rewarded Point */\n rewarded_point: number;\n //#endregion\n //#region Credit\n /** if customer balance is used in this invoice */\n use_customer_balance: boolean;\n /** add credit */\n add_credit: number;\n /** minus credit */\n minus_credit: number;\n /** rewarded credit rate */\n rewarded_credit_rate: number;\n /** Rewarded Credit */\n rewarded_credit: number;\n //#endregion\n /** Discount List */\n discounts: IInvoiceDiscount[];\n /** Total discount amount */\n discount_amount: number;\n /** Tax */\n tax: number;\n /** Rounding */\n rounding: number;\n /** Tip Amount */\n tip: number;\n /** Grand Total */\n grand_total: number;\n /** Customer ID */\n customer_id: number;\n /** Remark */\n remark: string;\n /** Sales User UID */\n sales_user_uid: string;\n /** Status */\n status: InvoiceStatus;\n /** Payment Method */\n paid_at: Date;\n /** Human readable date */\n humanized_paid_at: string;\n /** Payment Method */\n voided_at: Date;\n /** Human readable date */\n humanized_voided_at: string;\n \n humanized_created_at: string;\n /** Order ID */\n order_id: number;\n /** To Address */\n to_address: IAddress;\n /** Payment Source Method */\n payment_source_method: string;\n /** Payment Source Last4 */\n payment_source_last4: string;\n /** Payment Source Charge Reference */\n payment_source_charge_ref: string;\n\n /** Is Sales Exclusive */\n is_sales_exclusive: boolean;\n /** Etc */\n etc: Record<string, any>;\n /** Action : is mainly used for online order and tracking the invoice operation activities*/\n action: InvoiceAction;\n /** Invoice Lines */\n lines: IInvoiceLine[];\n /** Deleted invoice lines */\n deleted_lines: IInvoiceLine[];\n /** Invoice Signature */\n // invoice_signature: InvoiceSignatureModel;\n /** \n * if invoice payments has cash payment\n */\n payment_has_cash: boolean;\n /** Payment */\n payments: IPayment[];\n /** Table Switch ID */\n table_switch_id: number;\n /** Customer Spend */\n // customer_spend: CustomerSpendHistoryItemize\n /** Reservation */\n // reservation: TableReservationModel;\n /** Receipt Print Override */\n employee_uid: string;\n /**Employee Name */\n employee_name: string;\n receipt_print_override: boolean;\n /** Customer */\n customer: ICustomer;\n /** Is Duplicate */\n is_duplicate: boolean;\n /** Kitchen Print Override */\n kitchen_print_override: boolean;\n /** OTP */\n otp: string;\n /** Invoice Activity */\n activities: any []\n\n /** Receipt printer unique id */\n receipt_print_job_uid: string;\n\n /** Kitchen print job uids */\n kitchen_print_job_uids: string[][];\n\n /** Label print job uids */\n label_print_job_uids: string[][];\n\n /** Additional charges */\n charges: IInvoiceCharge[];\n \n /** Flag to track if charge has been manually deleted by user */\n is_charge_triggered: boolean;\n\n /** Meta data for the invoice */\n meta: Record<string, any>;\n\n /** If the key is not null or empty, meaning the items prices are from this price lookup key tier */\n price_lookup_key: string;\n}\n\nexport class InvoiceCoreLine implements IInvoiceCoreLine{\n public item_uid = '';\n public item = new CoreItem();\n public price = 0;\n public unit_of_measure = UomType.quantity;\n public quantity = 0;\n public sent = 0;\n public is_cancel_printed = false;\n public selected = false;\n public sales_user_uid = '';\n constructor() {}\n}\n\nexport class InvoiceLine extends AppCoreModel implements IInvoiceLine {\n public item_uid = '';\n public price = 0;\n public unit_of_measure = UomType.quantity; // You should define default value for UomType\n public quantity = 0;\n public remark = '';\n public invoice_uid = '';\n public discount_calc_type = CalcType.Flat; // You should define default value for CalcType\n public discount_amount = 0;\n public discount_percent = 0;\n public subtotal = 0;\n public subtotal_before_discount = 0;\n public item = new Item(); // You should define or instantiate default IItem\n public point = 0;\n public point_subtotal = 0;\n public up_size = false;\n public is_take_out = false;\n public is_duplicate = false;\n public is_combo = false;\n public is_combo_item = false;\n public combo_group_uid = '';\n public combo_line_uid = '';\n public modifiers = [];\n public duplicated_from_uid = '';\n public sent = 0;\n public is_cancel_printed = false;\n public selected = false;\n public sales_user_uid = '';\n public meta = {};\n constructor() {\n super();\n }\n}\n\nexport class Invoice extends AppCoreModel implements IInvoice {\n public ref_id = '';\n public call_num = '';\n public table_uid = '';\n public table_name = '';\n public type: InvoiceType = InvoiceType.DineIn;\n public pax = 0;\n public adult_pax = 0;\n public child_pax = 0;\n public baby_pax = 0;\n public subtotal = 0;\n public point_subtotal = 0;\n public service_chargeable_subtotal = 0;\n public discountable_subtotal = 0;\n public service_charge = 0;\n public delivery_id = 0;\n public delivery_charge = 0;\n public delivery_type = '';\n public delivery_by = '';\n public use_customer_point = false;\n public add_point = 0;\n public minus_point = 0;\n public rewarded_point_rate = 0;\n public rewarded_point = 0;\n public use_customer_balance = false;\n public add_credit = 0;\n public minus_credit = 0;\n public rewarded_credit_rate = 0;\n public rewarded_credit = 0;\n public discounts = [];\n public discount_amount = 0;\n public tax = 0;\n public rounding = 0;\n public tip = 0;\n public grand_total = 0;\n public customer_id = 0;\n public remark = '';\n public sales_user_uid = '';\n public status: InvoiceStatus = InvoiceStatus.Open;\n public paid_at = new Date(0);\n public voided_at = new Date(0);\n public humanized_paid_at = '';\n public humanized_voided_at = '';\n public humanized_created_at = '';\n // public get normalized_paid_at(): string {\n // if(!this.paid_at) return 'NA';\n // return humanizedData(this.paid_at);\n // }\n // public voided_at = new Date();\n // public get normalized_voided_at(): string {\n // if(!this.voided_at) return 'NA';\n // return humanizedData(this.voided_at);\n // }\n\n // public get normalized_created_at(): string {\n // if(!this.created_at) return 'NA';\n // return humanizedData(this.created_at);\n // }\n\n // public get normalized_updated_at(): string {\n // if(!this.updated_at) return 'NA';\n // return humanizedData(this.updated_at);\n // }\n\n // public get normalized_deleted_at(): string {\n // if(!this.deleted_at) return 'NA';\n // return humanizedData(this.deleted_at);\n // }\n\n public order_id = 0;\n public to_address = new Address();\n public payment_source_method = '';\n public payment_source_last4 = '';\n public payment_source_charge_ref = '';\n public is_sales_exclusive = false;\n public etc: Record<string, any> = {};\n public action: InvoiceAction;\n public lines: IInvoiceLine[] = [];\n public deleted_lines: IInvoiceLine[] = [];\n public payment_has_cash = false;\n public payments: IPayment[] = [];\n public table_switch_id = 0;\n public employee_uid = '';\n public employee_name = '';\n public receipt_print_override = false;\n public customer = new Customer();\n public is_duplicate = false;\n public kitchen_print_override = false;\n public otp = '';\n public activities = [];\n public receipt_print_job_uid = '';\n public kitchen_print_job_uids: string[][] = [];\n public label_print_job_uids: string[][] = [];\n public charges: IInvoiceCharge[] = [];\n /** Flag to track if charge has been manually deleted by user */\n public is_charge_triggered = false;\n public uid = ModelPrefix.Invoice + nanoid();\n public meta: Record<string, any> = {};\n public price_lookup_key = '';\n constructor() {\n super();\n }\n}\n\nexport type CreateInvoiceOptions = {\n invoice: IInvoice;\n section_item: ISectionItem;\n print_jobs? : IPrintJob[];\n}\nexport type CancelInvoiceOptions = CreateInvoiceOptions & {\n print_jobs?: IPrintJob[];\n}\nexport type CheckInvoiceOptions = CreateInvoiceOptions & {\n print_jobs?: IPrintJob[];\n};\nexport type UpdateInvoiceOptions = CreateInvoiceOptions;\nexport type SwitchInvoiceOptions = {\n invoice: IInvoice;\n target_section_item: ISectionItem;\n source_section_item: ISectionItem;\n}\nexport type VoidInvoiceOptions = {\n invoice : IInvoice;\n till : ITill;\n print_jobs?: IPrintJob[];\n section_item?: ISectionItem;\n}\nexport type PayInvoiceOptions = VoidInvoiceOptions & {\n section_item : ISectionItem;\n print_jobs?: IPrintJob[];\n};\nexport type DirectPayInvoiceOptions = VoidInvoiceOptions & {\n print_jobs?: IPrintJob[];\n};","import { AppCoreModel, IAppCoreModel } from './abstract.type';\nimport { ModelPrefix } from './misc.type';\nimport { nanoid } from 'nanoid';\n\nexport interface IEmployee extends IAppCoreModel {\n /** User ID */\n user_uid: string;\n /** User name */\n name: string;\n /** User email */\n email: string;\n /** 6 digits of password */\n password: string;\n /** role uid */\n role_uid: string;\n /** language preference */\n language : string;\n /** Whether employee can login to the system */\n can_login: boolean;\n}\n\nexport class Employee extends AppCoreModel implements IEmployee {\n user_uid: string;\n name: string;\n email: string;\n password: string;\n uid = ModelPrefix.Employee + nanoid();\n role_uid = '';\n language = 'en';\n can_login = true;\n constructor() {\n super();\n }\n}\n","import { AppCoreModel, IAppCoreModel } from './abstract.type';\nimport { OrderFlow, TaxMethod } from './invoice.type';\n\nexport interface IAppConfig extends IAppCoreModel {\n config: IConfig;\n cache: ICache;\n storage: {\n pricing_lookup_keys: string[];\n pay_in_reasons: string[];\n pay_out_reasons: string[];\n }\n}\n\nexport class AppConfig extends AppCoreModel implements IAppConfig {\n public config = new Config();\n public cache = new Cache();\n public storage = {\n pricing_lookup_keys: [],\n pay_in_reasons: [],\n pay_out_reasons: [],\n };\n constructor() {\n super();\n }\n}\n\nexport interface ICache {\n printers: string[];\n}\n\nexport class Cache implements ICache {\n public printers = [];\n constructor() {}\n}\n\n/* eslint-disable no-unused-vars */\nexport interface IConfig {\n /** General setting */\n general: IGeneralConfig;\n /** Till setting */\n till: ITillConfig;\n /** Report setting */\n report: IReportConfig;\n /** Receipt setting */\n receipt: IReceiptConfig;\n /** Kitchen slip setting */\n kitchen: IKitchenConfig;\n /** KDS setting */\n label: ILabelConfig;\n /** Order setting */\n order: IOrderConfig;\n /** Payment setting */\n payment: IPaymentConfig;\n /** User setting */\n user: IUserConfig;\n /** Service charge setting */\n /** Tax setting */\n tax: ITaxConfig;\n /** Rounding setting */\n rounding: IRoundingConfig;\n /** Charge setting */\n charges: IChargeConfig;\n /** Currency setting */\n currency: ICurrencyConfig;\n /** Inventory setting */\n inventory: IInventoryConfig;\n /** Pax setting */\n pax_config: IPaxConfig;\n /** Gto setting */\n gto: IGtoConfig;\n /** Cash drawer setting */\n cash_drawer: ICashDrawerConfig;\n /** Marketing setting */\n marketing: IMarketing;\n /** KDS setting */\n kds: IKdsConfig;\n /** Customer display system setting */\n cds: ICustomerDisplaySystemConfig;\n /** Order display setting */\n ods: IOrderDisplaySystemConfig;\n /** Kiosk system setting */\n kiosk: IKioskSystemConfig;\n /** Online order setting */\n online_order: IOnlineOrderConfig;\n /** Loyalty program setting */\n loyalty_program: ILoyaltyProgram & Record<string, any>\n /** CRM setting */\n crm: ICrmConfig;\n}\n\nexport interface ILoyaltyProgram {\n enable_price_tiers: boolean;\n rewarded_credit_rate: number;\n rewarded_point_rate: number;\n /** Whether service charge is inclusive */\n inclusive_service_charge: boolean;\n /** Whether tax is inclusive */\n inclusive_tax: boolean;\n /** Default country code for phone numbers */\n default_country_code: string;\n}\n\nexport interface ICrmConfig {}\n\nexport class CrmConfig implements ICrmConfig {\n constructor() {}\n}\n\nexport class LoyaltyProgram implements ILoyaltyProgram {\n public enable_price_tiers = false;\n public rewarded_credit_rate = 0.0;\n public rewarded_point_rate = 0.0;\n public inclusive_service_charge = false;\n public inclusive_tax = false;\n public default_country_code = '+65';\n constructor() {}\n}\n\nexport interface ICustomerDisplaySystemConfig {\n enabled: boolean;\n full_screen_assets: string[];\n half_screen_assets: string[];\n is_logo_hidden: boolean;\n order_list_font_size?: string; // order list item name font size\n order_modifier_font_size?: string; // order list modifier font size\n screen_width?: number;\n screen_height?: number;\n order_display_duration?: number;\n}\n\nexport class CustomerDisplaySystemConfig implements ICustomerDisplaySystemConfig {\n public enabled = false;\n public full_screen_assets = [];\n public half_screen_assets = [];\n public is_logo_hidden = false;\n public order_list_font_size = '1.875rem';\n public order_modifier_font_size = '1.25rem';\n public screen_width = 1024;\n public screen_height = 768;\n public order_display_duration = 60;\n constructor() {}\n}\n\nexport interface IKioskSystemConfig {\n takeaway_only: boolean;\n guest_order_only: boolean;\n disable_paynow_payment: boolean;\n disable_card_payment: boolean;\n landing_image: string;\n menu_banner_image: string;\n home_page_images: string [];\n paynow_method: PaynowMethod;\n card_payment_code: CardPaymentCode;\n}\n\nexport enum CardPaymentCode {\n SmoochPay = 'SPCD',\n YeahPay = 'YEAP',\n}\n\nexport class KioskSystemConfig implements IKioskSystemConfig {\n public takeaway_only = false;\n public guest_order_only = false;\n public disable_paynow_payment = false;\n public disable_card_payment = false;\n public landing_image = '';\n public menu_banner_image = '';\n public home_page_images = [];\n public paynow_method = PaynowMethod.WyoPaynow;\n public card_payment_code = CardPaymentCode.SmoochPay;\n constructor() {}\n}\n\nexport interface IMarketing {\n /** Marketing Point Configuration */\n point: IPoint;\n /** Marketing Credit Configuration */\n credit: ICredit;\n}\n\nexport interface ICredit {\n /** Indicates if SMS notification is enabled */\n sms_notification: boolean;\n /** Threshold for invoices to apply credits */\n above_invoice_amount: number;\n /** Rate of conversion for credits */\n conversion_rate: number;\n /** Whether service charge is inclusive */\n inclusive_service_charge: boolean;\n /** Whether tax is inclusive */\n inclusive_tax: boolean;\n}\n\nexport interface IPoint {\n /** Indicates if SMS notification is enabled */\n sms_notification: boolean;\n /** Threshold for invoices to apply points */\n above_invoice_amount: number;\n /** Rate of conversion for points */\n conversion_rate: number;\n /** Whether service charge is inclusive */\n inclusive_service_charge: boolean;\n /** Whether tax is inclusive */\n inclusive_tax: boolean;\n}\n\nexport class MarketingConfig implements IMarketing {\n public point: IPoint = {\n sms_notification: false,\n above_invoice_amount: 0.0,\n conversion_rate: 0.0,\n inclusive_service_charge: false,\n inclusive_tax: false,\n };\n\n public credit: ICredit = {\n sms_notification: false,\n above_invoice_amount: 0.0,\n conversion_rate: 0.0,\n inclusive_service_charge: false,\n inclusive_tax: false,\n };\n\n constructor() {}\n}\n\nexport class Config implements IConfig {\n public general = new GeneralConfig();\n public till = new TillConfig();\n public report = new ReportConfig();\n public receipt = new Receipt();\n public kitchen = new KitchenConfig();\n public kds = new KdsConfig();\n public label = new LabelConfig();\n public order = new OrderConfig();\n public ods = new OrderDisplaySystemConfig();\n public payment = new PaymentConfig();\n public user = new UserConfig();\n public tax = new TaxConfig();\n public rounding = new RoundingConfig();\n public inventory = new InventoryConfig();\n public pax_config = new PaxConfig();\n public gto = new GTOConfig();\n public cash_drawer = new CashDrawerConfig();\n public marketing = new MarketingConfig();\n public charges = new ChargeConfig();\n public currency = new CurrencyConfig();\n public cds = new CustomerDisplaySystemConfig();\n public kiosk = new KioskSystemConfig();\n public online_order = new OnlineOrderConfig();\n public loyalty_program = new LoyaltyProgram();\n public crm = new CrmConfig();\n constructor() {}\n}\n\nexport enum PaynowMethod {\n FomoOnlinePaynow = 'PNWO',\n WyoPaynow = 'WPPN'\n}\n\nexport type TDynamicOrderQR = {\n default_order_flow: OrderFlow;\n select_order_flow: boolean;\n select_menus: boolean;\n}\nexport interface IOnlineOrderConfig{\n enable_membership: boolean;\n login_call_to_action_text: string;\n menu_banner_image_url : string;\n paynow_method: PaynowMethod;\n disable_pay_at_counter: boolean;\n disable_paynow_payment: boolean;\n dynamic_order_qr: TDynamicOrderQR;\n default_language: string;\n category_selector_mode: 'photo_mode' | 'dropdown_mode';\n max_dining_time: number;\n disable_logo_for_item_photo_fallback: boolean;\n whatsapp_login_only: boolean;\n enable_whatsapp_login: boolean;\n}\n\nexport class OnlineOrderConfig implements IOnlineOrderConfig{\n public enable_membership = false;\n public login_call_to_action_text = '';\n public menu_banner_image_url = '';\n public paynow_method: PaynowMethod.WyoPaynow\n public disable_pay_at_counter = false;\n public disable_paynow_payment = false;\n public default_language = 'en';\n public category_selector_mode: 'photo_mode' | 'dropdown_mode' = 'photo_mode';\n public dynamic_order_qr: TDynamicOrderQR = {\n default_order_flow: OrderFlow.OrderFirstAndPayLater,\n select_order_flow: false,\n select_menus: false,\n };\n public max_dining_time = 0;\n public disable_logo_for_item_photo_fallback = false;\n public whatsapp_login_only = false;\n public enable_whatsapp_login = false;\n constructor() {}\n}\n\nexport interface IGeneralConfig {\n /**\n * The default language for system interfaces and communications.\n */\n language: string;\n\n /**\n * The official registered name of the company using the system.\n */\n company_name: string;\n\n /**\n * An alternative name or shorthand for the company used for convenience.\n */\n company_name_alias: string;\n\n /**\n * The logo of the company\n */\n company_logo: string;\n\n /**\n * The official tax identification number for the company, used for legal and financial documentation.\n */\n company_tax_reg_no: string;\n\n /**\n * The postal code where the company's primary office or headquarters is located.\n */\n company_postcode: string;\n\n /**\n * The full street address of the company's primary location.\n */\n company_address: string;\n\n /**\n * The country in which the company is legally registered and operates.\n */\n company_country: string;\n\n /**\n * The main contact telephone number for the company.\n */\n company_tel: string;\n\n /**\n * Hour (0-23) at which the business day resets. Stores operating past midnight use this\n * so transactions before this hour are counted as the previous day. Default 0 (midnight).\n */\n business_day_cutoff_hour?: number;\n\n /**\n * The name assigned to the table layout or map within the floor plan of the establishment.\n * @ignore\n */\n floor_plan_table_name: string;\n\n /**\n * The software distribution channel used for the deployment of updates or the application itself.\n * @ignore\n */\n deploy_channel: DeployChannel;\n\n /**\n * A flag indicating whether the system should run in debug mode for troubleshooting and development purposes.\n * @ignore\n */\n debug: boolean;\n\n /**\n * A flag that indicates whether system events should be logged for review and auditing purposes.\n * @ignore\n */\n logging: boolean;\n\n /**\n * A setting that determines whether the system is capable of operating without an active internet connection.\n * @ignore\n */\n offline_mode: boolean;\n\n /**\n * Business schedules\n * @ignore\n */\n opening_schedules: Schedule [];\n\n}\n\nexport type UpdateGeneralConfigOptions = {\n [P in keyof IGeneralConfig]?: IGeneralConfig[P];\n};\nexport enum DeployChannel {\n PROD = 'prod',\n DEV = 'dev',\n}\n\nexport class GeneralConfig implements IGeneralConfig {\n /** Name of the company */\n public company_name = '';\n /** Alias for the company name */\n public company_name_alias = '';\n /** Logo of the company */\n public company_logo = '';\n /** Tax registration number of the company */\n public company_tax_reg_no = '';\n /** Postcode of the company */\n public company_postcode = '';\n /** Address of the company */\n public company_address = '';\n /** Country of the company */\n public company_country = '';\n /** Telephone number of the company */\n public company_tel = '';\n /** Hour at which the business day resets (0-23), for stores operating past midnight */\n public business_day_cutoff_hour = 0;\n /** Name of the floor plan table */\n public floor_plan_table_name = 'table';\n /** Deployment channel */\n public deploy_channel = DeployChannel.PROD;\n /** Language setting */\n public language = 'en';\n /** Debug mode status */\n public debug = false;\n /** Logging status */\n public logging = false;\n /** Offline mode status */\n public offline_mode = false;\n\n /** Open schedule */\n public opening_schedules: Schedule [] = [{\n opening_hours: {\n open: '10:00',\n close: '22:00',\n },\n }];\n\n constructor() {}\n}\n\nexport type OpenHours = {\n open: string; // Format: \"HH:MM\" in 24-hour format\n close: string; // Format: \"HH:MM\" in 24-hour format\n};\n\nexport type DayOfWeek = 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday' | 'sunday';\n\nexport type SpecialDay = {\n date: string; // Format: \"YYYY-MM-DD\"\n hours: OpenHours[];\n};\n\nexport type Holiday = {\n name: string;\n date: string; // Format: \"YYYY-MM-DD\"\n};\n\nexport type BreakPeriod = {\n days: DayOfWeek[];\n time: {\n start: string; // Format: \"HH:MM\"\n end: string; // Format: \"HH:MM\"\n };\n};\n\nexport type Schedule = {\n opening_hours: OpenHours;\n};\n\nexport interface ITillConfig {\n /** Control flag for Till */\n control: boolean;\n /** Slip flag for Till */\n slip: boolean;\n}\n\nexport class TillConfig implements ITillConfig {\n /** Control flag for Till */\n public control = true;\n /** Slip flag for Till */\n public slip = true;\n constructor() {}\n}\n\nexport interface IReportConfig {\n /** Flag for itemized consolidated report */\n itemized_consolidated: boolean;\n /** Itemized separated report value */\n itemized_separated: string;\n /** Flag for shift itemized report */\n shift_itemized: boolean;\n /** Start time for report */\n start_time: string;\n /** End time for report */\n end_time: string;\n /** Time for shift print */\n shift_print_time: number;\n /** Flag to disable shift */\n shift_disable: boolean;\n /** Flag for email report */\n email: boolean;\n /** Day boundary offset in hours (-24 to +24), defines when a business day starts */\n day_boundary_offset: number;\n}\n\nexport class ReportConfig implements IReportConfig {\n public itemized_consolidated = true;\n public itemized_separated = '';\n public shift_itemized = true;\n public start_time = '09:00:01';\n public end_time = '23:59:59';\n public shift_print_time = 1;\n public shift_disable = false;\n public email = false;\n /** Day boundary offset in hours (-24 to +24), 0 = midnight */\n public day_boundary_offset = 0;\n constructor() {}\n}\n\nexport interface IReceiptConfig {\n enabled: boolean;\n show_print_dialog: boolean;\n print_docket: boolean;\n hide_non_price_item: boolean;\n receipt_no_reset_daily: boolean;\n language: string;\n disable_persistent_tcp: boolean;\n}\n\nexport class Receipt implements IReceiptConfig {\n public enabled = true;\n public show_print_dialog = false;\n public print_docket = false;\n public hide_non_price_item = false;\n public receipt_no_reset_daily = false;\n public language = 'en';\n public disable_persistent_tcp = false;\n constructor() {}\n}\n\nexport interface IKitchenConfig {\n /** Flag to print */\n enabled: boolean;\n /** Flag to print slip price */\n print_item_price: boolean;\n /** Flag to print cancel slip */\n print_cancel_slip: boolean;\n /** Flag to print whole invoice when order is cancelled */\n print_cancel_whole_invoice: boolean;\n /**\n * The language to use for the kitchen slip.\n */\n language: string;\n}\n\nexport class KitchenConfig implements IKitchenConfig {\n public enabled = true;\n public print_item_price = false;\n public print_cancel_slip = false;\n public print_cancel_whole_invoice = false;\n public language = 'en';\n constructor() {}\n}\n\n// KDS Configuration\nexport interface IKdsConfig {\n enabled: boolean;\n /** Display order after payment */\n display_order_after_payment: boolean;\n /** Print slip upon completion */\n print_slip_upon_completed: boolean;\n}\n\nexport class KdsConfig implements IKdsConfig {\n public enabled = true;\n public display_order_after_payment = false;\n public print_slip_upon_completed = false;\n constructor() {}\n}\n\n// Label Configuration\nexport interface ILabelConfig {\n /** Flag for printing the label */\n print: boolean;\n /** Convert text to raster image for compatibility (e.g., vscii) */\n text_to_raster: boolean;\n}\n\nexport class LabelConfig implements ILabelConfig {\n public print = false;\n public text_to_raster = false;\n constructor() {}\n}\n\n// Order Configuration\nexport interface IOrderConfig {\n /** Separation line for order */\n separation_line: boolean;\n /** Slip for order */\n slip: boolean;\n /** Font size ratio for the slip */\n slip_font_size_ratio: number;\n /** Maximum dining time in minutes */\n max_dinning: number;\n /** Flag to exit the menu after payment */\n exit_menu_after_payment: boolean;\n /** Flag to hide the combo item on receipt view */\n hide_combo_item_on_receipt: boolean;\n /** Flag to hide the point item on receipt view */\n hide_combo_item_on_interactive_view: boolean;\n /** Flag to hide categories when ordering */\n hide_categories_when_ordering: boolean;\n /** Flag to end shift with open tables */\n end_shift_with_open_tables: boolean;\n /** Date time format for humanized dates */\n datetime_format: string;\n /** Ref ID prefix, default '01', 2-3 digits */\n ref_prefix: string;\n}\n\nexport class OrderConfig implements IOrderConfig {\n public separation_line = false;\n public slip = true;\n public slip_font_size_ratio = 1.0;\n public max_dinning = 0;\n public exit_menu_after_payment = false;\n public hide_combo_item_on_receipt = false;\n public hide_combo_item_on_interactive_view = false;\n public hide_categories_when_ordering = false;\n public end_shift_with_open_tables = false;\n public datetime_format = 'YYYY-MMM-DD HH:mm:ss';\n public ref_prefix = '01';\n constructor() {}\n}\n\n// Order Display Configuration\nexport interface IOrderDisplaySystemConfig {\n enabled: boolean;\n language: string;\n}\n\nexport class OrderDisplaySystemConfig implements IOrderDisplaySystemConfig {\n public enabled = false;\n public language = 'en';\n constructor() {}\n}\n\n// Payment Configuration\nexport interface IPaymentConfig {\n /** Quick cash payment */\n quick_cash_payment: boolean;\n /** Notification for payment */\n notification: boolean;\n /** Quick payment option */\n quick: boolean;\n}\n\nexport class PaymentConfig implements IPaymentConfig {\n public quick_cash_payment = false;\n public notification = true;\n public quick = false;\n constructor() {}\n}\n\n// User Configuration\nexport interface IUserConfig {\n /** Control for the user */\n control: boolean;\n}\n\nexport class UserConfig implements IUserConfig {\n public control = true;\n constructor() {}\n}\n\n// Tax Configuration\nexport interface ITaxConfig {\n /** Tax applicable flag */\n enabled: boolean;\n /** Method for the tax */\n method: TaxMethod;\n /** Rate of the tax */\n rate: number;\n /** Name of the tax */\n name: string;\n}\n\nexport class TaxConfig implements ITaxConfig {\n public enabled = true;\n public method = TaxMethod.Inclusive;\n public rate = 7;\n public name = 'GST';\n constructor() {}\n}\n\n// Rounding Configuration\nexport interface IRoundingConfig {\n /** Base for rounding */\n base: number;\n /** Rounding up flag (always up when nearest=false) */\n up: boolean;\n /** Cashless rounding flag */\n cashless: boolean;\n /** Prepayment rounding flag */\n prepayment_rounding?: boolean;\n /** Round to nearest (half up) instead of always up/down */\n nearest?: boolean;\n}\n\nexport interface IChargeConfig {\n service_charge: boolean;\n service_charge_rate: number;\n}\n\nexport class ChargeConfig implements IChargeConfig {\n public service_charge = false;\n public service_charge_rate = 10;\n constructor() {}\n}\n\nexport interface ICurrencyConfig {\n currency_symbol: string;\n is_symbol_after_amount: boolean;\n}\nexport class CurrencyConfig implements ICurrencyConfig {\n public currency_symbol = '$';\n public is_symbol_after_amount = false;\n constructor() {}\n}\n\nexport class RoundingConfig implements IRoundingConfig {\n public base = 0.1;\n public up = true;\n public cashless = false;\n public prepayment_rounding = false;\n constructor() {}\n}\n\n/** Inventory Configuration */\nexport interface IInventoryConfig {\n /** Control flag for inventory */\n inventory_control: boolean;\n sold_out_for_today_only: boolean;\n}\n\nexport class InventoryConfig implements IInventoryConfig {\n public inventory_control = false;\n public sold_out_for_today_only = false;\n constructor() {}\n}\n\n/** Pax Configuration */\nexport interface IPaxConfig {\n /** Pax flag */\n pax: boolean;\n /** Detail flag for Pax */\n detail: boolean;\n}\n\nexport class PaxConfig implements IPaxConfig {\n public pax = true;\n public detail = false;\n constructor() {}\n}\n\n/** GTO Configuration */\nexport interface IGtoConfig {\n /** Interface type */\n interface: string;\n /** Genesis date */\n genesis_date: string;\n /** Upload time */\n upload_time: string;\n /** FTP server */\n ftp_svr: string;\n /** FTP user */\n ftp_usr: string;\n /** FTP port */\n ftp_port: string;\n /** FTP path */\n ftp_path: string;\n /** FTP password */\n ftp_pwd: string;\n /** Mall ID */\n mall_id: string;\n /** Machine ID */\n machine_id: string;\n /** FTP type */\n ftp_type: string;\n}\n\nexport class GTOConfig implements IGtoConfig {\n public interface = '';\n public genesis_date = '';\n public upload_time = '';\n public ftp_svr = '';\n public ftp_usr = '';\n public ftp_port = '';\n public ftp_path = '';\n public ftp_pwd = '';\n public mall_id = '';\n public machine_id = '';\n public ftp_type = 'ftp';\n constructor() {}\n}\n\n/** CashDrawer Configuration */\nexport interface ICashDrawerConfig {\n /** CashDrawer code */\n kick_code: string;\n /** Connection mode */\n connection_mode: 'via_receipt_printer' | 'via_imin_pos';\n}\n\nexport class CashDrawerConfig implements ICashDrawerConfig {\n /**\n * The kick code for the cash drawer.\n */\n public kick_code = '27, 112, 48, 55, 121';\n /** Connection mode */\n public connection_mode: 'via_receipt_printer' | 'via_imin_pos' = 'via_receipt_printer';\n /**\n * Creates a new instance of the CashDrawerConfig class.\n */\n constructor() {}\n}\n","export interface IFileUploadRequest {\n // Name of the file\n name: string;\n \n // Image in base64 format\n base64: string;\n \n // File extension\n extension: string;\n }\n\nexport class FileUploadRequest implements IFileUploadRequest {\n // Name of the file\n public name = '';\n \n // Image in base64 format\n public base64 = '';\n \n // File extension\n public extension = 'png';\n\n constructor(init?: Partial<IFileUploadRequest>) {\n Object.assign(this, init);\n }\n}","const isEmpty = (val) => val === '' || val === undefined;\n\nexport const Include = (query?: string) => {\n return (val) => isEmpty(query) || val.includes(query);\n};\n\nexport const In = (query?: never[]) => {\n return (val: never) => isEmpty(query) || query.includes(val);\n};\n\nexport const Between = (begin: number, end: number) => {\n return (val: number) => val > begin && val < end;\n};\n\nexport const Not = (query?: any) => {\n if (typeof query === 'function') {\n return (val, values) => !query(val, values);\n } else {\n return (val) => val != query;\n }\n};\n\nexport const Raw = (fn) => {\n return fn;\n};\n\nexport const filterByParams = (params: { [key: string]: any }) => {\n return (values) =>\n !values['deleted_at'] &&\n Object.keys(params).every((key) => {\n if (isEmpty(params[key]) || values[key] === params[key]) {\n return true;\n } else if (typeof params[key] === 'function') {\n return params[key](values[key], values);\n }\n });\n};\n","/* eslint-disable @typescript-eslint/no-unused-vars */\nimport { IAppCoreModel } from '../types/abstract.type';\nimport type { AxiosInstance } from 'axios';\nimport Dexie, { Observable, liveQuery } from 'dexie';\nimport { nanoid } from 'nanoid';\nimport { IServiceOptions } from '../types/misc.type';\nimport { filterByParams } from '../libs/FindOptions';\n\nexport type GetManyResult<T> = {\n list: T[];\n count: number;\n page: number;\n pageSize: number;\n};\n\n/**\n * Interface for a generic service.\n * @template T - Generic type parameter that extends IAppCoreModel.\n */\nexport interface IAppCoreService<T extends IAppCoreModel> {\n db: Dexie;\n table: Dexie.Table<T>;\n moduleName: string;\n\n /**\n * Creates a live query.\n * @param expr - Function that returns the query expression.\n * @returns A live query.\n */\n liveQuery<T>(expr: () => T): Observable\n\n /**\n * Saves a single entity.\n * @param item - Entity to save.\n * @returns A Promise that resolves to the saved entity.\n */\n saveOne(item: T): Promise<T>;\n\n /**\n * Saves multiple entities.\n * @param items - Entities to save.\n * @returns A Promise that resolves to the saved entities.\n */\n saveMany(items: T[]): Promise<T[]>; // #todo\n\n /**\n * Checks if any entity exists.\n * @returns A Promise that resolves to true if any entity exists or false otherwise.\n */\n hasAny(): Promise<boolean>;\n /**\n * Retrieves a single entity by its unique identifier.\n * @param id - Unique identifier of the entity to retrieve.\n * @returns A Promise that resolves to the retrieved entity.\n */\n getOne(id: string): Promise<T>;\n\n /**\n * Retrieves a single entity by its unique identifier.\n * @param params - Filtering parameters.\n * @returns A Promise that resolves to the retrieved entity or undefined.\n */\n getOneByParams(params: Partial<T>): Promise<T | undefined>;\n\n /**\n * Retrieves a single entity by its unique identifier.\n * @returns A Promise that resolves to the retrieved entity or undefined.\n */\n getDefaultOne(): Promise<T | undefined>;\n\n /**\n * Retrieves all entities with optional pagination.\n * @param skip - Number of entities to skip.\n * @param take - Number of entities to take.\n * @returns A Promise that resolves to an array of retrieved entities.\n */\n getAll(): Promise<T[]>;\n\n /**\n * Retrieves multiple entities with optional pagination and filtering.\n * @param params - [UNUSED PARAMETER, KEPT FOR POSSIBLE FUTURE USE]\n * Filtering parameters.\n * @param options - Query options including pagination.\n * @returns An object containing the retrieved entities and total count.\n */\n getMany(\n params: Partial<T>,\n options: { page?: number; pageSize?: number },\n ): Promise<GetManyResult<T>>;\n}\n\n// 数据库接入方法\n// export interface IAppDbService<T extends IAppCoreModel> extends IAppCoreService<T> {\n// getOne(uid: string): Promise<T>;\n// getAll(skip: number, take: number): Promise<T[]>;\n// getMany(\n// params,\n// options: FindManyOptions & Partial<{ page: number; pageSize: number }>,\n// ): getManyResult<T>;\n// }\n\n// #feat 读取\nexport abstract class AppCoreService<T extends IAppCoreModel> implements IAppCoreService<T> {\n public db: Dexie;\n public moduleName: string;\n\n public get table(): Dexie.Table<T> {\n return this.db.table(this.moduleName);\n }\n\n public liveQuery<T>(expr: () => T): Observable<T> {\n return liveQuery(expr);\n }\n\n async saveOne(item: T): Promise<T> {\n const data = { ...item };\n if (!data.created_at) {\n data.created_at = new Date();\n } \n if(!data.uid) data.uid = nanoid();\n data.updated_at = new Date();\n await this.db.table(this.moduleName).put(data);\n return data;\n }\n\n async saveMany(items: T[]): Promise<T[]> {\n const data = items.map((item) => {\n if (!item.uid) {\n item.uid = nanoid();\n item.created_at = new Date();\n }\n item.updated_at = new Date();\n return item;\n });\n await this.db.table(this.moduleName).bulkPut(data);\n return data;\n }\n\n async hasAny(): Promise<boolean> {\n const count = await this.db.table(this.moduleName).count();\n return count > 0;\n }\n\n /**\n * get one by uid\n * @param uid Primary nano id\n */\n async getOne(uid: string): Promise<T> {\n const item = await this.db.table(this.moduleName).get(uid);\n if(!item) return null;\n return item;\n }\n\n async getOneByParams(params: Partial<T>): Promise<T | null> {\n return this.db.table(this.moduleName).filter(filterByParams(params)).first();\n }\n\n async getDefaultOne(): Promise<T | undefined> {\n if(!this.moduleName) return null;\n return this.db\n .table(this.moduleName)\n .filter((x) => x.deleted_at === null || x.deleted_at === undefined)\n .first();\n }\n\n async getAll(): Promise<T[]> {\n return this.db.table(this.moduleName).toArray();\n }\n\n async getMany(params: Partial<T> = {}, options: any = {}): Promise<GetManyResult<T>> {\n const { page = 1, pageSize = 10, ...otherOpts } = options || {};\n\n const count = await this.db.table(this.moduleName).filter(filterByParams(params)).count();\n\n const query = this.db\n .table(this.moduleName)\n // .sortBy(otherOpts.orderBy || 'created_at')\n .filter(filterByParams(params));\n\n if (pageSize !== -1) {\n query.offset((page - 1) * pageSize).limit(pageSize);\n }\n\n const list = await query.toArray();\n\n return {\n list,\n count,\n page,\n pageSize,\n };\n }\n\n}\n\nexport interface IAppLocalService<T extends IAppCoreModel> extends IAppCoreService<T> {\n updateOne(id: string, item: Partial<T>): Promise<T>;\n deleteOne(id: string): Promise<T>;\n}\n\nexport class AppLocalService<T extends IAppCoreModel> extends AppCoreService<T> implements IAppLocalService<T> {\n async updateOne(id: string, item: Partial<T>): Promise<T> {\n throw new Error('Method not implemented.');\n }\n async deleteOne(id: string): Promise<T> {\n throw new Error('Method not implemented.');\n }\n}\n\nexport interface IAppRemoteService<T extends IAppCoreModel> extends IAppCoreService<T> {\n addOne(item: T): Promise<T>;\n updateOne(id: number, item: Partial<T>): Promise<T>;\n updateMany(items: T[]): Promise<T[]>;\n deleteOne(model: T): Promise<T>;\n /**\n * Hard delete one entity\n * @param model \n */\n hardDeleteOne(model: T): Promise<T>;\n}\n\n// #feat 创建,更新,删除,读取\nexport class AppRemoteService<T extends IAppCoreModel> extends AppCoreService<T> implements IAppRemoteService<T> {\n protected readonly http: AxiosInstance;\n declare public readonly moduleName: string;\n protected readonly methodName: string;\n protected readonly options: IServiceOptions;\n\n async addOne(item: T): Promise<T> {\n return this.http.put(`api/v5/merchants/${this.options.merchant_uid}/${this.moduleName}/${this.methodName}`, item);\n }\n async updateOne(id: number, item: Partial<T>): Promise<T> {\n return this.http.patch(`api/v5/merchants/${this.options.merchant_uid}/${this.moduleName}/${id}`, item);\n }\n async updateMany(items: T[]): Promise<T[]> {\n return this.http.patch(`api/v5/merchants/${this.options.merchant_uid}/${this.moduleName}`, items);\n }\n async deleteOne(model: T): Promise<T> {\n model.deleted_at = new Date();\n return this.http.delete(`api/v5/merchants/${this.options.merchant_uid}/${this.moduleName}/${model.id_in_server}`);\n }\n async hardDeleteOne(model: T): Promise<T> {\n await this.db.table(this.moduleName).delete(model.uid);\n return model;\n }\n}\n\nexport interface IAppModelSequence {\n sequence: number;\n}\n","import { IAppBase, IAppCoreModel, AppCoreModel } from './abstract.type';\nimport { ModelPrefix } from './misc.type';\nimport { nanoid } from 'nanoid';\nimport { IConfig } from '../types/config.type';\nimport { IItem, ICategory } from './product.type';\n\nexport type IReportCategory = IAppBase & {\n reports : IReport[];\n}\nexport type IReport = IAppBase & {\n type : ReportType;\n codename: string;\n}\nexport enum ReportType { 'printable' , 'generative' }\nexport class ReportCategory implements IReportCategory {\n public uid = ModelPrefix.ReportCategory + + nanoid();\n name = '';\n name_translations: Record<string, string> = {};\n reports = new Array<Report>();\n created_at = new Date();\n created_at_timestamp = new Date().getTime(); \n updated_at = new Date();\n deleted_at = null;\n constructor() {}\n}\nexport class Report implements IReport {\n public uid = ModelPrefix.Report + nanoid();\n name = '';\n name_translations: Record<string, string> = {};\n type: ReportType.printable\n codename = '';\n created_at = new Date();\n created_at_timestamp = new Date().getTime();\n updated_at = new Date();\n deleted_at = null;\n constructor() {}\n}\nexport interface IAppReport extends IAppCoreModel{\n reports: IReportCategory[];\n version: number;\n}\nexport class AppReport extends AppCoreModel implements IAppReport {\n public uid = ModelPrefix.AppReport + nanoid();\n reports = new Array<ReportCategory>();\n version = 1;\n constructor() {\n super();\n }\n}\n\nexport type IReportRequest = {\n /**\n * shift uid (if shift uid is provided, start and end date time will be ignored, and the report will be generated for the shift period.)\n */\n shift_uid: string;\n /**\n * start date and time\n */\n start_datetime: Date;\n /**\n * end date and time\n */\n end_datetime: Date;\n /**\n * report code name\n */\n report_code_name: string;\n /**\n * number of copies, default is 1\n */\n copies : number;\n\n declared_amount: number;\n}\n\nexport type IReportData = {\n start_datetime: string;\n humanized_start_datetime: string;\n end_datetime: string;\n humanized_end_datetime: string;\n sales_summary: ISalesSummary;\n drawer_summary: IDrawerSummary;\n payments_summary: IPaymentSummary[];\n loyalty_program_summary: ILoyaltyProgramSummary;\n item_sales_summary: TItemSalesSummary[];\n item_sales_summary_total: number;\n item_sales_summary_total_count: number;\n // 按类别分组的销售摘要\n item_sales_summary_by_category: TCategorySalesSummary[];\n modifier_sales_summary: TModifierSalesSummary[];\n modifier_sales_summary_total: number;\n modifier_sales_summary_total_count: number;\n config: IConfig;\n}\n\nexport class ReportData implements IReportData {\n start_datetime = '';\n humanized_start_datetime = '';\n end_datetime = '';\n humanized_end_datetime = '';\n humanized_printed_datetime = '';\n sales_summary = new SalesSummary();\n drawer_summary = new DrawerSummary();\n payments_summary = new Array<PaymentSummary>();\n loyalty_program_summary = new LoyaltyProgramSummary();\n item_sales_summary = new Array<ItemSalesSummary>();\n item_sales_summary_total = 0;\n item_sales_summary_total_count = 0;\n // 按类别分组的销售摘要\n item_sales_summary_by_category = new Array<CategorySalesSummary>();\n modifier_sales_summary = new Array<ModifierSalesSummary>();\n modifier_sales_summary_total = 0;\n modifier_sales_summary_total_count = 0;\n config = {} as IConfig;\n}\n\nexport type ISalesSummary = {\n sales_total: number;\n foc_sales_total: number;\n foc_sales_count: number;\n rounding_total: number;\n tax_total: number;\n service_charge_total: number;\n discount_total: number;\n voucher_total: number;\n voucher_count: number;\n coupon_total: number;\n coupon_count: number;\n paid_invoice_count: number;\n paid_invoice_total: number;\n void_invoice_count: number;\n void_invoice_total: number;\n total_pax: number;\n pax_sales_total: number;\n}\n\nexport class SalesSummary implements ISalesSummary {\n sales_total = 0;\n foc_sales_total = 0;\n foc_sales_count = 0;\n rounding_total = 0;\n tax_total = 0;\n service_charge_total = 0;\n discount_total = 0;\n voucher_total = 0;\n voucher_count = 0;\n coupon_total = 0;\n coupon_count = 0;\n paid_invoice_count = 0;\n paid_invoice_total = 0;\n void_invoice_count = 0;\n void_invoice_total = 0;\n total_pax = 0;\n pax_sales_total = 0;\n}\n\nexport type IDrawerSummary = {\n open_amount: number;\n declared_amount: number;\n drawer_amount: number;\n difference: number;\n pay_in_total: number;\n pay_in_count: number;\n pay_out_total: number;\n pay_out_count: number;\n}\n\nexport class DrawerSummary implements IDrawerSummary {\n open_amount = 0;\n declared_amount = 0;\n drawer_amount = 0;\n difference = 0;\n pay_in_total = 0;\n pay_in_count = 0;\n cash_invoice_total = 0;\n cash_invoice_count = 0;\n pay_out_total = 0;\n pay_out_count = 0;\n\n}\n\n\nexport type IPaymentSummary = {\n code: string;\n name: string;\n total: number;\n count: number;\n}\n\nexport class PaymentSummary implements IPaymentSummary {\n code = '';\n name = '';\n total = 0;\n count = 0;\n}\n\nexport type ILoyaltyProgramSummary = {\n add_credit_total: number;\n add_credit_count: number;\n topup_paid_total: number; // actual payment amount for top-up invoices\n topup_paid_count: number;\n rewarded_credit_total: number;\n rewarded_credit_count: number;\n minus_credit_total: number;\n minus_credit_count: number;\n rewarded_point_total: number;\n rewarded_point_count: number;\n minus_point_total: number;\n minus_point_count: number;\n}\n\nexport class LoyaltyProgramSummary implements ILoyaltyProgramSummary {\n add_credit_total = 0;\n add_credit_count = 0;\n topup_paid_total = 0;\n topup_paid_count = 0;\n rewarded_credit_total = 0;\n rewarded_credit_count = 0;\n minus_credit_total = 0;\n minus_credit_count = 0;\n rewarded_point_total = 0;\n rewarded_point_count = 0;\n minus_point_total = 0;\n minus_point_count = 0;\n}\n\nexport type TItemCoreSalesSummary = {\n item: IItem;\n quantity: number;\n total_amount: number;\n}\n\nexport type TItemSalesSummary = TItemCoreSalesSummary & {\n modifiers?: TItemCoreSalesSummary[]; // 改为非递归类型\n}\n\nexport class ItemSalesSummary implements TItemSalesSummary {\n item = {} as IItem;\n quantity = 0;\n total_amount = 0;\n modifiers: TItemCoreSalesSummary[] = []; // 非递归类型\n}\n\nexport type TModifierSalesSummary = {\n item: IItem;\n quantity: number;\n total_amount: number;\n}\n\nexport class ModifierSalesSummary implements TModifierSalesSummary {\n item = {} as IItem;\n quantity = 0;\n total_amount = 0;\n}\n\n// 按类别分组的销售摘要\nexport type TCategorySalesSummary = {\n category: ICategory | null; // null 表示未分类商品\n items: TItemSalesSummary[];\n total_quantity: number;\n total_amount: number;\n}\n\nexport class CategorySalesSummary implements TCategorySalesSummary {\n category = null as ICategory | null;\n items: TItemSalesSummary[] = [];\n total_quantity = 0;\n total_amount = 0;\n}\n","import { AppRemoteService, IAppRemoteService } from '../services/abstract.service';\nimport { CustomResponse, IServiceOptions } from '../types/misc.type';\nimport { INodePrinter, IPrinter, INode, PrinterType, PrintJob } from '../types/printer.type';\nimport type { AxiosInstance } from 'axios';\nimport Dexie from 'dexie';\nimport { NetworkInterface } from '@awesome-cordova-plugins/network-interface';\nimport { EscPosPrinter, PrintCommand, PrintType } from '../libs/escpos.printer';\nimport { ConfigService, PrintJobService } from './app.service';\nimport EscPosEncoder from 'esc-pos-encoder-ionic';\n\n/**\n * Represents the Printer Service interface.\n * Extends the IAppRemoteService interface with IPrinter.\n */\nexport interface IPrinterService extends IAppRemoteService<IPrinter> {\n /**\n * Retrieves the physical printers from the node.\n * @returns A promise that resolves to an array of INodePrinter objects.\n */\n getPhysicalPrintersFromNode(): Promise<INodePrinter[]>;\n\n /**\n * Retrieves the unpaired node.\n * @returns A promise that resolves to an array of INode objects.\n */\n getUnpairedNode(): Promise<CustomResponse<INode>>;\n\n /**\n * Pairs the node.\n * @param nodeUid The node UID.\n * @returns A promise that resolves to an array of INode objects.\n */\n pairNode(nodeUid: string): Promise<CustomResponse<INode>>;\n\n /**\n * Retrieves the default kiosk printer.\n * @returns A promise that resolves to an IPrinter object.\n */\n getDefaultKioskPrinter(): Promise<IPrinter>;\n\n /**\n * Retrieves the default receipt printer.\n * @returns A promise that resolves to an IPrinter object.\n */\n getDefaultReceiptPrinter(): Promise<IPrinter>;\n\n /**\n * Retrieves the default printer by type.\n * @param type The type of printer.\n * @returns A promise that resolves to an IPrinter object.\n */\n getDefaultPrinterByType(type: PrinterType): Promise<IPrinter>;\n\n /**\n * Searches for available printers on the network with the specified IP address and port number.\n * @param wifiName The name of the wifi the device is connected to\n * @param port The port number of the network. Default is 9100.\n * @param refresh A boolean value indicating whether to refresh the cache. Default is false.\n * @returns A promise that resolves to an array of printer names found on the network.\n */\n searchPrinters(refresh?: boolean, port?: number): Promise<string[]>;\n\n /**\n * Opens the cash drawer.\n */\n openCashDrawer(): Promise<void>;\n\n}\n\nexport class PrinterService extends AppRemoteService<IPrinter> implements IPrinterService {\n private configService: ConfigService;\n protected printJobService: PrintJobService;\n private printersFromCache: string [];\n constructor(readonly http: AxiosInstance, readonly db: Dexie, readonly options: IServiceOptions, readonly moduleName = 'printers', readonly methodName = 'printer') {\n super();\n this.configService = new ConfigService(http, db, options, 'configs', 'config');\n this.printJobService = new PrintJobService(http, db, options, 'print_jobs', 'print_job');\n this.init().catch(error => console.error(error));\n }\n\n private async init() {\n if (!this.printersFromCache) {\n const appConfig = await this.configService.getDefaultOne();\n this.printersFromCache = appConfig?.cache?.printers ?? [];\n }\n }\n\n async getPhysicalPrintersFromNode(): Promise<INodePrinter[]> {\n const res: CustomResponse<INodePrinter[]> = await this.http.get(`api/v5/merchants/` + this.options.merchant_uid + `/` + this.moduleName + `/get_physical_printers`);\n return res.data;\n }\n\n async getUnpairedNode(): Promise<CustomResponse<INode>> {\n return this.http.get(`api/v5/merchants/` + this.options.merchant_uid + `/node`);\n }\n\n async pairNode(nodeUid: string): Promise<CustomResponse<INode>> {\n return this.http.get(`api/v5/merchants/` + this.options.merchant_uid + `/nodes/${nodeUid}` + `/pair-node`);\n }\n\n private async getDefaultPrinter(type: PrinterType): Promise<IPrinter> {\n const printers = await this.db.table('printers').filter(p => p.type === type && p.deleted_at == null).toArray();\n return printers.find(p => !p.is_not_default) || printers[0] || null;\n }\n\n public async getDefaultReceiptPrinter(): Promise<IPrinter> {\n return this.getDefaultPrinter(PrinterType.ReceiptPrinter);\n }\n\n public async getDefaultPrinterByType(type: PrinterType): Promise<IPrinter> {\n return this.getDefaultPrinter(type);\n }\n\n public async getDefaultKioskPrinter(): Promise<IPrinter> {\n return this.getDefaultPrinter(PrinterType.KioskPrinter);\n }\n\n public async getDefaultCheckPrinter(): Promise<IPrinter> {\n return this.getDefaultPrinter(PrinterType.CheckPrinter);\n }\n\n public async getDefaultKitchenPrinter(): Promise<IPrinter> {\n return this.getDefaultPrinter(PrinterType.KitchenPrinter);\n }\n\n public async getDefaultOrderPrinter(): Promise<IPrinter> {\n return this.getDefaultPrinter(PrinterType.OrderPrinter);\n }\n\n public async getPrintersByUids(uids: string []): Promise<IPrinter[]> {\n return this.db.table('printers').where('uid').anyOf(uids).filter(printer => printer.deleted_at == null).toArray();\n\n }\n\n public async searchPrinters(refresh = false, port = 9100): Promise<string[]> {\n\n if(this.printersFromCache && !refresh) return this.printersFromCache;\n\n const printers = [];\n const ipAddress: NetworkInfo = await NetworkInterface.getWiFiIPAddress();\n console.log('ipAddress', ipAddress);\n const subnetParts = ipAddress.subnet.split('.').map(Number);\n const ipParts = ipAddress.ip.split('.').map(Number);\n ipParts[3] = 0; // Reset the last octet to start from the beginning of the subnet\n const hosts = subnetParts.reduce((acc, part, i) => acc + (part ^ 255) * Math.pow(256, 3 - i), 0);\n for (let i = 1; i < hosts; i++) {\n // Changed <= to <\n const ipPartsCopy = [...ipParts];\n let j = 3;\n let host = i;\n\n while (host > 0) {\n const increment = host % 256;\n host = Math.floor(host / 256);\n ipPartsCopy[j] += increment;\n while (ipPartsCopy[j] > 254 && j > 0) {\n // Changed 255 to 254\n ipPartsCopy[j] -= 256;\n ipPartsCopy[--j]++;\n }\n }\n\n const ip = ipPartsCopy.join('.');\n console.log('ip', ip);\n const escPrinter = new EscPosPrinter();\n const printer = await escPrinter.connect(ip, port, 200);\n\n if (printer) {\n printers.push(ip);\n }\n }\n \n await this.configService.updateCache({printers: printers});\n return printers;\n }\n\n public async openCashDrawer(): Promise<void> {\n const receiptPrinter = await this.getDefaultReceiptPrinter();\n const printCommand = new PrintCommand();\n printCommand.items.push({\n type: PrintType.OpenCashDrawer\n });\n const printJob = new PrintJob(receiptPrinter, printCommand, false, 1);\n await this.printJobService.addOne(printJob);\n }\n}\n\n// export interface IPrinterManager {\n// /**\n// * Searches for available printers on the network with the specified IP address and port number.\n// * @param ip The IP address of the network.\n// * @param port The port number of the network. Default is 9100.\n// * @returns A promise that resolves to an array of printer names found on the network.\n// */\n// searchPrinters(port?: number): Promise<string[]>;\n// }\n\ntype NetworkInfo = {\n ip: string;\n subnet: string;\n};\n\n\n\n// export class PrinterManager implements IPrinterManager {\n// public async searchPrinters(port = 9100): Promise<string[]> {\n// const printers = [];\n// const ipAddress: NetworkInfo = await NetworkInterface.getWiFiIPAddress();\n// console.log('ipAddress', ipAddress);\n// const subnetParts = ipAddress.subnet.split('.').map(Number);\n// const ipParts = ipAddress.ip.split('.').map(Number);\n// ipParts[3] = 0; // Reset the last octet to start from the beginning of the subnet\n// const hosts = subnetParts.reduce((acc, part, i) => acc + (part ^ 255) * Math.pow(256, 3 - i), 0);\n// for (let i = 1; i < hosts; i++) {\n// // Changed <= to <\n// const ipPartsCopy = [...ipParts];\n// let j = 3;\n// let host = i;\n\n// while (host > 0) {\n// const increment = host % 256;\n// host = Math.floor(host / 256);\n// ipPartsCopy[j] += increment;\n// while (ipPartsCopy[j] > 254 && j > 0) {\n// // Changed 255 to 254\n// ipPartsCopy[j] -= 256;\n// ipPartsCopy[--j]++;\n// }\n// }\n\n// const ip = ipPartsCopy.join('.');\n// console.log('ip', ip);\n// const escPrinter = new EscPosPrinter();\n// const printer = await escPrinter.connect(ip, port, 200);\n\n// if (printer) {\n// printers.push(ip);\n// }\n// }\n// return printers;\n// }\n// }\n","// import * as accounting from 'accounting-js';\n\n// export function round(input: any, n: number): number {\n// if (typeof input !== 'number') {\n// console.warn('Input is not a number, returning 0');\n// return 0;\n// }\n\n// try {\n\n// const result = accounting.toFixed(input, n);\n// return result;\n// } catch (err) {\n// console.error(err);\n// return 0;\n// }\n// }\n\nexport function preciseRound(num, decimalPlaces = 2): number {\n const factor = Math.pow(10, decimalPlaces);\n return Math.round(num * factor) / factor;\n}\n\nexport function getFileExtension(file: File): string {\n const fileName: string = file.name;\n const dotIndex: number = fileName.lastIndexOf('.');\n // Check if dotIndex is -1 or is the last character (no extension)\n if (dotIndex === -1 || dotIndex === fileName.length - 1) {\n return '';\n }\n return fileName.slice(dotIndex + 1);\n}\n\nexport function convertFileToBase64(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onloadend = () => {\n if (typeof reader.result === 'string') {\n resolve(reader.result.split(',')[1]); // extract only Base64 string part\n } else {\n reject(new Error('Could not convert file to Base64.'));\n }\n };\n reader.onerror = () => reject(new Error('File reading failed.'));\n reader.readAsDataURL(file);\n });\n}\n","/**\n * String Helpers for Handlebars\n * Browser-compatible string manipulation utilities\n */\n\nexport interface StringHelpers {\n // Case Conversion\n camelcase: (str: string) => string;\n capitalize: (str: string) => string;\n capitalizeAll: (str: string) => string;\n dashcase: (str: string) => string;\n dotcase: (str: string) => string;\n downcase: (str: string) => string;\n lowercase: (str: string) => string;\n pascalcase: (str: string) => string;\n pathcase: (str: string) => string;\n sentence: (str: string) => string;\n snakecase: (str: string) => string;\n titleize: (str: string) => string;\n upcase: (str: string) => string;\n uppercase: (str: string) => string;\n \n // String Manipulation\n append: (str: string, suffix: string) => string;\n center: (str: string, spaces: number) => string;\n chop: (str: string) => string;\n hyphenate: (str: string) => string;\n plusify: (str: string, ch?: string) => string;\n prepend: (str: string, prefix: string) => string;\n remove: (str: string, substring: string) => string;\n removeFirst: (str: string, substring: string) => string;\n replace: (str: string, a: string, b: string) => string;\n replaceFirst: (str: string, a: string, b: string) => string;\n reverse: (str: string) => string;\n split: (str: string, ch?: string) => string[];\n \n // Trimming & Truncation\n ellipsis: (str: string, limit: number) => string;\n trim: (str: string) => string;\n trimLeft: (str: string) => string;\n trimRight: (str: string) => string;\n truncate: (str: string, limit: number, suffix?: string) => string;\n truncateWords: (str: string, count: number, suffix?: string) => string;\n \n // Utilities\n isString: (value: any) => boolean;\n occurrences: (str: string, substring: string) => number;\n }\n \n // Helper function for case conversion\n const changecase = (str: string, fn: (ch: string) => string): string => {\n return str\n .replace(/([a-z])([A-Z])/g, '$1 $2')\n .replace(/[_\\-\\.]+/g, ' ')\n .toLowerCase()\n .replace(/[\\s]+(\\w)/g, (match, ch) => fn(ch));\n };\n \n // Helper function for chop\n const chopString = (str: string): string => {\n return str.replace(/^\\W+|\\W+$/g, '');\n };\n \n /**\n * camelCase the characters in the given string\n */\n export const camelcase = (str: string): string => {\n if (typeof str !== 'string') return '';\n return changecase(str, (ch) => ch.toUpperCase());\n };\n \n /**\n * Capitalize the first word in a sentence\n */\n export const capitalize = (str: string): string => {\n if (typeof str !== 'string') return '';\n return str.charAt(0).toUpperCase() + str.slice(1);\n };\n \n /**\n * Capitalize all words in a string\n */\n export const capitalizeAll = (str: string): string => {\n if (typeof str !== 'string') return '';\n return str.replace(/\\w\\S*/g, (word) => capitalize(word));\n };\n \n /**\n * dash-case the characters in string\n */\n export const dashcase = (str: string): string => {\n if (typeof str !== 'string') return '';\n return changecase(str, (ch) => '-' + ch);\n };\n \n /**\n * dot.case the characters in string\n */\n export const dotcase = (str: string): string => {\n if (typeof str !== 'string') return '';\n return changecase(str, (ch) => '.' + ch);\n };\n \n /**\n * Lowercase all characters (alias for lowercase)\n */\n export const downcase = (str: string): string => {\n return lowercase(str);\n };\n \n /**\n * Lowercase all characters in the given string\n */\n export const lowercase = (str: string): string => {\n if (typeof str !== 'string') return '';\n return str.toLowerCase();\n };\n \n /**\n * PascalCase the characters in string\n */\n export const pascalcase = (str: string): string => {\n if (typeof str !== 'string') return '';\n const camelCased = changecase(str, (ch) => ch.toUpperCase());\n return camelCased.charAt(0).toUpperCase() + camelCased.slice(1);\n };\n \n /**\n * path/case the characters in string\n */\n export const pathcase = (str: string): string => {\n if (typeof str !== 'string') return '';\n return changecase(str, (ch) => '/' + ch);\n };\n \n /**\n * Sentence case the given string\n */\n export const sentence = (str: string): string => {\n if (typeof str !== 'string') return '';\n return str.replace(/((?:\\S[^\\.\\?\\!]*)[\\.\\?\\!]*)/g, (txt) => {\n return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();\n });\n };\n \n /**\n * snake_case the characters in the given string\n */\n export const snakecase = (str: string): string => {\n if (typeof str !== 'string') return '';\n return changecase(str, (ch) => '_' + ch);\n };\n \n /**\n * Title case the given string\n */\n export const titleize = (str: string): string => {\n if (typeof str !== 'string') return '';\n const title = str.replace(/[- _]+/g, ' ');\n const words = title.split(' ');\n return words.map((word) => capitalize(word)).join(' ');\n };\n \n /**\n * Uppercase all characters (alias for uppercase)\n */\n export const upcase = (str: string): string => {\n return uppercase(str);\n };\n \n /**\n * Uppercase all of the characters in the given string\n */\n export const uppercase = (str: string): string => {\n if (typeof str !== 'string') return '';\n return str.toUpperCase();\n };\n \n /**\n * Append the specified suffix to the given string\n */\n export const append = (str: string, suffix: string): string => {\n if (typeof str === 'string' && typeof suffix === 'string') {\n return str + suffix;\n }\n return str;\n };\n \n /**\n * Center a string using non-breaking spaces\n */\n export const center = (str: string, spaces: number): string => {\n if (typeof str !== 'string') return '';\n let space = '';\n for (let i = 0; i < spaces; i++) {\n space += '&nbsp;';\n }\n return space + str + space;\n };\n \n /**\n * Remove whitespace and non-word characters from beginning and end\n */\n export const chop = (str: string): string => {\n if (typeof str !== 'string') return '';\n return chopString(str);\n };\n \n /**\n * Replace spaces in a string with hyphens\n */\n export const hyphenate = (str: string): string => {\n if (typeof str !== 'string') return '';\n return str.split(' ').join('-');\n };\n \n /**\n * Replace spaces (or custom character) with pluses\n */\n export const plusify = (str: string, ch: string = ' '): string => {\n if (typeof str !== 'string') return '';\n if (typeof ch !== 'string') ch = ' ';\n return str.split(ch).join('+');\n };\n \n /**\n * Prepend the given string with the specified prefix\n */\n export const prepend = (str: string, prefix: string): string => {\n return typeof str === 'string' && typeof prefix === 'string'\n ? prefix + str\n : str;\n };\n \n /**\n * Remove all occurrences of substring from the given string\n */\n export const remove = (str: string, substring: string): string => {\n if (typeof str !== 'string') return '';\n if (typeof substring !== 'string') return str;\n return str.split(substring).join('');\n };\n \n /**\n * Remove the first occurrence of substring from the given string\n */\n export const removeFirst = (str: string, substring: string): string => {\n if (typeof str !== 'string') return '';\n if (typeof substring !== 'string') return str;\n return str.replace(substring, '');\n };\n \n /**\n * Replace all occurrences of substring a with substring b\n */\n export const replace = (str: string, a: string, b: string): string => {\n if (typeof str !== 'string') return '';\n if (typeof a !== 'string') return str;\n if (typeof b !== 'string') b = '';\n return str.split(a).join(b);\n };\n \n /**\n * Replace the first occurrence of substring a with substring b\n */\n export const replaceFirst = (str: string, a: string, b: string): string => {\n if (typeof str !== 'string') return '';\n if (typeof a !== 'string') return str;\n if (typeof b !== 'string') b = '';\n return str.replace(a, b);\n };\n \n /**\n * Reverse a string\n */\n export const reverse = (str: string): string => {\n if (typeof str !== 'string') return '';\n return str.split('').reverse().join('');\n };\n \n /**\n * Split string by the given character\n */\n export const split = (str: string, ch: string = ','): string[] => {\n if (typeof str !== 'string') return [];\n if (typeof ch !== 'string') ch = ',';\n return str.split(ch);\n };\n \n /**\n * Truncate string and append ellipsis\n */\n export const ellipsis = (str: string, limit: number): string => {\n if (typeof str === 'string') {\n if (str.length <= limit) {\n return str;\n }\n return truncate(str, limit) + '…';\n }\n return '';\n };\n \n /**\n * Remove extraneous whitespace from beginning and end\n */\n export const trim = (str: string): string => {\n return typeof str === 'string' ? str.trim() : '';\n };\n \n /**\n * Remove extraneous whitespace from the beginning\n */\n export const trimLeft = (str: string): string => {\n if (typeof str === 'string') {\n return str.replace(/^\\s+/, '');\n }\n return '';\n };\n \n /**\n * Remove extraneous whitespace from the end\n */\n export const trimRight = (str: string): string => {\n if (typeof str === 'string') {\n return str.replace(/\\s+$/, '');\n }\n return '';\n };\n \n /**\n * Truncate a string to the specified length\n */\n export const truncate = (str: string, limit: number, suffix: string = ''): string => {\n if (typeof str === 'string') {\n if (typeof suffix !== 'string') {\n suffix = '';\n }\n if (str.length > limit) {\n return str.slice(0, limit - suffix.length) + suffix;\n }\n return str;\n }\n return '';\n };\n \n /**\n * Truncate a string to have the specified number of words\n */\n export const truncateWords = (str: string, count: number, suffix: string = '…'): string => {\n if (typeof str === 'string' && typeof count === 'number') {\n if (typeof suffix !== 'string') {\n suffix = '…';\n }\n \n const arr = str.split(/[ \\t]/);\n const limitedArr = count > arr.length ? arr : arr.slice(0, count);\n const val = limitedArr.join(' ').trim();\n return val + suffix;\n }\n return '';\n };\n \n /**\n * Check if value is a string\n */\n export const isString = (value: any): value is string => {\n return typeof value === 'string';\n };\n \n /**\n * Return the number of occurrences of substring within the given string\n */\n export const occurrences = (str: string, substring: string): number => {\n if (typeof str !== 'string') return 0;\n const len = substring.length;\n let pos = 0;\n let n = 0;\n \n while ((pos = str.indexOf(substring, pos)) > -1) {\n n++;\n pos += len;\n }\n return n;\n };\n \n /**\n * Export all helpers as a single object\n */\n export const stringHelpers: StringHelpers = {\n // Case Conversion\n camelcase,\n capitalize,\n capitalizeAll,\n dashcase,\n dotcase,\n downcase,\n lowercase,\n pascalcase,\n pathcase,\n sentence,\n snakecase,\n titleize,\n upcase,\n uppercase,\n \n // String Manipulation\n append,\n center,\n chop,\n hyphenate,\n plusify,\n prepend,\n remove,\n removeFirst,\n replace,\n replaceFirst,\n reverse,\n split,\n \n // Trimming & Truncation\n ellipsis,\n trim,\n trimLeft,\n trimRight,\n truncate,\n truncateWords,\n \n // Utilities\n isString,\n occurrences,\n };\n \n /**\n * Default export\n */\n export default stringHelpers;\n ","/**\n * Comparison Helpers for Handlebars\n * Browser-compatible comparison and logical utilities\n */\n\n// Check if value is a Handlebars options object\nconst isOptions = (val: any): boolean => val && typeof val === 'object' && typeof val.fn === 'function';\n\n// Get the result value for block/inline helpers\nconst getValue = (val: boolean, context: any, options: any): any => {\n if (isOptions(options)) {\n if (val) return options.fn ? options.fn(context) : true;\n return options.inverse ? options.inverse(context) : false;\n }\n return val;\n};\n\n/**\n * Block helper that renders if ALL given values are truthy\n * {{#and a b c}}...{{else}}...{{/and}}\n */\nexport const and = function(this: any, ...args: any[]): any {\n const options = args.pop();\n const val = args.every(arg => !!arg);\n return getValue(val, this, options);\n};\n\n/**\n * Block helper that renders if ANY given value is truthy\n * {{#or a b c}}...{{else}}...{{/or}}\n */\nexport const or = function(this: any, ...args: any[]): any {\n const options = args.pop();\n const val = args.some(arg => !!arg);\n return getValue(val, this, options);\n};\n\n/**\n * Returns true if value is falsey\n * {{#not val}}...{{/not}}\n */\nexport const not = function(this: any, val: any, options: any): any {\n return getValue(!val, this, options);\n};\n\n/**\n * Block helper that renders if a === b (strict equality)\n * {{#eq a b}}...{{else}}...{{/eq}}\n */\nexport const eq = function(this: any, a: any, b: any, options: any): any {\n if (arguments.length === 2) {\n options = b;\n b = options?.hash?.compare;\n }\n return getValue(a === b, this, options);\n};\n\n/**\n * Block helper that renders if a == b (loose equality)\n * {{#is a b}}...{{else}}...{{/is}}\n */\nexport const is = function(this: any, a: any, b: any, options: any): any {\n if (arguments.length === 2) {\n options = b;\n b = options?.hash?.compare;\n }\n return getValue(a == b, this, options);\n};\n\n/**\n * Block helper that renders if a !== b\n * {{#neq a b}}...{{else}}...{{/neq}}\n */\nexport const neq = function(this: any, a: any, b: any, options: any): any {\n if (arguments.length === 2) {\n options = b;\n b = options?.hash?.compare;\n }\n return getValue(a !== b, this, options);\n};\n\n/**\n * Block helper that renders if a != b (loose inequality)\n * {{#isnt a b}}...{{else}}...{{/isnt}}\n */\nexport const isnt = function(this: any, a: any, b: any, options: any): any {\n if (arguments.length === 2) {\n options = b;\n b = options?.hash?.compare;\n }\n return getValue(a != b, this, options);\n};\n\n/**\n * Block helper that renders if a > b\n * {{#gt a b}}...{{else}}...{{/gt}}\n */\nexport const gt = function(this: any, a: any, b: any, options: any): any {\n if (arguments.length === 2) {\n options = b;\n b = options?.hash?.compare;\n }\n return getValue(a > b, this, options);\n};\n\n/**\n * Block helper that renders if a >= b\n * {{#gte a b}}...{{else}}...{{/gte}}\n */\nexport const gte = function(this: any, a: any, b: any, options: any): any {\n if (arguments.length === 2) {\n options = b;\n b = options?.hash?.compare;\n }\n return getValue(a >= b, this, options);\n};\n\n/**\n * Block helper that renders if a < b\n * {{#lt a b}}...{{else}}...{{/lt}}\n */\nexport const lt = function(this: any, a: any, b: any, options: any): any {\n if (arguments.length === 2) {\n options = b;\n b = options?.hash?.compare;\n }\n return getValue(a < b, this, options);\n};\n\n/**\n * Block helper that renders if a <= b\n * {{#lte a b}}...{{else}}...{{/lte}}\n */\nexport const lte = function(this: any, a: any, b: any, options: any): any {\n if (arguments.length === 2) {\n options = b;\n b = options?.hash?.compare;\n }\n return getValue(a <= b, this, options);\n};\n\n/**\n * Generic compare helper with operator\n * {{#compare a \"===\" b}}...{{/compare}}\n */\nexport const compare = function(this: any, a: any, operator: string, b: any, options: any): any {\n if (arguments.length < 4) throw new Error('Helper {{compare}} expects 4 arguments');\n let result: boolean;\n switch (operator) {\n case '==': result = a == b; break;\n case '===': result = a === b; break;\n case '!=': result = a != b; break;\n case '!==': result = a !== b; break;\n case '<': result = a < b; break;\n case '>': result = a > b; break;\n case '<=': result = a <= b; break;\n case '>=': result = a >= b; break;\n case 'typeof': result = typeof a === b; break;\n default: throw new Error(`Helper {{compare}}: invalid operator: \\`${operator}\\``);\n }\n return getValue(result, this, options);\n};\n\n/**\n * Block helper that renders if collection contains value\n * {{#contains array \"value\"}}...{{else}}...{{/contains}}\n */\nexport const contains = function(this: any, collection: any, value: any, options: any): any {\n if (typeof options === 'number') options = arguments[3]; // handle startIndex\n if (collection == null) return getValue(false, this, options);\n if (Array.isArray(collection)) return getValue(collection.includes(value), this, options);\n if (typeof collection === 'string') return getValue(collection.includes(value), this, options);\n if (typeof collection === 'object') return getValue(value in collection, this, options);\n return getValue(false, this, options);\n};\n\n// Alias for contains\nexport const includes = contains;\n\n/**\n * Block helper that renders if value is in the list\n * {{#in value \"a\" \"b\" \"c\"}}...{{else}}...{{/in}}\n */\nexport const inArray = function(this: any, value: any, ...args: any[]): any {\n const options = args.pop();\n const val = args.includes(value);\n return getValue(val, this, options);\n};\n\n// Get nested property value by path like \"item.name\" or \"item.category_uid\"\nconst getByPath = (obj: any, path: string): any => {\n if (!obj || !path) return undefined;\n return path.split('.').reduce((o, k) => o?.[k], obj);\n};\n\n// Parse prop-value pairs from args: [\"prop1\", val1, \"prop2\", val2, ...] => [{prop, value}, ...]\nconst parseConditions = (args: any[]): Array<{prop: string, value: any}> => {\n const conditions: Array<{prop: string, value: any}> = [];\n for (let i = 0; i < args.length - 1; i += 2) {\n if (typeof args[i] === 'string' && !isOptions(args[i + 1])) {\n conditions.push({ prop: args[i], value: args[i + 1] });\n }\n }\n return conditions;\n};\n\n/**\n * Find first object matching ALL conditions (AND logic)\n * {{findAnd categories \"name\" \"Topping\" \"active\" true}}\n */\nexport const findAnd = function(collection: any[], ...args: any[]): any {\n if (!Array.isArray(collection)) return null;\n const conditions = parseConditions(args);\n return collection.find(item => conditions.every(c => getByPath(item, c.prop) === c.value)) || null;\n};\n\n/**\n * Find first object matching ANY condition (OR logic)\n * {{findOr categories \"name\" \"Topping\" \"name\" \"Topping one\"}}\n */\nexport const findOr = function(collection: any[], ...args: any[]): any {\n if (!Array.isArray(collection)) return null;\n const conditions = parseConditions(args);\n return collection.find(item => conditions.some(c => getByPath(item, c.prop) === c.value)) || null;\n};\n\n/**\n * Filter array matching ALL conditions (AND logic)\n * {{filterAnd modifiers \"item.category_uid\" \"imc_xxx\" \"price\" 0}}\n */\nexport const filterAnd = function(collection: any[], ...args: any[]): any[] {\n if (!Array.isArray(collection)) return [];\n const conditions = parseConditions(args);\n return collection.filter(item => conditions.every(c => getByPath(item, c.prop) === c.value));\n};\n\n/**\n * Filter array matching ANY condition (OR logic)\n * {{filterOr modifiers \"name\" \"Topping\" \"name\" \"Topping one\"}}\n */\nexport const filterOr = function(collection: any[], ...args: any[]): any[] {\n if (!Array.isArray(collection)) return [];\n const conditions = parseConditions(args);\n return collection.filter(item => conditions.some(c => getByPath(item, c.prop) === c.value));\n};\n\n/**\n * Returns the first truthy value, or default\n * {{default value \"fallback\"}}\n */\nexport const defaultValue = function(...args: any[]): any {\n for (let i = 0; i < args.length - 1; i++) {\n if (args[i] != null) return args[i];\n }\n return '';\n};\n\n/**\n * Block helper that renders if neither a nor b is truthy\n * {{#neither a b}}...{{else}}...{{/neither}}\n */\nexport const neither = function(this: any, a: any, b: any, options: any): any {\n return getValue(!a && !b, this, options);\n};\n\n/**\n * Block helper that renders if value is even\n * {{#ifEven value}}...{{else}}...{{/ifEven}}\n */\nexport const ifEven = function(this: any, num: number, options: any): any {\n return getValue(num % 2 === 0, this, options);\n};\n\n/**\n * Block helper that renders if value is odd\n * {{#ifOdd value}}...{{else}}...{{/ifOdd}}\n */\nexport const ifOdd = function(this: any, num: number, options: any): any {\n return getValue(num % 2 !== 0, this, options);\n};\n\n/**\n * Block helper that renders if b is divisible by a\n * {{#ifNth 3 value}}...{{else}}...{{/ifNth}}\n */\nexport const ifNth = function(this: any, a: number, b: number, options: any): any {\n const isNth = typeof a === 'number' && typeof b === 'number' && b % a === 0;\n return getValue(isNth, this, options);\n};\n\nexport interface ComparisonHelpers {\n and: typeof and;\n or: typeof or;\n not: typeof not;\n eq: typeof eq;\n is: typeof is;\n neq: typeof neq;\n isnt: typeof isnt;\n gt: typeof gt;\n gte: typeof gte;\n lt: typeof lt;\n lte: typeof lte;\n compare: typeof compare;\n contains: typeof contains;\n includes: typeof includes;\n in: typeof inArray;\n findAnd: typeof findAnd;\n findOr: typeof findOr;\n filterAnd: typeof filterAnd;\n filterOr: typeof filterOr;\n default: typeof defaultValue;\n neither: typeof neither;\n ifEven: typeof ifEven;\n ifOdd: typeof ifOdd;\n ifNth: typeof ifNth;\n}\n\nexport const comparisonHelpers: ComparisonHelpers = {\n and,\n or,\n not,\n eq,\n is,\n neq,\n isnt,\n gt,\n gte,\n lt,\n lte,\n compare,\n contains,\n includes,\n in: inArray,\n findAnd,\n findOr,\n filterAnd,\n filterOr,\n default: defaultValue,\n neither,\n ifEven,\n ifOdd,\n ifNth,\n};\n\nexport default comparisonHelpers;\n","/**\n * Helpers Registration - Following handlebars-helpers API pattern\n *\n * This module follows the same API as the original handlebars-helpers library:\n * helpers({ handlebars: Handlebars })\n */\n\nimport stringHelpers from './string.helpers';\nimport comparisonHelpers from './comparison.helpers';\n\ninterface HelperOptions {\n handlebars?: any;\n hbs?: any;\n}\n\n/**\n * Register all helpers with Handlebars\n *\n * @param options - Options object with handlebars instance\n * @returns The registered helpers object\n *\n * @example\n * ```typescript\n * import Handlebars from 'handlebars';\n * import helpers from './helpers.register';\n *\n * // Register all helpers\n * helpers({ handlebars: Handlebars });\n *\n * const template = Handlebars.compile('{{camelcase \"foo bar baz\"}}');\n * console.log(template({})); // 'fooBarBaz'\n *\n * const template2 = Handlebars.compile('{{#eq a b}}equal{{else}}not equal{{/eq}}');\n * console.log(template2({ a: 1, b: 1 })); // 'equal'\n * ```\n */\nfunction helpers(options?: HelperOptions) {\n const hbs = options?.handlebars || options?.hbs || require('handlebars');\n // Register string helpers\n Object.keys(stringHelpers).forEach((name) => {\n hbs.registerHelper(name, stringHelpers[name as keyof typeof stringHelpers]);\n });\n // Register comparison helpers\n Object.keys(comparisonHelpers).forEach((name) => {\n hbs.registerHelper(name, comparisonHelpers[name as keyof typeof comparisonHelpers]);\n });\n return hbs.helpers;\n}\n\n/**\n * Export default following the original API pattern\n */\nexport default helpers;\n","import { nanoid } from \"nanoid\";\nimport { AppCoreModel, IAppCoreModel } from \"./abstract.type\";\nimport { ModelPrefix } from \"./misc.type\";\n\nexport interface IOrderDisplay extends IAppCoreModel {\n order_number: string;\n status: OrderDisplayStatus;\n}\n\n\nexport class OrderDisplay extends AppCoreModel implements IOrderDisplay {\n public uid = ModelPrefix.OrderDisplaySystem + nanoid();\n order_number = '';\n status = OrderDisplayStatus.Preparing;\n constructor() {\n super();\n }\n}\n\nexport enum OrderDisplayStatus {\n Preparing = 'preparing',\n ReadyForPickup = 'ready_for_pickup'\n }\n","import type { AxiosInstance } from \"axios\";\nimport { IOrderDisplay, OrderDisplay, OrderDisplayStatus } from '../types/ods.type';\nimport { AppRemoteService, IAppRemoteService } from \"./abstract.service\";\nimport { Dexie } from \"dexie\";\nimport { IServiceOptions, SystemError } from \"../types/misc.type\";\n\n/**\n * Represents the interface for the Order Display Service.\n * Extends the IAppRemoteService interface with the IOrderDisplay type.\n */\nexport interface IOrderDisplayService extends IAppRemoteService<IOrderDisplay> {\n \n\n /**\n * Changes the status of the order to ready for pickup\n * @param uid The uid of the order\n * @returns The updated order\n */\n toPickUp(uid: string): Promise<IOrderDisplay>;\n /**\n * Changes the status of the order to preparing\n * @param uid The uid of the order\n */\n toPreparing(uid: string): Promise<IOrderDisplay>;\n /**\n * Undoes the last order that was marked as ready for pickup\n */\n undo(): Promise<IOrderDisplay>;\n}\n\nexport class OrderDisplayService extends AppRemoteService<IOrderDisplay> implements IOrderDisplayService {\n constructor(readonly http: AxiosInstance, readonly db: Dexie, readonly options: IServiceOptions, readonly moduleName = 'order_displays', readonly methodName = 'order_display') {\n super();\n }\n\n\n public async toPickUp(uid: string) : Promise<IOrderDisplay> {\n const orderDisplay = await this.getOne(uid);\n if(!orderDisplay) throw new SystemError('Display order not found');\n if(orderDisplay.status == 'ready_for_pickup') throw new SystemError('Order is already ready for pickup');\n orderDisplay.status = OrderDisplayStatus.ReadyForPickup;\n orderDisplay.updated_at = new Date();\n if(orderDisplay.id_in_server == 0) throw new SystemError('Order is not synced with server');\n await this.updateOne(orderDisplay.id_in_server, orderDisplay);\n return orderDisplay;\n }\n\n public async toPreparing(uid: string) : Promise<IOrderDisplay> {\n const orderDisplay = await this.getOne(uid);\n if(!orderDisplay) throw new SystemError('Display order not found');\n if(orderDisplay.status == 'preparing') throw new SystemError('Order is already preparing');\n orderDisplay.status = OrderDisplayStatus.Preparing;\n orderDisplay.updated_at = new Date();\n if(orderDisplay.id_in_server == 0) throw new SystemError('Order is not synced with server');\n await this.updateOne(orderDisplay.id_in_server, orderDisplay);\n return orderDisplay;\n }\n\n public async undo(): Promise<IOrderDisplay> {\n const orderDisplays = await this.db\n .table(this.moduleName)\n .filter(x=> x.status == OrderDisplayStatus.ReadyForPickup)\n .reverse()\n .limit(100).toArray();\n\n if (orderDisplays.length === 0) throw new SystemError('No order to undo');\n\n orderDisplays.sort((a, b) => {\n const dateA = new Date(a.updated_at).getTime();\n const dateB = new Date(b.updated_at).getTime();\n return dateB - dateA;\n });\n\n const latestOrderDisplay = orderDisplays[0];\n latestOrderDisplay.status = OrderDisplayStatus.Preparing;\n latestOrderDisplay.updated_at = new Date();\n if(latestOrderDisplay.id_in_server == 0) throw new SystemError('Order is not synced with server');\n await this.updateOne(latestOrderDisplay.id_in_server, latestOrderDisplay);\n return latestOrderDisplay;\n \n }\n\n\n}","import { IAppRemoteService, AppRemoteService } from './abstract.service';\nimport {\n CalcFlow,\n CalcType,\n IInvoice,\n IInvoiceLine,\n TaxMethod,\n InvoiceLine,\n IInvoiceCoreLine,\n InvoiceType,\n InvoiceDiscount,\n CreateInvoiceOptions,\n InvoiceStatus,\n CancelInvoiceOptions,\n CheckInvoiceOptions,\n DirectPayInvoiceOptions,\n InvoiceCoreLine,\n InvoiceCharge,\n} from '../types/invoice.type';\nimport { IAppConfig } from '../types/config.type';\nimport * as _ from 'lodash';\nimport { ICoreItem, IItem, ProductType, StockChange, TStockChange } from '../types/product.type';\nimport { ICustomer } from '../types/wyo.customer.type';\nimport { SystemError, ModelPrefix, CustomResponse, ErrorMsgs, IServiceOptions } from '../types/misc.type';\n\nimport { nanoid } from 'nanoid';\nimport { ISectionItem, SectionItemStatus } from '../types/section.type';\nimport { SectionItemService, TillService, ITillService, ISectionItemService, ConfigService, PrintTemplateService, PrintJobService, ItemService, IItemService } from './app.service';\nimport type { AxiosInstance } from 'axios';\nimport { Dexie } from 'dexie';\nimport { SwitchInvoiceOptions, PayInvoiceOptions, VoidInvoiceOptions, UpdateInvoiceOptions } from '../types/invoice.type';\nimport { ITill } from '../types/shift.type';\nimport { IChangePaymentMethodOption, IPaymentMethodHistory } from '../types/payment.type';\nimport { PrinterService } from './printer.service';\nimport { IPrintJob, IPrinter, PrintJob, PrintJobStatus, PrinterConnections, PrinterType, RenderPrintTemplateOptions } from '../types/printer.type';\nimport { IEmployee } from '../types/employee.type';\nimport { humanizedData } from '../utils/misc.utils';\nimport { preciseRound } from './misc.service';\nimport Handlebars from 'handlebars';\nimport { PrintCommand } from '../libs/escpos.printer';\nimport { ICouponItemized } from '../types/wyo.coupon.type';\nimport helpers from '../helpers/helpers.register';\nimport { QueryBuilder, QueryResponse } from '@litepos/autoquery';\nimport { OrderDisplay } from '../types/ods.type';\nimport { OrderDisplayService } from './ods.service';\n\nhelpers({ handlebars: Handlebars });\n\nexport interface IInvoiceBaseService extends IAppRemoteService<IInvoice> {\n calculate(invoice: IInvoice, appConfig: IAppConfig, disableRounding?: boolean): IInvoice;\n calculateLines(invoice: IInvoice): void;\n calculateLine(line: IInvoiceLine): void;\n // change from calculateSubtotalPoint\n calculatePointSubtotal(invoice: IInvoice): void;\n calculateDeliveryCharge(invoice: IInvoice): void;\n calculateInvoiceServiceChargeableSubtotal(invoice: IInvoice): void;\n // calculateCustomerPackage(invoice: IInvoice, line: IInvoiceLine, write: boolean): number;\n calculateDiscount(invoice: IInvoice, flow: CalcFlow): void;\n calculateRounding(invoice: IInvoice, roundingBase: number, roundingUp: boolean, roundingCashless: boolean, roundingNearest?: boolean): void;\n roundingStep(total: number, roundingBase: number, roundingUp: boolean, roundingNearest?: boolean): number;\n calculateServiceCharge(invoice: IInvoice, rate: number): void;\n calculateTax(invoice: IInvoice, taxRate: number, taxMethod: TaxMethod): void;\n calculateCreditDeduction(invoice: IInvoice): void;\n // calculateLineCouponDiscount(invoice: IInvoice): void;\n calculateTaxSubtotalRatio(invoice: IInvoice): number;\n calculateRewardCredit(invoice: IInvoice, aboveInvoiceAmount: number, includeServiceCharge: boolean, includeTax): void;\n calculateAddCredit(invoice: IInvoice): void;\n calculateRewardPoint(invoice: IInvoice, aboveInvoiceAmount: number, includeServiceCharge: boolean, includeTax: boolean): void;\n calculateChangeAmount(invoice: IInvoice): void;\n calculateInvoiceCharges(invoice: IInvoice, flow: CalcFlow): void;\n}\n\nexport type LineOptions = {\n quantity?: number;\n price?: number;\n remark?: string;\n};\n\nconst LINE_OPTIONS_DEFAULT: LineOptions = {\n quantity: 1,\n price: 0,\n remark: '',\n};\nexport class InvoiceBaseService extends AppRemoteService<IInvoice> implements IInvoiceBaseService {\n protected tillService: ITillService;\n protected sectionItemService: ISectionItemService;\n protected configService: ConfigService;\n protected printTemplateService: PrintTemplateService;\n protected printerService: PrinterService;\n protected printJobService: PrintJobService;\n protected itemService: IItemService;\n protected orderDisplayService: OrderDisplayService;\n\n constructor(readonly http: AxiosInstance, readonly db: Dexie, readonly options: IServiceOptions, readonly moduleName = 'invoices', readonly methodName = 'invoice') {\n super();\n this.tillService = new TillService(http, db, options, 'tills', 'till');\n this.sectionItemService = new SectionItemService(http, db, options, 'section_items', 'section_item');\n this.configService = new ConfigService(http, db, options, 'configs', 'config');\n this.printTemplateService = new PrintTemplateService(http, db, options, 'print_templates', 'print_template');\n this.printerService = new PrinterService(http, db, options, 'printers', 'printer');\n this.printJobService = new PrintJobService(http, db, options, 'print_jobs', 'print_job');\n this.itemService = new ItemService(http, db, options, 'items', 'item');\n this.orderDisplayService = new OrderDisplayService(http, db, options);\n }\n public calculate(invoice: IInvoice, appConfig: IAppConfig, disableRounding = false): IInvoice {\n if (invoice.lines == null || invoice.lines.length < 1) {\n this.resetInvoiceCalculations(invoice);\n return invoice;\n }\n // subtotal\n this.calculateLines(invoice);\n this.calculatePointSubtotal(invoice);\n this.calculateInvoiceServiceChargeableSubtotal(invoice);\n // invoice discount should be 0 here\n invoice.discount_amount = 0;\n this.calculateDiscount(invoice, CalcFlow.AfterSubtotal);\n if (invoice.grand_total < 0) {\n invoice.grand_total = 0;\n invoice.service_chargeable_subtotal = 0;\n }\n this.calculateInvoiceCharges(invoice, CalcFlow.AfterSubtotal);\n\n // service charge - recalculate service chargeable subtotal after discounts (apply discount proportionally)\n if (invoice.subtotal > 0 && invoice.discount_amount > 0) {\n const discountRatio = 1 - (invoice.discount_amount / invoice.subtotal);\n invoice.service_chargeable_subtotal = preciseRound(Math.max(0, invoice.service_chargeable_subtotal * discountRatio), 2);\n } else if (invoice.discount_amount >= invoice.subtotal) invoice.service_chargeable_subtotal = 0;\n const serviceChargeRate = appConfig.config.charges.service_charge ? appConfig.config.charges.service_charge_rate : 0;\n this.calculateServiceCharge(invoice, serviceChargeRate);\n this.calculateDiscount(invoice, CalcFlow.AfterServiceCharge);\n if (invoice.grand_total < 0) {\n invoice.grand_total = 0;\n }\n this.calculateInvoiceCharges(invoice, CalcFlow.AfterServiceCharge);\n\n // tax\n const taxRate = appConfig.config.tax.enabled ? appConfig.config.tax.rate : 0;\n this.calculateTax(invoice, taxRate, appConfig.config.tax.method);\n // delivery\n this.calculateDeliveryCharge(invoice);\n // credit deduction\n this.calculateCreditDeduction(invoice);\n // rounding\n if (!disableRounding) this.calculateRounding(invoice, appConfig.config.rounding.base, appConfig.config.rounding.up, appConfig.config.rounding.cashless, appConfig.config.rounding.nearest);\n else invoice.rounding = 0;\n // discount after rounding\n this.calculateDiscount(invoice, CalcFlow.AfterGrantTotal);\n if (invoice.grand_total < 0) {\n invoice.grand_total = 0;\n }\n this.calculateInvoiceCharges(invoice, CalcFlow.AfterGrantTotal);\n\n invoice.grand_total = preciseRound(invoice.grand_total);\n \n invoice.rewarded_credit_rate = appConfig.config?.loyalty_program?.rewarded_credit_rate ?? 0;\n this.calculateRewardCredit(\n invoice,\n 0,\n appConfig.config?.loyalty_program?.inclusive_service_charge,\n appConfig.config?.loyalty_program?.inclusive_tax,\n );\n this.calculateAddCredit(invoice);\n\n invoice.rewarded_point_rate = appConfig.config?.loyalty_program?.rewarded_point_rate ?? 0;\n this.calculateRewardPoint(\n invoice,\n appConfig.config?.loyalty_program?.rewarded_point_rate,\n appConfig.config?.loyalty_program?.inclusive_service_charge,\n appConfig.config?.loyalty_program?.inclusive_tax,\n );\n\n // to make sure grand_total doesn't goes to negative\n if (invoice.grand_total < 0) {\n invoice.grand_total = 0;\n }\n this.calculateChangeAmount(invoice);\n return invoice;\n }\n\n public calculateLines(invoice: IInvoice) {\n invoice.subtotal = 0;\n invoice.point_subtotal = 0;\n let rawSubtotal = 0;\n for (const line of invoice.lines) {\n this.calculateLine(line);\n rawSubtotal += line.subtotal;\n invoice.subtotal += preciseRound(line.subtotal, 2);\n invoice.point_subtotal += line.point_subtotal;\n }\n invoice.subtotal = preciseRound(rawSubtotal, 2);\n invoice.grand_total = preciseRound(invoice.subtotal, 2);\n }\n\n public calculateLine(line: IInvoiceLine): void {\n ////console.log('calculateLine', line);\n this.resetLineCalculations(line);\n line.point_subtotal = line.quantity * line.point;\n let modifiersTotal = 0;\n if (line.modifiers) modifiersTotal = line.modifiers.reduce((sum, modifier) => sum + modifier.price * modifier.quantity, 0);\n line.subtotal = line.subtotal_before_discount = preciseRound(line.quantity * (line.price + modifiersTotal), 2);\n if (line.item.discountable && (line.discount_amount > 0 || line.discount_percent > 0)) {\n if (line.discount_calc_type == CalcType.Flat) line.subtotal -= line.discount_amount;\n else {\n line.discount_amount = preciseRound(line.subtotal * line.discount_percent, 2);\n line.subtotal -= line.discount_amount;\n }\n }\n line.subtotal = preciseRound(line.subtotal, 2);\n }\n\n public calculatePointSubtotal(invoice: IInvoice): void {\n invoice.point_subtotal = 0;\n if (invoice.lines == null || invoice.lines.length < 1) return;\n for (const line of invoice.lines) {\n line.point_subtotal = line.quantity * line.point;\n invoice.point_subtotal += line.point_subtotal;\n }\n invoice.minus_point = invoice.point_subtotal;\n }\n\n /**\n * Calculate the invoice subtotal without considering take out\n * @param invoice - The invoice object containing invoice lines\n * @returns The updated invoice object with calculated subtotals\n */\n public calculateInvoiceServiceChargeableSubtotal(invoice: IInvoice): void {\n if (invoice.lines == null || invoice.lines.length < 1) invoice.service_chargeable_subtotal = 0;\n const rawServiceChargeableSubtotal = preciseRound(invoice.lines.filter((x) => !x.is_take_out && !x.item.is_service_charge_exempt).reduce((sum, x) => sum + x.subtotal, 0));\n invoice.service_chargeable_subtotal = preciseRound(rawServiceChargeableSubtotal, 2);\n }\n\n //#region Unused methods\n /**\n * Calculate customer package and update line subtotals\n * @param invoice - The invoice object containing customer details and lines\n * @param line - The invoice line to be calculated\n * @param write - Flag to decide if customer spend history should be updated\n * @returns The calculated line subtotal\n */\n // public calculateCustomerPackage(invoice: IInvoice, line: IInvoiceLine, write: boolean = false): number {\n // let line_subtotal = line.subtotal;\n // let line_subtotal_without_takeout = line.subtotal_without_takeout;\n // if (invoice.use_customer_package && invoice.customer_id !== 0 && invoice.customer) {\n // const purchases = this.customerPurchaseHistoryService.getAvailableItemizedByCustomerId(invoice.customer_id);\n // if (!purchases.some(p => p.item_id === line.item_id)) {\n // line.subtotal_without_takeout = line_subtotal_without_takeout;\n // return line_subtotal;\n // }\n // let pointer = 0;\n // for (const p of purchases) {\n // if (p.item_id === line.item_id) {\n // let quantity = 0;\n // for (let i = pointer; i < line.invoice_itemized.length; i++) {\n // if (quantity === p.available_quantity) break;\n // if (line_subtotal > 0 && line.invoice_itemized[pointer].actual_price > 0) {\n // line_subtotal -= line.invoice_itemized[pointer].actual_price;\n // if (!line.invoice_itemized[pointer].is_take_out) line_subtotal_without_takeout -= line.invoice_itemized[pointer].actual_price;\n // }\n // quantity++;\n // pointer++;\n // }\n // if (quantity > 0 && write) {\n // const model = new CustomerSpendHistoryItemizedModel(p, quantity);\n // const list = invoice.customer_spend ? [...invoice.customer_spend] : [];\n // list.push(model);\n // invoice.customer_spend = list;\n // }\n // }\n // }\n // }\n // line.subtotal_without_takeout = line_subtotal_without_takeout;\n // return line_subtotal;\n // }\n //#endregion\n\n /**\n * Calculate the total discount amount of an invoice and update grand total accordingly\n * @param invoice - The invoice object containing discount details and lines\n * @param flow - The calculation of discount flow\n * @returns The updated invoice object with calculated discount and grand total\n */\n public calculateDiscount(invoice: IInvoice, flow: CalcFlow): void {\n if (!invoice?.lines?.length) return;\n let totalDiscount = 0;\n invoice.discountable_subtotal = preciseRound(invoice.lines.filter(x => x.item.discountable).reduce((sum, x) => sum + x.subtotal, 0), 2);\n if (!invoice.discounts?.length) return;\n for (const discount of invoice.discounts.filter(x => x.calc_flow == flow)) {\n if (!discount.applying_item_uids?.length) {\n if (discount.calc_type == CalcType.Flat) totalDiscount += discount.amount;\n else {\n discount.percent_amount = preciseRound((invoice.discountable_subtotal - invoice.discount_amount - totalDiscount) * discount.percent);\n totalDiscount += discount.percent_amount;\n }\n } else {\n let largestLinePrice = 0;\n let flag = false;\n for (const line of invoice.lines) {\n if (discount.applying_item_uids.includes(line.item_uid) && line.price > largestLinePrice) {\n largestLinePrice = line.price;\n flag = true;\n }\n }\n if(!flag) {\n invoice.discounts = invoice.discounts.filter(x => x.uid != discount.uid);\n continue;\n }\n if (discount.calc_type == CalcType.Flat) {\n discount.amount = preciseRound(discount.amount > largestLinePrice ? largestLinePrice : discount.amount);\n totalDiscount += discount.amount;\n } else {\n discount.percent_amount = preciseRound(largestLinePrice * discount.percent);\n totalDiscount += discount.percent_amount;\n }\n }\n }\n invoice.discount_amount += preciseRound(totalDiscount);\n invoice.grand_total = preciseRound(invoice.grand_total - totalDiscount);\n }\n\n /**\n * Calculates the rounding for an invoice based on the given parameters.\n * @param invoice - The invoice to calculate the rounding for.\n * @param roundingBase - The base value to round to.\n * @param roundingUp - Whether to round up or down.\n * @param roundingCashless - Whether to apply rounding only for cash payments.\n */\n public calculateRounding(invoice: IInvoice, roundingBase: number, roundingUp: boolean, roundingCashless: boolean, roundingNearest?: boolean): void {\n invoice.rounding = 0;\n if (!roundingBase) return;\n if (!roundingCashless && !invoice.payment_has_cash) return;\n const cashlessPayments = invoice.payments?.filter(p => !p.payment_method?.is_cash) || [];\n const totalCashlessPaid = cashlessPayments.reduce((acc, p) => acc + p.tender_amount - p.change_amount, 0);\n const remainingBalance = totalCashlessPaid > 0 ? invoice.grand_total - totalCashlessPaid : invoice.grand_total;\n const rounding = this.roundingStep(remainingBalance, roundingBase, roundingUp, roundingNearest);\n invoice.rounding = preciseRound(rounding);\n invoice.grand_total += invoice.rounding;\n }\n\n public roundingStep(total: number, roundingBase: number, roundingUp: boolean, roundingNearest?: boolean): number {\n const scaleFactor = 100;\n const totalCents = Math.round(total * scaleFactor);\n const baseCents = Math.round(roundingBase * scaleFactor);\n const remainderCents = totalCents % baseCents;\n if (remainderCents === 0) return 0;\n let adjustmentCents: number;\n if (roundingNearest) adjustmentCents = remainderCents >= baseCents / 2 ? baseCents - remainderCents : -remainderCents;\n else adjustmentCents = roundingUp ? baseCents - remainderCents : -remainderCents;\n return preciseRound(adjustmentCents / scaleFactor);\n }\n\n /**\n * Calculate the delivery charge of an invoice\n * @param invoice - The invoice object containing delivery charge and type\n * @returns The updated invoice object with calculated grand total\n */\n public calculateDeliveryCharge(invoice: IInvoice): void {\n if (invoice.delivery_charge > 0 && invoice.type === InvoiceType.Delivery) {\n invoice.grand_total += invoice.delivery_charge;\n invoice.grand_total = preciseRound(invoice.grand_total, 2);\n }\n }\n\n /**\n * Calculate and set the service charge for a given invoice.\n * The method updates the service_charge and grand_total fields of the invoice.\n *\n * @param invoice - invoice to calculate the service charge for\n * @param rate - service charge rate. e.g. 0.1 for 10%\n * @returns {void} -\n */\n public calculateServiceCharge(invoice: IInvoice, rate: number): void {\n //console.log(rate);\n let serviceCharge = 0;\n invoice.service_charge = 0;\n if (invoice.lines == null || invoice.lines.length < 1) return;\n // console.log('invoice lines in service charge')\n //invoice.service_chargeable_subtotal = preciseRound(invoice.lines.filter((x) => !x.item.is_service_charge_exempt && !x.is_take_out).reduce((sum, x) => sum + x.subtotal, 0));\n //invoice.grand_total += invoice.service_charge;\n // console.log(\"invoice type\", invoice.type);\n if (invoice.type == InvoiceType.Delivery || invoice.type == InvoiceType.TakeOut) return;\n // Check if service charge is applicable and the invoice type is not TakeOut.\n // console.log('service charge rate ',rate);\n if (rate > 0) serviceCharge = invoice.service_chargeable_subtotal * (rate / 100);\n // Round off the service charge to two decimal places and update the invoice.\n invoice.service_charge = preciseRound(serviceCharge, 2);\n invoice.grand_total += invoice.service_charge;\n invoice.grand_total = preciseRound(invoice.grand_total, 2);\n }\n\n /**\n * Calculates the tax for an invoice based on the tax rate and tax method.\n * @param invoice - The invoice to calculate the tax for.\n * @param taxRate - The tax rate to apply.\n * @param taxMethod - The tax method to use (inclusive or exclusive).\n */\n public calculateTax(invoice: IInvoice, taxRate: number, taxMethod: TaxMethod): void {\n invoice.tax = 0;\n if (taxRate <= 0) return;\n const ratio = this.calculateTaxSubtotalRatio(invoice);\n // Item tax affected by ratio, service charge tax not affected by ratio, round only at the end\n const taxableBase = invoice.grand_total - invoice.service_charge;\n if (taxMethod === TaxMethod.Inclusive) {\n const itemTax = (taxableBase * ratio * taxRate) / (100 + taxRate);\n const serviceTax = (invoice.service_charge * taxRate) / (100 + taxRate);\n invoice.tax = preciseRound(itemTax + serviceTax, 2);\n } else {\n const itemTax = (taxableBase * ratio * taxRate) / 100;\n const serviceTax = (invoice.service_charge * taxRate) / 100;\n invoice.tax = preciseRound(itemTax + serviceTax, 2);\n invoice.grand_total = preciseRound(invoice.grand_total + invoice.tax, 2);\n }\n }\n\n /**\n * Adjusts the grand total of the invoice by the deduction balance\n * @param invoice - The invoice to adjust.\n * @returns void\n */\n public calculateCreditDeduction(invoice: IInvoice): void {\n if (invoice.minus_credit > 0) {\n if (invoice.minus_credit > invoice.grand_total) invoice.minus_credit = invoice.grand_total;\n invoice.grand_total -= invoice.minus_credit;\n }\n }\n\n /**\n * Calculate the tax subtotal ratio for the invoice.\n * @param invoice - The invoice for which the ratio is calculated.\n * @returns The calculated ratio as a number.\n */\n public calculateTaxSubtotalRatio(invoice: IInvoice): number {\n let ratio = 1;\n if (!invoice.lines || !invoice.lines.some((x) => x.item.is_tax_exempt)) return ratio;\n // const subtotal = invoice.lines.reduce((sum, x) => sum + x.subtotal, 0) - invoice.deduction_package;\n if (invoice.grand_total === 0 || invoice.subtotal === 0) return ratio;\n ratio = 1 - invoice.lines.filter((x) => x.item.is_tax_exempt).reduce((sum, line) => sum + line.subtotal, 0) / invoice.subtotal;\n return ratio;\n }\n\n /**\n * Calculates the rewarded credit for an invoice.\n * @param invoice - The invoice to calculate the rewarded credit for.\n * @param aboveInvoiceAmount - The minimum invoice amount required to be eligible for rewarded credit.\n * @param includeServiceCharge - Whether to include the service charge in the calculation.\n * @param includeTax - Whether to include the tax in the calculation.\n */\n public calculateRewardCredit(invoice: IInvoice, aboveInvoiceAmount: number, includeServiceCharge: boolean, includeTax: boolean): void {\n invoice.rewarded_credit = 0;\n if (invoice.grand_total <= 0) return;\n if (aboveInvoiceAmount > 0 && aboveInvoiceAmount > invoice.grand_total) return;\n\n const rate = invoice.rewarded_credit_rate;\n let total = invoice.grand_total;\n\n if (includeServiceCharge) total -= invoice.service_charge;\n if (includeTax) total -= invoice.tax;\n\n total -= invoice.lines.filter((x) => x.item.is_credit_reward_exempt).reduce((sum, x) => sum + x.subtotal, 0);\n invoice.rewarded_credit = preciseRound(total * rate, 2);\n }\n\n public calculateAddCredit(invoice: IInvoice): void {\n let addCredit = 0;\n invoice.add_credit = 0;\n if (!invoice.lines || invoice.lines.length <= 0) return;\n for (const line of invoice.lines.filter((x) => x.item.add_credit > 0)) {\n addCredit += line.item.add_credit * line.quantity;\n }\n invoice.add_credit = addCredit;\n return;\n }\n\n /**\n * Calculates and sets the rewarded points for the given invoice based on various conditions.\n * @param invoice - The invoice to calculate rewarded points for.\n * @returns void\n */\n public calculateRewardPoint(invoice: IInvoice, aboveInvoiceAmount: number, includeServiceCharge: boolean, includeTax: boolean): void {\n invoice.rewarded_point = 0;\n if (invoice.rewarded_point_rate <= 0) return;\n if (invoice.grand_total <= 0) return;\n let total = invoice.grand_total;\n\n if (includeServiceCharge) total -= invoice.service_charge;\n if (includeTax) total -= invoice.tax;\n\n total -= invoice.lines.filter((x) => x.item.is_point_reward_exempt).reduce((sum, x) => sum + x.subtotal, 0);\n invoice.rewarded_point = Math.floor(total * invoice.rewarded_point_rate);\n }\n\n private resetInvoiceCalculations(invoice: IInvoice): void {\n invoice.subtotal = 0;\n invoice.point_subtotal = 0;\n invoice.service_chargeable_subtotal = 0;\n invoice.service_charge = 0;\n invoice.tax = 0;\n invoice.grand_total = 0;\n invoice.rounding = 0;\n invoice.discount_amount = 0;\n invoice.minus_credit = 0;\n invoice.rewarded_credit = 0;\n invoice.rewarded_point = 0;\n invoice.add_credit = 0;\n\n if (invoice.charges && invoice.charges.length > 0) {\n invoice.charges.forEach((charge) => {\n charge.amount = 0;\n });\n }\n\n // reset line calculations\n }\n\n\n private resetLineCalculations(line: IInvoiceLine): void {\n line.subtotal = 0;\n line.subtotal_before_discount = 0;\n line.point_subtotal = 0;\n }\n\n public calculateChangeAmount(invoice: IInvoice): void {\n if (invoice.payments.length <= 0) return;\n if (invoice.payments.every((x) => !x.payment_method.is_cash)) return;\n const totalTenderAmount = invoice.payments.reduce((sum, x) => sum + x.tender_amount, 0);\n const changeAmount = preciseRound(totalTenderAmount - invoice.grand_total);\n invoice.payments.filter((x) => x.payment_method.is_cash);\n const cashPayments = invoice.payments.filter((x) => x.payment_method.is_cash);\n // reset all change amount\n cashPayments.forEach((x) => (x.change_amount = 0));\n const lastCashPayment = cashPayments[cashPayments.length - 1];\n lastCashPayment.change_amount = preciseRound(changeAmount);\n }\n\n public calculateInvoiceCharges(invoice: IInvoice, flow: CalcFlow): void {\n if (!invoice.charges || invoice.charges.length === 0) return;\n\n // Process each charge based on its calculation flow\n for (const charge of invoice.charges.filter((x) => x.calc_flow === flow)) {\n let baseAmount = 0;\n\n // Determine the base amount based on calculation flow\n switch (charge.calc_flow) {\n case CalcFlow.AfterSubtotal:\n baseAmount = invoice.subtotal;\n break;\n case CalcFlow.AfterServiceCharge:\n baseAmount = invoice.subtotal + invoice.service_charge;\n break;\n case CalcFlow.AfterGrantTotal:\n // Use current grand_total before adding this charge\n baseAmount = invoice.grand_total;\n break;\n default:\n baseAmount = invoice.subtotal;\n }\n\n // Calculate the charge amount based on percentage\n if (charge.percentage > 0) {\n charge.amount = preciseRound(baseAmount * (charge.percentage / 100), 2);\n }\n\n // Add charge amount to grand total\n invoice.grand_total += charge.amount;\n invoice.grand_total = preciseRound(invoice.grand_total, 2);\n }\n }\n}\n/**\n * Interface for the Invoice Operation Service, which extends the IInvoiceBaseService interface.\n * Provides methods for adding an item to an invoice line and adding a modifier to a list of modifiers.\n */\n/**\n * Represents an extended invoice operation service that includes additional methods for adding items and modifiers to an invoice.\n */\n/**\n * Interface for the Invoice Operation Service, which extends the Invoice Base Service.\n */\n/**\n * Interface for a service that performs operations on invoice lines.\n */\n/**\n * Represents a service that provides operations for manipulating invoice lines.\n */\nexport interface ILineOperationService extends IInvoiceBaseService {\n /**\n * Adds an item to an invoice line. If the item already exists in the invoice, the quantity is increased, otherwise a new line is created.\n * Adding items with positive quantities\n * Reducing quantities of existing items with negative values\n * Automatic removal of lines when quantity reaches 0 or below\n * @param invoice - The invoice to add the item to.\n * @param customer - The customer associated with the invoice.\n * @param appConfig - The app configuration.\n * @param item - The item to add to the invoice line.\n * @param modifiers - An array of modifiers to apply to the item.\n * @param options - Additional options for the line.\n * @returns The updated invoice.\n */\n addItemToLine(invoice: IInvoice, customer: ICustomer, appConfig: IAppConfig, item: IItem, modifiers?: IInvoiceCoreLine[], lineOptions?: LineOptions, createNewLine?: boolean, comboLineUid?: string, comboGroupUid?: string): IInvoiceLine;\n\n /**\n * Duplicates an invoice line\n * @param invoice - The invoice to duplicate the line in.\n * @param line - The line to duplicate.\n * @returns The updated invoice.\n */\n duplicateLine(invoice: IInvoice, line: IInvoiceLine): IInvoice;\n\n /**\n * Calibrates the duplicates in an invoice.\n * @param invoice - The invoice to calibrate the duplicates in.\n * @returns The updated invoice.\n */\n calibrateDuplicates(invoice: IInvoice): IInvoice;\n\n /**\n * Decreases the quantity of an item in an invoice line.\n * @param invoice - The invoice to decrease the item quantity in.\n * @param line - The invoice line to decrease the item quantity in.\n * @param quantity - The quantity of the item to decrease.\n * @param skipDeletedLines - Whether to skip the deleted lines, default is false.\n * @returns The updated invoice.\n */\n minusLineQuantity(invoice: IInvoice, line: IInvoiceLine, quantity: number, skipDeletedLines?: boolean): IInvoice;\n\n /**\n * Increases the quantity of an item in an invoice line.\n * @param invoice - The invoice to increase the item quantity in.\n * @param line - The invoice line to increase the item quantity in.\n * @param quantity - The quantity of the item to increase.\n * @returns The updated invoice.\n */\n addLineQuantity(invoice: IInvoice, line: IInvoiceLine, quantity: number): IInvoice;\n\n /**\n * Changes the unit price of an existing invoice line.\n * @param line - The invoice line to change the item price in.\n * @param price - The new price of the item.\n * @returns The updated invoice.\n */\n changeLinePrice(line: IInvoiceLine, price: number): IInvoiceLine;\n\n /**\n * Changes the discount of an existing invoice line.\n * @param line - The invoice line to change the discount in.\n * @param discountType - The type of discount to apply.\n * @param amountOrPercent - The amount of the discount to apply.\n * @returns The updated invoice.\n */\n changeLineDiscount(line: IInvoiceLine, discountType: CalcType, amountOrPercent: number): IInvoiceLine;\n \n /**\n * to convert a modifier to an invoice core line object\n * so it can be used in addModifier() method\n * @param modifier ICoreItem, the modifier to be added to the invoice line\n * @param quantity number, the quantity of the modifier to be added\n */\n toInvoiceCoreLine(modifier: ICoreItem, quantity: number): IInvoiceCoreLine;\n\n /**\n * Adds a modifier to a list of modifiers, if the modifier already exists in the list, the quantity is increased, otherwise a new modifier is created.\n * @param modifiers - The list of modifiers to add the modifier to.\n * @param modifier - The modifier to add to the list.\n * @returns The updated list of modifiers.\n */\n addModifier(modifiers: IInvoiceCoreLine[], modifier: IInvoiceCoreLine): IInvoiceCoreLine[];\n\n /**\n * @deprecated use changeModifierQuantity instead\n * Decreases the quantity of a modifier in a list of modifiers.\n * @param modifiers - The list of modifiers to decrease the quantity in.\n * @param modifier - The modifier to decrease the quantity of.\n * @param quantity - The quantity of the modifier to decrease.\n * @returns The updated list of modifiers.\n */\n minusModifierQuantity(modifiers: IInvoiceCoreLine[], modifier: IInvoiceCoreLine, quantity?: number): IInvoiceCoreLine[];\n\n /**\n * @deprecated use changeModifierQuantity instead\n * Increases the quantity of a modifier in a list of modifiers.\n * @param modifiers - The list of modifiers to increase the quantity in.\n * @param modifier - The modifier to increase the quantity of.\n * @param quantity - The quantity of the modifier to increase.\n * @returns The updated list of modifiers.\n */\n addModifierQuantity(modifiers: IInvoiceCoreLine[], modifier: IInvoiceCoreLine, quantity?: number): IInvoiceCoreLine[];\n\n /**\n * Changes the quantity of a modifier in a list of modifiers.\n * Positive quantity will increase the modifier quantity.\n * Negative quantity will decrease the modifier quantity.\n * If quantity becomes 0 or negative, the modifier will be removed.\n * @param modifiers - The list of modifiers to change the quantity in.\n * @param modifier - The modifier to change the quantity of.\n * @param quantity - The quantity to add (positive) or subtract (negative).\n * @returns The updated list of modifiers.\n */\n changeModifierQuantity(modifiers: IInvoiceCoreLine[], modifier: IInvoiceCoreLine, quantity?: number): IInvoiceCoreLine[];\n\n /**\n * Changes the unit price of a existing modifier.\n * @param modifier - The modifier to change the price of.\n * @param price - The new price of the modifier.\n * @returns The updated list of modifiers.\n */\n changeModifierPrice(modifier: IInvoiceCoreLine, price: number): IInvoiceCoreLine;\n\n /**\n * Overwrites the note of an invoice line.\n * @param line - The invoice line to overwrite the note of.\n * @param note - The new note to overwrite the old note with.\n * @returns The updated invoice line.\n */\n overwriteNoteToLine(line: IInvoiceLine, note: string): IInvoiceLine;\n\n /**\n * Compares two invoice lines.\n * @param target - The target invoice line to compare.\n * @param source - The source invoice line to compare.\n * @returns True if the lines are the same, false otherwise.\n */\n compareLines(target: IInvoiceLine, source: IInvoiceLine): boolean;\n\n //#region Combo Operations\n\n\n /**\n * To add combo items under one combo\n * @param invoice - The invoice to add the item to.\n * @param customer - The customer associated with the invoice.\n * @param appConfig - The app configuration.\n * @param item - The item to add to the invoice line.\n * @param comboLineUid the main combo's line uid\n * @param comboGroupUid the uid of the combo_group the item belongs to\n * @param modifiers - An array of modifiers to apply to the item (default is [])\n * @param options - Additional options for the line.\n */\n addComboItemToLine(invoice: IInvoice, customer: ICustomer, appConfig: IAppConfig, item: IItem,\n comboLineUid: string, comboGroupUid: string,\n modifiers?: IInvoiceCoreLine[], options?: LineOptions): IInvoiceLine;\n\n // 这个方法是套一层在基本line operation add or minus 上面,打算是来判断combo item 增加或者减少是否符合\n // min_order 或者 max_order, 目前不实现\n // changeComboItemQuantity()\n\n\n /**\n * For combo's operations, if a combo is removed, all combo items under it will be removed\n * Use this operation to remove all combo items\n * And use minusLineQuantity to remove main combo.\n * @param invoice the invoice\n * @param comboLineUid The combo's line uid\n * @param skipDeletedLines - Whether to skip the deleted lines, default is false.\n * @returns The deleted lines.\n */\n removeAllComboItems(Invoice: IInvoice, comboLineUid: string, skipDeletedLines?: boolean): IInvoiceLine[];\n\n /**\n * Duplicates a combo line and all its associated combo items from an invoice\n * @param invoice - The invoice containing the combo to duplicate\n * @param comboLine - The main combo line to duplicate\n * @returns The updated invoice with duplicated combo and its items\n */\n duplicateComboLines(invoice: IInvoice, comboLine: IInvoiceLine): IInvoice;\n //#endregion\n}\n\nexport class LineOperationService extends InvoiceBaseService implements ILineOperationService {\n public addItemToLine(invoice: IInvoice, customer: ICustomer, appConfig: IAppConfig, item: IItem, modifiers?: IInvoiceCoreLine[], lineOptions?: LineOptions, createNewLine?: boolean, comboLineUid?: string, comboGroupUid?: string): IInvoiceLine {\n // if (item.minus_point > 0) {\n // if (!customer?.id) throw new SystemError('Please select customer first');\n // else if (customer.point < item.minus_point) throw new SystemError('Customer has insufficient points to redeem this item');\n // }\n const options = { ...LINE_OPTIONS_DEFAULT, ...lineOptions };\n\n if (invoice.lines == null) invoice.lines = [];\n const line = this.findOrCreateLine(invoice, item, options.quantity, options.price, modifiers, options.remark, createNewLine, comboLineUid, comboGroupUid);\n\n // 检查产品是否是 Combo 类别\n if (item.type == ProductType.Combo) line.is_combo = true;\n\n // If line exists, update quantity or remove if becomes 0\n if (line.uid) {\n line.quantity += options.quantity;\n // Remove line if quantity becomes 0 or negative\n if (line.quantity <= 0) {\n invoice.lines = invoice.lines.filter((x) => x.uid !== line.uid);\n }\n } else {\n // Only add new line if quantity is positive\n if (options.quantity > 0) {\n line.uid = ModelPrefix.InvoiceLine + nanoid();\n invoice.lines.push(line);\n }\n }\n\n \n return line;\n }\n public duplicateLine(invoice: IInvoice, line: IInvoiceLine): IInvoice {\n const newLine = _.cloneDeep(line);\n newLine.is_duplicate = true;\n newLine.duplicated_from_uid = line.uid;\n newLine.uid = ModelPrefix.InvoiceLine + nanoid();\n invoice.lines.push(newLine);\n return invoice;\n }\n public calibrateDuplicates(invoice: IInvoice): IInvoice {\n if (!invoice.lines || invoice.lines.length <= 0) return invoice;\n\n const duplicateLines = invoice.lines.filter((x) => x.is_duplicate);\n for (const duplicateLine of duplicateLines) {\n const originalLine = invoice.lines.find((x) => x.uid === duplicateLine.duplicated_from_uid && !x.is_duplicate);\n if (originalLine && this.compareLines(originalLine, duplicateLine)) {\n originalLine.quantity += duplicateLine.quantity;\n originalLine.sent += duplicateLine.sent;\n invoice.lines = invoice.lines.filter((x) => x !== duplicateLine);\n } else {\n duplicateLine.is_duplicate = false;\n }\n }\n return invoice;\n }\n public toInvoiceCoreLine(modifier: ICoreItem, quantity = 1): IInvoiceCoreLine {\n const coreLine = new InvoiceCoreLine();\n coreLine.item = _.cloneDeep(modifier);\n coreLine.item_uid = modifier.uid;\n coreLine.quantity = quantity;\n coreLine.price = modifier.price;\n return coreLine;\n }\n public addModifier(modifiers: IInvoiceCoreLine[], modifier: IInvoiceCoreLine): IInvoiceCoreLine[] {\n if (!modifiers || modifiers.length <= 0) return [modifier];\n else {\n const index = modifiers.findIndex((x) => x.item_uid === modifier.item_uid && x.price === modifier.price);\n if (index < 0) modifiers.push(modifier);\n else {\n modifiers[index].quantity += modifier.quantity;\n }\n return modifiers;\n }\n }\n public changeLinePrice(line: IInvoiceLine, price: number): IInvoiceLine {\n if (line == null) return line;\n line.price = price;\n return line;\n }\n public changeLineDiscount(line: IInvoiceLine, discountType: CalcType, amountOrPercent: number): IInvoiceLine {\n if (line == null) return line;\n if (discountType == CalcType.Percent && amountOrPercent > 100) throw new SystemError('Discount percent can not be more than 100%');\n if (discountType == CalcType.Flat && amountOrPercent > line.subtotal) throw new SystemError('Discount amount can not be more than price');\n line.discount_calc_type = discountType;\n if (discountType == CalcType.Flat) line.discount_amount = amountOrPercent;\n else line.discount_percent = amountOrPercent;\n return line;\n }\n // 目前在项目里优化方案是,接受 item_uid, 然后找到最后添加的 line, 减去 line 的 quantity 或者删除 line\n public minusLineQuantity(invoice: IInvoice, line: IInvoiceLine, quantity: number, skipDeletedLines = false): IInvoice {\n if (quantity <= 0) throw new SystemError('Quantity can not be less than 0, input a positive quantity to minus the line quantity');\n if (invoice.lines == null || invoice.lines.length <= 0) return invoice;\n if (!line) throw new SystemError('Line can not be null or empty');\n if (line.quantity - line.sent < Math.abs(quantity)) {\n const deletedSentQuantity = Math.abs(quantity) - (line.quantity - line.sent);\n const deletedLine = _.cloneDeep(line);\n deletedLine.quantity = deletedSentQuantity;\n deletedLine.sent = deletedSentQuantity;\n if(!skipDeletedLines) invoice.deleted_lines.push(deletedLine);\n // to make sure sent is aligned after quantity minus\n // sent 只是去掉已发送的数量\n line.sent -= deletedSentQuantity;\n }\n if (line.quantity <= quantity) {\n invoice.lines = invoice.lines.filter((x) => x.uid !== line.uid);\n }\n line.quantity -= quantity;\n }\n public addLineQuantity(invoice: IInvoice, line: IInvoiceLine, quantity: number): IInvoice {\n if (invoice.lines == null || invoice.lines.length <= 0) return invoice;\n line.quantity += quantity;\n }\n public minusModifierQuantity(modifiers: IInvoiceCoreLine[], modifier: IInvoiceCoreLine, quantity = 0): IInvoiceCoreLine[] {\n if (!modifiers || modifiers.length <= 0) return modifiers;\n else {\n quantity = quantity ?? 0;\n const index = modifiers.findIndex((x) => x.item_uid === modifier.item_uid && x.price === modifier.price);\n if (index < 0) return modifiers;\n else {\n if (modifiers[index].quantity <= quantity) modifiers.splice(index, 1);\n else modifiers[index].quantity -= quantity;\n }\n return modifiers;\n }\n }\n public changeModifierQuantity(modifiers: IInvoiceCoreLine[], modifier: IInvoiceCoreLine, quantity?: number): IInvoiceCoreLine[] {\n if (!modifiers || modifiers.length <= 0) return modifiers;\n\n quantity = quantity ?? 0;\n const index = modifiers.findIndex((x) => x.item_uid === modifier.item_uid && x.price === modifier.price);\n if (index < 0) return modifiers;\n\n // Add or subtract quantity based on sign\n modifiers[index].quantity += quantity;\n\n // Remove modifier if quantity becomes 0 or negative\n if (modifiers[index].quantity <= 0) modifiers.splice(index, 1);\n\n return modifiers;\n }\n public addModifierQuantity(modifiers: IInvoiceCoreLine[], modifier: IInvoiceCoreLine, quantity = 0): IInvoiceCoreLine[] {\n if (!modifiers || modifiers.length <= 0) return modifiers;\n else {\n quantity = quantity ?? 0;\n const index = modifiers.findIndex((x) => x.item_uid === modifier.item_uid && x.price === modifier.price);\n if (index < 0) return modifiers;\n else {\n modifiers[index].quantity += quantity;\n }\n return modifiers;\n }\n }\n public changeModifierPrice(modifier: IInvoiceCoreLine, price: number): IInvoiceCoreLine {\n if (!modifier) return modifier;\n modifier.price = price;\n return modifier;\n }\n public overwriteNoteToLine(line: IInvoiceLine, note: string): IInvoiceLine {\n if (!note) return line;\n line.remark = note;\n return line;\n }\n public findOrCreateLine(invoice: IInvoice, item: IItem, quantity: number, price = 0, modifiers: IInvoiceCoreLine[] = [], remark = '', createNewLine = false, comboLineUid?: string, comboGroupUid?: string): IInvoiceLine {\n //console.log('findOrCreateLine');\n price = price ?? item.price;\n if (!invoice.lines || invoice.lines.length <= 0 || createNewLine) return this.createInvoiceLine(item, quantity, price, modifiers, remark);\n else {\n const lines = invoice.lines.filter((x) => x.item_uid === item.uid);\n if (!lines || lines.length <= 0) return this.createInvoiceLine(item, quantity, price, modifiers, remark);\n else {\n if(comboLineUid && comboGroupUid) {\n for (const line of lines.filter(l=> l.is_combo_item)) \n if (this.compareModifiers(line.modifiers, modifiers) && line.remark === remark && line.price === price && line.combo_line_uid === comboLineUid && line.combo_group_uid === comboGroupUid) return line;\n } else {\n for (const line of lines) if (this.compareModifiers(line.modifiers, modifiers) && line.remark === remark && line.price === price && !line.is_take_out) return line;\n }\n return this.createInvoiceLine(item, quantity, price, modifiers, remark);\n }\n }\n }\n private createInvoiceLine(item: IItem, quantity: number, price = 0, modifiers: IInvoiceCoreLine[] = [], remark = ''): IInvoiceLine {\n const line = new InvoiceLine();\n line.item = _.cloneDeep(item);\n line.item_uid = item.uid;\n line.quantity = quantity;\n line.point = item.minus_point;\n line.price = price ?? item.price;\n line.quantity = quantity;\n line.modifiers = modifiers;\n line.remark = remark;\n return line;\n }\n protected compareModifiers(target: IInvoiceCoreLine[], source: IInvoiceCoreLine[]): boolean {\n ////console.log('target modifiers', target);\n ////console.log('source modifiers', source);\n if (target.length !== source.length) return false;\n\n for (const modifier of target) {\n //console.log(source.some((x) => x.item_uid === modifier.item_uid && x.price === modifier.price && x.quantity === modifier.quantity));\n if (!source.some((x) => x.item_uid === modifier.item_uid && x.price === modifier.price && x.quantity === modifier.quantity)) return false;\n }\n return true;\n }\n /**\n * false if not equal\n * true if equal\n * @param target\n * @param source\n */\n public compareLines(target: IInvoiceLine, source: IInvoiceLine): boolean {\n if (target.remark != source.remark) return false;\n if (target.price != source.price) return false;\n if (target.is_take_out != source.is_take_out) return false;\n if (target.discount_calc_type != source.discount_calc_type) return false;\n if (target.discount_amount != source.discount_amount) return false;\n if (target.discount_percent != source.discount_percent) return false;\n if (!this.compareModifiers(target.modifiers, source.modifiers)) return false;\n return true;\n }\n\n //#region Combo Operations\n public addComboItemToLine(\n invoice: IInvoice,\n customer: ICustomer,\n appConfig: IAppConfig,\n item: IItem,\n comboLineUid: string,\n comboGroupUid: string,\n modifiers?: IInvoiceCoreLine[],\n options?: LineOptions,\n ) {\n const line = this.addItemToLine(invoice, customer, appConfig, item, modifiers, options, false, comboLineUid, comboGroupUid);\n line.is_combo_item = true;\n line.combo_line_uid = comboLineUid;\n line.combo_group_uid = comboGroupUid;\n return line;\n }\n\n public removeAllComboItems(invoice: IInvoice, comboLineUid: string, skipDeletedLines = false): IInvoiceLine[] {\n if(!invoice.lines || invoice.lines.length == 0) return [];\n const deletedLines = invoice.lines.filter(x=>x.combo_line_uid == comboLineUid && x.is_combo_item);\n invoice.lines = _.differenceBy(invoice.lines, deletedLines, 'uid');\n if(!skipDeletedLines) invoice.deleted_lines.push(...deletedLines);\n return deletedLines;\n }\n\n public duplicateComboLines(invoice: IInvoice, comboLine: IInvoiceLine): IInvoice {\n if (!comboLine.is_combo) throw new SystemError('Line is not a combo');\n const newComboLine = _.cloneDeep(comboLine);\n newComboLine.uid = ModelPrefix.InvoiceLine + nanoid();\n newComboLine.is_duplicate = true;\n newComboLine.duplicated_from_uid = comboLine.uid;\n invoice.lines.push(newComboLine);\n const comboItems = invoice.lines.filter(x => x.combo_line_uid === comboLine.uid && x.is_combo_item);\n comboItems.forEach(item => {\n const newItem = _.cloneDeep(item);\n newItem.uid = ModelPrefix.InvoiceLine + nanoid();\n newItem.combo_line_uid = newComboLine.uid;\n newItem.is_duplicate = true;\n invoice.lines.push(newItem);\n });\n return invoice;\n }\n\n //#endregion\n}\n\n/**\n * Interface for invoice operation service that extends line operation service\n */\nexport interface IInvoiceOperationService extends ILineOperationService {\n /**\n * Adds an invoice\n * @param invoice - The invoice to add\n * @returns A promise that resolves with the added invoice options\n */\n addInvoice(invoice: IInvoice): Promise<IInvoice>;\n /**\n * Hold an invoice\n * @param invoice - The invoice to hold\n * @param sectionItem - The section item to associate with the invoice\n * @returns A promise that resolves with the held invoice options\n */\n //holdInvoice(invoice: IInvoice, sectionItem: ISectionItem): Promise<IInvoice>;\n /**\n * Creates an invoice\n * @param invoice - The invoice to create\n * @param sectionItem - The section item to associate with the invoice\n * @param employee - The employee to associate with the invoice\n * @returns A promise that resolves with the created invoice options\n */\n createInvoice(invoice: IInvoice, sectionItem: ISectionItem, employee?: IEmployee): Promise<CreateInvoiceOptions>;\n\n /**\n * Updates an invoice\n * @param invoice - The invoice to update\n * @param sectionItem - The section item to associate with the invoice\n * @param employee - The employee to associate with the invoice\n * @returns A promise that resolves with the updated invoice\n */\n updateInvoice(invoice: IInvoice, sectionItem: ISectionItem, employee?: IEmployee): Promise<UpdateInvoiceOptions>;\n\n /**\n * Cancels an invoice\n * @param invoice - The invoice to cancel\n * @param sectionItem - The section item to associate with the invoice\n * @param employee - The employee to associate with the invoice\n * @returns A promise that resolves with the cancelled invoice options\n */\n cancelInvoice(invoice: IInvoice, sectionItem: ISectionItem, employee?: IEmployee): Promise<CancelInvoiceOptions>;\n\n /**\n * Checks an invoice\n * @param invoice - The invoice to check\n * @param SectionItem - The section item to associate with the invoice\n * @param employee - The employee to associate with the invoice\n * @returns A promise that resolves with the checked invoice options\n */\n checkInvoice(invoice: IInvoice, SectionItem: ISectionItem, employee?: IEmployee): Promise<CheckInvoiceOptions>;\n\n /**\n * Directly pays an invoice without creating it first (kiosk use case)\n * @param invoice the invoice to pay\n * @param till the till to use for the payment\n * @param employee the employee to associate with the invoice\n * @param specificPrinter the printer to use for the payment\n * @param specificKioskDeviceUid the kiosk device uid to use for the payment\n * @param kitchenPrintOverride override the kitchen print setting, if true, will print kitchen print even if kitchen print is disabled in config\n * @returns A promise that resolves with the direct pay invoice options\n * @internal 加入 specificKioskDeviceUid 主要是考虑到多台 kiosk 和 iPad 作为主 POS 情况下, iPad有可能没在运行 APP 的情况下, 需要指定 kiosk 设备来打印小票\n */\n directPayInvoice(invoice: IInvoice, till?: ITill, employee?: IEmployee, specificPrinter?: IPrinter, specificKioskDeviceUid?: string, kitchenPrintOverride?: boolean): Promise<DirectPayInvoiceOptions>;\n /**\n * Pays an invoice\n * @param invoice - The invoice to pay\n * @param sectionItem - The section item to associate with the invoice\n * @param till - (optional) The till to use for the payment\n * @param employee - (optional) The employee to associate with the invoice\n * @returns A promise that resolves with the paid invoice options\n */\n payInvoice(invoice: IInvoice, sectionItem: ISectionItem, till?: ITill, employee?: IEmployee): Promise<PayInvoiceOptions>;\n\n /**\n * Voids an invoice\n * @param invoice - The invoice to void\n * @param till - The till to use for the void\n * @param reason - The reason for the void\n * @returns A promise that resolves with the voided invoice options\n */\n voidInvoice(invoice: IInvoice, till?: ITill, reason?: string, employee?: IEmployee): Promise<VoidInvoiceOptions>;\n\n /**\n * duplicate an invoice\n * @param invoice the invoice to duplicate\n * @param employee the employee to associate with the invoice\n */\n duplicateInvoice(invoice: IInvoice, employee?: IEmployee): Promise<IInvoice>;\n\n /**\n * Switches an invoice from one section item to another\n * @param invoice - The invoice to switch\n * @param targetSectionItem - The target section item to switch to\n * @param sourceSectionItem - The source section item to switch from\n * @param employee - The employee to associate with the invoice\n * @returns A promise that resolves with the switched invoice options\n */\n switchInvoice(invoice: IInvoice, targetSectionItem: ISectionItem, sourceSectionItem: ISectionItem, employee?: IEmployee): Promise<SwitchInvoiceOptions>;\n\n reprintReceipt(invoice: IInvoice): Promise<IPrintJob>;\n\n createReceiptPrintJob(invoice: IInvoice, printerType: PrinterType, saveOnly?: boolean, printTimes?: number, specificPrinter?: IPrinter, specificDeviceUid?: string): Promise<PrintJob | null>;\n\n printLastKitchenSlips(invoiceUid: string): Promise<boolean>;\n\n /**\n * Adds a discount to an invoice\n * @param invoice - The invoice to add the discount to\n * @param discountType - The type of discount to add\n * @param amountOrPercent - The amount or percent of the discount\n * @param calcFlow - The calculation flow to use for the discount\n * @param name - The name of the discount\n * @param nameTranslations - The translations of the name\n * @returns The updated invoice with the added discount\n */\n addInvoiceDiscount(invoice: IInvoice, discountType: CalcType, amountOrPercent: number, calcFlow?: CalcFlow, name?: string, nameTranslations?: Record<string, string>): IInvoice;\n\n /**\n * Adds a coupon to an invoice\n * @param invoice - The invoice to add the coupon to\n * @param itemized - The coupon to add to the invoice\n * @param calcFlow - The calculation flow to use for the coupon\n * @returns The updated invoice with the added coupon\n */\n addCouponToInvoice(invoice: IInvoice, itemized: ICouponItemized, calcFlow?: CalcFlow): IInvoice;\n\n /**\n * Removes a discount from an invoice\n * @param invoice - The invoice to remove the discount from\n * @param discountUid - The uid of the discount to remove\n * @returns The updated invoice with the removed discount\n */\n removeInvoiceDiscount(invoice: IInvoice, discountUid: string): IInvoice;\n\n /**\n * Overwrites the note for an invoice\n * @param invoice - The invoice to overwrite the note for\n * @param note - The new note for the invoice\n * @returns The updated invoice with the new note\n */\n overwriteNoteToInvoice(invoice: IInvoice, note: string): IInvoice;\n\n /**\n * Adds a pax to an invoice\n * @param invoice - The invoice to add the pax to\n * @param pax - The pax to add to the invoice\n */\n addPaxToInvoice(invoice: IInvoice, pax: number): IInvoice;\n\n /**\n * Adds a customer to an invoice\n * @param invoice - The invoice to add the customer to\n * @param customer - The customer to add to the invoice\n */\n addCustomerToInvoice(invoice: IInvoice, customer: ICustomer): IInvoice;\n\n /**\n * Adds a payment to an invoice\n * @param invoice - The invoice to add the sales person to\n * @param salesUserUid - The sales person's uid to add to the invoice\n */\n addSalesPersonToInvoice(invoice: IInvoice, salesUserUid: string): IInvoice;\n\n /**\n * merge invoice from local db and invoice sent from signalr or online order\n * @param mainInvoice main invoice from local db\n * @param addOnInvoice incremental invoice from signalr or online order\n */\n appendInvoice(mainInvoice: IInvoice, addOnInvoice: IInvoice): IInvoice;\n\n /**\n * Merge sourceInvoice into targetInvoice\n * @param targetInvoice target invoice\n * @param sourceInvoice source invoice\n */\n mergeInvoice(targetInvoice: IInvoice, sourceInvoice: IInvoice): Promise<IInvoice>;\n\n /**\n * Queries invoices using the QueryBuilder to construct filter parameters\n * @param query QueryBuilder instance to build the query\n *\n * Example usage:\n * ```typescript\n * // Create a new query builder\n * const builder = new QueryBuilder<IInvoice>()\n *\n * // Add filter conditions:\n * builder\n * .addParam('status', 'Equals', InvoiceStatus.Paid) // Filter by status\n * .addParam('created_at', 'GreaterThan', '2023-01-01') // Filter by date\n * .addParam('customer_id', 'Equals', 123) // Filter by customer\n * .addParam('grand_total', 'GreaterThan', 100) // Filter by amount\n * .addParam('ref_id', 'Contains', 'INV') // Search by reference ID\n *\n * // Add sorting\n * builder.orderBy('created_at', 'DESC')\n *\n * // Add pagination\n * builder.skip(0).take(10)\n *\n * // Execute query\n * const response = await invoiceService.autoQuery(builder)\n * ```\n *\n * Common operators:\n * - Equals: Exact match\n * - Contains: Partial text match\n * - GreaterThan/LessThan: Numeric/date comparisons\n * - In: Match array of values\n *\n * @returns Promise<QueryResponse<IInvoice>> Response containing filtered invoices and total count\n */\n autoQuery<T extends Record<string, any> = Record<string, never>>(query: QueryBuilder<IInvoice & T>, options?: { timeout?: number }): Promise<QueryResponse<IInvoice>>;\n\n getRefId(): Promise<string>;\n\n /**\n * Change payments of an invoice\n * @param invoice invoice to change\n * @param payments payments to change\n */\n changePayments(invoice: IInvoice, options: IChangePaymentMethodOption[], shiftUid: string, userUid: string): Promise<IInvoice>;\n\n /**\n * Adds a charge to an invoice\n * @param invoice - The invoice to add the charge to\n * @param name - The name of the charge\n * @param percentage - The percentage of the charge (0 for flat amount)\n * @param amount - The flat amount of the charge (0 for percentage)\n * @param calcFlow - The calculation flow to use for the charge\n * @returns The updated invoice with the added charge\n */\n addInvoiceCharge(invoice: IInvoice, name: string, percentage: number, amount: number, calcFlow?: CalcFlow): IInvoice;\n\n /**\n * Removes a charge from an invoice\n * @param invoice - The invoice to remove the charge from\n * @param chargeUid - The uid of the charge to remove\n * @returns The updated invoice with the removed charge\n */\n removeInvoiceCharge(invoice: IInvoice, chargeUid: string): IInvoice;\n\n /**\n * Slices an invoice into multiple invoices where each invoice has a single line with quantity of 1\n * @param invoice - The invoice to slice\n * @returns An array of sliced invoices, one for each item quantity\n */\n sliceInvoice(invoice: IInvoice): IInvoice[];\n}\n\nexport class InvoiceOperationService extends LineOperationService implements IInvoiceOperationService {\n\n public async addInvoice(invoice: IInvoice): Promise<IInvoice> {\n const res : CustomResponse<IInvoice> = await this.http.put(`api/v5/merchants/${this.options.merchant_uid}/${this.moduleName}/add_invoice`, invoice);\n if (res.error == ErrorMsgs.outdatedInvoice) {\n await this.saveOne(res.data);\n throw new SystemError(res.error);\n } else if (res.error) throw new SystemError(res.error);\n return res.data;\n }\n\n public async createInvoice(invoice: IInvoice, sectionItem: ISectionItem, employee?: IEmployee): Promise<CreateInvoiceOptions> {\n invoice.status = InvoiceStatus.Open;\n // 如果没有ref_id,则生成一个\n if (!invoice.ref_id) invoice.ref_id = await this.getRefId();\n if (!invoice.call_num) invoice.call_num = invoice.ref_id.slice(-3);\n invoice.table_name = sectionItem.name;\n invoice.table_uid = sectionItem.uid;\n sectionItem.invoice_uid = invoice.uid;\n sectionItem.status = SectionItemStatus.OPENED;\n this.sectionItemService.syncInvoiceData(sectionItem, invoice);\n this.addEmployeeToInvoice(invoice, employee);\n invoice.created_at = new Date();\n invoice.created_at_timestamp = invoice.created_at.getTime();\n const datetimeFormat = (await this.configService.getDefaultOne()).config?.order?.datetime_format;\n invoice.humanized_created_at = humanizedData(invoice.created_at, datetimeFormat);\n sectionItem.invoice_created_at = new Date();\n const kitchenPrintJobs = await this.createKitchenPrintJobs(invoice);\n const labelPrintJobs = await this.createLabelPrintJobs(invoice);\n const orderPrintJobs = await this.createOrderPrintJobs(invoice);\n const printJobs = this.sortPrintJobsByPrinterSequence([...kitchenPrintJobs, ...labelPrintJobs, ...orderPrintJobs]);\n if (!invoice.kitchen_print_job_uids) invoice.kitchen_print_job_uids = [];\n if (!invoice.label_print_job_uids) invoice.label_print_job_uids = [];\n const previousKitchenUidsLength = invoice.kitchen_print_job_uids.length;\n const previousLabelUidsLength = invoice.label_print_job_uids.length;\n const kitchenUids = kitchenPrintJobs.map(job => job.uid);\n const labelUids = labelPrintJobs.map(job => job.uid);\n if (kitchenUids.length > 0) invoice.kitchen_print_job_uids.push(kitchenUids);\n if (labelUids.length > 0) invoice.label_print_job_uids.push(labelUids);\n await this.preprocessInvoice(invoice);\n const options: CreateInvoiceOptions = {\n invoice: invoice,\n section_item: sectionItem,\n };\n if (printJobs.length > 0) options.print_jobs = printJobs;\n try {\n const res: CustomResponse<any> = await this.http.put(`api/v5/merchants/${this.options.merchant_uid}/${this.moduleName}/${this.methodName}`, options);\n if (res.error == ErrorMsgs.outdatedInvoice) {\n await this.saveOne(res.data);\n options.invoice = res.data;\n throw new SystemError(res.error);\n } else if (res.error == ErrorMsgs.outdatedSectionItem) {\n await this.sectionItemService.saveOne(res.data);\n options.section_item = res.data;\n throw new SystemError(res.error);\n }\n return options;\n } catch (error) {\n invoice.kitchen_print_job_uids.length = previousKitchenUidsLength;\n invoice.label_print_job_uids.length = previousLabelUidsLength;\n throw error;\n }\n }\n public async updateInvoice(invoice: IInvoice, sectionItem: ISectionItem, employee?: IEmployee): Promise<UpdateInvoiceOptions> {\n this.sectionItemService.syncInvoiceData(sectionItem, invoice);\n this.addEmployeeToInvoice(invoice, employee);\n invoice.updated_at = new Date();\n const kitchenPrintJobs = await this.createKitchenPrintJobs(invoice);\n const cancelKitchenPrintJobs = await this.createCancelKitchenPrintJobs(invoice, invoice.deleted_lines);\n const labelPrintJobs = await this.createLabelPrintJobs(invoice);\n const orderPrintJobs = await this.createOrderPrintJobs(invoice);\n const printJobs = this.sortPrintJobsByPrinterSequence([...kitchenPrintJobs, ...cancelKitchenPrintJobs, ...labelPrintJobs, ...orderPrintJobs]);\n if (!invoice.kitchen_print_job_uids) invoice.kitchen_print_job_uids = [];\n if (!invoice.label_print_job_uids) invoice.label_print_job_uids = [];\n const previousKitchenUidsLength = invoice.kitchen_print_job_uids.length;\n const previousLabelUidsLength = invoice.label_print_job_uids.length;\n const kitchenUids = kitchenPrintJobs.map(job => job.uid);\n const labelUids = labelPrintJobs.map(job => job.uid);\n if (kitchenUids.length > 0) invoice.kitchen_print_job_uids.push(kitchenUids);\n if (labelUids.length > 0) invoice.label_print_job_uids.push(labelUids);\n await this.preprocessInvoice(invoice);\n const options: UpdateInvoiceOptions = {\n invoice: invoice,\n section_item: sectionItem,\n };\n if (printJobs.length > 0) options.print_jobs = printJobs;\n try {\n const res: CustomResponse<any> = await this.http.patch(`api/v5/merchants/${this.options.merchant_uid}/${this.moduleName}/update_invoice`, options);\n if (res.error == ErrorMsgs.outdatedInvoice) {\n await this.saveOne(res.data);\n throw new SystemError(`${res.error}, system has updated the data, please try again`);\n } else if (res.error == ErrorMsgs.outdatedSectionItem) {\n await this.sectionItemService.saveOne(res.data);\n options.section_item = res.data;\n throw new SystemError(`${res.error}, system has updated the data, please try again`);\n }\n return options;\n } catch (error) {\n invoice.kitchen_print_job_uids.length = previousKitchenUidsLength;\n invoice.label_print_job_uids.length = previousLabelUidsLength;\n throw error;\n }\n }\n public async cancelInvoice(invoice: IInvoice, sectionItem: ISectionItem, employee?: IEmployee): Promise<CancelInvoiceOptions> {\n if (invoice.id_in_server == 0 && invoice.lines.length <= 0) throw new SystemError('The invoice is empty and nothing can be canceled.');\n if (invoice.id_in_server == 0) {\n invoice.lines = [];\n return { invoice: invoice, section_item: sectionItem };\n }\n invoice.status = InvoiceStatus.Void;\n sectionItem.invoice_uid = '';\n sectionItem.status = SectionItemStatus.CLOSED;\n this.sectionItemService.reset(sectionItem);\n this.addEmployeeToInvoice(invoice, employee);\n const billPrintJob = await this.createReceiptPrintJob(invoice, PrinterType.ReceiptPrinter, true);\n const options: CancelInvoiceOptions = {\n invoice: invoice,\n section_item: sectionItem,\n };\n if (billPrintJob) options.print_jobs = [billPrintJob];\n const res: CustomResponse<any> = await this.http.post(`api/v5/merchants/${this.options.merchant_uid}/${this.moduleName}/cancel_invoice`, options);\n if (res.error == ErrorMsgs.outdatedInvoice) {\n await this.saveOne(res.data);\n options.invoice = res.data;\n throw new SystemError(res.error);\n } else if (res.error == ErrorMsgs.outdatedSectionItem) {\n await this.sectionItemService.saveOne(res.data);\n options.section_item = res.data;\n throw new SystemError(res.error);\n }\n return options;\n }\n public async checkInvoice(invoice: IInvoice, sectionItem: ISectionItem, employee?: IEmployee): Promise<CheckInvoiceOptions> {\n sectionItem.status = SectionItemStatus.PAYMENT;\n this.addEmployeeToInvoice(invoice, employee);\n const billPrintJob = await this.createReceiptPrintJob(invoice, PrinterType.CheckPrinter);\n const labelPrintJobs = await this.createLabelPrintJobs(invoice);\n const kitchenPrintJobs = await this.createKitchenPrintJobs(invoice);\n const orderPrintJobs = await this.createOrderPrintJobs(invoice);\n const unsortedPrintJobs = [...labelPrintJobs, ...kitchenPrintJobs, ...orderPrintJobs];\n if (billPrintJob) unsortedPrintJobs.push(billPrintJob);\n const printJobs = this.sortPrintJobsByPrinterSequence(unsortedPrintJobs);\n if (!invoice.kitchen_print_job_uids) invoice.kitchen_print_job_uids = [];\n if (!invoice.label_print_job_uids) invoice.label_print_job_uids = [];\n const previousKitchenUidsLength = invoice.kitchen_print_job_uids.length;\n const previousLabelUidsLength = invoice.label_print_job_uids.length;\n const kitchenUids = kitchenPrintJobs.map(job => job.uid);\n const labelUids = labelPrintJobs.map(job => job.uid);\n if (kitchenUids.length > 0) invoice.kitchen_print_job_uids.push(kitchenUids);\n if (labelUids.length > 0) invoice.label_print_job_uids.push(labelUids);\n await this.preprocessInvoice(invoice);\n const options: CheckInvoiceOptions = {\n invoice: invoice,\n section_item: sectionItem,\n };\n if (printJobs.length > 0) options.print_jobs = printJobs;\n try {\n const res: CustomResponse<any> = await this.http.post(`api/v5/merchants/${this.options.merchant_uid}/${this.moduleName}/check_invoice`, options);\n if (res.error == ErrorMsgs.outdatedInvoice) {\n await this.saveOne(res.data);\n options.invoice = res.data;\n throw new SystemError(res.error);\n } else if (res.error == ErrorMsgs.outdatedSectionItem) {\n await this.sectionItemService.saveOne(res.data);\n options.section_item = res.data;\n throw new SystemError(res.error);\n }\n return options;\n } catch (error) {\n invoice.kitchen_print_job_uids.length = previousKitchenUidsLength;\n invoice.label_print_job_uids.length = previousLabelUidsLength;\n throw error;\n }\n }\n public async switchInvoice(invoice: IInvoice, targetSectionItem: ISectionItem, sourceSectionItem: ISectionItem, employee?: IEmployee): Promise<SwitchInvoiceOptions> {\n if (targetSectionItem.uid == sourceSectionItem.uid) throw new SystemError('source and target table can not be the same');\n if (targetSectionItem.status != SectionItemStatus.CLOSED) throw new SystemError('target table is occupied');\n if (invoice.lines == null || invoice.lines.length <= 0) throw new SystemError('source table has nothing to switch');\n targetSectionItem.invoice_uid = invoice.uid;\n targetSectionItem.status = sourceSectionItem.status;\n this.sectionItemService.syncInvoiceData(targetSectionItem, invoice);\n sourceSectionItem.invoice_uid = '';\n sourceSectionItem.status = SectionItemStatus.CLOSED;\n this.sectionItemService.reset(sourceSectionItem);\n invoice.table_uid = targetSectionItem.uid;\n invoice.table_name = targetSectionItem.name;\n this.addEmployeeToInvoice(invoice, employee);\n const options: SwitchInvoiceOptions = {\n invoice: invoice,\n target_section_item: targetSectionItem,\n source_section_item: sourceSectionItem,\n };\n const res: CustomResponse<any> = await this.http.post(`api/v5/merchants/${this.options.merchant_uid}/${this.moduleName}/switch_invoice`, options);\n if (res.error == ErrorMsgs.outdatedInvoice) {\n await this.saveOne(res.data);\n options.invoice = res.data;\n throw new SystemError(res.error);\n } else if (res.error == ErrorMsgs.outdatedSourceSectionItem) {\n await this.sectionItemService.saveOne(res.data);\n options.source_section_item = res.data;\n throw new SystemError(res.error);\n } else if (res.error == ErrorMsgs.outdatedTargetSectionItem) {\n await this.sectionItemService.saveOne(res.data);\n options.target_section_item = res.data;\n throw new SystemError(res.error);\n }\n return options;\n }\n public async payInvoice(invoice: IInvoice, sectionItem: ISectionItem, till?: ITill, employee?: IEmployee): Promise<PayInvoiceOptions> {\n invoice.status = InvoiceStatus.Paid;\n sectionItem.invoice_uid = '';\n sectionItem.status = SectionItemStatus.CLOSED;\n this.sectionItemService.reset(sectionItem);\n this.addEmployeeToInvoice(invoice, employee);\n invoice.paid_at = new Date();\n const config = (await this.configService.getDefaultOne()).config;\n const datetimeFormat = config?.order?.datetime_format;\n invoice.humanized_paid_at = humanizedData(invoice.paid_at, datetimeFormat);\n invoice.payment_has_cash = invoice.payments?.some((payment) => payment.payment_method?.is_cash === true);\n const stockChanges = await this.getStockChangeList(invoice, false);\n const labelPrintJobs = await this.createLabelPrintJobs(invoice);\n const billPrintJob = await this.createReceiptPrintJob(invoice, PrinterType.ReceiptPrinter);\n const kitchenPrintJobs = await this.createKitchenPrintJobs(invoice);\n const cancelKitchenPrintJobs = await this.createCancelKitchenPrintJobs(invoice, invoice.deleted_lines);\n const orderPrintJobs = await this.createOrderPrintJobs(invoice);\n const unsortedPrintJobs = [...labelPrintJobs, ...kitchenPrintJobs, ...cancelKitchenPrintJobs, ...orderPrintJobs];\n if (billPrintJob) unsortedPrintJobs.push(billPrintJob);\n const printJobs = this.sortPrintJobsByPrinterSequence(unsortedPrintJobs);\n if (!invoice.kitchen_print_job_uids) invoice.kitchen_print_job_uids = [];\n if (!invoice.label_print_job_uids) invoice.label_print_job_uids = [];\n const previousKitchenUidsLength = invoice.kitchen_print_job_uids.length;\n const previousLabelUidsLength = invoice.label_print_job_uids.length;\n const kitchenUids = kitchenPrintJobs.map(job => job.uid);\n const labelUids = labelPrintJobs.map(job => job.uid);\n if (kitchenUids.length > 0) invoice.kitchen_print_job_uids.push(kitchenUids);\n if (labelUids.length > 0) invoice.label_print_job_uids.push(labelUids);\n await this.preprocessInvoice(invoice);\n const options: PayInvoiceOptions = {\n invoice: invoice,\n section_item: sectionItem,\n till: till,\n };\n if (printJobs.length > 0) options.print_jobs = printJobs;\n try {\n const res: CustomResponse<any> = await this.http.post(`api/v5/merchants/${this.options.merchant_uid}/${this.moduleName}/pay_invoice`, options);\n if (res.error == ErrorMsgs.outdatedInvoice) {\n await this.saveOne(res.data);\n options.invoice = res.data;\n throw new SystemError(`${res.error}, system has updated the data and please try again`);\n } else if (res.error == ErrorMsgs.outdatedSectionItem) {\n await this.sectionItemService.saveOne(res.data);\n options.section_item = res.data;\n throw new SystemError(`${res.error}, system has updated the data and please try again`);\n }\n if (stockChanges.length > 0) await this.itemService.changeItemsStock(stockChanges);\n if (invoice.call_num && config?.ods?.enabled) {\n const orderDisplay = new OrderDisplay();\n orderDisplay.order_number = invoice.call_num;\n await this.orderDisplayService.addOne(orderDisplay);\n }\n return options;\n } catch (error) {\n invoice.kitchen_print_job_uids.length = previousKitchenUidsLength;\n invoice.label_print_job_uids.length = previousLabelUidsLength;\n throw error;\n }\n }\n\n public async directPayInvoice(invoice: IInvoice, till?: ITill, employee?: IEmployee, specificPrinter?: IPrinter, specificKioskDeviceUid?: string, kitchenPrintOverride = false): Promise<DirectPayInvoiceOptions> {\n invoice.status = InvoiceStatus.Paid;\n if (employee != null) this.addEmployeeToInvoice(invoice, employee);\n invoice.paid_at = new Date();\n const config = (await this.configService.getDefaultOne()).config;\n const datetimeFormat = config?.order?.datetime_format;\n invoice.humanized_paid_at = humanizedData(invoice.paid_at, datetimeFormat);\n invoice.created_at = new Date();\n invoice.created_at_timestamp = invoice.created_at.getTime();\n invoice.humanized_created_at = humanizedData(invoice.created_at, datetimeFormat);\n // 如果没有ref_id,则生成一个\n if (!invoice.ref_id) invoice.ref_id = await this.getRefId();\n if (!invoice.call_num) invoice.call_num = invoice.ref_id.slice(-3);\n invoice.payment_has_cash = invoice.payments?.some((payment) => payment.payment_method?.is_cash === true);\n const stockChanges = await this.getStockChangeList(invoice, false);\n let receiptPrintJob: IPrintJob = null;\n let kioskPrintJob: IPrintJob = null;\n if (specificPrinter && specificPrinter.type == PrinterType.KioskPrinter) {\n receiptPrintJob = await this.createReceiptPrintJob(invoice, PrinterType.ReceiptPrinter);\n kioskPrintJob = await this.createReceiptPrintJob(invoice, PrinterType.KioskPrinter, false, 0, specificPrinter, specificKioskDeviceUid);\n } else {\n receiptPrintJob = await this.createReceiptPrintJob(invoice, PrinterType.ReceiptPrinter, false, 0, specificPrinter);\n }\n const labelPrintJobs = await this.createLabelPrintJobs(invoice);\n const kitchenPrintJobs = await this.createKitchenPrintJobs(invoice, kitchenPrintOverride);\n const orderPrintJobs = await this.createOrderPrintJobs(invoice);\n const unsortedPrintJobs = [...labelPrintJobs, ...kitchenPrintJobs, ...orderPrintJobs];\n if (receiptPrintJob) unsortedPrintJobs.push(receiptPrintJob);\n if (kioskPrintJob) unsortedPrintJobs.push(kioskPrintJob);\n const printJobs = this.sortPrintJobsByPrinterSequence(unsortedPrintJobs);\n const kitchenUids = kitchenPrintJobs.map(job => job.uid);\n const labelUids = labelPrintJobs.map(job => job.uid);\n if (kitchenUids.length > 0) invoice.kitchen_print_job_uids = [kitchenUids];\n if (labelUids.length > 0) invoice.label_print_job_uids = [labelUids];\n await this.preprocessInvoice(invoice);\n const options: DirectPayInvoiceOptions = {\n invoice: invoice,\n till: till,\n };\n if (printJobs.length > 0) options.print_jobs = printJobs;\n const res: CustomResponse<any> = await this.http.put(`api/v5/merchants/${this.options.merchant_uid}/${this.moduleName}/direct_pay_invoice`, options);\n if (res.error == ErrorMsgs.outdatedInvoice) {\n await this.saveOne(res.data);\n options.invoice = res.data;\n throw new SystemError(res.error);\n }\n if (stockChanges.length > 0) await this.itemService.changeItemsStock(stockChanges);\n if (invoice.call_num && config?.ods?.enabled) {\n const orderDisplay = new OrderDisplay();\n orderDisplay.order_number = invoice.call_num;\n await this.orderDisplayService.addOne(orderDisplay);\n }\n return options;\n }\n\n public async voidInvoice(invoice: IInvoice, till?: ITill, reason?: string, employee?: IEmployee): Promise<VoidInvoiceOptions> {\n if (reason) invoice.etc['void_reason'] = reason;\n const originalStatus = invoice.status;\n invoice.status = InvoiceStatus.Void;\n invoice.voided_at = new Date();\n const datetimeFormat = (await this.configService.getDefaultOne()).config?.order?.datetime_format;\n invoice.humanized_voided_at = humanizedData(invoice.voided_at, datetimeFormat);\n if(till) till.deleted_at = new Date();\n // Delete Till records for cash payments\n if (invoice.payments?.some(p => p.payment_method?.is_cash)) await this.tillService.deleteByInvoiceUid(invoice.uid);\n this.addEmployeeToInvoice(invoice, employee);\n const config = (await this.configService.getDefaultOne()).config;\n const receiptPrintJob = await this.createReceiptPrintJob(invoice, PrinterType.ReceiptPrinter, true);\n let kitchenPrintJobs = [];\n if (config.kitchen.print_cancel_whole_invoice) kitchenPrintJobs = await this.createCancelKitchenPrintJobs(invoice, invoice.lines) || [];\n const printJobs = [...kitchenPrintJobs];\n if (receiptPrintJob) printJobs.push(receiptPrintJob);\n const options: VoidInvoiceOptions = {\n invoice: invoice,\n till: till,\n };\n if (printJobs.length > 0) options.print_jobs = printJobs;\n // section item\n if (invoice.table_uid) {\n const sectionItem = await this.sectionItemService.getOne(invoice.table_uid);\n if (sectionItem.status != SectionItemStatus.CLOSED) {\n sectionItem.invoice_uid = '';\n sectionItem.status = SectionItemStatus.CLOSED;\n options.section_item = sectionItem;\n }\n }\n let stockChanges = [];\n if (originalStatus == InvoiceStatus.Paid) stockChanges = await this.getStockChangeList(invoice);\n const res: CustomResponse<any> = await this.http.post(`api/v5/merchants/${this.options.merchant_uid}/${this.moduleName}/void_invoice`, options);\n if (res.error == ErrorMsgs.outdatedInvoice) {\n await this.saveOne(res.data);\n options.invoice = res.data;\n throw new SystemError(res.error);\n }\n else if (stockChanges.length > 0) await this.itemService.changeItemsStock(stockChanges);\n return options;\n }\n public async duplicateInvoice(invoice: IInvoice, employee?: IEmployee): Promise<IInvoice> {\n if (invoice.status != InvoiceStatus.Paid) throw new SystemError('invalid invoice status');\n const cInvoice = _.cloneDeep(invoice);\n cInvoice.etc['is_duplicate'] = true;\n cInvoice.etc['duplicated_from_uid'] = cInvoice.uid;\n cInvoice.uid = ModelPrefix.Invoice + nanoid();\n cInvoice.status = InvoiceStatus.Open;\n cInvoice.ref_id = await this.getRefId();\n this.addEmployeeToInvoice(cInvoice, employee);\n if (cInvoice.lines) {\n for (const line of cInvoice.lines) {\n line.uid = ModelPrefix.InvoiceLine + nanoid();\n }\n }\n if (cInvoice.payments) {\n for (const payment of cInvoice.payments) {\n payment.uid = ModelPrefix.Payment + nanoid();\n }\n }\n return cInvoice;\n }\n public async reprintReceipt(invoice: IInvoice, saveOnly = false): Promise<IPrintJob> {\n if (!invoice?.receipt_print_job_uid) throw new SystemError('The invoice does not have a receipt');\n let printJob = await this.printJobService.getOne(invoice.receipt_print_job_uid);\n if (!printJob) {\n const builder = new QueryBuilder<IPrintJob>().addParam('uid','EqualTo', invoice.receipt_print_job_uid);\n const response = await this.printJobService.autoquery(builder);\n if (!response.results || response.results.length <= 0) throw new SystemError('The invoice does not have a receipt');\n printJob = response.results[0];\n }\n let printer = await this.printerService.getOne(printJob.printer_uid);\n if (!printer) printer = await this.printerService.getDefaultReceiptPrinter();\n if (!printer) throw new SystemError('Receipt printer not found');\n printJob = this.printJobService.replacePrinter(printJob, printer);\n // set save only to false and print.\n printJob.uid = ModelPrefix.PrintJob + nanoid();\n printJob.save_only = saveOnly;\n printJob.status = PrintJobStatus.Queued;\n printJob.print_times = 1;\n printJob.printed = 0;\n printJob.retries = 0;\n await this.printJobService.addOne(printJob);\n return printJob;\n }\n public async printLastKitchenSlips(invoiceUid: string): Promise<boolean> {\n const invoice = await this.getOne(invoiceUid);\n if (!invoice) throw new SystemError('Invoice not found');\n const kitchenUids = invoice.kitchen_print_job_uids?.[invoice.kitchen_print_job_uids.length - 1] || [];\n const labelUids = invoice.label_print_job_uids?.[invoice.label_print_job_uids.length - 1] || [];\n const allUids = [...kitchenUids, ...labelUids];\n if (allUids.length === 0) throw new SystemError('No kitchen or label print found');\n const builder = new QueryBuilder<IPrintJob>().addParam('uid', 'In', allUids);\n const response = await this.printJobService.autoquery(builder);\n if (!response.results || response.results.length === 0) throw new SystemError('Print jobs not found');\n for (const printJob of response.results) {\n const printer = await this.printerService.getOne(printJob.printer_uid);\n if (!printer) continue;\n const updatedJob = this.printJobService.replacePrinter(printJob, printer);\n const parentUid = updatedJob.uid;\n updatedJob.uid = ModelPrefix.PrintJob + nanoid();\n updatedJob.save_only = false;\n updatedJob.status = PrintJobStatus.Queued;\n updatedJob.print_times = 1;\n updatedJob.printed = 0;\n updatedJob.retries = 0;\n if (!updatedJob.meta) updatedJob.meta = {};\n updatedJob.meta.is_reprint = true;\n updatedJob.meta.parent_uid = parentUid;\n await this.printJobService.addOne(updatedJob);\n }\n return true;\n }\n public addInvoiceDiscount(invoice: IInvoice, discountType: CalcType, amountOrPercent: number, calcFlow = CalcFlow.AfterSubtotal, name = 'custom', nameTranslations: Record<string, string> = {}): IInvoice {\n if (!invoice.discounts) invoice.discounts = [];\n if (discountType == CalcType.Percent && amountOrPercent > 100) throw new SystemError('Discount percent can not be more than 100%');\n //if (discountType == CalcType.Flat && amountOrPercent > invoice.grand_total) throw new SystemError('Discount amount can not be more than total amount due');\n const discount = new InvoiceDiscount();\n discount.calc_type = discountType;\n discount.calc_flow = calcFlow;\n discount.name = name;\n discount.name_translation = nameTranslations;\n if (discountType == CalcType.Flat) discount.amount = amountOrPercent;\n else discount.percent = amountOrPercent;\n invoice.discounts.push(discount);\n return invoice;\n }\n\n public addCouponToInvoice(invoice:IInvoice, itemized: ICouponItemized, calcFlow = CalcFlow.AfterSubtotal): IInvoice {\n if (!invoice.discounts) invoice.discounts = [];\n const discount = new InvoiceDiscount();\n discount.calc_type = itemized.coupon.discount_calc_type == 1 ? CalcType.Flat : CalcType.Percent;\n discount.calc_flow = calcFlow;\n discount.name = itemized.coupon.name;\n if (discount.calc_type == CalcType.Flat) discount.amount = itemized.coupon.discount_amount;\n else discount.percent = itemized.coupon.discount_percent;\n discount.coupon_uid = itemized.guid;\n if(itemized.coupon.applying_plus.applying_items?.length > 0) {\n discount.applying_item_uids = itemized.coupon.applying_plus.applying_items;\n if(!invoice.lines) throw new SystemError('Coupon can not applied to any product in this order');\n const matchingUids = _.intersection(discount.applying_item_uids, invoice.lines.map(line => line.item_uid));\n if(matchingUids.length === 0) throw new SystemError('Coupon can not applied to any product in this order');\n }\n invoice.discounts.push(discount);\n return invoice;\n }\n public removeInvoiceDiscount(invoice: IInvoice, discountUid: string): IInvoice {\n if (!invoice.discounts) return invoice;\n invoice.discounts = invoice.discounts.filter((x) => x.uid !== discountUid);\n return invoice;\n }\n public overwriteNoteToInvoice(invoice: IInvoice, note: string): IInvoice {\n if (!note) return invoice;\n invoice.remark = note;\n return invoice;\n }\n public addSalesPersonToInvoice(invoice: IInvoice, salesUserUid: string): IInvoice {\n invoice.sales_user_uid = salesUserUid;\n return invoice;\n }\n public addPaxToInvoice(invoice: IInvoice, pax: number): IInvoice {\n invoice.pax = pax;\n return invoice;\n }\n public addCustomerToInvoice(invoice: IInvoice, customer: ICustomer): IInvoice {\n if (!customer) throw new SystemError('Customer object can not be null');\n invoice.customer_id = customer.id;\n invoice.customer = _.cloneDeep(customer);\n return invoice;\n }\n public async autoQuery<T extends Record<string, any> = Record<string, never>>(query: QueryBuilder<IInvoice & T>, options?: { timeout?: number }): Promise<QueryResponse<IInvoice>> {\n return await this.http.get(`sapi/v5/merchants/${this.options.merchant_uid}/${this.moduleName}`, { params: query.build(), ...options });\n }\n public appendInvoice(mainInvoice: IInvoice, addOnInvoice: IInvoice): IInvoice {\n if(mainInvoice?.id_in_server == 0) return addOnInvoice;\n // append lines\n for (const line of addOnInvoice.lines) {\n if (line.is_combo || line.is_combo_item) {\n if (line.quantity > 0) mainInvoice.lines.push(line);\n } else {\n const resultLine = this.findOrCreateLine(mainInvoice, line.item, line.quantity, line.price, line.modifiers, line.remark);\n if (resultLine.uid) resultLine.quantity += line.quantity;\n else if (line.quantity > 0) mainInvoice.lines.push(line);\n }\n }\n // append remark\n if (addOnInvoice.remark) mainInvoice.remark = addOnInvoice.remark;\n\n // 处理 customer_id\n if (addOnInvoice.customer_id && !mainInvoice.customer_id) mainInvoice.customer_id = addOnInvoice.customer_id;\n return mainInvoice;\n }\n\n public async mergeInvoice(targetInvoice: IInvoice, sourceInvoice: IInvoice): Promise<IInvoice> {\n if(sourceInvoice.lines?.length == 0) throw new SystemError('Source invoice has no nothing to merge');\n if(sourceInvoice.lines.some(x=>x.quantity != x.sent)) throw new SystemError('Please send first before merging');\n const targetInvoiceFromDb = await this.getOne(targetInvoice.uid);\n if(!targetInvoiceFromDb) throw new SystemError('Target invoice not found');\n const sourceInvoiceFromDb = await this.getOne(sourceInvoice.uid);\n if(!sourceInvoiceFromDb) throw new SystemError('Source invoice not found');\n if(targetInvoice?.id_in_server == 0) throw new SystemError('Target invoice is not synced to server');\n if(sourceInvoice?.id_in_server == 0) throw new SystemError('Source invoice is not synced to server');\n // merge lines\n for (const line of sourceInvoice.lines) {\n if (line.is_combo || line.is_combo_item) {\n if (line.quantity > 0) targetInvoice.lines.push(line);\n } else {\n const resultLine = this.findOrCreateLine(targetInvoice, line.item, line.quantity, line.price, line.modifiers, line.remark);\n if (resultLine.uid) resultLine.quantity += line.quantity;\n else if (line.quantity > 0) targetInvoice.lines.push(line);\n }\n }\n \n // merge customer_id\n if (!targetInvoice.customer_id) targetInvoice.customer_id = sourceInvoice.customer_id;\n return targetInvoice;\n }\n public async getRefId(): Promise<string> {\n const config = await this.configService.getDefaultOne();\n const prefix = config.config?.order?.ref_prefix || '01';\n const response: CustomResponse<number> = await this.http.get(`api/v5/merchants/${this.options.merchant_uid}/${this.moduleName}/${(this, this.methodName)}/get_invoice_counter`);\n const invoiceCounter = response.data.toString().padStart(9, '0');\n const date = this.formatDate(new Date());\n return `${prefix}${date}${invoiceCounter}`;\n }\n public async changePayments(invoice: IInvoice, options: IChangePaymentMethodOption[], shiftUid: string, userUid: string): Promise<IInvoice> {\n if (invoice.status != InvoiceStatus.Paid) throw new SystemError('invalid invoice status');\n if (!options || options.length < 1) throw new SystemError('invalid options');\n for (const option of options) {\n const payment = invoice.payments.find((x) => x.uid == option.source_payment.uid);\n if (!payment) throw new SystemError('payment not found');\n if (option.source_payment.payment_method?.is_cash) await this.tillService.deleteByInvoiceUid(invoice.uid);\n if (option.target_payment_method.is_cash) {\n const till = this.tillService.createCashInvoiceTill([option.source_payment], shiftUid, userUid, '', invoice.uid);\n await this.tillService.addOne(till);\n }\n payment.payment_method_uid = option.target_payment_method.uid;\n payment.payment_method_code = option.target_payment_method.payment_method_code;\n payment.payment_method_name = option.target_payment_method.name;\n payment.payment_method = _.cloneDeep(option.target_payment_method);\n payment.payment_method_history = _.cloneDeep(option.target_payment_method) as IPaymentMethodHistory;\n payment.payment_method_history.changed_at = new Date();\n }\n return invoice;\n }\n private formatDate(date: Date): string {\n const year = date.getFullYear().toString().slice(-2);\n const month = (date.getMonth() + 1).toString().padStart(2, '0');\n const day = date.getDate().toString().padStart(2, '0');\n return year + month + day;\n }\n\n private addEmployeeToInvoice(invoice: IInvoice, employee: IEmployee): IInvoice {\n if (!employee) return invoice;\n invoice.employee_uid = employee.uid;\n invoice.employee_name = employee.name;\n return invoice;\n }\n public async createReceiptPrintJob(\n invoice: IInvoice,\n printerType: PrinterType,\n saveOnly = false,\n printTimes = 0,\n specificPrinter: IPrinter = null,\n specificDeviceUid?: string,\n ): Promise<PrintJob | null> {\n let printer: IPrinter;\n if (specificPrinter) printer = specificPrinter;\n else if (printerType == PrinterType.ReceiptPrinter || printerType == PrinterType.CheckPrinter) {\n const sectionItem = invoice.table_uid ? await this.sectionItemService.getOne(invoice.table_uid) : null;\n const printerUid = printerType == PrinterType.ReceiptPrinter ? sectionItem?.receipt_printer_uid : sectionItem?.check_printer_uid;\n if (printerUid) printer = await this.printerService.getOne(printerUid);\n if (!printer) printer = printerType == PrinterType.ReceiptPrinter\n ? await this.printerService.getDefaultReceiptPrinter()\n : await this.printerService.getDefaultCheckPrinter();\n }\n if (!printer || !printer.print_template_uid) return null;\n if (!printTimes) printTimes = printer.print_times;\n const appConfig = await this.configService.getDefaultOne();\n const template = await this.printTemplateService.getOneByParams({ uid: printer.print_template_uid });\n if (!template) throw new SystemError('Print template not found');\n // 如果receipt enabled = false,则不打印,只保存\n if (printerType == PrinterType.ReceiptPrinter && !appConfig.config?.receipt?.enabled) saveOnly = true;\n const printCommand = await this.printTemplateService.renderPrintTemplate(invoice, appConfig.config, template, { ...new RenderPrintTemplateOptions(), printer_name: printer.name });\n const printJob = new PrintJob(printer, printCommand, saveOnly, printTimes);\n if (printerType != PrinterType.ReceiptPrinter) printJob.printer_type = printerType;\n if (printer.connection_type != PrinterConnections.ETHERNET) printJob.connection_type = printer.connection_type;\n if (printerType == PrinterType.ReceiptPrinter) invoice.receipt_print_job_uid = printJob.uid;\n if (specificDeviceUid) printJob.device_uid_to_print = specificDeviceUid;\n return printJob;\n }\n\n private sortLinesByItemSequence(lines: IInvoiceLine[]): IInvoiceLine[] {\n return _.chain(lines || [])\n .groupBy(l => l.is_combo_item ? l.combo_line_uid : l.uid)\n .map(g => _.sortBy(g, [l => !l.is_combo, l => l.item.printing_sequence || l.item.sequence || 999999]))\n .sortBy(g => g[0].item.printing_sequence || g[0].item.sequence || 999999)\n .flatten()\n .value();\n }\n\n private async createKitchenPrintJobs(invoice: IInvoice, override = false): Promise<IPrintJob[] | []> {\n const config = (await this.configService.getDefaultOne()).config;\n if (!config.kitchen.enabled && !override) return [];\n if (invoice.lines.every((x) => x.sent == x.quantity)) return [];\n const printJobs: IPrintJob[] = [];\n const { lines, printerUids } = this.filterLinesAndPrintersToPrint(invoice.lines, PrinterType.KitchenPrinter);\n const printers = await this.printerService.getPrintersByUids(printerUids);\n for (const printer of printers) {\n const template = await this.printTemplateService.getOneByParams({ uid: printer.print_template_uid });\n if (!template) continue;\n const filteredLines = lines.filter((x) => x.item.kitchen_printers_uids.includes(printer.uid));\n const sortedLines = this.sortLinesByItemSequence(filteredLines);\n const clonedInvoice = _.cloneDeep(invoice);\n // itemized printing\n if (printer.kitchen_itemized_print) {\n for (const line of sortedLines) {\n clonedInvoice.lines = [line];\n const printCommand = await this.printTemplateService.renderPrintTemplate(clonedInvoice, config, template, { ...new RenderPrintTemplateOptions(), printer_name: printer.name });\n const printJob = new PrintJob(printer, printCommand, false, printer.print_times);\n printJobs.push(printJob);\n }\n }\n // batch printing\n else {\n clonedInvoice.lines = sortedLines;\n const printCommand = await this.printTemplateService.renderPrintTemplate(clonedInvoice, config, template, { ...new RenderPrintTemplateOptions(), printer_name: printer.name });\n const printJob = new PrintJob(printer, printCommand, false, printer.print_times);\n printJobs.push(printJob);\n }\n }\n return printJobs;\n }\n\n private async createOrderPrintJobs(invoice: IInvoice): Promise<IPrintJob[] | []> {\n const config = (await this.configService.getDefaultOne()).config;\n if (!config.receipt.print_docket) return [];\n if (invoice.lines.every((x) => x.sent == x.quantity)) return [];\n const printJobs: IPrintJob[] = [];\n const { lines, printerUids } = this.filterLinesAndPrintersToPrint(invoice.lines, PrinterType.OrderPrinter);\n const sectionItem = invoice.table_uid ? await this.sectionItemService.getOne(invoice.table_uid) : null;\n const printers = await this.printerService.getPrintersByUids(printerUids);\n for (const printer of printers) {\n if (sectionItem?.order_printer_uids?.length > 0 && !sectionItem.order_printer_uids.includes(printer.uid)) continue;\n const template = await this.printTemplateService.getOneByParams({ uid: printer.print_template_uid });\n if (!template) continue;\n const filteredLines = lines.filter((x) => x.item.order_printers_uids.includes(printer.uid));\n const sortedLines = this.sortLinesByItemSequence(filteredLines);\n const clonedInvoice = _.cloneDeep(invoice);\n clonedInvoice.lines = sortedLines;\n const printCommand = await this.printTemplateService.renderPrintTemplate(clonedInvoice, config, template, { ...new RenderPrintTemplateOptions(), printer_name: printer.name });\n const printJob = new PrintJob(printer, printCommand, false, printer.print_times);\n printJobs.push(printJob);\n }\n return printJobs;\n }\n\n private async createLabelPrintJobs(invoice: IInvoice): Promise<IPrintJob[] | []> {\n const config = (await this.configService.getDefaultOne()).config;\n if (invoice.lines.every((x) => x.sent == x.quantity)) return [];\n const printJobs: IPrintJob[] = [];\n const { lines, printerUids } = this.filterLinesAndPrintersToPrint(invoice.lines, PrinterType.LabelPrinter);\n if (printerUids.length == 0 || lines.length == 0) return [];\n const printers = await this.printerService.getPrintersByUids(printerUids);\n const clonedInvoice = _.cloneDeep(invoice);\n const totalIndex = lines.length;\n let index = 1;\n for (const line of lines) {\n line.meta.total_index = totalIndex;\n line.meta.index = index;\n if (line.modifiers?.length && line.item.modifiers?.length) {\n const seqMap = new Map(line.item.modifiers.map(m => [m.uid, m.sequence ?? 0]));\n line.modifiers.sort((a, b) => (seqMap.get(a.item_uid) ?? 0) - (seqMap.get(b.item_uid) ?? 0));\n }\n index++;\n }\n for (const printer of printers) {\n for (const line of lines) {\n if (!line.item.label_printers_uids.includes(printer.uid)) continue;\n const template = await this.printTemplateService.getOneByParams({ uid: printer.print_template_uid });\n if (!template) continue;\n if (!template.commands) continue;\n const commandTemplate = Handlebars.compile(template.commands);\n clonedInvoice.lines = [line];\n const printCommand = commandTemplate({ invoice: clonedInvoice, config });\n const printJob = new PrintJob(printer, new PrintCommand(), false, printer.print_times);\n printJob.commands = printCommand;\n printJobs.push(printJob);\n }\n }\n return printJobs;\n }\n\n public filterLinesAndPrintersToPrint(invoiceLines: IInvoiceLine[], printerType: PrinterType): { lines: IInvoiceLine[]; printerUids: string[] } {\n let printerUidsKey: string;\n switch (printerType) {\n case PrinterType.KitchenPrinter:\n printerUidsKey = 'kitchen_printers_uids';\n break;\n case PrinterType.OrderPrinter:\n printerUidsKey = 'order_printers_uids';\n break;\n case PrinterType.LabelPrinter:\n printerUidsKey = 'label_printers_uids';\n break;\n default:\n printerUidsKey = 'kitchen_printers_uids';\n }\n\n const lines: IInvoiceLine[] = [];\n const printerUidsSet: Set<string> = new Set();\n for (const line of invoiceLines) {\n if (line.quantity <= line.sent) continue;\n else if (!line.item[printerUidsKey] || line.item[printerUidsKey].length == 0) continue;\n else {\n line.item[printerUidsKey].forEach((uid) => printerUidsSet.add(uid));\n const clonedLine = _.cloneDeep(line);\n clonedLine.quantity = clonedLine.quantity - clonedLine.sent;\n if (printerType == PrinterType.LabelPrinter) {\n for (let i = 0; i < clonedLine.quantity; i++) {\n const singleLine = _.cloneDeep(clonedLine);\n singleLine.quantity = 1;\n lines.push(singleLine);\n }\n } else lines.push(clonedLine);\n }\n }\n const printerUids: string[] = Array.from(printerUidsSet);\n return { lines, printerUids };\n }\n\n private filterDeletedLinesForCancelPrint(deletedLines: IInvoiceLine[]): { lines: IInvoiceLine[]; printerUids: string[] } {\n const lines: IInvoiceLine[] = [];\n const printerUidsSet: Set<string> = new Set();\n for (const line of deletedLines) {\n if (line.is_cancel_printed) continue;\n if (!line.item.kitchen_printers_uids || line.item.kitchen_printers_uids.length == 0) continue;\n line.item.kitchen_printers_uids.forEach((uid) => printerUidsSet.add(uid));\n const clonedLine = _.cloneDeep(line);\n lines.push(clonedLine);\n }\n return { lines, printerUids: Array.from(printerUidsSet) };\n }\n\n private async createCancelKitchenPrintJobs(invoice: IInvoice, linesToPrint: IInvoiceLine[]): Promise<IPrintJob[]> {\n const config = (await this.configService.getDefaultOne()).config;\n if (!config.kitchen.print_cancel_slip) return [];\n if (!linesToPrint || linesToPrint.length === 0) return [];\n const { lines, printerUids } = this.filterDeletedLinesForCancelPrint(linesToPrint);\n if (lines.length === 0) return [];\n const printers = await this.printerService.getPrintersByUids(printerUids);\n const printJobs: IPrintJob[] = [];\n for (const printer of printers) {\n const template = await this.printTemplateService.getOneByParams({ uid: printer.print_template_uid });\n if (!template) continue;\n const filteredLines = lines.filter((x) => x.item.kitchen_printers_uids.includes(printer.uid));\n const sortedLines = this.sortLinesByItemSequence(filteredLines);\n const clonedInvoice = _.cloneDeep(invoice);\n if (printer.kitchen_itemized_print) {\n for (const line of sortedLines) {\n clonedInvoice.lines = [line];\n const printCommand = await this.printTemplateService.renderPrintTemplate(clonedInvoice, config, template, { printer_name: printer.name, kitchen_itemized_print: printer.kitchen_itemized_print, is_cancel: true });\n const printJob = new PrintJob(printer, printCommand, false, printer.print_times);\n printJobs.push(printJob);\n }\n } else {\n clonedInvoice.lines = sortedLines;\n const printCommand = await this.printTemplateService.renderPrintTemplate(clonedInvoice, config, template, { printer_name: printer.name, kitchen_itemized_print: printer.kitchen_itemized_print, is_cancel: true });\n const printJob = new PrintJob(printer, printCommand, false, printer.print_times);\n printJobs.push(printJob);\n }\n }\n for (const line of invoice.deleted_lines) line.is_cancel_printed = true;\n return printJobs;\n }\n\n /**\n * Sorts print jobs by printer sequence\n * @param printJobs - Array of print jobs to sort\n * @returns Sorted array of print jobs (lower sequence number prints first)\n */\n private sortPrintJobsByPrinterSequence(printJobs: IPrintJob[]): IPrintJob[] {\n return printJobs.sort((a, b) => {\n const seqA = a?.print_sequence ?? 999;\n const seqB = b?.print_sequence ?? 999;\n return seqA - seqB;\n });\n }\n\n private async preprocessInvoice(invoice: IInvoice): Promise<IInvoice> {\n if (invoice.lines) {\n for (const line of invoice.lines) {\n line.sent = line.quantity; // mark all lines as sent\n }\n }\n return invoice;\n }\n\n /**\n * Adds a charge to an invoice\n * @param invoice - The invoice to add the charge to\n * @param name - The name of the charge\n * @param percentage - The percentage of the charge (0 for flat amount)\n * @param amount - The flat amount of the charge (0 for percentage)\n * @param calcFlow - The calculation flow to use for the charge\n * @returns The updated invoice with the added charge\n */\n public addInvoiceCharge(invoice: IInvoice, name: string, percentage: number, amount: number, calcFlow = CalcFlow.AfterSubtotal): IInvoice {\n if (!invoice.charges) invoice.charges = [];\n const charge = new InvoiceCharge();\n charge.name = name;\n charge.percentage = percentage;\n charge.amount = amount;\n charge.calc_flow = calcFlow;\n invoice.charges.push(charge);\n return invoice;\n }\n\n /**\n * Removes a charge from an invoice\n * @param invoice - The invoice to remove the charge from\n * @param chargeUid - The uid of the charge to remove\n * @returns The updated invoice with the removed charge\n */\n public removeInvoiceCharge(invoice: IInvoice, chargeUid: string): IInvoice {\n if (!invoice.charges) return invoice;\n invoice.charges = invoice.charges.filter((x) => x.uid !== chargeUid);\n return invoice;\n }\n\n /**\n * Creates a list of stock changes for all items in an invoice when it is paid.\n * Returns stock changes with negative quantities for each item and their modifiers.\n * Consolidates multiple entries for the same item_uid by summing quantities.\n * @param invoice - The paid invoice containing items to create stock changes for\n * @private\n */\n private async getStockChangeList(invoice: IInvoice, increment = true): Promise<TStockChange[] | []> {\n if (!invoice.lines || invoice.lines.length === 0) return [];\n const operator = increment ? 1 : -1;\n const stockChangeMap = new Map<string, TStockChange>();\n \n for (const line of invoice.lines) {\n // Get or create stockChange for this item\n const stockChange = stockChangeMap.get(line.item_uid) || new StockChange(line.item_uid);\n stockChange.quantity = stockChange.quantity + line.quantity * operator;\n \n if (line.modifiers && line.modifiers.length > 0) {\n for (const modifier of line.modifiers) {\n // Find existing modifier in the stockChange or create new one\n let existingModifier = stockChange.modifiers.find(m => m.item_uid === modifier.item_uid);\n if (!existingModifier) {\n existingModifier = { item_uid: modifier.item_uid, quantity: 0 };\n stockChange.modifiers.push(existingModifier);\n }\n existingModifier.quantity = existingModifier.quantity + (line.quantity * modifier.quantity * operator);\n }\n }\n stockChangeMap.set(line.item_uid, stockChange);\n }\n return Array.from(stockChangeMap.values());\n }\n\n /**\n * Slices an invoice into multiple invoices where each invoice has a single line with quantity of 1\n * @param invoice - The invoice to slice\n * @returns An array of sliced invoices, one for each item quantity\n */\n public sliceInvoice(invoice: IInvoice): IInvoice[] {\n if (!invoice || !invoice.lines || invoice.lines.length === 0) return [];\n const slicedInvoices: IInvoice[] = [];\n for (const line of invoice.lines) {\n for (let i = 0; i < line.quantity; i++) {\n const slicedInvoice = _.cloneDeep(invoice);\n const slicedLine = _.cloneDeep(line);\n slicedLine.quantity = 1;\n slicedInvoice.lines = [slicedLine];\n slicedInvoices.push(slicedInvoice);\n }\n }\n return slicedInvoices;\n }\n}\n\nexport type IInvoiceService = IInvoiceOperationService;\n\nexport class InvoiceService extends InvoiceOperationService implements IInvoiceService {}\n\n","import { Employee, IEmployee } from '../types/employee.type';\nimport { IEmployeeRole } from '../types/role.type';\nimport { AppRemoteService, IAppRemoteService, IAppModelSequence } from './abstract.service';\nimport {\n IAppConfig,\n IConfig,\n UpdateGeneralConfigOptions,\n GeneralConfig,\n AppConfig,\n TillConfig,\n ReportConfig,\n Receipt,\n KitchenConfig,\n KdsConfig,\n LabelConfig,\n OrderConfig,\n PaymentConfig,\n UserConfig,\n TaxConfig,\n RoundingConfig,\n ChargeConfig,\n CurrencyConfig,\n InventoryConfig,\n PaxConfig,\n GTOConfig,\n CashDrawerConfig,\n MarketingConfig,\n ICache,\n} from '../types/config.type';\nimport { IPrintJob, IPrintTemplate, IPrinter, IRenderPrintTemplateOptions, PrintTemplate, PrinterType, RenderPrintTemplateOptions, ITemplateData, PrintJob, TemplateData } from '../types/printer.type';\nimport { IPayment, IPaymentMethod, IStandardPaymentMethod, PaymentMethod, StandardPaymentMethod, Payment } from '../types/payment.type';\nimport { INote, INoteGroup } from '../types/note.type';\nimport { ISection, ISectionItem } from '../types/section.type';\nimport { Category, ICategory, ICoreItem, IItem, ISubcategory, Item, ProductType, TStockChange } from '../types/product.type';\nimport type { AxiosInstance } from 'axios';\nimport { v4 as uuidv4 } from 'uuid';\nimport { CustomResponse, IFileUploadResponse, IServiceOptions, ModelPrefix, SystemError } from '../types/misc.type';\nimport { FileUploadRequest } from '../types/request.type';\nimport Dexie from 'dexie';\nimport { ICoreCategory } from '../types/product.type';\nimport { nanoid } from 'nanoid';\nimport { IShift, ITill, ShiftStatus, Shift, Till, TillType } from '../types/shift.type';\nimport { IInvoice, Invoice, InvoiceStatus, IInvoiceLine, IInvoiceCoreLine } from '../types/invoice.type';\nimport * as _ from 'lodash';\nimport { IAppCoreModel } from '../types/abstract.type';\nimport { AppReport, IAppReport, IReportData, IReportRequest, ReportData, TItemSalesSummary, TItemCoreSalesSummary, ItemSalesSummary, TModifierSalesSummary, ModifierSalesSummary, TCategorySalesSummary, CategorySalesSummary } from '../types/report.type';\nimport axios from 'axios';\nimport CryptoJS from 'crypto-js';\nimport { PrintCommand, Codepages, IPrintCommandLine, IPrintCommand } from '../libs/escpos.printer';\nimport { SelectTransform } from 'selecttransform';\nimport { IInvoiceService, InvoiceService } from './invoice.service';\nimport { IPrinterService, PrinterService } from './printer.service';\nimport { humanizedData } from '../utils/misc.utils';\nimport bcryptjs from 'bcryptjs';\nimport { convertFileToBase64, getFileExtension, preciseRound } from './misc.service';\nimport { IStorage, Storage } from '../types/storage.type';\nimport { IMenu } from '../types/menu.type';\nimport { IStockLog } from '../types/stock.type';\nimport { QueryBuilder, QueryEtcParams, QueryResponse } from '@litepos/autoquery';\n\n// export interface IPermissionService extends IAppRemoteService<Permission> {\n// canAccess(_employee: IEmployee, resource: string): boolean;\n// }\n\nexport type IEmployeeRoleService = IAppRemoteService<IEmployeeRole> & IAppRemoteService<IEmployeeRole>;\nexport type INoteService = IAppRemoteService<INote>;\nexport type INoteGroupService = IAppRemoteService<INoteGroup>;\nexport type ISectionService = IAppRemoteService<ISection>;\nexport type ISubcategoryService = IAppRemoteService<ISubcategory>;\n\n\nexport class EmployeeRoleService extends AppRemoteService<IEmployeeRole> implements IEmployeeRoleService {\n constructor(readonly http: AxiosInstance, readonly db: Dexie, readonly options: IServiceOptions, readonly moduleName = 'employee_roles', readonly methodName = 'employee_role') {\n super();\n }\n}\n/**\n * Represents a service for managing items.\n * Extends the IAppRemoteService interface for CRUD operations on IItem objects.\n */\n\n/**\n * Represents a service for managing section items.\n * Extends the IAppRemoteService interface with ISectionItem type.\n */\nexport interface ISectionItemService extends IAppRemoteService<ISectionItem> {\n /**\n * Changes the section item with the specified uid to take out.\n * @param uid - The unique identifier of the section item to change.\n * @returns A promise that resolves with the updated section item.\n */\n changeToTakeOut(uid: string): Promise<ISectionItem>;\n /**\n * Resets section item data (total, pax, customer) to default values.\n * @param sectionItem - The section item to reset.\n */\n reset(sectionItem: ISectionItem): void;\n /**\n * Syncs invoice data (total, pax, customer) to section item.\n * @param sectionItem - The section item to sync to.\n * @param invoice - The invoice to sync from.\n */\n syncInvoiceData(sectionItem: ISectionItem, invoice: IInvoice): void;\n}\n\n/**\n * Represents a service for managing employees.\n * @template IEmployee The type of employee object.\n * @extends IAppRemoteService<IEmployee> The interface for a remote service that manages employees.\n */\nexport interface IEmployeeService extends IAppRemoteService<IEmployee> {\n /**\n * Logs in a user with the given user uid and password.\n * @param userUid The uid of the user to log in.\n * @param password The password of the user to log in.\n * @returns A promise that resolves to true if the login was successful, or false otherwise.\n */\n login(userUid: string, password: string): Promise<boolean>;\n\n createEmployee(employee: IEmployee): Promise<IEmployee>;\n /**\n * Changes the password of the user with the given user UID.\n * @param userUid The UID of the user whose password should be changed.\n * @param oldPassword The user's current password.\n * @param newPassword The new password to set for the user.\n * @returns A promise that resolves to true if the password was changed successfully, or false otherwise.\n */\n changePassword(newPassword: string): Promise<string>;\n}\n\nexport class EmployeeService extends AppRemoteService<Employee> implements IEmployeeService {\n constructor(readonly http, readonly db: Dexie, readonly options: IServiceOptions, readonly moduleName = 'employees', readonly methodName = 'employee') {\n super();\n }\n\n public async login(userUid: string, password: string): Promise<boolean> {\n try {\n const user = await this.getOne(userUid);\n if (user) {\n // Compare the provided password with the stored hashed password\n const isPasswordValid = await bcryptjs.compare(password, user.password);\n if (isPasswordValid) {\n return true;\n } else {\n throw new SystemError('Password is incorrect');\n }\n } else {\n throw new SystemError('User not found');\n }\n } catch (error) {\n // Handle specific errors\n if (error instanceof SystemError) {\n throw error;\n } else {\n throw new SystemError('Unexpected error, login failed');\n }\n }\n }\n\n public async createEmployee(employee: IEmployee): Promise<IEmployee> {\n try {\n // Check if the user already exists\n const user = await this.getOne(employee.uid);\n if (user) {\n throw new SystemError('User already exists');\n }\n \n // Check if the employee object has a password\n if (employee.password) {\n // Hash the password using bcryptjs\n const saltRounds = 12;\n const hashedPassword = await bcryptjs.hash(employee.password, saltRounds);\n \n // Replace the plain-text password with the hashed password\n employee.password = hashedPassword;\n }\n \n // Add the employee to the database\n return this.addOne(employee);\n } catch (error) {\n // Handle specific errors\n if (error instanceof SystemError) {\n throw error;\n } else {\n throw new SystemError('Unexpected error, creating employee failed');\n }\n }\n }\n\n public async changePassword(newPassword: string): Promise<string> {\n try {\n const saltRounds = 12;\n const hashedPassword = await bcryptjs.hash(newPassword, saltRounds);\n return hashedPassword;\n } catch (error) {\n throw new SystemError('Unexpected error, changing password failed');\n }\n }\n\n}\n\nexport interface IItemService extends IAppRemoteService<IItem> {\n /**\n * Adds an image to an item.\n * @param file - The image file to add.\n * @param item - The item to add the image to.\n * @returns A Promise that resolves to the updated IItem object.\n */\n addImageAsync(file: File, item: ICoreItem): Promise<void>;\n\n /**\n * Adds a modifier category to an item.\n * @param item - The item to add the modifier category to.\n * @param category - The category to add.\n * @returns A Promise that resolves to the updated IItem object.\n */\n addModifierCategory(item: IItem, category: ICoreCategory): Promise<IItem>;\n /**\n * Updates a modifier category of an item.\n * @param item - The item to update the modifier category of.\n * @param category - The category to update.\n * @returns A Promise that resolves to the updated IItem object.\n */\n updateModifierCategory(item: IItem, category: ICoreCategory): Promise<IItem>;\n /**\n * Removes a modifier category from an item.\n * @param item - The item to remove the modifier category from.\n * @param category - The category to remove.\n * @returns A Promise that resolves to the updated IItem object.\n */\n removeModifierCategory(item: IItem, category: ICoreCategory ): Promise<IItem>;\n\n /**\n * Adds a modifier to an item.\n * @param item - The item to add the modifier to.\n * @param modifier - The modifier to add.\n * @returns A Promise that resolves to the updated IItem object.\n */\n addModifier(item: IItem, modifier: ICoreItem): Promise<IItem>;\n /**\n * Updates a modifier of an item.\n * @param item - The item to update the modifier of.\n * @param modifier - The modifier to update.\n * @returns A Promise that resolves to the updated IItem object.\n */\n updateModifier(item: IItem, modifier: ICoreItem): Promise<IItem>;\n /**\n * Removes a modifier from an item.\n * @param item - The item to remove the modifier from.\n * @param modifier - The modifier to remove.\n * @returns A Promise that resolves to the updated IItem object.\n */\n removeModifier(item: IItem, modifier: ICoreItem): Promise<IItem>;\n /**\n * attach a ungrouped modifier to a modifier group (category)\n * if you want to detach a modifier from a group, pass an empty string as the category_uid\n * @param item the item to attach the modifier to it's modifier category\n * @param modifier_uid the uid of the modifier to attach\n * @param category_uid the uid of the category to attach the modifier to\n */\n attachModifierToGroup(item: IItem, modifier_uid: string, category_uid: string): Promise<IItem>;\n\n /**\n * Searches for items by name, codename or barcode.\n * @param query - The search query.\n * @returns A Promise that resolves to an array of IItem objects.\n */\n search(query: string): Promise<IItem[]>;\n\n /**\n * mark an item as sold out\n * @param uid uid of the item to change to sold out\n */\n changeToSoldOut(uid: string): Promise<IItem>;\n\n /**\n * mark an item as available and restore stock\n * @param uid uid of the item to change to available\n * @param stock the stock quantity to set (default: 1)\n */\n changeToAvailable(uid: string, stock?: number): Promise<IItem>;\n\n /**\n * change the stock of an item by increment or decrement\n * @param uid uid of the item to change stock\n * @param stock the quantity to change the stock by, can be negative\n */\n changeStock(uid: string, stock: number): Promise<IItem>;\n\n /**\n * change the stock of multiple items\n * @param stockChanges list of stock changes\n */\n changeItemsStock(stockChanges: TStockChange[]): Promise<void>;\n\n /**\n * Clone an item\n * @param item item to clone\n * @returns cloned item\n */\n cloneItem(item: IItem): Promise<IItem>;\n\n /**\n * Clone modifiers of an item\n * @param item item to clone modifiers\n * @returns cloned modifiers\n */\n cloneModifiers(modifierCategory: ICoreCategory, modifiers: ICoreItem[]): Promise<{modifierCategory: ICoreCategory, modifiers: ICoreItem[]}>;\n\n /**\n * Copy a modifier group (category) and its modifiers to multiple items\n * @param sourceModifierCategory - The modifier category to copy\n * @param sourceModifiers - Array of modifiers belonging to the category\n * @param targetItems - Array of items to copy the modifier group to\n * @returns Promise resolving to array of updated items\n */\n copyModifierGroupToItems(\n sourceModifierCategory: ICoreCategory,\n sourceModifiers: ICoreItem[],\n targetItems: IItem[]\n ): Promise<IItem[]>;\n\n /** Remove deprecated combo_item data from combo groups to reduce payload size */\n sanitize(item: IItem): IItem;\n}\nexport class ItemService extends AppRemoteService<IItem> implements IItemService {\n constructor(readonly http: AxiosInstance, readonly db: Dexie, readonly options: IServiceOptions, readonly moduleName = 'items', readonly methodName = 'item') {\n super();\n }\n\n public async search(query: string): Promise<IItem[]> {\n return this.db.transaction('r', this.db.table(this.moduleName), async () => {\n // Using Dexie's Collection.anyOfIgnoreCase() method to search for any of the search terms in the ref_id or id fields\n const results = await this.db.table(this.moduleName).where('name').anyOfIgnoreCase(query).or('codename').anyOfIgnoreCase(query).or('barcode').anyOfIgnoreCase(query).toArray();\n\n // If you need to search in the numeric field 'grand_total' as a string,\n // you may have to retrieve all invoices and filter them manually, which could be inefficient:\n // const allInvoices = await db.invoices.toArray();\n // const filteredByGrandTotal = allInvoices.filter((invoice) => searchTerms.some((term) => invoice.grand_total.toString().includes(term)));\n\n // // Combine the results, ensuring to remove duplicates\n // const combinedResults = [...new Set([...invoices, ...filteredByGrandTotal])];\n return results;\n });\n }\n public async addModifierCategory(item: IItem, category: ICoreCategory): Promise<IItem> {\n category.uid = ModelPrefix.ItemModifierCategory + nanoid();\n if (!item.modifier_categories) item.modifier_categories = [];\n item.modifier_categories.push(category);\n return item;\n }\n public async updateModifierCategory(item: IItem, category: ICoreCategory): Promise<IItem> {\n if (!item.modifier_categories) {\n item.modifier_categories = [];\n throw new SystemError('Item does not have any modifier categories');\n }\n const index = item.modifier_categories.findIndex((c) => c.uid === category.uid);\n if (index === -1) throw new SystemError('Modifier category not found');\n item.modifier_categories[index] = category;\n return item;\n }\n public async removeModifierCategory(item: IItem, category: ICoreCategory): Promise<IItem> {\n if (!item.modifier_categories) {\n item.modifier_categories = [];\n throw new SystemError('Item does not have any modifier categories');\n }\n item.modifier_categories = item.modifier_categories.filter((c) => c.uid !== category.uid);\n return item;\n }\n public async addModifier(item: IItem, modifier: ICoreItem): Promise<IItem> {\n if (!item.modifiers) item.modifiers = [];\n modifier.uid = ModelPrefix.ItemModifier + nanoid();\n item.modifiers.push(modifier);\n return item;\n }\n public async updateModifier(item: IItem, modifier: ICoreItem): Promise<IItem> {\n if (!item.modifiers) {\n item.modifiers = [];\n throw new SystemError('Item does not have any modifiers');\n }\n const index = item.modifiers.findIndex((m) => m.uid === modifier.uid);\n if (index === -1) throw new SystemError('Modifier not found');\n item.modifiers[index] = modifier;\n return item;\n }\n public async removeModifier(item: IItem, modifier: ICoreItem): Promise<IItem> {\n if (!item.modifiers) {\n item.modifiers = [];\n throw new SystemError('Item does not have any modifiers');\n }\n item.modifiers = item.modifiers.filter((m) => m.uid !== modifier.uid);\n return item;\n }\n public async attachModifierToGroup(item: IItem, modifier_uid: string, category_uid: string): Promise<IItem> {\n if (!item.modifier_categories) {\n item.modifier_categories = [];\n throw new SystemError('Item does not have any modifier categories');\n }\n const category = item.modifier_categories.find((c) => c.uid === category_uid);\n if (!category) throw new SystemError('Modifier category not found');\n const modifier = item.modifiers.find((m) => m.uid === modifier_uid);\n if (!modifier) throw new SystemError('Modifier not found');\n modifier.category_uid = category_uid;\n return item;\n }\n public async addImageAsync(file: File, item: ICoreItem): Promise<void> {\n const guid = uuidv4();\n const extension = this.getFileExtension(file);\n await this.http.post(\n `api/v5/merchants/` + this.options.merchant_uid + `/upload-image`,\n new FileUploadRequest({\n base64: await this.convertFileToBase64(file),\n name: guid,\n extension: this.getFileExtension(file),\n }),\n );\n item.image_url = `${this.options.base_url}images/${guid}.${extension}`;\n item.image_thumbnail_url = `${this.options.base_url}images/${guid}.thumbnail.${extension}`;\n }\n public async changeToSoldOut(uid: string): Promise<IItem> {\n const item = await this.getOne(uid);\n if (!item) throw new SystemError('Item not found');\n item.stock = 0;\n item.is_sold_out = true;\n return this.updateOne(item.id_in_server, item);\n }\n\n public async changeToAvailable(uid: string, stock = 1): Promise<IItem> {\n const item = await this.getOne(uid);\n if (!item) throw new SystemError('Item not found');\n item.stock = stock;\n item.is_sold_out = false;\n return this.updateOne(item.id_in_server, item);\n }\n public async changeStock(uid: string, stock: number): Promise<IItem> {\n const item = await this.getOne(uid);\n if (!item) throw new SystemError('Item not found');\n const currentStock = Number(item.stock);\n item.stock = (isNaN(currentStock) ? 0 : currentStock) + stock;\n return this.updateOne(item.id_in_server, item);\n }\n\n public async changeItemsStock(stockChanges: TStockChange[]): Promise<void> {\n const items: IItem[] = [];\n for (const stockChange of stockChanges) {\n const item = await this.getOne(stockChange.item_uid);\n if (!item) continue;\n const currentStock = Number(item.stock);\n item.stock = (isNaN(currentStock) ? 0 : currentStock) + stockChange.quantity;\n for (const modifier of stockChange.modifiers) {\n const modifierItem = item.modifiers?.find((m) => m.uid === modifier.item_uid);\n if (!modifierItem) continue;\n const currentModifierStock = Number(modifierItem.stock);\n modifierItem.stock = (isNaN(currentModifierStock) ? 0 : currentModifierStock) + Number(modifier.quantity);\n }\n items.push(item);\n }\n await this.updateMany(items);\n }\n\n private convertFileToBase64(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onloadend = () => {\n if (typeof reader.result === 'string') {\n resolve(reader.result.split(',')[1]); // extract only Base64 string part\n } else {\n reject(new Error('Could not convert file to Base64.'));\n }\n };\n reader.onerror = () => reject(new Error('File reading failed.'));\n reader.readAsDataURL(file);\n });\n }\n private getFileExtension(file: File): string {\n const fileName: string = file.name;\n const dotIndex: number = fileName.lastIndexOf('.');\n\n // Check if dotIndex is -1 or is the last character (no extension)\n if (dotIndex === -1 || dotIndex === fileName.length - 1) {\n return '';\n }\n\n return fileName.slice(dotIndex + 1);\n }\n\n public async cloneItem(item: IItem): Promise<IItem> {\n const newItem = _.cloneDeep(item);\n newItem.uid = ModelPrefix.Item + nanoid();\n newItem.id_in_server = 0;\n if (!newItem.modifier_categories || newItem.modifier_categories.length === 0) return newItem;\n const newModifierCategories: ICoreCategory[] = [];\n const newModifiers: ICoreItem[] = [];\n for (const modifierCategory of newItem.modifier_categories) {\n const filteredModifiers = newItem.modifiers?.filter((x) => x.category_uid === modifierCategory.uid);\n if (!filteredModifiers || filteredModifiers.length === 0) continue;\n const {modifierCategory: newModifierCategory, modifiers: newPartialModifiers} = await this.cloneModifiers(modifierCategory, filteredModifiers);\n newModifierCategories.push(newModifierCategory);\n newModifiers.push(...newPartialModifiers);\n }\n newItem.modifier_categories = newModifierCategories;\n newItem.modifiers = newModifiers;\n return newItem;\n }\n\n public async cloneModifiers(modifierCategory: ICoreCategory, modifiers: ICoreItem[]): Promise<{modifierCategory: ICoreCategory, modifiers: ICoreItem[]}> {\n const newModifierCategory = _.cloneDeep(modifierCategory);\n newModifierCategory.uid = ModelPrefix.ItemModifierCategory + nanoid();\n const newModifiers: ICoreItem[] = [];\n for (const modifier of modifiers) {\n const newModifier = _.cloneDeep(modifier);\n newModifier.uid = ModelPrefix.ItemModifier + nanoid();\n newModifier.category_uid = newModifierCategory.uid;\n newModifiers.push(newModifier);\n }\n return {modifierCategory: newModifierCategory, modifiers: newModifiers};\n }\n\n public async copyModifierGroupToItems(\n sourceModifierCategory: ICoreCategory,\n sourceModifiers: ICoreItem[],\n targetItems: IItem[]\n ): Promise<IItem[]> {\n if (!sourceModifierCategory || !sourceModifiers?.length || !targetItems?.length) {\n throw new SystemError('Invalid input parameters');\n }\n const updatedItems: IItem[] = [];\n for (const targetItem of targetItems) {\n targetItem.modifier_categories = targetItem.modifier_categories || [];\n targetItem.modifiers = targetItem.modifiers || [];\n const { modifierCategory: clonedCategory, modifiers: clonedModifiers } = await this.cloneModifiers(sourceModifierCategory, sourceModifiers);\n targetItem.modifier_categories.push(clonedCategory);\n targetItem.modifiers.push(...clonedModifiers);\n updatedItems.push(targetItem);\n }\n await this.updateMany(updatedItems);\n return updatedItems;\n }\n\n public sanitize(item: IItem): IItem {\n if (item.type !== ProductType.Combo) {\n item.combo_groups = [];\n return item;\n }\n if (!item.combo_groups?.length) return item;\n for (const group of item.combo_groups)\n for (const ci of group.combo_items)\n delete (ci as any).combo_item;\n return item;\n }\n}\n/**\n * Represents a service for managing categories.\n * Extends the IAppRemoteService interface with the ICategory type.\n */\nexport interface ICategoryService extends IAppRemoteService<ICategory> {\n /**\n * Adds a subcategory to a category.\n * @param category - The category to add the subcategory to.\n * @param subcategory - The subcategory to add.\n * @returns A promise that resolves to the updated category.\n */\n addSubcategory(category: ICategory, subcategory: ISubcategory): Promise<ICategory>;\n\n /**\n * Updates a subcategory of a category.\n * @param category - The category that contains the subcategory.\n * @param subcategory - The updated subcategory.\n * @returns A promise that resolves to the updated category.\n */\n updateSubcategory(category: ICategory, subcategory: ISubcategory): Promise<ICategory>;\n\n /**\n * Removes a subcategory from a category.\n * @param category - The category to remove the subcategory from.\n * @param subcategoryUid - The unique identifier of the subcategory to remove.\n * @returns A promise that resolves to the updated category.\n */\n removeSubcategory(category: ICategory, subcategoryUid: string): Promise<ICategory>;\n}\n\nexport class CategoryService extends AppRemoteService<Category> {\n constructor(readonly http: AxiosInstance, readonly db: Dexie, readonly options: IServiceOptions, readonly moduleName = 'categories', readonly methodName = 'category') {\n super();\n }\n public async addSubcategory(category: ICategory, subcategory: ISubcategory): Promise<ICategory> {\n if (!category.subcategories) category.subcategories = [];\n category.subcategories.push(subcategory);\n if (!category.has_subcategory) category.has_subcategory = true;\n if (category.id_in_server) await this.updateOne(category.id_in_server, category);\n else await this.addOne(category);\n return category;\n }\n\n public async updateSubcategory(category: ICategory, subcategory: ISubcategory): Promise<ICategory> {\n if (!category.subcategories) {\n category.subcategories = [];\n if (category.has_subcategory) category.has_subcategory = false;\n throw new SystemError('Category does not have any subcategories');\n }\n const index = category.subcategories.findIndex((c) => c.uid === subcategory.uid);\n if (index === -1) throw new SystemError('Subcategory not found');\n category.subcategories[index] = subcategory;\n if (category.id_in_server) await this.updateOne(category.id_in_server, category);\n else await this.addOne(category);\n return category;\n }\n\n public async removeSubcategory(category: ICategory, subcategoryUid: string): Promise<ICategory> {\n if (!category.subcategories) {\n category.subcategories = [];\n if (category.has_subcategory) category.has_subcategory = false;\n throw new SystemError('Category does not have any subcategories');\n }\n category.subcategories = category.subcategories.filter((c) => c.uid !== subcategoryUid);\n if (category.id_in_server) await this.updateOne(category.id_in_server, category);\n else await this.addOne(category);\n return category;\n }\n}\n\n/**\n * Represents a configuration service that extends the IAppRemoteService interface and provides methods for updating general configuration.\n */\nexport interface IConfigService extends IAppRemoteService<IAppConfig> {\n /**\n * Updates the general configuration with the specified options.\n * @param options The options for updating the general configuration.\n * @returns A promise that resolves to the updated application configuration.\n */\n updateGeneralConfig(options: UpdateGeneralConfigOptions): Promise<IAppConfig>;\n\n /**\n * Updates a config category with the specified options.\n * @param configKey the config category key to update\n * @param options the value to update the config category with\n */\n updateConfig(configKey: keyof IConfig, options: Partial<IConfig[typeof configKey]>): Promise<IAppConfig>;\n\n /**\n * Uploads an image to the server.\n * @param file - The file to upload.\n * @returns A promise that resolves with the uploaded file.\n */\n uploadFile(file: File): Promise<IFileUploadResponse>;\n}\n\nexport class ConfigService extends AppRemoteService<IAppConfig> implements IConfigService {\n constructor(readonly http: AxiosInstance, readonly db: Dexie, readonly options: IServiceOptions, readonly moduleName = 'configs', readonly methodName = 'config') {\n super();\n }\n\n private configFactories: { [K in keyof IConfig]?: () => IConfig[K] } = {\n general: () => new GeneralConfig(),\n till: () => new TillConfig(),\n report: () => new ReportConfig(),\n receipt: () => new Receipt(),\n kitchen: () => new KitchenConfig(),\n kds: () => new KdsConfig(),\n label: () => new LabelConfig(),\n order: () => new OrderConfig(),\n payment: () => new PaymentConfig(),\n user: () => new UserConfig(),\n tax: () => new TaxConfig(),\n rounding: () => new RoundingConfig(),\n charges: () => new ChargeConfig(),\n currency: () => new CurrencyConfig(),\n inventory: () => new InventoryConfig(),\n pax_config: () => new PaxConfig(),\n gto: () => new GTOConfig(),\n cash_drawer: () => new CashDrawerConfig(),\n marketing: () => new MarketingConfig(),\n };\n\n public async updateConfig<T extends keyof IConfig>(configKey: T, options: Partial<IConfig[T]>): Promise<IAppConfig> {\n let appConfig = await this.getDefaultOne();\n if (!appConfig) appConfig = new AppConfig();\n const factory = this.configFactories[configKey];\n let config = appConfig.config[configKey] || {} as IConfig[T];\n if (!appConfig.config[configKey]) {\n if (factory && typeof factory === 'function') {\n appConfig.config[configKey] = factory();\n } else {\n appConfig.config[configKey] = {} as IConfig[T];\n }\n config = appConfig.config[configKey];\n }\n Object.keys(options).forEach((key) => {\n if (options[key] !== undefined) {\n config[key] = options[key];\n }\n });\n if (!appConfig.id_in_server) return this.addOne(appConfig);\n return this.updateOne(appConfig.id_in_server, appConfig);\n }\n\n public async updateGeneralConfig(options: UpdateGeneralConfigOptions): Promise<IAppConfig> {\n let appConfig = await this.getDefaultOne();\n if (!appConfig) appConfig = new AppConfig();\n const generalConfig = appConfig.config.general;\n Object.keys(options).forEach((key) => {\n if (options[key] !== undefined) {\n generalConfig[key] = options[key];\n }\n });\n if (!appConfig.id_in_server) return this.addOne(appConfig);\n return this.updateOne(appConfig.id_in_server, appConfig);\n }\n\n public async updateCache(partialCache: Partial<ICache>): Promise<IAppConfig> {\n const appConfig = await this.getDefaultOne();\n appConfig.cache = { ...appConfig.cache, ...partialCache };\n if (!appConfig.id_in_server) return this.addOne(appConfig);\n return this.updateOne(appConfig.id_in_server, appConfig);\n }\n\n public async uploadFile(file: File): Promise<IFileUploadResponse> {\n const guid = uuidv4();\n const extension = getFileExtension(file);\n await this.http.post(\n `api/v5/merchants/` + this.options.merchant_uid + `/upload-image`,\n new FileUploadRequest({\n base64: await convertFileToBase64(file),\n name: guid,\n extension: extension,\n }),\n );\n const fileUrl = `${this.options.base_url}images/${guid}.${extension}`;\n const thumbnailUrl = `${this.options.base_url}images/${guid}.thumbnail.${extension}`;\n return {file_url:fileUrl, thumbnail_url:thumbnailUrl};\n }\n}\n\nexport class SectionService extends AppRemoteService<ISection> implements ISectionService {\n constructor(readonly http: AxiosInstance, readonly db: Dexie, readonly options: IServiceOptions, readonly moduleName = 'sections', readonly methodName = 'section') {\n super();\n }\n}\n\nexport class SectionItemService extends AppRemoteService<ISectionItem> implements ISectionItemService {\n constructor(readonly http: AxiosInstance, readonly db: Dexie, readonly options: IServiceOptions, readonly moduleName = 'section_items', readonly methodName = 'section_item') {\n super();\n }\n public async changeToTakeOut(uid: string): Promise<ISectionItem> {\n const item = await this.getOne(uid);\n if (!item) throw new Error('Item not found');\n item.is_take_out = !item.is_take_out;\n return this.updateOne(item.id_in_server, item);\n }\n public reset(sectionItem: ISectionItem): void {\n sectionItem.total = 0;\n sectionItem.pax = 0;\n sectionItem.customer = {};\n }\n public syncInvoiceData(sectionItem: ISectionItem, invoice: IInvoice): void {\n sectionItem.total = invoice.grand_total;\n sectionItem.pax = invoice.pax;\n sectionItem.customer = { display_name: invoice.customer?.display_name || '', phone_number: invoice.customer?.phone_number || '' };\n }\n}\n\nexport type IProductService = IAppRemoteService<IItem>;\n\nexport class ProductService extends AppRemoteService<IItem> implements IProductService {\n constructor(readonly http: AxiosInstance, readonly db: Dexie, readonly options: IServiceOptions, readonly moduleName = 'products', readonly methodName = 'product') {\n super();\n }\n \n}\n\nexport interface IShiftService extends IAppRemoteService<IShift> {\n closeShift(declareAmount: number, userUid: string): Promise<IShift>;\n openShift(openAmount: number, userUid: string, note?: string): Promise<IShift>;\n cashIn(amount: number, note: string): Promise<ITill>;\n cashOut(amount: number, note: string): Promise<ITill>;\n}\n\nexport class ShiftService extends AppRemoteService<IShift> implements IShiftService {\n private tillService: ITillService;\n constructor(readonly http: AxiosInstance, readonly db: Dexie, readonly options: IServiceOptions, readonly moduleName = 'shifts', readonly methodName = 'shift') {\n super();\n this.tillService = new TillService(http, db, options);\n }\n public async cashIn(amount: number, note: string): Promise<ITill> {\n const shift = (await this.db.table(this.moduleName)\n .filter(x => (x.deleted_at === null || x.deleted_at === undefined) && x.status === ShiftStatus.Open)\n .first()) as IShift;\n if (!shift) throw new SystemError('No opening shift found');\n const till = new Till();\n till.amount = amount;\n till.type = TillType.CashIn;\n till.user_uid = shift.user_uid;\n till.shift_uid = shift.uid;\n till.note = note;\n return this.tillService.addOne(till);\n }\n public async cashOut(amount: number, note: string): Promise<ITill> {\n const shift = (await this.db.table(this.moduleName)\n .filter(x => (x.deleted_at === null || x.deleted_at === undefined) && x.status === ShiftStatus.Open)\n .first()) as IShift;\n if (!shift) throw new SystemError('No opening shift found');\n const till = new Till();\n till.amount = amount;\n till.type = TillType.CashOut;\n till.user_uid = shift.user_uid;\n till.shift_uid = shift.uid;\n till.note = note;\n return this.tillService.addOne(till);\n }\n public async closeShift(declareAmount: number, userUid: string): Promise<IShift> {\n const shift = (await this.db\n .table(this.moduleName)\n .filter((item) => (item.deleted_at === null || item.deleted_at === undefined) && item.status == ShiftStatus.Open)\n .first()) as IShift;\n if (!shift) throw new SystemError('No opening shift found');\n shift.declared_amount = declareAmount;\n shift.ended_at = new Date();\n shift.user_uid = userUid;\n shift.status = ShiftStatus.Closed;\n\n return this.updateOne(shift.id_in_server, shift);\n }\n public async openShift(openAmount: number, userUid: string, note = ''): Promise<IShift> {\n console.log('open shift entry');\n const shift = (await this.db\n .table(this.moduleName)\n .filter((item) => (item.deleted_at === null || item.deleted_at === undefined) && item.status == ShiftStatus.Open)\n .first()) as IShift;\n if (shift) throw new SystemError(`shift is already opened shift at ${shift.started_at}`);\n\n const newShift = new Shift();\n newShift.started_at = new Date();\n newShift.user_uid = userUid;\n newShift.status = ShiftStatus.Open;\n await this.addOne(newShift);\n if (openAmount > 0) {\n const till = new Till();\n till.amount = openAmount;\n till.type = TillType.OpenDeposit;\n till.user_uid = userUid;\n till.amount = openAmount;\n till.shift_uid = newShift.uid;\n till.note = note;\n await this.tillService.addOne(till);\n }\n console.log('open shift end');\n return newShift;\n }\n}\n\n/**\n * Represents a service for creating cash invoice tills.\n * @interface\n * @extends IAppRemoteService\n */\nexport interface ITillService extends IAppRemoteService<ITill> {\n /**\n * Creates a cash invoice till.\n * @param {IPayment[]} payments - Invoice payments.\n * @param {string} shift_uid - The shift UID.\n * @param {string} user_uid - The user UID.\n * @param {string} [note] - The note for the till.\n * @param {string} [invoice_uid] - The invoice UID.\n * @returns {Promise<ITill>} - A promise that resolves with the created till.\n */\n createCashInvoiceTill(payments: IPayment[], shift_uid: string, user_uid: string, note?: string, invoice_uid?: string): ITill;\n /** Soft-delete all Till records by invoice_uid */\n deleteByInvoiceUid(invoiceUid: string): Promise<ITill[]>;\n}\n\nexport class TillService extends AppRemoteService<ITill> implements ITillService {\n constructor(readonly http: AxiosInstance, readonly db: Dexie, readonly options: IServiceOptions, readonly moduleName = 'tills', readonly methodName = 'till') {\n super();\n }\n public createCashInvoiceTill(payments: IPayment[], shift_uid: string, user_uid: string, note = '', invoice_uid = ''): ITill {\n const till = new Till();\n till.shift_uid = shift_uid;\n till.user_uid = user_uid;\n till.note = note;\n till.invoice_uid = invoice_uid;\n const sum = payments\n .filter((x) => x.payment_method.is_cash) // Select only payments that are cash\n .map((x) => x.tender_amount - x.change_amount) // Map to the amount after change\n .reduce((acc, current) => acc + current, 0); // Sum all the amounts\n till.amount = preciseRound(sum);\n till.type = TillType.CashInvoice;\n // 只是创建对象,till 和 invoice 是一同发送到服务器创建的\n return till;\n }\n public async deleteByInvoiceUid(invoiceUid: string): Promise<ITill[]> {\n const tills = await this.db.table(this.moduleName).filter((t: ITill) => t.invoice_uid === invoiceUid && !t.deleted_at).toArray();\n for (const till of tills) await this.deleteOne(till);\n return tills;\n }\n}\n\n/**\n * Represents a service for managing payment methods.\n * Extends the IAppRemoteService interface for CRUD operations.\n */\nexport interface IPaymentMethodService extends IAppRemoteService<IPaymentMethod> {\n /**\n * Synchronizes the standard payment methods from server and updates database.\n * @returns A promise that resolves with an array of IPaymentMethod objects.\n */\n syncStandardPaymentMethods(): Promise<IPaymentMethod[]>;\n\n /**\n * Enables a payment method.\n * @param paymentMethod - The payment method to enable.\n * @returns A promise that resolves with the enabled IPaymentMethod object.\n */\n enablePaymentMethod(paymentMethod: IPaymentMethod): Promise<IPaymentMethod>;\n\n /**\n * Disables a payment method.\n * @param paymentMethod - The payment method to disable.\n * @returns A promise that resolves with the disabled IPaymentMethod object.\n */\n disablePaymentMethod(paymentMethod: IPaymentMethod): Promise<IPaymentMethod>;\n\n /**\n * Changes the sequence of a payment method.\n * @deprecated Use AppMiscService.changeSequence instead\n * @param paymentMethod - The payment method to change the sequence of.\n * @param sequence - The new sequence number for the payment method.\n * @returns A promise that resolves with the updated IPaymentMethod object.\n */\n changeSequence(paymentMethod: IPaymentMethod, sequence: number): Promise<IPaymentMethod>;\n}\n\nexport class PaymentMethodService extends AppRemoteService<IPaymentMethod> implements IPaymentMethodService {\n constructor(readonly http: AxiosInstance, readonly db: Dexie, readonly options: IServiceOptions, readonly moduleName = 'payment_methods', readonly methodName = 'payment_method') {\n super();\n }\n\n public async syncStandardPaymentMethods(): Promise<IPaymentMethod[]> {\n try {\n const data: CustomResponse<IStandardPaymentMethod[]> = await this.http.get(`api/v5/merchants/` + this.options.merchant_uid + `/standard_payment_methods`);\n const { data: standardPaymentMethods } = data;\n const paymentMethods: IPaymentMethod[] = [];\n\n for (const item of standardPaymentMethods) {\n const standardPaymentMethod = new StandardPaymentMethod(item);\n const paymentMethod: PaymentMethod = await this.getOneByParams({ payment_method_code: standardPaymentMethod.payment_method_code });\n const newPaymentMethod = standardPaymentMethod.toPaymentMethod();\n\n if (paymentMethod) {\n newPaymentMethod.uid = paymentMethod.uid;\n newPaymentMethod.id_in_server = paymentMethod.id_in_server;\n newPaymentMethod.sequence = paymentMethod.sequence;\n newPaymentMethod.is_disabled = paymentMethod.is_disabled;\n newPaymentMethod.is_integrated = paymentMethod.is_integrated;\n newPaymentMethod.api_id = paymentMethod.api_id;\n newPaymentMethod.api_key = paymentMethod.api_key;\n } else {\n newPaymentMethod.is_disabled = true;\n await this.addOne(newPaymentMethod);\n }\n\n paymentMethods.push(newPaymentMethod);\n }\n\n return paymentMethods;\n } catch (error) {\n // It's often useful to log the error or handle it in some way before returning\n console.error('Failed to sync standard payment methods:', error);\n return [];\n }\n }\n\n public async enablePaymentMethod(paymentMethod: IPaymentMethod): Promise<IPaymentMethod> {\n paymentMethod.is_disabled = false;\n return this.updateOne(paymentMethod.id_in_server, paymentMethod);\n }\n\n public async disablePaymentMethod(paymentMethod: IPaymentMethod): Promise<IPaymentMethod> {\n paymentMethod.is_disabled = true;\n return this.updateOne(paymentMethod.id_in_server, paymentMethod);\n }\n\n /** @deprecated Use AppMiscService.changeSequence instead */\n public async changeSequence(paymentMethod: IPaymentMethod, sequence: number): Promise<IPaymentMethod> {\n // Get all enabled payment methods sorted by current sequence\n const allPaymentMethods = await this.db\n .table(this.moduleName)\n .filter(pm => !pm.is_disabled)\n .sortBy('sequence');\n \n // Remove target payment method from list\n const otherMethods = allPaymentMethods.filter(pm => pm.id_in_server !== paymentMethod.id_in_server);\n \n // Insert target payment method at new position\n if (sequence < 0) sequence = 0;\n if (sequence > otherMethods.length) sequence = otherMethods.length;\n otherMethods.splice(sequence, 0, paymentMethod);\n \n // Reassign sequence numbers from 0\n const methodsToUpdate: IPaymentMethod[] = [];\n for (let i = 0; i < otherMethods.length; i++) {\n if (otherMethods[i].sequence !== i) {\n otherMethods[i].sequence = i;\n methodsToUpdate.push(otherMethods[i]);\n }\n }\n \n // Batch update all changed payment methods\n if (methodsToUpdate.length > 0) await this.updateMany(methodsToUpdate);\n \n return paymentMethod;\n }\n}\n\n/**\n * Interface for Payment Service that extends IAppRemoteService with IPayment type.\n */\nexport interface IPaymentService extends IAppRemoteService<IPayment> {\n /**\n * Adds a payment to an invoice.\n * @param invoice - The invoice to add the payment to.\n * @param amount - The amount of the payment.\n * @param paymentMethod - The payment method used for the payment.\n * @returns A promise that resolves to the updated invoice.\n */\n addPayment(invoice: IInvoice, amount: number, paymentMethod: IPaymentMethod): Promise<IInvoice>;\n\n /**\n * Removes a payment from an invoice.\n * @param invoice - The invoice to remove the payment from.\n * @param payment_uid - The unique identifier of the payment to remove.\n * @returns A promise that resolves to the updated invoice.\n */\n removePayment(invoice: IInvoice, payment_uid: string): Promise<IInvoice>;\n}\n\nexport class PaymentService extends AppRemoteService<IPayment> implements IPaymentService {\n constructor(readonly http: AxiosInstance, readonly db: Dexie, readonly options: IServiceOptions, readonly moduleName = 'payments', readonly methodName = 'payment') {\n super();\n }\n\n public async addPayment(invoice: IInvoice, amount: number, paymentMethod: IPaymentMethod): Promise<IInvoice> {\n const payment = new Payment();\n payment.invoice_uid = invoice.uid;\n payment.tender_amount = amount;\n const totalTenderAmount = invoice.payments.reduce((acc, payment) => acc + payment.tender_amount, 0) + amount;\n if (paymentMethod.is_cash && totalTenderAmount >= invoice.grand_total) {\n payment.change_amount = preciseRound(totalTenderAmount - invoice.grand_total);\n }\n payment.payment_method_uid = paymentMethod.uid;\n payment.payment_method_code = paymentMethod.payment_method_code;\n payment.payment_method_name = paymentMethod.name;\n payment.payment_method = _.cloneDeep(paymentMethod);\n invoice.payments.push(payment);\n return invoice;\n }\n\n public async removePayment(invoice: IInvoice, payment_uid: string): Promise<IInvoice> {\n invoice.payments = invoice.payments.filter((p) => p.uid !== payment_uid);\n return invoice;\n }\n}\n\n/**\n * Represents the interface for the AppMiscService.\n */\nexport interface IAppMiscService {\n /**\n * Calibrates the sequence for a given service.\n * @param service - The service to calibrate the sequence for.\n * @returns A promise that resolves when the calibration is complete.\n */\n calibrateSequence<T extends IAppCoreModel & IAppModelSequence>(service: IAppRemoteService<T>): Promise<void>;\n\n /**\n * Changes the sequence of an item for a given service or item list.\n * @param service - The service to change the sequence for, or an array of items.\n * @param item - The item to change the sequence of.\n * @param targetIndex - The target array index (0-based) to move the item to.\n * @returns A promise that resolves with the array of items that were updated.\n */\n changeSequence<T extends IAppCoreModel & IAppModelSequence>(service: IAppRemoteService<T> | T[], item: T, targetIndex: number): Promise<T[]>;\n\n\n}\nexport class AppMiscService implements IAppMiscService {\n public async calibrateSequence<T extends IAppCoreModel & IAppModelSequence>(service: IAppRemoteService<T>): Promise<void> {\n const items = await service.getAll();\n items.sort((a, b) => a.sequence - b.sequence);\n const itemsToUpdate: T[] = [];\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n if (item.sequence !== i) {\n item.sequence = i;\n itemsToUpdate.push(item);\n }\n }\n await service.updateMany(itemsToUpdate);\n }\n\n public async changeSequence<T extends IAppCoreModel & IAppModelSequence>(service: IAppRemoteService<T> | T[], item: T, targetIndex: number): Promise<T[]> {\n if (targetIndex < 0) throw new SystemError('Invalid target index.');\n const isArray = Array.isArray(service);\n let items = isArray ? service : await service.getAll();\n items = items.filter(itm => itm.deleted_at === null).sort((a, b) => a.sequence - b.sequence);\n if (targetIndex >= items.length) throw new SystemError('Invalid target index.');\n const currentIndex = items.findIndex((itm) => itm.uid == item.uid);\n // Record original sequences for comparison\n const originalSequences = new Map(items.map(itm => [itm.uid, itm.sequence]));\n // Adjust target position when moving backwards\n if (currentIndex < targetIndex) targetIndex += 1;\n items.splice(targetIndex, 0, null);\n const allItems = items\n .filter((itm) => !(itm && itm.uid === item.uid))\n .map((itm, index) => {\n if (itm === null) {\n item.sequence = index + 1;\n return item;\n }\n itm.sequence = index + 1;\n return itm;\n });\n // Only update items with changed sequence\n const itemsToUpdate = allItems.filter(itm => originalSequences.get(itm.uid) !== itm.sequence);\n if (!isArray) await service.updateMany(itemsToUpdate);\n return itemsToUpdate;\n }\n}\n\n/**\n * Represents the interface for the App Report Service.\n * Extends the IAppRemoteService interface with methods specific to report functionality.\n */\nexport interface IAppReportService extends IAppRemoteService<IAppReport> {\n /**\n * Synchronizes standard reports.\n * @returns A promise that resolves to an instance of IAppReport.\n */\n syncStandardReports(): Promise<IAppReport>;\n /**\n * Prints a report.\n * @param request - The request object containing the necessary information for printing the report.\n * @returns A promise that resolves when the report is printed successfully.\n */\n printReport(request: IReportRequest): Promise<void>;\n}\nexport class AppReportService extends AppRemoteService<IAppReport> implements IAppReportService {\n private invoiceService: IInvoiceService;\n private tillService: ITillService;\n private paymentService: IPaymentService;\n private printerService: IPrinterService;\n private printTemplateService: IPrintTemplateService;\n private printJobService: IPrintJobService;\n private configService: IConfigService;\n\n constructor(readonly http: AxiosInstance, readonly db: Dexie, readonly options: IServiceOptions, readonly moduleName = 'reports', readonly methodName = 'report') {\n super();\n this.invoiceService = new InvoiceService(http, db, options, 'invoices', 'invoice');\n this.tillService = new TillService(http, db, options, 'tills', 'till');\n this.paymentService = new PaymentService(http, db, options, 'payments', 'payment');\n this.printerService = new PrinterService(http, db, options, 'printers', 'printer');\n this.printTemplateService = new PrintTemplateService(http, db, options, 'print_templates', 'print_template');\n this.printJobService = new PrintJobService(http, db, options, 'print_jobs', 'print_job');\n this.configService = new ConfigService(http, db, options, 'configs', 'config');\n }\n\n public async syncStandardReports(): Promise<IAppReport> {\n let appReport = await this.getDefaultOne();\n if (!appReport) appReport = new AppReport();\n const data: CustomResponse<AppReport> = await this.http.get(`api/v5/merchants/` + this.options.merchant_uid + `/standard_reports`);\n appReport = { ...appReport, ...data.data };\n appReport.updated_at = new Date();\n if (!appReport.id_in_server) await this.addOne(appReport);\n else await this.updateOne(appReport.id_in_server, appReport);\n return appReport;\n }\n\n public async printReport(request: IReportRequest): Promise<void> {\n request.copies = request.copies || 1;\n const printer = await this.printerService.getDefaultReceiptPrinter();\n if (!printer) throw new SystemError('No default receipt printer found');\n const template = await this.printTemplateService.getOneByParams({ report_code_name: request.report_code_name });\n if (!template) throw new SystemError('No print template found');\n const appConfig = await this.configService.getDefaultOne();\n const reportData = await this.getReportData(request, appConfig.config?.order?.datetime_format);\n const printCommand = await this.printTemplateService.renderReportPrintTemplate(reportData, appConfig.config, template);\n const printJob = new PrintJob(printer, printCommand, false, request.copies);\n await this.printJobService.addOne(printJob);\n }\n\n private async getReportData(request: IReportRequest, datetimeFormat?: string): Promise<IReportData> {\n const reportData = new ReportData();\n\n if (request.shift_uid) {\n const shift : IShift = await this.db\n .table('shifts')\n .where('uid')\n .equals(request.shift_uid)\n .and((shift) => shift.deleted_at == null || shift.deleted_at == undefined)\n .first();\n \n reportData.drawer_summary.declared_amount = request.declared_amount;\n \n const tills: Till[] = await this.db\n .table('tills')\n .where('shift_uid')\n .equals(request.shift_uid)\n .and((till) => till.deleted_at == null)\n .toArray();\n\n reportData.drawer_summary.open_amount = preciseRound(tills.filter((till) => till.type == TillType.OpenDeposit).reduce((acc, till) => acc + till.amount, 0));\n reportData.drawer_summary.pay_in_total = preciseRound(tills.filter((till) => till.type == TillType.CashIn).reduce((acc, till) => acc + till.amount, 0));\n reportData.drawer_summary.cash_invoice_total = preciseRound(tills.filter((till) => till.type == TillType.CashInvoice).reduce((acc, till) => acc + till.amount, 0));\n reportData.drawer_summary.cash_invoice_count = tills.filter((till) => till.type == TillType.CashInvoice).length;\n reportData.drawer_summary.pay_in_count = tills.filter((till) => till.type == TillType.CashIn).length;\n reportData.drawer_summary.pay_out_total = preciseRound(tills.filter((till) => till.type == TillType.CashOut).reduce((acc, till) => acc + till.amount, 0));\n reportData.drawer_summary.pay_out_count = tills.filter((till) => till.type == TillType.CashOut).length;\n\n reportData.drawer_summary.drawer_amount = preciseRound(reportData.drawer_summary.open_amount + reportData.drawer_summary.pay_in_total + reportData.drawer_summary.cash_invoice_total - reportData.drawer_summary.pay_out_total);\n reportData.drawer_summary.difference = preciseRound(reportData.drawer_summary.drawer_amount - reportData.drawer_summary.declared_amount) ;\n }\n\n reportData.start_datetime = (new Date(request.start_datetime)).toISOString();\n reportData.end_datetime = (new Date(request.end_datetime)).toISOString();\n reportData.humanized_start_datetime = humanizedData(new Date(request.start_datetime), datetimeFormat);\n reportData.humanized_end_datetime = humanizedData(new Date(request.end_datetime), datetimeFormat);\n reportData.humanized_printed_datetime = humanizedData(new Date(), datetimeFormat);\n // Use server API instead of local database\n const query = new QueryBuilder<IInvoice & QueryEtcParams>()\n .addParam('paid_at','GreaterThanOrEqualTo', new Date(request.start_datetime).toISOString())\n .addParam('paid_at', 'LessThanOrEqualTo', new Date(request.end_datetime).toISOString())\n .addParam('deleted_at', 'IsNull', true)\n .includeTotal(true);\n\n const response: QueryResponse<IInvoice> = await this.invoiceService.autoQuery(query, { timeout: 600000 });\n const invoices = response.results || [];\n\n return this.processReportInvoicesData(reportData, invoices);\n\n }\n\n public async processReportInvoicesData(reportData: IReportData, invoices: IInvoice[] = []): Promise<IReportData> {\n // 使用临时对象存储商品销售数据,key为唯一的菜品标识\n const itemSalesMap = new Map<string, TItemSalesSummary>();\n // 使用临时对象存储modifier销售数据,key为modifier的name去除空白字符\n const modifierSalesMap = new Map<string, TModifierSalesSummary>();\n\n // 获取所有分类用于排序(包括已删除的,因为历史数据中可能有已删除类别的菜品)\n const categories: ICategory[] = await this.db.table('categories').toArray();\n const categoryMap = new Map(categories.map(c => [c.uid, c]));\n\n invoices.forEach((invoice: Invoice) => {\n if (invoice.status == InvoiceStatus.Paid) {\n reportData.sales_summary.paid_invoice_total += invoice.grand_total;\n reportData.sales_summary.sales_total += invoice.grand_total;\n reportData.sales_summary.paid_invoice_count ++;\n reportData.sales_summary.rounding_total += invoice.rounding;\n reportData.sales_summary.tax_total += invoice.tax;\n reportData.sales_summary.service_charge_total += invoice.service_charge;\n reportData.sales_summary.discount_total += invoice.discount_amount;\n // Loyalty program summary\n if (invoice.add_credit > 0) { reportData.loyalty_program_summary.add_credit_total += invoice.add_credit; reportData.loyalty_program_summary.add_credit_count++; reportData.loyalty_program_summary.topup_paid_count++; }\n if (invoice.rewarded_credit > 0) { reportData.loyalty_program_summary.rewarded_credit_total += invoice.rewarded_credit; reportData.loyalty_program_summary.rewarded_credit_count++; }\n if (invoice.minus_credit > 0) { reportData.loyalty_program_summary.minus_credit_total += invoice.minus_credit; reportData.loyalty_program_summary.minus_credit_count++; }\n if (invoice.rewarded_point > 0) { reportData.loyalty_program_summary.rewarded_point_total += invoice.rewarded_point; reportData.loyalty_program_summary.rewarded_point_count++; }\n if (invoice.minus_point > 0) { reportData.loyalty_program_summary.minus_point_total += invoice.minus_point; reportData.loyalty_program_summary.minus_point_count++; }\n //reportData.sales_summary.voucher_total += invoice;\n // reportData.sales_summary.voucher_count\n // reportData.sales_summary.coupon_total\n // reportData.sales_summary.coupon_count\n reportData.sales_summary.total_pax += invoice.pax;\n if (invoice.pax > 0) reportData.sales_summary.pax_sales_total += invoice.grand_total;\n\n // Process item sales for item_sales_report\n invoice.lines.forEach((line: IInvoiceLine) => {\n // Top-up paid amount (actual payment for top-up items)\n if (line.item.add_credit > 0) reportData.loyalty_program_summary.topup_paid_total += line.subtotal;\n // 1. 生成唯一的菜品key: 菜品uid-modifier1:modifier1.quantity-modifier2:modifier2.quantity-modifier3:modifier3.quantity\n const itemKey = this.generateItemKey(line);\n \n // 2. 获取或创建商品销售汇总对象\n let existingItem = itemSalesMap.get(itemKey);\n \n if (existingItem) {\n // 3. 如果key已存在,更新quantity和total_amount字段\n existingItem.quantity += line.quantity;\n existingItem.total_amount = preciseRound(existingItem.total_amount + line.subtotal);\n \n // 处理modifier销售汇总(对于已存在的item也要累计modifier)\n if (line.modifiers && line.modifiers.length > 0) {\n line.modifiers.forEach((modifier: IInvoiceCoreLine) => {\n const modifierKey = modifier.item.name.trim();\n let existingModifier = modifierSalesMap.get(modifierKey);\n \n if (existingModifier) {\n existingModifier.quantity += modifier.quantity;\n existingModifier.total_amount = preciseRound(existingModifier.total_amount + (modifier.price * modifier.quantity));\n } else {\n existingModifier = new ModifierSalesSummary();\n existingModifier.item = modifier.item as IItem;\n existingModifier.quantity = modifier.quantity;\n existingModifier.total_amount = preciseRound(modifier.price * modifier.quantity);\n modifierSalesMap.set(modifierKey, existingModifier);\n }\n });\n }\n } else {\n // 4. 如果第一次添加,创建完整对象\n existingItem = new ItemSalesSummary();\n existingItem.item = line.item;\n existingItem.quantity = line.quantity;\n existingItem.total_amount = preciseRound(line.subtotal);\n existingItem.modifiers = [];\n \n // 5. 处理修饰符(只在首次创建时添加)\n if (line.modifiers && line.modifiers.length > 0) {\n line.modifiers.forEach((modifier: IInvoiceCoreLine) => {\n const newModifier: TItemCoreSalesSummary = {\n item: modifier.item as IItem,\n quantity: modifier.quantity,\n total_amount: preciseRound(modifier.price * modifier.quantity)\n };\n existingItem.modifiers.push(newModifier);\n \n // 处理modifier销售汇总 - 按name字段去除空白字符累计\n const modifierKey = modifier.item.name.trim();\n let existingModifier = modifierSalesMap.get(modifierKey);\n \n if (existingModifier) {\n existingModifier.quantity += modifier.quantity;\n existingModifier.total_amount = preciseRound(existingModifier.total_amount + (modifier.price * modifier.quantity));\n } else {\n existingModifier = new ModifierSalesSummary();\n existingModifier.item = modifier.item as IItem;\n existingModifier.quantity = modifier.quantity;\n existingModifier.total_amount = preciseRound(modifier.price * modifier.quantity);\n modifierSalesMap.set(modifierKey, existingModifier);\n }\n });\n }\n \n itemSalesMap.set(itemKey, existingItem);\n }\n });\n\n invoice.payments.forEach((payment: Payment) => {\n const currentPaymentSum = reportData.payments_summary.find((p) => p.code == payment.payment_method_code);\n if(!payment.tender_amount) payment.tender_amount = payment.change_amount\n if (currentPaymentSum) {\n currentPaymentSum.count++;\n currentPaymentSum.total = preciseRound(currentPaymentSum.total + (payment.tender_amount - payment.change_amount));\n } else {\n reportData.payments_summary.push({\n code: payment.payment_method_code,\n name: payment.payment_method_name,\n count: 1,\n total: preciseRound(payment.tender_amount - payment.change_amount),\n });\n }\n });\n }\n if (invoice.is_sales_exclusive) {\n reportData.sales_summary.foc_sales_total += invoice.grand_total;\n reportData.sales_summary.foc_sales_count++;\n }\n if (invoice.status == InvoiceStatus.Void) {\n reportData.sales_summary.void_invoice_total += invoice.grand_total;\n reportData.sales_summary.void_invoice_count++;\n }\n\n });\n\n // 5. 输出时输出成数组的形式,按照category.sequence, item.sequence排序\n const itemSalesArray = Array.from(itemSalesMap.values());\n itemSalesArray.sort((a, b) => {\n // 首先按category.sequence分组\n const aCategory = categoryMap.get(a.item.category_uid);\n const bCategory = categoryMap.get(b.item.category_uid);\n const aCategorySeq = aCategory?.sequence ?? 999999;\n const bCategorySeq = bCategory?.sequence ?? 999999;\n if (aCategorySeq !== bCategorySeq) {\n return aCategorySeq - bCategorySeq;\n }\n // 相同category,按item.sequence排序\n const aItemSeq = a.item.sequence ?? 999999;\n const bItemSeq = b.item.sequence ?? 999999;\n return aItemSeq - bItemSeq;\n });\n \n reportData.item_sales_summary = itemSalesArray;\n\n // Calculate total and group by category in one pass\n let totalAmount = 0;\n let totalItems = 0;\n const categorySalesMap = new Map<string, TCategorySalesSummary>();\n\n itemSalesArray.forEach(item => {\n // Calculate totals\n totalAmount += item.total_amount;\n totalItems += item.quantity;\n\n // Group by category (skip items without category)\n if (!item.item.category_uid) return;\n\n const categoryUid = item.item.category_uid;\n let categorySummary = categorySalesMap.get(categoryUid);\n\n if (!categorySummary) {\n categorySummary = new CategorySalesSummary();\n categorySummary.category = categoryMap.get(item.item.category_uid) || null;\n categorySalesMap.set(categoryUid, categorySummary);\n }\n\n categorySummary.items.push(item);\n categorySummary.total_quantity += item.quantity;\n categorySummary.total_amount += item.total_amount;\n });\n\n reportData.item_sales_summary_total = preciseRound(totalAmount);\n reportData.item_sales_summary_total_count = totalItems;\n\n // 按照 category.sequence 排序\n const categorySalesArray = Array.from(categorySalesMap.values());\n categorySalesArray.sort((a, b) => {\n const aSeq = a.category?.sequence ?? 999999;\n const bSeq = b.category?.sequence ?? 999999;\n return aSeq - bSeq;\n });\n\n // 对每个类别内的菜品按照金额降序排序,并精确化类别总额\n categorySalesArray.forEach(category => {\n category.total_amount = preciseRound(category.total_amount);\n category.items.sort((a, b) => {\n // 按照 total_amount 降序排序\n if (b.total_amount !== a.total_amount) {\n return b.total_amount - a.total_amount;\n }\n // 如果金额相同,按 quantity 降序排序\n return b.quantity - a.quantity;\n });\n });\n\n reportData.item_sales_summary_by_category = categorySalesArray;\n\n // Process modifier sales summary\n const modifierSalesArray = Array.from(modifierSalesMap.values());\n modifierSalesArray.sort((a, b) => {\n // 首先按quantity降序排序\n if (b.quantity !== a.quantity) {\n return b.quantity - a.quantity;\n }\n // 如果quantity相同,按total_amount降序排序\n return b.total_amount - a.total_amount;\n });\n \n reportData.modifier_sales_summary = modifierSalesArray;\n \n // Calculate modifier totals\n let totalModifierAmount = 0;\n let totalModifiers = 0;\n \n reportData.modifier_sales_summary.forEach(modifier => {\n totalModifierAmount += modifier.total_amount;\n totalModifiers += modifier.quantity;\n });\n \n reportData.modifier_sales_summary_total = preciseRound(totalModifierAmount);\n reportData.modifier_sales_summary_total_count = totalModifiers;\n\n reportData.sales_summary.paid_invoice_total = preciseRound(reportData.sales_summary.paid_invoice_total);\n reportData.sales_summary.sales_total = preciseRound(reportData.sales_summary.sales_total);\n reportData.sales_summary.rounding_total = preciseRound(reportData.sales_summary.rounding_total);\n reportData.sales_summary.tax_total = preciseRound(reportData.sales_summary.tax_total);\n reportData.sales_summary.service_charge_total = preciseRound(reportData.sales_summary.service_charge_total);\n reportData.sales_summary.discount_total = preciseRound(reportData.sales_summary.discount_total);\n reportData.sales_summary.foc_sales_total = preciseRound(reportData.sales_summary.foc_sales_total);\n reportData.sales_summary.void_invoice_total = preciseRound(reportData.sales_summary.void_invoice_total);\n reportData.sales_summary.pax_sales_total = preciseRound(reportData.sales_summary.pax_sales_total);\n reportData.loyalty_program_summary.add_credit_total = preciseRound(reportData.loyalty_program_summary.add_credit_total);\n reportData.loyalty_program_summary.topup_paid_total = preciseRound(reportData.loyalty_program_summary.topup_paid_total);\n reportData.loyalty_program_summary.rewarded_credit_total = preciseRound(reportData.loyalty_program_summary.rewarded_credit_total);\n reportData.loyalty_program_summary.minus_credit_total = preciseRound(reportData.loyalty_program_summary.minus_credit_total);\n return reportData;\n }\n\n /**\n * 生成唯一的菜品key\n * 格式: 菜品uid-modifier1:modifier1.quantity-modifier2:modifier2.quantity-modifier3:modifier3.quantity\n * 修饰符按uid排序,去除相同菜品不同modifier顺序的影响\n */\n private generateItemKey(line: IInvoiceLine): string {\n let key = line.item.uid;\n \n if (line.modifiers && line.modifiers.length > 0) {\n // 2. 按照modifier:modifier.quantity进行排序,去除相同菜品不同modifier顺序的影响\n const sortedModifiers = [...line.modifiers].sort((a, b) => {\n // 按照modifier.name:modifier.quantity的组合排序,name需要去掉两头的空白字符\n const aKey = `${a.item.name.trim()}:${a.quantity}`;\n const bKey = `${b.item.name.trim()}:${b.quantity}`;\n return aKey.localeCompare(bKey);\n });\n \n // 生成修饰符部分\n const modifierParts = sortedModifiers.map(modifier => \n `${modifier.item.uid}:${modifier.quantity}`\n );\n \n key += '-' + modifierParts.join('-');\n }\n \n return key;\n }\n}\n\n\nexport type IPrintJobService = IAppRemoteService<IPrintJob> & {\n /**\n * Autoquery print jobs\n * @param builder autoquery builder\n */\n autoquery(builder: QueryBuilder<IPrintJob>): Promise<QueryResponse<IPrintJob>>;\n\n replacePrinter(printJob: IPrintJob, printer: IPrinter): IPrintJob;\n};\nexport class PrintJobService extends AppRemoteService<IPrintJob> implements IPrintJobService {\n constructor(readonly http: AxiosInstance, readonly db: Dexie, readonly options: IServiceOptions, readonly moduleName = 'print_jobs', readonly methodName = 'print_job') {\n super();\n }\n\n public async autoquery(builder: QueryBuilder<IPrintJob>): Promise<QueryResponse<IPrintJob>> {\n const inputParams = builder.build();\n return await this.http.get(`sapi/v5/merchants/${this.options.merchant_uid}/${this.moduleName}`, { params: { ...inputParams } });\n }\n\n public replacePrinter(printJob: IPrintJob, printer: IPrinter): IPrintJob {\n printJob.printer_name = printer.name;\n printJob.printer_ip = printer.ip_address;\n printJob.printer_type = printer.type;\n printJob.printer_uid = printer.uid;\n printJob.driver_printer_name = printer.driver_printer_name;\n return printJob;\n }\n}\n\nexport type IMenuService = IAppRemoteService<IMenu>;\n\nexport class MenuService extends AppRemoteService<IMenu> implements IMenuService {\n constructor(readonly http: AxiosInstance, readonly db: Dexie, readonly options: IServiceOptions, readonly moduleName = 'menus', readonly methodName = 'menu') {\n super();\n }\n}\n\nexport interface IPrintTemplateService extends IAppRemoteService<IPrintTemplate> {\n /**\n * initialize all default print templates, it should be called only once\n * @returns void\n */\n initialize(): Promise<void>;\n\n /**\n * Render print template\n * @param invoice invoice to render\n * @param config config to render\n * @param template template to render\n * @returns print command\n */\n renderPrintTemplate(invoice: IInvoice, config: IConfig, template: IPrintTemplate, options: IRenderPrintTemplateOptions): Promise<IPrintCommand>;\n\n /**\n * Render report print template\n * @param reportData report data to render\n * @param template template to render\n * @returns print command\n */\n renderReportPrintTemplate(reportData: IReportData, config: IConfig, template: IPrintTemplate, options?: IRenderPrintTemplateOptions): Promise<IPrintCommand>;\n\n /**\n * Render print template by data\n * @param template template to render\n * @param templateData template data to render\n * @param options options to render\n * @returns print command\n */\n renderPrintTemplateByData(template: IPrintTemplate, templateData: ITemplateData, options?: IRenderPrintTemplateOptions): Promise<IPrintCommand>;\n}\n\nexport class PrintTemplateService extends AppRemoteService<IPrintTemplate> implements IPrintTemplateService {\n httpClient: AxiosInstance;\n private secretKey = 'tKB84ZlZRzLzA2LcglNNLquucKZwtJApRTaPKjAJHFbDd8nJRD';\n\n constructor(readonly http: AxiosInstance, readonly db: Dexie, readonly options: IServiceOptions, readonly moduleName = 'print_templates', readonly methodName = 'print_template') {\n super();\n this.httpClient = axios.create({\n baseURL: 'https://revopos-cdn.sgp1.digitaloceanspaces.com',\n timeout: 3000,\n });\n }\n\n public async initialize(): Promise<void> {\n if (!(await this.getOneByParams({ printer_type: PrinterType.ReceiptPrinter }))) {\n const receipt = new PrintTemplate();\n receipt.name = 'Default Receipt Template';\n receipt.body = await this.getPrintTemplate('rbt');\n receipt.header = await this.getPrintTemplate('rht');\n receipt.footer = await this.getPrintTemplate('rft');\n receipt.printer_type = PrinterType.ReceiptPrinter;\n await this.addOne(receipt);\n console.log('Default Receipt Template added');\n }\n\n if (!(await this.getOneByParams({ printer_type: PrinterType.CheckPrinter }))) {\n const check = new PrintTemplate();\n check.name = 'Default Check Template';\n check.body = await this.getPrintTemplate('cbt');\n check.header = await this.getPrintTemplate('cht');\n check.footer = await this.getPrintTemplate('cft');\n check.printer_type = PrinterType.CheckPrinter;\n await this.addOne(check);\n console.log('Default Check Template added');\n }\n\n if (!(await this.getOneByParams({ printer_type: PrinterType.OrderPrinter }))) {\n const order = new PrintTemplate();\n order.name = 'Default docket Template';\n order.body = await this.getPrintTemplate('obt');\n order.header = await this.getPrintTemplate('oht');\n order.footer = await this.getPrintTemplate('oft');\n order.printer_type = PrinterType.OrderPrinter;\n await this.addOne(order);\n console.log('Default Order Template added');\n }\n\n if (!(await this.getOneByParams({ printer_type: PrinterType.KitchenPrinter }))) {\n const kitchen = new PrintTemplate();\n kitchen.name = 'Default Kitchen Template';\n kitchen.body = await this.getPrintTemplate('kbt');\n kitchen.header = await this.getPrintTemplate('kht');\n kitchen.footer = await this.getPrintTemplate('kft');\n kitchen.printer_type = PrinterType.KitchenPrinter;\n await this.addOne(kitchen);\n console.log('Default Kitchen Template added');\n }\n\n if(!(await this.getOneByParams({ printer_type: PrinterType.KioskPrinter }))) {\n const kiosk = new PrintTemplate();\n kiosk.name = 'Default Kiosk Template';\n kiosk.body = await this.getPrintTemplate('kioskbt');\n kiosk.header = await this.getPrintTemplate('kioskht');\n kiosk.footer = await this.getPrintTemplate('kioskft');\n kiosk.printer_type = PrinterType.KioskPrinter;\n await this.addOne(kiosk);\n console.log('Default Kiosk Template added');\n }\n\n if(!(await this.getOneByParams({ printer_type: PrinterType.LabelPrinter }))) {\n const labelTemplate = new PrintTemplate();\n labelTemplate.commands = await this.getPrintTemplate('tspl_cmds');\n labelTemplate.name = 'Default Label Template';\n labelTemplate.printer_type = PrinterType.LabelPrinter;\n await this.addOne(labelTemplate);\n }\n\n if(!(await this.getOneByParams({ printer_type: PrinterType.QrCodePrinter }))) {\n const qrTemplate = new PrintTemplate();\n qrTemplate.name = 'Default QR Code Template';\n qrTemplate.body = await this.getPrintTemplate('qrbt');\n qrTemplate.header = await this.getPrintTemplate('qrht');\n qrTemplate.footer = await this.getPrintTemplate('qrft');\n qrTemplate.printer_type = PrinterType.QrCodePrinter;\n await this.addOne(qrTemplate);\n }\n\n if (!(await this.getOneByParams({ report_code_name: 'sales_summary_report' }))) {\n const report = new PrintTemplate();\n report.name = 'Sales Summary Report';\n report.body = await this.getPrintTemplate('sumbt');\n report.header = await this.getPrintTemplate('sumht');\n report.footer = await this.getPrintTemplate('sumft');\n report.report_code_name = 'sales_summary_report';\n await this.addOne(report);\n console.log('Sales Summary Report Template added');\n }\n\n if (!(await this.getOneByParams({ report_code_name: 'shift_report' }))) {\n const report = new PrintTemplate();\n report.name = 'Shift Report';\n report.body = await this.getPrintTemplate('sbt');\n report.header = await this.getPrintTemplate('sht');\n report.footer = await this.getPrintTemplate('sft');\n report.report_code_name = 'shift_report';\n await this.addOne(report);\n console.log('Shift Report Template added');\n }\n\n if (!(await this.getOneByParams({ report_code_name: 'item_sales_report' }))) {\n const report = new PrintTemplate();\n report.name = 'Item Sales Report';\n report.body = await this.getPrintTemplate('isrbt');\n report.header = await this.getPrintTemplate('isrht');\n report.footer = await this.getPrintTemplate('isrft');\n report.report_code_name = 'item_sales_report';\n await this.addOne(report);\n console.log('Item Sales Report Template added');\n }\n\n if (!(await this.getOneByParams({ report_code_name: 'modifier_sales_report' }))) {\n const report = new PrintTemplate();\n report.name = 'Modifier Sales Report';\n report.body = await this.getPrintTemplate('msrbt');\n report.header = await this.getPrintTemplate('msrht');\n report.footer = await this.getPrintTemplate('msrft');\n report.report_code_name = 'modifier_sales_report';\n await this.addOne(report);\n console.log('Modifier Sales Report Template added');\n }\n }\n\n public async renderPrintTemplate(invoice: IInvoice, config: IConfig, template: IPrintTemplate, options = new RenderPrintTemplateOptions()): Promise<IPrintCommand> {\n const printCommand = new PrintCommand();\n if(template.printer_type == PrinterType.KitchenPrinter || template.printer_type == PrinterType.OrderPrinter) {\n printCommand.codepage = template.codepage || this.getCodepageByCountryCode(config.kitchen.language);\n } else {\n printCommand.codepage = template.codepage || this.getCodepageByCountryCode(config.receipt.language);\n }\n const templateData = new TemplateData();\n templateData.invoice = invoice;\n templateData.config = config;\n templateData.normalized_printed_at = humanizedData(templateData.printed_at, config?.order?.datetime_format);\n templateData.printer_name = options.printer_name;\n if (options.is_cancel) templateData.is_cancel = options.is_cancel;\n printCommand.items.push(...(await this.renderPrintCommand(template.header, templateData)));\n printCommand.items.push(...(await this.renderPrintCommand(template.body, templateData)));\n printCommand.items.push(...(await this.renderPrintCommand(template.footer, templateData)));\n return printCommand;\n }\n\n public async renderReportPrintTemplate(reportData: ReportData, config: IConfig, template: IPrintTemplate, options = new RenderPrintTemplateOptions()): Promise<IPrintCommand> {\n const printCommand = new PrintCommand();\n const templateData = new TemplateData();\n templateData.report_data = reportData;\n templateData.config = config;\n templateData.normalized_printed_at = humanizedData(templateData.printed_at, config?.order?.datetime_format);\n printCommand.codepage = template.codepage || Codepages.SimplifiedChinese;\n printCommand.items.push(...(await this.renderPrintCommand(template.header, templateData)));\n printCommand.items.push(...(await this.renderPrintCommand(template.body, templateData)));\n printCommand.items.push(...(await this.renderPrintCommand(template.footer, templateData)));\n return printCommand;\n }\n\n public async renderPrintTemplateByData(template: IPrintTemplate, templateData: ITemplateData, options = new RenderPrintTemplateOptions()): Promise<IPrintCommand> {\n const printCommand = new PrintCommand();\n printCommand.items.push(...(await this.renderPrintCommand(template.header, templateData)));\n printCommand.items.push(...(await this.renderPrintCommand(template.body, templateData)));\n printCommand.items.push(...(await this.renderPrintCommand(template.footer, templateData)));\n return printCommand;\n }\n\n private async getPrintTemplate(fileName: string): Promise<string> {\n const res = await this.httpClient.get(`/xpos-core/${fileName}.enc`, { responseType: 'text' });\n const bytes = CryptoJS.AES.decrypt(res.data, this.secretKey);\n return bytes.toString(CryptoJS.enc.Utf8);\n }\n\n private getCodepageByCountryCode(countryCode: string): Codepages {\n const countryCodeToCodepage: { [key: string]: Codepages } = {\n US: Codepages.English,\n GR: Codepages.Greek,\n DE: Codepages.WesternEurope,\n LT: Codepages.BalticRim,\n PL: Codepages.CentralEurope,\n RU: Codepages.Cyrillic,\n TR: Codepages.Turkish,\n EU: Codepages.MultilingualLatin1WithEuro,\n PT: Codepages.Portuguese,\n IS: Codepages.Icelandic,\n IL: Codepages.Hebrew,\n CA: Codepages.FrenchCanadian,\n EG: Codepages.Arabic,\n NO: Codepages.Nordic,\n BY: Codepages.Russian,\n MK: Codepages.ModernGreek,\n CN: Codepages.SimplifiedChinese,\n KR: Codepages.Korean,\n TW: Codepages.TraditionalChinese,\n FR: Codepages.WesternEuropeanLatin,\n AE: Codepages.ArabicISO,\n JP: Codepages.Japanese,\n CZ: Codepages.CentralEuropeanLatinWindows,\n BG: Codepages.CyrillicWindows,\n ES: Codepages.WesternEuropeanLatinWindows,\n CY: Codepages.GreekWindows,\n AZ: Codepages.TurkishWindows,\n PS: Codepages.HebrewWindows,\n SA: Codepages.ArabicWindows,\n LV: Codepages.BalticWindows,\n VN: Codepages.Vietnamese,\n };\n\n if (!countryCode) return countryCodeToCodepage['CN'];\n const upperCaseCountryCode = countryCode.toUpperCase();\n return countryCodeToCodepage[upperCaseCountryCode] || countryCodeToCodepage['CN'];\n }\n\n private async renderPrintCommand(template: string, data: ITemplateData): Promise<IPrintCommandLine[]> {\n try {\n const st = new SelectTransform();\n const templateObj = JSON.parse(template);\n console.log('template', JSON.stringify(templateObj));\n console.log('templateData', JSON.stringify(data));\n let result = await st.transform(templateObj, data, false);\n result = _.flatMap(result, (item) => item);\n result = _.compact(result);\n return result;\n } catch (error) {\n // Handle the error here\n console.error(error);\n throw error;\n }\n }\n}\n\nexport type TStorageService<T = Record<string, unknown>> = IAppRemoteService<IStorage<T>>;\nexport class StorageService<T = Record<string, unknown>> extends AppRemoteService<IStorage<T>> implements TStorageService<T> {\n constructor(readonly http: AxiosInstance, readonly db: Dexie, readonly options: IServiceOptions,\n readonly moduleName = 'storages', readonly methodName = 'storage') {\n super();\n }\n}\n\nexport type IStockLogService = IAppRemoteService<IStockLog>;\nexport class StockLogService extends AppRemoteService<IStockLog> implements IStockLogService {\n constructor(readonly http: AxiosInstance, readonly db: Dexie, readonly options: IServiceOptions, readonly moduleName = 'stock_logs', readonly methodName = 'stock_log') {\n super();\n }\n}\n\n","import axios from 'axios';\n\n/**\n * create a new instance of axios\n * @param baseURL \n * @param key \n * @param uid \n * @param token \n * @returns \n */\nexport function createInstance(baseURL: string, uid: string, token: string) {\n const instance = axios.create({\n baseURL: baseURL,\n timeout: 20000,\n headers: { 'x-device-uid': uid, 'Authorization': `Bearer ${token}`}\n });\n\n instance.interceptors.response.use(\n function (response) {\n return response.data;\n },\n function (error) {\n return Promise.reject(error);\n },\n );\n\n return instance;\n}\n","import { createInstance } from './utils/http.utils';\nimport { ServiceMode, IServiceOptions } from './types/misc.type';\nimport { IAppRemoteService } from './services/abstract.service';\nimport {\n CategoryService,\n ItemService,\n SectionService,\n SectionItemService,\n ShiftService,\n TillService,\n EmployeeService,\n PaymentMethodService,\n ConfigService,\n AppReportService,\n PrintJobService,\n PrintTemplateService,\n EmployeeRoleService,\n StorageService,\n MenuService,\n StockLogService,\n} from './services/app.service';\nimport { Dexie } from 'dexie';\nimport { InvoiceService } from './services/invoice.service';\nimport { PrinterService } from './services/printer.service';\nimport { OrderDisplayService } from './services/ods.service';\nimport { ElectronSocket } from './libs/electron.socket';\n\nconst serviceProvider = new Map<string, any>([\n ['Item', ItemService],\n ['Section', SectionService],\n ['SectionItem', SectionItemService],\n ['Category', CategoryService],\n // ['Subcategory', SubcategoryService],\n ['Config', ConfigService],\n ['Shift', ShiftService],\n ['Till', TillService],\n ['Employee', EmployeeService],\n // ['\n ['PaymentMethod', PaymentMethodService],\n ['Invoice', InvoiceService],\n ['Report', AppReportService],\n ['Printer', PrinterService],\n ['PrintJob', PrintJobService],\n ['PrintTemplate', PrintTemplateService],\n [\"EmployeeRole\", EmployeeRoleService],\n ['OrderDisplay', OrderDisplayService],\n ['Storage', StorageService],\n ['Menu', MenuService],\n ['StockLog', StockLogService],\n]);\n\n// Base schema for most tables\nconst baseSchema = 'uid, updated_at, created_at, deleted_at, _timestamp, id_in_server, created_at_timestamp';\n\n// Extend base schema with additional properties for specific categories\nconst sequenceBaseSchema = `${baseSchema}, sequence`;\nconst shiftBaseSchema = `${sequenceBaseSchema}, status`;\nconst tillBaseSchema = `${baseSchema}, till_type, shift_uid, invoice_uid`;\nconst paymentMethodBaseSchema = `${sequenceBaseSchema}, payment_method_code, is_disabled`;\nconst invoiceSchema = `${baseSchema}, type, status, table_uid`;\nconst itemsSchema = `${sequenceBaseSchema}, name, barcode, codename`;\nconst printJobSchema = `${baseSchema}, status, printer_type, connection_type, protocol, save_only, device_uid_to_print`;\nconst printTemplateSchema = `${baseSchema}, name, printer_type`;\nconst orderDisplaySchema = `${baseSchema}, order_number, status`;\nconst storageSchema = `${baseSchema}, model`;\n// Define schema for each table, categorized by their base schema\nexport const dbSchemas = {\n // Tables using the sequence base schema\n items: itemsSchema,\n sections: sequenceBaseSchema,\n section_items: sequenceBaseSchema,\n categories: sequenceBaseSchema,\n // Table using the shift base schema\n shifts: shiftBaseSchema,\n // Table using the till base schema\n tills: tillBaseSchema,\n // Tables using the base schema only\n employees: `${baseSchema}, role_uid`,\n // Table using the payment method base schema\n payment_methods: paymentMethodBaseSchema,\n invoices: invoiceSchema,\n configs: baseSchema,\n reports: baseSchema,\n printers: baseSchema,\n print_jobs: printJobSchema,\n print_templates: printTemplateSchema,\n employee_roles: `${baseSchema}, name, is_default`,\n order_displays: orderDisplaySchema,\n storages: storageSchema,\n menus: baseSchema,\n stock_logs: `${baseSchema}, entity_type, entity_uid, type`,\n};\n\nenum DbStatus {\n DISCONNECTED = 'disconnected',\n CONNECTED = 'connected',\n ERROR = 'error',\n}\n\nexport class ServiceFactory {\n private mode: ServiceMode;\n private readonly http;\n public dataSource: Dexie;\n private status: DbStatus = DbStatus.DISCONNECTED;\n\n constructor(readonly options: IServiceOptions, readonly win: any, withoutDbInit = false) {\n this.mode = options.mode;\n this.http = createInstance(options.base_url, options.device_uid, options.token);\n if (!withoutDbInit) this.initializeDatabase();\n ElectronSocket.setWindow(win);\n }\n\n /**\n * Static factory method to create and initialize a ServiceFactory instance\n * Use this instead of constructor + separate init call for proper async handling\n */\n public static async init(options: IServiceOptions, win: any, withoutDbInit = false): Promise<ServiceFactory> {\n const factory = new ServiceFactory(options, win, true); // Pass true to skip DB init in constructor\n if (!withoutDbInit) await factory.initializeDatabase();\n return factory;\n }\n\n public async initializeDatabase() {\n try {\n if (!this.options.database || !this.options.database.name) throw new Error('Database name is not defined');\n this.dataSource = await new Dexie(this.options.database.name);\n this.dataSource.version(29).stores(dbSchemas);\n this.status = DbStatus.CONNECTED;\n } catch (e) {\n this.status = DbStatus.ERROR;\n console.error('Database connection error:', e);\n }\n return this.dataSource;\n }\n\n async dropDatabase() {\n await Dexie.delete(this.options.database.name);\n await this.initializeDatabase();\n }\n\n public clearTableData(tableName: string) {\n return this.dataSource.table(tableName).clear();\n }\n\n\n\n async getService<T>(serviceClass): Promise<T> {\n if (this.status == DbStatus.ERROR) throw new Error('Database connection error');\n\n while (this.status == DbStatus.DISCONNECTED) await new Promise((resolve) => setTimeout(resolve, 100));\n try {\n return new serviceClass(this.http, this.dataSource, this.options) as T;\n } catch (e: any) {\n throw new Error('Service instantiation error: ' + e?.message);\n }\n }\n\n async getServiceByName(modelName: string): Promise<IAppRemoteService<any>> {\n if (this.status == DbStatus.ERROR) throw new Error('Database connection error');\n\n while (this.status == DbStatus.DISCONNECTED) await new Promise((resolve) => setTimeout(resolve, 100));\n try {\n const service = serviceProvider.get(modelName);\n\n if (!service) {\n throw new Error(`No service found for model: ${modelName}`);\n }\n\n // Note: If you have specific service classes per model, replace the line below accordingly.\n return new service(this.http, this.dataSource, this.options) as IAppRemoteService<any>;\n } catch (e: any) {\n throw new Error('Service instantiation error: ' + e?.message);\n }\n }\n\n \n}\n","import { IExportRow } from '../types/csv.type';\nimport { ICategory, IItem, ICoreCategory, ICoreItem, Category, Item, CoreCategory, CoreItem, ProductType, IComboGroup, IComboGroupItem, ComboGroup, ComboGroupItem } from '../types/product.type';\n\n/** Create CSV export blob from categories and products */\nexport function createCSVExport(\n categories: ICategory[],\n products: IItem[],\n filename: string = 'export.csv'\n): Blob {\n const rows = convertToExportRows(categories, products);\n const csvContent = convertToCSV(rows);\n const BOM = '\\uFEFF';\n return new Blob([BOM + csvContent], { type: 'text/csv;charset=utf-8;' });\n}\n\nfunction sanitizeStock(stock: any): number | undefined {\n if (stock === null || stock === undefined || stock === '') return undefined;\n if (typeof stock === 'number' && !isNaN(stock)) return stock;\n if (typeof stock === 'string') {\n const parsed = parseFloat(stock);\n return !isNaN(parsed) ? parsed : undefined;\n }\n return undefined;\n}\n\n/** Convert categories and products to CSV export rows */\nfunction convertToExportRows(categories: ICategory[], products: IItem[]): IExportRow[] {\n const rows: IExportRow[] = [];\n\n for (const category of categories) {\n rows.push({\n type: 'category',\n name: category.name,\n sku: '',\n price: undefined,\n stock: undefined,\n is_internal: category.is_internal,\n min_order: undefined,\n max_order: undefined,\n image_url: category.image_url || '',\n image_thumbnail_url: category.image_thumbnail_url || '',\n sequence: category.sequence\n });\n\n const categoryItems = products.filter(item => item.category_uid === category.uid);\n\n for (const item of categoryItems) {\n const isCombo = item.type === ProductType.Combo;\n rows.push({\n type: isCombo ? 'combo' : 'product',\n name: item.name,\n sku: item.sku || '',\n price: item.price,\n stock: sanitizeStock(item.stock),\n is_internal: item.is_internal,\n min_order: undefined,\n max_order: undefined,\n image_url: item.image_url || '',\n image_thumbnail_url: item.image_thumbnail_url || '',\n sequence: item.sequence\n });\n\n // Export combo_groups for combo products\n if (isCombo && item.combo_groups && item.combo_groups.length > 0) {\n for (const comboGroup of item.combo_groups) {\n rows.push({\n type: 'combo_group',\n name: comboGroup.name,\n sku: '',\n price: undefined,\n stock: undefined,\n is_internal: undefined,\n min_order: comboGroup.min_order,\n max_order: comboGroup.max_order,\n image_url: '',\n image_thumbnail_url: '',\n sequence: comboGroup.sequence\n });\n if (comboGroup.combo_items && comboGroup.combo_items.length > 0) {\n for (const comboItem of comboGroup.combo_items) {\n rows.push({\n type: 'combo_item',\n name: comboItem.combo_item?.name || '',\n sku: '',\n price: comboItem.price,\n stock: undefined,\n is_internal: undefined,\n min_order: undefined,\n max_order: undefined,\n image_url: '',\n image_thumbnail_url: '',\n sequence: comboItem.sequence,\n item_uid: comboItem.item_uid\n });\n }\n }\n }\n }\n\n // Export modifier categories for non-combo products\n if (!isCombo && item.modifier_categories && item.modifier_categories.length > 0) {\n for (const modifierCategory of item.modifier_categories) {\n rows.push({\n type: 'modifier_category',\n name: modifierCategory.name,\n sku: '',\n price: undefined,\n stock: undefined,\n is_internal: undefined,\n min_order: modifierCategory.min_order,\n max_order: modifierCategory.max_order,\n image_url: '',\n image_thumbnail_url: '',\n sequence: modifierCategory.sequence\n });\n if (item.modifiers && item.modifiers.length > 0) {\n const categoryModifiers = item.modifiers.filter(modifier => modifier.category_uid === modifierCategory.uid);\n for (const modifier of categoryModifiers) {\n rows.push({\n type: 'modifier',\n name: modifier.name,\n sku: modifier.sku || '',\n price: modifier.price,\n stock: sanitizeStock(modifier.stock),\n is_internal: modifier.is_internal,\n min_order: undefined,\n max_order: undefined,\n image_url: modifier.image_url || '',\n image_thumbnail_url: modifier.image_thumbnail_url || '',\n sequence: modifier.sequence\n });\n }\n }\n }\n }\n }\n }\n\n return rows;\n}\n\n/** Convert export rows to CSV string */\nfunction convertToCSV(rows: IExportRow[]): string {\n const headers = ['Type', 'Name', 'SKU', 'Price', 'Stock', 'Is Internal', 'Min Order', 'Max Order', 'Image URL', 'Thumbnail URL', 'Sequence', 'Item UID'];\n const csvRows = [headers.join(',')];\n\n for (const row of rows) {\n const values = [\n row.type,\n `\"${row.name.replace(/\"/g, '\"\"')}\"`,\n row.sku || '',\n row.price !== undefined ? row.price.toString() : '',\n row.stock !== undefined ? row.stock.toString() : '',\n row.is_internal !== undefined ? row.is_internal.toString() : '',\n row.min_order !== undefined ? row.min_order.toString() : '',\n row.max_order !== undefined ? row.max_order.toString() : '',\n row.image_url || '',\n row.image_thumbnail_url || '',\n row.sequence !== undefined ? row.sequence.toString() : '',\n row.item_uid || ''\n ];\n csvRows.push(values.join(','));\n }\n\n return csvRows.join('\\n');\n}\n\n/** Import categories and products from CSV file */\nexport async function importFromCSV(file: File): Promise<{\n categories: ICategory[];\n products: IItem[];\n}> {\n const csvContent = await file.text();\n const rows = parseCSVContent(csvContent);\n return convertToEntities(rows);\n}\n\nconst VALID_TYPES = ['category', 'product', 'modifier_category', 'modifier', 'combo', 'combo_group', 'combo_item'];\n\n/** Parse CSV content into export rows */\nfunction parseCSVContent(csvContent: string): IExportRow[] {\n const normalizedContent = csvContent\n .replace(/^\\uFEFF/, '')\n .replace(/\\r\\n/g, '\\n')\n .replace(/\\r/g, '\\n');\n\n const lines = normalizedContent.trim().split('\\n');\n if (lines.length === 0) throw new Error('CSV file is empty');\n\n const header = lines[0].trim();\n const expectedHeader = 'Type,Name,SKU,Price,Stock,Is Internal,Min Order,Max Order,Image URL,Thumbnail URL,Sequence,Item UID';\n const legacyHeader = 'Type,Name,SKU,Price,Stock,Is Internal,Min Order,Max Order,Image URL,Thumbnail URL,Sequence';\n const isLegacy = header === legacyHeader;\n if (header !== expectedHeader && !isLegacy) {\n throw new Error(`Invalid CSV header. Expected: ${expectedHeader}\\nReceived: ${header}`);\n }\n\n const rows: IExportRow[] = [];\n const expectedColumns = isLegacy ? 11 : 12;\n\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i].trim();\n if (!line) continue;\n\n const values = parseCSVLine(line);\n if (values.length !== expectedColumns) {\n throw new Error(`Invalid CSV row at line ${i + 1}: expected ${expectedColumns} columns`);\n }\n\n const [type, name, sku, priceStr, stockStr, isInternalStr, minOrderStr, maxOrderStr, imageUrl, thumbnailUrl, sequenceStr] = values;\n const itemUid = isLegacy ? '' : values[11];\n\n if (!type || !name.trim()) throw new Error(`Missing required fields at line ${i + 1}`);\n if (!VALID_TYPES.includes(type)) {\n throw new Error(`Invalid type \"${type}\" at line ${i + 1}. Must be: ${VALID_TYPES.join(', ')}`);\n }\n\n let price: number | undefined;\n if (priceStr && priceStr.trim()) {\n price = parseFloat(priceStr);\n if (isNaN(price)) throw new Error(`Invalid price \"${priceStr}\" at line ${i + 1}`);\n }\n\n let stock: number | undefined;\n if (stockStr && stockStr.trim()) {\n stock = parseFloat(stockStr);\n if (isNaN(stock)) throw new Error(`Invalid stock \"${stockStr}\" at line ${i + 1}`);\n }\n\n let is_internal: boolean | undefined;\n if (isInternalStr && isInternalStr.trim()) {\n if (isInternalStr.trim() === 'true') is_internal = true;\n else if (isInternalStr.trim() === 'false') is_internal = false;\n else throw new Error(`Invalid is_internal \"${isInternalStr}\" at line ${i + 1}. Must be: true or false`);\n }\n\n let min_order: number | undefined;\n if (minOrderStr && minOrderStr.trim()) {\n min_order = parseInt(minOrderStr, 10);\n if (isNaN(min_order)) throw new Error(`Invalid min_order \"${minOrderStr}\" at line ${i + 1}`);\n }\n\n let max_order: number | undefined;\n if (maxOrderStr && maxOrderStr.trim()) {\n max_order = parseInt(maxOrderStr, 10);\n if (isNaN(max_order)) throw new Error(`Invalid max_order \"${maxOrderStr}\" at line ${i + 1}`);\n }\n\n let sequence: number | undefined;\n if (sequenceStr && sequenceStr.trim()) {\n sequence = parseInt(sequenceStr, 10);\n if (isNaN(sequence)) throw new Error(`Invalid sequence \"${sequenceStr}\" at line ${i + 1}`);\n }\n\n rows.push({\n type: type as IExportRow['type'],\n name: name.trim(),\n sku: sku?.trim() || '',\n price,\n stock,\n is_internal,\n min_order,\n max_order,\n image_url: imageUrl?.trim() || '',\n image_thumbnail_url: thumbnailUrl?.trim() || '',\n sequence,\n item_uid: itemUid?.trim() || ''\n });\n }\n\n return rows;\n}\n\n/** Parse a single CSV line, handling quoted values */\nfunction parseCSVLine(line: string): string[] {\n const values: string[] = [];\n let current = '';\n let inQuotes = false;\n\n for (let i = 0; i < line.length; i++) {\n const char = line[i];\n if (char === '\"') {\n if (inQuotes && line[i + 1] === '\"') {\n current += '\"';\n i++;\n } else {\n inQuotes = !inQuotes;\n }\n } else if (char === ',' && !inQuotes) {\n values.push(current);\n current = '';\n } else {\n current += char;\n }\n }\n\n values.push(current);\n return values;\n}\n\n/** Convert export rows to categories and products */\nfunction convertToEntities(rows: IExportRow[]): {\n categories: ICategory[];\n products: IItem[];\n} {\n const categories: ICategory[] = [];\n const products: IItem[] = [];\n\n let currentCategory: ICategory | null = null;\n let currentProduct: IItem | null = null;\n let currentModifierCategory: ICoreCategory | null = null;\n let currentComboGroup: IComboGroup | null = null;\n let categorySequence = 0;\n\n for (const row of rows) {\n if (row.type === 'category') {\n currentCategory = new Category();\n currentCategory.name = row.name;\n currentCategory.is_internal = row.is_internal !== undefined ? row.is_internal : false;\n currentCategory.sequence = row.sequence !== undefined ? row.sequence : categorySequence++;\n currentCategory.image_url = row.image_url || '';\n currentCategory.image_thumbnail_url = row.image_thumbnail_url || '';\n currentCategory.visibility = [];\n categories.push(currentCategory);\n currentProduct = null;\n currentModifierCategory = null;\n currentComboGroup = null;\n\n } else if (row.type === 'product' || row.type === 'combo') {\n if (!currentCategory) throw new Error(`${row.type === 'combo' ? 'Combo' : 'Product'} \"${row.name}\" found without a category`);\n\n currentProduct = new Item();\n currentProduct.name = row.name;\n currentProduct.sku = row.sku || '';\n currentProduct.price = row.price || 0;\n currentProduct.stock = row.stock !== undefined ? row.stock : 1000;\n currentProduct.is_internal = row.is_internal !== undefined ? row.is_internal : false;\n currentProduct.sequence = row.sequence || 0;\n currentProduct.image_url = row.image_url || '';\n currentProduct.image_thumbnail_url = row.image_thumbnail_url || '';\n currentProduct.category_uid = currentCategory.uid;\n currentProduct.type = row.type === 'combo' ? ProductType.Combo : ProductType.ByQuantity;\n currentProduct.modifier_categories = [];\n currentProduct.modifiers = [];\n currentProduct.combo_groups = [];\n products.push(currentProduct);\n currentModifierCategory = null;\n currentComboGroup = null;\n\n } else if (row.type === 'combo_group') {\n if (!currentProduct || currentProduct.type !== ProductType.Combo) {\n throw new Error(`Combo group \"${row.name}\" found without a combo product`);\n }\n currentComboGroup = new ComboGroup();\n currentComboGroup.name = row.name;\n currentComboGroup.min_order = row.min_order !== undefined ? row.min_order : 1;\n currentComboGroup.max_order = row.max_order !== undefined ? row.max_order : 1;\n currentComboGroup.sequence = row.sequence !== undefined ? row.sequence : currentProduct.combo_groups!.length;\n currentProduct.combo_groups!.push(currentComboGroup);\n\n } else if (row.type === 'combo_item') {\n if (!currentComboGroup) throw new Error(`Combo item \"${row.name}\" found without a combo group`);\n const comboItem = new ComboGroupItem();\n comboItem.item_uid = row.item_uid || '';\n comboItem.price = row.price || 0;\n comboItem.sequence = row.sequence || 0;\n comboItem.combo_item = new Item();\n comboItem.combo_item.name = row.name;\n currentComboGroup.combo_items.push(comboItem);\n\n } else if (row.type === 'modifier_category') {\n if (!currentProduct) throw new Error(`Modifier category \"${row.name}\" found without a product`);\n currentModifierCategory = new CoreCategory();\n currentModifierCategory.name = row.name;\n currentModifierCategory.min_order = row.min_order !== undefined ? row.min_order : 0;\n currentModifierCategory.max_order = row.max_order !== undefined ? row.max_order : 0;\n currentModifierCategory.sequence = row.sequence !== undefined ? row.sequence : currentProduct.modifier_categories!.length;\n currentModifierCategory.visibility = [];\n currentProduct.modifier_categories!.push(currentModifierCategory);\n\n } else if (row.type === 'modifier') {\n if (!currentProduct) throw new Error(`Modifier \"${row.name}\" found without a product`);\n const modifier = new CoreItem();\n modifier.name = row.name;\n modifier.sku = row.sku || '';\n modifier.price = row.price || 0;\n modifier.stock = row.stock !== undefined ? row.stock : 0;\n modifier.is_internal = row.is_internal !== undefined ? row.is_internal : false;\n modifier.sequence = row.sequence || 0;\n modifier.image_url = row.image_url || '';\n modifier.image_thumbnail_url = row.image_thumbnail_url || '';\n modifier.type = ProductType.Modifier;\n modifier.category_uid = currentModifierCategory ? currentModifierCategory.uid : currentProduct.category_uid;\n currentProduct.modifiers!.push(modifier);\n }\n }\n\n return { categories, products };\n}\n","export enum Condition {\n None = '',\n Always = 'always',\n}","\nexport type IMerchantAsset = {\n guid: string;\n name: string;\n tags: AssetTags[];\n asset_type: AssetType;\n url: string;\n created_at: Date;\n}\n\nexport enum AssetType {\n Image = \"image\",\n Video = \"video\",\n Unsupported = \"unsupported\"\n}\nexport enum AssetTags {\n CdsFullScreenImage = \"cds_full_screen_image\",\n CdsHalfScreenImage = \"cds_half_screen_image\"\n}\n\nexport type IEtc = {\n assets: IMerchantAsset[];\n}\n\nexport class Merchant implements IMerchant {\n name: string;\n address: string;\n postcode: string;\n tel: string;\n tax_number: string;\n user_id: string;\n uid: string;\n api_key: string;\n ip_address: string;\n meta: Record<string, string>;\n}\n\nexport type IMerchant = {\n name: string;\n address: string;\n postcode: string;\n tel: string;\n tax_number: string;\n user_id: string;\n uid: string;\n api_key: string;\n ip_address: string;\n meta: Record<string, string>;\n}","import { nanoid } from 'nanoid';\nimport { ModelPrefix } from './misc.type';\nimport { AppBaseModel, IAppBaseModel } from './abstract.type';\n\nexport interface IStorage<T = Record<string, unknown> | unknown[]> extends IAppBaseModel {\n uid: string;\n model: 'discounts' | string;\n data: T;\n}\n\nexport class Storage<T = Record<string, unknown> | unknown[]> extends AppBaseModel implements IStorage<T> {\n public uid = ModelPrefix.Storage + nanoid();\n public model: 'discounts' | string;\n public data: T;\n}\n","import { nanoid } from \"nanoid\";\nimport { AppBaseModel, IAppBaseModel } from \"./abstract.type\";\nimport { ModelPrefix } from \"./misc.type\";\n\nexport interface IMenu extends IAppBaseModel {\n icon: string;\n meta: Record<string, any>;\n category_uids: string[];\n online_order_expiry_in_minutes: number;\n online_order_session_expiry_in_minutes: number;\n}\n\nexport class Menu extends AppBaseModel implements IMenu {\n public uid = ModelPrefix.Menu + nanoid();\n public icon = '';\n public meta = {};\n public category_uids = [];\n public online_order_expiry_in_minutes = 0;\n public online_order_session_expiry_in_minutes = 0;\n}","import { AppCoreModel, IAppCoreModel } from './abstract.type';\nimport { ModelPrefix } from './misc.type';\nimport { nanoid } from 'nanoid';\n\nexport enum StockLogType {\n In = 'IN',\n Out = 'OUT',\n Adjust = 'ADJUST',\n Production = 'PRODUCTION',\n}\n\nexport enum StockLogRefType {\n Invoice = 'invoice',\n Purchase = 'purchase',\n Production = 'production',\n Stocktake = 'stocktake',\n}\n\nexport enum StockLogEntityType {\n Item = 'item',\n Material = 'material',\n}\n\nexport interface IStockLog extends IAppCoreModel {\n /** entity type: item or material */\n entity_type: StockLogEntityType;\n /** entity uid (item_uid or material_uid) */\n entity_uid: string;\n /** operation type */\n type: StockLogType;\n /** quantity changed */\n qty: number;\n /** quantity before change */\n qty_before: number;\n /** quantity after change */\n qty_after: number;\n /** reference document type */\n ref_type?: StockLogRefType;\n /** reference document uid */\n ref_uid?: string;\n /** reason or note */\n reason?: string;\n /** created by user uid */\n created_by?: string;\n}\n\nexport class StockLog extends AppCoreModel implements IStockLog {\n public entity_type = StockLogEntityType.Item;\n public entity_uid = '';\n public type = StockLogType.Adjust;\n public qty = 0;\n public qty_before = 0;\n public qty_after = 0;\n public ref_type?: StockLogRefType;\n public ref_uid?: string;\n public reason?: string;\n public created_by?: string;\n public uid = ModelPrefix.StockLog + nanoid();\n constructor() {\n super();\n }\n}\n","// ST template validation for SelectTransform syntax\nconst VALID_DIRECTIVES = ['#each', '#if', '#elseif', '#else', '#let', '#merge', '#concat', '#include', '#?', '#flatten']\n\ninterface ValidationError {\n type: 'JSON_PARSE' | 'BRACKET_MISMATCH' | 'UNKNOWN_DIRECTIVE' | 'INVALID_EXPRESSION' | 'INVALID_EACH' | 'INVALID_LET' | 'INVALID_STRUCTURE' | 'INVALID_CONDITIONAL'\n path: string | null\n message: string\n context?: string\n}\n\ninterface ValidationResult {\n valid: boolean\n errors: ValidationError[]\n}\n\nexport function validateSTTemplate(jsonStr: string): ValidationResult {\n const errors: ValidationError[] = []\n const warn = (type: ValidationError['type'], path: string | null, message: string, context?: string) => errors.push({ type, path, message, context })\n\n let template: unknown\n try {\n template = JSON.parse(jsonStr)\n } catch (e) {\n const pos = (e as Error).message.match(/position (\\d+)/)?.[1]\n return { valid: false, errors: [{ type: 'JSON_PARSE', path: null, message: (e as Error).message, context: pos ? jsonStr.slice(Math.max(0, +pos - 20), +pos + 20) : undefined }] }\n }\n\n const str = JSON.stringify(template)\n // Count brackets only within JSON string values to avoid false positives from JSON structure\n const strMatches = str.match(/\"[^\"]*\"/g) || []\n let opens = 0, closes = 0\n strMatches.forEach(s => { opens += (s.match(/\\{\\{/g) || []).length; closes += (s.match(/\\}\\}/g) || []).length })\n if (opens !== closes) warn('BRACKET_MISMATCH', null, `{{ : ${opens}, }} : ${closes}`)\n\n ;(str.match(/\\{\\{([^}]+)\\}\\}/g) || []).forEach(expr => {\n const inner = expr.slice(2, -2).trim()\n if (inner.startsWith('#')) {\n const directive = inner.split(/\\s/)[0]\n if (!VALID_DIRECTIVES.includes(directive)) warn('UNKNOWN_DIRECTIVE', null, directive, expr)\n return\n }\n try { new Function(`with(this){return(${inner})}`) }\n catch (e) { warn('INVALID_EXPRESSION', null, (e as Error).message, expr) }\n })\n\n ;(function check(node: unknown, path: string) {\n if (!node || typeof node !== 'object') return\n if (Array.isArray(node)) {\n const firstKey = node[0] && Object.keys(node[0])[0]\n if (firstKey?.includes('#if') && !firstKey.includes('#elseif')) validateConditional(node, path, warn)\n node.forEach((v, i) => check(v, `${path}[${i}]`))\n return\n }\n for (const key in node) {\n const val = (node as Record<string, unknown>)[key]\n if (key.includes('#each') && typeof val !== 'object') warn('INVALID_EACH', path, 'value must be object', key)\n if (key.includes('#let') && (!Array.isArray(val) || val.length !== 2)) warn('INVALID_LET', path, 'must be [definitions, template]', key)\n if ((key.includes('#merge') || key.includes('#concat')) && !Array.isArray(val)) warn('INVALID_STRUCTURE', path, 'value must be array', key)\n check(val, path ? `${path}.${key}` : key)\n }\n })(template, '')\n\n return { valid: !errors.length, errors }\n}\n\nfunction validateConditional(arr: Record<string, unknown>[], path: string, warn: (type: ValidationError['type'], path: string | null, message: string, context?: string) => void) {\n const key = (o: Record<string, unknown>) => Object.keys(o)[0] || ''\n if (!key(arr[0]).match(/#if\\s/)) warn('INVALID_CONDITIONAL', path, 'must start with #if', key(arr[0]))\n for (let i = 1; i < arr.length - 1; i++) {\n if (!key(arr[i]).includes('#elseif')) warn('INVALID_CONDITIONAL', `${path}[${i}]`, 'middle must be #elseif', key(arr[i]))\n }\n if (arr.length > 1 && !key(arr.at(-1)!).includes('#else')) warn('INVALID_CONDITIONAL', `${path}[${arr.length - 1}]`, 'last must be #else/#elseif', key(arr.at(-1)!))\n}\n\nexport type { ValidationError, ValidationResult }\n"],"mappings":"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"}