Files
opensourcepos/application/models/sale.php
jekkos-t520 babddd524c Refactor variable substitution for receiving invoice numbers
Use localStorage to store selected printer
Add printer selection for invoice template
Print after sale checkbox is now present in receivings and sales screen
Remove print after sale options from receipt_config
Add default translations to receivings_lang.csv
Fix some bugs preventing to print and email at the same time
2015-02-19 18:10:31 +01:00

302 lines
10 KiB
PHP

<?php
class Sale extends CI_Model
{
public function get_info($sale_id)
{
$this->db->from('sales');
$this->db->join('people', 'people.person_id = sales.customer_id', 'LEFT');
$this->db->where('sale_id',$sale_id);
return $this->db->get();
}
function get_invoice_count()
{
$this->db->from('sales');
$this->db->where('invoice_number is not null');
return $this->db->count_all_results();
}
function get_sale_by_invoice_number($invoice_number)
{
$this->db->from('sales');
$this->db->where('invoice_number', $invoice_number);
return $this->db->get();
}
function get_invoice_number_for_year($year='', $start_from = 0)
{
$year = $year == '' ? date('Y') : $year;
$this->db->select("COUNT( 1 ) AS invoice_number_year", FALSE);
$this->db->from('sales');
$this->db->where("DATE_FORMAT(sale_time, '%Y' ) = ", $year, FALSE);
$this->db->where("invoice_number IS NOT ", "NULL", FALSE);
$result = $this->db->get()->row_array();
return ($start_from + $result[ 'invoice_number_year' ] + 1);
}
function exists($sale_id)
{
$this->db->from('sales');
$this->db->where('sale_id',$sale_id);
$query = $this->db->get();
return ($query->num_rows()==1);
}
function update($sale_data, $sale_id)
{
$this->db->where('sale_id', $sale_id);
$success = $this->db->update('sales',$sale_data);
return $success;
}
function save ($items,$customer_id,$employee_id,$comment,$invoice_number,$payments,$sale_id=false)
{
if(count($items)==0)
return -1;
//Alain Multiple payments
//Build payment types string
$payment_types='';
foreach($payments as $payment_id=>$payment)
{
$payment_types=$payment_types.$payment['payment_type'].': '.to_currency($payment['payment_amount']).'<br />';
}
$sales_data = array(
'sale_time' => date('Y-m-d H:i:s'),
'customer_id'=> $this->Customer->exists($customer_id) ? $customer_id : null,
'employee_id'=>$employee_id,
'payment_type'=>$payment_types,
'comment'=>$comment,
'invoice_number'=>$invoice_number
);
//Run these queries as a transaction, we want to make sure we do all or nothing
$this->db->trans_start();
$this->db->insert('sales',$sales_data);
$sale_id = $this->db->insert_id();
foreach($payments as $payment_id=>$payment)
{
if ( substr( $payment['payment_type'], 0, strlen( $this->lang->line('sales_giftcard') ) ) == $this->lang->line('sales_giftcard') )
{
/* We have a gift card and we have to deduct the used value from the total value of the card. */
$splitpayment = explode( ':', $payment['payment_type'] );
$cur_giftcard_value = $this->Giftcard->get_giftcard_value( $splitpayment[1] );
$this->Giftcard->update_giftcard_value( $splitpayment[1], $cur_giftcard_value - $payment['payment_amount'] );
}
$sales_payments_data = array
(
'sale_id'=>$sale_id,
'payment_type'=>$payment['payment_type'],
'payment_amount'=>$payment['payment_amount']
);
$this->db->insert('sales_payments',$sales_payments_data);
}
foreach($items as $line=>$item)
{
$cur_item_info = $this->Item->get_info($item['item_id']);
$sales_items_data = array
(
'sale_id'=>$sale_id,
'item_id'=>$item['item_id'],
'line'=>$item['line'],
'description'=>$item['description'],
'serialnumber'=>$item['serialnumber'],
'quantity_purchased'=>$item['quantity'],
'discount_percent'=>$item['discount'],
'item_cost_price' => $cur_item_info->cost_price,
'item_unit_price'=>$item['price'],
'item_location'=>$item['item_location']
);
$this->db->insert('sales_items',$sales_items_data);
//Update stock quantity
$item_quantity = $this->Item_quantities->get_item_quantity($item['item_id'], $item['item_location']);
$this->Item_quantities->save(array('quantity'=>$item_quantity->quantity - $item['quantity'],
'item_id'=>$item['item_id'],
'location_id'=>$item['item_location']), $item['item_id'], $item['item_location']);
//Ramel Inventory Tracking
//Inventory Count Details
$qty_buy = -$item['quantity'];
$sale_remarks ='POS '.$sale_id;
$inv_data = array
(
'trans_date'=>date('Y-m-d H:i:s'),
'trans_items'=>$item['item_id'],
'trans_user'=>$employee_id,
'trans_location'=>$item['item_location'],
'trans_comment'=>$sale_remarks,
'trans_inventory'=>$qty_buy
);
$this->Inventory->insert($inv_data);
//------------------------------------Ramel
$customer = $this->Customer->get_info($customer_id);
if ($customer_id == -1 or $customer->taxable)
{
foreach($this->Item_taxes->get_info($item['item_id']) as $row)
{
$this->db->insert('sales_items_taxes', array(
'sale_id' =>$sale_id,
'item_id' =>$item['item_id'],
'line' =>$item['line'],
'name' =>$row['name'],
'percent' =>$row['percent']
));
}
}
}
$this->db->trans_complete();
if ($this->db->trans_status() === FALSE)
{
return -1;
}
return $sale_id;
}
function delete_list($sale_ids, $employee_id,$update_inventory=TRUE)
{
$result = TRUE;
foreach($sale_ids as $sale_id) {
$result &= $this->delete($sale_id, $employee_id, $update_inventory);
}
return $result;
}
function delete($sale_id,$employee_id,$update_inventory=TRUE)
{
// start a transaction to assure data integrity
$this->db->trans_start();
// first delete all payments
$this->db->delete('sales_payments', array('sale_id' => $sale_id));
// then delete all taxes on items
$this->db->delete('sales_items_taxes', array('sale_id' => $sale_id));
if ($update_inventory) {
// defect, not all item deletions will be undone??
// get array with all the items involved in the sale to update the inventory tracking
$items = $this->get_sale_items($sale_id)->result_array();
foreach($items as $item) {
// create query to update inventory tracking
$inv_data = array
(
'trans_date'=>date('Y-m-d H:i:s'),
'trans_items'=>$item['item_id'],
'trans_user'=>$employee_id,
'trans_comment'=>'Deleting sale ' . $sale_id,
'trans_location'=>$item['item_location'],
'trans_inventory'=>$item['quantity_purchased']
);
// update inventory
$this->Inventory->insert($inv_data);
// update quantities
$this->Item_quantities->change_quantity($item['item_id'],
$item['item_location'],
$item['quantity_purchased']);
}
}
// delete all items
$this->db->delete('sales_items', array('sale_id' => $sale_id));
// delete sale itself
$this->db->delete('sales', array('sale_id' => $sale_id));
// execute transaction
$this->db->trans_complete();
return $this->db->trans_status();
}
function get_sale_items($sale_id)
{
$this->db->from('sales_items');
$this->db->where('sale_id',$sale_id);
return $this->db->get();
}
function get_sale_payments($sale_id)
{
$this->db->from('sales_payments');
$this->db->where('sale_id',$sale_id);
return $this->db->get();
}
function get_customer($sale_id)
{
$this->db->from('sales');
$this->db->where('sale_id',$sale_id);
return $this->Customer->get_info($this->db->get()->row()->customer_id);
}
function invoice_number_exists($invoice_number,$sale_id='')
{
$this->db->from('sales');
$this->db->where('invoice_number', $invoice_number);
if (!empty($sale_id))
{
$this->db->where('sale_id !=', $sale_id);
}
$query=$this->db->get();
return ($query->num_rows()==1);
}
//We create a temp table that allows us to do easy report/sales queries
public function create_sales_items_temp_table()
{
$this->db->query("DROP TABLE IF EXISTS phppos_sales_items_temp");
$this->db->query("CREATE TEMPORARY TABLE ".$this->db->dbprefix('sales_items_temp')."
(SELECT date(sale_time) as sale_date, sale_time, ".$this->db->dbprefix('sales_items').".sale_id, comment,payments.payment_type, customer_id, employee_id,
".$this->db->dbprefix('items').".item_id, supplier_id, quantity_purchased, item_cost_price, item_unit_price, SUM(percent) as item_tax_percent,
discount_percent, (item_unit_price*quantity_purchased-item_unit_price*quantity_purchased*discount_percent/100) as subtotal,
".$this->db->dbprefix('sales_items').".line as line, serialnumber, ".$this->db->dbprefix('sales_items').".description as description,
(item_unit_price*quantity_purchased-item_unit_price*quantity_purchased*discount_percent/100)*(1+(SUM(percent)/100)) as total,
(item_unit_price*quantity_purchased-item_unit_price*quantity_purchased*discount_percent/100)*(SUM(percent)/100) as tax,
(item_unit_price*quantity_purchased-item_unit_price*quantity_purchased*discount_percent/100) - (item_cost_price*quantity_purchased) as profit
FROM ".$this->db->dbprefix('sales_items')."
INNER JOIN ".$this->db->dbprefix('sales')." ON ".$this->db->dbprefix('sales_items').'.sale_id='.$this->db->dbprefix('sales').'.sale_id'."
INNER JOIN ".$this->db->dbprefix('items')." ON ".$this->db->dbprefix('sales_items').'.item_id='.$this->db->dbprefix('items').'.item_id'."
INNER JOIN (SELECT sale_id, SUM(payment_amount) AS sale_payment_amount,
GROUP_CONCAT(payment_type SEPARATOR ', ') AS payment_type FROM " .$this->db->dbprefix('sales_payments') . " GROUP BY sale_id) AS payments
ON " . $this->db->dbprefix('sales_items') . '.sale_id'. "=" . "payments.sale_id
LEFT OUTER JOIN ".$this->db->dbprefix('suppliers')." ON ".$this->db->dbprefix('items').'.supplier_id='.$this->db->dbprefix('suppliers').'.person_id'."
LEFT OUTER JOIN ".$this->db->dbprefix('sales_items_taxes')." ON "
.$this->db->dbprefix('sales_items').'.sale_id='.$this->db->dbprefix('sales_items_taxes').'.sale_id'." and "
.$this->db->dbprefix('sales_items').'.item_id='.$this->db->dbprefix('sales_items_taxes').'.item_id'." and "
.$this->db->dbprefix('sales_items').'.line='.$this->db->dbprefix('sales_items_taxes').'.line'."
GROUP BY sale_id, item_id, line)");
//Update null item_tax_percents to be 0 instead of null
$this->db->where('item_tax_percent IS NULL');
$this->db->update('sales_items_temp', array('item_tax_percent' => 0));
//Update null tax to be 0 instead of null
$this->db->where('tax IS NULL');
$this->db->update('sales_items_temp', array('tax' => 0));
//Update null subtotals to be equal to the total as these don't have tax
$this->db->query('UPDATE '.$this->db->dbprefix('sales_items_temp'). ' SET total=subtotal WHERE total IS NULL');
}
public function get_giftcard_value( $giftcardNumber )
{
if ( !$this->Giftcard->exists( $this->Giftcard->get_giftcard_id($giftcardNumber)))
return 0;
$this->db->from('giftcards');
$this->db->where('giftcard_number',$giftcardNumber);
return $this->db->get()->row()->value;
}
}
?>