Commit 2a927814 authored by Stephane Bouvry's avatar Stephane Bouvry
Browse files

Backup (refonte paramètres)

parent e603b7ce
Loading
Loading
Loading
Loading
+118 −0
Original line number Diff line number Diff line
{
  "version": 1,
  "parameters": [
    {
      "key": "allow_numerotation_custom",
      "label": "Type de numerotation personnalisable",
      "description": "Autorise l'ajout de types de numerotation non references.",
      "category": "Activites de recherche",
      "type": "boolean",
      "default": false
    },
    {
      "key": "frais_de_gestion_inclus",
      "label": "Frais de gestion inclus",
      "description": "Indique si le montant saisi inclut les frais de gestion.",
      "category": "Activites de recherche",
      "type": "boolean",
      "default": false
    },
    {
      "key": "activity_request_limit",
      "label": "Nombre maximum de demandes",
      "description": "Utiliser -1 pour desactiver la limite.",
      "category": "Activites de recherche",
      "type": "integer",
      "default": 5
    },
    {
      "key": "allow_node_selection",
      "label": "Selection de tous les types d'activites",
      "description": "Active la selection de tous les types d'activites.",
      "category": "Activites de recherche",
      "type": "boolean",
      "default": true
    },
    {
      "key": "spents_account_filter",
      "label": "Comptes exclus (depenses)",
      "description": "Liste de comptes separes par des virgules.",
      "category": "Depenses / Finances",
      "type": "csv",
      "default": []
    },
    {
      "key": "financial_label",
      "label": "Intitule du numero financier",
      "description": "Libelle affiche pour le numero financier (ex: PFI).",
      "category": "Depenses / Finances",
      "type": "string",
      "default": "PFI"
    },
    {
      "key": "pfi_strict",
      "label": "Mode strict numero financier",
      "description": "Active la validation stricte du numero financier.",
      "category": "Depenses / Finances",
      "type": "boolean",
      "default": true
    },
    {
      "key": "pfi_strict_format",
      "label": "Expression reguliere numero financier",
      "description": "Regex utilisee si le mode strict est actif.",
      "category": "Depenses / Finances",
      "type": "string",
      "default": ""
    },
    {
      "key": "theme",
      "label": "Theme",
      "description": "Theme visuel de l'application.",
      "category": "Apparence",
      "type": "select",
      "options_source": "themes",
      "default": ""
    },
    {
      "key": "document_use_version_in_name",
      "label": "Version dans le nom du document",
      "description": "Ajoute la version au nom de fichier telecharge.",
      "category": "Apparence",
      "type": "boolean",
      "default": false
    },
    {
      "key": "timesheet_preview",
      "label": "Apercu feuille de temps",
      "description": "Autorise l'apercu avant validation numerique.",
      "category": "Feuille de temps",
      "type": "boolean",
      "default": false
    },
    {
      "key": "timesheet_excel",
      "label": "Export Excel feuille de temps",
      "description": "Autorise le telechargement du format Excel.",
      "category": "Feuille de temps",
      "type": "boolean",
      "default": false
    },
    {
      "key": "organization_require_type",
      "label": "Organisation: type obligatoire",
      "description": "Rend le type d'organisation obligatoire sur les formulaires.",
      "category": "Organisations",
      "type": "boolean",
      "default": false
    },
    {
      "key": "organization_require_country",
      "label": "Organisation: pays obligatoire",
      "description": "Rend le pays obligatoire sur les formulaires.",
      "category": "Organisations",
      "type": "boolean",
      "default": false
    }
  ]
}
+262 −1
Original line number Diff line number Diff line
@@ -490,6 +490,66 @@ class AdministrationController extends AbstractOscarController implements
            return $this->ajaxResponse(['pfi' => $pfis]);
        }

        $format = $this->params()->fromQuery('format', '');
        if ($this->isAjax() || $format === 'json') {
            $action = $this->params()->fromQuery('a', 'schema');
            switch ($action) {
                case 'schema':
                    $schema = $this->getAdministrationParametersSchema();
                    return $this->jsonOutput([
                        'schema' => $schema,
                        'values' => $this->getAdministrationParametersCurrentValues(),
                    ]);

                case 'save':
                    if ($this->getHttpXMethod() !== 'POST') {
                        return $this->getResponseBadRequest("Methode invalide");
                    }
                    try {
                        $payload = $this->getJsonPosted();
                        $values = is_array($payload) && array_key_exists('values', $payload) ? $payload['values'] : [];
                        $this->applyAdministrationParametersValues($values);
                        return $this->jsonOutput([
                            'ok' => true,
                            'values' => $this->getAdministrationParametersCurrentValues(),
                        ]);
                    } catch (\Exception $e) {
                        return $this->jsonError($e->getMessage());
                    }

                case 'export':
                    return $this->jsonOutput([
                        'schema_version' => $this->getAdministrationParametersSchemaVersion(),
                        'exported_at' => date(DATE_ATOM),
                        'values' => $this->getAdministrationParametersCurrentValues(),
                    ]);

                case 'import':
                    if ($this->getHttpXMethod() !== 'POST') {
                        return $this->getResponseBadRequest("Methode invalide");
                    }
                    try {
                        $payload = $this->getJsonPosted();
                        $values = [];
                        if (is_array($payload) && array_key_exists('values', $payload) && is_array($payload['values'])) {
                            $values = $payload['values'];
                        } elseif (is_array($payload)) {
                            $values = $payload;
                        }
                        $this->applyAdministrationParametersValues($values);
                        return $this->jsonOutput([
                            'ok' => true,
                            'values' => $this->getAdministrationParametersCurrentValues(),
                        ]);
                    } catch (\Exception $e) {
                        return $this->jsonError($e->getMessage());
                    }

                default:
                    return $this->getResponseBadRequest("Action inconnue '$action'");
            }
        }

        if ($this->getHttpXMethod() == "POST") {
            $option = $this->params()->fromPost('parameter_name');
            switch ($option) {
@@ -624,10 +684,211 @@ class AdministrationController extends AbstractOscarController implements
            "organizationRequire" => [
                "type" => $this->getOscarConfigurationService()->getOrganizationRequired()['type'],
                "country" => $this->getOscarConfigurationService()->getOrganizationRequired()['country']
            ]
            ],
            'activity_person_roles' => $this->getOscarUserContextService()->getAvailabledRolesPersonActivity(),
            'activity_organization_roles' => $this->getOscarUserContextService()->getAvailabledRolesOrganizationActivity(),

            OscarConfigurationService::activity_form_person_roles =>
                $this->getOscarConfigurationService()->getActivityFormPersonRoles(),
            OscarConfigurationService::activity_form_organization_roles =>
                $this->getOscarConfigurationService()->getActivityFormOrganizationRoles(),
        ];
    }

    private function getAdministrationParametersSchemaVersion(): int
    {
        $schema = $this->getAdministrationParametersSchema();
        return intval($schema['version'] ?? 1);
    }

    private function getAdministrationParametersSchemaPath(): string
    {
        return __DIR__ . '/../../../config/administration-parameters.schema.json';
    }

    private function getAdministrationParametersSchema(): array
    {
        $path = $this->getAdministrationParametersSchemaPath();
        if (!file_exists($path)) {
            throw new OscarException("Schema des parametres introuvable");
        }

        $raw = file_get_contents($path);
        if ($raw === false) {
            throw new OscarException("Impossible de lire le schema des parametres");
        }

        $decoded = json_decode($raw, true);
        if (!is_array($decoded)) {
            throw new OscarException("Schema des parametres invalide (JSON)");
        }

        $parameters = $decoded['parameters'] ?? [];
        if (!is_array($parameters)) {
            throw new OscarException("Schema des parametres invalide (parameters)");
        }

        $themes = $this->getOscarConfigurationService()->getConfiguration('themes');

        foreach ($parameters as &$parameter) {
            if (!is_array($parameter)) {
                continue;
            }
            if (($parameter['options_source'] ?? null) === 'themes') {
                $parameter['options'] = array_values($themes);
            }
        }

        $decoded['parameters'] = $parameters;
        return $decoded;
    }

    private function getAdministrationParametersCurrentValues(): array
    {
        $organizationRequired = $this->getOscarConfigurationService()->getOrganizationRequired();

        return [
            OscarConfigurationService::allow_numerotation_custom => $this->getOscarConfigurationService()->getNumerotationEditable(),
            OscarConfigurationService::frais_de_gestion_inclus => $this->getOscarConfigurationService()->getFraisDeGestionInclus(),
            OscarConfigurationService::activity_request_limit => $this->getOscarConfigurationService()->getActivityRequestLimit(),
            OscarConfigurationService::allow_node_selection => $this->getOscarConfigurationService()->isAllowNodeSelection(),
            OscarConfigurationService::spents_account_filter => $this->getOscarConfigurationService()->getSpentAccountFilter(),
            OscarConfigurationService::financial_label => $this->getOscarConfigurationService()->getFinancialLabel(),
            OscarConfigurationService::pfi_strict => $this->getOscarConfigurationService()->isPfiStrict(),
            OscarConfigurationService::pfi_strict_format => $this->getOscarConfigurationService()->getPfiRegex(),
            OscarConfigurationService::theme => $this->getOscarConfigurationService()->getTheme(),
            OscarConfigurationService::document_use_version_in_name => $this->getOscarConfigurationService()->getDocumentUseVersionInName(),
            'timesheet_preview' => $this->getOscarConfigurationService()->getTimesheetPreview(),
            'timesheet_excel' => $this->getOscarConfigurationService()->getTimesheetExcel(),
            'organization_require_type' => boolval($organizationRequired['type'] ?? false),
            'organization_require_country' => boolval($organizationRequired['country'] ?? false),
        ];
    }

    private function applyAdministrationParametersValues($inputValues): void
    {
        if (!is_array($inputValues)) {
            throw new OscarException("Format de donnees invalide");
        }

        $schema = $this->getAdministrationParametersSchema();
        $definitions = [];
        foreach (($schema['parameters'] ?? []) as $parameter) {
            if (is_array($parameter) && array_key_exists('key', $parameter)) {
                $definitions[$parameter['key']] = $parameter;
            }
        }

        $incoming = [];

        foreach ($inputValues as $key => $value) {
            if (!array_key_exists($key, $definitions)) {
                continue;
            }
            $incoming[$key] = $this->castAdministrationParameterValue($definitions[$key], $value);
        }

        foreach ($incoming as $key => $value) {
            $this->saveAdministrationParameterValue($key, $value);
        }
    }

    private function castAdministrationParameterValue(array $definition, $value)
    {
        $type = $definition['type'] ?? 'string';

        switch ($type) {
            case 'boolean':
                if (is_bool($value)) {
                    return $value;
                }
                return in_array(strtolower((string)$value), ['1', 'true', 'on', 'yes'], true);

            case 'integer':
                return intval($value);

            case 'csv':
                if (is_array($value)) {
                    return array_values(array_filter(array_map('trim', $value), function ($item) {
                        return $item !== '';
                    }));
                }
                $parts = explode(',', (string)$value);
                return array_values(array_filter(array_map('trim', $parts), function ($item) {
                    return $item !== '';
                }));

            case 'select':
                return (string)$value;

            case 'text':
            case 'string':
            default:
                return (string)$value;
        }
    }

    private function saveAdministrationParameterValue(string $key, $value): void
    {
        switch ($key) {
            case OscarConfigurationService::allow_numerotation_custom:
                $this->getOscarConfigurationService()->setNumerotationEditable(boolval($value));
                return;

            case OscarConfigurationService::frais_de_gestion_inclus:
                $this->getOscarConfigurationService()->setFraisDeGestionInclus(boolval($value));
                return;

            case OscarConfigurationService::activity_request_limit:
                $this->getOscarConfigurationService()->setActivityRequestLimit(intval($value));
                return;

            case OscarConfigurationService::allow_node_selection:
                $this->getOscarConfigurationService()->setAllowNodeSelection(boolval($value));
                return;

            case OscarConfigurationService::spents_account_filter:
                $this->getOscarConfigurationService()->setSpentAccountFilter($value);
                return;

            case OscarConfigurationService::financial_label:
                $this->getOscarConfigurationService()->setFinancialLabel((string)$value);
                return;

            case OscarConfigurationService::pfi_strict:
                $this->getOscarConfigurationService()->setStrict(boolval($value));
                return;

            case OscarConfigurationService::pfi_strict_format:
                $this->getOscarConfigurationService()->saveEditableConfKey(OscarConfigurationService::pfi_strict_format, (string)$value);
                return;

            case OscarConfigurationService::theme:
                $this->getOscarConfigurationService()->setTheme((string)$value);
                return;

            case OscarConfigurationService::document_use_version_in_name:
                $this->getOscarConfigurationService()->setDocumentUseVersionInName(boolval($value));
                return;

            case 'timesheet_preview':
                $this->getOscarConfigurationService()->setTimesheetPreview(boolval($value));
                return;

            case 'timesheet_excel':
                $this->getOscarConfigurationService()->setTimesheetExcel(boolval($value));
                return;

            case 'organization_require_type':
                $this->getOscarConfigurationService()->saveEditableConfKey('organization_require_type', boolval($value));
                return;

            case 'organization_require_country':
                $this->getOscarConfigurationService()->saveEditableConfKey('organization_require_country', boolval($value));
                return;
        }
    }

    public function accessAction()
    {
        return [];
+24 −0
Original line number Diff line number Diff line
@@ -51,6 +51,8 @@ class OscarConfigurationService implements ServiceLocatorAwareInterface


    const theme = 'theme';
    const activity_form_person_roles = 'activity_form_person_roles';
    const activity_form_organization_roles = 'activity_form_organization_roles';

    public function getOrganizationRequired(): array
    {
@@ -1238,4 +1240,26 @@ class OscarConfigurationService implements ServiceLocatorAwareInterface
    {
        return $this->getConfiguration('urlAbsolute');
    }

    public function getActivityFormPersonRoles()
    {
        if( $this->getEditableConfKey(OscarConfigurationService::activity_form_person_roles) === null){
            return [
                'roleids' => [],
                'min' => 1
            ];
        }
        return $this->getEditableConfKey(OscarConfigurationService::activity_form_person_roles);
    }

    public function getActivityFormOrganizationRoles()
    {
        if( $this->getEditableConfKey(OscarConfigurationService::activity_form_organization_roles) === null){
            return [
                'roleids' => [],
                'min' => 1
            ];
        }
        return $this->getEditableConfKey(OscarConfigurationService::activity_form_organization_roles);
    }
}
+8 −502

File changed.

Preview size limit exceeded, changes collapsed.

+11 −0
Original line number Diff line number Diff line
import { createApp } from "vue";
import AdminParameters from "./views/administration/AdminParameters.vue";

const element = document.querySelector("#admin-parameters");

if (element) {
    const app = createApp(AdminParameters, {
        url: element.dataset.url,
    });
    app.mount("#admin-parameters");
}
Loading