purityselect/app/Http/Controllers/Admin/Api/ReportsController.php
2024-10-25 01:05:27 +05:00

585 lines
24 KiB
PHP

<?php
namespace App\Http\Controllers\Admin\Api;
use App\Classes\Constant;
use App\Http\Controllers\Controller;
use App\Models\Admin;
use App\Models\Appointment;
use App\Models\Cart;
use App\Models\Item;
use App\Models\ItemHistory;
use App\Models\LabkitOrderItem;
use App\Models\LicenseNumberModel;
use App\Models\Patient;
use App\Models\PatientNote;
use App\Models\PatientPrescription;
use App\Models\ProfileQuestion;
use App\Models\Setting;
use App\Models\Telemedpro;
use DateInterval;
use DatePeriod;
use DateTime;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Routing\UrlGenerator;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use PhpParser\Node\Stmt\Const_;
use Illuminate\Auth\Access\AuthorizationException;
class ReportsController extends Controller
{
protected $url;
protected $user;
public function __construct(UrlGenerator $url)
{
$this->url = $url;
$this->user = Auth::guard('admin')->user();
}
public function providerReportFilters()
{
$providers = Telemedpro::select(
DB::raw("CONCAT(license_numbers.license_number,',',license_numbers.state) as provider_license_number"),
'appointments.patient_name',
'appointments.appointment_date',
'appointments.appointment_time',
'appointments.timezone',
'start_time',
'end_time',
'duration',
DB::raw("CONCAT(patients.first_name,',',patients.last_name) as patient_name"),
'patients.phone_no',
'patients.email',
'patients.address',
'patients.city',
'patients.state',
'patients.zip_code',
'patients.country',
'patients.gender',
'patients.dob',
'patients.height',
'patients.weight'
)
->LeftJoin('license_numbers', 'provider_id', 'telemed_pros.id')
->LeftJoin('appointments', 'appointments.telemed_pros_id', 'telemed_pros.id')
->leftJoin('patients', 'appointments.patient_id', 'patients.id')
->whereNotNull('appointments.start_time')
->whereNotNull('appointments.end_time')
->get();
foreach ($providers as $provider) {
$start_datetime = new DateTime($provider->start_time);
$diff = $start_datetime->diff(new DateTime($provider->end_time));
$duration = $diff->h . " hours " . $diff->i . " Min";
// dd($providers->duration,$duration);
$provider->duration = $duration;
}
return response()->json([
'provider_list' => $providers,
]);
}
public function providerReportPost(Request $request)
{
return response()->json([
'provider_list' => ''
]);
}
public function overviewReport(Request $request)
{
try {
$this->authorizeForUser($this->user, 'overview_analytics', new ProfileQuestion);
$start_date = $request->get('start_date');
$end_date = $request->get('end_date');
$totalOrdersStats = Cart::select(
DB::raw("sum(case when carts.status = 'completed' then 1 else 0 end) as total_sales"),
DB::raw("sum(case when carts.status = 'completed' then carts.total_amount else 0 end) as sales_amount"),
DB::raw("count(items.id) as products_sold")
)
->Join('items', 'items.cart_id', 'carts.id')
->where('carts.created_at', '>=', $start_date . " 00:00:00")
->where('carts.created_at', '<=', $end_date . " 23:59:59")
->where('carts.status', '=', 'completed')
->get();
$orderCollection = Cart::select(
'carts.id as order_id',
'carts.status',
'carts.email',
'carts.total_amount',
'carts.created_at as date',
DB::raw("CONCAT(carts.first_name,' ',carts.last_name) as patient_name")
)
->where('carts.created_at', '>=', $start_date . " 00:00:00")
->where('carts.created_at', '<=', $end_date . " 23:59:59")
->where('carts.status', '=', 'completed')
->get();
$orderData = $orderCollection->map(function ($query, $key) {
$patientType = $query->where('email', $query->email)->count();
$itemSold = Item::select(DB::raw("GROUP_CONCAT(title SEPARATOR ', ') as items"))
->where('cart_id', $query->order_id)
->leftJoin('plans_v1', 'items.plans_id', 'plans_v1.id');
$itemCount = $itemSold->count();
$products = $itemSold->first();
if ($patientType > 1)
$query->customer_type = 'returning';
else
$query->customer_type = 'new';
$query->products = $products->items ?? null;
$query->item_sold = $itemCount ?? 0;
$query->attribution = 'direct';
return $query;
});
$dates = [];
$sales = [];
$startDate = Carbon::parse($start_date);
$endDate = Carbon::parse($end_date);
for ($date = $startDate; $date->lte($endDate); $date->addDay()) {
$values = Cart::select(
DB::raw('DATE(created_at) as date'),
DB::raw("SUM(case when carts.status = 'completed' then carts.total_amount else 0 end) as amount")
)
->where('carts.created_at', '>=', $date->format("Y-m-d") . " 00:00:00")
->where('carts.created_at', '<=', $date->format("Y-m-d") . " 23:59:59")
->groupBy(DB::raw('DATE(created_at)'));
$graphsValues = $values->first();
$dates[] = $date->format("M d/y");
if ($graphsValues)
$sales[] = $graphsValues->amount;
else
$sales[] = 0;
}
$newUser = 0;
$returnUser = 0;
$newUsers = [];
$returningUsers = [];
//getting here unique rows for patient stats
$uniqueKeys = array_map(function ($item) {
return $item['email'];
}, $orderCollection->toArray());
$uniqueRecords = array_intersect_key($orderCollection->toArray(), array_unique($uniqueKeys));
$uniqueRecords = array_values($uniqueRecords);
foreach ($orderCollection as $userStats) {
$userStatus = Cart::where('email', $userStats->email)->count();
if ($userStatus > 1) {
$returnUser++;
$returningUsers[] = $userStats;
} else {
$newUser++;
$newUsers[] = $userStats;
}
};
$percentageReturning = 0;
$percentageNewuser = 0;
if ($returnUser > 0 || $newUser > 0) {
$percentageReturning = ($returnUser / ($returnUser + $newUser)) * 100;
$percentageNewuser = ($newUser / ($returnUser + $newUser)) * 100;
}
//check here users engagement
$newUserEngagement = $this->calculateEngagement($newUsers);
$returningUserEngagement = $this->calculateEngagement($returningUsers);
return response()->json([
'totals' => $totalOrdersStats,
'orders' => $orderData,
'chart' => [
'chart_dates' => $dates,
'chart_data' => $sales
],
'patient_stats' =>
[
'returning_users' => [$returnUser, round($percentageReturning, 0) . "%"],
'new_users' => [$newUser, round($percentageNewuser, 0) . "%"]
]
]);
} catch (AuthorizationException $e) {
return $e->getMessage();
}
}
public function ordersFilters()
{
$patient = Patient::select('id', DB::raw("CONCAT(first_name,' ',last_name) as patient_name"))->get();
return response()->json([
'patients' => $patient
]);
}
public function initialPatients()
{
$patients = Patient::select('id', DB::raw("CONCAT(first_name,' ',last_name) as patient_name"))
->limit(100)
->orderBy('patient_name', 'asc')
->get();
return response()->json([
'patients' => $patients
]);
}
public function searchPatients(Request $request)
{
$searchTerm = $request->input('term');
$patients = Patient::select('id', DB::raw("CONCAT(first_name,' ',last_name) as patient_name"))
->where(DB::raw("CONCAT(first_name,' ',last_name)"), 'LIKE', "%{$searchTerm}%")
->limit(500)
->orderBy('patient_name', 'asc')
->get();
return response()->json([
'patients' => $patients
]);
}
// Function to calculate engagement metrics
function calculateEngagement($users)
{
$totalUsers = count($users);
$completedOrders = 0;
$totalAmount = 0;
foreach ($users as $user) {
if ($user['status'] === 'delivered') {
$completedOrders++;
}
$totalAmount += floatval($user['total_amount']);
}
$orderCompletionRate = $totalUsers > 0 ? ($completedOrders / $totalUsers) * 100 : 0;
$averageOrderValue = $totalUsers > 0 ? $totalAmount / $totalUsers : 0;
return [
'total_users' => $totalUsers,
'completed_orders' => $completedOrders,
'order_completion_rate' => $orderCompletionRate,
'average_order_value' => $averageOrderValue
];
}
public function ordersReport(Request $request)
{
try {
$this->authorizeForUser($this->user, 'orders_analytics', new ProfileQuestion);
$start_date = $request->get('start_date');
$end_date = $request->get('end_date');
$status = $request->get('status');
$patient = $request->get('patient');
$query = Cart::select(
'carts.id as order_id',
'carts.status',
'carts.email',
'carts.total_amount',
'carts.created_at as date',
DB::raw("CONCAT(carts.first_name,' ',carts.last_name) as patient_name")
)
->where('carts.created_at', '>=', $start_date . " 00:00:00")
->where('carts.created_at', '<=', $end_date . " 23:59:59");
// Apply filters
if ($status != 'all') {
$query->where('carts.status', $status);
}
if ($patient != 'all') {
$query->where('carts.patient_id', $patient);
}
$dates = [];
$sales = [];
$startDate = Carbon::parse($start_date);
$endDate = Carbon::parse($end_date);
for ($date = $startDate; $date->lte($endDate); $date->addDay()) {
$values = Cart::select(
DB::raw('DATE(created_at) as date'),
DB::raw("SUM(carts.total_amount) as amount")
)
->where('carts.created_at', '>=', $date->format("Y-m-d") . " 00:00:00")
->where('carts.created_at', '<=', $date->format("Y-m-d") . " 23:59:59")
->groupBy(DB::raw('DATE(created_at)'));
if ($status != 'all') {
$values->where('carts.status', $status);
}
if ($patient != 'all') {
$values->where('carts.patient_id', $patient);
}
$graphsValues = $values->first();
$dates[] = $date->format("M d/y");
if ($graphsValues)
$sales[] = $graphsValues->amount;
else
$sales[] = 0;
}
// dd(Constant::getFullSql($query));
$orderCollection = $query->get();
$orderData = $orderCollection->map(function ($cart) {
$patientType = Cart::where('email', $cart->email)->count();
$itemSold = Item::select(DB::raw("GROUP_CONCAT(plans_v1.title SEPARATOR ', ') as items"))
->where('cart_id', $cart->order_id)
->leftJoin('plans_v1', 'items.plans_id', 'plans_v1.id');
$itemCount = $itemSold->count();
$products = $itemSold->first();
$cart->customer_type = $patientType > 1 ? 'returning' : 'new';
$cart->products = $products->items ?? null;
$cart->item_sold = $itemCount ?? null;
$cart->attribution = 'direct';
return $cart;
});
$totalOrdersStats = Cart::select(
// DB::raw("sum(case when carts.status = 'delivered' then 1 else 0 end) as total_sales"),
DB::raw("count(carts.id) as total_sales"),
DB::raw("sum(carts.total_amount ) as sales_amount"),
DB::raw("count(items.id) as products_sold")
)
->Join('items', 'items.cart_id', 'carts.id')
->where('carts.created_at', '>=', $start_date . " 00:00:00")
->where('carts.created_at', '<=', $end_date . " 23:59:59");
if ($status != 'all') {
$totalOrdersStats->where('carts.status', $status);
}
if ($patient != 'all') {
$totalOrdersStats->where('carts.patient_id', $patient);
}
$totals = $totalOrdersStats->get();
return response()->json([
'orders' => $orderData,
'totals' => $totals,
'chart' => [
'chart_dates' => $dates,
'chart_data' => $sales
]
]);
} catch (AuthorizationException $e) {
return $e->getMessage();
}
}
public function productAnalytics(Request $request)
{
try {
$this->authorizeForUser($this->user, 'orders_analytics', new ProfileQuestion);
$start_date = $request->get('start_date');
$end_date = $request->get('end_date');
$singleProduct = $request->get('single_product');
$patient = $request->get('patient');
$query = Item::select(
DB::raw("sum(case when items.status='delivered' then items.quantity else 0 end) as total_item_sold"),
DB::raw("sum(case when items.status='delivered' then 1 else 0 end) as total_orders"),
DB::raw("sum(case when items.status='delivered' then (items.quantity*plans_v1.price) else 0 end) as total_amount"),
'plans_v1.title as product_name',
'items.plans_id as product_id'
)
->leftJoin('plans_v1', 'plans_v1.id', 'items.plans_id')
->where('items.created_at', '>=', $start_date . " 00:00:00")
->where('items.created_at', '<=', $end_date . " 23:59:59")
->where('items.status', 'delivered')
->groupby('plans_v1.title', 'items.plans_id');
// Apply filters
if ($singleProduct != 'all') {
$query->where('items.plans_id', $singleProduct);
}
$dates = [];
$sales = [];
$startDate = Carbon::parse($start_date);
$endDate = Carbon::parse($end_date);
for ($date = $startDate; $date->lte($endDate); $date->addDay()) {
$graphsValues = Item::select(
DB::raw("sum(case when items.status='delivered' then 1 else 0 end) as total_orders"),
DB::raw("sum(case when items.status='delivered' then (items.quantity*plans_v1.price) else 0 end) as total_amount"),
)
->leftJoin('plans_v1', 'plans_v1.id', 'items.plans_id')
->where('items.created_at', '>=', $date->format("Y-m-d") . " 00:00:00")
->where('items.created_at', '<=', $date->format("Y-m-d") . " 23:59:59")
->where('items.status', 'delivered')
->groupby('plans_v1.title', 'items.plans_id');
if ($singleProduct != 'all') {
$graphsValues->where('items.plans_id', $singleProduct);
}
$graphVal = $graphsValues->first();
$dates[] = $date->format("M d/y");
if ($graphVal)
$sales[] = $graphVal->total_amount;
else
$sales[] = 0;
}
$orderData = $query->get();
$totalOrdersStats = Item::select(
DB::raw("count(items.id) as total_orders"),
DB::raw("sum(case when items.status='delivered' then (items.quantity*plans_v1.price) else 0 end) as sales_amount"),
DB::raw("sum(case when items.status='delivered' then items.quantity else 0 end) as products_sold")
)
->leftJoin('plans_v1', 'plans_v1.id', 'items.plans_id')
->where('items.created_at', '>=', $start_date . " 00:00:00")
->where('items.created_at', '<=', $end_date . " 23:59:59")
->where('items.status', 'delivered');
if ($singleProduct != 'all') {
$totalOrdersStats->where('items.plans_id', $singleProduct);
}
$totals = $totalOrdersStats->get();
return response()->json([
'orders' => $orderData,
'totals' => $totals,
'chart' => [
'chart_dates' => $dates,
'chart_data' => $sales
]
]);
} catch (AuthorizationException $e) {
return $e->getMessage();
}
}
public function totalSales()
{
$start_date = request()->input('start_date');
$end_date = request()->input('end_date');
$startDate = Carbon::parse($start_date);
$endDate = Carbon::parse($end_date);
$sales = [];
for ($date = $startDate; $date->lte($endDate); $date->addDay()) {
$graphsValues = Item::select(
DB::raw("sum(case when items.status='delivered' then 1 else 0 end) as total_orders"),
DB::raw("sum(case when items.status='delivered' then (items.quantity*plans_v1.price) else 0 end) as total_amount"),
)
->leftJoin('plans_v1', 'plans_v1.id', 'items.plans_id')
->where('items.created_at', '>=', $date->format("Y-m-d") . " 00:00:00")
->where('items.created_at', '<=', $date->format("Y-m-d") . " 23:59:59")
->where('items.status', 'delivered')
->groupby('plans_v1.title', 'items.plans_id');
$graphVal = $graphsValues->first();
$dates[] = $date->format("M d/y");
if ($graphVal) {
$sales[$date->format("Y-m-d")] = ["total_amount" => $graphVal->total_amount, "order_count" => $graphVal->total_orders];
} else {
$sales[$date->format("Y-m-d")] = ["total_amount" => 0, "order_count" => 0];
}
}
dd($dates, $sales);
}
public function ordersAnalytics(Request $request)
{
try {
$this->authorizeForUser($this->user, 'orders_analytics', new ProfileQuestion);
$start_date = $request->get('start_date');
$end_date = $request->get('end_date');
$singleProduct = $request->get('single_product');
$query = Cart::select(
'carts.id as order_id',
"carts.status as order_status",
"carts.created_at as order_date",
DB::raw("GROUP_CONCAT(plans_v1.title SEPARATOR ', ') as items"),
DB::raw("CONCAT(carts.first_name,' ',carts.last_name) as patient_name"),
"carts.total_amount",
DB::raw("sum(case when carts.status='completed' then 1 else 0 end) as item_sold")
)
->leftJoin('items', 'items.cart_id', 'carts.id')
->leftJoin('plans_v1', 'plans_v1.id', 'items.plans_id')
->where('carts.created_at', '>=', $start_date . " 00:00:00")
->where('carts.created_at', '<=', $end_date . " 23:59:59")
->where('carts.status', 'completed')
->groupby('carts.id',
'carts.status',
'carts.created_at',
DB::raw("CONCAT(carts.first_name,' ',carts.last_name)"),
"carts.total_amount");
$dates = [];
$sales = [];
$singleMonth = [];
$current_month = null;
$graphDates = null;
$startDate = Carbon::parse($start_date);
$endDate = Carbon::parse($end_date);
for ($date = $startDate; $date->lte($endDate); $date->addDay())
{
$graphsValues = Cart::select(
DB::raw('DATE(created_at) as date'),
DB::raw("SUM(carts.total_amount) as amount")
)
->where('carts.created_at', '>=', $date->format("Y-m-d") . " 00:00:00")
->where('carts.created_at', '<=', $date->format("Y-m-d") . " 23:59:59")
->where('carts.status', 'completed')
->groupBy(DB::raw('DATE(created_at)'));
$graphVal = $graphsValues->first();
$month = $date->format('F Y');
if ($month != $current_month)
{
// Month has changed or it's the first iteration, echo the first day of the month
$dates[] = $month;
$current_month = $month;
} else {
$dates[] = " ";
}
$singleMonth[] = $date->format("M d/y");
if ($graphVal)
$sales[] = $graphVal->amount;
else
$sales[] = 0;
}
// count if user select more then one month
$dateIterate = $this->monthItrator($start_date, $end_date);
if ($dateIterate == 1)
$graphDates = $singleMonth;
else
$graphDates = $dates;
$orderData = $query->get();
$totalOrdersStats = Item::select(
DB::raw("count(items.id) as total_orders"),
DB::raw("sum(case when items.status='delivered' then (items.quantity*plans_v1.price) else 0 end) as sales_amount"),
DB::raw("sum(case when items.status='delivered' then items.quantity else 0 end) as products_sold")
)
->leftJoin('plans_v1', 'plans_v1.id', 'items.plans_id')
->where('items.created_at', '>=', $start_date . " 00:00:00")
->where('items.created_at', '<=', $end_date . " 23:59:59")
->where('items.status', 'delivered');
$totals = $totalOrdersStats->get();
return response()->json([
'orders' => $orderData,
'totals' => $totals,
'chart' => [
'chart_dates' => $graphDates,
'chart_data' => $sales
]
]);
} catch (AuthorizationException $e) {
return $e->getMessage();
}
}
public function monthItrator($start_date, $end_date)
{
$start = (clone Carbon::parse($start_date))->modify('first day of this month');
$end = (clone Carbon::parse($end_date))->modify('first day of next month');
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
return iterator_count($period);
}
}