} if ($request->partial_payment && !Helpers::get_business_settings('partial_payment_status')) { return response()->json([ 'errors' => [ ['code' => 'order_method', 'message' => translate('messages.partial_payment_is_not_active')] ] ]); } if ($request->payment_method == 'offline_payment' && Helpers::get_mail_status('offline_payment_status') == 0) { return response()->json([ 'errors' => [ ['code' => 'offline_payment_status', 'message' => translate('messages.offline_payment_for_the_order_not_available_at_this_time')] ] ]); } $digital_payment = Helpers::get_business_settings('digital_payment'); if ($digital_payment['status'] == 0 && $request->payment_method == 'digital_payment') { return response()->json([ 'errors' => [ ['code' => 'digital_payment', 'message' => translate('messages.digital_payment_for_the_order_not_available_at_this_time')] ] ]); } $data = DMVehicle::active()->where(function ($query) use ($distance_data) { $query->where('starting_coverage_area', '<=', $distance_data)->where('maximum_coverage_area', '>=', $distance_data) ->orWhere(function ($query) use ($distance_data) { $query->where('starting_coverage_area', '>=', $distance_data); }); }) ->orderBy('starting_coverage_area')->first(); $extra_charges = (float) (isset($data) ? $data->extra_charges : 0); $vehicle_id = (isset($data) ? $data->id : null); $zone = null; if ($request->latitude[$key] && $request->longitude[$key]) { $point = new Point($request->latitude[$key], $request->longitude[$key]); if ($request->order_type == 'parcel') { // if(isset($request->sender_zone_id) ){ // $zone_id = $request->sender_zone_id; $zone_ids = $request->header('zoneId') ? json_decode($request->header('zoneId'), true) : []; $zone = Zone::whereIn('id', $zone_ids)->whereContains('coordinates', new Point($request->latitude[$key], $request->longitude[$key], POINT_SRID))->wherehas('modules', function ($q) { $q->where('module_type', 'parcel'); })->first(); } else { // ->selectRaw('*, IF(((select count(*) from `store_schedule` where `stores`.`id` = `store_schedule`.`store_id` and `store_schedule`.`day` = ' . $schedule_at->format('w') . ' and `store_schedule`.`opening_time` < "' . $schedule_at->format('H:i:s') . '" and `store_schedule`.`closing_time` >"' . $schedule_at->format('H:i:s') . '") > 0), true, false) as open') $store = Store::with('discount')->where('id', $request->store_id)->first(); if (!$store) { return response()->json([ 'errors' => [ ['code' => 'order_time', 'message' => translate('messages.store_not_found')] ] ]); } $zone_id = [$store->zone_id]; $zone = Zone::where('id', $zone_id)->whereContains('coordinates', new Point($request->latitude[$key], $request->longitude[$key], POINT_SRID))->first(); } } if (!$zone) { $errors = []; array_push($errors, ['code' => 'coordinates', 'message' => translate('messages.out_of_coverage')]); return response()->json([ 'errors' => $errors ]); } if ($zone && $zone->increased_delivery_fee_status == 1) { $increased = $zone->increased_delivery_fee ?? 0; } if ($request->order_type !== 'parcel') { if (!$store->active) { return response()->json([ 'errors' => [ ['code' => 'order_time', 'message' => translate('messages.store_is_closed_at_order_time')] ] ]); } if ($request->coupon_code) { $coupon = Coupon::active()->where(['code' => $request->coupon_code])->first(); if (isset($coupon)) { $staus = CouponLogic::is_valide($coupon, $user->id, $request->store_id); if ($staus == 407) { return response()->json([ 'errors' => [ ['code' => 'coupon', 'message' => translate('messages.coupon_expire')] ] ]); } else if ($staus == 408) { return response()->json([ 'errors' => [ ['code' => 'coupon', 'message' => translate('messages.You_are_not_eligible_for_this_coupon')] ] ]); } else if ($staus == 406) { return response()->json([ 'errors' => [ ['code' => 'coupon', 'message' => translate('messages.coupon_usage_limit_over')] ] ]); } else if ($staus == 404) { return response()->json([ 'errors' => [ ['code' => 'coupon', 'message' => translate('messages.not_found')] ] ]); } $coupon_created_by = $coupon->created_by; if ($coupon->coupon_type == 'free_delivery') { $delivery_charge = 0; $free_delivery_by = $coupon_created_by; $coupon_created_by = null; } } else { return response()->json([ 'errors' => [ ['code' => 'coupon', 'message' => translate('messages.not_found')] ] ], 404); } } $module_wise_delivery_charge = $store->zone->modules()->where('modules.id', 5)->first(); if ($module_wise_delivery_charge) { $per_km_shipping_charge = $module_wise_delivery_charge->pivot->per_km_shipping_charge; $minimum_shipping_charge = $module_wise_delivery_charge->pivot->minimum_shipping_charge; $maximum_shipping_charge = $module_wise_delivery_charge->pivot->maximum_shipping_charge; } else { $per_km_shipping_charge = (float)BusinessSetting::where(['key' => 'per_km_shipping_charge'])->first()->value; $minimum_shipping_charge = (float)BusinessSetting::where(['key' => 'minimum_shipping_charge'])->first()->value; } if ($request->order_type != 'take_away' && !$store->free_delivery && !isset($delivery_charge) && $store->self_delivery_system == 1) { $per_km_shipping_charge = $store->per_km_shipping_charge; $minimum_shipping_charge = $store->minimum_shipping_charge; $maximum_shipping_charge = $store->maximum_shipping_charge; $extra_charges = 0; $vehicle_id = null; $increased = 0; } if ($store->free_delivery || $free_delivery_by == 'vendor') { $per_km_shipping_charge = $store->per_km_shipping_charge; $minimum_shipping_charge = $store->minimum_shipping_charge; $maximum_shipping_charge = $store->maximum_shipping_charge; $extra_charges = 0; $increased = 0; } $original_delivery_charge = (($request->distance * $per_km_shipping_charge) > $minimum_shipping_charge) ? $request->distance * $per_km_shipping_charge : $minimum_shipping_charge; if ($request->order_type == 'take_away') { $per_km_shipping_charge = 0; $minimum_shipping_charge = 0; $maximum_shipping_charge = 0; $extra_charges = 0; $distance_data = 0; $vehicle_id = null; $original_delivery_charge = 0; $increased = 0; } if ($maximum_shipping_charge >= $minimum_shipping_charge && $original_delivery_charge > $maximum_shipping_charge) { $original_delivery_charge = $maximum_shipping_charge; } else { $original_delivery_charge = $original_delivery_charge; } if (!isset($delivery_charge)) { $delivery_charge = ($request->distance * $per_km_shipping_charge > $minimum_shipping_charge) ? $request->distance * $per_km_shipping_charge : $minimum_shipping_charge; if ($maximum_shipping_charge >= $minimum_shipping_charge && $delivery_charge > $maximum_shipping_charge) { $delivery_charge = $maximum_shipping_charge; } else { $delivery_charge = $delivery_charge; } } $original_delivery_charge = $original_delivery_charge + $extra_charges; $delivery_charge = $delivery_charge + $extra_charges; } else { $parcel_category = ParcelCategory::findOrFail($request->parcel_category_id); if (isset($parcel_category) && isset($parcel_category->parcel_minimum_shipping_charge)) { $per_km_shipping_charge = $parcel_category->parcel_per_km_shipping_charge; $minimum_shipping_charge = $parcel_category->parcel_minimum_shipping_charge; } else { $per_km_shipping_charge = (float)BusinessSetting::where(['key' => 'parcel_per_km_shipping_charge'])->first()->value; $minimum_shipping_charge = (float)BusinessSetting::where(['key' => 'parcel_minimum_shipping_charge'])->first()->value; } $original_delivery_charge = (($request->distance * $per_km_shipping_charge) > $minimum_shipping_charge) ? ($request->distance * $per_km_shipping_charge) + $extra_charges : ($minimum_shipping_charge + $extra_charges); } if ($increased > 0) { if ($delivery_charge > 0) { $increased_fee = ($delivery_charge * $increased) / 100; $delivery_charge = $delivery_charge + $increased_fee; } if ($original_delivery_charge > 0) { $increased_fee = ($original_delivery_charge * $increased) / 100; $original_delivery_charge = $original_delivery_charge + $increased_fee; } } $address = [ 'contact_person_name' => $request->contact_person_name[$key] ? $request->contact_person_name[$key] : ($user ? $user->f_name . ' ' . $user->f_name : ''), 'contact_person_number' => $request->contact_person_number[$key] ? ($user ? $request->contact_person_number[$key] : str_replace('+', '', $request->contact_person_number[$key])) : ($user ? $user->phone : ''), 'contact_person_email' => $user ? $user->email : '', 'address_type' => $request->address_type ? $request->address_type : 'Delivery', 'address' => $request?->address[$key] ?? '', 'floor' => $request?->floor[$key] ?? '', 'road' => $request?->road[$key] ?? '', 'house' => $request?->house[$key] ?? '', 'longitude' => (string)$request->longitude[$key], 'latitude' => (string)$request->latitude[$key], ]; $total_addon_price = 0; $product_price = 0; $store_discount_amount = 0; $flash_sale_vendor_discount_amount = 0; $flash_sale_admin_discount_amount = 0; $store_discount_amount = 0; $product_data = []; $order_details = []; $order = new Order(); $lastOrder = Order::orderBy('id', 'desc')->first(); if ($lastOrder) { $order->id = $lastOrder->id + 1; } else { $order->id = 10001; } $order->invoice_id = _generateOrderInvoiceId($request->store_id); $order_status = 'pending'; if (($request->partial_payment && $request->payment_method != 'offline_payment') || $request->payment_method == 'wallet') { $order_status = 'confirmed'; } $order->user_id = $user ? $user->id : 0; $order->order_amount = $request->order_amount; $order->payment_status = ($request->partial_payment ? 'partially_paid' : ($request->payment_method == 'wallet' ? 'paid' : 'unpaid')); $order->order_status = $order_status; $order->coupon_code = $request->coupon_code; $order->payment_method = $request->partial_payment ? 'partial_payment' : $request->payment_method; $order->transaction_reference = null; $order->order_note = $request->order_note; $order->unavailable_item_note = $request->unavailable_item_note; $order->delivery_instruction = $request->delivery_instruction; $order->order_type = $request->order_type; $order->store_id = $request->store_id; if ($store->delivery_charges_on && $store->delivery_charges_on <= $request->order_amount) { $order->delivery_charge = 0; } else { $order->delivery_charge = round($delivery_charge, config('round_up_to_digit')) ?? 0; } $order->original_delivery_charge = round($original_delivery_charge, config('round_up_to_digit')); $order->delivery_address = json_encode($address); $order->schedule_at = $schedule_at; $order->scheduled = $request->schedule_at ? 1 : 0; $order->cutlery = $request->cutlery ? 1 : 0; $order->is_guest = $user ? 0 : 1; $order->otp = rand(1000, 9999); $order->zone_id = isset($zone) ? $zone->id : end(json_decode($this->zone_id, true)); $order->module_id = 5; $order->parcel_category_id = $request->parcel_category_id; $order->receiver_details = json_decode($request->receiver_details); if ($order_status == 'confirmed') { $order->confirmed = now(); } $order->dm_vehicle_id = $vehicle_id; $order->pending = now(); $order->order_attachment = $request->has('order_attachment') ? Helpers::upload('order/', 'png', $request->file('order_attachment')) : null; $order->distance = $distance_data; $order->created_at = now(); $order->updated_at = now(); $order->charge_payer = null; //Added DM TIPS $dm_tips_manage_status = BusinessSetting::where('key', 'dm_tips_status')->first()->value; if ($dm_tips_manage_status == 1) { $order->dm_tips = $request->dm_tips ?? 0; } else { $order->dm_tips = 0; } //Added service charge $additional_charge_status = BusinessSetting::where('key', 'additional_charge_status')->first()->value; $additional_charge = BusinessSetting::where('key', 'additional_charge')->first()->value; if ($additional_charge_status == 1) { $order->additional_charge = $additional_charge ?? 0; } else { $order->additional_charge = 0; } $carts = Cart::where('user_id', $order->user_id)->where('is_guest', 0)->where('module_id', 5) ->when(isset($request->is_buy_now) && $request->is_buy_now == 1 && $request->cart_id, function ($query) use ($request) { return $query->where('id', $request->cart_id); }) ->get()->map(function ($data) { $data->add_on_ids = json_decode($data->add_on_ids, true); $data->add_on_qtys = json_decode($data->add_on_qtys, true); $data->variation = json_decode($data->variation, true); return $data; }); if (isset($request->is_buy_now) && $request->is_buy_now == 1) { $carts = json_decode($request->cart, true); } if ($request->order_type !== 'parcel') { foreach ($carts as $c) { if ($c['item_type'] === 'App\Models\ItemCampaign' || $c['item_type'] === 'AppModelsItemCampaign') { $product = ItemCampaign::with('module')->active()->find($c['item_id']); if ($product) { if ($product->store_id != $order->store_id) { return response()->json([ 'errors' => [ ['code' => 'different_stores', 'message' => translate('messages.Please_select_items_from_the_same_store')] ] ], 403); } if ($product->module->module_type == 'food' && $product->food_variations) { $product_variations = json_decode($product->food_variations, true); $variations = []; if (count($product_variations)) { $variation_data = Helpers::get_varient($product_variations, $c['variation']); $price = $product['price'] + $variation_data['price']; $variations = $variation_data['variations']; } else { $price = $product['price']; } // $product->tax = $store->tax; $product = Helpers::product_data_formatting($product, false, false, app()->getLocale()); $addon_data = Helpers::calculate_addon_price(\App\Models\AddOn::whereIn('id', $c['add_on_ids'])->get(), $c['add_on_qtys']); $or_d = [ 'item_id' => null, 'item_campaign_id' => $c['item_id'], 'item_details' => json_encode($product), 'quantity' => $c['quantity'], 'price' => round($price, config('round_up_to_digit')), 'tax_amount' => Helpers::tax_calculate($product, $price), 'discount_on_item' => Helpers::product_discount_calculate($product, $price, $store)['discount_amount'], 'discount_type' => 'discount_on_product', 'variant' => json_encode($c['variant']), 'variation' => json_encode($variations), 'add_ons' => json_encode($addon_data['addons']), 'total_add_on_price' => $addon_data['total_add_on_price'], 'created_at' => now(), 'updated_at' => now() ]; $order_details[] = $or_d; $total_addon_price += $or_d['total_add_on_price']; $product_price += $price * $or_d['quantity']; $store_discount_amount += $or_d['discount_on_item'] * $or_d['quantity']; } else { if (count(json_decode($product['variations'], true)) > 0) { $variant_data = Helpers::variation_price($product, json_encode($c['variation'])); $price = $variant_data['price']; $stock = $variant_data['stock']; $mychitti_fee = $variant_data['price'] - $variant_data['askingprice']; } else { $price = $product['price']; $stock = $product->stock; $mychitti_fee = $product->mychitty_fee; } if (config('module.' . $product->module->module_type)['stock']) { if ($c['quantity'] > $stock) { return response()->json([ 'errors' => [ ['code' => 'campaign', 'message' => translate('messages.product_out_of_stock', ['item' => $product->title])] ] ]); } $product_data[] = [ 'item' => clone $product, 'quantity' => $c['quantity'], 'variant' => count($c['variation']) > 0 ? $c['variation'][0]['type'] : null ]; } // $product->tax = $store->tax; $product = Helpers::product_data_formatting($product, false, false, app()->getLocale()); $addon_data = Helpers::calculate_addon_price(\App\Models\AddOn::whereIn('id', $c['add_on_ids'])->get(), $c['add_on_qtys']); $or_d = [ 'item_id' => null, 'item_campaign_id' => $c['item_id'], 'item_details' => json_encode($product), 'quantity' => $c['quantity'], 'price' => $price, 'tax_amount' => Helpers::tax_calculate($product, $price), 'discount_on_item' => Helpers::product_discount_calculate($product, $price, $store)['discount_amount'], 'discount_type' => 'discount_on_product', 'variant' => json_encode($c['variant']), 'variation' => json_encode($c['variation']), 'add_ons' => json_encode($addon_data['addons']), 'total_add_on_price' => $addon_data['total_add_on_price'], 'platform_fee' => $mychitti_fee ?? 0, 'created_at' => now(), 'updated_at' => now() ]; $order_details[] = $or_d; $total_addon_price += $or_d['total_add_on_price']; $product_price += $price * $or_d['quantity']; $store_discount_amount += $or_d['discount_on_item'] * $or_d['quantity']; } } else { return response()->json([ 'errors' => [ ['code' => 'campaign', 'message' => translate('messages.product_unavailable_warning')] ] ]); } } else { $product = Item::hydrate( DB::table('items')->where('id', $c['item_id'])->get()->toArray() )->first(); if ($product) { if ($product->store_id != $order->store_id) { return response()->json([ 'errors' => [ ['code' => 'different_stores', 'message' => translate('messages.Please_select_items_from_the_same_store')] ] ]); } if ($product->maximum_cart_quantity && ($c['quantity'] > $product->maximum_cart_quantity)) { return response()->json([ 'errors' => [ ['code' => 'quantity', 'message' => translate('messages.maximum_cart_quantity_limit_over')] ] ]); } if ($product->module->module_type == 'food' && $product->food_variations) { $product_variations = json_decode($product->food_variations, true); $variations = []; if (count($product_variations)) { $variation_data = Helpers::get_varient($product_variations, $c['variation']); $mrpprice = $variation_data['mrpprice']; $price = $variation_data['mrpprice']; $variations = $variation_data['variations']; $mychitti_fee = $variation_data['price'] - $variation_data['askingprice']; } else { $mrpprice = $product['mrp_price'] ?? $product['price']; $price = $product['price']; $mychitti_fee = $product->mychitty_fee; } // $product->tax = $store->tax; $product = Helpers::product_data_formatting($product, false, false, app()->getLocale()); $addon_data = Helpers::calculate_addon_price(\App\Models\AddOn::whereIn('id', $c['add_on_ids'])->get(), $c['add_on_qtys']); $product_discount = Helpers::product_discount_calculate($product, $mrpprice, $store); $tax = _taxCalcluation($price, $product->tax)['gst_amount']; $taxable = _taxCalcluation($price, $product->tax)['price_excluding_gst']; $or_d = [ 'item_id' => $c['item_id'], 'item_campaign_id' => null, 'item_details' => json_encode($product), 'quantity' => $c['quantity'], 'price' => $price, 'tax_amount' => $tax, 'taxable_amount' => $taxable, 'discount_on_item' => $product_discount['discount_amount'], 'discount_type' => $product_discount['discount_type'], 'variant' => json_encode($c['variant']), 'variation' => json_encode($variations), 'platform_fee' => $mychitti_fee ?? 0, 'add_ons' => json_encode($addon_data['addons']), 'total_add_on_price' => round($addon_data['total_add_on_price'], config('round_up_to_digit')), 'created_at' => now(), 'updated_at' => now() ]; $total_addon_price += $or_d['total_add_on_price']; $product_price += $price * $or_d['quantity']; $store_discount_amount += $or_d['discount_type'] != 'flash_sale' ? $or_d['discount_on_item'] * $or_d['quantity'] : 0; $flash_sale_admin_discount_amount += $or_d['discount_type'] == 'flash_sale' ? $product_discount['admin_discount_amount'] * $or_d['quantity'] : 0; $flash_sale_vendor_discount_amount += $or_d['discount_type'] == 'flash_sale' ? $product_discount['vendor_discount_amount'] * $or_d['quantity'] : 0; $order_details[] = $or_d; } else { if (count(json_decode($product['variations'], true)) > 0 && count($c['variation']) > 0) { $variant_data = Helpers::variation_price($product, json_encode($c['variation'])); $price = $variant_data['mrpprice']; $stock = $variant_data['stock']; $is_vr = true; $mychitti_fee = $variant_data['price'] - $variant_data['askingprice']; } else { $price = $product['price']; $stock = $product->stock; $is_vr = false; $mychitti_fee = $product->mychitty_fee; } if (($stock - $c['quantity']) < 6) { _stock_alert_sms($store->phone, $product['name']); $title = 'Low Stock Alert for ' . $product['name']; $msg = "Dear Vendor, Stock for " . $product['name'] . " is low. Please update accordingly."; $to = $store->id; $url = route('vendor.item.stock-limit-list'); $user_typ = 'vendor'; _inAppNotification($title, $msg, $acceptnce_id = '', $to, $url, $user_typ); } if (config('module.' . $product->module->module_type)['stock']) { if ($c['quantity'] > $stock) { return response()->json([ 'errors' => [ ['code' => 'campaign', 'message' => translate('messages.product_out_of_stock', ['item' => $product->name])] ] ]); } $product_data[] = [ 'item' => clone $product, 'quantity' => $c['quantity'], 'variant' => count($c['variation']) > 0 ? $c['variation'][0]['type'] : null ]; } // $product->tax = $store->tax; $product = Helpers::product_data_formatting($product, false, false, app()->getLocale()); $addon_data = Helpers::calculate_addon_price(\App\Models\AddOn::whereIn('id', $c['add_on_ids'])->get(), $c['add_on_qtys']); if (isset($c['variation']) && $c['variation']) { $mrpprice = $c['variation'][0]['mrpprice'] ?? $c['variation'][0]['price']; $price = $c['variation'][0]['price']; $product_discount = Helpers::product_discount_calculate_vr($c['variation']); $mychitti_fee = isset($c['variation'][0]['askingprice']) ? $price - $c['variation'][0]['askingprice'] : 0; } else { $mrpprice = $product->mrp_price; $price = $product->price; $mychitti_fee = $product->mychitty_fee; $product_discount = Helpers::product_discount_calculate($product, $mrpprice, $store); } $tax_amount = _taxCalcluation($price, $product->tax)['gst_amount']; $taxable = _taxCalcluation($price, $product->tax)['price_excluding_gst']; $or_d = [ 'item_id' => $c['item_id'], 'item_campaign_id' => null, 'item_details' => json_encode($product), 'quantity' => $c['quantity'], 'price' => $price, 'taxable_amount' => $taxable, 'tax_amount' => $tax_amount, 'discount_on_item' => $product_discount['discount_amount'], 'discount_type' => $product_discount['discount_type'], 'variant' => json_encode($c['variant']), 'variation' => json_encode($c['variation']), 'platform_fee' => $mychitti_fee ?? 0, 'add_ons' => json_encode($addon_data['addons']), 'total_add_on_price' => $addon_data['total_add_on_price'], 'created_at' => now(), 'updated_at' => now() ]; // prx($product_discount['discount_amount']); $total_addon_price += $or_d['total_add_on_price']; $total_order_tax += ($tax_amount * $or_d['quantity']); if ($is_vr) { $product_price += ($price * $or_d['quantity']); } else { $product_price += $price * $or_d['quantity']; } $store_discount_amount += $or_d['discount_type'] != 'flash_sale' ? $or_d['discount_on_item'] * $or_d['quantity'] : 0; $flash_sale_admin_discount_amount += $or_d['discount_type'] == 'flash_sale' ? $product_discount['admin_discount_amount'] * $or_d['quantity'] : 0; $flash_sale_vendor_discount_amount += $or_d['discount_type'] == 'flash_sale' ? $product_discount['vendor_discount_amount'] * $or_d['quantity'] : 0; $order_details[] = $or_d; } } else { return response()->json([ 'errors' => [ ['code' => 'item', 'message' => translate('messages.product_unavailable_warning')] ] ]); } } } $order->discount_on_product_by = 'vendor'; $store_discount = Helpers::get_store_discount($store); if (isset($store_discount)) { $order->discount_on_product_by = 'admin'; if ($product_price + $total_addon_price < $store_discount['min_purchase']) { $store_discount_amount = 0; } if ($store_discount['max_discount'] != 0 && $store_discount_amount > $store_discount['max_discount']) { $store_discount_amount = $store_discount['max_discount']; } } $coupon_discount_amount = $coupon ? CouponLogic::get_discount($coupon, $product_price + $total_addon_price - $store_discount_amount - $flash_sale_admin_discount_amount - $flash_sale_vendor_discount_amount) : 0; $total_price = $product_price + $total_addon_price - $total_addon_price - $flash_sale_admin_discount_amount - $flash_sale_vendor_discount_amount - $coupon_discount_amount; $tax = ($store->tax > 0) ? $store->tax : 0; $order->tax_status = 'included'; $tax_included = BusinessSetting::where(['key' => 'tax_included'])->first() ? BusinessSetting::where(['key' => 'tax_included'])->first()->value : 0; if ($tax_included == 1) { $order->tax_status = 'included'; } $total_tax_amount = Helpers::product_tax($total_price, $tax, $order->tax_status == 'included'); $tax_a = $order->tax_status == 'included' ? 0 : $total_tax_amount; if ($store->minimum_order > $product_price + $total_addon_price) { return response()->json([ 'errors' => [ ['code' => 'order_time', 'message' => translate('messages.you_need_to_order_at_least') . $store->minimum_order . ' ' . Helpers::currency_code()] ] ]); } $free_delivery_over = BusinessSetting::where('key', 'free_delivery_over')->first()->value; if (isset($free_delivery_over)) { if ($free_delivery_over <= $product_price + $total_addon_price - $coupon_discount_amount - $store_discount_amount - $flash_sale_admin_discount_amount - $flash_sale_vendor_discount_amount) { $order->delivery_charge = 0; $free_delivery_by = 'admin'; } } if ($store->free_delivery) { $order->delivery_charge = 0; $free_delivery_by = 'vendor'; } if ($coupon) { if ($coupon->coupon_type == 'free_delivery') { if ($coupon->min_purchase <= $product_price + $total_addon_price - $store_discount_amount - $flash_sale_admin_discount_amount - $flash_sale_vendor_discount_amount) { $order->delivery_charge = 0; $free_delivery_by = $coupon->created_by; } } $coupon->increment('total_uses'); } $order->coupon_created_by = $coupon_created_by; $order->coupon_discount_amount = round($coupon_discount_amount, config('round_up_to_digit')); $order->coupon_discount_title = $coupon ? $coupon->title : ''; $order->store_discount_amount = round($store_discount_amount, config('round_up_to_digit')); $order->tax_percentage = $tax; $order->total_tax_amount = $total_order_tax ?? round($total_tax_amount, config('round_up_to_digit')); $order->rounded_off = ($total_price + $tax_a + $order->delivery_charge) - floor($total_price + $tax_a + $order->delivery_charge); $order->order_amount = round($total_price + $tax_a + $order->delivery_charge); $order->free_delivery_by = $free_delivery_by; } else { $point = new Point(json_decode($request->receiver_details, true)['latitude'], json_decode($request->receiver_details, true)['longitude']); $zone_id = json_decode($request->receiver_details, true)['zone_id']; $zone = Zone::where('id', $zone_id)->whereContains('coordinates', new Point(json_decode($request->receiver_details, true)['latitude'], json_decode($request->receiver_details, true)['longitude'], POINT_SRID))->first(); if (!$zone) { $errors = []; array_push($errors, ['code' => 'receiver_details', 'message' => translate('messages.out_of_coverage')]); return response()->json([ 'errors' => $errors ]); } $order->delivery_charge = round($original_delivery_charge, config('round_up_to_digit')) ?? 0; $order->original_delivery_charge = round($original_delivery_charge, config('round_up_to_digit')); $order->order_amount = round($order->delivery_charge); } $order->flash_admin_discount_amount = round($flash_sale_admin_discount_amount, config('round_up_to_digit')); $order->flash_store_discount_amount = round($flash_sale_vendor_discount_amount, config('round_up_to_digit')); //DM TIPs $order->order_amount = $order->order_amount + $order->dm_tips + $order->additional_charge; $order->rounded_off = ($order->order_amount) - floor($order->order_amount); if ($request->payment_method == 'wallet' && $user->wallet_balance < $order->order_amount) { return response()->json([ 'errors' => [ ['code' => 'order_amount', 'message' => translate('messages.insufficient_balance')] ] ]); } if ($request->partial_payment && $user->wallet_balance > $order->order_amount) { return response()->json([ 'errors' => [ ['code' => 'partial_payment', 'message' => translate('messages.order_amount_must_be_greater_than_wallet_amount')] ] ]); } if (isset($module_wise_delivery_charge) && $request->payment_method == 'cash_on_delivery' && $module_wise_delivery_charge->pivot->maximum_cod_order_amount && $order->order_amount > $module_wise_delivery_charge->pivot->maximum_cod_order_amount) { return response()->json([ 'errors' => [ ['code' => 'order_amount', 'message' => translate('messages.amount_crossed_maximum_cod_order_amount')] ] ]); } try { DB::beginTransaction(); $order->save(); if ($request->order_type !== 'parcel') { foreach ($order_details as $key => $item) { $order_details[$key]['order_id'] = $order->id; if ($store_discount_amount <= 0) { $order_details[$key]['discount_on_item'] = 0; } } OrderDetail::insert($order_details); if (count($product_data) > 0) { foreach ($product_data as $item) { ProductLogic::update_stock($item['item'], $item['quantity'], $item['variant'])->save(); ProductLogic::update_flash_stock($item['item'], $item['quantity'])?->save(); } } $store->increment('total_order'); } if (!isset($request->is_buy_now) || (isset($request->is_buy_now) && $request->is_buy_now == 0)) { foreach ($carts as $cart) { // $cart->delete(); } } if ($user) { $customer = $user; $customer->zone_id = $order->zone_id; $customer->save(); if ($request->payment_method == 'wallet') CustomerLogic::create_wallet_transaction($order->user_id, $order->order_amount, 'order_place', $order->id); if ($request->partial_payment) { if ($user->wallet_balance <= 0) { return response()->json([ 'errors' => [ ['code' => 'order_amount', 'message' => translate('messages.insufficient_balance_for_partial_amount')] ] ], 203); } $p_amount = min($user->wallet_balance, $order->order_amount); $unpaid_amount = $order->order_amount - $p_amount; $order->partially_paid_amount = $p_amount; $order->save(); CustomerLogic::create_wallet_transaction($order->user_id, $p_amount, 'partial_payment', $order->id); OrderLogic::create_order_payment(order_id: $order->id, amount: $p_amount, payment_status: 'paid', payment_method: 'wallet'); OrderLogic::create_order_payment(order_id: $order->id, amount: $unpaid_amount, payment_status: 'unpaid', payment_method: $request->payment_method); } } DB::commit(); $payments = $order->payments()->where('payment_method', 'cash_on_delivery')->exists(); $order_mail_status = Helpers::get_mail_status('place_order_mail_status_user'); $order_verification_mail_status = Helpers::get_mail_status('order_verification_mail_status_user'); //PlaceOrderMail try { if (0 && !in_array($order->payment_method, ['digital_payment', 'partial_payment', 'offline_payment']) || $payments) { Helpers::send_order_notification($order); if ($order->order_status == 'pending' && config('mail.status') && $order_mail_status == '1' && $user) { Mail::to($user->email)->send(new PlaceOrder($order->id)); } if ($order->order_status == 'pending' && config('order_delivery_verification') == 1 && $order_verification_mail_status == '1' && $user) { Mail::to($user->email)->send(new OrderVerificationMail($order->otp, $user->f_name)); } if ($order->is_guest == 1 && $order->order_status == 'pending' && config('mail.status') && $order_mail_status == '1' && isset($request->contact_person_email)) { Mail::to($request->contact_person_email)->send(new PlaceOrder($order->id)); } if ($order->is_guest == 1 && $order->order_status == 'pending' && config('order_delivery_verification') == 1 && $order_verification_mail_status == '1' && isset($request->contact_person_email)) { Mail::to($request->contact_person_email)->send(new OrderVerificationMail($order->otp, $request->contact_person_name)); } } } catch (\Exception $ex) { // info($ex->getMessage()); } // place order sms, email and in app notification to vendor =================== $title = "Received New Order"; $msg = "Good news! You've got a new order. Let's get it ready!"; $acceptnce_id = ''; $to = $store->id; $url = route('vendor.order.list', ['pending']); $user_typ = 'vendor'; _inAppNotification($title, $msg, $acceptnce_id, $to, $url, $user_typ); // _sendMailToVendor($title, $msg, $to, $url); $smsTemplate = "Hello! Your order NO " . $order->id . " is received. Please review the details on My Chitti Vendor Dashboard and confirm accuracy."; _sendSMS($store->phone, $smsTemplate); _sendOrderSMSToAdmins($order, $user, $store); // SendOrderNotifications::dispatch( // $title, // $msg, // $acceptnce_id, // $to, // $url, // $user_typ, // $order->id, // $store->phone // ); // place order sms, email and in app notification to vendor =================== return response()->json([ 'message' => translate('messages.order_placed_successfully'), 'order_id' => $order->id, 'payment_method' => $request->payment_method, 'total_ammount' => $order->order_amount, 'status' => $order->order_status, 'created_at' => $order->created_at, 'url' => $request->payment_method == 'digital_payment' ? "payment-mobile?customer_id=" . $user_id . "&order_id=" . $order->id . "&payment_platform=web&payment_method=razor_pay&callback=/success" : '' ], 200); } catch (\Exception $e) { DB::rollBack(); return response()->json([$e], 403); } return response()->json([ 'errors' => [ ['code' => 'order_time', 'message' => translate('messages.failed_to_place_order')] ] ]); } public function change_variation(Request $request) { $vrType = $request->type; $prId = $request->id; $item = DB::table('items')->where('id', $prId)->first(); $variations = json_decode($item->variations); $selectedVr = []; foreach ($variations as $key => $value) { if ($value->type == $vrType) { $selectedVr = $value; $selectedVr->discounted_price = $selectedVr->price; $vrDetails = ItemVariationDetail::find($selectedVr->variations_table_id); $selectedVr->variation_details = $vrDetails; } } return response()->json(['status' => true, 'data' => $selectedVr]); } public function order_success(Request $request, $order_id = null) { $order_id = $order_id; return view('front-views.order-success', compact('order_id')); } public function store_gallery(Request $request, $slug = null) { // If the store is already resolved via custom domain middleware, use that context $store = $request->attributes->get('store_domain_store'); if ($store) { $store->load('galleries'); } else { // Resolve from the route param explicitly (not $request->slug, which can be shadowed // by input) and bypass global scopes — the slug is unique, and on a custom domain // there's no zone/session context to scope by. $slug = $slug ?: $request->route('slug'); $store = Store::withoutGlobalScopes()->with('galleries')->where('slug', $slug)->first(); } if (!$store) { abort(404); } return view('front-views.store_gallery', compact('store')); } public function trackBannerClick(Request $request) { $bannerId = $request->banner_id; $banner = DB::table('banners')->where('id', $bannerId)->first(); if (!$banner) { return response()->json(['message' => 'Banner not found'], 404); } $ip = $request->ip(); $isUnique = !DB::table('analytics_logs') ->where('screen_type', 'banner') ->where('ref_id', $bannerId) ->where('ip', $ip) ->whereDate('created_at', now()->toDateString()) ->exists(); DB::table('banners')->where('id', $bannerId)->increment('total_clicks'); if ($isUnique) { DB::table('banners')->where('id', $bannerId)->increment('unique_clicks'); } DB::table('analytics_logs')->insert([ 'screen_type' => 'banner', 'sub_type' => 'web', 'ref_id' => $bannerId, 'user_id' => auth()->check() ? auth()->id() : null, 'ip' => $ip, 'created_at' => now(), ]); return response()->json(['message' => 'Banner click counted']); } public function trackAdClick(Request $request) { $adId = $request->ad_id; $ad = DB::table('notifications')->where('id', $adId)->whereNotNull('vendor_id')->first(); if (!$ad) { return response()->json(['message' => 'Ad not found'], 404); } $ip = $request->ip(); DB::table('notifications')->where('id', $adId)->increment('total_clicks'); try { $isUnique = !DB::table('analytics_logs') ->where('screen_type', 'ad') ->where('ref_id', $adId) ->where('ip', $ip) ->whereDate('created_at', now()->toDateString()) ->exists(); if ($isUnique) { DB::table('notifications')->where('id', $adId)->increment('unique_clicks'); } DB::table('analytics_logs')->insert([ 'screen_type' => 'ad', 'sub_type' => 'web', 'ref_id' => $adId, 'user_id' => auth()->check() ? auth()->id() : null, 'ip' => $ip, 'created_at' => now(), ]); } catch (\Exception $e) { // analytics_logs failure must not prevent the increment } return response()->json(['message' => 'Ad click counted']); } public function trackStoreContactClick(Request $request) { $storeId = $request->store_id; $action = $request->action; // Platform analytics events (analytics_logs) — call reuses phone-call analytics, // copy is a web-only event, share = store share, whatsapp/enquiry come from the // store cards (product detail page, store page) and get their own Performance // Analytics stat. $screenType = match ($action) { 'call' => 'call', 'copy' => 'copy', 'share' => 'share', 'whatsapp' => 'whatsapp', 'enquiry' => 'enquiry', default => null, }; // Inbound-lead actions (Phase 3 §3.3) — also recorded to lead_signals for the MC Vendor Hub // Lead Inbox. 'copy'/'share' are analytics-only; everything here is a real lead intent. // lead_signals.type is an ENUM, so 'enquiry' rides on the existing 'booking' member. $leadType = $action === 'enquiry' ? 'booking' : $action; $leadTypes = ['call', 'whatsapp', 'booking', 'quote', 'direction', 'website']; $isLead = in_array($leadType, $leadTypes, true); if (!$screenType && !$isLead) { return response()->json(['message' => 'Invalid action'], 422); } $store = DB::table('stores')->where('id', $storeId)->first(); if (!$store) { return response()->json(['message' => 'Store not found'], 404); } $ip = $request->ip(); // 1) Platform analytics — identical to before (only for call/copy/share). if ($screenType) { // sub_type: for 'share' it holds the share target ('store'); otherwise the source platform ('web'). $subType = $action === 'share' ? 'store' : 'web'; try { DB::table('analytics_logs')->insert([ 'screen_type' => $screenType, 'sub_type' => $subType, 'ref_id' => $storeId, 'user_id' => auth()->check() ? auth()->id() : null, 'ip' => $ip, 'created_at' => now(), ]); } catch (\Exception $e) { // analytics failure must not break the click } } // 2) Lead Inbox signal — full funnel (call/whatsapp/booking/quote/direction/website). if ($isLead) { try { DB::table('lead_signals')->insert([ 'store_id' => $storeId, 'user_id' => auth()->check() ? auth()->id() : null, 'type' => $leadType, 'source' => $request->input('source', 'web'), 'utm_source' => $request->input('utm_source'), 'utm_medium' => $request->input('utm_medium'), 'utm_campaign' => $request->input('utm_campaign'), 'meta' => json_encode(['ip' => $ip, 'ua' => substr((string) $request->userAgent(), 0, 255)]), 'created_at' => now(), 'updated_at' => now(), ]); } catch (\Exception $e) { // lead capture failure must not break the click } } return response()->json(['message' => 'ok']); } private function adsBaseQuery() { $zone_ids = json_decode($this->zone_id, true); return \App\Models\Notification::whereNotNull('vendor_id') ->where('approval', 1) ->where('status', 1) ->whereNotNull('image') ->where(function ($q) { $q->whereNull('days') ->orWhereNull('approved_at') ->orWhereRaw('DATE_ADD(approved_at, INTERVAL days DAY) >= NOW()'); }) ->where(function ($q) use ($zone_ids) { $q->whereIn('zone_id', $zone_ids) ->orWhereNull('zone_id') ->orWhere('zone_id', 0); }) ->latest(); } public function allAds() { $ads = $this->adsBaseQuery()->paginate(18); return view('front-views.ads.index', compact('ads')); } public function loadAds(Request $request) { $ads = $this->adsBaseQuery()->paginate(12); $html = view('front-views.ads._ad_cards', compact('ads'))->render(); return response()->json([ 'html' => $html, 'has_more' => $ads->hasMorePages(), ]); } public function adDetail($id) { $ad = \App\Models\Notification::whereNotNull('vendor_id') ->where('approval', 1) ->where('status', 1) ->findOrFail($id); try { $ip = request()->ip(); $isUnique = !DB::table('analytics_logs') ->where('screen_type', 'ad') ->where('ref_id', $id) ->where('ip', $ip) ->whereDate('created_at', now()->toDateString()) ->exists(); DB::table('notifications')->where('id', $id)->increment('total_clicks'); if ($isUnique) { DB::table('notifications')->where('id', $id)->increment('unique_clicks'); } DB::table('analytics_logs')->insert([ 'screen_type' => 'ad', 'sub_type' => 'web', 'ref_id' => $id, 'user_id' => auth()->check() ? auth()->id() : null, 'ip' => $ip, 'created_at' => now(), ]); } catch (\Exception $e) { // analytics failure must not break the page } $store = $ad->vendor_id ? DB::table('stores')->where('id', $ad->vendor_id)->first() : null; return view('front-views.ads.detail', compact('ad', 'store')); } public function store_details(Request $request, $city, $slug) { $check_module = DB::table('stores')->where('slug', $slug)->first(); if ($check_module) { $module = $check_module->module_id; } else { abort(404); } // One canonical city per store (falls back to the platform default for zone-less stores). $canonicalCity = 'tirupati'; if ($check_module->zone_id) { $zone = DB::table('zones')->where('id', $check_module->zone_id)->value('name'); if ($zone) { $canonicalCity = _zoneCitySlug($zone); } } // 301 any other city to the single canonical URL — kills duplicate / soft-404 pages. if ($city !== $canonicalCity) { return redirect()->to(url($canonicalCity . '/store/' . $slug), 301); } // True canonical for the store page (overrides the layout's self-referencing default). view()->share('canonical', url($canonicalCity . '/store/' . $slug)); $invItemdata = []; $longitude = $this->longitude; $latitude = $this->latitude; $store = Store::with(['discount' => function ($q) { return $q->validate(); }, 'campaigns', 'schedules', 'activeCoupons']) ->withCount(['items', 'campaigns']) ->when($module, function ($query) use ($module) { $query->module($module); }) ->where('slug', $slug) ->first(); if ($store) { // Thin-content guard: keep genuinely empty store shells (no items, no campaigns, // no specialised business type) out of the index so they aren't flagged soft-404. view()->share('metaRobots', ($store->items_count == 0 && $store->campaigns_count == 0 && empty($store->business_type)) ? 'noindex, follow' : null); // LocalBusiness JSON-LD (P0) — emitted in the layout head for every store template. view()->share('localBusinessStore', $store); // Increment store visit analytics $ip = $request->ip(); $isUnique = !DB::table('analytics_logs') ->where('screen_type', 'store') ->where('ref_id', $store->id) ->where('ip', $ip) ->whereDate('created_at', now()->toDateString()) ->exists(); DB::table('stores')->where('id', $store->id)->increment('total_visits'); if ($isUnique) { DB::table('stores')->where('id', $store->id)->increment('unique_visits'); } DB::table('analytics_logs')->insert([ 'screen_type' => 'store', 'sub_type' => 'web', 'ref_id' => $store->id, 'user_id' => auth()->check() ? auth()->id() : null, 'ip' => $ip, 'created_at' => now(), ]); if ($module == 5) { $keywordsData = DB::table('items') ->where('items.is_approved', 1) ->join('categories', 'items.category_id', '=', 'categories.id') ->where('items.store_id', $store->id) ->select('items.name as item_name', 'categories.name as category_name') ->distinct() ->get(); $keywords = implode(',', $keywordsData->pluck('item_name')->merge($keywordsData->pluck('category_name'))->toArray()); $category_ids = DB::table('items') ->join('categories', 'items.category_id', '=', 'categories.id') ->selectRaw('categories.position as positions, IF((categories.position = "0"), categories.id, categories.parent_id) as categories') ->where('items.store_id', $store->id) ->where('categories.status', 1) ->groupBy('categories', 'positions') ->get(); $store = Helpers::store_data_formatting($store); $store['category_ids'] = array_map('intval', $category_ids->pluck('categories')->toArray()); $store['category_details'] = Category::whereIn('id', $store['category_ids'])->get(); $store['price_range'] = Item::withoutGlobalScopes()->where('store_id', $store->id) ->select(DB::raw('MIN(price) AS min_price, MAX(price) AS max_price')) ->get(['min_price', 'max_price']); $productdata = DB::table('items') ->join('categories', 'items.category_id', 'categories.id') ->where('items.store_id', $store->id) ->where('items.status', 1) ->where('items.is_approved', 1) ->select('categories.id', 'categories.name', 'categories.slug as cat_slug') ->distinct() ->get() ->toArray(); foreach ($productdata as $key => $cat) { $cat->items = DB::table('items') ->where('store_id', $store->id) ->where('category_id', $cat->id) ->where('status', 1) ->where('is_approved', 1) ->get(); } } else { $keywordsData = DB::table('items') ->where('items.is_approved', 1) ->join('categories', 'items.category_id', '=', 'categories.id') ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id)) ->select('items.name as item_name', 'categories.name as category_name') ->distinct() ->get(); $keywords = implode(',', $keywordsData->pluck('item_name')->merge($keywordsData->pluck('category_name'))->toArray()); // echo '
';
                // SERVICES
                $productdata1 = DB::table('items')
                    ->join('categories', 'items.category_id', 'categories.id')
                    ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                    ->whereNull('items.inventory_item_id')
                    ->where('categories.status', 1)
                    ->select('categories.id', 'categories.name', 'categories.slug as cat_slug')
                    ->distinct()
                    ->get();


                foreach ($productdata1 as $cat) {
                    $cat->items = DB::table('items')
                        ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                        ->whereNull('items.inventory_item_id')
                        ->where('category_id', $cat->id)
                        ->where('status', 1)
                        ->get();
                }

                //INVENTORY ITEMS
                $invItemdata = DB::table('items')
                    ->join('categories', 'items.category_id', 'categories.id')
                    ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                    ->whereNotNull('items.inventory_item_id')
                    ->select('categories.id', 'categories.name', 'categories.slug as cat_slug')
                    ->distinct()
                    ->get();

                foreach ($invItemdata as $cat) {
                    $cat->items = DB::table('items')
                        ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                        ->whereNotNull('items.inventory_item_id')
                        ->where        }

        if ($request->partial_payment && !Helpers::get_business_settings('partial_payment_status')) {
            return response()->json([
                'errors' => [
                    ['code' => 'order_method', 'message' => translate('messages.partial_payment_is_not_active')]
                ]
            ]);
        }

        if ($request->payment_method == 'offline_payment' &&  Helpers::get_mail_status('offline_payment_status') == 0) {
            return response()->json([
                'errors' => [
                    ['code' => 'offline_payment_status', 'message' => translate('messages.offline_payment_for_the_order_not_available_at_this_time')]
                ]
            ]);
        }

        $digital_payment = Helpers::get_business_settings('digital_payment');
        if ($digital_payment['status'] == 0 && $request->payment_method == 'digital_payment') {
            return response()->json([
                'errors' => [
                    ['code' => 'digital_payment', 'message' => translate('messages.digital_payment_for_the_order_not_available_at_this_time')]
                ]
            ]);
        }

        $data =  DMVehicle::active()->where(function ($query) use ($distance_data) {
            $query->where('starting_coverage_area', '<=', $distance_data)->where('maximum_coverage_area', '>=', $distance_data)
                ->orWhere(function ($query) use ($distance_data) {
                    $query->where('starting_coverage_area', '>=', $distance_data);
                });
        })
            ->orderBy('starting_coverage_area')->first();

        $extra_charges = (float) (isset($data) ? $data->extra_charges  : 0);
        $vehicle_id = (isset($data) ? $data->id  : null);

        $zone = null;
        if ($request->latitude[$key] && $request->longitude[$key]) {
            $point = new Point($request->latitude[$key], $request->longitude[$key]);
            if ($request->order_type == 'parcel') {
                // if(isset($request->sender_zone_id) ){
                // $zone_id = $request->sender_zone_id;
                $zone_ids = $request->header('zoneId') ? json_decode($request->header('zoneId'), true) : [];
                $zone = Zone::whereIn('id', $zone_ids)->whereContains('coordinates', new Point($request->latitude[$key], $request->longitude[$key], POINT_SRID))->wherehas('modules', function ($q) {
                    $q->where('module_type', 'parcel');
                })->first();
            } else {
                // ->selectRaw('*, IF(((select count(*) from `store_schedule` where `stores`.`id` = `store_schedule`.`store_id` and `store_schedule`.`day` = ' . $schedule_at->format('w') . ' and `store_schedule`.`opening_time` < "' . $schedule_at->format('H:i:s') . '" and `store_schedule`.`closing_time` >"' . $schedule_at->format('H:i:s') . '") > 0), true, false) as open')
                $store = Store::with('discount')->where('id', $request->store_id)->first();

                if (!$store) {
                    return response()->json([
                        'errors' => [
                            ['code' => 'order_time', 'message' => translate('messages.store_not_found')]
                        ]
                    ]);
                }
                $zone_id =  [$store->zone_id];
                $zone = Zone::where('id', $zone_id)->whereContains('coordinates', new Point($request->latitude[$key], $request->longitude[$key], POINT_SRID))->first();
            }
        }
        if (!$zone) {
            $errors = [];
            array_push($errors, ['code' => 'coordinates', 'message' => translate('messages.out_of_coverage')]);
            return response()->json([
                'errors' => $errors
            ]);
        }
        if ($zone && $zone->increased_delivery_fee_status == 1) {
            $increased = $zone->increased_delivery_fee ?? 0;
        }

        if ($request->order_type !== 'parcel') {


            if (!$store->active) {
                return response()->json([
                    'errors' => [
                        ['code' => 'order_time', 'message' => translate('messages.store_is_closed_at_order_time')]
                    ]
                ]);
            }

            if ($request->coupon_code) {
                $coupon = Coupon::active()->where(['code' => $request->coupon_code])->first();
                if (isset($coupon)) {


                    $staus = CouponLogic::is_valide($coupon, $user->id, $request->store_id);


                    if ($staus == 407) {
                        return response()->json([
                            'errors' => [
                                ['code' => 'coupon', 'message' => translate('messages.coupon_expire')]
                            ]
                        ]);
                    } else if ($staus == 408) {
                        return response()->json([
                            'errors' => [
                                ['code' => 'coupon', 'message' => translate('messages.You_are_not_eligible_for_this_coupon')]
                            ]
                        ]);
                    } else if ($staus == 406) {
                        return response()->json([
                            'errors' => [
                                ['code' => 'coupon', 'message' => translate('messages.coupon_usage_limit_over')]
                            ]
                        ]);
                    } else if ($staus == 404) {
                        return response()->json([
                            'errors' => [
                                ['code' => 'coupon', 'message' => translate('messages.not_found')]
                            ]
                        ]);
                    }

                    $coupon_created_by = $coupon->created_by;
                    if ($coupon->coupon_type == 'free_delivery') {
                        $delivery_charge = 0;
                        $free_delivery_by =  $coupon_created_by;
                        $coupon_created_by = null;
                    }
                } else {
                    return response()->json([
                        'errors' => [
                            ['code' => 'coupon', 'message' => translate('messages.not_found')]
                        ]
                    ], 404);
                }
            }

            $module_wise_delivery_charge = $store->zone->modules()->where('modules.id', 5)->first();
            if ($module_wise_delivery_charge) {
                $per_km_shipping_charge = $module_wise_delivery_charge->pivot->per_km_shipping_charge;
                $minimum_shipping_charge = $module_wise_delivery_charge->pivot->minimum_shipping_charge;
                $maximum_shipping_charge = $module_wise_delivery_charge->pivot->maximum_shipping_charge;
            } else {
                $per_km_shipping_charge = (float)BusinessSetting::where(['key' => 'per_km_shipping_charge'])->first()->value;
                $minimum_shipping_charge = (float)BusinessSetting::where(['key' => 'minimum_shipping_charge'])->first()->value;
            }

            if ($request->order_type != 'take_away' && !$store->free_delivery && !isset($delivery_charge) &&  $store->self_delivery_system == 1) {
                $per_km_shipping_charge = $store->per_km_shipping_charge;
                $minimum_shipping_charge = $store->minimum_shipping_charge;
                $maximum_shipping_charge = $store->maximum_shipping_charge;
                $extra_charges = 0;
                $vehicle_id = null;
                $increased = 0;
            }

            if ($store->free_delivery || $free_delivery_by == 'vendor') {
                $per_km_shipping_charge = $store->per_km_shipping_charge;
                $minimum_shipping_charge = $store->minimum_shipping_charge;
                $maximum_shipping_charge = $store->maximum_shipping_charge;
                $extra_charges = 0;
                $increased = 0;
            }

            $original_delivery_charge = (($request->distance * $per_km_shipping_charge) > $minimum_shipping_charge) ? $request->distance * $per_km_shipping_charge  : $minimum_shipping_charge;

            if ($request->order_type == 'take_away') {
                $per_km_shipping_charge = 0;
                $minimum_shipping_charge = 0;
                $maximum_shipping_charge = 0;
                $extra_charges = 0;
                $distance_data = 0;
                $vehicle_id = null;
                $original_delivery_charge = 0;
                $increased = 0;
            }

            if ($maximum_shipping_charge  >= $minimum_shipping_charge  && $original_delivery_charge >  $maximum_shipping_charge) {
                $original_delivery_charge = $maximum_shipping_charge;
            } else {
                $original_delivery_charge = $original_delivery_charge;
            }

            if (!isset($delivery_charge)) {
                $delivery_charge = ($request->distance * $per_km_shipping_charge > $minimum_shipping_charge) ? $request->distance * $per_km_shipping_charge : $minimum_shipping_charge;
                if ($maximum_shipping_charge  >= $minimum_shipping_charge  && $delivery_charge >  $maximum_shipping_charge) {
                    $delivery_charge = $maximum_shipping_charge;
                } else {
                    $delivery_charge = $delivery_charge;
                }
            }
            $original_delivery_charge = $original_delivery_charge + $extra_charges;
            $delivery_charge = $delivery_charge + $extra_charges;
        } else {
            $parcel_category = ParcelCategory::findOrFail($request->parcel_category_id);
            if (isset($parcel_category) && isset($parcel_category->parcel_minimum_shipping_charge)) {
                $per_km_shipping_charge = $parcel_category->parcel_per_km_shipping_charge;
                $minimum_shipping_charge = $parcel_category->parcel_minimum_shipping_charge;
            } else {
                $per_km_shipping_charge = (float)BusinessSetting::where(['key' => 'parcel_per_km_shipping_charge'])->first()->value;
                $minimum_shipping_charge = (float)BusinessSetting::where(['key' => 'parcel_minimum_shipping_charge'])->first()->value;
            }

            $original_delivery_charge = (($request->distance * $per_km_shipping_charge) > $minimum_shipping_charge) ? ($request->distance * $per_km_shipping_charge) + $extra_charges : ($minimum_shipping_charge + $extra_charges);
        }

        if ($increased > 0) {
            if ($delivery_charge > 0) {
                $increased_fee = ($delivery_charge * $increased) / 100;
                $delivery_charge = $delivery_charge + $increased_fee;
            }
            if ($original_delivery_charge > 0) {
                $increased_fee = ($original_delivery_charge * $increased) / 100;
                $original_delivery_charge = $original_delivery_charge + $increased_fee;
            }
        }
        $address = [
            'contact_person_name' => $request->contact_person_name[$key] ? $request->contact_person_name[$key] : ($user ? $user->f_name . ' ' . $user->f_name : ''),
            'contact_person_number' => $request->contact_person_number[$key] ? ($user ? $request->contact_person_number[$key] : str_replace('+', '', $request->contact_person_number[$key])) : ($user ? $user->phone : ''),
            'contact_person_email' => $user ? $user->email : '',
            'address_type' => $request->address_type ? $request->address_type : 'Delivery',
            'address' => $request?->address[$key] ?? '',
            'floor' => $request?->floor[$key] ?? '',
            'road' => $request?->road[$key] ?? '',
            'house' => $request?->house[$key] ?? '',
            'longitude' => (string)$request->longitude[$key],
            'latitude' => (string)$request->latitude[$key],
        ];
        $total_addon_price = 0;
        $product_price = 0;
        $store_discount_amount = 0;
        $flash_sale_vendor_discount_amount = 0;
        $flash_sale_admin_discount_amount = 0;
        $store_discount_amount = 0;
        $product_data = [];

        $order_details = [];
        $order = new Order();
        $lastOrder = Order::orderBy('id', 'desc')->first();

        if ($lastOrder) {
            $order->id = $lastOrder->id + 1;
        } else {
            $order->id = 10001;
        }
        $order->invoice_id = _generateOrderInvoiceId($request->store_id);

        $order_status = 'pending';
        if (($request->partial_payment && $request->payment_method != 'offline_payment') || $request->payment_method == 'wallet') {
            $order_status = 'confirmed';
        }

        $order->user_id = $user ? $user->id : 0;
        $order->order_amount = $request->order_amount;
        $order->payment_status = ($request->partial_payment ? 'partially_paid' : ($request->payment_method == 'wallet' ? 'paid' : 'unpaid'));
        $order->order_status = $order_status;
        $order->coupon_code = $request->coupon_code;
        $order->payment_method = $request->partial_payment ? 'partial_payment' : $request->payment_method;
        $order->transaction_reference = null;
        $order->order_note = $request->order_note;
        $order->unavailable_item_note = $request->unavailable_item_note;
        $order->delivery_instruction = $request->delivery_instruction;
        $order->order_type = $request->order_type;
        $order->store_id = $request->store_id;
        if ($store->delivery_charges_on && $store->delivery_charges_on <= $request->order_amount) {
            $order->delivery_charge = 0;
        } else {
            $order->delivery_charge = round($delivery_charge, config('round_up_to_digit')) ?? 0;
        }
        $order->original_delivery_charge = round($original_delivery_charge, config('round_up_to_digit'));
        $order->delivery_address = json_encode($address);
        $order->schedule_at = $schedule_at;
        $order->scheduled = $request->schedule_at ? 1 : 0;
        $order->cutlery = $request->cutlery ? 1 : 0;
        $order->is_guest = $user ? 0 : 1;
        $order->otp = rand(1000, 9999);
        $order->zone_id = isset($zone) ? $zone->id : end(json_decode($this->zone_id, true));
        $order->module_id = 5;
        $order->parcel_category_id = $request->parcel_category_id;
        $order->receiver_details = json_decode($request->receiver_details);

        if ($order_status == 'confirmed') {
            $order->confirmed = now();
        }
        $order->dm_vehicle_id = $vehicle_id;
        $order->pending = now();
        $order->order_attachment = $request->has('order_attachment') ? Helpers::upload('order/', 'png', $request->file('order_attachment')) : null;
        $order->distance = $distance_data;
        $order->created_at = now();
        $order->updated_at = now();
        $order->charge_payer = null;

        //Added DM TIPS
        $dm_tips_manage_status = BusinessSetting::where('key', 'dm_tips_status')->first()->value;
        if ($dm_tips_manage_status == 1) {
            $order->dm_tips = $request->dm_tips ?? 0;
        } else {
            $order->dm_tips = 0;
        }
        //Added service charge
        $additional_charge_status = BusinessSetting::where('key', 'additional_charge_status')->first()->value;
        $additional_charge = BusinessSetting::where('key', 'additional_charge')->first()->value;
        if ($additional_charge_status == 1) {
            $order->additional_charge = $additional_charge ?? 0;
        } else {
            $order->additional_charge = 0;
        }

        $carts = Cart::where('user_id', $order->user_id)->where('is_guest', 0)->where('module_id', 5)
            ->when(isset($request->is_buy_now) && $request->is_buy_now == 1 && $request->cart_id, function ($query) use ($request) {
                return $query->where('id', $request->cart_id);
            })
            ->get()->map(function ($data) {
                $data->add_on_ids = json_decode($data->add_on_ids, true);
                $data->add_on_qtys = json_decode($data->add_on_qtys, true);
                $data->variation = json_decode($data->variation, true);
                return $data;
            });

        if (isset($request->is_buy_now) && $request->is_buy_now == 1) {
            $carts = json_decode($request->cart, true);
        }


        if ($request->order_type !== 'parcel') {
            foreach ($carts as $c) {
                if ($c['item_type'] === 'App\Models\ItemCampaign' || $c['item_type'] === 'AppModelsItemCampaign') {
                    $product = ItemCampaign::with('module')->active()->find($c['item_id']);
                    if ($product) {
                        if ($product->store_id != $order->store_id) {
                            return response()->json([
                                'errors' => [
                                    ['code' => 'different_stores', 'message' => translate('messages.Please_select_items_from_the_same_store')]
                                ]
                            ], 403);
                        }

                        if ($product->module->module_type == 'food' && $product->food_variations) {
                            $product_variations = json_decode($product->food_variations, true);
                            $variations = [];
                            if (count($product_variations)) {
                                $variation_data = Helpers::get_varient($product_variations, $c['variation']);
                                $price = $product['price'] + $variation_data['price'];
                                $variations = $variation_data['variations'];
                            } else {
                                $price = $product['price'];
                            }
                            // $product->tax = $store->tax;
                            $product = Helpers::product_data_formatting($product, false, false, app()->getLocale());
                            $addon_data = Helpers::calculate_addon_price(\App\Models\AddOn::whereIn('id', $c['add_on_ids'])->get(), $c['add_on_qtys']);
                            $or_d = [
                                'item_id' => null,
                                'item_campaign_id' => $c['item_id'],
                                'item_details' => json_encode($product),
                                'quantity' => $c['quantity'],
                                'price' => round($price, config('round_up_to_digit')),
                                'tax_amount' => Helpers::tax_calculate($product, $price),
                                'discount_on_item' => Helpers::product_discount_calculate($product, $price, $store)['discount_amount'],
                                'discount_type' => 'discount_on_product',
                                'variant' => json_encode($c['variant']),
                                'variation' => json_encode($variations),
                                'add_ons' => json_encode($addon_data['addons']),
                                'total_add_on_price' => $addon_data['total_add_on_price'],
                                'created_at' => now(),
                                'updated_at' => now()
                            ];
                            $order_details[] = $or_d;
                            $total_addon_price += $or_d['total_add_on_price'];
                            $product_price += $price * $or_d['quantity'];
                            $store_discount_amount += $or_d['discount_on_item'] * $or_d['quantity'];
                        } else {
                            if (count(json_decode($product['variations'], true)) > 0) {
                                $variant_data = Helpers::variation_price($product, json_encode($c['variation']));
                                $price = $variant_data['price'];
                                $stock = $variant_data['stock'];
                                $mychitti_fee = $variant_data['price'] - $variant_data['askingprice'];
                            } else {
                                $price = $product['price'];
                                $stock = $product->stock;
                                $mychitti_fee = $product->mychitty_fee;
                            }
                            if (config('module.' . $product->module->module_type)['stock']) {
                                if ($c['quantity'] > $stock) {
                                    return response()->json([
                                        'errors' => [
                                            ['code' => 'campaign', 'message' => translate('messages.product_out_of_stock', ['item' => $product->title])]
                                        ]
                                    ]);
                                }

                                $product_data[] = [
                                    'item' => clone $product,
                                    'quantity' => $c['quantity'],
                                    'variant' => count($c['variation']) > 0 ? $c['variation'][0]['type'] : null
                                ];
                            }

                            // $product->tax = $store->tax;
                            $product = Helpers::product_data_formatting($product, false, false, app()->getLocale());
                            $addon_data = Helpers::calculate_addon_price(\App\Models\AddOn::whereIn('id', $c['add_on_ids'])->get(), $c['add_on_qtys']);
                            $or_d = [
                                'item_id' => null,
                                'item_campaign_id' => $c['item_id'],
                                'item_details' => json_encode($product),
                                'quantity' => $c['quantity'],
                                'price' => $price,
                                'tax_amount' => Helpers::tax_calculate($product, $price),
                                'discount_on_item' => Helpers::product_discount_calculate($product, $price, $store)['discount_amount'],
                                'discount_type' => 'discount_on_product',
                                'variant' => json_encode($c['variant']),
                                'variation' => json_encode($c['variation']),
                                'add_ons' => json_encode($addon_data['addons']),
                                'total_add_on_price' => $addon_data['total_add_on_price'],
                                'platform_fee' => $mychitti_fee ??  0,
                                'created_at' => now(),
                                'updated_at' => now()
                            ];
                            $order_details[] = $or_d;
                            $total_addon_price += $or_d['total_add_on_price'];
                            $product_price += $price * $or_d['quantity'];
                            $store_discount_amount += $or_d['discount_on_item'] * $or_d['quantity'];
                        }
                    } else {
                        return response()->json([
                            'errors' => [
                                ['code' => 'campaign', 'message' => translate('messages.product_unavailable_warning')]
                            ]
                        ]);
                    }
                } else {
                    $product = Item::hydrate(
                        DB::table('items')->where('id',  $c['item_id'])->get()->toArray()
                    )->first();

                    if ($product) {

                        if ($product->store_id != $order->store_id) {
                            return response()->json([
                                'errors' => [
                                    ['code' => 'different_stores', 'message' => translate('messages.Please_select_items_from_the_same_store')]
                                ]
                            ]);
                        }


                        if ($product->maximum_cart_quantity && ($c['quantity'] > $product->maximum_cart_quantity)) {
                            return response()->json([
                                'errors' => [
                                    ['code' => 'quantity', 'message' => translate('messages.maximum_cart_quantity_limit_over')]
                                ]
                            ]);
                        }
                        if ($product->module->module_type == 'food' && $product->food_variations) {

                            $product_variations = json_decode($product->food_variations, true);
                            $variations = [];
                            if (count($product_variations)) {
                                $variation_data = Helpers::get_varient($product_variations, $c['variation']);
                                $mrpprice = $variation_data['mrpprice'];
                                $price = $variation_data['mrpprice'];
                                $variations =  $variation_data['variations'];
                                $mychitti_fee = $variation_data['price'] - $variation_data['askingprice'];
                            } else {
                                $mrpprice = $product['mrp_price'] ?? $product['price'];
                                $price = $product['price'];
                                $mychitti_fee = $product->mychitty_fee;
                            }
                            // $product->tax = $store->tax;
                            $product = Helpers::product_data_formatting($product, false, false, app()->getLocale());
                            $addon_data = Helpers::calculate_addon_price(\App\Models\AddOn::whereIn('id', $c['add_on_ids'])->get(), $c['add_on_qtys']);
                            $product_discount = Helpers::product_discount_calculate($product, $mrpprice, $store);

                            $tax =  _taxCalcluation($price, $product->tax)['gst_amount'];
                            $taxable = _taxCalcluation($price, $product->tax)['price_excluding_gst'];


                            $or_d = [
                                'item_id' => $c['item_id'],
                                'item_campaign_id' => null,
                                'item_details' => json_encode($product),
                                'quantity' => $c['quantity'],
                                'price' => $price,
                                'tax_amount' =>  $tax,
                                'taxable_amount' => $taxable,
                                'discount_on_item' => $product_discount['discount_amount'],
                                'discount_type' => $product_discount['discount_type'],
                                'variant' => json_encode($c['variant']),
                                'variation' => json_encode($variations),
                                'platform_fee' => $mychitti_fee ?? 0,
                                'add_ons' => json_encode($addon_data['addons']),
                                'total_add_on_price' => round($addon_data['total_add_on_price'], config('round_up_to_digit')),
                                'created_at' => now(),
                                'updated_at' => now()
                            ];
                            $total_addon_price += $or_d['total_add_on_price'];

                            $product_price += $price * $or_d['quantity'];
                            $store_discount_amount += $or_d['discount_type'] != 'flash_sale' ? $or_d['discount_on_item'] * $or_d['quantity'] : 0;
                            $flash_sale_admin_discount_amount += $or_d['discount_type'] == 'flash_sale' ? $product_discount['admin_discount_amount'] * $or_d['quantity'] : 0;
                            $flash_sale_vendor_discount_amount += $or_d['discount_type'] == 'flash_sale' ? $product_discount['vendor_discount_amount'] * $or_d['quantity'] : 0;
                            $order_details[] = $or_d;
                        } else {

                            if (count(json_decode($product['variations'], true)) > 0 && count($c['variation']) > 0) {
                                $variant_data = Helpers::variation_price($product, json_encode($c['variation']));
                                $price = $variant_data['mrpprice'];
                                $stock = $variant_data['stock'];
                                $is_vr = true;
                                $mychitti_fee = $variant_data['price'] - $variant_data['askingprice'];
                            } else {
                                $price = $product['price'];
                                $stock = $product->stock;
                                $is_vr = false;
                                $mychitti_fee = $product->mychitty_fee;
                            }

                            if (($stock - $c['quantity']) < 6) {
                                _stock_alert_sms($store->phone, $product['name']);
                                $title = 'Low Stock Alert for ' . $product['name'];
                                $msg = "Dear Vendor, Stock for " . $product['name'] . " is low. Please update accordingly.";
                                $to = $store->id;
                                $url = route('vendor.item.stock-limit-list');
                                $user_typ = 'vendor';
                                _inAppNotification($title, $msg, $acceptnce_id = '', $to, $url, $user_typ);
                            }


                            if (config('module.' . $product->module->module_type)['stock']) {
                                if ($c['quantity'] > $stock) {
                                    return response()->json([
                                        'errors' => [
                                            ['code' => 'campaign', 'message' => translate('messages.product_out_of_stock', ['item' => $product->name])]
                                        ]
                                    ]);
                                }

                                $product_data[] = [
                                    'item' => clone $product,
                                    'quantity' => $c['quantity'],
                                    'variant' => count($c['variation']) > 0 ? $c['variation'][0]['type'] : null
                                ];
                            }

                            // $product->tax = $store->tax;
                            $product = Helpers::product_data_formatting($product, false, false, app()->getLocale());
                            $addon_data = Helpers::calculate_addon_price(\App\Models\AddOn::whereIn('id', $c['add_on_ids'])->get(), $c['add_on_qtys']);

                            if (isset($c['variation']) && $c['variation']) {
                                $mrpprice = $c['variation'][0]['mrpprice'] ?? $c['variation'][0]['price'];
                                $price = $c['variation'][0]['price'];
                                $product_discount = Helpers::product_discount_calculate_vr($c['variation']);
                                $mychitti_fee = isset($c['variation'][0]['askingprice']) ? $price - $c['variation'][0]['askingprice'] : 0;
                            } else {
                                $mrpprice = $product->mrp_price;
                                $price = $product->price;
                                $mychitti_fee = $product->mychitty_fee;
                                $product_discount = Helpers::product_discount_calculate($product, $mrpprice, $store);
                            }
                            $tax_amount =  _taxCalcluation($price, $product->tax)['gst_amount'];
                            $taxable = _taxCalcluation($price, $product->tax)['price_excluding_gst'];

                            $or_d = [
                                'item_id' => $c['item_id'],
                                'item_campaign_id' => null,
                                'item_details' => json_encode($product),
                                'quantity' => $c['quantity'],
                                'price' => $price,
                                'taxable_amount' => $taxable,
                                'tax_amount' => $tax_amount,
                                'discount_on_item' => $product_discount['discount_amount'],
                                'discount_type' => $product_discount['discount_type'],
                                'variant' => json_encode($c['variant']),
                                'variation' => json_encode($c['variation']),
                                'platform_fee' => $mychitti_fee ?? 0,
                                'add_ons' => json_encode($addon_data['addons']),
                                'total_add_on_price' => $addon_data['total_add_on_price'],
                                'created_at' => now(),
                                'updated_at' => now()
                            ];

                            // prx($product_discount['discount_amount']);
                            $total_addon_price += $or_d['total_add_on_price'];
                            $total_order_tax += ($tax_amount * $or_d['quantity']);
                            if ($is_vr) {
                                $product_price += ($price * $or_d['quantity']);
                            } else {
                                $product_price += $price * $or_d['quantity'];
                            }

                            $store_discount_amount += $or_d['discount_type'] != 'flash_sale' ? $or_d['discount_on_item'] * $or_d['quantity'] : 0;
                            $flash_sale_admin_discount_amount += $or_d['discount_type'] == 'flash_sale' ? $product_discount['admin_discount_amount'] * $or_d['quantity'] : 0;
                            $flash_sale_vendor_discount_amount += $or_d['discount_type'] == 'flash_sale' ? $product_discount['vendor_discount_amount'] * $or_d['quantity'] : 0;
                            $order_details[] = $or_d;
                        }
                    } else {
                        return response()->json([
                            'errors' => [
                                ['code' => 'item', 'message' => translate('messages.product_unavailable_warning')]
                            ]
                        ]);
                    }
                }
            }
            $order->discount_on_product_by = 'vendor';
            $store_discount = Helpers::get_store_discount($store);
            if (isset($store_discount)) {
                $order->discount_on_product_by = 'admin';
                if ($product_price + $total_addon_price < $store_discount['min_purchase']) {
                    $store_discount_amount = 0;
                }
                if ($store_discount['max_discount'] != 0 && $store_discount_amount > $store_discount['max_discount']) {
                    $store_discount_amount = $store_discount['max_discount'];
                }
            }
            $coupon_discount_amount = $coupon ? CouponLogic::get_discount($coupon, $product_price + $total_addon_price - $store_discount_amount - $flash_sale_admin_discount_amount - $flash_sale_vendor_discount_amount) : 0;
            $total_price = $product_price + $total_addon_price - $total_addon_price - $flash_sale_admin_discount_amount - $flash_sale_vendor_discount_amount  - $coupon_discount_amount;
            $tax = ($store->tax > 0) ? $store->tax : 0;
            $order->tax_status = 'included';

            $tax_included = BusinessSetting::where(['key' => 'tax_included'])->first() ?  BusinessSetting::where(['key' => 'tax_included'])->first()->value : 0;
            if ($tax_included ==  1) {
                $order->tax_status = 'included';
            }

            $total_tax_amount = Helpers::product_tax($total_price, $tax, $order->tax_status == 'included');
            $tax_a = $order->tax_status == 'included' ? 0 : $total_tax_amount;


            if ($store->minimum_order > $product_price + $total_addon_price) {
                return response()->json([
                    'errors' => [
                        ['code' => 'order_time', 'message' => translate('messages.you_need_to_order_at_least') . $store->minimum_order . ' ' . Helpers::currency_code()]
                    ]
                ]);
            }

            $free_delivery_over = BusinessSetting::where('key', 'free_delivery_over')->first()->value;
            if (isset($free_delivery_over)) {
                if ($free_delivery_over <= $product_price + $total_addon_price - $coupon_discount_amount - $store_discount_amount - $flash_sale_admin_discount_amount - $flash_sale_vendor_discount_amount) {
                    $order->delivery_charge = 0;
                    $free_delivery_by = 'admin';
                }
            }

            if ($store->free_delivery) {
                $order->delivery_charge = 0;
                $free_delivery_by = 'vendor';
            }

            if ($coupon) {
                if ($coupon->coupon_type == 'free_delivery') {
                    if ($coupon->min_purchase <= $product_price + $total_addon_price - $store_discount_amount - $flash_sale_admin_discount_amount - $flash_sale_vendor_discount_amount) {
                        $order->delivery_charge = 0;
                        $free_delivery_by = $coupon->created_by;
                    }
                }
                $coupon->increment('total_uses');
            }
            $order->coupon_created_by = $coupon_created_by;
            $order->coupon_discount_amount = round($coupon_discount_amount, config('round_up_to_digit'));
            $order->coupon_discount_title = $coupon ? $coupon->title : '';

            $order->store_discount_amount = round($store_discount_amount, config('round_up_to_digit'));
            $order->tax_percentage = $tax;
            $order->total_tax_amount = $total_order_tax ?? round($total_tax_amount, config('round_up_to_digit'));
            $order->rounded_off = ($total_price + $tax_a + $order->delivery_charge) - floor($total_price + $tax_a + $order->delivery_charge);
            $order->order_amount = round($total_price + $tax_a + $order->delivery_charge);

            $order->free_delivery_by = $free_delivery_by;
        } else {

            $point = new Point(json_decode($request->receiver_details, true)['latitude'], json_decode($request->receiver_details, true)['longitude']);
            $zone_id =  json_decode($request->receiver_details, true)['zone_id'];
            $zone = Zone::where('id', $zone_id)->whereContains('coordinates', new Point(json_decode($request->receiver_details, true)['latitude'], json_decode($request->receiver_details, true)['longitude'], POINT_SRID))->first();
            if (!$zone) {
                $errors = [];
                array_push($errors, ['code' => 'receiver_details', 'message' => translate('messages.out_of_coverage')]);
                return response()->json([
                    'errors' => $errors
                ]);
            }
            $order->delivery_charge = round($original_delivery_charge, config('round_up_to_digit')) ?? 0;
            $order->original_delivery_charge = round($original_delivery_charge, config('round_up_to_digit'));


            $order->order_amount = round($order->delivery_charge);
        }
        $order->flash_admin_discount_amount = round($flash_sale_admin_discount_amount, config('round_up_to_digit'));
        $order->flash_store_discount_amount = round($flash_sale_vendor_discount_amount, config('round_up_to_digit'));
        //DM TIPs

        $order->order_amount = $order->order_amount + $order->dm_tips + $order->additional_charge;

        $order->rounded_off = ($order->order_amount) - floor($order->order_amount);

        if ($request->payment_method == 'wallet' && $user->wallet_balance < $order->order_amount) {
            return response()->json([
                'errors' => [
                    ['code' => 'order_amount', 'message' => translate('messages.insufficient_balance')]
                ]
            ]);
        }
        if ($request->partial_payment && $user->wallet_balance > $order->order_amount) {
            return response()->json([
                'errors' => [
                    ['code' => 'partial_payment', 'message' => translate('messages.order_amount_must_be_greater_than_wallet_amount')]
                ]
            ]);
        }
        if (isset($module_wise_delivery_charge) && $request->payment_method == 'cash_on_delivery' && $module_wise_delivery_charge->pivot->maximum_cod_order_amount && $order->order_amount > $module_wise_delivery_charge->pivot->maximum_cod_order_amount) {
            return response()->json([
                'errors' => [
                    ['code' => 'order_amount', 'message' => translate('messages.amount_crossed_maximum_cod_order_amount')]
                ]
            ]);
        }

        try {
            DB::beginTransaction();

            $order->save();
            if ($request->order_type !== 'parcel') {
                foreach ($order_details as $key => $item) {
                    $order_details[$key]['order_id'] = $order->id;

                    if ($store_discount_amount <= 0) {
                        $order_details[$key]['discount_on_item'] = 0;
                    }
                }
                OrderDetail::insert($order_details);
                if (count($product_data) > 0) {
                    foreach ($product_data as $item) {
                        ProductLogic::update_stock($item['item'], $item['quantity'], $item['variant'])->save();
                        ProductLogic::update_flash_stock($item['item'], $item['quantity'])?->save();
                    }
                }
                $store->increment('total_order');
            }
            if (!isset($request->is_buy_now) || (isset($request->is_buy_now) && $request->is_buy_now == 0)) {
                foreach ($carts as $cart) {
                    // $cart->delete();
                }
            }

            if ($user) {
                $customer = $user;
                $customer->zone_id = $order->zone_id;
                $customer->save();

                if ($request->payment_method == 'wallet') CustomerLogic::create_wallet_transaction($order->user_id, $order->order_amount, 'order_place', $order->id);

                if ($request->partial_payment) {
                    if ($user->wallet_balance <= 0) {
                        return response()->json([
                            'errors' => [
                                ['code' => 'order_amount', 'message' => translate('messages.insufficient_balance_for_partial_amount')]
                            ]
                        ], 203);
                    }
                    $p_amount = min($user->wallet_balance, $order->order_amount);
                    $unpaid_amount = $order->order_amount - $p_amount;
                    $order->partially_paid_amount = $p_amount;

                    $order->save();
                    CustomerLogic::create_wallet_transaction($order->user_id, $p_amount, 'partial_payment', $order->id);
                    OrderLogic::create_order_payment(order_id: $order->id, amount: $p_amount, payment_status: 'paid', payment_method: 'wallet');
                    OrderLogic::create_order_payment(order_id: $order->id, amount: $unpaid_amount, payment_status: 'unpaid', payment_method: $request->payment_method);
                }
            }

            DB::commit();


            $payments = $order->payments()->where('payment_method', 'cash_on_delivery')->exists();
            $order_mail_status = Helpers::get_mail_status('place_order_mail_status_user');
            $order_verification_mail_status = Helpers::get_mail_status('order_verification_mail_status_user');

            //PlaceOrderMail
            try {
                if (0 && !in_array($order->payment_method, ['digital_payment', 'partial_payment', 'offline_payment'])  || $payments) {
                    Helpers::send_order_notification($order);

                    if ($order->order_status == 'pending' && config('mail.status') && $order_mail_status == '1' && $user) {

                        Mail::to($user->email)->send(new PlaceOrder($order->id));
                    }
                    if ($order->order_status == 'pending' && config('order_delivery_verification') == 1 && $order_verification_mail_status == '1' && $user) {
                        Mail::to($user->email)->send(new OrderVerificationMail($order->otp, $user->f_name));
                    }
                    if ($order->is_guest == 1 && $order->order_status == 'pending' && config('mail.status') && $order_mail_status == '1' && isset($request->contact_person_email)) {
                        Mail::to($request->contact_person_email)->send(new PlaceOrder($order->id));
                    }
                    if ($order->is_guest == 1 && $order->order_status == 'pending' && config('order_delivery_verification') == 1 && $order_verification_mail_status == '1' && isset($request->contact_person_email)) {
                        Mail::to($request->contact_person_email)->send(new OrderVerificationMail($order->otp, $request->contact_person_name));
                    }
                }
            } catch (\Exception $ex) {
                // info($ex->getMessage());
            }

            // place order sms, email and in app notification to vendor  =================== 
            $title = "Received New Order";
            $msg = "Good news! You've got a new order. Let's get it ready!";
            $acceptnce_id = '';
            $to = $store->id;
            $url = route('vendor.order.list', ['pending']);
            $user_typ = 'vendor';

            _inAppNotification($title, $msg, $acceptnce_id, $to, $url, $user_typ);
            // _sendMailToVendor($title, $msg, $to, $url); 
            $smsTemplate = "Hello! Your order NO " . $order->id . " is received. Please review the details on My Chitti Vendor Dashboard and confirm accuracy.";
            _sendSMS($store->phone, $smsTemplate);
            _sendOrderSMSToAdmins($order, $user, $store);

            // SendOrderNotifications::dispatch( 
            //     $title, 
            //     $msg,
            //     $acceptnce_id, 
            //     $to,
            //     $url,
            //     $user_typ,
            //     $order->id,
            //     $store->phone
            // );


            // place order sms, email and in app notification to vendor ===================
            return response()->json([
                'message' => translate('messages.order_placed_successfully'),
                'order_id' => $order->id,
                'payment_method' => $request->payment_method,
                'total_ammount' => $order->order_amount,
                'status' => $order->order_status,
                'created_at' => $order->created_at,
                'url' => $request->payment_method == 'digital_payment'  ? "payment-mobile?customer_id=" . $user_id . "&order_id=" . $order->id . "&payment_platform=web&payment_method=razor_pay&callback=/success" : ''
            ], 200);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([$e], 403);
        }
        return response()->json([
            'errors' => [
                ['code' => 'order_time', 'message' => translate('messages.failed_to_place_order')]
            ]
        ]);
    }

    public function change_variation(Request $request)
    {
        $vrType = $request->type;
        $prId = $request->id;

        $item = DB::table('items')->where('id', $prId)->first();
        $variations = json_decode($item->variations);
        $selectedVr = [];

        foreach ($variations as $key => $value) {
            if ($value->type == $vrType) {
                $selectedVr = $value;
                $selectedVr->discounted_price =  $selectedVr->price;
                $vrDetails = ItemVariationDetail::find($selectedVr->variations_table_id);
                $selectedVr->variation_details = $vrDetails;
            }
        }
        return response()->json(['status' => true, 'data' => $selectedVr]);
    }
    public function order_success(Request $request, $order_id = null)
    {
        $order_id = $order_id;
        return view('front-views.order-success', compact('order_id'));
    }
    public function store_gallery(Request $request, $slug = null)
    {
        // If the store is already resolved via custom domain middleware, use that context
        $store = $request->attributes->get('store_domain_store');
        if ($store) {
            $store->load('galleries');
        } else {
            // Resolve from the route param explicitly (not $request->slug, which can be shadowed
            // by input) and bypass global scopes — the slug is unique, and on a custom domain
            // there's no zone/session context to scope by.
            $slug = $slug ?: $request->route('slug');
            $store = Store::withoutGlobalScopes()->with('galleries')->where('slug', $slug)->first();
        }
        if (!$store) {
            abort(404); 
        }
        return view('front-views.store_gallery', compact('store'));
    }
    public function trackBannerClick(Request $request)
    {
        $bannerId = $request->banner_id;
        $banner = DB::table('banners')->where('id', $bannerId)->first();
        if (!$banner) {
            return response()->json(['message' => 'Banner not found'], 404);
        }

        $ip = $request->ip();
        $isUnique = !DB::table('analytics_logs')
            ->where('screen_type', 'banner')
            ->where('ref_id', $bannerId)
            ->where('ip', $ip)
            ->whereDate('created_at', now()->toDateString())
            ->exists();

        DB::table('banners')->where('id', $bannerId)->increment('total_clicks');
        if ($isUnique) {
            DB::table('banners')->where('id', $bannerId)->increment('unique_clicks');
        }

        DB::table('analytics_logs')->insert([
            'screen_type' => 'banner',
            'sub_type' => 'web',
            'ref_id' => $bannerId,
            'user_id' => auth()->check() ? auth()->id() : null,
            'ip' => $ip,
            'created_at' => now(),
        ]);

        return response()->json(['message' => 'Banner click counted']);
    }

    public function trackAdClick(Request $request)
    {
        $adId = $request->ad_id;
        $ad = DB::table('notifications')->where('id', $adId)->whereNotNull('vendor_id')->first();
        if (!$ad) {
            return response()->json(['message' => 'Ad not found'], 404);
        }

        $ip = $request->ip();

        DB::table('notifications')->where('id', $adId)->increment('total_clicks');

        try {
            $isUnique = !DB::table('analytics_logs')
                ->where('screen_type', 'ad')
                ->where('ref_id', $adId)
                ->where('ip', $ip)
                ->whereDate('created_at', now()->toDateString())
                ->exists();

            if ($isUnique) {
                DB::table('notifications')->where('id', $adId)->increment('unique_clicks');
            }

            DB::table('analytics_logs')->insert([
                'screen_type' => 'ad',
                'sub_type'    => 'web',
                'ref_id'      => $adId,
                'user_id'     => auth()->check() ? auth()->id() : null,
                'ip'          => $ip,
                'created_at'  => now(),
            ]);
        } catch (\Exception $e) {
            // analytics_logs failure must not prevent the increment
        }

        return response()->json(['message' => 'Ad click counted']);
    }

    public function trackStoreContactClick(Request $request)
    {
        $storeId = $request->store_id;
        $action  = $request->action;

        // Platform analytics events (analytics_logs) — call reuses phone-call analytics,
        // copy is a web-only event, share = store share, whatsapp/enquiry come from the
        // store cards (product detail page, store page) and get their own Performance
        // Analytics stat.
        $screenType = match ($action) {
            'call'     => 'call',
            'copy'     => 'copy',
            'share'    => 'share',
            'whatsapp' => 'whatsapp',
            'enquiry'  => 'enquiry',
            default    => null,
        };

        // Inbound-lead actions (Phase 3 §3.3) — also recorded to lead_signals for the MC Vendor Hub
        // Lead Inbox. 'copy'/'share' are analytics-only; everything here is a real lead intent.
        // lead_signals.type is an ENUM, so 'enquiry' rides on the existing 'booking' member.
        $leadType  = $action === 'enquiry' ? 'booking' : $action;
        $leadTypes = ['call', 'whatsapp', 'booking', 'quote', 'direction', 'website'];
        $isLead = in_array($leadType, $leadTypes, true);

        if (!$screenType && !$isLead) {
            return response()->json(['message' => 'Invalid action'], 422);
        }

        $store = DB::table('stores')->where('id', $storeId)->first();
        if (!$store) {
            return response()->json(['message' => 'Store not found'], 404);
        }

        $ip = $request->ip();

        // 1) Platform analytics — identical to before (only for call/copy/share).
        if ($screenType) {
            // sub_type: for 'share' it holds the share target ('store'); otherwise the source platform ('web').
            $subType = $action === 'share' ? 'store' : 'web';
            try {
                DB::table('analytics_logs')->insert([
                    'screen_type' => $screenType,
                    'sub_type'    => $subType,
                    'ref_id'      => $storeId,
                    'user_id'     => auth()->check() ? auth()->id() : null,
                    'ip'          => $ip,
                    'created_at'  => now(),
                ]);
            } catch (\Exception $e) {
                // analytics failure must not break the click
            }
        }

        // 2) Lead Inbox signal — full funnel (call/whatsapp/booking/quote/direction/website).
        if ($isLead) {
            try {
                DB::table('lead_signals')->insert([
                    'store_id'     => $storeId,
                    'user_id'      => auth()->check() ? auth()->id() : null,
                    'type'         => $leadType,
                    'source'       => $request->input('source', 'web'),
                    'utm_source'   => $request->input('utm_source'),
                    'utm_medium'   => $request->input('utm_medium'),
                    'utm_campaign' => $request->input('utm_campaign'),
                    'meta'         => json_encode(['ip' => $ip, 'ua' => substr((string) $request->userAgent(), 0, 255)]),
                    'created_at'   => now(),
                    'updated_at'   => now(),
                ]);
            } catch (\Exception $e) {
                // lead capture failure must not break the click
            }
        }

        return response()->json(['message' => 'ok']);
    }

    private function adsBaseQuery()
    {
        $zone_ids = json_decode($this->zone_id, true);
        return \App\Models\Notification::whereNotNull('vendor_id')
            ->where('approval', 1)
            ->where('status', 1)
            ->whereNotNull('image')
            ->where(function ($q) {
                $q->whereNull('days')
                  ->orWhereNull('approved_at')
                  ->orWhereRaw('DATE_ADD(approved_at, INTERVAL days DAY) >= NOW()');
            })
            ->where(function ($q) use ($zone_ids) {
                $q->whereIn('zone_id', $zone_ids)
                    ->orWhereNull('zone_id')
                    ->orWhere('zone_id', 0);
            })
            ->latest();
    }
 
    public function allAds()
    {
        $ads = $this->adsBaseQuery()->paginate(18);
        return view('front-views.ads.index', compact('ads'));
    }

    public function loadAds(Request $request)
    {
        $ads = $this->adsBaseQuery()->paginate(12);
        $html = view('front-views.ads._ad_cards', compact('ads'))->render();
        return response()->json([
            'html'     => $html,
            'has_more' => $ads->hasMorePages(),
        ]);
    }

    public function adDetail($id)
    {
        $ad = \App\Models\Notification::whereNotNull('vendor_id')
            ->where('approval', 1)
            ->where('status', 1)
            ->findOrFail($id);

        try {
            $ip = request()->ip();
            $isUnique = !DB::table('analytics_logs')
                ->where('screen_type', 'ad')
                ->where('ref_id', $id)
                ->where('ip', $ip)
                ->whereDate('created_at', now()->toDateString())
                ->exists();

            DB::table('notifications')->where('id', $id)->increment('total_clicks');
            if ($isUnique) {
                DB::table('notifications')->where('id', $id)->increment('unique_clicks');
            }
            DB::table('analytics_logs')->insert([
                'screen_type' => 'ad',
                'sub_type'    => 'web',
                'ref_id'      => $id,
                'user_id'     => auth()->check() ? auth()->id() : null,
                'ip'          => $ip,
                'created_at'  => now(),
            ]);
        } catch (\Exception $e) {
            // analytics failure must not break the page
        }

        $store = $ad->vendor_id ? DB::table('stores')->where('id', $ad->vendor_id)->first() : null;
        return view('front-views.ads.detail', compact('ad', 'store'));
    }

    public function store_details(Request $request, $city, $slug)
    {
        $check_module = DB::table('stores')->where('slug', $slug)->first();
        if ($check_module) {
            $module = $check_module->module_id;
        } else {
            abort(404);
        }

        // One canonical city per store (falls back to the platform default for zone-less stores).
        $canonicalCity = 'tirupati';
        if ($check_module->zone_id) {
            $zone = DB::table('zones')->where('id', $check_module->zone_id)->value('name');
            if ($zone) {
                $canonicalCity = _zoneCitySlug($zone);
            }
        }
        // 301 any other city to the single canonical URL — kills duplicate / soft-404 pages.
        if ($city !== $canonicalCity) {
            return redirect()->to(url($canonicalCity . '/store/' . $slug), 301);
        }
        // True canonical for the store page (overrides the layout's self-referencing default).
        view()->share('canonical', url($canonicalCity . '/store/' . $slug));
        $invItemdata = [];
        $longitude = $this->longitude;
        $latitude = $this->latitude;
        $store = Store::with(['discount' => function ($q) {
            return $q->validate();
        }, 'campaigns', 'schedules', 'activeCoupons'])
            ->withCount(['items', 'campaigns'])
            ->when($module, function ($query) use ($module) {
                $query->module($module);
            })
            ->where('slug', $slug)
            ->first();


        if ($store) {
            // Thin-content guard: keep genuinely empty store shells (no items, no campaigns,
            // no specialised business type) out of the index so they aren't flagged soft-404.
            view()->share('metaRobots',
                ($store->items_count == 0 && $store->campaigns_count == 0 && empty($store->business_type)) ? 'noindex, follow' : null);
 
            // LocalBusiness JSON-LD (P0) — emitted in the layout head for every store template.
            view()->share('localBusinessStore', $store);

            // Increment store visit analytics
            $ip = $request->ip();
            $isUnique = !DB::table('analytics_logs')
                ->where('screen_type', 'store')
                ->where('ref_id', $store->id)
                ->where('ip', $ip)
                ->whereDate('created_at', now()->toDateString())
                ->exists();

            DB::table('stores')->where('id', $store->id)->increment('total_visits');
            if ($isUnique) {
                DB::table('stores')->where('id', $store->id)->increment('unique_visits');
            }

            DB::table('analytics_logs')->insert([
                'screen_type' => 'store',
                'sub_type' => 'web',
                'ref_id' => $store->id,
                'user_id' => auth()->check() ? auth()->id() : null,
                'ip' => $ip,
                'created_at' => now(),
            ]);

            if ($module == 5) {

                $keywordsData = DB::table('items')
                    ->where('items.is_approved', 1)
                    ->join('categories', 'items.category_id', '=', 'categories.id')
                    ->where('items.store_id', $store->id)
                    ->select('items.name as item_name', 'categories.name as category_name')
                    ->distinct()
                    ->get();

                $keywords = implode(',', $keywordsData->pluck('item_name')->merge($keywordsData->pluck('category_name'))->toArray());

                $category_ids = DB::table('items')
                    ->join('categories', 'items.category_id', '=', 'categories.id')
                    ->selectRaw('categories.position as positions, IF((categories.position = "0"), categories.id, categories.parent_id) as categories')
                    ->where('items.store_id', $store->id)
                    ->where('categories.status', 1)
                    ->groupBy('categories', 'positions')
                    ->get();

                $store = Helpers::store_data_formatting($store);
                $store['category_ids'] = array_map('intval', $category_ids->pluck('categories')->toArray());
                $store['category_details'] = Category::whereIn('id', $store['category_ids'])->get();
                $store['price_range']  = Item::withoutGlobalScopes()->where('store_id', $store->id)
                    ->select(DB::raw('MIN(price) AS min_price, MAX(price) AS max_price'))
                    ->get(['min_price', 'max_price']);

                $productdata = DB::table('items')
                    ->join('categories', 'items.category_id', 'categories.id')
                    ->where('items.store_id', $store->id)
                    ->where('items.status', 1)
                    ->where('items.is_approved', 1)
                    ->select('categories.id', 'categories.name', 'categories.slug as cat_slug')
                    ->distinct()
                    ->get()
                    ->toArray();

                foreach ($productdata as $key => $cat) {
                    $cat->items = DB::table('items')
                        ->where('store_id', $store->id)
                        ->where('category_id', $cat->id)
                        ->where('status', 1)
                        ->where('is_approved', 1)
                        ->get();
                }
            } else {
                $keywordsData = DB::table('items')
                    ->where('items.is_approved', 1)
                    ->join('categories', 'items.category_id', '=', 'categories.id')
                    ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                    ->select('items.name as item_name', 'categories.name as category_name')
                    ->distinct()
                    ->get();

                $keywords = implode(',', $keywordsData->pluck('item_name')->merge($keywordsData->pluck('category_name'))->toArray());
                // echo '
';
                // SERVICES
                $productdata1 = DB::table('items')
                    ->join('categories', 'items.category_id', 'categories.id')
                    ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                    ->whereNull('items.inventory_item_id')
                    ->where('categories.status', 1)
                    ->select('categories.id', 'categories.name', 'categories.slug as cat_slug')
                    ->distinct()
                    ->get();


                foreach ($productdata1 as $cat) {
                    $cat->items = DB::table('items')
                        ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                        ->whereNull('items.inventory_item_id')
                        ->where('category_id', $cat->id)
                        ->where('status', 1)
                        ->get();
                }

                //INVENTORY ITEMS
                $invItemdata = DB::table('items')
                    ->join('categories', 'items.category_id', 'categories.id')
                    ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                    ->whereNotNull('items.inventory_item_id')
                    ->select('categories.id', 'categories.name', 'categories.slug as cat_slug')
                    ->distinct()
                    ->get();

                foreach ($invItemdata as $cat) {
                    $cat->items = DB::table('items')
                        ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                        ->whereNotNull('items.inventory_item_id')
                        ->where        }

        if ($request->partial_payment && !Helpers::get_business_settings('partial_payment_status')) {
            return response()->json([
                'errors' => [
                    ['code' => 'order_method', 'message' => translate('messages.partial_payment_is_not_active')]
                ]
            ]);
        }

        if ($request->payment_method == 'offline_payment' &&  Helpers::get_mail_status('offline_payment_status') == 0) {
            return response()->json([
                'errors' => [
                    ['code' => 'offline_payment_status', 'message' => translate('messages.offline_payment_for_the_order_not_available_at_this_time')]
                ]
            ]);
        }

        $digital_payment = Helpers::get_business_settings('digital_payment');
        if ($digital_payment['status'] == 0 && $request->payment_method == 'digital_payment') {
            return response()->json([
                'errors' => [
                    ['code' => 'digital_payment', 'message' => translate('messages.digital_payment_for_the_order_not_available_at_this_time')]
                ]
            ]);
        }

        $data =  DMVehicle::active()->where(function ($query) use ($distance_data) {
            $query->where('starting_coverage_area', '<=', $distance_data)->where('maximum_coverage_area', '>=', $distance_data)
                ->orWhere(function ($query) use ($distance_data) {
                    $query->where('starting_coverage_area', '>=', $distance_data);
                });
        })
            ->orderBy('starting_coverage_area')->first();

        $extra_charges = (float) (isset($data) ? $data->extra_charges  : 0);
        $vehicle_id = (isset($data) ? $data->id  : null);

        $zone = null;
        if ($request->latitude[$key] && $request->longitude[$key]) {
            $point = new Point($request->latitude[$key], $request->longitude[$key]);
            if ($request->order_type == 'parcel') {
                // if(isset($request->sender_zone_id) ){
                // $zone_id = $request->sender_zone_id;
                $zone_ids = $request->header('zoneId') ? json_decode($request->header('zoneId'), true) : [];
                $zone = Zone::whereIn('id', $zone_ids)->whereContains('coordinates', new Point($request->latitude[$key], $request->longitude[$key], POINT_SRID))->wherehas('modules', function ($q) {
                    $q->where('module_type', 'parcel');
                })->first();
            } else {
                // ->selectRaw('*, IF(((select count(*) from `store_schedule` where `stores`.`id` = `store_schedule`.`store_id` and `store_schedule`.`day` = ' . $schedule_at->format('w') . ' and `store_schedule`.`opening_time` < "' . $schedule_at->format('H:i:s') . '" and `store_schedule`.`closing_time` >"' . $schedule_at->format('H:i:s') . '") > 0), true, false) as open')
                $store = Store::with('discount')->where('id', $request->store_id)->first();

                if (!$store) {
                    return response()->json([
                        'errors' => [
                            ['code' => 'order_time', 'message' => translate('messages.store_not_found')]
                        ]
                    ]);
                }
                $zone_id =  [$store->zone_id];
                $zone = Zone::where('id', $zone_id)->whereContains('coordinates', new Point($request->latitude[$key], $request->longitude[$key], POINT_SRID))->first();
            }
        }
        if (!$zone) {
            $errors = [];
            array_push($errors, ['code' => 'coordinates', 'message' => translate('messages.out_of_coverage')]);
            return response()->json([
                'errors' => $errors
            ]);
        }
        if ($zone && $zone->increased_delivery_fee_status == 1) {
            $increased = $zone->increased_delivery_fee ?? 0;
        }

        if ($request->order_type !== 'parcel') {


            if (!$store->active) {
                return response()->json([
                    'errors' => [
                        ['code' => 'order_time', 'message' => translate('messages.store_is_closed_at_order_time')]
                    ]
                ]);
            }

            if ($request->coupon_code) {
                $coupon = Coupon::active()->where(['code' => $request->coupon_code])->first();
                if (isset($coupon)) {


                    $staus = CouponLogic::is_valide($coupon, $user->id, $request->store_id);


                    if ($staus == 407) {
                        return response()->json([
                            'errors' => [
                                ['code' => 'coupon', 'message' => translate('messages.coupon_expire')]
                            ]
                        ]);
                    } else if ($staus == 408) {
                        return response()->json([
                            'errors' => [
                                ['code' => 'coupon', 'message' => translate('messages.You_are_not_eligible_for_this_coupon')]
                            ]
                        ]);
                    } else if ($staus == 406) {
                        return response()->json([
                            'errors' => [
                                ['code' => 'coupon', 'message' => translate('messages.coupon_usage_limit_over')]
                            ]
                        ]);
                    } else if ($staus == 404) {
                        return response()->json([
                            'errors' => [
                                ['code' => 'coupon', 'message' => translate('messages.not_found')]
                            ]
                        ]);
                    }

                    $coupon_created_by = $coupon->created_by;
                    if ($coupon->coupon_type == 'free_delivery') {
                        $delivery_charge = 0;
                        $free_delivery_by =  $coupon_created_by;
                        $coupon_created_by = null;
                    }
                } else {
                    return response()->json([
                        'errors' => [
                            ['code' => 'coupon', 'message' => translate('messages.not_found')]
                        ]
                    ], 404);
                }
            }

            $module_wise_delivery_charge = $store->zone->modules()->where('modules.id', 5)->first();
            if ($module_wise_delivery_charge) {
                $per_km_shipping_charge = $module_wise_delivery_charge->pivot->per_km_shipping_charge;
                $minimum_shipping_charge = $module_wise_delivery_charge->pivot->minimum_shipping_charge;
                $maximum_shipping_charge = $module_wise_delivery_charge->pivot->maximum_shipping_charge;
            } else {
                $per_km_shipping_charge = (float)BusinessSetting::where(['key' => 'per_km_shipping_charge'])->first()->value;
                $minimum_shipping_charge = (float)BusinessSetting::where(['key' => 'minimum_shipping_charge'])->first()->value;
            }

            if ($request->order_type != 'take_away' && !$store->free_delivery && !isset($delivery_charge) &&  $store->self_delivery_system == 1) {
                $per_km_shipping_charge = $store->per_km_shipping_charge;
                $minimum_shipping_charge = $store->minimum_shipping_charge;
                $maximum_shipping_charge = $store->maximum_shipping_charge;
                $extra_charges = 0;
                $vehicle_id = null;
                $increased = 0;
            }

            if ($store->free_delivery || $free_delivery_by == 'vendor') {
                $per_km_shipping_charge = $store->per_km_shipping_charge;
                $minimum_shipping_charge = $store->minimum_shipping_charge;
                $maximum_shipping_charge = $store->maximum_shipping_charge;
                $extra_charges = 0;
                $increased = 0;
            }

            $original_delivery_charge = (($request->distance * $per_km_shipping_charge) > $minimum_shipping_charge) ? $request->distance * $per_km_shipping_charge  : $minimum_shipping_charge;

            if ($request->order_type == 'take_away') {
                $per_km_shipping_charge = 0;
                $minimum_shipping_charge = 0;
                $maximum_shipping_charge = 0;
                $extra_charges = 0;
                $distance_data = 0;
                $vehicle_id = null;
                $original_delivery_charge = 0;
                $increased = 0;
            }

            if ($maximum_shipping_charge  >= $minimum_shipping_charge  && $original_delivery_charge >  $maximum_shipping_charge) {
                $original_delivery_charge = $maximum_shipping_charge;
            } else {
                $original_delivery_charge = $original_delivery_charge;
            }

            if (!isset($delivery_charge)) {
                $delivery_charge = ($request->distance * $per_km_shipping_charge > $minimum_shipping_charge) ? $request->distance * $per_km_shipping_charge : $minimum_shipping_charge;
                if ($maximum_shipping_charge  >= $minimum_shipping_charge  && $delivery_charge >  $maximum_shipping_charge) {
                    $delivery_charge = $maximum_shipping_charge;
                } else {
                    $delivery_charge = $delivery_charge;
                }
            }
            $original_delivery_charge = $original_delivery_charge + $extra_charges;
            $delivery_charge = $delivery_charge + $extra_charges;
        } else {
            $parcel_category = ParcelCategory::findOrFail($request->parcel_category_id);
            if (isset($parcel_category) && isset($parcel_category->parcel_minimum_shipping_charge)) {
                $per_km_shipping_charge = $parcel_category->parcel_per_km_shipping_charge;
                $minimum_shipping_charge = $parcel_category->parcel_minimum_shipping_charge;
            } else {
                $per_km_shipping_charge = (float)BusinessSetting::where(['key' => 'parcel_per_km_shipping_charge'])->first()->value;
                $minimum_shipping_charge = (float)BusinessSetting::where(['key' => 'parcel_minimum_shipping_charge'])->first()->value;
            }

            $original_delivery_charge = (($request->distance * $per_km_shipping_charge) > $minimum_shipping_charge) ? ($request->distance * $per_km_shipping_charge) + $extra_charges : ($minimum_shipping_charge + $extra_charges);
        }

        if ($increased > 0) {
            if ($delivery_charge > 0) {
                $increased_fee = ($delivery_charge * $increased) / 100;
                $delivery_charge = $delivery_charge + $increased_fee;
            }
            if ($original_delivery_charge > 0) {
                $increased_fee = ($original_delivery_charge * $increased) / 100;
                $original_delivery_charge = $original_delivery_charge + $increased_fee;
            }
        }
        $address = [
            'contact_person_name' => $request->contact_person_name[$key] ? $request->contact_person_name[$key] : ($user ? $user->f_name . ' ' . $user->f_name : ''),
            'contact_person_number' => $request->contact_person_number[$key] ? ($user ? $request->contact_person_number[$key] : str_replace('+', '', $request->contact_person_number[$key])) : ($user ? $user->phone : ''),
            'contact_person_email' => $user ? $user->email : '',
            'address_type' => $request->address_type ? $request->address_type : 'Delivery',
            'address' => $request?->address[$key] ?? '',
            'floor' => $request?->floor[$key] ?? '',
            'road' => $request?->road[$key] ?? '',
            'house' => $request?->house[$key] ?? '',
            'longitude' => (string)$request->longitude[$key],
            'latitude' => (string)$request->latitude[$key],
        ];
        $total_addon_price = 0;
        $product_price = 0;
        $store_discount_amount = 0;
        $flash_sale_vendor_discount_amount = 0;
        $flash_sale_admin_discount_amount = 0;
        $store_discount_amount = 0;
        $product_data = [];

        $order_details = [];
        $order = new Order();
        $lastOrder = Order::orderBy('id', 'desc')->first();

        if ($lastOrder) {
            $order->id = $lastOrder->id + 1;
        } else {
            $order->id = 10001;
        }
        $order->invoice_id = _generateOrderInvoiceId($request->store_id);

        $order_status = 'pending';
        if (($request->partial_payment && $request->payment_method != 'offline_payment') || $request->payment_method == 'wallet') {
            $order_status = 'confirmed';
        }

        $order->user_id = $user ? $user->id : 0;
        $order->order_amount = $request->order_amount;
        $order->payment_status = ($request->partial_payment ? 'partially_paid' : ($request->payment_method == 'wallet' ? 'paid' : 'unpaid'));
        $order->order_status = $order_status;
        $order->coupon_code = $request->coupon_code;
        $order->payment_method = $request->partial_payment ? 'partial_payment' : $request->payment_method;
        $order->transaction_reference = null;
        $order->order_note = $request->order_note;
        $order->unavailable_item_note = $request->unavailable_item_note;
        $order->delivery_instruction = $request->delivery_instruction;
        $order->order_type = $request->order_type;
        $order->store_id = $request->store_id;
        if ($store->delivery_charges_on && $store->delivery_charges_on <= $request->order_amount) {
            $order->delivery_charge = 0;
        } else {
            $order->delivery_charge = round($delivery_charge, config('round_up_to_digit')) ?? 0;
        }
        $order->original_delivery_charge = round($original_delivery_charge, config('round_up_to_digit'));
        $order->delivery_address = json_encode($address);
        $order->schedule_at = $schedule_at;
        $order->scheduled = $request->schedule_at ? 1 : 0;
        $order->cutlery = $request->cutlery ? 1 : 0;
        $order->is_guest = $user ? 0 : 1;
        $order->otp = rand(1000, 9999);
        $order->zone_id = isset($zone) ? $zone->id : end(json_decode($this->zone_id, true));
        $order->module_id = 5;
        $order->parcel_category_id = $request->parcel_category_id;
        $order->receiver_details = json_decode($request->receiver_details);

        if ($order_status == 'confirmed') {
            $order->confirmed = now();
        }
        $order->dm_vehicle_id = $vehicle_id;
        $order->pending = now();
        $order->order_attachment = $request->has('order_attachment') ? Helpers::upload('order/', 'png', $request->file('order_attachment')) : null;
        $order->distance = $distance_data;
        $order->created_at = now();
        $order->updated_at = now();
        $order->charge_payer = null;

        //Added DM TIPS
        $dm_tips_manage_status = BusinessSetting::where('key', 'dm_tips_status')->first()->value;
        if ($dm_tips_manage_status == 1) {
            $order->dm_tips = $request->dm_tips ?? 0;
        } else {
            $order->dm_tips = 0;
        }
        //Added service charge
        $additional_charge_status = BusinessSetting::where('key', 'additional_charge_status')->first()->value;
        $additional_charge = BusinessSetting::where('key', 'additional_charge')->first()->value;
        if ($additional_charge_status == 1) {
            $order->additional_charge = $additional_charge ?? 0;
        } else {
            $order->additional_charge = 0;
        }

        $carts = Cart::where('user_id', $order->user_id)->where('is_guest', 0)->where('module_id', 5)
            ->when(isset($request->is_buy_now) && $request->is_buy_now == 1 && $request->cart_id, function ($query) use ($request) {
                return $query->where('id', $request->cart_id);
            })
            ->get()->map(function ($data) {
                $data->add_on_ids = json_decode($data->add_on_ids, true);
                $data->add_on_qtys = json_decode($data->add_on_qtys, true);
                $data->variation = json_decode($data->variation, true);
                return $data;
            });

        if (isset($request->is_buy_now) && $request->is_buy_now == 1) {
            $carts = json_decode($request->cart, true);
        }


        if ($request->order_type !== 'parcel') {
            foreach ($carts as $c) {
                if ($c['item_type'] === 'App\Models\ItemCampaign' || $c['item_type'] === 'AppModelsItemCampaign') {
                    $product = ItemCampaign::with('module')->active()->find($c['item_id']);
                    if ($product) {
                        if ($product->store_id != $order->store_id) {
                            return response()->json([
                                'errors' => [
                                    ['code' => 'different_stores', 'message' => translate('messages.Please_select_items_from_the_same_store')]
                                ]
                            ], 403);
                        }

                        if ($product->module->module_type == 'food' && $product->food_variations) {
                            $product_variations = json_decode($product->food_variations, true);
                            $variations = [];
                            if (count($product_variations)) {
                                $variation_data = Helpers::get_varient($product_variations, $c['variation']);
                                $price = $product['price'] + $variation_data['price'];
                                $variations = $variation_data['variations'];
                            } else {
                                $price = $product['price'];
                            }
                            // $product->tax = $store->tax;
                            $product = Helpers::product_data_formatting($product, false, false, app()->getLocale());
                            $addon_data = Helpers::calculate_addon_price(\App\Models\AddOn::whereIn('id', $c['add_on_ids'])->get(), $c['add_on_qtys']);
                            $or_d = [
                                'item_id' => null,
                                'item_campaign_id' => $c['item_id'],
                                'item_details' => json_encode($product),
                                'quantity' => $c['quantity'],
                                'price' => round($price, config('round_up_to_digit')),
                                'tax_amount' => Helpers::tax_calculate($product, $price),
                                'discount_on_item' => Helpers::product_discount_calculate($product, $price, $store)['discount_amount'],
                                'discount_type' => 'discount_on_product',
                                'variant' => json_encode($c['variant']),
                                'variation' => json_encode($variations),
                                'add_ons' => json_encode($addon_data['addons']),
                                'total_add_on_price' => $addon_data['total_add_on_price'],
                                'created_at' => now(),
                                'updated_at' => now()
                            ];
                            $order_details[] = $or_d;
                            $total_addon_price += $or_d['total_add_on_price'];
                            $product_price += $price * $or_d['quantity'];
                            $store_discount_amount += $or_d['discount_on_item'] * $or_d['quantity'];
                        } else {
                            if (count(json_decode($product['variations'], true)) > 0) {
                                $variant_data = Helpers::variation_price($product, json_encode($c['variation']));
                                $price = $variant_data['price'];
                                $stock = $variant_data['stock'];
                                $mychitti_fee = $variant_data['price'] - $variant_data['askingprice'];
                            } else {
                                $price = $product['price'];
                                $stock = $product->stock;
                                $mychitti_fee = $product->mychitty_fee;
                            }
                            if (config('module.' . $product->module->module_type)['stock']) {
                                if ($c['quantity'] > $stock) {
                                    return response()->json([
                                        'errors' => [
                                            ['code' => 'campaign', 'message' => translate('messages.product_out_of_stock', ['item' => $product->title])]
                                        ]
                                    ]);
                                }

                                $product_data[] = [
                                    'item' => clone $product,
                                    'quantity' => $c['quantity'],
                                    'variant' => count($c['variation']) > 0 ? $c['variation'][0]['type'] : null
                                ];
                            }

                            // $product->tax = $store->tax;
                            $product = Helpers::product_data_formatting($product, false, false, app()->getLocale());
                            $addon_data = Helpers::calculate_addon_price(\App\Models\AddOn::whereIn('id', $c['add_on_ids'])->get(), $c['add_on_qtys']);
                            $or_d = [
                                'item_id' => null,
                                'item_campaign_id' => $c['item_id'],
                                'item_details' => json_encode($product),
                                'quantity' => $c['quantity'],
                                'price' => $price,
                                'tax_amount' => Helpers::tax_calculate($product, $price),
                                'discount_on_item' => Helpers::product_discount_calculate($product, $price, $store)['discount_amount'],
                                'discount_type' => 'discount_on_product',
                                'variant' => json_encode($c['variant']),
                                'variation' => json_encode($c['variation']),
                                'add_ons' => json_encode($addon_data['addons']),
                                'total_add_on_price' => $addon_data['total_add_on_price'],
                                'platform_fee' => $mychitti_fee ??  0,
                                'created_at' => now(),
                                'updated_at' => now()
                            ];
                            $order_details[] = $or_d;
                            $total_addon_price += $or_d['total_add_on_price'];
                            $product_price += $price * $or_d['quantity'];
                            $store_discount_amount += $or_d['discount_on_item'] * $or_d['quantity'];
                        }
                    } else {
                        return response()->json([
                            'errors' => [
                                ['code' => 'campaign', 'message' => translate('messages.product_unavailable_warning')]
                            ]
                        ]);
                    }
                } else {
                    $product = Item::hydrate(
                        DB::table('items')->where('id',  $c['item_id'])->get()->toArray()
                    )->first();

                    if ($product) {

                        if ($product->store_id != $order->store_id) {
                            return response()->json([
                                'errors' => [
                                    ['code' => 'different_stores', 'message' => translate('messages.Please_select_items_from_the_same_store')]
                                ]
                            ]);
                        }


                        if ($product->maximum_cart_quantity && ($c['quantity'] > $product->maximum_cart_quantity)) {
                            return response()->json([
                                'errors' => [
                                    ['code' => 'quantity', 'message' => translate('messages.maximum_cart_quantity_limit_over')]
                                ]
                            ]);
                        }
                        if ($product->module->module_type == 'food' && $product->food_variations) {

                            $product_variations = json_decode($product->food_variations, true);
                            $variations = [];
                            if (count($product_variations)) {
                                $variation_data = Helpers::get_varient($product_variations, $c['variation']);
                                $mrpprice = $variation_data['mrpprice'];
                                $price = $variation_data['mrpprice'];
                                $variations =  $variation_data['variations'];
                                $mychitti_fee = $variation_data['price'] - $variation_data['askingprice'];
                            } else {
                                $mrpprice = $product['mrp_price'] ?? $product['price'];
                                $price = $product['price'];
                                $mychitti_fee = $product->mychitty_fee;
                            }
                            // $product->tax = $store->tax;
                            $product = Helpers::product_data_formatting($product, false, false, app()->getLocale());
                            $addon_data = Helpers::calculate_addon_price(\App\Models\AddOn::whereIn('id', $c['add_on_ids'])->get(), $c['add_on_qtys']);
                            $product_discount = Helpers::product_discount_calculate($product, $mrpprice, $store);

                            $tax =  _taxCalcluation($price, $product->tax)['gst_amount'];
                            $taxable = _taxCalcluation($price, $product->tax)['price_excluding_gst'];


                            $or_d = [
                                'item_id' => $c['item_id'],
                                'item_campaign_id' => null,
                                'item_details' => json_encode($product),
                                'quantity' => $c['quantity'],
                                'price' => $price,
                                'tax_amount' =>  $tax,
                                'taxable_amount' => $taxable,
                                'discount_on_item' => $product_discount['discount_amount'],
                                'discount_type' => $product_discount['discount_type'],
                                'variant' => json_encode($c['variant']),
                                'variation' => json_encode($variations),
                                'platform_fee' => $mychitti_fee ?? 0,
                                'add_ons' => json_encode($addon_data['addons']),
                                'total_add_on_price' => round($addon_data['total_add_on_price'], config('round_up_to_digit')),
                                'created_at' => now(),
                                'updated_at' => now()
                            ];
                            $total_addon_price += $or_d['total_add_on_price'];

                            $product_price += $price * $or_d['quantity'];
                            $store_discount_amount += $or_d['discount_type'] != 'flash_sale' ? $or_d['discount_on_item'] * $or_d['quantity'] : 0;
                            $flash_sale_admin_discount_amount += $or_d['discount_type'] == 'flash_sale' ? $product_discount['admin_discount_amount'] * $or_d['quantity'] : 0;
                            $flash_sale_vendor_discount_amount += $or_d['discount_type'] == 'flash_sale' ? $product_discount['vendor_discount_amount'] * $or_d['quantity'] : 0;
                            $order_details[] = $or_d;
                        } else {

                            if (count(json_decode($product['variations'], true)) > 0 && count($c['variation']) > 0) {
                                $variant_data = Helpers::variation_price($product, json_encode($c['variation']));
                                $price = $variant_data['mrpprice'];
                                $stock = $variant_data['stock'];
                                $is_vr = true;
                                $mychitti_fee = $variant_data['price'] - $variant_data['askingprice'];
                            } else {
                                $price = $product['price'];
                                $stock = $product->stock;
                                $is_vr = false;
                                $mychitti_fee = $product->mychitty_fee;
                            }

                            if (($stock - $c['quantity']) < 6) {
                                _stock_alert_sms($store->phone, $product['name']);
                                $title = 'Low Stock Alert for ' . $product['name'];
                                $msg = "Dear Vendor, Stock for " . $product['name'] . " is low. Please update accordingly.";
                                $to = $store->id;
                                $url = route('vendor.item.stock-limit-list');
                                $user_typ = 'vendor';
                                _inAppNotification($title, $msg, $acceptnce_id = '', $to, $url, $user_typ);
                            }


                            if (config('module.' . $product->module->module_type)['stock']) {
                                if ($c['quantity'] > $stock) {
                                    return response()->json([
                                        'errors' => [
                                            ['code' => 'campaign', 'message' => translate('messages.product_out_of_stock', ['item' => $product->name])]
                                        ]
                                    ]);
                                }

                                $product_data[] = [
                                    'item' => clone $product,
                                    'quantity' => $c['quantity'],
                                    'variant' => count($c['variation']) > 0 ? $c['variation'][0]['type'] : null
                                ];
                            }

                            // $product->tax = $store->tax;
                            $product = Helpers::product_data_formatting($product, false, false, app()->getLocale());
                            $addon_data = Helpers::calculate_addon_price(\App\Models\AddOn::whereIn('id', $c['add_on_ids'])->get(), $c['add_on_qtys']);

                            if (isset($c['variation']) && $c['variation']) {
                                $mrpprice = $c['variation'][0]['mrpprice'] ?? $c['variation'][0]['price'];
                                $price = $c['variation'][0]['price'];
                                $product_discount = Helpers::product_discount_calculate_vr($c['variation']);
                                $mychitti_fee = isset($c['variation'][0]['askingprice']) ? $price - $c['variation'][0]['askingprice'] : 0;
                            } else {
                                $mrpprice = $product->mrp_price;
                                $price = $product->price;
                                $mychitti_fee = $product->mychitty_fee;
                                $product_discount = Helpers::product_discount_calculate($product, $mrpprice, $store);
                            }
                            $tax_amount =  _taxCalcluation($price, $product->tax)['gst_amount'];
                            $taxable = _taxCalcluation($price, $product->tax)['price_excluding_gst'];

                            $or_d = [
                                'item_id' => $c['item_id'],
                                'item_campaign_id' => null,
                                'item_details' => json_encode($product),
                                'quantity' => $c['quantity'],
                                'price' => $price,
                                'taxable_amount' => $taxable,
                                'tax_amount' => $tax_amount,
                                'discount_on_item' => $product_discount['discount_amount'],
                                'discount_type' => $product_discount['discount_type'],
                                'variant' => json_encode($c['variant']),
                                'variation' => json_encode($c['variation']),
                                'platform_fee' => $mychitti_fee ?? 0,
                                'add_ons' => json_encode($addon_data['addons']),
                                'total_add_on_price' => $addon_data['total_add_on_price'],
                                'created_at' => now(),
                                'updated_at' => now()
                            ];

                            // prx($product_discount['discount_amount']);
                            $total_addon_price += $or_d['total_add_on_price'];
                            $total_order_tax += ($tax_amount * $or_d['quantity']);
                            if ($is_vr) {
                                $product_price += ($price * $or_d['quantity']);
                            } else {
                                $product_price += $price * $or_d['quantity'];
                            }

                            $store_discount_amount += $or_d['discount_type'] != 'flash_sale' ? $or_d['discount_on_item'] * $or_d['quantity'] : 0;
                            $flash_sale_admin_discount_amount += $or_d['discount_type'] == 'flash_sale' ? $product_discount['admin_discount_amount'] * $or_d['quantity'] : 0;
                            $flash_sale_vendor_discount_amount += $or_d['discount_type'] == 'flash_sale' ? $product_discount['vendor_discount_amount'] * $or_d['quantity'] : 0;
                            $order_details[] = $or_d;
                        }
                    } else {
                        return response()->json([
                            'errors' => [
                                ['code' => 'item', 'message' => translate('messages.product_unavailable_warning')]
                            ]
                        ]);
                    }
                }
            }
            $order->discount_on_product_by = 'vendor';
            $store_discount = Helpers::get_store_discount($store);
            if (isset($store_discount)) {
                $order->discount_on_product_by = 'admin';
                if ($product_price + $total_addon_price < $store_discount['min_purchase']) {
                    $store_discount_amount = 0;
                }
                if ($store_discount['max_discount'] != 0 && $store_discount_amount > $store_discount['max_discount']) {
                    $store_discount_amount = $store_discount['max_discount'];
                }
            }
            $coupon_discount_amount = $coupon ? CouponLogic::get_discount($coupon, $product_price + $total_addon_price - $store_discount_amount - $flash_sale_admin_discount_amount - $flash_sale_vendor_discount_amount) : 0;
            $total_price = $product_price + $total_addon_price - $total_addon_price - $flash_sale_admin_discount_amount - $flash_sale_vendor_discount_amount  - $coupon_discount_amount;
            $tax = ($store->tax > 0) ? $store->tax : 0;
            $order->tax_status = 'included';

            $tax_included = BusinessSetting::where(['key' => 'tax_included'])->first() ?  BusinessSetting::where(['key' => 'tax_included'])->first()->value : 0;
            if ($tax_included ==  1) {
                $order->tax_status = 'included';
            }

            $total_tax_amount = Helpers::product_tax($total_price, $tax, $order->tax_status == 'included');
            $tax_a = $order->tax_status == 'included' ? 0 : $total_tax_amount;


            if ($store->minimum_order > $product_price + $total_addon_price) {
                return response()->json([
                    'errors' => [
                        ['code' => 'order_time', 'message' => translate('messages.you_need_to_order_at_least') . $store->minimum_order . ' ' . Helpers::currency_code()]
                    ]
                ]);
            }

            $free_delivery_over = BusinessSetting::where('key', 'free_delivery_over')->first()->value;
            if (isset($free_delivery_over)) {
                if ($free_delivery_over <= $product_price + $total_addon_price - $coupon_discount_amount - $store_discount_amount - $flash_sale_admin_discount_amount - $flash_sale_vendor_discount_amount) {
                    $order->delivery_charge = 0;
                    $free_delivery_by = 'admin';
                }
            }

            if ($store->free_delivery) {
                $order->delivery_charge = 0;
                $free_delivery_by = 'vendor';
            }

            if ($coupon) {
                if ($coupon->coupon_type == 'free_delivery') {
                    if ($coupon->min_purchase <= $product_price + $total_addon_price - $store_discount_amount - $flash_sale_admin_discount_amount - $flash_sale_vendor_discount_amount) {
                        $order->delivery_charge = 0;
                        $free_delivery_by = $coupon->created_by;
                    }
                }
                $coupon->increment('total_uses');
            }
            $order->coupon_created_by = $coupon_created_by;
            $order->coupon_discount_amount = round($coupon_discount_amount, config('round_up_to_digit'));
            $order->coupon_discount_title = $coupon ? $coupon->title : '';

            $order->store_discount_amount = round($store_discount_amount, config('round_up_to_digit'));
            $order->tax_percentage = $tax;
            $order->total_tax_amount = $total_order_tax ?? round($total_tax_amount, config('round_up_to_digit'));
            $order->rounded_off = ($total_price + $tax_a + $order->delivery_charge) - floor($total_price + $tax_a + $order->delivery_charge);
            $order->order_amount = round($total_price + $tax_a + $order->delivery_charge);

            $order->free_delivery_by = $free_delivery_by;
        } else {

            $point = new Point(json_decode($request->receiver_details, true)['latitude'], json_decode($request->receiver_details, true)['longitude']);
            $zone_id =  json_decode($request->receiver_details, true)['zone_id'];
            $zone = Zone::where('id', $zone_id)->whereContains('coordinates', new Point(json_decode($request->receiver_details, true)['latitude'], json_decode($request->receiver_details, true)['longitude'], POINT_SRID))->first();
            if (!$zone) {
                $errors = [];
                array_push($errors, ['code' => 'receiver_details', 'message' => translate('messages.out_of_coverage')]);
                return response()->json([
                    'errors' => $errors
                ]);
            }
            $order->delivery_charge = round($original_delivery_charge, config('round_up_to_digit')) ?? 0;
            $order->original_delivery_charge = round($original_delivery_charge, config('round_up_to_digit'));


            $order->order_amount = round($order->delivery_charge);
        }
        $order->flash_admin_discount_amount = round($flash_sale_admin_discount_amount, config('round_up_to_digit'));
        $order->flash_store_discount_amount = round($flash_sale_vendor_discount_amount, config('round_up_to_digit'));
        //DM TIPs

        $order->order_amount = $order->order_amount + $order->dm_tips + $order->additional_charge;

        $order->rounded_off = ($order->order_amount) - floor($order->order_amount);

        if ($request->payment_method == 'wallet' && $user->wallet_balance < $order->order_amount) {
            return response()->json([
                'errors' => [
                    ['code' => 'order_amount', 'message' => translate('messages.insufficient_balance')]
                ]
            ]);
        }
        if ($request->partial_payment && $user->wallet_balance > $order->order_amount) {
            return response()->json([
                'errors' => [
                    ['code' => 'partial_payment', 'message' => translate('messages.order_amount_must_be_greater_than_wallet_amount')]
                ]
            ]);
        }
        if (isset($module_wise_delivery_charge) && $request->payment_method == 'cash_on_delivery' && $module_wise_delivery_charge->pivot->maximum_cod_order_amount && $order->order_amount > $module_wise_delivery_charge->pivot->maximum_cod_order_amount) {
            return response()->json([
                'errors' => [
                    ['code' => 'order_amount', 'message' => translate('messages.amount_crossed_maximum_cod_order_amount')]
                ]
            ]);
        }

        try {
            DB::beginTransaction();

            $order->save();
            if ($request->order_type !== 'parcel') {
                foreach ($order_details as $key => $item) {
                    $order_details[$key]['order_id'] = $order->id;

                    if ($store_discount_amount <= 0) {
                        $order_details[$key]['discount_on_item'] = 0;
                    }
                }
                OrderDetail::insert($order_details);
                if (count($product_data) > 0) {
                    foreach ($product_data as $item) {
                        ProductLogic::update_stock($item['item'], $item['quantity'], $item['variant'])->save();
                        ProductLogic::update_flash_stock($item['item'], $item['quantity'])?->save();
                    }
                }
                $store->increment('total_order');
            }
            if (!isset($request->is_buy_now) || (isset($request->is_buy_now) && $request->is_buy_now == 0)) {
                foreach ($carts as $cart) {
                    // $cart->delete();
                }
            }

            if ($user) {
                $customer = $user;
                $customer->zone_id = $order->zone_id;
                $customer->save();

                if ($request->payment_method == 'wallet') CustomerLogic::create_wallet_transaction($order->user_id, $order->order_amount, 'order_place', $order->id);

                if ($request->partial_payment) {
                    if ($user->wallet_balance <= 0) {
                        return response()->json([
                            'errors' => [
                                ['code' => 'order_amount', 'message' => translate('messages.insufficient_balance_for_partial_amount')]
                            ]
                        ], 203);
                    }
                    $p_amount = min($user->wallet_balance, $order->order_amount);
                    $unpaid_amount = $order->order_amount - $p_amount;
                    $order->partially_paid_amount = $p_amount;

                    $order->save();
                    CustomerLogic::create_wallet_transaction($order->user_id, $p_amount, 'partial_payment', $order->id);
                    OrderLogic::create_order_payment(order_id: $order->id, amount: $p_amount, payment_status: 'paid', payment_method: 'wallet');
                    OrderLogic::create_order_payment(order_id: $order->id, amount: $unpaid_amount, payment_status: 'unpaid', payment_method: $request->payment_method);
                }
            }

            DB::commit();


            $payments = $order->payments()->where('payment_method', 'cash_on_delivery')->exists();
            $order_mail_status = Helpers::get_mail_status('place_order_mail_status_user');
            $order_verification_mail_status = Helpers::get_mail_status('order_verification_mail_status_user');

            //PlaceOrderMail
            try {
                if (0 && !in_array($order->payment_method, ['digital_payment', 'partial_payment', 'offline_payment'])  || $payments) {
                    Helpers::send_order_notification($order);

                    if ($order->order_status == 'pending' && config('mail.status') && $order_mail_status == '1' && $user) {

                        Mail::to($user->email)->send(new PlaceOrder($order->id));
                    }
                    if ($order->order_status == 'pending' && config('order_delivery_verification') == 1 && $order_verification_mail_status == '1' && $user) {
                        Mail::to($user->email)->send(new OrderVerificationMail($order->otp, $user->f_name));
                    }
                    if ($order->is_guest == 1 && $order->order_status == 'pending' && config('mail.status') && $order_mail_status == '1' && isset($request->contact_person_email)) {
                        Mail::to($request->contact_person_email)->send(new PlaceOrder($order->id));
                    }
                    if ($order->is_guest == 1 && $order->order_status == 'pending' && config('order_delivery_verification') == 1 && $order_verification_mail_status == '1' && isset($request->contact_person_email)) {
                        Mail::to($request->contact_person_email)->send(new OrderVerificationMail($order->otp, $request->contact_person_name));
                    }
                }
            } catch (\Exception $ex) {
                // info($ex->getMessage());
            }

            // place order sms, email and in app notification to vendor  =================== 
            $title = "Received New Order";
            $msg = "Good news! You've got a new order. Let's get it ready!";
            $acceptnce_id = '';
            $to = $store->id;
            $url = route('vendor.order.list', ['pending']);
            $user_typ = 'vendor';

            _inAppNotification($title, $msg, $acceptnce_id, $to, $url, $user_typ);
            // _sendMailToVendor($title, $msg, $to, $url); 
            $smsTemplate = "Hello! Your order NO " . $order->id . " is received. Please review the details on My Chitti Vendor Dashboard and confirm accuracy.";
            _sendSMS($store->phone, $smsTemplate);
            _sendOrderSMSToAdmins($order, $user, $store);

            // SendOrderNotifications::dispatch( 
            //     $title, 
            //     $msg,
            //     $acceptnce_id, 
            //     $to,
            //     $url,
            //     $user_typ,
            //     $order->id,
            //     $store->phone
            // );


            // place order sms, email and in app notification to vendor ===================
            return response()->json([
                'message' => translate('messages.order_placed_successfully'),
                'order_id' => $order->id,
                'payment_method' => $request->payment_method,
                'total_ammount' => $order->order_amount,
                'status' => $order->order_status,
                'created_at' => $order->created_at,
                'url' => $request->payment_method == 'digital_payment'  ? "payment-mobile?customer_id=" . $user_id . "&order_id=" . $order->id . "&payment_platform=web&payment_method=razor_pay&callback=/success" : ''
            ], 200);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([$e], 403);
        }
        return response()->json([
            'errors' => [
                ['code' => 'order_time', 'message' => translate('messages.failed_to_place_order')]
            ]
        ]);
    }

    public function change_variation(Request $request)
    {
        $vrType = $request->type;
        $prId = $request->id;

        $item = DB::table('items')->where('id', $prId)->first();
        $variations = json_decode($item->variations);
        $selectedVr = [];

        foreach ($variations as $key => $value) {
            if ($value->type == $vrType) {
                $selectedVr = $value;
                $selectedVr->discounted_price =  $selectedVr->price;
                $vrDetails = ItemVariationDetail::find($selectedVr->variations_table_id);
                $selectedVr->variation_details = $vrDetails;
            }
        }
        return response()->json(['status' => true, 'data' => $selectedVr]);
    }
    public function order_success(Request $request, $order_id = null)
    {
        $order_id = $order_id;
        return view('front-views.order-success', compact('order_id'));
    }
    public function store_gallery(Request $request, $slug = null)
    {
        // If the store is already resolved via custom domain middleware, use that context
        $store = $request->attributes->get('store_domain_store');
        if ($store) {
            $store->load('galleries');
        } else {
            // Resolve from the route param explicitly (not $request->slug, which can be shadowed
            // by input) and bypass global scopes — the slug is unique, and on a custom domain
            // there's no zone/session context to scope by.
            $slug = $slug ?: $request->route('slug');
            $store = Store::withoutGlobalScopes()->with('galleries')->where('slug', $slug)->first();
        }
        if (!$store) {
            abort(404); 
        }
        return view('front-views.store_gallery', compact('store'));
    }
    public function trackBannerClick(Request $request)
    {
        $bannerId = $request->banner_id;
        $banner = DB::table('banners')->where('id', $bannerId)->first();
        if (!$banner) {
            return response()->json(['message' => 'Banner not found'], 404);
        }

        $ip = $request->ip();
        $isUnique = !DB::table('analytics_logs')
            ->where('screen_type', 'banner')
            ->where('ref_id', $bannerId)
            ->where('ip', $ip)
            ->whereDate('created_at', now()->toDateString())
            ->exists();

        DB::table('banners')->where('id', $bannerId)->increment('total_clicks');
        if ($isUnique) {
            DB::table('banners')->where('id', $bannerId)->increment('unique_clicks');
        }

        DB::table('analytics_logs')->insert([
            'screen_type' => 'banner',
            'sub_type' => 'web',
            'ref_id' => $bannerId,
            'user_id' => auth()->check() ? auth()->id() : null,
            'ip' => $ip,
            'created_at' => now(),
        ]);

        return response()->json(['message' => 'Banner click counted']);
    }

    public function trackAdClick(Request $request)
    {
        $adId = $request->ad_id;
        $ad = DB::table('notifications')->where('id', $adId)->whereNotNull('vendor_id')->first();
        if (!$ad) {
            return response()->json(['message' => 'Ad not found'], 404);
        }

        $ip = $request->ip();

        DB::table('notifications')->where('id', $adId)->increment('total_clicks');

        try {
            $isUnique = !DB::table('analytics_logs')
                ->where('screen_type', 'ad')
                ->where('ref_id', $adId)
                ->where('ip', $ip)
                ->whereDate('created_at', now()->toDateString())
                ->exists();

            if ($isUnique) {
                DB::table('notifications')->where('id', $adId)->increment('unique_clicks');
            }

            DB::table('analytics_logs')->insert([
                'screen_type' => 'ad',
                'sub_type'    => 'web',
                'ref_id'      => $adId,
                'user_id'     => auth()->check() ? auth()->id() : null,
                'ip'          => $ip,
                'created_at'  => now(),
            ]);
        } catch (\Exception $e) {
            // analytics_logs failure must not prevent the increment
        }

        return response()->json(['message' => 'Ad click counted']);
    }

    public function trackStoreContactClick(Request $request)
    {
        $storeId = $request->store_id;
        $action  = $request->action;

        // Platform analytics events (analytics_logs) — call reuses phone-call analytics,
        // copy is a web-only event, share = store share, whatsapp/enquiry come from the
        // store cards (product detail page, store page) and get their own Performance
        // Analytics stat.
        $screenType = match ($action) {
            'call'     => 'call',
            'copy'     => 'copy',
            'share'    => 'share',
            'whatsapp' => 'whatsapp',
            'enquiry'  => 'enquiry',
            default    => null,
        };

        // Inbound-lead actions (Phase 3 §3.3) — also recorded to lead_signals for the MC Vendor Hub
        // Lead Inbox. 'copy'/'share' are analytics-only; everything here is a real lead intent.
        // lead_signals.type is an ENUM, so 'enquiry' rides on the existing 'booking' member.
        $leadType  = $action === 'enquiry' ? 'booking' : $action;
        $leadTypes = ['call', 'whatsapp', 'booking', 'quote', 'direction', 'website'];
        $isLead = in_array($leadType, $leadTypes, true);

        if (!$screenType && !$isLead) {
            return response()->json(['message' => 'Invalid action'], 422);
        }

        $store = DB::table('stores')->where('id', $storeId)->first();
        if (!$store) {
            return response()->json(['message' => 'Store not found'], 404);
        }

        $ip = $request->ip();

        // 1) Platform analytics — identical to before (only for call/copy/share).
        if ($screenType) {
            // sub_type: for 'share' it holds the share target ('store'); otherwise the source platform ('web').
            $subType = $action === 'share' ? 'store' : 'web';
            try {
                DB::table('analytics_logs')->insert([
                    'screen_type' => $screenType,
                    'sub_type'    => $subType,
                    'ref_id'      => $storeId,
                    'user_id'     => auth()->check() ? auth()->id() : null,
                    'ip'          => $ip,
                    'created_at'  => now(),
                ]);
            } catch (\Exception $e) {
                // analytics failure must not break the click
            }
        }

        // 2) Lead Inbox signal — full funnel (call/whatsapp/booking/quote/direction/website).
        if ($isLead) {
            try {
                DB::table('lead_signals')->insert([
                    'store_id'     => $storeId,
                    'user_id'      => auth()->check() ? auth()->id() : null,
                    'type'         => $leadType,
                    'source'       => $request->input('source', 'web'),
                    'utm_source'   => $request->input('utm_source'),
                    'utm_medium'   => $request->input('utm_medium'),
                    'utm_campaign' => $request->input('utm_campaign'),
                    'meta'         => json_encode(['ip' => $ip, 'ua' => substr((string) $request->userAgent(), 0, 255)]),
                    'created_at'   => now(),
                    'updated_at'   => now(),
                ]);
            } catch (\Exception $e) {
                // lead capture failure must not break the click
            }
        }

        return response()->json(['message' => 'ok']);
    }

    private function adsBaseQuery()
    {
        $zone_ids = json_decode($this->zone_id, true);
        return \App\Models\Notification::whereNotNull('vendor_id')
            ->where('approval', 1)
            ->where('status', 1)
            ->whereNotNull('image')
            ->where(function ($q) {
                $q->whereNull('days')
                  ->orWhereNull('approved_at')
                  ->orWhereRaw('DATE_ADD(approved_at, INTERVAL days DAY) >= NOW()');
            })
            ->where(function ($q) use ($zone_ids) {
                $q->whereIn('zone_id', $zone_ids)
                    ->orWhereNull('zone_id')
                    ->orWhere('zone_id', 0);
            })
            ->latest();
    }
 
    public function allAds()
    {
        $ads = $this->adsBaseQuery()->paginate(18);
        return view('front-views.ads.index', compact('ads'));
    }

    public function loadAds(Request $request)
    {
        $ads = $this->adsBaseQuery()->paginate(12);
        $html = view('front-views.ads._ad_cards', compact('ads'))->render();
        return response()->json([
            'html'     => $html,
            'has_more' => $ads->hasMorePages(),
        ]);
    }

    public function adDetail($id)
    {
        $ad = \App\Models\Notification::whereNotNull('vendor_id')
            ->where('approval', 1)
            ->where('status', 1)
            ->findOrFail($id);

        try {
            $ip = request()->ip();
            $isUnique = !DB::table('analytics_logs')
                ->where('screen_type', 'ad')
                ->where('ref_id', $id)
                ->where('ip', $ip)
                ->whereDate('created_at', now()->toDateString())
                ->exists();

            DB::table('notifications')->where('id', $id)->increment('total_clicks');
            if ($isUnique) {
                DB::table('notifications')->where('id', $id)->increment('unique_clicks');
            }
            DB::table('analytics_logs')->insert([
                'screen_type' => 'ad',
                'sub_type'    => 'web',
                'ref_id'      => $id,
                'user_id'     => auth()->check() ? auth()->id() : null,
                'ip'          => $ip,
                'created_at'  => now(),
            ]);
        } catch (\Exception $e) {
            // analytics failure must not break the page
        }

        $store = $ad->vendor_id ? DB::table('stores')->where('id', $ad->vendor_id)->first() : null;
        return view('front-views.ads.detail', compact('ad', 'store'));
    }

    public function store_details(Request $request, $city, $slug)
    {
        $check_module = DB::table('stores')->where('slug', $slug)->first();
        if ($check_module) {
            $module = $check_module->module_id;
        } else {
            abort(404);
        }

        // One canonical city per store (falls back to the platform default for zone-less stores).
        $canonicalCity = 'tirupati';
        if ($check_module->zone_id) {
            $zone = DB::table('zones')->where('id', $check_module->zone_id)->value('name');
            if ($zone) {
                $canonicalCity = _zoneCitySlug($zone);
            }
        }
        // 301 any other city to the single canonical URL — kills duplicate / soft-404 pages.
        if ($city !== $canonicalCity) {
            return redirect()->to(url($canonicalCity . '/store/' . $slug), 301);
        }
        // True canonical for the store page (overrides the layout's self-referencing default).
        view()->share('canonical', url($canonicalCity . '/store/' . $slug));
        $invItemdata = [];
        $longitude = $this->longitude;
        $latitude = $this->latitude;
        $store = Store::with(['discount' => function ($q) {
            return $q->validate();
        }, 'campaigns', 'schedules', 'activeCoupons'])
            ->withCount(['items', 'campaigns'])
            ->when($module, function ($query) use ($module) {
                $query->module($module);
            })
            ->where('slug', $slug)
            ->first();


        if ($store) {
            // Thin-content guard: keep genuinely empty store shells (no items, no campaigns,
            // no specialised business type) out of the index so they aren't flagged soft-404.
            view()->share('metaRobots',
                ($store->items_count == 0 && $store->campaigns_count == 0 && empty($store->business_type)) ? 'noindex, follow' : null);
 
            // LocalBusiness JSON-LD (P0) — emitted in the layout head for every store template.
            view()->share('localBusinessStore', $store);

            // Increment store visit analytics
            $ip = $request->ip();
            $isUnique = !DB::table('analytics_logs')
                ->where('screen_type', 'store')
                ->where('ref_id', $store->id)
                ->where('ip', $ip)
                ->whereDate('created_at', now()->toDateString())
                ->exists();

            DB::table('stores')->where('id', $store->id)->increment('total_visits');
            if ($isUnique) {
                DB::table('stores')->where('id', $store->id)->increment('unique_visits');
            }

            DB::table('analytics_logs')->insert([
                'screen_type' => 'store',
                'sub_type' => 'web',
                'ref_id' => $store->id,
                'user_id' => auth()->check() ? auth()->id() : null,
                'ip' => $ip,
                'created_at' => now(),
            ]);

            if ($module == 5) {

                $keywordsData = DB::table('items')
                    ->where('items.is_approved', 1)
                    ->join('categories', 'items.category_id', '=', 'categories.id')
                    ->where('items.store_id', $store->id)
                    ->select('items.name as item_name', 'categories.name as category_name')
                    ->distinct()
                    ->get();

                $keywords = implode(',', $keywordsData->pluck('item_name')->merge($keywordsData->pluck('category_name'))->toArray());

                $category_ids = DB::table('items')
                    ->join('categories', 'items.category_id', '=', 'categories.id')
                    ->selectRaw('categories.position as positions, IF((categories.position = "0"), categories.id, categories.parent_id) as categories')
                    ->where('items.store_id', $store->id)
                    ->where('categories.status', 1)
                    ->groupBy('categories', 'positions')
                    ->get();

                $store = Helpers::store_data_formatting($store);
                $store['category_ids'] = array_map('intval', $category_ids->pluck('categories')->toArray());
                $store['category_details'] = Category::whereIn('id', $store['category_ids'])->get();
                $store['price_range']  = Item::withoutGlobalScopes()->where('store_id', $store->id)
                    ->select(DB::raw('MIN(price) AS min_price, MAX(price) AS max_price'))
                    ->get(['min_price', 'max_price']);

                $productdata = DB::table('items')
                    ->join('categories', 'items.category_id', 'categories.id')
                    ->where('items.store_id', $store->id)
                    ->where('items.status', 1)
                    ->where('items.is_approved', 1)
                    ->select('categories.id', 'categories.name', 'categories.slug as cat_slug')
                    ->distinct()
                    ->get()
                    ->toArray();

                foreach ($productdata as $key => $cat) {
                    $cat->items = DB::table('items')
                        ->where('store_id', $store->id)
                        ->where('category_id', $cat->id)
                        ->where('status', 1)
                        ->where('is_approved', 1)
                        ->get();
                }
            } else {
                $keywordsData = DB::table('items')
                    ->where('items.is_approved', 1)
                    ->join('categories', 'items.category_id', '=', 'categories.id')
                    ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                    ->select('items.name as item_name', 'categories.name as category_name')
                    ->distinct()
                    ->get();

                $keywords = implode(',', $keywordsData->pluck('item_name')->merge($keywordsData->pluck('category_name'))->toArray());
                // echo '
';
                // SERVICES
                $productdata1 = DB::table('items')
                    ->join('categories', 'items.category_id', 'categories.id')
                    ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                    ->whereNull('items.inventory_item_id')
                    ->where('categories.status', 1)
                    ->select('categories.id', 'categories.name', 'categories.slug as cat_slug')
                    ->distinct()
                    ->get();


                foreach ($productdata1 as $cat) {
                    $cat->items = DB::table('items')
                        ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                        ->whereNull('items.inventory_item_id')
                        ->where('category_id', $cat->id)
                        ->where('status', 1)
                        ->get();
                }

                //INVENTORY ITEMS
                $invItemdata = DB::table('items')
                    ->join('categories', 'items.category_id', 'categories.id')
                    ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                    ->whereNotNull('items.inventory_item_id')
                    ->select('categories.id', 'categories.name', 'categories.slug as cat_slug')
                    ->distinct()
                    ->get();

                foreach ($invItemdata as $cat) {
                    $cat->items = DB::table('items')
                        ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                        ->whereNotNull('items.inventory_item_id')
                        ->where        }

        if ($request->partial_payment && !Helpers::get_business_settings('partial_payment_status')) {
            return response()->json([
                'errors' => [
                    ['code' => 'order_method', 'message' => translate('messages.partial_payment_is_not_active')]
                ]
            ]);
        }

        if ($request->payment_method == 'offline_payment' &&  Helpers::get_mail_status('offline_payment_status') == 0) {
            return response()->json([
                'errors' => [
                    ['code' => 'offline_payment_status', 'message' => translate('messages.offline_payment_for_the_order_not_available_at_this_time')]
                ]
            ]);
        }

        $digital_payment = Helpers::get_business_settings('digital_payment');
        if ($digital_payment['status'] == 0 && $request->payment_method == 'digital_payment') {
            return response()->json([
                'errors' => [
                    ['code' => 'digital_payment', 'message' => translate('messages.digital_payment_for_the_order_not_available_at_this_time')]
                ]
            ]);
        }

        $data =  DMVehicle::active()->where(function ($query) use ($distance_data) {
            $query->where('starting_coverage_area', '<=', $distance_data)->where('maximum_coverage_area', '>=', $distance_data)
                ->orWhere(function ($query) use ($distance_data) {
                    $query->where('starting_coverage_area', '>=', $distance_data);
                });
        })
            ->orderBy('starting_coverage_area')->first();

        $extra_charges = (float) (isset($data) ? $data->extra_charges  : 0);
        $vehicle_id = (isset($data) ? $data->id  : null);

        $zone = null;
        if ($request->latitude[$key] && $request->longitude[$key]) {
            $point = new Point($request->latitude[$key], $request->longitude[$key]);
            if ($request->order_type == 'parcel') {
                // if(isset($request->sender_zone_id) ){
                // $zone_id = $request->sender_zone_id;
                $zone_ids = $request->header('zoneId') ? json_decode($request->header('zoneId'), true) : [];
                $zone = Zone::whereIn('id', $zone_ids)->whereContains('coordinates', new Point($request->latitude[$key], $request->longitude[$key], POINT_SRID))->wherehas('modules', function ($q) {
                    $q->where('module_type', 'parcel');
                })->first();
            } else {
                // ->selectRaw('*, IF(((select count(*) from `store_schedule` where `stores`.`id` = `store_schedule`.`store_id` and `store_schedule`.`day` = ' . $schedule_at->format('w') . ' and `store_schedule`.`opening_time` < "' . $schedule_at->format('H:i:s') . '" and `store_schedule`.`closing_time` >"' . $schedule_at->format('H:i:s') . '") > 0), true, false) as open')
                $store = Store::with('discount')->where('id', $request->store_id)->first();

                if (!$store) {
                    return response()->json([
                        'errors' => [
                            ['code' => 'order_time', 'message' => translate('messages.store_not_found')]
                        ]
                    ]);
                }
                $zone_id =  [$store->zone_id];
                $zone = Zone::where('id', $zone_id)->whereContains('coordinates', new Point($request->latitude[$key], $request->longitude[$key], POINT_SRID))->first();
            }
        }
        if (!$zone) {
            $errors = [];
            array_push($errors, ['code' => 'coordinates', 'message' => translate('messages.out_of_coverage')]);
            return response()->json([
                'errors' => $errors
            ]);
        }
        if ($zone && $zone->increased_delivery_fee_status == 1) {
            $increased = $zone->increased_delivery_fee ?? 0;
        }

        if ($request->order_type !== 'parcel') {


            if (!$store->active) {
                return response()->json([
                    'errors' => [
                        ['code' => 'order_time', 'message' => translate('messages.store_is_closed_at_order_time')]
                    ]
                ]);
            }

            if ($request->coupon_code) {
                $coupon = Coupon::active()->where(['code' => $request->coupon_code])->first();
                if (isset($coupon)) {


                    $staus = CouponLogic::is_valide($coupon, $user->id, $request->store_id);


                    if ($staus == 407) {
                        return response()->json([
                            'errors' => [
                                ['code' => 'coupon', 'message' => translate('messages.coupon_expire')]
                            ]
                        ]);
                    } else if ($staus == 408) {
                        return response()->json([
                            'errors' => [
                                ['code' => 'coupon', 'message' => translate('messages.You_are_not_eligible_for_this_coupon')]
                            ]
                        ]);
                    } else if ($staus == 406) {
                        return response()->json([
                            'errors' => [
                                ['code' => 'coupon', 'message' => translate('messages.coupon_usage_limit_over')]
                            ]
                        ]);
                    } else if ($staus == 404) {
                        return response()->json([
                            'errors' => [
                                ['code' => 'coupon', 'message' => translate('messages.not_found')]
                            ]
                        ]);
                    }

                    $coupon_created_by = $coupon->created_by;
                    if ($coupon->coupon_type == 'free_delivery') {
                        $delivery_charge = 0;
                        $free_delivery_by =  $coupon_created_by;
                        $coupon_created_by = null;
                    }
                } else {
                    return response()->json([
                        'errors' => [
                            ['code' => 'coupon', 'message' => translate('messages.not_found')]
                        ]
                    ], 404);
                }
            }

            $module_wise_delivery_charge = $store->zone->modules()->where('modules.id', 5)->first();
            if ($module_wise_delivery_charge) {
                $per_km_shipping_charge = $module_wise_delivery_charge->pivot->per_km_shipping_charge;
                $minimum_shipping_charge = $module_wise_delivery_charge->pivot->minimum_shipping_charge;
                $maximum_shipping_charge = $module_wise_delivery_charge->pivot->maximum_shipping_charge;
            } else {
                $per_km_shipping_charge = (float)BusinessSetting::where(['key' => 'per_km_shipping_charge'])->first()->value;
                $minimum_shipping_charge = (float)BusinessSetting::where(['key' => 'minimum_shipping_charge'])->first()->value;
            }

            if ($request->order_type != 'take_away' && !$store->free_delivery && !isset($delivery_charge) &&  $store->self_delivery_system == 1) {
                $per_km_shipping_charge = $store->per_km_shipping_charge;
                $minimum_shipping_charge = $store->minimum_shipping_charge;
                $maximum_shipping_charge = $store->maximum_shipping_charge;
                $extra_charges = 0;
                $vehicle_id = null;
                $increased = 0;
            }

            if ($store->free_delivery || $free_delivery_by == 'vendor') {
                $per_km_shipping_charge = $store->per_km_shipping_charge;
                $minimum_shipping_charge = $store->minimum_shipping_charge;
                $maximum_shipping_charge = $store->maximum_shipping_charge;
                $extra_charges = 0;
                $increased = 0;
            }

            $original_delivery_charge = (($request->distance * $per_km_shipping_charge) > $minimum_shipping_charge) ? $request->distance * $per_km_shipping_charge  : $minimum_shipping_charge;

            if ($request->order_type == 'take_away') {
                $per_km_shipping_charge = 0;
                $minimum_shipping_charge = 0;
                $maximum_shipping_charge = 0;
                $extra_charges = 0;
                $distance_data = 0;
                $vehicle_id = null;
                $original_delivery_charge = 0;
                $increased = 0;
            }

            if ($maximum_shipping_charge  >= $minimum_shipping_charge  && $original_delivery_charge >  $maximum_shipping_charge) {
                $original_delivery_charge = $maximum_shipping_charge;
            } else {
                $original_delivery_charge = $original_delivery_charge;
            }

            if (!isset($delivery_charge)) {
                $delivery_charge = ($request->distance * $per_km_shipping_charge > $minimum_shipping_charge) ? $request->distance * $per_km_shipping_charge : $minimum_shipping_charge;
                if ($maximum_shipping_charge  >= $minimum_shipping_charge  && $delivery_charge >  $maximum_shipping_charge) {
                    $delivery_charge = $maximum_shipping_charge;
                } else {
                    $delivery_charge = $delivery_charge;
                }
            }
            $original_delivery_charge = $original_delivery_charge + $extra_charges;
            $delivery_charge = $delivery_charge + $extra_charges;
        } else {
            $parcel_category = ParcelCategory::findOrFail($request->parcel_category_id);
            if (isset($parcel_category) && isset($parcel_category->parcel_minimum_shipping_charge)) {
                $per_km_shipping_charge = $parcel_category->parcel_per_km_shipping_charge;
                $minimum_shipping_charge = $parcel_category->parcel_minimum_shipping_charge;
            } else {
                $per_km_shipping_charge = (float)BusinessSetting::where(['key' => 'parcel_per_km_shipping_charge'])->first()->value;
                $minimum_shipping_charge = (float)BusinessSetting::where(['key' => 'parcel_minimum_shipping_charge'])->first()->value;
            }

            $original_delivery_charge = (($request->distance * $per_km_shipping_charge) > $minimum_shipping_charge) ? ($request->distance * $per_km_shipping_charge) + $extra_charges : ($minimum_shipping_charge + $extra_charges);
        }

        if ($increased > 0) {
            if ($delivery_charge > 0) {
                $increased_fee = ($delivery_charge * $increased) / 100;
                $delivery_charge = $delivery_charge + $increased_fee;
            }
            if ($original_delivery_charge > 0) {
                $increased_fee = ($original_delivery_charge * $increased) / 100;
                $original_delivery_charge = $original_delivery_charge + $increased_fee;
            }
        }
        $address = [
            'contact_person_name' => $request->contact_person_name[$key] ? $request->contact_person_name[$key] : ($user ? $user->f_name . ' ' . $user->f_name : ''),
            'contact_person_number' => $request->contact_person_number[$key] ? ($user ? $request->contact_person_number[$key] : str_replace('+', '', $request->contact_person_number[$key])) : ($user ? $user->phone : ''),
            'contact_person_email' => $user ? $user->email : '',
            'address_type' => $request->address_type ? $request->address_type : 'Delivery',
            'address' => $request?->address[$key] ?? '',
            'floor' => $request?->floor[$key] ?? '',
            'road' => $request?->road[$key] ?? '',
            'house' => $request?->house[$key] ?? '',
            'longitude' => (string)$request->longitude[$key],
            'latitude' => (string)$request->latitude[$key],
        ];
        $total_addon_price = 0;
        $product_price = 0;
        $store_discount_amount = 0;
        $flash_sale_vendor_discount_amount = 0;
        $flash_sale_admin_discount_amount = 0;
        $store_discount_amount = 0;
        $product_data = [];

        $order_details = [];
        $order = new Order();
        $lastOrder = Order::orderBy('id', 'desc')->first();

        if ($lastOrder) {
            $order->id = $lastOrder->id + 1;
        } else {
            $order->id = 10001;
        }
        $order->invoice_id = _generateOrderInvoiceId($request->store_id);

        $order_status = 'pending';
        if (($request->partial_payment && $request->payment_method != 'offline_payment') || $request->payment_method == 'wallet') {
            $order_status = 'confirmed';
        }

        $order->user_id = $user ? $user->id : 0;
        $order->order_amount = $request->order_amount;
        $order->payment_status = ($request->partial_payment ? 'partially_paid' : ($request->payment_method == 'wallet' ? 'paid' : 'unpaid'));
        $order->order_status = $order_status;
        $order->coupon_code = $request->coupon_code;
        $order->payment_method = $request->partial_payment ? 'partial_payment' : $request->payment_method;
        $order->transaction_reference = null;
        $order->order_note = $request->order_note;
        $order->unavailable_item_note = $request->unavailable_item_note;
        $order->delivery_instruction = $request->delivery_instruction;
        $order->order_type = $request->order_type;
        $order->store_id = $request->store_id;
        if ($store->delivery_charges_on && $store->delivery_charges_on <= $request->order_amount) {
            $order->delivery_charge = 0;
        } else {
            $order->delivery_charge = round($delivery_charge, config('round_up_to_digit')) ?? 0;
        }
        $order->original_delivery_charge = round($original_delivery_charge, config('round_up_to_digit'));
        $order->delivery_address = json_encode($address);
        $order->schedule_at = $schedule_at;
        $order->scheduled = $request->schedule_at ? 1 : 0;
        $order->cutlery = $request->cutlery ? 1 : 0;
        $order->is_guest = $user ? 0 : 1;
        $order->otp = rand(1000, 9999);
        $order->zone_id = isset($zone) ? $zone->id : end(json_decode($this->zone_id, true));
        $order->module_id = 5;
        $order->parcel_category_id = $request->parcel_category_id;
        $order->receiver_details = json_decode($request->receiver_details);

        if ($order_status == 'confirmed') {
            $order->confirmed = now();
        }
        $order->dm_vehicle_id = $vehicle_id;
        $order->pending = now();
        $order->order_attachment = $request->has('order_attachment') ? Helpers::upload('order/', 'png', $request->file('order_attachment')) : null;
        $order->distance = $distance_data;
        $order->created_at = now();
        $order->updated_at = now();
        $order->charge_payer = null;

        //Added DM TIPS
        $dm_tips_manage_status = BusinessSetting::where('key', 'dm_tips_status')->first()->value;
        if ($dm_tips_manage_status == 1) {
            $order->dm_tips = $request->dm_tips ?? 0;
        } else {
            $order->dm_tips = 0;
        }
        //Added service charge
        $additional_charge_status = BusinessSetting::where('key', 'additional_charge_status')->first()->value;
        $additional_charge = BusinessSetting::where('key', 'additional_charge')->first()->value;
        if ($additional_charge_status == 1) {
            $order->additional_charge = $additional_charge ?? 0;
        } else {
            $order->additional_charge = 0;
        }

        $carts = Cart::where('user_id', $order->user_id)->where('is_guest', 0)->where('module_id', 5)
            ->when(isset($request->is_buy_now) && $request->is_buy_now == 1 && $request->cart_id, function ($query) use ($request) {
                return $query->where('id', $request->cart_id);
            })
            ->get()->map(function ($data) {
                $data->add_on_ids = json_decode($data->add_on_ids, true);
                $data->add_on_qtys = json_decode($data->add_on_qtys, true);
                $data->variation = json_decode($data->variation, true);
                return $data;
            });

        if (isset($request->is_buy_now) && $request->is_buy_now == 1) {
            $carts = json_decode($request->cart, true);
        }


        if ($request->order_type !== 'parcel') {
            foreach ($carts as $c) {
                if ($c['item_type'] === 'App\Models\ItemCampaign' || $c['item_type'] === 'AppModelsItemCampaign') {
                    $product = ItemCampaign::with('module')->active()->find($c['item_id']);
                    if ($product) {
                        if ($product->store_id != $order->store_id) {
                            return response()->json([
                                'errors' => [
                                    ['code' => 'different_stores', 'message' => translate('messages.Please_select_items_from_the_same_store')]
                                ]
                            ], 403);
                        }

                        if ($product->module->module_type == 'food' && $product->food_variations) {
                            $product_variations = json_decode($product->food_variations, true);
                            $variations = [];
                            if (count($product_variations)) {
                                $variation_data = Helpers::get_varient($product_variations, $c['variation']);
                                $price = $product['price'] + $variation_data['price'];
                                $variations = $variation_data['variations'];
                            } else {
                                $price = $product['price'];
                            }
                            // $product->tax = $store->tax;
                            $product = Helpers::product_data_formatting($product, false, false, app()->getLocale());
                            $addon_data = Helpers::calculate_addon_price(\App\Models\AddOn::whereIn('id', $c['add_on_ids'])->get(), $c['add_on_qtys']);
                            $or_d = [
                                'item_id' => null,
                                'item_campaign_id' => $c['item_id'],
                                'item_details' => json_encode($product),
                                'quantity' => $c['quantity'],
                                'price' => round($price, config('round_up_to_digit')),
                                'tax_amount' => Helpers::tax_calculate($product, $price),
                                'discount_on_item' => Helpers::product_discount_calculate($product, $price, $store)['discount_amount'],
                                'discount_type' => 'discount_on_product',
                                'variant' => json_encode($c['variant']),
                                'variation' => json_encode($variations),
                                'add_ons' => json_encode($addon_data['addons']),
                                'total_add_on_price' => $addon_data['total_add_on_price'],
                                'created_at' => now(),
                                'updated_at' => now()
                            ];
                            $order_details[] = $or_d;
                            $total_addon_price += $or_d['total_add_on_price'];
                            $product_price += $price * $or_d['quantity'];
                            $store_discount_amount += $or_d['discount_on_item'] * $or_d['quantity'];
                        } else {
                            if (count(json_decode($product['variations'], true)) > 0) {
                                $variant_data = Helpers::variation_price($product, json_encode($c['variation']));
                                $price = $variant_data['price'];
                                $stock = $variant_data['stock'];
                                $mychitti_fee = $variant_data['price'] - $variant_data['askingprice'];
                            } else {
                                $price = $product['price'];
                                $stock = $product->stock;
                                $mychitti_fee = $product->mychitty_fee;
                            }
                            if (config('module.' . $product->module->module_type)['stock']) {
                                if ($c['quantity'] > $stock) {
                                    return response()->json([
                                        'errors' => [
                                            ['code' => 'campaign', 'message' => translate('messages.product_out_of_stock', ['item' => $product->title])]
                                        ]
                                    ]);
                                }

                                $product_data[] = [
                                    'item' => clone $product,
                                    'quantity' => $c['quantity'],
                                    'variant' => count($c['variation']) > 0 ? $c['variation'][0]['type'] : null
                                ];
                            }

                            // $product->tax = $store->tax;
                            $product = Helpers::product_data_formatting($product, false, false, app()->getLocale());
                            $addon_data = Helpers::calculate_addon_price(\App\Models\AddOn::whereIn('id', $c['add_on_ids'])->get(), $c['add_on_qtys']);
                            $or_d = [
                                'item_id' => null,
                                'item_campaign_id' => $c['item_id'],
                                'item_details' => json_encode($product),
                                'quantity' => $c['quantity'],
                                'price' => $price,
                                'tax_amount' => Helpers::tax_calculate($product, $price),
                                'discount_on_item' => Helpers::product_discount_calculate($product, $price, $store)['discount_amount'],
                                'discount_type' => 'discount_on_product',
                                'variant' => json_encode($c['variant']),
                                'variation' => json_encode($c['variation']),
                                'add_ons' => json_encode($addon_data['addons']),
                                'total_add_on_price' => $addon_data['total_add_on_price'],
                                'platform_fee' => $mychitti_fee ??  0,
                                'created_at' => now(),
                                'updated_at' => now()
                            ];
                            $order_details[] = $or_d;
                            $total_addon_price += $or_d['total_add_on_price'];
                            $product_price += $price * $or_d['quantity'];
                            $store_discount_amount += $or_d['discount_on_item'] * $or_d['quantity'];
                        }
                    } else {
                        return response()->json([
                            'errors' => [
                                ['code' => 'campaign', 'message' => translate('messages.product_unavailable_warning')]
                            ]
                        ]);
                    }
                } else {
                    $product = Item::hydrate(
                        DB::table('items')->where('id',  $c['item_id'])->get()->toArray()
                    )->first();

                    if ($product) {

                        if ($product->store_id != $order->store_id) {
                            return response()->json([
                                'errors' => [
                                    ['code' => 'different_stores', 'message' => translate('messages.Please_select_items_from_the_same_store')]
                                ]
                            ]);
                        }


                        if ($product->maximum_cart_quantity && ($c['quantity'] > $product->maximum_cart_quantity)) {
                            return response()->json([
                                'errors' => [
                                    ['code' => 'quantity', 'message' => translate('messages.maximum_cart_quantity_limit_over')]
                                ]
                            ]);
                        }
                        if ($product->module->module_type == 'food' && $product->food_variations) {

                            $product_variations = json_decode($product->food_variations, true);
                            $variations = [];
                            if (count($product_variations)) {
                                $variation_data = Helpers::get_varient($product_variations, $c['variation']);
                                $mrpprice = $variation_data['mrpprice'];
                                $price = $variation_data['mrpprice'];
                                $variations =  $variation_data['variations'];
                                $mychitti_fee = $variation_data['price'] - $variation_data['askingprice'];
                            } else {
                                $mrpprice = $product['mrp_price'] ?? $product['price'];
                                $price = $product['price'];
                                $mychitti_fee = $product->mychitty_fee;
                            }
                            // $product->tax = $store->tax;
                            $product = Helpers::product_data_formatting($product, false, false, app()->getLocale());
                            $addon_data = Helpers::calculate_addon_price(\App\Models\AddOn::whereIn('id', $c['add_on_ids'])->get(), $c['add_on_qtys']);
                            $product_discount = Helpers::product_discount_calculate($product, $mrpprice, $store);

                            $tax =  _taxCalcluation($price, $product->tax)['gst_amount'];
                            $taxable = _taxCalcluation($price, $product->tax)['price_excluding_gst'];


                            $or_d = [
                                'item_id' => $c['item_id'],
                                'item_campaign_id' => null,
                                'item_details' => json_encode($product),
                                'quantity' => $c['quantity'],
                                'price' => $price,
                                'tax_amount' =>  $tax,
                                'taxable_amount' => $taxable,
                                'discount_on_item' => $product_discount['discount_amount'],
                                'discount_type' => $product_discount['discount_type'],
                                'variant' => json_encode($c['variant']),
                                'variation' => json_encode($variations),
                                'platform_fee' => $mychitti_fee ?? 0,
                                'add_ons' => json_encode($addon_data['addons']),
                                'total_add_on_price' => round($addon_data['total_add_on_price'], config('round_up_to_digit')),
                                'created_at' => now(),
                                'updated_at' => now()
                            ];
                            $total_addon_price += $or_d['total_add_on_price'];

                            $product_price += $price * $or_d['quantity'];
                            $store_discount_amount += $or_d['discount_type'] != 'flash_sale' ? $or_d['discount_on_item'] * $or_d['quantity'] : 0;
                            $flash_sale_admin_discount_amount += $or_d['discount_type'] == 'flash_sale' ? $product_discount['admin_discount_amount'] * $or_d['quantity'] : 0;
                            $flash_sale_vendor_discount_amount += $or_d['discount_type'] == 'flash_sale' ? $product_discount['vendor_discount_amount'] * $or_d['quantity'] : 0;
                            $order_details[] = $or_d;
                        } else {

                            if (count(json_decode($product['variations'], true)) > 0 && count($c['variation']) > 0) {
                                $variant_data = Helpers::variation_price($product, json_encode($c['variation']));
                                $price = $variant_data['mrpprice'];
                                $stock = $variant_data['stock'];
                                $is_vr = true;
                                $mychitti_fee = $variant_data['price'] - $variant_data['askingprice'];
                            } else {
                                $price = $product['price'];
                                $stock = $product->stock;
                                $is_vr = false;
                                $mychitti_fee = $product->mychitty_fee;
                            }

                            if (($stock - $c['quantity']) < 6) {
                                _stock_alert_sms($store->phone, $product['name']);
                                $title = 'Low Stock Alert for ' . $product['name'];
                                $msg = "Dear Vendor, Stock for " . $product['name'] . " is low. Please update accordingly.";
                                $to = $store->id;
                                $url = route('vendor.item.stock-limit-list');
                                $user_typ = 'vendor';
                                _inAppNotification($title, $msg, $acceptnce_id = '', $to, $url, $user_typ);
                            }


                            if (config('module.' . $product->module->module_type)['stock']) {
                                if ($c['quantity'] > $stock) {
                                    return response()->json([
                                        'errors' => [
                                            ['code' => 'campaign', 'message' => translate('messages.product_out_of_stock', ['item' => $product->name])]
                                        ]
                                    ]);
                                }

                                $product_data[] = [
                                    'item' => clone $product,
                                    'quantity' => $c['quantity'],
                                    'variant' => count($c['variation']) > 0 ? $c['variation'][0]['type'] : null
                                ];
                            }

                            // $product->tax = $store->tax;
                            $product = Helpers::product_data_formatting($product, false, false, app()->getLocale());
                            $addon_data = Helpers::calculate_addon_price(\App\Models\AddOn::whereIn('id', $c['add_on_ids'])->get(), $c['add_on_qtys']);

                            if (isset($c['variation']) && $c['variation']) {
                                $mrpprice = $c['variation'][0]['mrpprice'] ?? $c['variation'][0]['price'];
                                $price = $c['variation'][0]['price'];
                                $product_discount = Helpers::product_discount_calculate_vr($c['variation']);
                                $mychitti_fee = isset($c['variation'][0]['askingprice']) ? $price - $c['variation'][0]['askingprice'] : 0;
                            } else {
                                $mrpprice = $product->mrp_price;
                                $price = $product->price;
                                $mychitti_fee = $product->mychitty_fee;
                                $product_discount = Helpers::product_discount_calculate($product, $mrpprice, $store);
                            }
                            $tax_amount =  _taxCalcluation($price, $product->tax)['gst_amount'];
                            $taxable = _taxCalcluation($price, $product->tax)['price_excluding_gst'];

                            $or_d = [
                                'item_id' => $c['item_id'],
                                'item_campaign_id' => null,
                                'item_details' => json_encode($product),
                                'quantity' => $c['quantity'],
                                'price' => $price,
                                'taxable_amount' => $taxable,
                                'tax_amount' => $tax_amount,
                                'discount_on_item' => $product_discount['discount_amount'],
                                'discount_type' => $product_discount['discount_type'],
                                'variant' => json_encode($c['variant']),
                                'variation' => json_encode($c['variation']),
                                'platform_fee' => $mychitti_fee ?? 0,
                                'add_ons' => json_encode($addon_data['addons']),
                                'total_add_on_price' => $addon_data['total_add_on_price'],
                                'created_at' => now(),
                                'updated_at' => now()
                            ];

                            // prx($product_discount['discount_amount']);
                            $total_addon_price += $or_d['total_add_on_price'];
                            $total_order_tax += ($tax_amount * $or_d['quantity']);
                            if ($is_vr) {
                                $product_price += ($price * $or_d['quantity']);
                            } else {
                                $product_price += $price * $or_d['quantity'];
                            }

                            $store_discount_amount += $or_d['discount_type'] != 'flash_sale' ? $or_d['discount_on_item'] * $or_d['quantity'] : 0;
                            $flash_sale_admin_discount_amount += $or_d['discount_type'] == 'flash_sale' ? $product_discount['admin_discount_amount'] * $or_d['quantity'] : 0;
                            $flash_sale_vendor_discount_amount += $or_d['discount_type'] == 'flash_sale' ? $product_discount['vendor_discount_amount'] * $or_d['quantity'] : 0;
                            $order_details[] = $or_d;
                        }
                    } else {
                        return response()->json([
                            'errors' => [
                                ['code' => 'item', 'message' => translate('messages.product_unavailable_warning')]
                            ]
                        ]);
                    }
                }
            }
            $order->discount_on_product_by = 'vendor';
            $store_discount = Helpers::get_store_discount($store);
            if (isset($store_discount)) {
                $order->discount_on_product_by = 'admin';
                if ($product_price + $total_addon_price < $store_discount['min_purchase']) {
                    $store_discount_amount = 0;
                }
                if ($store_discount['max_discount'] != 0 && $store_discount_amount > $store_discount['max_discount']) {
                    $store_discount_amount = $store_discount['max_discount'];
                }
            }
            $coupon_discount_amount = $coupon ? CouponLogic::get_discount($coupon, $product_price + $total_addon_price - $store_discount_amount - $flash_sale_admin_discount_amount - $flash_sale_vendor_discount_amount) : 0;
            $total_price = $product_price + $total_addon_price - $total_addon_price - $flash_sale_admin_discount_amount - $flash_sale_vendor_discount_amount  - $coupon_discount_amount;
            $tax = ($store->tax > 0) ? $store->tax : 0;
            $order->tax_status = 'included';

            $tax_included = BusinessSetting::where(['key' => 'tax_included'])->first() ?  BusinessSetting::where(['key' => 'tax_included'])->first()->value : 0;
            if ($tax_included ==  1) {
                $order->tax_status = 'included';
            }

            $total_tax_amount = Helpers::product_tax($total_price, $tax, $order->tax_status == 'included');
            $tax_a = $order->tax_status == 'included' ? 0 : $total_tax_amount;


            if ($store->minimum_order > $product_price + $total_addon_price) {
                return response()->json([
                    'errors' => [
                        ['code' => 'order_time', 'message' => translate('messages.you_need_to_order_at_least') . $store->minimum_order . ' ' . Helpers::currency_code()]
                    ]
                ]);
            }

            $free_delivery_over = BusinessSetting::where('key', 'free_delivery_over')->first()->value;
            if (isset($free_delivery_over)) {
                if ($free_delivery_over <= $product_price + $total_addon_price - $coupon_discount_amount - $store_discount_amount - $flash_sale_admin_discount_amount - $flash_sale_vendor_discount_amount) {
                    $order->delivery_charge = 0;
                    $free_delivery_by = 'admin';
                }
            }

            if ($store->free_delivery) {
                $order->delivery_charge = 0;
                $free_delivery_by = 'vendor';
            }

            if ($coupon) {
                if ($coupon->coupon_type == 'free_delivery') {
                    if ($coupon->min_purchase <= $product_price + $total_addon_price - $store_discount_amount - $flash_sale_admin_discount_amount - $flash_sale_vendor_discount_amount) {
                        $order->delivery_charge = 0;
                        $free_delivery_by = $coupon->created_by;
                    }
                }
                $coupon->increment('total_uses');
            }
            $order->coupon_created_by = $coupon_created_by;
            $order->coupon_discount_amount = round($coupon_discount_amount, config('round_up_to_digit'));
            $order->coupon_discount_title = $coupon ? $coupon->title : '';

            $order->store_discount_amount = round($store_discount_amount, config('round_up_to_digit'));
            $order->tax_percentage = $tax;
            $order->total_tax_amount = $total_order_tax ?? round($total_tax_amount, config('round_up_to_digit'));
            $order->rounded_off = ($total_price + $tax_a + $order->delivery_charge) - floor($total_price + $tax_a + $order->delivery_charge);
            $order->order_amount = round($total_price + $tax_a + $order->delivery_charge);

            $order->free_delivery_by = $free_delivery_by;
        } else {

            $point = new Point(json_decode($request->receiver_details, true)['latitude'], json_decode($request->receiver_details, true)['longitude']);
            $zone_id =  json_decode($request->receiver_details, true)['zone_id'];
            $zone = Zone::where('id', $zone_id)->whereContains('coordinates', new Point(json_decode($request->receiver_details, true)['latitude'], json_decode($request->receiver_details, true)['longitude'], POINT_SRID))->first();
            if (!$zone) {
                $errors = [];
                array_push($errors, ['code' => 'receiver_details', 'message' => translate('messages.out_of_coverage')]);
                return response()->json([
                    'errors' => $errors
                ]);
            }
            $order->delivery_charge = round($original_delivery_charge, config('round_up_to_digit')) ?? 0;
            $order->original_delivery_charge = round($original_delivery_charge, config('round_up_to_digit'));


            $order->order_amount = round($order->delivery_charge);
        }
        $order->flash_admin_discount_amount = round($flash_sale_admin_discount_amount, config('round_up_to_digit'));
        $order->flash_store_discount_amount = round($flash_sale_vendor_discount_amount, config('round_up_to_digit'));
        //DM TIPs

        $order->order_amount = $order->order_amount + $order->dm_tips + $order->additional_charge;

        $order->rounded_off = ($order->order_amount) - floor($order->order_amount);

        if ($request->payment_method == 'wallet' && $user->wallet_balance < $order->order_amount) {
            return response()->json([
                'errors' => [
                    ['code' => 'order_amount', 'message' => translate('messages.insufficient_balance')]
                ]
            ]);
        }
        if ($request->partial_payment && $user->wallet_balance > $order->order_amount) {
            return response()->json([
                'errors' => [
                    ['code' => 'partial_payment', 'message' => translate('messages.order_amount_must_be_greater_than_wallet_amount')]
                ]
            ]);
        }
        if (isset($module_wise_delivery_charge) && $request->payment_method == 'cash_on_delivery' && $module_wise_delivery_charge->pivot->maximum_cod_order_amount && $order->order_amount > $module_wise_delivery_charge->pivot->maximum_cod_order_amount) {
            return response()->json([
                'errors' => [
                    ['code' => 'order_amount', 'message' => translate('messages.amount_crossed_maximum_cod_order_amount')]
                ]
            ]);
        }

        try {
            DB::beginTransaction();

            $order->save();
            if ($request->order_type !== 'parcel') {
                foreach ($order_details as $key => $item) {
                    $order_details[$key]['order_id'] = $order->id;

                    if ($store_discount_amount <= 0) {
                        $order_details[$key]['discount_on_item'] = 0;
                    }
                }
                OrderDetail::insert($order_details);
                if (count($product_data) > 0) {
                    foreach ($product_data as $item) {
                        ProductLogic::update_stock($item['item'], $item['quantity'], $item['variant'])->save();
                        ProductLogic::update_flash_stock($item['item'], $item['quantity'])?->save();
                    }
                }
                $store->increment('total_order');
            }
            if (!isset($request->is_buy_now) || (isset($request->is_buy_now) && $request->is_buy_now == 0)) {
                foreach ($carts as $cart) {
                    // $cart->delete();
                }
            }

            if ($user) {
                $customer = $user;
                $customer->zone_id = $order->zone_id;
                $customer->save();

                if ($request->payment_method == 'wallet') CustomerLogic::create_wallet_transaction($order->user_id, $order->order_amount, 'order_place', $order->id);

                if ($request->partial_payment) {
                    if ($user->wallet_balance <= 0) {
                        return response()->json([
                            'errors' => [
                                ['code' => 'order_amount', 'message' => translate('messages.insufficient_balance_for_partial_amount')]
                            ]
                        ], 203);
                    }
                    $p_amount = min($user->wallet_balance, $order->order_amount);
                    $unpaid_amount = $order->order_amount - $p_amount;
                    $order->partially_paid_amount = $p_amount;

                    $order->save();
                    CustomerLogic::create_wallet_transaction($order->user_id, $p_amount, 'partial_payment', $order->id);
                    OrderLogic::create_order_payment(order_id: $order->id, amount: $p_amount, payment_status: 'paid', payment_method: 'wallet');
                    OrderLogic::create_order_payment(order_id: $order->id, amount: $unpaid_amount, payment_status: 'unpaid', payment_method: $request->payment_method);
                }
            }

            DB::commit();


            $payments = $order->payments()->where('payment_method', 'cash_on_delivery')->exists();
            $order_mail_status = Helpers::get_mail_status('place_order_mail_status_user');
            $order_verification_mail_status = Helpers::get_mail_status('order_verification_mail_status_user');

            //PlaceOrderMail
            try {
                if (0 && !in_array($order->payment_method, ['digital_payment', 'partial_payment', 'offline_payment'])  || $payments) {
                    Helpers::send_order_notification($order);

                    if ($order->order_status == 'pending' && config('mail.status') && $order_mail_status == '1' && $user) {

                        Mail::to($user->email)->send(new PlaceOrder($order->id));
                    }
                    if ($order->order_status == 'pending' && config('order_delivery_verification') == 1 && $order_verification_mail_status == '1' && $user) {
                        Mail::to($user->email)->send(new OrderVerificationMail($order->otp, $user->f_name));
                    }
                    if ($order->is_guest == 1 && $order->order_status == 'pending' && config('mail.status') && $order_mail_status == '1' && isset($request->contact_person_email)) {
                        Mail::to($request->contact_person_email)->send(new PlaceOrder($order->id));
                    }
                    if ($order->is_guest == 1 && $order->order_status == 'pending' && config('order_delivery_verification') == 1 && $order_verification_mail_status == '1' && isset($request->contact_person_email)) {
                        Mail::to($request->contact_person_email)->send(new OrderVerificationMail($order->otp, $request->contact_person_name));
                    }
                }
            } catch (\Exception $ex) {
                // info($ex->getMessage());
            }

            // place order sms, email and in app notification to vendor  =================== 
            $title = "Received New Order";
            $msg = "Good news! You've got a new order. Let's get it ready!";
            $acceptnce_id = '';
            $to = $store->id;
            $url = route('vendor.order.list', ['pending']);
            $user_typ = 'vendor';

            _inAppNotification($title, $msg, $acceptnce_id, $to, $url, $user_typ);
            // _sendMailToVendor($title, $msg, $to, $url); 
            $smsTemplate = "Hello! Your order NO " . $order->id . " is received. Please review the details on My Chitti Vendor Dashboard and confirm accuracy.";
            _sendSMS($store->phone, $smsTemplate);
            _sendOrderSMSToAdmins($order, $user, $store);

            // SendOrderNotifications::dispatch( 
            //     $title, 
            //     $msg,
            //     $acceptnce_id, 
            //     $to,
            //     $url,
            //     $user_typ,
            //     $order->id,
            //     $store->phone
            // );


            // place order sms, email and in app notification to vendor ===================
            return response()->json([
                'message' => translate('messages.order_placed_successfully'),
                'order_id' => $order->id,
                'payment_method' => $request->payment_method,
                'total_ammount' => $order->order_amount,
                'status' => $order->order_status,
                'created_at' => $order->created_at,
                'url' => $request->payment_method == 'digital_payment'  ? "payment-mobile?customer_id=" . $user_id . "&order_id=" . $order->id . "&payment_platform=web&payment_method=razor_pay&callback=/success" : ''
            ], 200);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([$e], 403);
        }
        return response()->json([
            'errors' => [
                ['code' => 'order_time', 'message' => translate('messages.failed_to_place_order')]
            ]
        ]);
    }

    public function change_variation(Request $request)
    {
        $vrType = $request->type;
        $prId = $request->id;

        $item = DB::table('items')->where('id', $prId)->first();
        $variations = json_decode($item->variations);
        $selectedVr = [];

        foreach ($variations as $key => $value) {
            if ($value->type == $vrType) {
                $selectedVr = $value;
                $selectedVr->discounted_price =  $selectedVr->price;
                $vrDetails = ItemVariationDetail::find($selectedVr->variations_table_id);
                $selectedVr->variation_details = $vrDetails;
            }
        }
        return response()->json(['status' => true, 'data' => $selectedVr]);
    }
    public function order_success(Request $request, $order_id = null)
    {
        $order_id = $order_id;
        return view('front-views.order-success', compact('order_id'));
    }
    public function store_gallery(Request $request, $slug = null)
    {
        // If the store is already resolved via custom domain middleware, use that context
        $store = $request->attributes->get('store_domain_store');
        if ($store) {
            $store->load('galleries');
        } else {
            // Resolve from the route param explicitly (not $request->slug, which can be shadowed
            // by input) and bypass global scopes — the slug is unique, and on a custom domain
            // there's no zone/session context to scope by.
            $slug = $slug ?: $request->route('slug');
            $store = Store::withoutGlobalScopes()->with('galleries')->where('slug', $slug)->first();
        }
        if (!$store) {
            abort(404); 
        }
        return view('front-views.store_gallery', compact('store'));
    }
    public function trackBannerClick(Request $request)
    {
        $bannerId = $request->banner_id;
        $banner = DB::table('banners')->where('id', $bannerId)->first();
        if (!$banner) {
            return response()->json(['message' => 'Banner not found'], 404);
        }

        $ip = $request->ip();
        $isUnique = !DB::table('analytics_logs')
            ->where('screen_type', 'banner')
            ->where('ref_id', $bannerId)
            ->where('ip', $ip)
            ->whereDate('created_at', now()->toDateString())
            ->exists();

        DB::table('banners')->where('id', $bannerId)->increment('total_clicks');
        if ($isUnique) {
            DB::table('banners')->where('id', $bannerId)->increment('unique_clicks');
        }

        DB::table('analytics_logs')->insert([
            'screen_type' => 'banner',
            'sub_type' => 'web',
            'ref_id' => $bannerId,
            'user_id' => auth()->check() ? auth()->id() : null,
            'ip' => $ip,
            'created_at' => now(),
        ]);

        return response()->json(['message' => 'Banner click counted']);
    }

    public function trackAdClick(Request $request)
    {
        $adId = $request->ad_id;
        $ad = DB::table('notifications')->where('id', $adId)->whereNotNull('vendor_id')->first();
        if (!$ad) {
            return response()->json(['message' => 'Ad not found'], 404);
        }

        $ip = $request->ip();

        DB::table('notifications')->where('id', $adId)->increment('total_clicks');

        try {
            $isUnique = !DB::table('analytics_logs')
                ->where('screen_type', 'ad')
                ->where('ref_id', $adId)
                ->where('ip', $ip)
                ->whereDate('created_at', now()->toDateString())
                ->exists();

            if ($isUnique) {
                DB::table('notifications')->where('id', $adId)->increment('unique_clicks');
            }

            DB::table('analytics_logs')->insert([
                'screen_type' => 'ad',
                'sub_type'    => 'web',
                'ref_id'      => $adId,
                'user_id'     => auth()->check() ? auth()->id() : null,
                'ip'          => $ip,
                'created_at'  => now(),
            ]);
        } catch (\Exception $e) {
            // analytics_logs failure must not prevent the increment
        }

        return response()->json(['message' => 'Ad click counted']);
    }

    public function trackStoreContactClick(Request $request)
    {
        $storeId = $request->store_id;
        $action  = $request->action;

        // Platform analytics events (analytics_logs) — call reuses phone-call analytics,
        // copy is a web-only event, share = store share, whatsapp/enquiry come from the
        // store cards (product detail page, store page) and get their own Performance
        // Analytics stat.
        $screenType = match ($action) {
            'call'     => 'call',
            'copy'     => 'copy',
            'share'    => 'share',
            'whatsapp' => 'whatsapp',
            'enquiry'  => 'enquiry',
            default    => null,
        };

        // Inbound-lead actions (Phase 3 §3.3) — also recorded to lead_signals for the MC Vendor Hub
        // Lead Inbox. 'copy'/'share' are analytics-only; everything here is a real lead intent.
        // lead_signals.type is an ENUM, so 'enquiry' rides on the existing 'booking' member.
        $leadType  = $action === 'enquiry' ? 'booking' : $action;
        $leadTypes = ['call', 'whatsapp', 'booking', 'quote', 'direction', 'website'];
        $isLead = in_array($leadType, $leadTypes, true);

        if (!$screenType && !$isLead) {
            return response()->json(['message' => 'Invalid action'], 422);
        }

        $store = DB::table('stores')->where('id', $storeId)->first();
        if (!$store) {
            return response()->json(['message' => 'Store not found'], 404);
        }

        $ip = $request->ip();

        // 1) Platform analytics — identical to before (only for call/copy/share).
        if ($screenType) {
            // sub_type: for 'share' it holds the share target ('store'); otherwise the source platform ('web').
            $subType = $action === 'share' ? 'store' : 'web';
            try {
                DB::table('analytics_logs')->insert([
                    'screen_type' => $screenType,
                    'sub_type'    => $subType,
                    'ref_id'      => $storeId,
                    'user_id'     => auth()->check() ? auth()->id() : null,
                    'ip'          => $ip,
                    'created_at'  => now(),
                ]);
            } catch (\Exception $e) {
                // analytics failure must not break the click
            }
        }

        // 2) Lead Inbox signal — full funnel (call/whatsapp/booking/quote/direction/website).
        if ($isLead) {
            try {
                DB::table('lead_signals')->insert([
                    'store_id'     => $storeId,
                    'user_id'      => auth()->check() ? auth()->id() : null,
                    'type'         => $leadType,
                    'source'       => $request->input('source', 'web'),
                    'utm_source'   => $request->input('utm_source'),
                    'utm_medium'   => $request->input('utm_medium'),
                    'utm_campaign' => $request->input('utm_campaign'),
                    'meta'         => json_encode(['ip' => $ip, 'ua' => substr((string) $request->userAgent(), 0, 255)]),
                    'created_at'   => now(),
                    'updated_at'   => now(),
                ]);
            } catch (\Exception $e) {
                // lead capture failure must not break the click
            }
        }

        return response()->json(['message' => 'ok']);
    }

    private function adsBaseQuery()
    {
        $zone_ids = json_decode($this->zone_id, true);
        return \App\Models\Notification::whereNotNull('vendor_id')
            ->where('approval', 1)
            ->where('status', 1)
            ->whereNotNull('image')
            ->where(function ($q) {
                $q->whereNull('days')
                  ->orWhereNull('approved_at')
                  ->orWhereRaw('DATE_ADD(approved_at, INTERVAL days DAY) >= NOW()');
            })
            ->where(function ($q) use ($zone_ids) {
                $q->whereIn('zone_id', $zone_ids)
                    ->orWhereNull('zone_id')
                    ->orWhere('zone_id', 0);
            })
            ->latest();
    }
 
    public function allAds()
    {
        $ads = $this->adsBaseQuery()->paginate(18);
        return view('front-views.ads.index', compact('ads'));
    }

    public function loadAds(Request $request)
    {
        $ads = $this->adsBaseQuery()->paginate(12);
        $html = view('front-views.ads._ad_cards', compact('ads'))->render();
        return response()->json([
            'html'     => $html,
            'has_more' => $ads->hasMorePages(),
        ]);
    }

    public function adDetail($id)
    {
        $ad = \App\Models\Notification::whereNotNull('vendor_id')
            ->where('approval', 1)
            ->where('status', 1)
            ->findOrFail($id);

        try {
            $ip = request()->ip();
            $isUnique = !DB::table('analytics_logs')
                ->where('screen_type', 'ad')
                ->where('ref_id', $id)
                ->where('ip', $ip)
                ->whereDate('created_at', now()->toDateString())
                ->exists();

            DB::table('notifications')->where('id', $id)->increment('total_clicks');
            if ($isUnique) {
                DB::table('notifications')->where('id', $id)->increment('unique_clicks');
            }
            DB::table('analytics_logs')->insert([
                'screen_type' => 'ad',
                'sub_type'    => 'web',
                'ref_id'      => $id,
                'user_id'     => auth()->check() ? auth()->id() : null,
                'ip'          => $ip,
                'created_at'  => now(),
            ]);
        } catch (\Exception $e) {
            // analytics failure must not break the page
        }

        $store = $ad->vendor_id ? DB::table('stores')->where('id', $ad->vendor_id)->first() : null;
        return view('front-views.ads.detail', compact('ad', 'store'));
    }

    public function store_details(Request $request, $city, $slug)
    {
        $check_module = DB::table('stores')->where('slug', $slug)->first();
        if ($check_module) {
            $module = $check_module->module_id;
        } else {
            abort(404);
        }

        // One canonical city per store (falls back to the platform default for zone-less stores).
        $canonicalCity = 'tirupati';
        if ($check_module->zone_id) {
            $zone = DB::table('zones')->where('id', $check_module->zone_id)->value('name');
            if ($zone) {
                $canonicalCity = _zoneCitySlug($zone);
            }
        }
        // 301 any other city to the single canonical URL — kills duplicate / soft-404 pages.
        if ($city !== $canonicalCity) {
            return redirect()->to(url($canonicalCity . '/store/' . $slug), 301);
        }
        // True canonical for the store page (overrides the layout's self-referencing default).
        view()->share('canonical', url($canonicalCity . '/store/' . $slug));
        $invItemdata = [];
        $longitude = $this->longitude;
        $latitude = $this->latitude;
        $store = Store::with(['discount' => function ($q) {
            return $q->validate();
        }, 'campaigns', 'schedules', 'activeCoupons'])
            ->withCount(['items', 'campaigns'])
            ->when($module, function ($query) use ($module) {
                $query->module($module);
            })
            ->where('slug', $slug)
            ->first();


        if ($store) {
            // Thin-content guard: keep genuinely empty store shells (no items, no campaigns,
            // no specialised business type) out of the index so they aren't flagged soft-404.
            view()->share('metaRobots',
                ($store->items_count == 0 && $store->campaigns_count == 0 && empty($store->business_type)) ? 'noindex, follow' : null);
 
            // LocalBusiness JSON-LD (P0) — emitted in the layout head for every store template.
            view()->share('localBusinessStore', $store);

            // Increment store visit analytics
            $ip = $request->ip();
            $isUnique = !DB::table('analytics_logs')
                ->where('screen_type', 'store')
                ->where('ref_id', $store->id)
                ->where('ip', $ip)
                ->whereDate('created_at', now()->toDateString())
                ->exists();

            DB::table('stores')->where('id', $store->id)->increment('total_visits');
            if ($isUnique) {
                DB::table('stores')->where('id', $store->id)->increment('unique_visits');
            }

            DB::table('analytics_logs')->insert([
                'screen_type' => 'store',
                'sub_type' => 'web',
                'ref_id' => $store->id,
                'user_id' => auth()->check() ? auth()->id() : null,
                'ip' => $ip,
                'created_at' => now(),
            ]);

            if ($module == 5) {

                $keywordsData = DB::table('items')
                    ->where('items.is_approved', 1)
                    ->join('categories', 'items.category_id', '=', 'categories.id')
                    ->where('items.store_id', $store->id)
                    ->select('items.name as item_name', 'categories.name as category_name')
                    ->distinct()
                    ->get();

                $keywords = implode(',', $keywordsData->pluck('item_name')->merge($keywordsData->pluck('category_name'))->toArray());

                $category_ids = DB::table('items')
                    ->join('categories', 'items.category_id', '=', 'categories.id')
                    ->selectRaw('categories.position as positions, IF((categories.position = "0"), categories.id, categories.parent_id) as categories')
                    ->where('items.store_id', $store->id)
                    ->where('categories.status', 1)
                    ->groupBy('categories', 'positions')
                    ->get();

                $store = Helpers::store_data_formatting($store);
                $store['category_ids'] = array_map('intval', $category_ids->pluck('categories')->toArray());
                $store['category_details'] = Category::whereIn('id', $store['category_ids'])->get();
                $store['price_range']  = Item::withoutGlobalScopes()->where('store_id', $store->id)
                    ->select(DB::raw('MIN(price) AS min_price, MAX(price) AS max_price'))
                    ->get(['min_price', 'max_price']);

                $productdata = DB::table('items')
                    ->join('categories', 'items.category_id', 'categories.id')
                    ->where('items.store_id', $store->id)
                    ->where('items.status', 1)
                    ->where('items.is_approved', 1)
                    ->select('categories.id', 'categories.name', 'categories.slug as cat_slug')
                    ->distinct()
                    ->get()
                    ->toArray();

                foreach ($productdata as $key => $cat) {
                    $cat->items = DB::table('items')
                        ->where('store_id', $store->id)
                        ->where('category_id', $cat->id)
                        ->where('status', 1)
                        ->where('is_approved', 1)
                        ->get();
                }
            } else {
                $keywordsData = DB::table('items')
                    ->where('items.is_approved', 1)
                    ->join('categories', 'items.category_id', '=', 'categories.id')
                    ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                    ->select('items.name as item_name', 'categories.name as category_name')
                    ->distinct()
                    ->get();

                $keywords = implode(',', $keywordsData->pluck('item_name')->merge($keywordsData->pluck('category_name'))->toArray());
                // echo '
';
                // SERVICES
                $productdata1 = DB::table('items')
                    ->join('categories', 'items.category_id', 'categories.id')
                    ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                    ->whereNull('items.inventory_item_id')
                    ->where('categories.status', 1)
                    ->select('categories.id', 'categories.name', 'categories.slug as cat_slug')
                    ->distinct()
                    ->get();


                foreach ($productdata1 as $cat) {
                    $cat->items = DB::table('items')
                        ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                        ->whereNull('items.inventory_item_id')
                        ->where('category_id', $cat->id)
                        ->where('status', 1)
                        ->get();
                }

                //INVENTORY ITEMS
                $invItemdata = DB::table('items')
                    ->join('categories', 'items.category_id', 'categories.id')
                    ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                    ->whereNotNull('items.inventory_item_id')
                    ->select('categories.id', 'categories.name', 'categories.slug as cat_slug')
                    ->distinct()
                    ->get();

                foreach ($invItemdata as $cat) {
                    $cat->items = DB::table('items')
                        ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                        ->whereNotNull('items.inventory_item_id')
                        ->where        }

        if ($request->partial_payment && !Helpers::get_business_settings('partial_payment_status')) {
            return response()->json([
                'errors' => [
                    ['code' => 'order_method', 'message' => translate('messages.partial_payment_is_not_active')]
                ]
            ]);
        }

        if ($request->payment_method == 'offline_payment' &&  Helpers::get_mail_status('offline_payment_status') == 0) {
            return response()->json([
                'errors' => [
                    ['code' => 'offline_payment_status', 'message' => translate('messages.offline_payment_for_the_order_not_available_at_this_time')]
                ]
            ]);
        }

        $digital_payment = Helpers::get_business_settings('digital_payment');
        if ($digital_payment['status'] == 0 && $request->payment_method == 'digital_payment') {
            return response()->json([
                'errors' => [
                    ['code' => 'digital_payment', 'message' => translate('messages.digital_payment_for_the_order_not_available_at_this_time')]
                ]
            ]);
        }

        $data =  DMVehicle::active()->where(function ($query) use ($distance_data) {
            $query->where('starting_coverage_area', '<=', $distance_data)->where('maximum_coverage_area', '>=', $distance_data)
                ->orWhere(function ($query) use ($distance_data) {
                    $query->where('starting_coverage_area', '>=', $distance_data);
                });
        })
            ->orderBy('starting_coverage_area')->first();

        $extra_charges = (float) (isset($data) ? $data->extra_charges  : 0);
        $vehicle_id = (isset($data) ? $data->id  : null);

        $zone = null;
        if ($request->latitude[$key] && $request->longitude[$key]) {
            $point = new Point($request->latitude[$key], $request->longitude[$key]);
            if ($request->order_type == 'parcel') {
                // if(isset($request->sender_zone_id) ){
                // $zone_id = $request->sender_zone_id;
                $zone_ids = $request->header('zoneId') ? json_decode($request->header('zoneId'), true) : [];
                $zone = Zone::whereIn('id', $zone_ids)->whereContains('coordinates', new Point($request->latitude[$key], $request->longitude[$key], POINT_SRID))->wherehas('modules', function ($q) {
                    $q->where('module_type', 'parcel');
                })->first();
            } else {
                // ->selectRaw('*, IF(((select count(*) from `store_schedule` where `stores`.`id` = `store_schedule`.`store_id` and `store_schedule`.`day` = ' . $schedule_at->format('w') . ' and `store_schedule`.`opening_time` < "' . $schedule_at->format('H:i:s') . '" and `store_schedule`.`closing_time` >"' . $schedule_at->format('H:i:s') . '") > 0), true, false) as open')
                $store = Store::with('discount')->where('id', $request->store_id)->first();

                if (!$store) {
                    return response()->json([
                        'errors' => [
                            ['code' => 'order_time', 'message' => translate('messages.store_not_found')]
                        ]
                    ]);
                }
                $zone_id =  [$store->zone_id];
                $zone = Zone::where('id', $zone_id)->whereContains('coordinates', new Point($request->latitude[$key], $request->longitude[$key], POINT_SRID))->first();
            }
        }
        if (!$zone) {
            $errors = [];
            array_push($errors, ['code' => 'coordinates', 'message' => translate('messages.out_of_coverage')]);
            return response()->json([
                'errors' => $errors
            ]);
        }
        if ($zone && $zone->increased_delivery_fee_status == 1) {
            $increased = $zone->increased_delivery_fee ?? 0;
        }

        if ($request->order_type !== 'parcel') {


            if (!$store->active) {
                return response()->json([
                    'errors' => [
                        ['code' => 'order_time', 'message' => translate('messages.store_is_closed_at_order_time')]
                    ]
                ]);
            }

            if ($request->coupon_code) {
                $coupon = Coupon::active()->where(['code' => $request->coupon_code])->first();
                if (isset($coupon)) {


                    $staus = CouponLogic::is_valide($coupon, $user->id, $request->store_id);


                    if ($staus == 407) {
                        return response()->json([
                            'errors' => [
                                ['code' => 'coupon', 'message' => translate('messages.coupon_expire')]
                            ]
                        ]);
                    } else if ($staus == 408) {
                        return response()->json([
                            'errors' => [
                                ['code' => 'coupon', 'message' => translate('messages.You_are_not_eligible_for_this_coupon')]
                            ]
                        ]);
                    } else if ($staus == 406) {
                        return response()->json([
                            'errors' => [
                                ['code' => 'coupon', 'message' => translate('messages.coupon_usage_limit_over')]
                            ]
                        ]);
                    } else if ($staus == 404) {
                        return response()->json([
                            'errors' => [
                                ['code' => 'coupon', 'message' => translate('messages.not_found')]
                            ]
                        ]);
                    }

                    $coupon_created_by = $coupon->created_by;
                    if ($coupon->coupon_type == 'free_delivery') {
                        $delivery_charge = 0;
                        $free_delivery_by =  $coupon_created_by;
                        $coupon_created_by = null;
                    }
                } else {
                    return response()->json([
                        'errors' => [
                            ['code' => 'coupon', 'message' => translate('messages.not_found')]
                        ]
                    ], 404);
                }
            }

            $module_wise_delivery_charge = $store->zone->modules()->where('modules.id', 5)->first();
            if ($module_wise_delivery_charge) {
                $per_km_shipping_charge = $module_wise_delivery_charge->pivot->per_km_shipping_charge;
                $minimum_shipping_charge = $module_wise_delivery_charge->pivot->minimum_shipping_charge;
                $maximum_shipping_charge = $module_wise_delivery_charge->pivot->maximum_shipping_charge;
            } else {
                $per_km_shipping_charge = (float)BusinessSetting::where(['key' => 'per_km_shipping_charge'])->first()->value;
                $minimum_shipping_charge = (float)BusinessSetting::where(['key' => 'minimum_shipping_charge'])->first()->value;
            }

            if ($request->order_type != 'take_away' && !$store->free_delivery && !isset($delivery_charge) &&  $store->self_delivery_system == 1) {
                $per_km_shipping_charge = $store->per_km_shipping_charge;
                $minimum_shipping_charge = $store->minimum_shipping_charge;
                $maximum_shipping_charge = $store->maximum_shipping_charge;
                $extra_charges = 0;
                $vehicle_id = null;
                $increased = 0;
            }

            if ($store->free_delivery || $free_delivery_by == 'vendor') {
                $per_km_shipping_charge = $store->per_km_shipping_charge;
                $minimum_shipping_charge = $store->minimum_shipping_charge;
                $maximum_shipping_charge = $store->maximum_shipping_charge;
                $extra_charges = 0;
                $increased = 0;
            }

            $original_delivery_charge = (($request->distance * $per_km_shipping_charge) > $minimum_shipping_charge) ? $request->distance * $per_km_shipping_charge  : $minimum_shipping_charge;

            if ($request->order_type == 'take_away') {
                $per_km_shipping_charge = 0;
                $minimum_shipping_charge = 0;
                $maximum_shipping_charge = 0;
                $extra_charges = 0;
                $distance_data = 0;
                $vehicle_id = null;
                $original_delivery_charge = 0;
                $increased = 0;
            }

            if ($maximum_shipping_charge  >= $minimum_shipping_charge  && $original_delivery_charge >  $maximum_shipping_charge) {
                $original_delivery_charge = $maximum_shipping_charge;
            } else {
                $original_delivery_charge = $original_delivery_charge;
            }

            if (!isset($delivery_charge)) {
                $delivery_charge = ($request->distance * $per_km_shipping_charge > $minimum_shipping_charge) ? $request->distance * $per_km_shipping_charge : $minimum_shipping_charge;
                if ($maximum_shipping_charge  >= $minimum_shipping_charge  && $delivery_charge >  $maximum_shipping_charge) {
                    $delivery_charge = $maximum_shipping_charge;
                } else {
                    $delivery_charge = $delivery_charge;
                }
            }
            $original_delivery_charge = $original_delivery_charge + $extra_charges;
            $delivery_charge = $delivery_charge + $extra_charges;
        } else {
            $parcel_category = ParcelCategory::findOrFail($request->parcel_category_id);
            if (isset($parcel_category) && isset($parcel_category->parcel_minimum_shipping_charge)) {
                $per_km_shipping_charge = $parcel_category->parcel_per_km_shipping_charge;
                $minimum_shipping_charge = $parcel_category->parcel_minimum_shipping_charge;
            } else {
                $per_km_shipping_charge = (float)BusinessSetting::where(['key' => 'parcel_per_km_shipping_charge'])->first()->value;
                $minimum_shipping_charge = (float)BusinessSetting::where(['key' => 'parcel_minimum_shipping_charge'])->first()->value;
            }

            $original_delivery_charge = (($request->distance * $per_km_shipping_charge) > $minimum_shipping_charge) ? ($request->distance * $per_km_shipping_charge) + $extra_charges : ($minimum_shipping_charge + $extra_charges);
        }

        if ($increased > 0) {
            if ($delivery_charge > 0) {
                $increased_fee = ($delivery_charge * $increased) / 100;
                $delivery_charge = $delivery_charge + $increased_fee;
            }
            if ($original_delivery_charge > 0) {
                $increased_fee = ($original_delivery_charge * $increased) / 100;
                $original_delivery_charge = $original_delivery_charge + $increased_fee;
            }
        }
        $address = [
            'contact_person_name' => $request->contact_person_name[$key] ? $request->contact_person_name[$key] : ($user ? $user->f_name . ' ' . $user->f_name : ''),
            'contact_person_number' => $request->contact_person_number[$key] ? ($user ? $request->contact_person_number[$key] : str_replace('+', '', $request->contact_person_number[$key])) : ($user ? $user->phone : ''),
            'contact_person_email' => $user ? $user->email : '',
            'address_type' => $request->address_type ? $request->address_type : 'Delivery',
            'address' => $request?->address[$key] ?? '',
            'floor' => $request?->floor[$key] ?? '',
            'road' => $request?->road[$key] ?? '',
            'house' => $request?->house[$key] ?? '',
            'longitude' => (string)$request->longitude[$key],
            'latitude' => (string)$request->latitude[$key],
        ];
        $total_addon_price = 0;
        $product_price = 0;
        $store_discount_amount = 0;
        $flash_sale_vendor_discount_amount = 0;
        $flash_sale_admin_discount_amount = 0;
        $store_discount_amount = 0;
        $product_data = [];

        $order_details = [];
        $order = new Order();
        $lastOrder = Order::orderBy('id', 'desc')->first();

        if ($lastOrder) {
            $order->id = $lastOrder->id + 1;
        } else {
            $order->id = 10001;
        }
        $order->invoice_id = _generateOrderInvoiceId($request->store_id);

        $order_status = 'pending';
        if (($request->partial_payment && $request->payment_method != 'offline_payment') || $request->payment_method == 'wallet') {
            $order_status = 'confirmed';
        }

        $order->user_id = $user ? $user->id : 0;
        $order->order_amount = $request->order_amount;
        $order->payment_status = ($request->partial_payment ? 'partially_paid' : ($request->payment_method == 'wallet' ? 'paid' : 'unpaid'));
        $order->order_status = $order_status;
        $order->coupon_code = $request->coupon_code;
        $order->payment_method = $request->partial_payment ? 'partial_payment' : $request->payment_method;
        $order->transaction_reference = null;
        $order->order_note = $request->order_note;
        $order->unavailable_item_note = $request->unavailable_item_note;
        $order->delivery_instruction = $request->delivery_instruction;
        $order->order_type = $request->order_type;
        $order->store_id = $request->store_id;
        if ($store->delivery_charges_on && $store->delivery_charges_on <= $request->order_amount) {
            $order->delivery_charge = 0;
        } else {
            $order->delivery_charge = round($delivery_charge, config('round_up_to_digit')) ?? 0;
        }
        $order->original_delivery_charge = round($original_delivery_charge, config('round_up_to_digit'));
        $order->delivery_address = json_encode($address);
        $order->schedule_at = $schedule_at;
        $order->scheduled = $request->schedule_at ? 1 : 0;
        $order->cutlery = $request->cutlery ? 1 : 0;
        $order->is_guest = $user ? 0 : 1;
        $order->otp = rand(1000, 9999);
        $order->zone_id = isset($zone) ? $zone->id : end(json_decode($this->zone_id, true));
        $order->module_id = 5;
        $order->parcel_category_id = $request->parcel_category_id;
        $order->receiver_details = json_decode($request->receiver_details);

        if ($order_status == 'confirmed') {
            $order->confirmed = now();
        }
        $order->dm_vehicle_id = $vehicle_id;
        $order->pending = now();
        $order->order_attachment = $request->has('order_attachment') ? Helpers::upload('order/', 'png', $request->file('order_attachment')) : null;
        $order->distance = $distance_data;
        $order->created_at = now();
        $order->updated_at = now();
        $order->charge_payer = null;

        //Added DM TIPS
        $dm_tips_manage_status = BusinessSetting::where('key', 'dm_tips_status')->first()->value;
        if ($dm_tips_manage_status == 1) {
            $order->dm_tips = $request->dm_tips ?? 0;
        } else {
            $order->dm_tips = 0;
        }
        //Added service charge
        $additional_charge_status = BusinessSetting::where('key', 'additional_charge_status')->first()->value;
        $additional_charge = BusinessSetting::where('key', 'additional_charge')->first()->value;
        if ($additional_charge_status == 1) {
            $order->additional_charge = $additional_charge ?? 0;
        } else {
            $order->additional_charge = 0;
        }

        $carts = Cart::where('user_id', $order->user_id)->where('is_guest', 0)->where('module_id', 5)
            ->when(isset($request->is_buy_now) && $request->is_buy_now == 1 && $request->cart_id, function ($query) use ($request) {
                return $query->where('id', $request->cart_id);
            })
            ->get()->map(function ($data) {
                $data->add_on_ids = json_decode($data->add_on_ids, true);
                $data->add_on_qtys = json_decode($data->add_on_qtys, true);
                $data->variation = json_decode($data->variation, true);
                return $data;
            });

        if (isset($request->is_buy_now) && $request->is_buy_now == 1) {
            $carts = json_decode($request->cart, true);
        }


        if ($request->order_type !== 'parcel') {
            foreach ($carts as $c) {
                if ($c['item_type'] === 'App\Models\ItemCampaign' || $c['item_type'] === 'AppModelsItemCampaign') {
                    $product = ItemCampaign::with('module')->active()->find($c['item_id']);
                    if ($product) {
                        if ($product->store_id != $order->store_id) {
                            return response()->json([
                                'errors' => [
                                    ['code' => 'different_stores', 'message' => translate('messages.Please_select_items_from_the_same_store')]
                                ]
                            ], 403);
                        }

                        if ($product->module->module_type == 'food' && $product->food_variations) {
                            $product_variations = json_decode($product->food_variations, true);
                            $variations = [];
                            if (count($product_variations)) {
                                $variation_data = Helpers::get_varient($product_variations, $c['variation']);
                                $price = $product['price'] + $variation_data['price'];
                                $variations = $variation_data['variations'];
                            } else {
                                $price = $product['price'];
                            }
                            // $product->tax = $store->tax;
                            $product = Helpers::product_data_formatting($product, false, false, app()->getLocale());
                            $addon_data = Helpers::calculate_addon_price(\App\Models\AddOn::whereIn('id', $c['add_on_ids'])->get(), $c['add_on_qtys']);
                            $or_d = [
                                'item_id' => null,
                                'item_campaign_id' => $c['item_id'],
                                'item_details' => json_encode($product),
                                'quantity' => $c['quantity'],
                                'price' => round($price, config('round_up_to_digit')),
                                'tax_amount' => Helpers::tax_calculate($product, $price),
                                'discount_on_item' => Helpers::product_discount_calculate($product, $price, $store)['discount_amount'],
                                'discount_type' => 'discount_on_product',
                                'variant' => json_encode($c['variant']),
                                'variation' => json_encode($variations),
                                'add_ons' => json_encode($addon_data['addons']),
                                'total_add_on_price' => $addon_data['total_add_on_price'],
                                'created_at' => now(),
                                'updated_at' => now()
                            ];
                            $order_details[] = $or_d;
                            $total_addon_price += $or_d['total_add_on_price'];
                            $product_price += $price * $or_d['quantity'];
                            $store_discount_amount += $or_d['discount_on_item'] * $or_d['quantity'];
                        } else {
                            if (count(json_decode($product['variations'], true)) > 0) {
                                $variant_data = Helpers::variation_price($product, json_encode($c['variation']));
                                $price = $variant_data['price'];
                                $stock = $variant_data['stock'];
                                $mychitti_fee = $variant_data['price'] - $variant_data['askingprice'];
                            } else {
                                $price = $product['price'];
                                $stock = $product->stock;
                                $mychitti_fee = $product->mychitty_fee;
                            }
                            if (config('module.' . $product->module->module_type)['stock']) {
                                if ($c['quantity'] > $stock) {
                                    return response()->json([
                                        'errors' => [
                                            ['code' => 'campaign', 'message' => translate('messages.product_out_of_stock', ['item' => $product->title])]
                                        ]
                                    ]);
                                }

                                $product_data[] = [
                                    'item' => clone $product,
                                    'quantity' => $c['quantity'],
                                    'variant' => count($c['variation']) > 0 ? $c['variation'][0]['type'] : null
                                ];
                            }

                            // $product->tax = $store->tax;
                            $product = Helpers::product_data_formatting($product, false, false, app()->getLocale());
                            $addon_data = Helpers::calculate_addon_price(\App\Models\AddOn::whereIn('id', $c['add_on_ids'])->get(), $c['add_on_qtys']);
                            $or_d = [
                                'item_id' => null,
                                'item_campaign_id' => $c['item_id'],
                                'item_details' => json_encode($product),
                                'quantity' => $c['quantity'],
                                'price' => $price,
                                'tax_amount' => Helpers::tax_calculate($product, $price),
                                'discount_on_item' => Helpers::product_discount_calculate($product, $price, $store)['discount_amount'],
                                'discount_type' => 'discount_on_product',
                                'variant' => json_encode($c['variant']),
                                'variation' => json_encode($c['variation']),
                                'add_ons' => json_encode($addon_data['addons']),
                                'total_add_on_price' => $addon_data['total_add_on_price'],
                                'platform_fee' => $mychitti_fee ??  0,
                                'created_at' => now(),
                                'updated_at' => now()
                            ];
                            $order_details[] = $or_d;
                            $total_addon_price += $or_d['total_add_on_price'];
                            $product_price += $price * $or_d['quantity'];
                            $store_discount_amount += $or_d['discount_on_item'] * $or_d['quantity'];
                        }
                    } else {
                        return response()->json([
                            'errors' => [
                                ['code' => 'campaign', 'message' => translate('messages.product_unavailable_warning')]
                            ]
                        ]);
                    }
                } else {
                    $product = Item::hydrate(
                        DB::table('items')->where('id',  $c['item_id'])->get()->toArray()
                    )->first();

                    if ($product) {

                        if ($product->store_id != $order->store_id) {
                            return response()->json([
                                'errors' => [
                                    ['code' => 'different_stores', 'message' => translate('messages.Please_select_items_from_the_same_store')]
                                ]
                            ]);
                        }


                        if ($product->maximum_cart_quantity && ($c['quantity'] > $product->maximum_cart_quantity)) {
                            return response()->json([
                                'errors' => [
                                    ['code' => 'quantity', 'message' => translate('messages.maximum_cart_quantity_limit_over')]
                                ]
                            ]);
                        }
                        if ($product->module->module_type == 'food' && $product->food_variations) {

                            $product_variations = json_decode($product->food_variations, true);
                            $variations = [];
                            if (count($product_variations)) {
                                $variation_data = Helpers::get_varient($product_variations, $c['variation']);
                                $mrpprice = $variation_data['mrpprice'];
                                $price = $variation_data['mrpprice'];
                                $variations =  $variation_data['variations'];
                                $mychitti_fee = $variation_data['price'] - $variation_data['askingprice'];
                            } else {
                                $mrpprice = $product['mrp_price'] ?? $product['price'];
                                $price = $product['price'];
                                $mychitti_fee = $product->mychitty_fee;
                            }
                            // $product->tax = $store->tax;
                            $product = Helpers::product_data_formatting($product, false, false, app()->getLocale());
                            $addon_data = Helpers::calculate_addon_price(\App\Models\AddOn::whereIn('id', $c['add_on_ids'])->get(), $c['add_on_qtys']);
                            $product_discount = Helpers::product_discount_calculate($product, $mrpprice, $store);

                            $tax =  _taxCalcluation($price, $product->tax)['gst_amount'];
                            $taxable = _taxCalcluation($price, $product->tax)['price_excluding_gst'];


                            $or_d = [
                                'item_id' => $c['item_id'],
                                'item_campaign_id' => null,
                                'item_details' => json_encode($product),
                                'quantity' => $c['quantity'],
                                'price' => $price,
                                'tax_amount' =>  $tax,
                                'taxable_amount' => $taxable,
                                'discount_on_item' => $product_discount['discount_amount'],
                                'discount_type' => $product_discount['discount_type'],
                                'variant' => json_encode($c['variant']),
                                'variation' => json_encode($variations),
                                'platform_fee' => $mychitti_fee ?? 0,
                                'add_ons' => json_encode($addon_data['addons']),
                                'total_add_on_price' => round($addon_data['total_add_on_price'], config('round_up_to_digit')),
                                'created_at' => now(),
                                'updated_at' => now()
                            ];
                            $total_addon_price += $or_d['total_add_on_price'];

                            $product_price += $price * $or_d['quantity'];
                            $store_discount_amount += $or_d['discount_type'] != 'flash_sale' ? $or_d['discount_on_item'] * $or_d['quantity'] : 0;
                            $flash_sale_admin_discount_amount += $or_d['discount_type'] == 'flash_sale' ? $product_discount['admin_discount_amount'] * $or_d['quantity'] : 0;
                            $flash_sale_vendor_discount_amount += $or_d['discount_type'] == 'flash_sale' ? $product_discount['vendor_discount_amount'] * $or_d['quantity'] : 0;
                            $order_details[] = $or_d;
                        } else {

                            if (count(json_decode($product['variations'], true)) > 0 && count($c['variation']) > 0) {
                                $variant_data = Helpers::variation_price($product, json_encode($c['variation']));
                                $price = $variant_data['mrpprice'];
                                $stock = $variant_data['stock'];
                                $is_vr = true;
                                $mychitti_fee = $variant_data['price'] - $variant_data['askingprice'];
                            } else {
                                $price = $product['price'];
                                $stock = $product->stock;
                                $is_vr = false;
                                $mychitti_fee = $product->mychitty_fee;
                            }

                            if (($stock - $c['quantity']) < 6) {
                                _stock_alert_sms($store->phone, $product['name']);
                                $title = 'Low Stock Alert for ' . $product['name'];
                                $msg = "Dear Vendor, Stock for " . $product['name'] . " is low. Please update accordingly.";
                                $to = $store->id;
                                $url = route('vendor.item.stock-limit-list');
                                $user_typ = 'vendor';
                                _inAppNotification($title, $msg, $acceptnce_id = '', $to, $url, $user_typ);
                            }


                            if (config('module.' . $product->module->module_type)['stock']) {
                                if ($c['quantity'] > $stock) {
                                    return response()->json([
                                        'errors' => [
                                            ['code' => 'campaign', 'message' => translate('messages.product_out_of_stock', ['item' => $product->name])]
                                        ]
                                    ]);
                                }

                                $product_data[] = [
                                    'item' => clone $product,
                                    'quantity' => $c['quantity'],
                                    'variant' => count($c['variation']) > 0 ? $c['variation'][0]['type'] : null
                                ];
                            }

                            // $product->tax = $store->tax;
                            $product = Helpers::product_data_formatting($product, false, false, app()->getLocale());
                            $addon_data = Helpers::calculate_addon_price(\App\Models\AddOn::whereIn('id', $c['add_on_ids'])->get(), $c['add_on_qtys']);

                            if (isset($c['variation']) && $c['variation']) {
                                $mrpprice = $c['variation'][0]['mrpprice'] ?? $c['variation'][0]['price'];
                                $price = $c['variation'][0]['price'];
                                $product_discount = Helpers::product_discount_calculate_vr($c['variation']);
                                $mychitti_fee = isset($c['variation'][0]['askingprice']) ? $price - $c['variation'][0]['askingprice'] : 0;
                            } else {
                                $mrpprice = $product->mrp_price;
                                $price = $product->price;
                                $mychitti_fee = $product->mychitty_fee;
                                $product_discount = Helpers::product_discount_calculate($product, $mrpprice, $store);
                            }
                            $tax_amount =  _taxCalcluation($price, $product->tax)['gst_amount'];
                            $taxable = _taxCalcluation($price, $product->tax)['price_excluding_gst'];

                            $or_d = [
                                'item_id' => $c['item_id'],
                                'item_campaign_id' => null,
                                'item_details' => json_encode($product),
                                'quantity' => $c['quantity'],
                                'price' => $price,
                                'taxable_amount' => $taxable,
                                'tax_amount' => $tax_amount,
                                'discount_on_item' => $product_discount['discount_amount'],
                                'discount_type' => $product_discount['discount_type'],
                                'variant' => json_encode($c['variant']),
                                'variation' => json_encode($c['variation']),
                                'platform_fee' => $mychitti_fee ?? 0,
                                'add_ons' => json_encode($addon_data['addons']),
                                'total_add_on_price' => $addon_data['total_add_on_price'],
                                'created_at' => now(),
                                'updated_at' => now()
                            ];

                            // prx($product_discount['discount_amount']);
                            $total_addon_price += $or_d['total_add_on_price'];
                            $total_order_tax += ($tax_amount * $or_d['quantity']);
                            if ($is_vr) {
                                $product_price += ($price * $or_d['quantity']);
                            } else {
                                $product_price += $price * $or_d['quantity'];
                            }

                            $store_discount_amount += $or_d['discount_type'] != 'flash_sale' ? $or_d['discount_on_item'] * $or_d['quantity'] : 0;
                            $flash_sale_admin_discount_amount += $or_d['discount_type'] == 'flash_sale' ? $product_discount['admin_discount_amount'] * $or_d['quantity'] : 0;
                            $flash_sale_vendor_discount_amount += $or_d['discount_type'] == 'flash_sale' ? $product_discount['vendor_discount_amount'] * $or_d['quantity'] : 0;
                            $order_details[] = $or_d;
                        }
                    } else {
                        return response()->json([
                            'errors' => [
                                ['code' => 'item', 'message' => translate('messages.product_unavailable_warning')]
                            ]
                        ]);
                    }
                }
            }
            $order->discount_on_product_by = 'vendor';
            $store_discount = Helpers::get_store_discount($store);
            if (isset($store_discount)) {
                $order->discount_on_product_by = 'admin';
                if ($product_price + $total_addon_price < $store_discount['min_purchase']) {
                    $store_discount_amount = 0;
                }
                if ($store_discount['max_discount'] != 0 && $store_discount_amount > $store_discount['max_discount']) {
                    $store_discount_amount = $store_discount['max_discount'];
                }
            }
            $coupon_discount_amount = $coupon ? CouponLogic::get_discount($coupon, $product_price + $total_addon_price - $store_discount_amount - $flash_sale_admin_discount_amount - $flash_sale_vendor_discount_amount) : 0;
            $total_price = $product_price + $total_addon_price - $total_addon_price - $flash_sale_admin_discount_amount - $flash_sale_vendor_discount_amount  - $coupon_discount_amount;
            $tax = ($store->tax > 0) ? $store->tax : 0;
            $order->tax_status = 'included';

            $tax_included = BusinessSetting::where(['key' => 'tax_included'])->first() ?  BusinessSetting::where(['key' => 'tax_included'])->first()->value : 0;
            if ($tax_included ==  1) {
                $order->tax_status = 'included';
            }

            $total_tax_amount = Helpers::product_tax($total_price, $tax, $order->tax_status == 'included');
            $tax_a = $order->tax_status == 'included' ? 0 : $total_tax_amount;


            if ($store->minimum_order > $product_price + $total_addon_price) {
                return response()->json([
                    'errors' => [
                        ['code' => 'order_time', 'message' => translate('messages.you_need_to_order_at_least') . $store->minimum_order . ' ' . Helpers::currency_code()]
                    ]
                ]);
            }

            $free_delivery_over = BusinessSetting::where('key', 'free_delivery_over')->first()->value;
            if (isset($free_delivery_over)) {
                if ($free_delivery_over <= $product_price + $total_addon_price - $coupon_discount_amount - $store_discount_amount - $flash_sale_admin_discount_amount - $flash_sale_vendor_discount_amount) {
                    $order->delivery_charge = 0;
                    $free_delivery_by = 'admin';
                }
            }

            if ($store->free_delivery) {
                $order->delivery_charge = 0;
                $free_delivery_by = 'vendor';
            }

            if ($coupon) {
                if ($coupon->coupon_type == 'free_delivery') {
                    if ($coupon->min_purchase <= $product_price + $total_addon_price - $store_discount_amount - $flash_sale_admin_discount_amount - $flash_sale_vendor_discount_amount) {
                        $order->delivery_charge = 0;
                        $free_delivery_by = $coupon->created_by;
                    }
                }
                $coupon->increment('total_uses');
            }
            $order->coupon_created_by = $coupon_created_by;
            $order->coupon_discount_amount = round($coupon_discount_amount, config('round_up_to_digit'));
            $order->coupon_discount_title = $coupon ? $coupon->title : '';

            $order->store_discount_amount = round($store_discount_amount, config('round_up_to_digit'));
            $order->tax_percentage = $tax;
            $order->total_tax_amount = $total_order_tax ?? round($total_tax_amount, config('round_up_to_digit'));
            $order->rounded_off = ($total_price + $tax_a + $order->delivery_charge) - floor($total_price + $tax_a + $order->delivery_charge);
            $order->order_amount = round($total_price + $tax_a + $order->delivery_charge);

            $order->free_delivery_by = $free_delivery_by;
        } else {

            $point = new Point(json_decode($request->receiver_details, true)['latitude'], json_decode($request->receiver_details, true)['longitude']);
            $zone_id =  json_decode($request->receiver_details, true)['zone_id'];
            $zone = Zone::where('id', $zone_id)->whereContains('coordinates', new Point(json_decode($request->receiver_details, true)['latitude'], json_decode($request->receiver_details, true)['longitude'], POINT_SRID))->first();
            if (!$zone) {
                $errors = [];
                array_push($errors, ['code' => 'receiver_details', 'message' => translate('messages.out_of_coverage')]);
                return response()->json([
                    'errors' => $errors
                ]);
            }
            $order->delivery_charge = round($original_delivery_charge, config('round_up_to_digit')) ?? 0;
            $order->original_delivery_charge = round($original_delivery_charge, config('round_up_to_digit'));


            $order->order_amount = round($order->delivery_charge);
        }
        $order->flash_admin_discount_amount = round($flash_sale_admin_discount_amount, config('round_up_to_digit'));
        $order->flash_store_discount_amount = round($flash_sale_vendor_discount_amount, config('round_up_to_digit'));
        //DM TIPs

        $order->order_amount = $order->order_amount + $order->dm_tips + $order->additional_charge;

        $order->rounded_off = ($order->order_amount) - floor($order->order_amount);

        if ($request->payment_method == 'wallet' && $user->wallet_balance < $order->order_amount) {
            return response()->json([
                'errors' => [
                    ['code' => 'order_amount', 'message' => translate('messages.insufficient_balance')]
                ]
            ]);
        }
        if ($request->partial_payment && $user->wallet_balance > $order->order_amount) {
            return response()->json([
                'errors' => [
                    ['code' => 'partial_payment', 'message' => translate('messages.order_amount_must_be_greater_than_wallet_amount')]
                ]
            ]);
        }
        if (isset($module_wise_delivery_charge) && $request->payment_method == 'cash_on_delivery' && $module_wise_delivery_charge->pivot->maximum_cod_order_amount && $order->order_amount > $module_wise_delivery_charge->pivot->maximum_cod_order_amount) {
            return response()->json([
                'errors' => [
                    ['code' => 'order_amount', 'message' => translate('messages.amount_crossed_maximum_cod_order_amount')]
                ]
            ]);
        }

        try {
            DB::beginTransaction();

            $order->save();
            if ($request->order_type !== 'parcel') {
                foreach ($order_details as $key => $item) {
                    $order_details[$key]['order_id'] = $order->id;

                    if ($store_discount_amount <= 0) {
                        $order_details[$key]['discount_on_item'] = 0;
                    }
                }
                OrderDetail::insert($order_details);
                if (count($product_data) > 0) {
                    foreach ($product_data as $item) {
                        ProductLogic::update_stock($item['item'], $item['quantity'], $item['variant'])->save();
                        ProductLogic::update_flash_stock($item['item'], $item['quantity'])?->save();
                    }
                }
                $store->increment('total_order');
            }
            if (!isset($request->is_buy_now) || (isset($request->is_buy_now) && $request->is_buy_now == 0)) {
                foreach ($carts as $cart) {
                    // $cart->delete();
                }
            }

            if ($user) {
                $customer = $user;
                $customer->zone_id = $order->zone_id;
                $customer->save();

                if ($request->payment_method == 'wallet') CustomerLogic::create_wallet_transaction($order->user_id, $order->order_amount, 'order_place', $order->id);

                if ($request->partial_payment) {
                    if ($user->wallet_balance <= 0) {
                        return response()->json([
                            'errors' => [
                                ['code' => 'order_amount', 'message' => translate('messages.insufficient_balance_for_partial_amount')]
                            ]
                        ], 203);
                    }
                    $p_amount = min($user->wallet_balance, $order->order_amount);
                    $unpaid_amount = $order->order_amount - $p_amount;
                    $order->partially_paid_amount = $p_amount;

                    $order->save();
                    CustomerLogic::create_wallet_transaction($order->user_id, $p_amount, 'partial_payment', $order->id);
                    OrderLogic::create_order_payment(order_id: $order->id, amount: $p_amount, payment_status: 'paid', payment_method: 'wallet');
                    OrderLogic::create_order_payment(order_id: $order->id, amount: $unpaid_amount, payment_status: 'unpaid', payment_method: $request->payment_method);
                }
            }

            DB::commit();


            $payments = $order->payments()->where('payment_method', 'cash_on_delivery')->exists();
            $order_mail_status = Helpers::get_mail_status('place_order_mail_status_user');
            $order_verification_mail_status = Helpers::get_mail_status('order_verification_mail_status_user');

            //PlaceOrderMail
            try {
                if (0 && !in_array($order->payment_method, ['digital_payment', 'partial_payment', 'offline_payment'])  || $payments) {
                    Helpers::send_order_notification($order);

                    if ($order->order_status == 'pending' && config('mail.status') && $order_mail_status == '1' && $user) {

                        Mail::to($user->email)->send(new PlaceOrder($order->id));
                    }
                    if ($order->order_status == 'pending' && config('order_delivery_verification') == 1 && $order_verification_mail_status == '1' && $user) {
                        Mail::to($user->email)->send(new OrderVerificationMail($order->otp, $user->f_name));
                    }
                    if ($order->is_guest == 1 && $order->order_status == 'pending' && config('mail.status') && $order_mail_status == '1' && isset($request->contact_person_email)) {
                        Mail::to($request->contact_person_email)->send(new PlaceOrder($order->id));
                    }
                    if ($order->is_guest == 1 && $order->order_status == 'pending' && config('order_delivery_verification') == 1 && $order_verification_mail_status == '1' && isset($request->contact_person_email)) {
                        Mail::to($request->contact_person_email)->send(new OrderVerificationMail($order->otp, $request->contact_person_name));
                    }
                }
            } catch (\Exception $ex) {
                // info($ex->getMessage());
            }

            // place order sms, email and in app notification to vendor  =================== 
            $title = "Received New Order";
            $msg = "Good news! You've got a new order. Let's get it ready!";
            $acceptnce_id = '';
            $to = $store->id;
            $url = route('vendor.order.list', ['pending']);
            $user_typ = 'vendor';

            _inAppNotification($title, $msg, $acceptnce_id, $to, $url, $user_typ);
            // _sendMailToVendor($title, $msg, $to, $url); 
            $smsTemplate = "Hello! Your order NO " . $order->id . " is received. Please review the details on My Chitti Vendor Dashboard and confirm accuracy.";
            _sendSMS($store->phone, $smsTemplate);
            _sendOrderSMSToAdmins($order, $user, $store);

            // SendOrderNotifications::dispatch( 
            //     $title, 
            //     $msg,
            //     $acceptnce_id, 
            //     $to,
            //     $url,
            //     $user_typ,
            //     $order->id,
            //     $store->phone
            // );


            // place order sms, email and in app notification to vendor ===================
            return response()->json([
                'message' => translate('messages.order_placed_successfully'),
                'order_id' => $order->id,
                'payment_method' => $request->payment_method,
                'total_ammount' => $order->order_amount,
                'status' => $order->order_status,
                'created_at' => $order->created_at,
                'url' => $request->payment_method == 'digital_payment'  ? "payment-mobile?customer_id=" . $user_id . "&order_id=" . $order->id . "&payment_platform=web&payment_method=razor_pay&callback=/success" : ''
            ], 200);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([$e], 403);
        }
        return response()->json([
            'errors' => [
                ['code' => 'order_time', 'message' => translate('messages.failed_to_place_order')]
            ]
        ]);
    }

    public function change_variation(Request $request)
    {
        $vrType = $request->type;
        $prId = $request->id;

        $item = DB::table('items')->where('id', $prId)->first();
        $variations = json_decode($item->variations);
        $selectedVr = [];

        foreach ($variations as $key => $value) {
            if ($value->type == $vrType) {
                $selectedVr = $value;
                $selectedVr->discounted_price =  $selectedVr->price;
                $vrDetails = ItemVariationDetail::find($selectedVr->variations_table_id);
                $selectedVr->variation_details = $vrDetails;
            }
        }
        return response()->json(['status' => true, 'data' => $selectedVr]);
    }
    public function order_success(Request $request, $order_id = null)
    {
        $order_id = $order_id;
        return view('front-views.order-success', compact('order_id'));
    }
    public function store_gallery(Request $request, $slug = null)
    {
        // If the store is already resolved via custom domain middleware, use that context
        $store = $request->attributes->get('store_domain_store');
        if ($store) {
            $store->load('galleries');
        } else {
            // Resolve from the route param explicitly (not $request->slug, which can be shadowed
            // by input) and bypass global scopes — the slug is unique, and on a custom domain
            // there's no zone/session context to scope by.
            $slug = $slug ?: $request->route('slug');
            $store = Store::withoutGlobalScopes()->with('galleries')->where('slug', $slug)->first();
        }
        if (!$store) {
            abort(404); 
        }
        return view('front-views.store_gallery', compact('store'));
    }
    public function trackBannerClick(Request $request)
    {
        $bannerId = $request->banner_id;
        $banner = DB::table('banners')->where('id', $bannerId)->first();
        if (!$banner) {
            return response()->json(['message' => 'Banner not found'], 404);
        }

        $ip = $request->ip();
        $isUnique = !DB::table('analytics_logs')
            ->where('screen_type', 'banner')
            ->where('ref_id', $bannerId)
            ->where('ip', $ip)
            ->whereDate('created_at', now()->toDateString())
            ->exists();

        DB::table('banners')->where('id', $bannerId)->increment('total_clicks');
        if ($isUnique) {
            DB::table('banners')->where('id', $bannerId)->increment('unique_clicks');
        }

        DB::table('analytics_logs')->insert([
            'screen_type' => 'banner',
            'sub_type' => 'web',
            'ref_id' => $bannerId,
            'user_id' => auth()->check() ? auth()->id() : null,
            'ip' => $ip,
            'created_at' => now(),
        ]);

        return response()->json(['message' => 'Banner click counted']);
    }

    public function trackAdClick(Request $request)
    {
        $adId = $request->ad_id;
        $ad = DB::table('notifications')->where('id', $adId)->whereNotNull('vendor_id')->first();
        if (!$ad) {
            return response()->json(['message' => 'Ad not found'], 404);
        }

        $ip = $request->ip();

        DB::table('notifications')->where('id', $adId)->increment('total_clicks');

        try {
            $isUnique = !DB::table('analytics_logs')
                ->where('screen_type', 'ad')
                ->where('ref_id', $adId)
                ->where('ip', $ip)
                ->whereDate('created_at', now()->toDateString())
                ->exists();

            if ($isUnique) {
                DB::table('notifications')->where('id', $adId)->increment('unique_clicks');
            }

            DB::table('analytics_logs')->insert([
                'screen_type' => 'ad',
                'sub_type'    => 'web',
                'ref_id'      => $adId,
                'user_id'     => auth()->check() ? auth()->id() : null,
                'ip'          => $ip,
                'created_at'  => now(),
            ]);
        } catch (\Exception $e) {
            // analytics_logs failure must not prevent the increment
        }

        return response()->json(['message' => 'Ad click counted']);
    }

    public function trackStoreContactClick(Request $request)
    {
        $storeId = $request->store_id;
        $action  = $request->action;

        // Platform analytics events (analytics_logs) — call reuses phone-call analytics,
        // copy is a web-only event, share = store share, whatsapp/enquiry come from the
        // store cards (product detail page, store page) and get their own Performance
        // Analytics stat.
        $screenType = match ($action) {
            'call'     => 'call',
            'copy'     => 'copy',
            'share'    => 'share',
            'whatsapp' => 'whatsapp',
            'enquiry'  => 'enquiry',
            default    => null,
        };

        // Inbound-lead actions (Phase 3 §3.3) — also recorded to lead_signals for the MC Vendor Hub
        // Lead Inbox. 'copy'/'share' are analytics-only; everything here is a real lead intent.
        // lead_signals.type is an ENUM, so 'enquiry' rides on the existing 'booking' member.
        $leadType  = $action === 'enquiry' ? 'booking' : $action;
        $leadTypes = ['call', 'whatsapp', 'booking', 'quote', 'direction', 'website'];
        $isLead = in_array($leadType, $leadTypes, true);

        if (!$screenType && !$isLead) {
            return response()->json(['message' => 'Invalid action'], 422);
        }

        $store = DB::table('stores')->where('id', $storeId)->first();
        if (!$store) {
            return response()->json(['message' => 'Store not found'], 404);
        }

        $ip = $request->ip();

        // 1) Platform analytics — identical to before (only for call/copy/share).
        if ($screenType) {
            // sub_type: for 'share' it holds the share target ('store'); otherwise the source platform ('web').
            $subType = $action === 'share' ? 'store' : 'web';
            try {
                DB::table('analytics_logs')->insert([
                    'screen_type' => $screenType,
                    'sub_type'    => $subType,
                    'ref_id'      => $storeId,
                    'user_id'     => auth()->check() ? auth()->id() : null,
                    'ip'          => $ip,
                    'created_at'  => now(),
                ]);
            } catch (\Exception $e) {
                // analytics failure must not break the click
            }
        }

        // 2) Lead Inbox signal — full funnel (call/whatsapp/booking/quote/direction/website).
        if ($isLead) {
            try {
                DB::table('lead_signals')->insert([
                    'store_id'     => $storeId,
                    'user_id'      => auth()->check() ? auth()->id() : null,
                    'type'         => $leadType,
                    'source'       => $request->input('source', 'web'),
                    'utm_source'   => $request->input('utm_source'),
                    'utm_medium'   => $request->input('utm_medium'),
                    'utm_campaign' => $request->input('utm_campaign'),
                    'meta'         => json_encode(['ip' => $ip, 'ua' => substr((string) $request->userAgent(), 0, 255)]),
                    'created_at'   => now(),
                    'updated_at'   => now(),
                ]);
            } catch (\Exception $e) {
                // lead capture failure must not break the click
            }
        }

        return response()->json(['message' => 'ok']);
    }

    private function adsBaseQuery()
    {
        $zone_ids = json_decode($this->zone_id, true);
        return \App\Models\Notification::whereNotNull('vendor_id')
            ->where('approval', 1)
            ->where('status', 1)
            ->whereNotNull('image')
            ->where(function ($q) {
                $q->whereNull('days')
                  ->orWhereNull('approved_at')
                  ->orWhereRaw('DATE_ADD(approved_at, INTERVAL days DAY) >= NOW()');
            })
            ->where(function ($q) use ($zone_ids) {
                $q->whereIn('zone_id', $zone_ids)
                    ->orWhereNull('zone_id')
                    ->orWhere('zone_id', 0);
            })
            ->latest();
    }
 
    public function allAds()
    {
        $ads = $this->adsBaseQuery()->paginate(18);
        return view('front-views.ads.index', compact('ads'));
    }

    public function loadAds(Request $request)
    {
        $ads = $this->adsBaseQuery()->paginate(12);
        $html = view('front-views.ads._ad_cards', compact('ads'))->render();
        return response()->json([
            'html'     => $html,
            'has_more' => $ads->hasMorePages(),
        ]);
    }

    public function adDetail($id)
    {
        $ad = \App\Models\Notification::whereNotNull('vendor_id')
            ->where('approval', 1)
            ->where('status', 1)
            ->findOrFail($id);

        try {
            $ip = request()->ip();
            $isUnique = !DB::table('analytics_logs')
                ->where('screen_type', 'ad')
                ->where('ref_id', $id)
                ->where('ip', $ip)
                ->whereDate('created_at', now()->toDateString())
                ->exists();

            DB::table('notifications')->where('id', $id)->increment('total_clicks');
            if ($isUnique) {
                DB::table('notifications')->where('id', $id)->increment('unique_clicks');
            }
            DB::table('analytics_logs')->insert([
                'screen_type' => 'ad',
                'sub_type'    => 'web',
                'ref_id'      => $id,
                'user_id'     => auth()->check() ? auth()->id() : null,
                'ip'          => $ip,
                'created_at'  => now(),
            ]);
        } catch (\Exception $e) {
            // analytics failure must not break the page
        }

        $store = $ad->vendor_id ? DB::table('stores')->where('id', $ad->vendor_id)->first() : null;
        return view('front-views.ads.detail', compact('ad', 'store'));
    }

    public function store_details(Request $request, $city, $slug)
    {
        $check_module = DB::table('stores')->where('slug', $slug)->first();
        if ($check_module) {
            $module = $check_module->module_id;
        } else {
            abort(404);
        }

        // One canonical city per store (falls back to the platform default for zone-less stores).
        $canonicalCity = 'tirupati';
        if ($check_module->zone_id) {
            $zone = DB::table('zones')->where('id', $check_module->zone_id)->value('name');
            if ($zone) {
                $canonicalCity = _zoneCitySlug($zone);
            }
        }
        // 301 any other city to the single canonical URL — kills duplicate / soft-404 pages.
        if ($city !== $canonicalCity) {
            return redirect()->to(url($canonicalCity . '/store/' . $slug), 301);
        }
        // True canonical for the store page (overrides the layout's self-referencing default).
        view()->share('canonical', url($canonicalCity . '/store/' . $slug));
        $invItemdata = [];
        $longitude = $this->longitude;
        $latitude = $this->latitude;
        $store = Store::with(['discount' => function ($q) {
            return $q->validate();
        }, 'campaigns', 'schedules', 'activeCoupons'])
            ->withCount(['items', 'campaigns'])
            ->when($module, function ($query) use ($module) {
                $query->module($module);
            })
            ->where('slug', $slug)
            ->first();


        if ($store) {
            // Thin-content guard: keep genuinely empty store shells (no items, no campaigns,
            // no specialised business type) out of the index so they aren't flagged soft-404.
            view()->share('metaRobots',
                ($store->items_count == 0 && $store->campaigns_count == 0 && empty($store->business_type)) ? 'noindex, follow' : null);
 
            // LocalBusiness JSON-LD (P0) — emitted in the layout head for every store template.
            view()->share('localBusinessStore', $store);

            // Increment store visit analytics
            $ip = $request->ip();
            $isUnique = !DB::table('analytics_logs')
                ->where('screen_type', 'store')
                ->where('ref_id', $store->id)
                ->where('ip', $ip)
                ->whereDate('created_at', now()->toDateString())
                ->exists();

            DB::table('stores')->where('id', $store->id)->increment('total_visits');
            if ($isUnique) {
                DB::table('stores')->where('id', $store->id)->increment('unique_visits');
            }

            DB::table('analytics_logs')->insert([
                'screen_type' => 'store',
                'sub_type' => 'web',
                'ref_id' => $store->id,
                'user_id' => auth()->check() ? auth()->id() : null,
                'ip' => $ip,
                'created_at' => now(),
            ]);

            if ($module == 5) {

                $keywordsData = DB::table('items')
                    ->where('items.is_approved', 1)
                    ->join('categories', 'items.category_id', '=', 'categories.id')
                    ->where('items.store_id', $store->id)
                    ->select('items.name as item_name', 'categories.name as category_name')
                    ->distinct()
                    ->get();

                $keywords = implode(',', $keywordsData->pluck('item_name')->merge($keywordsData->pluck('category_name'))->toArray());

                $category_ids = DB::table('items')
                    ->join('categories', 'items.category_id', '=', 'categories.id')
                    ->selectRaw('categories.position as positions, IF((categories.position = "0"), categories.id, categories.parent_id) as categories')
                    ->where('items.store_id', $store->id)
                    ->where('categories.status', 1)
                    ->groupBy('categories', 'positions')
                    ->get();

                $store = Helpers::store_data_formatting($store);
                $store['category_ids'] = array_map('intval', $category_ids->pluck('categories')->toArray());
                $store['category_details'] = Category::whereIn('id', $store['category_ids'])->get();
                $store['price_range']  = Item::withoutGlobalScopes()->where('store_id', $store->id)
                    ->select(DB::raw('MIN(price) AS min_price, MAX(price) AS max_price'))
                    ->get(['min_price', 'max_price']);

                $productdata = DB::table('items')
                    ->join('categories', 'items.category_id', 'categories.id')
                    ->where('items.store_id', $store->id)
                    ->where('items.status', 1)
                    ->where('items.is_approved', 1)
                    ->select('categories.id', 'categories.name', 'categories.slug as cat_slug')
                    ->distinct()
                    ->get()
                    ->toArray();

                foreach ($productdata as $key => $cat) {
                    $cat->items = DB::table('items')
                        ->where('store_id', $store->id)
                        ->where('category_id', $cat->id)
                        ->where('status', 1)
                        ->where('is_approved', 1)
                        ->get();
                }
            } else {
                $keywordsData = DB::table('items')
                    ->where('items.is_approved', 1)
                    ->join('categories', 'items.category_id', '=', 'categories.id')
                    ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                    ->select('items.name as item_name', 'categories.name as category_name')
                    ->distinct()
                    ->get();

                $keywords = implode(',', $keywordsData->pluck('item_name')->merge($keywordsData->pluck('category_name'))->toArray());
                // echo '
';
                // SERVICES
                $productdata1 = DB::table('items')
                    ->join('categories', 'items.category_id', 'categories.id')
                    ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                    ->whereNull('items.inventory_item_id')
                    ->where('categories.status', 1)
                    ->select('categories.id', 'categories.name', 'categories.slug as cat_slug')
                    ->distinct()
                    ->get();


                foreach ($productdata1 as $cat) {
                    $cat->items = DB::table('items')
                        ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                        ->whereNull('items.inventory_item_id')
                        ->where('category_id', $cat->id)
                        ->where('status', 1)
                        ->get();
                }

                //INVENTORY ITEMS
                $invItemdata = DB::table('items')
                    ->join('categories', 'items.category_id', 'categories.id')
                    ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                    ->whereNotNull('items.inventory_item_id')
                    ->select('categories.id', 'categories.name', 'categories.slug as cat_slug')
                    ->distinct()
                    ->get();

                foreach ($invItemdata as $cat) {
                    $cat->items = DB::table('items')
                        ->whereIn('items.id', \App\CentralLogics\Helpers::store_items_sub($store->id))
                        ->whereNotNull('items.inventory_item_id')
                        ->where



    
    

    
    
    
    

    Target class [App\Http\Controllers\Front\FrontController] does not exist.