Sh3ll
OdayForums


Server : Apache
System : Linux 145.162.205.92.host.secureserver.net 5.14.0-611.45.1.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Apr 1 05:56:53 EDT 2026 x86_64
User : tradze ( 1001)
PHP Version : 8.1.34
Disable Function : NONE
Directory :  /home/tradze/www/app/Modules/Users/Http/Controllers/Api/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/tradze/www/app/Modules/Users/Http/Controllers/Api/ApiBasketNowController.php
<?php
namespace App\Modules\Users\Http\Controllers\Api;

use App\Events\ApiOverdueBasketEvent;
use App\Events\CheckExtensionBasketEvent;
use App\Http\Controllers\ApiController;
use App\Modules\Banners\Repositories\BannersRepo;
use App\Modules\Invoices\Repositories\BookingInvoiceRepository;
use App\Modules\Notifications\Facades\NotifRepository;
use App\Modules\Postcodes\Models\TransportCost;
use App\Modules\Schedules\Models\BasketTherapist;
use App\Modules\Schedules\Models\BasketVoucher;
use App\Modules\Schedules\Models\BookingOrder;
use App\Modules\Schedules\Models\Order;
use App\Modules\Schedules\Repositories\BookingRepository;
use App\Modules\Services\Models\FocalPoint;
use App\Modules\Services\Models\ServiceDuration;
use App\Modules\Services\Models\ServiceType;
use App\Modules\Postcodes\Models\Postcode;
use App\Modules\Vouchers\Repositories\VoucherRepository;
use App\User;
use Carbon\Carbon;

use Darryldecode\Cart\Cart;
use Darryldecode\Cart\CartCondition;
use Illuminate\Console\Scheduling\Event;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Mail;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\Request;
use Laracasts\Flash\Flash;
use Mockery\CountValidator\Exception;

class ApiBasketNowController extends ApiController
{
    /**
     * The book repository instance
     *
     * @var BookingRepository
     */
    protected $book;
    protected $ttl;
    protected $order_table_hours_limit;

    /**
     * Create a new controller instance.
     */
    public function __construct(BannersRepo $banners, BookingRepository $book)
    {
        parent::__construct($banners);
        $this->book = $book;

        //time to live item basket: in minutes
        $this->ttl = 5;

        //user can order table only his booking will be over x hours. for more flexibility and accuracy, the value is in seconds
        $this->order_table_hours_limit = 86400;
    }

    /**
     * Add items in basket
     * @param int $checkout
     * @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response
     */
    public function add(Request $request, $checkout=0)
    {
        //first clear basket session tables for overdue items
        \Event::fire(new ApiOverdueBasketEvent());

        //get booking data from session
        $booking = Session::get('booking');

        $booking['postcode'] = $request->postcode;
        $booking['address'] = $request->address;
        $booking['date'] = $request->date;
        $booking['hour'] = $request->hour;
        $booking['massage'] = $request->massage;
        $booking['duration'] = $request->duration;
        $booking['therapists_opt'] = $request->therapists_opt;
        $booking['selected_therapists'] = $request->selected_therapists;

        \Cart::clear();

        BasketVoucher::where('session_id',request()->session()->getId())->delete();
        BasketTherapist::where('session_id',request()->session()->getId())->delete();

        $therapists=1;
        $type='1 therapist';
        switch ($request->therapists_opt){
            case '1_th':
                $therapists=1;
                $type='1 therapist';
                break;
            case '2_th':
                $therapists=2;
                $type='2 therapists';
                break;
            case '4hands':
                $therapists=2;
                $type='four hands massage';
                break;
        } //end switch

        $booking['therapists_opt'] = $request->therapists_opt;
        $booking['therapists'] = $therapists;
        $booking['type'] = $type;

        unset($booking['selected_therapists']);

        if (count($request->selected_therapists)){
          foreach($request->selected_therapists as $th){
            if (is_array($th))
              $booking['selected_therapists'][] = $th['id'];
            else
              $booking['selected_therapists'][] = $th;
          } //endoreach
        }
//        $booking['selected_therapists'] = $request->selected_therapists;

        Session::put('booking',$booking);

        $mandatory_fields = ['postcode','duration','massage','date', 'hour', 'selected_therapists'];
        foreach($mandatory_fields as $field){
            if (!isset($booking[$field])){
              return response([$booking,$field],200);
              //return booking data
              return response([
                  'success'=>false,
                  'message'=>'You must select the postcode, massage duration, type of massage, date of massage, desired hour and the therapist',
                  'booking'=>$booking,
              ],200);
            }
        } //endforeach

//        //testing
//        return response([
//            'success'=>false,
//            'message'=>'sunt aici',
//            'items'=>[],
//            'booking'=>$booking,
//        ],200);

        //add to basket
        switch ($booking['therapists_opt']){
            case '2_th':{
                $this->add_therapists($booking);
                break;
            }
            case '4hands':{
                $this->add_4hands($booking);
                break;
            }
            default:{
                $test = $this->add_single($booking);
                break;
            }
        } //end switch

        $items = \Cart::getContent();

        foreach($items as $item){
          $data[] = [
            'id'=>$item->id,
            'price'=>$item->getPriceSum(),
            'total'=>$item->getPriceSumWithConditions(),
            'reserved_until'=>$item->attributes['reserved_until'],
            'can_order_table'=>$item->attributes['can_order_table'],
            'has_table'=>$item->attributes['has_table'],
            'table_price' => env('TABLE_VALUE',9.99),
            'disclaimer' => (!$item->attributes['can_order_table'])?'can be delivered only over 24h notice!':'',
            'has_transport' => $item->attributes['has_transport'],
            'transport_cost' => $item->attributes['transport_cost'],
          ];
        } //endforeach

        //return booking session data
        return response([
            'success'=>true,
            'message'=>null,
            'items'=>$data,
            'total'=>\Cart::getTotal(),
            'session'=> $request->session()->getId(),
        ],200);
    }

