    //lastSection = document.querySelector(".selected-cart");
    //ambilakhir('register','user',vm.register.kuser,vm.register.kuser);

    aaa = 1;
    // xbrand = 'xxx';
    // xcab = 'yyy';
    online = false;
    umeja = false;


    const app = Vue.createApp({
    	data() {
    		return {
        isAdjustMode: false, // Flag untuk menandakan kita sedang dalam mode edit/adjust
        originalTransactionNumber: null, // Untuk menyimpan nomor transaksi yg sedang di-edit
        showAdjustModal: false, // Untuk menampilkan/menyembunyikan modal pilihan transaksi
        adjustTransactions: [], // Untuk menampung daftar transaksi dari tabel 'jual'
        adjustIsLoading: false, // Status loading saat mengambil data 'jual'
updateTimeout: null ,				
	bacatulis:false,			
    showKioskModal: false,
    kioskTransactions: [],
    kioskSearchTerm: '',
    kioskIsLoading: false,
				jenisdelete:'',
        showReportIframe: false,
        reportIframeUrl: '',
				currentTransactionType: null, // Tambahkan ini        
    			// ... data lainnya
    			currentCartItemId: null, // ID item yang dipilih
    			selectedItemName: '', // Nama item yang dipilih untuk konfirmasi
    			selectedCartItemObject: null, // <-- TAMBAHKAN BARIS INI
    			xsplit: '',
    			activeSplitFilter: '',
    			imagePreviewUrl: null, // <-- TAMBAHKAN BARIS INI      
    			tipeTransaksi: [], // <-- TAMBAHKAN BARIS INI
    			isMasterPaymentDisabled: false, // <-- TAMBAHKAN BARIS INI
    			shoconfbayar: false,
    			ncab: '',
    			paketData: new Map(),
    			outlet: '',
    			xcab: xcab,
    			xbrand: xbrand,
    			closePreviewModal: false,
    			group_harga: '1', // Sesuai permintaan Anda
    			harga: [], // Untuk menampung data dari tabel harga
				users:[],
				botor:[],
    			qty_mode: '',
    			overadmin: false,
    			p_tampilkan_modal: false,
    			p_pesan_modal: '',
    			p_tipe_modal: 'info',
    			p_confirmCallback: null,
    			selectedShift: 0,
    			register: {},
    			no_jual: '',
    			sbill: '',
    			masterd: [],
    			masterdb: [],
    			masterds: [],
    			cabang: [],
    			mdisc: [],
    			result: {},
    			gdisc: {},
    			gd: [],
    			md: [],
    			bhs: 'ind', // Bahasa default
    			bh: {
    				"login": {
    					"ind": "Masuk",
    					"jpn": "ログイン",
    					"chn": "登录",
    					"arb": "تسجيل الدخول",
    					"eng": "Login"
    				},
    				"pos_kasir_restoran": {
    					"ind": "POS Kasir Restoran",
    					"jpn": "レストランPOSレジ",
    					"chn": "餐厅收银系统",
    					"arb": "نظام نقاط البيع للمطعم",
    					"eng": "Restaurant POS System"
    				},
    				"restaurant_bill": {
    					"ind": "Tagihan Restoran",
    					"jpn": "レストラン伝票",
    					"chn": "餐厅账单",
    					"arb": "فاتورة المطعم",
    					"eng": "Restaurant Bill"
    				},
    				"struk_belanja": {
    					"ind": "Struk Belanja",
    					"jpn": "お買い物レシート",
    					"chn": "购物收据",
    					"arb": "إيصال التسوق",
    					"eng": "Shopping Receipt"
    				},
    				"split_bills": {
    					"ind": "Pisah Tagihan",
    					"jpn": "分割会計",
    					"chn": "分单",
    					"arb": "تقسيم الفواتير",
    					"eng": "Split Bills"
    				},
    				"menu_item": {
    					"ind": "Item Menu",
    					"jpn": "メニュー項目",
    					"chn": "菜单项目",
    					"arb": "عنصر القائمة",
    					"eng": "Menu Item"
    				},
    				"category": {
    					"ind": "Kategori",
    					"jpn": "カテゴリー",
    					"chn": "类别",
    					"arb": "الفئة",
    					"eng": "Category"
    				},
    				"top": {
    					"ind": "Atas",
    					"jpn": "トップ",
    					"chn": "顶部",
    					"arb": "أعلى",
    					"eng": "Top"
    				},
    				"lantai": {
    					"ind": "Lantai",
    					"jpn": "フロア",
    					"chn": "楼层",
    					"arb": "طابق",
    					"eng": "Floor"
    				},
    				"table": {
    					"ind": "Meja",
    					"jpn": "テーブル",
    					"chn": "桌子",
    					"arb": "طاولة",
    					"eng": "Table"
    				},
    				"discount": {
    					"ind": "Diskon",
    					"jpn": "割引",
    					"chn": "折扣",
    					"arb": "خصم",
    					"eng": "Discount"
    				},
    				"setup": {
    					"ind": "Pengaturan",
    					"jpn": "設定",
    					"chn": "设置",
    					"arb": "إعداد",
    					"eng": "Setup"
    				},
    				"cancel": {
    					"ind": "Batal",
    					"jpn": "キャンセル",
    					"chn": "取消",
    					"arb": "إلغاء",
    					"eng": "Cancel"
    				},
    				"total": {
    					"ind": "Total",
    					"jpn": "合計",
    					"chn": "总计",
    					"arb": "المجموع",
    					"eng": "Total"
    				},
    				"pembayaran": {
    					"ind": "Pembayaran",
    					"jpn": "支払い",
    					"chn": "支付",
    					"arb": "دفع",
    					"eng": "Payment"
    				},
    				"kembali": {
    					"ind": "Kembali",
    					"jpn": "お釣り",
    					"chn": "找零",
    					"arb": "الباقي",
    					"eng": "Change"
    				},
    				"kurang_bayar": {
    					"ind": "Kurang Bayar",
    					"jpn": "不足額",
    					"chn": "欠款",
    					"arb": "نقص الدفع",
    					"eng": "Underpayment"
    				},
    				"cover": {
    					"ind": "Cover",
    					"jpn": "カバー",
    					"chn": "餐位费",
    					"arb": "تغطية",
    					"eng": "Cover"
    				},
    				"guest": {
    					"ind": "Tamu",
    					"jpn": "ゲスト",
    					"chn": "顾客",
    					"arb": "ضيف",
    					"eng": "Guest"
    				},
    				"subtotal": {
    					"ind": "Subtotal",
    					"jpn": "小計",
    					"chn": "小计",
    					"arb": "المجموع الفرعي",
    					"eng": "Subtotal"
    				},
    				"total_discount": {
    					"ind": "Total Diskon",
    					"jpn": "割引合計",
    					"chn": "总折扣",
    					"arb": "إجمالي الخصم",
    					"eng": "Total Discount"
    				},
    				"service": {
    					"ind": "Layanan",
    					"jpn": "サービス料",
    					"chn": "服务费",
    					"arb": "خدمة",
    					"eng": "Service"
    				},
    				"pajak": {
    					"ind": "Pajak",
    					"jpn": "税金",
    					"chn": "税",
    					"arb": "ضريبة",
    					"eng": "Tax"
    				},
    				"item_count": {
    					"ind": "Jumlah Item",
    					"jpn": "商品数",
    					"chn": "商品数量",
    					"arb": "عدد العناصر",
    					"eng": "Item Count"
    				},
    				"qty": {
    					"ind": "Jumlah",
    					"jpn": "数量",
    					"chn": "数量",
    					"arb": "الكمية",
    					"eng": "Qty"
    				},
    				"nama": {
    					"ind": "Nama",
    					"jpn": "名前",
    					"chn": "名称",
    					"arb": "اسم",
    					"eng": "Name"
    				},
    				"disc": {
    					"ind": "Diskon",
    					"jpn": "割引",
    					"chn": "折扣",
    					"arb": "خصم",
    					"eng": "Disc"
    				},
    				"jumlah": {
    					"ind": "Jumlah",
    					"jpn": "合計",
    					"chn": "总额",
    					"arb": "المبلغ",
    					"eng": "Amount"
    				},
    				"user": {
    					"ind": "Pengguna",
    					"jpn": "ユーザー",
    					"chn": "用户",
    					"arb": "مستخدم",
    					"eng": "User"
    				},
    				"kontan": {
    					"ind": "Tunai",
    					"jpn": "現金",
    					"chn": "现金",
    					"arb": "نقداً",
    					"eng": "Cash"
    				},
    				"kartu_kredit_bca": {
    					"ind": "Kartu Kredit BCA",
    					"jpn": "BCAクレジットカード",
    					"chn": "BCA信用卡",
    					"arb": "بطاقة BCA الائتمانية",
    					"eng": "BCA Credit Card"
    				},
    				"kartu_debet": {
    					"ind": "Kartu Debet",
    					"jpn": "デビットカード",
    					"chn": "借记卡",
    					"arb": "بطاقة الخصم",
    					"eng": "Debit Card"
    				},
    				"gopay": {
    					"ind": "GoPay",
    					"jpn": "GoPay",
    					"chn": "GoPay",
    					"arb": "GoPay",
    					"eng": "GoPay"
    				},
    				"voucher": {
    					"ind": "Voucher",
    					"jpn": "バウチャー",
    					"chn": "代金券",
    					"arb": "قسيمة",
    					"eng": "Voucher"
    				},
    				"userid": {
    					"ind": "ID Pengguna",
    					"jpn": "ユーザーID",
    					"chn": "用户ID",
    					"arb": "معرف المستخدم",
    					"eng": "User ID"
    				},
    				"password": {
    					"ind": "Kata Sandi",
    					"jpn": "パスワード",
    					"chn": "密码",
    					"arb": "كلمة المرور",
    					"eng": "Password"
    				},
    				"pesan_penting": {
    					"ind": "Pesan Penting",
    					"jpn": "重要なメッセージ",
    					"chn": "重要消息",
    					"arb": "رسالة مهمة",
    					"eng": "Important Message"
    				},
    				"mengerti": {
    					"ind": "Mengerti",
    					"jpn": "了解",
    					"chn": "明白",
    					"arb": "مفهوم",
    					"eng": "Understood"
    				},
    				"yes": {
    					"ind": "Ya",
    					"jpn": "はい",
    					"chn": "是",
    					"arb": "نعم",
    					"eng": "Yes"
    				},
    				"no": {
    					"ind": "Tidak",
    					"jpn": "いいえ",
    					"chn": "否",
    					"arb": "لا",
    					"eng": "No"
    				},
    				"ok": {
    					"ind": "OK",
    					"jpn": "OK",
    					"chn": "确定",
    					"arb": "موافق",
    					"eng": "OK"
    				},
    				"move_item": {
    					"ind": "Pindah Item",
    					"jpn": "商品移動",
    					"chn": "移动项目",
    					"arb": "نقل العنصر",
    					"eng": "Move Item"
    				},
    				"move_1pc": {
    					"ind": "Pindah 1 Buah",
    					"jpn": "1個移動",
    					"chn": "移动1个",
    					"arb": "نقل قطعة واحدة",
    					"eng": "Move 1pc"
    				},
    				"move_menu": {
    					"ind": "Pindah Menu",
    					"jpn": "メニュー移動",
    					"chn": "移动菜单",
    					"arb": "نقل القائمة",
    					"eng": "Move Menu"
    				},
    				"move_all": {
    					"ind": "Pindah Semua",
    					"jpn": "全て移動",
    					"chn": "全部移动",
    					"arb": "نقل الكل",
    					"eng": "Move All"
    				},
    				"return_1pc": {
    					"ind": "Retur 1 Buah",
    					"jpn": "1個返品",
    					"chn": "退回1个",
    					"arb": "إرجاع قطعة واحدة",
    					"eng": "Return 1pc"
    				},
    				"return_menu": {
    					"ind": "Retur Menu",
    					"jpn": "メニュー返品",
    					"chn": "退回菜单",
    					"arb": "إرجاع القائمة",
    					"eng": "Return Menu"
    				},
    				"return_all": {
    					"ind": "Retur Semua",
    					"jpn": "全て返品",
    					"chn": "全部退回",
    					"arb": "إرجاع الكل",
    					"eng": "Return All"
    				},
    				"save": {
    					"ind": "Simpan",
    					"jpn": "保存",
    					"chn": "保存",
    					"arb": "حفظ",
    					"eng": "Save"
    				},
    				"master_bill": {
    					"ind": "Tagihan Utama",
    					"jpn": "親伝票",
    					"chn": "主账单",
    					"arb": "الفاتورة الرئيسية",
    					"eng": "Master Bill"
    				},
    				"name": {
    					"ind": "Nama",
    					"jpn": "名前",
    					"chn": "名称",
    					"arb": "اسم",
    					"eng": "Name"
    				},
    				"background_color": {
    					"ind": "Warna Latar",
    					"jpn": "背景色",
    					"chn": "背景颜色",
    					"arb": "لون الخلفية",
    					"eng": "Background Color"
    				},
    				"text_color": {
    					"ind": "Warna Teks",
    					"jpn": "テキスト色",
    					"chn": "文字颜色",
    					"arb": "لون النص",
    					"eng": "Text Color"
    				},
    				"label": {
    					"ind": "Label",
    					"jpn": "ラベル",
    					"chn": "标签",
    					"arb": "تسمية",
    					"eng": "Label"
    				},
    				"image": {
    					"ind": "Gambar",
    					"jpn": "画像",
    					"chn": "图片",
    					"arb": "صورة",
    					"eng": "Image"
    				},
    				"copy_to_new_table": {
    					"ind": "Salin ke Meja Baru",
    					"jpn": "新しいテーブルにコピー",
    					"chn": "复制到新桌子",
    					"arb": "نسخ إلى طاولة جديدة",
    					"eng": "Copy to New Table"
    				},
    				"update_table": {
    					"ind": "Perbarui Meja",
    					"jpn": "テーブル更新",
    					"chn": "更新桌子",
    					"arb": "تحديث الطاولة",
    					"eng": "Update Table"
    				},
    				"hapus_meja": {
    					"ind": "Hapus Meja",
    					"jpn": "テーブル削除",
    					"chn": "删除桌子",
    					"arb": "حذف الطاولة",
    					"eng": "Delete Table"
    				},
    				"copy_atribut": {
    					"ind": "Salin Atribut",
    					"jpn": "属性をコピー",
    					"chn": "复制属性",
    					"arb": "نسخ السمات",
    					"eng": "Copy Attributes"
    				},
    				"paste_atribut": {
    					"ind": "Tempel Atribut",
    					"jpn": "属性を貼り付け",
    					"chn": "粘贴属性",
    					"arb": "لصق السمات",
    					"eng": "Paste Attributes"
    				},
    				"paket": {
    					"ind": "Paket",
    					"jpn": "セット",
    					"chn": "套餐",
    					"arb": "حزمة",
    					"eng": "Package"
    				},
    				"condiment": {
    					"ind": "Bumbu",
    					"jpn": "調味料",
    					"chn": "调味品",
    					"arb": "توابل",
    					"eng": "Condiment"
    				},
    				"optional": {
    					"ind": "Opsional",
    					"jpn": "オプション",
    					"chn": "可选",
    					"arb": "اختياري",
    					"eng": "Optional"
    				},
    				"wajib": {
    					"ind": "(Wajib)",
    					"jpn": "(必須)",
    					"chn": "(必需)",
    					"arb": "(إلزامي)",
    					"eng": "(Required)"
    				},
    				"opsional": {
    					"ind": "(Opsional)",
    					"jpn": "(オプション)",
    					"chn": "(可选)",
    					"arb": "(اختياري)",
    					"eng": "(Optional)"
    				},
    				"masukan_jumlah": {
    					"ind": "Masukan Jumlah",
    					"jpn": "数量を入力",
    					"chn": "输入数量",
    					"arb": "أدخل الكمية",
    					"eng": "Enter Amount"
    				},
    				"masukan_jumlah_tamu": {
    					"ind": "Masukan Jumlah Tamu",
    					"jpn": "ゲスト数を入力",
    					"chn": "输入客人数量",
    					"arb": "أدخل عدد الضيوف",
    					"eng": "Enter Guest Count"
    				},
    				"masukan_jumlah_pembayaran": {
    					"ind": "Masukan Jumlah Pembayaran",
    					"jpn": "支払額を入力",
    					"chn": "输入支付金额",
    					"arb": "أدخل مبلغ الدفع",
    					"eng": "Enter Payment Amount"
    				},
    				"catatan_untuk": {
    					"ind": "Catatan untuk",
    					"jpn": "メモ:",
    					"chn": "备注",
    					"arb": "ملاحظة لـ",
    					"eng": "Note for"
    				}
    			},
    			bqty: 1,
    			pos: {},
    			items: [    			],
    			showyesnobayar: false,
    			showSplit: false,
    			gridCodes: [],
    			selectedGridCode: '',
    			selectedMasterItem: '',
    			selectedSplitItem: '',
    			GRID_CODES: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',


    			showPopup: false,
    			showPopupm: false,
    			fungsi3: [],
    			fungsim: [],

    			mejakiri: '',
    			mejakanan: '',
    			isVisible: false,
    			// pesanp: [],
    			pesanp: [],
    			selectedLeft: [],
    			selectedRight: [],
    			backkiri: [],
    			backkanan: [],
    			tempmeja: '',
    			inputField: '',
    			lastmeja: '',
    			move: '',
    			cart2: [],
    			jam: '',
    			itemx: {},
    			kba: false,
    			edc: '',
    			tipe_bayar: 'xx',
    			kbn: '',
    			kb_for: 3,
    			mejao: [],
    			loop: 0,
    			newItem: {},
    			paymentdinamis: true,
    			item_bayar: 0,
    			layer: '',
    			xitem: 0,
    			xsubtotal: 0,
    			xtdiscf: 0,
    			xtdisc: 0,
    			xtservice: 0,
    			xtpajak: 0,
    			xgrandtotal: 0,
    			xpayment: 0,
    			xkembali: 0,
    			xcard: 0,
    			xcash: 0,
    			nuser: '',
    			kuser: '',
    			posisi: '',
    			xmeja: '',
    			lebarl: window.screen.availWidth / 100,
    			tinggil: window.screen.availHeight / 100,
    			inputValue: '',
    			inputValue1: '',
    			ipilih: 1,
    			inputValue2: '',
    			currmeja: 0,
    			currmejac: 0,
    			currpayment: 0,
    			lantai: [    			],
    			meja: [],
    			meja: [    			],

    			payment: [    			],


    			fungsi: [    			],

    			zz: [],
    			oo: [],
    			digits: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.', '@'],
    			digitsd: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.', 'Cancel'],
    			digitskb1: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"],
    			digitskb2: ["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"],
    			digitskb3: ["A", "S", "D", "F", "G", "H", "J", "K", "L", "."],
    			digitskb4: ["Z", "X", "C", "V", "B", "N", "M", ".", ""],
    			showModalkb: false,
    			showModalAngkakb: false,
    			showModalLogin: true,
    			showModal: false,
    			showModalAngka: false,
    			inputV: {
    				1: '',
    				2: ''
    			},
    			activeInput: 1,
    			showToppings: false,
    			selectedMenuItem: null,
    			message: "Halo dari Vue!",
    			satu: "satu",
    			qty: ['1', '2', '3', '4', '5', '6', '7', '8', '9'],
    			condiment: [    			],
    			menuTops: [    			],
    			menuGroups: [  			],
    			menus: [    			],


    			toppings: [  			],
    			ya: 0,
    			currentMenuGroup: '01',
    			currentMenuTop: 'Makanan',
    			currentLantai: '1',
    			currentMeja: '',
    			currentLayer: '1',
    			currentNamaMeja: '',
    			currentKodeMeja: '',
    			currentItem: '',
    			currentcart: null,
    			pesant: [],
    			copymeja: [],
    			selectedPayment: null,
    			isTransactionComplete: false,
    			discount: 0,
    			nomor: "",
    			edit: false,

    			isedit: false,
    			isDragging: false,
    			isResizing: false,
    			isChangingBorderRadius: false,
    			activeKotakIndex: null,
    			activeContextMenuIndex: null,
    			showContextMenu: false,
    			pshowContextMenu: false,
    			contextMenuX: 0,
    			contextMenuY: 0,
    			contenMeja: '',
    			initialMouseX: 0,
    			initialMouseY: 0,
    			initialLeft: 0,
    			initialTop: 0,
    			initialWidth: 0,
    			initialHeight: 0,
    			initialBorderRadius: 0,
    			bselectedColor: "#3498db", // Warna awal
    			fselectedColor: "#3498db",

    		};
    	},

    	computed: {

// Ganti seluruh paymentBreakdown computed property di pos.js
paymentBreakdown() {
    // 1. Filter semua item yang merupakan pembayaran (bukan item menu/diskon faktur)
    const allPayments = this.cart.filter(item => 
        item.payment && String(item.payment).trim() !== '' && String(item.payment).trim() !== '06'
    );

    // 2. Kelompokkan berdasarkan metode pembayaran dan jumlahkan nilainya
    const summary = allPayments.reduce((acc, payment) => {
        let name;
        if (payment.payment === '10') {
            name = 'Tunai (Cash)';
        } else if (payment.edc && payment.edc.trim() !== '') {
            name = payment.edc; // Gunakan nama EDC jika ada
        } else if (payment.name && payment.name.trim() !== '') {
            name = payment.name; // Fallback ke nama item (e.g., GoPay, Voucher)
        } else {
            name = 'Non-Tunai Lain';
        }
        
        if (!acc[name]) {
            acc[name] = 0;
        }
        
        // Tambahkan harga item pembayaran
        acc[name] += payment.harga; 
        
        return acc;
    }, {});

    // 3. Ubah hasil menjadi format array untuk ditampilkan di modal
    return Object.keys(summary).map(name => {
        return {
            name: name,
            amount: summary[name]
        };
    });
},
    filteredKioskTransactions() {
        if (!this.kioskSearchTerm) {
            return this.kioskTransactions;
        }
        return this.kioskTransactions.filter(trx =>
            trx.transaction_code.toLowerCase().includes(this.kioskSearchTerm.toLowerCase())
        );
    },			

    		mejaDisplayName() {
    			if (this.activeSplitFilter && this.activeSplitFilter.trim() !== '') {
    				return `${this.mejao.nama} (${this.activeSplitFilter})`;
    			}
    			return this.mejao.nama;
    		},

    		masterTitle() {
    			const tableNumber = new URLSearchParams(window.location.search).get('meja') || ''
    			return tableNumber ? `Master Bill ${tableNumber}` : 'Master Grid'
    		},
    		unsplitItems() {
    			return this.items.filter(item => item.split === '')
    		},



    		filtertoping() {



    			if (!this.selectedMenuItem || !this.selectedMenuItem.toppings) {

    				return []; // Kembalikan array kosong jika data belum siap
    			};
    			return this.selectedMenuItem.toppings.filter(topping => topping.items.length > 1);
    		},


    		filteredCondiment() {
    			if (!this.cart || !this.cart[this.currentcart]) {
    				return []; // Kembalikan array kosong jika data belum siap
    			}
    			return this.condiment.filter(item => item.kode === this.cart[this.currentcart].condiment);
    		},



    		selected(a) {
    			if (!Array.isArray(a)) {
    				return []; // Pastikan `a` adalah array
    			}
    			return a
    				.filter(topping => topping.checked)
    				.map(topping => topping.nama_toping);
    		},

    		gabung() {
    			const mergedData = this.menus.map(menuItem => {
    				// Periksa apakah menuItem.toping tidak null atau undefined sebelum di-split
    				const topingIds = menuItem.toping ? menuItem.toping.split('-') : [];
    				const mergedToppings = [];

    				topingIds.forEach(topingId => {
    					const toping = this.toppings.find(topping => topping.toping === topingId);
    					if (toping) {
    						mergedToppings.push(toping);
    					}
    				});

    				return {
    					...menuItem,
    					toppings: mergedToppings
    				};
    			});
    			return mergedData;
    		},

    		cart() {
    			return this.pesant.filter(carts => carts.meja === this.currentMeja);
    		},

    		currentMejas() {
    			return this.meja.filter(mejas => mejas.lantai === this.currentLantai);
    		},

    		currentPayment() {
    			return this.payment.filter(mejas => mejas.lantai === this.currentLayer);
    		},

    		currentGroup() {
    			return this.menuGroups.filter(menuGroups => menuGroups.top === this.currentMenuTop);
    		},

    		currentMenu() {
    			b = this.menus.filter(menu => menu.kgroup === this.currentMenuGroup);
    			return this.menus.filter(menu => menu.kgroup === this.currentMenuGroup);
    		},

    		// cartSubtotal() {
    		//   return this.cart.reduce((total, item) => total + item.harga * item.quantity, 0);
    		// },


    		// Ganti seluruh computed property cartSubtotal di pos.js dengan ini:
    		cartSubtotal() {
    			let itemb = 0,
    				zitem = 0,
    				total = 0,
    				disc = 0,
    				service = 0,
    				pajak = 0;
    			let xpayment = 0,
    				xcash = 0,
    				xcard = 0;

    			// DEBUG: Tampilkan currentTransactionType


    			// Ambil setting service dan pajak dari tipe transaksi aktif
    			let applyService = false;
    			let applyPajak = false;
    			let serviceChargeRate = 0;
    			let pajakChargeRate = 0;

    			if (this.currentTransactionType) {
    				applyService = this.currentTransactionType.service === '1';
    				applyPajak = this.currentTransactionType.pajak === '1';
    				serviceChargeRate = parseFloat(this.currentTransactionType.service_charge) || 0;
    				pajakChargeRate = parseFloat(this.currentTransactionType.pajak_charge) || 0;
    			}

    			// DEBUG: Tampilkan nilai yang diambil


    			// Proses diskon item
    			this.findAndApplyDiscount();

    			// Iterasi semua item di cart
    			this.cart.forEach((item, index) => {
    				if (item.split == this.activeSplitFilter) {
    					if (!item.payment) {
    						// Hitung harga dasar item + topping
    						let xx = Number(item.price);
    						if (item.toppings) {
    							for (const toppingGroupx of item.toppings) {
    								for (const itemx of toppingGroupx.items) {
    									if (itemx.harga > 0) {
    										xx += itemx.harga;
    									}
    								}
    							}
    						}

    						// Update harga item
    						item.harga = xx;
    						const xtotal = Math.round(xx * item.quantity);
    						const discp = parseFloat(item.discp) || 0;
    						const discr = parseFloat(item.discr) || 0;

    						// Set service dan pajak berdasarkan tipe transaksi
    						item.serv = applyService ? serviceChargeRate : 0;
    						item.ppn = applyPajak ? pajakChargeRate : 0;

    						// DEBUG: Tampilkan nilai service dan pajak untuk item


    						// Hitung jumlah item
    						item.jumlah = item.harga * item.quantity;

    						// Hitung diskon item
    						item.disc = Math.round(xtotal * (discp / 100) + discr);

    						// Hitung service charge (jika aktif)
    						item.service = Math.round((xtotal - item.disc) * (item.serv / 100));

    						// Hitung pajak (jika aktif)
    						item.pajak = Math.round((xtotal - item.disc + item.service) * (item.ppn / 100));

    						// DEBUG: Tampilkan perhitungan service dan pajak


    						// Hitung netto
    						item.netto = Math.round(xtotal - item.disc + item.service + item.pajak);

    						// Akumulasi untuk total
    						zitem += 1;
    						total += item.jumlah;
    						disc += item.disc;
    						service += item.service;
    						pajak += item.pajak;

    					} else {
    						// Proses item pembayaran
    						if (item.payment && String(item.payment).trim() !== '06') {
    							xcash += (item.payment === '10') ? item.harga : 0;
    							xcard += (item.payment === '12') ? item.harga : 0;
    							xpayment += item.harga;
    						}
    						itemb += 1;
    					}
    				}
    			});

    			// DEBUG: Tampilkan total service dan pajak


    			// Hitung diskon faktur
    			this.xtdiscf = 0;
    			const discountFlag = this.cart.find(item => String(item.payment).trim() == '06');
    			if (discountFlag) {
    				const discountRule = this.masterd.find(d => d.kode === discountFlag.kode);
    				if (discountRule) {
    					const minPurchase = parseFloat(discountRule.min) || 0;
    					if (minPurchase > 0 && total >= minPurchase) {
    						const maxDiscount = parseFloat(discountRule.max) || 0;
    						const discp = parseFloat(discountRule.discp) || 0;
    						const potentialDiscount = total * (discp / 100);
    						this.xtdiscf = (maxDiscount > 0) ? Math.min(potentialDiscount, maxDiscount) : potentialDiscount;
    					}
    				}
    			}

    			// Update item diskon faktur jika ada
    			const discountLineItem = this.cart.find(item => item.payment === '06' && item.harga < 0);
    			if (discountLineItem) {
    				const correctDiscountValue = -this.xtdiscf;
    				discountLineItem.harga = correctDiscountValue;
    				discountLineItem.jumlah = correctDiscountValue;
    				discountLineItem.netto = correctDiscountValue;
    			}

    			// Hitung grand total
    			const grandTotal = total - disc - this.xtdiscf + service + pajak;

    			// DEBUG: Tampilkan grand total


    			// Update semua properti untuk ditampilkan
    			this.cart2 = this.cart;
    			this.xsubtotal = total;
    			this.xtdisc = disc;
    			this.xtservice = service;
    			this.xtpajak = pajak;
    			this.xgrandtotal = grandTotal;
    			this.xitem = zitem;
    			this.xpayment = xpayment;
    			this.xkembali = xpayment - grandTotal;
    			this.item_bayar = itemb;
    			this.xcash = xcash;
    			this.xcard = xcard;

    			// Update total di meja
    			if (grandTotal !== 0) {
    				if (this.mejao) this.mejao.jumlah = grandTotal;
    				if (this.meja[this.currmeja]) this.meja[this.currmeja].jumlah = grandTotal;
    			}

    			return grandTotal;
    		},
    	},

    	// Fungsi untuk membulatkan ke 2 digit di belakang koma
		async mounted() {
			await PrintManager.init(); // Inisialisasi Print Manager
			window.showConfirmationDialog = this.showConfirmationDialog;
			this.xcab = xcab;
			this.xbrand = xbrand;
			this.baca_set();
			this.baca_bhs();
			this.loadSettings();
			this.generateObject();
            this.loadOpenRegisterSession();
			bacamaster();
			
		},

    	methods: {

// Di dalam file pos.js -> methods: { ... }

			async saveAdjustedTransaction() {
				this.pesan('Menyimpan perubahan transaksi...', 'info');

				// 1. Konfirmasi akhir
				const confirmed = await this.showConfirmationDialog(
					`Anda akan MENIMPA data transaksi No. ${this.originalTransactionNumber}. Proses ini tidak bisa dibatalkan. Yakin?`
				);
				if (!confirmed) {
					this.pesan('Penyimpanan dibatalkan.', 'info');
					return;
				}

				try {
					// --- PROSES DATABASE KRUSIAL ---

					// 2. Hapus semua record LAMA di 'pesani' yang terkait dengan nomor ini
					await hapus('pesani', 'nomor', this.originalTransactionNumber);

					// 3. Siapkan data 'jual' yang baru (kalkulasi ulang total, pembayaran, dll)
					// Kita bisa meminjam logika dari _generateTransactionHeader tapi tanpa membuat nomor baru
					const finalGrandTotal = this.xgrandtotal;
					const updatedJualData = {
						jumlah: finalGrandTotal,
						bayar: this.xpayment,
						kembali: this.xkembali,
						ttot: this.xsubtotal,
						tserv: this.xtservice,
						ttax: this.xtpajak,
						cash: this.xcash,
						card: this.xcard,
						jams: getWaktu(), // Update jam selesai transaksi
						user: this.nuser, // Update user yg melakukan perubahan terakhir
					};

					// 4. Update record di tabel 'jual'
					await rubahjson('jual', updatedJualData, this.originalTransactionNumber, 'nomor');

					// 5. Siapkan data 'pesani' yang baru
					const newPesaniItems = this._preparePesaniData(this.cart, this.originalTransactionNumber);

					// 6. Insert semua record BARU ke 'pesani'
					await insertData('pesani', newPesaniItems);

					// --- SELESAI PROSES DATABASE ---

					this.pesan(`Transaksi No. ${this.originalTransactionNumber} berhasil diperbarui.`, 'success');

					// Cetak bill baru
					const billText = generateBill(newPesaniItems);
					this.print_receipt(billText);

					try {
						const adjustTableObject = this.meja.find(m => m.kode === 'ADJUST');
						if (adjustTableObject) {
							// Kosongkan cart di database
							await rubahjson('cart', { cart: '[]' }, 'ADJUST', 'meja');
							// Lepaskan user dari meja
							await rubahjson('meja', { user: '', jumlah: 0, cover: 0, guest: '' }, adjustTableObject.id);
						}
					} catch (cleanupError) {
						console.error("Gagal membersihkan meja ADJUST:", cleanupError);
						// Tidak perlu menghentikan proses, hanya catat errornya
					}
					// --- Akhir Blok Pembersihan ---

					// Reset state aplikasi
					this.isAdjustMode = false;
					this.originalTransactionNumber = null;
					this.pesant = []; // Kosongkan keranjang
					this.shoconfbayar = false;

					// Kembali ke tampilan awal
					this.Map_table();



				} catch (error) {
					console.error("Gagal menyimpan transaksi yang disesuaikan:", error);
					this.pesan(`ERROR: Gagal menyimpan perubahan. ${error.message}`, 'error');
				}
			},			

			async fetchAdjustableTransactions() {
				this.showAdjustModal = true;
				this.adjustIsLoading = true;
				try {
					// Mengambil 50 transaksi terakhir sebagai contoh
					const query = "SELECT id, tanggal, nomor, jumlah, user FROM jual WHERE batal != '1' ORDER BY id DESC LIMIT 50";
					const resultJson = await ambil_select('jual', query);
					this.adjustTransactions = JSON.parse(resultJson);
				} catch (error) {
					console.error("Gagal mengambil daftar transaksi:", error);
					this.pesan('Gagal mengambil data transaksi dari server.', 'error');
				} finally {
					this.adjustIsLoading = false;
				}
			},

			// 2. Memilih transaksi dan memuat datanya
			// Di dalam file pos.js -> methods: { ... }

			// Di dalam file pos.js -> methods: { ... }

			// Di dalam file pos.js -> methods: { ... }

async selectTransactionForAdjust(transaction) {
    const confirmed = await this.showConfirmationDialog(
        `Anda akan membuka kembali transaksi No. ${transaction.nomor}. Lanjutkan?`
    );
    if (!confirmed) return;

    this.pesan(`Mempersiapkan sesi penyesuaian untuk ${transaction.nomor}...`, 'info');

    try {
        // --- Langkah 1: Temukan dan validasi Meja Khusus 'ADJUST' ---
        const adjustTableObject = this.meja.find(m => m.kode === 'ADJUST');
        if (!adjustTableObject) {
            this.pesan("Kesalahan Kritis: Meja dengan kode 'ADJUST' tidak ditemukan. Mohon buat terlebih dahulu di database.", 'error');
            return;
        }

        if (adjustTableObject.user && adjustTableObject.user.trim() !== '' && adjustTableObject.user !== this.nuser) {
            this.pesan(`Meja 'ADJUST' sedang digunakan oleh kasir lain (${adjustTableObject.user}). Coba beberapa saat lagi.`, 'error');
            return;
        }

        // --- Langkah 2: Ambil data flat dan lakukan Rekonstruksi Cart ---
        const query = `SELECT * FROM pesani WHERE nomor = '${transaction.nomor}' ORDER BY noit ASC`;
        const itemsJson = await ambil_select('pesani', query);
        const flatItemsFromDb = JSON.parse(itemsJson);
        
        const reconstructedCart = [];
        const mainItemsMap = new Map();

        for (const item of flatItemsFromDb) {
            item.quantity = parseFloat(item.quantity || 1);
            item.harga = parseFloat(item.harga || 0);
            item.price = parseFloat(item.price || 0);

            if ((!item.sub || item.sub === '0') && !item.payment) {
                item.toppings = [];
                item.paketItems = [];
                reconstructedCart.push(item);
                mainItemsMap.set(item.noit, item);
            } else if (item.sub === '1') {
                const parentNoit = item.noit.substring(0, 2);
                const parentItem = mainItemsMap.get(parentNoit);
                if (parentItem) {
                    if (item.harga > 0) {
                        let toppingGroup = parentItem.toppings.find(t => t.toping === item.toping);
                        if (!toppingGroup) {
                            toppingGroup = { toping: item.toping || 'GROUP_TDK_DIKETAHUI', Group: 'Pilihan Tambahan', items: [] };
                            parentItem.toppings.push(toppingGroup);
                        }
                        toppingGroup.items.push({ nama_toping: item.name, kode_toping: item.kode, harga: item.harga, checked: true });
                    } else {
                        parentItem.paketItems.push({ kode: item.kode, name: item.name, quantity: item.quantity });
                    }
                }
            } else if (item.payment) {
                reconstructedCart.push(item);
            }
        }
        
        reconstructedCart.forEach(item => {
            item.meja = 'ADJUST';
        });

        // --- Langkah 3: Hapus data lama dan "Suntikkan" Data baru ke Meja 'ADJUST' ---
        const originalTipe = this.adjustTransactions.find(t => t.nomor === transaction.nomor)?.tipe || '1';
        await rubahjson('meja', { tipe: originalTipe, user: this.nuser }, adjustTableObject.id);

        // **LOGIKA BARU**: Hapus record lama, lalu selalu insert record baru.
        await hapus('cart', 'meja', 'ADJUST');

        const dataToInsert = { 
            meja: 'ADJUST', 
            cart: JSON.stringify(reconstructedCart),
            brand: this.xbrand,
            cab: this.xcab,
            nomor: transaction.nomor
        };
        await tambahjson('cart', dataToInsert);
        
        // --- Langkah 4: Buka Meja 'ADJUST' dan masuk ke mode edit ---
        this.isAdjustMode = true;
        this.originalTransactionNumber = transaction.nomor;
        this.showAdjustModal = false;
        
        this.changeMeja(adjustTableObject);

    } catch (error) {
        console.error("Gagal memproses penyesuaian:", error);
        this.pesan(`Terjadi kesalahan: ${error.message}`, 'error');
    }
},

			showTransactionSummary(data) {
				this.sbill = data; // Simpan data rekap di data Vue
				const modal = document.getElementById('transactionSummaryModal');
				if (modal) {
					modal.style.display = 'flex';
				}
			},

			async closeTransactionSummary() {
				// Logika reset cart dan meja (dipindah dari tutup_ok)
				const remainingItems = this.pesant.filter(item => item.meja === this.currentMeja);

				if (remainingItems.length === 0) {
					// Reset status meja & hapus cart di database
					if (this.mejao) {
						this.mejao.user = '';
						this.mejao.jumlah = 0;
						this.mejao.cover = 0;
						this.mejao.guest = '';
						this.mejao.split = ''; // Pastikan split dihapus
						rubahjson('meja', this.mejao, this.mejao.id);
					}
					const dataToSave = { meja: this.currentMeja, cart: '[]', brand: xbrand, cab: xcab };
					rubahjson('cart', dataToSave, dataToSave.meja, 'meja');
					this.activeSplitFilter = '';
				} else {
					// Update data cart di database jika masih ada sisa
					this.updatecart2();

					// Cek sisa split bill
					const remainingSplits = this.pesant.some(item => item.split && item.split.trim() !== '');
					if (!remainingSplits) {
						this.mejao.split = '';
						rubahjson('meja', { split: '' }, this.mejao.id);
						this.isMasterPaymentDisabled = false;
						this.activeSplitFilter = '';
					}
				}

				// --- LANGKAH PENTING: KIRIM SINYAL TUTUP & CLEAR KE CUSTOMER DISPLAY ---
				try {
					const secondDisplayData = {
						command: 'hidePayment',
						payload: {
							meja: '', // Kosongkan
							cart: [], // Kosongkan
							totals: null // Kosongkan
						}
					};
					localStorage.setItem('secondDisplay', JSON.stringify(secondDisplayData));

				} catch (error) {
					console.error('Gagal mengirim perintah clear ke Second Display:', error);
				}
				//
				// Tutup modal dan kembali ke Map Table
				const modal = document.getElementById('transactionSummaryModal');
				if (modal) {
					modal.style.display = 'none';
				}
				// this.pesan('Transaksi selesai. Kembali ke Map Table.', 'success');
				this.Map_table();
			},			

			async _generateTransactionHeader(itemsToPay) {
				// 1. Baca kode mesin dari localStorage
				let kodeMesin = 'XX';
				try {
					const xposData = localStorage.getItem('xpos');
					if (xposData) {
						const xpos = JSON.parse(xposData);
						if (xpos.mesin) {
							kodeMesin = String(xpos.mesin).padStart(2, '0');
						}
					}
				} catch (e) {
					console.error("Gagal membaca kode mesin dari localStorage:", e);
				}

				// 2. Generate nomor transaksi baru
				const data = ambilakhir('jual', 'nomor', '', '');
				const newTransactionNumber = gennomor(data === '[]' ? '' : JSON.parse(data)[0].nomor);

				// Hitung total hanya untuk item yang aktif (item produk dan item pembayaran)
				const activeSubtotal = itemsToPay.reduce((total, item) => {
					if (!item.payment) return total + item.jumlah;
					return total;
				}, 0);

				const activeDisc = itemsToPay.reduce((total, item) => {
					if (!item.payment) return total + item.disc;
					return total;
				}, 0);

				const activeService = itemsToPay.reduce((total, item) => {
					if (!item.payment) return total + item.service;
					return total;
				}, 0);

				const activeTax = itemsToPay.reduce((total, item) => {
					if (!item.payment) return total + item.pajak;
					return total;
				}, 0);

				const activePayment = itemsToPay.reduce((total, item) => {
					if (item.payment) return total + item.harga;
					return total;
				}, 0);

				// Hitung total cash (hanya CASH '10')
				const cashPayment = itemsToPay.filter(item => item.payment === '10').reduce((total, item) => total + item.harga, 0);

				const finalGrandTotal = activeSubtotal - activeDisc + activeService + activeTax;

				// 3. Persiapkan data untuk tabel 'jual'
				var ijual = {
					"tipe": this.mejao.tipe,
					"brand": xbrand,
					"cab": xcab,
					"komplit": "1",
					"nomor": newTransactionNumber,
					"tanggal": new Date().toISOString().slice(0, 10),
					"jamm": getWaktu(),
					"jams": getWaktu(),
					"shift": this.register.shift || 1,
					"guest": this.mejao.guest + (this.activeSplitFilter ? ` (Split ${this.activeSplitFilter})` : ''),
					"cover": Number(this.mejao.cover) || 0,
					"jumlah": finalGrandTotal,
					"bayar": activePayment,
					"meja": this.mejao.kode,
					"ttax": activeTax,
					"ttot": activeSubtotal,
					"tserv": activeService,
					"user": this.nuser,
					"batal": 0,
					"kasir": this.kuser,
					"register": this.register.nomor,
					"mesin": kodeMesin,
					"deliver": "0",
					// PENTING: Untuk transaksi TUNAI, harga di tabel pesani dikurangi kembalian.
					// Di sini, kita masukkan total penerimaan CASH dikurangi kembalian.
					"cash": cashPayment - (this.xkembali || 0),
					"card": itemsToPay.filter(item => item.payment === '12').reduce((total, item) => total + item.harga, 0),
					"kembali": this.xkembali || 0,
					"rounding": 0,
					"pvoucher": 0,
					"diskrupiah": 0
				};

				// 4. Kirim data header ke tabel 'jual'
				insertData('jual', [ijual]);

				// 5. Update data register kasir jika sedang aktif (Logika dipersingkat)
				if (this.pos.register && this.register.open && ijual.jumlah > 0) {
					let bx = JSON.parse(ambilakhir('register', 'nomor', this.register.nomor, this.register.nomor));
					if (bx.length > 0) {
						bx = bx[0];
						bx.frek = Number(bx.frek || 0) + 1;
						bx.jumlah = Number(bx.jumlah || 0) + finalGrandTotal;
						bx.cash = Number(bx.cash || 0) + Number(ijual.cash);
						bx.card = Number(bx.card || 0) + Number(ijual.card);
						bx.noakhir = newTransactionNumber;
						rubahjson('register', bx, bx.nomor, 'nomor');
					}
				}

				return newTransactionNumber;
			},
			updateMenuPrices() {
				//console.log("Memperbarui harga menu berdasarkan aturan...");

				// 1. Dapatkan tanggal hari ini (tanpa jam) untuk perbandingan
				const today = new Date();
				today.setHours(0, 0, 0, 0);

				// 2. Ambil grup harga yang aktif (defaultnya '1' saat aplikasi dimuat)
				const activePriceGroup = this.group_harga || '1';

				// 3. Buat Peta (Map) untuk pencarian aturan harga yang lebih cepat dan efisien
				const priceRulesMap = new Map(this.harga.map(rule => [rule.barang, rule]));

				// 4. Iterasi setiap item di master menu
				this.menus.forEach(menuItem => {
					// Cek apakah ada aturan harga untuk item menu ini
					const rule = priceRulesMap.get(menuItem.kode);

					if (rule) {
						const startDate = new Date(rule.tgl_mulai);
						const endDate = new Date(rule.tgl_akhir);
						startDate.setHours(0, 0, 0, 0);
						endDate.setHours(0, 0, 0, 0);

						// 5. Cek apakah aturan tersebut aktif hari ini
						if (today >= startDate && today <= endDate) {
							// Tentukan key harga dan diskon berdasarkan grup yang aktif
							const hargaKey = 'harga' + activePriceGroup;
							const diskpKey = 'diskp' + activePriceGroup;
							const diskrKey = 'diskr' + activePriceGroup;

							// 6. Perbarui harga & diskon HANYA JIKA ada harga yang didefinisikan untuk grup ini
							if (rule[hargaKey] !== null && rule[hargaKey] !== undefined) {
								menuItem.price = parseFloat(rule[hargaKey]);
								menuItem.discp = parseFloat(rule[diskpKey]) || 0;
								menuItem.discr = parseFloat(rule[diskrKey]) || 0;
							}
						}
					}
				});

				// 7. Gabungkan kembali dengan data topping setelah harga diperbarui
				this.menus = this.gabung;
				//console.log("Pembaruan harga menu selesai.");
			},			

			logout() {
				this.activeSplitFilter = '';
				this.inputValue1 = '';
				this.inputValue2 = '';
				this.ipilih = 1;
				this.digits = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.', '@'];
				this.loadOpenRegisterSession();
				document.getElementById("overlogin").style.display = "block";
				document.getElementById('userlog').click();
			},

// Ganti seluruh fungsi _preparePesaniData di pos.js
_preparePesaniData(itemsToSave, transactionNumber) {
    const pesaniItems = [];
    let itemCounter = 0;
    const finalKembali = this.xkembali > 0 ? this.xkembali : 0; 
    const nowTglo = getWaktu(); // Ambil waktu sekali saja

    itemsToSave.forEach(item => {
        // =================================================================================
        // ✨ PERBAIKAN UTAMA ADA DI SINI ✨
        // Kondisi ini disederhanakan agar HANYA memproses item produk 
        // (yaitu item yang TIDAK memiliki properti 'payment').
        // =================================================================================
        if (!item.payment) { 
            itemCounter++;
            const mainNoit = String(itemCounter).padStart(2, '0');

            // --- 1. SIAPKAN ITEM UTAMA (Produk) ---
            const mainItemData = {
                nomor: transactionNumber,
                noit: mainNoit,
                sub: '0', 
                tglo: item.tglo || nowTglo,
                kode: item.kode || 'UNKNOWN',
                name: item.name || 'Produk Tanpa Nama',
                quantity: item.quantity || 1,
                harga: item.harga || 0,
                price: item.price || 0,
                meja: item.meja || this.currentMeja || 'TA',
                user: item.user || this.nuser || 'GUEST',
                brand: item.brand || xbrand,
                cab: item.cab || xcab,
                split: item.split || '',
                discp: item.discp || 0,
                discr: item.discr || 0,
                disc: item.disc || 0,
                serv: item.serv || 0,
                ppn: item.ppn || 0,
                service: item.service || 0,
                pajak: item.pajak || 0,
                jumlah: item.jumlah || 0,
                netto: item.netto || 0,
                dname: item.dname || '',
                note: item.note || '',
                cetak: item.cetak || '',
                kgroup: item.kgroup || '',
                group_name: item.group || '',
                condiment: item.condiment || '',
                condiment_name: item.condiment_name || '',
                toping: item.toping || '',
                image: item.image || '',
                ket: item.ket || '',
                payment: '', // Dibuat kosong karena ini adalah item produk
                edc: item.edc,
                nocard: item.nocard
            };
            
            ['eng', 'ind', 'chn', 'jpn', 'arb', 'group'].forEach(key => delete mainItemData[key]);
            
            pesaniItems.push(mainItemData);

            // --- 2. LOGIKA SUB-ITEM (Toppings & Paket) ---
            if (item.toppings && Array.isArray(item.toppings)) {
                let toppingSubCounter = 0;
                item.toppings.forEach(toppingGroup => {
                    if (toppingGroup.items && Array.isArray(toppingGroup.items)) {
                        toppingGroup.items.forEach(toppingItem => {
                            if (toppingItem.checked) {
                                toppingSubCounter++;
                                pesaniItems.push({
                                    brand: xbrand,
                                    cab: xcab,
                                    nomor: transactionNumber,
                                    noit: `${mainNoit}${String(toppingSubCounter).padStart(2, '0')}`,
                                    sub: '1', 
                                    tglo: nowTglo,
                                    kode: toppingItem.kode_toping || 'T000',
                                    name: toppingItem.nama_toping || 'Topping',
                                    quantity: item.quantity || 1,
                                    harga: toppingItem.harga || 0,
                                    price: toppingItem.harga || 0,
                                    meja: item.meja || this.currentMeja || 'TA',
                                    user: item.user || this.nuser || 'GUEST',
                                    nocard: item.kode
                                });
                            }
                        });
                    }
                });
            }

            if (item.paketItems && Array.isArray(item.paketItems)) {
                 let paketSubCounter = 0;
                 item.paketItems.forEach(paketItem => {
                    paketSubCounter++;
                     pesaniItems.push({
                         brand: xbrand,
                         cab: xcab,
                         nomor: transactionNumber,
                         noit: `${mainNoit}${String(paketSubCounter).padStart(2, '0')}`,
                         sub: '1',
                         tglo: nowTglo,
                         kode: paketItem.kode || 'P000',
                         name: paketItem.name || 'Item Paket',
                         quantity: (paketItem.quantity * (item.quantity || 1)) || 1, 
                         harga: 0, 
                         price: 0,
                         meja: item.meja || this.currentMeja || 'TA',
                         user: item.user || this.nuser || 'GUEST',
                         nocard: item.kode
                     });
                 });
            }
        }
    });

    // --- 3. SIAPKAN ITEM PEMBAYARAN & DISKON FAKTUR ---
    const paymentItems = itemsToSave.filter(item => item.payment && item.payment !== '');
    paymentItems.forEach(paymentItem => {
        itemCounter++;
        let finalHarga = paymentItem.harga;
        
        if (paymentItem.payment === '10') {
            finalHarga = paymentItem.harga - finalKembali;
        }

        const paymentData = {
            nomor: transactionNumber,
            noit: String(itemCounter).padStart(2, '0'),
            harga: finalHarga, 
            jumlah: finalHarga,
            payment: paymentItem.payment,
            edc: paymentItem.edc || '',
            nocard: paymentItem.nocard || '',
            name: paymentItem.name || 'Pembayaran',
            brand: paymentItem.brand || xbrand,
            cab: paymentItem.cab || xcab,
            tglo: paymentItem.tglo || nowTglo,
            meja: paymentItem.meja || this.currentMeja || 'TA',
            user: paymentItem.user || this.nuser || 'GUEST',
            sub: '0', 
            kode: paymentItem.kode || paymentItem.payment,
            quantity: 1,
            price: finalHarga,
            discp: 0,
            discr: 0,
            disc: 0,
            serv: 0,
            ppn: 0,
            service: 0,
            pajak: 0,
            netto: finalHarga,
            kgroup: '',
            group_name: '',
            condiment: '',
            condiment_name: '',
            toping: '',
            image: '',
            ket: '',
            note: '',
            cetak: '',
            split: paymentItem.split || ''
        };
        pesaniItems.push(paymentData);
    });

    return pesaniItems;
},
			

    async fetchKioskTransactions() {
        this.kioskIsLoading = true;
        try {
            // Mengambil 50 transaksi terbaru
            const query = "SELECT * FROM transactions WHERE status = 'completed' ORDER BY id DESC LIMIT 50";
            const resultJson = await ambil_select('transactions', query);
            const transactions = JSON.parse(resultJson);
            this.kioskTransactions = transactions;
        } catch (error) {
            console.error("Gagal mengambil transaksi Kiosk:", error);
            this.pesan('Gagal mengambil data transaksi dari Kiosk.', 'error');
        } finally {
            this.kioskIsLoading = false;
        }
    },

// pos.js -> methods

async selectKioskTransaction(transaction) {
    const confirmed = await this.showConfirmationDialog(
        `Anda akan menambahkan item dari transaksi ${transaction.transaction_code} ke meja saat ini. Lanjutkan?`
    );

    if (!confirmed) {
        return;
    }

    try {
        this.pesan('Memuat item dari transaksi Kiosk...', 'info');
        
        const query = `SELECT * FROM transaction_items WHERE transaction_id = ${transaction.id}`;
        const itemsJson = await ambil_select('transaction_items', query);
        const kioskItems = JSON.parse(itemsJson);

        if (kioskItems.length === 0) {
            this.pesan('Tidak ada item ditemukan untuk transaksi ini.', 'warning');
            return;
        }

        for (const kioskItem of kioskItems) {
            
            // --- BAGIAN LOGIKA PENCARIAN YANG DIPERBARUI ---
            
            // 1. Prioritas utama: Cari berdasarkan 'kode' (product_id dari kiosk)
            let masterMenuItem = this.menus.find(m => m.kode == kioskItem.product_id);

            // 2. Jika tidak ditemukan berdasarkan 'kode', coba cari berdasarkan 'nama' sebagai cadangan
            if (!masterMenuItem) {
                console.warn(`Pencarian berdasarkan KODE ${kioskItem.product_id} gagal. Mencoba mencari berdasarkan NAMA "${kioskItem.product_name}"...`);
                // Mencari dengan mencocokkan nama (setelah diubah ke huruf kecil dan di-trim)
                masterMenuItem = this.menus.find(m => 
                    m.name.toLowerCase().trim() === kioskItem.product_name.toLowerCase().trim()
                );
            }

            // 3. Jika setelah dua kali pencarian tetap tidak ditemukan, lewati item ini
            if (!masterMenuItem) {
                console.error(`GAGAL TOTAL: Item Kiosk "${kioskItem.product_name}" tidak ditemukan di master menu POS. Item ini dilewati.`);
                this.pesan(`Item "${kioskItem.product_name}" tidak ada di master menu.`, 'warning');
                continue; // Lanjut ke item berikutnya
            }
            
            // ---------------------------------------------------

            let newItem = JSON.parse(JSON.stringify(masterMenuItem));
            let itemDetails = {};
            try {
                itemDetails = JSON.parse(kioskItem.item_details);
            } catch(e) { /* Abaikan jika JSON tidak valid */ }
            
            // Mengisi properti item dengan lebih lengkap untuk memastikan kompatibilitas
            newItem.id = padNumberWithZeros(generateRandomNumber(), 10);
            newItem.quantity = parseFloat(kioskItem.quantity);
            newItem.price = parseFloat(kioskItem.price_per_item);
            newItem.harga = parseFloat(kioskItem.price_per_item);
            newItem.name = kioskItem.product_name;
            newItem.note = itemDetails.note || '';
            
            newItem.meja = this.currentMeja;
            newItem.user = this.nuser;
            newItem.tglo = getWaktu();
            newItem.brand = this.xbrand;
            newItem.cab = this.xcab;
            newItem.payment = '';
            newItem.split = this.activeSplitFilter;

            newItem.discp = newItem.discp || 0;
            newItem.discr = newItem.discr || 0;
            newItem.disc = 0;
            newItem.serv = 0;
            newItem.ppn = 0;
            newItem.service = 0;
            newItem.pajak = 0;
            newItem.jumlah = newItem.harga * newItem.quantity;
            newItem.netto = 0;
            
            newItem.cetak = '';
            newItem.toppings = newItem.toppings || [];
            newItem.paketItems = newItem.paketItems || [];

            this.pesant.push(newItem);
        }

        this.showKioskModal = false;
        
        const triggerKalkulasi = this.cartSubtotal;

        this.updatecart2();
        this.pesan('Item dari Kiosk berhasil ditambahkan ke keranjang.', 'success');

    } catch (error) {
        console.error("Gagal memproses transaksi Kiosk:", error);
        this.pesan('Terjadi kesalahan saat memproses item dari Kiosk.', 'error');
    }
},
			

async loadOpenRegisterSession() {
	
    try {
        // 1. Ambil data register terakhir, tanpa filter user
        const resultJson = await ambilakhir('register', '', '');
        const lastRegisterArr = JSON.parse(resultJson);
		
        if (lastRegisterArr.length > 0) {
            const lastRegister = lastRegisterArr[0];

            // 2. Cek status 'tutup' dari register terakhir
            if (lastRegister.tutup == '1') {
                this.register = {
                    open: false,
                    nomor: '', // Sesuai permintaan, nomor dikosongkan
					nama:'-'
                };
                //console.log('Register terakhir sudah ditutup. Tidak ada sesi aktif.');
            } else {
                let bx = ambil('users', 'kode', lastRegister.user, lastRegister.user);
    				bh = JSON.parse(bx);
					nama=bh[0].nama;
                   this.register = {
                    open: true,
                    kuser: lastRegister.user,
                    nama: nama, // Nama diambil dari user yg login saat ini
                    nomor: lastRegister.nomor, // Sesuai permintaan, isi dengan nomor register
                    modal: parseFloat(lastRegister.saldoawal),
                    shift: lastRegister.shift
                };
                //console.log('Sesi register terakhir ditemukan terbuka:', this.register.nomor);
            }
        } else {
            // Jika tidak ada data register sama sekali di database
            this.register = {
                open: false,
                nomor: ''
            };
            //console.log('Tidak ada data register di database.');
        }
    } catch (error) {
        console.error('Gagal memuat sesi register terakhir:', error);
        this.register = { open: false, nomor: '' }; // Fallback jika terjadi error
    }
},

// GANTI method prosesBukaRegister DENGAN VERSI INI
async prosesBukaRegister(modalAwal,shift) {
    try {
        // Cek sekali lagi untuk memastikan tidak ada register terbuka
        //await this.loadOpenRegisterSession();
        if (this.register.open) {
            this.tampilkanPesan(`Kasir ${this.nuser} sudah memiliki sesi register yang terbuka (No: ${this.register.nomor}). Tutup sesi sebelumnya terlebih dahulu.`, 'error');
            return;
        }
		
		

        const dataAkhirRegister = await ambilakhir('register', 'nomor', '', '');
        const noAkhir = dataAkhirRegister === '[]' ? '' : JSON.parse(dataAkhirRegister)[0].nomor;
        const noRegisterBaru = gennomor(noAkhir);

        const now = new Date();
        const dataUntukDb = {
            tanggal: now.toISOString().slice(0, 10),
            jam: now.toTimeString().slice(0, 8),
            nomor: noRegisterBaru,
            saldoawal: modalAwal,
            user: this.kuser,
            tutup: 0,
			shift:this.selectedShift,
            brand: this.xbrand,
            cab: this.xcab,
            shift: this.selectedShift // PERBAIKAN: Memastikan shift tersimpan
        };
        await insertData('register', dataUntukDb);

        // Perbarui state aplikasi
        this.register = {
            nomor: noRegisterBaru,
            kuser: this.kuser,
            nama: this.nuser,
            open: true,
            shift: this.selectedShift, // PERBAIKAN: Memastikan shift ada di state
            modal: modalAwal
        };

        // Buat Teks Slip dengan Desain Baru
        const slipText = this._buildOpenRegisterSlip(noRegisterBaru, modalAwal);

        // Cetak Slip Menggunakan PrintManager
        const receiptPrinterCode = this.pos['receipt_printer_code'] || '04'; 
        const isSuccess = await PrintManager.cetak(slipText, receiptPrinterCode, 'OPEN_REGISTER');
        
        if (!isSuccess) {
            this.tampilkanPesan('Register berhasil dibuka, namun gagal mencetak slip bukti.', 'error');
        } else {
            this.tampilkanPesan(`Register ${noRegisterBaru} berhasil dibuka.`, 'success');
        }

    } catch (error) {
        console.error("Gagal memproses buka register:", error);
        this.tampilkanPesan(`Error: Gagal membuka register. ${error.message}`, 'error');
    }
},

// GANTI JUGA method _buildOpenRegisterSlip DENGAN VERSI INI
_buildOpenRegisterSlip(nomorRegister, modal) {
    const padCenter = (text, width) => { /* ... (helper function, biarkan sama) ... */ };
    const line = (char = '=', width = 42) => char.repeat(width);

    // --- AWAL PERBAIKAN UTAMA ---

    // 1. Ambil data header dari this.pos
    const namaResto = this.pos['nama'] || 'Nama Resto';
    const alamatResto = this.pos['alamat'] || 'Alamat Resto';
    const slogan = this.pos['ket'] || '';
    const kota = this.pos['kota'] || '';
    const kodeMesin = this.xpos ? this.xpos.mesin : 'N/A';
    
    // 2. Perintah ESC/POS untuk cetak besar (Double Width) dan kembali normal
    const doubleWidthOn = '\x1B\x21\x10';
    const doubleWidthOff = '\x1B\x21\x00';

    const now = new Date();
    const tanggalCetak = now.toLocaleDateString('id-ID', { day: '2-digit', month: 'short', year: 'numeric' });
    const jamCetak = now.toTimeString().slice(0, 8);
    const formattedModal = `Rp ${new Intl.NumberFormat('id-ID').format(modal)}`;

    // 3. Susun ulang teks struk dengan header dan format baru
    let report = [];
    // Menambahkan Header
    report.push(padCenter(namaResto, 42));
    if (slogan) report.push(padCenter(slogan, 42));
    if (alamatResto) report.push(padCenter(alamatResto, 42));
    if (kota) report.push(padCenter(kota, 42));
    report.push(line('='));
    report.push(padCenter('BUKTI BUKA REGISTER', 42));
    report.push(line('-'));
    report.push('');

    report.push(`Nomor   : ${nomorRegister}`);
    report.push(`Kasir   : ${this.register.kuser} - ${this.register.nama}`);
    report.push(`Shift   : ${this.register.shift}`); // Nilai shift sekarang sudah benar
    report.push(`Waktu   : ${tanggalCetak} ${jamCetak}`);
    report.push(`Mesin   : ${kodeMesin}`);
    report.push(line('-'));
    
    // Mencetak modal dengan font besar
    report.push('MODAL AWAL:'.padEnd(20) + doubleWidthOn + formattedModal.padStart(22) + doubleWidthOff);
    report.push(line('='));
    report.push('');

    report.push('KASIR'.padEnd(21) + 'KOORDINATOR');
    report.push('\n\n\n');
    report.push(this.register.nama.padEnd(21, ' ') + '___________________');
    report.push(`(${'-'.repeat(18)}) (${'-'.repeat(19)})`);
    
    // --- AKHIR PERBAIKAN UTAMA ---

    return report.join('\n');
},

/**
 * Helper untuk membuat string struk buka register dengan format rapi.
 */
_buildOpenRegisterSlip(nomorRegister, modal) {
    // Helper internal untuk format teks
    const padCenter = (text, width) => {
        const textStr = String(text || '');
        const pad = Math.max(0, width - textStr.length);
        return ' '.repeat(Math.floor(pad / 2)) + textStr + ' '.repeat(Math.ceil(pad / 2));
    };
    const line = (char = '=', width = 42) => char.repeat(width);

    // --- AWAL PERBAIKAN ---

    // 1. Ambil data header dari this.pos dengan kunci yang BENAR
    const namaResto = this.pos['nama'] || 'Nama Resto';
    const alamatResto = this.pos['alamat'] || 'Alamat Resto';
    const slogan = this.pos['ket'] || '';
    const kota = this.pos['kota'] || '';

    // 2. Ambil kode mesin langsung dari localStorage untuk memastikan data terbaru
    const xposData = JSON.parse(localStorage.getItem('xpos')) || {};
    const kodeMesin = xposData.mesin || 'N/A';
    
    // 3. Perintah ESC/POS untuk cetak besar (Double Width) dan kembali normal
    const doubleWidthOn = '\x1B\x21\x10';
    const doubleWidthOff = '\x1B\x21\x00';

    const now = new Date();
    const tanggalCetak = now.toLocaleDateString('id-ID', { day: '2-digit', month: 'short', year: 'numeric' });
    const jamCetak = now.toTimeString().slice(0, 8);
    const formattedModal = `Rp ${new Intl.NumberFormat('id-ID').format(modal)}`;

    // 4. Susun ulang teks struk dengan header dan format baru
    let report = [];
    // Menambahkan Header
    report.push(padCenter(namaResto, 42));
    if (slogan) report.push(padCenter(slogan, 42));
    if (alamatResto) report.push(padCenter(alamatResto, 42));
    if (kota) report.push(padCenter(kota, 42));
    report.push(line('='));
    report.push(padCenter('BUKTI BUKA REGISTER', 42));
    report.push(line('-'));
    report.push('');

    report.push(`Nomor   : ${nomorRegister}`);
    report.push(`Kasir   : ${this.register.kuser} - ${this.register.nama}`);
    report.push(`Shift   : ${this.register.shift}`);
    report.push(`Waktu   : ${tanggalCetak} ${jamCetak}`);
    report.push(`Mesin   : ${kodeMesin}`); // <-- Kode mesin sudah benar
    report.push(line('-'));
    
    // Mencetak modal dengan font besar
    report.push('MODAL AWAL:'.padEnd(20) + doubleWidthOn + formattedModal.padStart(22) + doubleWidthOff);
    report.push(line('='));
    report.push('');

    report.push('KASIR'.padEnd(21) + 'KOORDINATOR');
    report.push('\n\n\n');
    report.push(this.register.nama.padEnd(21, ' ') + '___________________');
    report.push(`(${'-'.repeat(18)}) (${'-'.repeat(19)})`);
    
    // --- AKHIR PERBAIKAN ---

    return report.join('\n');
},
			

			showConfirmationDialog(message) {
        return new Promise(resolve => {
            // Menggunakan confirm bawaan browser, atau ganti dengan modal custom Anda
            const result = confirm(message);
            resolve(result); // true jika OK, false jika Cancel
        });
    },

async cetakStruk() {
    const dataStruk = "--- Struk Belanja ---\nNasi Goreng x 1\n\n";
    const kodePrinterKasir = '04'; // Kode untuk printer KASIR dari tabel kitchen
    const isSuccess = await PrintManager.cetak(dataStruk, kodePrinterKasir, '3');
    if (!isSuccess) {
        this.tampilkanPesan('Gagal mencetak struk. Silakan cek log atau coba lagi.', 'error');
    }
},

// GANTI FUNGSI LAMA DENGAN INI di dalam methods di pos.js
async showClosingReport(closingBalance) {
    try {
        // Ambil data register yang SEDANG TERBUKA
       //alert(this.register.nomor);
        const query = `SELECT * FROM register WHERE nomor='${this.register.nomor}' `;
        const result = await ambil_select('register', query);
        const registerData = JSON.parse(result)[0];
		// js(registerData);

        if (!registerData) {
            this.tampilkanPesan('Error: Sesi register yang akan ditutup tidak ditemukan di database.', 'error');
            return;
        }

        // ... sisa kode tetap sama (const namaKasir, params, etc.)
        const userQuery = `SELECT nama FROM users WHERE kode='${registerData.user}' AND brand='${this.xbrand}' AND cab='${this.xcab}'`;
        const userResult = await ambil_select('users', userQuery);
        const userData = JSON.parse(userResult)[0];
        const namaKasir = userData ? userData.nama : registerData.user;
                const options = {
                    isClosingMode: true,
                    registerNomor:  registerData.nomor,
                    tanggal:  registerData.tanggal,
                    saldoAwal:  registerData.saldoawal,
                    saldoAkhir: closingBalance,
                    namaKasir: namaKasir
                };
                const reportText = await generateReport(options);


    const dataStruk = reportText;
    const kodePrinterKasir = '04'; // Kode untuk printer KASIR dari tabel kitchen
    const isSuccess = await PrintManager.cetak(dataStruk, kodePrinterKasir, '3');

        const dataUpdate = {
             tutup: 1,
             jamtutup: new Date().toTimeString().slice(0, 8)
			 
             // Anda bisa tambahkan field lain yang perlu diupdate saat tutup
        };

        // Update database untuk menutup register
		this.register.open=false;
        await rubahjson('register', dataUpdate,registerData.nomor, 'nomor');

    if (!isSuccess) {
        this.tampilkanPesan('Gagal mencetak. Silakan cek log printer.', 'error');
		sukses=0;
        const dataUpdate = {
             tutup: 0,
             jamtutup: new Date().toTimeString().slice(0, 8)
             // Anda bisa tambahkan field lain yang perlu diupdate saat tutup
        };

        // Update database untuk menutup register

	} else {
		sukses=1;

	}
	this.register.open=false;
        await rubahjson('register', dataUpdate,registerData.nomor, 'nomor');
  

    } catch (error) {
        console.error('Error saat mempersiapkan laporan closing:', error);
        this.tampilkanPesan(`Error: ${error.message}`, 'error');
    }
},


 async closeReportModal() {
    this.showReportIframe = false;
    this.reportIframeUrl = '';
    
    try {
        // Ambil saldo akhir dari URL (jika diperlukan untuk update) atau dari state
        // Tapi cara paling andal adalah saat memanggil showClosingReport
        // Di sini kita hanya update status tutup
        const dataUpdate = {
             tutup: 1,
             jamtutup: new Date().toTimeString().slice(0, 8)
             // Anda bisa tambahkan field lain yang perlu diupdate saat tutup
        };

        // Update database untuk menutup register
        await rubahjson('register', dataUpdate, this.register.nomor, 'nomor');

        // Reset state register di aplikasi
        this.register = { open: false };

        this.tampilkanPesan('Register berhasil ditutup.', 'success');
        this.resetTransaksi(); // Kembali ke kondisi awal atau Map Table
        this.Map_table();

    } catch(error) {
        this.tampilkanPesan(`Error saat menutup register di database: ${error.message}`, 'error');
    }
},

		

    		saveSplitAndGoToOrder(splitCode) {
    			// 1. Simpan data split bill ke database
    			this.pesant = this.items;

    			// 2. Update data di tabel cart
    			const allItemsForThisTable = this.pesant.filter(item => item.meja === this.currentMeja);
    			const dataToSave = {
    				meja: this.currentMeja,
    				cart: JSON.stringify(allItemsForThisTable).replace(/:null/g, ':""'),
    				brand: xbrand,
    				cab: xcab
    			};

    			// Cek apakah data sudah ada di database
    			const cartExists = ambil('cart', 'meja', this.currentMeja);
    			if (cartExists && cartExists !== '[]') {
    				// Update jika sudah ada
    				rubahjson('cart', dataToSave, dataToSave.meja, 'meja');
    			} else {
    				// Insert jika belum ada
    				tambahjson('cart', dataToSave);
    			}

    			// 3. Set split filter aktif
    			this.activeSplitFilter = splitCode;

    			// 4. Reset pilihan item
    			this.currentCartItemId = null;
    			this.selectedItemName = '';
    			this.currentcart = null;

    			// 5. Tutup split screen
    			this.showSplit = false;

    			// 6. Tampilkan pesan sukses
    			// this.pesan(`Bill ${splitCode} berhasil disimpan.`, 'success');

    			// 7. Navigasi ke halaman order dengan mode split
    			document.getElementById("Map").style.display = 'none'; // Tutup map table
    			vm.posisi = 'order'; // Set posisi ke order
    		},

    		saveMasterAndGoToOrder() {
    			// 1. Simpan data master bill ke database
    			this.pesant = this.items;

    			// 2. Update data di tabel cart
    			const allItemsForThisTable = this.pesant.filter(item => item.meja === this.currentMeja);
    			const dataToSave = {
    				meja: this.currentMeja,
    				cart: JSON.stringify(allItemsForThisTable).replace(/:null/g, ':""'),
    				brand: xbrand,
    				cab: xcab
    			};

    			// Cek apakah data sudah ada di database
    			const cartExists = ambil('cart', 'meja', this.currentMeja);
    			if (cartExists && cartExists !== '[]') {
    				// Update jika sudah ada
    				rubahjson('cart', dataToSave, dataToSave.meja, 'meja');
    			} else {
    				// Insert jika belum ada
    				tambahjson('cart', dataToSave);
    			}

    			// 3. Reset split filter
    			this.activeSplitFilter = '';

    			// 4. Reset pilihan item
    			this.currentCartItemId = null;
    			this.selectedItemName = '';
    			this.currentcart = null;

    			// 5. Tutup split screen
    			this.showSplit = false;

    			// 6. Tampilkan pesan sukses
    			//this.pesan(`Master Bill berhasil disimpan.`, 'success');

    			// 7. Navigasi ke halaman order (PERBAIKAN UTAMA DI SINI)
    			document.getElementById("Map").style.display = 'none'; // Tutup map table
    			vm.posisi = 'order'; // Set posisi ke order

    			// Pastikan tampilan order muncul
    			if (document.getElementById("app")) {
    				document.getElementById("app").style.display = 'block';
    			}

    			// Refresh data keranjang untuk memastikan tampilan terbaru
    			this.updatecart2();
    		},

    		saveSplitTransaction(splitCode, paidItems, totalAmount) {
    			this.pesan('Menyimpan transaksi...', 'info');

    			// 1. Generate nomor transaksi baru yang unik
    			const data = ambilakhir('jual', 'nomor', '', '');
    			const newTransactionNumber = gennomor(data === '[]' ? '' : JSON.parse(data)[0].nomor);

    			// 2. Siapkan data untuk tabel 'jual'
    			const jualData = {
    				"tipe": this.mejao.tipe,
    				"brand": xbrand,
    				"cab": xcab,
    				"nomor": newTransactionNumber,
    				"tanggal": new Date().toISOString().slice(0, 10),
    				"jamm": getWaktu(),
    				"meja": this.mejao.kode,
    				"guest": `${this.mejao.guest || 'Guest'} (Split ${splitCode})`,
    				"jumlah": totalAmount,
    				"bayar": totalAmount, // Asumsi lunas dengan metode ini
    				"ttot": paidItems.reduce((sum, item) => sum + item.jumlah, 0),
    				"tserv": paidItems.reduce((sum, item) => sum + item.service, 0),
    				"ttax": paidItems.reduce((sum, item) => sum + item.pajak, 0),
    				"user": this.nuser,
    				"kasir": this.kuser,
    				"register": this.register.nomor,
    				// (Tambahkan field lain yang relevan jika ada)
    			};

    			// 3. Siapkan data untuk tabel 'pesani'
    			const pesaniData = paidItems.map((item, index) => {
    				return {
    					...item, // Salin semua properti dari item asli
    					nomor: newTransactionNumber, // Gunakan nomor transaksi yang baru
    					noit: String(index + 1).padStart(2, '0')
    				};
    			});

    			// 4. Simpan ke database
    			insertData('jual', [jualData]);
    			insertData('pesani', pesaniData);

    			// 5. Update UI setelah berhasil disimpan
    			// Hapus item yang sudah dibayar dari array utama 'pesant'
    			const paidItemIds = new Set(paidItems.map(item => item.id));
    			this.pesant = this.pesant.filter(item => !paidItemIds.has(item.id));

    			// Panggil lagi updatecart2 untuk menyimpan state terbaru dari cart meja
    			this.updatecart2();

    			this.pesan(`Bill ${splitCode} berhasil dibayar dengan No. Transaksi: ${newTransactionNumber}`, 'success');

    			// 6. Cek apakah semua split sudah lunas
    			const remainingSplits = this.pesant.some(item => item.split && item.split.trim() !== '');
    			if (!remainingSplits) {
    				this.pesan('Semua split bill telah lunas!', 'info');
    				this.mejao.split = ''; // Hapus flag split di data meja
    				rubahjson('meja', {
    					split: ''
    				}, this.mejao.id);
    				this.isMasterPaymentDisabled = false; // Aktifkan kembali tombol bayar utama
    			}
    		},

    		handleImageUpload(event) {
    			const file = event.target.files[0];
    			if (file) {
    				// Buat URL sementara untuk gambar yang dipilih
    				this.imagePreviewUrl = URL.createObjectURL(file);
    				// Update model input teks dengan nama file
    				this.contenMejaimage = 'image/' + file.name;
    			}
    		},

    		onImageError(event) {
    			// Jika URL gambar error, tampilkan gambar placeholder
    			event.target.src = 'image';
    		},


    		refreshFungsiButtons() {
    			try {
    				this.pesan('Memuat ulang daftar fungsi...', 'info');
    				// Ambil data terbaru dari tabel fungsi2
    				let bx = xambil('fungsi2', 'kode', '', 'zz');
            
    				if (bx && bx !== '[]') {
    					this.fungsix = JSON.parse(bx);
    					// Filter ulang data ke dalam array masing-masing
    					this.fungsi2 = this.fungsix.filter(item => item.kelas == '1');
    					this.fungsi3 = this.fungsix.filter(item => item.kelas == '2');
    					this.fungsim = this.fungsix.filter(item => item.kelas == '3');

    					// Urutkan kembali (opsional, tapi disarankan)
    					this.fungsi2.sort((a, b) => a.kode.localeCompare(b.kode));
    					this.fungsi3.sort((a, b) => a.kode.localeCompare(b.kode));
    					this.fungsim.sort((a, b) => a.kode.localeCompare(b.kode));

    					this.pesan('Daftar fungsi berhasil diperbarui!', 'success');
    				} else {
    					throw new Error("Data fungsi tidak ditemukan atau kosong.");
    				}
    			} catch (error) {
    				console.error("Gagal me-refresh fungsi:", error);
    				this.pesan(`Gagal me-refresh fungsi: ${error.message}`, 'error');
    			}
    		},


    		handlePosScroll(event) {
    			// Untuk mencegah pengiriman data yang berlebihan, kita gunakan debounce sederhana
    			if (this.scrollTimeout) {
    				clearTimeout(this.scrollTimeout);
    			}
    			this.scrollTimeout = setTimeout(() => {
    				const {
    					scrollTop,
    					scrollHeight,
    					clientHeight
    				} = event.target;
    				// Hanya kirim jika bisa di-scroll
    				if (scrollHeight > clientHeight) {
    					const scrollRatio = scrollTop / (scrollHeight - clientHeight);
    					try {
    						const scrollData = {
    							command: 'scroll',
    							ratio: scrollRatio
    						};
    						localStorage.setItem('secondDisplay', JSON.stringify(scrollData));
							
    					} catch (error) {
    						console.error('Gagal mengirim data scroll:', error);
    					}
    				}
    			}, 50); // Delay 50ms
    		},

    		hideConfirm() {

    			this.shoconfbayar = false;
    		},


    		// Di dalam file: pos.js -> methods: { ... }
    		async logKeCetak(tipeCetak, teksPreview, infoPrinter) {
    			try {
    				const now = new Date();
    				const dataLog = {
    					tanggal: now.toISOString().slice(0, 10),
    					jam: now.toTimeString().slice(0, 8),
    					tipe: tipeCetak,
    					preview: teksPreview,
    					printer_info: JSON.stringify(infoPrinter),
    					sukses: 0, // Default status adalah 0 (gagal)
    					brand: xbrand,
    					cab: xcab
    				};
    				// 'tambahjson' sekarang harus mengembalikan ID baru
    				const newId = await tambahjson('cetak', dataLog);

    				if (!newId || isNaN(newId)) {
    					throw new Error("Server tidak mengembalikan ID log yang valid.");
    				}
    				return newId; // Kembalikan ID untuk update status nanti
    			} catch (error) {
    				console.error("Gagal menyimpan log cetak:", error);
    				return null; // Kembalikan null jika gagal
    			}
    		},

    		async prosesTutupRegister(closingBalance) {
    			try {
    				this.pesan('Menghitung transaksi & membuat laporan...', 'info');

    				// Panggil generateReport dengan menyertakan saldoAkhir
    				const reportText = await generateReport({
    					registerNomor: this.register.nomor,
    					saldoAkhir: closingBalance
    				});

    				document.getElementById('billDisplay').textContent = reportText;
    				document.getElementById('modalOverlay').style.display = 'flex';

    				// Panggil print_receipt dengan TIPE 3 (Lainnya)
    				this.print_receipt(reportText, 3);

    				// ... (sisa kode Anda untuk update database register) ...
    				const now = new Date();
    				const dataToUpdate = {
    					saldoakhir: closingBalance,
    					jamtutup: now.toTimeString().slice(0, 8),
    					tutup: 1
    				};
					this.register.open=false;
    				rubahjson('register', dataToUpdate, this.register.nomor, 'nomor');

    				this.register.open = false;
    				this.register.nama = '';
    				this.register.nomor = '';
    				localStorage.setItem('register', JSON.stringify(this.register));

    				this.pesan('Register berhasil ditutup.', 'success');



    			} catch (error) {
    				this.pesan(`Terjadi error saat tutup register: ${error.message}`, 'error');
    				console.error(error);
    			}
    		},
    		// Tambahkan metode baru ini juga untuk memanggil laporan
    		async tampilkanDanCetakLaporanHarian(kasirId) {
    			const tgl = new Date().toISOString().slice(0, 10);
    			// Panggil fungsi generateReport dari report.js
    			const reportText = await generateReport({
    				startDate: tgl,
    				endDate: tgl,
    				kasir: kasirId
    			});

    			// Tampilkan di layar
    			document.getElementById('billDisplay').textContent = reportText;
    			document.getElementById('modalOverlay').style.display = 'flex';

    			// Cetak ke printer
    			this.print_receipt(reportText);
    		},

    		prosesBukaRegisterxx(saldoAwal, shift) {
				
    			// ... (kode Anda untuk generate nomor register baru) ...
    			const queryUrutan = `SELECT nomor FROM register WHERE brand='${xbrand}' AND cab='${xcab}' AND nomor LIKE '%-${new Date().getFullYear().toString().slice(-2)}-%' ORDER BY id DESC LIMIT 1`;
    			let registerTerakhirArr = JSON.parse(ambil_select('register', queryUrutan));
    			let nomorUrutBerikutnya = 1;
    			if (registerTerakhirArr.length > 0) {
    				const nomorTerakhir = registerTerakhirArr[0].nomor;
    				const urutanTerakhir = nomorTerakhir.split('-')[3];
    				const angkaUrutan = parseInt(urutanTerakhir.slice(2), 10);
    				nomorUrutBerikutnya = angkaUrutan + 1;
    			}
    			const kodeMesin = (JSON.parse(localStorage.getItem('xpos')) || {}).mesin || 'XX';
    			const nomorBaru = `${xbrand}-${xcab}-${new Date().getFullYear().toString().slice(-2)}-${kodeMesin}${String(nomorUrutBerikutnya).padStart(6, '0')}`;

    			const now = new Date();
    			const dataRegisterBaru = {
    				nomor: nomorBaru,
    				tanggal: now.toISOString().slice(0, 10),
    				jam: now.toTimeString().slice(0, 8),
    				user: this.kuser,
    				saldoawal: saldoAwal,
    				tutup: 0,
    				shift: shift,
    				brand: xbrand,
    				cab: xcab
    			};

    			let hasil = tambahjson('register', dataRegisterBaru);

    			if (hasil && !isNaN(hasil)) {
    				this.register = {
    					open: true,
    					kuser: this.kuser,
    					nama: this.nuser,
    					nomor: nomorBaru,
    					modal: saldoAwal,
    					shift: shift
    				};
    				localStorage.setItem('register', JSON.stringify(this.register));

    				// <<< PEMBARUAN DIMULAI DI SINI >>>
    				// Buat struk buka kasir
    				const width = 42;
    				const formattedModal = new Intl.NumberFormat('id-ID').format(saldoAwal);
    				const printTime = `${now.toLocaleDateString("id-ID")} ${now.toLocaleTimeString("id-ID")}`;

    				let openReceipt = [];
    				openReceipt.push("".padStart(width, '='));
    				openReceipt.push("BUKTI BUKA KASIR".center(width));
    				openReceipt.push("".padStart(width, '='));
    				openReceipt.push(`Nomor   : ${nomorBaru}`);
    				openReceipt.push(`Kasir   : ${this.kuser} - ${this.nuser}`);
    				openReceipt.push(`Shift   : ${shift}`);
    				openReceipt.push(`Waktu   : ${printTime}`);
    				openReceipt.push("".padStart(width, '-'));
    				openReceipt.push(`MODAL AWAL:`.padEnd(20) + formattedModal.padStart(22));
    				openReceipt.push("".padStart(width, '='));
    				openReceipt.push("\n\n");
    				openReceipt.push("KASIR".center(width / 2) + "KOORDINATOR".center(width / 2));
    				openReceipt.push("\n\n\n");
    				openReceipt.push("------------".center(width / 2) + "------------".center(width / 2));

    				// Cetak struk dengan tipe 3 (Lainnya)
    				this.print_receipt(openReceipt.join('\n'), 3);
    				// <<< AKHIR PEMBARUAN >>>

    				this.pesan(`Register berhasil dibuka dengan nomor ${nomorBaru}.`, 'success');
    			} else {
    				this.pesan(`Gagal membuka register: ${hasil}`, 'error');
    			}
    		},
    		async generateCloseRegisterReport(closingBalance) {
    			// Fungsi bantuan untuk format (tetap sama)
    			const padRight = (text, len) => String(text).padEnd(len);
    			const padLeft = (text, len) => String(text).padStart(len);
    			const formatCurrency = (amount) => Math.round(Number(amount)).toLocaleString('id-ID');
    			const width = 42;
    			let report = [];

    			// --- PERBAIKAN DIMULAI DI SINI ---
    			//alert(this.register.nomor);
    			const registerDataJson = ambilakhir('register', 'nomor', '0', '0');

    			// Cek dulu apakah responsnya valid sebelum di-parse
    			if (!registerDataJson || !registerDataJson.startsWith('[')) {
    				throw new Error("Gagal mengambil data sesi register dari database.");
    			}

    			const registerDataArray = JSON.parse(registerDataJson);
    			if (registerDataArray.length === 0) {
    				throw new Error(`Data untuk nomor register ${this.register.nomor} tidak ditemukan.`);
    			}
    			const registerData = registerDataArray[0];
    			// --- AKHIR PERBAIKAN ---

    			// 2. Ambil semua transaksi penjualan untuk sesi register ini
    			const salesQuery = `SELECT * FROM jual WHERE register = '${this.register.nomor}' AND batal != '1'`;
    			const salesData = JSON.parse(await ambil_select('jual', salesQuery));

    			let totalSales = 0,
    				totalRevenue = 0,
    				paymentMap = {};
    			if (salesData.length > 0) {
    				const nomorList = salesData.map(j => `'${j.nomor}'`).join(',');
    				// 3. Ambil rincian pembayaran
    				const paymentQuery = `SELECT * FROM pesani WHERE nomor IN (${nomorList}) AND payment IS NOT NULL AND payment != '' AND payment != '06'`;
    				const paymentData = JSON.parse(await ambil_select('pesani', paymentQuery));

    				totalSales = salesData.reduce((sum, j) => sum + parseFloat(j.ttot || 0), 0);
    				totalRevenue = salesData.reduce((sum, j) => sum + parseFloat(j.jumlah || 0), 0);

    				// Rekapitulasi pembayaran
    				paymentData.forEach(p => {
    					let method = p.edc ? p.edc.toUpperCase() : (p.name ? p.name.toUpperCase() : 'UNKNOWN');
    					if (p.payment === '10') method = 'CASH';
    					if (!paymentMap[method]) paymentMap[method] = {
    						count: 0,
    						amount: 0
    					};
    					paymentMap[method].count++;
    					paymentMap[method].amount += parseFloat(p.harga || 0);
    				});
    			}

    			// 4. Hitung selisih
    			const totalSetoran = parseFloat(paymentMap['CASH']?.amount || 0);
    			const selisih = parseFloat(closingBalance) - (parseFloat(registerData.saldoawal) + totalSetoran);

    			// 5. Buat Teks Laporan (Sama seperti sebelumnya)
    			const now = new Date();
    			report.push("".padStart(width, '='));
    			report.push("CLOSE REGISTER REPORT".center(width));
    			report.push("".padStart(width, '='));
    			report.push(`Kasir    : ${registerData.user} - ${this.register.nama}`);
    			report.push(`Nomor Reg: ${registerData.nomor}`);
    			report.push(`Wkt Buka : ${registerData.jam}`);
    			report.push(`Wkt Tutup: ${now.toLocaleDateString('id-ID')} ${now.toLocaleTimeString('id-ID')}`);
    			report.push("".padStart(width, '-'));
    			report.push(padRight('TOTAL OMSET (REVENUE)', 20) + padLeft(formatCurrency(totalRevenue), 22));
    			report.push("".padStart(width, '-'));
    			report.push("PENERIMAAN KAS:");
    			report.push(padRight('  Saldo Awal', 20) + padLeft(formatCurrency(registerData.saldoawal), 22));
    			report.push(padRight('  Penerimaan Tunai', 20) + padLeft(formatCurrency(totalSetoran), 22));
    			report.push("".padStart(width, '-'));
    			report.push(padRight('  Total di Laci', 20) + padLeft(formatCurrency(parseFloat(registerData.saldoawal) + totalSetoran), 22));
    			report.push(padRight('  Saldo Akhir (Fisik)', 20) + padLeft(formatCurrency(closingBalance), 22));
    			report.push("".padStart(width, '='));
    			report.push(padRight('SELISIH ( +/- )', 20) + padLeft(formatCurrency(selisih), 22));
    			report.push("".padStart(width, '='));

    			return report.join('\n');
    		},

			async print_receipt(billText, printType = 1) {
				
				try {
					// 1. Ambil kode printer kasir dari pengaturan (this.pos)
				
					const receiptPrinterCode = this.pos['receipt_printer_code'] || '04'; // Fallback ke '04' jika tidak ada
					if (!receiptPrinterCode) {
						this.tampilkanPesan('Printer struk belum diatur di POS Settings.', 'error');
						return; // Hentikan jika printer tidak diatur
					}

					// 2. Panggil PrintManager untuk mencetak
					//console.log(`Mencetak via PrintManager (Tipe: ${printType})`);
					const isSuccess = await PrintManager.cetak(billText, receiptPrinterCode, printType);

					// 3. Tangani hasilnya (hanya tampilkan pesan jika gagal)
					if (!isSuccess) {
						this.tampilkanPesan('Gagal mengirim ke printer. Silakan cek status printer atau coba lagi.', 'error');
					}
					// Jika berhasil, tidak ada pesan yang muncul (sesuai permintaan sebelumnya)

				} catch (error) {
				
					// Menangkap error tak terduga dari proses cetak
					console.error("Error tak terduga saat print_receipt:", error);
					this.tampilkanPesan(`Terjadi error pada sistem cetak: ${error.message}`, 'error');
				}
			},

			getHarga(menuItem) {
				const today = new Date();
				today.setHours(0, 0, 0, 0);

				// Ambil harga group dari tipe transaksi aktif

				const hargaGroup = this.currentTransactionType ? this.currentTransactionType.harga_group : 1;

				// Cari aturan harga yang relevan
				const hargaRules = this.harga.filter(h =>
					h.barang === menuItem.kode
				);

				// Cari harga yang aktif berdasarkan periode
				const activeRule = hargaRules.find(rule => {
					const startDate = new Date(rule.tgl_mulai);
					const endDate = new Date(rule.tgl_akhir);
					startDate.setHours(0, 0, 0, 0);
					endDate.setHours(0, 0, 0, 0);
					return today >= startDate && today <= endDate;
				});

				// Jika aturan harga aktif ditemukan
				if (activeRule) {
					//console.log(`Harga khusus ditemukan untuk ${menuItem.kode} dengan grup ${hargaGroup}`);
					const harga = parseFloat(activeRule['harga' + hargaGroup]) || 0;
					const discp = parseFloat(activeRule['diskp' + hargaGroup]) || 0;
					const discr = parseFloat(activeRule['diskr' + hargaGroup]) || 0;
					return {
						harga: harga,
						discp: discp,
						discr: discr
					};
				}

				// Jika tidak ada aturan harga aktif, gunakan harga default
				//console.log(`Harga khusus tidak ditemukan, menggunakan harga default untuk ${menuItem.kode}`);
				return {
					harga: parseFloat(menuItem.price) || 0,
					discp: parseFloat(menuItem.discp) || 0,
					discr: parseFloat(menuItem.discr) || 0
				};
			},

    		// Di dalam file pos.js -> methods: { ... }
    		// GANTI SELURUH FUNGSI INI DI pos.js
    		// Di dalam file pos.js -> ganti seluruh fungsi findAndApplyDiscount() dengan ini

    		findAndApplyDiscount() {
    			// 1. Cari flag/pemicu diskon yang aktif TERLEBIH DAHULU
    			const discountFlag = this.cart.find(item => String(item.payment).trim() == '06');

    			// 2. Hapus item diskon faktur LAMA (yang harga < 0) HANYA JIKA ADA pemicu.
    			// Ini untuk memastikan diskon dihitung ulang dengan benar, tanpa menghapus pemicunya sendiri.
    			const oldDiscountIndex = this.cart.findIndex(item => item.payment === '06' && item.harga < 0);
    			if (oldDiscountIndex > -1) {
    				const oldDiscountId = this.cart[oldDiscountIndex].id;
    				this.cart.splice(oldDiscountIndex, 1);
    				const oldPesantIndex = this.pesant.findIndex(item => item.id === oldDiscountId);
    				if (oldPesantIndex > -1) this.pesant.splice(oldPesantIndex, 1);
    			}

    			// 3. Kosongkan semua diskon per-item (untuk reset)
    			this.cart.forEach(item => {
    				if (!item.payment) {
    					item.discp = 0;
    					item.discr = 0;
    					item.dname = '';
    				}
    			});

    			// 4. Jika tidak ada pemicu diskon sama sekali, hentikan fungsi.
    			if (!discountFlag) return;

    			// 5. Lanjutkan sisa logika seperti sebelumnya untuk menerapkan diskon faktur atau diskon item
    			const kode_disc = discountFlag.kode;
    			const discountRule = this.masterd.find(d => d.kode === kode_disc);
    			if (!discountRule) return;

    			const minPurchase = parseFloat(discountRule.min) || 0;
    			if (minPurchase > 0) {
    				// Logika untuk diskon FAKTUR (yang Anda gunakan)
    				const flagIndex = this.pesant.findIndex(item => item.id === discountFlag.id);
    				if (flagIndex > -1 && this.pesant[flagIndex].harga >= 0) { // Hanya hapus pemicu awal, bukan hasil kalkulasi
    					this.pesant.splice(flagIndex, 1);
    				}

    				const productSubtotal = this.cart.reduce((sum, item) => {
    					return (!item.payment) ? sum + item.jumlah : sum;
    				}, 0);

    				if (productSubtotal >= minPurchase) {
    					const maxDiscount = parseFloat(discountRule.max) || 0;
    					const discp = parseFloat(discountRule.discp) || 0;
    					const potentialDiscount = productSubtotal * (discp / 100);
    					const actualDiscount = (maxDiscount > 0) ? Math.min(potentialDiscount, maxDiscount) : potentialDiscount;

    					if (actualDiscount > 0) {
    						const discountItem = {
    							id: padNumberWithZeros(generateRandomNumber(), 10),
    							kode: discountRule.kode,
    							name: discountRule.nama,
    							quantity: 1,
    							price: -actualDiscount,
    							harga: -actualDiscount,
    							jumlah: -actualDiscount,
    							netto: -actualDiscount,
    							payment: '06',
    							meja: this.currentMeja,
    							user: this.nuser,
    							tglo: getWaktu(),
    							brand: xbrand,
    							cab: xcab,
    							split: '',
    							toppings: [],
    							note: '',
    							cetak: '',
    							disc: 0,
    							discp: 0,
    							discr: 0,
    							serv: 0,
    							ppn: 0,
    							service: 0,
    							pajak: 0
    						};
    						this.pesant.push(discountItem);
    					}
    				}
    			} else {
    				// Logika untuk diskon PER-ITEM (tetap sama)
    				const masterdbMap = new Map(this.masterdb.filter(db => db.masterd === kode_disc).map(db => [db.barang, db.ya]));
    				const masterdsMap = new Map(this.masterds.filter(ds => ds.masterd === kode_disc).map(ds => [ds.submenu, ds.ya]));

    				this.cart.forEach(orderItem => {
    					if (orderItem.payment) return;

    					let isEligible = false;
    					let finalDecisionMade = false;

    					const itemRule = masterdbMap.get(orderItem.kode);
    					if (itemRule !== undefined) {
    						if (discountRule.kecuali_Item === '0') {
    							if (itemRule === '1') isEligible = true;
    						} else {
    							if (itemRule !== '1') isEligible = true;
    						}
    						finalDecisionMade = true;
    					}

    					if (!finalDecisionMade) {
    						const groupRule = masterdsMap.get(orderItem.kgroup);
    						if (groupRule !== undefined) {
    							if (discountRule.kecuali_group === '0') {
    								if (groupRule === '1') isEligible = true;
    							} else {
    								if (groupRule !== '1') isEligible = true;
    							}
    						} else {
    							if (discountRule.kecuali_Item === '1' || discountRule.kecuali_group === '1') {
    								isEligible = true;
    							} else if (discountRule.kecuali_Item === '0' || discountRule.kecuali_group === '0') {
    								isEligible = false;
    							}
    						}
    					}

    					if (isEligible) {
    						const discpValue = parseFloat(discountRule.discp) || 0;
    						const discrValue = parseFloat(discountRule.discr) || 0;
    						if (discpValue > 0) {
    							orderItem.discp = discpValue;
    							orderItem.discr = 0;
    						} else if (discrValue > 0) {
    							orderItem.discp = 0;
    							orderItem.discr = discrValue;
    						}
    						orderItem.dname = discountRule.nama;
    					}
    				});
    			}
    		},

    		tampilkanPesan(message, type, callback = null) {
    			this.p_pesan_modal = message;
    			this.p_tipe_modal = type;
    			this.p_tampilkan_modal = true;
    			this.p_confirmCallback = callback;
    		},
    		p_closeModal() {
    			this.p_tampilkan_modal = false;
    			this.p_confirmCallback = null;
    		},
    		p_handleConfirm(value) {
    			if (this.p_confirmCallback) {
    				this.p_confirmCallback(value);
    			}
    			this.p_closeModal();
    		},
    		pesan(message, type) {
    			this.tampilkanPesan(message, type)
    		},

    		loadSettings() {
				this.users = JSON.parse(ambil('users', 'kode', '', 'z'));
				//js(this.users);
    			this.masterd = JSON.parse(xambil('masterd', 'kode', '', 'z'));
    			this.masterdb = JSON.parse(xambil('masterdb', 'masterd', '', 'z'));
    			this.masterds = JSON.parse(xambil('masterds', 'masterd', '', 'z'));
				this.botor = JSON.parse(xambil('botor', 'g_user', '', 'z')); 
    			this.harga = JSON.parse(xambil('harga', 'barang', '', 'zz')); // Tambahkan baris ini
				
    			this.tipeTransaksi = JSON.parse(xambil('tipe_transaksi', 'kode', '', 'z')); // Tambahkan ini

    			this.cabang = JSON.parse(xambil('cabang', 'kode', '', 'z'));
    			const selectedCabang = this.cabang.find(branch => branch.kode === xcab);
    			this.ncab = selectedCabang ? `${selectedCabang.kode} (${selectedCabang.nama})` : xcab;

    			this.outlet = this.cabang.find(d => d.kode === xcab);


    			//this.masterd = JSON.parse(ambil('masterd', 'kode', '', 'z'));
    			// this.gd = JSON.parse(ambil('gdisc', 'kode', '', 'z'));

    		},



    		generateObject() {
    			this.result = {};
    			this.masterd.forEach(m => {
    				this.result[m.kode] = m;
    				this.masterd.forEach(d => {
    					if (m.kode === d.kode) {
    						this.result[m.kode][d.barang] = d.yn;
    					}
    				});
    			});


    			this.gdisc = {};
    			this.masterd.forEach(m => {
    				this.gdisc[m.kode] = {
    					"kode": m.kode
    				};
    				this.gd.forEach(d => {
    					if (m.kode === d.kode) {
    						this.gdisc[m.kode][d.groupd] = d.yn;
    					}
    				});
    			});

    			// this.gdisc = {};
    			// this.masterd.forEach(m => {
    			//     this.gdisc[m.kode] = {"kode":m.kode} ;
    			//     this.gd.forEach(d => {
    			//         if (m.kode === d.kode) {
    			//             this.gdisc[m.kode][d.groupd] = d.yn;
    			//         }
    			//     });
    			// });
    		},
    		xfindPayment() {

    			found = this.pesant.find(item => item.payment === '06');

    			if (found) {
    				kode_disc = found.kode;
    				decr = this.result[kode_disc];

    				// --- TAMBAHKAN PENGECEKAN INI ---
    				if (!decr) {
    					console.error(`Aturan diskon untuk kode '${kode_disc}' tidak ditemukan di 'this.result'. Proses diskon dibatalkan.`);
    					// Hentikan fungsi agar tidak error
    					return;
    				}
    				// --- AKHIR PENAMBAHAN ---

    				const today = new Date();
    				const dayOfWeek = today.getDay(); // 0 for Sunday, 1 for Monday, ..., 6 for Saturday
    				const currentHour = today.getHours();
    				this.pesant.forEach(item => {
    					const isValidDate = (!decr.dt || new Date(decr.dt) <= today) && (!decr.st || new Date(decr.st) >= today);
    					const isValidDay = decr[`h${dayOfWeek}`] === "1";
    					const isValidHour = decr[`j${currentHour}`] === "1";
    					

    					if (isValidDate && isValidDay && isValidHour) {
    						if (decr.kecuali_Item === '0' || decr.kecuali_Item === "") {
    							if (this.result[kode_disc][item.kode] == 1) {
    								
    								item.discp = decr.discp;
    								item.discr = decr.discr;
    								item.dname = decr.nama;
    							}
    						} else if (decr.kecuali_Item === "1" && decr[item.kode] !== "1") {
    							item.discp = decr.discp;
    							item.discr = decr.discr;
    							item.dname = decr.nama;
    						};

    						if (decr.kecuali_group == "0" || decr.kecuali_group == "") {
    							
    							if (this.gdisc[kode_disc][item.kgroup] == 1) {
    								
    								item.discp = decr.discp;
    								item.discr = decr.discr;
    								item.dname = decr.nama;
    							}
    						} else if (decr.kecuali_group === "1" && decr[item.kgroup] !== "1") {
    							item.discp = decr.discp;
    							item.discr = decr.discr;
    							item.dname = decr.nama;
    						}


    					};

    				});

    				
    			} else {
    				this.pesant.forEach(item => {
    					item.discp = 0;
    					item.discr = 0;
    					item.dname = '';
    				});

    				
    			}
    		},


    		baca_set() {

    			bx = ambil('pos', 'kode', '', 'zz');
    			bx = JSON.parse(bx);
    			this.pos = {};
    			bx.forEach(item => {
    				this.pos[item.kode] = item.isi;
    			});

    			this.pos.pajak = parseFloat(this.pos.pajak);
    			this.pos.service = parseFloat(this.pos.service);
				alamat_kirim=this.pos.url_server_pusat;
    		},

    		baca_bhs() {
    			let bx = xambil('bahasa', 'original', '', 'zz');
    			bx = JSON.parse(bx);
    			this.bh = {};
    			bx.forEach(item => {
    				this.bh[item.kunci] = {
    					"ind": item.ind,
    					"jpn": item.jpn,
    					"chn": item.chn,
    					"arb": item.arb,
    					"eng": item.eng
    				};
    			});
    			// ee=JSON.stringify(this.bahasa);
    			
    			// localStorage.setItem("bahasa", ee);
    			
    		},


    		toggleVisibility() {
    			if (!this.isVisible) {
    				this.move = 'Select a table to move the menu items.';
    				this.Map_table();
    			}
    		},



    		save_ok() {

    			this.pesanp.forEach((item) => {
    				item.meja = this.mejakanan; // Ganti semua item.meja dengan nilai dari this.mejakanan
    			});

    			this.pesant.forEach((item) => {
    				item.meja = this.mejakiri; // Ganti semua item.meja dengan nilai dari this.mejakanan
    			});

    			ss = {};
    			ss.cart = JSON.stringify(this.pesant);
    			bx = rubahjson('cart', ss, this.mejakiri, 'meja');


    			bx = ambil('cart', 'meja', this.mejakanan);
    			if (bx == '[]' || bx == '') {
    				tm = {};
    				tm.meja = this.mejakanan;
    				tm.cart = '';
    				tm.cab = xcab;
    				tm.brand = xbrand;
    				cc = tambahjson('cart', tm);
    			};
    			ss.cart = JSON.stringify(this.pesanp);
    			bx = rubahjson('cart', ss, this.mejakanan, 'meja');


    			a = this.cartSubtotal;
    			this.isVisible = false;

    		},
    		cancel_ok(halo) {
    			this.pesant = this.backkiri;
    			this.isVisible = false;
    		},
    		showx() {
    			this.items = this.pesant;
    			this.showSplit = !this.showSplit;
    			
    		},



    		selectItem(index, grid) {
    			if (grid === 'left') {
    				this.selectedLeft = index;
    				this.selectedRight = null;
    			} else {
    				this.selectedRight = index;
    				this.selectedLeft = null;
    			}
    		},
    		moveRightOne() {
    			if (this.selectedLeft !== null && this.pesant[this.selectedLeft].quantity > 0) {
    				const itemToMove = this.pesant[this.selectedLeft];
    				itemToMove.quantity--;
    				const existingItem = this.pesanp.find(item => item.id === itemToMove.id);
    				if (existingItem) {
    					existingItem.quantity++;
    				} else {
    					this.pesanp.push({
    						...itemToMove
    					});
    					this.pesanp[this.pesanp.length - 1].quantity = 1;
    				}
    				if (itemToMove.quantity === 0) {
    					this.pesant.splice(this.selectedLeft, 1);
    				}
    				this.selectedLeft = null;
    			}
    		},
    		moveRightItem() {
    			if (this.selectedLeft !== null) {
    				const itemToMove = this.pesant[this.selectedLeft];
    				const existingItem = this.pesanp.find(item => item.id === itemToMove.id);
    				if (existingItem) {
    					existingItem.quantity += itemToMove.quantity;
    				} else {
    					this.pesanp.push({
    						...itemToMove
    					});
    				}
    				this.pesant.splice(this.selectedLeft, 1);
    				this.selectedLeft = null;
    			}
    		},
    		moveRightAll() {
    			for (let i = this.pesant.length - 1; i >= 0; i--) {
    				const itemToMove = this.pesant[i];
    				const existingItem = this.pesanp.find(item => item.id === itemToMove.id);
    				if (existingItem) {
    					existingItem.quantity += itemToMove.quantity;
    				} else {
    					this.pesanp.push({
    						...itemToMove
    					});
    				}
    				this.pesant.splice(i, 1);
    			}
    		},
    		moveLeftOne() {
    			if (this.selectedRight !== null && this.pesanp[this.selectedRight].quantity > 0) {
    				const itemToMove = this.pesanp[this.selectedRight];
    				itemToMove.quantity--;
    				const existingItem = this.pesant.find(item => item.id === itemToMove.id);
    				if (existingItem) {
    					existingItem.quantity++;
    				} else {
    					this.pesant.push({
    						...itemToMove
    					});
    					this.pesant[this.pesant.length - 1].quantity = 1;
    				}
    				if (itemToMove.quantity === 0) {
    					this.pesanp.splice(this.selectedRight, 1);
    				}
    				this.selectedRight = null;
    			}
    		},
    		moveLeftItem() {
    			if (this.selectedRight !== null) {
    				const itemToMove = this.pesanp[this.selectedRight];
    				const existingItem = this.pesant.find(item => item.id === itemToMove.id);
    				if (existingItem) {
    					existingItem.quantity += itemToMove.quantity;
    				} else {
    					this.pesant.push({
    						...itemToMove
    					});
    				}
    				this.pesanp.splice(this.selectedRight, 1);
    				this.selectedRight = null;
    			}
    		},
    		moveLeftAll() {
    			for (let i = this.pesanp.length - 1; i >= 0; i--) {
    				const itemToMove = this.pesanp[i];
    				const existingItem = this.pesant.find(item => item.id === itemToMove.id);
    				if (existingItem) {
    					existingItem.quantity += itemToMove.quantity;
    				} else {
    					this.pesant.push({
    						...itemToMove
    					});
    				}
    				this.pesanp.splice(i, 1);
    			}
    		},












    		tot(cc) {
    			fff = this.meja.filter(mejas => mejas.kode === cc);
    			return fff[0].jumlah;
    		},

			async login() {
				// Validasi input
				if (!this.inputValue1) {
					document.getElementById("userlog")?.click(); // Optional chaining untuk mencegah error
					return;
				}
				if (this.inputValue1 && !this.inputValue2 ) {
					document.getElementById("passlog")?.click(); // Optional chaining untuk mencegah error
					return;
				}


				if (!this.inputValue1 || !this.inputValue2) {

					document.getElementById("passlog")?.click(); // Optional chaining untuk mencegah error
					return;
				}

				const username = this.inputValue1;
				const password = this.inputValue2;
				try {


					// Ambil data pengguna
					//let bx = xambil('users', 'username', username, username);
					//bx = JSON.parse(bx);
					let bx = this.users.filter(user => user.username === username);


					// Periksa apakah data pengguna ditemukan
					if (!bx || !bx[0]) {
						this.pesan('Login gagal, pengguna tidak ditemukan...', 'Login');
						this.inputValue1 = '';
						this.inputValue2 = '';
						document.getElementById("userlog")?.click();
						return;
					}
					const user = bx[0];

					// Verifikasi password (catatan: password harus di-hash di dunia nyata)
					if (user.password === password) {
						this.nuser = user.nama;
						this.kuser = user.kode;
						localStorage.setItem("bepos", username);

						// Panggil fungsi lain
						//alert(this.bacatulis);

						//bacamaster();

						// -- AWAL PERUBAIKAN --
						// Muat status register dari database setelah login berhasil
						await this.loadOpenRegisterSession();
						// -- AKHIR PERBAIKAN --

						this.Map_table();
                        //toggleFullscreen();
						// Sembunyikan overlay login
						const overlogin = document.getElementById("overlogin");
						if (overlogin) {
							overlogin.style.display = "none";
						}
					} else {
						alert('Login gagal, password salah');
						this.inputValue1 = '';
						this.inputValue2 = '';
						document.getElementById("userlog")?.click();
					}
				} catch (error) {
					console.error("Error saat login:", error);
					alert('Terjadi kesalahan saat login, silakan coba lagi');
					this.inputValue1 = '';
					this.inputValue2 = '';
					document.getElementById("userlog")?.click();
				}
			},

    		selectInput(input) {
    			this.ipilih = input.toString();
    		},

    		mlogin(ip, xx) {
    			if (xx <= '9') {
    				if (ip == 1) {
    					this.inputValue1 += xx
    				} else {
    					this.inputValue2 += xx
    				}
    			};
    			if (xx == 'C') {
    				if (ip == 1) {
    					this.inputValue1 = ''
    				} else {
    					this.inputValue2 = ''
    				}
    			};

    			if (xx == 'Back') {
    				if (ip == 1) {
    					this.inputValue1 = this.inputValue1.slice(0, -1);
    				} else {
    					this.inputValue2 = this.inputValue2.slice(0, -1);
    				}
    			};
    			if (xx == 'Cancel') {
    				this.overadmin = false;
    			};
    		},

    		// File: pos.js

    		// GANTI SELURUH FUNGSI updatecart2() DENGAN VERSI BARU INI

    		// File: pos.js

    		// GANTI SELURUH FUNGSI updatecart2() DENGAN VERSI BARU INI
    		// GANTI SELURUH FUNGSI INI DI pos.js

 // File: pos.js -> methods -> updatecart2()

    updatecart2() {
        // PERBAIKAN UTAMA: Panggil computed property di sini untuk MEMAKSA 
        // kalkulasi ulang nilai total (xsubtotal, xgrandtotal, dll.)
        const triggerRecalculation = this.cartSubtotal; 
        
        // 1. Lakukan semua pembaruan UI LOKAL secara instan agar UI tidak terasa lambat.
        const sp = this.pesant.some(item => item.split && item.split.trim() !== '') ? '1' : '';
        if (this.mejao) {
            this.mejao.split = sp;
            const mejaIndex = this.meja.findIndex(m => m.id === this.mejao.id);
            if (mejaIndex !== -1) {
                if (this.cart.length === 0) {
                    this.mejao.jumlah = 0;
                    this.mejao.cover = 0;
                    this.mejao.guest = '';
                }
                this.meja[mejaIndex] = { ...this.meja[mejaIndex], ...this.mejao };
            }
        }
        
        // Pastikan kalkulasi selesai sebelum mengirim ke secondDisplay
        // Kita gunakan $nextTick untuk memastikan semua side effects dari computed property 
        // (yaitu, update this.xgrandtotal) sudah selesai.
        this.$nextTick(() => {
            try {
                const payloadData = {
                    meja: this.mejao.nama || 'Take Away',
                    cart: this.cart,
                    totals: {
                        subtotal: this.xsubtotal,
                        totalDiscount: this.xtdisc + this.xtdiscf,
                        diskonFaktur: this.xtdiscf, // ✨ BARU: Kirim diskon faktur
                        service: this.xtservice,
                        tax: this.xtpajak,
                        grandTotal: this.xgrandtotal,
                        payment: this.xpayment,
                        change: this.xkembali
                    }
                };
                const secondDisplayData = { command: 'update', payload: payloadData };
                localStorage.setItem('secondDisplay', JSON.stringify(secondDisplayData));
				
				
				// alert(JSON.stringify(secondDisplayData));
                // alert(JSON.stringify(secondDisplayData)); 
            } catch (error) {
                console.error('Gagal mengirim data ke Second Display:', error);
            }
        });

        // 2. Terapkan logika Debouncing untuk menyimpan ke server.
        clearTimeout(this.updateTimeout); // Hapus timer sebelumnya (jika ada)

        this.updateTimeout = setTimeout(() => {
            this._performServerUpdate(); // Panggil fungsi yang akan menyimpan ke server
        }, 500); // Jeda 0.5 detik (saya ubah dari 5000 ke 500ms agar lebih responsif)
    },

    async _performServerUpdate() {
        //console.log("Menyimpan data terbaru ke server setelah jeda...");
        try {
            const allItemsForThisTable = this.pesant.filter(item => item.meja === this.currentMeja);
            const dataToSave = {
                meja: this.currentMeja,
                cart: JSON.stringify(allItemsForThisTable).replace(/:null/g, ':""'),
                brand: xbrand,
                cab: xcab
            };

            await rubahjson('meja', this.mejao, this.mejao.id);
            const cartExists = await ambil('cart', 'meja', this.currentMeja);

            if (cartExists && cartExists !== '[]') {
                await rubahjson('cart', dataToSave, dataToSave.meja, 'meja');
            } else {
                await tambahjson('cart', dataToSave);
            }
            //console.log("Penyimpanan ke server berhasil.");
        } catch (error) {
            console.error("Gagal menyimpan data ke server:", error);
            this.pesan('Gagal menyimpan otomatis. Cek koneksi Anda.', 'error');
        }
    },

    		updatecart() {

    			ss = this.currentMejas[this.activeKotakIndex];
    			bx = rubahjson('meja', ss, ss.id);
    			bbb = JSON.stringify(vm.meja);
    			localStorage.setItem('meja', bbb);

    			xmeja = this.meja;
    			filteredData = this.cart;

    			var xhr = new XMLHttpRequest();
    			xhr.open("POST", "updatecart.php", true);
    			xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
    			xhr.onreadystatechange = function() {
    				if (xhr.readyState === XMLHttpRequest.DONE) {
    					if (xhr.status === 200) {
    						alert("Data berhasil disimpan ke tabel cart.");
    					} else {
    						alert("Gagal menyimpan data ke tabel cart.");
    					}
    				}
    			};
    			xhr.send(JSON.stringify(filteredData));
    		},

    		// bayar_cash() {
    		//   const index = this.cart.findIndex(item => item.payment === '1' && item.edc === 'Cash');
    		//   if (index !== -1) {
    		//     this.cart[index].harga = parseFloat(this.cart[index].harga) + Number(cx);
    		//   } else {
    		//     this.newItem.id = padNumberWithZeros(generateRandomNumber(), 10);
    		//     this.newItem.harga = Number(cx);
    		//     this.newItem.nomor = this.nomor;
    		//     this.newItem.meja = this.currentMeja;
    		//     this.newItem.payment = '1';
    		//     this.newItem.edc = 'Cash';
    		//     this.newItem.nocard = '';
    		//     this.newItem.name = 'Cash';
    		//     this.newItem.quantity = 1;

    		//     this.pesant.push(this.newItem);

    		//     this.currentcart = this.cart.length - this.item_bayar - 1;
    		//     this.cart.sort((a, b) => {
    		//       return a.payment.localeCompare(b.payment);
    		//     });
    		//   };  
    		//   insert_jual();
    		// },

			bayar_edc() {

				const index = this.cart.findIndex(item => item.payment === '10' && item.edc === 'CASH');
				if (index !== -1 && this.edc == 'CASH') {
					this.cart[index].harga = parseFloat(this.cart[index].harga) + Number(this.inputValue);
					this.cart[index].split = this.activeSplitFilter;
				} else {
					this.newItem = {};
					this.newItem.id = padNumberWithZeros(generateRandomNumber(), 10);
					this.newItem.harga = Number(this.inputValue);
					this.newItem.jumlah = Number(this.inputValue);
					this.newItem.nomor = this.nomor;
					this.newItem.meja = this.currentMeja;
					this.newItem.payment = this.edc == 'CASH' ? '10' : '12';
					this.newItem.edc = this.edc;
					this.newItem.nocard = '';
					this.newItem.name = this.edc;
					this.newItem.quantity = 1;
					this.newItem.discp = 0;
					this.newItem.discr = 0;
					this.newItem.tglo = getWaktu();
					this.newItem.brand = xbrand;
					this.newItem.cab = xcab;
					this.newItem.user = this.nuser;
					this.newItem.split = this.activeSplitFilter;

					// Tambahkan inisialisasi properti yang diperlukan untuk pembayaran
					this.newItem.serv = 0;
					this.newItem.ppn = 0;
					this.newItem.service = 0;
					this.newItem.pajak = 0;
					this.newItem.netto = this.newItem.harga;
					this.newItem.disc = 0;
					this.newItem.jumlah = this.newItem.harga;

					this.pesant.push(this.newItem);
				}
				this.currentcart = this.cart.length - this.item_bayar - 1;

				// Sortir cart berdasarkan payment
				this.cart.sort((a, b) => {
					const paymentA = a.payment || '';
					const paymentB = b.payment || '';
					return paymentA.localeCompare(paymentB);
				});

				a = this.cartSubtotal;
				this.ya = 2;
				this.updatecart2();

				try {
					const paymentDisplayData = {
						command: 'showPayment',
						payload: {
							meja: this.mejao.nama || 'Take Away',
							cart: this.cart,
							totals: {
								subtotal: this.xsubtotal,
								totalDiscount: this.xtdisc + this.xtdiscf,
								service: this.xtservice,
								tax: this.xtpajak,
								grandTotal: this.xgrandtotal,
								payment: this.xpayment,
								change: this.xkembali
							}
						}
					};
					localStorage.setItem('secondDisplay', JSON.stringify(paymentDisplayData));
					
				} catch (error) {
					console.error('Gagal mengirim perintah showPayment:', error);
				}

				if (this.xkembali >= 0 && this.cartSubtotal > 0) {
					this.xfungsi('tutup_bayar_otomatis');
				}

				insert_jual();

			},
            
			async xfungsi(xpil, isAuthorized = false) {


				

            if (!isAuthorized) {
                // Gabungkan semua kemungkinan sumber fungsi untuk pencarian
                const allFungsi = [...this.fungsi, ...this.fungsi2, ...this.fungsi3, ...this.fungsim];
                const clickedButton = allFungsi.find(f => f.fungsi === xpil);

                // Cek apakah tombol ditemukan dan memiliki kode otorisasi
                if (clickedButton && clickedButton.otor && clickedButton.otor.trim() !== '') {
                    
                    // Simpan data yang dibutuhkan untuk proses otorisasi
                    this.requiredOtor = clickedButton.otor;
                    this.functionToExecuteAfterOtor = xpil;
                    this.jenisdelete = 'Otorisasi untuk: ' + (clickedButton[this.bhs] || clickedButton.nama);

                    // Tampilkan jendela login
                    this.inputValue1 = '';
                    this.inputValue2 = '';
                    this.overadmin = true;
                    document.getElementById("userlog")?.click();
                    
                    // Hentikan eksekusi fungsi asli untuk sementara
                    return; 
                }
            };				

				if (['table', 'logout', 'lepas_meja', 'change_table'].includes(xpil)) {
					if (this.updateTimeout) {
						//console.log("Ada update tertunda, menyimpan paksa sebelum navigasi...");
						clearTimeout(this.updateTimeout); // Batalkan timer yang dijadwalkan
						this.updateTimeout = null; // Bersihkan ID timer
						await this._performServerUpdate(); // Jalankan dan TUNGGU simpan selesai
					}
				}

				if (xpil.startsWith('open_link:')) {
					const url = xpil.split(':')[1];
					window.open(url, '_blank');
					return; // Hentikan eksekusi agar tidak masuk ke switch
				}


    			let splitResult = xpil.split(':');
    			let pil = splitResult[0];
    			this.edc = splitResult[1];
    			this.tipe_bayar = pil;
    			this.showPopup = false;
    			this.showPopupm = false;



				switch (pil) {
					case 'bo_cab':
					        this.showKioskModal = true;
        this.kioskSearchTerm = '';
        this.fetchKioskTransactions();
        break;	

					case 'ajust':
						// Pastikan tidak ada transaksi aktif sebelum memulai mode adjust
						if (this.cart.length > 0) {
							this.pesan('Selesaikan atau batalkan transaksi saat ini terlebih dahulu sebelum melakukan penyesuaian.', 'error');
							return;
						}
						this.jenisdelete = 'Otorisasi Penyesuaian Transaksi'; // Teks untuk modal otorisasi
						this.afterAuthAction = 'startAdjust'; // Aksi yang akan dijalankan setelah login berhasil
						this.inputValue1 = '';
						this.inputValue2 = '';
						// this.overadmin = true; // Tampilkan modal login admin
						// document.getElementById("userlog")?.click();

                this.overadmin = false;
                this.fetchAdjustableTransactions();
				
				
						break;					

					case 'tutup_bayar_otomatis':
						// Hanya tampilkan modal konfirmasi jika pembayaran sudah lunas (kembalian >= 0)
						if (this.xkembali >= 0 && this.cartSubtotal > 0) {
							// --- BARU: KIRIM SINYAL showPayment KE CUSTOMER DISPLAY ---
							try {
								const paymentDisplayData = {
									command: 'showPayment',
									payload: {
										meja: this.mejao.nama || 'Take Away',
										cart: this.cart,
										totals: {
											subtotal: this.xsubtotal,
											totalDiscount: this.xtdisc + this.xtdiscf,
											diskonFaktur: this.xtdiscf,
											service: this.xtservice,
											tax: this.xtpajak,
											grandTotal: this.xgrandtotal,
											payment: this.xpayment,
											change: this.xkembali
										}
									}
								};
								localStorage.setItem('secondDisplay', JSON.stringify(paymentDisplayData));
								// alert(JSON.stringify(paymentDisplayData));
							} catch (error) {
								console.error('Gagal mengirim perintah showPayment:', error);
							}
							// --- AKHIR BARU ---

							this.shoconfbayar = true; // Menampilkan modal konfirmasi pembayaran di POS
							// Mengisi nomor jual yang sementara
							const data = ambilakhir('jual', 'nomor', '', '');
							this.no_jual = gennomor(data === '[]' ? '' : JSON.parse(data)[0].nomor);
						}
						break;


    				case 'refresh_master':
    					js('Memperbarui data master...', 'info');

    					// Baca semua tabel master
    					this.loadSettings();
    					this.baca_bhs();
    					this.bacatoping();
    					bacameja();
    					bacapayment();
    					bacacart();

    					const fungsix = JSON.parse( xambil('fungsi2', 'kode', '', 'zz'));
    					this.fungsi2 = fungsix.filter(item => item.kelas == '1');
    					this.fungsi3 = fungsix.filter(item => item.kelas == '2');
    					this.fungsim = fungsix.filter(item => item.kelas == '3');
    					this.menus = JSON.parse(xambil('menus', 'kode', '', 'zz'));
    					this.menuGroups = JSON.parse(xambil('menugroups', 'kode', '', 'zz'));
    					this.menuTops = JSON.parse(xambil('menutops', 'kode', '', 'zz'));
    					this.menus = this.gabung;

    					// Simpan ke localStorage
    					const gb = {
    						"lantai": this.lantai,
    						"fungsi": this.fungsi,
    						"fungsi2": this.fungsi2,
    						"condiment": this.condiment,
    						"menutops": this.menuTops,
    						"meja": this.meja,
    						"menugroups": this.menuGroups,
    						"menus": this.menus
    					};
    					localStorage.setItem('gb', JSON.stringify(gb));

    					js('Data master berhasil diperbarui!', 'success');
    					break;

    				case 'subtot':
						
      	  			    this.cetakStruk();

    					
    					// document.getElementById('reportFrame').src = '../bo_pos/index.html';
    					// document.getElementById('reportModal').style.display = 'flex';
    					break;

    					// --- AKHIR BLOK TAMBAHAN ---  open_link:second.htm      open_link:bener/bo_pos/index.html open_link:bener/pos2/kds/kds.html
    				case 'newfungsi':
    					this.kb_for = 4; // Gunakan '4' sebagai mode "Tambah Fungsi Baru"
    					this.inputV[1] = ''; // Kosongkan input label
    					this.inputV[2] = ''; // Kosongkan input fungsi
    					this.activeInput = 1; // Fokus ke input pertama
    					this.showModalAngkakb = true; // Tampilkan modal keyboard
    					break;
    case 'kios':
		
        this.showKioskModal = true;
        this.kioskSearchTerm = '';
        this.fetchKioskTransactions();
        break;

    				case 'show_total':
    					try {
    						const secondDisplayData = {
    							command: 'showTotals', // Perintah spesifik
    							payload: { // Payload tetap dikirim untuk jaga-jaga
    								meja: this.mejao.nama || 'Take Away',
    								cart: this.cart,
    								totals: {
    									subtotal: this.xsubtotal,
    									totalDiscount: this.xtdisc + this.xtdiscf,
    									service: this.xtservice,
    									tax: this.xtpajak,
    									grandTotal: this.xgrandtotal,
    								}
    							}
    						};
							
    						localStorage.setItem('secondDisplay', JSON.stringify(secondDisplayData));
							// alert(11);
    					} catch (error) {
    						console.error('Gagal mengirim perintah show_total:', error);
    					}
    					break;


    				case 'quit':
    					alert('quit');
    					break;
    				case 'rubah_sandi':
    					document.getElementById('passwordFrame').src = 'rubah_sandi.html';
    					document.getElementById('passwordModal').style.display = 'flex';
    					break;
   case 'reprint': { // Add opening brace
        const reprintUrl = 'reprint.html'; // Nama file HTML baru Anda
        const reportFrame = document.getElementById('reportFrame');
        const reportModal = document.getElementById('reportModal');
        if (reportFrame && reportModal) {
            reportFrame.src = reprintUrl;
            reportModal.style.display = 'flex';
        } else {
            this.pesan('Komponen modal tidak ditemukan.', 'error');
        }
        break;
    } 
	
	   case 'backup': { // Add opening brace
        const reprintUrl = 'backup.html'; // Nama file HTML baru Anda
        const reportFrame = document.getElementById('reportFrame');
        const reportModal = document.getElementById('reportModal');
        if (reportFrame && reportModal) {
            reportFrame.src = reprintUrl;
            reportModal.style.display = 'flex';
        } else {
            this.pesan('Komponen modal tidak ditemukan.', 'error');
        }
        break;
	}
	// Add closing brace
    				case 'open_drawer':
    					try {
    						// 1. Perintah standar ESC/POS untuk membuka laci kasir
    						// Ini adalah string karakter khusus, bukan teks biasa.
    						const openDrawerCommand = '\x1b\x70\x00\x19\xfa';

    						this.pesan('Mengirim perintah buka drawer...', 'info');

    						// 2. Panggil fungsi cetak struk yang sudah ada,
    						//    tapi dengan "teks" berisi perintah khusus tadi.
    						this.print_receipt(openDrawerCommand);

    					} catch (error) {
    						this.pesan(`❌ Gagal membuka drawer: ${error.message}`, 'error');
    						console.error(error);
    					}

    				case 'ambil_data_master':
    					// Pastikan fungsi ini dijalankan sebagai async
    					(async () => {
    						// 1. Dapatkan URL dari setingan 'pos' yang sudah dimuat
    						const serverUrl = this.pos.url_sync_server;

    						if (!serverUrl) {
    							this.pesan('URL server sinkronisasi belum diatur di tabel `pos` (kode: url_sync_server).', 'error');
    							return;
    						}

    						// URL untuk skrip PHP di server lokal yang akan menyimpan data
    						const localSaveUrl = 'simpan_master_lokal.php';

    						this.pesan('Memulai sinkronisasi data master...', 'info');

    						// 2. Daftar tabel master yang akan disinkronisasi
    						// const tablesToSync = [
    						//     { name: 'mahasiswa', filter: 'brand_cab' },
    						//     { name: 'lantai', filter: 'brand_cab' },
    						//     { name: 'cabang', filter: 'brand_cab' }
    						// ];


    						const tablesToSync = [{
    								name: 'pos',
    								filter: 'brand_cab'
    							},
    							{
    								name: 'users',
    								filter: 'brand_cab'
    							},
    							{
    								name: 'cabang',
    								filter: 'brand_cab'
    							},
    							{
    								name: 'kitchen',
    								filter: 'brand_cab'
    							},
    							{
    								name: 'lantai',
    								filter: 'brand_cab'
    							},
    							{
    								name: 'meja',
    								filter: 'brand_cab'
    							},
    							{
    								name: 'payment',
    								filter: 'brand_cab'
    							},
    							{
    								name: 'fungsi',
    								filter: 'brand'
    							},
    							{
    								name: 'fungsi2',
    								filter: 'brand_cab'
    							},
    							{
    								name: 'menus',
    								filter: 'brand'
    							},
    							{
    								name: 'menutops',
    								filter: 'brand_cab'
    							},
    							{
    								name: 'menugroups',
    								filter: 'brand'
    							},
    							{
    								name: 'harga',
    								filter: 'brand'
    							},
    							{
    								name: 'toppings',
    								filter: 'brand'
    							},
    							{
    								name: 'topping_items',
    								filter: 'brand'
    							},
    							{
    								name: 'btoppings',
    								filter: 'brand'
    							},
    							{
    								name: 'condiment',
    								filter: 'brand'
    							},
    							{
    								name: 'masterd',
    								filter: 'brand'
    							},
    							{
    								name: 'masterdb',
    								filter: 'brand'
    							},
    							{
    								name: 'masterds',
    								filter: 'brand'
    							},
    							{
    								name: 'bcab',
    								filter: 'brand'
    							},
    							{
    								name: 'botor',
    								filter: 'brand'
    							},
    							{
    								name: 'bprinter',
    								filter: 'brand_cab'
    							},
    							{
    								name: 'g_user',
    								filter: 'brand'
    							},
    							{
    								name: 'node',
    								filter: 'brand_cab'
    							},
    							{
    								name: 'otor',
    								filter: 'brand'
    							}
    						];

    						// 3. Looping untuk mengambil dan menyimpan data per tabel
    						for (const table of tablesToSync) {
    							try {
    								// Membuat URL dinamis berdasarkan filter
    								let requestUrl = `${serverUrl}?file=${table.name}`;
    								if (table.filter === 'brand' || table.filter === 'brand_cab') {
    									requestUrl += `&brand=${xbrand}`;
    								}
    								if (table.filter === 'brand_cab') {
    									requestUrl += `&cab=${xcab}`;
    								}

    								this.pesan(`Mengambil data: ${table.name}...`);

    								// 4. Ambil data dari server cloud
    								const cloudResponse = await fetch(requestUrl);
    								if (!cloudResponse.ok) throw new Error(`Gagal mengambil data dari cloud (HTTP ${cloudResponse.status})`);
    								const data = await cloudResponse.json();

    								// 5. Kirim data ke skrip PHP lokal untuk disimpan
    								const localResponse = await fetch(localSaveUrl, {
    									method: 'POST',
    									headers: {
    										'Content-Type': 'application/json'
    									},
    									body: JSON.stringify({
    										table: table.name,
    										data: data
    									})
    								});

    								if (!localResponse.ok) throw new Error(`Server lokal error (HTTP ${localResponse.status})`);
    								const saveResult = await localResponse.json();

    								if (!saveResult.success) throw new Error(saveResult.error);

    								this.pesan(`✅ Data ${table.name} (${data.length} baris) berhasil disinkronisasi.`, 'success');

    							} catch (error) {
    								this.pesan(`❌ GAGAL saat sinkronisasi tabel '${table.name}': ${error.message}`, 'error');
    								// Hentikan seluruh proses jika satu tabel gagal
    								return;
    							}
    						}

    						this.pesan('🎉 Sinkronisasi semua data master telah selesai!', 'success');
    						// Opsi: Muat ulang halaman untuk menerapkan data baru
    						// window.location.reload();

    					})(); // Langsung jalankan fungsi async
    					break;

    					// ... case selanjutnya ...      
    				case 'bill':
    					if (this.cart.length === 0) {
    						this.pesan('Tidak ada item untuk dibuatkan tagihan.', 'info');
    						return;
    					}

    					// 1. Ubah data pesanan menjadi format yang bisa dibaca oleh generateBill
    					billData = transformPesanan(this.pesant);

    					// 2. Buat teks struk menggunakan fungsi dari pos_bill.js
    					billText = generateBill(billData);

    					// 3. Tampilkan struk di modal (sama seperti saat tutup transaksi)
    					document.getElementById('billDisplay').textContent = billText;
    					document.getElementById('modalOverlay').style.display = 'flex';

    					// 4. Panggil fungsi cetak dengan nama dan argumen yang benar
						// alert(billText)
    					this.print_receipt(billText);
    					break;
    				case 'Change_Qty':
    					this.qty_mode = 'Change';
    					this.setqty('=qty');
    					break;
    				case 'openmenu':
    					this.setkb(3);
    					break;
case 'report': { // Add opening brace
        const reprintUrl = 'report.html';
        const reportFrame = document.getElementById('reportFrame');
        const reportModal = document.getElementById('reportModal');
        if (reportFrame && reportModal) {
            reportFrame.src = reprintUrl;
            reportModal.style.display = 'flex';
        } else {
            this.pesan('Komponen modal tidak ditemukan.', 'error');
        }
        break;
    } // Add closing brace
					case 'sent':
						this.updatecart2();
						// Saring item yang belum dicetak
						const pesanc = this.pesant.filter(item => !item.cetak);

						if (pesanc.length > 0) {
							// Cek pengaturan: jika print_preview TIDAK bernilai '1', maka cetak langsung.
							
							if (this.pos.print_preview==='0' ) {
								// Panggil fungsi untuk cetak langsung.
								print_kitchen_direct(pesanc, this.mejao.tipe);

								// Setelah mencetak, periksa apakah harus logout.
								//alert(this.pos.kitchen_logout);
								if (this.pos.kitchen_logout === '1') {
									this.logout();
								}
							} else {
								// Jika print_preview bernilai '1', panggil fungsi untuk menampilkan pratinjau.
								// Logika logout untuk mode ini sudah seharusnya ditangani di dalam file kitchen.js,
								// tepatnya pada event listener untuk tombol 'Kirim Semua Pesanan'.
								document.getElementById('frame-modal').style.display = 'flex';
								print_kitchen_preview(pesanc);


							}
						} else {
							this.pesan('Tidak ada item baru untuk dikirim ke dapur.', 'info');
						}
						break;


    				case 'split':
    					this.items = this.pesant;
    					this.items = this.items.map(item => {
    						return {
    							...item, // Menyalin semua properti yang ada pada item
    							split: item.split !== undefined ? item.split : "" // Hanya menambahkan "split" jika belum ada
    						};
    					});
    					this.showSplit = true;
    					this.initGrid();
    					break;
    				case 'split_ok':
    					this.pesant = this.items;
    					this.showSplit = false;
    					ss = {};
    					ss.cart = JSON.stringify(this.pesant);
    					bx = rubahjson('cart', ss, this.mejao.kode, 'meja');

    					break;


    				case 'more':
    					this.showPopup = true;
    					break;
    				case 'morem':
    					this.showPopupm = true;
    					break;
    				case 'lepas_meja':
    					this.move = 'Select a table to release';
    					this.Map_table();
    					break;
    				case 'moveitem':
    					if (!this.isVisible) {
    						this.move = 'Select a table to move the menu items.';
    						this.Map_table();
    					};
    					break;

    				case 'change_table':

    					const ii = this.meja.find(item => item.kode === this.currentMeja);
    					this.tempmeja = this.mejao;
    					mm = ii ? ii.id : null;
    					vm.lastcart = this.cart;
    					vm.tmeja = ii;
    					this.lastmeja = mm;
    					this.move = 'MOVE TABLE';
    					this.activeSplitFilter = '';
    					cm = this.Map_table('MOVE TABLE');
    					break;
    				case 'RP':
    					this.newItem = {};
    					cx = Number(this.edc);

    					const index = this.cart.findIndex(item => item.payment === '10' && item.edc === 'CASH');
    					if (index !== -1) {
    						this.cart[index].harga = parseFloat(this.cart[index].harga) + Number(cx);
    						this.cart[index].split = this.activeSplitFilter;
    					} else {
    						this.newItem.id = padNumberWithZeros(generateRandomNumber(), 10);
    						this.newItem.harga = Number(cx);
    						this.newItem.nomor = this.nomor;
    						this.newItem.meja = this.currentMeja;
    						this.newItem.payment = '10';
    						this.newItem.jumlah = Number(cx);
    						this.newItem.edc = 'CASH';
    						this.newItem.nocard = '';
    						this.newItem.name = 'Cash';
    						this.newItem.quantity = 1;
    						this.newItem.tglo = getWaktu();
    						this.newItem.brand = xbrand;
    						this.newItem.cab = xcab;
    						this.newItem.user = this.nuser;
    						this.newItem.split = this.activeSplitFilter;

    						// Tambahkan inisialisasi properti yang diperlukan
    						this.newItem.serv = 0;
    						this.newItem.ppn = 0;
    						this.newItem.service = 0;
    						this.newItem.pajak = 0;
    						this.newItem.netto = this.newItem.harga;
    						this.newItem.disc = 0;
    						this.newItem.jumlah = this.newItem.harga;

    						this.pesant.push(this.newItem);
    					};

    					// Sortir cart berdasarkan payment
    					this.cart.sort((a, b) => {
    						const paymentA = a.payment || '';
    						const paymentB = b.payment || '';
    						return paymentA.localeCompare(paymentB);
    					});

    					a = this.cartSubtotal;
    					this.ya = 2;
    					this.updatecart2();
    					insert_jual();
    					break;
    				case 'openregister':
    					if (!this.register.open) {
    						this.kbn = 'Open_register';
    						this.kba = true;
    						this.inputValue = '';
    						this.selectedShift = 1;
    						this.digits = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '000'];
    						this.showModalAngka = true;
    					} else {
    						this.pesan('Sudah Open Register');
    					}
    					break;
    				case 'closeregister':
    					// Cek dulu apakah register sudah terbuka
						
						
    					if (!this.register.open) {
    						this.pesan('Tidak ada sesi register yang sedang aktif.', 'error');
    						return;
    					}
    					this.kbn = 'Close_register';
    					this.kba = true;
    					this.inputValue = ''; // Kosongkan input
    					this.digits = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '000'];
    					this.showModalAngka = true;
    					break;
    				case 'EDC':
    					this.kbn = 'payment';
    					this.kba = true;
    					this.inputValue = -this.xkembali;
    					this.digits = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '000'];
    					this.showModalAngka = true;
    					this.tipe_bayar = 'edc';
    					break;
    				case 'MDISC':
    					this.newItem = {
    						id: padNumberWithZeros(generateRandomNumber(), 10),
    						harga: 0,
    						name: `${this.currentNamaMeja}`,
    						nomor: this.nomor,
    						meja: this.currentMeja,
    						payment: '06',
    						jumlah: 0,
    						kode: this.edc,
    						edc: 'MDISC:' + this.edc,
    						nocard: '',
    						quantity: 0,
    						tglo: getWaktu(),
    						brand: xbrand,
    						cab: xcab,
    						user: this.nuser,
    						split: this.activeSplitFilter,
    						// Inisialisasi semua properti yang diperlukan
    						discp: 0,
    						discr: 0,
    						disc: 0,
    						serv: 0,
    						ppn: 0,
    						service: 0,
    						pajak: 0,
    						netto: 0,
    						toppings: [],
    						note: '',
    						cetak: ''
    					};
    					this.pesant.push(this.newItem);

    					// Sortir cart berdasarkan payment
    					this.cart.sort((a, b) => {
    						const paymentA = a.payment || '';
    						const paymentB = b.payment || '';
    						return paymentA.localeCompare(paymentB);
    					});

    					a = this.cartSubtotal;
    					this.ya = 2;

    					this.updatecart2();
						this.xfungsi('payment');
    					break;
    				case 'cover':

    					if (this.currentTransactionType && this.currentTransactionType.guest === 1) {
    						this.kbn = 'cover';
    						this.inputValue = '';
    						this.digits = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'];
    						this.showModalAngka = true;
    					} else {
    						// this.pesan('Input tamu tidak diperlukan untuk tipe transaksi ini', 'info');
    					}
    					break;
    				case 'back':
    					document.getElementById("Fungsi").style.display = 'none';
    					break;
    				case 'fungsi':
    					this.currentLayer = this.edc;
    					break;
    				case 'payment':
						// alert(this.pos.register);
						// alert(!this.register.open);
    					if (this.pos.register && !this.register.open) {
    						alert('Harus Open Kasir dahulu');
    						return;
    					}

    					// alert(JSON.stringify(this.pesant));
    					// alert(JSON.stringify(this.cart));
    					vv = this.activeSplitFilter;
    					this.activeSplitFilter = '';
    					ss = this.cart.filter(item => item.split !== "").length;
    					this.activeSplitFilter = vv;
    					if (this.cart.length > 0 && ss > 0 && this.activeSplitFilter == '') {
    						this.pesan('Lakukan pembayaran bill bill yg di split dahulu', 'error');
    						return; // Hentikan proses pembayaran
    					}

    					// ^-- AKHIR DARI BLOK KODE BARU --^

    					insert_jual();

    					// TAMBAHKAN KODE INI: Pastikan tombol aktif saat modal muncul
    					const btnTutup = document.getElementById('btn-tutup-ok');
    					if (btnTutup) {
    						btnTutup.disabled = false;
    						btnTutup.innerText = 'OK';
    					}

						this.currentLayer = '1';
						document.getElementById("Fungsi").style.display = 'block';
						break;
case 'tutup_batal':
    this.shoconfbayar = false; // Tutup modal konfirmasi di POS

    // --- PERBAIKAN: KIRIM SINYAL hidePayment UNTUK CANCEL ---
    try {
        const secondDisplayData = { 
            command: 'hidePayment', // Mengganti 'default' menjadi 'hidePayment'
            payload: {
                 meja: this.mejao.nama || 'Take Away',
                 cart: this.cart, 
                 totals: null
            } 
        };
        localStorage.setItem('secondDisplay', JSON.stringify(secondDisplayData));
    } catch (error) {
        console.error('Gagal mengirim perintah hidePayment:', error);
    }
    // --- AKHIR PERBAIKAN ---
    break;
					// Ganti seluruh case 'tutup_ok' di dalam methods: { xfungsi() { ... } } di pos.js
					// Ganti seluruh case 'tutup_ok' di dalam methods: { xfungsi() { ... } } di pos.js
// Ganti seluruh blok case 'tutup_ok' di pos.js dengan ini

// Ganti seluruh blok case 'tutup_ok' di pos.js dengan ini

case 'tutup_ok':

    // if (this.isAdjustMode) {
    //     this.saveAdjustedTransaction(); // Panggil fungsi khusus untuk menyimpan hasil adjust
    //     return; // Hentikan eksekusi agar tidak menjalankan logika 'tutup_ok' normal
    // }


    this.shoconfbayar = false;

    const itemsToPay = this.cart.filter(item => item.split === this.activeSplitFilter);

    if (itemsToPay.length === 0) {
        this.pesan('Tidak ada item yang perlu dibayar pada split ini.', 'error');
        return;
    }

    const okButton = document.getElementById('btn-tutup-ok');
    if (okButton) {
        okButton.disabled = true;
        okButton.innerText = 'Menyimpan...';
    }

    // Menggunakan try...catch untuk menangani potensi error selama proses async
    try {
        const newTransactionNumber = await this._generateTransactionHeader(itemsToPay);
        if (!newTransactionNumber) {
            // Error ini akan ditangkap oleh blok catch di bawah
            throw new Error('Gagal membuat nomor transaksi.');
        }
        this.no_jual = newTransactionNumber;

        const itemsForPesani = this._preparePesaniData(itemsToPay, this.no_jual);

        const originalCashPayment = itemsToPay.find(item => item.payment === '10');
        const itemsForBill = itemsForPesani.map(item => {
            if (item.payment === '10' && originalCashPayment) {
                return { ...item, harga: originalCashPayment.harga, jumlah: originalCashPayment.harga };
            }
            return item;
        });
        const billText = generateBill(itemsForBill);
        
        // Cetak struk terlebih dahulu
        this.print_receipt(billText);

        // ====================================================================
        // ✨ PERBAIKAN UTAMA: Tambahkan 'await' di sini ✨
        // Ini memaksa program untuk menunggu sampai data 'pesani' berhasil disimpan
        // sebelum melanjutkan ke baris kode berikutnya.
        // ====================================================================
        await insertData('pesani', itemsForPesani);
        
        // Kirim data ke server pusat (setelah data lokal aman)
        kirimTransaksiManual(this.no_jual);

        // Hapus item yang sudah dibayar dari array master lokal (this.pesant)
        const paidItemIds = new Set(itemsToPay.map(item => item.id));
        this.pesant = this.pesant.filter(item => !paidItemIds.has(item.id));
        
        // Tampilkan modal rekapitulasi transaksi
        const manualPaymentBreakdown = [];
        if (this.xcash > 0) {
            manualPaymentBreakdown.push({ name: 'Tunai (Cash)', amount: this.xcash });
        }
        const nonCashPayments = itemsToPay.filter(item => 
            item.payment && item.payment !== '10' && item.payment !== '06'
        );
        const nonCashSummary = nonCashPayments.reduce((acc, payment) => {
            const name = payment.edc || payment.name || 'Non-Tunai';
            if (!acc[name]) { acc[name] = 0; }
            acc[name] += payment.harga;
            return acc;
        }, {});
        Object.keys(nonCashSummary).forEach(name => {
            manualPaymentBreakdown.push({ name: name, amount: nonCashSummary[name] });
        });
        const rekapData = {
            nomor: newTransactionNumber,
            total: this.xgrandtotal, 
            pembayaran: this.xpayment,
            kembalian: this.xkembali,
            paymentBreakdown: manualPaymentBreakdown 
        };
        this.showTransactionSummary(rekapData); 

        // --- PROSES 6: FINALISASI & RESET (sekarang berjalan setelah semua proses simpan selesai) ---
        const remainingItems = this.pesant.filter(item => item.meja === this.currentMeja);

        if (remainingItems.length === 0) {
            // Reset status meja & hapus cart di database
            if (this.mejao) {
                this.mejao.user = '';
                this.mejao.jumlah = 0;
                this.mejao.cover = 0;
                this.mejao.guest = '';
                rubahjson('meja', this.mejao, this.mejao.id);
            }
            const dataToSave = { meja: this.currentMeja, cart: '[]', brand: xbrand, cab: xcab };
            rubahjson('cart', dataToSave, dataToSave.meja, 'meja');
            this.activeSplitFilter = '';
        } else {
            // Update data cart di database jika masih ada sisa item (untuk split bill)
            this.updatecart2();

            const remainingSplits = this.pesant.some(item => item.split && item.split.trim() !== '');
            if (!remainingSplits) {
                this.mejao.split = '';
                rubahjson('meja', { split: '' }, this.mejao.id);
                this.isMasterPaymentDisabled = false;
                this.activeSplitFilter = '';
            }
        }
    } catch (error) {
        // Jika terjadi error di salah satu proses 'await', tampilkan pesan
        console.error("Gagal memproses transaksi:", error);
        this.pesan(`Transaksi Gagal: ${error.message || 'Error tidak diketahui'}`, 'error');
    } finally {
        // Bagian ini akan selalu dijalankan, baik sukses maupun gagal
        // untuk memastikan UI kembali normal.
        this.shoconfbayar = false;
        document.getElementById("Fungsi").style.display = 'none';
        if (okButton) { 
            okButton.disabled = false; 
            okButton.innerText = 'Konfirmasi & Cetak'; 
        }
    }
    break;

   case 'kirim_data': { // Add opening brace
        const kirimUrl = 'kirim_data.html';
        const reportFrame = document.getElementById('reportFrame');
        const reportModal = document.getElementById('reportModal');
        if (reportFrame && reportModal) {
            reportFrame.src = kirimUrl;
            reportModal.style.display = 'flex';
        } else {
            this.pesan('Komponen modal untuk laporan tidak ditemukan.', 'error');
        }
        break;
    } 
					case 'logout':
						this.logout()
						//  this.Map_table();
						break;
					case 'table':
						this.activeSplitFilter = '';
						// rubahjson('meja', {
						// 	user: ''
						// }, this.mejao.id, 'id');
						// this.updatecart2();
						this.Map_table();
						break;
					case 'note':
						this.setkb(1);
						break;
					case 'editToppings':
						this.editToppings();
						break;
					case 'voiditem':
						this.jenisdelete = 'Otorisasi Delete Item';
						this.voiditem();
						break;
					case 'batal':
						this.jenisdelete = 'Otorisasi Delete all Item';
						this.batal();
						break;
					case 'guest':
						this.setkb(2);
					default:
						// Handle default case if needed
						break;
				}
			},

    		note(special) {
    			this.inputValue = this.inputV[1];
    			this.inputValue2 = this.inputV[2];
    			this.inputValue1 = this.inputV[2];
    			if (this.kb_for == 1) {
    				if (this.inputValue != '') {
    					this.cart[this.currentcart].note = this.inputValue;
    					this.cart[this.currentcart].split = this.activeSplitFilter; // PERBAIKAN: Update split
    					this.showModalAngkakb = false;
    					this.ya = 2;
    					this.updatecart2();
    				} else {
    					this.showModalAngkakb = false;
    				}
    			} else if (this.kb_for == 2) {
    				this.showModalAngkakb = false;
    				this.mejao.guest = this.inputValue;
    				bx = rubahjson('meja', this.mejao, this.mejao.id);
    				// this.meja[this.currmeja].guest = this.inputValue;
    			} else if (this.kb_for == 3) {
    				this.showModalAngkakb = false;
    				bb = {
    					"id": "20",
    					"kode": "OPEN",
    					"name": this.inputV[1],
    					"condiment": "02",
    					"condiment_name": "Proses Masak",
    					"kgroup": "01",
    					"group": "Mie dan Kwetiau",
    					"harga": this.inputV[2],
    					"price": this.inputV[2],
    					"image": "",
    					"toping": "",
    					"discp": "0.00",
    					"discr": "0.00",
    					"pajak": "0.00",
    					"serv": "0.00",
    					"brand": "001",
    					"cab": "002",
    					"note": "",
    					"cetak": "",
    					"ind": this.inputV[1],
    					"eng": this.inputV[1],
    					"chn": this.inputV[1],
    					"jpn": this.inputV[1],
    					"arb": this.inputV[1],
    					"toppings": []
    				};
    				this.pilihmenu(bb);
    			}

    		},


    		appendDigit(digit) {
    			this.inputValue += digit.toString();
    		},

			appendSpecial(special) {

				if (special === 'Backspace') {
					this.inputValue = this.inputValue.slice(0, -1);
				} else if (special === 'Enter') {

					if (this.kbn == 'qty') {
						if (this.pos.qty == 'After' || this.qty_mode == 'Change') {

							if (this.inputValue != '') {
								this.cart[this.currentcart].quantity = this.inputValue;
								this.showModalAngka = false;
								this.updatecart2();
							} else {
								this.showModalAngka = false;
							}
						} else {
							this.bqty = this.inputValue;
							this.showModalAngka = false;
						}
						this.qty_mode = '';
					} else if (this.kbn == 'payment') {
						this.showModalAngka = false;
						this.bayar_edc();
					} else if (this.kbn == 'cover') {
						this.mejao.cover = this.inputValue;
						bx = rubahjson('meja', this.mejao, this.mejao.id);
						this.showModalAngka = false;
					} else if (this.kbn == 'Close_register') {
						
						const closingBalance = this.inputValue;
						this.showModalAngka = false;

						this.tampilkanPesan('Yakin akan tutup register?', 'confirm', (confirmed) => {
							if (confirmed) {
								// Panggil fungsi baru untuk menampilkan laporan closing
								this.showClosingReport(closingBalance);
							}
						});
					} else if (this.kbn == 'Open_register') {
						this.prosesBukaRegister(this.inputValue); // Panggil method baru
						this.showModalAngka = false;
					} else if (this.kbn == 'Close_register') {
						this.register.kuser = '';
						this.register.nama = '';
						this.register.open = false;
						this.register.modal = 0;
						localStorage.setItem('register', JSON.stringify(this.register));
						this.showModalAngka = false;
					};

					;
				}
			},


    		// Ganti di pos.js
				voiditem() {
						this.inputValue1 = '';
						this.inputValue2 = '';
						this.overadmin = false;
					this.afterAuthAction = 'voidItem';
	

					// Cek apakah ada item yang dipilih
					if (this.currentcart === null || this.currentcart === undefined) {
						this.pesan('Silakan pilih item yang ingin dihapus.', 'info');
						return;
					}

					// Ambil item yang dipilih dari cart
					const selectedItem = this.cart[this.currentcart];
					if (!selectedItem) {
						this.pesan('Item yang dipilih tidak ditemukan.', 'error');
						return;
					}

					// Simpan nama item untuk konfirmasi
					this.itemNameToDelete = selectedItem.name;

					if (selectedItem.cetak) {
						this.overadmin = true;
					} else {
						this.showModal = true;
					}
					document.getElementById("userlog")?.click();
				},


                batal() {
                // 1. Periksa apakah ada item di meja saat ini
                if (this.cart.length === 0) {
                    this.pesan('Meja ini kosong, tidak ada yang bisa dibatalkan.', 'info');
                    return;
                }

                // 2. Simpan aksi yang akan dijalankan setelah otorisasi berhasil
                this.afterAuthAction = 'batalMeja';

                // 3. Reset input dan tampilkan modal otorisasi
                this.inputValue1 = '';
                this.inputValue2 = '';
                this.overadmin = true;
                document.getElementById("userlog")?.click();
            },

            // +++ FUNGSI BARU: Logika inti untuk membatalkan meja setelah otorisasi +++
            prosesBatalMeja() {
                // 3. Hapus semua item dari meja saat ini
                this.pesant = this.pesant.filter(item => item.meja !== this.currentMeja);

                // Update data 'cart' di database menjadi kosong
                const dataToSave = {
    				meja: this.currentMeja,
    				cart: '[]', // Simpan sebagai array kosong
    				brand: xbrand,
    				cab: xcab
    			};
    			rubahjson('cart', dataToSave, dataToSave.meja, 'meja');
                
                // Reset status meja
                if (this.mejao) {
                    this.mejao.user = '';
                    this.mejao.jumlah = 0;
                    this.mejao.cover = 0;
                    this.mejao.guest = '';
                    rubahjson('meja', this.mejao, this.mejao.id);
                }

                this.pesan(`Semua pesanan di meja ${this.mejao.nama} berhasil dibatalkan.`, 'success');

                // 4. Kembali ke halaman map table
                this.Map_table();
            },

            // +++ AKHIR FUNGSI BARU +++



    		otor() {
            const username = this.inputValue1;
            const password = this.inputValue2;

            if (!username || !password) {
                this.pesan('Username dan Password harus diisi.', 'error');
                return;
            }

            // 1. Cari user dan validasi password
            const user = this.users.find(u => u.username === username && u.password === password);

            if (!user) {
                this.pesan('Username atau Password salah.', 'error');
                this.inputValue1 = '';
                this.inputValue2 = '';
                return;
            }

            // 2. Cek hak akses di tabel botor
            const hasPermission = this.botor.some(b => 
                b.g_user === user.grp && 
                b.otor === this.requiredOtor && 
                b.ya === '1'
            );

            // 3. Proses hasil otorisasi
            this.overadmin = false; // Selalu tutup jendela setelah proses
            this.inputValue1 = '';
            this.inputValue2 = '';

            if (hasPermission) {
                //this.pesan('Otorisasi berhasil.', 'success');
                // Jalankan fungsi yang tadinya ditunda, dengan penanda 'sudah diotorisasi'
                this.xfungsi(this.functionToExecuteAfterOtor, true); 
            } else {
                this.pesan('Akses ditolak. Anda tidak memiliki hak otorisasi yang diperlukan.', 'error');
            }

            // Reset variabel otorisasi
            this.requiredOtor = null;
            this.functionToExecuteAfterOtor = null;
        },

    		// Ganti fungsi confirmAction di pos.js
    		confirmAction(choice) {
    			if (choice === 'Yes') {
    				// Cek apakah ada item yang dipilih
    				if (this.currentcart === null || this.currentcart === undefined) {
    					this.pesan('Tidak ada item yang dipilih untuk dihapus.', 'error');
    					this.showModal = false;
    					return;
    				}

    				// Ambil item yang dipilih dari cart
    				const selectedItem = this.cart[this.currentcart];
    				if (!selectedItem) {
    					this.pesan('Item yang dipilih tidak ditemukan.', 'error');
    					this.showModal = false;
    					return;
    				}

    				// Cari dan hapus item di array pesant berdasarkan ID
    				const pesantIndex = this.pesant.findIndex(item =>
    					item.id === selectedItem.id &&
    					(this.activeSplitFilter === '' || item.split === this.activeSplitFilter)
    				);

    				if (pesantIndex !== -1) {
    					this.pesant.splice(pesantIndex, 1);
    					this.pesan('Item berhasil dihapus.', 'success');
    				} else {
    					this.pesan('Gagal menghapus: Item tidak ditemukan di data master keranjang.', 'error');
    				}

    				// Update database
    				this.updatecart2();

    				// Reset selection
    				this.currentcart = null;
    			}

    			// Tutup modal dan hitung ulang total
    			this.showModal = false;
    			let j = this.cartSubtotal;
    		},

    		selectCity(toping, top) {
    			for (const toppingGroup of toping.items) {
    				toppingGroup.checked = false;
    			};
    			toping.pilih = top.nama_toping;
    			top.checked = true;
    		},

    		showToppings(menuItem) {
    			xx = JSON.stringify(menuItem);
    			xx = JSON.parse(xx);
    			this.selectedMenu = xx;
    		},

    		editToppings() {

    			itemx = this.cart[this.currentcart];
    			this.itemx = itemx;
    			oo = this.cart[this.currentcart];

    			xx = this.menus.find(menu => menu.name === itemx.name);
    			xx = JSON.stringify(xx);
    			xx = JSON.parse(xx);


    			// Mencocokkan kode_toping dan mengisi checked
    			for (let i = 0; i < xx.toppings.length; i++) {
    				for (let k = 0; k < xx.toppings[i].items.length; k++) {

    					for (let j = 0; j < oo.toppings.length; j++) {
    						if (xx.toppings[i].toping === oo.toppings[j].toping) {
    							for (let l = 0; l < oo.toppings[j].items.length; l++) {
    								if (xx.toppings[i].items[k].kode_toping === oo.toppings[j].items[l].kode_toping) {
    									xx.toppings[i].items[k].checked = oo.toppings[j].items[l].checked;
    									xx.toppings[i].pilih = oo.toppings[j].items[l].nama_toping;
    									// break; // Break setelah menemukan kecocokan
    								}
    							}
    						}
    						// break; // Break setelah menemukan kecocokan
    					}
    				}
    			};


    			yy = JSON.stringify(xx);
    			gg = JSON.parse(yy);
    			this.edit = true;
    			this.selectedMenuItem = gg;
    			this.showToppings = true;

    		},


    		// GANTI LAGI SELURUH FUNGSI INI DI pos.js

    		// GANTI SELURUH FUNGSI INI DI pos.js
    		// GANTI SELURUH FUNGSI INI DI pos.js

    		pilihmenu(item) {
    			let itemSalinan = JSON.parse(JSON.stringify(item));
    			if (itemSalinan.toppings && itemSalinan.toppings.length > 0) {
    				this.selectedMenuItem = itemSalinan;
    				this.showToppings = true;
    				return;
    			}

    			// Ambil harga berdasarkan tipe transaksi
    			const hargaInfo = this.getHarga(itemSalinan);

    			const mainItemId = padNumberWithZeros(generateRandomNumber(), 10);
    			const newItem = {
    				...itemSalinan,
    toppings: itemSalinan.toppings, // Ambil yang sudah dipastikan ada
    paketItems: itemSalinan.paketItems, // Ambil yang sudah dipastikan ada					
    				price: hargaInfo.harga,
    				discp: hargaInfo.discp,
    				discr: hargaInfo.discr,
    				quantity: this.pos.qty === 'After' ? 1 : this.bqty,
    				nomor: this.nomor,
    				meja: this.currentMeja,
    				ket: '',
    				// Tambahkan inisialisasi properti yang diperlukan
    				payment: '', // Inisialisasi payment dengan string kosong
    				edc: '',
    				nocard: '',
    				serv: 0, // Inisialisasi service
    				ppn: 0, // Inisialisasi pajak
    				service: 0, // Inisialisasi nilai service
    				pajak: 0, // Inisialisasi nilai pajak
    				netto: 0, // Inisialisasi netto
    				disc: 0, // Inisialisasi diskon
    				jumlah: 0, // Inisialisasi jumlah
    				id: mainItemId,
    				tglo: getWaktu(),
    				user: this.nuser,
    				split: this.activeSplitFilter,
    				name: itemSalinan[this.bhs] || itemSalinan.name,
    				paketItems: []
    			};

    			// Hitung jumlah setelah harga diperbarui
    			newItem.jumlah = newItem.quantity * newItem.price;

    			// ... lanjutan kode untuk paket items
    			const itemKodeBersih = String(item.kode).trim();
    			if (this.paketData.has(itemKodeBersih)) {
    				const paketItemsData = this.paketData.get(itemKodeBersih);
    				paketItemsData.forEach(paketItem => {
    					newItem.paketItems.push({
    						kode: paketItem.kode,
    						name: paketItem.npaket,
    						quantity: paketItem.quantity
    					});
    				});
    			}

    			this.pesant.push(newItem);
    			this.bqty = 1;
    			this.showToppings = false;

    			// Sortir cart berdasarkan payment (pastikan semua item memiliki properti payment)
    			this.cart.sort((a, b) => {
    				const paymentA = a.payment || '';
    				const paymentB = b.payment || '';
    				return paymentA.localeCompare(paymentB);
    			});

    			this.ya = 2;
    			this.currentcart = this.cart.length - this.item_bayar - 1;
    			this.updatecart2();
    		},
    		// GANTI JUGA FUNGSI INI DI pos.js
    		// GANTI JUGA FUNGSI INI DI pos.js

    		showToppings2(item) {
    			let lengkap = true;
    			let slengkap = '';
				item.toppings = item.toppings || [];
item.paketItems = item.paketItems || [];

    			for (const toppingGroup of item.toppings) {
    				if (toppingGroup.wajib && toppingGroup.ok === 0 && toppingGroup.items.length > 1) {
    					slengkap += toppingGroup.Group + ', ';
    					lengkap = false;
    				}
    			}

    			if (!lengkap) {
    				this.pesan('Pilihan wajib belum lengkap: ' + slengkap.slice(0, -2), 'error');
    				return;
    			}

    			for (const toppingGroup of item.toppings) {
    				toppingGroup.items = toppingGroup.items.filter(topping => topping.checked === true);
    			}

    			if (this.edit === true) {
    				this.itemx.toppings = item.toppings;
    				const currentItemInCart = this.cart[this.currentcart];
    				if (currentItemInCart) {
    					currentItemInCart.toppings = item.toppings;
    				}
    				this.showToppings = false;
    				this.edit = false;
    				this.updatecart2();
    				return;
    			}

    			// Ambil harga berdasarkan tipe transaksi
    			const hargaInfo = this.getHarga(item);

    			delete item.toping;

    			const mainItemId = padNumberWithZeros(generateRandomNumber(), 10);
    			const newItem = {
    				...item,
    				price: hargaInfo.harga,
    				discp: hargaInfo.discp,
    				discr: hargaInfo.discr,
    				id: mainItemId,
    toppings: item.toppings, // Pastikan menggunakan properti yang sudah diinisialisasi/diperbarui
    paketItems: item.paketItems,					
    				quantity: this.pos.qty === 'After' ? 1 : this.bqty,
    				nomor: this.nomor,
    				meja: this.currentMeja,
    				ket: '-',
    				// Tambahkan inisialisasi properti yang diperlukan
    				payment: '', // Inisialisasi payment dengan string kosong
    				edc: '',
    				nocard: '',
    				serv: 0, // Inisialisasi service
    				ppn: 0, // Inisialisasi pajak
    				service: 0, // Inisialisasi nilai service
    				pajak: 0, // Inisialisasi nilai pajak
    				netto: 0, // Inisialisasi netto
    				disc: 0, // Inisialisasi diskon
    				jumlah: 0, // Inisialisasi jumlah
    				tglo: getWaktu(),
    				user: this.nuser,
    				split: this.activeSplitFilter,
    				paketItems: []
    			};

    			// Hitung jumlah setelah harga diperbarui
    			newItem.jumlah = newItem.quantity * newItem.harga;

    			// ... lanjutan kode untuk paket items
    			const itemKodeBersih = String(item.kode).trim();
    			if (this.paketData.has(itemKodeBersih)) {
    				const paketItemsData = this.paketData.get(itemKodeBersih);
    				paketItemsData.forEach(paketItem => {
    					newItem.paketItems.push({
    						kode: paketItem.kode,
    						name: paketItem.npaket,
    						quantity: paketItem.quantity
    					});
    				});
    			}

    			this.pesant.push(newItem);

    			this.showToppings = false;
    			this.bqty = 1;
    			this.ya = 2;

    			// Sortir cart berdasarkan payment (pastikan semua item memiliki properti payment)
    			this.cart.sort((a, b) => {
    				const paymentA = a.payment || '';
    				const paymentB = b.payment || '';
    				return paymentA.localeCompare(paymentB);
    			});

    			this.currentcart = this.cart.length - this.item_bayar - 1;
    			this.updatecart2();
    		},

    		checkToppingsLimit(topping, top) {
    			if (top.checked) {
    				top.checked = false;
    			} else if (topping.items.filter(item => item.checked).length < topping.max) {
    				top.checked = true;
    			}
    		},
    		countSelectedItems(topping) {
    			const selectedItems = topping.items.filter(item => item.checked);

    			if (topping.max == selectedItems.length || topping.wajib == false) {
    				topping.ok = 1;
    			} else {
    				topping.ok = 0;
    			};

    			return selectedItems.length;
    		},

    		changeLantai(top) {
    			bx = ambil('meja', 'kode', '', 'zz');
    			bx = JSON.parse(bx);
    			bx.forEach(function(item) {
    				item.left = parseFloat(item.left);
    				item.top = parseFloat(item.top);
    				item.width = parseFloat(item.width);
    				item.height = parseFloat(item.height);
    				item.id = parseFloat(item.id);
    				item.cover = parseFloat(item.cover);
    				item.borderRadius = parseFloat(item.borderRadius);
    			});
    			this.meja = bx;
          //this.meja = [{ "lantai": "1", "kode": "11", "nama": "11", "cover": 0, "timein": "", "timeout": "", "join": "", "left": 6.5, "top": 36.75, "width": 5, "height": 7.75, "warna": "#3498db", "fore": "#000000", "borderRadius": 36.875 }];

          this.currentLantai = top.kode;
    			m = this.meja.filter(mejax => mejax.lantai === this.currentLantai);
    			if (m.length > 1) {
    				this.currentMeja = m[0].kode;
    				document.getElementById("lantai-img").src = top.image;
    			}
    		},

    		changeMeja(top, idx) {
    			this.isMasterPaymentDisabled = false;

    			if (this.move == 'Select a table to release') {
    				this.move = '';
    				rubahjson('meja', {
    					user: ''
    				}, top.id, 'id')
    				this.pesan(`Release Table ` + top.kode + ' berhasil', 'success');
    				return;
    			};

    			this.umeja = true;
    			const mejaDbJson = ambil('meja', 'id', top.id);
    			if (!mejaDbJson || mejaDbJson === '[]') {
    				this.pesan(`Gagal memverifikasi status meja ${top.nama}.`, 'error');
    				return;
    			};

    			if (top.split && top.split.trim() !== '') {
    				this.isMasterPaymentDisabled = true;
    			}

    			const mejaDariDb = JSON.parse(mejaDbJson)[0];
    			this.umeja = false;

    			if (!mejaDariDb.user == '  ' && mejaDariDb.user !== this.nuser) {
    				this.pesan(`Meja ${top.nama} sedang dibuka oleh kasir: ${mejaDariDb.user}`, 'error');
    				return;
    			};

    			const tipeKode = top.tipe || '01'; // Default ke '01' jika tidak ada
    			const tipeData = this.tipeTransaksi.find(t => t.kode === tipeKode);

    			if (tipeData) {
    				this.currentTransactionType = tipeData;
    				this.mejao.tipe = tipeKode;

    				// Update group harga yang digunakan
    				this.group_harga = tipeData.harga_group;

    				// Tampilkan informasi tipe transaksi
    				//console.log(`Tipe Transaksi: ${tipeData.nama}`);
    				//console.log(`Service Charge: ${tipeData.service_charge}% (${tipeData.service ? 'Aktif' : 'Tidak Aktif'})`);
    				//console.log(`Pajak: ${tipeData.pajak_charge}% (${tipeData.pajak ? 'Aktif' : 'Tidak Aktif'})`);

    				// Jika guest wajib diinput dan belum ada, tampilkan input
    				if (tipeData.guest === 1 && !this.mejao.cover) {
    					this.xfungsi('cover');
    				}
    			};



    			if (this.move == 'Select a table to move the menu items.') {
    				bx = ambil('cart', 'meja', top.kode, top.kode);
    				let parsedBx = JSON.parse(bx); // Attempt to parse the JSON string
    				if (Array.isArray(parsedBx) && parsedBx.length === 0) {
    					var cartString = '[]'; // Initialize cartString as an empty array
    				} else if (parsedBx.length > 0) {
    					var cartString = parsedBx[0].cart; // Access the 'cart' property
    				} else {
    					var cartString = '[]'; // Fallback to empty array if no valid data
    				};
    				this.pesanp = JSON.parse(cartString);
    				this.backkiri = JSON.parse(JSON.stringify(this.pesant));
    				this.backkanan = JSON.parse(JSON.stringify(this.pesanp));
    				this.mejakanan = top.kode;
    				this.mejakiri = this.mejao.kode;
    				this.isVisible = !this.isVisible;
    				this.move = '';
    				this.cart.sort((a, b) => a.payment.localeCompare(b.payment));

    				return;
    			};

    			// Toggle status visibilitas


    			if (this.move == 'MOVE TABLE') {
    				bx = ambil('cart', 'meja', top.kode, top.kode);
    				if (!(bx == '' || bx == '[]' || JSON.parse(bx)[0].cart == '[]')) {
    					alert('Meja sudah ada isi nya');
    					document.getElementById("Map").style.display = 'none';
    					this.move = '';
    					return;
    				};
    				this.pesant.forEach(function(item) {
    					item.meja = top.kode; // Ganti semua item.meja dengan '20'
    				});
    				let b = {};
    				b.jumlah = 0;
    				b.cover = 0;
    				b.guest = '';
    				b.user = '';
    				b.split = '';
    				bx = rubahjson('meja', b, this.mejao.id);
    				ss = {};
    				ss.cart = '[]';
    				bx = rubahjson('cart', ss, this.mejao.kode, 'meja');

    				top.jumlah = this.mejao.jumlah;
    				top.guest = this.mejao.guest;
    				top.cover = this.mejao.cover;

    				this.mejao = top;
    				this.currentMeja = top.kode;
    				this.currmeja = this.currentMejas.findIndex(item => item.kode === top.kode);
    				this.move = '';
    				bx = rubahjson('meja', this.mejao, this.mejao.id);

    				ss = {};
    				ss.cart = JSON.stringify(this.pesant);
    				bx = rubahjson('cart', ss, top.kode, 'meja');


    				document.getElementById("Map").style.display = 'none';
    				return;
    			};

    			idx = this.meja.findIndex(item => item.kode === top.kode);
    			this.currmejac = this.currentMejas.findIndex(item => item.kode === top.kode);

    			this.mejao = top;
    			if (top.fungsi == '0') {
    				return;
    			};

    			if (top.fungsi !== '1') {
    				this.xfungsi(top.fungsi);
    				return;
    			};


    			if (this.isedit == true) {
    				this.isedit = false;
    				return
    			};

    			//bacameja();
    			this.currmeja = idx;
    			this.currentMeja = top.kode;
    			this.currentNamaMeja = top.nama;



    			// --- AWAL PERUBAHAN ---
    			// Kunci meja dengan nama user yang login
    			top.user = this.nuser;
    			top.lastbuka = new Date().toISOString();
    			rubahjson('meja', top, top.id);
    			// --- AKHIR PERUBAHAN ---

    			bx = ambil('cart', 'meja', this.currentMeja, this.currentMeja);
    			jsonData = JSON.parse(bx);


    			var cartArray = [];
    			// Iterasi setiap objek dalam jsonData

    			jsonData.forEach(function(obj) {
    				// Parse nilai cart dari string JSON ke objek JavaScript
    				obj.cart = obj.cart ? obj.cart : '[]';

    				var cartItems = JSON.parse(obj.cart);

    				// Iterasi setiap item dalam cartItems
    				cartItems.forEach(function(item) {
    					// Push item ke dalam array cartArray
    					cartArray.push(item);
    				});
    			});


    			this.pesant = cartArray;
    			document.getElementById("Map").style.display = 'none';
    			vm.posisi = 'order';
    			this.ya = 2;
    			this.currentcart = this.cart.length - 1;
    			x = this.cartSubtotal;
    			if (this.cart.length == 0) {
    				this.mejao.timein = getWaktu();
    				if (this.move == '') {
    					this.xfungsi('cover');
    				}
    			};
    			this.move = '';

    			// CEK: Jika meja sudah di-split, langsung buka split screen
    			if (top.split && top.split.trim() !== '') {
    				// Reset pilihan item
    				this.currentCartItemId = null;
    				this.selectedItemName = '';
    				this.currentcart = null;

    				// Buka split screen
    				this.items = this.pesant;
    				this.showSplit = true;
    				this.initGrid();
    				return;
    			}

    		},


    		pchangeMeja(top, idx) {
    			if (top.fungsi == '0') {
    				return;
    			};

    			if (top.fungsi !== '1') {
    				this.currentNamaMeja = top.nama;
    				this.xfungsi(top.fungsi);
    				return;
    			};


    			if (this.isedit == true) {
    				this.isedit = false;
    				return
    			};

    			bacameja();
    			top = this.meja[idx];


    			this.posisi = 'order';
    			this.currmeja = idx;
    			this.currentMeja = top.kode;
    			this.currentNamaMeja = top.nama;
    			top.user = this.nuser;
    			top.lastbuka = new Date().toISOString();
    			bx = rubahjson('meja', top, top.id);
    			bx = ambil('cart', 'meja', '', 'zz');
    			jsonData = JSON.parse(bx);
    			var cartArray = [];
    			// Iterasi setiap objek dalam jsonData
    			jsonData.forEach(function(obj) {
    				// Parse nilai cart dari string JSON ke objek JavaScript
    				var cartItems = JSON.parse(obj.cart);
    				// Iterasi setiap item dalam cartItems
    				cartItems.forEach(function(item) {
    					// Push item ke dalam array cartArray
    					cartArray.push(item);
    				});
    			});
    			this.pesant = cartArray;

    			document.getElementById("Map").style.display = 'none';
    			this.ya = 2;
    			this.currentcart = this.cart.length - 1;
    			insert_jual();
    		},



    		changeMenuTop(top) {
    			this.currentMenuTop = top;
    			b = this.menuGroups.filter(menuGroups => menuGroups.top === this.currentMenuTop);
    			this.currentMenuGroup = b[0].kode;
    		},

    		changeMenuGroup(group) {
    			this.currentMenuGroup = group.kode;
    		},


    		// addToCart(item) {
    		//   const existingItem = this.cart.find(cartItem => cartItem.name === item.name);
    		//   if (existingItem) {
    		//     existingItem.quantity++;
    		//     existingItem.jumlah = existingItem.quantity * existingItem.harga;
    		//   } else {
    		//     const this.newItem = { ...item, quantity: 1 };
    		//     this.newItem.jumlah = this.newItem.quantity * this.newItem.harga; // Hitung jumlah
    		//     this.newItem.nomor = this.nomor;
    		//     this.newItem.meja = this.currentMeja;
    		//     this.newItem.discp = 5;
    		//     this.newItem.discr = 1000;
    		//     this.newItem.ket = '-';
    		//     this.newItem.serv = 5 ;
    		//     this.newItem.ppn  = 10 ;
    		//     this.newItem.service = 0;
    		//     this.newItem.pajak   = 0;
    		//     this.newItem.netto   = 0;
    		//     this.newItem.disc    = 0;

    		//     this.newItem.payment = '';
    		//     this.newItem.edc     = '';
    		//     this.newItem.nocard  = '';


    		//     this.pesant.push(this.newItem);

    		//     this.cart.sort((a, b) => {
    		//       return a.payment.localeCompare(b.payment);
    		//     });

    		//   };

    		// },

    		removeFromCart(index) {
    			this.cart.splice(index, 1);
    		},
    		selectPayment(paymentType) {
    			this.selectedPayment = paymentType;
    		},
    		checkout() {
    			this.isTransactionComplete = true;
    		},
    		closeReceipt() {
    			this.Kirim();
    			this.isTransactionComplete = false;
    			this.cart = [];
    			this.selectedPayment = null;
    			this.discount = 0;
    			this.nomor = padNumberWithZeros(generateRandomNumber(), 6);

    		},
    		applyDiscount() {
    			this.discount = this.cartSubtotal * 0.05;
    		},


    		tampilkanKonfirmasiHapus() {
    			if (this.currentcart === null || this.cart[this.currentcart] === undefined) {
    				this.pesan('Silakan pilih item yang valid untuk dihapus.', 'info');
    				return;
    			}

    			const itemToDelete = this.cart[this.currentcart];

    			// Tampilkan modal konfirmasi dengan nama item yang benar
    			this.itemNameToDelete = itemToDelete.name;
    			this.showModal = true;
    		},

    		pilihcart(item, index) {
    			// Simpan ID item yang dipilih
    			this.currentCartItemId = item.id;

    			// Simpan juga index untuk styling
    			this.currentcart = index;

    			// Simpan nama item untuk konfirmasi
    			this.selectedItemName = item.name;
    		},

    		setqty(item) {
    			if (this.pos.qty == 'After' || item == '=qty') {
    				if (this.cart.length == 0) {
    					return
    				};
    				if (item > 0) {
    					this.cart[this.currentcart].quantity = item;
    					this.cart[this.currentcart].split = this.activeSplitFilter;
    				} else {
    					this.kbn = 'qty';
    					this.inputValue = '';
    					this.qty_mode = 'Change';
    					this.digits = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'];
    					this.showModalAngka = true;
    				}
    			} else {
    				this.bqty = item;
    				if (!(item > 0)) {
    					this.kbn = 'qty';
    					this.inputValue = '';
    					this.digits = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'];
    					this.showModalAngka = true;
    				}
    			};
    		},

    		setkb(item) {
    			if (item == 1) {
    				this.kb_for = 1;
    				if (this.cart.length == 0) {
    					return
    				} else {
    					if (this.cart[this.currentcart].note) {
    						this.inputValue = this.cart[this.currentcart].note
    					} else {
    						this.inputValue = '';
    					}
    					this.showModalAngkakb = true;
    				}
    			} else if (item == 2) {
    				this.kb_for = 2;
    				this.inputValue = this.meja[this.currmeja].guest;
    				this.showModalAngkakb = true;
    			} else if (item == 3) {
    				this.kb_for = 3;
    				this.inputValue = '';
    				this.inputV[2] = '';
    				this.showModalAngkakb = true;
    			};
    			this.inputV[1] = this.inputValue;
    		},

    		getClass(index) {

    			if (this.currentcart === index) {
    				return 'selected-cart';
    			} else if (index % 2 === 0) {
    				return 'selected-cart-genap';
    			} else {
    				return 'selected-cart-ganjil';
    			}
    		},

    		Kirim() {
    			n = this.cart.length;
    			for (let i = 0; i <= n - 1; i++) {
    				dat = this.cart[i];
    				kirimdata(dat);
    			};
    			alert('seleai');;
    		},



    		Map_table() {
    			if (this.showSplit) {
    				this.showSplit = false;
    				this.activeSplitFilter = '';
    				this.currentCartItemId = null;
    				this.selectedItemName = '';
    				this.currentcart = null;
    			};

    			// Reset tipe transaksi saat kembali ke peta meja
    			this.currentTransactionType = null;
    			this.group_harga = '1'; // Reset ke default
    			if (this.move === '') {
    				bx = ambil('cart', 'meja', '.', 'zz');
    				let mcart = JSON.parse(bx);
    				let tcart = new Set(mcart.map(item => item.meja));

    				this.changeLantai(this.lantai[0]);
    				bx = ambil('meja', 'kode', '', 'zz');
    				bx = JSON.parse(bx);
    				bx.forEach(function(item) {
    					item.left = parseFloat(item.left);
    					item.top = parseFloat(item.top);
    					item.width = parseFloat(item.width);
    					item.height = parseFloat(item.height);
    					item.id = parseFloat(item.id);
    					item.cover = parseFloat(item.cover);
    					item.borderRadius = parseFloat(item.borderRadius);

    					existingItem = mcart.find(itema => (itema.meja === item.kode) && itema.cart.length > 4);

    					if (existingItem) {
    						item.ada = '1';
    					} else {
    						item.ada = '0';
    						item.jumlah = 0;
    						item.guest = '';
    					};
    				});
    				this.meja = bx;

    				// this.neja.forEach(item => {
    				//   item.ada = tcart.has(item.kode) ? "1" : "0";
    				//   ; // true jika ada, false jika tidak ada
    				// });

    				// this.currentMeja = '';
    				// this.currentNamaMeja = '';
    			};
    			document.getElementById("Map").style.display = 'flex';
    			this.posisi = 'table';
    			//pesan('123', '2323');
    		},

    		test() {},



    		startDrag(index, event) {
    			if (this.nuser !== 'ADMIN') {
    				return;
    			}

    			this.activeKotakIndex = index;
    			this.initialMouseX = event.clientX;
    			this.initialMouseY = event.clientY;
    			this.initialLeft = this.currentMejas[index].left;
    			this.initialTop = this.currentMejas[index].top;
    			this.initialWidth = this.currentMejas[index].width;
    			this.initialHeight = this.currentMejas[index].height;
    			this.initialBorderRadius = this.currentMejas[index].borderRadius;
    			this.isDragging = true;

    			if (event.ctrlKey) {
    				this.isResizing = true;
    			}

    			if (event.shiftKey) {
    				this.isChangingBorderRadius = true;
    			}

    			window.addEventListener("mousemove", this.handleDrag);
    			window.addEventListener("mouseup", this.stopDrag);
    		},
    		handleDrag(event) {
    			this.isedit = true;
    			if (this.isDragging) {
    				const deltaX = (event.clientX - this.initialMouseX);
    				const deltaY = (event.clientY - this.initialMouseY);

    				if (this.isChangingBorderRadius) {
    					this.currentMejas[this.activeKotakIndex].borderRadius = Math.max(
    						0,
    						this.initialBorderRadius + Math.max(deltaX, deltaY) / 4
    					);
    				} else if (this.isResizing) {
    					this.currentMejas[this.activeKotakIndex].width = this.initialWidth + deltaX / this.lebarl;
    					this.currentMejas[this.activeKotakIndex].height = this.initialHeight + deltaY / this.tinggil;
    				} else {
    					this.currentMejas[this.activeKotakIndex].left = this.initialLeft + deltaX / this.lebarl;
    					this.currentMejas[this.activeKotakIndex].top = this.initialTop + deltaY / this.tinggil;
    				}
    			};
    		},




    		stopDrag() {
    			ss = this.currentMejas[this.activeKotakIndex];
    			ss.timein = '';
    			//      ss.jumlah='';
    			if (ss.image !== '1') {
    				ss.warna = '';
    				ss.fore = '';
    			};
    			for (let key in ss) {
    				if (ss[key] === null || ss[key] === '') {
    					ss[key] = '';
    				}
    			};
    			bx = rubahjson('meja', ss, ss.id);

    			bbb = JSON.stringify(vm.meja);
    			localStorage.setItem('meja', bbb);

    			this.isDragging = false;
    			this.isResizing = false;
    			this.isChangingBorderRadius = false;
    			this.activeKotakIndex = null;
    			window.removeEventListener("mousemove", this.handleDrag);
    			window.removeEventListener("mouseup", this.stopDrag);

    			// this.isedit=false;
    		},
    		showColorMenu(index, event) {
    			event.preventDefault();
    			this.activeContextMenuIndex = index;
    			this.showContextMenu = true;
    			this.contextMenuX = event.clientX;
    			this.contextMenuY = event.clientY;
    			this.contenMeja = this.currentMejas[this.activeContextMenuIndex].nama;
    			this.contenMejafungsi = this.currentMejas[this.activeContextMenuIndex].fungsi;
    			this.contenMejaimage = this.currentMejas[this.activeContextMenuIndex].image;
    			this.contenMejatipe = this.currentMejas[this.activeContextMenuIndex].tipe;
    		},
    		changeColor() {
    			if (this.activeContextMenuIndex !== null) {
    				this.currentMejas[this.activeContextMenuIndex].warna = this.selectedColor;
    				ss = this.currentMejas[this.activeContextMenuIndex];
    				bx = rubahjson('meja', ss);

    				this.hideContextMenu();
    				bbb = JSON.stringify(this.meja);
    				localStorage.setItem('meja', bbb);

    				//this.isedit=false;
    			}
    		},


    		pstartDrag(index, event) {

    			this.activeKotakIndex = index;
    			this.initialMouseX = event.clientX;
    			this.initialMouseY = event.clientY;
    			this.initialLeft = this.currentPayment[index].kiri;
    			this.initialTop = this.currentPayment[index].atas;
    			this.initialWidth = this.currentPayment[index].lebar;
    			this.initialHeight = this.currentPayment[index].tinggi;
    			this.initialBorderRadius = this.currentPayment[index].borderRadius;
    			this.isDragging = true;

    			if (event.ctrlKey) {
    				this.isResizing = true;
    			}

    			if (event.shiftKey) {
    				this.isChangingBorderRadius = true;
    			}

    			window.addEventListener("mousemove", this.phandleDrag);
    			window.addEventListener("mouseup", this.pstopDrag);
    		},
    		phandleDrag(event) {
    			this.isedit = true;
    			if (this.isDragging) {
    				const deltaX = (event.clientX - this.initialMouseX);
    				const deltaY = (event.clientY - this.initialMouseY);


    				if (this.isChangingBorderRadius) {
    					this.currentPayment[this.activeKotakIndex].borderRadius = Math.max(
    						0,
    						this.initialBorderRadius + Math.max(deltaX, deltaY) / 4
    					);
    				} else if (this.isResizing) {
    					this.currentPayment[this.activeKotakIndex].lebar = this.initialWidth + deltaX / this.lebarl;
    					this.currentPayment[this.activeKotakIndex].tinggi = this.initialHeight + deltaY / this.tinggil;
    				} else {
    					this.currentPayment[this.activeKotakIndex].kiri = this.initialLeft + deltaX / this.lebarl;
    					this.currentPayment[this.activeKotakIndex].atas = this.initialTop + deltaY / this.tinggil;
    				}
    			};
    		},
    		pstopDrag() {
    			ss = this.currentPayment[this.activeKotakIndex];
    			if (ss.image !== '1') {
    				ss.warna = '';
    				ss.fore = '';
    			};
    			for (let key in ss) {
    				if (ss[key] === null || ss[key] === '') {
    					ss[key] = '';
    				}
    			};
    			bx = rubahjson('payment', ss, ss.id);
    			bbb = JSON.stringify(vm.payment);
    			localStorage.setItem('payment', bbb);

    			this.isDragging = false;
    			this.isResizing = false;
    			this.isChangingBorderRadius = false;
    			this.activeKotakIndex = null;
    			window.removeEventListener("mousemove", this.phandleDrag);
    			window.removeEventListener("mouseup", this.pstopDrag);

    			// this.isedit=false;
    		},

    		pshowColorMenu(index, event) {
    			event.preventDefault();
    			this.activeContextMenuIndex = index;
    			this.pshowContextMenu = true;
    			this.contextMenuX = event.clientX;
    			this.contextMenuY = event.clientY;
    			this.contenMeja = this.currentPayment[this.activeContextMenuIndex].nama;
    			this.contenMejafungsi = this.currentPayment[this.activeContextMenuIndex].fungsi;
    			this.contenMejaimage = this.currentPayment[this.activeContextMenuIndex].image;
    			this.contenMejatipe = this.currentPayment[this.activeContextMenuIndex].tipe;
    			this.contenMejacolor = this.currentPayment[this.activeContextMenuIndex].fore;
    			this.contenMejasize = this.currentPayment[this.activeContextMenuIndex].fontsize;
    			this.bselectedColor = this.currentPayment[this.activeContextMenuIndex].warna;
    			this.fselectedColor = this.currentPayment[this.activeContextMenuIndex].fore;


    		},

    		pchangeColor() {
    			if (this.activeContextMenuIndex !== null) {
    				this.currentPayment[this.activeContextMenuIndex].warna = this.bselectedColor;
    				ss = this.currentPayment[this.activeContextMenuIndex];
    				
    				bx = rubahjson('payment', ss, ss.id);
    				// this.hideContextMenu();
    				bbb = JSON.stringify(this.meja);
    				localStorage.setItem('payment', bbb);
    				//this.isedit=false;
    			}
    		},
    		ptchangeColor() {
    			if (this.activeContextMenuIndex !== null) {
    				this.currentPayment[this.activeContextMenuIndex].fore = this.fselectedColor;
    				ss = this.currentPayment[this.activeContextMenuIndex];
    				bx = rubahjson('payment', ss, ss.id);
    				// this.hideContextMenu();
    				bbb = JSON.stringify(this.meja);
    				localStorage.setItem('payment', bbb);
    				//this.isedit=false;
    			}
    		},



    		hideContextMenu() {
    			this.activeContextMenuIndex = null;
    			this.pshowContextMenu = false;
    			this.showContextMenu = false;
    			//this.isedit=false;
    		},










    		// split *********************

    		getGridItems(code) {
    			return this.items.filter(item => item.split === code)
    		},
    		selectMasterItem(id) {
    			this.selectedMasterItem = id
    			this.selectedSplitItem = ''
    		},
    		selectGrid(code) {
    			this.selectedGridCode = code
    			this.selectedSplitItem = ''
    		},
    		selectSplitItem(id) {
    			this.selectedSplitItem = id
    			this.selectedMasterItem = ''
    		},
    		getNextAvailableGridCode() {
    			return this.GRID_CODES.split('').find(code => !this.gridCodes.includes(code))
    		},

    		initGrid() {
    			this.gridCodes = [];
    			this.gridCodes.push('A');
    			this.pesant.forEach(item => {
    				// Cek apakah field split tidak kosong
    				if (item.split !== "") {
    					// Jika split belum ada di gridCodes, tambahkan
    					if (!this.gridCodes.includes(item.split)) {
    						this.gridCodes.push(item.split);
    					}
    				}
    			});
    			this.selectedGridCode = 'A';
    		},

    		addGrid() {
    			const nextCode = this.getNextAvailableGridCode()
    			if (nextCode) {
    				this.gridCodes.push(nextCode)
    				this.selectGrid(nextCode)
    			}
    		},
    		removeGrid(code) {
    			this.returnAllItems()
    			const index = this.gridCodes.indexOf(code)
    			if (index > -1) {
    				this.gridCodes.splice(index, 1)
    			}
    			if (this.selectedGridCode === code) {
    				this.selectedGridCode = ''
    				this.selectedSplitItem = ''
    			}
    		},
    		moveOnePiece() {
    			if (!this.selectedGridCode || !this.selectedMasterItem) return
    			const itemIndex = this.items.findIndex(item => item.id === this.selectedMasterItem)
    			if (itemIndex === -1 || this.items[itemIndex].quantity <= 0) return

    			const existingInTarget = this.items.find(item =>
    				item.id === this.selectedMasterItem &&
    				item.split === this.selectedGridCode
    			)

    			if (existingInTarget) {
    				existingInTarget.quantity++
    				this.items[itemIndex].quantity--
    				if (this.items[itemIndex].quantity === 0) {
    					this.items.splice(itemIndex, 1)
    				}
    			} else {
    				const sourceItem = this.items[itemIndex]
    				const newItem = {
    					...sourceItem,
    					id: padNumberWithZeros(generateRandomNumber(), 10), // ID baru
    					quantity: 1,
    					split: this.selectedGridCode
    				}
    				this.items.push(newItem)
    				sourceItem.quantity--
    				if (sourceItem.quantity === 0) {
    					this.items.splice(itemIndex, 1)
    				}
    			}
    		},
    		moveEntireMenu() {
    			if (!this.selectedGridCode || !this.selectedMasterItem) return
    			const itemIndex = this.items.findIndex(item => item.id === this.selectedMasterItem)
    			if (itemIndex === -1) return

    			const sourceItem = this.items[itemIndex]
    			const existingInTarget = this.items.find(item =>
    				item.id === this.selectedMasterItem &&
    				item.split === this.selectedGridCode
    			)

    			if (existingInTarget) {
    				existingInTarget.quantity += sourceItem.quantity
    				this.items.splice(itemIndex, 1)
    			} else {
    				const newItem = {
    					...sourceItem,
    					id: padNumberWithZeros(generateRandomNumber(), 10), // ID baru
    					split: this.selectedGridCode
    				}
    				this.items.push(newItem)
    				this.items.splice(itemIndex, 1)
    			}
    		},
    		moveAllItems() {
    			if (!this.selectedGridCode) return

    			const unsplitItems = this.items.filter(item => item.split === '')
    			unsplitItems.forEach(item => {
    				item.split = this.selectedGridCode
    			})
    		},
    		returnOnePiece() {
    			if (!this.selectedGridCode || !this.selectedSplitItem) return
    			const itemIndex = this.items.findIndex(item =>
    				item.id === this.selectedSplitItem &&
    				item.split === this.selectedGridCode
    			)
    			if (itemIndex === -1) return

    			const splitItem = this.items[itemIndex]
    			let masterItem = this.items.find(item =>
    				item.id === this.selectedSplitItem &&
    				item.split === ''
    			)

    			if (masterItem) {
    				masterItem.quantity++
    			} else {
    				masterItem = {
    					...splitItem,
    					id: padNumberWithZeros(generateRandomNumber(), 10), // ID baru
    					quantity: 1,
    					split: ''
    				}
    				this.items.push(masterItem)
    			}

    			splitItem.quantity--
    			if (splitItem.quantity === 0) {
    				this.items.splice(itemIndex, 1)
    			}

    			this.selectedSplitItem = ''
    		},


    		resetSelectedItem() {
    			this.currentCartItemId = null;
    			this.selectedItemName = '';
    			this.currentcart = null;
    			this.activeSplitFilter = '';
    		},
    		returnEntireMenu() {
    			if (!this.selectedGridCode || !this.selectedSplitItem) return
    			const itemIndex = this.items.findIndex(item =>
    				item.id === this.selectedSplitItem &&
    				item.split === this.selectedGridCode
    			)
    			if (itemIndex === -1) return

    			const splitItem = this.items[itemIndex]
    			let masterItem = this.items.find(item =>
    				item.id === this.selectedSplitItem &&
    				item.split === ''
    			)

    			if (masterItem) {
    				masterItem.quantity += splitItem.quantity
    				this.items.splice(itemIndex, 1)
    			} else {
    				const newItem = {
    					...splitItem,
    					id: padNumberWithZeros(generateRandomNumber(), 10), // ID baru
    					split: ''
    				}
    				this.items.push(newItem)
    				this.items.splice(itemIndex, 1)
    			}

    			this.selectedSplitItem = ''
    		},
    		returnAllItems() {
    			if (!this.selectedGridCode) return

    			const splitItems = this.items.filter(item => item.split === this.selectedGridCode)

    			splitItems.forEach(splitItem => {
    				const masterItem = this.items.find(item =>
    					item.id === splitItem.id &&
    					item.split === ''
    				)

    				if (masterItem) {
    					masterItem.quantity += splitItem.quantity
    					const index = this.items.indexOf(splitItem)
    					this.items.splice(index, 1)
    				} else {
    					splitItem.split = ''
    				}
    			})

    			this.selectedSplitItem = ''
    		},
    		handleBill(code) {
    			
    		},

    		// Di dalam methods: { ... }, ganti fungsi handlePayment yang lama
    		handlePayment(code) {
    			// 1. Simpan perubahan dari array kerja 'items' ke array utama 'pesant'.
    			// Ini adalah langkah krusial yang hilang sebelumnya.
    			this.pesant = this.items;

    			// 2. Perbarui data meja untuk menandakan bahwa ada proses split bill aktif.
    			if (this.mejao) {
    				this.mejao.split = '1'; // Flag untuk menandakan ada split.
    				rubahjson('meja', { split: '1' }, this.mejao.id);
    			}

    			// 3. Simpan seluruh data keranjang yang sudah ter-split ke database.
    			const dataToSave = {
    				meja: this.currentMeja,
    				cart: JSON.stringify(this.pesant).replace(/:null/g, ':""'),
    				brand: xbrand,
    				cab: xcab
    			};
    			rubahjson('cart', dataToSave, dataToSave.meja, 'meja');

    			// 4. Reset item yang dipilih di UI.
    			this.currentCartItemId = null;
    			this.selectedItemName = '';
    			this.currentcart = null;

    			// 5. Atur filter aktif. Ini akan digunakan oleh tampilan keranjang dan kalkulasi.
    			this.activeSplitFilter = code;

    			// 6. Tutup antarmuka split bill.
    			this.showSplit = false;

    			// 7. Beri notifikasi ke kasir.
    			this.pesan(`Mode Pembayaran untuk Bill ${code}. Silakan gunakan tombol payment utama.`, 'info');
    		},


    	}
    });


    const vm = app.mount('#app');




    //============ mulai ============

    document.getElementById("Fungsi").style.display = 'none';




    function bacamaster() {
		
    	document.getElementById('loading-overlay').style.display = 'block';

    	fetch('topi.php')
    		.then(response => {
    			if (!response.ok) {
    				throw new Error(`HTTP error! Status: ${response.status}`);
    			}
    			return response.json();
    		})
    		.then(data => {

    			const toppings = data.map(topping => {
    				return {
    					toping: topping.toping,
    					Group: topping.Group,
    					tipe: topping.tipe,
    					wajib: topping.wajib,
    					max: topping.max,
    					pilih: topping.pilih,
    					ok: topping.ok,
    					items: topping.items.map(item => {
    						return {
    							nama_toping: item.nama_toping,
    							kode_toping: item.kode_toping,
    							quantity: item.quantity,
    							harga: item.harga,
    							pilih: item.pilih,
    							tipe: item.tipe,
    							cek: item.cek,
    							checked: item.checked
    						};
    					})
    				};
    			});
    			vm.toppings = toppings;
    		})
    		.catch(error => {
    			console.error('Error:', error);
    		});



    	//console.log("Memuat data paket...");
    	y = ambil('paket', 'id', 0, 99999);
    	const paketArray = JSON.parse(y);
    	//  JSON.parse(await ambil('kitchen', 'id', '1', '999'));

    	if (paketArray && paketArray.length > 0) {
    		paketArray.forEach(p => {
    			const triggerItemCode = p.barang;

    			// Ganti `this` menjadi `vm`
    			if (!vm.paketData.has(triggerItemCode)) {
    				vm.paketData.set(triggerItemCode, []);
    			}
    			vm.paketData.get(triggerItemCode).push({
    				kode: p.kode,
    				npaket: p.npaket,
    				quantity: parseInt(p.qtt, 10) || 1
    			});
    		});
    	}

    	const paketKeys = Array.from(vm.paketData.keys());
    	
    	// <<< AKHIR TAMBAHAN >>>

    	



    	// vm.toppings.forEach(topping => {
    	//   // Mengonversi "pilih": null menjadi "pilih": 0
    	//   if (topping.pilih === null) {
    	//     topping.pilih = 0;
    	//   }

    	//   // Mengonversi "ok" menjadi numerik
    	//   topping.ok = Number(topping.ok);

    	//   // Mengonversi "max" menjadi numerik
    	//   topping.max = Number(topping.max);

    	//   // Mengonversi "wajib" menjadi boolean
    	//   // topping.wajib = !!topping.wajib;

    	//   // Loop melalui setiap item dalam objek topping
    	//   topping.items.forEach(item => {
    	//     // Mengonversi "quantity" menjadi numerik
    	//     item.quantity = Number(item.quantity);

    	//     // Mengonversi "harga" menjadi numerik
    	//     item.harga = Number(item.harga);

    	//     // Mengonversi "cek" menjadi numerik
    	//     item.cek = Number(item.cek);

    	//     // Mengonversi "checked" menjadi boolean
    	//     item.checked = false;
    	//   });
    	// });


    	bacacart();

    	bx = xambil('lantai', 'kode', '', 'zz');

    	if (bx.startsWith('[')) {
    		vm.lantai = JSON.parse(bx);

    		// bx = ambil('toppings', 'toping', '', 'zz');
    		// vm.toppings = JSON.parse(bx);    

    		bx = xambil('fungsi', 'kode', '', 'zz');
    		vm.fungsi = JSON.parse(bx);

    		bx = xambil('fungsi2', 'kode', '', 'zz');
    		vm.fungsix = JSON.parse(bx);
    		vm.fungsi2 = vm.fungsix.filter(item => item.kelas == '1');
    		vm.fungsi3 = vm.fungsix.filter(item => item.kelas == '2');
    		vm.fungsim = vm.fungsix.filter(item => item.kelas == '3');

    		vm.fungsi2.sort((a, b) => a.kode.localeCompare(b.kode));
    		vm.fungsi3.sort((a, b) => a.kode.localeCompare(b.kode));
    		vm.fungsim.sort((a, b) => a.kode.localeCompare(b.kode));

    		bx = xambil('condiment', 'kode', '', 'zz');
    		vm.condiment = JSON.parse(bx);

    		bx = xambil('menutops', 'kode', '', 'zz');
    		vm.menuTops = JSON.parse(bx);

    		bx = xambil('menugroups', 'kode', '', 'zz');
    		vm.menuGroups = JSON.parse(bx);


    		bacameja();
    		bacapayment();


    		// fetch('topping.php')
    		//   .then(response => response.json())
    		//   .then(data => {
    		//     vm.toppings = data;
    		//   })
    		//   .catch(error => {
    		//     // Tangani kesalahan jika ada
    		//     console.error('Error:', error);
    		//   });

    		//   gg=JSON.stringify(vm.toppings);
    		//   if (gg.substring(0, 1) !== '[') {
    		//     gg = '[' + gg + ']';
    		//  };
    		//  vm.toppings = JSON.parse(gg);


    		bx = xambil('menus', 'kode', '', 'zz');

    		vm.menus = JSON.parse(bx);



    		// =======================================================================
    		// --- AWAL KODE TAMBAHAN UNTUK MENGISI menus.toping ---

    		// 1. Ambil data btoppings yang aktif (ya=1)



    		const btoppingsData = JSON.parse(xambil('btoppings', 'ya', '1', '1'));
    		// 2. Buat "Peta Topping" untuk optimasi agar proses lebih cepat
    		const btoppingsMap = new Map();
    		btoppingsData.forEach(btopping => {
    			if (!btoppingsMap.has(btopping.barang)) {
    				btoppingsMap.set(btopping.barang, []);
    			}
    			btoppingsMap.get(btopping.barang).push(btopping.toppings);
    		});

    		// 3. Loop melalui setiap menu untuk mengisi field 'toping' berdasarkan Peta
    		vm.menus.forEach(menu => {
    			if (btoppingsMap.has(menu.kode)) {
    				// Jika ada, gabungkan kode-kode topping dengan tanda hubung '-'
    				menu.toping = btoppingsMap.get(menu.kode).join('-');
    			} else {
    				// Jika tidak ada, pastikan field 'toping' berisi string kosong
    				menu.toping = '';
    			}

    		});

    		// --- AKHIR KODE TAMBAHAN ---
    		// =======================================================================




    		vm.menus = vm.gabung;
    		gb = {
    			"lantai": vm.lantai,
    			"fungsi": vm.fungsi,
    			"fungsi2": vm.fungsi2,
    			"condiment": vm.condiment,
    			"menutops": vm.menuTops,
    			"meja": vm.meja,
    			"menugroups": vm.menuGroups,
    			"menus": vm.menus
    		};

    		gb = JSON.stringify(gb);
    		localStorage.setItem('gb', gb);
			vm.updateMenuPrices(); 
    	} else {
    		gb = localStorage.getItem('gb');
    		gb = JSON.parse(gb);
    		vm.lantai = gb.lantai;
    		vm.fungsi = gb.fungsi;
    		vm.fungsi2 = gb.fungsi2;
    		vm.condiment = gb.condiment;
    		vm.menutops = gb.menutops;
    		vm.meja = gb.meja;
    		vm.menugroups = gb.menugroups;
    		vm.menus = gb.menus;
    		alert('data lokal');
    	};
    	document.getElementById('loading-overlay').style.display = 'none';
    };

