ultimatepos/Modules/ManagementTools/Utils/ManagementToolsUtil.php

319 lines
9.8 KiB
PHP

<?php
namespace Modules\ManagementTools\Utils;
use App\Utils\Util;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Modules\ManagementTools\Entities\MtSkill;
use Modules\ManagementTools\Entities\MtTool;
class ManagementToolsUtil
{
protected $commonUtil;
public function __construct(Util $commonUtil)
{
$this->commonUtil = $commonUtil;
}
/**
* Convert user-entered date (Jalali or Gregorian) to MySQL Y-m-d.
*/
public function parseInputDate(?string $date): ?string
{
if (empty($date)) {
return null;
}
if (function_exists('jalali_to_gregorian')) {
$converted = jalali_to_gregorian($date, session('business.date_format', 'Y/m/d'), false);
if (! empty($converted) && preg_match('/^\d{4}-\d{2}-\d{2}/', $converted)) {
return $converted;
}
}
return $this->commonUtil->uf_date($date);
}
/**
* Convert user-entered datetime to MySQL Y-m-d H:i:s.
*/
public function parseInputDateTime(?string $date): ?string
{
if (empty($date)) {
return null;
}
if (function_exists('jalali_to_gregorian')) {
$converted = jalali_to_gregorian($date, session('business.date_format', 'Y/m/d'), true);
if (! empty($converted) && preg_match('/^\d{4}-\d{2}-\d{2}/', $converted)) {
return $converted;
}
}
return $this->commonUtil->uf_date($date, true);
}
/**
* Format a stored date for display/inputs — always Jalali in this module.
*/
public function formatForInput($date): ?string
{
if (empty($date)) {
return null;
}
try {
$carbon = $date instanceof \Carbon\Carbon ? $date->copy() : \Carbon\Carbon::parse($date);
$format = session('business.date_format', 'Y/m/d');
$formatted = format_jalali_date($carbon, $format);
return function_exists('persian_number') ? persian_number($formatted) : $formatted;
} catch (\Exception $e) {
return format_date($date);
}
}
/**
* Format a stored datetime for display/inputs — always Jalali in this module.
*/
public function formatDateTimeForInput($date): ?string
{
if (empty($date)) {
return null;
}
try {
$carbon = $date instanceof \Carbon\Carbon ? $date->copy() : \Carbon\Carbon::parse($date);
$format = session('business.date_format', 'Y/m/d');
$time_format = session('business.time_format', 24) == 12 ? ' h:i A' : ' H:i';
$formatted = format_jalali_date($carbon, $format.$time_format);
return function_exists('persian_number') ? persian_number($formatted) : $formatted;
} catch (\Exception $e) {
return format_datetime($date);
}
}
/**
* Shorthand for views — format date in Jalali.
*/
public function formatDate($date): ?string
{
return $this->formatForInput($date);
}
/**
* Shorthand for views — format datetime in Jalali.
*/
public function formatDateTime($date): ?string
{
return $this->formatDateTimeForInput($date);
}
/**
* Build hierarchical tree from flat collection.
*/
public function buildTree(Collection $items, $parent_id = null, $depth = 0): array
{
$branch = [];
foreach ($items->where('parent_id', $parent_id) as $item) {
$node = $item->toArray();
$node['depth'] = $depth;
$node['children'] = $this->buildTree($items, $item->id, $depth + 1);
$branch[] = $node;
}
return $branch;
}
/**
* Flatten tree for table display with indentation.
*/
public function flattenTree(array $tree, &$flat = []): array
{
foreach ($tree as $node) {
$children = $node['children'] ?? [];
unset($node['children']);
$flat[] = $node;
if (! empty($children)) {
$this->flattenTree($children, $flat);
}
}
return $flat;
}
public function getSkillsDropdown($business_id, $exclude_id = null): array
{
$query = MtSkill::forBusiness($business_id)->orderBy('title');
if ($exclude_id) {
$query->where('id', '!=', $exclude_id);
}
return $query->pluck('title', 'id')->toArray();
}
public function getToolsDropdown($business_id, $exclude_id = null): array
{
$query = MtTool::forBusiness($business_id)->orderBy('title');
if ($exclude_id) {
$query->where('id', '!=', $exclude_id);
}
return $query->pluck('title', 'id')->toArray();
}
public function parseToolAttributes(array $names, array $values): array
{
$attributes = [];
foreach ($names as $key => $name) {
$name = trim((string) $name);
if ($name === '') {
continue;
}
$attributes[$name] = $values[$key] ?? '';
}
return $attributes;
}
/**
* Assigned skills for a user: [skill_id => skill_level].
*/
public function getUserAssignedSkills(int $business_id, int $user_id): array
{
return DB::table('mt_user_skill')
->where('business_id', $business_id)
->where('user_id', $user_id)
->pluck('skill_level', 'skill_id')
->toArray();
}
/**
* Skills with title and level for profile display.
*/
public function getUserSkillsList(int $business_id, int $user_id): Collection
{
return DB::table('mt_user_skill as us')
->join('mt_skills as s', 's.id', '=', 'us.skill_id')
->where('us.business_id', $business_id)
->where('us.user_id', $user_id)
->select('s.id', 's.title', 'us.skill_level')
->orderBy('s.title')
->get();
}
/**
* Sync employee skills (replace all).
*/
public function syncUserSkills(int $business_id, int $user_id, ?array $skill_ids, ?array $skill_levels = []): void
{
DB::table('mt_user_skill')
->where('business_id', $business_id)
->where('user_id', $user_id)
->delete();
foreach ($skill_ids ?? [] as $skill_id) {
DB::table('mt_user_skill')->insert([
'business_id' => $business_id,
'skill_id' => (int) $skill_id,
'user_id' => $user_id,
'skill_level' => (int) ($skill_levels[$skill_id] ?? 1),
'created_at' => now(),
'updated_at' => now(),
]);
}
}
/**
* Sync employee tools (replace all).
*/
public function syncUserTools(int $business_id, int $user_id, ?array $tool_ids): void
{
DB::table('mt_user_tool')
->where('business_id', $business_id)
->where('user_id', $user_id)
->delete();
foreach ($tool_ids ?? [] as $tool_id) {
DB::table('mt_user_tool')->insert([
'business_id' => $business_id,
'tool_id' => (int) $tool_id,
'user_id' => $user_id,
'created_at' => now(),
'updated_at' => now(),
]);
}
}
/**
* Report: employee count per skill.
*/
public function getSkillsEmployeeReport(int $business_id): array
{
$skills = MtSkill::forBusiness($business_id)->orderBy('title')->get();
$total_employees = DB::table('users')
->where('business_id', $business_id)
->where('user_type', 'user')
->where('allow_login', 1)
->whereNull('deleted_at')
->count();
$assigned_user_ids = DB::table('mt_user_skill')
->where('business_id', $business_id)
->distinct()
->pluck('user_id');
$rows = $skills->map(function ($skill) use ($business_id) {
$employees = DB::table('mt_user_skill as us')
->join('users as u', 'u.id', '=', 'us.user_id')
->where('us.business_id', $business_id)
->where('us.skill_id', $skill->id)
->where('u.user_type', 'user')
->where('u.allow_login', 1)
->whereNull('u.deleted_at')
->select('u.id', 'u.first_name', 'u.last_name', 'u.surname', 'us.skill_level')
->orderBy('u.first_name')
->get();
return (object) [
'skill' => $skill,
'employee_count' => $employees->count(),
'employees' => $employees,
];
});
return [
'rows' => $rows,
'total_employees' => $total_employees,
'employees_with_skills' => $assigned_user_ids->count(),
'employees_without_skills' => max(0, $total_employees - $assigned_user_ids->count()),
'unassigned_skills' => $rows->where('employee_count', 0)->count(),
];
}
public function getUserRecentScores(int $business_id, int $user_id, int $limit = 6)
{
return \Modules\ManagementTools\Entities\MtUserScore::forBusiness($business_id)
->where('user_id', $user_id)
->with('scoreCard')
->orderByDesc('created_at')
->limit($limit)
->get();
}
public function getUserTotalScorePoints(int $business_id, int $user_id): float
{
return \Modules\ManagementTools\Entities\MtUserScore::forBusiness($business_id)
->where('user_id', $user_id)
->with('scoreCard')
->get()
->sum(function ($s) {
return $s->scoreCard ? (float) $s->scoreCard->points : (float) $s->score;
});
}
}