    /**
     * Add item in basket for single massage option
     * @param $booking
     */
    protected function add_single($booking)
    {

        $therapists = $this->book->selected_therapists();
        // $therapists = User::whereIn('id',$booking['selected_therapists'])->get();
        $duration = ServiceDuration::where('id',$booking['duration'])->first();
        $massage_type = ServiceType::where('id',$booking['massage'])->first();
        $client = User::find($this->user->id);

        $quantity = $booking['therapists'];
        $price =  $duration->price;

        foreach($therapists as $addth){
            $names[] = $addth->name;
            $images[] = $addth->avatar_url;
            $thIds[] = $addth->id;
            break;
        } //end foreach

        //get geo-location with google places
        $googlePlaces = $this->getGeoLocation($booking['postcode']);

        //get focal points
        $focal_points_string = $this->getFocalPoints($booking);

        foreach($therapists as $therapist){

            $itemId = str_random(10);
            $item = [
                'id' => $itemId,
                'name' => $massage_type->name,
                'price' => $price,
                'quantity' => $quantity,
                'attributes' => array(
                    'reserved_until' => Carbon::now()->addMinutes($this->ttl)->format('Y-m-d H:i:s'),
                    'therapist' => $names,
                    'therapistIds' => $thIds,
                    'therapistImage' => $images,
                    'therapistsNo' => $booking['therapists'],
                    'therapistsOpt' => $booking['therapists_opt'],
                    'type' => $booking['type'],
                    'date' => Carbon::createFromFormat('Y-m-d',$booking['date'])->format('d M Y'),
                    'hour'=>$booking['hour'],
                    'duration' => $duration->name,
                    'duration_min' => $duration->duration,
                    'duration_id' => $duration->id,
                    'duration_commision' => [
                        'company' => $duration->commision_co,
                        'therapist' => $duration->commision_th,
                    ],
                    'massage_type' => $massage_type->name,
                    'massage_type_id' => $massage_type->id,
                    'focal_points' => $focal_points_string,
                    'can_order_table' => $this->can_order_table($booking),
                    'disclaimer' => $this->disclaimer_info($booking),
                    'has_table' => false,
                    'has_transport' => false,
                    'transport_cost' => 0,
                    'has_voucher' => false,
                    'user_name' => $client->name?$client->name:'',
                    'user_phone' => $client->profile->mobile_number?$client->profile->mobile_number:'',
                    'address' => $booking['address'],
                    'postcode' => $booking['postcode'],
                    'county' => 'London',
                    'location' => $googlePlaces['formatted_address'],
                    'locationGeo' => $googlePlaces['geometry']['location'],
                    'notes' => '',
                ),
            ];

            \Cart::add($item);
            $this->calc_transport_condition($booking,$itemId);

            //add to session basket
            $sesBasket = [
                'basket_item_id' => $itemId,
                'session_id' => request()->session()->getId(),
                'user_id' => $client->id,
                'therapist_id' => $therapist->id,
                'reserved_until' => $item['attributes']['reserved_until'],
                'date' => Carbon::createFromFormat('Y-m-d',$booking['date'])->format('Y-m-d'),
                'hour' => $item['attributes']['hour'],
                'duration' => $item['attributes']['duration'],
                'duration_min' => $item['attributes']['duration_min'],
                'duration_id' => $item['attributes']['duration_id'],
            ];

            BasketTherapist::create($sesBasket);
        } //endforeach

        //unset session booking
//        Session::forget('booking');
    }

