added scheda cliente
This commit is contained in:
@@ -95,32 +95,16 @@ class MagoSalesStats
|
||||
$by[$c]['orders'][] = $r;
|
||||
}
|
||||
|
||||
$today = new DateTime('today');
|
||||
$out = [];
|
||||
foreach ($by as $c) {
|
||||
$dates = array_keys($c['dates']);
|
||||
sort($dates);
|
||||
$n = count($dates);
|
||||
if ($n < self::DORMANT_MIN_ORDERS) continue;
|
||||
|
||||
$gaps = [];
|
||||
for ($k = 1; $k < $n; $k++) {
|
||||
$gaps[] = (int)(new DateTime($dates[$k - 1]))->diff(new DateTime($dates[$k]))->days;
|
||||
}
|
||||
sort($gaps);
|
||||
$m = count($gaps);
|
||||
$median = $m % 2 ? $gaps[intdiv($m, 2)] : ($gaps[$m / 2 - 1] + $gaps[$m / 2]) / 2;
|
||||
$rhythm = max(7, (float)$median);
|
||||
|
||||
$last = end($dates);
|
||||
$since = (int)(new DateTime($last))->diff($today)->days;
|
||||
if ($since < self::DORMANT_MIN_DAYS) continue;
|
||||
|
||||
$ratio = $since / $rhythm;
|
||||
if ($ratio >= self::DORMANT_LOST || $since >= 365) $level = 'lost';
|
||||
elseif ($ratio >= self::DORMANT_SLEEP) $level = 'dormant';
|
||||
elseif ($ratio >= self::DORMANT_WATCH) $level = 'watch';
|
||||
else continue;
|
||||
$info = self::rhythmInfo(array_keys($c['dates']));
|
||||
if (!$info || !in_array($info['level'], ['watch', 'dormant', 'lost'], true)) continue;
|
||||
$last = $info['last_date'];
|
||||
$since = $info['days_since'];
|
||||
$rhythm = $info['rhythm'];
|
||||
$ratio = $info['ratio'];
|
||||
$level = $info['level'];
|
||||
$n = $info['orders'];
|
||||
|
||||
// ordinato nei 12 mesi fino all'ultimo ordine = quanto vale il cliente "a regime"
|
||||
$from12 = (new DateTime($last))->modify('-365 days')->format('Y-m-d');
|
||||
@@ -142,8 +126,8 @@ class MagoSalesStats
|
||||
'last_date' => $last,
|
||||
'last_no' => $lastOrder['ord_no'],
|
||||
'days_since' => $since,
|
||||
'rhythm' => (int)round($rhythm),
|
||||
'ratio' => round($ratio, 1),
|
||||
'rhythm' => $rhythm,
|
||||
'ratio' => $ratio,
|
||||
'orders' => $n,
|
||||
'value12' => round($v12, 2),
|
||||
'level' => $level,
|
||||
@@ -155,6 +139,45 @@ class MagoSalesStats
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ritmo d'ordine di un cliente a partire dalle date d'ordine (Y-m-d) degli ultimi DORMANT_WINDOW_YEARS anni.
|
||||
* level: 'ok' | 'watch' | 'dormant' | 'lost' | 'few' (troppo pochi ordini per stimare un ritmo)
|
||||
*/
|
||||
public static function rhythmInfo(array $dates)
|
||||
{
|
||||
$dates = array_values(array_unique($dates));
|
||||
sort($dates);
|
||||
$n = count($dates);
|
||||
if (!$n) return null;
|
||||
|
||||
$today = new DateTime('today');
|
||||
$last = end($dates);
|
||||
$since = (int)(new DateTime($last))->diff($today)->days;
|
||||
$out = ['orders' => $n, 'last_date' => $last, 'days_since' => $since, 'rhythm' => null, 'ratio' => null, 'level' => 'few'];
|
||||
if ($n < self::DORMANT_MIN_ORDERS) return $out;
|
||||
|
||||
$gaps = [];
|
||||
for ($k = 1; $k < $n; $k++) {
|
||||
$gaps[] = (int)(new DateTime($dates[$k - 1]))->diff(new DateTime($dates[$k]))->days;
|
||||
}
|
||||
sort($gaps);
|
||||
$m = count($gaps);
|
||||
$median = $m % 2 ? $gaps[intdiv($m, 2)] : ($gaps[$m / 2 - 1] + $gaps[$m / 2]) / 2;
|
||||
$rhythm = max(7, (float)$median);
|
||||
$ratio = $since / $rhythm;
|
||||
|
||||
if ($since < self::DORMANT_MIN_DAYS) $level = 'ok';
|
||||
elseif ($ratio >= self::DORMANT_LOST || $since >= 365) $level = 'lost';
|
||||
elseif ($ratio >= self::DORMANT_SLEEP) $level = 'dormant';
|
||||
elseif ($ratio >= self::DORMANT_WATCH) $level = 'watch';
|
||||
else $level = 'ok';
|
||||
|
||||
$out['rhythm'] = (int)round($rhythm);
|
||||
$out['ratio'] = round($ratio, 1);
|
||||
$out['level'] = $level;
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Previsione di fine anno: valore dell'anno in corso ad oggi diviso la quota che, negli anni
|
||||
* precedenti (max 3), si era raggiunta alla stessa data. $rows: [y, full, ytd].
|
||||
|
||||
Reference in New Issue
Block a user