function bacameja() {
        xpos = JSON.parse(localStorage.getItem('xpos')) || {};
        xcab=xpos.cab;
        xbrand=xpos.brand;
        
        let bx = ambil('meja', 'kode', '', 'zz');
        let bxParsed = JSON.parse(bx);
   

  if (bxParsed.length === 0) {
    // Data sampel telah diperbarui dengan struktur yang benar.
    const sampleMeja = [{
        "lantai": "1",
        "kode": "Sample",
        "tipe": "01",
        "nama": "Sample",
        "cover": 0,
        "lastbuka": "",
        "user": "",
        "guest": "",
        "timein": "",
        "timeout": "",
        "jumlah": 0,
        "split": "",
        "join_info": "",
        "left": 10.5,
        "top": 5.0,
        "width": 8.0,
        "height": 12.0,
        "warna": "#004675",
        "fore": "#FFFFFF",
        "borderRadius": 5.0,
        "fungsi": "1",
        "image": "1",
        "ada": "0"
    }];
    
    // Logika untuk menambah data dan membaca ulang tetap sama.
    tambahjson('meja', sampleMeja[0]);
    
    bx = ambil('meja', 'kode', '', 'zz');
    bxParsed = JSON.parse(bx);
  } 

  bxParsed.forEach(function (item) {
    item.left = parseFloat(item.left);
    item.top = parseFloat(item.top);
    item.width = parseFloat(item.width);
    item.height = parseFloat(item.height);
    item.id = parseFloat(item.id);
    item.cover = parseFloat(item.cover);
    item.borderRadius = parseFloat(item.borderRadius);
  });
  
  vm.meja = bxParsed;
};

    function bacapayment() {
    	bx = ambil('payment', 'kode', '', 'zz');
    	bx = JSON.parse(bx);
    	bx.forEach(function(item) {
    		item.kiri = parseFloat(item.kiri);
    		item.atas = parseFloat(item.atas);
    		item.lebar = parseFloat(item.lebar);
    		item.tinggi = parseFloat(item.tinggi);
    		item.id = parseFloat(item.id);
    		item.borderRadius = parseFloat(item.borderRadius);
    	});
    	vm.payment = bx;
    };

    function bacacart() {
    	bx = ambil('cart', 'meja', '', 'zz');
    	jsonData = JSON.parse(bx);
    	//  jsonData = =JSON.parse(JSON.parse(bx));
    	var cartArray = [];
    	// Iterasi setiap objek dalam jsonData

    	jsonData.forEach(function(obj) {

    		if (obj.cart !== '[]') {
    			let cartString = obj.cart;
    			cartString = cartString.replace(/:null/g, ':""');
    			cartString = cartString ? cartString : '[]';
    			try {
    				var cartItems = JSON.parse(cartString);
    				// //console.log(cartItems);
    			} catch (error) {
    				console.error('Error parsing JSON:', error);
    			};

    			//var cartItems = JSON.parse(obj.cart);
    			// Iterasi setiap item dalam cartItems

    			cartItems.forEach(function(item) {
    				// Push item ke dalam array cartArray
    				cartArray.push(item);
    			});
    		}
    	});
    	vm.pesant = cartArray;
    };

    function tambahMeja() {
    	n = document.getElementById("fname").value;
    	if (vm.activeContextMenuIndex !== null && n != '') {
    		tm = vm.currentMejas[vm.activeContextMenuIndex];
    		tm = JSON.parse(JSON.stringify(tm));
    		tm.left = tm.left + 5;
    		tm.top = tm.top + 5;
    		n = document.getElementById("fname").value;
    		tm.kode = n;
    		tm.nama = n;

    		cc = tambahjson('meja', tm);
    		tm.id = cc;
    		vm.meja.push(tm);
    		bbb = JSON.stringify(vm.meja);
    		localStorage.setItem('meja', bbb);
    		document.getElementById("fname").value = '';
    		vm.hideContextMenu();
    	}
    };

    function ptambahMeja() {
    	n = document.getElementById("gname").value;
    	if (vm.activeContextMenuIndex !== null && n != '') {
    		tm = vm.currentPayment[vm.activeContextMenuIndex];
    		tm = JSON.parse(JSON.stringify(tm));
    		tm.kiri = tm.kiri + 5;
    		tm.atas = tm.atas + 5;
    		n = document.getElementById("gname").value;
    		tm.kode = n;
    		tm.nama = n;
    		cc = tambahjson('payment', tm);
    		tm.id = cc;
    		vm.payment.push(tm);
    		bbb = JSON.stringify(vm.payment);
    		localStorage.setItem('payment', bbb);
    		document.getElementById("gname").value = '';
    		vm.hideContextMenu();
    	}
    };

    function updateMeja() {
    	n = document.getElementById("funame").value;
    	nf = document.getElementById("fufungsi").value;
    	ni = document.getElementById("fuimage").value;
    	ht = document.getElementById("ftipe").value;
    	if (vm.activeContextMenuIndex !== null) {
    		tm = vm.currentMejas[vm.activeContextMenuIndex];
    		tm.fungsi = nf;
    		tm.image = ni;
    		tm.nama = n;
    		tm.kode = n;
    		tm.tipe = ht;

    		cc = rubahjson('meja', tm, tm.id, 'id');
    		
    		bbb = JSON.stringify(vm.meja);
    		localStorage.setItem('meja', bbb);
    		document.getElementById("fname").value = '';
    		vm.hideContextMenu();
    	}
    };

    function pupdateMeja() {
    	n = document.getElementById("guname").value;
    	nf = document.getElementById("gufungsi").value;
    	ni = document.getElementById("guimage").value;
    	nc = document.getElementById("gucolor").value;
    	ns = document.getElementById("gusize").value;
    	if (vm.activeContextMenuIndex !== null) {
    		tm = vm.currentPayment[vm.activeContextMenuIndex];
    		tm.fungsi = nf;
    		tm.image = ni;
    		tm.nama = n;
    		tm.kode = n;
    		tm.fore = nc;
    		tm.fontsize = ns;
    		cc = rubahjson('payment', tm, tm.id);
    		bbb = JSON.stringify(vm.payment);
    		localStorage.setItem('payment', bbb);
    		document.getElementById("gname").value = '';
    		vm.hideContextMenu();
    	}
    };


    function deleteMeja() {
    	xx = vm.currentMejas[vm.activeContextMenuIndex].id;
    	const index = vm.meja.findIndex((meja) => meja.id === xx);
    	cc = hapus('meja', 'id', xx);
    	if (cc == '1') {

    		if (index !== -1) {
    			vm.meja.splice(index, 1);
    		};

    		vm.currentMejas.splice(vm.activeContextMenuIndex, 1);
    		ccc = JSON.stringify(vm.currentMejas);
    		bbb = JSON.stringify(vm.meja);
    		localStorage.setItem('meja', bbb);
    	} else {
    		alert('Proses Delete Gagal');
    	}
    	vm.hideContextMenu();
    };

    function pdeleteMeja() {
    	const idToDelete = vm.currentPayment[vm.activeContextMenuIndex].id;
    	const paymentIndex = vm.payment.findIndex((p) => p.id === idToDelete);
    	const cc = hapus('payment', 'id', idToDelete);


    	if (cc == '1') {
    		if (paymentIndex !== -1) {
    			vm.payment.splice(paymentIndex, 1);
    		}

    		vm.currentPayment.splice(vm.activeContextMenuIndex, 1);


    		const updatedPaymentJson = JSON.stringify(vm.payment);
    		localStorage.setItem('payment', updatedPaymentJson);

    	} else {
    		alert('Proses Delete Gagal');
    	}

    	vm.hideContextMenu();
    };


    function cancelMenu() {
    	vm.hideContextMenu();
    };

    function copyMeja() {
    	vm.copymeja = vm.currentMejas[vm.activeContextMenuIndex];
    	vm.hideContextMenu();
    };

    function pcopyMeja() {
    	vm.copymeja = vm.currentPayment[vm.activeContextMenuIndex];
    	vm.hideContextMenu();
    };

    function pasteMeja() {
    	if (vm.copymeja.height > 0) {
    		vm.currentMejas[vm.activeContextMenuIndex].height = vm.copymeja.height;
    		vm.currentMejas[vm.activeContextMenuIndex].width = vm.copymeja.width;
    		vm.currentMejas[vm.activeContextMenuIndex].warna = vm.copymeja.warna;
    		vm.currentMejas[vm.activeContextMenuIndex].borderRadius = vm.copymeja.borderRadius;
    		cc = rubahjson('meja', vm.currentMejas[vm.activeContextMenuIndex], vm.currentMejas[vm.activeContextMenuIndex].id);
    	}
    	vm.hideContextMenu();
    };


    function ppasteMeja() {
    	if (vm.copymeja.tinggi > 0) {
    		vm.currentPayment[vm.activeContextMenuIndex].tinggi = vm.copymeja.tinggi;
    		vm.currentPayment[vm.activeContextMenuIndex].lebar = vm.copymeja.lebar;
    		vm.currentPayment[vm.activeContextMenuIndex].warna = vm.copymeja.warna;
    		vm.currentPayment[vm.activeContextMenuIndex].borderRadius = vm.copymeja.borderRadius;
    		cc = rubahjson('payment', vm.currentPayment[vm.activeContextMenuIndex], vm.currentPayment[vm.activeContextMenuIndex].id);
    	}
    	vm.hideContextMenu();
    };


    function bacaurl(hal, m, s) {
    	let xmlhttp;
    	if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari
    		xmlhttp = new XMLHttpRequest();
    	} else { // code for IE6, IE5
    		xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    	}

    	xmlhttp.onreadystatechange = function() {
    		if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
    			return xmlhttp.responseText;
    		}
    	}
    	url = "https://api.sheetson.com/v2/sheets/" + hal + "/?skip=" + m + "&limit=" + s + "&apiKey=xjAwiVn5HuJak4TlPXi8wD_C3nOMju_kygzojYO9tb-selKH6NjN5_bx8_I&spreadsheetId=1X_3Xmp4K671jI9cjN_PaLO8aagGDVMOM-ED220YysHs";
    	url = url + ((/\?/).test(url) ? "&" : "?") + (new Date()).getTime();
    	xmlhttp.open("GET", url, false);
    	xmlhttp.send();
    	return xmlhttp.response;
    }

    function kirimdata(data) {
    	const apiKey = "xjAwiVn5HuJak4TlPXi8wD_C3nOMju_kygzojYO9tb-selKH6NjN5_bx8_I";
    	const spreadsheetId = "1X_3Xmp4K671jI9cjN_PaLO8aagGDVMOM-ED220YysHs";

    	fetch("https://api.sheetson.com/v2/sheets/Penjualan", {

    			method: "POST",
    			headers: {
    				"Authorization": `Bearer ${apiKey}`,
    				"X-Spreadsheet-Id": spreadsheetId,
    				"Content-Type": "application/json"
    			},
    			body: JSON.stringify(data)
    		})
    		.then(response => response.json())
    		.then(result => {})
    		.catch(error => {
    			alert("Kesalahan:\n" + JSON.stringify(error));
    		});

    }

    function generateRandomNumber() {
    	const min = 0;
    	const max = 999999;
    	return Math.floor(Math.random() * (max - min + 1)) + min;
    }

    function padNumberWithZeros(number, length) {
    	let str = number.toString();
    	while (str.length < length) {
    		str = '0' + str;
    	}
    	return str;
    }

    vm.nomor = generateRandomNumber();
    vm.nomor = padNumberWithZeros(vm.nomor, 6);

    n = 0;
    // history.pushState(null, null, window.location.href);
    // history.back();
    // window.onpopstate = () => {n=n+1;history.forward()};

    //  bbb=JSON.stringify(vm.meja);
    //  localStorage.setItem('meja', bbb);

    tampil = 2;

    tampil = 2;
    setInterval(function() {
    	vm.jam = new Date().toLocaleTimeString('id-ID', {
    		hour12: false
    	});
    	if (tampil < 0) {
    		document.getElementById("app").style.display = 'block';
    	} else {
    		tampil = tampil - 1;
    	};

    	if (vm.ya > 0 && vm.cart.length > 0 && vm.posisi === 'order') {
    		vm.ya = vm.ya - 1;

    		let lastSection = document.querySelector(".selected-cart");

    		if (lastSection) {
    			lastSection.scrollIntoView({
    				behavior: "smooth"
    			});
    		} else {
    			lastSection = document.querySelector(".cart-item:last-child");

    			// ===== PERBAIKAN DI SINI =====
    			// Pastikan elemen ditemukan sebelum mencoba scroll
    			if (lastSection) {
    				lastSection.scrollIntoView({
    					behavior: "smooth"
    				});
    			}
    			// =============================
    		}
    	};

    }, 150);


    // function updateJam() {
    //   const jamSaatIni = new Date();
    //   const jam = String(jamSaatIni.getHours()).padStart(2, '0');
    //   const menit = String(jamSaatIni.getMinutes()).padStart(2, '0');
    //   const detik = String(jamSaatIni.getSeconds()).padStart(2, '0');
    //   const waktuSaatIni = `${jam}:${menit}:${detik}`;
    //   // Menampilkan jam saat ini di dalam elemen dengan id "jam"
    //   document.getElementById('jam').textContent = waktuSaatIni;
    // }
    // Memanggil fungsi updateJam setiap detik
    // setInterval(updateJam, 1000);
    // // Memanggil fungsi updateJam saat halaman dimuat pertama kali
    // updateJam();




    //   setInterval(function(){
    //   window.location.reload();
    //   window.stop();

    // },1000)



    digits = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'];
    document.getElementById("overlogin").style.display = "block";
    document.getElementById("userlog").click();


    alertContainer = document.getElementById('custom-alert');
    alertButton = document.getElementById('custom-alert-button');

    alertButton.addEventListener('click', () => {
    	alertContainer.style.display = 'none';
    });


    function pesan(title, message) {
    	const alertContainer = document.getElementById('custom-alert');
    	const alertButton = document.getElementById('custom-alert-button');
    	const alertTitle = document.getElementById('custom-alert-title');
    	const alertMessage = document.getElementById('custom-alert-message');

    	alertTitle.textContent = title;
    	alertMessage.textContent = message;
    	alertContainer.style.display = 'flex';
    };


    function yesno(message, callback) {
    	var overlay = document.getElementById("overlay2");
    	var messageElem = document.getElementById("pesan_alert");
    	var yesBtn = document.getElementById("btn_yes");
    	var noBtn = document.getElementById("btn_no");

    	messageElem.innerHTML = message;

    	yesBtn.addEventListener("click", function() {
    		overlay.style.display = "none";
    		callback(true);
    	});

    	noBtn.addEventListener("click", function() {
    		overlay.style.display = "none";
    		callback(false);
    	});

    	overlay.style.display = "flex";
    }

    // Contoh penggunaan
    var message = `Ini adalah pesan peringatan yang menarik!<br>
                Ini adalah baris kedua dari pesan.<br>
                Dan ini adalah baris ketiga.`;

    // yesno(message, function(result) {
    //   if (result) {
    //     console.log("Anda memilih Ya");
    //   } else {
    //     console.log("Anda memilih Tidak");
    //   }
    // });

    function insert_jualx() {
    	x = vm.cartSubtotal;
    	let insertCalled = false;
    	if (vm.xkembali > 0 && !insertCalled && vm.cartSubtotal > 0 ) {
    		yesno('Apakah tutup transaksi dan print struk ?', function(result) {
    			if (result && !insertCalled) {
    				insertCalled = true; // Mengatur penanda menjadi true
    				insert_jual2()
    			} else {
    				vm.loop += 1;
    			};
    		});
    	};
    }

    // Di dalam file: pos.js

    function gennomor(nomorTerakhir) {
    	// 1. Ambil data 'xpos' dari localStorage untuk mendapatkan kode mesin
    	let kodeMesin = 'XX'; // Nilai default jika tidak ditemukan
    	try {
    		const xposData = localStorage.getItem('xpos');
    		if (xposData) {
    			const xpos = JSON.parse(xposData);
    			// Pastikan kode mesin ada dan formatnya 2 digit
    			if (xpos.mesin) {
    				kodeMesin = String(xpos.mesin).padStart(2, '0');
    			}
    		}
    	} catch (e) {
    		console.error("Gagal membaca kode mesin dari localStorage:", e);
    	}

    	// 2. Dapatkan tahun saat ini (2 digit)
    	const tahunSekarang = new Date().getFullYear().toString().slice(-2);

    	// 3. Cek nomor terakhir
    	if (nomorTerakhir && nomorTerakhir.includes('-')) {
    		const parts = nomorTerakhir.split('-');
    		const brandDariNomor = parts[0];
    		const cabDariNomor = parts[1];
    		const tahunDariNomor = parts[2];

    		// Ambil bagian nomor urut (contoh: 'XX000001')
    		const urutanTerakhir = parts[3];

    		// Jika tahun sama, brand sama, dan cabang sama, lanjutkan nomor urut
    		if (tahunDariNomor === tahunSekarang && brandDariNomor === xbrand && cabDariNomor === xcab) {
    			// Ambil 6 digit terakhir untuk nomor urut
    			const angkaUrutan = parseInt(urutanTerakhir.slice(2), 10);
    			const nomorUrutBaru = String(angkaUrutan + 1).padStart(6, '0');
    			return `${xbrand}-${xcab}-${tahunSekarang}-${kodeMesin}${nomorUrutBaru}`;
    		}
    	}

    	// 4. Jika tidak ada nomor terakhir yang valid (awal hari, tahun baru, dll.), mulai dari 1
    	const nomorAwal = '1'.padStart(6, '0');
    	return `${xbrand}-${xcab}-${tahunSekarang}-${kodeMesin}${nomorAwal}`;
    }

    // File: pos.js
    // GANTI SELURUH FUNGSI LAMA ANDA DENGAN YANG INI




    function insert_jual2() {
		return;
    	// 1. Baca kode mesin dari localStorage
    	let kodeMesin = 'XX';
    	try {
    		const xposData = localStorage.getItem('xpos');
    		if (xposData) {
    			const xpos = JSON.parse(xposData);
    			if (xpos.mesin) {
    				kodeMesin = String(xpos.mesin).padStart(2, '0');
    			}
    		}
    	} catch (e) {
    		console.error("Gagal membaca kode mesin dari localStorage:", e);
    	}

    	// 2. Generate nomor transaksi baru
    	const data = ambilakhir('jual', 'nomor', '', '');
    	const na = gennomor(data === '[]' ? '' : JSON.parse(data)[0].nomor);
    	vm.no_jual = na; // Set nomor jual agar bisa digunakan oleh 'tutup_ok'

    	// 3. Filter item hanya yang sesuai dengan split filter aktif
    	const activeSplitItems = vm.cart.filter(item => item.split === vm.activeSplitFilter);

    	// Hitung total hanya untuk item yang aktif
    	const activeSubtotal = activeSplitItems.reduce((total, item) => {
    		if (!item.payment) {
    			return total + item.jumlah;
    		}
    		return total;
    	}, 0);

    	const activeDisc = activeSplitItems.reduce((total, item) => {
    		if (!item.payment) {
    			return total + item.disc;
    		}
    		return total;
    	}, 0);

    	const activeService = activeSplitItems.reduce((total, item) => {
    		if (!item.payment) {
    			return total + item.service;
    		}
    		return total;
    	}, 0);

    	const activeTax = activeSplitItems.reduce((total, item) => {
    		if (!item.payment) {
    			return total + item.pajak;
    		}
    		return total;
    	}, 0);

    	const activePayment = activeSplitItems.reduce((total, item) => {
    		if (item.payment) {
    			return total + item.harga;
    		}
    		return total;
    	}, 0);

    	// 4. Persiapkan data HANYA untuk tabel 'jual'
    	var ijual = {
    		"tipe": vm.mejao.tipe,
    		"brand": xbrand,
    		"cab": xcab,
    		"komplit": "1",
    		"nomor": na,
    		"tanggal": new Date().toISOString().slice(0, 10),
    		"jamm": getWaktu(),
    		"jams": getWaktu(),
    		"shift": vm.register.shift || 1,
    		"guest": vm.mejao.guest + (vm.activeSplitFilter ? ` (Split ${vm.activeSplitFilter})` : ''),
    		"cover": Number(vm.mejao.cover) || 0,
    		"segmen": "",
    		"member": "",
    		"jumlah": activeSubtotal - activeDisc + activeService + activeTax,
    		"bayar": activePayment,
    		"meja": vm.mejao.kode,
    		"ttax": activeTax,
    		"ttot": activeSubtotal,
    		"tserv": activeService,
    		"user": vm.nuser,
    		"batal": 0,
    		"kasir": vm.kuser,
    		"register": vm.register.nomor,
    		"mesin": kodeMesin,
    		"deliver": "0",
    		"cash": activePayment - (vm.xkembali || 0),
    		"card": 0,
    		"voucher": 0,
    		"house": 0,
    		"gift": 0,
    		"usia": "0",
    		"sex": "0",
    		"kembali": vm.xkembali || 0,
    		"rounding": 0,
    		"pvoucher": 0,
    		"diskrupiah": 0
    	};

    	// DEBUG: Tampilkan data yang akan dikirim untuk verifikasi
    	//console.log('DATA JUAL YANG DIKIRIM (setelah perbaikan):', JSON.stringify(ijual, null, 2));

    	// 5. Kirim data header ke tabel 'jual'
    	insertData('jual', [ijual]);
		insert_pesani(na);

    	// 6. Update data register kasir jika sedang aktif
    	if (vm.pos.register && vm.register.open) {
    		let bx = JSON.parse(ambilakhir('register', 'nomor', vm.register.nomor, vm.register.nomor));
    		if (bx.length > 0) {
    			bx = bx[0];
    			bx.frek = Number(bx.frek) + 1;
    			bx.jumlah = Number(bx.jumlah) + Number(ijual.jumlah);
    			bx.cash = Number(bx.cash) + Number(ijual.cash);
    			bx.card = Number(bx.card) + Number(ijual.card);
    			bx.noakhir = na;
    			rubahjson('register', bx, bx.nomor, 'nomor');
    		}
    	}
    };

