<?php
defined("BASEPATH") or exit("No direct script access allowed");
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
	/**
		* Penjualan
	*/
		class Penjualan extends CI_Controller
		{
		/**
			* __construct
			*
			* @return void
		*/
			
			public function __construct()
			{
				parent::__construct();
				
			//cek sesi login
				cek_session_login();
				
				$this->load->model("model_penjualan");
				$this->load->model('Komisi_sales_model', 'komisi_sales');
				$this->load->model('Komisi_penjualan_model', 'komisi_penjualan');
				$this->load->model('model_dropshiper', 'dropship');
				$this->load->model('Journal_model','journal');
				$this->load->model('Kas_model','kas');
				$this->load->dbforge();
			//default global perpage
				$this->perPage = 10;
			//global title
				$this->title = info()["title"];
			//session id user
				$this->iduser = $this->session->idu;
				$this->ensureTaxSchema();
				bayar_order_access_id();
			}

			private function ensureTaxSchema()
			{
				if (!$this->db->table_exists('invoice')) {
					return;
				}

				$fields = [];

				if (!$this->db->field_exists('pajak', 'invoice')) {
					$fields['pajak'] = [
						'type' => 'FLOAT',
						'null' => false,
						'default' => 0,
					];
				}

				if (!$this->db->field_exists('total_pajak', 'invoice')) {
					$fields['total_pajak'] = [
						'type' => 'INT',
						'constraint' => 11,
						'null' => false,
						'default' => 0,
					];
				}

				if (!empty($fields)) {
					$this->dbforge->add_column('invoice', $fields);
				}
			}

			private function ensureBahanUkuranDefaultSchema()
			{
				if (!$this->db->table_exists('bahan')) {
					return;
				}

				if ($this->db->field_exists('ukuran_default', 'bahan')) {
					return;
				}

				$this->dbforge->add_column('bahan', [
					'ukuran_default' => [
						'type' => 'VARCHAR',
						'constraint' => 100,
						'null' => true,
						'default' => '',
						'after' => 'barcode',
					],
				]);

				if (
					$this->db->table_exists('produk') &&
					$this->db->field_exists('id_produk', 'bahan') &&
					$this->db->field_exists('ukuran', 'produk')
				) {
					$this->db->query('
						UPDATE `bahan`
						INNER JOIN `produk` ON `produk`.`id` = `bahan`.`id_produk`
						SET `bahan`.`ukuran_default` = `produk`.`ukuran`
						WHERE (`bahan`.`ukuran_default` IS NULL OR `bahan`.`ukuran_default` = "")
					');
				}
			}

			private function resolveUkuranDefault($row, $fallback = '')
			{
				if (is_object($row)) {
					$value = isset($row->ukuran_default) ? $row->ukuran_default : '';
				} else {
					$value = is_array($row) && isset($row['ukuran_default']) ? $row['ukuran_default'] : '';
				}

				$value = trim((string) $value);
				return $value !== '' ? $value : (string) $fallback;
			}

			private function getBahanUkuranDefaultById($id_bahan, $fallback = '')
			{
				$this->ensureBahanUkuranDefaultSchema();
				$id_bahan = (int) $id_bahan;
				if ($id_bahan <= 0) {
					return (string) $fallback;
				}

				$row = $this->model_app->pilih_where('ukuran_default', 'bahan', ['id' => $id_bahan])->row();
				return $this->resolveUkuranDefault($row, $fallback);
			}

			private function getKomposisiVariantOptionsByBahan($id_bahan)
			{
				$id_bahan = (int) $id_bahan;
				if (
					$id_bahan <= 0 ||
					!$this->db->table_exists('bahan') ||
					!$this->db->table_exists('bahan_komposisi') ||
					!$this->db->field_exists('parent_bahan_id', 'bahan') ||
					!$this->db->field_exists('varian_warna', 'bahan') ||
					!$this->db->field_exists('varian_ukuran', 'bahan')
				) {
					return [];
				}

				$rows = $this->db
					->select('
						komponen.id AS id_komponen,
						komponen.title AS komponen_title,
						varian.id AS id_varian,
						varian.title AS varian_title,
						varian.varian_warna,
						varian.varian_ukuran
					', false)
					->from('bahan_komposisi')
					->join('bahan komponen', 'komponen.id = bahan_komposisi.id_bahan_komponen', 'inner')
					->join('bahan varian', 'varian.parent_bahan_id = komponen.id AND varian.pub = 1', 'inner')
					->where('bahan_komposisi.id_bahan_parent', $id_bahan)
					->order_by('komponen.title', 'ASC')
					->order_by('varian.varian_warna', 'ASC')
					->order_by('varian.varian_ukuran', 'ASC')
					->get()
					->result();

				$options = [];
				$used = [];
				foreach ($rows as $row) {
					$value = trim((string) $row->varian_title);
					if ($value === '') {
						$label = trim(trim((string) $row->varian_warna).' / '.trim((string) $row->varian_ukuran), ' /');
						$value = trim((string) $row->komponen_title.($label !== '' ? ' - '.$label : ''));
					}

					if ($value === '' || isset($used[$value])) {
						continue;
					}

					$used[$value] = true;
					$options[] = [
						'id' => (int) $row->id_varian,
						'id_komponen' => (int) $row->id_komponen,
						'value' => $value,
						'label' => $value,
						'ukuran' => trim((string) $row->varian_ukuran),
					];
				}

				return $options;
			}

			private function getKomposisiVariantOptionsMap($detail)
			{
				$map = [];
				if (!is_array($detail)) {
					return $map;
				}

				foreach ($detail as $row) {
					$id_bahan = isset($row['idbahan']) ? (int) $row['idbahan'] : 0;
					if ($id_bahan <= 0 || isset($map[$id_bahan])) {
						continue;
					}

					$options = $this->getKomposisiVariantOptionsByBahan($id_bahan);
					if (!empty($options)) {
						$map[$id_bahan] = $options;
					}
				}

				return $map;
			}
			
		/**
			* cart
			*
			* @return void
		*/
			
			public function cart()
			{
			//cek jika di method GET message error
				cek_nput_post("GET");
				cek_crud_akses(8, "json");
				$data["komisi_sales_aktif"] = $this->komisi_sales->isFeatureEnabled();
				$data["dropshipper_aktif"] = $this->dropship->isFeatureEnabled();
				$data["komisi_penjualan_aktif"] = $this->komisi_penjualan->isFeatureEnabled();
				
				//post id invoice
				$id = $this->input->post("id");
			//post type invoice
				$edit = $this->input->post("edit");
				if ((int) $id <= 0) {
					$this->clear_stale_cart_references();
				}
				
				$data["referal"] = $this->model_app->view_where('referal', ['pub' => 1])->result_array();
				$data["result_produk"] = $this->model_app->view_where('produk', ['pub' => 1])->result_array();
				$data["sales_users"] = $data["komisi_sales_aktif"] ? $this->komisi_sales->getSalesOptions() : [];
				$data["sales_penjualan_users"] = $data["komisi_penjualan_aktif"] ? $this->komisi_penjualan->getSalesOptions() : [];
				
				$_select = "SUM(jumlah * harga) AS `jml`";
				if ($id > 0) {
				//0
					$data["echo"] = 0;
					$data["type"] = $edit;
					$data["diskon"] = $this->model_app->diskon("bayar_invoice_detail", [
						"bayar_invoice_detail.id_invoice" => $id,
					]);
					$this->cek_konsumen_kosong($id);
					$data["id"] = $id;
					$data["detail"] = $this->model_app->produk_cart([
						"invoice_detail.id_invoice" => $id,
					]);
					$data["proses"] = $this->model_app
					->edit("invoice", ["id_invoice" => $id])
					->row_array();
					
				//sum detail
					$cdetail = $this->model_app->cek_total("invoice_detail", $_select, [
						"id_invoice" => $id,
					]);
					$data["cdetail"] = $cdetail->jml;
				//end
					
				//hapus data kosong
					$this->cek_data_kosong($id);
				} else {
					$cari_last_invoice = $this->model_app->view_where("tb_users", [
						"last_invoice >" => 0,
						"id_user" => $this->iduser,
					]);
					if ($cari_last_invoice->num_rows() > 0) {
					//1
						$data["echo"] = 1;
						$rows = $cari_last_invoice->row();
						$data["type"] = "baru";
						$data["diskon"] = $this->model_app->diskon(
							"bayar_invoice_detail",
							["bayar_invoice_detail.id_invoice" => $rows->last_invoice]
						);
						$this->cek_konsumen_kosong($rows->last_invoice);
						$data["id"] = $rows->last_invoice;
						$data["detail"] = $this->model_app->produk_cart([
							"invoice_detail.id_invoice" => $rows->last_invoice,
						]);
						$data["proses"] = $this->model_app
						->edit("invoice", ["id_invoice" => $rows->last_invoice])
						->row_array();
					//sum detail
						$cdetail = $this->model_app->cek_total(
							"invoice_detail",
							$_select,
							["id_invoice" => $rows->last_invoice]
						);
						$data["cdetail"] = $cdetail->jml;
					//end
						
					//hapus data kosong
						$this->cek_data_kosong($rows->last_invoice);
					} else {
					//2
						$data["echo"] = 2;
						$search = $this->model_app->view_where("invoice", [
							"id_invoice" => $this->session->cart,
						]);
						if ($search->num_rows() > 0) {
						//3
							$data["echo"] = 3;
							$rows = $search->row();
							$data["type"] = "baru";
							$data["diskon"] = $this->model_app->diskon(
								"bayar_invoice_detail",
								["bayar_invoice_detail.id_invoice" => $rows->id_invoice]
							);
							
							$this->cek_konsumen_kosong($rows->id_invoice);
							$data["id"] = $rows->id_invoice;
							$data["detail"] = $this->model_app->produk_cart([
								"invoice_detail.id_invoice" => $rows->id_invoice,
							]);
							$data["proses"] = $this->model_app
							->edit("invoice", ["id_invoice" => $rows->id_invoice])
							->row_array();
						//sum detail
							$cdetail = $this->model_app->cek_total(
								"invoice_detail",
								$_select,
								["id_invoice" => $rows->id_invoice]
							);
							$data["cdetail"] = $cdetail->jml;
						//end
							
						//hapus data kosong
							$this->cek_data_kosong($rows->id_invoice);
						} else {
							$search = $this->model_app->view_where_ordering_limit(
								"invoice",
								["id_user" => $this->iduser, "id_konsumen" => 1, 'POS' => 'N', 'status' => 'baru'],
								"id_invoice",
								"DESC",
								1
							);
							if ($search->num_rows() > 0) {
							//4 edit
								$rows = $search->row();
								$data["echo"] = 4;
								$data["type"] = "baru";
								$data["diskon"] = $this->model_app->diskon(
									"bayar_invoice_detail",
									[
										"bayar_invoice_detail.id_invoice" =>
										$rows->id_invoice,
									]
								);
								$this->cek_konsumen_kosong($rows->id_invoice);
								$data["id"] = $rows->id_invoice;
								$data["detail"] = $this->model_app->produk_cart([
									"invoice_detail.id_invoice" => $rows->id_invoice,
								]);
								$data["proses"] = $this->model_app
								->edit("invoice", [
									"id_invoice" => $rows->id_invoice,
								])
								->row_array();
							//sum detail
								$cdetail = $this->model_app->cek_total(
									"invoice_detail",
									$_select,
									["id_invoice" => $rows->id_invoice]
								);
								$data["cdetail"] = $cdetail->jml;
							//end
								$this->cek_data_kosong($rows->id_invoice);
								
							} else {
							//5 input
								
								$data["echo"] = 5;
								$data["type"] = "baru";
				$autoNumber = next_transaction_number();
								
				$orderCreatedAt = new DateTimeImmutable('now');
				$defaultDeadline = $orderCreatedAt->modify('+4 hours');
				$data_arr = [
					"id_transaksi" => $autoNumber,
					"id_konsumen" => 1,
					"id_user" => $this->iduser,
					"id_marketing" => $this->iduser,
					"tgl_trx" => $orderCreatedAt->format("Y-m-d"),
					"jam_order" => $orderCreatedAt->format("H:i:s"),
					"tgl_ambil" => $defaultDeadline->format("Y-m-d H:i:s"),
									"status" => "baru",
									"sesi_cart" => session_id(),
								];
								
								$data["autonumber"] = $autoNumber;
								$input = $this->model_app->input("invoice", $data_arr);
								if ($input["status"] == "error") {
									echo $input["msg"];
									exit();
								}
								$last_id = $this->db->insert_id();
								$datain = [
									"id_invoice" => $last_id,
									"id_produk" => 1,
									"id_bahan" => 1,
									"jenis_cetakan" => 1,
									"jumlah" => 1,
								];
							// $this->db->insert("invoice_detail", $datain);
								$data["diskon"] = $this->model_app->diskon(
									"bayar_invoice_detail",
									["bayar_invoice_detail.id_invoice" => $last_id]
								);
								$data["detail"] = $this->model_app->produk_cart([
									"invoice_detail.id_invoice" => $last_id,
								]);
								$data["id"] = $last_id;
								$data["proses"] = $this->model_app
								->edit("invoice", ["id_invoice" => $last_id])
								->row_array();
							//sum detail
								$cdetail = $this->model_app->cek_total(
									"invoice_detail",
									$_select,
									["id_invoice" => $last_id]
								);
								$data["cdetail"] = $cdetail->jml;
							//end
								$this->session->set_userdata(["cart" => $last_id]);
							}
						}
					}
				}
				
				$data["komposisi_variant_options"] = $this->getKomposisiVariantOptionsMap($data["detail"]);
				$data["idsesi"] = $this->iduser;
				$data["active_printers"] = $this->db
					->select("id,name,shared_name,slug,ukuran_kertas,posisi")
					->order_by("id", "DESC")
					->get_where("printer", ["pub" => 1])
					->result_array();
				$this->load->view("penjualan/keranjang", $data);
			}

			public function komposisi_variant_options()
			{
				cek_nput_post("GET");
				$id_bahan = (int) $this->input->post("id_bahan");
				$options = $this->getKomposisiVariantOptionsByBahan($id_bahan);

				$this->output
					->set_content_type('application/json', 'utf-8')
					->set_output(json_encode([
						'status' => 200,
						'options' => $options,
					], JSON_HEX_APOS | JSON_HEX_QUOT | JSON_UNESCAPED_UNICODE))
					->_display();
				exit;
			}

			private function clear_stale_cart_references()
			{
				$user = $this->model_app->view_where("tb_users", [
					"id_user" => $this->iduser,
				]);
				if ($user->num_rows() > 0) {
					$last_invoice = (int) $user->row()->last_invoice;
					if ($last_invoice > 0 && !$this->is_reusable_cart_invoice($last_invoice)) {
						$this->model_app->update(
							"tb_users",
							["last_invoice" => 0],
							["id_user" => $this->iduser]
						);
					}
				}

				$cart = (int) $this->session->userdata("cart");
				if ($cart > 0 && !$this->is_reusable_cart_invoice($cart)) {
					$this->session->unset_userdata("cart");
				}
			}

			private function is_reusable_cart_invoice($id)
			{
				$id = (int) $id;
				if ($id <= 0) {
					return false;
				}

				$invoice = $this->model_app->pilih_where(
					"id_invoice,status",
					"invoice",
					["id_invoice" => $id]
				);
				if ($invoice->num_rows() == 0) {
					return false;
				}

				return $invoice->row()->status === "baru";
			}
			
			
			private function cek_konsumen_kosong($id)
			{
				$where= ["id_konsumen" => 0,"id_invoice" => $id];
				$sql = $this->model_app->pilih("id_konsumen", "invoice", $where);
			// if($sql->num_rows() > 0){
			// $this->model_app->update("invoice",['id_konsumen'=>1],["id_invoice" => $id]);
			// }
			}
			
			private function cek_data_kosong($id)
			{
				$where_produk = ["id_produk" => 0,"id_invoice" => $id];
				$this->hapus_data_kosong('invoice_detail',$where_produk);
				$where_jenis = ["jenis_cetakan" => 0,"id_invoice" => $id];
				$this->hapus_data_kosong('invoice_detail',$where_jenis);
			}
			
			private function hapus_data_kosong($tabel,$where)
			{
				$this->model_app->delete($tabel, $where);
			}
			
			
		/**
			* del_bayar
			*
			* @return json
		*/
			public function del_bayar()
			{
				cek_nput_post("GET");
				cek_crud_akses(10);
				$id_rincian = xss_filter($this->input->post("id"), 'xss');
				$no_invoice = xss_filter($this->input->post("noin"), 'xss');
				$kunci      = xss_filter($this->input->post("kunci"), 'xss');
				$jml        = xss_filter($this->input->post("jml"), 'xss');
				$idbayar    = xss_filter($this->input->post("idbayar"), 'xss');
				
				$where = ($this->session->level == "admin" or
					$this->session->level == "owner") ? ["id" => $id_rincian, "id_invoice" => $no_invoice] : [
					"id" => $id_rincian,
					"id_invoice" => $no_invoice,
					"kunci" => $kunci,
				];
				$get_id_transaksi = get_id_transaksi($no_invoice)['nomor_order'];
				$res = $this->model_app->delete("bayar_invoice_detail", $where);
				if ($res == true) {
					$this->hapus_jurnal($get_id_transaksi);
					$this->model_app->delete("deposit", ['id_invoice' => $no_invoice]);
					$data = ["ok" => "ok", "uang" => $jml];
				} else {
					$data = ["ok" => "no", "uang" => 0];
				}
				echo json_encode($data);
			}
			
		/**
			* list_bayar
			*
			* @return void
		*/
			public function list_bayar()
			{
				$noin = $this->db->escape_str($this->input->post("id"));
				$noin = decrypt_url($noin);
				$data["total_bayar"] = $this->model_app
				->pilih("total_bayar", "invoice", ["id_invoice" => $noin])
				->row();
				$data["bayar"] = $this->model_app->view_where("bayar_invoice_detail", [
					"id_invoice" => $noin,
				]);
				$this->load->view("penjualan/bayar", $data);
			}

			public function member_discount()
			{
				cek_nput_post('GET');
				$id = $this->input->post('id', true);
				$decoded = decrypt_url((string) $id);
				$invoiceId = is_numeric($decoded) ? (int) $decoded : (int) $id;
				$this->output->set_content_type('application/json')
					->set_output(json_encode($this->member_discount_for_invoice($invoiceId)));
			}

			private function member_discount_for_invoice($invoiceId)
			{
				$empty = array('active'=>false,'percentage'=>0,'discount'=>0,'member'=>'','reason'=>'disabled');
				if ($invoiceId <= 0 || !$this->db->table_exists('shared_folder')) return $empty;
				$setting = $this->db->select('isi')->from('shared_folder')
					->where('nama','diskon_level_member_aktif')->limit(1)->get()->row_array();
				if (!$setting || (string)$setting['isi'] !== '1') return $empty;

				$row = $this->db->select('i.total_bayar, i.potongan_harga, m.title, m.potongan_diskon')
					->from('invoice i')->join('konsumen k','k.id=i.id_konsumen','inner')
					->join('member m','m.id=k.jenis_member AND m.status=1','inner')
					->where('i.id_invoice',$invoiceId)->limit(1)->get()->row_array();
				if (!$row) return $empty;
				$percentage = max(0, min(100, (float)$row['potongan_diskon']));
				if ($percentage <= 0) return array_merge($empty,array('member'=>$row['title'],'reason'=>'zero'));

				$payment = $this->db->select_sum('jml_bayar','total')->from('bayar_invoice_detail')
					->where('id_invoice',$invoiceId)->get()->row_array();
				$paid = isset($payment['total']) ? (float)$payment['total'] : 0;
				if ($paid > 0 || (float)$row['potongan_harga'] > 0) {
					return array_merge($empty,array('member'=>$row['title'],'percentage'=>$percentage,'reason'=>'already_paid'));
				}

				$base = max(0, (float)$row['total_bayar']);
				$discount = (int)round($base * $percentage / 100);
				return array('active'=>$discount>0,'percentage'=>$percentage,'discount'=>$discount,
					'member'=>$row['title'],'reason'=>$discount>0?'ok':'zero');
			}
			
		/**
			* list_bayar_piutang
			*
			* @return void
		*/
			public function list_bayar_piutang()
			{
				$noin = $this->db->escape_str($this->input->post("id"));
				$noin = decrypt_url($noin);
				$data["total_bayar"] = $this->model_app
				->pilih("total_bayar", "invoice", ["id_invoice" => $noin])
				->row();
				$data["bayar"] = $this->model_app->view_where("bayar_invoice_detail", [
					"id_invoice" => $noin,
				]);
				$this->load->view("penjualan/list_bayar_piutang", $data);
			}
			
		/**
			* list_invoice
			*
			* @return void
		*/
			public function list_invoice()
			{
				$data["invoice"] = $this->model_app
				->view_where_ordering_limit(
					"invoice",
					["id_konsumen!=" => 1],
					"id_invoice",
					"DESC",
					11
				)
				->result_array();
				$this->load->view("penjualan/list_invoice", $data);
			}
			
		/**
			* list_invoice_desain
			*
			* @return html
		*/
			public function list_invoice_desain()
			{
				$data["invoice"] = $this->model_app
				->view_where_ordering_limit(
					"invoice",
					["id_konsumen!=" => 1, "id_desain" => $this->iduser],
					"id_invoice",
					"DESC",
					10
				)
				->result_array();
				$this->load->view("penjualan/list_invoice", $data);
			}

		/**
			* input_kas
			*
			* @param  mixed $diskon_harga
			* @param  mixed $data
			* @return array
		*/
			
			private function update_invoice($diskon_harga,$total_bayar,$jumlah_bayar,$kembalian,$total_cashback,$noin)
			{
				$this->komisi_sales->ensureSchema();
				if ($diskon_harga == 1) {
					$update_invoice = [
						"total_bayar"    => $total_bayar,
						"jumlah_bayar"   => $jumlah_bayar,
						"kembalian"      => $kembalian,
						"potongan_harga" => $total_cashback,
						"pos"            => 'Y',
						"status"         => 'simpan',
					];
				} elseif ($diskon_harga == 2) {
					$update_invoice = [
						"total_bayar"    => $total_bayar,
						"jumlah_bayar"   => $jumlah_bayar,
						"kembalian"      => $kembalian,
						"potongan_harga" => $total_cashback,
						"pos"            => 'Y',
						"status"         => 'simpan',
					];
				} else {
					$update_invoice = [
						"total_bayar"  => $total_bayar,
						"jumlah_bayar" => $jumlah_bayar,
						"kembalian"    => $kembalian,
						"pos"          => 'Y',
						"status"       => 'simpan',
					];
				}

            // update invoice biasa (seperti semula)
				$this->model_app->update(
					"invoice",
					$update_invoice,
					["id_invoice" => $noin]
				);
				$this->komisi_sales->syncInvoiceCommissionAmount($noin);
				$this->komisi_penjualan->syncInvoiceAmount($noin);

			}

			private function persist_invoice_komisi_from_request($invoiceId)
			{
				if ($this->komisi_penjualan->isFeatureEnabled() && $this->input->post('sales_penjualan') !== null) {
					$this->komisi_penjualan->saveInvoiceSales($invoiceId, (int)$this->input->post('sales_penjualan'));
				}
				if (!$this->komisi_sales->isFeatureEnabled()) {
					return;
				}

				$this->komisi_sales->ensureSchema();

				$invoiceId = (int) $invoiceId;
				if ($invoiceId <= 0) {
					return;
				}

				$salesKomisi = $this->input->post("sales_komisi");

				if ($salesKomisi === null) {
					return;
				}

				$current = $this->db
					->select('id_sales_komisi')
					->from('invoice')
					->where('id_invoice', $invoiceId)
					->get()
					->row_array();

				if (!$current) {
					return;
				}

				$currentSales = isset($current['id_sales_komisi']) ? (int) $current['id_sales_komisi'] : 0;
				$salesId = ($salesKomisi !== null)
					? (int) xss_filter($salesKomisi, 'xss')
					: $currentSales;

				$this->komisi_sales->saveInvoiceCommissionMeta($invoiceId, $salesId, null);
			}

			public function save_komisi_invoice()
			{
				cek_nput_post("GET");
				if (!$this->komisi_sales->isFeatureEnabled()) {
					$this->output
						->set_content_type("application/json")
						->set_output(json_encode([
							"ok" => "disabled",
							"data" => []
						]));
					return;
				}

				$this->komisi_sales->ensureSchema();

				$invoiceId = (int) xss_filter($this->input->post("id"), 'xss');
				$salesKomisi = $this->input->post("sales_komisi");

				if ($invoiceId <= 0) {
					$this->output
						->set_content_type("application/json")
						->set_output(json_encode([
							"ok" => "err",
							"msg" => "Invoice tidak valid"
						]));
					return;
				}

				$this->komisi_sales->saveInvoiceCommissionMeta($invoiceId, $salesKomisi, null);

				$row = $this->db
					->select('id_sales_komisi, komisi_persen, komisi_nominal')
					->from('invoice')
					->where('id_invoice', $invoiceId)
					->get()
					->row_array();

				$this->output
					->set_content_type("application/json")
					->set_output(json_encode([
						"ok" => "ok",
						"data" => $row
					]));
			}

			public function komisi_desain_required()
			{
				cek_nput_post("GET");

				if (!$this->komisi_sales->isFeatureEnabled()) {
					$this->output
						->set_content_type("application/json")
						->set_output(json_encode([
							"required" => false
						]));
					return;
				}

				$this->komisi_sales->ensureSchema();

				$invoiceId = (int) xss_filter($this->input->post("id"), 'xss');
				if ($invoiceId <= 0 || !$this->db->table_exists('invoice_detail') || !$this->db->table_exists('bahan') || !$this->db->field_exists('komisi_desain_aktif', 'bahan')) {
					$this->output
						->set_content_type("application/json")
						->set_output(json_encode([
							"required" => false
						]));
					return;
				}

				$count = $this->db
					->from('invoice_detail d')
					->join('bahan b', 'b.id = d.id_bahan', 'inner')
					->where('d.id_invoice', $invoiceId)
					->where('b.komisi_desain_aktif', 1)
					->count_all_results();

				$this->output
					->set_content_type("application/json")
					->set_output(json_encode([
						"required" => $count > 0
					]));
			}

			public function save_komisi_penjualan_invoice()
			{
				cek_nput_post('GET');
				if (!$this->komisi_penjualan->isFeatureEnabled()) return $this->output->set_content_type('application/json')->set_output(json_encode(['ok'=>'disabled']));
				$id=(int)$this->input->post('id'); $sales=(int)$this->input->post('sales_penjualan');
				$this->komisi_penjualan->saveInvoiceSales($id,$sales);
				return $this->output->set_content_type('application/json')->set_output(json_encode(['ok'=>'ok']));
			}

			public function komisi_penjualan_required()
			{
				cek_nput_post('GET'); $id=(int)$this->input->post('id');
				$required=$this->komisi_penjualan->isFeatureEnabled() && $this->komisi_penjualan->invoiceRequiresSales($id);
				return $this->output->set_content_type('application/json')->set_output(json_encode(['required'=>$required]));
			}


		/**
			* save_bayar
			*
			* @return void
		*/
			public function save_bayar()
			{
				cek_nput_post("GET");
				wajib_akses_bayar_order_json();
			// dump($_POST);
				$lampiran = "";
				$demo = info()['demo'];
				
				$rekening = $this->db->escape_str($this->input->post("rekening"));
				if ($rekening > 0 AND $demo=='N') {
					$config["upload_path"] = "./uploads/lampiran/";
					$config["allowed_types"] = "jpeg|jpg|png|webp";
				$config["max_size"] = "5000"; // kb
				$this->load->library("upload", $config);
				$this->upload->initialize($config);
				if (!empty($_FILES["lampiran"]["name"])) {
					if (!$this->upload->do_upload("lampiran")) {
						echo $this->upload->display_errors();
					} else {
						$data = $this->upload->data();
						$finalUpload = bm_finalize_ci_upload_as_webp($data, 80);
						if (!$finalUpload['status']) {
							$alert = [
								"status" => 301,
								"msg" => $finalUpload['message'],
								"id" => 0,
								"uang" => 0,
								"total" => 0,
							];
							$this->output
							->set_content_type("application/json")
							->set_output(json_encode($alert));
							return;
						}
						$lampiran = $finalUpload["file_name"];
					}
				}
			}
			
			if ($rekening > 0 AND $demo=='Y') {
				$lampiran = "lampiran.jpg";
			}
			
			$type           = xss_filter($this->input->post("type"), 'xss');
			$id_invoice     = xss_filter($this->input->post("noin"), 'xss');
			$id_bayar       = xss_filter($this->input->post("id_byr"), 'xss');
			$jml_bayar      = xss_filter($this->input->post("uang"), 'xss');
			$nourut         = xss_filter($this->input->post("nourut"), 'xss');
			$pajak          = xss_filter($this->input->post("pajak"), 'xss');
			$sumpajak       = xss_filter($this->input->post("sumpajak"), 'xss');
			$total_order    = xss_filter($this->input->post("sisabayar"), 'xss');
			$jumlah_bayar   = xss_filter($this->input->post("jumlah_bayar"), 'xss');
			$kembalian      = xss_filter($this->input->post("kembalian"), 'xss');
			$diskon_harga   = xss_filter($this->input->post("diskon_harga"), 'xss');
			$total_cashback = xss_filter($this->input->post("total_cashback"), 'xss');
			$id_konsumen    = xss_filter($this->input->post("id_konsumen"), 'xss');
			$status    		= xss_filter($this->input->post("status"), 'xss');
			$member_discount = $this->member_discount_for_invoice((int) $id_invoice);
			if (!empty($member_discount['active'])) {
				$diskon_harga = 1;
				$total_cashback = (int) $member_discount['discount'];
			}
			if($rekening==0){
				$getIdAkun = getIdAkun($id_bayar);
			}else{
				$getIdAkun = getIdAkunBank($rekening);
			}
			$get_id_transaksi = get_id_transaksi($id_invoice)['nomor_order'];
			$tgl_transaksi = tgl_transaksi($id_invoice);
			
			// $akun_detail =  $this->model_jurnal->sum_order($id_invoice);
			// dump($akun_detail);
			
			$no_transaction =  $this->journal->check_number_tramsaction();
			$no_order = substr($no_transaction, 6, 4);
			$no_transaction_now = intval($no_order) + 1;
			if($no_transaction == null){
				$no_trans = date("ymd").'0001';
			} else {
				$no_trans = date("ymd").sprintf("%04s",$no_transaction_now);
			}
			$arr = [];
			$alert = [];
			
			if ($type == "simpan_bayar") 
			{
				$nama = cekKonsumen($id_konsumen)['nama'];
				$catatan =  "ORDER NO#".$get_id_transaksi.' - '.$nama;
				$data_bayar = [
					"id_invoice" => $id_invoice,
					"tgl_bayar" => date("Y-m-d"),
					"jam_bayar" => date("H:i:s"),
					"jml_bayar" => $jml_bayar,
					"id_bayar" => $id_bayar,
					"id_sub_bayar" => $getIdAkun,
					"urutan" => $nourut,
					"lampiran" => $lampiran,
					"id_user" => $this->iduser,
				];
				
				// dump($data_bayar);
				if ($id_invoice != null and $jml_bayar > 0) 
				{
					$cek_lunas = $this->cek_lunas($id_invoice);
					if($cek_lunas==true)
					{
						$alert = [
							"status" => 301,
							"msg" => "Order sudah lunas",
							"id" => $id_invoice,
							"uang" => $jml_bayar,
							"total" => 0,
						];
					}else{
						$this->db->trans_begin();
						$this->update_invoice($diskon_harga,$total_order,$jumlah_bayar,$kembalian,$total_cashback,$id_invoice);
						$this->persist_invoice_komisi_from_request($id_invoice);
						$input = $this->model_app->input("bayar_invoice_detail", $data_bayar);
						if ($input["status"] == "ok") 
						{
							$cek_count =$this->model_jurnal->cek_count($id_invoice);
							$ceklunas = $this->cek_lunas($id_invoice);
							// dump($ceklunas);
							$conditions['jurnal'] = [
								'id_user'=>$this->iduser,
								'no_trans'=>$no_trans,
								'tgl_transaksi'=>$tgl_transaksi,
								'id_akun'=>$getIdAkun,
								'id_invoice'=>$id_invoice,
								'id_transaksi'=>$get_id_transaksi,
								'jml_bayar'=>convert_to_number($jml_bayar),
								'total_order'=>convert_to_number($total_order),
								'cek_lunas'=>$ceklunas,
								'pajak'=>$pajak,
								'total_pajak'=>convert_to_number($sumpajak),
								'diskon_harga'=>convert_to_number($diskon_harga),
								'diskon'=>convert_to_number($total_cashback),
								'cashback'=>convert_to_number($total_cashback),
								'ket'=>$catatan,
								'cek_count'=>$cek_count,
								'nama'=>$nama,
								'status'=>$status,
								'lampiran'=>$lampiran
							];
							
							$this->model_jurnal->input_jurnal($conditions);
							if ($this->db->trans_status() === FALSE) {
								$this->db->trans_rollback();
								$alert = [
									"status" => 304,
									"msg" => "Gagal simpan",
									"id" => 0,
									"uang" => 0,
									"total" => 0,
								];
							} else {
								$this->db->trans_commit();
								$alert = [
									"status" => 200,
									"id" => $id_invoice,
									"uang" => $jml_bayar,
									"total" => $total_order,
									"msg" => "Berhasil simpan",
								];
							}
							
						}else{
							$this->db->trans_rollback();
							$alert = [
								"status" => 304,
								"msg" => "Gagal simpan",
								"id" => 0,
								"uang" => 0,
								"total" => 0,
							];
							
						}
						
					}
				}
				
			}
			
			$this->output
			->set_content_type("application/json")
			->set_output(json_encode($alert));
		}
		
		

		
		/**
			* input_kas
			*
			* @param  mixed $diskon_harga
			* @param  mixed $data
			* @return array
		*/
			private function cek_lunas($no_order)
			{
				$_diskon = "ROUND(SUM((`invoice_detail`.`jumlah`) * (`invoice_detail`.`harga` * `invoice_detail`.`diskon`/100))) AS diskon";
				$cek_diskon = $this->model_app->cek_total("invoice_detail", $_diskon, ["id_invoice" => $no_order])->diskon;
				$sum_detail = $this->model_penjualan->cek_total_detail($no_order);
				$cek_total_bayar = $this->model_penjualan->cek_total_bayar($no_order);
				$diskon = $this->model_penjualan->cek_total_diskon_invoice($no_order);
				
			$sisa =$sum_detail - $cek_total_bayar -  $cek_diskon - $diskon; //piutang
			
			if($sisa ==0){
				return true;
			}else{
				return false;
			}
		}
		
		private function input_kas($array)
		{
			$this->model_app->insert("kas_masuk", $array);	
		}
		
		/**
			* deposit
			*
			* @param  mixed $diskon_harga
			* @param  mixed $data
			* @return array
		*/
			private function deposit($diskon_harga, $data)
			{
				if ($diskon_harga == 2) {
					$this->model_app->input("deposit", $data);
				}
			}
			
		/**
			* add_detail
			*
			* @return void
		*/
			public function add_detail()
			{
				cek_nput_post("GET");
				$id = $this->db->escape_str($this->input->post("id"));
				$res = $this->db->insert("invoice_detail", ["id_invoice" => $id]);
				$last_id = $this->db->insert_id();
				if ($res == true) {
					$data = ["status" => 200, "idr" => $last_id];
				} else {
					$data = ["status" => 400, "idr" => 0];
				}
				$this->output
				->set_content_type("application/json")
				->set_output(json_encode($data));
			}
			
		/**
			* Summary of hapus_detail
			* @return void
		*/
			public function hapus_detail()
			{
				cek_nput_post("GET");
				$id = [
					"id_rincianinvoice" => $this->db->escape_str(
						$this->input->post("idr")
					),
				];
				$res = $this->model_app->delete("invoice_detail", $id);
				if ($res == true) {
					$data = ["status" => 200, 'msg' => 'Berhasil'];
				} else {
					$data = ["status" => 400, 'msg' => 'Gagal'];
				}
				$this->output
				->set_content_type("application/json")
				->set_output(json_encode($data));
			}
			
		/**
			* Summary of pending_order
			* @return array
		*/
			public function pending_order()
			{
				cek_nput_post("GET");
				$id = $this->input->post("id");
				$id = decrypt_url($id);
				$res = $this->model_app->update("invoice",['status'=>'pending'],['id_invoice'=>$id]);
				if ($res == true) {
					$data = ["status" => 200, 'msg' => 'Berhasil'];
				} else {
					$data = ["status" => 400, 'msg' => 'Gagal'];
				}
				$this->output
				->set_content_type("application/json")
				->set_output(json_encode($data));
			}
			
		/**
			* Summary of tagih_order
			* @return void
		*/
			public function tagih_order()
			{
				cek_nput_post("GET");
				$id = $this->input->post("id");
				$id = decrypt_url($id);
				$id = xss_filter($id, "sql");
				$marker = "#DITAGIH#";

				if (empty($id)) {
					$data = ["status" => 400, "msg" => "ID transaksi tidak valid"];
					$this->output
					->set_content_type("application/json")
					->set_output(json_encode($data));
					return;
				}

				$invoice = $this->model_app->view_where("invoice", ["id_invoice" => $id])->row_array();
				if (empty($invoice)) {
					$data = ["status" => 404, "msg" => "Transaksi tidak ditemukan"];
					$this->output
					->set_content_type("application/json")
					->set_output(json_encode($data));
					return;
				}
				if ((int) $invoice["lunas"] === 1 || $invoice["status"] == "batal") {
					$data = ["status" => 400, "msg" => "Transaksi tidak dapat ditandai ditagih"];
					$this->output
					->set_content_type("application/json")
					->set_output(json_encode($data));
					return;
				}

				$history = isset($invoice["history"]) ? trim((string) $invoice["history"]) : "";
				if (strpos($history, $marker) === false) {
					$history = trim($history." ".$marker);
				}

				$res = $this->model_app->update("invoice", ["history" => $history], ["id_invoice" => $id]);
				if (!empty($res["status"]) && $res["status"] == "ok") {
					$data = ["status" => 200, "msg" => "Berhasil ditandai ditagih"];
				} else {
					$data = ["status" => 400, "msg" => "Gagal menandai ditagih"];
				}

				$this->output
				->set_content_type("application/json")
				->set_output(json_encode($data));
			}

		/**
			* Summary of hapus_order_batal
			* @return void
		*/
			public function hapus_order_batal()
			{
				cek_nput_post("GET");
				cek_crud_akses(10);
				$id = $this->input->post("id");
				$id = decrypt_url($id);
				$id = xss_filter($id, 'sql');
				$id_invoice = ["id_invoice" => $id];
				$get_id_transaksi = get_id_transaksi($id)['nomor_order'];
				
				$res = $this->model_app->delete("invoice", $id_invoice);
				if ($res == true) {
					$this->model_app->delete("invoice_detail", $id_invoice);
					$this->model_app->delete("bayar_invoice_detail", $id_invoice);
					$this->model_app->update('tb_users', ['last_invoice'=>0], ['last_invoice'=>$id]);
					$this->hapus_jurnal($get_id_transaksi);
					$data = ["status" => 200, 'msg' => 'Berhasil'];
				} else {
					$data = ["status" => 400, 'msg' => 'Gagal'];
				}
				$this->output
				->set_content_type("application/json")
				->set_output(json_encode($data));
			}
		/**
			* Summary of totaltrx
			* @return void
		*/


		// =======================================
		// OMSET HARI INI
		// Definisi KPI #1:
		// "total uang dari seluruh order / transaksi yang dibuat hari ini"
		// -> sum total tagihan semua invoice yang tgl_trx = hari ini dan tidak batal
		// =======================================
			function totaltrxx()
			{
			// Mendapatkan total jumlah transaksi berdasarkan status
				$total_jumlah_transaksi = $this->model_penjualan->get_total_jumlah_transaksi();
				
			// Menyiapkan data untuk dikirim dalam format JSON
				$response = array(
            'status' => 'success',  // Status untuk hasil
            'total_transaksi' => $total_jumlah_transaksi  // Data jumlah transaksi
        );
				
			// Mengatur header response dengan tipe JSON dan mengirimkan data JSON
				$this->output
				->set_content_type('application/json')
				->set_output(json_encode($response));
			}
		/**
			* Summary of totaltrx
			* @return void
		*/
		// ===============================
// ===============================
// OMSET HARI INI
// "total uang dari seluruh order / transaksi yang dibuat hari ini"
// = total nilai invoice_detail (jumlah * harga) untuk invoice yang tgl_trx = hari ini
// ===============================
			public function totaltrx()
			{
				$today = date('Y-m-d');

				$this->db->select('SUM(id.jumlah * id.harga) AS total_order', false);
				$this->db->from('invoice i');
				$this->db->join('invoice_detail id', 'i.id_invoice = id.id_invoice', 'left');
				$this->db->where('i.tgl_trx', $today);
    $this->db->where('i.status !=', 'batal'); // invoice batal jangan dihitung

    $row = $this->db->get()->row_array();
    $total = isset($row['total_order']) ? (float)$row['total_order'] : 0;

    $formatted = number_format($total, 0, ',', '.');

    $this->output
    ->set_content_type("application/json")
    ->set_output(json_encode($formatted));
}



// ===============================
// PENDAPATAN HARI INI
// "total uang dari seluruh transaksi yang BAYAR hari ini"
// = total jml_bayar di tabel bayar_invoice_detail untuk tgl_bayar = hari ini
// (nggak peduli invoice-nya dibuat kapan)
// ===============================
public function hari_ini()
{
	$today = date('Y-m-d');

	$this->db->select('SUM(bid.jml_bayar) AS total_bayar', false);
	$this->db->from('bayar_invoice_detail bid');
	$this->db->where('bid.tgl_bayar', $today);

	$row = $this->db->get()->row_array();
	$total_bayar_hari_ini = isset($row['total_bayar']) ? (float)$row['total_bayar'] : 0;

	$formatted = number_format($total_bayar_hari_ini, 0, ',', '.');

	$this->output
	->set_content_type("application/json")
	->set_output(json_encode($formatted));
}



// ===============================
// PIUTANG HARI INI
// "total piutang dari seluruh transaksi yang dibuat hari ini"
// piutang = (total tagihan invoice hari ini) - (total pembayaran utk invoice tsb, sampai sekarang)
// ===============================
public function baru()
{
    // ===============================
    // TOTAL SELURUH PIUTANG (ALL-TIME)
    // Rumus:
    //   piutang_total = (Σ jumlah*harga semua invoice non-batal)
    //                   - (Σ semua pembayaran untuk invoice non-batal)
    // Catatan:
    // - Mengabaikan invoice berstatus 'batal'
    // - Jika hasil negatif, paksa 0 (guard)
    // ===============================

    // Total nilai order dari semua invoice non-batal
	$this->db->select('SUM(id.jumlah * id.harga) AS total_order', false);
	$this->db->from('invoice i');
	$this->db->join('invoice_detail id', 'i.id_invoice = id.id_invoice', 'left');
	$this->db->where('i.status !=', 'batal');
	$row_order   = $this->db->get()->row_array();
	$total_order = isset($row_order['total_order']) ? (float)$row_order['total_order'] : 0;

    // Total seluruh pembayaran untuk invoice non-batal
	$this->db->select('SUM(bid.jml_bayar) AS total_bayar', false);
	$this->db->from('invoice i');
	$this->db->join('bayar_invoice_detail bid', 'i.id_invoice = bid.id_invoice', 'left');
	$this->db->where('i.status !=', 'batal');
	$row_bayar   = $this->db->get()->row_array();
	$total_bayar = isset($row_bayar['total_bayar']) ? (float)$row_bayar['total_bayar'] : 0;

    // Hitung piutang total
	$piutang_total = $total_order - $total_bayar;
	if ($piutang_total < 0) { $piutang_total = 0; }

    // Format sebagai angka ribuan Indonesia dan kirim JSON
	$formatted = number_format($piutang_total, 0, ',', '.');

	$this->output
	->set_content_type("application/json")
	->set_output(json_encode($formatted));
}




// ===============================
// OMSET BULAN INI
// "total uang dari seluruh order / transaksi yang dibuat BULAN INI"
// = total nilai invoice_detail (jumlah * harga) untuk invoice bulan ini
// ===============================
public function pending()
{
    $periode = date('Y-m'); // contoh "2025-10"

    $this->db->select('SUM(id.jumlah * id.harga) AS total_order', false);
    $this->db->from('invoice i');
    $this->db->join('invoice_detail id', 'i.id_invoice = id.id_invoice', 'left');
    $this->db->where('DATE_FORMAT(i.tgl_trx, "%Y-%m") = "'.$periode.'"', null, false);
    $this->db->where('i.status !=', 'batal');

    $row = $this->db->get()->row_array();
    $total_bulan_ini = isset($row['total_order']) ? (float)$row['total_order'] : 0;

    $formatted = number_format($total_bulan_ini, 0, ',', '.');

    $this->output
    ->set_content_type("application/json")
    ->set_output(json_encode($formatted));
}



// ===============================
// PENDAPATAN BULAN INI
// "total uang dari seluruh transaksi yang bayar BULAN INI"
// = total jml_bayar dari bayar_invoice_detail utk tgl_bayar bulan ini
// ===============================
public function batal()
{
	$periode = date('Y-m');

	$this->db->select('SUM(bid.jml_bayar) AS total_bayar', false);
	$this->db->from('bayar_invoice_detail bid');
	$this->db->where('DATE_FORMAT(bid.tgl_bayar, "%Y-%m") = "'.$periode.'"', null, false);

	$row = $this->db->get()->row_array();
	$total_bayar_bulan_ini = isset($row['total_bayar']) ? (float)$row['total_bayar'] : 0;

	$formatted = number_format($total_bayar_bulan_ini, 0, ',', '.');

	$this->output
	->set_content_type("application/json")
	->set_output(json_encode($formatted));
}



// ===============================
// PIUTANG BULAN INI
// "total piutang dari seluruh transaksi yang dibuat bulan ini"
// piutang = total order invoice bulan ini - total bayar utk invoice tsb
// ===============================
public function piutang_bulan()
{
	$periode = date('Y-m');

    // total nilai order dari semua invoice bulan ini
	$this->db->select('SUM(id.jumlah * id.harga) AS total_order', false);
	$this->db->from('invoice i');
	$this->db->join('invoice_detail id', 'i.id_invoice = id.id_invoice', 'left');
	$this->db->where('DATE_FORMAT(i.tgl_trx, "%Y-%m") = "'.$periode.'"', null, false);
	$this->db->where('i.status !=', 'batal');
	$row_order = $this->db->get()->row_array();
	$total_order_bln = isset($row_order['total_order']) ? (float)$row_order['total_order'] : 0;

    // total bayar yang sudah masuk utk invoice2 yang dibuat bulan ini
	$this->db->select('SUM(bid.jml_bayar) AS total_bayar', false);
	$this->db->from('invoice i');
	$this->db->join('bayar_invoice_detail bid', 'i.id_invoice = bid.id_invoice', 'left');
	$this->db->where('DATE_FORMAT(i.tgl_trx, "%Y-%m") = "'.$periode.'"', null, false);
	$this->db->where('i.status !=', 'batal');
	$row_bayar = $this->db->get()->row_array();
	$total_bayar_bln = isset($row_bayar['total_bayar']) ? (float)$row_bayar['total_bayar'] : 0;

	$piutang_bln = $total_order_bln - $total_bayar_bln;
	if ($piutang_bln < 0) { $piutang_bln = 0; }

	$formatted = number_format($piutang_bln, 0, ',', '.');

	$this->output
	->set_content_type("application/json")
	->set_output(json_encode($formatted));
}



// ===============================
// PENGELUARAN BULAN INI
// KPI: total kas keluar / pengeluaran bulan berjalan
//
// LOGIC:
// - Ambil semua baris kas keluar di tabel `kas_keluar` (alias kk)
// - Kolom tanggal transaksi: kk.tanggal
// - Nominal rupiah per transaksi: kk.jumlah
// - Total bulan ini = SUM(kk.jumlah) untuk bulan berjalan
//
// CATATAN:
// Struktur ini mengikuti Model_kas.php:
//   kas_keluar: id, no_transaksi, tanggal, keterangan, id_user, id_akun, jumlah
//   kas_keluar_detail: relasi by kk.id -> kas_keluar_detail.id_kas
// Untuk KPI cukup total header (kk.jumlah), jadi tidak perlu join detail.
// ===============================
public function kas_keluar_bulan()
{
    $periode = date('Y-m'); // contoh "2025-10"

    // Hitung total pengeluaran uang kas keluar bulan ini
    $this->db->select('SUM(kk.jumlah) AS total_pengeluaran', false);
    $this->db->from('kas_keluar kk');
    // filter bulan+tahun dari kolom tanggal (DATE / DATETIME)
    $this->db->where('DATE_FORMAT(kk.tanggal, "%Y-%m") = "'.$periode.'"', null, false);

    $row = $this->db->get()->row_array();

    $total_pengeluaran = isset($row['total_pengeluaran']) ? (float)$row['total_pengeluaran'] : 0;

    // Format rupiah ribuan pakai titik, tanpa desimal
    $formatted = number_format($total_pengeluaran, 0, ',', '.');

    $this->output
    ->set_content_type("application/json")
    ->set_output(json_encode($formatted));
}



// ===============================
// PEMBELIAN BULAN INI
// KPI: total pembelian bahan/barang bulan berjalan
//
// LOGIC:
// - Join header `pembelian` (pb) dengan `pembelian_detail` (pbd)
// - Ambil SUM(pbd.jumlah * pbd.harga)
// - Filter berdasarkan bulan+tahun dari pb.tgl_pembelian
//
// CATATAN STRUKTUR (Model_pembelian.php):
//   - Header: pembelian (punya kolom tgl_pembelian, id_pembelian, supplier, dll)
//   - Detail: pembelian_detail (punya jumlah, harga, id_pembelian, dst)
// ===============================
public function pembelian_bulan()
{
    $periode = date('Y-m'); // contoh "2025-10"

    $this->db->select('SUM(pbd.jumlah * pbd.harga) AS total_pembelian', false);
    $this->db->from('pembelian pb');
    $this->db->join('pembelian_detail pbd', 'pb.id_pembelian = pbd.id_pembelian', 'left');

    // filter bulan+tahun berdasar kolom tanggal yang BENAR di tabel pembelian
    $this->db->where('DATE_FORMAT(pb.tgl_pembelian, "%Y-%m") = "'.$periode.'"', null, false);

    $row = $this->db->get()->row_array();

    $total_pembelian = isset($row['total_pembelian']) ? (float)$row['total_pembelian'] : 0;

    $formatted = number_format($total_pembelian, 0, ',', '.');

    $this->output
    ->set_content_type("application/json")
    ->set_output(json_encode($formatted));
}




// ===============================
// KONSUMEN AKTIF
// KPI konsumen aktif (jumlah konsumen aktif)
// di screenshot kamu angkanya 102, jadi logic lama udah benar:
// konsumen.kunci = '0'
// ===============================
public function konsumen_total()
{
	$conditions["where"] = [
		"kunci" => "0"
	];
	$jumlah = $this->model_app->counter("konsumen", $conditions);

	$formatted = number_format((int)$jumlah, 0, ',', '.');

	$this->output
	->set_content_type("application/json")
	->set_output(json_encode($formatted));
}


			/**
			* Summary of desain
			* @return void
		*/
			public function desain()
			{
				$conditions["where"] = [
					"id_desain" => $this->iduser,
				];
				$data = $this->model_app->counter("invoice", $conditions);
				$this->output
				->set_content_type("application/json")
				->set_output(json_encode($data));
			}
			
		/**
			* Summary of desainnow
			* @return void
		*/
			public function desainnow()
			{
				$conditions["where"] = [
					"tgl_trx" => date("Y-m-d"),
					"id_desain" => $this->iduser,
				];
				$data = $this->model_app->counter("invoice", $conditions);
				$this->output
				->set_content_type("application/json")
				->set_output(json_encode($data));
			}

			
		/**
			* Summary of cari
			* @return void
		*/
			public function cari()
			{
				cek_nput_post("GET");
				$search = $this->input->post("search");
				$data = $this->model_data->getdata($search);
				$this->output
				->set_content_type("application/json")
				->set_output(json_encode($data));
			}
			
		/**
			* Summary of simpan_data
			* @return void
		*/
			public function simpan_data()
			{
				cek_nput_post("GET");
				$noin = $this->input->post("id");
				if ((int)$noin) {
					$noin = $noin;
				} else {
					$noin = decrypt_url($noin);
				}
				$idkon = $this->input->post("idk");
				$total = $this->input->post("total");
				$uangmuka = $this->input->post("uangmuka");
				$status = $this->input->post("status");
				$this->session->unset_userdata("cart");
				if ($noin != null and $total > 0) {
					$this->db->trans_begin();
				//hapus data kosong
					$this->cek_data_kosong($noin);
				//cek jml bayar
					$select = "SUM(jml_bayar) AS total";
					$where = ["id_invoice" => $noin];
					$cek_print = $this->model_app->view_where("invoice", $where)->row();
					// Catat jam order tepat saat transaksi pertama kali disimpan.
					// Saat transaksi tersimpan dibuka/dicetak kembali, nilai lama harus dipertahankan.
					$jamOrderSaatDisimpan = ($cek_print && $cek_print->status !== 'simpan')
						? date('H:i:s')
						: null;
					
					$konsumen = $this->model_app
					->view_where("konsumen", ["id" => $idkon])
					->row();
					if ($konsumen->max_utang > 0 and $cek_print->cetak <= 1) {
						$max_utang = $konsumen->max_utang - 1;
						$this->model_app->update(
							"konsumen",
							["max_utang" => $max_utang],
							["id" => $idkon]
						);
					}
					
					$search = $this->model_app->cek_total("bayar_invoice_detail", $select, $where);
				//total di invoice
					$invoice = "total_bayar AS total";
					$searchin = $this->model_app->cek_total("invoice", $invoice, $where);
				// dump($_POST);
					if ($uangmuka == 0 AND $status=='baru') {
						
					// dump($ceklunas);
						$no_transaction =  $this->journal->check_number_tramsaction();
						$no_order = substr($no_transaction, 6, 4);
						$no_transaction_now = intval($noin) + 1;
						if($no_transaction == null){
							$no_trans = date("ymd").'0001';
						} else {
							$no_trans = date("ymd").sprintf("%04s",$no_transaction_now);
						}
						$get_id_transaksi = get_id_transaksi($noin)['nomor_order'];
						$tgl_transaksi = tgl_transaksi($noin);
						$id_konsumen = get_id_transaksi($noin)['idkonsumen'];
						$nama = cekKonsumen($id_konsumen)['nama'];
						$catatan =  "ORDER NO#".$get_id_transaksi.' - '.$nama;
						$getIdAkun = getIdAkun(6);
						
						$conditions['jurnal'] = [
							'id_user'=>$this->iduser,
							'no_trans'=>$no_trans,
							'tgl_transaksi'=>$tgl_transaksi,
							'id_akun'=>$getIdAkun,
							'id_invoice'=>$noin,
							'id_transaksi'=>$get_id_transaksi,
							'jml_bayar'=>$uangmuka,
							'total_order'=>$total,
							'cek_lunas'=>false,
							'pajak'=>0,
							'total_pajak'=>0,
							'diskon_harga'=>0,
							'diskon'=>0,
							'cashback'=>0,
							'ket'=>$catatan,
							'cek_count'=>0,
							'nama'=>$nama,
							'status'=>$status,
							'lampiran'=>''
						];
						
						$this->model_jurnal->input_jurnal($conditions);
					}
					if ($searchin->total == $search->total) {
						$this->model_app->update(
							"invoice",
							["lunas" => 1,
							"status" => "simpan",
							"pos" => "Y",
							"oto" => 6,
						],
						["id_invoice" => $noin]
					);
						if ($jamOrderSaatDisimpan !== null) {
							$this->model_app->update(
								"invoice",
								["jam_order" => $jamOrderSaatDisimpan],
								["id_invoice" => $noin]
							);
						}
						$data = [
							"status" => 200,
							"id" => $noin,
							"total" => $search->total,
						];
					} else {
						$this->model_app->update(
							"invoice",["status" => "simpan", "pos" => "Y", "oto" => 6],
							["id_invoice" => $noin]
						);
						if ($jamOrderSaatDisimpan !== null) {
							$this->model_app->update(
								"invoice",
								["jam_order" => $jamOrderSaatDisimpan],
								["id_invoice" => $noin]
							);
						}
						$data = [
							"status" => 200,
							"id" => $noin,
							"total" => $searchin->total,
						];
					}
					$this->model_app->update(
						"tb_users",
						["last_invoice" => 0],
						["id_user" => $this->iduser]
					);
				} else {
					$data = ["status" => 400, "id" => $noin, "total" => 0];
				}

				if ($noin != null && $total > 0) {
					if ($this->db->trans_status() === FALSE) {
						$this->db->trans_rollback();
						$data = [
							"status" => 500,
							"id" => $noin,
							"total" => 0,
							"msg" => "Gagal menyimpan transaksi",
						];
					} else {
						$this->db->trans_commit();
					}
				}

				echo json_encode($data);
			}
			
			private function normalizeInvoiceDate($value)
			{
				$value = trim((string) $value);
				foreach (['Y-m-d', 'd/m/Y'] as $format) {
					$date = DateTime::createFromFormat('!' . $format, $value);
					$errors = DateTime::getLastErrors();
					$isValid = $date && ($errors === false || ($errors['warning_count'] === 0 && $errors['error_count'] === 0));
					if ($isValid && $date->format($format) === $value) {
						return $date->format('Y-m-d');
					}
				}
				return null;
			}

		/**
			* Summary of auto_save_invoice
			* @return void
			*/
			public function auto_save_invoice()
			{
				cek_nput_post("GET");
				$komisiSalesAktif = $this->komisi_sales->isFeatureEnabled();
				if ($komisiSalesAktif) {
					$this->komisi_sales->ensureSchema();
				}

				$id        = (int) xss_filter($this->input->post("id"), 'xss');
				$tgli      = $this->normalizeInvoiceDate($this->input->post("tglin"));
				$tgla      = $this->normalizeInvoiceDate($this->input->post("tgla"));
				$jam       = trim((string) xss_filter($this->input->post("jam"), 'xss'));
				$marketing = xss_filter($this->input->post("marketing"), 'xss');
				$referal   = xss_filter($this->input->post("referal"), 'xss');
				$salesKomisiRaw  = $komisiSalesAktif ? $this->input->post("sales_komisi") : null;
				$salesPenjualanRaw = $this->komisi_penjualan->isFeatureEnabled() ? $this->input->post('sales_penjualan') : null;

				if ($id <= 0 || $tgli === null || $tgla === null || !preg_match('/^(?:[01]\\d|2[0-3]):[0-5]\\d$/', $jam)) {
					$this->output
						->set_status_header(422)
						->set_content_type('application/json')
						->set_output(json_encode(['status' => false, 'msg' => 'Format tanggal atau jam tidak valid']));
					return;
				}

				$currentInvoice = $this->db
					->select('status')
					->get_where('invoice', ['id_invoice' => $id])
					->row_array();
				if (!$currentInvoice) {
					$this->output
						->set_status_header(404)
						->set_content_type('application/json')
						->set_output(json_encode(['status' => false, 'msg' => 'Transaksi tidak ditemukan']));
					return;
				}
				if ($currentInvoice['status'] === 'baru' && $tgli !== date('Y-m-d')) {
					$this->output
						->set_status_header(422)
						->set_content_type('application/json')
						->set_output(json_encode(['status' => false, 'msg' => 'Tanggal order harus menggunakan tanggal hari ini']));
					return;
				}

		    // Tanggal selalu dinormalisasi sebelum masuk ke kolom DATE/DATETIME.
				$data = [
					"tgl_trx"      => $tgli,
					"tgl_ambil"    => $tgla . " " . $jam . ":00",
					"id_marketing" => $marketing,
				];

		    // Hanya sertakan id_referal jika kolomnya memang ada di tabel 'invoice'
				if ($this->db->field_exists('id_referal', 'invoice')) {
					$data["id_referal"] = $referal;
				}
				if ($this->db->field_exists('id_sales_komisi', 'invoice') && $salesKomisiRaw !== null) {
					$data["id_sales_komisi"] = (int) xss_filter($salesKomisiRaw, 'xss');
				}

				$where = ["id_invoice" => $id];

				$res = $this->model_app->update("invoice", $data, $where);
				if ($salesKomisiRaw !== null) {
					$this->komisi_sales->saveInvoiceCommissionMeta($id, $salesKomisiRaw, null);
				}
				if ($salesPenjualanRaw !== null) {
					$this->komisi_penjualan->saveInvoiceSales($id, $salesPenjualanRaw);
				}
				if ($res["status"] == "ok") {
					$resp = ["ok" => "ok"];
				} else {
					$resp = ["ok" => "err"];
				}

				echo json_encode($resp);
			}

			
		/**
			* Summary of auto_save_invoice_detail
			* @return never
		*/
			public function auto_save_invoice_detail()
			{
				cek_nput_post("GET");
				$this->ensure_invoice_detail_decimal_schema();
				$idorder       = xss_filter($this->input->post("id_invoice"), 'xss');
				$jml           = xss_filter($this->input->post("jml"), 'xss');
				$uangmuka      = xss_filter($this->input->post("uangmuka"), 'xss');
				$id            = xss_filter($this->input->post("id_rincianinvoice"), 'xss');
				$harga         = xss_filter($this->input->post("harga"), 'xss');
				$harga_satuan  = xss_filter($this->input->post("harga_satuan"), 'xss');
				$jumlah        = xss_filter($this->input->post("jumlah"), 'xss');
				$id_produk     = xss_filter($this->input->post("id_produk"), 'xss');
				$ket           = xss_filter($this->input->post("ket"), 'xss');
				$ukuran        = xss_filter($this->input->post("ukuran"), 'xss');
				$ukuran        = comma_to_dot($ukuran);
				$satuan        = xss_filter($this->input->post("satuan"), 'xss');
				$id_bahan      = xss_filter($this->input->post("id_bahan"), 'xss');
				$jenis         = xss_filter($this->input->post("jenis"), 'xss');
				$totukuran     = xss_filter($this->input->post("totukuran"), 'xss');
				$ukuran_hitung = xss_filter($this->input->post("ukuran_hitung"), 'xss');
				$diskon        = xss_filter($this->input->post("diskon"), 'xss');
				$type_harga    = xss_filter($this->input->post("type_harga"), 'xss');
				$status_hitung = xss_filter($this->input->post("status_hitung"), 'xss');
				$hsatuan       = xss_filter($this->input->post("hargasatuan"), 'xss');

		    // =========================================================
		    // >>> EDITED: normalisasi angka harga input dari user
		    // "80.000" -> 80000, "125.500" -> 125500, "50000" -> 50000
		    $harga_num        = $this->decimal_number($harga);           // >>> EDITED
		    $harga_satuan_num = $this->decimal_number($harga_satuan);    // >>> EDITED
		    // =========================================================
		    
		    if (empty($id_bahan)) {
		    	$id_bahan = 1;
		    }
		    if (empty($satuan)) {
		    	$satuan = "-";
		    }
		    if (empty($satuan)) {
		    	$satuan = "-";
		    }
		    
		    if (empty($totukuran) or $totukuran == 'NaN') {
		    	$totukuran = 1;
		    } else {
		    	if ($status_hitung > 0) {
		    		$totukuran = $totukuran;
		    	}
		    }
		    
		    // harga_hpp(id_bahan) = modal per satuan bahan (biaya pokok dasar, bukan harga jual)
		    $harga_hpp = harga_hpp($id_bahan);

		    // hitung total HPP baris
		    if (!empty($totukuran) and $harga_hpp > 0) {
		    	$hpp = $totukuran * $harga_hpp;
		    } elseif (empty($totukuran) and $harga_hpp > 0) {
		    	$hpp = $jumlah * $harga_hpp;
		    } else {
		    	$hpp = 0;
		    }
		    
		    $this->form_validation->set_rules(array(
		    	array(
		    		'field' => 'ukuran',
		    		'label' => 'Ukuran',
		    		'rules' => 'required|trim|min_length[1]|max_length[20]',
		    		'errors' => array(
		    			'required' => '%s. Harus di isi',
		    			'min_length' => '%s minimal 20 digit.',
		    			'max_length' => '%s minimal 20 digit.'
		    		)
		    	),
		    	
		    	array(
		    		'field' => 'ket',
		    		'label' => 'Keterangan',
		    		'rules' => 'trim|min_length[1]|max_length[150]',
		    		'errors' => array(
		    			'min_length' => '%s minimal 1 digit.',
		    			'max_length' => '%s minimal 50 digit.'
		    		)
		    	),
		    ));
		    
		    if ($this->form_validation->run() == FALSE) {
		    	$response['status'] = false;
		    	$response['msg']    = validation_errors();
		    } else {
		    	$this->model_app->update("invoice", ['total_bayar' => $jml], ['id_invoice' => $idorder]);

		        // where clause buat update detail
		    	$where = ["id_rincianinvoice" => $id];

		        // ambil data bahan untuk referensi type_harga + kemungkinan modal
		    	$cek_harga   = $this->model_app->view_where("bahan", ["id" => $id_bahan]);
		    	$row         = $cek_harga->row();
		    	$type_harga  = $row->type_harga;

		        // =========================================================
		        // >>> EDITED: tentukan modal_satuan yg valid
		        //
		        // Tujuan:
		        //  - Kita cuma mau blokir kalau emang harga < modal asli.
		        //  - Kalau kita GAK TAU modalnya, jangan blok sama sekali.
		        //
		        // Sumber modal yg kita percaya:
		        //   1. $harga_hpp (hasil harga_hpp($id_bahan))  -> biasanya modal/HPP per satuan bahan
		        //   2. $row->harga_beli kalau kolom itu ada dan >0
		        //
		        // Catatan penting:
		        //   DULU kita fallback ke harga_jual_default (pricelist),
		        //   itu bikin masalah karena dianggap "rugi" padahal masih untung.
		        //   SEKARANG fallback harga_jual_default DIHAPUS.
		        // =========================================================

		        // ambil kemungkinan harga_beli dari tabel (kalau kolomnya ada dan mungkin disimpan pakai format "50.000")
		        $row_harga_beli_raw = isset($row->harga_beli) ? $row->harga_beli : 0;                          // >>> EDITED
		        $row_harga_beli_num = (int) preg_replace('/[^0-9]/', '', (string)$row_harga_beli_raw);         // >>> EDITED

		        // normalisasi harga_hpp jadi integer bersih
		        $harga_hpp_num      = (int) preg_replace('/[^0-9]/', '', (string)$harga_hpp);                  // >>> EDITED

		        // tentukan modal_satuan
		        $modal_satuan = 0;                                                                            // >>> EDITED
		        if ($harga_hpp_num > 0) {
		            $modal_satuan = $harga_hpp_num;                                                           // >>> EDITED
		        } elseif ($row_harga_beli_num > 0) {
		            $modal_satuan = $row_harga_beli_num;                                                      // >>> EDITED
		        } else {
		            $modal_satuan = 0; // kita TIDAK lagi fallback ke harga_jual/pricelist                     // >>> EDITED
		        }

		        // SEKARANG modal_satuan:
		        // - >0  berarti kita tahu modalnya
		        // - ==0 berarti kita gak tau modal -> jangan paksa popup
		        // =========================================================
		        
		        // =========================================================
		        // >>> EDITED: logika cek rugi
		        //
		        // Popup hanya muncul kalau:
		        //   - kita TAU modal (modal_satuan > 0)
		        //   - dan harga yg dimasukkan user ($harga_num) lebih kecil dari modal_satuan
		        //
		        // Kalau modal_satuan == 0 -> kita anggap aman (tidak munculin popup)
		        // =========================================================
		        if (
		            $modal_satuan > 0 &&                // >>> EDITED
		            $harga_num < $modal_satuan &&       // >>> EDITED
		            $harga_num > 0 &&
		            $totukuran >= 1 &&
		            $type_harga == 1
		        ) {

		            // harga di bawah modal -> kita blokir dan kembalikan harga minimum aman (modal_satuan)
		        	$response = [
		        		"status" => 401,
		                "harga"  => rp($modal_satuan),              // >>> EDITED (pakai modal_satuan)
		                "msg"    => "Harga dibawah harga modal (RUGI DONG)",
		            ];

		            $data_array = [
		            	"id_produk"      => $id_produk,
		            	"jumlah"         => $jumlah,
		                "harga"          => $modal_satuan,          // >>> EDITED (revert ke modal yg aman)
		                "harga_satuan"   => $harga_satuan_num,      // >>> EDITED (sudah dinormalisasi)
		                "ukuran"         => $ukuran,
		                "satuan"         => $satuan,
		                "id_satuan"      => $satuan,
		                "keterangan"     => $ket,
		                "id_bahan"       => $id_bahan,
		                "jenis_cetakan"  => $jenis,
		                "type_harga"     => $type_harga,
		                "status_hitung"  => $status_hitung,
		                "ukuran_hitung"  => $ukuran_hitung,
		                "tot_ukuran"     => $totukuran,
		                "hpp"            => $hpp,
		                "diskon"         => $diskon,
		                "kunci"          => 0,
		            ];

		            $this->model_app->update("invoice_detail", $data_array, $where);

		        // ======================
		        // END BLOK RUGI
		        // ======================

		        } else {
		            // harga aman (>= modal atau modal tidak diketahui), lanjut update biasa

		        	if (empty($id_produk)) {
		        		$id_produk = 1;
		        	}
		        	
		        	if (empty($jenis)) {
		        		$jenis = 1;
		        	}
		        	
		        	if (empty($totukuran)) {
		        		$totukuran = 1;
		        	}
		        	
		        	$cek_harga = $this->model_app->view_where("harga", [
		        		"title" => $harga,
		        	]);
		        	
		        	$_reload = $this->model_app
		        	->view_where("invoice_detail", $where)
		        	->row_array();

		        	if ($jml < $uangmuka) {
		        		$response = [
		        			"status" => 400,
		        			"jml"    => $_reload["jumlah"],
		        			"harga"  => $_reload["harga"],
		        			"diskon" => $_reload["diskon"],
		        			"ukuran" => $_reload["ukuran"],
		        		];
		        	} else {

		                // =====================================================
		                // >>> EDITED: simpan harga hasil normalisasi ($harga_num)
		                // supaya database nyimpen 80000, bukan string "80.000"
		        		$data_array = [
		        			"id_produk"      => $id_produk,
		        			"jumlah"         => $jumlah,
		                    "harga"          => $harga_num,         // >>> EDITED
		                    "harga_satuan"   => $harga_satuan_num,  // >>> EDITED
		                    "ukuran"         => $ukuran,
		                    "satuan"         => $satuan,
		                    "id_satuan"      => $satuan,
		                    "keterangan"     => $ket,
		                    "id_bahan"       => $id_bahan,
		                    "jenis_cetakan"  => $jenis,
		                    "type_harga"     => $type_harga,
		                    "status_hitung"  => $status_hitung,
		                    "tot_ukuran"     => $totukuran,
		                    "ukuran_hitung"  => $ukuran_hitung,
		                    "hpp"            => $hpp,
		                    "diskon"         => $diskon,
		                    "kunci"          => 0,
		                ];
		                // =====================================================

		                $res = $this->model_app->update(
		                	"invoice_detail",
		                	$data_array,
		                	$where
		                );

		                if ($res["status"] == "ok") {
		                	$response = ["status" => 200, "msg" => "Saved", 'ukuran' => $ukuran];
		                } else {
		                	$response = ["status" => 400, "msg" => "Save Gagal"];
		                }
		            }
		        }
		    }

		    $this->output
		    ->set_status_header(200)
		    ->set_content_type('application/json', 'utf-8')
		    ->set_output(json_encode($response, JSON_HEX_APOS | JSON_HEX_QUOT))
		    ->_display();
		    exit();
		}

			private function decimal_number($value)
			{
				$value = preg_replace('/\s+/', '', (string) $value);
				$value = preg_replace('/[^0-9\.,-]/', '', $value);
				if ($value === '' || $value === '-') {
					return '0';
				}

				$negative = strpos($value, '-') === 0 ? '-' : '';
				$value = str_replace('-', '', $value);
				$lastComma = strrpos($value, ',');
				$lastDot = strrpos($value, '.');
				$decimalPos = -1;

				if ($lastComma !== false && $lastDot !== false) {
					$decimalPos = max($lastComma, $lastDot);
				} else {
					$decimalPos = max($lastComma === false ? -1 : $lastComma, $lastDot === false ? -1 : $lastDot);
					if ($decimalPos !== -1) {
						$separator = $value[$decimalPos];
						$decimalLength = strlen($value) - $decimalPos - 1;
						$firstSeparator = strpos($value, $separator);
						if ($firstSeparator !== $decimalPos || $decimalLength > 4 || ($separator === '.' && $decimalLength === 3 && $firstSeparator === $decimalPos)) {
							$decimalPos = -1;
						}
					}
				}

				if ($decimalPos === -1) {
					$digits = preg_replace('/\D/', '', $value);
					return $negative.($digits === '' ? '0' : $digits);
				}

				$whole = preg_replace('/\D/', '', substr($value, 0, $decimalPos));
				$decimal = rtrim(preg_replace('/\D/', '', substr($value, $decimalPos + 1)), '0');
				$whole = $whole === '' ? '0' : $whole;
				return $negative.$whole.($decimal !== '' ? '.'.$decimal : '');
			}

			private function harga_response($value)
			{
				$value = (float) $value;
				return rtrim(rtrim(number_format($value, 4, '.', ''), '0'), '.');
			}

			private function ensure_invoice_detail_decimal_schema()
			{
				if (!$this->db->table_exists('invoice_detail')) {
					return;
				}

				foreach (['harga_satuan', 'harga'] as $field) {
					foreach ($this->db->field_data('invoice_detail') as $meta) {
						if ($meta->name === $field && stripos($meta->type, 'decimal') === false) {
							$this->db->query("ALTER TABLE `invoice_detail` MODIFY `$field` DECIMAL(15,4) NULL DEFAULT 0");
							break;
						}
					}
				}
			}

		
		/**
			* Summary of simpan_pajak
			* @return void
		*/
			public function simpan_pajak()
			{
				cek_nput_post("GET");
				$id    = xss_filter($this->input->post("id"), 'xss');
				$pajak = xss_filter($this->input->post("pajak"), 'xss');
				$total = xss_filter($this->input->post("totalbyr"), 'xss');
				$where = ["id_invoice" => $id];
				$data  = ["pajak" => $pajak];
				$res   = $this->model_app->update("invoice", $data, $where);
				$value = $this->hitung_pajak($total,$pajak);
				if ($res["status"] == "ok") {
					$data = ["ok" => "ok", 
					"pajak" => $pajak,
					"total_pajak" => $value['total_pajak'],
					'total_bayar'=>$value['total_bayar']
				];
			} else {
				$data = ["ok" => "err", "pajak" => 0,'total_pajak'=>0,'total_bayar'=>0];
			}
			echo json_encode($data);
		}
		
		private function hitung_pajak($total,$pajak)
		{
			if($pajak > 0){
				$hitung = ($total * $pajak)/100;
				return ['total_order'=>$total-$hitung,'total_pajak'=>$hitung,'total_bayar'=>$total];
			}else{
				return ['total_order'=>0,'total_pajak'=>0,'total_bayar'=>$total];
			}
		}
		/**
			* Summary of bayar_detail
			* @return void
		*/
			public function bayar_detail()
			{
				cek_nput_post("GET");
				$id = $this->input->post("id");
				$select = "SUM(jml_bayar) AS `total`";
				$where = ["id_invoice" => $id];
				$search = $this->model_app->cek_total(
					"bayar_invoice_detail` ",
					$select,
					$where
				);
			// print_r($search);
				if (!empty($search->total)) {
					$data = $search->total;
				} else {
					$data = 0;
				}
				$this->output
				->set_content_type("application/json")
				->set_output(json_encode($data));
			}
			
		/**
			* Summary of cek_jml_bayar
			* @return void
		*/
			public function cek_jml_bayar()
			{
				cek_nput_post("GET");
				$id = $this->input->post("id");
				$select = "total_bayar AS total";
				$where = ["id_invoice" => $id];
				$search = $this->model_app->cek_total("invoice", $select, $where);
				if (!empty($search->total)) {
					$data = $search->total;
				} else {
					$data = 0;
				}
				$this->output
				->set_content_type("application/json")
				->set_output(json_encode($data));
			}
			
		/**
			* Summary of cek_total_detail
			* @return void
		*/
			public function cek_total_detail()
			{
				cek_nput_post("GET");
				$id = $this->input->post("id");
				$select = "SUM(jumlah * harga) AS `total`";
				$where = ["id_invoice" => $id];
				$search = $this->model_app->cek_total(
					"invoice_detail",
					$select,
					$where
				);
				if (!empty($search->total)) {
					$data = $search->total;
				} else {
					$data = 0;
				}
				$this->output
				->set_content_type("application/json")
				->set_output(json_encode($data));
			}
			
		/**
			* Summary of cek_data_total
			* @return void
		*/
			public function cek_data_total()
			{
				cek_nput_post("GET");
				$id = $this->input->post("id");
				$iduser = $this->input->post("iduser");
				$pajak = $this->input->post("pajak");
				$where = ["id_invoice" => $id];
				$invoice = "total_bayar AS total";
				$searchin = $this->model_app->cek_total("invoice", $invoice, $where);
			//cek konsumen
				$idkon = $this->model_app->view_where("invoice", $where)->row();
				
				$this->cek_boleh_utang($idkon->id_konsumen, $id);
				
			//diskon
				$sisa =
				"ROUND(SUM((`invoice_detail`.`jumlah`) * (`invoice_detail`.`harga` * `invoice_detail`.`diskon`/100))) AS sisa";
				$cari_sisa = $this->model_app->cek_total(
					"invoice_detail",
					$sisa,
					$where
				);
			////
				$select = "SUM(jumlah * harga) AS `total`";
				$search = $this->model_app->cek_total(
					"invoice_detail",
					$select,
					$where
				);
				$total_detail = $search->total - $cari_sisa->sisa;
				$kurangpajak = $searchin->total - $total_detail;
				$total_bayar = $searchin->total - $kurangpajak;
				if ($total_detail == $total_bayar and $pajak > 0) {
					$data = [
						"urutan" => 1,
						"ok" => "ok",
						"id" => $id,
						"iduser" => $iduser,
						"total" => $total_detail,
					];
				} elseif ($total_detail == $searchin->total and $pajak == 0) {
					$data = [
						"urutan" => 2,
						"ok" => "ok",
						"id" => $id,
						"idkon" => $idkon->id_konsumen,
						"iduser" => $iduser,
						"total" => $total_detail,
					];
				} else {
					$data = [
						"urutan" => 3,
						"ok" => "err",
						"id" => $id,
						"idkon" => $idkon->id_konsumen,
						"iduser" => $iduser,
						"total" => 0,
						"tipe" => "simpan_cetak",
					];
				}
			// echo json_encode($data);
				$this->output
				->set_content_type("application/json")
				->set_output(json_encode($data));
			}
			
		/**
			* cek_di_invoice
			*
			* @return void
		*/
			public function cek_di_invoice()
			{
				cek_nput_post("GET");
				$id = $this->input->post("id");
				$total = $this->input->post("total");
				$pajak = $this->input->post("pajak");
				$where = ["id_invoice" => $id];
			// $invoice = 'total_bayar AS total';
				$invoice = "SUM(total_bayar) AS `total`";
			//cek konsumen
				$idkon = $this->model_app->view_where("invoice", $where)->row();
			//cek total invoice
				$searchin = $this->model_app->cek_total("invoice", $invoice, $where);
			//cek pajak di invoice
				
			//diskon`/100
				$sisa =
				"ROUND(SUM((`invoice_detail`.`jumlah` * `invoice_detail`.`harga`) - (`invoice_detail`.`jumlah` * `invoice_detail`.`harga` * `invoice_detail`.`diskon`/100))) AS sisa";
				$cari_sisa = $this->model_app->cek_total(
					"invoice_detail",
					$sisa,
					$where
				);
			//invoice_detail
				$select = "SUM(jumlah * harga) AS `total`";
				$search = $this->model_app->cek_total(
					"invoice_detail",
					$select,
					$where
				);
				$total_detail = $cari_sisa->sisa;
				if ($pajak > 0) {
					$pajak = $pajak;
					$total_detail = $total_detail + ($total_detail * $pajak) / 100;
				}
				if ($total_detail == $searchin->total and $pajak == 0) {
					$data = [
						"ok" => "ok",
						"id" => $id,
						"idkon" => $idkon->id_konsumen,
						"total" => $search->total,
					];
				} elseif ($total_detail == $searchin->total and $pajak > 0) {
					$data = [
						"ok" => "ok",
						"id" => $id,
						"idkon" => $idkon->id_konsumen,
						"total" => $search->total,
					];
				} else {
					$data = [
						"ok" => "err",
						"id" => $id,
						"idkon" => $idkon->id_konsumen,
						"total_1" => $searchin->total,
						"total_2" => $search->total,
						"sisa" => $cari_sisa->sisa,
						"total" => $total_detail,
						"tipe" => "simpan",
					];
				}
				$this->output
				->set_content_type("application/json")
				->set_output(json_encode($data));
			}
			
		/**
			* Summary of update_data
			* @return void
		*/
			public function update_data()
			{
				cek_nput_post("GET");
				$id = $this->input->post("id");
				$iduser = $this->input->post("iduser");
				$idlunas = $this->input->post("idlunas");
				$total = $this->input->post("total");
				$tipe = $this->input->post("tipe");
				if ($tipe === 'bayar') {
					wajib_akses_bayar_order_json();
				}
				$data = ["total_bayar" => $total];
				$where = ["id_invoice" => $id];
				$idkon = $this->model_app->view_where("invoice", $where)->row();
				$search = $this->model_app->update("invoice", $data, $where);
				$this->persist_invoice_komisi_from_request($id);
				
			//sum detail
				$cdetail = $this->model_app->cek_total(
					"invoice_detail",
					"SUM(jumlah * harga) AS `jml`",
					["id_invoice" => $id]
				);
				if ($idlunas == 1 and $cdetail->jml != $total) {
					$this->model_app->update("invoice", ["lunas" => 0], $where);
				}
				
			//end
				if ($search["status"] == "ok") {
					$this->model_app->update(
						"tb_users",
						["last_invoice" => $id],
						["id_user" => $iduser]
					);
					$data = [
						"ok" => "ok",
						"id" => encrypt_url($id),
						"idkon" => $idkon->id_konsumen,
						"tipe" => $tipe,
						"total" => $total,
					];
				} else {
					$data = [
						"ok" => "err",
						"id" => 0,
						"idkon" => 0,
						"tipe" => "",
						"total" => 0,
					];
				}
				$this->output
				->set_content_type("application/json")
				->set_output(json_encode($data));
			}
			
		/**
			* Summary of update_lunas
			* @return void
		*/
			public function update_lunas()
			{
				cek_nput_post("GET");
				$noin = $this->input->post("id");
				$iduser = $this->input->post("iduser");
				$total = $this->input->post("total");
				$status = $this->input->post("status");
				
				if ($noin != null and $total > 0) {
					
				//cek jml bayar
					$select = "SUM(jml_bayar) AS `total`";
					$where = ["id_invoice" => $noin];
					$search = $this->model_app->cek_total(
						"bayar_invoice_detail`",
						$select,
						$where
					);
				//total di invoice
					$invoice = "total_bayar AS total, potongan_harga AS diskon, cashback AS cashback";
					$searchin = $this->model_app->cek_total(
						"invoice",
						$invoice,
						$where
					);
					$total_bayar = $search->total;
					if($searchin->diskon > 0){
						$total_bayar = $search->total + $searchin->diskon;
					}
					
					if ($searchin->total == $total_bayar) {
						$this->model_app->update(
							"invoice",
							["lunas" => 1],
							["id_invoice" => $noin]
						);
						$data = [
							"ok" => "ok",
							"id" => $noin,
							"iduser" => $iduser,
							"total" => $search->total,
							"lunas" => 'Y',
						];
					} else {
						$data = [
							"ok" => "ok",
							"id" => $noin,
							"iduser" => $iduser,
							"total" => $searchin->total,
							"lunas" => 'N',
						];
					}
				}
				$this->output
				->set_content_type("application/json")
				->set_output(json_encode($data));
			}
			
		/**
			* Summary of trx
			* @param mixed $id
			* @return void
		*/
			public function trx($id = "")
			{
				$data["id"] = $id;
				$conditions["returnType"] = "count";
				$totalRec = $this->model_data->getRows($conditions);
				
			// Pagination configuration
				$config["target"] = "#dataList";
				$config["base_url"] = base_url("penjualan/ajaxPaginationData");
				$config["total_rows"] = $totalRec;
				$config["per_page"] = $this->perPage;
				
			// Initialize pagination library
				$this->ajax_pagination->initialize($config);
				
			// Get records
				$conditions = [
					"limit" => $this->perPage,
				];
				$data["posts"] = $this->model_data->getRows($conditions);
				
				$this->load->view("penjualan/trx", $data);
			}
			
		/**
			* Summary of order
			* @return void
		*/
			public function order()
			{
				cek_menu_akses();
				cek_crud_akses(8);
				$this->template->set("title", "Data order | " . $this->title);
				$data["id"] = "";
				$data["tgl"] = tgl_dari_slash().' - '.tgl_sampai_slash();
				$data["select"] = [
					0 => "SEMUA",
					1 => "LUNAS",
					2 => "BELUM LUNAS",
					"belum_dibayar" => "BELUM DI BAYAR",
					"dibayar_sebagian" => "DIBAYAR SEBAGIAN",
					"ditagih" => "DITAGIH",
					"baru" => "BARU / BELUM DISIMPAN",
					"pending" => "PENDING",
					"edit" => "EDIT",
					"batal" => "BATAL",
				];
				
				
				$this->template->load("main/themes", "penjualan/order", $data);
			}
			
		/**
			* Summary of ajaxPaginationData
			* @return void
		*/
			function ajaxPaginationData()
			{
				cek_nput_post("GET");
				$page = $this->input->post("page");
				if (!$page) {
					$offset = 0;
				} else {
					$offset = $page;
				}
				
				$limits = $this->input->post("limits");
				if (!empty($limits)) {
					$limit = $limits;
				} else {
					$limit = $this->perPage;
				}
			// Set conditions for search and filter
				$keywords = $this->input->post("keywords");
				$sortBy = $this->input->post("sortBy");
				$trx = $this->input->post("trx");
				$tgl = $this->input->post("tgl");
				
				$data['tanggal']	= 'TANGGAL : '.day_ymd();
				if (!empty($trx)) {
					$conditions["search"]["trx"] = $trx;
				}
				if (!empty($keywords)) {
					if (transaction_number_has_prefix($keywords)) {
						$conditions["search"]["keywords"] = $keywords;
						$arr["a"] = "a";
					} elseif (substr(trim($keywords), 0, 1) == "0") {
						$conditions["search"]["keywords"] = $keywords;
						$arr["a"] = "b";
					} elseif (substr(trim($keywords), 0, 2) == "62") {
						$conditions["search"]["keywords"] = clearnohp($keywords);
						$arr["a"] = "c";
					} elseif (substr(trim($keywords), 0, 3) == "+62") {
						$conditions["search"]["keywords"] = clearnohp($keywords);
						$arr["a"] = "d";
					} elseif (substr(trim($keywords), 0, 1) == "#") {
						$conditions["search"]["keywords"] = clean($keywords);
						$arr["a"] = "f";
					} else {
						$conditions["search"]["keywords"] = trim($keywords);
						$arr["a"] = "g";
					}
				// print_r($arr);
				}
				if (!empty($sortBy)) {
					$conditions["search"]["sortBy"] = $sortBy;
				}
				if (!empty($limits)) {
					$conditions["search"]["limits"] = $limits;
				}
				if (!empty($tgl)) {
					$date = date_ranges($tgl);
					$dari = date_replace_slash($date['dari']);
					$sampai = date_replace_slash($date['sampai']);
					$conditions["search"]["dari"] = $dari;
					$conditions["search"]["sampai"] = $sampai;
					if(strtotime($dari)==strtotime($sampai)){
						$data['tanggal']	= 'TANGGAL : '.$date['dari'];
					}else{
						$data['tanggal']	= 'PEROIDE : '.$date['dari'].' - '.$date['sampai'];
					}
				}
			// dump($conditions);
			// Get record count
				$conditions["returnType"] = "count";
				$totalRec = $this->model_penjualan->getRows($conditions);
				
			// Pagination configuration
				$config["target"] = "#dataList";
				$config["base_url"] = base_url("penjualan/ajaxPaginationData");
				$config["total_rows"] = $totalRec;
				$config["per_page"] = $limit;
				$config["link_func"] = "searchFilter";
				
			// Initialize pagination library
				$this->ajax_pagination->initialize($config);
				
			// Get records
				$conditions["start"] = $offset;
				$conditions["limit"] = $limit;
				
				unset($conditions["returnType"]);
				$data["posts"] = $this->model_penjualan->getRows($conditions);
				$data["sum_page"] = $this->calculate_order_totals_from_rows($data["posts"]);
				$data["total_rec"] = (int) $totalRec;
				$data["limit_used"] = (int) $limit;

				$sumConditions = $conditions;
				unset($sumConditions["start"], $sumConditions["limit"]);
				$data["sum"] = $totalRec <= $limit
					? $data["sum_page"]
					: $this->calculate_order_totals_from_rows($this->model_penjualan->getRows($sumConditions));
				
			// Load the data list view
				$this->load->view("penjualan/ajax-order", $data, false);
			}
			
		/**
			* Summary of pending_data
			* @return void
		*/
			public function pending_data()
			{
				cek_nput_post("GET");
				$noin = $this->input->post("id");
				$cari_pending = $this->model_app->view_where("invoice", [
					"status" => "pending",
					"id_invoice" => $noin,
				]);
				if ($cari_pending->num_rows() > 0) {
					$data = ["ok" => "pending"];
				} else {
					$res = $this->model_app->update(
						"invoice",
						[
							"pos" => "N",
							"status" => "pending",
							"id_user" => $this->iduser,
						],
						["id_invoice" => $noin]
					);
					if ($res["status"] == "ok") {
						$this->model_app->update(
							"tb_users",
							["last_invoice" => 0],
							["id_user" => $this->iduser]
						);
						$this->session->unset_userdata("cart");
						$data = ["ok" => "ok"];
					} else {
						$data = ["ok" => "err"];
					}
				}
				$this->output
				->set_content_type("application/json")
				->set_output(json_encode($data));
			}
			
		/**
			* Summary of grafik
			* @return void
		*/
			public function grafik()
			{
				$page = $this->input->post("bulan");
				$tahunReq = $this->input->post("tahun", true);
				if (!empty($page)) {
					$bulan = (int)$page;
				} else {
					$bulan = (int)date("m");
				}
				$bulan = max(1, min(12, $bulan));
				$tahun = !empty($tahunReq) ? (int)$tahunReq : (int)date("Y");
				$totalRec = $this->model_data->grafik_perbulan($bulan, $tahun);
				$mapHarian = [];
				if (!empty($totalRec)) {
					foreach ($totalRec as $row) {
						$hari = (int)$row->hari;
						if (!isset($mapHarian[$hari])) {
							$mapHarian[$hari] = 0;
						}
						$mapHarian[$hari] += (float)$row->jml_bayar;
					}
				}
				$hasil = ["omset" => []];
				$jumlahHari = cal_days_in_month(CAL_GREGORIAN, $bulan, $tahun);
				for ($hari = 1; $hari <= $jumlahHari; $hari++) {
					$hasil["omset"][] = [
						"total" => isset($mapHarian[$hari]) ? $mapHarian[$hari] : 0,
						"tanggal" => "TGL." . $hari,
					];
				}
				$bulan = ["bulan" => getBulan($bulan), "tahun" => (string)$tahun];
				$array_merge = array_merge($hasil, $bulan);
			// print_r($array_merge);exit;
				echo json_encode($array_merge);
			}
			
		/**
			* Summary of grafik_desain
			* @return void
		*/
			public function grafik_desain()
			{
				$page = $this->input->post("bulan");
				$tahunReq = $this->input->post("tahun", true);
				$hari = date("d");
				if (!empty($page)) {
					$bulan = $page;
				} else {
					$bulan = date("m");
				}
				$tahun = !empty($tahunReq) ? (int)$tahunReq : (int)date("Y");
				$where = ["id_desain" => $this->iduser];
				$totalRec = $this->model_data->grafik_perbulan_desain(
					$bulan,
					$tahun,
					$where
				);
				$hasil = [];
				if (!empty($totalRec)) {
					foreach ($totalRec as $row) {
						$hasil["omset"][] = [
							"total" => $row->counter,
							"tanggal" => "TGL." . $row->hari,
						];
					}
				} else {
					$hasil["omset"][] = [
						"total" => 0,
						"tanggal" =>  "TGL." . $hari,
					];
				}
				$bulan = ["bulan" => getBulan($bulan), "tahun" => (string)$tahun];
				$array_merge = array_merge($hasil, $bulan);
				echo json_encode($array_merge);
			}


			public function grafik_dashboard_6bulan()
			{
			  $end = new DateTime(date('Y-m-01')); // awal bulan ini

			  $labels = [];
			  $pendapatan = [];
			  $beban = [];
			  $arus_kas = [];

			  for ($i = 5; $i >= 0; $i--) {
			    $dt = (clone $end)->modify('-' . $i . ' months');

			    $monthStart = $dt->format('Y-m-01');
			    $monthEnd   = $dt->format('Y-m-t');

			    // 1) Pendapatan = SUM(jml_bayar) dari bayar_invoice_detail per bulan
			    $this->db->select('SUM(bid.jml_bayar) AS total', false);
			    $this->db->from('bayar_invoice_detail bid');
			    $this->db->where('bid.tgl_bayar >=', $monthStart);
			    $this->db->where('bid.tgl_bayar <=', $monthEnd);
			    $rowP = $this->db->get()->row_array();
			    $valPendapatan = isset($rowP['total']) ? (float)$rowP['total'] : 0;

			    // 2) Pengeluaran = SUM(kas_keluar.jumlah) per bulan
			    $this->db->select('SUM(kk.jumlah) AS total', false);
			    $this->db->from('kas_keluar kk');
			    $this->db->where('kk.tanggal >=', $monthStart);
			    $this->db->where('kk.tanggal <=', $monthEnd);
			    $rowK = $this->db->get()->row_array();
			    $valPengeluaran = isset($rowK['total']) ? (float)$rowK['total'] : 0;

			    // 3) Pembelian = SUM(pembelian_detail.jumlah * pembelian_detail.harga) per bulan
			    $this->db->select('SUM(pbd.jumlah * pbd.harga) AS total', false);
			    $this->db->from('pembelian pb');
			    $this->db->join('pembelian_detail pbd', 'pb.id_pembelian = pbd.id_pembelian', 'left');
			    $this->db->where('pb.tgl_pembelian >=', $monthStart);
			    $this->db->where('pb.tgl_pembelian <=', $monthEnd);
			    $rowB = $this->db->get()->row_array();
			    $valPembelian = isset($rowB['total']) ? (float)$rowB['total'] : 0;

			    $valBeban = $valPengeluaran + $valPembelian;
			    $valArusKas = $valPendapatan - $valBeban;

			    $labels[]     = $dt->format('M Y'); // contoh: Dec 2025
			    $pendapatan[] = (int)round($valPendapatan);
			    $beban[]      = (int)round($valBeban);
			    $arus_kas[]   = (int)round($valArusKas);
			  }

			  $out = [
			    'labels'     => $labels,
			    'pendapatan' => $pendapatan,
			    'beban'      => $beban,
			    'arus_kas'   => $arus_kas,
			  ];

			  return $this->output
			    ->set_content_type('application/json')
			    ->set_output(json_encode($out));
			}


			public function dashboard_extra_charts()
			{
			    // Output JSON
			    $this->output->set_content_type("application/json");

			    // ==============================
			    // RANGE dari AJAX: month | 3m | 6m | year
			    // Default: 3m
			    // ==============================
			    $range = strtolower(trim((string) $this->input->get('range', true)));
			    if (!in_array($range, ['month', '3m', '6m', 'year'], true)) {
			        $range = '3m';
			    }

			    // hitung start & end
			    $today    = date('Y-m-d');
			    $endNext  = date('Y-m-d', strtotime($today . ' +1 day')); // pakai < endNext agar aman kalau tgl_trx datetime

			    switch ($range) {
			        case 'month':
			            // bulan ini: dari tgl 1 bulan ini sampai hari ini
			            $start = date('Y-m-01');
			            break;

			        case 'year':
			            // tahun ini: 1 Jan sampai hari ini
			            $start = date('Y-01-01');
			            break;

			        case '6m':
			            // 6 bulan terakhir: mulai tgl 1, 5 bulan lalu (include bulan ini)
			            $start = date('Y-m-01', strtotime('-5 months'));
			            break;

			        case '3m':
			        default:
			            // 3 bulan terakhir: mulai tgl 1, 2 bulan lalu (include bulan ini)
			            $start = date('Y-m-01', strtotime('-2 months'));
			            break;
			    }

			    // ==============================
			    // 1) "Produk Terlaris" (sebenarnya bahan terlaris) - tetap key: produk_terlaris
			    // ==============================

			    // --- Top bahan by NILAI (Rp) ---
			    $this->db->select("
			        IF(d.id_bahan = 0 OR b.title IS NULL OR b.title = '', '(Bahan tidak di-set)', b.title) AS label,
			        SUM( (d.jumlah * d.harga) - IFNULL(d.diskon,0) ) AS total
			    ", false);
			    $this->db->from('invoice_detail d');
			    $this->db->join('invoice i', 'i.id_invoice = d.id_invoice', 'left');
			    $this->db->join('bahan b', 'b.id = d.id_bahan', 'left');
			    $this->db->where('i.tgl_trx >=', $start);
			    $this->db->where('i.tgl_trx <',  $endNext);
			    $this->db->where('i.status !=', 'batal');
			    $this->db->group_by('d.id_bahan');
			    $this->db->order_by('total', 'DESC');
			    $this->db->limit(9);
			    $qNilai = $this->db->get()->result();

			    $labelsNilai = [];
			    $valuesNilai = [];
			    foreach ($qNilai as $r) {
			        $labelsNilai[] = (string) $r->label;
			        $valuesNilai[] = (float)  $r->total;
			    }

			    // --- Top bahan by QTY ---
			    $this->db->select("
			        IF(d.id_bahan = 0 OR b.title IS NULL OR b.title = '', '(Bahan tidak di-set)', b.title) AS label,
			        SUM(d.jumlah) AS total
			    ", false);
			    $this->db->from('invoice_detail d');
			    $this->db->join('invoice i', 'i.id_invoice = d.id_invoice', 'left');
			    $this->db->join('bahan b', 'b.id = d.id_bahan', 'left');
			    $this->db->where('i.tgl_trx >=', $start);
			    $this->db->where('i.tgl_trx <',  $endNext);
			    $this->db->where('i.status !=', 'batal');
			    $this->db->group_by('d.id_bahan');
			    $this->db->order_by('total', 'DESC');
			    $this->db->limit(9);
			    $qQty = $this->db->get()->result();

			    $labelsQty = [];
			    $valuesQty = [];
			    foreach ($qQty as $r) {
			        $labelsQty[] = (string) $r->label;
			        $valuesQty[] = (float)  $r->total;
			    }

			    $produk_terlaris = [
			        'nilai' => ['labels' => $labelsNilai, 'values' => $valuesNilai],
			        'qty'   => ['labels' => $labelsQty,   'values' => $valuesQty],
			    ];

			    // ==============================
			    // 2) Pelanggan transaksi terbesar
			    // ==============================
			    $this->db->select("
			        IF(k.nama IS NULL OR k.nama = '', 'Pelanggan', k.nama) AS label,
			        SUM( (d.jumlah * d.harga) - IFNULL(d.diskon,0) ) AS total
			    ", false);
			    $this->db->from('invoice i');
			    $this->db->join('invoice_detail d', 'd.id_invoice = i.id_invoice', 'left');
			    $this->db->join('konsumen k', 'k.id = i.id_konsumen', 'left');
			    $this->db->where('i.tgl_trx >=', $start);
			    $this->db->where('i.tgl_trx <',  $endNext);
			    $this->db->where('i.status !=', 'batal');
			    $this->db->group_by('i.id_konsumen');
			    $this->db->order_by('total', 'DESC');
			    $this->db->limit(9);
			    $qPelanggan = $this->db->get()->result();

			    $pelLabels = [];
			    $pelValues = [];
			    foreach ($qPelanggan as $r) {
			        $pelLabels[] = (string) $r->label;
			        $pelValues[] = (float)  $r->total;
			    }

			    $pelanggan_terbesar = [
			        'labels' => $pelLabels,
			        'values' => $pelValues,
			    ];

			    // ==============================
				// 3) Stok bahan menipis
				// Samakan rule dengan halaman Data Stok Barang:
				// - stok_total <= 0                        => STOK KOSONG
				// - batas_minimum_stok > 0 && stok <= batas => LOW STOCK
				// ==============================
				if (!$this->db->field_exists('batas_minimum_stok', 'bahan')) {
					$this->load->dbforge();
					$this->dbforge->add_column('bahan', [
						'batas_minimum_stok' => [
							'type' => 'DECIMAL',
							'constraint' => '15,2',
							'default' => '0.00',
							'null' => false,
							'after' => 'status_stok',
						],
					]);
				}

				$this->db->select("
				  b.id,
				  b.title,
				  b.id_satuan,
				  st.satuan AS satuan,
				  IFNULL(b.batas_minimum_stok,0) AS batas_minimum_stok,
				  IFNULL(sm.masuk,0) AS stok_masuk,
				  IFNULL(sk.keluar,0) AS stok_keluar,
				  (IFNULL(sm.masuk,0) - IFNULL(sk.keluar,0)) AS stok_total,
				  CASE
				    WHEN (IFNULL(sm.masuk,0) - IFNULL(sk.keluar,0)) <= 0 THEN 'stok_kosong'
				    WHEN IFNULL(b.batas_minimum_stok,0) > 0
				      AND (IFNULL(sm.masuk,0) - IFNULL(sk.keluar,0)) <= IFNULL(b.batas_minimum_stok,0)
				      THEN 'low_stock'
				    ELSE ''
				  END AS stok_status,
				  CASE
				    WHEN (IFNULL(sm.masuk,0) - IFNULL(sk.keluar,0)) <= 0 THEN 'STOK KOSONG'
				    WHEN IFNULL(b.batas_minimum_stok,0) > 0
				      AND (IFNULL(sm.masuk,0) - IFNULL(sk.keluar,0)) <= IFNULL(b.batas_minimum_stok,0)
				      THEN 'LOW STOCK'
				    ELSE ''
				  END AS stok_label
				", false);

				$this->db->from('bahan b');
				$this->db->join('satuan st', 'st.id = b.id_satuan', 'left');
				$this->db->join("(SELECT id_bahan, SUM(jumlah) AS masuk FROM stok_masuk GROUP BY id_bahan) sm", "sm.id_bahan=b.id", "left", false);
				$this->db->join("(SELECT id_bahan, SUM(jumlah) AS keluar FROM stok_keluar GROUP BY id_bahan) sk", "sk.id_bahan=b.id", "left", false);

				$this->db->where('b.pub', 1);
				$this->db->where('b.status_stok', 'Y');

				$having = "(stok_total <= 0 OR (batas_minimum_stok > 0 AND stok_total <= batas_minimum_stok))";
				$this->db->having($having, null, false);


				$this->db->order_by('stok_total', 'ASC');
				$this->db->order_by('b.title', 'ASC');

				$stok_menipis = $this->db->get()->result_array();


			    // ==============================
			    // OUTPUT
			    // ==============================
			    $out = [
			        'range'               => $range,             // optional: buat debugging di browser network
			        'range_start'         => $start,             // optional
			        'range_end_exclusive' => $endNext,           // optional
			        'produk_terlaris'     => $produk_terlaris,
			        'pelanggan_terbesar'  => $pelanggan_terbesar,
			        'stok_menipis'        => $stok_menipis,
			    ];

			    return $this->output->set_output(json_encode($out));
			}





			
		/**
			* Summary of ajaxKonsumen
			* @return void
		*/
			function ajaxKonsumen()
			{
				cek_nput_post("GET");
				$page = $this->input->post("page");
				if (!$page) {
					$offset = 0;
				} else {
					$offset = $page;
				}
				
				$limits = $this->input->post("limits");
				if (!empty($limits)) {
					$limit = $limits;
				} else {
					$limit = $this->perPage;
				}
			// Set conditions for search and filter
				$keywords = $this->input->post("keywords");
				$sortBy = $this->input->post("sortBy");
				
				if (!empty($keywords)) {
					$conditions["search"]["keywords"] = $keywords;
				}
				if (!empty($sortBy)) {
					$conditions["search"]["sortBy"] = $sortBy;
				}
				if (!empty($limits)) {
					$conditions["search"]["limits"] = $limits;
				}
				
			// Get record count
				$conditions["returnType"] = "count";
				$totalRec = $this->model_data->getKonsumen($conditions);
				
			// Pagination configuration
				$config["target"] = "#dataListKonsumen";
				$config["base_url"] = base_url("konsumen/ajaxKonsumen");
				$config["total_rows"] = $totalRec;
				$config["per_page"] = $limit;
				$config["link_func"] = "searchFilterKonsumen";
				
			// Initialize pagination library
				$this->ajax_pagination->initialize($config);
				
			// Get records
				$conditions["start"] = $offset;
				$conditions["limit"] = $limit;
				unset($conditions["returnType"]);
				$data["posts"] = $this->model_data->getKonsumen($conditions);
				
			// Load the data list view
				$this->load->view("konsumen/ajax-konsumen", $data, false);
			}
			
		/**
			* Summary of cek_harga_type
			* @return never
		*/
			public function cek_harga_type()
			{
				$this->ensureBahanUkuranDefaultSchema();
				$cari_produk = $this->input->post("cari_produk");
				$id_konsumen = $this->input->post("id_konsumen_cari");
				$id_detail = $this->input->post("id_detail");
				$invoice_add = $this->input->post("invoice_add");
				$id_member = $this->input->post("idmember_add");
				$jumlah = $this->input->post("jumlah");
				if(empty($jumlah))
				{
					$jumlah = 1;
				}else{
					$jumlah = $jumlah;
				}
			// $id_member = $this->model_app->pilih_where('jenis_member','konsumen',['id'=>$id_konsumen])->row()->jenis_member;
				
				if (!empty($cari_produk) and (int)$cari_produk) {
					
					$result = $this->cari_produk($cari_produk);
					if ($result != false) {
						$row = $result->row();
						$id_bahan =  $row->id_bahan;
						$this->cek_stok($id_bahan, 1);
						$getBahan = getDetailBahan($id_bahan);
						$array = ['type_harga' => $getBahan->type_harga, 'id_bahan' => $row->id_bahan, 'id_member' => $id_member, 'jumlah' => $jumlah];
						$getHarga = $this->model_data->getHarga($array);
						$ukuran_default = $this->getBahanUkuranDefaultById($getHarga['id_bahan'], $row->ukuran);
						
						$data_insert = [
							'id_invoice' => $invoice_add,
							'id_produk' => $row->id,
							'jenis_cetakan' => $row->id_jenis,
							'status_hitung' => $getBahan->status,
							'type_harga' => $getBahan->type_harga,
							'jumlah' => $row->jumlah,
							'harga' => $getHarga['harga'],
							'id_satuan' => $getHarga['satuan'],
							'ukuran' => $ukuran_default,
							'id_bahan' => $getHarga['id_bahan'],
						];
						$addDetail = $this->addDetail($data_insert);
						
						if ($addDetail['status'] == true) {
							
							$data = [
								'status' => 'qr',
								'id' => $addDetail['id'],
								'kodeproduk' => $row->title,
								'id_produk' => $row->id,
								'harga' => $getHarga['harga'],
								'jenis_cetakan' => $row->jenis_cetakan,
								'id_jenis' => $row->id_jenis,
								'bahan' => $getHarga['title'],
								'id_bahan' => $getHarga['id_bahan'],
								'status_hitung' => $getBahan->status,
								'type_harga' => $getBahan->type_harga,
								'id_satuan' => $getHarga['satuan'],
								'ukuran' => $ukuran_default,
								'jumlah' => $row->jumlah,
								'lock_harga' => $row->lock_harga,
								'iddetail' => $id_detail,
							];
						} else {
							$data = ['status' => false, 'msg' => 'qr 1'];
						}
					} else {
						$data = ['status' => false, 'msg' => 'qr 2'];
					}
				} else {
					$id_bahan = (!empty($this->input->post('id_bahan')) ? $this->input->post('id_bahan') : 0);
					$jumlah = (!empty($this->input->post('jumlah')) ? $this->input->post('jumlah') : 1);
					
					$type_harga = $this->input->post("type_harga");
					$configured_type_harga = $type_harga;
					$id_satuan = $this->input->post("satuan_add");
					$harga_jual = $satuan = 0;
					
					$this->cek_stok($id_bahan, $jumlah);

					if ((int) $type_harga === 6) {
						$type_harga = resolve_semua_metode_harga(
							$id_bahan,
							isset($id_member) ? $id_member : 0,
							isset($id_satuan) ? $id_satuan : 0,
							$jumlah
						);
					}
					
					if ($type_harga == 1) {
						$sql1 = $this->db->query("SELECT 
							`satuan`.`id` AS idsatuan,
							`satuan`.`satuan`,
							`satu_harga`.`harga_jual`,
							`bahan`.`title`
							FROM
							`bahan`
							INNER JOIN `satu_harga` ON (`bahan`.`id` = `satu_harga`.`id_bahan`)
							INNER JOIN `satuan` ON (`satu_harga`.`id_satuan` = `satuan`.`id`)
							WHERE
							`bahan`.`id` = $id_bahan");
						if ($sql1->num_rows() > 0) {
							$harga_jual = $sql1->row()->harga_jual;
							$satuan = $sql1->row()->idsatuan;
						} else {
							$sql = $this->db->query("select id,id_satuan,harga_jual from bahan where id=$id_bahan");
							$harga_jual = $sql->row()->harga_jual;
							$satuan = $sql->row()->id_satuan;
						}
						$data = ['status' => true, 'harga' => $harga_jual, 'satuan' => $satuan, 'id_bahan' => $id_bahan];
					} elseif ($type_harga == 2) {
						$default = $this->db->query("select id,id_satuan,harga_jual from bahan where id=$id_bahan")->row();
						$sql2 = $this->db->query("SELECT 
							`satuan`.`id` AS idsatuan,
							`satuan`.`satuan`,
							`harga_satuan`.`id_satuan`,
							`bahan`.`title`,
							`harga_satuan`.`harga_jual`,
							`harga_satuan`.`id_bahan`
							FROM
							`satuan`
							INNER JOIN `harga_satuan` ON (`satuan`.`id` = `harga_satuan`.`id_satuan`)
							INNER JOIN `bahan` ON (`harga_satuan`.`id_bahan` = `bahan`.`id`)
							WHERE
							`harga_satuan`.`id_bahan` = $id_bahan AND `harga_satuan`.`id_satuan` = {$default->id_satuan}");
						if ($sql2->num_rows() > 0) {
							$harga_jual = $sql2->row()->harga_jual;
							$satuan = $sql2->row()->id_satuan;
						} else {
							$harga_jual = $default->harga_jual;
							$satuan = $default->id_satuan;
						}
						$data = ['status' => true, 'harga' => $harga_jual, 'satuan' => $satuan, 'type_harga' => $type_harga];
					} elseif ($type_harga == 3) {
						
						$sql3 = $this->db->query("SELECT 
							`harga_member`.`id_bahan`,
							`harga_member`.`id_satuan`,
							`harga_member`.`id_member`,
							`harga_member`.`harga_jual`
							FROM
							`satuan`
							INNER JOIN `harga_member` ON (`satuan`.`id` = `harga_member`.`id_satuan`)
							INNER JOIN `bahan` ON (`harga_member`.`id_bahan` = `bahan`.`id`)
							INNER JOIN `konsumen` ON (`harga_member`.`id_member` = `konsumen`.`jenis_member`)
							WHERE
							`harga_member`.`id_member` = $id_member AND 
							`harga_member`.`id_bahan` = $id_bahan
							GROUP BY
							`harga_member`.`id_bahan`,
							`harga_member`.`id_satuan`,
							`harga_member`.`id_member`,
							`harga_member`.`harga_jual`");
						if ($sql3->num_rows() > 0) {
							$harga_jual = $sql3->row()->harga_jual;
							$satuan = $sql3->row()->id_satuan;
						} else {
							$sql = $this->db->query("select id,id_satuan,harga_jual from bahan where id=$id_bahan");
							$harga_jual = $sql->row()->harga_jual;
							$satuan = $sql->row()->id_satuan;
						}
						$data = ['status' => true, 'harga' => $harga_jual, 'satuan' => $satuan, 'type_harga' => $type_harga];
					} elseif ($type_harga == 4) {
						
						
						$sql = $this->db->query("select id_satuan,harga_jual from range_harga where id_bahan=$id_bahan AND $jumlah between jumlah_minimal and jumlah_maksimal");
						if ($sql->num_rows() > 0) {
							$harga_jual = $sql->row()->harga_jual;
							$satuan = $sql->row()->id_satuan;
						} else {
							$sql = $this->db->query("select id,id_satuan,harga_jual from bahan where id=$id_bahan");
							$harga_jual = $sql->row()->harga_jual;
							$satuan = $sql->row()->id_satuan;
						}
						$data = ['status' => true, 'harga' => $harga_jual, 'satuan' => $satuan, 'type_harga' => $type_harga];
						
					//cari type harga 5
					} elseif ($type_harga == 5) {
						$sql4 = $this->db->query("select id_satuan,harga_jual from harga_range_member where id_bahan=$id_bahan AND id_member='$id_member' AND $jumlah between jumlah_minimal and jumlah_maksimal");
						if ($sql4->num_rows() > 0) {
							$harga_jual = $sql4->row()->harga_jual;
							$satuan = $sql4->row()->id_satuan;
						} else {
							$sql = $this->db->query("select id,id_satuan,harga_jual from bahan where id=$id_bahan");
							$harga_jual = $sql->row()->harga_jual;
							$satuan = $sql->row()->id_satuan;
						}
						$data = ['status' => true, 'harga' => $harga_jual, 'satuan' => $satuan, 'type_harga' => $type_harga];
					} else {
						$sql = $this->db->query("select id,id_satuan,harga_jual from bahan where id=$id_bahan");
						$harga_jual = $sql->row()->harga_jual;
						$satuan = $sql->row()->id_satuan;
						$data = ['status' => true, 'harga' => $harga_jual, 'satuan' => $satuan, 'type_harga' => $type_harga];
					}
				}

				if (isset($configured_type_harga) && (int) $configured_type_harga === 6 && is_array($data)) {
					$data['type_harga'] = 6;
				}
				
				$this->output
				->set_content_type('application/json', 'utf-8')
				->set_output(json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES))
				->_display();
				exit;
			}
		/**
			* Summary of addDetail
			* @param mixed $param
			* @return array
		*/
			private function addDetail($param = array())
			{
				
				$res = $this->db->insert("invoice_detail", $param);
				$last_id = $this->db->insert_id();
				if ($res == true) {
					$data = ["status" => true, "id" => $last_id];
				} else {
					$data = ["status" => false, "id" => 0];
				}
				return $data;
			}
			
		/**
			* Summary of cari_produk
			* @param mixed $name
			* @return mixed
		*/
			private function cari_produk($name)
			{
				$query = "SELECT 
				`jenis_cetakan`.`jenis_cetakan`,
				`produk`.`barcode`,
				`produk`.`title`,
				`produk`.`ukuran`,
				`produk`.`id`,
				`produk`.`id_jenis`,
				`produk`.`id_bahan`,
				`produk`.`jumlah`,
				`produk`.`lock_harga`
				FROM
				`jenis_cetakan`
				INNER JOIN `produk` ON (`jenis_cetakan`.`id_jenis` = `produk`.`id_jenis`)
				where `produk`.`barcode`='" . $name . "' AND produk.pub='1'";
				$result = $this->db->query($query);
				if ($result->num_rows() > 0) {
					return $result;
				} else {
					return $this->cari_produk_barcode($name);
				}
			}
			
			private function cari_produk_barcode($name)
			{
				$query = "SELECT 
				`produk`.`title`,
				`produk`.`ukuran`,
				`produk`.`jumlah`,
				`produk`.`lock_harga`,
				`produk`.`harga_beli`,
				`bahan`.`id_satuan`,
				`bahan`.`harga_jual`,
				`bahan`.`type_harga`,
				`bahan`.`status`,
				`bahan`.`ukuran_default`,
				`satuan`.`id` AS `satuan`,
				`jenis_cetakan`.`jenis_cetakan`,
				`bahan`.`id` AS `id_bahan`,
				`produk`.`id_jenis`,
				`produk`.`kunci`,
				`bahan`.`barcode`,
				`bahan`.`status_stok`,
				`produk`.`id`
				FROM
				`produk`
				INNER JOIN `bahan` ON (`produk`.`id` = `bahan`.`id_produk`)
				INNER JOIN `satuan` ON (`bahan`.`id_satuan` = `satuan`.`id`)
				INNER JOIN `jenis_cetakan` ON (`produk`.`id_jenis` = `jenis_cetakan`.`id_jenis`)
				WHERE  `bahan`.`barcode` LIKE '%" . $name . "%' AND produk.pub=1";
				$result = $this->db->query($query);
				if ($result->num_rows() > 0) {
					return $result;
				} else {
					return false;
				}
			}
			
		/**
			* Summary of update_detail
			* @return void
		*/
			public function update_detail()
			{
				$id_konsumen = $this->input->post("idkonsumen");
				$id_bahan    = $this->input->post("idbahan");
				$jumlah      = $this->input->post("jumlah");
				$baris       = $this->input->post("baris");
				$totukuran   = $this->input->post("totukuran");
				
				$id_member = $this->model_app->pilih_where('jenis_member', 'konsumen', ['id' => $id_konsumen])->row()->jenis_member;
				$cek_status = $this->model_app->pilih_where('status_stok,type_harga,id_satuan,status', 'bahan', ['id' => $id_bahan])->row();
				$cek_satuan = $this->model_app->pilih_where('satuan', 'satuan', ['id' => $cek_status->id_satuan])->row();
				$type_harga = $cek_status->type_harga;
				
				if ($cek_status->status_stok == 'Y') {
					$this->cek_stok($id_bahan, $jumlah);
				}
				
				$status = $cek_status->status;
				
				if ($status > 0) {
					$jml = $totukuran / $jumlah;
				} else {
					$jml = 1;
				}

				if ((int) $type_harga === 6) {
					$type_harga = resolve_semua_metode_harga(
						$id_bahan,
						isset($id_member) ? $id_member : 0,
						isset($id_satuan) ? $id_satuan : 0,
						$jml
					);
				}
				
				if ($type_harga == 1) {
					$sql1 = $this->db->query("SELECT 
						`satuan`.`id` AS idsatuan,
						`satuan`.`satuan`,
						`satu_harga`.`harga_jual`,
						`bahan`.`title`
						FROM
						`bahan`
						INNER JOIN `satu_harga` ON (`bahan`.`id` = `satu_harga`.`id_bahan`)
						INNER JOIN `satuan` ON (`satu_harga`.`id_satuan` = `satuan`.`id`)
						WHERE
						`bahan`.`id` = $id_bahan");
					if ($sql1->num_rows() > 0) {
						$harga_jual = $sql1->row()->harga_jual * $jml;
						$satuan = $sql1->row()->idsatuan;
					} else {
						$sql = $this->db->query("select id,id_satuan,harga_jual from bahan where id=$id_bahan");
						$harga_jual = $sql->row()->harga_jual;
						$satuan = $sql->row()->id_satuan;
					}
					$data = ['status' => true, 'harga' =>$harga_jual, 'satuan' => $satuan, 'id_bahan' => $id_bahan, 'type_harga' => $type_harga,'stat'=>$status];
				} elseif ($type_harga == 2) {
					$sql2 = $this->db->query("SELECT 
						`satuan`.`id` AS idsatuan,
						`satuan`.`satuan`,
						`harga_satuan`.`id_satuan`,
						`bahan`.`title`,
						`harga_satuan`.`harga_jual`,
						`harga_satuan`.`id_bahan`
						FROM
						`satuan`
						INNER JOIN `harga_satuan` ON (`satuan`.`id` = `harga_satuan`.`id_satuan`)
						INNER JOIN `bahan` ON (`harga_satuan`.`id_bahan` = `bahan`.`id`)
						WHERE
						`harga_satuan`.`id_bahan` = $id_bahan");
					if ($sql2->num_rows() > 0) {
						$harga_jual = $sql2->row()->harga_jual;
						$satuan = $sql2->row()->id_satuan;
					} else {
						$sql = $this->db->query("select id,id_satuan,harga_jual from bahan where id=$id_bahan");
						$harga_jual = $sql->row()->harga_jual;
						$satuan = $sql->row()->id_satuan;
					}
					$data = ['status' => true, 'harga' => $harga_jual, 'satuan' => $satuan, 'type_harga' => $type_harga];
				} elseif ($type_harga == 3) {
					
					$sql3 = $this->db->query("SELECT 
						`harga_member`.`id_bahan`,
						`harga_member`.`id_satuan`,
						`harga_member`.`id_member`,
						`harga_member`.`harga_jual`
						FROM
						`satuan`
						INNER JOIN `harga_member` ON (`satuan`.`id` = `harga_member`.`id_satuan`)
						INNER JOIN `bahan` ON (`harga_member`.`id_bahan` = `bahan`.`id`)
						INNER JOIN `konsumen` ON (`harga_member`.`id_member` = `konsumen`.`jenis_member`)
						WHERE
						`harga_member`.`id_member` = $id_member AND 
						`harga_member`.`id_bahan` = $id_bahan
						GROUP BY
						`harga_member`.`id_bahan`,
						`harga_member`.`id_satuan`,
						`harga_member`.`id_member`,
						`harga_member`.`harga_jual`");
					if ($sql3->num_rows() > 0) {
						$harga_jual = $sql3->row()->harga_jual;
						$satuan = $sql3->row()->id_satuan;
					} else {
						$sql = $this->db->query("select id,id_satuan,harga_jual from bahan where id=$id_bahan");
						$harga_jual = $sql->row()->harga_jual;
						$satuan = $sql->row()->id_satuan;
					}
					$data = ['status' => true, 'harga' => $harga_jual, 'satuan' => $satuan, 'type_harga' => $type_harga];
				} elseif ($type_harga == 4) {
					$sql = $this->db->query("select id_satuan,harga_jual from range_harga where id_bahan=$id_bahan AND $jml between jumlah_minimal and jumlah_maksimal");
					if ($sql->num_rows() > 0) {
						$harga_jual = $sql->row()->harga_jual;
						$satuan = $sql->row()->id_satuan;
						$arr = 'jual';
					} else {
						$sql = $this->db->query("select id,id_satuan,harga_jual from bahan where id=$id_bahan");
						$harga_jual = $sql->row()->harga_jual;
						$satuan = $sql->row()->id_satuan;
						$arr = 'modal';
					}
					$data = ['status' => true, 'harga' => $harga_jual, 'satuan' => $satuan, 'type_harga' => $arr];
					
				//cari type harga 5
				} elseif ($type_harga == 5) {
					$sql4 = $this->db->query("select id_satuan,harga_jual from harga_range_member where id_bahan=$id_bahan AND id_member='$id_member' AND $jumlah between jumlah_minimal and jumlah_maksimal");
					if ($sql4->num_rows() > 0) {
						$harga_jual = $sql4->row()->harga_jual;
						$satuan = $sql4->row()->id_satuan;
					} else {
						$sql = $this->db->query("select id,id_satuan,harga_jual from bahan where id=$id_bahan");
						$harga_jual = $sql->row()->harga_jual;
						$satuan = $sql->row()->id_satuan;
					}
					$data = ['status' => true, 'harga' => $harga_jual, 'satuan' => $satuan, 'type_harga' => $type_harga];
				} else {
					$sql = $this->db->query("select id,id_satuan,harga_jual from bahan where id=$id_bahan");
					$harga_jual = $sql->row()->harga_jual;
					$satuan = $sql->row()->id_satuan;
					$data = ['status' => true, 'harga' => $harga_jual, 'satuan' => $satuan, 'type_harga' => $type_harga];
				}
				echo json_encode($data);
			}
			
		/**
			* Summary of cek_harga_range
			* @return void
		*/
			public function cek_harga_range()
			{
				cek_nput_post("GET");
				$id_konsumen = $this->input->post("id_member");
				$id_member   = $this->model_app->pilih_where('jenis_member', 'konsumen', ['id' => $id_konsumen])->row()->jenis_member;
				$id_bahan    = $this->input->post("id_bahan");
				$id_satuan	 = $this->input->post("satuan");
				$harga_awal  = $this->input->post("harga");
				$harga_satuan  = $this->input->post("harga_satuan");
				$jumlah      = $this->input->post("jumlah");
				$totukuran   = $this->input->post("totukuran");
				$totukuran   = $totukuran != 'NaN' ? $totukuran : 1;
				$tot_ukuran   = $this->input->post("tot_ukuran");
				$ukuran_hitung   = $this->input->post("ukuran_hitung");
				$type_harga  = $this->input->post("type_harga");
				$status_hitung  = $this->input->post("status_hitung");
			// dump($_POST);
				$this->cek_stok($id_bahan, $jumlah);
				
				if ($status_hitung > 0) {
					$jml = $totukuran * $jumlah;
				} else {
					$jml = $jumlah;
				}
				$get_harga_range = $this->model_penjualan->get_harga_range($id_member, $id_bahan,$id_satuan,$type_harga,$jml,$harga_awal,$status_hitung,$ukuran_hitung);
				
				$this->output
				->set_content_type('application/json')
				->set_output(json_encode($get_harga_range));
			}
			
		/**
			* Summary of cek_harga_satuan
			* @return void
		*/
			public function cek_harga_satuan()
			{
				$id_satuan     = $this->input->post("satuan");
				$id_bahan   = $this->input->post("id_bahan");
				$harga_awal = $this->input->post("harga");
				$jml        = $this->input->post("jumlah");
				$totukuran  = $this->input->post("totukuran");
				$totukuran  = $totukuran != '' ? $totukuran : 1;
				$id_member  = $this->db->escape_str($this->input->post('idmember'));
				$type_harga  = $this->input->post("type_harga");
				$status_hitung  = $this->input->post("status_hitung");
				
				$cek_status = $this->model_app->pilih_where('status_stok,type_harga,id_satuan,status,harga_jual', 'bahan', ['id' => $id_bahan])->row();
				
				$cek_satuan = $this->model_app->pilih_where('id_satuan,id_bahan,harga_jual', 'harga_satuan', ['id_satuan' => $id_satuan,'id_bahan'=>$id_bahan]);
				
				$get_satuan = $this->model_app->pilih_where('satuan,jumlah', 'satuan', ['id' => $id_satuan])->row();
				
				if(empty($id_satuan)){
					$data = ['status' => 200,
					'harga' => rp($cek_status->harga_jual), 
					'satuan' => $cek_status->id_satuan, 
					'type_harga' => $type_harga,
					'msg'=>'Satuan harus dipilih'];
					echo json_encode($data);
					exit;
				}
				if ((string) $id_satuan === (string) $cek_status->id_satuan) {
					$data = [
						'status' => true,
						'harga' => $this->harga_response($cek_status->harga_jual),
						'satuan' => $cek_status->id_satuan,
						'type_harga' => $type_harga,
						'log' => 'Default satuan bahan'
					];
					echo json_encode($data);
					exit;
				}
				if($cek_satuan->num_rows() == 0){
					$data = ['status' => 200,
					'harga' => rp($cek_status->harga_jual), 
					'satuan' => $cek_status->id_satuan, 
					'type_harga' => $type_harga,
					'msg'=>'Tidak ada Harga dengan satuan '.$get_satuan->satuan];
					echo json_encode($data);
					exit;
				}
				if ((int) $cek_status->type_harga === 2) {
					$data = [
						'status' => true,
						'harga' => $this->harga_response($cek_satuan->row()->harga_jual),
						'satuan' => $id_satuan,
						'type_harga' => $cek_status->type_harga,
						'log' => 'Harga satuan bahan'
					];
					echo json_encode($data);
					exit;
				}
			// $type_harga = $cek_status->type_harga;
				
				if ($cek_status->status_stok == 'Y') {
					$this->cek_stok($id_bahan, $jml);
				}
				
			// $status = $cek_status->status;
				if ($type_harga > 0) {
					$jumlah = (int)$totukuran * $jml;
				} else {
					$jumlah = $jml;
				}
				
				$get_harga_satuan = $this->model_penjualan->get_harga_satuan($id_member, $id_bahan,$id_satuan,$type_harga,$jumlah,$harga_awal);
				
				$this->output
				->set_content_type('application/json')
				->set_output(json_encode($get_harga_satuan));
			}
			
		/**
			* Summary of cek_stok
			* @param mixed $id
			* @param mixed $jumlah
			* @return void
		*/
			private function cek_stok($id, $jumlah)
			{
				$cek_status = $this->model_app->pilih_where('status_stok', 'bahan', ['id' => $id])->row()->status_stok;
				if ($cek_status == 'Y') {
					$jml_masuk = stok_masuk($id);
					$jml_keluar = stok_keluar($id);
					$total = $jml_masuk - $jml_keluar;
					return $total;
				}
				return 0;
			}
			
		/**
			* Summary of cek_boleh_utang
			* @param mixed $id_konsumen
			* @param mixed $id_invoice
			* @return void
		*/
			private function cek_boleh_utang($id_konsumen, $id_invoice)
			{
				$max_utang = $this->model_app
				->pilih_where("max_utang,status", "konsumen", ["id" => $id_konsumen])
				->row();
				
				$cek_bayar = $this->model_app->cek_total("bayar_invoice_detail", "SUM(jml_bayar) AS `total`", ['id_invoice' => $id_invoice]);
				
				if ($max_utang->max_utang == 0 and $max_utang->status == 0 and $cek_bayar->total == 0) {
					$data = ["status" => 'harus_dp', "id" => $id_invoice, "msg" => 'Belum ada pembayaran'];
					$this->output
					->set_content_type('application/json', 'utf-8')
					->set_output(json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES))
					->_display();
					exit;
				}
			}


			


			
		/**
			* Summary of save_bayar_piutang
			* @return void
		*/
			public function save_bayar_piutang()
			{
				cek_nput_post("GET");
				wajib_akses_bayar_order_json();
				
			// dump($_POST);
				$lampiran = "";
				$arr = [];
				
				if (!empty($_FILES["lampiran"]["name"]) AND info()['demo']=='N') {
					$config["upload_path"] = "./uploads/lampiran/";
					$config["allowed_types"] = "jpeg|jpg|png|webp";
				$config["max_size"] = "2000"; // kb
				$this->load->library("upload", $config);
				$this->upload->initialize($config);
				// if (!empty($_FILES["lampiran"]["name"])) {
				if (!$this->upload->do_upload("lampiran")) {
					
					$alert = [
						"status" => 301,
						"msg" => 'Error upload',
						"id" => 0,
						"uang" => 0,
						"total" => 0,
					];
					$this->output
					->set_content_type('application/json', 'utf-8')
					->set_output(json_encode($alert, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES))
					->_display();
					exit;
				} else {
					$data = $this->upload->data();
					$finalUpload = bm_finalize_ci_upload_as_webp($data, 80);
					if (!$finalUpload['status']) {
						$alert = [
							"status" => 301,
							"msg" => $finalUpload['message'],
							"id" => 0,
							"uang" => 0,
							"total" => 0,
						];
						$this->output
						->set_content_type('application/json', 'utf-8')
						->set_output(json_encode($alert, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES))
						->_display();
						exit;
					}
					$lampiran = $finalUpload["file_name"];
				}
			}
			if (!empty($_FILES["lampiran"]["name"]) AND info()['demo']=='Y') {
				$lampiran = 'lampiran.jpg';
			}
			// exit;
			$type         = xss_filter($this->input->post("type"), 'xss');
			$status       = xss_filter($this->input->post("status_bayar"), 'xss');
			$noin         = $this->input->post("noin");
			$no_order     = decrypt_url($noin);
			$id_bayar     = xss_filter($this->input->post("id_byr"), 'xss');
			$nourut        = xss_filter($this->input->post("nourut"), 'xss');
			$rekening     = xss_filter($this->input->post("rekening"), 'xss');
			$jml_bayar    = xss_filter($this->input->post("uang"), 'xss');
			$total_order    = xss_filter($this->input->post("sisabayar"), 'xss');
			$jumlah_bayar = xss_filter($this->input->post("jumlah_bayar"), 'xss');
			$kembalian    = xss_filter($this->input->post("kembalian"), 'xss');
			
			if($rekening==0){
				$getIdAkun = getIdAkun($id_bayar);
			}else{
				$getIdAkun = getIdAkunBank($rekening);
			}
			
			$sisa        = 0;
			$alert        = [];
			if ($type     == "simpan_bayar") {
				$this->session->unset_userdata("cart");
				
				$_diskon = "ROUND(SUM((`invoice_detail`.`jumlah`) * (`invoice_detail`.`harga` * `invoice_detail`.`diskon`/100))) AS diskon";
				
				$data_bayar = [
					"id_invoice" => $no_order,
					"tgl_bayar" => date("Y-m-d"),
					"jam_bayar" => date("H:i:s"),
					"jml_bayar" => $jml_bayar,
					"id_bayar" => $id_bayar,
					"id_sub_bayar" => $getIdAkun,
					"urutan" => $nourut,
					"lampiran" => $lampiran,
					"id_user" => $this->iduser,
				];
				
				
				
				if ($no_order != null and $jml_bayar > 0) 
				{
					// $this->model_app->update("invoice",["pos" => 'Y',"status" => 'simpan'],["id_invoice" => $no_order]);
					$cek_lunas = $this->cek_lunas($no_order);
					if($cek_lunas==true){
						$alert = [
							"status" => 301,
							"msg" => "Order sudah lunas",
							"id" => $noin,
							"uang" => $jml_bayar,
							"sisa" => $sisa,
							"total" => 0,
						];
					}else{
						$this->update_invoice(0,$total_order,$jumlah_bayar,$kembalian,0,$no_order);
						$this->persist_invoice_komisi_from_request($no_order);
						$input = $this->model_app->input("bayar_invoice_detail", $data_bayar);
						
						
						$cek_diskon = $this->model_app->cek_total("invoice_detail", $_diskon, ["id_invoice" => $no_order])->diskon;
						$sum_detail = $this->model_penjualan->cek_total_detail($no_order);
						$cek_total_bayar = $this->model_penjualan->cek_total_bayar($no_order);
						$sisa =$sum_detail - $cek_total_bayar -  $cek_diskon; //piutang
						
						
						$get_id_transaksi = get_id_transaksi($no_order)['nomor_order'];
						$tgl_transaksi = tgl_transaksi($no_order);
						$no_transaction =  $this->journal->check_number_tramsaction();
						$noorder = substr($no_transaction, 6, 4);
						$no_transaction_now = intval($noorder) + 1;
						if($no_transaction == null){
							$no_trans = date("ymd").'0001';
						} else {
							$no_trans = date("ymd").sprintf("%04s",$no_transaction_now);
						}
						$id_konsumen = get_id_transaksi($no_order)['idkonsumen'];
						$nama = cekKonsumen($id_konsumen)['nama'];
						$catatan =  "ORDER NO#".$get_id_transaksi.' - '.$nama;
						
						$cek_count =$this->model_jurnal->cek_count($no_order);
						$ceklunas = $this->cek_lunas($no_order);
						
						$conditions['jurnal'] = [
							'id_user'=>$this->iduser,
							'no_trans'=>$no_trans,
							'tgl_transaksi'=>$tgl_transaksi,
							'id_akun'=>$getIdAkun,
							'id_invoice'=>$no_order,
							'id_transaksi'=>$get_id_transaksi,
							'jml_bayar'=>$jml_bayar,
							'total_order'=>$total_order,
							'cek_lunas'=>$ceklunas,
							'pajak'=>0,
							'total_pajak'=>0,
							'diskon_harga'=>0,
							'diskon'=>0,
							'cashback'=>0,
							'ket'=>$catatan,
							'cek_count'=>$cek_count,
							'nama'=>$nama,
							'status'=>'simpan',
							'lampiran'=>$lampiran
						];
						
						$this->model_jurnal->input_jurnal($conditions);
						if($status =='baru' OR $status =='edit' OR $status =='pending'){
							
							if ($input["status"] == "ok") 
							{
								
								$alert = ["status" => 200,
								"id" => $no_order,
								"uang" => $jml_bayar,
								"total" => $jml_bayar,
								"idkon" => $id_konsumen,
								"msg" => $arr
							];
						}else{
							$alert = [
								"status" => 304,
								"id" => 0,
								"uang" => 0,
								"total" => 0,
								"sisa" => $sisa
							];
						}
					}elseif($status =='simpan'){
						
						
						if ($input["status"] == "ok") 
						{
							$alert = ["status" => 200,
							"id" => $no_order,
							"uang" => $jml_bayar,
							"total" => $jml_bayar,
							"idkon" => $id_konsumen,
							"msg" => $arr
						];
					}else{
						$alert = ["status" => 304,"id" => 0,"uang" => 0,"total" => 0,"sisa" => $sisa];
					}
				}else{
					$alert = [
						"status" => 301,
						"msg" => "error",
						"id" => $noin,
						"uang" => $jml_bayar,
						"sisa" => $sisa,
						"total" => 0,
					];
				}
				
			}
		}
		
		
		$this->output
		->set_content_type("application/json")
		->set_output(json_encode($alert));
	}
}
public function load_total() {
	$conditions = $this->build_order_total_conditions_from_request();
	$rows = $this->model_penjualan->getRows($conditions);
	$laporan = $this->calculate_order_totals_from_rows($rows);

	$this->output
		->set_content_type("application/json")
		->set_output(json_encode([
			'total_order' => rp($laporan['totalbeli']),
			'total_bayar' => rp($laporan['totalbayar']),
			'total_diskon' => rp($laporan['totaldiskon']),
			'total_pajak' => rp($laporan['totalpajak']),
			'total_piutang' => rp($laporan['sisa']),
		]));
}

private function build_order_total_conditions_from_request()
{
	$conditions = [];
	$trx = $this->input->post("trx");
	if ($trx === null || $trx === '') {
		$trx = $this->input->post("status");
	}
	$tgl = trim((string) $this->input->post("tgl"));
	$keywords = trim((string) $this->input->post("keywords"));

	if ($trx !== null && $trx !== '' && $trx !== '0' && $trx !== 0) {
		$conditions["search"]["trx"] = $trx;
	}

	if ($keywords !== '') {
		if (transaction_number_has_prefix($keywords)) {
			$conditions["search"]["keywords"] = $keywords;
		} elseif (substr(trim($keywords), 0, 1) == "0") {
			$conditions["search"]["keywords"] = $keywords;
		} elseif (substr(trim($keywords), 0, 2) == "62") {
			$conditions["search"]["keywords"] = clearnohp($keywords);
		} elseif (substr(trim($keywords), 0, 3) == "+62") {
			$conditions["search"]["keywords"] = clearnohp($keywords);
		} elseif (substr(trim($keywords), 0, 1) == "#") {
			$conditions["search"]["keywords"] = clean($keywords);
		} else {
			$conditions["search"]["keywords"] = $keywords;
		}
	}

	if ($tgl !== '') {
		$date = date_ranges($tgl);
		$conditions["search"]["dari"] = date_replace_slash($date['dari']);
		$conditions["search"]["sampai"] = date_replace_slash($date['sampai']);
	}

	return $conditions;
}

private function calculate_order_totals_from_rows($rows = [])
{
	$laporan = [
		'totalbeli' => 0,
		'totalbayar' => 0,
		'totaldiskon' => 0,
		'totalpajak' => 0,
		'sisa' => 0,
	];

	if (empty($rows)) {
		return $laporan;
	}

	foreach ($rows as $row) {
		$invoiceId = isset($row['id_invoice']) ? (int) $row['id_invoice'] : 0;
		if ($invoiceId <= 0) {
			continue;
		}

		$sumOrder = (float) sumOrder($invoiceId);
		$sumOrderDiskon = sumOrderDiskon($invoiceId);
		$diskonDetail = (is_object($sumOrderDiskon) && isset($sumOrderDiskon->sisa)) ? (float) $sumOrderDiskon->sisa : 0;
		$diskonInvoice = isset($row['potongan_harga']) ? (float) $row['potongan_harga'] : 0;

		$sumPiutangRaw = sumPiutang($invoiceId);
		$totalBayarMurni = 0;
		if (is_array($sumPiutangRaw)) {
			if (isset($sumPiutangRaw[0]) && is_array($sumPiutangRaw[0]) && array_key_exists('piutang', $sumPiutangRaw[0])) {
				$totalBayarMurni = (float) $sumPiutangRaw[0]['piutang'];
			}
		} else {
			$totalBayarMurni = (float) $sumPiutangRaw;
		}

		$pajakPersen = isset($row['pajak']) ? (float) $row['pajak'] : 0;
		$nominalPajak = isset($row['total_pajak']) ? (float) $row['total_pajak'] : 0;
		if ($nominalPajak <= 0 && $pajakPersen > 0) {
			$nominalPajak = round(($sumOrder * $pajakPersen) / 100);
		}
		$nominalPajak = (int) round($nominalPajak);

		$sisa = ($sumOrder + $nominalPajak) - $totalBayarMurni - $diskonInvoice;

		$laporan['totalbeli'] += ($sumOrder - $diskonDetail);
		$laporan['totalbayar'] += $totalBayarMurni;
		$laporan['totaldiskon'] += $diskonInvoice;
		$laporan['totalpajak'] += $nominalPajak;
		$laporan['sisa'] += $sisa;
	}

	return [
		'totalbeli' => (int) round($laporan['totalbeli']),
		'totalbayar' => (int) round($laporan['totalbayar']),
		'totaldiskon' => (int) round($laporan['totaldiskon']),
		'totalpajak' => (int) round($laporan['totalpajak']),
		'sisa' => (int) round($laporan['sisa']),
	];
}

		/**
			* Summary of kas_masuk
			* @return void
		*/
			private function kas_masuk()
			{
				
				$noin      = $this->input->post("noin");
				$id_bayar  = xss_filter($this->input->post("id_byr"), 'xss');
				$jml_bayar = xss_filter($this->input->post("uang"), 'xss');
				$rekening  = xss_filter($this->input->post("rekening"), 'xss');
				
				if ($id_bayar == 1) {
					$no_reff = 411;
				} elseif ($id_bayar == 2) {
					$no_reff = 110;
				}
				
				$autoNumber = autoNumber(
					NOMOR_REFF,
					DIGIT_REFF,
					"id_generate",
					"kas_masuk"
				);
				$this->model_app->insert("kas_masuk", [
					"no_reff" => $no_reff,
					"id_bayar" => $id_bayar,
					"id_sub_bayar" => $rekening,
					"id_user" => $this->iduser,
					"id_generate" => $autoNumber,
					"pemasukan" => $jml_bayar,
					"catatan" => "Pendapatan INVOICE NO.#" .$noin,
				]);
			}
			
		/**
			* Summary of get_data_produk
			* @return void
		*/
			public function get_data_produk()
			{
				$this->ensureBahanUkuranDefaultSchema();
				
				$id = $this->db->escape_str($this->input->post("id"));
				$id_member = $this->db->escape_str($this->input->post("idmember"));
				
				$query = "SELECT 
				`jenis_cetakan`.`jenis_cetakan`,
				`produk`.`barcode`,
				`produk`.`title`,
				`produk`.`ukuran`,
				`produk`.`id`,
				`produk`.`id_jenis`,
				`produk`.`id_bahan`,
				`produk`.`jumlah`,
				`produk`.`lock_harga`
				FROM
				`jenis_cetakan`
				INNER JOIN `produk` ON (`jenis_cetakan`.`id_jenis` = `produk`.`id_jenis`)
				where `produk`.`id` = $id AND produk.pub='1'";
				$result = $this->db->query($query);
				
				$idb         = 0;
				$title       = '-';
				$harga_dasar = 0;
				$status      = 0;
				$type_harga  = 1;
				$id_satuan   = 1;
				$ukuran_default = '';
				$data = array();
				foreach ($result->result_array() as $row) {
					$ukuran_default = $row['ukuran'];
					if (!empty($row['id_bahan'])) {
						$res = $this->db->query("SELECT * FROM bahan where id IN ($row[id_bahan])");
						if ($res->num_rows() > 0) {
							$rowx = $res->row_array();
							$id_bahan = $rowx['id'];
							$title = $rowx['title'];
							$harga_dasar = $rowx['harga'];
							$status = $rowx['status'];
							$type_harga = $rowx['type_harga'];
							$id_satuan = $rowx['id_satuan'];
							$ukuran_default = $this->resolveUkuranDefault($rowx, $row['ukuran']);
						}
					} else {
						$this->output
						->set_content_type("application/json")
						->set_output(json_encode($data));
						exit;
					}
					if ((int) $type_harga === 6) {
						$type_harga = resolve_semua_metode_harga(
							$id_bahan,
							isset($id_member) ? $id_member : 0,
							$id_satuan,
							isset($jumlah) ? $jumlah : 1
						);
					}
					if ($type_harga == 1) {
						$sql1 = $this->db->query("SELECT 
							`satuan`.`id` AS idsatuan,
							`satuan`.`satuan`,
							`satu_harga`.`harga_jual`,
							`bahan`.`title`
							FROM
							`bahan`
							INNER JOIN `satu_harga` ON (`bahan`.`id` = `satu_harga`.`id_bahan`)
							INNER JOIN `satuan` ON (`satu_harga`.`id_satuan` = `satuan`.`id`)
							WHERE
							`bahan`.`id` = $id_bahan");
						$harga_jual = $sql1->row()->harga_jual;
					} elseif ($type_harga == 2) {
						$sql2 = $this->db->query("SELECT 
							`satuan`.`id` AS idsatuan,
							`satuan`.`satuan`,
							`harga_satuan`.`id_satuan`,
							`bahan`.`title`,
							`harga_satuan`.`harga_jual`,
							`harga_satuan`.`id_bahan`
							FROM
							`satuan`
							INNER JOIN `harga_satuan` ON (`satuan`.`id` = `harga_satuan`.`id_satuan`)
							INNER JOIN `bahan` ON (`harga_satuan`.`id_bahan` = `bahan`.`id`)
							WHERE
							`harga_satuan`.`id_bahan` = $id_bahan");
						$harga_jual = $sql2->row()->harga_jual;
					} elseif ($type_harga == 3) {
						$sql3 = $this->db->query("SELECT 
							`harga_member`.`id_bahan`,
							`harga_member`.`id_satuan`,
							`harga_member`.`id_member`,
							`harga_member`.`harga_jual`
							FROM
							`satuan`
							INNER JOIN `harga_member` ON (`satuan`.`id` = `harga_member`.`id_satuan`)
							INNER JOIN `bahan` ON (`harga_member`.`id_bahan` = `bahan`.`id`)
							INNER JOIN `konsumen` ON (`harga_member`.`id_member` = `konsumen`.`jenis_member`)
							WHERE
							`harga_member`.`id_member` = $id_member AND 
							`harga_member`.`id_bahan` = $id_bahan
							GROUP BY
							`harga_member`.`id_bahan`,
							`harga_member`.`id_satuan`,
							`harga_member`.`id_member`,
							`harga_member`.`harga_jual`");
						if ($sql3->num_rows() > 0) {
							$harga_jual = $sql3->row()->harga_jual;
						} else {
							$sql = $this->db->query("select id,id_satuan,harga_jual from bahan where id=$id_bahan");
							$harga_jual = $sql->row()->harga_jual;
						}
					} elseif ($type_harga == 4) {
						$sql = $this->db->query("select id_satuan,harga_jual from range_harga where id_bahan=$id_bahan AND 1 between jumlah_minimal and jumlah_maksimal");
						if ($sql->num_rows() > 0) {
							
							$harga_jual = $sql->row()->harga_jual;
						} else {
							$sql = $this->db->query("select id,id_satuan,harga_jual from bahan where id=$id_bahan");
							$harga_jual = $sql->row()->harga_jual;
						}
					} elseif ($type_harga == 5) {
						$sql4 = $this->db->query("select id_satuan,harga_jual from harga_range_member where id_bahan=$id_bahan AND id_member='$id_member' AND 1 between jumlah_minimal and jumlah_maksimal");
						if ($sql4->num_rows() > 0) {
							$harga_jual = $sql4->row()->harga_jual;
						} else {
							$sql = $this->db->query("select id,id_satuan,harga_jual from bahan where id=$id_bahan");
							$harga_jual = $sql->row()->harga_jual;
						}
					}
					
					$data = [
						'harga' => rp($harga_jual),
						'id_produk' => $row['id'],
						'jenis_cetakan' => $row['jenis_cetakan'],
						'id_jenis' => $row['id_jenis'],
						'bahan' => $title,
						'id_bahan' => $id_bahan,
						'status' => $status,
						'satuan' => $id_satuan,
						'ukuran' => $ukuran_default,
						'jumlah' => $row['jumlah'],
						'lock_harga' => $row['lock_harga'],
						'type_harga' => $type_harga
					];
				}
				$this->output
				->set_content_type("application/json")
				->set_output(json_encode($data));
			}
			
		/**
			* Summary of set_produk
			* @param mixed $id
			* @return void
		*/
			public function set_produk($id)
			{
			// $searchTerm = $this->input->get("searchTerm");
				$json = [];
				
				if (!empty($id)) {
					$this->db->where('id', $id);
					$query = $this->db->select('id,title as name')
					->where('kunci', 0)
					->limit(10)
					->get("produk");
					$json = $query->result();
				}
				$this->output
				->set_content_type("application/json")
				->set_output(json_encode($json));
			}
			
		/**
			* Summary of get_produk
			* @return void
		*/
			public function get_produk()
			{
				$searchTerm = $this->input->get("q");
				$json = [];
				
				if (!empty($searchTerm)) {
					$this->db->like('title', $searchTerm);
					$query = $this->db->select('id,title as text')
					->where('kunci', 0)
					->limit(10)
					->get("produk");
					$json = $query->result();
				} else {
					$query = $this->db->select('id,title as text')
					->where('kunci', 0)
					->limit(10)
					->get("produk");
					$json = $query->result();
				}
				$this->output
				->set_content_type("application/json")
				->set_output(json_encode($json));
			}
			
		/**
			* Summary of duplikat_data
			* @return void
		*/
			public function duplikat_data()
			{
			// $id = $this->input->get("id");
				$product_id = $this->input->post('id', TRUE); 
			// remove white spaces 
				if($product_id) { 
					$last_id = $this->duplicate($product_id,1); 
					$result = $this->model_app->view_where('invoice_detail',['id_rincianinvoice'=>$last_id])->row();
					
					if (!empty($result)) { 
						$response = [
							'id' =>$result->id_rincianinvoice,
							'id_produk' =>$result->id_produk,
							'nama_produk' =>nama_produk($result->id_produk),
							'id_jenis' =>$result->jenis_cetakan,
							'jenis' =>jenis_cetakan($result->jenis_cetakan),
							'id_jenis' =>$result->jenis_cetakan,
							'status_hitung' =>$result->status_hitung,
							'type_harga' =>$result->type_harga,
							'ket' =>$result->keterangan,
							'jumlah' =>$result->jumlah,
							'harga' =>$result->harga,
							'harga_satuan' =>$result->harga_satuan,
							'id_satuan' =>$result->id_satuan,
							'ukuran' =>$result->ukuran,
							'ukuran_hitung' =>$result->ukuran_hitung,
							'tot_ukuran' =>$result->tot_ukuran,
							'id_bahan' =>$result->id_bahan,
							'bahan' =>getBahan($result->id_bahan),
						];
						$data = ['status'=>true,'data'=>$response,'msg'=>'Sukses'];
					} else { 
						$data = ['status'=>false,'msg'=>'Gagal'];
					} 
					$this->output
					->set_content_type("application/json")
					->set_output(json_encode($data));
				}
				
			}
			
			private function duplicate($id, $count) {
				$this->db->where('id_rincianinvoice', $id);
				$query = $this->db->get('invoice_detail');
				foreach ($query->result() as $row){
					foreach($row as $key => $val){
						
						if($key != 'id_rincianinvoice'){                
							$this->db->set($key, $val);
						}
					}
				}        
				$result = array();
				for ($i=0; $i < $count; $i++) { 
					$this->db->insert('invoice_detail');
					$last_id = $this->db->insert_id();
				}
				
				return $last_id;
			}
			public function cek_order(){
				$id = $this->db->escape_str($this->input->post('id'));
				$id = decrypt_url($id);
				$total = $this->model_app->sum_data('jml_bayar','bayar_invoice_detail',['id_invoice'=>$id]);
				$total_order = $this->model_app->cek_total_detail(['id_invoice'=>$id])->row()->total;
				$get_id_transaksi = get_id_transaksi($id)['nomor_order'];
				$cek = $this->model_app->view_where('invoice',['id_invoice'=>$id]);
				if($cek->num_rows() > 0){
					$row = $cek->row();
					$msg = array('status'=>'ok','id'=>encrypt_url($id),'no_order'=>$get_id_transaksi,'total_order'=>$total_order,'total'=>$total,'ket'=>$row->history);
				}else{
					$msg = array('status'=>'error','id'=>0);
				}
				echo json_encode($msg);
			}
			
			
			public function simpan_batal(){
				simpan_demo("Simpan");
			// $this->jurnal_batal();
			// return;
			// dump($_POST);
				$id = decrypt_url($this->input->post('no_order'));
				$mod = $this->db->escape_str($this->input->post('mod_batal'));
				$keterangan = $this->db->escape_str($this->input->post('keterangan'));
				$query_cek = $this->model_cek->cek_akses(5,$this->iduser);
				if ($query_cek->num_rows()>0){
					$this->session->unset_userdata("cart");
					$id_konsumen = get_id_transaksi($id)['idkonsumen'];
					$nama = cekKonsumen($id_konsumen)['nama'];
					$get_id_transaksi = get_id_transaksi($id)['nomor_order'];
					$catatan =  "ORDER NO#".$get_id_transaksi.' - '.$nama;
					$_catatan =  "BAYAR ORDER NO#".$get_id_transaksi.' - '.$nama;
					
					$cek_count =$this->model_jurnal->cek_count($id);
					$where = array('id_invoice' => $id);
					$cek_invoice = $this->model_app->view_where('stok_keluar',$where);
					if($cek_invoice->num_rows() > 0){
						
						$data = array('status'=>'batal','oto'=>5,'history' => $keterangan);
						$res= $this->model_app->update('invoice', $data, $where);
						if($res['status']=='ok'){
							
							$query_stok_keluar = $this->model_app->pilih_where('id_invoice,id_bahan,jumlah','stok_keluar',['id_invoice'=>$id])->result();
							
							foreach($query_stok_keluar AS $row){
								$cek_jenis_bahan = $this->model_app->pilih_where('kunci,status_stok','bahan',['id'=>$row->id_bahan])->row();
								if($cek_jenis_bahan->status_stok=='Y' AND $cek_jenis_bahan->kunci==1){
									$_data = [
										'id_bahan'=>$row->id_bahan,
										'jumlah'=>$row->jumlah,
										'create_date'=>today(),
										'ket'=>'Retur penjualan No.'.$row->id_invoice
									];
									$this->model_app->insert('stok_masuk',$_data);
								}
							}
							
							$this->model_app->update('bayar_invoice_detail', ['hapus'=>1], $where);
							$this->model_app->update('tb_users', ['last_invoice'=>0], ['id_user'=>$this->iduser]);
							$this->model_app->delete("stok_keluar", $where);
						// $this->model_app->delete("jurnal", ['keterangan'=>$catatan]);
						// $this->model_app->delete("jurnal", ['keterangan'=>$_catatan]);
							$this->jurnal_batal();
							$msg = array('status'=>'ok','msg'=>'No. Order '. get_id_transaksi($id)['nomor_order'].' dibatalkan');
						}else{
							$msg = array('status'=>'err','msg'=>'Gagal');
						}
					}else{
						$data = array('status'=>'batal','oto'=>5,'history' => $keterangan);
						$res= $this->model_app->update('invoice', $data, $where);
						if($res['status']=='ok'){
							$this->model_app->update('bayar_invoice_detail', ['hapus'=>1], $where);
							$this->model_app->delete("stok_keluar", $where);
						// $this->model_app->delete("jurnal", ['keterangan'=>$catatan]);
						// $this->model_app->delete("jurnal", ['keterangan'=>$_catatan]);
							$this->jurnal_batal();
							$msg = array('status'=>'ok','msg'=>'No. Order '. get_id_transaksi($id)['nomor_order'].' dibatalkan');
						}else{
							$msg = array('status'=>'err','msg'=>'Gagal');
						}
					}
				}else{
					$msg = array('status'=>400,'msg'=>'Akses ditolak');
				}
				$this->output
				->set_content_type('application/json')
				->set_output(json_encode($msg));
			}
			
			private function jurnal_batal()
			{
				
				$id = decrypt_url($this->input->post('no_order'));
				$id_akun = $this->db->escape_str($this->input->post('id_akun'));
			//total order
				$total_order_batal = $this->db->escape_str($this->input->post('total_order_batal'));
				$total_order_batal = convert_to_number($total_order_batal);
			//total retur
				$total_batal = $this->db->escape_str($this->input->post('total_batal'));
				$total_batal = convert_to_number($total_batal);
			//sisa piutang
				$sisa = $total_order_batal - $total_batal;
				
				$get_id_transaksi = get_id_transaksi($id)['nomor_order'];
				$tgl_transaksi = tgl_transaksi($id);
				$idkonsumen = get_id_transaksi($id)['idkonsumen'];
				$nama = cekKonsumen($idkonsumen)['nama'];
				$catatan =  "RETUR ORDER NO#".$get_id_transaksi.' - '.$nama;
				
				$no_transaction =  $this->journal->check_number_tramsaction();
				$no_order = substr($no_transaction, 6, 4);
				$no_transaction_now = intval($no_order) + 1;
				if($no_transaction == null){
					$no_trans = date("ymd").'0001';
				} else {
					$no_trans = date("ymd").sprintf("%04s",$no_transaction_now);
				}
				
				if($total_order_batal == $total_batal)
				{
					$input_jurnal = [
						"no_trans" 		=> $no_trans,
						"tgl"	 		=> $tgl_transaksi,
						"keterangan" 	=> $catatan,
						"bukti" 	    => '',
						"id_user" 		=> $this->iduser
					];
				// dump($input_jurnal);
					$input = $this->model_app->input('jurnal', $input_jurnal);
					if($input['status']=='ok'){
						$input_jurnal_detail = array(
							array(
								'id_jurnal' 		=> $input['id'],
								'id_akun'			=> $this->model_jurnal->get_akun(9),
								'tipe_kas'			=> 1,
								'id_perkiraan'		=> 1, 
								'nilai'				=> $total_batal, 
								'catatan_jurnal' 	=> 'A', 
							),
							array(
								'id_jurnal' 		=> $input['id'],
								'id_akun'			=> $id_akun,
								'tipe_kas'			=> 1,
								'id_perkiraan'		=> 2, 
								'nilai'				=> $total_batal, 
								'catatan_jurnal' 	=> 'A', 
							)
						);
						$this->db->insert_batch('jurnal_detail', $input_jurnal_detail);
					}
				}
				
				if($total_batal == 0)
				{
					$catatan =  "BATAL ORDER NO#".$get_id_transaksi.' - '.$nama;
					$input_jurnal = [
						"no_trans" 		=> $no_trans,
						"tgl"	 		=> $tgl_transaksi,
						"keterangan" 	=> $catatan,
						"bukti" 	    => '',
						"id_user" 		=> $this->iduser
					];
				// dump($input_jurnal);
					$input = $this->model_app->input('jurnal', $input_jurnal);
					if($input['status']=='ok'){
						$input_jurnal_detail = array(
							array(
								'id_jurnal' 		=> $input['id'],
								'id_akun'			=> 5,
								'tipe_kas'			=> 0,
								'id_perkiraan'		=> 2, 
								'nilai'				=> $total_order_batal, 
								'catatan_jurnal' 	=> 'A', 
							),
							array(
								'id_jurnal' 		=> $input['id'],
								'id_akun'			=> $this->model_jurnal->get_akun(9),
								'tipe_kas'			=> 0,
								'id_perkiraan'		=> 1, 
								'nilai'				=> $total_order_batal, 
								'catatan_jurnal' 	=> 'A', 
							)
						);
						$this->db->insert_batch('jurnal_detail', $input_jurnal_detail);
					}
				}
				
				if($sisa >0 AND $total_batal > 0)
				{
					$akun_detail    =  $this->model_jurnal->akun_detail($id)->result();
					$input_jurnal = [
						"no_trans" 		=> $no_trans,
						"tgl"	 		=> $tgl_transaksi,
						"keterangan" 	=> $catatan,
						"bukti" 	    => '',
						"id_user" 		=> $this->iduser
					];
				// dump($input_jurnal);
					$input = $this->model_app->input('jurnal', $input_jurnal);
				// $input['id'] =0;
					if($input['status']=='ok'){
						$input_jurnal_detail = array(
							array(
								'id_jurnal' 		=> $input['id'],
					'id_akun'			=> $this->model_jurnal->get_akun(8),//akun kas DP
					'tipe_kas'			=> $this->model_jurnal->getIdAkunKasById(8),
					'id_perkiraan'		=> 2, 
					'nilai'				=> $total_batal, 
					'catatan_jurnal' 	=> 'K', 
				),
							array(
								'id_jurnal' 		=> $input['id'],
					'id_akun'			=> $this->model_jurnal->get_akun(6),//akun piutang
					'tipe_kas'			=> $this->model_jurnal->getIdAkunKasById(6),
					'id_perkiraan'		=> 2, 
					'nilai'				=> $total_batal, 
					'catatan_jurnal' 	=> 'K', 
				),
							array(
								'id_jurnal' 		=> $input['id'],
					'id_akun'			=> $this->model_jurnal->get_akun(9),//akun kewajiban
					'tipe_kas'			=> $this->model_jurnal->getIdAkunKasById(9),
					'id_perkiraan'		=> 1, 
					'nilai'				=> $total_order_batal, 
					'catatan_jurnal' 	=> 'D', 
				),
						);
					// dump($input_jurnal_detail);
						$this->db->insert_batch('jurnal_detail', $input_jurnal_detail);
						
					}
				}
			}
			
			private function hapus_jurnal($jurnal)
			{
				$cek = $this->model_app->view_like('jurnal',['keterangan'=>$jurnal]);
				if($cek->num_rows() >0)
				{
					$result = $cek->result();
					
					foreach($result AS $row)
					{
						$this->model_app->delete('jurnal', ['id_jurnal'=>$row->id_jurnal]);
					}
					
				}
			}
			
			public function cek_spk_lunas()
			{
				
				$no_order = xss_filter($this->input->post('id'), 'xss');
				
				$cek_status = $this->model_penjualan->cek_status_invoice($no_order);
			// dump($cek_status);
				if($cek_status->status =='baru'){
					$response = ['status'=>true,'msg'=>$cek_status];
				}else{
					$response = ['status'=>false,'msg'=>$cek_status];
				}
				
				$this->output
				->set_content_type('application/json')
				->set_output(json_encode($response));
			}
			
			public function export_to_excel()
			{
			// Mengambil data dari POST
				$data = $this->input->post('data');
				$periode = $this->input->post('periode');
				
				if (empty($data)) {
					echo json_encode(['error' => 'No data received']);
					return;
				}
			// dump($_POST);
			// Membuat objek Spreadsheet baru
				$spreadsheet = new Spreadsheet();
				$sheet = $spreadsheet->getActiveSheet();
			// Menambahkan metadata untuk file Excel, termasuk title
				$spreadsheet->getProperties()
			->setTitle('Laporan Transaksi')  // Set Title Excel
			->setCreator('Munajat')  // Set Creator (opsional)
			->setSubject('Export Data') // Set Subject (opsional)
			->setDescription('Laporan Ekspor Data dalam format Excel'); // Set Description (opsional)
			
			// Menambahkan judul awal di baris pertama
			$sheet->setCellValue('A1', 'Laporan Transaksi Periode: '.$periode)  // Judul di A1
			->mergeCells('A1:H1');  // Merge semua kolom untuk judul
			
			// Mengatur gaya untuk judul awal (misalnya bold dan ukuran font besar)
			$sheet->getStyle('A1')->getFont()->setBold(true)->setSize(14); // Bold dan ukuran font
			$sheet->getStyle('A1')->getAlignment()->setHorizontal('center'); // Teks center
			
			// Menambahkan jarak (kosongkan baris 2)
			$sheet->setCellValue('A2', '')->mergeCells('A2:H2');  // Menambahkan baris kosong setelah judul
			
			$sheet->getStyle('A3')->getFont()->setBold(true); // Set bold kolom A1
			$sheet->getStyle('B3')->getFont()->setBold(true); // Set bold kolom A1
			$sheet->getStyle('C3')->getFont()->setBold(true); // Set bold kolom A1
			$sheet->getStyle('D3')->getFont()->setBold(true); // Set bold kolom A1
			$sheet->getStyle('E3')->getFont()->setBold(true); // Set bold kolom A1
			$sheet->getStyle('F3')->getFont()->setBold(true); // Set bold kolom A1
			$sheet->getStyle('G3')->getFont()->setBold(true); // Set bold kolom A1
			$sheet->getStyle('H3')->getFont()->setBold(true); // Set bold kolom A1
			
			
			if (!empty($data['header'])) {
				
				$row = 3;
				$col = 1;
				foreach ($data['header'] as $header) {
					$sheet->setCellValueByColumnAndRow($col, $row, $header);
					$col++;
				}
				$row++;
			}
			
			
			if (!empty($data['body'])) {
				foreach ($data['body'] as $rowData) {
					$col = 1;
					foreach ($rowData as $cell) {
						$sheet->setCellValueExplicitByColumnAndRow($col, $row, $cell, \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
						// $sheet->setCellValueByColumnAndRow($col, $row, $cell);
						$col++;
					}
					$row++;
				}
			}
			
			// Menambahkan footer tabel
			$footerRow = $row;
			if (!empty($data['footer'])) {
				foreach ($data['footer'] as $footerData) {
					$col = 1;
					foreach ($footerData as $footerCell) {
						// $sheet->setCellValueByColumnAndRow($col, $footerRow, $footerCell);
						$sheet->setCellValueExplicitByColumnAndRow($col, $footerRow, $footerCell, \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
						$col++;
					}
					$footerRow++;
				}
			}
			if (!empty($data['header2'])) {
				
				$rows = $footerRow;
				$cols = 1;
				foreach ($data['header2'] as $header) {
					$sheet->setCellValueByColumnAndRow($cols, $rows, $header);
					$cols++;
				}
				$rows++;
			}
			if (!empty($data['body2'])) {
				foreach ($data['body2'] as $rowData) {
					// Merge kolom 1-4 (A-D) pada baris saat ini
					$sheet->mergeCellsByColumnAndRow(1, $rows, 4, $rows);
					
					// Optional: bisa kasih isi merge cell kalau perlu, contoh "Grup"
					$sheet->setCellValueExplicitByColumnAndRow(1, $rows, 'TOTAL KESELURUHAN
						', \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
					
					$col = 4; // Mulai dari kolom ke-5 (E), setelah merge
					foreach ($rowData as $cell) {
						$sheet->setCellValueExplicitByColumnAndRow($col, $rows, $cell, \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
						$col++;
					}
					
					$rows++;
				}
			}
			// Menetapkan Auto Width pada setiap kolom
			$highestColumn = $sheet->getHighestColumn(); // Mendapatkan kolom terakhir yang digunakan
			for ($col = 'A'; $col <= $highestColumn; $col++) {
				$sheet->getColumnDimension($col)->setAutoSize(true);
			}
			
			
			
			// Menambahkan border pada seluruh tabel
			$styleArray = [
				'borders' => [
					'allBorders' => [
						'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
			'color' => ['argb' => '000000'],  // Warna border (hitam)
		],
	],
];

			// Menerapkan border pada seluruh range yang digunakan
$sheet->getStyle('A1:' . $highestColumn . $row)->applyFromArray($styleArray);	

			// $this->mergeColspanCells($sheet);
			// Menyimpan file Excel sementara
$filename = 'DATA_TRANSAKSI.xlsx';
$file_path = './uploads/' . $filename;

$writer = new Xlsx($spreadsheet);
$writer->save($file_path);

			// Menanggapi dengan URL untuk file yang disimpan
echo json_encode(['url' => base_url('uploads/' . $filename)]);
}

}																																																							