    /**
     * Add items in basket for 2 therapists massage option
     * @param $booking
     */
    protected function add_therapists($booking)
    {
        return $booking;
        $therapists = $this->book->selected_therapists();
        $duration = ServiceDuration::where('id',$booking['duration'])->first();
        $massage_type = ServiceType::where('id',$booking['massage'])->first();

        $quantity = 1;
        $price =  $duration->price;

       foreach($therapists as $addth){
           $names[] = $addth->name;
           $images[] = $addth->avatar_url;
           $thIds[] = $addth->id;
       } //end foreach

        //get geo-location with google places
        $googlePlaces = $this->getGeoLocation($booking['postcode']);

        //get focal points
        $focal_points_string = $this->getFocalPoints($booking);

        foreach($therapists as $therapist){
            $itemId = str_random(10);

            $item = [
                'id' => $itemId,
                'name' => $massage_type->name,
                'price' => $price,
                'quantity' => $quantity,
                'attributes' => array(
                    'reserved_until' => Carbon::now()->addMinutes($this->ttl)->format('Y-m-d H:i:s'),
                    'therapist' => [$therapist->name],
                    'therapistIds' => [$therapist->id],
                    'therapistImage' => [$therapist->avatar_url],
                    'therapistsNo' => $booking['therapists'],
                    'therapistsOpt' => $booking['therapists_opt'],
                    'type' => $booking['type'],
                    'date' => Carbon::createFromFormat('Y-m-d',$booking['date'])->format('d M Y'),
                    'hour'=>$booking['hour'],
                    'duration' => $duration->name,
                    'duration_min' => $duration->duration,
                    'duration_id' => $duration->id,
                    'duration_commision' => [
                        'company' => $duration->commision_co,
                        'therapist' => $duration->commision_th,
                    ],
                    'massage_type' => $massage_type->name,
                    'massage_type_id' => $massage_type->id,
                    'focal_points' => $focal_points_string,
                    'has_table' => false,
                    'can_order_table' => $this->can_order_table($booking),
                    'disclaimer' => $this->disclaimer_info($booking),
                    'has_transport' => false,
                    'transport_cost' => 0,
                    'has_voucher' => false,
                    'user_name' => \Auth::check()?\Auth::user()->name:'',
                    'user_phone' => \Auth::check()?\Auth::user()->profile->mobile_number:'',
                    'address' => $booking['address'],
                    'postcode' => $booking['postcode'],
                    'county' => 'London',
                    'location' => $booking['address'],
                    'locationGeo' => $googlePlaces['geometry']['location'],
                    'notes' => '',
                ),
            ];
            \Cart::add($item);
            $this->calc_transport_condition($booking,$itemId);

            //add to session basket
            $sesBasket = [
                'basket_item_id' => $itemId,
                'session_id' => request()->session()->getId(),
                'user_id' => \Auth::check()?\Auth::user()->id:'',
                'therapist_id' => $therapist->id,
                'reserved_until' => $item['attributes']['reserved_until'],
                'date' => Carbon::createFromFormat('Y-m-d',$booking['date'])->format('Y-m-d'),
                'hour' => $item['attributes']['hour'],
                'duration' => $item['attributes']['duration'],
                'duration_min' => $item['attributes']['duration_min'],
                'duration_id' => $item['attributes']['duration_id'],
            ];
            BasketTherapist::create($sesBasket);

        } //endforeach

        //unset session booking
        Session::forget('booking');

    }

    /**
     * Add item in baset for the 4hands massage option
     * @param $booking
     */
    protected function add_4hands($booking)
    {

        $therapists = $this->book->selected_therapists();
        $duration = ServiceDuration::where('id',$booking['duration'])->first();
        $massage_type = ServiceType::where('id',$booking['massage'])->first();

        $quantity=1;
        $price =  $duration->price*2;

        foreach($therapists as $addth){
            $names[] = $addth->name;
            $images[] = $addth->avatar_url;
            $thIds[] = $addth->id;
        } //end foreach

        //get geo-location with google places
        $googlePlaces = $this->getGeoLocation($booking['postcode']);

        //get focal points
        $focal_points_string = $this->getFocalPoints($booking);

        $itemId = str_random(10);
        $item = [
            'id' => $itemId,
            'name' => $massage_type->name,
            'price' => $price,
            'quantity' => $quantity,
            'attributes' => array(
                'reserved_until' => Carbon::now()->addMinutes($this->ttl)->format('Y-m-d H:i:s'),
                'therapist' => $names,
                'therapistIds' => $thIds,
                'therapistImage' => $images,
                'therapistsNo' => $booking['therapists'],
                'therapistsOpt' => $booking['therapists_opt'],
                'type' => $booking['type'],
                'date' => Carbon::createFromFormat('Y-m-d',$booking['date'])->format('d M Y'),
                'hour'=>$booking['hour'],
                'duration' => $duration->name,
                'duration_min' => $duration->duration,
                'duration_id' => $duration->id,
                'duration_commision' => [
                    'company' => $duration->commision_co,
                    'therapist' => $duration->commision_th,
                ],
                'massage_type' => $massage_type->name,
                'massage_type_id' => $massage_type->id,
                'focal_points' => $focal_points_string,
                'can_order_table' => $this->can_order_table($booking),
                'disclaimer' => $this->disclaimer_info($booking),
                'has_table' => false,
                'has_transport' => false,
                'transport_cost' => 0,
                'has_voucher' => false,
                'user_name' => \Auth::check()?\Auth::user()->name:'',
                'user_phone' => \Auth::check()?\Auth::user()->profile->mobile_number:'',
                'address' => $booking['address'],
                'postcode' => $booking['postcode'],
                'county' => 'London',
                'location' => $booking['address'],
                'locationGeo' => $googlePlaces['geometry']['location'],
                'notes' => '',
            ),
        ];
        \Cart::add($item);
        $this->calc_transport_condition($booking,$itemId);

        //add to session basket
        foreach($therapists as $therapist){
            $sesBasket = [
                'basket_item_id' => $itemId,
                'session_id' => request()->session()->getId(),
                'user_id' => \Auth::check()?\Auth::user()->id:'',
                'therapist_id' => $therapist->id,
                'reserved_until' => $item['attributes']['reserved_until'],
                'date' => Carbon::createFromFormat('Y-m-d',$booking['date'])->format('Y-m-d'),
                'hour' => $item['attributes']['hour'],
                'duration' => $item['attributes']['duration'],
                'duration_min' => $item['attributes']['duration_min'],
                'duration_id' => $item['attributes']['duration_id'],
            ];
            BasketTherapist::create($sesBasket);
        } //end foreach



        //unset session booking
        Session::forget('booking');
    }