function insert_pesani(nomo) {
	return
    pesani = {};
    pes = {};
    no = 0;
    //alert(JSON.stringify(vm.cart));
    vm.cart.forEach(item => {
        no += 1;
        pesani.noit = String(no).padStart(2, '0');
        pesani.brand = item.brand;
        pesani.cab = item.cab;
        pesani.payment = item.payment;
        pesani.kode = item.kode;
        gg = pesani.kode; // Menyimpan kode item induk
        pesani.name = item.name;
        pesani.kgroup = item.kgroup;
        pesani.group_name = item.group_name;
        pesani.quantity = item.quantity;
        qq = pesani.quantity; // Menyimpan kuantitas item induk
        pesani.harga = item.harga;
        pesani.price = item.price;
        pesani.discp = parseFloat(item.discp);
        pesani.discr = parseFloat(item.discr);
        pesani.netto = item.netto;
        pesani.disc = item.disc;
        pesani.ppn = item.ppn;
        pesani.pajak = item.pajak;
        pesani.serv = item.serv;
        pesani.service = item.service;
        pesani.jumlah = item.jumlah;
        pesani.nomor = nomo;
        pesani.meja = item.meja;
        pesani.edc = item.edc;
        pesani.nocard = item.nocard;
        pesani.tglo = item.tglo;

        if (item.edc == 'CASH') {
            pesani.jumlah = pesani.harga - vm.xkembali;
        }
        if (pesani.payment == '10') {
            pesani.harga = item.harga - vm.xkembali;
            //alert(pesani.harga);
        };
        yy = pesani;
        cc = tambahjson('pesani', pesani);

        // Blok untuk Toppings (tidak diubah)
        if (item.toppings && item.toppings.length > 0) {
            item.toppings.forEach(topping => {
                ite = 0;
                topping.items.forEach(itemd => {
                    ite += 1;
                    pesanid = {};
                    pesanid.brand = xbrand;
                    pesanid.cab = xcab;
                    pesanid.noit = String(no).padStart(2, '0') + String(ite).padStart(2, '0');
                    pesanid.sub = 1;
                    pesanid.kode = itemd.kode_toping;
                    pesanid.name = itemd.nama_toping;
                    pesanid.quantity = qq;
                    pesanid.price = itemd.harga;
                    pesanid.nomor = nomo;
                    pesanid.nocard = gg;
                    pesanid.tglo = yy.tglo;
                    pesanid.meja = yy.meja;
                    cc = tambahjson('pesani', pesanid);
                });
            });
        }
        
        // ==========================================================
        // AWAL TAMBAHAN KODE UNTUK 'paketItems'
        // ==========================================================
        if (item.paketItems && item.paketItems.length > 0) {
            let ite_paket = 0;
            item.paketItems.forEach(paketItem => {
                ite_paket += 1;
                let pesanipaket = {};
                
                // Mengambil data dari item induk (yy)
                pesanipaket.brand = yy.brand;
                pesanipaket.cab = yy.cab;
                pesanipaket.nomor = yy.nomor;
                pesanipaket.meja = yy.meja;
                pesanipaket.tglo = yy.tglo;

                // Mengisi data spesifik dari paketItem
                pesanipaket.kode = paketItem.kode;
                pesanipaket.name = paketItem.name;
                
                // **Logika utama: mengalikan kuantitas induk dengan kuantitas paket**
                pesanipaket.quantity = qq * paketItem.quantity;

                // Menandakan ini adalah sub-item, dengan harga 0 (karena sudah termasuk dalam harga paket)
                pesanipaket.sub = 1;
                pesanipaket.price = 0; 
                pesanipaket.harga = 0;

                // Membuat nomor item unik, 'P' untuk menandakan 'Paket'
                pesanipaket.noit = String(no).padStart(2, '0') + 'P' + String(ite_paket).padStart(2, '0'); 
                
                // Menggunakan kode item induk sebagai referensi (disimpan di nocard)
                pesanipaket.nocard = gg; 

                cc = tambahjson('pesani', pesanipaket);
            });
        }
        // ==========================================================
        // AKHIR TAMBAHAN KODE
        // ==========================================================

    });
    oo = {};
    oo.komplit = '1',
    oo.JAMS = getWaktu();
    oo.GUEST = vm.mejao.guest;
    bx = rubahjson('jual', oo, nomo, 'NOMOR');
    vm.pesant = vm.pesant.filter(item => item.meja !== vm.currentMeja);
    vm.mejao.jumlah = 0;
    vm.mejao.user = '';
    vm.mejao.guest = '';
    vm.mejao.cover = 0;
    bx = rubahjson('meja', vm.mejao, vm.mejao.id);
    ss = {};
    ss.meja = vm.currentMeja;
    ss.cart = '';
    bx = rubahjson('cart', ss, ss.meja, 'meja');
    vm.updatecart2();
    vm.Map_table();
    document.getElementById("Fungsi").style.display = 'none';
};


    function hideConfirm() {
    	var modal = document.getElementById("confirmModal");
    	modal.style.display = "none";
    }

