<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Pos_model extends CI_Model {

	public function inclusive($price='',$tax_per){
		return ($tax_per!=0) ? $price/(($tax_per/100)+1)/10 : $tax_per;
	}
	
public function get_item_current_stock($item_id) //start
{
    $warehouse_id = $this->input->post('warehouse_id');

    // fallback if warehouse not sent from AJAX
    if (empty($warehouse_id)) {
        $warehouse_id = get_store_warehouse_id();
    }

    return total_available_qty_items_of_warehouse(
        $warehouse_id,
        get_current_store_id(),
        $item_id
    );
}//end

	public function get_item_details(
	$item_id,
	$unit_id = null,
	$unit_name = null,
	$conversion_qty = 1,
	$sales_price = null,
	$alternate_id = null
)
	{
		  $this->db->select("b.id as tax_id, a.*,b.tax,b.tax_name");
	      $this->db->from("db_items a");
	      $this->db->join("db_tax b","b.id=a.tax_id","left");
	      $this->db->where("a.status=1");
	      $this->db->where("a.id",$item_id);
		  //echo $this->db->get_compiled_select();exit();
		  $res1=$this->db->get()->row();

		  // Get customer price type and use appropriate price
		  $customer_id = $this->input->post('customer_id');
		  $price_type = 'retail'; // Default to retail
		  
		  // Debug logging
		  log_message('debug', 'POS get_item_details - Item ID: ' . $item_id . ', Customer ID: ' . $customer_id);
		  
		  if (!empty($customer_id)) {
		  	$customer_query = $this->db->query("SELECT customer_type FROM db_customers WHERE id = $customer_id");
		  	if ($customer_query->num_rows() > 0) {
		  		$customer = $customer_query->row();
		  		$price_type = $customer->customer_type ?: 'retail';
		  		log_message('debug', 'Customer type: ' . $price_type);
		  	}
		  }
		  
		  // Use appropriate price based on customer type
		  $final_sales_price = $res1->sales_price; // Default
		  log_message('debug', 'Item prices - Sales: ' . $res1->sales_price . ', Wholesale: ' . $res1->wholesale_price . ', Retail: ' . $res1->retail_price);
		  
		  if ($price_type == 'wholesale' && !empty($res1->wholesale_price) && $res1->wholesale_price > 0) {
		  	$final_sales_price = $res1->wholesale_price;
		  	log_message('debug', 'Using wholesale price: ' . $final_sales_price);
		  } elseif ($price_type == 'retail' && !empty($res1->retail_price) && $res1->retail_price > 0) {
		  	$final_sales_price = $res1->retail_price;
		  	log_message('debug', 'Using retail price: ' . $final_sales_price);
		  } else {
		  	log_message('debug', 'Using sales price: ' . $final_sales_price);
		  }

	      $item_tax_amt = ($res1->tax_type=='Inclusive') ? calculate_inclusive($final_sales_price,$res1->tax) :calculate_exclusive($final_sales_price,$res1->tax);
	      
	      $warehouse_stock = total_available_qty_items_of_warehouse($this->input->post('warehouse_id'),null,$item_id);
	      /* =====================================================
   ALTERNATE UNIT COST CALCULATION
===================================================== */

$purchase_price = $res1->purchase_price;

if(
	!empty($alternate_id) &&
	!empty($conversion_qty) &&
	$conversion_qty > 0
){

	// Main unit cost divided by conversion
	$purchase_price = $res1->purchase_price / $conversion_qty;

	// Optional safety formatting
	$purchase_price = number_format($purchase_price, decimals(), '.', '');
}
	      $main_unit_name = '';
	      $alternate_unit_name = '';
	      $conversion_factor = isset($res1->conversion_factor) ? (float)$res1->conversion_factor : 0;
	      $has_dual_units = 0;
	      $sales_price_main = $final_sales_price;
	      $sales_price_alternate = $final_sales_price;
	      if (!empty($res1->main_unit_id) && !empty($res1->alternate_unit_id) && $conversion_factor > 0) {
	      	$mu = $this->db->select('unit_name')->where('id', $res1->main_unit_id)->get('db_units')->row();
	      	$au = $this->db->select('unit_name')->where('id', $res1->alternate_unit_id)->get('db_units')->row();
	      	$main_unit_name = $mu ? $mu->unit_name : '';
	      	$alternate_unit_name = $au ? $au->unit_name : '';
	      	if ($main_unit_name !== '' && $alternate_unit_name !== '') {
	      		$has_dual_units = 1;
	      		if (!empty($res1->sales_price_main) && $res1->sales_price_main > 0) {
	      			$sales_price_main = $res1->sales_price_main;
	      			if (!empty($res1->sales_price_alternate) && $res1->sales_price_alternate > 0) {
	      				$sales_price_alternate = $res1->sales_price_alternate;
	      			} else {
	      				$sales_price_alternate = $sales_price_main / $conversion_factor;
	      			}
	      		} else {
	      			$sales_price_alternate = $final_sales_price;
	      			$sales_price_main = $final_sales_price * $conversion_factor;
	      		}
	      	}
	      }
	      $item_array = array(
	      				'id' 					=> $res1->id,
	      				'item_name' 			=> $res1->item_name,
	      				'stock' 				=> $warehouse_stock,
	      				'sales_price' 			=> $sales_price_main,
	      				'purchase_price' 		=> $purchase_price,
	      				'tax_id' 				=> $res1->tax_id,
	      				'tax_type' 				=> $res1->tax_type,
	      				'tax' 					=> $res1->tax,
	      				'tax_name' 				=> $res1->tax_name,
	      				'item_tax_amt' 			=> $item_tax_amt,
	      				'discount_type' 		=> $res1->discount_type,
	      				'discount' 				=> $res1->discount,
	      				'service_bit' 			=> $res1->service_bit,
	      				'batch_tracking_enabled' => isset($res1->batch_tracking_enabled) ? (int)$res1->batch_tracking_enabled : 0,
	      				'tracking_type' 		=> isset($res1->tracking_type) ? $res1->tracking_type : 'none',
	      				'has_dual_units' 		=> $has_dual_units,
	      				'main_unit_name' 		=> $main_unit_name,
	      				'alternate_unit_name' 	=> $alternate_unit_name,
	      				'conversion_factor' 	=> $conversion_factor,
	      				'sales_price_main' 	=> $sales_price_main,
	      				'sales_price_alternate' => $sales_price_alternate,
	      );

	      return json_encode($item_array);

	}

	public function get_details(){

		//echo "<pre>";print_r($this->xss_html_filter(array_merge($this->data,$_POST,$_GET)));exit();

		$data=$this->data;
		extract($data);
		extract($_POST);
		$CI =& get_instance();
		
		
		  $i=0;
		 
		  if(!empty($id)){
		  	$this->db->where(" a.category_id=$id ");
		  }
		  if($brand_id!=''){
		  	$this->db->where(" a.brand_id=$brand_id");
		  }
		  
		  $this->db->select("a.*,b.tax,b.tax_name");

		  $this->db->join(" db_tax b ","b.id=a.tax_id",'left');
		  
		  $this->db->from("db_items as a");
		  $this->db->where("a.store_id",$store_id);
		  $this->db->where("a.status",1);
		  if(!empty($item_name)){
		  	$this->db->where("upper(a.item_name) like upper('%".$item_name."%')");
		  }
		  if(isset($last_id) && !empty($last_id)){
		  	$this->db->where("a.id>".$last_id);
		  }
		  $this->db->limit(30);

		  //echo $this->db->get_compiled_select();exit();

	      $q2=$this->db->get();
	      $table='';
	      if($q2->num_rows()>0){
	        foreach($q2->result() as $res2){
	        	if($res2->item_group=='Variants'){continue;}
	        	$w_stock = total_available_qty_items_of_warehouse($warehouse_id,$store_id,$res2->id);
	        	$item_code = $res2->item_code;
	        	$item_tax_type = $res2->tax_type;
	        	$item_tax_id = $res2->tax_id;


	        	$discount_type = $res2->discount_type;
	        	$discount = $res2->discount;
	        	

	        	// Get customer price type and use appropriate price
	        	$price_type = 'retail'; // Default to retail
	        	if (!empty($customer_id)) {
	        		$customer_query = $this->db->query("SELECT customer_type FROM db_customers WHERE id = $customer_id");
	        		if ($customer_query->num_rows() > 0) {
	        			$customer = $customer_query->row();
	        			$price_type = $customer->customer_type ?: 'retail';
	        		}
	        	}
	        	
	        	// Debug logging
	        	log_message('debug', 'POS get_details - Customer ID: ' . $customer_id . ', Price Type: ' . $price_type);
	        	log_message('debug', 'Item prices - Sales: ' . $res2->sales_price . ', Wholesale: ' . $res2->wholesale_price . ', Retail: ' . $res2->retail_price);
	        	
	        	// Use appropriate price based on customer type
	        	if ($price_type == 'wholesale' && !empty($res2->wholesale_price) && $res2->wholesale_price > 0) {
	        		$item_sales_price = $res2->wholesale_price;
	        		log_message('debug', 'Using wholesale price: ' . $item_sales_price);
	        	} elseif ($price_type == 'retail' && !empty($res2->retail_price) && $res2->retail_price > 0) {
	        		$item_sales_price = $res2->retail_price;
	        		log_message('debug', 'Using retail price: ' . $item_sales_price);
	        	} else {
	        		$item_sales_price = $res2->sales_price;
	        		log_message('debug', 'Using sales price: ' . $item_sales_price);
	        	}
	        	$sales_price_main = $item_sales_price;
	        	$sales_price_alternate = $item_sales_price;
	        	$has_dual_units = 0;
	        	$main_unit_name = '';
	        	$alternate_unit_name = '';
	        	$conversion_factor = 0;
	        	if (!empty($res2->main_unit_id) && !empty($res2->alternate_unit_id) && isset($res2->conversion_factor) && (float)$res2->conversion_factor > 0) {
	        		$mu = $this->db->select('unit_name')->where('id', $res2->main_unit_id)->get('db_units')->row();
	        		$au = $this->db->select('unit_name')->where('id', $res2->alternate_unit_id)->get('db_units')->row();
	        		$main_unit_name = $mu ? $mu->unit_name : '';
	        		$alternate_unit_name = $au ? $au->unit_name : '';
	        		if ($main_unit_name !== '' && $alternate_unit_name !== '') {
	        			$has_dual_units = 1;
	        			$conversion_factor = (float)$res2->conversion_factor;
	        			if (!empty($res2->sales_price_main) && $res2->sales_price_main > 0) {
	        				$sales_price_main = $res2->sales_price_main;
	        				$sales_price_alternate = (!empty($res2->sales_price_alternate) && $res2->sales_price_alternate > 0) ? $res2->sales_price_alternate : ($res2->sales_price_main / $conversion_factor);
	        			} else {
	        				$sales_price_main = $item_sales_price;
	        				$sales_price_alternate = $item_sales_price / $conversion_factor;
	        			}
	        			$sales_price_main = number_format($sales_price_main, decimals(), '.', '');
	        			$sales_price_alternate = number_format($sales_price_alternate, decimals(), '.', '');
	        		}
	        	}
	        	
				$item_sales_price = number_format($item_sales_price,decimals(),'.','');

	        	$item_cost = $res2->purchase_price;
	        	$item_tax = $res2->tax;
	        	$item_tax_name = $res2->tax_name;
	        	$service_bit = $res2->service_bit;
	        	$item_sales_qty = 1;

				$item_tax_amt = ($item_tax_type=='Inclusive') ? calculate_inclusive($item_sales_price,$item_tax) :calculate_exclusive($item_sales_price,$item_tax);

				
	        	if($w_stock <1 && !$service_bit){
	        		$str="zero_stock()";
	        		$disabled='';
	        		$bg_color="background-color:#9d9999";
	        		$card_class='pos-product-outstock';
	        	}
	        	else{
	        		$str="addrow($res2->id)";
	        		$disabled="disabled=disabled";
	        		$bg_color="background-color:#d9f5d1";
	        		$card_class='pos-product-instock';
	        	}

	        	$label_title = (!$service_bit) ? $w_stock.' Quantity in Stock' : 'Service Item';
	        	$label = (!$service_bit) ? "Qty: ".$w_stock : 'Service';

	        	// Batch tracking: show badge on product card and pass data for cart
	        	$batch_tracking_enabled = isset($res2->batch_tracking_enabled) ? (int)$res2->batch_tracking_enabled : 0;
	        	$tracking_type = isset($res2->tracking_type) ? $res2->tracking_type : 'none';
	        	$batch_ribbon = '';
	        	if ($batch_tracking_enabled == 1) {
	        		$batch_ribbon = '<span class="pos-batch-ribbon" data-toggle="tooltip" title="Batch tracking – select batch in cart"><i class="fa fa-tags"></i></span>';
	        	}

	        	$item_image = $res2->item_image;
	        	if(!empty($res2->parent_id)){
	        		$item_image = get_item_details($res2->parent_id)->item_image;
	        	}

	        	$img_src = (!empty($item_image) && file_exists($item_image)) ? base_url(return_item_image_thumb($item_image)) : base_url('theme/images/no_image.png');

	        	$item_name_esc = htmlspecialchars($res2->item_name, ENT_QUOTES, 'UTF-8');
	        	$table .= '<div class="col-md-3 col-xs-6 pos-product-col" id="item_parent_'.$i.'" '.$disabled.' data-toggle="tooltip" style="padding:5px; position:relative;" title="'.$item_name_esc.'">
	          <div class="box box-default item_box pos-product-card '.$card_class.'" id="div_'.$res2->id.'" onclick="'.$str.'"
	          				data-item-id="'.$res2->id.'"
	          				data-item-name="'.$item_name_esc.'"
	          				data-item-available-qty="'.$w_stock.'"
	          				data-item-sales-price="'.$item_sales_price.'"
	          				data-item-cost="'.$item_cost.'"
	          				data-item-tax-id="'.$item_tax_id.'"
	          				data-item-tax-type="'.$item_tax_type.'"
	          				data-item-tax-value="'.$item_tax.'"
	          				data-item-tax-name="'.$item_tax_name.'"
	          				data-item-tax-amt="'.$item_tax_amt.'"
	          				data-service_bit="'.$service_bit.'"
	          				data-discount_type="'.$discount_type.'"
	          				data-discount="'.$discount.'"
	          				data-batch-tracking-enabled="'.$batch_tracking_enabled.'"
	          				data-tracking-type="'.htmlspecialchars($tracking_type, ENT_QUOTES, 'UTF-8').'"
	          				data-has-dual-units="'.$has_dual_units.'"
	          				data-main-unit-name="'.htmlspecialchars($main_unit_name, ENT_QUOTES, 'UTF-8').'"
	          				data-alternate-unit-name="'.htmlspecialchars($alternate_unit_name, ENT_QUOTES, 'UTF-8').'"
	          				data-conversion-factor="'.$conversion_factor.'"
	          				data-sales-price-main="'.$sales_price_main.'"
	          				data-sales-price-alternate="'.$sales_price_alternate.'"
	           				style="cursor: pointer;'.$bg_color.'">
	           	<div class="item_box_top_badges">
	           		<span class="item_box_qty_badge label label-danger" data-toggle="tooltip" title="'.$label_title.'">'.$label.'</span>
	           		<span class="item_box_batch_badge">'.$batch_ribbon.'</span>
	           	</div>
	            <div class="box-body box-profile pos-product-card-body">
	            	<div class="pos-product-card-image">
	            		<img class="img-responsive item_image pos-product-img" src="'.$img_src.'" alt="Item">
	            	</div>
	            	<div class="pos-product-card-name search_item" id="item_'.$i.'">'.$item_name_esc.'</div>
	            	<div class="pos-product-card-price">'.$CI->currency(store_number_format($item_sales_price)).'</div>
	            </div>
	          </div>
	        </div>';
	          $i++;
	          }//for end
	          return $table;
	      }//if num_rows() end
	     
	}
	//CROSS SITE FILTER
	public function xss_html_filter($input){
		return $this->security->xss_clean(html_escape($input));
	}
	
	//Save Sales
	public function pos_save_update(){//Save or update sales
		$this->db->trans_begin();
		extract($this->xss_html_filter(array_merge($this->data,$_POST,$_GET)));
		//print_r($this->xss_html_filter(array_merge($this->data,$_POST,$_GET)));exit();

		//varify max sales usage of the package subscription
		validate_package_offers('max_invoices','db_sales');
		//END

		//check payment method
		if(isset($by_cash) && $by_cash==true){ //by cash payment
			$by_cash=true;
			$payment_row_count=1;
		}else{ //by multiple payments
			$by_cash=false;
		}
		//end 

		$store_id=(store_module() && is_admin()) ? $store_id : get_current_store_id();
		$rowcount 			=$hidden_rowcount;
		$sales_date 		=date("Y-m-d",strtotime($CUR_DATE));
		//$points 			= (empty($points_use)) ? 'NULL' : $points_use;
		$discount_input 	= (empty($discount_input)) ? 'NULL' : $discount_input;
		// Normalize totals: strip commas so "5,940.48" is saved as 5940.48, not truncated
		if (isset($tot_grand) && $tot_grand !== '' && trim($tot_grand) !== '') {
			$tot_grand = (float)str_replace(',', '', trim($tot_grand));
		}
		if (isset($tot_amt) && $tot_amt !== '' && trim($tot_amt) !== '') {
			$tot_amt = (float)str_replace(',', '', trim($tot_amt));
		}
		if (isset($tot_disc) && $tot_disc !== '' && trim($tot_disc) !== '') {
			$tot_disc = (float)str_replace(',', '', trim($tot_disc));
		}
		// ================= FINAL DISCOUNT PROTECTION (STRICT POS) =================

// Normalize values safely
$tot_amt_val  = ($tot_amt === 'NULL' || $tot_amt == NULL) ? 0 : (float)$tot_amt;
$tot_disc_val = ($tot_disc === 'NULL' || $tot_disc == NULL) ? 0 : (float)$tot_disc;
$tot_grand_val = ($tot_grand === 'NULL' || $tot_grand == NULL) ? 0 : (float)$tot_grand;

// ❌ RULE 0: Prevent negative discount (tampering)
if ($tot_disc_val < 0) {
    $this->db->trans_rollback();
    return "Invalid discount value.";
}

// Avoid division errors
if ($tot_amt_val > 0) {

    // Calculate discount %
    $discount_percent = ($tot_disc_val / $tot_amt_val) * 100;

    // ❌ RULE 1: Max 10% discount allowed
    if ($discount_percent > 10) {
        $this->db->trans_rollback();
        return "Discount Error: Maximum allowed discount is 10%. You entered "
               . number_format($discount_percent, 2) . "%";
    }

    // ❌ RULE 2: Prevent amount abuse
    if ($tot_disc_val > ($tot_amt_val * 0.10)) {
        $this->db->trans_rollback();
        return "Discount Alert: Discount amount exceeds 10% of invoice total.";
    }

    // ❌ RULE 3: Prevent total tampering
    $expected_grand = $tot_amt_val - $tot_disc_val;

    if (abs($expected_grand - $tot_grand_val) > 0.5) {
        $this->db->trans_rollback();
        return "Calculation Error: Invoice totals mismatch. Possible manipulation detected.";
    }
}

// ========================================================================
		

		//FIND CUSTOMER INFORMATION BY ITS ID
		$q1=$this->db->query("select customer_name,mobile from db_customers where id=$customer_id");
		$customer_name 	= $q1->row()->customer_name;
		$mobile 		= $q1->row()->mobile;


		//Get coupon details
	    $customer_coupon_id = null;
	    if(!empty($coupon_code)){
	    	$coupon_details = get_customer_coupon_details_by_coupon_code($coupon_code);
	    	
		    if($coupon_details->num_rows()>0){
		    	if($coupon_details->row()->customer_id==$customer_id){
		    		$customer_coupon_id = $coupon_details->row()->id;		
		    	}
		    }
	    }





	    //Verify Sales Code
		$this->db->where("sales_code",$init_code.$count_id);
		if($command=='update'){
			$this->db->where("id<>",$sales_id);
		}
		$this->db->from('db_sales');
		//echo $this->db->get_compiled_select();exit;
		$count = $this->db->count_all_results();
		

		if($count>0){

			$autosynch_sales_code = true;

			if($autosynch_sales_code){
				$count_id = autosynch_sales_code();
			}
			else{
				echo "Sales Code already exist";
				exit;	
			}
		}




		$sales_entry_init = array(
	    							'init_code' 				=> $init_code,
				    				'count_id' 					=> $count_id,
				    				'sales_code' 				=> $init_code.$count_id,
				    				/*Coupon disocunt amt*/
				    				'coupon_id' 				=> $customer_coupon_id,
				    				'coupon_amt' 				=> $coupon_discount_amt,
				    				'invoice_terms' 			=> $invoice_terms,
	    						);
		//echo "<pre>";print_r($sales_entry_init);exit;

		$prev_item_ids = array();

		if($command=='update'){
				$sales_entry = array(
		    				'store_id' 				=> $store_id,
		    				//'sales_date' 				=> $sales_date,
		    				'sales_status' 				=> 'Final',
		    				'customer_id' 				=> $customer_id,
		    				/*'warehouse_id' 				=> $warehouse_id,*/
		    				/*Discount*/
		    				'discount_to_all_input' 	=> $discount_input,
		    				'discount_to_all_type' 		=> $discount_type,
		    				'tot_discount_to_all_amt' 	=> $tot_disc,
		    				/*Subtotal & Total */
		    				'subtotal' 					=> $tot_amt,
		    				'round_off' 				=> $round_off,
		    				'grand_total' 				=> $tot_grand,
		    				'sales_note' 				=> $sales_note,
		    			);
				$sales_entry['warehouse_id']=(warehouse_module() && warehouse_count()>1) ? $warehouse_id : get_store_warehouse_id();
				$q3 = $this->db->where('id',$sales_id)->update('db_sales', array_merge($sales_entry,$sales_entry_init));

				##############################################START
				//FIND THE PREVIOUSE ITEM LIST ID'S
				$prev_item_ids = $this->db->select("item_id")->from("db_salesitems")->where("sales_id",$sales_id)->get()->result_array();
				##############################################END

				// Restore batch stock before deleting sales items (edit: return qty to batch; delete: full qty back)
				// Use MAIN unit quantity only: item may have alt & main unit; restore only what was deducted (main)
				$batch_items = $this->db->select("item_id, batch_number, sales_qty, sales_qty_main, unit_type")->from("db_salesitems")->where("sales_id", $sales_id)->where("batch_number IS NOT NULL")->where("batch_number !=", "")->get()->result();
				foreach ($batch_items as $batch_item) {
					$qty_to_restore = $this->_pos_sales_item_qty_in_main_unit($batch_item->item_id, $batch_item->sales_qty, $batch_item->sales_qty_main, $batch_item->unit_type);
					$this->db->where('item_id', $batch_item->item_id);
					$this->db->where('batch_number', $batch_item->batch_number);
					$this->db->set('remaining_quantity', 'remaining_quantity + ' . (float)$qty_to_restore, FALSE);
					$this->db->update('db_item_batches');
				}
				
				$q11=$this->db->query("delete from db_salesitems where sales_id='$sales_id'");
				$q12=$this->db->query("delete from db_salespayments where sales_id='$sales_id'");
				if(!$q11 || !$q12){
					return "failed";
				}
		}
		else{
			$this->db->query("ALTER TABLE db_sales AUTO_INCREMENT = 1");

			$sales_entry = array(
							//'count_id' 					=> get_count_id('db_sales'),  
		    				//'sales_code' 				=> get_init_code('sales'), 
		    				'store_id' 				=> $store_id,
		    				'sales_date' 				=> $sales_date,
		    				'sales_status' 				=> 'Final',
		    				'customer_id' 				=> $customer_id,
		    				/*'warehouse_id' 				=> $warehouse_id,*/
		    				/*Discount*/
		    				'discount_to_all_input' 	=> $discount_input,
		    				'discount_to_all_type' 		=> $discount_type,
		    				'tot_discount_to_all_amt' 	=> $tot_disc,
		    				/*Subtotal & Total */
		    				'subtotal' 					=> $tot_amt,
		    				'round_off' 				=> $round_off,
		    				'grand_total' 				=> $tot_grand,
		    				/*System Info*/
		    				'created_date' 				=> $CUR_DATE,
		    				'created_time' 				=> $CUR_TIME,
		    				'created_by' 				=> $CUR_USERNAME,
		    				'system_ip' 				=> $SYSTEM_IP,
		    				'system_name' 				=> $SYSTEM_NAME,
		    				'pos' 						=> 1,
		    				'status' 					=> 1,
		    				'sales_note' 				=> $sales_note,
		    			);
			$sales_entry['warehouse_id']=(warehouse_module() && warehouse_count()>1) ? $warehouse_id : get_store_warehouse_id();

			
			$q3 = $this->db->insert('db_sales', array_merge($sales_entry,$sales_entry_init));
			$sales_id = $this->db->insert_id();
		}

	//Lose prevention
	$invoice_items = array();
   $invoice_total_cost = 0;
   $invoice_total_purchase = 0;

		//Import post data from form
		for($i=0;$i<$rowcount;$i++){
		
			if(isset($_REQUEST['tr_item_id_'.$i]) && trim($_REQUEST['tr_item_id_'.$i])!=''){
			
				//RECEIVE VALUES FROM FORM (normalize numbers: strip commas so "4,373.20" saves as 4373.20)
				$item_id 	=$this->xss_html_filter(trim($_REQUEST['tr_item_id_'.$i]));
				$sales_qty 	= trim($_REQUEST['item_qty_'.$i]);
				$sales_qty 	= ($sales_qty !== '') ? (float)str_replace(',', '', $sales_qty) : 0;
				$price_per_unit = trim($_REQUEST['sales_price_'.$i]);
				$price_per_unit = ($price_per_unit !== '') ? (float)str_replace(',', '', $price_per_unit) : 0;
				$tax_amt = trim($_REQUEST['td_data_'.$i.'_11']);
				$tax_amt = ($tax_amt !== '') ? (float)str_replace(',', '', $tax_amt) : null;
				$tax_type =$this->xss_html_filter(trim($_REQUEST['tr_tax_type_'.$i]));
				$tax_id =$this->xss_html_filter(trim($_REQUEST['tr_tax_id_'.$i]));
				$tax_value = trim($_REQUEST['tr_tax_value_'.$i]);
				$tax_value = ($tax_value !== '') ? (float)str_replace(',', '', $tax_value) : 0;
				$total_cost = trim($_REQUEST['td_data_'.$i.'_4']);
				$total_cost = ($total_cost !== '') ? (float)str_replace(',', '', $total_cost) : null;
				$description =$this->xss_html_filter(trim($_REQUEST['description_'.$i]));
				
				$discount_type =$this->xss_html_filter(trim($_REQUEST['item_discount_type_'.$i]));
				$discount_input =$this->xss_html_filter(trim($_REQUEST['item_discount_input_'.$i]));
				$discount_amt = trim($_REQUEST['item_discount_'.$i]);
				$discount_amt = ($discount_amt !== '') ? (float)str_replace(',', '', $discount_amt) : 0;

				$batch_number = isset($_REQUEST['batch_number_'.$i]) ? $this->xss_html_filter(trim($_REQUEST['batch_number_'.$i])) : '';
				$manufacturing_date = isset($_REQUEST['manufacturing_date_'.$i]) ? $this->xss_html_filter(trim($_REQUEST['manufacturing_date_'.$i])) : '';
				$expiry_date = isset($_REQUEST['expiry_date_'.$i]) ? $this->xss_html_filter(trim($_REQUEST['expiry_date_'.$i])) : '';
				$unit_type = isset($_REQUEST['unit_type_'.$i]) ? $this->xss_html_filter(trim($_REQUEST['unit_type_'.$i])) : 'main';
				$sales_qty_main = null;
				$sales_qty_alternate = null;
				$item_multi = $this->db->select('conversion_factor')->from('db_items')->where('id', $item_id)->get()->row();
				if ($item_multi && isset($item_multi->conversion_factor) && (float)$item_multi->conversion_factor > 0) {
					if ($unit_type === 'main') {
						$sales_qty_main = $sales_qty;
						$sales_qty_alternate = round($sales_qty * (float)$item_multi->conversion_factor, 4);
					} else {
						$sales_qty_alternate = $sales_qty;
						$sales_qty_main = round($sales_qty / (float)$item_multi->conversion_factor, 4);
					}
				} else {
					$unit_type = 'main';
					$sales_qty_main = $sales_qty;
				}
				$qty_for_batch = ($sales_qty_main !== null) ? (float)$sales_qty_main : (float)$sales_qty;

				if($tax_type=='Exclusive'){
					$single_unit_total_cost = $price_per_unit + ($tax_value * $price_per_unit / 100);
				}
				else{//Inclusive
					$single_unit_total_cost =$price_per_unit;
				}

				
				if($tax_id=='' || $tax_id==0){$tax_id=null;}
				if($tax_amt=='' || $tax_amt==0){$tax_amt=null;}
				if($total_cost=='' || $total_cost==0){$total_cost=null;}
				
				
				/* ******************************** */
				//Find the qty available or not
				$item_row = $this->db
    ->select('item_name, purchase_price, mrp, service_bit')
    ->from('db_items')
    ->where('id', $item_id)
    ->get()
    ->row();

$item_name   = $item_row->item_name;
$purchase    = (float)$item_row->purchase_price;
$item_mrp    = (float)$item_row->mrp;
$service_bit = $item_row->service_bit;

	// ================= FULL PROFIT PROTECTION (ITEM LEVEL) =================

if ($service_bit == 0) {

    $qty = max((float)$sales_qty, 1);

    // Normalize inputs safely
    $price = (float)str_replace(',', '', $price_per_unit);
    $item_discount = (float)str_replace(',', '', $discount_amt);


    // ❌ RULE 0: Prevent negative or invalid values (ABUSE PROTECTION)
    if ($price <= 0) {
        $this->db->trans_rollback();
        return "Item Error: {$item_name} has invalid selling price.";
    }

    if ($item_discount < 0) {
        $this->db->trans_rollback();
        return "Item Error: {$item_name} has invalid negative discount.";
    }

    if ($purchase < 0) {
        $this->db->trans_rollback();
        return "Item Error: {$item_name} has invalid purchase price.";
    }

    if ($qty <= 0) {
        $this->db->trans_rollback();
        return "Item Error: {$item_name} has invalid quantity.";
    }

    // Effective unit selling price after item discount
    $net_unit_price = $price - ($item_discount / $qty);

    // ❌ RULE 1: Prevent selling at zero or negative price
    if ($net_unit_price <= 0) {
        $this->db->trans_rollback();
        return "Item Error: {$item_name} selling price becomes zero or negative after discount.";
    }

    // ❌ RULE 2: Prevent selling below or equal to purchase price
    if ($net_unit_price <= $purchase) {
        $this->db->trans_rollback();
        return "Item Error: {$item_name} selling price after discount (" .
               number_format($net_unit_price, 2) .
               ") is less than or equal to purchase price (" .
               number_format($purchase, 2) . ")";
    }
    // ❌ RULE 3: Enforce MRP as MINIMUM selling price
if ($item_mrp > 0 && $net_unit_price < $item_mrp) {
    $this->db->trans_rollback();
    return "MSP Violation: {$item_name} cannot be sold below MSP (" .
           number_format($item_mrp, 2) . "). Current: " .
           number_format($net_unit_price, 2);
}

    // Track for invoice-level validation
    $line_total_sell = $net_unit_price * $sales_qty;
    $line_total_purchase = $purchase * $sales_qty;

    $invoice_total_cost += $line_total_sell;
    $invoice_total_purchase += $line_total_purchase;

    $invoice_items[] = array(
        'item_name' => $item_name,
        'sell' => $line_total_sell,
        'purchase' => $line_total_purchase
    );
}

// =====================================================================
				$batch_tracking_enabled = isset($item_details->batch_tracking_enabled) ? (int)$item_details->batch_tracking_enabled : 0;
				if ($batch_tracking_enabled == 1 && empty($batch_number)) {
					$this->db->trans_rollback();
					return $item_name . " has batch tracking. Please select a batch.";
				}

				
				/*$current_stock_of_item = total_available_qty_items_of_warehouse($warehouse_id,null,$item_id);
				if($current_stock_of_item<$sales_qty && $service_bit==0){
					return $item_name." has only ".$current_stock_of_item." in Stock!!";exit;
				}*/
				
				$salesitems_entry = array(
		    				'store_id' 			=> $store_id, 
		    				'sales_id' 			=> $sales_id, 
		    				'sales_status'		=> 'Final', 
		    				'item_id' 			=> $item_id, 
		    				'description' 		=> $description, 
		    				'sales_qty' 		=> $sales_qty,
		    				'price_per_unit' 	=> $price_per_unit,
		    				'tax_id' 			=> $tax_id,
		    				'tax_amt' 			=> $tax_amt,
		    				'tax_type' 			=> $tax_type,
		    				'discount_type' 	=> $discount_type,
		    				'discount_input' 	=> $discount_input,
		    				'discount_amt' 		=> $discount_amt,
		    				'unit_total_cost' 	=> $single_unit_total_cost,
		    				'total_cost' 		=> $total_cost,
		    				'purchase_price' 	=> $purchase_price,
		    				'status'	 		=> 1,
		    				'seller_points'		=> get_seller_points($item_id) * $sales_qty,
		    				'batch_number' 		=> $batch_number ? $batch_number : '',
		    				'manufacturing_date' => $manufacturing_date ? $manufacturing_date : null,
		    				'expiry_date' 		=> $expiry_date ? $expiry_date : null,
		    				'unit_type' 		=> $unit_type,
		    				'sales_qty_main' 	=> $sales_qty_main,
		    				'sales_qty_alternate' => $sales_qty_alternate,
		    			);
				$q4 = $this->db->insert('db_salesitems', $salesitems_entry);

				// Deduct from batch when batch-tracked item is sold (batch is always in main unit)
				if (!empty($batch_number)) {
					$this->db->where('item_id', $item_id);
					$this->db->where('batch_number', $batch_number);
					$this->db->set('remaining_quantity', 'remaining_quantity - ' . (float)$qty_for_batch, FALSE);
					$this->db->update('db_item_batches');
				}

				$q11=$this->update_items_quantity($item_id);
				if(!$q11){
					return "failed";
				}

			}
		
		}//for end
		
		// ================= FULL INVOICE PROFIT VALIDATION =================

if ($invoice_total_cost < $invoice_total_purchase) {

    $this->db->trans_rollback();

    return "Invoice Error: Total selling amount (" .
           number_format($invoice_total_cost, 2) .
           ") is less than total purchase cost (" .
           number_format($invoice_total_purchase, 2) .
           "). Reduce discount.";
}

// ===================================================================

		if($pay_all=='true'){
			$by_cash=true;
			$payment_row_count=1;
		}
		else{
			$by_cash=false;
		}

		$tot_received_amt = 0;
		// Walk-in customer (customer_id = 1): only Cash allowed, no Credit; full payment required
		if ($customer_id == 1) {
			$walkin_sum = 0;
			for ($wi = 1; $wi <= $payment_row_count; $wi++) {
				if ((isset($_REQUEST['amount_' . $wi]) && trim($_REQUEST['amount_' . $wi]) !== '') || $by_cash) {
					$pt = $by_cash ? 'Cash' : $this->xss_html_filter(trim($_REQUEST['payment_type_' . $wi]));
					if (strtolower($pt) === 'credit') {
						return "Walk-in customers cannot pay on Credit. Only Cash is allowed.";
					}
					$am = $by_cash ? $tot_grand : $this->xss_html_filter(trim($_REQUEST['amount_' . $wi]));
					$walkin_sum += (float)str_replace(',', '', $am);
				}
			}
			$tot_grand_num = (float)str_replace(',', '', trim($tot_grand));
			if ($walkin_sum < ($tot_grand_num - 0.01)) {
				return "Walk-in customers must pay in full. Total: " . store_number_format($tot_grand_num) . ", Entered: " . store_number_format($walkin_sum);
			}
		}
		//UPDATE CUSTMER MULTPLE PAYMENTS
		for($i=1;$i<=$payment_row_count;$i++){
		
			if((isset($_REQUEST['amount_'.$i]) && trim($_REQUEST['amount_'.$i])!='') || ($by_cash==true)){

				if($by_cash==true){
					//RECEIVE VALUES FROM FORM
					$amount 		=$tot_grand;
					$payment_type 	='Cash';
					$payment_note 	='Paid By Cash';
				}
				else{
					//RECEIVE VALUES FROM FORM
					$amount 		=$this->xss_html_filter(trim($_REQUEST['amount_'.$i]));
					$payment_type 	=$this->xss_html_filter(trim($_REQUEST['payment_type_'.$i]));
					$payment_note 	=$this->xss_html_filter(trim($_REQUEST['payment_note_'.$i]));
				}
				// Walk-in: reject Credit payment type
				if ($customer_id == 1 && strtolower(trim($payment_type)) === 'credit') {
					return "Walk-in customers cannot pay on Credit. Only Cash is allowed.";
				}

				if($command=='save' && $pay_all=='true'){
					// For Pay All, ensure we use a base currency account
					$account_id = $this->get_default_cash_account_for_pay_all();
				}
				else{
					$account_id 	=$this->xss_html_filter(trim($_REQUEST['account_id_'.$i]));
				}
				

				// Parse amount so comma-formatted values (e.g. 5,940.48) are stored correctly, not truncated
				$change_return=0;
				$amount_num = (float)str_replace(',', '', trim($amount));
				$tot_grand_num_here = (float)str_replace(',', '', trim($tot_grand));
				if($amount_num > $tot_grand_num_here){
					$change_return = $amount_num - $tot_grand_num_here;
					$amount_num = $tot_grand_num_here;
				}
				// end
				$payment_code=get_init_code('sales_payment');
				$salespayments_entry = array(
					'payment_code' 		=> $payment_code,
		    		'count_id'	  		=> get_count_id('db_salespayments'),
					'store_id' 		=> $store_id, 
					'sales_id' 		=> $sales_id, 
					'payment_date'		=> $sales_date,//Current Payment with sales entry
					'payment_type' 		=> $payment_type,
					'payment' 			=> $amount_num,
					'payment_note' 		=> $payment_note,
					'created_date' 		=> $CUR_DATE,
    				'created_time' 		=> $CUR_TIME,
    				'created_by' 		=> $CUR_USERNAME,
    				'system_ip' 		=> $SYSTEM_IP,
    				'system_name' 		=> $SYSTEM_NAME,
    				'change_return' 	=> $change_return,
    				'status' 			=> 1,
    				'customer_id' 		=> $customer_id,
    				'account_id' 		=> (empty($account_id)) ? null : $account_id,
				);


				//is total advance payment enabled ?
				$advance_adjusted=0;
				if(isset($allow_tot_advance)){
					$tot_advance = get_customer_details($customer_id)->tot_advance;
					if($tot_advance>0){
						if($amount_num==$tot_advance){
							$advance_adjusted = $amount_num;
						}
						else if($amount_num>$tot_advance){
							$advance_adjusted = $tot_advance;	
						}
						else{
							$advance_adjusted =  $amount_num;
						}
					}
				}
				//end 
				$salespayments_entry['advance_adjusted'] = $advance_adjusted;


			  
			  $q7 = $this->db->insert('db_salespayments', $salespayments_entry);
			  $last_insert_id = $this->db->insert_id();

			    if(!$q7)
				{
					return "failed";
				}

				if(!set_customer_tot_advance($customer_id)){
		        	return 'failed';
		        }
				//Set the payment to specified account
				if(!empty($account_id)){
					//ACCOUNT INSERT
					$insert_bit = insert_account_transaction(array(
																'transaction_type'  	=> 'SALES PAYMENT',
																'reference_table_id'  	=> $last_insert_id,
																'debit_account_id'  	=> null,
																'credit_account_id'  	=> $account_id,
																'debit_amt'  			=> 0,
																'credit_amt'  			=> $amount_num,
																'process'  				=> 'SAVE',
																'note'  				=> $payment_note,
																'transaction_date'  	=> $CUR_DATE,
																'payment_code'  		=> $payment_code,
																'customer_id'  			=> $customer_id,
																'supplier_id'  			=> null,
														));
					if(!$insert_bit){
						return "failed";
					}
				}
				//end


				$tot_received_amt += $amount_num;
				
			}//if()
		
		}//for end


		// Normalize amounts for comparison (form may send formatted string; avoid rounding false positives)
		$tot_grand_num = (float)str_replace(',', '', trim($tot_grand));
		$tot_received_num = (float)$tot_received_amt;
		if($tot_received_num > $tot_grand_num + 0.001){
			echo "Payble amount should not be exceeds Invoice Amount!!";exit;
		}

		/**
		 * Verifying previous and current payment total with invoice amount
		 */
		$tot_payment = $this->db->select('coalesce(sum(payment),0) as payment')->where('sales_id',$sales_id)->get('db_salespayments')->row()->payment;
		$tot_payment_num = (float)$tot_payment;
		if($tot_payment_num > $tot_grand_num + 0.001){
			echo "Payble amount should not be exceeds Invoice Amount!!\nPlease check previous payments as well.";exit;
		}
		

	
		//UPDATE itemS QUANTITY IN itemS TABLE
		$this->load->model('sales_model');				
		$q6=$this->sales_model->update_sales_payment_status($sales_id,$customer_id);
		if(!$q6){
			return "failed";
		}

		//Calculate Opening balance before and after invoice
		/*$q7=calculate_ob_of_customer($sales_id,$customer_id);
		if(!$q7){
			return "failed";
		}*/

		if(isset($hidden_invoice_id) && !empty($hidden_invoice_id)){
			$q13=$this->hold_invoice_delete($hidden_invoice_id);
			if(!$q13){
				return "failed";
			}
		}
		
		
		$sms_info='';
		if(isset($send_sms) && $customer_id!=1){
			if(send_sms_using_template($sales_id,1)==true){
				$sms_info = 'SMS Has been Sent!';
			}else{
				$sms_info = 'Failed to Send SMS';
			}
		}

		##############################################START
		//FIND THE PREVIOUSE ITEM LIST ID'S
		$curr_item_ids = $this->db->select("item_id")->from("db_salesitems")->where("sales_id",$sales_id)->get()->result_array();
		$two_array = array_merge($prev_item_ids,$curr_item_ids);

		/*Update items in all warehouses of the item*/
		$q7=update_warehouse_items($two_array);
		if(!$q7){
			return "failed";
		}
		##############################################END

		

		//Dont save if invoice credit limit exceeds
		if(!check_credit_limit_with_invoice($customer_id,$sales_id)){
			return 'failed';
		}

		
		//COMMIT RECORD
		$this->db->trans_commit();
		
		$this->session->set_flashdata('success', 'Success!! Sales Created Successfully!'.$sms_info);
        return "success<<<###>>>$sales_id";


	}

	public function update_items_quantity($item_id){
		//FIND IS IS SERVICE OR NOT
		$service_bit=$this->db->query("select service_bit from db_items where id='$item_id'")->row()->service_bit;
		if($service_bit==1){
			return true;
		}
		
		//UPDATE itemS QUANTITY IN itemS TABLE
		$q7=$this->db->query("select COALESCE(SUM(adjustment_qty),0) as stock_qty from db_stockadjustmentitems where item_id='$item_id'");
		$stock_qty=$q7->row()->stock_qty;

		$q8=$this->db->query("select COALESCE(SUM(purchase_qty),0) as pu_tot_qty from db_purchaseitems where item_id='$item_id' and purchase_status='Received'");
		$pu_tot_qty=$q8->row()->pu_tot_qty;
		
		$q9=$this->db->query("select coalesce(SUM(sales_qty),0) as sl_tot_qty from db_salesitems where item_id='$item_id' and sales_status='Final'");
		$sl_tot_qty=$q9->row()->sl_tot_qty;

		/*Fid Return Items Count*/
		$q6=$this->db->query("select COALESCE(SUM(return_qty),0) as pu_return_tot_qty from db_purchaseitemsreturn where item_id='$item_id' ");/*and purchase_id is null */
		$pu_return_tot_qty=$q6->row()->pu_return_tot_qty;

		/*Fid Return Items Count*/
		$q6=$this->db->query("select COALESCE(SUM(return_qty),0) as sl_return_tot_qty from db_salesitemsreturn where item_id='$item_id' ");/*and sales_id is null */
		$sl_return_tot_qty=$q6->row()->sl_return_tot_qty;

		$stock=((($stock_qty+$pu_tot_qty)-$sl_tot_qty)+$sl_return_tot_qty)-$pu_return_tot_qty;
		$q7=$this->db->query("update db_items set stock=$stock where id='$item_id'");
		if($q7){
			return true;
		}
		else{
			return false;
		}
	}	
	

	public function edit_pos($sales_id){
		$data=$this->data;
		extract($data);
	     $q2=$this->db->query("select * from db_sales where id='$sales_id'");
	    if($q2->num_rows()>0){
	      $res2=$q2->row();
	      $sales_date=show_date($res2->sales_date);
	      $customer_id=$res2->customer_id;
	      $discount_input=$res2->discount_to_all_input;
	      $discount_type=$res2->discount_to_all_type;
	      $grand_total=$res2->grand_total;
	      $store_id=$res2->store_id;
	      $warehouse_id=$res2->warehouse_id;
	      $sales_note=$res2->sales_note;
	      $invoice_terms=trim($res2->invoice_terms);

	      $q3=$this->db->query("SELECT * FROM db_salesitems WHERE sales_id='$sales_id'");
		  $rows=$q3->num_rows();
		  if($rows>0){
		  	$i=0;
		  	
		  	foreach ($q3->result() as $res3) { 
		  		$q5=$this->db->query("select * from db_items where id=".$res3->item_id);
		  		$price_per_unit = $res3->price_per_unit;
		  		$description = $res3->description;
		  		$service_bit = $q5->row()->service_bit;

		  		$stock = total_available_qty_items_of_warehouse($warehouse_id,$store_id,$q5->row()->id);
		  		$stock+=$res3->sales_qty;

		  		$item_discount = $res3->discount_amt;
		  		$item_discount_type = $res3->discount_type;
		  		$item_discount_input = $res3->discount_input;


		  		$q6=$this->db->query("select * from db_tax where id=".$res3->tax_id)->row();

		  		//$item_tax_type = $q5->row()->tax_type;
	        	/*if($item_tax_type=='Exclusive'){
	        		$per_item_price_inc_tax=$price_per_unit+(($price_per_unit*$q5->row()->tax)/100);
				}
				else{//Inclusive	
					$per_item_price_inc_tax=$price_per_unit;
				}*/
				$per_item_price_inc_tax=$price_per_unit;
				$per_item_price_inc_tax=number_format($per_item_price_inc_tax,decimals(),'.','');	

				$tax_amt = $res3->tax_amt;
				$tax_type = $res3->tax_type;
				$tax_id = $res3->tax_id;
				$tax_value = $q6->tax;

		  		// Quantity input uses row index $i (same as addrow/final_total)
		  		$quantity        ='<div class="input-group input-group-sm"><span class="input-group-btn"><button onclick="decrement_qty('.$res3->item_id.','.$i.')" type="button" class="btn btn-default btn-flat"><i class="fa fa-minus text-danger"></i></button></span>';
			    $quantity       .='<input typ="text" value="'.format_qty($res3->sales_qty).'" class="form-control min_width" onkeyup="item_qty_input('.$res3->item_id.','.$i.')" id="item_qty_'.$i.'" name="item_qty_'.$i.'">';
			    $quantity       .='<span class="input-group-btn"><button onclick="increment_qty('.$res3->item_id.','.$i.')" type="button" class="btn btn-default btn-flat"><i class="fa fa-plus text-success"></i></button></span></div>';
			    $sub_total       =$res3->total_cost;
			    $remove_btn      ='<a class="fa fa-fw fa-trash-o text-red" style="cursor: pointer;font-size: 20px;" onclick="removerow('.$i.')" title="Delete Item?"></a>';
			    
			    // Batch: icon + hidden fields (from db_salesitems / db_items)
			    $batch_tracking_enabled = isset($q5->row()->batch_tracking_enabled) ? (int)$q5->row()->batch_tracking_enabled : 0;
			    $tracking_type = isset($q5->row()->tracking_type) ? $q5->row()->tracking_type : 'none';
			    $batch_number = isset($res3->batch_number) ? trim($res3->batch_number) : '';
			    $manufacturing_date = isset($res3->manufacturing_date) ? $res3->manufacturing_date : '';
			    $expiry_date = isset($res3->expiry_date) ? $res3->expiry_date : '';
			    $batch_icon = '';
			    if ($batch_tracking_enabled == 1) {
			    	$batch_icon = ' <i class="fa fa-tags pointer pos-cart-batch-icon" onclick="show_pos_batch_selection_modal('.$res3->item_id.','.$i.')" title="Select Batch" style="margin-left: 5px;"></i>';
			    }
			    // Visible batch details in item cell when loading hold/edit (same as update_pos_batch_display)
			    $batch_display = '';
			    if ($batch_number !== '') {
			    	$batch_display = '<br><small class="text-info">Batch: '.htmlspecialchars($batch_number, ENT_QUOTES, 'UTF-8').'</small>';
			    	if (!empty($expiry_date) && $expiry_date !== '0000-00-00') {
			    		$exp_fmt = date('d-m-Y', strtotime($expiry_date));
			    		$batch_display .= ' <span class="text-muted">(Exp: '.$exp_fmt.')</span>';
			    	}
			    }
			    
		  		echo '<tr id="row_'.$i.'" data-row="0" data-item-id="'.$res3->item_id.'" >'; /*item id */
		  		echo '<td id="td_'.$i.'_0">
		  		<a data-toggle="tooltip" title="Click to Change Tax" class="pointer" id="td_data_'.$i.'_0" onclick="show_sales_item_modal('.$i.')">'.htmlspecialchars($q5->row()->item_name, ENT_QUOTES, 'UTF-8').'</a>'.$batch_icon.$batch_display.'
		  		</td>';  /*td_0_0 item name*/
		  		echo '<td id="td_'.$i.'_1">'.$stock.'</td>';  /*td_0_1 item available qty*/
		  		echo '<td id="td_'.$i.'_2">'.$quantity.'</td>';    /*td_0_2 item available qty */

		  		$info = '<input id="sales_price_'.$i.'" onblur="set_to_original('.$i.','.$q5->row()->purchase_price.')" onkeyup="update_price('.$i.','.$q5->row()->purchase_price.')" name="sales_price_'.$i.'" type="text" class="form-control min_width" value="'.$per_item_price_inc_tax.'">';

		  		echo '<td id="td_'.$i.'_3" class="text-right" >'.$info.'</td>';    /*td_0_3 item sales price */

		  		$info = '<input data-toggle="tooltip" title="Click to Change" onclick="show_sales_item_modal('.$i.')" id="item_discount_'.$i.'" readonly name="item_discount_'.$i.'" type="text" class="form-control text-left no-padding" value="'.$item_discount.'">';

		  		echo '<td id="td_'.$i.'_6" class="text-right" >'.$info.'</td>';
		  		echo '<td id="td_'.$i.'_11"><input data-toggle="tooltip" title="Click to Change" id="td_data_'.$i.'_11" onclick="show_sales_item_modal('.$i.')" name="td_data_'.$i.'_11" type="text" class="form-control no-padding pointer min_width" readonly value="'.$tax_amt.'"></td>';
		  		echo '<td id="td_'.$i.'_4" class="text-right" >
		  		<input data-toggle="tooltip" title="Total" id="td_data_'.$i.'_4" name="td_data_'.$i.'_4" type="text" class="form-control no-padding pointer min_width" readonly value="'.store_number_format($sub_total,false).'"></td>';    /*td_0_4 item sub_total */
		  		echo '<td id="td_'.$i.'_5">'.$remove_btn.'</td>';    /* td_0_5 item gst_amt  */

		  		echo '<input type="hidden" name="tr_item_id_'.$i.'" id="tr_item_id_'.$i.'" value="'.$res3->item_id.'">';
		  		echo '<input type="hidden" id="tr_item_per_'.$i.'" name="tr_item_per_'.$i.'" value="'.$q6->tax.'">';
		  		echo '<input type="hidden" id="tr_sales_price_temp_'.$i.'" name="tr_sales_price_temp_'.$i.'" value="'.$per_item_price_inc_tax.'">';
		  		echo '<input type="hidden" id="tr_tax_type_'.$i.'" name="tr_tax_type_'.$i.'" value="'.$tax_type.'">';
		  		echo '<input type="hidden" id="tr_tax_id_'.$i.'" name="tr_tax_id_'.$i.'" value="'.$tax_id.'">';
		  		echo '<input type="hidden" id="tr_tax_value_'.$i.'" name="tr_tax_value_'.$i.'" value="'.$tax_value.'">';
		  		echo '<input type="hidden" id="description_'.$i.'" name="description_'.$i.'" value="'.htmlspecialchars($description, ENT_QUOTES, 'UTF-8').'">';
		  		echo '<input type="hidden" id="service_bit_'.$i.'" name="service_bit_'.$i.'" value="'.$service_bit.'">';
		  		echo '<input type="hidden" id="item_discount_type_'.$i.'" name="item_discount_type_'.$i.'" value="'.$item_discount_type.'">';
		  		echo '<input type="hidden" id="item_discount_input_'.$i.'" name="item_discount_input_'.$i.'" value="'.$item_discount_input.'">';
		  		echo '<input type="hidden" id="batch_tracking_enabled_'.$i.'" name="batch_tracking_enabled_'.$i.'" value="'.$batch_tracking_enabled.'">';
		  		echo '<input type="hidden" id="tracking_type_'.$i.'" name="tracking_type_'.$i.'" value="'.htmlspecialchars($tracking_type, ENT_QUOTES, 'UTF-8').'">';
		  		echo '<input type="hidden" id="batch_number_'.$i.'" name="batch_number_'.$i.'" value="'.htmlspecialchars($batch_number, ENT_QUOTES, 'UTF-8').'">';
		  		echo '<input type="hidden" id="manufacturing_date_'.$i.'" name="manufacturing_date_'.$i.'" value="'.htmlspecialchars($manufacturing_date, ENT_QUOTES, 'UTF-8').'">';
		  		echo '<input type="hidden" id="expiry_date_'.$i.'" name="expiry_date_'.$i.'" value="'.htmlspecialchars($expiry_date, ENT_QUOTES, 'UTF-8').'">';
		  		echo '</tr>';
		  		$i++;
		  	}//foreach() end

		  	echo "<<<###>>>".$discount_input."<<<###>>>".$discount_type."<<<###>>>".$customer_id."<<<###>>>".$store_id."<<<###>>>".$warehouse_id."<<<###>>>".$sales_note."<<<###>>>".$invoice_terms;

		  }//if ()
		 
	    }
	    else{
	      print "Record Not Available";
	    }
	     
	}//edit_pos()

	
	/* ######################################## HOLD INVOICE ############################# */
	
	public function hold_invoice_list(){
		$data=$this->data;
		extract($data);
		extract($_POST);
		  $i=0;
		  $str ='';
	      $this->db->select('id, sales_date, reference_id');
	      $this->db->where('store_id', get_current_store_id());
	      $this->db->order_by('id', 'desc');
	      $this->db->limit(100);
	      $q2 = $this->db->get('db_hold');
	      if($q2->num_rows()>0){
	        foreach($q2->result() as $res2){
	     
                  $str =$str."<tr>";
                  $str =$str."<td>".$res2->id."</td>";
                  $str =$str."<td>".show_date($res2->sales_date)."</td>";
                  $str =$str."<td>".$res2->reference_id."</td>";
                  $str =$str."<td>";
                  	$str =$str.'<a class="fa fa-fw fa-trash-o text-red" style="cursor: pointer;font-size: 20px;" onclick="hold_invoice_delete('.$res2->id.')" title="Delete Invoive?"></a>';
                  	$str =$str.'<a class="fa fa-fw fa-edit text-success" style="cursor: pointer;font-size: 20px;" onclick="hold_invoice_edit('.$res2->id.')" title="Edit Invoive?"></a>';
                  $str =$str."</td>";
                $str =$str."</tr>";
	     
	          $i++;
	          }//for end
	      }//if num_rows() end
	      else{
	      	
	      	$str =$str."<tr>";
	      		$str =$str.'<td colspan="4" class="text-danger text-center">No Records Found</td>';
	      	$str =$str.'</tr>';
	      	
	      }
		return $str;
	}
	public function hold_invoice_delete($id){
		$this->db->trans_begin();
		$q1=$this->db->query("DELETE from db_hold where id='$id' and store_id=".get_current_store_id());
		if(!$q1){
			return "failed";
		}
		//COMMIT RECORD
		$this->db->trans_commit();
        return "success";

	}


	/**
	 * Load hold invoice for edit: same logic as reference – load everything that was on the hold.
	 * From db_hold: customer_id, discount_input, discount_type, store_id, warehouse_id, sales_note.
	 * From db_holditems per row: sales_qty, price_per_unit, discount_amt/type/input, tax_*, total_cost, description.
	 * Quantity uses row index (item_qty_$i) so duplicate items and final_total() work; we also send qty list so JS can set values.
	 */
	public function hold_invoice_edit(){
		$data=$this->data;
		extract($this->xss_html_filter(array_merge($this->data,$_POST,$_GET)));
		$q2=$this->db->query("select * from db_hold where id='$hold_id'");
		if($q2->num_rows()>0){
			$res2=$q2->row();
			$sales_date=show_date($res2->sales_date);
			$customer_id=$res2->customer_id;
			$discount_input=$res2->discount_to_all_input;
			$discount_type=$res2->discount_to_all_type;
			$grand_total=$res2->grand_total;
			$store_id=$res2->store_id;
			$warehouse_id=$res2->warehouse_id;
			$sales_note=$res2->sales_note;

			$q3=$this->db->query("SELECT * FROM db_holditems WHERE hold_id='$hold_id'");
			$rows=$q3->num_rows();
			if($rows>0){
				$i=0;
				$hold_qtys = array(); // qty per row, sent to JS so edit hold loads exact qty (same idea as loading all hold data)
				foreach ($q3->result() as $res3) { 
		  		$q5=$this->db->query("select * from db_items where id=".$res3->item_id);
		  		$price_per_unit = $res3->price_per_unit;
		  		$description = $res3->description;
		  		$service_bit = $q5->row()->service_bit;

		  		$warehouse_stock = total_available_qty_items_of_warehouse($warehouse_id,null,$res3->item_id);
		  		$stock=$warehouse_stock;//$q5->row()->stock + $res3->sales_qty;

		  		$item_discount = $res3->discount_amt;
		  		$item_discount_type = $res3->discount_type;
		  		$item_discount_input = $res3->discount_input;


		  		$q6=$this->db->query("select * from db_tax where id=".$res3->tax_id)->row();

		  		
				$per_item_price_inc_tax=$price_per_unit;
				$per_item_price_inc_tax=number_format($per_item_price_inc_tax,decimals(),'.','');	

				$tax_amt = $res3->tax_amt;
				$tax_type = $res3->tax_type;
				$tax_id = $res3->tax_id;
				$tax_value = $q6->tax;

				// Batch: icon + hidden fields (db_holditems has no batch columns yet; show icon so user can select batch)
				$batch_tracking_enabled = isset($q5->row()->batch_tracking_enabled) ? (int)$q5->row()->batch_tracking_enabled : 0;
				$tracking_type = isset($q5->row()->tracking_type) ? $q5->row()->tracking_type : 'none';
				$batch_number = '';
				$manufacturing_date = '';
				$expiry_date = '';
				$batch_icon = '';
				if ($batch_tracking_enabled == 1) {
					$batch_icon = ' <i class="fa fa-tags pointer pos-cart-batch-icon" onclick="show_pos_batch_selection_modal('.$res3->item_id.','.$i.')" title="Select Batch" style="margin-left: 5px;"></i>';
				}
				$batch_display = '';

				// Ensure qty is numeric (DB can return null/empty; avoid showing 0 when value exists)
				$sales_qty_val = isset($res3->sales_qty) && $res3->sales_qty !== '' && $res3->sales_qty !== null ? (float)$res3->sales_qty : 0;
				$hold_qtys[] = $sales_qty_val;

		  		// Quantity uses row index $i (same as edit_pos / addrow)
		  		$quantity        ='<div class="input-group input-group-sm"><span class="input-group-btn"><button onclick="decrement_qty('.$res3->item_id.','.$i.')" type="button" class="btn btn-default btn-flat"><i class="fa fa-minus text-danger"></i></button></span>';
			    $quantity       .='<input type="text" value="'.format_qty($sales_qty_val).'" data-qty="'.(float)$sales_qty_val.'" class="form-control min_width" onkeyup="item_qty_input('.$res3->item_id.','.$i.')" id="item_qty_'.$i.'" name="item_qty_'.$i.'">';
			    $quantity       .='<span class="input-group-btn"><button onclick="increment_qty('.$res3->item_id.','.$i.')" type="button" class="btn btn-default btn-flat"><i class="fa fa-plus text-success"></i></button></span></div>';
			    $sub_total       =$res3->total_cost;
			    $remove_btn      ='<a class="fa fa-fw fa-trash-o text-red" style="cursor: pointer;font-size: 20px;" onclick="removerow('.$i.')" title="Delete Item?"></a>';
			    
		  		echo '<tr id="row_'.$i.'" data-row="0" data-item-id="'.$res3->item_id.'" data-row-qty="'.(float)$sales_qty_val.'">'; /*item id */
		  		echo '<td id="td_'.$i.'_0">
		  		<a data-toggle="tooltip" title="Click to Change Tax" class="pointer" id="td_data_'.$i.'_0" onclick="show_sales_item_modal('.$i.')">'.htmlspecialchars($q5->row()->item_name, ENT_QUOTES, 'UTF-8').'</a>'.$batch_icon.$batch_display.'
		  		</td>';  /*td_0_0 item name*/
		  		echo '<td id="td_'.$i.'_1">'.$stock.'</td>';  /*td_0_1 item available qty*/
		  		echo '<td id="td_'.$i.'_2">'.$quantity.'</td>';    /*td_0_2 item available qty */

		  		$info = '<input id="sales_price_'.$i.'" onblur="set_to_original('.$i.','.$q5->row()->purchase_price.')" onkeyup="update_price('.$i.','.$q5->row()->purchase_price.')" name="sales_price_'.$i.'" type="text" class="form-control min_width" value="'.$per_item_price_inc_tax.'">';

		  		echo '<td id="td_'.$i.'_3" class="text-right" >'.$info.'</td>';    /*td_0_3 item sales price */

		  		$info = '<input data-toggle="tooltip" title="Click to Change" onclick="show_sales_item_modal('.$i.')" id="item_discount_'.$i.'" readonly name="item_discount_'.$i.'" type="text" class="form-control text-left no-padding" value="'.$item_discount.'">';

		  		echo '<td id="td_'.$i.'_6" class="text-right" >'.$info.'</td>';

		  		echo '<td id="td_'.$i.'_11"><input data-toggle="tooltip" title="Click to Change" id="td_data_'.$i.'_11" onclick="show_sales_item_modal('.$i.')" name="td_data_'.$i.'_11" type="text" class="form-control no-padding pointer min_width" readonly value="'.$tax_amt.'"></td>';
		  		echo '<td id="td_'.$i.'_4" class="text-right" >
		  		<input data-toggle="tooltip" title="Total" id="td_data_'.$i.'_4" name="td_data_'.$i.'_4" type="text" class="form-control no-padding pointer min_width" readonly value="'.store_number_format($sub_total,false).'"></td>';    /*td_0_4 item sub_total */
		  		echo '<td id="td_'.$i.'_5">'.$remove_btn.'</td>';    /* td_0_5 item gst_amt  */

		  		echo '<input type="hidden" name="tr_item_id_'.$i.'" id="tr_item_id_'.$i.'" value="'.$res3->item_id.'">'; 
		  		echo '<input type="hidden" id="tr_item_per_'.$i.'" name="tr_item_per_'.$i.'" value="'.$q6->tax.'">';
		  		echo '<input type="hidden" id="tr_sales_price_temp_'.$i.'" name="tr_sales_price_temp_'.$i.'" value="'.$per_item_price_inc_tax.'">';
		  		echo '<input type="hidden" id="tr_tax_type_'.$i.'" name="tr_tax_type_'.$i.'" value="'.$tax_type.'">';
		  		echo '<input type="hidden" id="tr_tax_id_'.$i.'" name="tr_tax_id_'.$i.'" value="'.$tax_id.'">';
		  		echo '<input type="hidden" id="tr_tax_value_'.$i.'" name="tr_tax_value_'.$i.'" value="'.$tax_value.'">';
		  		echo '<input type="hidden" id="description_'.$i.'" name="description_'.$i.'" value="'.htmlspecialchars($description, ENT_QUOTES, 'UTF-8').'">';
		  		echo '<input type="hidden" id="service_bit_'.$i.'" name="service_bit_'.$i.'" value="'.$service_bit.'">';
		  		echo '<input type="hidden" id="item_discount_type_'.$i.'" name="item_discount_type_'.$i.'" value="'.$item_discount_type.'">';
		  		echo '<input type="hidden" id="item_discount_input_'.$i.'" name="item_discount_input_'.$i.'" value="'.$item_discount_input.'">';
		  		echo '<input type="hidden" id="batch_tracking_enabled_'.$i.'" name="batch_tracking_enabled_'.$i.'" value="'.$batch_tracking_enabled.'">';
		  		echo '<input type="hidden" id="tracking_type_'.$i.'" name="tracking_type_'.$i.'" value="'.htmlspecialchars($tracking_type, ENT_QUOTES, 'UTF-8').'">';
		  		echo '<input type="hidden" id="batch_number_'.$i.'" name="batch_number_'.$i.'" value="'.htmlspecialchars($batch_number, ENT_QUOTES, 'UTF-8').'">';
		  		echo '<input type="hidden" id="manufacturing_date_'.$i.'" name="manufacturing_date_'.$i.'" value="'.htmlspecialchars($manufacturing_date, ENT_QUOTES, 'UTF-8').'">';
		  		echo '<input type="hidden" id="expiry_date_'.$i.'" name="expiry_date_'.$i.'" value="'.htmlspecialchars($expiry_date, ENT_QUOTES, 'UTF-8').'">';
		  		echo '</tr>';
		  		$i++;
		  	}//foreach() end

		  	// Send quantities with unique delimiter so JS always gets them (avoids 0 on edit hold)
		  	echo "<<<###>>>".$discount_input."<<<###>>>".$discount_type."<<<###>>>".$customer_id."<<<###>>>".$store_id."<<<###>>>".$warehouse_id."<<<###>>>".$sales_note."<<<###>>>".$hold_id."<<<QTY>>>".implode(',', $hold_qtys);

		  }//if ()
		 
	    }
	    else{
	      print "Record Not Available";
	    }
	     
	}//hold_invoice_edit()


	public function hold_list_save_update(){//Save or update sales
		$this->db->trans_begin();
		extract($this->xss_html_filter(array_merge($this->data,$_POST,$_GET)));
		//print_r($this->xss_html_filter(array_merge($this->data,$_POST,$_GET)));exit();

		$store_id= get_current_store_id();
		$rowcount 			=$hidden_rowcount;
		$sales_date 		=date("Y-m-d",strtotime($CUR_DATE));
		//$points 			= (empty($points_use)) ? 'NULL' : $points_use;
		$discount_input 	= (empty($discount_input)) ? 'NULL' : $discount_input;
		// Normalize totals: strip commas so "5,940.48" is saved correctly
		if (isset($tot_grand) && $tot_grand !== '' && trim($tot_grand) !== '') { $tot_grand = (float)str_replace(',', '', trim($tot_grand)); }
		if (isset($tot_amt) && $tot_amt !== '' && trim($tot_amt) !== '') { $tot_amt = (float)str_replace(',', '', trim($tot_amt)); }
		if (isset($tot_disc) && $tot_disc !== '' && trim($tot_disc) !== '') { $tot_disc = (float)str_replace(',', '', trim($tot_disc)); }
		$tot_disc 		= (empty($tot_disc) || $tot_disc==0) ? 'NULL' : $tot_disc;
		$tot_grand 		= (empty($tot_grand)) ? 'NULL' : $tot_grand;
		//$tot_grand		=round($tot_amt);
		$round_off = number_format((float)$tot_grand-(float)$tot_amt,decimals(),'.','');

		

		$prev_item_ids = array();


		$tot = $this->db->select("count(*) as tot")->where("store_id",$store_id)->where("reference_id",$reference_id)->get("db_hold")->row()->tot;
		if($tot>0){
			$q11=$this->db->query("delete from db_hold where reference_id='$reference_id' and store_id=".$store_id);
			if(!$q11){
				return "failed";
			}
		}
		

		$sales_entry = array(
						'reference_id' 				=> $reference_id,
	    				'store_id' 					=> $store_id,
	    				'sales_date' 				=> $sales_date,
	    				'sales_status' 				=> 'Final',
	    				'customer_id' 				=> $customer_id,
	    				/*Discount*/
	    				'discount_to_all_input' 	=> $discount_input,
	    				'discount_to_all_type' 		=> $discount_type,
	    				'tot_discount_to_all_amt' 	=> $tot_disc,
	    				/*Subtotal & Total */
	    				'subtotal' 					=> $tot_amt,
	    				'round_off' 				=> $round_off,
	    				'grand_total' 				=> $tot_grand,
	    				'pos' 						=> 1,
	    				'sales_note' 				=> $sales_note,
	    			);
		$sales_entry['warehouse_id']=(warehouse_module() && warehouse_count()>1) ? $warehouse_id : get_store_warehouse_id();
		$q3 = $this->db->insert('db_hold', $sales_entry);
		$hold_id = $this->db->insert_id();
		
		//Import post data from form
		for($i=0;$i<$rowcount;$i++){
		
			if(isset($_REQUEST['tr_item_id_'.$i]) && trim($_REQUEST['tr_item_id_'.$i])!=''){
			
				//RECEIVE VALUES FROM FORM (quantity by row index $i; normalize numbers: strip commas)
				$item_id 	=$this->xss_html_filter(trim($_REQUEST['tr_item_id_'.$i]));
				$sales_qty 	= trim($_REQUEST['item_qty_'.$i]);
				$sales_qty 	= ($sales_qty !== '') ? (float)str_replace(',', '', $sales_qty) : 0;
				$price_per_unit = trim($_REQUEST['sales_price_'.$i]);
				$price_per_unit = ($price_per_unit !== '') ? (float)str_replace(',', '', $price_per_unit) : 0;
				$tax_amt = trim($_REQUEST['td_data_'.$i.'_11']);
				$tax_amt = ($tax_amt !== '') ? (float)str_replace(',', '', $tax_amt) : null;
				$tax_type =$this->xss_html_filter(trim($_REQUEST['tr_tax_type_'.$i]));
				$tax_id =$this->xss_html_filter(trim($_REQUEST['tr_tax_id_'.$i]));
				$tax_value = trim($_REQUEST['tr_tax_value_'.$i]);
				$tax_value = ($tax_value !== '') ? (float)str_replace(',', '', $tax_value) : 0;
				$total_cost = trim($_REQUEST['td_data_'.$i.'_4']);
				$total_cost = ($total_cost !== '') ? (float)str_replace(',', '', $total_cost) : null;
				$description =$this->xss_html_filter(trim($_REQUEST['description_'.$i]));
				
				$discount_type =$this->xss_html_filter(trim($_REQUEST['item_discount_type_'.$i]));
				$discount_input =$this->xss_html_filter(trim($_REQUEST['item_discount_input_'.$i]));
				$discount_amt = trim($_REQUEST['item_discount_'.$i]);
				$discount_amt = ($discount_amt !== '') ? (float)str_replace(',', '', $discount_amt) : 0;

				if($tax_type=='Exclusive'){
					$single_unit_total_cost = $price_per_unit + ($tax_value * $price_per_unit / 100);
				}
				else{//Inclusive
					$single_unit_total_cost =$price_per_unit;
				}

				
				if($tax_id=='' || $tax_id==0){$tax_id=null;}
				if($tax_amt=='' || $tax_amt==0){$tax_amt=null;}
				if($total_cost=='' || $total_cost==0){$total_cost=null;}
				
				
				/* ******************************** */
				//Find the qty available or not
				$item_details = get_item_details($item_id);
				$item_name = $item_details->item_name;
				$service_bit = $item_details->service_bit;
				$current_stock_of_item = total_available_qty_items_of_warehouse($warehouse_id,null,$item_id);
				if($current_stock_of_item<$sales_qty && $service_bit==0){
					return $item_name." has only ".$current_stock_of_item." in Stock!!";exit;
				}
				
				$salesitems_entry = array(
							'store_id' 			=> $store_id,
		    				'hold_id' 			=> $hold_id, 
		    				'item_id' 			=> $item_id, 
		    				'description' 		=> $description, 
		    				'sales_qty' 		=> $sales_qty,
		    				'price_per_unit' 	=> $price_per_unit,
		    				'tax_id' 			=> $tax_id,
		    				'tax_amt' 			=> $tax_amt,
		    				'tax_type' 			=> $tax_type,
		    				'discount_type' 	=> $discount_type,
		    				'discount_input' 	=> $discount_input,
		    				'discount_amt' 		=> $discount_amt,
		    				'unit_total_cost' 	=> $single_unit_total_cost,
		    				'total_cost' 		=> $total_cost,
		    			);
				$q4 = $this->db->insert('db_holditems', $salesitems_entry);

				$q11=$this->update_items_quantity($item_id);
				if(!$q11){
					return "failed";
				}

			}
		
		}//for end
		

		//COMMIT RECORD
		$this->db->trans_commit();
		
		$this->session->set_flashdata('success', 'Success!! Sales Created Successfully!');
        return "success";


	}
	
	/**
	 * Get default cash account for Pay All functionality
	 * Ensures the account uses base currency
	 */
	private function get_default_cash_account_for_pay_all() {
		$CI =& get_instance();
		$store_id = get_current_store_id();
		$base_currency_id = get_base_currency()->id;
		
		// First check if user selected an account for this Pay All operation
		$pay_all_account_id = $CI->session->userdata('pay_all_account_id');
		if (!empty($pay_all_account_id)) {
			// Verify the selected account is valid and uses base currency
			$CI->db->select('id, currency_id');
			$CI->db->where('id', $pay_all_account_id);
			$CI->db->where('store_id', $store_id);
			$CI->db->where('currency_id', $base_currency_id);
			$CI->db->where('(delete_bit = 0 OR delete_bit = 1)'); // Include both regular and cash accounts
			$CI->db->where('status', 1); // Only active accounts
			$account = $CI->db->get('ac_accounts')->row();
			
			if ($account) {
				// Clear the temporary session data
				$CI->session->unset_userdata('pay_all_account_id');
				return $account->id;
			}
		}
		
		// Try to get the default account from store settings
		$store_details = get_store_details();
		$default_account_id = $store_details->default_account_id;
		
		if (!empty($default_account_id)) {
			// Check if the default account uses base currency
			$CI->db->select('id, currency_id');
			$CI->db->where('id', $default_account_id);
			$CI->db->where('store_id', $store_id);
			$CI->db->where('(delete_bit = 0 OR delete_bit = 1)'); // Include both regular and cash accounts
			$CI->db->where('status', 1); // Only active accounts
			$account = $CI->db->get('ac_accounts')->row();
			
			if ($account && $account->currency_id == $base_currency_id) {
				return $account->id;
			}
		}
		
		// If no default account or wrong currency, get/create cash account with base currency
		$CI->db->select('id');
		$CI->db->where('store_id', $store_id);
		$CI->db->where('currency_id', $base_currency_id);
		$CI->db->where('account_name', 'Cash Account');
		$CI->db->where('(delete_bit = 0 OR delete_bit = 1)'); // Include both regular and cash accounts
		$CI->db->where('status', 1); // Only active accounts
		$cash_account = $CI->db->get('ac_accounts')->row();
		
		if ($cash_account) {
			return $cash_account->id;
		}
		
		// Create cash account with base currency if it doesn't exist
		$CI->load->helper('cash_account_helper');
		return create_default_cash_account($store_id);
	}

	/**
	 * Get sales item quantity in main unit (for batch restore on sale remove/edit).
	 * When item has alt & main unit, batch is in main unit only - restore only that.
	 */
	private function _pos_sales_item_qty_in_main_unit($item_id, $sales_qty, $sales_qty_main, $unit_type) {
		if ($sales_qty_main !== null && $sales_qty_main > 0) {
			return (float) $sales_qty_main;
		}
		$item = $this->db->select('conversion_factor')->from('db_items')->where('id', $item_id)->get()->row();
		if ($item && $item->conversion_factor > 0 && $unit_type === 'alternate') {
			return round((float)$sales_qty / (float)$item->conversion_factor, 4);
		}
		return (float) $sales_qty;
	}
}
