Files
breadcrumb-the-shire/lib/Service/Org/DepartmentService.php

281 lines
9.3 KiB
PHP
Raw Normal View History

2026-02-04 23:31:53 +01:00
<?php
2026-02-11 19:28:12 +01:00
namespace MintyPHP\Service\Org;
2026-02-04 23:31:53 +01:00
2026-02-11 19:28:12 +01:00
use MintyPHP\Repository\Org\DepartmentRepository;
2026-02-23 12:58:19 +01:00
use MintyPHP\Service\Directory\DirectoryScopeGateway;
use MintyPHP\Service\Directory\DirectorySettingsGateway;
use MintyPHP\Service\Settings\SettingServicesFactory;
use MintyPHP\Service\User\UserServicesFactory;
2026-02-04 23:31:53 +01:00
class DepartmentService
{
2026-02-23 12:58:19 +01:00
public function __construct(
private readonly ?DepartmentRepository $departmentRepository = null,
private readonly ?UserServicesFactory $userServicesFactory = null,
private readonly ?DirectorySettingsGateway $settingsGateway = null,
private readonly ?DirectoryScopeGateway $scopeGateway = null
) {
}
public function list(): array
2026-02-04 23:31:53 +01:00
{
2026-02-23 12:58:19 +01:00
return $this->departmentRepository()->list();
2026-02-04 23:31:53 +01:00
}
2026-02-23 12:58:19 +01:00
public function listPaged(array $options): array
2026-02-04 23:31:53 +01:00
{
if (!empty($options['tenantUserId'])) {
$tenantUserId = (int) $options['tenantUserId'];
2026-02-23 12:58:19 +01:00
if ($tenantUserId > 0 && $this->scopeGateway()->hasGlobalAccess($tenantUserId)) {
2026-02-04 23:31:53 +01:00
unset($options['tenantUserId'], $options['tenantIds']);
}
}
2026-02-23 12:58:19 +01:00
return $this->departmentRepository()->listPaged($options);
2026-02-04 23:31:53 +01:00
}
2026-02-23 12:58:19 +01:00
public function listByTenantIds(array $tenantIds): array
2026-02-04 23:31:53 +01:00
{
2026-02-23 12:58:19 +01:00
return $this->departmentRepository()->listByTenantIds($tenantIds);
2026-02-04 23:31:53 +01:00
}
2026-02-23 12:58:19 +01:00
public function groupActiveByTenantIds(array $tenantIds): array
{
$tenantIds = array_values(array_unique(array_map('intval', $tenantIds)));
$tenantIds = array_values(array_filter($tenantIds, static fn ($id) => $id > 0));
if (!$tenantIds) {
return [];
}
2026-02-23 12:58:19 +01:00
$departments = $this->listByTenantIds($tenantIds);
if (!$departments) {
return [];
}
$grouped = [];
foreach ($departments as $department) {
$tenantId = (int) ($department['tenant_id'] ?? 0);
if ($tenantId <= 0) {
continue;
}
$grouped[$tenantId] ??= [];
$grouped[$tenantId][] = $department;
}
foreach ($grouped as &$items) {
usort($items, static function (array $a, array $b): int {
return strcmp((string) ($a['description'] ?? ''), (string) ($b['description'] ?? ''));
});
}
unset($items);
return $grouped;
}
2026-02-23 12:58:19 +01:00
public function listByIds(array $departmentIds): array
2026-02-04 23:31:53 +01:00
{
2026-02-23 12:58:19 +01:00
return $this->departmentRepository()->listByIds($departmentIds);
2026-02-04 23:31:53 +01:00
}
2026-02-23 12:58:19 +01:00
public function listForUserAssignments(array $tenantIds, array $selectedDepartmentIds): array
2026-02-04 23:31:53 +01:00
{
2026-02-23 12:58:19 +01:00
$departments = $tenantIds ? $this->listByTenantIds($tenantIds) : $this->list();
$extraDepartments = $selectedDepartmentIds ? $this->listByIds($selectedDepartmentIds) : [];
2026-02-04 23:31:53 +01:00
if (!$extraDepartments) {
return $departments;
}
$departmentMap = [];
foreach ($departments as $department) {
if (isset($department['id'])) {
$departmentMap[(int) $department['id']] = $department;
}
}
foreach ($extraDepartments as $department) {
if (isset($department['id'])) {
$departmentMap[(int) $department['id']] = $department;
}
}
return array_values($departmentMap);
}
2026-02-23 12:58:19 +01:00
public function findByUuid(string $uuid): ?array
2026-02-04 23:31:53 +01:00
{
2026-02-23 12:58:19 +01:00
return $this->departmentRepository()->findByUuid($uuid);
2026-02-04 23:31:53 +01:00
}
2026-02-23 12:58:19 +01:00
public function findById(int $id): ?array
2026-02-04 23:31:53 +01:00
{
2026-02-23 12:58:19 +01:00
return $this->departmentRepository()->find($id);
2026-02-04 23:31:53 +01:00
}
2026-02-23 12:58:19 +01:00
public function createFromAdmin(array $input, int $currentUserId = 0): array
2026-02-04 23:31:53 +01:00
{
2026-02-23 12:58:19 +01:00
$form = $this->sanitizeBase($input);
$errors = $this->validateBase($form);
$warnings = $this->warningsForCode($form, 0);
2026-02-04 23:31:53 +01:00
if ($errors) {
2026-02-11 19:28:12 +01:00
return ['ok' => false, 'errors' => $errors, 'warnings' => $warnings, 'form' => $form];
2026-02-04 23:31:53 +01:00
}
2026-02-23 12:58:19 +01:00
$createdId = $this->departmentRepository()->create([
2026-02-04 23:31:53 +01:00
'description' => $form['description'],
'tenant_id' => $form['tenant_id'],
2026-02-11 19:28:12 +01:00
'code' => $form['code'] ?: null,
'cost_center' => $form['cost_center'] ?: null,
'active' => $form['active'],
2026-02-04 23:31:53 +01:00
'created_by' => $currentUserId > 0 ? $currentUserId : null,
]);
if (!$createdId) {
return ['ok' => false, 'errors' => [t('Department can not be created')], 'form' => $form];
}
2026-02-23 12:58:19 +01:00
$createdDepartment = $this->departmentRepository()->find((int) $createdId);
2026-02-04 23:31:53 +01:00
$uuid = $createdDepartment['uuid'] ?? null;
if (!empty($input['is_default'])) {
2026-02-23 12:58:19 +01:00
$this->settingsGateway()->setDefaultDepartmentId((int) $createdId);
2026-02-04 23:31:53 +01:00
}
2026-02-11 19:28:12 +01:00
return ['ok' => true, 'form' => $form, 'warnings' => $warnings, 'uuid' => $uuid, 'id' => (int) $createdId];
2026-02-04 23:31:53 +01:00
}
2026-02-23 12:58:19 +01:00
public function updateFromAdmin(int $departmentId, array $input, int $currentUserId = 0): array
2026-02-04 23:31:53 +01:00
{
2026-02-23 12:58:19 +01:00
$form = $this->sanitizeBase($input);
$errors = $this->validateBase($form);
$warnings = $this->warningsForCode($form, $departmentId);
2026-02-04 23:31:53 +01:00
if ($errors) {
2026-02-11 19:28:12 +01:00
return ['ok' => false, 'errors' => $errors, 'warnings' => $warnings, 'form' => $form];
2026-02-04 23:31:53 +01:00
}
2026-02-23 12:58:19 +01:00
$updated = $this->departmentRepository()->update($departmentId, [
2026-02-04 23:31:53 +01:00
'description' => $form['description'],
'tenant_id' => $form['tenant_id'],
2026-02-11 19:28:12 +01:00
'code' => $form['code'] ?: null,
'cost_center' => $form['cost_center'] ?: null,
'active' => $form['active'],
2026-02-04 23:31:53 +01:00
'modified_by' => $currentUserId > 0 ? $currentUserId : null,
]);
if (!$updated) {
return ['ok' => false, 'errors' => [t('Department can not be updated')], 'form' => $form];
}
2026-02-11 19:28:12 +01:00
return ['ok' => true, 'form' => $form, 'warnings' => $warnings];
2026-02-04 23:31:53 +01:00
}
2026-02-23 12:58:19 +01:00
public function syncTenant(int $departmentId, int $tenantId): int
2026-02-04 23:31:53 +01:00
{
2026-02-23 12:58:19 +01:00
$updated = $this->departmentRepository()->setTenant($departmentId, $tenantId);
2026-02-04 23:31:53 +01:00
if (!$updated) {
return -1;
}
2026-02-23 12:58:19 +01:00
return $this->cleanupUserAssignments($departmentId);
}
2026-02-23 12:58:19 +01:00
public function syncTenants(int $departmentId, array $tenantIds): int
{
$tenantId = (int) ($tenantIds[0] ?? 0);
if ($tenantId <= 0) {
return -1;
}
2026-02-23 12:58:19 +01:00
return $this->syncTenant($departmentId, $tenantId);
}
2026-02-23 12:58:19 +01:00
public function cleanupUserAssignments(int $departmentId): int
{
2026-02-23 12:58:19 +01:00
return $this->userServicesFactory()
->createUserDepartmentRepository()
->removeInvalidForDepartment($departmentId);
2026-02-04 23:31:53 +01:00
}
2026-02-23 12:58:19 +01:00
public function deleteByUuid(string $uuid): array
2026-02-04 23:31:53 +01:00
{
$uuid = trim($uuid);
if ($uuid === '') {
return ['ok' => false, 'status' => 404, 'error' => 'not_found'];
}
2026-02-23 12:58:19 +01:00
$department = $this->departmentRepository()->findByUuid($uuid);
2026-02-04 23:31:53 +01:00
if (!$department || !isset($department['id'])) {
return ['ok' => false, 'status' => 404, 'error' => 'not_found'];
}
2026-02-23 12:58:19 +01:00
$deleted = $this->departmentRepository()->delete((int) $department['id']);
2026-02-04 23:31:53 +01:00
if (!$deleted) {
return ['ok' => false, 'status' => 500, 'error' => 'delete_failed'];
}
return ['ok' => true, 'department' => $department];
}
2026-02-23 12:58:19 +01:00
private function sanitizeBase(array $input): array
2026-02-04 23:31:53 +01:00
{
return [
'description' => trim((string) ($input['description'] ?? '')),
'tenant_id' => (int) ($input['tenant_id'] ?? 0),
2026-02-11 19:28:12 +01:00
'code' => trim((string) ($input['code'] ?? '')),
'cost_center' => trim((string) ($input['cost_center'] ?? '')),
2026-02-23 12:58:19 +01:00
'active' => $this->normalizeActive($input['active'] ?? 1),
2026-02-04 23:31:53 +01:00
];
}
2026-02-23 12:58:19 +01:00
private function validateBase(array $form): array
2026-02-04 23:31:53 +01:00
{
$errors = [];
if ($form['description'] === '') {
$errors[] = t('Description cannot be empty');
}
if ((int) ($form['tenant_id'] ?? 0) <= 0) {
$errors[] = t('Please select at least one tenant');
}
2026-02-04 23:31:53 +01:00
return $errors;
}
2026-02-11 19:28:12 +01:00
2026-02-23 12:58:19 +01:00
private function warningsForCode(array $form, int $excludeId): array
2026-02-11 19:28:12 +01:00
{
$warnings = [];
$code = $form['code'] ?? '';
2026-02-23 12:58:19 +01:00
if ($code !== '' && $this->departmentRepository()->existsByCode($code, $excludeId)) {
2026-02-11 19:28:12 +01:00
$warnings[] = t('Department code already exists');
}
return $warnings;
}
2026-02-23 12:58:19 +01:00
private function normalizeActive($value): int
2026-02-11 19:28:12 +01:00
{
$value = strtolower(trim((string) $value));
if (in_array($value, ['0', 'false', 'inactive'], true)) {
return 0;
}
return 1;
}
2026-02-23 12:58:19 +01:00
private function departmentRepository(): DepartmentRepository
{
return $this->departmentRepository ?? new DepartmentRepository();
}
private function userServicesFactory(): UserServicesFactory
{
return $this->userServicesFactory ?? new UserServicesFactory();
}
private function settingsGateway(): DirectorySettingsGateway
{
if ($this->settingsGateway instanceof DirectorySettingsGateway) {
return $this->settingsGateway;
}
return new DirectorySettingsGateway(
(new SettingServicesFactory())->createSettingGateway()
);
}
private function scopeGateway(): DirectoryScopeGateway
{
return $this->scopeGateway ?? new DirectoryScopeGateway();
}
2026-02-04 23:31:53 +01:00
}