Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 015586a9df | |||
| 3992384d96 | |||
| cf523cbd86 |
+76
-17
@@ -83,6 +83,11 @@ class DirectAccessReportGenerator
|
||||
$content = file_get_contents($outputPath);
|
||||
@unlink($outputPath);
|
||||
|
||||
// Clean up temp template if downloaded from storage
|
||||
if (str_starts_with($templatePath, self::TEMP_DIR)) {
|
||||
@unlink($templatePath);
|
||||
}
|
||||
|
||||
// Create Attachment
|
||||
$attachment = $this->entityManager->getNewEntity('Attachment');
|
||||
$attachment->set([
|
||||
@@ -106,10 +111,10 @@ class DirectAccessReportGenerator
|
||||
]);
|
||||
$this->entityManager->saveEntity($document);
|
||||
|
||||
// Link Document to Case
|
||||
$this->entityManager->getRDBRepository('Document')
|
||||
->getRelation($document, 'cases')
|
||||
->relate($case);
|
||||
// Link Document to Case (via Case side of relationship)
|
||||
$this->entityManager->getRDBRepository('Case')
|
||||
->getRelation($case, 'documents')
|
||||
->relate($document);
|
||||
|
||||
$this->log->info("LegalAssistance: Report generated — Document {$document->getId()} attached to Case {$caseId}");
|
||||
|
||||
@@ -230,32 +235,37 @@ class DirectAccessReportGenerator
|
||||
|
||||
private function resolveTemplatePath(): string
|
||||
{
|
||||
// Look up template via DocumentTemplate entity
|
||||
$template = $this->entityManager
|
||||
->getRDBRepository('DocumentTemplate')
|
||||
->where(['name' => self::TEMPLATE_NAME])
|
||||
->findOne();
|
||||
|
||||
if ($template) {
|
||||
$fileId = $template->get('fileId');
|
||||
if ($fileId) {
|
||||
$filePath = 'data/upload/' . $fileId;
|
||||
if (file_exists($filePath)) {
|
||||
return $filePath;
|
||||
}
|
||||
}
|
||||
|
||||
// Try templatePath field
|
||||
$templatePath = $template->get('templatePath');
|
||||
if ($templatePath && file_exists($templatePath)) {
|
||||
if ($templatePath) {
|
||||
// Try as-is (absolute or relative)
|
||||
if (file_exists($templatePath)) {
|
||||
return $templatePath;
|
||||
}
|
||||
|
||||
// Try under data/document-templates/
|
||||
$resolved = 'data/document-templates/' . ltrim($templatePath, '/');
|
||||
if (file_exists($resolved)) {
|
||||
return $resolved;
|
||||
}
|
||||
|
||||
// Fallback: look in known locations
|
||||
// Download from NetworkStorage (WebDAV)
|
||||
$downloaded = $this->downloadTemplateFromStorage($templatePath);
|
||||
if ($downloaded) {
|
||||
return $downloaded;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: known locations
|
||||
$fallbackPaths = [
|
||||
'data/document-templates/direct-access-report.docx',
|
||||
'custom/Espo/Modules/LegalAssistance/templates/direct-access-report.docx',
|
||||
__DIR__ . '/../../../../../../templates/direct-access-report.docx',
|
||||
];
|
||||
|
||||
foreach ($fallbackPaths as $path) {
|
||||
@@ -267,8 +277,57 @@ class DirectAccessReportGenerator
|
||||
throw new Error("Template '" . self::TEMPLATE_NAME . "' not found.");
|
||||
}
|
||||
|
||||
private function downloadTemplateFromStorage(string $templatePath): ?string
|
||||
{
|
||||
try {
|
||||
$nds = $this->injectableFactory->create(
|
||||
\Espo\Modules\NetworkStorageIntegration\Services\NetworkDocumentService::class
|
||||
);
|
||||
$client = $nds->getClient();
|
||||
|
||||
// Try Templates/{templatePath} on the storage
|
||||
$integration = $this->entityManager->getEntityById('Integration', 'NetworkStorage');
|
||||
$templatesFolderPath = 'Templates';
|
||||
if ($integration && $integration->get('enabled')) {
|
||||
$data = (array) ($integration->get('data') ?? []);
|
||||
$templatesFolderPath = $data['templatesFolderPath'] ?? 'Templates';
|
||||
}
|
||||
|
||||
$storagePath = $templatesFolderPath . '/' . $templatePath;
|
||||
|
||||
if (!$client->exists($storagePath)) {
|
||||
$this->log->debug("LegalAssistance: Template not found on storage: {$storagePath}");
|
||||
return null;
|
||||
}
|
||||
|
||||
$content = $client->downloadFile($storagePath);
|
||||
|
||||
// Save locally for this request
|
||||
if (!is_dir(self::TEMP_DIR)) {
|
||||
mkdir(self::TEMP_DIR, 0775, true);
|
||||
}
|
||||
$localPath = self::TEMP_DIR . 'template_' . uniqid() . '.docx';
|
||||
file_put_contents($localPath, $content);
|
||||
|
||||
$this->log->debug("LegalAssistance: Template downloaded from storage: {$storagePath} → {$localPath}");
|
||||
return $localPath;
|
||||
} catch (\Exception $e) {
|
||||
$this->log->warning("LegalAssistance: Failed to download template from storage: " . $e->getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private function processTemplate(string $inputPath, string $outputPath, array $data): void
|
||||
{
|
||||
// Ensure PHPWord autoloader is registered
|
||||
if (!class_exists(TemplateProcessor::class, false)) {
|
||||
$autoloader = 'vendor/phpoffice/phpword/src/PhpWord/Autoloader.php';
|
||||
if (file_exists($autoloader)) {
|
||||
require_once $autoloader;
|
||||
\PhpOffice\PhpWord\Autoloader::register();
|
||||
}
|
||||
}
|
||||
|
||||
$processor = new TemplateProcessor($inputPath);
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "LegalAssistance",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.2",
|
||||
"acceptableVersions": [">=8.0.0"],
|
||||
"php": [">=8.1"],
|
||||
"releaseDate": "2026-04-07",
|
||||
"releaseDate": "2026-04-09",
|
||||
"author": "Marcus-Law",
|
||||
"description": "סיוע משפטי — יצירת דוח גישה ישירה (JSON ישירות ל-DOCX), אינטגרציה עם שירה",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"casePromptAppend": "=== סיוע משפטי — דוח גישה ישירה ===\n\nלתיקים עם מינוי גישה ישירה (cLegalAidType = DirectAccess) יש לך כלי מיוחד: generate_initial_report.\n\n## מה זה גישה ישירה?\nגישה ישירה היא מסלול של הסיוע המשפטי בו עורך דין מתמנה לייצג פונה בהליך מול ביטוח לאומי. העורך דין נדרש להגיש דוח דיווח ראשוני תוך 14 יום מקבלת המינוי.\n\n## מתי להפעיל את התהליך?\n- כשהמשתמש מזכיר: \"גישה ישירה\", \"דוח גישה ישירה\", \"דיווח ראשוני\", \"דוח דיווח ראשוני\", \"מינוי גישה ישירה\"\n- כשיש תיק עם cLegalAidType = DirectAccess\n- כשהמשתמש שואל על תהליך הדיווח או המינוי\n\nכשמזהים שהתיק הוא גישה ישירה, הסבר למשתמש שיש לך כלי ייעודי ליצירת דוח גישה ישירה, ושאל אם הוא רוצה להתחיל.\n\n## תהליך השיחה (8 שלבים)\n\nIMPORTANT: אל תפעיל את generate_initial_report עד שאספת את כל המידע הנדרש.\n\n### שלב 1 — מילוי אוטומטי:\n- משוך מהתיק: מספר תיק סיוע, מספר הליך (cCourtCaseNumber)\n- משוך מאיש הקשר: שם פרטי, שם משפחה\n- ספר למשתמש מה כבר יש לך ומה חסר\n\n### שלב 2 — פרטי המינוי:\n- מתי קיבלת את המינוי? (appointmentDate)\n- מה מהות הסיוע? (הגשת ערעור / יעוץ והדרכה / סיוע נוסף ביטוח לאומי / סיוע נוסף תחום אחר / אי מתן סיוע)\n- מה דחיפות ההליך? (רגיל / דחוף / בהול)\n- מועד אחרון להגשה?\n\n### שלב 3 — קשר עם הלקוח:\n- מתי יצרת קשר ראשוני?\n- אם עברו יותר מ-48 שעות מהמינוי: מה סיבת העיכוב?\n- מתי נפגשתם? מי נכח?\n- אם עברו יותר מ-10 ימים: מה סיבת העיכוב?\n- הקשר תקין? (אם לא — פרט)\n\n### שלב 4 — פרטי ההליך:\n- בית הדין? (חובה לבחור מ: בית הדין האזורי לעבודה ירושלים / תל אביב / חיפה / באר שבע / נצרת / בית הדין הארצי לעבודה)\n- עניין ההליך? (נכות כללית / מעבודה / איבה / ניידות / אי כושר / שירותים מיוחדים / סיעוד / הבטחת הכנסה / אבטלה / אחר)\n- תמצית התביעה/הערעור?\n- טענות ההגנה?\n\n### שלב 5 — ניתוח סיכוי משפטי (לפי סוג ההליך):\n\nאם נכות כללית/מעבודה/איבה/ניידות:\n- הוועדה התייחסה לכל המסמכים הרפואיים? פרט\n- ההחלטה מנומקת? ניתן להתחקות אחר הלך הרוח? פרט חוסרים\n- הרכב הוועדה תואם ליקויים? הרכב חסר?\n- התייחסו לכל תלונות הלקוח? פרט חוסרים\n- בדיקה קלינית נערכה? פער בין בדיקה למסמכים?\n\nאם אי כושר (בנוסף):\n- בחינת הלכת מוהרה (גיל, רקע תעסוקתי, השכלה)? נתונים חסרים?\n- פער בין פקיד שיקום לוועדה?\n\nאם שירותים מיוחדים/סיעוד:\n- פער ניקוד vs מצב ומסמכים?\n- התייחסות להיבטים ייחודיים (נפילות, מצב קוגניטיבי, השגחה)?\n\n### שלב 6 — המלצה:\n- סוג ההמלצה? (ייעוץ והדרכה חלף ייצוג / ויתור הלקוח / החלפת ייצוג / לא נוצר קשר / לא ��תקיימה פגישה / עדיין לא ניתן להחליט / נדרשים מסמכים נוספים / המלצה לסירוב)\n- כתוב פירוט מנומק על בסיס התשובות\n\n### שלב 7 — מיצוי זכויות:\n- הלקוח צריך סיוע נוסף? (לא נחוץ / נחוץ בתחום ביטוח לאומי / נחוץ בתחום אחר)\n- אם כן: פרטים, דחיפות, מועדים\n- הסיוע בתחום התמחותך? מעוניין לייצג?\n- הערות נוספות?\n\n### שלב 8 — יצירת הדוח:\n- סכם את כל המידע שנאסף\n- בקש אישור מהמשתמש\n- הפעל generate_initial_report עם כל הנתונים\n\n## הנחיות כלליות:\n- שאל בסגנון שיחה טבעי, לא כטופס\n- קבץ 2-3 שאלות קשורות ביחד\n- השתמש בהקשר התיק למילוי מוקדם\n- הפירוט של ההמלצה צריך להיות נימוק משפטי מנוסח היטב\n- אם המשתמש שואל \"מה זה גישה ישירה?\" או \"יש כאן מינוי גישה ישירה\" — הסבר את התהליך והצע ליצור דוח"
|
||||
"casePromptAppend": "=== סיוע משפטי — דוח גישה ישירה ===\n\nלתיקים עם מינוי גישה ישירה (cLegalAidType = DirectAccess) יש לך כלי מיוחד: generate_direct_access_report.\n\n## מה זה גישה ישירה?\nגישה ישירה היא מסלול של הסיוע המשפטי בו עורך דין מתמנה לייצג פונה בהליך מול ביטוח לאומי. העורך דין נדרש להגיש דוח דיווח ראשוני תוך 14 יום מקבלת המינוי.\n\n## מתי להפעיל את התהליך?\n- כשהמשתמש מזכיר: \"גישה ישירה\", \"דוח גישה ישירה\", \"דיווח ראשוני\", \"דוח דיווח ראשוני\", \"מינוי גישה ישירה\"\n- כשיש תיק עם cLegalAidType = DirectAccess\n- כשהמשתמש שואל על תהליך הדיווח או המינוי\n\nכשמזהים שהתיק הוא גישה ישירה, הסבר למשתמש שיש לך כלי ייעודי ליצירת דוח גישה ישירה, ושאל אם הוא רוצה להתחיל.\n\n## תהליך השיחה (8 שלבים)\n\nIMPORTANT: אל תפעיל את generate_direct_access_report עד שאספת את כל המידע הנדרש.\n\n### שלב 1 — מילוי אוטומטי:\n- משוך מהתיק: מספר תיק סיוע, מספר הליך (cCourtCaseNumber)\n- משוך מאיש הקשר: שם פרטי, שם משפחה\n- ספר למשתמש מה כבר יש לך ומה חסר\n\n### שלב 2 — פרטי המינוי:\n- מתי קיבלת את המינוי? (appointmentDate)\n- מה מהות הסיוע? (הגשת ערעור / יעוץ והדרכה / סיוע נוסף ביטוח לאומי / סיוע נוסף תחום אחר / אי מתן סיוע)\n- מה דחיפות ההליך? (רגיל / דחוף / בהול)\n- מועד אחרון להגשה?\n\n### שלב 3 — קשר עם הלקוח:\n- מתי יצרת קשר ראשוני?\n- אם עברו יותר מ-48 שעות מהמינוי: מה סיבת העיכוב?\n- מתי נפגשתם? מי נכח?\n- אם עברו יותר מ-10 ימים: מה סיבת העיכוב?\n- הקשר תקין? (אם לא — פרט)\n\n### שלב 4 — פרטי ההליך:\n- בית הדין? (חובה לבחור מ: בית הדין האזורי לעבודה ירושלים / תל אביב / חיפה / באר שבע / נצרת / בית הדין הארצי לעבודה)\n- עניין ההליך? (נכות כללית / מעבודה / איבה / ניידות / אי כושר / שירותים מיוחדים / סיעוד / הבטחת הכנסה / אבטלה / אחר)\n- תמצית התביעה/הערעור?\n- טענות ההגנה?\n\n### שלב 5 — ניתוח סיכוי משפטי (לפי סוג ההליך):\n\nאם נכות כללית/מעבודה/איבה/ניידות:\n- הוועדה התייחסה לכל המסמכים הרפואיים? פרט\n- ההחלטה מנומקת? ניתן להתחקות אחר הלך הרוח? פרט חוסרים\n- הרכב הוועדה תואם ליקויים? הרכב חסר?\n- התייחסו לכל תלונות הלקוח? פרט חוסרים\n- בדיקה קלינית נערכה? פער בין בדיקה למסמכים?\n\nאם אי כושר (בנוסף):\n- בחינת הלכת מוהרה (גיל, רקע תעסוקתי, השכלה)? נתונים חסרים?\n- פער בין פקיד שיקום לוועדה?\n\nאם שירותים מיוחדים/סיעוד:\n- פער ניקוד vs מצב ומסמכים?\n- התייחסות להיבטים ייחודיים (נפילות, מצב קוגניטיבי, השגחה)?\n\n### שלב 6 — המלצה:\n- סוג ההמלצה? (ייעוץ והדרכה חלף ייצוג / ויתור הלקוח / החלפת ייצוג / לא נוצר קשר / לא ��תקיימה פגישה / עדיין לא ניתן להחליט / נדרשים מסמכים נוספים / המלצה לסירוב)\n- כתוב פירוט מנומק על בסיס התשובות\n\n### שלב 7 — מיצוי זכויות:\n- הלקוח צריך סיוע נוסף? (לא נחוץ / נחוץ בתחום ביטוח לאומי / נחוץ בתחום אחר)\n- אם כן: פרטים, דחיפות, מועדים\n- הסיוע בתחום התמחותך? מעוניין לייצג?\n- הערות נוספות?\n\n### שלב 8 — יצירת הדוח:\n- סכם את כל המידע שנאסף\n- בקש אישור מהמשתמש\n- הפעל generate_direct_access_report עם כל הנתונים\n\n## הנחיות כלליות:\n- שאל בסגנון שיחה טבעי, לא כטופס\n- קבץ 2-3 שאלות קשורות ביחד\n- השתמש בהקשר התיק למילוי מוקדם\n- הפירוט של ההמלצה צריך להיות נימוק משפטי מנוסח היטב\n- אם המשתמש שואל \"מה זה גישה ישירה?\" או \"יש כאן מינוי גישה ישירה\" — הסבר את התהליך והצע ליצור דוח"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user