@php $max_qty_rule = $product->qty_available; $formatted_max_quantity = $product->formatted_qty_available; $max_qty_msg = __('validation.custom-messages.quantity_not_available', ['qty'=> $formatted_max_quantity, 'unit' => $product->unit ]); $allow_decimal = true; $has_serial_error = false; // If this product has a serial number, query DB for available quantity if(!empty($product->matched_serial_number) && !empty($product->serial_number_id)) { try { $business_id = session()->get('user.business_id'); $serial_number_id = $product->serial_number_id; // ============================================================ // GET SERIAL NUMBER DETAILS WITH TRANSFERRED QUANTITY DEDUCTION // ============================================================ // Get total quantity from product_serial_numbers $serialData = DB::table('product_serial_numbers') ->where('id', $serial_number_id) ->where('business_id', $business_id) ->first(); if ($serialData) { $total_quantity = $serialData->quantity; // Get transferred quantity (if this serial number was transferred to another location) $transferredData = DB::table('product_serial_numbers') ->where('source_serial_id', $serial_number_id) ->where('type', 'transfer') ->select(DB::raw('SUM(quantity) as total_transferred')) ->first(); $transferred_quantity = $transferredData->total_transferred ?? 0; // Get sold quantity from completed sales $soldData = DB::table('transaction_sell_lines as tsl') ->join('transactions as t', 'tsl.transaction_id', '=', 't.id') ->where('tsl.serial_number_id', $serial_number_id) ->where('t.business_id', $business_id) ->where('t.type', 'sell') ->where('t.status', 'completed') ->select(DB::raw('SUM(tsl.quantity - IFNULL(tsl.quantity_returned, 0)) as total_sold')) ->first(); $total_sold = $soldData->total_sold ?? 0; // ============================================================ // AVAILABLE QUANTITY = TOTAL - TRANSFERRED - SOLD // ============================================================ $available_quantity = max(0, $total_quantity - $transferred_quantity - $total_sold); // Update the product object $product->serial_number_quantity = $total_quantity; $product->serial_number_transferred = $transferred_quantity; $product->serial_number_available = $available_quantity; $max_qty_rule = $available_quantity; $formatted_max_quantity = number_format($available_quantity, 2); $max_qty_msg = __('Quantity cannot exceed :qty for this serial number', ['qty'=> $formatted_max_quantity]); // Check if quantity exceeds available if(!empty($product->quantity_ordered) && $product->quantity_ordered > $available_quantity) { $has_serial_error = true; } } } catch (\Exception $e) { // Log error but continue \Log::error('Failed to get serial number quantity: ' . $e->getMessage()); } } @endphp {{$product->product_name}}
{{$product->sub_sku}} {{-- Display serial number if present --}} @if(!empty($product->matched_serial_number)) SN: {{ $product->matched_serial_number }} @endif @if( session()->get('business.enable_lot_number') == 1 || session()->get('business.enable_product_expiry') == 1) @php $lot_enabled = session()->get('business.enable_lot_number'); $exp_enabled = session()->get('business.enable_product_expiry'); $lot_no_line_id = ''; if(!empty($product->lot_no_line_id)){ $lot_no_line_id = $product->lot_no_line_id; } @endphp @if($product->enable_stock == 1)
@lang('report.current_stock'): {{$product->formatted_qty_available}} {{ $product->unit }} @endif @if(!empty($product->lot_numbers)) @endif @endif @php if(empty($product->quantity_ordered)) { $product->quantity_ordered = 1; } $multiplier = 1; if($product->unit_allow_decimal != 1) { $allow_decimal = false; } $qty_ordered = $product->quantity_ordered; @endphp @foreach($sub_units as $key => $value) @if(!empty($product->sub_unit_id) && $product->sub_unit_id == $key) @php $multiplier = $value['multiplier']; $max_qty_rule = $max_qty_rule / $multiplier; $unit_name = $value['name']; $max_qty_msg = __('validation.custom-messages.quantity_not_available', ['qty'=> $max_qty_rule, 'unit' => $unit_name ]); if(!empty($product->lot_no_line_id)){ $max_qty_msg = __('lang_v1.quantity_error_msg_in_lot', ['qty'=> $max_qty_rule, 'unit' => $unit_name ]); } if($value['allow_decimal']) { $allow_decimal = true; } @endphp @endif @endforeach @php $qty_ordered = $product->quantity_ordered / $multiplier; @endphp {{-- If edit then transaction sell lines will be present --}} @if(!empty($product->transaction_sell_lines_id)) @endif @if(empty($product->quantity_ordered)) @php $product->quantity_ordered = 1; @endphp @endif
unit_allow_decimal == 1) data-decimal=1 @else data-rule-abs_digit="true" data-msg-abs_digit="@lang('lang_v1.decimal_value_not_allowed')" data-decimal=0 @endif data-rule-required="true" data-msg-required="@lang('validation.custom-messages.this_field_is_required')" @if($product->enable_stock) data-rule-max-value="{{$max_qty_rule}}" data-msg-max-value="{{$max_qty_msg}}" data-qty-available="{{$product->qty_available}}" data-msg_max_default="@lang('validation.custom-messages.quantity_not_available', ['qty'=> $product->formatted_qty_available, 'unit' => $product->unit ])" @endif @if(!empty($product->matched_serial_number) && isset($product->serial_number_available)) data-serial-number="true" data-serial-max-qty="{{ $product->serial_number_available }}" data-rule-max-value="{{ $product->serial_number_available }}" data-msg-max-value="@lang('Available :qty available', ['qty' => $product->serial_number_available])" style="border-color: #17a2b8;" data-serial-available="{{ $product->serial_number_available }}" @endif >
{{-- Serial number quantity warning --}} @if(!empty($product->matched_serial_number) && isset($product->serial_number_available)) @if($has_serial_error)
Quantity cannot exceed {{ $product->serial_number_available }} for this serial number
@endif @endif @if(!empty($sub_units))
@else {{$product->unit}} @endif