0
 public function add($quote_id = null)
{
    $this->sma->checkPermissions();
    $sale_id = $this->input->get('sale_id') ? $this->input->get('sale_id') : NULL;

    $this->form_validation->set_message('is_natural_no_zero', lang("no_zero_required"));
    $this->form_validation->set_rules('customer', lang("customer"), 'required');
    $this->form_validation->set_rules('biller', lang("biller"), 'required');
    $this->form_validation->set_rules('sale_status', lang("sale_status"), 'required');
    $this->form_validation->set_rules('payment_status', lang("payment_status"), 'required');

    if ($this->form_validation->run() == true) {

        $reference = $this->input->post('reference_no') ? $this->input->post('reference_no') : $this->site->getReference('so');
        if ($this->Owner || $this->Admin) {
            $date = $this->sma->fld(trim($this->input->post('date')));
        } else {
            $date = date('Y-m-d H:i:s');
        }
        $warehouse_id = $this->input->post('warehouse');
        $customer_id = $this->input->post('customer');
        $biller_id = $this->input->post('biller');
        $total_items = $this->input->post('total_items');
        $sale_status = $this->input->post('sale_status');
        $payment_status = $this->input->post('payment_status');
        $payment_term = $this->input->post('payment_term');
        $due_date = $payment_term ? date('Y-m-d', strtotime('+' . $payment_term . ' days', strtotime($date))) : null;
        $shipping = $this->input->post('shipping') ? $this->input->post('shipping') : 0;
        $customer_details = $this->site->getCompanyByID($customer_id);
        $customer = $customer_details->company != '-' ? $customer_details->company : $customer_details->name;
        $biller_details = $this->site->getCompanyByID($biller_id);
        $biller = $biller_details->company != '-' ? $biller_details->company : $biller_details->name;
        $note = $this->sma->clear_tags($this->input->post('note'));
        $staff_note = $this->sma->clear_tags($this->input->post('staff_note'));
        $quote_id = $this->input->post('quote_id') ? $this->input->post('quote_id') : null;

        $total = 0;
        $product_tax = 0;
        $order_tax = 0;
        $product_discount = 0;
        $order_discount = 0;
        $percentage = '%';
        $digital = FALSE;
        $i = isset($_POST['product_code']) ? sizeof($_POST['product_code']) : 0;
        for ($r = 0; $r < $i; $r++) {
            $item_id = $_POST['product_id'][$r];
            $item_type = $_POST['product_type'][$r];
            $item_code = $_POST['product_code'][$r];
            $item_name = $_POST['product_name'][$r];
            $item_option = isset($_POST['product_option'][$r]) && $_POST['product_option'][$r] != 'false' && $_POST['product_option'][$r] != 'null' ? $_POST['product_option'][$r] : null;
            $real_unit_price = $this->sma->formatDecimal($_POST['real_unit_price'][$r]);
            $unit_price = $this->sma->formatDecimal($_POST['unit_price'][$r]);
            $item_unit_quantity = $_POST['quantity'][$r];
            $item_serial = isset($_POST['serial'][$r]) ? $_POST['serial'][$r] : '';
            $item_tax_rate = isset($_POST['product_tax'][$r]) ? $_POST['product_tax'][$r] : null;
            $item_discount = isset($_POST['product_discount'][$r]) ? $_POST['product_discount'][$r] : null;
            $item_unit = $_POST['product_unit'][$r];
            $item_quantity = $_POST['product_base_quantity'][$r];

            if (isset($item_code) && isset($real_unit_price) && isset($unit_price) && isset($item_quantity)) {
                $product_details = $item_type != 'manual' ? $this->sales_model->getProductByCode($item_code) : null;
                // $unit_price = $real_unit_price;
                $pr_discount = 0;
                if ($item_type == 'digital') {
                    $digital = TRUE;
                }

                if (isset($item_discount)) {
                    $discount = $item_discount;
                    $dpos = strpos($discount, $percentage);
                    if ($dpos !== false) {
                        $pds = explode("%", $discount);
                        $pr_discount = $this->sma->formatDecimal(((($this->sma->formatDecimal($unit_price)) * (Float) ($pds[0])) / 100), 4);
                    } else {
                        $pr_discount = $this->sma->formatDecimal($discount);
                    }
                }

                $unit_price = $this->sma->formatDecimal($unit_price - $pr_discount);
                $item_net_price = $unit_price;
                $pr_item_discount = $this->sma->formatDecimal($pr_discount * $item_unit_quantity);
                $product_discount += $pr_item_discount;
                $pr_tax = 0;
                $pr_item_tax = 0;
                $item_tax = 0;
                $tax = "";

                if (isset($item_tax_rate) && $item_tax_rate != 0) {
                    $pr_tax = $item_tax_rate;
                    $tax_details = $this->site->getTaxRateByID($pr_tax);
                    if ($tax_details->type == 1 && $tax_details->rate != 0) {

                        if ($product_details && $product_details->tax_method == 1) {
                            $item_tax = $this->sma->formatDecimal((($unit_price) * $tax_details->rate) / 100, 4);
                            $tax = $tax_details->rate . "%";
                        } else {
                            $item_tax = $this->sma->formatDecimal((($unit_price) * $tax_details->rate) / (100 + $tax_details->rate), 4);
                            $tax = $tax_details->rate . "%";
                            $item_net_price = $unit_price - $item_tax;
                        }

                    } elseif ($tax_details->type == 2) {

                        if ($product_details && $product_details->tax_method == 1) {
                            $item_tax = $this->sma->formatDecimal((($unit_price) * $tax_details->rate) / 100, 4);
                            $tax = $tax_details->rate . "%";
                        } else {
                            $item_tax = $this->sma->formatDecimal((($unit_price) * $tax_details->rate) / (100 + $tax_details->rate), 4);
                            $tax = $tax_details->rate . "%";
                            $item_net_price = $unit_price - $item_tax;
                        }

                        $item_tax = $this->sma->formatDecimal($tax_details->rate);
                        $tax = $tax_details->rate;

                    }
                    $pr_item_tax = $this->sma->formatDecimal($item_tax * $item_unit_quantity, 4);

                }

                $product_tax += $pr_item_tax;
                $subtotal = (($item_net_price * $item_unit_quantity) + $pr_item_tax);
                $unit = $this->site->getUnitByID($item_unit);

                $products[] = array(
                    'product_id' => $item_id,
                    'product_code' => $item_code,
                    'product_name' => $item_name,
                    'product_type' => $item_type,
                    'option_id' => $item_option,
                    'net_unit_price' => $item_net_price,
                    'unit_price' => $this->sma->formatDecimal($item_net_price + $item_tax),
                    'quantity' => $item_quantity,
                    'product_unit_id' => $item_unit,
                    'product_unit_code' => $unit ? $unit->code : NULL,
                    'unit_quantity' => $item_unit_quantity,
                    'warehouse_id' => $warehouse_id,
                    'item_tax' => $pr_item_tax,
                    'tax_rate_id' => $pr_tax,
                    'tax' => $tax,
                    'discount' => $item_discount,
                    'item_discount' => $pr_item_discount,
                    'subtotal' => $this->sma->formatDecimal($subtotal),
                    'serial_no' => $item_serial,
                    'real_unit_price' => $real_unit_price,
                );

                $total += $this->sma->formatDecimal(($item_net_price * $item_unit_quantity), 4);
            }
        }
        if (empty($products)) {
            $this->form_validation->set_rules('product', lang("order_items"), 'required');
        } else {
            krsort($products);
        }

        if ($this->input->post('order_discount')) {
            $order_discount_id = $this->input->post('order_discount');
            $opos = strpos($order_discount_id, $percentage);
            if ($opos !== false) {
                $ods = explode("%", $order_discount_id);
                $order_discount = $this->sma->formatDecimal(((($total + $product_tax) * (Float) ($ods[0])) / 100), 4);
            } else {
                $order_discount = $this->sma->formatDecimal($order_discount_id);
            }
        } else {
            $order_discount_id = null;
        }
        $total_discount = $this->sma->formatDecimal($order_discount + $product_discount);

        if ($this->Settings->tax2) {
            $order_tax_id = $this->input->post('order_tax');
            if ($order_tax_details = $this->site->getTaxRateByID($order_tax_id)) {
                if ($order_tax_details->type == 2) {
                    $order_tax = $this->sma->formatDecimal($order_tax_details->rate);
                } elseif ($order_tax_details->type == 1) {
                    $order_tax = $this->sma->formatDecimal(((($total + $product_tax - $order_discount) * $order_tax_details->rate) / 100), 4);
                }
            }
        } else {
            $order_tax_id = null;
        }

        $total_tax = $this->sma->formatDecimal(($product_tax + $order_tax), 4); 
        $grand_total = $this->sma->formatDecimal(($total + $total_tax + $this->sma->formatDecimal($shipping) - $order_discount), 4);
        $data = array('date' => $date,
            'reference_no' => $reference,
            'customer_id' => $customer_id,
            'customer' => $customer,
            'biller_id' => $biller_id,
            'biller' => $biller,
            'warehouse_id' => $warehouse_id,
            'note' => $note,
            'staff_note' => $staff_note,
            'total' => $total,
            'product_discount' => $product_discount,
            'order_discount_id' => $order_discount_id,
            'order_discount' => $order_discount,
            'total_discount' => $total_discount,
            'product_tax' => $product_tax,
            'order_tax_id' => $order_tax_id,
            'order_tax' => $order_tax,
            'total_tax' => $total_tax,
            'shipping' => $this->sma->formatDecimal($shipping),
            'grand_total' => $grand_total,
            'total_items' => $total_items,
            'sale_status' => $sale_status,
            'payment_status' => $payment_status,
            'payment_term' => $payment_term,
            'due_date' => $due_date,
            'paid' => 0,
            'created_by' => $this->session->userdata('user_id'),
        );

        if ($payment_status == 'partial' || $payment_status == 'paid') {
            if ($this->input->post('paid_by') == 'deposit') {
                if ( ! $this->site->check_customer_deposit($customer_id, $this->input->post('amount-paid'))) {
                    $this->session->set_flashdata('error', lang("amount_greater_than_deposit"));
                    redirect($_SERVER["HTTP_REFERER"]);
                }
            }
            if ($this->input->post('paid_by') == 'gift_card') {
                $gc = $this->site->getGiftCardByNO($this->input->post('gift_card_no'));
                $amount_paying = $grand_total >= $gc->balance ? $gc->balance : $grand_total;
                $gc_balance = $gc->balance - $amount_paying;
                $payment = array(
                    'date' => $date,
                    'reference_no' => $this->input->post('payment_reference_no'),
                    'amount' => $this->sma->formatDecimal($amount_paying),
                    'paid_by' => $this->input->post('paid_by'),
                    'cheque_no' => $this->input->post('cheque_no'),
                    'cc_no' => $this->input->post('gift_card_no'),
                    'cc_holder' => $this->input->post('pcc_holder'),
                    'cc_month' => $this->input->post('pcc_month'),
                    'cc_year' => $this->input->post('pcc_year'),
                    'cc_type' => $this->input->post('pcc_type'),
                    'created_by' => $this->session->userdata('user_id'),
                    'note' => $this->input->post('payment_note'),
                    'type' => 'received',
                    'gc_balance' => $gc_balance,
                );
            } else {
                $payment = array(
                    'date' => $date,
                    'reference_no' => $this->input->post('payment_reference_no'),
                    'amount' => $this->sma->formatDecimal($this->input->post('amount-paid')),
                    'paid_by' => $this->input->post('paid_by'),
                    'cheque_no' => $this->input->post('cheque_no'),
                    'cc_no' => $this->input->post('pcc_no'),
                    'cc_holder' => $this->input->post('pcc_holder'),
                    'cc_month' => $this->input->post('pcc_month'),
                    'cc_year' => $this->input->post('pcc_year'),
                    'cc_type' => $this->input->post('pcc_type'),
                    'created_by' => $this->session->userdata('user_id'),
                    'note' => $this->input->post('payment_note'),
                    'type' => 'received',
                );
            }
        } else {
            $payment = array();
        }

        if ($_FILES['document']['size'] > 0) {
            $this->load->library('upload');
            $config['upload_path'] = $this->digital_upload_path;
            $config['allowed_types'] = $this->digital_file_types;
            $config['max_size'] = $this->allowed_file_size;
            $config['overwrite'] = false;
            $config['encrypt_name'] = true;
            $this->upload->initialize($config);
            if (!$this->upload->do_upload('document')) {
                $error = $this->upload->display_errors();
                $this->session->set_flashdata('error', $error);
                redirect($_SERVER["HTTP_REFERER"]);
            }
            $photo = $this->upload->file_name;
            $data['attachment'] = $photo;
        }

        // $this->sma->print_arrays($data, $products, $payment);
    }

    if ($this->form_validation->run() == true && $this->sales_model->addSale($data, $products, $payment)) {
        $this->session->set_userdata('remove_slls', 1);
        if ($quote_id) {
            $this->db->update('quotes', array('status' => 'completed'), array('id' => $quote_id));
        }
        $this->session->set_flashdata('message', lang("sale_added"));
        redirect("sales");
    } else {

        if ($quote_id || $sale_id) {
            if ($quote_id) {
                $this->data['quote'] = $this->sales_model->getQuoteByID($quote_id);
                $items = $this->sales_model->getAllQuoteItems($quote_id);
            } elseif ($sale_id) {
                $this->data['quote'] = $this->sales_model->getInvoiceByID($sale_id);
                $items = $this->sales_model->getAllInvoiceItems($sale_id);
            }
            krsort($items);
            $c = rand(100000, 9999999);
            foreach ($items as $item) {
                $row = $this->site->getProductByID($item->product_id);
                if (!$row) {
                    $row = json_decode('{}');
                    $row->tax_method = 0;
                } else {
                    unset($row->cost, $row->details, $row->product_details, $row->image, $row->barcode_symbology, $row->cf1, $row->cf2, $row->cf3, $row->cf4, $row->cf5, $row->cf6, $row->supplier1price, $row->supplier2price, $row->cfsupplier3price, $row->supplier4price, $row->supplier5price, $row->supplier1, $row->supplier2, $row->supplier3, $row->supplier4, $row->supplier5, $row->supplier1_part_no, $row->supplier2_part_no, $row->supplier3_part_no, $row->supplier4_part_no, $row->supplier5_part_no);
                }
                $row->quantity = 0;
                $pis = $this->site->getPurchasedItems($item->product_id, $item->warehouse_id, $item->option_id);
                if ($pis) {
                    foreach ($pis as $pi) {
                        $row->quantity += $pi->quantity_balance;
                    }
                }
                $row->id = $item->product_id;
                $row->code = $item->product_code;
                $row->name = $item->product_name;
                $row->type = $item->product_type;
                $row->qty = $item->quantity;
                $row->base_quantity = $item->quantity;
                $row->base_unit = $row->unit ? $row->unit : $item->product_unit_id;
                $row->base_unit_price = $row->price ? $row->price : $item->unit_price;
                $row->unit = $item->product_unit_id;
                $row->qty = $item->unit_quantity;
                $row->discount = $item->discount ? $item->discount : '0';
                $row->price = $this->sma->formatDecimal($item->net_unit_price + $this->sma->formatDecimal($item->item_discount / $item->quantity));
                $row->unit_price = $row->tax_method ? $item->unit_price + $this->sma->formatDecimal($item->item_discount / $item->quantity) + $this->sma->formatDecimal($item->item_tax / $item->quantity) : $item->unit_price + ($item->item_discount / $item->quantity);
                $row->real_unit_price = $item->real_unit_price;
                $row->tax_rate = $item->tax_rate_id;
                $row->serial = '';
                $row->option = $item->option_id;
                $options = $this->sales_model->getProductOptions($row->id, $item->warehouse_id);
                if ($options) {
                    $option_quantity = 0;
                    foreach ($options as $option) {
                        $pis = $this->site->getPurchasedItems($row->id, $item->warehouse_id, $item->option_id);
                        if ($pis) {
                            foreach ($pis as $pi) {
                                $option_quantity += $pi->quantity_balance;
                            }
                        }
                        if ($option->quantity > $option_quantity) {
                            $option->quantity = $option_quantity;
                        }
                    }
                }
                $combo_items = false;
                if ($row->type == 'combo') {
                    $combo_items = $this->sales_model->getProductComboItems($row->id, $item->warehouse_id);
                }
                $units = $this->site->getUnitsByBUID($row->base_unit);
                $tax_rate = $this->site->getTaxRateByID($row->tax_rate);
                $ri = $this->Settings->item_addition ? $row->id : $c;

                $pr[$ri] = array('id' => $c, 'item_id' => $row->id, 'label' => $row->name . " (" . $row->code . ")", 
                        'row' => $row, 'combo_items' => $combo_items, 'tax_rate' => $tax_rate, 'units' => $units, 'options' => $options);
                $c++;
            }
            $this->data['quote_items'] = json_encode($pr);
        }

        $this->data['error'] = (validation_errors() ? validation_errors() : $this->session->flashdata('error'));
        $this->data['quote_id'] = $quote_id ? $quote_id : $sale_id;
        $this->data['billers'] = $this->site->getAllCompanies('biller');
        $this->data['warehouses'] = $this->site->getAllWarehouses();
        $this->data['tax_rates'] = $this->site->getAllTaxRates();
        //$this->data['currencies'] = $this->sales_model->getAllCurrencies();
        $this->data['slnumber'] = ''; //$this->site->getReference('so');
        $this->data['payment_ref'] = ''; //$this->site->getReference('pay');
        $bc = array(array('link' => base_url(), 'page' => lang('home')), array('link' => site_url('sales'), 'page' => lang('sales')), array('link' => '#', 'page' => lang('add_sale')));
        $meta = array('page_title' => lang('add_sale'), 'bc' => $bc);
        $this->page_construct('sales/add', $meta, $this->data);
    }
}