function insert_jual(action) {
    // Ganti logika lama dengan pemicu konfirmasi baru
    if (vm.xkembali >= 0 && vm.cartSubtotal > 0) {
        vm.xfungsi('tutup_bayar_otomatis');
    } else {
		//   this.hideConfirm();
	}
}

    function confirmAction(action) {
    	var modal = document.getElementById("confirmModal");
    	modal.style.display = "none";
    	if (action) {
    		aaa = aaa + 1;
    		insert_jual2()
    	} else {}
    }

    function getWaktu() {
    	let now = new Date();

    	let year = now.getFullYear();
    	let month = String(now.getMonth() + 1).padStart(2, '0');
    	let day = String(now.getDate()).padStart(2, '0');

    	let hours = String(now.getHours()).padStart(2, '0');
    	let minutes = String(now.getMinutes()).padStart(2, '0');
    	let seconds = String(now.getSeconds()).padStart(2, '0');

    	// Format standar SQL: YYYY-MM-DD HH:MM:SS
    	return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
    }

    bacatoping();


    function bacatoping() {
    	bx = xambil('toppings', 'toping', '', 'zz');
    	toppings = (typeof bx === 'string') ? JSON.parse(bx) : bx;

    	bx = xambil('topping_items', 'kode_toping', '', 'zz');
    	toppingItems = JSON.parse(bx);

    	function combineData(toppings, toppingItems) {
    		const menu = [];
    		toppings.forEach(topping => {
    			const item = {
    				toping: topping.toping,
    				Group: topping.groupname,
    				tipe: topping.tipe,
    				wajib: topping.wajib === "1",
    				max: parseInt(topping.max),
    				pilih: 0,
    				ok: 0,
    				items: [] // Inisialisasi array untuk menyimpan data topping_items yang sesuai
    			};

    			// Filter topping_items yang sesuai dengan topping_id dari objek topping saat ini
    			const matchingItems = toppingItems.filter(item => item.topping_id === topping.id);

    			// Iterasi melalui setiap item yang sesuai dan tambahkan ke dalam properti 'items' pada objek topping
    			matchingItems.forEach(matchingItem => {
    				item.items.push({
    					nama_toping: matchingItem.nama_toping,
    					kode_toping: matchingItem.kode_toping,
    					quantity: parseInt(matchingItem.quantity),
    					harga: parseInt(matchingItem.harga),
    					pilih: parseInt(matchingItem.pilih),
    					tipe: matchingItem.tipe,
    					cek: parseInt(matchingItem.cek),
    					checked: matchingItem.checked === "true"
    				});
    			});

    			// Tambahkan objek topping beserta item-itemnya ke dalam array menu
    			menu.push(item);
    		});
    		return menu;
    	}

    	const menu = combineData(toppings, toppingItems);
    	qq = {
    		Menu: menu
    	};
    	vm.toppings = qq.Menu;

    }

    function insertData(tableName, data) {


    	if (typeof data === 'object' && !Array.isArray(data) && data !== null) {
    		// Jika object, jadikan array dengan object tersebut sebagai elemennya
    		data = [data];
    	};

    	$('#loader').show();
    	$('#message').empty();

    	const requestData = {
    		table: tableName,
    		data: data
    	};

    	$.ajax({
    		url: 'insert_data.php',
    		type: 'POST',
    		contentType: 'application/json',
    		data: JSON.stringify(requestData),

    		success: function(response) {
    			$('#loader').hide();
    			if (response.success) {
    				$('#message').html(`<div class="message success">${response.message}</div>`);
    			} else {
    				$('#message').html(`<div class="message error">${response.message}</div>`);
    			}
    		},
    		error: function(xhr, status, error) {
    			$('#loader').hide();
    			let errorMessage = 'An error occurred';
    			try {
    				const response = JSON.parse(xhr.responseText);
    				errorMessage = response.message || error;
    			} catch (e) {
    				errorMessage = error;
    			}
    			$('#message').html(`<div class="message error">Error: ${errorMessage}</div>`);
    		}
    	});
    };

    function roundToTwo(num) {
    	return num;
    	// return Math.round(num * 100) / 100;
    };

    window.onpageshow = function(event) {
    	if (event.persisted) { // Halaman dari cache
    		vm.baca_set();
    		vm.baca_bhs();

    	}
    };

    function js(a) {
    	alert(JSON.stringify(a));
    };





    function closePasswordModal() {
    	const modal = document.getElementById('passwordModal');
    	const frame = document.getElementById('passwordFrame');
    	if (modal) {
    		modal.style.display = 'none';
    		frame.src = 'about:blank';
    	}
    }

    String.prototype.center = function(width, char = ' ') {
    	const padding = Math.max(0, width - this.length);
    	const left = Math.floor(padding / 2);
    	const right = padding - left;
    	return char.repeat(left) + this + char.repeat(right);
    };



