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/public_html/app/Modules/Schedules/Http/Controllers/Admin/ |
<?php
namespace App\Modules\Schedules\Http\Controllers\Admin;
use App\Http\Controllers\AdminController;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Modules\Invoices\Repositories\BookingInvoiceRepository;
use App\Modules\Schedules\Http\Requests\BookingUpdateRequest;
use App\Modules\Schedules\Models\BookingOrder;
use App\Modules\Schedules\Models\BookingInternalNote;
use App\Modules\Schedules\Repositories\BookingRepository;
use App\Modules\Schedules\Scopes\ActiveScope;
use App\Modules\Services\Models\ServiceDuration;
use App\Modules\Services\Models\ServiceType;
//use Braintree\Transaction;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Session;
use Laracasts\Flash\Flash;
use App\User;
use Yajra\Datatables\Datatables;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Artisan;
class BookingsController extends AdminController
{
/**
* The booking repository instance.
*
* @var pageRepository
*/
protected $repo;
/**
* Create a new controller instance.
*
* @param TaskRepository $tasks
* @return void
*/
public function __construct(BookingRepository $repository)
{
parent::__construct();
$this->repo = $repository;
}
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index(Request $request)
{
// dd("saivbsa");
//unset any booking key from session
$this->repo->unset_booking_data();
//store filters to sessions
if ($request->get('search')) {
$request->session()->put('schedules.bookings.filters', $request->except(['_token', 'search']));
return redirect(route('admin.schedules.bookings.index'));
} elseif ($request->get('reset')) {
$request->session()->forget('schedules.bookings.filters');
return redirect(route('admin.schedules.bookings.index'));
}
//create data array
$this->data['page_title'] = trans('schedules::booking.page_title');
$this->data['filters'] = $request->session()->get('schedules.bookings.filters');
if (Auth::user()->hasRole('salon')) {
$this->data['search'] = [
'clients' => ['' => trans('schedules::booking.search_by_client')],
'therapists' => User::where('salon_id', Auth::user()->id)->pluck('name', 'id')->put('', trans('schedules::booking.search_by_therapist')),
'salon' => User::ofSalon()->pluck('name', 'id')->put('', trans('schedules::booking.search_by_salon')),
];
} else {
$this->data['search'] = [
'clients' => User::ofClients()->pluck('name', 'id')->put('', trans('schedules::booking.search_by_client')),
'therapists' => User::ofTherapists()->pluck('name', 'id')->put('', trans('schedules::booking.search_by_therapist')),
'salon' => User::ofSalon()->pluck('name', 'id')->put('', trans('schedules::booking.search_by_salon')),
];
}
//render page
return view('schedules::admin.bookings.booking_index', $this->data);
}
/**
* Show a list of all companies
*
* @return mixed
*/
public function data(Request $request)
{
//create object contact
$obj = $this->getData($request);
//create array with contacts permissions access
$this->data['can'] = [
'view' => $this->data['user']->roles->pluck('slug')[0] == 'developer' || $this->data['user']->roles->pluck('slug')[0] == 'salon',
'edit' => $this->data['user']->roles->pluck('slug')[0] == 'developer' || $this->data['user']->roles->pluck('slug')[0] == 'salon',
'delete' => $this->data['user']->roles->pluck('slug')[0] == 'developer' || $this->data['user']->roles->pluck('slug')[0] == 'salon',
'create_invoice' => $this->data['user']->roles->pluck('slug')[0] == 'developer' || $this->data['user']->roles->pluck('slug')[0] == 'salon',
];
//return datatables data
return Datatables::of($obj)
->editColumn('internal_notes', function ($o) {
$this->data['o'] = $o;
return view('schedules::admin.bookings.partial_booking_internal_notes', $this->data)->render();
})
->addColumn('date_hour', function ($o) {
return $o->date_to_human . ', ' . $o->hour_to_human;
})
->editColumn('invoice', function ($o) {
$this->data['invoice'] = $o->invoice;
return view('schedules::admin.bookings.partial_invoice', $this->data)->render();
})
->addColumn('client', function ($o) {
if (!$o->user)
return '';
return $o->user->name;
})
->addColumn('therapist', function ($o) {
$list = [];
foreach ($o->therapists as $th)
$list[] = $th->name;
return implode(', ', $list);
})
->editColumn('is_active', function ($o) {
$this->data['o'] = $o;
return view('schedules::admin.bookings.partial_booking_status', $this->data)->render();
})
->addColumn('actions', function ($o) {
$this->data['o'] = $o;
return view('schedules::admin.bookings.booking_list_actions', $this->data)->render();
})
->rawColumns([
'amount',
'internal_notes',
'invoice',
'is_active',
'actions'
])
->make(true);
}
public function clearCache()
{
if (!Artisan::call('cache:clear')) {
return 'Cache cleared successfully.';
} else {
return 'Cache not cleared.';
}
return "nothing";
}
/**
* Get object entries
* @param Request $request
*/
protected function getData(Request $request)
{
if (Auth::user()->hasRole('salon')) {
$filters = $request->session()->get('schedules.bookings.filters');
$obj = BookingOrder::query()
->where('salon_id', Auth::user()->id)
->OfTherapist(isset($filters['search_therapist']) ? $filters['search_therapist'] : null)
->OfClient(isset($filters['search_client']) ? $filters['search_client'] : null)
->OfOrder(isset($filters['search_order_number']) ? $filters['search_order_number'] : null)
->OfNumber(isset($filters['search_number']) ? $filters['search_number'] : null)
->OfDateFrom(isset($filters['search_date_from']) ? $filters['search_date_from'] : null)
->OfDateTo(isset($filters['search_date_to']) ? $filters['search_date_to'] : null)
->withoutGlobalScope(ActiveScope::class)
->orderBy('id', 'desc');
} else {
$filters = $request->session()->get('schedules.bookings.filters');
$obj = BookingOrder::query()
->OfTherapist(isset($filters['search_therapist']) ? $filters['search_therapist'] : null)
->ofSalon(isset($filters['search_salon']) ? $filters['search_salon'] : null)
->OfClient(isset($filters['search_client']) ? $filters['search_client'] : null)
->OfOrder(isset($filters['search_order_number']) ? $filters['search_order_number'] : null)
->OfNumber(isset($filters['search_number']) ? $filters['search_number'] : null)
->OfDateFrom(isset($filters['search_date_from']) ? $filters['search_date_from'] : null)
->OfDateTo(isset($filters['search_date_to']) ? $filters['search_date_to'] : null)
->withoutGlobalScope(ActiveScope::class)
->orderBy('id', 'desc');
}
//return object
return $obj;
}
/**
* Display booking details
* @param $id
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function show($id)
{
//unset any booking key from session
$this->repo->unset_booking_data();
$bookings = BookingOrder::where('id', $id)->withoutGlobalScope(ActiveScope::class)->first();
$bookingRepo = new BookingRepository();
$card_trans_status = null;
$refundID = null;
// if ($bookings->card_trans_id){
// try{
// $trans = Transaction::find($bookings->card_trans_id);
// $refundID = $trans->refundId;
// if (!$refundID)
// $card_trans_status=trans("schedules::booking.text_{$trans->status}");
// else
// $card_trans_status=trans("schedules::booking.text_refunded");
// }
// catch(\Exception $e){
//
// }
// } //end booking has been paid with card
//create data array
$this->data['page_title'] = trans('schedules::booking.page_title');
$this->data['booking'] = $bookings;
$this->data['order_items'] = $bookingRepo->get_order_cart($bookings->cart_trans_id);
$this->data['info'] = json_decode($bookings->orderInfo, true);
$this->data['card_trans_status'] = $card_trans_status;
$this->data['refundID'] = $refundID;
if ($bookings->salon_id) {
return view('schedules::admin.bookings.salon_booking_show', $this->data);
}
//render page
return view('schedules::admin.bookings.booking_show', $this->data);
}
/**
* Edit Page
* @param $id
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
*/
public function edit($id)
{
//get booking
$booking = BookingOrder::where('id', $id)->withoutGlobalScope(ActiveScope::class)->first();
// dd($booking);
if (!$booking) {
flash('Booking not found!', 'danger');
return redirect(route('admin.schedules.bookings.index'));
} //endif
//can be edited only the future bookings
// if (!$booking->time_left_in_seconds){
// flash(trans('schedules::booking.message_error_restrict_edit'),'danger');
// return redirect(route('admin.schedules.bookings.show',['bookings'=>$booking->id]));
// } //endif
//set booking data
$this->repo->set_booking_data($booking);
$booking_info = json_decode($booking->orderInfo, true);
$hours = $this->get_hours($booking->date->format('Y-m-d'), !empty($booking_info['therapistIds']) ? $booking_info['therapistIds'] : '');
//create data array
$this->data['page_title'] = trans('schedules::booking.page_title');
$this->data['obj'] = $booking;
$this->data['hours'] = $hours;
$this->data['info'] = json_decode($booking->orderInfo, true);
// dd($this->data['info']);
$this->data['form']['massage_types'] = ServiceType::pluck('name', 'id');
$this->data['form']['durations'] = ServiceDuration::where('is_extra', 0)->pluck('name', 'id');
$this->data['form']['therapists'] = User::OfTherapists()->get()->pluck('name', 'id');
if ($booking->salon_id) {
return view('schedules::admin.bookings.salon_booking_edit_v2', $this->data);
}
//render page
return view('schedules::admin.bookings.booking_edit_v2', $this->data);
}
/**
* Update
* @param Request $request
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function update(BookingUpdateRequest $request, $id)
{
if ($request->is_salon) {
//for Salon
//get booking
$booking = BookingOrder::where('id', $id)->withoutGlobalScope(ActiveScope::class)->first();
$orderInfo = json_decode($booking->orderInfo, true);
// $duration = ServiceDuration::find($request->duration_id);
// $massage_type = ServiceType::find($request->massage_type);
//get therapists info
// $therapistName = [];
// $therapistImage = [];
// $therapistIds = [];
// $invoiceTableToThID = null;
// foreach ($request->therapists as $key => $newth) {
// $objTh = User::find($newth);
// if (!$objTh) continue;
// $therapistName[] = trim($objTh->name);
// $therapistIds[] = trim($objTh->id);
// $therapistImage[] = trim($objTh->public_avatar_url);
// if ($request->invoice_table == "invoice_therapist_{$key}")
// $invoiceTableToThID = trim($objTh->id);
// } //endforeach therapists
$data = [
'amount' => $request->amount,
'hour' => $request->newhour,
'date' => $request->newdate,
'internal_notes' => $request->internal_notes,
];
//start saving the booking
DB::beginTransaction();
//update bookiing details
$status = $booking->update($data);
//update booking therapists:
//1. detach all boking therapist
// $booking->therapists()->detach();
//2. attach new therapist with date, hour, duration details
// foreach ($therapistIds as $thid) {
// if ($invoiceTableToThID == $thid)
// $invoice_table = 1;
// else
// $invoice_table = 0;
// $booking->therapists()->attach($thid, ['date' => $request->newdate, 'hour' => $request->newhour, 'duration' => $duration->duration, 'invoice_table' => $invoice_table]);
// }
//check the booking update status and commit/rollback database transaction
if ($status) {
//commit
DB::commit();
//inform user about the action
flash(trans('schedules::booking.message_success_update'), 'info');
//send email to customer with the new booking details
// $this->sendOrderMail($booking);
//redirect to booking details page
return redirect(route('admin.schedules.bookings.show', ['id' => $booking->id]));
} else {
//rollback
DB::rollBack();
//redirect back to edit page
return redirect(route('admin.schedules.bookings.edit', ['id' => $booking->id]));
} //end transaction
//redirect
return redirect(route('admin.schedules.bookings.show', ['id' => $booking->id]));
} else {
//for Face 2 Face
//get booking
$booking = BookingOrder::where('id', $id)->withoutGlobalScope(ActiveScope::class)->first();
$orderInfo = json_decode($booking->orderInfo, true);
$duration = ServiceDuration::find($request->duration_id);
$massage_type = ServiceType::find($request->massage_type);
//get therapists info
$therapistName = [];
$therapistImage = [];
$therapistIds = [];
$invoiceTableToThID = null;
foreach ($request->therapists as $key => $newth) {
$objTh = User::find($newth);
if (!$objTh) continue;
$therapistName[] = trim($objTh->name);
$therapistIds[] = trim($objTh->id);
$therapistImage[] = trim($objTh->public_avatar_url);
if ($request->invoice_table == "invoice_therapist_{$key}")
$invoiceTableToThID = trim($objTh->id);
} //endforeach therapists
$data = [
'amount' => $request->amount,
'hour' => $request->newhour,
'date' => $request->newdate,
'duration' => $duration->name,
'duration_min' => $duration->duration,
'massage_type' => $massage_type->name,
'address' => trim($request->address),
'location' => trim($request->location),
'locationGeo' => json_encode([
'lat' => $request->locationGeoLat,
'lng' => $request->locationGeoLng,
]),
'internal_notes' => $request->internal_notes,
'orderInfo' => json_encode([
'therapist' => $therapistName,
'therapistIds' => $therapistIds,
'therapistImage' => $therapistImage,
'therapistsNo' => $orderInfo['therapistsNo'],
'therapistsOpt' => $orderInfo['therapistsOpt'],
'type' => $orderInfo['type'],
'date' => Carbon::createFromFormat('Y-m-d', $request->newdate)->format('d M Y'),
'hour' => $request->newhour,
'duration' => $duration->name,
'duration_min' => $duration->duration,
'duration_id' => $duration->id,
'duration_commision' => $orderInfo['duration_commision'],
'massage_type' => $massage_type->name,
'massage_type_id' => $massage_type->id,
'focal_points' => $orderInfo['focal_points'],
'can_order_table' => $orderInfo['can_order_table'],
'disclaimer' => $orderInfo['disclaimer'],
'has_table' => (bool)$request->has_table,
'table_value' => (bool)$request->has_table ? env('TABLE_VALUE', 9.99) : 0,
'has_transport' => ($request->transport_cost != 0) ? true : false,
'transport_cost' => $request->transport_cost,
'has_voucher' => $orderInfo['has_voucher'],
'voucher' => array_key_exists('voucher', $orderInfo) ? $orderInfo['voucher'] : [],
'user_name' => $request->user_name,
'user_phone' => $request->user_phone,
'address' => $request->address,
'postcode' => $request->postcode,
'county' => $request->county,
'location' => $request->location,
'locationGeo' => [
'lat' => $request->locationGeoLat,
'lng' => $request->locationGeoLng,
],
'price_net' => $orderInfo['price_net'],
'amount' => $request->amount,
'has_extension' => isset($orderInfo['has_extension']) ? $orderInfo['has_extension'] : false,
'extension' => isset($orderInfo['extension']) ? $orderInfo['extension'] : [],
]),
];
//start saving the booking
DB::beginTransaction();
//update bookiing details
$status = $booking->update($data);
if (!empty($request->internal_notes)) {
//add internal note
$note = new BookingInternalNote();
$note->booking_id = $booking->id;
$note->text_body = $request->internal_notes;
$note->save();
}
//update booking therapists:
//1. detach all boking therapist
$booking->therapists()->detach();
//2. attach new therapist with date, hour, duration details
foreach ($therapistIds as $thid) {
if ($invoiceTableToThID == $thid)
$invoice_table = 1;
else
$invoice_table = 0;
$booking->therapists()->attach($thid, ['date' => $request->newdate, 'hour' => $request->newhour, 'duration' => $duration->duration, 'invoice_table' => $invoice_table]);
}
//check the booking update status and commit/rollback database transaction
if ($status) {
//commit
DB::commit();
//inform user about the action
flash(trans('schedules::booking.message_success_update'), 'info');
//send email to customer with the new booking details
$this->sendOrderMail($booking);
//redirect to booking details page
return redirect(route('admin.schedules.bookings.show', ['booking' => $booking->id]));
} else {
//rollback
DB::rollBack();
//redirect back to edit page
return redirect(route('admin.schedules.bookings.edit', ['booking' => $booking->id]));
} //end transaction
// //update hour
// if ($data['hour'] && $data['date']){
//
// $orderInfo['hour'] = $data['hour'];
// $orderInfo['date'] = $data['date'];
//
// $booking->date = $data['date'];
// $booking->hour = $data['hour'];
// $booking->orderInfo = json_encode($orderInfo);
// $booking->save();
//
// foreach($booking->therapists as $therapist){
// $thID = $therapist->id;
// $booking->therapists()->updateExistingPivot($thID,['date'=>$data['date'], 'hour'=>$data['hour']]);
// } //endforeach
// } //endif hour
//send email
// $this->sendOrderMail($booking);
//inform user about the status of the update action
// flash(trans('schedules::booking.message_success_update'),'info');
//redirect
return redirect(route('admin.schedules.bookings.show', ['id' => $booking->id]));
}
}
/**
* Generate invoice for the selected booking
*
* @param $id
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function create_invoice($id)
{
//get booking
$booking = BookingOrder::where('id', $id)->withoutGlobalScope(ActiveScope::class)->first();
if (!$booking) {
flash('Booking not found!', 'danger');
return redirect(route('admin.schedules.bookings.index'));
} //endif
//create invoice repository object
$repo = new BookingInvoiceRepository();
if ($booking->salon_id) {
//generate invoice
$repo->new_salon_invoice($booking);
} else {
//generate invoice
$repo->new_invoice($booking);
}
//return to booking index
return redirect(route('admin.schedules.bookings.index'));
}
/**
* Get available hours
* @param $date
* @param $therapistIds
* @return mixed
*/
public function get_hours($date, $therapistIds)
{
$hours = collect($this->repo->hours_without_buffer($date, $therapistIds));
if ($hours->isEmpty()) {
$results[''] = trans('schedules::booking.text_other_no_av_hours');
return $results;
}
$avhours = $hours->filter(function ($data, $key) {
return $data['available'];
});
if ($avhours->isEmpty()) {
$results[''] = trans('schedules::booking.text_other_no_av_hours');
return $results;
} //endif
$results[''] = trans('schedules::booking.text_other_av_hours');
$results += $avhours->pluck('hour', 'hour')->toArray();
return $results;
}
/**
* Get hours with post request
* @param Request $request
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response
*/
public function get_post_hours(Request $request)
{
$booking = session('booking');
$data = $this->get_hours($booking['date'], $booking['selected_therapists']);
//return get available hours for requested date
return response($data, 200);
}
/**
* Set new booking date
* @param $date
*/
public function set_date(Request $request)
{
$date = $request->date;
$booking = Session::get('booking');
//if selected date is marked as day off, return empty hours array
$daysOff = $this->repo->days_off($date);
// if ($daysOff->count())
// return response('no working day',403);
//store the new date into session
$booking['date'] = $date;
Session::put('booking', $booking);
}
/**
* Refund
* @param $id
*/
public function refund($id)
{
$obj = BookingOrder::where('id', $id)
->withoutGlobalScope(ActiveScope::class)
->first();
if (!$obj) {
flash('The booking is not found!', 'danger');
return redirect(route('admin.schedules.bookings.show', ['booking_id' => $id]));
} //endif
$repo = new BookingRepository();
try {
if ($obj->is_active == 0) {
$response = $repo->active_order($obj, true);
// Modified by CIS
} else {
$response = $repo->cancel_order($obj, true);
}
$statusClass = $response['success'] ? 'info' : 'danger';
flash($response['message'], $statusClass);
return redirect(route('admin.schedules.bookings.show', ['booking_id' => $id]));
} catch (\Exception $e) {
flash($e->getMessage(), 'danger');
return redirect(route('admin.schedules.bookings.show', ['booking_id' => $id]));
}
}
/**
* Send condfirmation order
* @param $order
*/
public function sendOrderMail($order)
{
$user = User::findOrFail($order->user_id);
$data['user'] = $user;
$data['order'] = $order;
//send confirmation email
Mail::send('schedules::frontend.emails.editorder', ['user' => $user, 'order' => $order], function ($m) use ($data) {
$m->from(env('MAIL_FROM'), env('APP_NAME'));
$m->to($data['user']->email, $data['user']->name);
// $m->bcc(env('MAIL_NEWORDER_BCC'), env('MAIL_NEWORDER_BCC_NAME'));
$m->bcc(explode(',', env('MAIL_NEWORDER_BCC')), env('MAIL_NEWORDER_BCC_NAME'));
$m->subject('Tradze-Booking Updates');
});
}
/**
* Format text right
* @param $string
* @param bool $number
* @return string
*/
protected function text_right($string, $number = true)
{
$value = $string;
if ($number)
$value = number_format($string, 2, '.', ',') . " £";
return "<div class='text-right'>{$value}</div>";
}
public function getInternalNotes($bookingId)
{
$booking = BookingOrder::where('id', $bookingId)->withoutGlobalScope(ActiveScope::class)->first();
if (!$booking) {
flash('Booking not found!', 'danger');
return redirect(route('admin.schedules.bookings.index'));
} //endif
//create data array
$this->data['page_title'] = trans('schedules::booking.page_title');
$this->data['booking'] = $booking;
$this->data['internal_notes'] = BookingInternalNote::where('booking_id', $bookingId)->orderBy('created_at', 'desc')->get();
//render page
return view('schedules::admin.bookings.booking_internal_notes', $this->data);
}
public function removeInternalNotes(Request $request)
{
$noteId = $request->input('note_id');
$note = BookingInternalNote::find($noteId);
if (!$note) {
return response()->json([
'success' => false,
'message' => 'Internal note not found.',
], 404);
}
$note->delete();
return response()->json([
'success' => true,
'message' => 'Internal note removed successfully.',
]);
}
}