    /**
     * Add item in basket for single massage option
     * @param $booking
     */
    public function extend_booking_check(BookingOrder $booking, ServiceDuration $extension)
    {

        //set default response message
        $response = ['message'=>trans('schedules::booking.message_error_extension_overlap')];

        //validate the booking and the extension
        $client = User::find($booking->user_id);

        //the booking must be owned by
        if (!$booking || !$extension){
            $response['message']  = trans('schedules::booking.message_error_extension_access_denied');
            return response($response,403);
        } //endif

        //check extension availability
        $can_extend = $this->book->can_extend_with($booking,$extension);

        //if cant extend, return response
        if (!$can_extend)
            return response($response,403);

        //create extension ttl
        $ttl_min = 1;
        $reservedDateLimit = Carbon::now()->addMinutes($ttl_min);

        //add to session
        $extensionProduct = [
            'id' => 'extension_'.$booking->id,
            'name' => $extension->name,
            'price'=>$extension->price,
            'quantity'=>1,
            'attributes' => [
                'booking_id' => $booking->id,
                'booking_obj' => $booking,
                'duration' => $extension->name,
                'duration_min' => $extension->duration,
                'duration_id' => $extension->id,
                'duration_commision' => [
                    'commision_co' => $extension->commision_co,
                    'commision_th' => $extension->commision_th,
                ],
                'reserved_until' => $reservedDateLimit->format('Y-m-d H:i:s'),
            ]
        ];

        $cartID = 'extension_'.$booking->id;
        $cart = app('cart_extension');

        //delete from extension basket the therapists and extension service
        $sesExtBasket = BasketTherapist::where('session_id',request()->session()->getId())->delete();
        $cart->clear();

        //add extension service to cart
        $cart->add($extensionProduct);

        //add extension to the session_therapist_basket
        foreach($booking->therapists as $therapist){
            //add basket session table
            $sesBasket = [
                'basket_item_id' => $cartID,
                'session_id' => request()->session()->getId(),
                'user_id' => $client->id,
                'therapist_id' => $therapist->id,
                'reserved_until' => $reservedDateLimit->format('Y-m-d H:i:s'),
                'date' => $booking->date->format('Y-m-d'),
                'hour' => Carbon::createFromFormat('H:i',$booking->hour)->addMinutes($booking->duration_min)->format('H:i'),
                'duration' => $extension->name,
                'duration_min' => $extension->duration,
                'duration_id' => $extension->id,
            ];
            BasketTherapist::create($sesBasket);
        } //endforeach

        //return response
        return response(['message'=>'You can extend your booking. You have '.$ttl_min.' minutes to confirm your extension. Hurry up!'],200);
    }

    /**
     * Determine if user can order table. This method is used to compute item basket attribute names can_order_table
     * @param $booking
     * @return bool
     */
    protected function can_order_table($booking)
    {
        //default value is false
        $status = false;

        //transform booking hour and time in carbon date-time format
        $datehour = Carbon::createFromFormat('Y-m-d H:i',$booking['date']." ".$booking['hour']);

        //calculate difference with current time
        $diff = Carbon::now()->diffInSeconds($datehour,false);

        //set status value
        if ($diff < $this->order_table_hours_limit)
            $status=false;
        else
            $status=true;

        //return status
        return $status;
    }

    /**
     * Checkout disclaimer
     * @param $booking
     * @return null|string|\Symfony\Component\Translation\TranslatorInterface
     */
    protected function disclaimer_info($booking)
    {
        $status = null;
        if (!isset($booking['disclaimer']))
            return $status;

        switch($booking['disclaimer']){
            case 'now':
                $status = trans('schedules::booking.message_disclaimer_massagemenow');
                break;
        } //endswitch

        //return status disclaimer
        return $status;
    }

    /**
     * Get google location based on user postcode
     * @param $booking
     * @return mixed
     */
    protected function getGeoLocation($postcode)
    {
//        $response = \GoogleMaps::load('textsearch')
//            ->setParam([
//                'query' => "{$postcode} London UK",
//            ])->get('results'); // return $this

        $response = \GoogleMaps::load('geocoding')
            ->setParam (['address' => "{$postcode} London UK"])
            ->get('results');

        if ($response['results'])
            $geoLocation = $response['results'][0];
        else
            $geoLocation=null;

        //return geolocation
        return $geoLocation;
    }

    /**
     * Get focal points for basket booking
     * @param $booking
     * @return string
     */
    protected function getFocalPoints($booking)
    {
        if (!isset($booking['focal_points']))
            $booking['focal_points'] = [];

        $objfp = FocalPoint::select('name')->whereIn('id',$booking['focal_points'])->get();

        $focal_points=[];
        foreach($objfp as $fp)
            $focal_points[] = $fp->name;

        $response = implode(' / ',$focal_points);

        //return response
        return $response;
    }

    public function calc_transport_condition($booking,$productID)
    {

        //get item cart
        $item = \Cart::get($productID);

        //initialize default cost value
        $cost = 0;

        //get massage location district
        $postcode = Postcode::where('postcode',$item->attributes->postcode)->first();
        $postcode_district = $postcode->zone->district()->first();

        //get selected therapists
        $users = User::whereIn('id',$item->attributes->therapistIds)->get();

        //calculate transport cost for each selected therapist
        foreach($users as $user){
            $district = $user->profile->district;
            $transportCost = TransportCost::where('from_id',$district->id)
                ->where('to_id',$postcode_district->id)
                ->first();
            $cost += $transportCost->price;
        } //endforeach

        //return cost
        if (!$cost)
            return;

        $costValue = $cost;
        if ($item->quantity>1)
            $costValue = $costValue/2;

        //add voucher condition
        $travel_cond = new CartCondition(array(
            'name' => 'Travel supplements',
            'type' => 'cost',
            'target' => 'item',
            'value' => $costValue,
            'order'=>3,
        ));

        //add travel supplements condition to the item cart
        \Cart::addItemCondition($productID, $travel_cond);

        $attributes = $item->attributes;
        $attributes['has_transport'] = true;
        $attributes['transport_cost'] = $cost;

        \Cart::update($productID,array('attributes'=>$attributes));
    }

