2
2
3
3
namespace Webkul \Admin \Helpers \Reporting ;
4
4
5
+ use Carbon \Carbon ;
5
6
use Illuminate \Support \Facades \DB ;
6
7
use Webkul \Lead \Repositories \LeadRepository ;
7
8
use Webkul \Lead \Repositories \StageRepository ;
@@ -55,6 +56,8 @@ public function getTotalLeadsOverTime($period = 'auto'): array
55
56
{
56
57
$ this ->stageIds = $ this ->allStageIds ;
57
58
59
+ $ period = $ this ->determinePeriod ($ period );
60
+
58
61
return $ this ->getOverTimeStats ($ this ->startDate , $ this ->endDate , 'leads.id ' , 'created_at ' , $ period );
59
62
}
60
63
@@ -67,6 +70,8 @@ public function getTotalWonLeadsOverTime($period = 'auto'): array
67
70
{
68
71
$ this ->stageIds = $ this ->wonStageIds ;
69
72
73
+ $ period = $ this ->determinePeriod ($ period );
74
+
70
75
return $ this ->getOverTimeStats ($ this ->startDate , $ this ->endDate , 'leads.id ' , 'closed_at ' , $ period );
71
76
}
72
77
@@ -79,9 +84,37 @@ public function getTotalLostLeadsOverTime($period = 'auto'): array
79
84
{
80
85
$ this ->stageIds = $ this ->lostStageIds ;
81
86
87
+ $ period = $ this ->determinePeriod ($ period );
88
+
82
89
return $ this ->getOverTimeStats ($ this ->startDate , $ this ->endDate , 'leads.id ' , 'closed_at ' , $ period );
83
90
}
84
91
92
+ /**
93
+ * Determine the appropriate period based on date range
94
+ *
95
+ * @param string $period
96
+ */
97
+ protected function determinePeriod ($ period = 'auto ' ): string
98
+ {
99
+ if ($ period !== 'auto ' ) {
100
+ return $ period ;
101
+ }
102
+
103
+ $ diffInDays = $ this ->startDate ->diffInDays ($ this ->endDate );
104
+ $ diffInMonths = $ this ->startDate ->diffInMonths ($ this ->endDate );
105
+ $ diffInYears = $ this ->startDate ->diffInYears ($ this ->endDate );
106
+
107
+ if ($ diffInYears > 3 ) {
108
+ return 'year ' ;
109
+ } elseif ($ diffInMonths > 6 ) {
110
+ return 'month ' ;
111
+ } elseif ($ diffInDays > 60 ) {
112
+ return 'week ' ;
113
+ } else {
114
+ return 'day ' ;
115
+ }
116
+ }
117
+
85
118
/**
86
119
* Retrieves total leads and their progress.
87
120
*/
@@ -311,41 +344,140 @@ public function getOpenLeadsByStates()
311
344
* @param \Carbon\Carbon $startDate
312
345
* @param \Carbon\Carbon $endDate
313
346
* @param string $valueColumn
347
+ * @param string $dateColumn
314
348
* @param string $period
315
349
*/
316
350
public function getOverTimeStats ($ startDate , $ endDate , $ valueColumn , $ dateColumn = 'created_at ' , $ period = 'auto ' ): array
317
351
{
318
- $ config = $ this ->getTimeInterval ( $ startDate , $ endDate , $ dateColumn , $ period );
352
+ $ period = $ this ->determinePeriod ( $ period );
319
353
320
- $ groupColumn = $ config ['group_column ' ];
354
+ $ intervals = $ this ->generateTimeIntervals ($ startDate , $ endDate , $ period );
355
+
356
+ $ groupColumn = $ this ->getGroupColumn ($ dateColumn , $ period );
321
357
322
358
$ query = $ this ->leadRepository
323
359
->resetModel ()
324
360
->select (
325
361
DB ::raw ("$ groupColumn AS date " ),
326
- DB ::raw (DB :: getTablePrefix (). " $ valueColumn AS total " ),
327
- DB ::raw (' COUNT(* ) AS count ' )
362
+ DB ::raw (' COUNT(DISTINCT id) AS count ' ),
363
+ DB ::raw (" SUM( $ valueColumn ) AS total " )
328
364
)
329
365
->whereIn ('lead_pipeline_stage_id ' , $ this ->stageIds )
330
366
->whereBetween ($ dateColumn , [$ startDate , $ endDate ])
331
- ->groupBy ('date ' );
332
-
333
- if (! empty ($ stageIds )) {
334
- $ query ->whereIn ('lead_pipeline_stage_id ' , $ stageIds );
335
- }
367
+ ->groupBy (DB ::raw ($ groupColumn ))
368
+ ->orderBy (DB ::raw ($ groupColumn ));
336
369
337
370
$ results = $ query ->get ();
371
+ $ resultLookup = $ results ->keyBy ('date ' );
338
372
339
- foreach ($ config ['intervals ' ] as $ interval ) {
340
- $ total = $ results ->where ('date ' , $ interval ['filter ' ])->first ();
373
+ $ stats = [];
374
+
375
+ foreach ($ intervals as $ interval ) {
376
+ $ result = $ resultLookup ->get ($ interval ['key ' ]);
341
377
342
378
$ stats [] = [
343
- 'label ' => $ interval ['start ' ],
344
- 'total ' => $ total ?->total ?? 0 ,
345
- 'count ' => $ total ?->count ?? 0 ,
379
+ 'label ' => $ interval ['label ' ],
380
+ 'count ' => $ result ? (int ) $ result ->count : 0 ,
381
+ 'total ' => $ result ? (float ) $ result ->total : 0 ,
382
+ ];
383
+ }
384
+
385
+ return $ stats ;
386
+ }
387
+
388
+ /**
389
+ * Generate time intervals based on period
390
+ */
391
+ protected function generateTimeIntervals (Carbon $ startDate , Carbon $ endDate , string $ period ): array
392
+ {
393
+ $ intervals = [];
394
+ $ current = $ startDate ->copy ();
395
+
396
+ while ($ current <= $ endDate ) {
397
+ $ interval = [
398
+ 'key ' => $ this ->formatDateForGrouping ($ current , $ period ),
399
+ 'label ' => $ this ->formatDateForLabel ($ current , $ period ),
346
400
];
401
+
402
+ $ intervals [] = $ interval ;
403
+
404
+ switch ($ period ) {
405
+ case 'day ' :
406
+ $ current ->addDay ();
407
+
408
+ break ;
409
+ case 'week ' :
410
+ $ current ->addWeek ();
411
+
412
+ break ;
413
+ case 'month ' :
414
+ $ current ->addMonth ();
415
+
416
+ break ;
417
+ case 'year ' :
418
+ $ current ->addYear ();
419
+
420
+ break ;
421
+ }
347
422
}
348
423
349
- return $ stats ?? [];
424
+ return $ intervals ;
425
+ }
426
+
427
+ /**
428
+ * Get the SQL group column based on period
429
+ */
430
+ protected function getGroupColumn (string $ dateColumn , string $ period ): string
431
+ {
432
+ switch ($ period ) {
433
+ case 'day ' :
434
+ return "DATE( $ dateColumn) " ;
435
+ case 'week ' :
436
+ return "DATE_FORMAT( $ dateColumn, '%Y-%u') " ;
437
+ case 'month ' :
438
+ return "DATE_FORMAT( $ dateColumn, '%Y-%m') " ;
439
+ case 'year ' :
440
+ return "YEAR( $ dateColumn) " ;
441
+ default :
442
+ return "DATE( $ dateColumn) " ;
443
+ }
444
+ }
445
+
446
+ /**
447
+ * Format date for grouping key
448
+ */
449
+ protected function formatDateForGrouping (Carbon $ date , string $ period ): string
450
+ {
451
+ switch ($ period ) {
452
+ case 'day ' :
453
+ return $ date ->format ('Y-m-d ' );
454
+ case 'week ' :
455
+ return $ date ->format ('Y-W ' );
456
+ case 'month ' :
457
+ return $ date ->format ('Y-m ' );
458
+ case 'year ' :
459
+ return $ date ->format ('Y ' );
460
+ default :
461
+ return $ date ->format ('Y-m-d ' );
462
+ }
463
+ }
464
+
465
+ /**
466
+ * Format date for display label
467
+ */
468
+ protected function formatDateForLabel (Carbon $ date , string $ period ): string
469
+ {
470
+ switch ($ period ) {
471
+ case 'day ' :
472
+ return $ date ->format ('M d ' );
473
+ case 'week ' :
474
+ return 'Week ' .$ date ->format ('W, Y ' );
475
+ case 'month ' :
476
+ return $ date ->format ('M Y ' );
477
+ case 'year ' :
478
+ return $ date ->format ('Y ' );
479
+ default :
480
+ return $ date ->format ('M d ' );
481
+ }
350
482
}
351
483
}
0 commit comments