@php
$tax_status = session()->get('tax_status', 'active');
$hide_tax = session()->get('business.enable_inline_tax') == 1 ? '' : 'hide';
// If tax is disabled, override hide_tax to always hide tax-related fields
if($tax_status == 'disabled') {
$hide_tax = 'hide';
$tax_id = null;
$item_tax = 0;
$unit_price_inc_tax = $product->default_sell_price; // Use price without tax
} else {
$tax_id = $product->tax_id;
$item_tax = !empty($product->item_tax) ? $product->item_tax : 0;
$unit_price_inc_tax = $product->sell_price_inc_tax;
}
@endphp
@php
$common_settings = session()->get('business.common_settings');
$multiplier = 1;
$action = !empty($action) ? $action : '';
@endphp
@foreach($sub_units as $key => $value)
@if(!empty($product->sub_unit_id) && $product->sub_unit_id == $key)
@php
$multiplier = $value['multiplier'];
@endphp
@endif
@endforeach
@php
$tax_amount = 0;
if(session()->get('business.enable_inline_tax') == 1) {
// Calculate the tax amount as the difference between price including tax and default price
$tax_amount = ($product->sell_price_inc_tax - $product->default_sell_price) * $product->quantity_ordered;
}
@endphp
@php
$total_tax_amount = 0;
// Force reload the product with discounts to get the correct data
$product_with_discounts = \App\Product::with(['discounts'])->find($product->product_id);
// Get discount_allowed as boolean
$discount_allowed = false;
if($product_with_discounts) {
if(isset($product_with_discounts->discount_allowed)) {
if(is_bool($product_with_discounts->discount_allowed)) {
$discount_allowed = $product_with_discounts->discount_allowed;
} else {
$discount_allowed = (int)$product_with_discounts->discount_allowed === 1 || $product_with_discounts->discount_allowed === '1';
}
}
}
// If there's a discount applied, discount is allowed
if(!empty($discount)) {
$discount_allowed = true;
}
// Get discounts
$product_discounts = collect();
$discounts_data = [];
$discounts_json = '[]';
if($discount_allowed && $product_with_discounts) {
$product_discounts = $product_with_discounts->discounts ?? collect();
$discounts_data = $product_discounts->toArray();
// 🔥 FIX: Multiply discount quantities by the multiplier
$adjusted_discounts = [];
foreach($discounts_data as $discount) {
$adjusted_discount = $discount;
// Convert from_quantity to base unit by multiplying by multiplier
if(isset($discount['from_quantity'])) {
$adjusted_discount['from_quantity'] = $discount['from_quantity'] * $multiplier;
}
if(isset($discount['to_quantity']) && !is_null($discount['to_quantity'])) {
$adjusted_discount['to_quantity'] = $discount['to_quantity'] * $multiplier;
}
// 🔥 FIX: Also multiply discount amount for fixed discounts
if(isset($discount['discount_type']) && $discount['discount_type'] == 'fixed' && isset($discount['discount_amount'])) {
$adjusted_discount['discount_amount'] = $discount['discount_amount'] * $multiplier;
}
$adjusted_discounts[] = $adjusted_discount;
}
$discounts_data = $adjusted_discounts;
$discounts_json = json_encode($adjusted_discounts);
// If no discounts in relationship, try direct query
if($product_discounts->count() == 0) {
try {
$product_discounts = \App\ProductDiscount::where('product_id', $product->product_id)
->orderBy('from_quantity', 'asc')
->get();
$discounts_data = $product_discounts->toArray();
// 🔥 FIX: Multiply discount quantities and amounts by the multiplier
$adjusted_discounts = [];
foreach($discounts_data as $discount) {
$adjusted_discount = $discount;
if(isset($discount['from_quantity'])) {
$adjusted_discount['from_quantity'] = $discount['from_quantity'] * $multiplier;
}
if(isset($discount['to_quantity']) && !is_null($discount['to_quantity'])) {
$adjusted_discount['to_quantity'] = $discount['to_quantity'] * $multiplier;
}
if(isset($discount['discount_type']) && $discount['discount_type'] == 'fixed' && isset($discount['discount_amount'])) {
$adjusted_discount['discount_amount'] = $discount['discount_amount'] * $multiplier;
}
$adjusted_discounts[] = $adjusted_discount;
}
$discounts_data = $adjusted_discounts;
$discounts_json = json_encode($adjusted_discounts);
} catch(\Exception $e) {
Log::error('Failed to fetch discounts: ' . $e->getMessage());
}
}
}
// Get global discount info
$global_discount_type = !empty($discount) ? $discount->discount_type : 'fixed';
$global_discount_amount = !empty($discount) ? $discount->discount_amount : 0;
$has_global_discount = !empty($discount);
$base_price = $product->sell_price_inc_tax;
// 🔥 FIX: Fetch unit prices directly from the units table using the unit ID
$unit_prices = [];
$unit_prices_data = [];
foreach($sub_units as $key => $value) {
// Try to get unit price from the value array first
$unit_price = isset($value['unit_price']) && !empty($value['unit_price'])
? (float)$value['unit_price']
: null;
// If no unit price in the array, try to fetch from database using the unit ID
if(is_null($unit_price) || $unit_price == 0) {
try {
$unit = \App\Unit::find($key);
if($unit && !empty($unit->unit_price)) {
$unit_price = (float)$unit->unit_price;
}
} catch(\Exception $e) {
Log::error('Failed to fetch unit price for unit ID ' . $key . ': ' . $e->getMessage());
}
}
$unit_prices[$key] = $unit_price;
$unit_prices_data[$key] = [
'unit_id' => $key,
'unit_name' => $value['name'] ?? 'Unknown',
'unit_price' => $unit_price,
'multiplier' => $value['multiplier'] ?? 1,
'has_price' => !is_null($unit_price) && $unit_price > 0
];
}
// 🔥 Check if a price group is active (only if it's a valid ID, not '0' or empty)
$has_price_group = false;
$price_group_id = null;
if(!empty($price_group) && $price_group != '0' && $price_group != 0) {
$has_price_group = true;
$price_group_id = $price_group;
}
// Also check if there's a hidden price group from the form
if(!$has_price_group && !empty(request()->input('price_group')) && request()->input('price_group') != '0') {
$has_price_group = true;
$price_group_id = request()->input('price_group');
}
// Check session for price group
if(!$has_price_group && session()->has('price_group_id') && session()->get('price_group_id') != '0') {
$has_price_group = true;
$price_group_id = session()->get('price_group_id');
}
// Log for debugging
Log::info('Product Row Debug - RELOADED', [
'product_id' => $product->product_id,
'product_name' => $product->product_name,
'discount_allowed' => $discount_allowed,
'has_global_discount' => $has_global_discount,
'global_discount_type' => $global_discount_type,
'global_discount_amount' => $global_discount_amount,
'discounts_count' => count($product_discounts),
'discounts' => $discounts_data,
'base_price' => $base_price,
'discounts_json' => $discounts_json,
'multiplier' => $multiplier,
'unit_prices' => $unit_prices_data,
'has_price_group' => $has_price_group,
'price_group_id' => $price_group_id,
]);
@endphp
@if(!empty($so_line))
@endif
@php
$product_name = $product->product_name;
if(!empty($product->brand)){ $product_name .= ' ' . $product->brand; }
@endphp
@php
$hide_tax = session()->get('business.enable_inline_tax') == 1 ? '' : 'hide';
$tax_id = $product->tax_id;
$item_tax = !empty($product->item_tax) ? $product->item_tax : 0;
$unit_price_inc_tax = $product->sell_price_inc_tax;
if($hide_tax == 'hide'){
$tax_id = null;
$unit_price_inc_tax = $product->default_sell_price;
}
if(!empty($so_line) && $action !== 'edit') {
$tax_id = $so_line->tax_id;
$item_tax = $so_line->item_tax;
$unit_price_inc_tax = $so_line->unit_price_inc_tax;
}
$discount_type = !empty($product->line_discount_type) ? $product->line_discount_type : 'fixed';
$discount_amount = !empty($product->line_discount_amount) ? $product->line_discount_amount : 0;
if(!empty($discount)) {
$discount_type = $discount->discount_type;
$discount_amount = $discount->discount_amount;
}
if(!empty($so_line) && $action !== 'edit') {
$discount_type = $so_line->line_discount_type;
$discount_amount = $so_line->line_discount_amount;
}
$sell_line_note = !empty($product->sell_line_note) ? $product->sell_line_note : '';
if(!empty($so_line)){
$sell_line_note = $so_line->sell_line_note;
}
$warranty_id = !empty($action) && $action == 'edit' && !empty($product->warranties->first()) ? $product->warranties->first()->id : $product->warranty_id;
if($discount_type == 'fixed') {
$discount_amount = $discount_amount * $multiplier;
}
$max_quantity = $product->qty_available;
$formatted_max_quantity = $product->formatted_qty_available;
if(!empty($action) && $action == 'edit' && !empty($so_line)) {
$qty_available = $so_line->quantity - $so_line->so_quantity_invoiced + $product->quantity_ordered;
$max_quantity = $qty_available;
$formatted_max_quantity = number_format($qty_available, session('business.quantity_precision', 2), session('currency')['decimal_separator'], session('currency')['thousand_separator']);
} elseif(!empty($so_line) && $so_line->qty_available <= $max_quantity) {
$max_quantity = $so_line->qty_available;
$formatted_max_quantity = $so_line->formatted_qty_available;
}
$max_qty_rule = $max_quantity;
$max_qty_msg = __('validation.custom-messages.quantity_not_available', ['qty'=> $formatted_max_quantity, 'unit' => $product->unit]);
$lot_enabled = session()->get('business.enable_lot_number');
$exp_enabled = session()->get('business.enable_product_expiry');
$lot_no_line_id = !empty($product->lot_no_line_id) ? $product->lot_no_line_id : '';
@endphp
@if(!empty($discount))
{!! Form::hidden("products[$row_count][discount_id]", $discount->id); !!}
@endif
@if( ($edit_price || $edit_discount) && empty($is_direct_sell) )
{!! $product_name !!}
@else
{!! $product_name !!}
@endif
{{-- Lot Number & Expiry Inline --}}
@if(!empty($product->lot_numbers) && empty($is_sales_order))
transaction_sell_lines_id)) disabled @endif>
@lang('lang_v1.lot_n_expiry')
@foreach($product->lot_numbers as $lot_number)
@php
$selected = ($lot_number->purchase_line_id == $lot_no_line_id || (!empty($purchase_line_id) && $purchase_line_id == $lot_number->purchase_line_id)) ? "selected" : "";
$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') . ')';
}
}
if($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]);
}
@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
{{-- Serial Number Display with Quantity Info --}}
@if(!empty($product->matched_serial_number))
SN: {{ $product->matched_serial_number }}
@if(!empty($product->serial_number_id))
@endif
@endif
{{-- Product Price Modal --}}
@if(empty($is_direct_sell))
@include('sale_pos.partials.row_edit_product_price_modal')
@endif
{{-- Modifiers --}}
@if(in_array('modifiers', $enabled_modules))
@if(!empty($product->product_ms))
@include('restaurant.product_modifier_set.modifier_for_product', ['edit_modifiers' => true, 'row_count' => $loop->index, 'product_ms' => $product->product_ms])
@endif
@endif
{{-- Direct sell note --}}
@if(!empty($is_direct_sell))
@lang('lang_v1.sell_line_description_help')
@endif
{{-- 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
@php
$allow_decimal = true;
if($product->unit_allow_decimal != 1) {
$allow_decimal = false;
}
@endphp
@foreach($sub_units as $key => $value)
@if(!empty($product->sub_unit_id) && $product->sub_unit_id == $key)
@php
$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
matched_serial_number) && !empty($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('Quantity Exceeded', ['qty' => $product->serial_number_available])"
data-msg_max_default="@lang('Quantity Exceeded', ['qty' => $product->serial_number_available])"
style="border-color: #17a2b8;"
@elseif($product->enable_stock && empty($pos_settings['allow_overselling']) && empty($is_sales_order))
data-rule-max-value="{{$max_qty_rule}}"
data-qty_available="{{$product->qty_available}}"
data-msg-max-value="{{$max_qty_msg}}"
data-msg_max_default="@lang('validation.custom-messages.quantity_not_available', ['qty'=> $product->formatted_qty_available, 'unit' => $product->unit])"
@endif
>
@if(count($sub_units) > 0)
@foreach($sub_units as $key => $value)
@php
// 🔥 FIX: Get the unit price from the database using the unit ID
$unit_price = null;
// First check if it's in the value array
if(isset($value['unit_price']) && !empty($value['unit_price'])) {
$unit_price = (float)$value['unit_price'];
} else {
// If not, try to fetch from database
try {
$unit = \App\Unit::find($key);
if($unit && !empty($unit->unit_price)) {
$unit_price = (float)$unit->unit_price;
}
} catch(\Exception $e) {
// Silently fail
}
}
// Check if this is the default unit
$is_default = !empty($product->sub_unit_id) && $product->sub_unit_id == $key;
// Calculate the calculated price for display
$calculated_price = $product->sell_price_inc_tax * $value['multiplier'];
@endphp
{{$value['name']}}
@if($unit_price)
@else
@endif
@endforeach
@else
{{$product->unit}}
@endif
@if(count($sub_units) > 0)
@foreach($sub_units as $key => $value)
@php
// 🔥 FIX: Get the unit price from the database using the unit ID
$unit_price = null;
// First check if it's in the value array
if(isset($value['unit_price']) && !empty($value['unit_price'])) {
$unit_price = (float)$value['unit_price'];
} else {
// If not, try to fetch from database
try {
$unit = \App\Unit::find($key);
if($unit && !empty($unit->unit_price)) {
$unit_price = (float)$unit->unit_price;
}
} catch(\Exception $e) {
// Silently fail
}
}
// Check if this is the default unit
$is_default = !empty($product->sub_unit_id) && $product->sub_unit_id == $key;
// Calculate the calculated price for display
$calculated_price = $product->sell_price_inc_tax * $value['multiplier'];
@endphp
{{$value['name']}}
@if($unit_price)
@else
@endif
@endforeach
@else
{{$product->unit}}
@endif
@if(!empty($product->second_unit))
@lang('lang_v1.quantity_in_second_unit', ['unit' => $product->second_unit])*:
@endif
{{-- Hidden fields for combo products --}}
@if($product->product_type == 'combo' && !empty($product->combo_products))
@foreach($product->combo_products as $k => $combo_product)
@if(isset($action) && $action == 'edit')
@php
$combo_product['qty_required'] = $combo_product['quantity'] / $product->quantity_ordered;
$qty_total = $combo_product['quantity'];
@endphp
@else
@php
$qty_total = $combo_product['qty_required'];
@endphp
@endif
@if(isset($action) && $action == 'edit')
@endif
@endforeach
@endif
@if(!empty($is_direct_sell))
@if(!empty($pos_settings['inline_service_staff']))
@endif
@php
$pos_unit_price = !empty($product->unit_price_before_discount) ? $product->unit_price_before_discount : $product->default_sell_price;
if(!empty($so_line) && $action !== 'edit') {
$pos_unit_price = $so_line->unit_price_before_discount;
}
@endphp
@if(!empty($last_sell_line))
@lang('lang_v1.prev_unit_price'): @format_currency($last_sell_line->unit_price_before_discount)
@endif
{!! Form::text("products[$row_count][line_discount_amount]", @num_format($discount_amount), ['class' => 'form-control input_number row_discount_amount']); !!}
{!! Form::select("products[$row_count][line_discount_type]", ['fixed' => __('lang_v1.fixed'), 'percentage' => __('lang_v1.percentage')], $discount_type , ['class' => 'form-control row_discount_type']); !!}
@if(!empty($discount))
{!! __('lang_v1.applied_discount_text', ['discount_name' => $discount->name, 'starts_at' => $discount->formated_starts_at, 'ends_at' => $discount->formated_ends_at]) !!}
@endif
@if(!empty($last_sell_line))
@lang('lang_v1.prev_discount'):
@if($last_sell_line->line_discount_type == 'percentage')
{{@num_format($last_sell_line->line_discount_amount)}}%
@else
@format_currency($last_sell_line->line_discount_amount)
@endif
@endif
{!! Form::hidden("products[$row_count][item_tax]", @num_format($item_tax), ['class' => 'item_tax']); !!}
{!! Form::select("products[$row_count][tax_id]", $tax_dropdown['tax_rates'], $tax_id, [
'placeholder' => 'Select',
'class' => 'form-control tax_id',
'disabled' => $tax_status == 'disabled' ? 'disabled' : ''
], $tax_dropdown['attributes']); !!}
@else
@if(!empty($pos_settings['inline_service_staff']))
@endif
@endif
{{-- Unit price including tax column --}}
{{-- Unit price including tax column --}}
@php
// Get the default purchase price from the variation
$default_purchase_price = 0;
if(!empty($product->variation_id)) {
$variation = \App\Variation::find($product->variation_id);
if($variation && isset($variation->default_purchase_price)) {
$default_purchase_price = $variation->default_purchase_price;
}
}
// Fallback: if still 0, try to get from the product's variations relationship
if($default_purchase_price == 0 && !empty($product->variations) && $product->variations->count() > 0) {
$default_purchase_price = $product->variations->first()->default_purchase_price ?? 0;
}
@endphp
@if (empty($pos_settings['show_margin']))
@php
// Get the profit_percent from the product object
$profit_percent = $product->profit_percent ?? 0;
// If not set, try to get from variation
if(empty($profit_percent) && !empty($product->variations) && $product->variations->count() > 0) {
$profit_percent = $product->variations->first()->profit_percent ?? 0;
}
// Check if we have a price group that might affect profit
$has_price_group = $product->has_price_group ?? false;
$price_group_id = $product->price_group_id ?? null;
@endphp
@endif
@if(!empty($common_settings['enable_product_warranty']) && !empty($is_direct_sell))
{!! Form::select("products[$row_count][warranty_id]", $warranties, $warranty_id, ['placeholder' => __('messages.please_select'), 'class' => 'form-control']); !!}
@endif
@php
$subtotal_type = !empty($pos_settings['is_pos_subtotal_editable']) ? 'text' : 'hidden';
@endphp
{{$product->quantity_ordered*$unit_price_inc_tax}}
@if(session()->get('business.enable_inline_tax') == 1)
@endif