mirror of
https://github.com/opensourcepos/opensourcepos.git
synced 2026-05-25 08:44:42 -04:00
Compare commits
3 Commits
fix/4559-m
...
fix-requis
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b64a93e483 | ||
|
|
7f073bce8f | ||
|
|
6ab72ce5c2 |
@@ -213,10 +213,13 @@ class Receivings extends Secure_Controller
|
||||
|
||||
$price = parse_decimals($this->request->getPost('price'));
|
||||
$quantity = parse_quantity($this->request->getPost('quantity'));
|
||||
$discount = parse_decimals($this->request->getPost('discount'));
|
||||
$raw_receiving_quantity = parse_quantity($this->request->getPost('receiving_quantity'));
|
||||
|
||||
$description = $this->request->getPost('description', FILTER_SANITIZE_FULL_SPECIAL_CHARS); //TODO: Duplicated code
|
||||
$serialnumber = $this->request->getPost('serialnumber', FILTER_SANITIZE_FULL_SPECIAL_CHARS) ?? '';
|
||||
$price = filter_var($price, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
|
||||
$quantity = filter_var($quantity, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
|
||||
$discount_type = $this->request->getPost('discount_type', FILTER_SANITIZE_NUMBER_INT);
|
||||
$discount = $discount_type
|
||||
? parse_quantity(filter_var($this->request->getPost('discount'), FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION))
|
||||
@@ -263,6 +266,7 @@ class Receivings extends Secure_Controller
|
||||
$data['selected_supplier_name'] = !empty($receiving_info['supplier_id']) ? $receiving_info['company_name'] : '';
|
||||
$data['selected_supplier_id'] = $receiving_info['supplier_id'];
|
||||
$data['receiving_info'] = $receiving_info;
|
||||
$balance_due = round($receiving_info['amount_due'] - $receiving_info['amount_tendered'] + $receiving_info['cash_refund'], totals_decimals(), PHP_ROUND_HALF_UP);
|
||||
|
||||
echo view('receivings/form', $data);
|
||||
}
|
||||
@@ -324,22 +328,26 @@ class Receivings extends Secure_Controller
|
||||
*/
|
||||
public function postComplete(): void
|
||||
{
|
||||
|
||||
$amount_tendered = parse_decimals($this->request->getPost('amount_tendered'));
|
||||
$data = [];
|
||||
|
||||
$data['cart'] = $this->receiving_lib->get_cart();
|
||||
$data['total'] = $this->receiving_lib->get_total();
|
||||
$data['transaction_time'] = to_datetime(time());
|
||||
$data['transaction_time'] = date('Y-m-d H:i:s'); // Fecha y hora actuales
|
||||
$data['mode'] = $this->receiving_lib->get_mode();
|
||||
$data['comment'] = $this->receiving_lib->get_comment();
|
||||
$data['reference'] = $this->receiving_lib->get_reference();
|
||||
$data['term_days'] = $this->receiving_lib->get_term_days();
|
||||
$data['payment_type'] = $this->request->getPost('payment_type', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
||||
$data['payments'] = $this->receiving_lib->get_payments(); // Obtener pagos del carrito
|
||||
$data['show_stock_locations'] = $this->stock_location->show_locations('receivings');
|
||||
$data['stock_location'] = $this->receiving_lib->get_stock_source();
|
||||
if($this->request->getPost('amount_tendered') != null)
|
||||
{
|
||||
$data['amount_tendered'] = parse_decimals($this->request->getPost('amount_tendered'));
|
||||
$data['amount_change'] = to_currency($data['amount_tendered'] - $data['total']);
|
||||
|
||||
if ($this->request->getPost('amount_tendered') != null) {
|
||||
$data['amount_tendered'] = filter_var($amount_tendered, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
|
||||
$data['amount_change'] = $data['amount_tendered'] - $data['total'];
|
||||
} else {
|
||||
$data['amount_change'] = 0;
|
||||
}
|
||||
|
||||
$employee_id = $this->employee->get_logged_in_employee_info()->person_id;
|
||||
@@ -347,40 +355,62 @@ class Receivings extends Secure_Controller
|
||||
$data['employee'] = $employee_info->first_name . ' ' . $employee_info->last_name;
|
||||
|
||||
$supplier_id = $this->receiving_lib->get_supplier();
|
||||
if($supplier_id != -1)
|
||||
{
|
||||
if ($supplier_id != -1) {
|
||||
$supplier_info = $this->supplier->get_info($supplier_id);
|
||||
$data['supplier'] = $supplier_info->company_name; //TODO: duplicated code
|
||||
$data['supplier'] = $supplier_info->company_name;
|
||||
$data['first_name'] = $supplier_info->first_name;
|
||||
$data['last_name'] = $supplier_info->last_name;
|
||||
$data['supplier_email'] = $supplier_info->email;
|
||||
$data['supplier_address'] = $supplier_info->address_1;
|
||||
if(!empty($supplier_info->zip) or !empty($supplier_info->city))
|
||||
{
|
||||
|
||||
if (!empty($supplier_info->zip) || !empty($supplier_info->city)) {
|
||||
$data['supplier_location'] = $supplier_info->zip . ' ' . $supplier_info->city;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$data['supplier_location'] = '';
|
||||
}
|
||||
}
|
||||
|
||||
//SAVE receiving to database
|
||||
$data['receiving_id'] = 'RECV ' . $this->receiving->save_value($data['cart'], $supplier_id, $employee_id, $data['comment'], $data['reference'], $data['payment_type'], $data['stock_location']);
|
||||
// Guardar el registro de compra en la base de datos
|
||||
$receiving_id = $this->receiving->save_value(
|
||||
$data['cart'],
|
||||
$supplier_id,
|
||||
$employee_id,
|
||||
$data['comment'],
|
||||
$data['reference'],
|
||||
$data['term_days'],
|
||||
$data['payment_type']
|
||||
);
|
||||
|
||||
if($data['receiving_id'] == 'RECV -1')
|
||||
{
|
||||
if ($receiving_id == -1) {
|
||||
$data['error_message'] = lang('Receivings.transaction_failed');
|
||||
}
|
||||
else
|
||||
{
|
||||
$data['barcode'] = $this->barcode_lib->generate_receipt_barcode($data['receiving_id']);
|
||||
} else {
|
||||
$data['receiving_id'] = $receiving_id;
|
||||
|
||||
// Calcular el cambio (cash_refund)
|
||||
$total_payments = array_sum(array_column($data['payments'], 'payment_amount'));
|
||||
$cash_refund = max(0, $total_payments - $data['total']);
|
||||
|
||||
// Guardar los pagos en la base de datos
|
||||
foreach ($data['payments'] as $payment) {
|
||||
$this->receiving->save_payment([
|
||||
'receiving_id' => $receiving_id, // Utiliza el ID generado
|
||||
'payment_type' => $payment['payment_type'],
|
||||
'payment_amount' => $payment['payment_amount'],
|
||||
'cash_refund' => ($payment['payment_type'] === lang('Sales.cash')) ? $cash_refund : 0,
|
||||
'employee_id' => $employee_id,
|
||||
'payment_time' => $data['transaction_time'], // Fecha y hora actuales
|
||||
]);
|
||||
}
|
||||
|
||||
$data['barcode'] = $this->barcode_lib->generate_receipt_barcode($receiving_id);
|
||||
}
|
||||
|
||||
$data['print_after_sale'] = $this->receiving_lib->is_print_after_sale();
|
||||
|
||||
echo view("receivings/receipt",$data);
|
||||
echo view("receivings/receipt", $data);
|
||||
|
||||
// Limpiar pagos y otros datos
|
||||
$this->receiving_lib->clear_payments(); // Limpia los pagos
|
||||
$this->receiving_lib->clear_all();
|
||||
}
|
||||
|
||||
@@ -392,23 +422,58 @@ class Receivings extends Secure_Controller
|
||||
*/
|
||||
public function postRequisitionComplete(): void
|
||||
{
|
||||
if($this->receiving_lib->get_stock_source() != $this->receiving_lib->get_stock_destination())
|
||||
{
|
||||
foreach($this->receiving_lib->get_cart() as $item)
|
||||
{
|
||||
$this->receiving_lib->delete_item($item['line']);
|
||||
$this->receiving_lib->add_item($item['item_id'], $item['quantity'], $this->receiving_lib->get_stock_destination(), $item['discount_type']);
|
||||
$this->receiving_lib->add_item($item['item_id'], -$item['quantity'], $this->receiving_lib->get_stock_source(), $item['discount_type']);
|
||||
}
|
||||
$data = [];
|
||||
|
||||
$this->postComplete();
|
||||
}
|
||||
else
|
||||
{
|
||||
$data['error'] = lang('Receivings.error_requisition');
|
||||
// Check if stock locations are different
|
||||
if ($this->receiving_lib->get_stock_source() != $this->receiving_lib->get_stock_destination()) {
|
||||
// Process items in the cart
|
||||
foreach ($this->receiving_lib->get_cart() as $item) {
|
||||
$this->receiving_lib->delete_item($item['line']);
|
||||
$this->receiving_lib->add_item($item['item_id'], $item['quantity'], $this->receiving_lib->get_stock_destination(), $item['discount_type']);
|
||||
$this->receiving_lib->add_item($item['item_id'], -$item['quantity'], $this->receiving_lib->get_stock_source(), $item['discount_type']);
|
||||
}
|
||||
|
||||
$this->_reload($data); //TODO: Hungarian notation
|
||||
}
|
||||
// Prepare data to complete the requisition
|
||||
$data['cart'] = $this->receiving_lib->get_cart();
|
||||
$data['total'] = $this->receiving_lib->get_total();
|
||||
$data['transaction_time'] = to_datetime(time());
|
||||
$data['mode'] = $this->receiving_lib->get_mode();
|
||||
$data['comment'] = $this->receiving_lib->get_comment();
|
||||
$data['term_days'] = $this->receiving_lib->get_term_days();
|
||||
$data['reference'] = $this->receiving_lib->get_reference();
|
||||
$data['show_stock_locations'] = $this->stock_location->show_locations('receivings');
|
||||
$data['stock_location_source'] = $this->receiving_lib->get_stock_source();
|
||||
$data['stock_location_destination'] = $this->receiving_lib->get_stock_destination();
|
||||
|
||||
$employee_id = $this->employee->get_logged_in_employee_info()->person_id;
|
||||
$employee_info = $this->employee->get_info($employee_id);
|
||||
$data['employee'] = $employee_info->first_name . ' ' . $employee_info->last_name;
|
||||
|
||||
// Save the requisition in the database
|
||||
$data['receiving_id'] = 'REQ ' . $this->receiving->save_requisition(
|
||||
$data['cart'],
|
||||
$employee_id,
|
||||
$data['comment'],
|
||||
$data['reference'],
|
||||
$data['stock_location_source'],
|
||||
$data['stock_location_destination']
|
||||
);
|
||||
|
||||
if ($data['receiving_id'] == 'REQ -1') {
|
||||
$data['error_message'] = lang('Receivings.transaction_failed');
|
||||
} else {
|
||||
$data['barcode'] = $this->barcode_lib->generate_receipt_barcode($data['receiving_id']);
|
||||
}
|
||||
|
||||
$data['print_after_sale'] = $this->receiving_lib->is_print_after_sale();
|
||||
|
||||
echo view("receivings/receipt", $data);
|
||||
|
||||
$this->receiving_lib->clear_all();
|
||||
} else {
|
||||
$data['error'] = lang('Receivings.error_requisition');
|
||||
$this->_reload($data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -464,7 +529,7 @@ class Receivings extends Secure_Controller
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
private function _reload(array $data = []): void //TODO: Hungarian notation
|
||||
private function _reload(array $data = []): void
|
||||
{
|
||||
$data['cart'] = $this->receiving_lib->get_cart();
|
||||
$data['modes'] = ['receive' => lang('Receivings.receiving'), 'return' => lang('Receivings.return')];
|
||||
@@ -481,15 +546,26 @@ class Receivings extends Secure_Controller
|
||||
$data['total'] = $this->receiving_lib->get_total();
|
||||
$data['items_module_allowed'] = $this->employee->has_grant('items', $this->employee->get_logged_in_employee_info()->person_id);
|
||||
$data['comment'] = $this->receiving_lib->get_comment();
|
||||
$data['term_days'] = $this->receiving_lib->get_term_days();
|
||||
$data['reference'] = $this->receiving_lib->get_reference();
|
||||
$data['payment_options'] = $this->receiving->get_payment_options();
|
||||
$data['selected_payment_type'] = $this->receiving_lib->get_payment_type();
|
||||
$data['amount_due'] = $this->receiving_lib->get_total() - $this->receiving_lib->get_payments_total();
|
||||
|
||||
// Agregar pagos al arreglo de datos
|
||||
$data['payments'] = $this->receiving_lib->get_payments();
|
||||
|
||||
// Inicializar tabindex
|
||||
$data['tabindex'] = 0;
|
||||
|
||||
$supplier_id = $this->receiving_lib->get_supplier();
|
||||
|
||||
if($supplier_id != -1) //TODO: Duplicated Code... replace -1 with a constant
|
||||
if($supplier_id != -1)
|
||||
{
|
||||
$supplier_info = $this->supplier->get_info($supplier_id);
|
||||
$data['supplier'] = $supplier_info->company_name;
|
||||
$data['avatar'] = $supplier_info->avatar;
|
||||
$data['gender'] = $supplier_info->gender;
|
||||
$data['first_name'] = $supplier_info->first_name;
|
||||
$data['last_name'] = $supplier_info->last_name;
|
||||
$data['supplier_email'] = $supplier_info->email;
|
||||
@@ -512,9 +588,9 @@ class Receivings extends Secure_Controller
|
||||
/**
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function save(int $receiving_id = -1): void //TODO: Replace -1 with a constant
|
||||
public function save(int $receiving_id = -1): void
|
||||
{
|
||||
$newdate = $this->request->getPost('date', FILTER_SANITIZE_FULL_SPECIAL_CHARS); //TODO: newdate does not follow naming conventions
|
||||
$newdate = $this->request->getPost('date', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
||||
|
||||
$date_formatter = date_create_from_format($this->config['dateformat'] . ' ' . $this->config['timeformat'], $newdate);
|
||||
$receiving_time = $date_formatter->format('Y-m-d H:i:s');
|
||||
@@ -554,8 +630,77 @@ class Receivings extends Secure_Controller
|
||||
*/
|
||||
public function postCancelReceiving(): void
|
||||
{
|
||||
// Limpiar los pagos
|
||||
$this->receiving_lib->clear_payments();
|
||||
|
||||
// Limpiar todos los datos relacionados con la transacción
|
||||
$this->receiving_lib->clear_all();
|
||||
|
||||
$this->_reload(); //TODO: Hungarian Notation
|
||||
// Recargar la vista
|
||||
$this->_reload();
|
||||
}
|
||||
|
||||
public function postAddPayment(): void
|
||||
{
|
||||
$data = [];
|
||||
$payment_type = $this->request->getPost('payment_type', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
||||
|
||||
// Validar el tipo de pago
|
||||
if ($payment_type !== lang('Sales.giftcard')) {
|
||||
$rules = ['amount_tendered' => 'trim|required|decimal_locale'];
|
||||
$messages = ['amount_tendered' => lang('Sales.must_enter_numeric')];
|
||||
} else {
|
||||
$rules = ['amount_tendered' => 'trim|required'];
|
||||
$messages = ['amount_tendered' => lang('Sales.must_enter_numeric_giftcard')];
|
||||
}
|
||||
|
||||
if (!$this->validate($rules, $messages)) {
|
||||
$data['error'] = $payment_type === lang('Sales.giftcard')
|
||||
? lang('Sales.must_enter_numeric_giftcard')
|
||||
: lang('Sales.must_enter_numeric');
|
||||
} else {
|
||||
if ($payment_type === lang('Sales.giftcard')) {
|
||||
$amount_tendered = parse_decimals($this->request->getPost('amount_tendered'));
|
||||
$giftcard_num = filter_var($amount_tendered, FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_FLAG_ALLOW_FRACTION);
|
||||
|
||||
$payments = $this->receiving_lib->get_payments();
|
||||
$payment_type = $payment_type . ':' . $giftcard_num;
|
||||
$current_payments_with_giftcard = isset($payments[$payment_type]) ? $payments[$payment_type]['payment_amount'] : 0;
|
||||
|
||||
$giftcard = model(Giftcard::class);
|
||||
$cur_giftcard_value = $giftcard->get_giftcard_value($giftcard_num);
|
||||
|
||||
if (($cur_giftcard_value - $current_payments_with_giftcard) <= 0) {
|
||||
$data['error'] = lang('Giftcards.remaining_balance', [$giftcard_num, $cur_giftcard_value]);
|
||||
} else {
|
||||
$amount_tendered = min($this->receiving_lib->get_amount_due(), $cur_giftcard_value);
|
||||
$this->receiving_lib->add_payment($payment_type, $amount_tendered);
|
||||
}
|
||||
} elseif ($payment_type === lang('Sales.cash')) {
|
||||
$raw_amount_tendered = parse_decimals($this->request->getPost('amount_tendered'));
|
||||
$amount_tendered = filter_var($raw_amount_tendered, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
|
||||
$this->receiving_lib->add_payment($payment_type, $amount_tendered);
|
||||
} else {
|
||||
$raw_amount_tendered = parse_decimals($this->request->getPost('amount_tendered'));
|
||||
$amount_tendered = filter_var($raw_amount_tendered, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
|
||||
$this->receiving_lib->add_payment($payment_type, $amount_tendered);
|
||||
}
|
||||
}
|
||||
|
||||
$this->_reload($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiple Payments. Used in app/Views/sales/register.php
|
||||
*
|
||||
* @param string $payment_id
|
||||
* @return void
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function getDeletePayment(string $payment_id): void
|
||||
{
|
||||
$this->receiving_lib->delete_payment($payment_id);
|
||||
|
||||
$this->_reload();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,11 +6,13 @@ use App\Models\Attribute;
|
||||
use App\Models\Item;
|
||||
use App\Models\Item_kit_items;
|
||||
use App\Models\Item_quantity;
|
||||
use App\Models\Enums\Rounding_mode;
|
||||
use App\Models\Receiving;
|
||||
use App\Models\Stock_location;
|
||||
|
||||
use CodeIgniter\Session\Session;
|
||||
use Config\OSPOS;
|
||||
use ReflectionException;
|
||||
|
||||
/**
|
||||
* Receiving library
|
||||
@@ -26,6 +28,7 @@ class Receiving_lib
|
||||
private Receiving $receiving;
|
||||
private Stock_location $stock_location;
|
||||
private Session $session;
|
||||
private array $config;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
@@ -35,6 +38,7 @@ class Receiving_lib
|
||||
$this->item_quantity = model(Item_quantity::class);
|
||||
$this->receiving = model(Receiving::class);
|
||||
$this->stock_location = model(Stock_location::class);
|
||||
$this->config = config(OSPOS::class)->settings;
|
||||
|
||||
$this->session = session();
|
||||
}
|
||||
@@ -194,6 +198,31 @@ class Receiving_lib
|
||||
$this->session->remove('recv_reference');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_term_days(): string
|
||||
{
|
||||
return $this->session->get('recv_term_days') ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $term_days
|
||||
* @return void
|
||||
*/
|
||||
public function set_term_days(string $term_days): void
|
||||
{
|
||||
$this->session->set('recv_term_days', $term_days);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function clear_term_days(): void //TODO: This function verb is inconsistent from the others. Consider refactoring to remove_reference()
|
||||
{
|
||||
$this->session->remove('recv_term_days');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
@@ -516,6 +545,7 @@ class Receiving_lib
|
||||
$this->remove_supplier();
|
||||
$this->clear_comment();
|
||||
$this->clear_reference();
|
||||
$this->clear_term_days();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -554,4 +584,200 @@ class Receiving_lib
|
||||
|
||||
return $total;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $payment_type
|
||||
* @return void
|
||||
*/
|
||||
public function set_payment_type(string $payment_type): void
|
||||
{
|
||||
$this->session->set('payment_type', $payment_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function get_payment_type(): ?string
|
||||
{
|
||||
return $this->session->get('payment_type');
|
||||
}
|
||||
|
||||
public function get_total_due(): float
|
||||
{
|
||||
return $this->get_total() - $this->get_payments_total();
|
||||
}
|
||||
|
||||
public function get_payments_total(): string
|
||||
{
|
||||
$subtotal = '0.0';
|
||||
$cash_mode_eligible = CASH_MODE_TRUE;
|
||||
|
||||
foreach($this->get_payments() as $payments)
|
||||
{
|
||||
if(!$payments['cash_adjustment'])
|
||||
{
|
||||
$subtotal = bcadd($payments['payment_amount'], $subtotal);
|
||||
}
|
||||
if(lang('Sales.cash') != $payments['payment_type'] && lang('Sales.cash_adjustment') != $payments['payment_type'])
|
||||
{
|
||||
$cash_mode_eligible = CASH_MODE_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if($cash_mode_eligible && $this->session->get('cash_rounding'))
|
||||
{
|
||||
$this->session->set('cash_mode', CASH_MODE_TRUE);
|
||||
}
|
||||
|
||||
return $subtotal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiple Payments
|
||||
*/
|
||||
public function get_payments(): array
|
||||
{
|
||||
if(!$this->session->get('sales_payments'))
|
||||
{
|
||||
$this->set_payments ([]);
|
||||
}
|
||||
|
||||
return $this->session->get('sales_payments');
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiple Payments
|
||||
*/
|
||||
public function set_payments(array $payments_data): void
|
||||
{
|
||||
$this->session->set('sales_payments', $payments_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new payment to the payments array or updates an existing one.
|
||||
* It will also disable cash_mode if a non-qualifying payment type is added.
|
||||
* @param string $payment_id
|
||||
* @param string $payment_amount
|
||||
* @param int $cash_adjustment
|
||||
*/
|
||||
public function add_payment(string $payment_id, string $payment_amount, int $cash_adjustment = CASH_ADJUSTMENT_FALSE): void
|
||||
{
|
||||
$payments = $this->get_payments();
|
||||
if(isset($payments[$payment_id]))
|
||||
{
|
||||
//payment_method already exists, add to payment_amount
|
||||
$payments[$payment_id]['payment_amount'] = bcadd($payments[$payment_id]['payment_amount'], $payment_amount);
|
||||
}
|
||||
else
|
||||
{
|
||||
//add to existing array
|
||||
$payment = [
|
||||
$payment_id => [
|
||||
'payment_type' => $payment_id,
|
||||
'payment_amount' => $payment_amount,
|
||||
'cash_refund' => 0,
|
||||
'cash_adjustment' => $cash_adjustment
|
||||
]
|
||||
];
|
||||
|
||||
$payments += $payment;
|
||||
}
|
||||
|
||||
if($this->session->get('cash_mode'))
|
||||
{
|
||||
if($this->session->get('cash_rounding') && $payment_id != lang('Sales.cash') && $payment_id != lang('Sales.cash_adjustment'))
|
||||
{
|
||||
$this->session->set('cash_mode', CASH_MODE_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
$this->set_payments($payments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiple Payments
|
||||
*/
|
||||
public function edit_payment(string $payment_id, float $payment_amount): bool
|
||||
{
|
||||
$payments = $this->get_payments();
|
||||
if(isset($payments[$payment_id]))
|
||||
{
|
||||
$payments[$payment_id]['payment_type'] = $payment_id;
|
||||
$payments[$payment_id]['payment_amount'] = $payment_amount;
|
||||
$this->set_payments($payments);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the selected payment from the payment array and if cash rounding is enabled
|
||||
* and the payment type is one of the cash types then automatically delete the other
|
||||
* @param string $payment_id
|
||||
*/
|
||||
public function delete_payment(string $payment_id): void
|
||||
{
|
||||
$payments = $this->get_payments();
|
||||
$decoded_payment_id = urldecode($payment_id);
|
||||
|
||||
unset($payments[$decoded_payment_id]);
|
||||
|
||||
$cash_rounding = $this->reset_cash_rounding();
|
||||
|
||||
if($cash_rounding)
|
||||
{
|
||||
if($decoded_payment_id == lang('Sales.cash'))
|
||||
{
|
||||
unset($payments[lang('Sales.cash_adjustment')]);
|
||||
}
|
||||
|
||||
if($decoded_payment_id == lang('Sales.cash_adjustment'))
|
||||
{
|
||||
unset($payments[lang('Sales.cash')]);
|
||||
}
|
||||
}
|
||||
$this->set_payments($payments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if cash rounding should be a consideration for this site
|
||||
* It also set resets the cash mode to disabled which will then be re-evaluated when
|
||||
* retrieving payments.
|
||||
*/
|
||||
public function reset_cash_rounding(): int
|
||||
{
|
||||
$cash_rounding_code = $this->config['cash_rounding_code'];
|
||||
|
||||
if(cash_decimals() < totals_decimals() || $cash_rounding_code == Rounding_mode::HALF_FIVE)
|
||||
{
|
||||
$cash_rounding = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
$cash_rounding = 0;
|
||||
}
|
||||
$this->session->set('cash_rounding', $cash_rounding);
|
||||
$this->session->set('cash_mode', CASH_MODE_FALSE);
|
||||
|
||||
return $cash_rounding;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $total
|
||||
* @return string
|
||||
*/
|
||||
public function check_for_cash_rounding(string $total): string
|
||||
{
|
||||
$cash_decimals = cash_decimals();
|
||||
$cash_rounding_code = $this->config['cash_rounding_code'];
|
||||
|
||||
return Rounding_mode::round_number($cash_rounding_code, (float)$total, $cash_decimals);
|
||||
}
|
||||
|
||||
public function clear_payments(): void
|
||||
{
|
||||
$this->set_payments([]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ class Receiving extends Model
|
||||
/**
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function save_value(array $items, int $supplier_id, int $employee_id, string $comment, string $reference, string $payment_type, int $receiving_id = NEW_ENTRY): int //TODO: $receiving_id gets overwritten before it's evaluated. It doesn't make sense to pass this here.
|
||||
public function save_value(array $items, int $supplier_id, int $employee_id, string $comment, string $reference, string $term_days, string $payment_type, int $receiving_id = NEW_ENTRY): int //TODO: $receiving_id gets overwritten before it's evaluated. It doesn't make sense to pass this here.
|
||||
{
|
||||
$attribute = model(Attribute::class);
|
||||
$inventory = model('Inventory');
|
||||
@@ -123,7 +123,8 @@ class Receiving extends Model
|
||||
'employee_id' => $employee_id,
|
||||
'payment_type' => $payment_type,
|
||||
'comment' => $comment,
|
||||
'reference' => $reference
|
||||
'reference' => $reference,
|
||||
'term_days' => $term_days
|
||||
];
|
||||
|
||||
//Run these queries as a transaction, we want to make sure we do all or nothing
|
||||
@@ -187,7 +188,7 @@ class Receiving extends Model
|
||||
|
||||
$inventory->insert($inv_data, false);
|
||||
$attribute->copy_attribute_links($item_data['item_id'], 'receiving_id', $receiving_id);
|
||||
$supplier = $supplier->get_info($supplier_id); //TODO: supplier is never used after this.
|
||||
// $supplier = $supplier->get_info($supplier_id); //TODO: supplier is never used after this.
|
||||
}
|
||||
|
||||
$this->db->transComplete();
|
||||
@@ -195,6 +196,153 @@ class Receiving extends Model
|
||||
return $this->db->transStatus() ? $receiving_id : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a requisition to the `ospos_receivings` and `ospos_receivings_items` tables
|
||||
* and update stock quantities in the respective locations.
|
||||
*
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function save_requisition(array $items, int $employee_id, string $comment, string $reference, int $stock_source, int $stock_destination): int
|
||||
{
|
||||
$inventory = model('Inventory');
|
||||
$item_quantity_model = model(Item_quantity::class);
|
||||
|
||||
if (count($items) == 0) {
|
||||
return -1; // No items to save
|
||||
}
|
||||
|
||||
// Prepare the receiving data
|
||||
$receivings_data = [
|
||||
'receiving_time' => date('Y-m-d H:i:s'),
|
||||
'employee_id' => $employee_id,
|
||||
'comment' => $comment,
|
||||
'reference' => $reference,
|
||||
'total' => 0, // This will be updated later
|
||||
'amount_change' => 0,
|
||||
'amount_tendered' => 0,
|
||||
'operation_type' => 'Requisition',
|
||||
];
|
||||
|
||||
// Run these queries as a transaction
|
||||
$this->db->transStart();
|
||||
|
||||
// Insert into `ospos_receivings`
|
||||
$builder = $this->db->table('ospos_receivings');
|
||||
$builder->insert($receivings_data);
|
||||
$receiving_id = $this->db->insertID();
|
||||
|
||||
if (!$receiving_id) {
|
||||
log_message('error', 'Failed to insert requisition header: ' . print_r($receivings_data, true));
|
||||
$this->db->transRollback();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Insert items into `ospos_receivings_items`
|
||||
$builder = $this->db->table('ospos_receivings_items');
|
||||
$total_cost = 0;
|
||||
|
||||
foreach ($items as $item_data) {
|
||||
$receivings_items_data = [
|
||||
'receiving_id' => $receiving_id,
|
||||
'item_id' => $item_data['item_id'],
|
||||
'line' => $item_data['line'],
|
||||
'description' => $item_data['description'] ?? '',
|
||||
'serialnumber' => $item_data['serialnumber'] ?? '',
|
||||
'quantity_purchased' => $item_data['quantity'],
|
||||
'item_cost_price' => $item_data['price'],
|
||||
'item_unit_price' => $item_data['price'],
|
||||
'discount' => $item_data['discount'] ?? 0,
|
||||
'discount_type' => $item_data['discount_type'] ?? 0,
|
||||
'item_location' => $item_data['item_location'] ?? 1,
|
||||
'receiving_quantity' => $item_data['receiving_quantity'] ?? 1,
|
||||
];
|
||||
|
||||
$builder->insert($receivings_items_data);
|
||||
|
||||
if (!$this->db->affectedRows()) {
|
||||
log_message('error', 'Failed to insert requisition item: ' . print_r($receivings_items_data, true));
|
||||
$this->db->transRollback();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Calculate the total cost
|
||||
$total_cost += ($item_data['price'] * $item_data['quantity']) - ($item_data['discount'] ?? 0);
|
||||
|
||||
// Update stock quantities
|
||||
$item_id = $item_data['item_id'] > 0 ? $item_data['item_id'] : 0;
|
||||
$quantity = $item_data['quantity'] > 0 ? $item_data['quantity'] : 0;
|
||||
|
||||
if ($item_id === 0 || $quantity === 0) {
|
||||
continue; // Skip if item or quantity is invalid
|
||||
}
|
||||
|
||||
// Subtract from stock at the source
|
||||
$source_quantity = $item_quantity_model->get_item_quantity($item_id, $stock_source);
|
||||
$item_quantity_model->save_value([
|
||||
'quantity' => $source_quantity->quantity - $quantity,
|
||||
'item_id' => $item_id,
|
||||
'location_id' => $stock_source,
|
||||
], $item_id, $stock_source);
|
||||
|
||||
// Add to stock at the destination
|
||||
$destination_quantity = $item_quantity_model->get_item_quantity($item_id, $stock_destination);
|
||||
$item_quantity_model->save_value([
|
||||
'quantity' => $destination_quantity->quantity + $quantity,
|
||||
'item_id' => $item_id,
|
||||
'location_id' => $stock_destination,
|
||||
], $item_id, $stock_destination);
|
||||
|
||||
// Register inventory for the outgoing location (only if not already registered)
|
||||
$recv_remarks = 'REQ ' . $receiving_id;
|
||||
|
||||
$inv_data_source = [
|
||||
'trans_date' => date('Y-m-d H:i:s'),
|
||||
'trans_items' => $item_id,
|
||||
'trans_user' => $employee_id,
|
||||
'trans_location' => $stock_source,
|
||||
'trans_comment' => $recv_remarks . ' OUT',
|
||||
'trans_inventory' => -$quantity,
|
||||
];
|
||||
$existing_source = $inventory->where([
|
||||
'trans_items' => $item_id,
|
||||
'trans_location' => $stock_source,
|
||||
'trans_comment' => $recv_remarks . ' OUT'
|
||||
])->countAllResults();
|
||||
if ($existing_source === 0) {
|
||||
$inventory->insert($inv_data_source, false);
|
||||
}
|
||||
|
||||
// Register inventory for the incoming location (only if not already registered)
|
||||
$inv_data_destination = [
|
||||
'trans_date' => date('Y-m-d H:i:s'),
|
||||
'trans_items' => $item_id,
|
||||
'trans_user' => $employee_id,
|
||||
'trans_location' => $stock_destination,
|
||||
'trans_comment' => $recv_remarks . ' IN',
|
||||
'trans_inventory' => $quantity,
|
||||
];
|
||||
$existing_destination = $inventory->where([
|
||||
'trans_items' => $item_id,
|
||||
'trans_location' => $stock_destination,
|
||||
'trans_comment' => $recv_remarks . ' IN'
|
||||
])->countAllResults();
|
||||
if ($existing_destination === 0) {
|
||||
$inventory->insert($inv_data_destination, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the total cost in ospos_receivings
|
||||
$this->db->table('ospos_receivings')
|
||||
->where('receiving_id', $receiving_id)
|
||||
->update(['total' => $total_cost]);
|
||||
|
||||
if (!$this->db->transComplete()) {
|
||||
log_message('error', 'Transaction failed for requisition: ' . print_r($receivings_data, true));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return $receiving_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ReflectionException
|
||||
@@ -364,4 +512,9 @@ class Receiving extends Model
|
||||
|
||||
$this->db->query($sql);
|
||||
}
|
||||
|
||||
public function save_payment(array $payment_data): bool
|
||||
{
|
||||
return $this->db->table('ospos_receivings_payments')->insert($payment_data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
?>
|
||||
<tr>
|
||||
<td colspan="3" style='text-align:right;'><?= lang('Sales.amount_tendered') ?></td>
|
||||
<td><div class="total-value"><?= to_currency($amount_tendered) ?></div></td>
|
||||
<td><div class="total-value">0.00</div></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
@@ -155,77 +155,76 @@ if (isset($success))
|
||||
<td><?= anchor("$controller_name/deleteItem/$line", '<span class="glyphicon glyphicon-trash"></span>') ?></td>
|
||||
<td><?= esc($item['item_number']) ?></td>
|
||||
<td style="text-align:center;">
|
||||
<?= esc($item['name'] . ' '. implode(' ', [$item['attribute_values'], $item['attribute_dtvalues']])) ?><br /> <?= '[' . to_quantity_decimals($item['in_stock']) . ' in ' . $item['stock_name'] . ']' ?>
|
||||
<?= esc($item['name'] . ' ' . implode(' ', [$item['attribute_values'], $item['attribute_dtvalues']])) ?><br />
|
||||
<?= '[' . to_quantity_decimals($item['in_stock']) . ' in ' . $item['stock_name'] . ']' ?>
|
||||
<?= form_hidden('location', (string)$item['item_location']) ?>
|
||||
</td>
|
||||
|
||||
<?php
|
||||
if ($items_module_allowed && $mode != 'requisition')
|
||||
{
|
||||
?>
|
||||
<td><?= form_input ([
|
||||
<?php if ($items_module_allowed && $mode != 'requisition') { ?>
|
||||
<td><?= form_input([
|
||||
'name' => 'price',
|
||||
'class' => 'form-control input-sm',
|
||||
'value' => to_currency_no_money($item['price']),
|
||||
'value' => (string)to_currency_no_money($item['price']),
|
||||
'onClick' => 'this.select();'
|
||||
]) ?></td>
|
||||
<?php
|
||||
}
|
||||
else
|
||||
{
|
||||
?>
|
||||
<?php } else { ?>
|
||||
<td>
|
||||
<?= $item['price'] ?>
|
||||
<?= form_hidden('price', to_currency_no_money($item['price'])) ?>
|
||||
<?= (string)$item['price'] ?>
|
||||
<?= form_hidden('price', (string)to_currency_no_money($item['price'])) ?>
|
||||
</td>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<?php } ?>
|
||||
|
||||
<td><?= form_input (['name' => 'quantity', 'class' => 'form-control input-sm', 'value' => to_quantity_decimals($item['quantity']),'onClick' => 'this.select();']) ?></td>
|
||||
<td><?= form_input([
|
||||
'name' => 'quantity',
|
||||
'class' => 'form-control input-sm',
|
||||
'value' => (string)to_quantity_decimals($item['quantity']),
|
||||
'onClick' => 'this.select();'
|
||||
]) ?></td>
|
||||
<td><?= form_dropdown(
|
||||
'receiving_quantity',
|
||||
$item['receiving_quantity_choices'],
|
||||
$item['receiving_quantity'],
|
||||
['class' => 'form-control input-sm']
|
||||
) ?></td>
|
||||
'receiving_quantity',
|
||||
$item['receiving_quantity_choices'],
|
||||
(string)$item['receiving_quantity'],
|
||||
['class' => 'form-control input-sm']
|
||||
) ?></td>
|
||||
|
||||
<?php
|
||||
if ($items_module_allowed && $mode != 'requisition')
|
||||
{
|
||||
?>
|
||||
<?php if ($items_module_allowed && $mode != 'requisition') { ?>
|
||||
<td>
|
||||
<div class="input-group">
|
||||
<?= form_input (['name' => 'discount', 'class' => 'form-control input-sm', 'value' => $item['discount_type'] ? to_currency_no_money($item['discount']) : to_decimals($item['discount']), 'onClick' => 'this.select();']) ?>
|
||||
<span class="input-group-btn">
|
||||
<?= form_checkbox ([
|
||||
'id' => 'discount_toggle',
|
||||
'name' => 'discount_toggle',
|
||||
'value' => 1,
|
||||
'data-toggle' => "toggle",
|
||||
'data-size' => 'small',
|
||||
'data-onstyle' => 'success',
|
||||
'data-on' => '<b>' . $config['currency_symbol'] .'</b>',
|
||||
'data-off' => '<b>%</b>',
|
||||
'data-line' => $line,
|
||||
'checked' => $item['discount_type'] == 1
|
||||
<div class="input-group">
|
||||
<?= form_input([
|
||||
'name' => 'discount',
|
||||
'class' => 'form-control input-sm',
|
||||
'value' => (string)($item['discount_type'] ? to_currency_no_money($item['discount']) : to_decimals($item['discount'])),
|
||||
'onClick' => 'this.select();'
|
||||
]) ?>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<?php
|
||||
}
|
||||
else
|
||||
{
|
||||
?>
|
||||
<td><?= $item['discount'] ?></td>
|
||||
<?= form_hidden('discount', $item['discount']) ?>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<span class="input-group-btn">
|
||||
<?= form_checkbox([
|
||||
'id' => 'discount_toggle',
|
||||
'name' => 'discount_toggle',
|
||||
'value' => 1,
|
||||
'data-toggle' => "toggle",
|
||||
'data-size' => 'small',
|
||||
'data-onstyle' => 'success',
|
||||
'data-on' => '<b>' . $config['currency_symbol'] . '</b>',
|
||||
'data-off' => '<b>%</b>',
|
||||
'data-line' => $line,
|
||||
'checked' => $item['discount_type'] == 1
|
||||
]) ?>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<?php } else { ?>
|
||||
<td><?= (string)$item['discount'] ?></td>
|
||||
<?= form_hidden('discount', (string)$item['discount']) ?>
|
||||
<?php } ?>
|
||||
|
||||
<td>
|
||||
<?= to_currency(($item['discount_type'] == PERCENT) ? $item['price']*$item['quantity']*$item['receiving_quantity'] - $item['price'] * $item['quantity'] * $item['receiving_quantity'] * $item['discount'] / 100 : $item['price']*$item['quantity']*$item['receiving_quantity'] - $item['discount']) ?></td>
|
||||
<td><a href="javascript:$('#<?= esc("cart_$line", 'js') ?>').submit();" title=<?= lang(ucfirst($controller_name) .'.update') ?> ><span class="glyphicon glyphicon-refresh"></span></a></td>
|
||||
<?= to_currency(
|
||||
($item['discount_type'] == PERCENT)
|
||||
? $item['price'] * $item['quantity'] * $item['receiving_quantity'] - $item['price'] * $item['quantity'] * $item['receiving_quantity'] * $item['discount'] / 100
|
||||
: $item['price'] * $item['quantity'] * $item['receiving_quantity'] - $item['discount']
|
||||
) ?>
|
||||
</td>
|
||||
<td><a href="javascript:$('#<?= esc("cart_$line", 'js') ?>').submit();" title=<?= lang(ucfirst($controller_name) . '.update') ?>><span class="glyphicon glyphicon-refresh"></span></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<?php
|
||||
@@ -375,6 +374,53 @@ if (isset($success))
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<?= form_open("$controller_name/addPayment", ['id' => 'add_payment_form', 'class' => 'form-horizontal']) ?>
|
||||
<section class="mainContent">
|
||||
<div class="formContainer">
|
||||
<form action="">
|
||||
<fieldset class="fieldInput">
|
||||
<div class="dropdown">
|
||||
<?= form_dropdown('payment_type', $payment_options, $selected_payment_type, ['id' => 'payment_types', 'class' => 'dropdown-toggle', 'data-style' => 'btn-default btn-sm', 'data-width' => 'fit']) ?>
|
||||
</div>
|
||||
<?= form_input (['name' => 'amount_tendered', 'id' => 'amount_tendered', 'class' => 'form-input', 'value' => to_currency_no_money($amount_due), 'size' => '5', 'tabindex' => ++$tabindex, 'onClick' => 'this.select();']) ?>
|
||||
<?= form_input (['name' => 'amount_tendered', 'id' => 'amount_tendered', 'class' => 'form-input', 'disabled' => true, 'value' => to_currency_no_money($amount_due), 'size' => '5', 'tabindex' => ++$tabindex]) ?>
|
||||
<button type="submit" class="form-submit" id='add_payment_button' tabindex="<?= ++$tabindex ?>"><i class="bi bi-credit-card-fill"></i> Pagar</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
<?= form_close() ?>
|
||||
|
||||
<table class="sales_table_100" id="registersss">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 10%;"><?= lang('Common.delete') ?></th>
|
||||
<th style="width: 60%;"><?= lang(ucfirst($controller_name) .'.payment_type') ?></th>
|
||||
<th style="width: 20%;"><?= lang(ucfirst($controller_name) .'.payment_amount') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody id="payment_contents">
|
||||
<?php
|
||||
$payment_types = [];
|
||||
|
||||
foreach($payments as $payment_id => $payment)
|
||||
{
|
||||
$payment_types[] = $payment['payment_type'];
|
||||
?>
|
||||
<tr>
|
||||
<td><?= anchor("$controller_name/deletePayment/$payment_id", '<span class="glyphicon glyphicon-trash"></span>') ?></td>
|
||||
<td><?= esc($payment['payment_type']) ?></td>
|
||||
<td style="text-align: right;"><?= to_currency($payment['payment_amount']) ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
$payment_types_string = implode(', ', $payment_types);
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php
|
||||
if(count($cart) > 0)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user