| 1 |
<?php |
| 2 |
|
| 3 |
namespace FluentCart\App\Http\Controllers\Reports; |
| 4 |
|
| 5 |
use FluentCart\Api\Resource\OrderItemResource; |
| 6 |
use FluentCart\Api\Resource\OrderResource; |
| 7 |
use FluentCart\Api\StoreSettings; |
| 8 |
use FluentCart\App\Helpers\CurrenciesHelper; |
| 9 |
use FluentCart\App\Helpers\CustomerHelper; |
| 10 |
use FluentCart\App\Helpers\Status; |
| 11 |
use FluentCart\App\Http\Controllers\Controller; |
| 12 |
use FluentCart\App\Models\Order; |
| 13 |
use FluentCart\App\Modules\ReportingModule\OrdersReport; |
| 14 |
use FluentCart\App\Services\DateTime\DateTime; |
| 15 |
use FluentCart\App\Services\Report\DashBoardReportService; |
| 16 |
use FluentCart\App\Services\Report\ReportHelper; |
| 17 |
use FluentCart\Framework\Http\Request\Request; |
| 18 |
use FluentCart\Framework\Support\Arr; |
| 19 |
|
| 20 |
class ReportingController extends Controller |
| 21 |
{ |
| 22 |
public function getOrderQuickStats(Request $request): array |
| 23 |
{ |
| 24 |
$compare = true; |
| 25 |
$fromRange = $request->get('day_range', '-0 days'); |
| 26 |
if ($fromRange == 'this_month') { |
| 27 |
$fromDate = gmdate('Y-m-01 00:00:00'); |
| 28 |
} else if ($fromRange == 'all_time') { |
| 29 |
$fromDate = false; |
| 30 |
$compare = false; |
| 31 |
} else { |
| 32 |
$fromDate = gmdate('Y-m-d 00:00:00', strtotime($fromRange)); |
| 33 |
} |
| 34 |
|
| 35 |
return [ |
| 36 |
'stats' => (new OrdersReport())->getOrderStats($fromDate, false, $compare), |
| 37 |
'from_date' => $fromDate, |
| 38 |
'to_date' => gmdate('Y-m-d 23:59:59', current_time('timestamp')) |
| 39 |
]; |
| 40 |
} |
| 41 |
|
| 42 |
/** |
| 43 |
* @deprecated since v1.4. Use GET reports/overview (OverviewReportController::getOverview) instead. |
| 44 |
*/ |
| 45 |
public function getReportOverview(Request $request): array |
| 46 |
{ |
| 47 |
_deprecated_function(__METHOD__, '1.4', 'GET /fluent-cart/v2/reports/overview'); |
| 48 |
|
| 49 |
$params = $request->get('params'); |
| 50 |
$params["status"] = ["column" => "status", "operator" => "in", "value" => Status::getOrderSuccessStatuses()]; |
| 51 |
$queryParam = Arr::only($params, ['created_at', 'status', 'payment_status']); |
| 52 |
|
| 53 |
$reportOverview = OrderResource::reportOverview($queryParam); |
| 54 |
|
| 55 |
$ordersByPaymentMethod = OrderResource::orderSummaryByPayment($queryParam); |
| 56 |
|
| 57 |
return [ |
| 58 |
'_deprecated' => 'This endpoint is deprecated since v1.4 and will be removed in a future release. Use GET /fluent-cart/v2/reports/overview instead.', |
| 59 |
'data' => $reportOverview, |
| 60 |
'orders_by_payment_method' => $ordersByPaymentMethod, |
| 61 |
]; |
| 62 |
} |
| 63 |
|
| 64 |
public function searchRepeatCustomer(Request $request): array |
| 65 |
{ |
| 66 |
$params = $request->get('params'); |
| 67 |
|
| 68 |
return [ |
| 69 |
'repeat_customers' => CustomerHelper::getRepeatCustomerBySearch($params)->paginate(Arr::get($params, 'per_page'), ['*'], 'page', Arr::get($params, 'current_page')) |
| 70 |
]; |
| 71 |
} |
| 72 |
|
| 73 |
/** |
| 74 |
* @deprecated since v1.4. Use GET reports/fetch-top-sold-products (DefaultReportController::getTopSoldProducts) instead. |
| 75 |
*/ |
| 76 |
public function getTopProductsSold(Request $request): array |
| 77 |
{ |
| 78 |
_deprecated_function(__METHOD__, '1.4', 'GET /fluent-cart/v2/reports/fetch-top-sold-products'); |
| 79 |
|
| 80 |
return [ |
| 81 |
'_deprecated' => 'This endpoint is deprecated since v1.4 and will be removed in a future release. Use GET /fluent-cart/v2/reports/fetch-top-sold-products instead.', |
| 82 |
'top_products_sold' => OrderItemResource::topProductsSold($request->get('params')), |
| 83 |
]; |
| 84 |
} |
| 85 |
|
| 86 |
public function getReportMeta(Request $request): array |
| 87 |
{ |
| 88 |
|
| 89 |
$startDate = $request->get('params.startDate', null); |
| 90 |
$endDate = $request->get('params.endDate', null); |
| 91 |
|
| 92 |
$data = Order::query() |
| 93 |
->select('currency') |
| 94 |
->selectRaw('COUNT(*) as order_count') |
| 95 |
->selectRaw('MIN(created_at) as min_created_at') |
| 96 |
->when($startDate && $endDate, function ($query) use ($startDate, $endDate) { |
| 97 |
$query->whereBetween('created_at', [$startDate, $endDate]); |
| 98 |
}) |
| 99 |
->groupBy('currency') |
| 100 |
->orderBy('order_count', 'desc') |
| 101 |
->get(['currency', 'min_created_at']); |
| 102 |
|
| 103 |
$min_created_at = $data->min('min_created_at'); |
| 104 |
|
| 105 |
if ($min_created_at < $startDate) { |
| 106 |
$min_created_at = $startDate; |
| 107 |
} |
| 108 |
|
| 109 |
if (!$min_created_at) { |
| 110 |
$min_created_at = (new DateTime())->format('Y-m-d H:i:s'); |
| 111 |
} |
| 112 |
|
| 113 |
$currentCurrency = (new StoreSettings())->getCurrency(); |
| 114 |
|
| 115 |
$currencyWithSign = CurrenciesHelper::getCurrencyWithSign([$currentCurrency]); |
| 116 |
|
| 117 |
return [ |
| 118 |
'currencies' => $currencyWithSign, |
| 119 |
'min_date' => $min_created_at, |
| 120 |
'storeMode' => (new StoreSettings())->get('order_mode'), |
| 121 |
'first_order_date' => Order::query()->min('created_at') |
| 122 |
]; |
| 123 |
|
| 124 |
} |
| 125 |
|
| 126 |
//Dashboard Report Controllers |
| 127 |
|
| 128 |
public function getDashBoardSummary(Request $request) |
| 129 |
{ |
| 130 |
|
| 131 |
return DashBoardReportService::getSummary(); |
| 132 |
} |
| 133 |
public function getRecentOrders(Request $request) |
| 134 |
{ |
| 135 |
|
| 136 |
return DashBoardReportService::getRecentOrders(); |
| 137 |
} |
| 138 |
|
| 139 |
public function getRecentActivities(Request $request) |
| 140 |
{ |
| 141 |
|
| 142 |
$groupKey = Arr::get($request->all(), 'groupKey', 'all'); |
| 143 |
return DashBoardReportService::getRecentActivities($groupKey); |
| 144 |
} |
| 145 |
public function getDashBoardStats(Request $request): array |
| 146 |
{ |
| 147 |
$filters = [ |
| 148 |
'currency' => $request->get('params.currency', null), |
| 149 |
'payment_status' => $request->get('params.paymentStatus', null) === 'all' ? '' : $request->get('params.paymentStatus', null), |
| 150 |
]; |
| 151 |
$startDate = $request->get('params.startDate', null); |
| 152 |
$endDate = $request->get('params.endDate', null); |
| 153 |
// |
| 154 |
// $startDate = null; |
| 155 |
// $endDate = null; |
| 156 |
|
| 157 |
if (empty($startDate) && empty($endDate)) { |
| 158 |
// Retrieve the first order's created_at date and set the start date |
| 159 |
$firstOrder = Order::query()->orderBy('created_at', 'asc')->first(); |
| 160 |
|
| 161 |
$startDate = $firstOrder ? new DateTime($firstOrder->created_at) : null; |
| 162 |
|
| 163 |
// Set the end date to the current date |
| 164 |
$endDate = new DateTime(); |
| 165 |
} else { |
| 166 |
$startDate = !empty($startDate) ? new DateTime($startDate) : null; |
| 167 |
$endDate = !empty($endDate) ? new DateTime($endDate) : null; |
| 168 |
} |
| 169 |
|
| 170 |
if (!$startDate || !$endDate) { |
| 171 |
return [ |
| 172 |
'dashBoardStats' => [ |
| 173 |
'total_orders' => [ |
| 174 |
'title' => __('All Orders', 'fluent-cart'), |
| 175 |
'icon' => 'AllOrdersIcon', |
| 176 |
'current_count' => 0, |
| 177 |
'compare_count' => 0, |
| 178 |
], |
| 179 |
'paid_orders' => [ |
| 180 |
'title' => __('Paid Orders', 'fluent-cart'), |
| 181 |
'icon' => 'Money', |
| 182 |
'current_count' => 0, |
| 183 |
'compare_count' => 0, |
| 184 |
], |
| 185 |
'total_paid_order_items' => [ |
| 186 |
'title' => __('Paid Order Items', 'fluent-cart'), |
| 187 |
'icon' => 'OrderItemsIcon', |
| 188 |
'current_count' => 0, |
| 189 |
'compare_count' => 0, |
| 190 |
], |
| 191 |
'total_paid_amounts' => [ |
| 192 |
'title' => __('Order Value (Paid)', 'fluent-cart'), |
| 193 |
'icon' => 'OrderValueIcon', |
| 194 |
'current_count' => 0, |
| 195 |
'compare_count' => 0, |
| 196 |
'is_cents' => true, |
| 197 |
], |
| 198 |
] |
| 199 |
]; |
| 200 |
} |
| 201 |
$interval = $startDate->diff($endDate)->days; |
| 202 |
|
| 203 |
$previousEndDate = (clone $startDate)->modify('-1 day')->endOfDay(); |
| 204 |
$previousStartDate = (clone $previousEndDate)->modify("-$interval days")->setTime(0, 0, 0); |
| 205 |
|
| 206 |
$service = DashBoardReportService::make($filters) |
| 207 |
->setSelects(['id', 'total_amount', 'manual_discount_total', 'tax_total', 'shipping_total', 'total_refund', 'created_at', 'subtotal', 'coupon_discount_total', 'payment_status']) |
| 208 |
->setRange($startDate && $endDate ? $previousStartDate : null, $startDate && $endDate ? $endDate : null) |
| 209 |
->setAmountColumns(['total_amount', 'manual_discount_total', 'tax_total', 'shipping_total', 'total_refund', 'subtotal', 'coupon_discount_total']); |
| 210 |
|
| 211 |
return $service->getDashboardStats($startDate, $endDate, $previousStartDate, $previousEndDate); |
| 212 |
|
| 213 |
} |
| 214 |
|
| 215 |
public function getSalesGrowthChart(Request $request): array |
| 216 |
{ |
| 217 |
$params = ReportHelper::processParams($request->get('params'), ['orderStatus']); |
| 218 |
|
| 219 |
$service = DashBoardReportService::make(); |
| 220 |
|
| 221 |
return [ |
| 222 |
'salesGrowthChart' => $service->getSalesGrowthChart($params) |
| 223 |
]; |
| 224 |
} |
| 225 |
|
| 226 |
public function getCountryHeatMap(Request $request) |
| 227 |
{ |
| 228 |
|
| 229 |
|
| 230 |
$filters = [ |
| 231 |
'currency' => $request->get('params.currency', null), |
| 232 |
]; |
| 233 |
|
| 234 |
$service = DashBoardReportService::make($filters) |
| 235 |
->setAmountColumns(['total_amount', 'manual_discount_total', 'tax_total', 'shipping_total', 'total_refund', 'subtotal', 'coupon_discount_total']); |
| 236 |
|
| 237 |
return $service->getCountryHeatMap(); |
| 238 |
|
| 239 |
} |
| 240 |
|
| 241 |
} |
| 242 |
|