    /**
     * Update item id info
     * @param Request $request
     */
    public function update(Request $request)
    {
        //get input request
        $i = $request->all();

        //all fields must be set
        if (!$i['name'] || !$i['itemId'])
            return response(['message'=>"not allowed"],403);

        //allow only fields
        $allowed_names = ['user_name','user_phone','address','notes','county'];
        if (!in_array($i['name'],$allowed_names))
            return response(['message'=>"not allowed"],403);

        //get item cart and update value
        $item = \Cart::get($i['itemId']);
        $attributes = $item->attributes;
        $attributes[$i['name']] = $i['value'];
        \Cart::update($i['itemId'],array('attributes'=>$attributes));

        //return success
        return response(['success'=>true],200);
    }

    /**
     * Remove item from basket
     * @param Request $request
     */
    public function cancel(Request $request)
    {
        $productID = $request->itemId;

        //remove item from cart
        \Cart::remove($productID);

        //delete all basket from session tables
        $session_id = $request->session()->getId();

        $sesTh = BasketTherapist::where('session_id',$session_id)
                                ->where('basket_item_id',$productID)
                                ->get();
        if ($sesTh){
            foreach($sesTh as $sth)
                $sth->delete();
        } //endif

        $sesCodes = BasketVoucher::where('session_id',$session_id)
                                ->where('basket_item_id',$productID)
                                ->get();
        if ($sesCodes){
            foreach($sesCodes as $scode)
                $scode->delete();
        } //endif

        //return response
        return response('success',200);
    }

    /**
     * Clear basket
     * @param Request $request
     * @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response
     */
    public function cancel_all(Request $request)
    {

        //clear basket
        \Cart::clear();

        //delete all basket from session tables
        $session_id = $request->session()->getId();

        $sesTh = BasketTherapist::where('session_id',$session_id)->get();
        if ($sesTh){
            foreach($sesTh as $sth)
                $sth->delete();
        } //endif

        $sesCodes = BasketVoucher::where('session_id',$session_id)->get();
        if ($sesCodes){
            foreach($sesCodes as $scode)
                $scode->delete();
        } //endif

        //return response
        return response('success',200);
    }

    /**
     * Add table condition
     * @param Request $request
     */
    public function add_table(Request $request)
    {
        $productID = $request->cartId;
        $table_value = 9.99;

        return response([
            'success'=>false,
            'message'=> 'Unfortunately we do not deliver tables to your location at this time!',
            'data' => [],
        ],200);

        //check again if table can be added to the basket
        $check = \Cart::get($productID);

        //cannnot order table if the area is not covered
        $postCode = Postcode::where('postcode',$check->attributes->postcode)->first();
        $district = $postCode->zone->district()->first();
        $deliverInArea = (bool)$district->table_restriction->display;

        if (!$deliverInArea){
            return response([
              'success'=>false,
              'message'=> 'Unfortunately we do not deliver tables to your location at this time!',
              'data' => [],
            ],200);
        }

        //cannot order table only over 24h
        if (!$check->attributes->can_order_table){
            return response([
              'success'=>false,
              'message'=>'can be delivered only over 24h notice!',
              'data'=>[],
            ],200);
        } //endif

        if ($check->attributes->has_table){
          return response([
            'success'=>false,
            'message'=>'Table has been already added!',
            'data' => [
              'has_table'=>true,
              'total'=>$check->getPriceSumWithConditions(),
            ],
          ],200);
        }

        $additional_table = new CartCondition(array(
            'name' => 'Massage Table',
            'type' => 'addtable',
            'target' => 'item',
            'value' => $table_value,
            'order'=>2,
        ));

        //add table condition to the item cart
        \Cart::addItemCondition($productID, $additional_table);

        //get item and update attributes has table index
        $item = \Cart::get($productID);
        $attributes = $item->attributes;
        $attributes['has_table'] = true;
        $attributes['table_value'] = $table_value;
        \Cart::update($productID,array('attributes'=>$attributes));

        //return response
        $message = [
            'success'=>true,
            'message'=>null,
            'data'=>[
              'has_table'=>$attributes['has_table'],
              'total' => $item->getPriceSumWithConditions()
            ]
        ];

        //return response
        return response($message,200);
    }

    /**
     * Remove table condition
     * @param Request $request
     */
    public function remove_table(Request $request)
    {
        $productID = $request->cartId;

        //remove table condition from the item table
        \Cart::removeItemCondition($productID, $conditionName="Massage Table");

        //get item
        $item = \Cart::get($productID);
        $attributes = $item->attributes;
        $attributes['has_table'] = false;
        $attributes['table_value'] = 0;
        \Cart::update($productID,array('attributes'=>$attributes));


        //return response
        $message = [
            'success'=>true,
            'data'=>[
              'has_table'=>$attributes['has_table'],
              'total'=>$item->getPriceSumWithConditions(),
            ]
        ];

        //return response
        return response($message,200);
    }