public function calculateAVCost($product_id, $warehouse_id, $net_unit_price, $unit_price, $quantity, $product_name, $option_id, $item_quantity) {
    $product = $this->getProductByID($product_id);
    $real_item_qty = $quantity;
    $wp_details = $this->getWarehouseProduct($warehouse_id, $product_id);
    $avg_net_unit_cost = $wp_details ? $wp_details->avg_cost : $product->cost;
    $avg_unit_cost = $wp_details ? $wp_details->avg_cost : $product->cost;
    if ($pis = $this->getPurchasedItems($product_id, $warehouse_id, $option_id)) {
        $cost_row = array();
        $quantity = $item_quantity;
        $balance_qty = $quantity;
        foreach ($pis as $pi) {
            if (!empty($pi) && $pi->quantity > 0 && $balance_qty <= $quantity && $quantity > 0) {
                if ($pi->quantity_balance >= $quantity && $quantity > 0) {
                    $balance_qty = $pi->quantity_balance - $quantity;
                    $cost_row = array('date' => date('Y-m-d'), 'product_id' => $product_id, 'sale_item_id' => 'sale_items.id', 'purchase_item_id' => $pi->id, 'quantity' => $real_item_qty, 'purchase_net_unit_cost' => $avg_net_unit_cost, 'purchase_unit_cost' => $avg_unit_cost, 'sale_net_unit_price' => $net_unit_price, 'sale_unit_price' => $unit_price, 'quantity_balance' => $balance_qty, 'inventory' => 1, 'option_id' => $option_id);
                    $quantity = 0;
                } elseif ($quantity > 0) {
                    $quantity = $quantity - $pi->quantity_balance;
                    $balance_qty = $quantity;
                    $cost_row = array('date' => date('Y-m-d'), 'product_id' => $product_id, 'sale_item_id' => 'sale_items.id', 'purchase_item_id' => $pi->id, 'quantity' => $pi->quantity_balance, 'purchase_net_unit_cost' => $avg_net_unit_cost, 'purchase_unit_cost' => $avg_unit_cost, 'sale_net_unit_price' => $net_unit_price, 'sale_unit_price' => $unit_price, 'quantity_balance' => 0, 'inventory' => 1, 'option_id' => $option_id);
                }
            }
            if (empty($cost_row)) {
                break;
            }
            $cost[] = $cost_row;
            if ($quantity == 0) {
                break;
            }
        }
    }
    if ($quantity > 0 && !$this->Settings->overselling) {
        $this->session->set_flashdata('error', sprintf(lang("quantity_out_of_stock_for_%s"), ($pi->product_name ? $pi->product_name : $product_name)));
        redirect($_SERVER["HTTP_REFERER"]);
    } elseif ($quantity > 0) {
        $cost[] = array('date' => date('Y-m-d'), 'product_id' => $product_id, 'sale_item_id' => 'sale_items.id', 'purchase_item_id' => NULL, 'quantity' => $real_item_qty, 'purchase_net_unit_cost' => $avg_net_unit_cost, 'purchase_unit_cost' => $avg_unit_cost, 'sale_net_unit_price' => $net_unit_price, 'sale_unit_price' => $unit_price, 'quantity_balance' => NULL, 'overselling' => 1, 'inventory' => 1);
        $cost[] = array('pi_overselling' => 1, 'product_id' => $product_id, 'quantity_balance' => (0 - $quantity), 'warehouse_id' => $warehouse_id, 'option_id' => $option_id);
    }
    return $cost;
}

