format === 'json' ? self::jsonResponse($context) : self::pageResponse($request, $context); } private static function buildContext(Request $request): array { $starting = isset($request->dates) ? (string) $request->dates : date('Y-m-d', strtotime('-1 days')); $schema = Schema::connection(config('m3.connection', 'pgsql')); $users = self::users($schema); $user = isset($request->user) ? (string) $request->user : ''; $empno = 0; foreach ($users as $candidate) { if ($candidate['userprf'] === $user) { $empno = $candidate['empno']; break; } } return [ 'starting' => $starting, 'schema' => $schema, 'users' => $users, 'user' => $user, 'empno' => $empno, 'targets' => Config::get('arrays_custom.lph_per_code_array', []), 'statistics' => [], 'lbpfRows' => [], 'lbpf' => 0, 'monitor' => [], 'totals' => ['value' => 0, 'weight' => 0, 'timediff' => 0, 'picked' => 0, 'entries' => 0], 'performance' => [], ]; } private static function users($schema): array { if (! $schema->hasTable('icm428m')) { return []; } $connection = DB::connection(config('m3.connection', 'pgsql')); $profile = $connection->table('icm428m')->select('R428CO', 'R428WH') ->where('R428US', strtoupper(m3User()))->first(); $rows = $connection->table('icm428m') ->selectRaw("R428US as userprf, (trim(R428FIRST) || ' ' || trim(R428FAMILY)) as name, R428EMPCDE as empno") ->where('R428STS', 'A')->where('R428EMPCDE', '!=', 0) ->where('R428CO', $profile->R428CO ?? '')->where('R428WH', $profile->R428WH ?? '')->get(); $users = []; foreach ($rows as $row) { $users[] = ['userprf' => trim($row->USERPRF), 'name' => trim($row->NAME), 'empno' => $row->EMPNO]; } usort($users, static fn (array $a, array $b): int => $a['name'] <=> $b['name']); return $users; } private static function loadPickingData(array &$context): void { $targets = $context['targets']; ksort($targets); $codes = implode(',', array_keys($targets)); $date = $context['starting']; $sql = sprintf( 'select oppno, sum(cast (hrs as integer)+ (hrs-cast (hrs as integer))/0.6) as hrs from LBPF where empno=%d and lbyr=%d and lbmo=%d and lbdy=%d and oppno in (%s) group by oppno', (int) $context['empno'], (int) substr($date, 0, 4) - 2000, (int) substr($date, 5, 2), (int) substr($date, 8, 2), $codes ); $context['lbpfRows'] = $context['schema']->hasTable('lbpf') ? DB::connection(config('m3.connection', 'pgsql'))->select($sql) : []; foreach ($context['lbpfRows'] as $row) { $context['lbpf'] += $row->HRS; } if ((isset(request()->dates) || isset(request()->user)) && $context['schema']->hasTable('perfstat')) { $context['statistics'] = DB::connection(config('m3.connection', 'pgsql'))->table('perfstat') ->where('dt', $date)->where('a5pickcomu', $context['user'])->get()->all(); } } private static function calculatePerformance(array &$context): void { self::initializeMonitors($context); if ($context['statistics'] === []) { return; } self::accumulateStatistics($context); $hours = $context['lbpf']; $context['performance']['tot_hours'] = $hours; $context['performance']['per_hour_actual'] = $hours != 0 ? $context['totals']['entries'] / $hours : 0; self::calculateMonitorTargets($context); $target = $context['monitor'][0]['lph_blended_per_activity'] ?? 0; if ($target != 0) { $context['performance']['performance_activity'] = $context['performance']['per_hour_actual'] / $target; } } private static function initializeMonitors(array &$context): void { foreach ($context['lbpfRows'] as $row) { $context['monitor'][$row->OPPNO] = self::monitorDefaults('Mon' . $row->OPPNO, $row->HRS); } foreach ($context['statistics'] as $row) { $context['monitor'][$row->CODE] = array_replace( self::monitorDefaults('Mon' . $row->CODE, 0), $context['monitor'][$row->CODE] ?? [] ); } if ($context['statistics'] !== []) { $context['monitor'][0] = self::monitorDefaults('0', 0); } } private static function monitorDefaults(string $header, float|int $hours): array { return ['tot_hours' => $hours, 'header' => $header, 'timediff' => 0, 'percent_per_monitor' => 0, 'percent_per_activity' => 0, 'lph_blended_per_activity' => 0, 'picked' => 0, 'weight' => 0, 'lines' => 0]; } private static function accumulateStatistics(array &$context): void { $previous = null; $limit = (float) Config::get('arrays.ignore_picks_that_last_longer_than_this_many_hours', 8); foreach ($context['statistics'] as $row) { $row->WEIGHT = round($row->WEIGHT); $row->A5VALUE = round($row->A5VALUE); $row->A5PICKED = round($row->A5PICKED); $row->A5PICKCMTS = date('Y-m-d H:i', strtotime($row->A5PICKCMTS)); $now = strtotime($row->A5CMTSADJ); $diff = $previous === null ? 0 : round(abs($now - $previous)); $diff = $diff > $limit * 3600 ? -1 : $diff; $row->TIMEDIFF = $diff; $row->COLOUR = self::durationColour($diff); $previous = $now; self::addRowTotals($context, $row, $diff); } } private static function durationColour(float|int $diff): string { $minutes = $diff / 60; return match (true) { $minutes < 5 => '', $minutes <= 10 => 'yellow', $minutes <= 15 => '#88ace0', default => 'red', }; } private static function addRowTotals(array &$context, object $row, float|int $diff): void { $monitor = &$context['monitor'][$row->CODE]; $monitor['timediff'] += $diff; $monitor['picked'] += $row->A5PICKED; $monitor['weight'] += $row->WEIGHT; $monitor['lines']++; $context['totals']['entries']++; $context['totals']['weight'] += $row->WEIGHT; $context['totals']['value'] += $row->A5VALUE; $context['totals']['timediff'] += $diff; $context['totals']['picked'] += $row->A5PICKED; } private static function calculateMonitorTargets(array &$context): void { ksort($context['monitor']); foreach ($context['monitor'] as $code => &$monitor) { if ((string) $code === '0') { continue; } $monitor['percent_per_monitor'] = $context['totals']['timediff'] != 0 ? $monitor['timediff'] / $context['totals']['timediff'] : 0; $monitor['percent_per_activity'] = $context['lbpf'] != 0 ? $monitor['tot_hours'] / $context['lbpf'] : 0; $monitor['lph_blended_per_activity'] = $monitor['percent_per_activity'] * ($context['targets'][$code] ?? 0); $context['monitor'][0]['lph_blended_per_activity'] += $monitor['lph_blended_per_activity']; } unset($monitor); } private static function jsonResponse(array $context): string { return json_encode([ 'day' => $context['starting'], 'performance' => number_format(($context['performance']['performance_activity'] ?? 0) * 100, 0), 'blendedTargetLPH' => number_format($context['monitor'][0]['lph_blended_per_activity'] ?? 0, 1), 'actualLPH' => number_format($context['performance']['per_hour_actual'] ?? 0, 1), 'grossHours' => $context['performance']['tot_hours'] ?? 0, ]); } private static function pageResponse(Request $request, array $context) { $request->ports = Config::get('arrays.env_ports'); $no_data = $context['statistics'] === [] && ($_SERVER['REQUEST_URI'] ?? '') !== '/UserPickingStats4' ? 'Y' : 'N'; return view('m3::liberty-theme.pages.UserPickingStats4', [ 'statistic4' => $context['statistics'], 'starting' => $context['starting'], 'user' => $context['user'], 'user_array' => $context['users'], 'monitor_array' => $context['monitor'], 'totals_array' => $context['totals'], 'perf_array' => $context['performance'], 'request' => $request, 'no_data' => $no_data, ]); } }