    /**
     * Add table condition
     * @param Request $request
     */
    public function add_voucher(Request $request)
    {
//        return response([
//            'success'=>false,
//            'message'=>"Oops, something went wrong! Please try again.",
//            'data'=> \Cart::getContent(),
//            'session'=> $request->session()->getId(),
//        ],200);

        $productID = $request->cartId;

        //get item cart
        $item = \Cart::get($productID);

        if (!$item){
            return response([
                'success'=>false,
                'message'=>"Oops, something went wrong! Please try again.",
                'data'=>\Cart::getContent(),
            ],200);

        }


        $appliedCond = collect($item->conditions);

        //check if item has already voucher applied
        if ($item->attributes->has_voucher)
            return response([
              'success'=>false,
              'message'=>"You can add only one voucher or code!",
              'data'=>[],
            ],200);

        //get voucher code

        $checkVoucher = new VoucherRepository();

        $voucher = $checkVoucher->validate_voucher($request->value,$productID,$this->user);

        //if voucher is not valid, return response with message
        if (!$voucher['valid'])
            return response([
              'success'=>false,
              'message'=>$voucher['message'],
              'data'=>[],
            ],200);


        //compose condition amount/percent
        if ($voucher['voucher']->type=="value"){
            $condValue = -($voucher['voucher']->value > $item->getPriceSum()?$item->getPriceSum():$voucher['voucher']->value);
        }
        else
        {
            //the value is as percentage
            $condValue = -$voucher['voucher']->value."%";
        }

        //add voucher condition
        $additional_voucher = new CartCondition(array(
            'name' => 'Voucher',
            'type' => 'Voucher',
            'target' => 'item',
            'value' => $condValue,
            'order'=>0,
        ));

        //add table condition to the item cart
        \Cart::addItemCondition($productID, $additional_voucher);

        //get item and update attributes has table index
        $item = \Cart::get($productID);
        $attributes = $item->attributes;
        $attributes['has_voucher'] = true;
        $attributes['voucher'] = [
            'id'=>$voucher['voucher']->id,
            'name'=>$voucher['voucher']->name,
            'code'=>$voucher['voucher']->code,
            'value' => $voucher['voucher']->value,
            'type' => $voucher['voucher']->type,
            'discount' => $condValue,
        ];

        \Cart::update($productID,array('attributes'=>$attributes));

        //add voucher to session basket voucher
        $basketVoucher = [
            'basket_item_id' => $productID,
            'basket_item_value' => $item->getPriceSum(), // basket item value without conditions
            'session_id' => $request->session()->getId(),
            'voucher_code' => $voucher['voucher']->code,
        ];
        BasketVoucher::create($basketVoucher);

        //return response
        $message = [
            'success'=>true,
            'data'=>[
              'discount'=>(-$condValue),
              'total'=>$item->getPriceSumWithConditions(),
            ],
            'cart'=> \Cart::getContent(),
            'session'=> $request->session()->getId(),
        ];

        //return response
        return response($message,200);
    }

    /**
     * Remove table condition
     * @param Request $request
     */
    public function remove_voucher(Request $request)
    {
        $productID = $request->cartId;

        //remove table condition from the item table
        \Cart::removeItemCondition($productID, $conditionName="Voucher");

        //get item
        $item = \Cart::get($productID);
        $attributes = $item->attributes;
        $attributes['has_voucher'] = false;
        $attributes['voucher'] = [];

        //update cart attributes
        \Cart::update($productID,array('attributes'=>$attributes));

        //remove from session basket
        $sesVoucher = BasketVoucher::where('basket_item_id',$productID)
                                    ->where('session_id',$request->session()->getId())
                                    ->first();
        if ($sesVoucher)
            $sesVoucher->delete();


        //create response message
        $message = [
            'success'=>true,
            'data'=>[
              'total'=>$item->getPriceSumWithConditions(),
            ]
        ];

        //return response
        return response($message,200);
    }


    /**
     * Pay method
     * @param Request $request
     */
    public function pay(Request $request)
    {
        if (\Cart::isEmpty()){
            return response([
                'success'=>false,
                'message' => 'Time\'s up. The therapists reservations has overdue.',
            ],200);
        } //endif

        $total = \Cart::getTotal();
        $user = User::find($request->client_id);
        $token = $request->input('payment-method-nonce');

        //if user has no plans, create one
        if (!$user->braintree_id){
            $user->newSubscription('single-charge', 'qrjb')->create($token,[
                'email'=>$user->email,
                'phone'=>$user->profile->mobile_phone,
            ]);
        }
        else{
            //update token for each payment
            try{
                $user->updateCard($token);
            }
            catch (\Exception $e){

                $message = $e->getMessage();
                $message = str_ireplace('braintree','Tradze',$message);

                return response([
                    'success'=>false,
                    'message'=>$message,
                ],200);
            }
        }

        //change user amount
        try {
            $name = "massage services";
            $response = $user->invoiceFor($name,$total);
        } catch (\Exception $e) {

            $message = $e->getMessage();
            $message = str_ireplace('braintree','Tradze',$message);

            return response([
                'success'=>false,
                'message'=>$message,
            ],200);
        }

        //register payment
        $this->register_payment($response,$request);

        //redirect to success page
        return response([
            'success'=>true,
            'message'=>'YOUR ORDER IS CONFIRMED',
            'card_info' => [
                'payment_id' => $user->braintree_id,
                'paypal_email' => $user->paypal_email,
                'card_brand' => $user->card_brand,
                'card_last_four' => $user->card_last_four,
                'expiry'=>$response->transaction->creditCardDetails->expirationDate,
            ],
        ],200);

    }

