@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))
@lang('lang_v1.lot_n_expiry')
@foreach($product->lot_numbers as $lot_number)
@php
$selected = "";
if($lot_number->purchase_line_id == $lot_no_line_id){
$selected = "selected";
$max_qty_rule = $lot_number->qty_available;
$max_qty_msg = __('lang_v1.quantity_error_msg_in_lot', ['qty'=> $lot_number->qty_formated, 'unit' => $product->unit ]);
}
$expiry_text = '';
if($exp_enabled == 1 && !empty($lot_number->exp_date)){
if( \Carbon::now()->gt(\Carbon::createFromFormat('Y-m-d', $lot_number->exp_date)) ){
$expiry_text = '(' . __('report.expired') . ')';
}
}
@endphp
@if(!empty($lot_number->lot_number) && $lot_enabled == 1){{$lot_number->lot_number}} @endif @if($lot_enabled == 1 && $exp_enabled == 1) - @endif @if($exp_enabled == 1 && !empty($lot_number->exp_date)) @lang('product.exp_date'): {{@format_date($lot_number->exp_date)}} @endif {{$expiry_text}}
@endforeach
@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))
@foreach($sub_units as $key => $value)
sub_unit_id) && $product->sub_unit_id == $key) selected @endif>
{{$value['name']}}
@endforeach
@else
{{$product->unit}}
@endif