feat: Refactor CPuls entity and related resources; enhance localization, update layouts, and improve validation logic
This commit is contained in:
@@ -1,121 +1,90 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Espo\Custom\Api\CPuls;
|
namespace Espo\Custom\Api\CPuls;
|
||||||
|
|
||||||
use Espo\Core\Api\Action;
|
use Espo\Core\Api\Action;
|
||||||
use Espo\Core\Api\Request;
|
use Espo\Core\Api\Request;
|
||||||
use Espo\Core\Api\Response;
|
use Espo\Core\Api\Response;
|
||||||
|
use Espo\Core\Api\ResponseComposer;
|
||||||
use Espo\Core\Exceptions\BadRequest;
|
use Espo\Core\Exceptions\BadRequest;
|
||||||
use Espo\Core\Exceptions\Forbidden;
|
use Espo\Core\Exceptions\Forbidden;
|
||||||
use Espo\Core\Exceptions\NotFound;
|
use Espo\Core\Exceptions\NotFound;
|
||||||
|
use Espo\ORM\EntityManager;
|
||||||
|
|
||||||
class AbschliessenFuerTeam implements Action
|
class AbschliessenFuerTeam implements Action
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private \Espo\ORM\EntityManager $entityManager,
|
private EntityManager $entityManager
|
||||||
private \Espo\Core\Acl\Table $acl,
|
|
||||||
private \Espo\Entities\User $user,
|
|
||||||
private \Espo\Core\Utils\Log $log
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function process(Request $request): Response
|
public function process(Request $request): Response
|
||||||
{
|
{
|
||||||
$pulsId = $request->getRouteParam('id');
|
$id = $request->getRouteParam('id');
|
||||||
$data = $request->getParsedBody();
|
if (!$id) {
|
||||||
$teamId = $data->teamId ?? null;
|
throw new BadRequest('ID fehlt.');
|
||||||
|
|
||||||
if (!$pulsId || !$teamId) {
|
|
||||||
throw new BadRequest('pulsId oder teamId fehlt');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Validierung: Ist User in diesem Team?
|
$puls = $this->entityManager->getEntityById('CPuls', $id);
|
||||||
$userTeams = $this->user->getLinkMultipleIdList('teams');
|
|
||||||
|
|
||||||
if (!in_array($teamId, $userTeams)) {
|
|
||||||
throw new Forbidden('User nicht in angegebenem Team');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Lade Puls
|
|
||||||
$puls = $this->entityManager->getEntity('CPuls', $pulsId);
|
|
||||||
|
|
||||||
if (!$puls) {
|
if (!$puls) {
|
||||||
throw new NotFound('Puls nicht gefunden');
|
throw new NotFound('Puls nicht gefunden.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Validierung: syncStatus = clean?
|
// Prüfe, ob bereits finalisiert
|
||||||
if ($puls->get('syncStatus') !== 'clean') {
|
if ($puls->get('status') === 'Finalisiert') {
|
||||||
throw new BadRequest('Puls hat neue Dokumente (unclean) - bitte warten Sie auf die KI-Analyse');
|
throw new Forbidden('Puls wurde bereits finalisiert.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Finde Zuordnung
|
// Prüfe syncStatus
|
||||||
$zuordnung = $this->entityManager
|
if ($puls->get('syncStatus') === 'unclean') {
|
||||||
->getRDBRepository('CPulsTeamZuordnung')
|
throw new BadRequest('Neue Dokumente vorhanden. Bitte warten Sie auf die KI-Analyse.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hole aktuelle Team-ID des Benutzers
|
||||||
|
$user = $this->entityManager->getEntityById('User', $request->getServerParam('ESPO_USER_ID'));
|
||||||
|
if (!$user) {
|
||||||
|
throw new Forbidden('Benutzer nicht gefunden.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$teamIds = $user->getLinkMultipleIdList('teams');
|
||||||
|
if (empty($teamIds)) {
|
||||||
|
throw new Forbidden('Sie sind keinem Team zugeordnet.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finde Zuordnung für erstes Team des Benutzers
|
||||||
|
$zuordnung = $this->entityManager->getRDBRepositoryByClass('CPulsTeamZuordnung')
|
||||||
->where([
|
->where([
|
||||||
'pulsId' => $pulsId,
|
'pulsId' => $id,
|
||||||
'teamId' => $teamId,
|
'teamId' => $teamIds,
|
||||||
'aktiv' => true
|
'aktiv' => true
|
||||||
])
|
])
|
||||||
->findOne();
|
->findOne();
|
||||||
|
|
||||||
if (!$zuordnung) {
|
if (!$zuordnung) {
|
||||||
throw new NotFound('Team-Zuordnung nicht gefunden oder nicht aktiv');
|
throw new Forbidden('Sie sind diesem Puls nicht zugeordnet oder nicht aktiv.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. Bereits abgeschlossen?
|
// Markiere Zuordnung als abgeschlossen
|
||||||
if ($zuordnung->get('abgeschlossen')) {
|
|
||||||
return Response::json([
|
|
||||||
'success' => true,
|
|
||||||
'message' => 'Bereits abgeschlossen',
|
|
||||||
'alreadyCompleted' => true
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6. Abschluss setzen
|
|
||||||
$zuordnung->set([
|
$zuordnung->set([
|
||||||
'abgeschlossen' => true,
|
'abgeschlossen' => true,
|
||||||
'abgeschlossenAm' => date('Y-m-d H:i:s'),
|
'abgeschlossenAm' => date('Y-m-d H:i:s'),
|
||||||
'abgeschlossenVonId' => $this->user->getId()
|
'abgeschlossenVon' => $user->getId()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->entityManager->saveEntity($zuordnung);
|
$this->entityManager->saveEntity($zuordnung);
|
||||||
|
|
||||||
// 6.5. FIRST-READ-CLOSES: Finalisiere Block bei erstem Abschluss
|
// FIRST-READ-CLOSES: Finalisiere den Puls sofort
|
||||||
if (!$puls->get('finalisiert')) {
|
$puls->set([
|
||||||
$puls->set([
|
'status' => 'Finalisiert',
|
||||||
'finalisiert' => true,
|
'finalisiertAm' => date('Y-m-d H:i:s'),
|
||||||
'finalisierungsGrund' => 'Erstes Team',
|
'finalisiertVon' => $user->getId()
|
||||||
'finalisiertAm' => date('Y-m-d H:i:s'),
|
]);
|
||||||
'finalisiertVonId' => $this->user->getId()
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->log->info("Block finalisiert durch erstes Team (Team {$teamId}, User {$this->user->getId()})");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 7. Prüfe: Alle Teams abgeschlossen?
|
|
||||||
$offeneTeams = $this->entityManager
|
|
||||||
->getRDBRepository('CPulsTeamZuordnung')
|
|
||||||
->where([
|
|
||||||
'pulsId' => $pulsId,
|
|
||||||
'aktiv' => true,
|
|
||||||
'abgeschlossen' => false
|
|
||||||
])
|
|
||||||
->count();
|
|
||||||
|
|
||||||
// 8. Update Puls-Status
|
|
||||||
if ($offeneTeams === 0) {
|
|
||||||
$puls->set('status', 'Abgeschlossen');
|
|
||||||
} else {
|
|
||||||
$puls->set('status', 'Teilweise abgeschlossen');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->entityManager->saveEntity($puls);
|
$this->entityManager->saveEntity($puls);
|
||||||
|
|
||||||
$this->log->info("Team {$teamId} hat Puls {$pulsId} abgeschlossen");
|
$GLOBALS['log']->info("Puls {$id} durch Team {$zuordnung->get('teamId')} finalisiert (First-Read-Closes).");
|
||||||
|
|
||||||
return Response::json([
|
return ResponseComposer::json([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'status' => $puls->get('status'),
|
'finalized' => true,
|
||||||
'finalisiert' => $puls->get('finalisiert'),
|
'message' => 'Puls wurde finalisiert (First-Read-Closes).'
|
||||||
'offeneTeams' => $offeneTeams
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
namespace Espo\Custom\Hooks\CPuls;
|
namespace Espo\Custom\Hooks\CPuls;
|
||||||
|
|
||||||
use Espo\ORM\Entity;
|
use Espo\ORM\Entity;
|
||||||
|
use Espo\ORM\Repository\Option\SaveOptions;
|
||||||
use Espo\Core\Hook\Hook\BeforeSave;
|
use Espo\Core\Hook\Hook\BeforeSave;
|
||||||
|
|
||||||
class UpdateTeamStats implements BeforeSave
|
class UpdateTeamStats implements BeforeSave
|
||||||
@@ -10,7 +11,7 @@ class UpdateTeamStats implements BeforeSave
|
|||||||
private \Espo\ORM\EntityManager $entityManager
|
private \Espo\ORM\EntityManager $entityManager
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function beforeSave(Entity $entity, array $options): void
|
public function beforeSave(Entity $entity, SaveOptions $options): void
|
||||||
{
|
{
|
||||||
// Zähle Dokumente
|
// Zähle Dokumente
|
||||||
if ($entity->isNew() || $entity->isAttributeChanged('id')) {
|
if ($entity->isNew() || $entity->isAttributeChanged('id')) {
|
||||||
|
|||||||
@@ -1,37 +1,35 @@
|
|||||||
{
|
{
|
||||||
"labels": {
|
"labels": {
|
||||||
"Create CPuls": "Puls erstellen",
|
|
||||||
"CPuls": "Puls",
|
"CPuls": "Puls",
|
||||||
"cPuls": "Pulse"
|
"CPulse": "Pulse",
|
||||||
},
|
"Create CPuls": "Puls erstellen",
|
||||||
"fields": {
|
"name": "Name",
|
||||||
"name": "Bezeichnung",
|
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"syncStatus": "Synchronisations-Status",
|
"syncStatus": "Synchronisierungs-Status",
|
||||||
"kiAnalyse": "KI-Analyse",
|
"kiAnalyse": "KI-Analyse",
|
||||||
"zusammenfassung": "Zusammenfassung",
|
"zusammenfassung": "Zusammenfassung",
|
||||||
"anzahlDokumente": "Anzahl Dokumente",
|
"anzahlDokumente": "Anzahl Dokumente",
|
||||||
"anzahlTeamsAktiv": "Teams (aktiv)",
|
"anzahlTeamsAktiv": "Teams aktiv",
|
||||||
"anzahlTeamsAbgeschlossen": "Teams (abgeschlossen)",
|
"anzahlTeamsAbgeschlossen": "Teams abgeschlossen",
|
||||||
"finalisiert": "Finalisiert",
|
|
||||||
"finalisierungsGrund": "Finalisierungsgrund",
|
|
||||||
"finalisiertAm": "Finalisiert am",
|
"finalisiertAm": "Finalisiert am",
|
||||||
"finalisiertVon": "Finalisiert von",
|
"finalisiertVon": "Finalisiert von",
|
||||||
|
"mandantMitteilung": "Mitteilung an Mandant",
|
||||||
|
"mandantMitteilungText": "Mitteilungstext",
|
||||||
"parent": "Vorgang",
|
"parent": "Vorgang",
|
||||||
"dokumente": "Dokumente",
|
"assignedUser": "Zugewiesen"
|
||||||
"teamZuordnungen": "Team-Zuordnungen"
|
|
||||||
},
|
},
|
||||||
"links": {
|
"links": {
|
||||||
"parent": "Vorgang",
|
|
||||||
"dokumente": "Dokumente",
|
"dokumente": "Dokumente",
|
||||||
"teamZuordnungen": "Team-Zuordnungen"
|
"teamZuordnungen": "Team-Zuordnungen"
|
||||||
},
|
},
|
||||||
"tooltips": {
|
"tooltips": {
|
||||||
"syncStatus": "clean = KI-Analyse aktuell | unclean = Neue Dokumente, Analyse ausstehend",
|
"syncStatus": "Status der KI-Analyse für neue Dokumente",
|
||||||
"kiAnalyse": "Automatisch generierte Zusammenfassung durch KI-Middleware",
|
"kiAnalyse": "Vollständige Analyse der KI zu den Dokumenten",
|
||||||
"zusammenfassung": "Kurze Zusammenfassung für Listen-Ansicht",
|
"zusammenfassung": "Kurze Zusammenfassung der KI-Analyse",
|
||||||
"finalisiert": "Block wurde geschlossen - neue Dokumente erzeugen automatisch einen neuen Block (First-Read-Closes Prinzip)",
|
"finalisiertAm": "Zeitpunkt, zu dem dieser Puls finalisiert wurde",
|
||||||
"finalisierungsGrund": "Grund der Finalisierung: Erstes Team = Team hat abgeschlossen | Manuell = Admin-Aktion | Automatisch = System-Regel"
|
"finalisiertVon": "Benutzer, der den Puls durch Abschluss finalisiert hat",
|
||||||
|
"mandantMitteilung": "Soll eine Mitteilung an den Mandanten versendet werden?",
|
||||||
|
"mandantMitteilungText": "Text der Mitteilung an den Mandanten"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"status": {
|
"status": {
|
||||||
@@ -40,19 +38,12 @@
|
|||||||
"Bereit": "Bereit",
|
"Bereit": "Bereit",
|
||||||
"In Review": "In Review",
|
"In Review": "In Review",
|
||||||
"Teilweise abgeschlossen": "Teilweise abgeschlossen",
|
"Teilweise abgeschlossen": "Teilweise abgeschlossen",
|
||||||
"Abgeschlossen": "Abgeschlossen"
|
"Abgeschlossen": "Abgeschlossen",
|
||||||
|
"Finalisiert": "Finalisiert"
|
||||||
},
|
},
|
||||||
"syncStatus": {
|
"syncStatus": {
|
||||||
"clean": "Aktuell",
|
"clean": "Synchron",
|
||||||
"unclean": "Ausstehend"
|
"unclean": "Ausstehend"
|
||||||
},
|
|
||||||
"finalisierungsGrund": {
|
|
||||||
"Erstes Team": "Erstes Team",
|
|
||||||
"Manuell": "Manuell",
|
|
||||||
"Automatisch": "Automatisch"
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"presetFilters": {
|
|
||||||
"meineOffenen": "Meine offenen Pulse"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,58 +1,49 @@
|
|||||||
{
|
{
|
||||||
"labels": {
|
"labels": {
|
||||||
"Create CPuls": "Create Pulse",
|
|
||||||
"CPuls": "Pulse",
|
"CPuls": "Pulse",
|
||||||
"cPuls": "Pulses"
|
"CPulse": "Pulses",
|
||||||
},
|
"Create CPuls": "Create Pulse",
|
||||||
"fields": {
|
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"syncStatus": "Sync Status",
|
"syncStatus": "Sync Status",
|
||||||
"kiAnalyse": "AI Analysis",
|
"kiAnalyse": "AI Analysis",
|
||||||
"zusammenfassung": "Summary",
|
"zusammenfassung": "Summary",
|
||||||
"anzahlDokumente": "Number of Documents",
|
"anzahlDokumente": "Document Count",
|
||||||
"anzahlTeamsAktiv": "Teams (active)",
|
"anzahlTeamsAktiv": "Active Teams",
|
||||||
"anzahlTeamsAbgeschlossen": "Teams (completed)",
|
"anzahlTeamsAbgeschlossen": "Completed Teams",
|
||||||
"finalisiert": "Finalized",
|
|
||||||
"finalisierungsGrund": "Finalization Reason",
|
|
||||||
"finalisiertAm": "Finalized At",
|
"finalisiertAm": "Finalized At",
|
||||||
"finalisiertVon": "Finalized By",
|
"finalisiertVon": "Finalized By",
|
||||||
"parent": "Parent Record",
|
"mandantMitteilung": "Client Notification",
|
||||||
"dokumente": "Documents",
|
"mandantMitteilungText": "Notification Text",
|
||||||
"teamZuordnungen": "Team Assignments"
|
"parent": "Case",
|
||||||
|
"assignedUser": "Assigned To"
|
||||||
},
|
},
|
||||||
"links": {
|
"links": {
|
||||||
"parent": "Parent Record",
|
|
||||||
"dokumente": "Documents",
|
"dokumente": "Documents",
|
||||||
"teamZuordnungen": "Team Assignments"
|
"teamZuordnungen": "Team Assignments"
|
||||||
},
|
},
|
||||||
"tooltips": {
|
"tooltips": {
|
||||||
"syncStatus": "clean = AI analysis up-to-date | unclean = New documents, analysis pending",
|
"syncStatus": "AI analysis status for new documents",
|
||||||
"kiAnalyse": "Automatically generated summary by AI middleware",
|
"kiAnalyse": "Complete AI analysis of the documents",
|
||||||
"zusammenfassung": "Short summary for list views",
|
"zusammenfassung": "Brief summary of the AI analysis",
|
||||||
"finalisiert": "Block has been closed - new documents will automatically create a new block (First-Read-Closes principle)",
|
"finalisiertAm": "Date and time when this pulse was finalized",
|
||||||
"finalisierungsGrund": "Reason for finalization: First Team = Team completed | Manual = Admin action | Automatic = System rule"
|
"finalisiertVon": "User who finalized the pulse by completion",
|
||||||
|
"mandantMitteilung": "Should a notification be sent to the client?",
|
||||||
|
"mandantMitteilungText": "Text of the notification to the client"
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"status": {
|
"status": {
|
||||||
"Neu": "New",
|
"Neu": "New",
|
||||||
"In Verarbeitung": "Processing",
|
"In Verarbeitung": "In Progress",
|
||||||
"Bereit": "Ready",
|
"Bereit": "Ready",
|
||||||
"In Review": "In Review",
|
"In Review": "In Review",
|
||||||
"Teilweise abgeschlossen": "Partially Completed",
|
"Teilweise abgeschlossen": "Partially Completed",
|
||||||
"Abgeschlossen": "Completed"
|
"Abgeschlossen": "Completed",
|
||||||
|
"Finalisiert": "Finalized"
|
||||||
},
|
},
|
||||||
"syncStatus": {
|
"syncStatus": {
|
||||||
"clean": "Up-to-date",
|
"clean": "Synchronized",
|
||||||
"unclean": "Pending"
|
"unclean": "Pending"
|
||||||
},
|
|
||||||
"finalisierungsGrund": {
|
|
||||||
"Erstes Team": "First Team",
|
|
||||||
"Manuell": "Manual",
|
|
||||||
"Automatisch": "Automatic"
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"presetFilters": {
|
|
||||||
"meineOffenen": "My Open Pulses"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,27 @@
|
|||||||
{
|
{
|
||||||
"teamZuordnungen": {
|
"_delimiter_": {
|
||||||
|
"disabled": true
|
||||||
|
},
|
||||||
|
"activities": {
|
||||||
|
"disabled": true
|
||||||
|
},
|
||||||
|
"history": {
|
||||||
|
"disabled": true
|
||||||
|
},
|
||||||
|
"_tabBreak_0": {
|
||||||
"index": 0,
|
"index": 0,
|
||||||
"sticked": true,
|
"tabBreak": true,
|
||||||
"style": "info",
|
"tabLabel": "Dokumente"
|
||||||
"label": "Team-Zuordnungen"
|
|
||||||
},
|
},
|
||||||
"dokumente": {
|
"dokumente": {
|
||||||
"index": 1,
|
"index": 1
|
||||||
"sticked": false,
|
},
|
||||||
"label": "Dokumente"
|
"_tabBreak_1": {
|
||||||
|
"index": 2,
|
||||||
|
"tabBreak": true,
|
||||||
|
"tabLabel": "Aktivitäten"
|
||||||
},
|
},
|
||||||
"stream": {
|
"stream": {
|
||||||
"index": 2,
|
"index": 3
|
||||||
"sticked": false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": ":assignedUser"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "teams"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "teamZuordnungen"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"label": "Übersicht",
|
"label": "Übersicht",
|
||||||
|
"style": "default",
|
||||||
|
"tabBreak": false,
|
||||||
"rows": [
|
"rows": [
|
||||||
[
|
[
|
||||||
{"name": "name"},
|
{"name": "name"},
|
||||||
@@ -14,10 +16,6 @@
|
|||||||
{"name": "anzahlDokumente"},
|
{"name": "anzahlDokumente"},
|
||||||
{"name": "anzahlTeamsAktiv"}
|
{"name": "anzahlTeamsAktiv"}
|
||||||
],
|
],
|
||||||
[
|
|
||||||
{"name": "finalisiert"},
|
|
||||||
{"name": "finalisierungsGrund"}
|
|
||||||
],
|
|
||||||
[
|
[
|
||||||
{"name": "zusammenfassung", "span": 2}
|
{"name": "zusammenfassung", "span": 2}
|
||||||
]
|
]
|
||||||
@@ -25,6 +23,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "KI-Analyse",
|
"label": "KI-Analyse",
|
||||||
|
"style": "default",
|
||||||
|
"tabBreak": false,
|
||||||
"rows": [
|
"rows": [
|
||||||
[
|
[
|
||||||
{"name": "kiAnalyse", "span": 2}
|
{"name": "kiAnalyse", "span": 2}
|
||||||
@@ -32,7 +32,24 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "System",
|
"label": "Mandant",
|
||||||
|
"style": "default",
|
||||||
|
"tabBreak": false,
|
||||||
|
"rows": [
|
||||||
|
[
|
||||||
|
{"name": "mandantMitteilung"},
|
||||||
|
{}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{"name": "mandantMitteilungText", "span": 2}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Metadaten",
|
||||||
|
"style": "default",
|
||||||
|
"tabBreak": true,
|
||||||
|
"tabLabel": "Erweitert",
|
||||||
"rows": [
|
"rows": [
|
||||||
[
|
[
|
||||||
{"name": "createdAt"},
|
{"name": "createdAt"},
|
||||||
@@ -41,6 +58,10 @@
|
|||||||
[
|
[
|
||||||
{"name": "createdBy"},
|
{"name": "createdBy"},
|
||||||
{"name": "modifiedBy"}
|
{"name": "modifiedBy"}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{"name": "finalisiertAm"},
|
||||||
|
{"name": "finalisiertVon"}
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,8 @@
|
|||||||
"Bereit",
|
"Bereit",
|
||||||
"In Review",
|
"In Review",
|
||||||
"Teilweise abgeschlossen",
|
"Teilweise abgeschlossen",
|
||||||
"Abgeschlossen"
|
"Abgeschlossen",
|
||||||
|
"Finalisiert"
|
||||||
],
|
],
|
||||||
"default": "Neu",
|
"default": "Neu",
|
||||||
"required": true,
|
"required": true,
|
||||||
@@ -26,7 +27,8 @@
|
|||||||
"Bereit": "success",
|
"Bereit": "success",
|
||||||
"In Review": "warning",
|
"In Review": "warning",
|
||||||
"Teilweise abgeschlossen": "info",
|
"Teilweise abgeschlossen": "info",
|
||||||
"Abgeschlossen": "success"
|
"Abgeschlossen": "success",
|
||||||
|
"Finalisiert": "danger"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"syncStatus": {
|
"syncStatus": {
|
||||||
@@ -66,24 +68,6 @@
|
|||||||
"notStorable": false,
|
"notStorable": false,
|
||||||
"isCustom": true
|
"isCustom": true
|
||||||
},
|
},
|
||||||
"finalisiert": {
|
|
||||||
"type": "bool",
|
|
||||||
"default": false,
|
|
||||||
"readOnly": true,
|
|
||||||
"isCustom": true,
|
|
||||||
"tooltip": true
|
|
||||||
},
|
|
||||||
"finalisierungsGrund": {
|
|
||||||
"type": "enum",
|
|
||||||
"options": [
|
|
||||||
"Erstes Team",
|
|
||||||
"Manuell",
|
|
||||||
"Automatisch"
|
|
||||||
],
|
|
||||||
"readOnly": true,
|
|
||||||
"isCustom": true,
|
|
||||||
"tooltip": true
|
|
||||||
},
|
|
||||||
"finalisiertAm": {
|
"finalisiertAm": {
|
||||||
"type": "datetime",
|
"type": "datetime",
|
||||||
"readOnly": true,
|
"readOnly": true,
|
||||||
@@ -95,6 +79,17 @@
|
|||||||
"readOnly": true,
|
"readOnly": true,
|
||||||
"isCustom": true
|
"isCustom": true
|
||||||
},
|
},
|
||||||
|
"mandantMitteilung": {
|
||||||
|
"type": "bool",
|
||||||
|
"default": false,
|
||||||
|
"isCustom": true,
|
||||||
|
"tooltip": true
|
||||||
|
},
|
||||||
|
"mandantMitteilungText": {
|
||||||
|
"type": "text",
|
||||||
|
"isCustom": true,
|
||||||
|
"tooltip": true
|
||||||
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "datetime",
|
"type": "datetime",
|
||||||
"readOnly": true
|
"readOnly": true
|
||||||
@@ -117,10 +112,6 @@
|
|||||||
"type": "link",
|
"type": "link",
|
||||||
"entity": "User",
|
"entity": "User",
|
||||||
"isCustom": true
|
"isCustom": true
|
||||||
},
|
|
||||||
"teams": {
|
|
||||||
"type": "linkMultiple",
|
|
||||||
"isCustom": true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"links": {
|
"links": {
|
||||||
@@ -180,9 +171,6 @@
|
|||||||
"syncStatus": {
|
"syncStatus": {
|
||||||
"columns": ["syncStatus"]
|
"columns": ["syncStatus"]
|
||||||
},
|
},
|
||||||
"finalisiert": {
|
|
||||||
"columns": ["finalisiert"]
|
|
||||||
},
|
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"columns": ["createdAt"]
|
"columns": ["createdAt"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,14 @@
|
|||||||
"type": "varchar",
|
"type": "varchar",
|
||||||
"notStorable": true,
|
"notStorable": true,
|
||||||
"select": {
|
"select": {
|
||||||
"select": "CONCAT:(team.name, ' - ', puls.name)"
|
"select": "CONCAT:(team.name, ' - ', puls.name)",
|
||||||
|
"leftJoins": ["team", "puls"]
|
||||||
},
|
},
|
||||||
"orderBy": {
|
"orderBy": {
|
||||||
"order": [
|
"order": [
|
||||||
["team.name", "{direction}"]
|
["team.name", "{direction}"]
|
||||||
]
|
],
|
||||||
|
"leftJoins": ["team"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"puls": {
|
"puls": {
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"beforeSaveApiScript": "// Verhindere Abschluss bei unclean Status\nif (\n (status == 'Abgeschlossen' || entity\\isAttributeChanged('status'))\n && syncStatus == 'unclean'\n) {\n recordService\\throwBadRequest('Puls kann nicht abgeschlossen werden: Neue Dokumente vorhanden (Status: unclean). Bitte warten Sie auf die KI-Analyse.');\n}\n\n// Verhindere Änderungen an finalisiertem Puls\nif (\n finalisiert == true\n && entity\\isAttributeChanged('finalisiert') == false\n && (entity\\isAttributeChanged('status') || entity\\isAttributeChanged('syncStatus'))\n) {\n recordService\\throwBadRequest('Puls ist finalisiert. Neue Dokumente erzeugen automatisch einen neuen Block.');\n}"
|
"beforeSaveApiScript": "// Verhindere Abschluss bei unclean Status\nif (\n entity\\isAttributeChanged('status') &&\n status == 'Abgeschlossen' &&\n syncStatus == 'unclean'\n) {\n recordService\\throwBadRequest('Puls kann nicht abgeschlossen werden: Neue Dokumente vorhanden (Status: unclean). Bitte warten Sie auf die KI-Analyse.');\n}\n\n// Verhindere Änderungen an finalisiertem Puls\nif (\n status == 'Finalisiert' &&\n !entity\\isAttributeChanged('status') &&\n (entity\\isAttributeChanged('syncStatus'))\n) {\n recordService\\throwBadRequest('Puls ist finalisiert. Neue Dokumente erzeugen automatisch einen neuen Block.');\n}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -358,7 +358,7 @@ return [
|
|||||||
0 => 'youtube.com',
|
0 => 'youtube.com',
|
||||||
1 => 'google.com'
|
1 => 'google.com'
|
||||||
],
|
],
|
||||||
'microtime' => 1770973606.273594,
|
'microtime' => 1770974863.576723,
|
||||||
'siteUrl' => 'https://crm.bitbylaw.com',
|
'siteUrl' => 'https://crm.bitbylaw.com',
|
||||||
'fullTextSearchMinLength' => 4,
|
'fullTextSearchMinLength' => 4,
|
||||||
'webSocketUrl' => 'ws://api.bitbylaw.com:5000/espocrm/ws',
|
'webSocketUrl' => 'ws://api.bitbylaw.com:5000/espocrm/ws',
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
return [
|
return [
|
||||||
'cacheTimestamp' => 1770973606,
|
'cacheTimestamp' => 1770974863,
|
||||||
'microtimeState' => 1770973606.458758,
|
'microtimeState' => 1770974863.697017,
|
||||||
'currencyRates' => [
|
'currencyRates' => [
|
||||||
'EUR' => 1.0
|
'EUR' => 1.0
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user