warehouse id 2

warehouse id 2

I am trying to sell the item from warehouse_id 2 where i have 43 products in stock where it shows of stock when i am selling 1 or 2 quantity from this warehouse i dont know which piece of code causing the issue.

Quantity issue is quite likely in this code as i have asked the tecdiary about the issue but they themselves dont know which piece of code is causing the issue

error when selling

error when selling

  • 4
    ~380 lines of code! do you have a unit test for this method so if you play with it you can verify your changes don't cause any side issues? for me there's a lot of loose comparisons in this code (== vs === and != vs !==), this can often cause problems – Wee Zel Aug 19 '17 at 10:33
  • are you sure you have the right product_id? the avg_cost in your db table is 1380, but your displayed price is 1420 (before tax) – Wee Zel Aug 19 '17 at 10:59
  • actually this product is of someone else , i purchased this from them for my friend but it becomes an issue for me because at first they have profit issue that i solved it by analyzing the code but i am stuck here and dont know how to analyze the code because this does not behave improper everytime but some it does and it puts me in this condition. what would be the best way to analyze and solve it because it behaves improper sometime not everytime – Haseebuddin09 Aug 20 '17 at 21:57
  • if it was me, I'd use xdebug to trace the execution path to find out what is going wrong. I don't see the "out of stock" processing in this method, you should find this and look around there – Wee Zel Aug 21 '17 at 08:49
  • I have added the calculateAVCost method which is used for average cost calculation and also out of stock – Haseebuddin09 Sep 05 '17 at 09:12
  • now lets look for where `$warehouse_id` is passed to the `calculateAVCost()` method `public function calculateAVCost($product_id, $warehouse_id,...)` somewhere a decision is being made to choose a warehouse to pass to this function and it is picking the wrong one – Wee Zel Sep 05 '17 at 09:34
  • check this line in your `add()` method `$warehouse_id = $this->input->post('warehouse');`. It looks to me like the warehouse id is set by the post data and cannot be satisfied by any warehouse that has stock. – Wee Zel Sep 05 '17 at 09:51
  • i have added the whole code in here https://jsfiddle.net/y90cw95z/ i have tried but couldnt find the code which is causing this problem although i have this item in stock and also it disturbs the whole stock whenever the sale is made which becomes hectic to find the issue – Haseebuddin09 Sep 07 '17 at 10:23
  • couldnt figure out the problem in code can you please suggest the issue – Haseebuddin09 Sep 13 '17 at 21:30
  • I couldn't see anything in the code to help you. It looks like this logic wasn't designed into the system. The possibility that an order could be filled by 2 or more Warehouses sounds problematic! – Wee Zel Sep 13 '17 at 22:18
  • as i have tested this on different scenarios , i found the issue when the item is not in purchased it generates the issue however it shouldnt look for it in the purchase because the item is in warehouse so i just to prevent this code from looking into purchasing while sale is being made , it just look into the warehouse stock , can you please tell me how can i do this in the add sale – Haseebuddin09 Sep 21 '17 at 11:09

0 Answers0