PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.5.2
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.5.2
1.6.6 1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 All 49 releases
fluent-cart / app / Services / Report / RevenueReportService.php

RevenueReportService.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.5.2, at app/Services/Report/RevenueReportService.php

196 lines 6.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Services\Report;
4
5 use FluentCart\App\App;
6
7 class RevenueReportService extends ReportService
8 {
9 public function revenueByGroup(array $params = []): array
10 {
11 $itemsSub = App::db()->table('fct_order_items')
12 ->selectRaw('order_id, SUM(quantity) AS total_items')
13 ->groupBy('order_id');
14
15 $query = App::db()->table('fct_orders as o')
16 ->leftJoinSub($itemsSub, 'oi_sum', fn($join) => $join->on('oi_sum.order_id', '=', 'o.id'));
17
18 $query = $this->applyFilters($query, $params);
19
20 $groupKeyExpression = '';
21
22 if (in_array($params['groupKey'], ['billing_country', 'shipping_country'])) {
23 $type = $params['groupKey'] === 'billing_country' ? 'billing' : 'shipping';
24
25 $query->leftJoin('fct_order_addresses as a', function ($join) use ($type) {
26 $join->on('o.id', 'a.order_id')->where('a.type', $type);
27 });
28
29 $groupKeyExpression = "COALESCE(a.country, 'Uncategorized') AS `{$params['groupKey']}`";
30 } elseif ($params['groupKey'] === 'payment_method') {
31 $groupKeyExpression = "COALESCE(o.payment_method, 'Unknown') AS `{$params['groupKey']}`";
32 } else {
33 $groupKeyExpression = "COALESCE(o.{$params['groupKey']}, 'Unknown') AS `{$params['groupKey']}`";
34 }
35
36 $query->selectRaw("{$groupKeyExpression},
37
38 COUNT(o.id) AS orders,
39
40 COUNT(CASE WHEN o.total_refund > 0 THEN 1 END) AS refunded_orders,
41
42 SUM(o.total_paid) / 100 AS gross_sale,
43
44 SUM(
45 o.total_paid
46 - o.total_refund
47 - o.tax_total
48 - o.shipping_tax
49 ) / 100 AS net_sale,
50
51 CASE
52 WHEN COUNT(o.id) = 0 THEN 0
53 ELSE SUM(o.total_paid) / COUNT(o.id) / 100
54 END AS average_order_gross,
55
56 CASE
57 WHEN COUNT(o.id) = 0 THEN 0
58 ELSE SUM(
59 o.total_paid
60 - o.total_refund
61 - o.tax_total
62 - o.shipping_tax
63 ) / COUNT(o.id) / 100
64 END AS average_order_net,
65
66 SUM(COALESCE(oi_sum.total_items, 0)) AS items,
67
68 SUM(o.shipping_total) / 100 AS shipping_total,
69
70 SUM(o.tax_total + o.shipping_tax) / 100 AS total_tax,
71
72 SUM(o.total_refund) / 100 AS total_refunds,
73
74 COUNT(DISTINCT o.customer_id) AS customer_count");
75
76 return $query->groupByRaw($params['groupKey'])->orderByRaw($params['groupKey'])->get()->toArray();
77 }
78
79 public function getRevenueData($params = []): array
80 {
81 $startDate = $params['startDate'];
82 $endDate = $params['endDate'];
83
84 $group = ReportHelper::processGroup($startDate, $endDate, $params['groupKey']);
85
86 $query = App::db()->table('fct_orders as o')
87 ->selectRaw("{$group['field']},
88
89 SUM(o.total_paid) / 100 AS total_sales,
90
91 SUM(
92 o.total_paid
93 - o.total_refund
94 - o.tax_total
95 - o.shipping_tax
96 ) / 100 AS net_revenue,
97
98 SUM(o.shipping_total) / 100 AS shipping_total,
99
100 SUM(o.tax_total + o.shipping_tax) / 100 AS total_tax,
101
102 SUM(o.total_refund) / 100 AS total_refunds,
103
104 CASE
105 WHEN COUNT(o.id) = 0 THEN 0
106 ELSE SUM(o.total_paid / 100) / COUNT(o.id)
107 END AS average_order_value,
108
109 COUNT(o.id) AS order_count,
110
111 -- COUNT(CASE WHEN o.total_paid = o.total_refund AND o.total_paid > 0 THEN 1 END) AS refunded_orders
112 COUNT(CASE WHEN o.total_refund > 0 THEN 1 END) AS refunded_orders");
113
114 $query = $this->applyFilters($query, $params);
115
116 $results = $query->groupByRaw($group['by'])->orderBy('group')->get();
117
118 $summary = [
119 'net_revenue' => 0,
120 'gross_sale' => 0,
121 'total_refunded_amount' => 0,
122 'tax_total' => 0,
123 'shipping_total' => 0,
124 'order_count' => 0,
125 'refunded_orders' => 0,
126 ];
127
128 $keys = [
129 'total_sales',
130 'net_revenue',
131 'shipping_total',
132 'total_tax',
133 'total_refunds',
134 'order_count',
135 'refunded_orders'
136 ];
137
138 $groups = $this->getPeriodRange($startDate, $endDate, $group['key'], $keys);
139
140 foreach ($results as $row) {
141 $groups[$row->group] = [
142 'year' => $row->year,
143 'group' => $row->group,
144 'total_sales' => $row->total_sales,
145 'net_revenue' => $row->net_revenue,
146 'shipping_total' => $row->shipping_total,
147 'total_tax' => $row->total_tax,
148 'total_refunds' => $row->total_refunds,
149 'order_count' => $row->order_count,
150 'refunded_orders' => $row->refunded_orders,
151 ];
152
153 $summary['net_revenue'] += $row->net_revenue;
154 $summary['gross_sale'] += $row->total_sales;
155 $summary['total_refunded_amount'] += $row->total_refunds;
156 $summary['tax_total'] += $row->total_tax;
157 $summary['shipping_total'] += $row->shipping_total;
158 $summary['order_count'] += $row->order_count;
159 $summary['refunded_orders'] += $row->refunded_orders;
160 }
161
162 return [
163 'groups' => array_values($groups),
164 'summary' => $summary,
165 'groupKey' => $group['key'],
166 ];
167 }
168
169 public function getFluctuations($currentMetrics, $previousMetrics)
170 {
171 $fluctuations = [];
172
173 $indices = [
174 'net_revenue',
175 'gross_sale',
176 'total_refunded_amount',
177 'tax_total',
178 'shipping_total',
179 'discount',
180 ];
181
182 foreach ($indices as $key) {
183 $previousValue = $previousMetrics[$key] ?? 0;
184 $currentValue = $currentMetrics[$key] ?? 0;
185
186 if ($previousValue > 0) {
187 $fluctuations[$key] = (($currentValue - $previousValue) / $previousValue) * 100;
188 } else {
189 $fluctuations[$key] = $currentValue > 0 ? 100 : 0;
190 }
191 }
192
193 return $fluctuations;
194 }
195 }
196