    /**
     * Pay with existing card
     * @param Request $request
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     */
    public function pay_with_existing_card(Request $request)
    {

        if (\Cart::isEmpty()){
            return response([
                'success'=>false,
                'message' => 'Time\'s up. The therapists reservations has overdue.',
            ],403);
        } //endif

        //get current user
        $user = User::find($request->client_id);

        if (!$user->braintree_id){
            return response([
                'success'=>false,
                'message'=>'You have no valid card defined. Please enter one!',
            ],200);
        } //end

//        return response([
//            'success'=>false,
//            'message'=>'You have no valid card defined. Please enter one!',
//        ],200);

        //get total amount
        $total = round(\Cart::getTotal(),2);

        //charge user amount
        try {
            $name = "massage services";
            $response = $user->invoiceFor($name,$total);
        } catch (\Exception $e) {

            $message = $e->getMessage();
            $message = str_ireplace('braintree','Tradze',$message);

            return response([
                'success'=>false,
                'message'=>$message,
            ],200);
        }

        //register payment
        $this->register_payment($response,$request);

        //redirect to success page
        return response([
            'success'=>true,
            'message'=>'YOUR ORDER IS CONFIRMED',
        ],200);
    }

    /**
     * Pay with existing card
     * @param Request $request
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     */
    public function pay_with_cash(Request $request)
    {
        if (\Cart::isEmpty()){
            return response([
                'success'=>false,
                'message' => 'Time\'s up. The therapists reservations has overdue.',
            ],403);
        } //endif

        //get current user
        $user = User::find($this->user->id);

        //get total amount
        $total = \Cart::getTotal();

        //register payment
        DB::beginTransaction();

        //Create order
        $dataOrder = [
            'user_id' => $user->id,
            'amount' => \Cart::getTotal(),
            'type' => 'cash',
        ];


        $order = Order::create($dataOrder);

        $voucherRepo = new VoucherRepository();

        //create booking orders
        $bookingOrders = [];
        foreach(\Cart::getContent()as $item){
            $allInfo = $item->attributes;
            $allInfo['price_net'] = $item->getPriceSum();
            unset($allInfo['reserved_until']);
            //create order bookings array
            $data = [
                'order_id' => $order->id,
                'user_id' => $user->id,
                'is_active' => true,
                'amount' => $item->getPriceSumWithConditions(),
                'date' => Carbon::createFromFormat('d M Y',$item->attributes->date)->format('Y-m-d'),
                'hour' => $item->attributes->hour,
                'duration' => $item->attributes->duration,
                'duration_min' => $item->attributes->duration_min,
                'massage_type' => $item->attributes->massage_type,
                'address' => $item->attributes->address?$item->attributes->address:'no address',
                'location' => $item->attributes->location?$item->attributes->location:'location not found',
                'locationGeo' => json_encode($item->attributes->locationGeo),
                'orderInfo' => json_encode($allInfo),
                'updatedby_id' => $this->user->id,
            ];

            //save booking order
            $bookorder = BookingOrder::create($data);

            //attach therapists to booking order
            foreach($allInfo['therapistIds'] as $thid){
                $bookorder->therapists()->attach($thid,[
                                'date'=>Carbon::createFromFormat('d M Y',$item->attributes->date)->format('Y-m-d'),
                                'duration'=>$item->attributes->duration_min,
                                'hour'=>$item->attributes->hour
                ]);
            } //endforeach

            //if voucher code was used, mark it as used
            if ($item->attributes->has_voucher){
                $voucherRepo->mark_as_used($item->attributes->voucher['code'],$item->getPriceSum(),$item->id);
            } //end

            //start a new thread message
            $this->book->create_thread($bookorder);

            $bookingOrders[] = $bookorder;

        } //endforeach

        //add mobile notifications
        foreach($bookingOrders as $bo){
            $notif_message = trans("schedules::booking.mobile_update_order",['number'=>$bo->id,'date'=>$bo->date_to_human,'hour'=>$bo->hour_to_human]);

            $notif_users[] = $bo->user_id;
            $boInfo = json_decode($bo->orderInfo,true);
            $boTherapistsIds = $boInfo['therapistIds'];

            foreach($boTherapistsIds as $thid)
                $notif_users[] = $thid;

            //store notifications
            foreach($notif_users as $user)
                NotifRepository::add($user,$notif_message, 'booking', 'New Booking');
        } //endforeach


        //delete session tables: voucher and therapist
        $session_id = $request->session()->getId();

        $sesTh = BasketTherapist::where('session_id',$session_id)->get();
        if ($sesTh){
            foreach($sesTh as $sth)
                $sth->delete();
        } //endif

        $sesCodes = BasketVoucher::where('session_id',$session_id)->get();
        if ($sesCodes){
            foreach($sesCodes as $scode)
                $scode->delete();
        } //endif
//
//
//        return response([
//            'success'=>false,
//            'message' => 'Final',
//            'order' => $bookorder,
//
//        ],200);

        //commit transaction order details
        if ($order){
            DB::commit();

            //clear cart contents
            \Cart::clear();

            //unset session booking key
            $request->session()->forget('booking');

            //send email
            $this->sendEmailCheckout($bookingOrders);
        }
        else{
            DB::rollBack();

            return response([
                'success'=>false,
                'message' => 'Something went wrong. Please try again!',
            ],403);
        }

        //return success response
        return response([
            'success'=>true,
            'message' => 'Your appointment has been successfully registered',
        ],200);
    }

