Provide a way to enter a line total and have the quantity sold automatically calculated.

This commit is contained in:
Steve Ireland
2017-12-31 16:09:09 -05:00
parent 9bf1d66b74
commit 62f34663ae
12 changed files with 128 additions and 53 deletions

View File

@@ -299,6 +299,7 @@ class Config extends Secure_Controller
'suggestions_second_column' => $this->input->post('suggestions_second_column'),
'suggestions_third_column' => $this->input->post('suggestions_third_column'),
'giftcard_number' => $this->input->post('giftcard_number'),
'derive_sale_quantity' => $this->input->post('derive_sale_quantity') != NULL,
'statistics' => $this->input->post('statistics') != NULL,
'custom1_name' => $this->input->post('custom1_name'),
'custom2_name' => $this->input->post('custom2_name'),

View File

@@ -464,10 +464,12 @@ class Sales extends Secure_Controller
$quantity = parse_decimals($this->input->post('quantity'));
$discount = parse_decimals($this->input->post('discount'));
$item_location = $this->input->post('location');
$total = $this->input->post('total') != '' ? $this->input->post('total') : NULL;
error_log('>>>Sales.php total-' . $total);
if($this->form_validation->run() != FALSE)
{
$this->sale_lib->edit_item($item_id, $description, $serialnumber, $quantity, $discount, $price);
$this->sale_lib->edit_item($item_id, $description, $serialnumber, $quantity, $discount, $price, $total);
}
else
{

View File

@@ -88,6 +88,8 @@ $lang["config_default_tax_rate_1"] = "Tax 1 Rate";
$lang["config_default_tax_rate_2"] = "Tax 2 Rate";
$lang["config_default_tax_rate_number"] = "Default Tax Rate must be a number.";
$lang["config_default_tax_rate_required"] = "Default Tax Rate is a required field.";
$lang["config_derive_sale_quantity"] = "Allow Derived Sale Quantity";
$lang["config_derive_sale_quantity_tooltip"] = "If checked then a new item type will provided for items ordered by extended amount";
$lang["config_dinner_table"] = "Table";
$lang["config_dinner_table_duplicate"] = "Table must be unique.";
$lang["config_dinner_table_enable"] = "Enable Dinner Tables";

View File

@@ -4,6 +4,7 @@ $lang["items_add_minus"] = "Inventory to add or subtract.";
$lang["items_allow_alt_desciption"] = "";
$lang["items_allow_alt_description"] = "Allow Alternate Description";
$lang["items_amazon"] = "Amazon";
$lang["items_amount_entry"] = "Amount Entry";
$lang["items_bulk_edit"] = "Bulk Edit";
$lang["items_buy_price_required"] = "Purchase Price is a required field.";
$lang["items_cannot_be_deleted"] = "Could not delete selected Item(s), one or more of the selected Items have sales.";

View File

@@ -807,6 +807,7 @@ class Sale_lib
'discounted_total' => $discounted_total,
'print_option' => $print_option_selected,
'stock_type' => $stock_type,
'item_type' => $item_type,
'tax_category_id' => $item_info->tax_category_id
)
);
@@ -882,12 +883,16 @@ class Sale_lib
return -1;
}
public function edit_item($line, $description, $serialnumber, $quantity, $discount, $price)
public function edit_item($line, $description, $serialnumber, $quantity, $discount, $price, $total=NULL)
{
$items = $this->get_cart();
if(isset($items[$line]))
{
$line = &$items[$line];
if($total != NULL && $total != $line['total'])
{
$quantity = $this->get_quantity_sold($total, $price);
}
$line['description'] = $description;
$line['serialnumber'] = $serialnumber;
$line['quantity'] = $quantity;
@@ -1185,6 +1190,21 @@ class Sale_lib
return $total;
}
/**
* Derive the quantity sold based on the new total entered, returning the quanitity rounded to the
* appropriate decimal positions.
* @param $total
* @param $price
* @return string
*/
public function get_quantity_sold($total, $price)
{
$quantity = bcdiv($total, $price, quantity_decimals());
return $quantity;
}
public function get_extended_amount($quantity, $price, $discount_amount = 0)
{
$extended_amount = bcmul($quantity, $price);

View File

@@ -0,0 +1,4 @@
-- Add new config option to allow derive sale quantity feature
INSERT INTO `ospos_app_config` (`key`, `value`) VALUES
('derive_sale_quantity', '0');

View File

@@ -5,6 +5,7 @@ define('HAS_NO_STOCK', 1);
define('ITEM', 0);
define('ITEM_KIT', 1);
define('ITEM_AMOUNT_ENTRY', 2);
define('PRINT_ALL', 0);
define('PRINT_PRICED', 1);
@@ -492,11 +493,12 @@ class Item extends CI_Model
public function get_search_suggestions($search, $filters = array('is_deleted' => FALSE, 'search_custom' => FALSE), $unique = FALSE, $limit = 25)
{
$suggestions = array();
$non_kit = array(ITEM, ITEM_AMOUNT_ENTRY);
$this->db->select($this->get_search_suggestion_format('item_id, name'));
$this->db->from('items');
$this->db->where('deleted', $filters['is_deleted']);
$this->db->where("item_type = " . ITEM); // standard, exclude kit items since kits will be picked up later
$this->db->where_in('item_type', $non_kit); // standard, exclude kit items since kits will be picked up later
$this->db->like('name', $search);
$this->db->order_by('name', 'asc');
foreach($this->db->get()->result() as $row)
@@ -507,7 +509,7 @@ class Item extends CI_Model
$this->db->select($this->get_search_suggestion_format('item_id, item_number'));
$this->db->from('items');
$this->db->where('deleted', $filters['is_deleted']);
$this->db->where("item_type = " . ITEM); // standard, exclude kit items since kits will be picked up later
$this->db->where_in('item_type', $non_kit); // standard, exclude kit items since kits will be picked up later
$this->db->like('item_number', $search);
$this->db->order_by('item_number', 'asc');
foreach($this->db->get()->result() as $row)
@@ -521,7 +523,7 @@ class Item extends CI_Model
$this->db->select('category');
$this->db->from('items');
$this->db->where('deleted', $filters['is_deleted']);
$this->db->where("item_type = " . ITEM); // standard, exclude kit items since kits will be picked up later
$this->db->where_in('item_type', $non_kit); // standard, exclude kit items since kits will be picked up later
$this->db->distinct();
$this->db->like('category', $search);
$this->db->order_by('category', 'asc');
@@ -536,7 +538,7 @@ class Item extends CI_Model
$this->db->like('company_name', $search);
// restrict to non deleted companies only if is_deleted is FALSE
$this->db->where('deleted', $filters['is_deleted']);
$this->db->where("item_type = " . ITEM); // standard, exclude kit items since kits will be picked up later
$this->db->where_in('item_type', $non_kit); // standard, exclude kit items since kits will be picked up later
$this->db->distinct();
$this->db->order_by('company_name', 'asc');
foreach($this->db->get()->result() as $row)
@@ -548,7 +550,7 @@ class Item extends CI_Model
$this->db->select($this->get_search_suggestion_format('item_id, name, description'));
$this->db->from('items');
$this->db->where('deleted', $filters['is_deleted']);
$this->db->where("item_type = " . ITEM); // standard, exclude kit items since kits will be picked up later
$this->db->where_in('item_type', $non_kit); // standard, exclude kit items since kits will be picked up later
$this->db->like('description', $search);
$this->db->order_by('description', 'asc');
foreach($this->db->get()->result() as $row)
@@ -577,7 +579,7 @@ class Item extends CI_Model
$this->db->or_like('custom10', $search);
$this->db->group_end();
$this->db->where('deleted', $filters['is_deleted']);
$this->db->where("item_type = " . ITEM); // standard, exclude kit items since kits will be picked up later
$this->db->where_in('item_type', $non_kit); // standard, exclude kit items since kits will be picked up later
foreach($this->db->get()->result() as $row)
{
$suggestions[] = array('value' => $row->item_id, 'label' => get_search_suggestion_label($row));
@@ -598,11 +600,12 @@ class Item extends CI_Model
public function get_stock_search_suggestions($search, $filters = array('is_deleted' => FALSE, 'search_custom' => FALSE), $unique = FALSE, $limit = 25)
{
$suggestions = array();
$non_kit = array(ITEM, ITEM_PRICE_BASED);
$this->db->select($this->get_search_suggestion_format('item_id, name'));
$this->db->from('items');
$this->db->where('deleted', $filters['is_deleted']);
$this->db->where("item_type = " . ITEM); // standard, exclude kit items since kits will be picked up later
$this->db->where_in('item_type', $non_kit); // standard, exclude kit items since kits will be picked up later
$this->db->where("stock_type = '0'"); // stocked items only
$this->db->like('name', $search);
$this->db->order_by('name', 'asc');
@@ -614,7 +617,7 @@ class Item extends CI_Model
$this->db->select($this->get_search_suggestion_format('item_id, item_number'));
$this->db->from('items');
$this->db->where('deleted', $filters['is_deleted']);
$this->db->where("item_type = " . ITEM); // standard, exclude kit items since kits will be picked up later
$this->db->where_in('item_type', $non_kit); // standard, exclude kit items since kits will be picked up later
$this->db->where("stock_type = '0'"); // stocked items only
$this->db->like('item_number', $search);
$this->db->order_by('item_number', 'asc');
@@ -629,7 +632,7 @@ class Item extends CI_Model
$this->db->select('category');
$this->db->from('items');
$this->db->where('deleted', $filters['is_deleted']);
$this->db->where("item_type = " . ITEM); // standard, exclude kit items since kits will be picked up later
$this->db->where_in('item_type', $non_kit); // standard, exclude kit items since kits will be picked up later
$this->db->where("stock_type = '0'"); // stocked items only
$this->db->distinct();
$this->db->like('category', $search);
@@ -656,7 +659,7 @@ class Item extends CI_Model
$this->db->select($this->get_search_suggestion_format('item_id, name, description'));
$this->db->from('items');
$this->db->where('deleted', $filters['is_deleted']);
$this->db->where("item_type = " . ITEM); // standard, exclude kit items since kits will be picked up later
$this->db->where_in('item_type', $non_kit); // standard, exclude kit items since kits will be picked up later
$this->db->where("stock_type = '0'"); // stocked items only
$this->db->like('description', $search);
$this->db->order_by('description', 'asc');
@@ -685,7 +688,7 @@ class Item extends CI_Model
$this->db->or_like('custom9', $search);
$this->db->or_like('custom10', $search);
$this->db->group_end();
$this->db->where("item_type = " . ITEM); // standard, exclude kit items since kits will be picked up later
$this->db->where_in('item_type', $non_kit); // standard, exclude kit items since kits will be picked up later
$this->db->where("stock_type = '0'"); // stocked items only
$this->db->where('deleted', $filters['is_deleted']);
foreach($this->db->get()->result() as $row)
@@ -707,11 +710,12 @@ class Item extends CI_Model
public function get_kit_search_suggestions($search, $filters = array('is_deleted' => FALSE, 'search_custom' => FALSE), $unique = FALSE, $limit = 25)
{
$suggestions = array();
$non_kit = array(ITEM, ITEM_PRICE_BASED);
$this->db->select('item_id, name');
$this->db->from('items');
$this->db->where('deleted', $filters['is_deleted']);
$this->db->where("item_type = " . ITEM_KIT); // standard, exclude kit items since kits will be picked up later
$this->db->where_in('item_type', $non_kit); // standard, exclude kit items since kits will be picked up later
$this->db->like('name', $search);
$this->db->order_by('name', 'asc');
foreach($this->db->get()->result() as $row)

View File

@@ -172,7 +172,22 @@
</div>
</div>
<div class="form-group form-group-sm">
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('config_derive_sale_quantity'), 'derive_sale_quantity', array('class' => 'control-label col-xs-2')); ?>
<div class='col-xs-1'>
<?php echo form_checkbox(array(
'name' => 'derive_sale_quantity',
'id' => 'derive_sale_quantity',
'value' => 'derive_sale_quantity',
'checked' => $this->config->item('derive_sale_quantity'))); ?>
&nbsp
<label class="control-label">
<span class="glyphicon glyphicon-info-sign" data-toggle="tooltip" data-placement="right" title="<?php echo $this->lang->line('config_derive_sale_quantity_tooltip'); ?>"></span>
</label>
</div>
</div>
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('config_statistics'), 'statistics', array('class' => 'control-label col-xs-2')); ?>
<div class='col-xs-1'>
<?php echo form_checkbox(array(

View File

@@ -92,11 +92,27 @@
'checked'=>$item_info->item_type == ITEM_KIT)
); ?> <?php echo $this->lang->line('items_kit'); ?>
</label>
<?php
if($this->config->item('derive_sale_quantity') == '1') {
?>
<label class="radio-inline">
<?php echo form_radio(array(
'name' => 'item_type',
'type' => 'radio',
'id' => 'item_type',
'value' => 2,
'checked' => $item_info->item_type == ITEM_AMOUNT_ENTRY)
); ?><?php echo $this->lang->line('items_amount_entry'); ?>
</label>
<?php
}
?>
</div>
</div>
<?php endif; ?>
<div class="form-group form-group-sm">
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('items_supplier'), 'supplier', array('class'=>'control-label col-xs-3')); ?>
<div class='col-xs-8'>
<?php echo form_dropdown('supplier_id', $suppliers, $selected_supplier, array('class'=>'form-control')); ?>
@@ -166,7 +182,7 @@
</div>
</div>
<div class="form-group form-group-sm">
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('items_tax_2'), 'tax_percent_2', array('class'=>'control-label col-xs-3')); ?>
<div class='col-xs-4'>
<?php echo form_input(array(
@@ -190,15 +206,15 @@
</div>
<?php if($customer_sales_tax_enabled) { ?>
<div class="form-group form-group-sm">
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('taxes_tax_category'), 'tax_category', array('class'=>'control-label col-xs-3')); ?>
<div class='col-xs-8'>
<div class='col-xs-8'>
<?php echo form_dropdown('tax_category_id', $tax_categories, $selected_tax_category, array('class'=>'form-control')); ?>
</div>
</div>
</div>
</div>
<?php } ?>
<?php
<?php
foreach($stock_locations as $key=>$location_detail)
{
?>

View File

@@ -175,10 +175,18 @@ if(isset($success))
</td>
<td><?php echo form_input(array('name'=>'discount', 'class'=>'form-control input-sm', 'value'=>to_decimals($item['discount'], 0), 'tabindex'=>++$tabindex));?></td>
<td><?php echo to_currency($item['price']*$item['quantity']-$item['price']*$item['quantity']*$item['discount']/100); ?></td>
<td>
<?php
if($item['item_type'] == 2) {
echo form_input(array('name'=>'total', 'class'=>'form-control input-sm', 'value'=>to_currency_no_money($item['total']), 'tabindex'=>++$tabindex));
} else {
echo to_currency($item['total']);
}
?>
</td>
<td><a href="javascript:document.getElementById('<?php echo 'cart_'.$line ?>').submit();" title=<?php echo $this->lang->line('sales_update')?> ><span class="glyphicon glyphicon-refresh"></span></a></td>
</tr>
<tr>
</tr>
<tr>
<?php
if($item['allow_alt_description']==1)
{
@@ -413,16 +421,16 @@ if(isset($success))
</tr>
</table>
<?php echo form_close(); ?>
<?php
<?php
// Only show this part if the payment cover the total and in sale or return mode
if($pos_mode == '1')
{
?>
<div class='btn btn-sm btn-success pull-right' id='finish_sale_button' tabindex='<?php echo ++$tabindex; ?>'><span class="glyphicon glyphicon-ok">&nbsp</span><?php echo $this->lang->line('sales_complete_sale'); ?></div>
<div class='btn btn-sm btn-success pull-right' id='finish_sale_button' tabindex='<?php echo ++$tabindex; ?>'><span class="glyphicon glyphicon-ok">&nbsp</span><?php echo $this->lang->line('sales_complete_sale'); ?></div>
<?php
}
?>
<?php
?>
<?php
}
else
{
@@ -539,20 +547,20 @@ if(isset($success))
<?php
}
?>
<?php
if($mode == "sale_work_order")
{
?>
<div class="col-xs-6">
<label for="price_work_orders" class="control-label checkbox">
<?php echo form_checkbox(array('name'=>'price_work_orders', 'id'=>'price_work_orders', 'value'=>1, 'checked'=>$price_work_orders)); ?>
<?php echo $this->lang->line('sales_include_prices');?>
</label>
</div>
<?php
}
?>
</div>
<?php
if($mode == "sale_work_order")
{
?>
<div class="col-xs-6">
<label for="price_work_orders" class="control-label checkbox">
<?php echo form_checkbox(array('name'=>'price_work_orders', 'id'=>'price_work_orders', 'value'=>1, 'checked'=>$price_work_orders)); ?>
<?php echo $this->lang->line('sales_include_prices');?>
</label>
</div>
<?php
}
?>
</div>
</div>
<?php
if(($mode == "sale") && $this->config->item('invoice_enable') == TRUE)
@@ -597,7 +605,7 @@ $(document).ready(function()
source: '<?php echo site_url($controller_name."/item_search"); ?>',
minChars: 0,
autoFocus: false,
delay: 500,
delay: 500,
select: function (a, ui) {
$(this).val(ui.item.value);
$("#add_item_form").submit();
@@ -696,10 +704,10 @@ $(document).ready(function()
$.post('<?php echo site_url($controller_name."/set_print_after_sale");?>', {sales_print_after_sale: $(this).is(":checked")});
});
$("#price_work_orders").change(function()
{
$.post('<?php echo site_url($controller_name."/set_price_work_orders");?>', {price_work_orders: $(this).is(":checked")});
});
$("#price_work_orders").change(function()
{
$.post('<?php echo site_url($controller_name."/set_price_work_orders");?>', {price_work_orders: $(this).is(":checked")});
});
$('#email_receipt').change(function()
{
@@ -792,7 +800,7 @@ $(document).ready(function()
}
}
$('[name="price"],[name="quantity"],[name="discount"],[name="description"],[name="serialnumber"]').change(function() {
$('[name="price"],[name="quantity"],[name="discount"],[name="description"],[name="serialnumber"],[name="total"]').change(function() {
$(this).parents("tr").prevAll("form:first").submit()
});

View File

@@ -39,7 +39,7 @@ INSERT INTO `ospos_app_config` (`key`, `value`) VALUES
('barcode_second_row', 'item_code'),
('barcode_third_row', 'unit_price'),
('barcode_num_in_row', '2'),
('barcode_page_width', '100'),
('barcode_page_width', '100'),
('barcode_page_cellspacing', '20'),
('barcode_generate_if_empty', '0'),
('receipt_show_company_name', '1'),
@@ -118,7 +118,8 @@ INSERT INTO `ospos_app_config` (`key`, `value`) VALUES
('suggestions_first_column', 'name'),
('suggestions_second_column', ''),
('suggestions_third_column', ''),
('allow_duplicate_barcodes', '0');
('allow_duplicate_barcodes', '0'),
('derive_sale_quantity', '0');
-- --------------------------------------------------------
@@ -997,7 +998,7 @@ ALTER TABLE `ospos_item_quantities`
--
ALTER TABLE `ospos_suppliers`
ADD CONSTRAINT `ospos_suppliers_ibfk_1` FOREIGN KEY (`person_id`) REFERENCES `ospos_people` (`person_id`);
--
-- Constraints for table `ospos_giftcards`
--

View File

@@ -118,7 +118,8 @@ INSERT INTO `ospos_app_config` (`key`, `value`) VALUES
('suggestions_first_column', 'name'),
('suggestions_second_column', ''),
('suggestions_third_column', ''),
('allow_duplicate_barcodes', '0');
('allow_duplicate_barcodes', '0'),
('derive_sale_quantity', '0');
-- --------------------------------------------------------