    /**
     * Register payment
     * @param $response
     */
    protected function register_payment($response,Request $request)
    {

        DB::beginTransaction();

        $user = User::find($this->user->id);

        //Create order
        $dataOrder = [
            'user_id' => $user->id,
            'amount' => \Cart::getTotal(),
            'type' => 'card',
            'card_trans_id' => $response->transaction->id,
            'card_trans_status' => (bool)$response->success,
            'card_details' => json_encode([
                'customerLocation' => $response->transaction->creditCardDetails->customerLocation,
                'cardType' => $response->transaction->creditCardDetails->cardType,
                'expirationDate' => $response->transaction->creditCardDetails->expirationDate,
                'imageUrl' => $response->transaction->creditCardDetails->imageUrl,
                'maskedNumber' => $response->transaction->creditCardDetails->maskedNumber,
                'last4' => $response->transaction->creditCardDetails->last4,
                'bin' => $response->transaction->creditCardDetails->bin,
            ]),
        ];
        $order = Order::create($dataOrder);

        $voucherRepo = new VoucherRepository();

        //create booking orders
        $bookingOrders = [];
        foreach(\Cart::getContent()as $item){
            $allInfo = $item->attributes;
            $allInfo['price_net'] = $item->getPriceSum();
            $allInfo['amount'] = $item->getPriceSumWithConditions();
            unset($allInfo['reserved_until']);

            //create order bookings array
            $data = [
                'order_id' => $order->id,
                'user_id' => $user->id,
                'is_active' => true,
                'amount' => $item->getPriceSumWithConditions(),
                'date' => Carbon::createFromFormat('d M Y',$item->attributes->date)->format('Y-m-d'),
                'hour' => $item->attributes->hour,
                'duration' => $item->attributes->duration,
                'duration_min' => $item->attributes->duration_min,
                'massage_type' => $item->attributes->massage_type,
                'massage_type_id' => $item->attributes->massage_type_id,
                'address' => ($item->attributes->address!=null)?$item->attributes->address:'no address',
                'location' => $item->attributes->location,
                'locationGeo' => json_encode($item->attributes->locationGeo),
                'orderInfo' => json_encode($allInfo),
                'card_trans_id' => $response->transaction->id,
                'card_trans_status' => (bool)$response->success,
                'card_details' => json_encode([
                    'customerLocation' => $response->transaction->creditCardDetails->customerLocation,
                    'cardType' => $response->transaction->creditCardDetails->cardType,
                    'expirationDate' => $response->transaction->creditCardDetails->expirationDate,
                    'imageUrl' => $response->transaction->creditCardDetails->imageUrl,
                    'maskedNumber' => $response->transaction->creditCardDetails->maskedNumber,
                    'last4' => $response->transaction->creditCardDetails->last4,
                    'bin' => $response->transaction->creditCardDetails->bin,
                ]),
                'updatedby_id' => $this->user->id,
            ];

            //save booking order
            $bookorder = BookingOrder::create($data);

            //add mobile notifications
            foreach($bookingOrders as $bo){
                $notif_message = trans("schedules::booking.mobile_update_order",['number'=>$bo->id,'date'=>$bo->date_to_human,'hour'=>$bo->hour_to_human]);

                $notif_users[] = $bo->user_id;
                $boInfo = json_decode($bo->orderInfo,true);
                $boTherapistsIds = $boInfo['therapistIds'];

                foreach($boTherapistsIds as $thid)
                    $notif_users[] = $thid;

                //store notifications
                foreach($notif_users as $user)
                    NotifRepository::add($user,$notif_message, 'booking', 'New Booking');
            } //endforeach

            //create invoice
            if ($response->transaction->id){
                $invRepo = new BookingInvoiceRepository();
                $invRepo->new_invoice($bookorder);
            } //endif

            //attach therapists to booking order
            foreach($allInfo['therapistIds'] as $thid){
                $bookorder->therapists()->attach($thid,[
                    'date'=>Carbon::createFromFormat('d M Y',$item->attributes->date)->format('Y-m-d'),
                    'duration'=>$item->attributes->duration_min,
                    'hour'=>$item->attributes->hour
                ]);
            } //endforeach

            //if voucher code was used, mark it as used
            if ($item->attributes->has_voucher){
                $voucherRepo->mark_as_used($item->attributes->voucher['code'],$item->getPriceSum(),$item->id);
            } //end

            $bookingOrders[] = $bookorder;
        } //endforeach


        //delete session tables: voucher and therapist
        $session_id = $request->session()->getId();

        $sesTh = BasketTherapist::where('session_id',$session_id)->get();
        if ($sesTh){
            foreach($sesTh as $sth)
                $sth->delete();
        } //endif

        $sesCodes = BasketVoucher::where('session_id',$session_id)->get();
        if ($sesCodes){
            foreach($sesCodes as $scode)
                $scode->delete();
        } //endif

        //start a new thread message
        $this->book->create_thread($bookorder);

        //commit transaction order details
        if ($order){
            DB::commit();

            //clear cart contents
            \Cart::clear();

            //unset session booking key
            $request->session()->forget('booking');

            //send email
            $this->sendEmailCheckout($bookingOrders);
        }
        else{
            DB::rollBack();
        }
    }

    /**
     * Send condfirmation order
     * @param $order
     */
    public function sendEmailCheckout($orders)
    {
        $user = User::findOrFail($orders[0]->user_id);
        $data['user'] = $user;
        $data['orders'] = $orders;

        //send confirmation email
        Mail::send('schedules::frontend.emails.neworder', ['user' => $user, 'orders'=>$orders], function ($m) use ($data) {
            $m->from(env('MAIL_FROM'), env('APP_NAME'));
            $m->to($data['user']->email, $data['user']->name);
            $m->bcc(explode(',',env('MAIL_NEWORDER_BCC')), env('MAIL_NEWORDER_BCC_NAME'));
            $m->subject('Tradze Massage website – booking confirmation');
        });
    }


}

ZeroDay Forums Mini