diff --git a/Core/Resgrid.Config/RecordsSystemAccessConfig.cs b/Core/Resgrid.Config/RecordsSystemAccessConfig.cs
new file mode 100644
index 00000000..45d322e5
--- /dev/null
+++ b/Core/Resgrid.Config/RecordsSystemAccessConfig.cs
@@ -0,0 +1,21 @@
+namespace Resgrid.Config
+{
+ ///
+ /// Explicitly scoped Record access for system principals — the SMTP relay API key and the
+ /// client_credentials service accounts (Identifier Allocation Registry section 4.4). A system principal
+ /// receives no Record claim at all unless a grant below names its department, and the most a grant can
+ /// ever give is Record_View: every mutating and restricted Record policy stays denied by
+ /// construction, not by configuration. Empty (the default) means no system principal reads Records.
+ /// Environment key: RESGRID:RecordsSystemAccessConfig:Grants.
+ ///
+ public static class RecordsSystemAccessConfig
+ {
+ ///
+ /// Semicolon-delimited grants, each departmentId|purpose|scope, where scope is either
+ /// DepartmentWide or Groups:1,2,3. The purpose is required, is written to the Record
+ /// access audit on every read, and is what makes the grant explicit rather than ambient.
+ /// Example: 12|NerisAudit|DepartmentWide;45|StationReporting|Groups:101,102.
+ ///
+ public static string Grants = "";
+ }
+}
diff --git a/Core/Resgrid.Localization/Areas/User/Records/Records.ar.resx b/Core/Resgrid.Localization/Areas/User/Records/Records.ar.resx
index 37e4bb73..f9a6e128 100644
--- a/Core/Resgrid.Localization/Areas/User/Records/Records.ar.resx
+++ b/Core/Resgrid.Localization/Areas/User/Records/Records.ar.resx
@@ -1,4 +1,4 @@
-
+
text/microsoft-resx
2.0
@@ -343,4 +343,625 @@
قائمة انتظار الإرسال
تم حفظ إعدادات NERIS.
تمت إضافة الإرسال إلى قائمة انتظار NERIS.
+
+ مقبول
+
+
+ كل التعريفات
+
+
+ تحليلات بانتظار الإيداع
+
+
+ اكتمل هذا التحليل وسيُودَع فور وصول الحادث نفسه إلى NERIS.
+
+
+ أقسام التحليل
+
+
+ ينطبق
+
+
+ مُسند إلى
+
+
+ سيارة
+
+
+ بانتظار المراجعة
+
+
+ سجلات أُرسلت للمراجعة ولم تُعتمد بعد
+
+
+ العودة إلى تقرير الحادث
+
+
+ طراز الهيكل
+
+
+ بلاغ
+
+
+ التقاط
+
+
+ سبب التقاط هذا الدليل
+
+
+ التقطه
+
+
+ تاريخ الالتقاط
+
+
+ المصابون وعمليات الإنقاذ
+
+
+ مصاب
+
+
+ النشاط وقت الإصابة
+
+
+ سبب الإصابة
+
+
+ توقيت الحدوث
+
+
+ مدني
+
+
+ إغلاق الطلب
+
+
+ تاريخ الإغلاق
+
+
+ الأقسام المشروطة
+
+
+ نوع البناء
+
+
+ خسارة المحتويات
+
+
+ قيمة المحتويات
+
+
+ تغطية مطابقة الرموز
+
+
+ كل نوع بلاغ محلي بلا رمز NERIS سيحتاج إلى تصنيف يدوي وقت الحادث.
+
+
+ العملة
+
+
+ درجة الضرر
+
+
+ تعذّر إنتاج بعض الإحصاءات:
+
+
+ التعريف
+
+
+ التفاصيل
+
+
+ طلب الاطلاع على السجلات
+
+
+ أُغلق طلب الاطلاع على السجلات.
+
+
+ تم تسجيل طلب الاطلاع على السجلات.
+
+
+ لطلب الاطلاع مهلة قانونية، لذلك يُتابَع هنا بدل الرد عليه ارتجالاً.
+
+
+ تجاوز هذا الطلب مهلته القانونية.
+
+
+ أُعدّت نسخة منقّحة للتسليم.
+
+
+ طلبات الاطلاع على السجلات
+
+
+ يلزم بيان السبب لإغلاق طلب الاطلاع.
+
+
+ سُلِّمت النسخة إلى مقدّم الطلب.
+
+
+ تم حفظ النطاق.
+
+
+ الاطلاع على السجلات
+
+
+ سبب القرار
+
+
+ المسودات
+
+
+ نوع المهمة حينها
+
+
+ تحرير مطابقة الرموز
+
+
+ تحرير تحليل الحادث
+
+
+ خطأ
+
+
+ الخسارة التقديرية
+
+
+ القيمة التقديرية
+
+
+ الأدلة
+
+
+ تم التقاط الدليل.
+
+
+ الشهادات وقت الحادث
+
+
+ رسائل الحادث المُدرجة
+
+
+ كل دليل لقطة محدودة تُلتقط مرة واحدة ولها بصمة تحقق ولا تُعدَّل أبداً؛ والتصحيح التقاط جديد.
+
+
+ المستهلكات والمواد الخاضعة للرقابة المستخدمة
+
+
+ الجاهزية وقت البلاغ
+
+
+ يلزم بيان السبب لإدراج دليل في سجل رسمي.
+
+
+ قرار الإرسال
+
+
+ المصدر
+
+
+ مواقع الوحدات
+
+
+ لم يكن لدى مصدر الأدلة هذا ما يلتقطه لهذا السجل.
+
+
+ العنصر المعرَّض
+
+
+ العناصر المعرَّضة
+
+
+ قاتلة
+
+
+ الإنهاء يكتب النسخة غير القابلة للتغيير. ويظل الإيداع منتظراً معرّف NERIS للحادث إن لم يكن متاحاً بعد.
+
+
+ تاريخ الإنهاء
+
+
+ امتداد الحريق
+
+
+ رجل إطفاء
+
+
+ الجنس
+
+
+ السبب العام
+
+
+ تحليل الحادث
+
+
+ يُودع التحقيق في الحريق والمواد الخطرة بشكل منفصل عن الحادث بعد أن تصبح الجهة المستقبِلة تملكه.
+
+
+ تقارير غير مكتملة
+
+
+ تقارير حوادث لم تُنهَ بعد
+
+
+ تضمين قيود السجل القديم
+
+
+ غير مكتمل
+
+
+ مصاب
+
+
+ أنواع التحقيق
+
+
+ العناصر
+
+
+ الاختصاص القضائي
+
+
+ النوع
+
+
+ لوحة التسجيل
+
+
+ الرمز المحلي
+
+
+ تسجيل طلب اطلاع
+
+
+ الصانع
+
+
+ بيان المحتوى
+
+
+ مطابَقة
+
+
+ مطابقة
+
+
+ الطراز
+
+
+ سنة الطراز
+
+
+ معرّف تحليل NERIS
+
+
+ رمز NERIS
+
+
+ لا توجد طلبات اطلاع مسجّلة.
+
+
+ لم يُلتقط أي دليل لهذا التقرير.
+
+
+ لم يُنتَج شيء بعد.
+
+
+ لا تنطبق أي أقسام مشروطة قبل اختيار نوع الحادث.
+
+
+ مفتوحة
+
+
+ فتح التحليل
+
+
+ فتح طلبات الاطلاع
+
+
+ فتح قائمة الحوادث
+
+
+ فتح قائمة السجلات
+
+
+ السجلات التشغيلية
+
+
+ متأخرة
+
+
+ التزامات تجاوزت موعدها
+
+
+ نوع الشخص
+
+
+ عضو
+
+
+ نظام الدفع
+
+
+ تاريخ الإعداد
+
+
+ في السجل
+
+
+ الرمز الأساسي
+
+
+ إعداد النسخة
+
+
+ النسخة المُعدّة وثيقة جديدة غير قابلة للتغيير؛ ولا يغيّر أي تعديل لاحق ما جرى تسليمه.
+
+
+ قابل للتسليم
+
+
+ لا تزال بصمة التحقق مطابقة؛ لم تُعدَّل النسخة.
+
+
+ بصمة التحقق لا تطابق ما هو مخزَّن.
+
+
+ النسخ المُعدّة
+
+
+ إصدار العقد
+
+
+ الممتلكات
+
+
+ الكمية
+
+
+ إدراج الإيداع في الطابور
+
+
+ في الطابور
+
+
+ العِرق
+
+
+ الرتبة
+
+
+ تاريخ الاستلام
+
+
+ السجلات
+
+
+ لوحة السجلات
+
+
+ لم تُفعَّل وحدة السجلات لهذه الإدارة بعد.
+
+
+ ملف التنقيح
+
+
+ مرفوضة
+
+
+ رُفضت من الجهة المستقبِلة ولم تُصحَّح بعد
+
+
+ تسليم
+
+
+ تاريخ التسليم
+
+
+ الطلب
+
+
+ الرقم المرجعي
+
+
+ مقدّم الطلب
+
+
+ بيانات الاتصال
+
+
+ هوية مقدّم الطلب محظورة ولا تُعرض هنا.
+
+
+ اسم مقدّم الطلب
+
+
+ الجهة
+
+
+ إلزامي
+
+
+ إنقاذ
+
+
+ منسوب الإنقاذ
+
+
+ أسلوب الإنقاذ
+
+
+ مسار الإنقاذ
+
+
+ نوع الإنقاذ
+
+
+ المورد
+
+
+ الموارد
+
+
+ تُحفظ في سجل الإدارة فقط ولا تُرسل إلى NERIS
+
+
+ بعض الحقول محظورة ولا تُعرض لك.
+
+
+ أُعيدت للتصحيح
+
+
+ حفظ النطاق
+
+
+ النطاق
+
+
+ النطاق مجمَّد لأنه سبق إعداد نسخة استناداً إليه.
+
+
+ ما تم طلبه
+
+
+ ما يشمله النطاق
+
+
+ عدد السجلات المطابقة أكبر مما هو مدرج هنا.
+
+
+ الرمز الثانوي
+
+
+ البطارية المعنية
+
+
+ المادة الكيميائية المتسربة
+
+
+ نظام إطفاء المطابخ
+
+
+ أنابيب غاز فولاذية مموجة
+
+
+ خطر كهربائي
+
+
+ تفاصيل الحريق
+
+
+ نظام إنذار الحريق
+
+
+ نظام الإطفاء
+
+
+ الوضع الخطر
+
+
+ تحليل الوضع الخطر
+
+
+ رعاية المريض
+
+
+ الأكسجين الطبي المنزلي
+
+
+ لم يعد هذا القسم ينطبق على أنواع الحوادث المختارة.
+
+
+ إنذار آخر
+
+
+ تحليل الحريق في العراء
+
+
+ موقع الحريق في العراء
+
+
+ خطر توليد الطاقة
+
+
+ المنتج المعني
+
+
+ جهاز إنذار الدخان
+
+
+ موقع حريق المبنى
+
+
+ منشأ حريق المبنى
+
+
+ أُرسل
+
+
+ مجموعة القيم
+
+
+ قديمة
+
+
+ بدء التحليل
+
+
+ الحالات
+
+
+ إذا تُرك فارغاً حدّدته المهلة القانونية للإدارة.
+
+
+ الموعد القانوني
+
+
+ طوابق فوق الأرض
+
+
+ طوابق تحت الأرض
+
+
+ إيداع
+
+
+ مُودعة
+
+
+ مُقترح
+
+
+ مُستبدَل
+
+
+ العنوان
+
+
+ حالة الإشغال
+
+
+ المركبات
+
+
+ التحقق من بصمة السلامة
+
+
+ رقم هيكل المركبة
+
+
+ كان مشغولاً حينها
+
+
+ السنة
+
+
+ سنة البناء
+
+
+ مركبة أخرى
+
+
+ يلزم إدخال بيانات اعتماد جديدة عند تغيير نوع منح الوصول في NERIS.
+
diff --git a/Core/Resgrid.Localization/Areas/User/Records/Records.de.resx b/Core/Resgrid.Localization/Areas/User/Records/Records.de.resx
index 54b39584..386e6977 100644
--- a/Core/Resgrid.Localization/Areas/User/Records/Records.de.resx
+++ b/Core/Resgrid.Localization/Areas/User/Records/Records.de.resx
@@ -1,4 +1,4 @@
-
+
text/microsoft-resx
2.0
@@ -343,4 +343,625 @@
Übermittlungswarteschlange
NERIS-Einstellungen gespeichert.
Übermittlung an NERIS eingereiht.
+
+ Angenommen
+
+
+ Alle Definitionen
+
+
+ Analysen warten auf Einreichung
+
+
+ Diese Analyse ist abgeschlossen und wird eingereicht, sobald der Einsatz selbst NERIS erreicht.
+
+
+ Analyseabschnitte
+
+
+ Gilt
+
+
+ Zugewiesen an
+
+
+ Personenkraftwagen
+
+
+ Wartet auf Prüfung
+
+
+ Berichte zur Prüfung eingereicht und noch nicht freigegeben
+
+
+ Zurück zum Einsatzbericht
+
+
+ Karosserieform
+
+
+ Einsatz
+
+
+ Erfassen
+
+
+ Grund für die Erfassung dieses Nachweises
+
+
+ Erfasst von
+
+
+ Erfasst am
+
+
+ Verletzte und Rettungen
+
+
+ Verletzte Person
+
+
+ Tätigkeit zum Zeitpunkt
+
+
+ Ursache der Verletzung
+
+
+ Zeitpunkt im Einsatzverlauf
+
+
+ Zivilperson
+
+
+ Antrag abschließen
+
+
+ Abgeschlossen am
+
+
+ Bedingte Abschnitte
+
+
+ Bauart
+
+
+ Schaden am Inventar
+
+
+ Wert des Inventars
+
+
+ Abdeckung der Codezuordnung
+
+
+ Jede lokale Einsatzart ohne NERIS-Code muss im Ernstfall von Hand zugeordnet werden.
+
+
+ Währung
+
+
+ Schadensgrad
+
+
+ Einige Zählungen konnten nicht erstellt werden:
+
+
+ Definition
+
+
+ Angabe
+
+
+ Auskunftsersuchen
+
+
+ Das Auskunftsersuchen wurde abgeschlossen.
+
+
+ Das Auskunftsersuchen wurde erfasst.
+
+
+ Ein Auskunftsersuchen unterliegt einer gesetzlichen Frist und wird deshalb hier nachverfolgt statt beiläufig beantwortet.
+
+
+ Die gesetzliche Frist für dieses Ersuchen ist abgelaufen.
+
+
+ Eine geschwärzte Fassung wurde erstellt.
+
+
+ Auskunftsersuchen
+
+
+ Zum Abschluss eines Auskunftsersuchens ist eine Begründung erforderlich.
+
+
+ Die Fassung wurde an die antragstellende Person herausgegeben.
+
+
+ Der Umfang wurde gespeichert.
+
+
+ Auskunftsersuchen
+
+
+ Begründung der Entscheidung
+
+
+ Entwürfe
+
+
+ Dienstart zum Zeitpunkt
+
+
+ Codezuordnung bearbeiten
+
+
+ Einsatzanalyse bearbeiten
+
+
+ Fehler
+
+
+ Geschätzter Schaden
+
+
+ Geschätzter Wert
+
+
+ Nachweise
+
+
+ Der Nachweis wurde erfasst.
+
+
+ Qualifikationen zum Einsatzzeitpunkt
+
+
+ Übernommene Einsatznachrichten
+
+
+ Jeder Nachweis ist eine einmalige, begrenzte Momentaufnahme mit Prüfsumme, die nie geändert wird; eine Korrektur ist eine neue Erfassung.
+
+
+ Verbrauchtes Material und Betäubungsmittel
+
+
+ Einsatzbereitschaft zum Alarmzeitpunkt
+
+
+ Für die Aufnahme eines Nachweises in einen amtlichen Bericht ist eine Begründung erforderlich.
+
+
+ Alarmierungsentscheidung
+
+
+ Quelle
+
+
+ Fahrzeugpositionen
+
+
+ Diese Nachweisquelle hatte für diesen Bericht nichts zu erfassen.
+
+
+ Betroffenes Objekt
+
+
+ Nachbarobjekte
+
+
+ Tödlich
+
+
+ Der Abschluss schreibt die unveränderliche Fassung. Die Einreichung wartet auf die NERIS-Kennung des Einsatzes, falls diese noch fehlt.
+
+
+ Abgeschlossen am
+
+
+ Brandausbreitung
+
+
+ Einsatzkraft
+
+
+ Geschlecht
+
+
+ Allgemeine Ursache
+
+
+ Einsatzanalyse
+
+
+ Die Brand- und Gefahrgutuntersuchung wird getrennt vom Einsatz eingereicht, sobald dieser beim Empfänger vorliegt.
+
+
+ Unvollständige Berichte
+
+
+ Einsatzberichte, die noch nicht abgeschlossen sind
+
+
+ Alt-Protokolleinträge einbeziehen
+
+
+ Unvollständig
+
+
+ Verletzt
+
+
+ Untersuchungsarten
+
+
+ Einträge
+
+
+ Rechtsraum
+
+
+ Art
+
+
+ Kennzeichen
+
+
+ Lokaler Code
+
+
+ Auskunftsersuchen erfassen
+
+
+ Marke
+
+
+ Nachweisinhalt
+
+
+ zugeordnet
+
+
+ gefunden
+
+
+ Modell
+
+
+ Baujahr
+
+
+ NERIS-Analysekennung
+
+
+ NERIS-Code
+
+
+ Es sind keine Auskunftsersuchen erfasst.
+
+
+ Für diesen Bericht wurden noch keine Nachweise erfasst.
+
+
+ Es wurde noch nichts erstellt.
+
+
+ Bedingte Abschnitte gelten erst, wenn eine Einsatzart gewählt ist.
+
+
+ Offen
+
+
+ Analyse öffnen
+
+
+ Auskunftsersuchen öffnen
+
+
+ Einsatzberichte öffnen
+
+
+ Berichtsliste öffnen
+
+
+ Einsatzdokumentation
+
+
+ Überfällig
+
+
+ Pflichten, deren Frist abgelaufen ist
+
+
+ Personengruppe
+
+
+ Mitglied
+
+
+ Antriebsart
+
+
+ Erstellt am
+
+
+ Im Bericht enthalten
+
+
+ Hauptcode
+
+
+ Fassung erstellen
+
+
+ Eine Fassung ist ein neues unveränderliches Dokument; eine spätere Änderung kann das Herausgegebene nicht verändern.
+
+
+ Herausgabefähig
+
+
+ Die Prüfsumme stimmt weiterhin; die Fassung wurde nicht verändert.
+
+
+ Die Prüfsumme stimmt nicht mit dem gespeicherten Wert überein.
+
+
+ Herausgegebene Fassungen
+
+
+ Vertragsversion
+
+
+ Objekte
+
+
+ Menge
+
+
+ Einreichung einreihen
+
+
+ Eingereiht
+
+
+ Ethnische Zugehörigkeit
+
+
+ Dienstgrad
+
+
+ Eingegangen am
+
+
+ Berichte
+
+
+ Berichtsübersicht
+
+
+ Die Berichtsverwaltung ist für diese Organisation noch nicht aktiviert.
+
+
+ Schwärzungsprofil
+
+
+ Abgelehnt
+
+
+ Vom Empfänger abgelehnt und noch nicht korrigiert
+
+
+ Herausgeben
+
+
+ Herausgegeben am
+
+
+ Ersuchen
+
+
+ Aktenzeichen
+
+
+ Antragstellende Person
+
+
+ Kontaktangaben
+
+
+ Wer das Ersuchen gestellt hat, ist geschützt und wird hier nicht angezeigt.
+
+
+ Name der antragstellenden Person
+
+
+ Organisation
+
+
+ Erforderlich
+
+
+ Rettung
+
+
+ Höhenlage der Rettung
+
+
+ Rettungsart
+
+
+ Rettungsweg
+
+
+ Rettungsart
+
+
+ Mittel
+
+
+ Eingesetzte Mittel
+
+
+ nur im Bericht der Organisation, wird nie an NERIS gesendet
+
+
+ Einige Felder sind geschützt und werden Ihnen nicht angezeigt.
+
+
+ Zur Korrektur zurückgegeben
+
+
+ Umfang speichern
+
+
+ Umfang
+
+
+ Der Umfang ist festgeschrieben, weil bereits eine Fassung daraus erstellt wurde.
+
+
+ Gegenstand des Ersuchens
+
+
+ Was der Umfang derzeit umfasst
+
+
+ Es entsprechen mehr Berichte, als hier aufgeführt sind.
+
+
+ Zweiter Code
+
+
+ Beteiligte Batterie
+
+
+ Freigesetzter Stoff
+
+
+ Küchenlöschanlage
+
+
+ Gewellte Edelstahl-Gasleitung
+
+
+ Elektrische Gefahr
+
+
+ Branddaten
+
+
+ Brandmeldeanlage
+
+
+ Löschanlage
+
+
+ Gefahrenlage
+
+
+ Analyse der Gefahrenlage
+
+
+ Patientenversorgung
+
+
+ Medizinischer Sauerstoff im Haushalt
+
+
+ Dieser Abschnitt gilt für die gewählten Einsatzarten nicht mehr.
+
+
+ Sonstige Warnanlage
+
+
+ Analyse des Freilandbrands
+
+
+ Brandort im Freien
+
+
+ Gefahr durch Stromerzeugung
+
+
+ Beteiligtes Erzeugnis
+
+
+ Rauchwarnmelder
+
+
+ Brandort im Gebäude
+
+
+ Brandausbruchstelle im Gebäude
+
+
+ Gesendet
+
+
+ Werteliste
+
+
+ veraltet
+
+
+ Analyse beginnen
+
+
+ Status
+
+
+ Bleibt das Feld leer, setzt die gesetzliche Frist der Organisation den Termin.
+
+
+ Gesetzliche Frist
+
+
+ Geschosse über Grund
+
+
+ Geschosse unter Grund
+
+
+ Einreichen
+
+
+ Eingereicht
+
+
+ Empfohlen
+
+
+ Ersetzt
+
+
+ Bezeichnung
+
+
+ Nutzungszustand
+
+
+ Fahrzeuge
+
+
+ Prüfsumme überprüfen
+
+
+ Fahrgestellnummer
+
+
+ Zum Zeitpunkt besetzt
+
+
+ Jahr
+
+
+ Baujahr
+
+
+ Sonstiges Fahrzeug
+
+
+ Beim Wechsel des NERIS-Grant-Typs sind neue Zugangsdaten erforderlich.
+
diff --git a/Core/Resgrid.Localization/Areas/User/Records/Records.el.resx b/Core/Resgrid.Localization/Areas/User/Records/Records.el.resx
index 9eefd3e3..a1b591db 100644
--- a/Core/Resgrid.Localization/Areas/User/Records/Records.el.resx
+++ b/Core/Resgrid.Localization/Areas/User/Records/Records.el.resx
@@ -1,4 +1,4 @@
-
+
text/microsoft-resx
2.0
@@ -343,4 +343,625 @@
Ουρά υποβολών
Οι ρυθμίσεις NERIS αποθηκεύτηκαν.
Η υποβολή μπήκε στην ουρά για το NERIS.
+
+ Έγινε αποδεκτό
+
+
+ Όλοι οι ορισμοί
+
+
+ Αναλύσεις σε αναμονή υποβολής
+
+
+ Η ανάλυση οριστικοποιήθηκε και θα υποβληθεί μόλις το ίδιο το συμβάν φτάσει στο NERIS.
+
+
+ Ενότητες ανάλυσης
+
+
+ Ισχύει
+
+
+ Ανατέθηκε σε
+
+
+ Αυτοκίνητο
+
+
+ Σε αναμονή ελέγχου
+
+
+ Αρχεία που υποβλήθηκαν για έλεγχο και δεν έχουν εγκριθεί
+
+
+ Επιστροφή στην αναφορά συμβάντος
+
+
+ Τύπος αμαξώματος
+
+
+ Κλήση
+
+
+ Καταγραφή
+
+
+ Λόγος καταγραφής αυτού του τεκμηρίου
+
+
+ Καταγράφηκε από
+
+
+ Καταγράφηκε στις
+
+
+ Τραυματίες και διασώσεις
+
+
+ Τραυματίας
+
+
+ Ενέργεια τη στιγμή εκείνη
+
+
+ Αιτία τραυματισμού
+
+
+ Πότε συνέβη
+
+
+ Πολίτης
+
+
+ Κλείσιμο του αιτήματος
+
+
+ Έκλεισε στις
+
+
+ Υπό όρους ενότητες
+
+
+ Τύπος κατασκευής
+
+
+ Ζημιά περιεχομένου
+
+
+ Αξία περιεχομένου
+
+
+ Κάλυψη αντιστοίχισης κωδικών
+
+
+ Κάθε τοπικός τύπος κλήσης χωρίς κωδικό NERIS θα πρέπει να ταξινομηθεί χειροκίνητα την ίδια νύχτα.
+
+
+ Νόμισμα
+
+
+ Βαθμός ζημιάς
+
+
+ Ορισμένες μετρήσεις δεν ήταν δυνατό να παραχθούν:
+
+
+ Ορισμός
+
+
+ Λεπτομέρεια
+
+
+ Αίτημα πρόσβασης σε αρχεία
+
+
+ Το αίτημα πρόσβασης έκλεισε.
+
+
+ Το αίτημα πρόσβασης καταχωρήθηκε.
+
+
+ Ένα αίτημα πρόσβασης έχει νόμιμη προθεσμία, γι' αυτό παρακολουθείται εδώ αντί να απαντάται περιστασιακά.
+
+
+ Το αίτημα αυτό έχει ξεπεράσει τη νόμιμη προθεσμία.
+
+
+ Ετοιμάστηκε παραδοτέο με απαλείψεις.
+
+
+ Αιτήματα πρόσβασης σε αρχεία
+
+
+ Απαιτείται αιτιολογία για το κλείσιμο ενός αιτήματος.
+
+
+ Το παραδοτέο δόθηκε στον αιτούντα.
+
+
+ Το εύρος αποθηκεύτηκε.
+
+
+ Πρόσβαση σε αρχεία
+
+
+ Αιτιολογία της έκβασης
+
+
+ Πρόχειρα
+
+
+ Υπηρεσία τη στιγμή εκείνη
+
+
+ Επεξεργασία αντιστοίχισης
+
+
+ Επεξεργασία ανάλυσης συμβάντος
+
+
+ Σφάλμα
+
+
+ Εκτιμώμενη ζημιά
+
+
+ Εκτιμώμενη αξία
+
+
+ Τεκμήρια
+
+
+ Το τεκμήριο καταγράφηκε.
+
+
+ Πιστοποιήσεις τη στιγμή του συμβάντος
+
+
+ Μηνύματα συμβάντος που εντάχθηκαν
+
+
+ Κάθε τεκμήριο είναι ένα οριοθετημένο στιγμιότυπο που λαμβάνεται μία φορά, με άθροισμα ελέγχου και δεν αλλάζει ποτέ· η διόρθωση είναι νέα καταγραφή.
+
+
+ Αναλώσιμα και ελεγχόμενες ουσίες που χρησιμοποιήθηκαν
+
+
+ Ετοιμότητα τη στιγμή της κλήσης
+
+
+ Απαιτείται αιτιολογία για την ένταξη τεκμηρίου σε επίσημο αρχείο.
+
+
+ Απόφαση κινητοποίησης
+
+
+ Πηγή
+
+
+ Στίγματα οχημάτων
+
+
+ Αυτή η πηγή τεκμηρίων δεν είχε τίποτα να καταγράψει για το αρχείο αυτό.
+
+
+ Εκτεθειμένο αντικείμενο
+
+
+ Εκτεθειμένα αντικείμενα
+
+
+ Θανατηφόρο
+
+
+ Η οριστικοποίηση γράφει την αμετάβλητη αναθεώρηση. Η υποβολή περιμένει το αναγνωριστικό NERIS του συμβάντος αν δεν υπάρχει ακόμη.
+
+
+ Οριστικοποιήθηκε στις
+
+
+ Εξάπλωση πυρκαγιάς
+
+
+ Πυροσβέστης
+
+
+ Φύλο
+
+
+ Γενική αιτία
+
+
+ Ανάλυση συμβάντος
+
+
+ Η διερεύνηση πυρκαγιάς και επικίνδυνων υλικών υποβάλλεται χωριστά από το συμβάν, αφού ο παραλήπτης το έχει ήδη.
+
+
+ Ημιτελείς αναφορές
+
+
+ Αναφορές συμβάντων που δεν έχουν οριστικοποιηθεί
+
+
+ Συμπερίληψη παλαιών καταχωρίσεων
+
+
+ Ημιτελείς
+
+
+ Τραυματισμένος
+
+
+ Είδη διερεύνησης
+
+
+ Στοιχεία
+
+
+ Δικαιοδοσία
+
+
+ Είδος
+
+
+ Πινακίδα κυκλοφορίας
+
+
+ Τοπικός κωδικός
+
+
+ Καταχώριση αιτήματος πρόσβασης
+
+
+ Μάρκα
+
+
+ Κατάλογος περιεχομένου
+
+
+ αντιστοιχισμένοι
+
+
+ αντιστοιχίες
+
+
+ Μοντέλο
+
+
+ Έτος μοντέλου
+
+
+ Αναγνωριστικό ανάλυσης NERIS
+
+
+ Κωδικός NERIS
+
+
+ Δεν έχουν καταχωριστεί αιτήματα πρόσβασης.
+
+
+ Δεν έχουν καταγραφεί τεκμήρια για την αναφορά αυτή.
+
+
+ Δεν έχει παραχθεί τίποτα ακόμη.
+
+
+ Καμία υπό όρους ενότητα δεν ισχύει έως ότου επιλεγεί τύπος συμβάντος.
+
+
+ Ανοικτά
+
+
+ Άνοιγμα ανάλυσης
+
+
+ Άνοιγμα αιτημάτων πρόσβασης
+
+
+ Άνοιγμα ουράς συμβάντων
+
+
+ Άνοιγμα ουράς αρχείων
+
+
+ Επιχειρησιακά αρχεία
+
+
+ Εκπρόθεσμα
+
+
+ Υποχρεώσεις που έχουν λήξει
+
+
+ Τύπος προσώπου
+
+
+ Μέλος
+
+
+ Σύστημα κίνησης
+
+
+ Ετοιμάστηκε στις
+
+
+ Στο αρχείο
+
+
+ Κύριος κωδικός
+
+
+ Παραγωγή
+
+
+ Το παραδοτέο είναι νέο αμετάβλητο τεκμήριο· μεταγενέστερη τροποποίηση δεν αλλάζει ό,τι δόθηκε.
+
+
+ Δυνατόν να δοθεί
+
+
+ Το άθροισμα ελέγχου εξακολουθεί να ταιριάζει· δεν έχει αλλοιωθεί.
+
+
+ Το άθροισμα ελέγχου δεν ταιριάζει με το αποθηκευμένο.
+
+
+ Παραδοτέα
+
+
+ Έκδοση συμβολαίου
+
+
+ Ακίνητα
+
+
+ Ποσότητα
+
+
+ Προσθήκη υποβολής στην ουρά
+
+
+ Σε ουρά
+
+
+ Εθνοτική καταγωγή
+
+
+ Βαθμός
+
+
+ Παραλήφθηκε στις
+
+
+ Αρχεία
+
+
+ Πίνακας αρχείων
+
+
+ Το αρχείο δεν έχει ενεργοποιηθεί ακόμη για την υπηρεσία αυτή.
+
+
+ Προφίλ απαλείψεων
+
+
+ Απορρίφθηκαν
+
+
+ Απορρίφθηκαν από τον παραλήπτη και δεν διορθώθηκαν
+
+
+ Χορήγηση
+
+
+ Χορηγήθηκε στις
+
+
+ Αίτημα
+
+
+ Αριθμός αναφοράς
+
+
+ Αιτών
+
+
+ Στοιχεία επικοινωνίας
+
+
+ Η ταυτότητα του αιτούντος είναι περιορισμένη και δεν εμφανίζεται εδώ.
+
+
+ Όνομα αιτούντος
+
+
+ Οργανισμός
+
+
+ Υποχρεωτική
+
+
+ Διάσωση
+
+
+ Υψόμετρο διάσωσης
+
+
+ Τρόπος διάσωσης
+
+
+ Διαδρομή διάσωσης
+
+
+ Είδος διάσωσης
+
+
+ Πόρος
+
+
+ Πόροι
+
+
+ τηρούνται μόνο στο αρχείο της υπηρεσίας, δεν αποστέλλονται στο NERIS
+
+
+ Ορισμένα πεδία είναι περιορισμένα και δεν σας εμφανίζονται.
+
+
+ Επιστράφηκαν για διόρθωση
+
+
+ Αποθήκευση εύρους
+
+
+ Εύρος
+
+
+ Το εύρος έχει παγώσει επειδή έχει ήδη παραχθεί υλικό βάσει αυτού.
+
+
+ Τι ζητήθηκε
+
+
+ Τι αποδίδει το εύρος
+
+
+ Ταιριάζουν περισσότερα αρχεία από όσα εμφανίζονται εδώ.
+
+
+ Δευτερεύων κωδικός
+
+
+ Εμπλεκόμενη μπαταρία
+
+
+ Χημική ουσία που διέρρευσε
+
+
+ Σύστημα κατάσβεσης κουζίνας
+
+
+ Κυματοειδής ανοξείδωτη σωλήνωση αερίου
+
+
+ Ηλεκτρικός κίνδυνος
+
+
+ Στοιχεία πυρκαγιάς
+
+
+ Σύστημα πυρανίχνευσης
+
+
+ Σύστημα κατάσβεσης
+
+
+ Επικίνδυνη κατάσταση
+
+
+ Ανάλυση επικίνδυνης κατάστασης
+
+
+ Φροντίδα ασθενούς
+
+
+ Ιατρικό οξυγόνο κατ' οίκον
+
+
+ Η ενότητα αυτή δεν ισχύει πλέον για τους επιλεγμένους τύπους συμβάντος.
+
+
+ Άλλος συναγερμός
+
+
+ Ανάλυση υπαίθριας πυρκαγιάς
+
+
+ Θέση υπαίθριας πυρκαγιάς
+
+
+ Κίνδυνος από παραγωγή ενέργειας
+
+
+ Εμπλεκόμενο προϊόν
+
+
+ Ανιχνευτής καπνού
+
+
+ Θέση πυρκαγιάς σε κτίριο
+
+
+ Εστία πυρκαγιάς κτιρίου
+
+
+ Στάλθηκε
+
+
+ Σύνολο τιμών
+
+
+ παρωχημένοι
+
+
+ Έναρξη ανάλυσης
+
+
+ Καταστάσεις
+
+
+ Αν μείνει κενό, το ορίζει η νόμιμη προθεσμία της υπηρεσίας.
+
+
+ Νόμιμη προθεσμία
+
+
+ Όροφοι πάνω από το έδαφος
+
+
+ Όροφοι κάτω από το έδαφος
+
+
+ Υποβολή
+
+
+ Υποβλήθηκαν
+
+
+ Προτεινόμενη
+
+
+ Αντικαταστάθηκε
+
+
+ Τίτλος
+
+
+ Κατάσταση κατοίκησης
+
+
+ Οχήματα
+
+
+ Έλεγχος αθροίσματος ελέγχου
+
+
+ Αριθμός πλαισίου
+
+
+ Κατειλημμένο τη στιγμή εκείνη
+
+
+ Έτος
+
+
+ Έτος κατασκευής
+
+
+ Άλλο όχημα
+
+
+ Απαιτούνται νέα διαπιστευτήρια όταν αλλάζει ο τύπος παραχώρησης NERIS.
+
diff --git a/Core/Resgrid.Localization/Areas/User/Records/Records.en.resx b/Core/Resgrid.Localization/Areas/User/Records/Records.en.resx
index 6a41a5d3..f6fa6c34 100644
--- a/Core/Resgrid.Localization/Areas/User/Records/Records.en.resx
+++ b/Core/Resgrid.Localization/Areas/User/Records/Records.en.resx
@@ -1,4 +1,4 @@
-
+
text/microsoft-resx
2.0
@@ -343,4 +343,625 @@
Submission queue
NERIS settings saved.
Submission queued for NERIS.
+
+ Accepted
+
+
+ All definitions
+
+
+ Analyses awaiting filing
+
+
+ This analysis is finalized and will be filed as soon as the incident itself reaches NERIS.
+
+
+ Analysis sections
+
+
+ Applies
+
+
+ Assigned to
+
+
+ Automobile
+
+
+ Awaiting review
+
+
+ Records submitted for review and not yet approved
+
+
+ Back to the incident report
+
+
+ Body style
+
+
+ Call
+
+
+ Capture
+
+
+ Why this evidence is being captured
+
+
+ Captured by
+
+
+ Captured on
+
+
+ Casualties and rescues
+
+
+ Casualty
+
+
+ Action at the time
+
+
+ Cause of the casualty
+
+
+ When it happened
+
+
+ Civilian
+
+
+ Close the request
+
+
+ Closed on
+
+
+ Conditional sections
+
+
+ Construction type
+
+
+ Contents loss
+
+
+ Contents value
+
+
+ Crosswalk coverage
+
+
+ Every local call type that has no NERIS code will need classifying by hand on the night.
+
+
+ Currency
+
+
+ Damage rating
+
+
+ Some counts could not be produced:
+
+
+ Definition
+
+
+ Detail
+
+
+ Records request
+
+
+ The records request was closed.
+
+
+ The records request was logged.
+
+
+ A records request carries a statutory clock, so it is tracked here rather than answered ad hoc.
+
+
+ This request is past its statutory due date.
+
+
+ A redacted production was prepared.
+
+
+ Records requests
+
+
+ A reason is required to close a records request.
+
+
+ The production was released to the requester.
+
+
+ The scope was saved.
+
+
+ Records requests
+
+
+ Reason for the outcome
+
+
+ Drafts
+
+
+ Duty at the time
+
+
+ Edit the crosswalk
+
+
+ Edit the incident analysis
+
+
+ Error
+
+
+ Estimated loss
+
+
+ Estimated value
+
+
+ Evidence
+
+
+ The evidence artifact was captured.
+
+
+ Certifications at the incident time
+
+
+ Promoted incident messages
+
+
+ Each artifact is a bounded snapshot taken once, checksummed and never changed; a correction is a new capture.
+
+
+ Supplies and controlled substances used
+
+
+ Readiness at the time of the call
+
+
+ A reason is required to capture evidence into an official record.
+
+
+ Dispatch decision
+
+
+ Source
+
+
+ Unit tracking fixes
+
+
+ That evidence source had nothing to capture for this record.
+
+
+ Exposed item
+
+
+ Exposures
+
+
+ Fatal
+
+
+ Finalizing writes the immutable revision. Filing waits for the incident's NERIS id if it does not have one yet.
+
+
+ Finalized on
+
+
+ Fire spread
+
+
+ Firefighter
+
+
+ Gender
+
+
+ General cause
+
+
+ Incident analysis
+
+
+ The fire and hazmat investigation is filed separately from the incident, once the destination already holds it.
+
+
+ Incomplete reports
+
+
+ Incident reports not yet finalized
+
+
+ Include legacy log entries
+
+
+ Incomplete
+
+
+ Injured
+
+
+ Investigation types
+
+
+ Items
+
+
+ Jurisdiction
+
+
+ Kind
+
+
+ Registration plate
+
+
+ Local code
+
+
+ Log a records request
+
+
+ Make
+
+
+ Manifest
+
+
+ mapped
+
+
+ matched
+
+
+ Model
+
+
+ Model year
+
+
+ NERIS analysis id
+
+
+ NERIS code
+
+
+ No records requests are logged.
+
+
+ No evidence has been captured against this report.
+
+
+ Nothing has been produced yet.
+
+
+ No conditional sections apply until an incident type is chosen.
+
+
+ Open
+
+
+ Open the analysis
+
+
+ Open the records requests
+
+
+ Open the incident queue
+
+
+ Open the records queue
+
+
+ Operational records
+
+
+ Overdue
+
+
+ Obligations past their due date
+
+
+ Person type
+
+
+ Member
+
+
+ Powertrain
+
+
+ Prepared on
+
+
+ On the record
+
+
+ Primary code
+
+
+ Produce
+
+
+ A production is a new immutable artifact; a later amendment cannot change what was released.
+
+
+ Producible
+
+
+ The production checksum still matches; it has not been altered.
+
+
+ The production checksum does not match what was stored.
+
+
+ Productions
+
+
+ Contract version
+
+
+ Properties
+
+
+ Quantity
+
+
+ Queue the filing
+
+
+ Queued
+
+
+ Race
+
+
+ Rank
+
+
+ Received on
+
+
+ Records
+
+
+ Records dashboard
+
+
+ Records is not activated for this department yet.
+
+
+ Redaction profile
+
+
+ Rejected
+
+
+ Rejected by the destination and not yet corrected
+
+
+ Release
+
+
+ Released on
+
+
+ Request
+
+
+ Reference
+
+
+ Requester
+
+
+ Contact details
+
+
+ Who asked is restricted and is not shown here.
+
+
+ Requester name
+
+
+ Organisation
+
+
+ Required
+
+
+ Rescue
+
+
+ Elevation of the rescue
+
+
+ Rescue mode
+
+
+ Route of the rescue
+
+
+ Rescue type
+
+
+ Resource
+
+
+ Resources
+
+
+ kept on the department record only, never sent to NERIS
+
+
+ Some fields are restricted and are not shown to you.
+
+
+ Returned for correction
+
+
+ Save the scope
+
+
+ Scope
+
+
+ The scope is frozen because something has already been produced against it.
+
+
+ What was asked for
+
+
+ What the scope resolves to
+
+
+ More records match than are listed here.
+
+
+ Secondary code
+
+
+ Battery involved
+
+
+ Released chemical
+
+
+ Kitchen suppression system
+
+
+ Corrugated stainless gas tubing
+
+
+ Electrical hazard
+
+
+ Fire detail
+
+
+ Fire alarm system
+
+
+ Fire suppression system
+
+
+ Hazardous situation
+
+
+ Hazardous situation analysis
+
+
+ Patient care
+
+
+ Home medical oxygen
+
+
+ This section no longer applies to the selected incident types.
+
+
+ Other alarm
+
+
+ Outdoor fire analysis
+
+
+ Outdoor fire location
+
+
+ Power generation hazard
+
+
+ Product involved
+
+
+ Smoke alarm
+
+
+ Structure fire location
+
+
+ Origin of the structure fire
+
+
+ Sent
+
+
+ Value set
+
+
+ stale
+
+
+ Start the analysis
+
+
+ States
+
+
+ Left blank, the department's statutory clock sets it.
+
+
+ Statutory due date
+
+
+ Storeys above grade
+
+
+ Storeys below grade
+
+
+ File it
+
+
+ Submitted
+
+
+ Suggested
+
+
+ Superseded
+
+
+ Title
+
+
+ Occupancy status
+
+
+ Vehicles
+
+
+ Verify the checksum
+
+
+ VIN
+
+
+ Occupied at the time
+
+
+ Year
+
+
+ Year built
+
+
+ Other vehicle
+
+
+ A new credential is required when the NERIS grant type changes.
+
diff --git a/Core/Resgrid.Localization/Areas/User/Records/Records.es.resx b/Core/Resgrid.Localization/Areas/User/Records/Records.es.resx
index 6bdab4fe..79abf044 100644
--- a/Core/Resgrid.Localization/Areas/User/Records/Records.es.resx
+++ b/Core/Resgrid.Localization/Areas/User/Records/Records.es.resx
@@ -1,4 +1,4 @@
-
+
text/microsoft-resx
2.0
@@ -343,4 +343,625 @@
Cola de envíos
Configuración NERIS guardada.
Envío en cola para NERIS.
+
+ Aceptado
+
+
+ Todas las definiciones
+
+
+ Análisis pendientes de envío
+
+
+ Este análisis está finalizado y se enviará en cuanto el propio incidente llegue a NERIS.
+
+
+ Secciones del análisis
+
+
+ Se aplica
+
+
+ Asignado a
+
+
+ Automóvil
+
+
+ Pendiente de revisión
+
+
+ Registros enviados a revisión y aún no aprobados
+
+
+ Volver al informe del incidente
+
+
+ Tipo de carrocería
+
+
+ Aviso
+
+
+ Capturar
+
+
+ Motivo por el que se captura esta evidencia
+
+
+ Capturado por
+
+
+ Capturado el
+
+
+ Víctimas y rescates
+
+
+ Víctima
+
+
+ Actividad en ese momento
+
+
+ Causa de la lesión
+
+
+ Momento en que ocurrió
+
+
+ Civil
+
+
+ Cerrar la solicitud
+
+
+ Cerrada el
+
+
+ Secciones condicionales
+
+
+ Tipo de construcción
+
+
+ Pérdida de contenido
+
+
+ Valor del contenido
+
+
+ Cobertura de la correspondencia
+
+
+ Cada tipo de aviso local sin código NERIS habrá que clasificarlo a mano durante el servicio.
+
+
+ Moneda
+
+
+ Grado de daño
+
+
+ No se han podido calcular algunos recuentos:
+
+
+ Definición
+
+
+ Detalle
+
+
+ Solicitud de acceso a registros
+
+
+ Se ha cerrado la solicitud de acceso.
+
+
+ Se ha registrado la solicitud de acceso.
+
+
+ Una solicitud de acceso tiene un plazo legal, por eso se registra aquí y no se responde de forma improvisada.
+
+
+ Esta solicitud ha superado su plazo legal.
+
+
+ Se ha preparado una entrega con datos ocultados.
+
+
+ Solicitudes de acceso
+
+
+ Se necesita un motivo para cerrar una solicitud de acceso.
+
+
+ La entrega se ha remitido a la persona solicitante.
+
+
+ Se ha guardado el alcance.
+
+
+ Acceso a registros
+
+
+ Motivo de la resolución
+
+
+ Borradores
+
+
+ Servicio en ese momento
+
+
+ Editar la correspondencia
+
+
+ Editar el análisis del incidente
+
+
+ Error
+
+
+ Pérdida estimada
+
+
+ Valor estimado
+
+
+ Evidencias
+
+
+ Se ha capturado la evidencia.
+
+
+ Certificaciones en el momento del incidente
+
+
+ Mensajes del incidente incorporados
+
+
+ Cada evidencia es una instantánea acotada, tomada una vez, con suma de verificación y nunca modificada; una corrección es una captura nueva.
+
+
+ Material y sustancias controladas utilizados
+
+
+ Disponibilidad en el momento del aviso
+
+
+ Se necesita un motivo para incorporar evidencia a un registro oficial.
+
+
+ Decisión de despacho
+
+
+ Fuente
+
+
+ Posiciones de las unidades
+
+
+ Esa fuente de evidencia no tenía nada que capturar para este registro.
+
+
+ Elemento expuesto
+
+
+ Elementos expuestos
+
+
+ Mortal
+
+
+ Al finalizar se escribe la revisión inmutable. El envío espera al identificador NERIS del incidente si aún no lo tiene.
+
+
+ Finalizado el
+
+
+ Propagación del fuego
+
+
+ Bombero
+
+
+ Sexo
+
+
+ Causa general
+
+
+ Análisis del incidente
+
+
+ La investigación de incendio y mercancías peligrosas se envía aparte del incidente, una vez que el destino ya lo tiene.
+
+
+ Informes incompletos
+
+
+ Informes de incidente aún sin finalizar
+
+
+ Incluir entradas del registro heredado
+
+
+ Incompleto
+
+
+ Herido
+
+
+ Tipos de investigación
+
+
+ Elementos
+
+
+ Jurisdicción
+
+
+ Tipo
+
+
+ Matrícula
+
+
+ Código local
+
+
+ Registrar una solicitud de acceso
+
+
+ Marca
+
+
+ Manifiesto
+
+
+ asignados
+
+
+ coincidencias
+
+
+ Modelo
+
+
+ Año del modelo
+
+
+ Identificador NERIS del análisis
+
+
+ Código NERIS
+
+
+ No hay solicitudes de acceso registradas.
+
+
+ No se ha capturado ninguna evidencia para este informe.
+
+
+ Todavía no se ha preparado ninguna entrega.
+
+
+ No se aplica ninguna sección condicional hasta elegir un tipo de incidente.
+
+
+ Abiertas
+
+
+ Abrir el análisis
+
+
+ Abrir las solicitudes de acceso
+
+
+ Abrir la cola de incidentes
+
+
+ Abrir la cola de registros
+
+
+ Registros operativos
+
+
+ Vencidas
+
+
+ Obligaciones fuera de plazo
+
+
+ Tipo de persona
+
+
+ Miembro
+
+
+ Motorización
+
+
+ Preparada el
+
+
+ En el registro
+
+
+ Código principal
+
+
+ Preparar entrega
+
+
+ La entrega es un documento nuevo e inmutable; una modificación posterior no puede cambiar lo entregado.
+
+
+ Entregable
+
+
+ La suma de verificación sigue coincidiendo; la entrega no se ha alterado.
+
+
+ La suma de verificación no coincide con lo almacenado.
+
+
+ Entregas
+
+
+ Versión del contrato
+
+
+ Inmuebles
+
+
+ Cantidad
+
+
+ Poner el envío en cola
+
+
+ En cola
+
+
+ Origen étnico
+
+
+ Rango
+
+
+ Recibida el
+
+
+ Registros
+
+
+ Panel de registros
+
+
+ El módulo de registros aún no está activado para este departamento.
+
+
+ Perfil de ocultación
+
+
+ Rechazados
+
+
+ Rechazados por el destino y aún sin corregir
+
+
+ Entregar
+
+
+ Entregada el
+
+
+ Solicitud
+
+
+ Referencia
+
+
+ Persona solicitante
+
+
+ Datos de contacto
+
+
+ La identidad de quien solicita está restringida y no se muestra aquí.
+
+
+ Nombre de la persona solicitante
+
+
+ Organización
+
+
+ Obligatoria
+
+
+ Rescate
+
+
+ Altura del rescate
+
+
+ Modo de rescate
+
+
+ Vía de rescate
+
+
+ Tipo de rescate
+
+
+ Recurso
+
+
+ Recursos
+
+
+ solo en el registro del departamento, nunca se envía a NERIS
+
+
+ Algunos campos están restringidos y no se le muestran.
+
+
+ Devueltos para corrección
+
+
+ Guardar el alcance
+
+
+ Alcance
+
+
+ El alcance está congelado porque ya se ha preparado una entrega a partir de él.
+
+
+ Qué se ha solicitado
+
+
+ Resultado del alcance
+
+
+ Coinciden más registros de los que se listan aquí.
+
+
+ Código secundario
+
+
+ Batería implicada
+
+
+ Sustancia liberada
+
+
+ Sistema de extinción de cocina
+
+
+ Tubería de gas de acero inoxidable corrugado
+
+
+ Riesgo eléctrico
+
+
+ Datos del incendio
+
+
+ Sistema de alarma de incendios
+
+
+ Sistema de extinción
+
+
+ Situación peligrosa
+
+
+ Análisis de la situación peligrosa
+
+
+ Atención al paciente
+
+
+ Oxígeno medicinal domiciliario
+
+
+ Esta sección ya no corresponde a los tipos de incidente elegidos.
+
+
+ Otra alarma
+
+
+ Análisis del incendio exterior
+
+
+ Ubicación del incendio exterior
+
+
+ Riesgo de generación eléctrica
+
+
+ Producto implicado
+
+
+ Detector de humo
+
+
+ Ubicación del incendio en el edificio
+
+
+ Origen del incendio en el edificio
+
+
+ Enviado
+
+
+ Conjunto de valores
+
+
+ obsoletos
+
+
+ Iniciar el análisis
+
+
+ Estados
+
+
+ Si se deja en blanco, lo fija el plazo legal del departamento.
+
+
+ Plazo legal
+
+
+ Plantas sobre rasante
+
+
+ Plantas bajo rasante
+
+
+ Enviar
+
+
+ Enviados
+
+
+ Recomendada
+
+
+ Sustituida
+
+
+ Título
+
+
+ Estado de ocupación
+
+
+ Vehículos
+
+
+ Verificar la suma de comprobación
+
+
+ Número de bastidor
+
+
+ Ocupado en ese momento
+
+
+ Año
+
+
+ Año de construcción
+
+
+ Otro vehículo
+
+
+ Se necesitan credenciales nuevas al cambiar el tipo de concesión NERIS.
+
diff --git a/Core/Resgrid.Localization/Areas/User/Records/Records.fr.resx b/Core/Resgrid.Localization/Areas/User/Records/Records.fr.resx
index 72b4cf68..43045aad 100644
--- a/Core/Resgrid.Localization/Areas/User/Records/Records.fr.resx
+++ b/Core/Resgrid.Localization/Areas/User/Records/Records.fr.resx
@@ -1,4 +1,4 @@
-
+
text/microsoft-resx
2.0
@@ -343,4 +343,625 @@
File d'envoi
Paramètres NERIS enregistrés.
Envoi mis en file pour NERIS.
+
+ Accepté
+
+
+ Toutes les définitions
+
+
+ Analyses en attente de dépôt
+
+
+ Cette analyse est finalisée et sera déposée dès que l'incident lui-même parviendra à NERIS.
+
+
+ Sections de l'analyse
+
+
+ S'applique
+
+
+ Attribué à
+
+
+ Voiture
+
+
+ En attente de vérification
+
+
+ Dossiers soumis à vérification et pas encore approuvés
+
+
+ Retour au rapport d'incident
+
+
+ Type de carrosserie
+
+
+ Appel
+
+
+ Capturer
+
+
+ Motif de la saisie de cette preuve
+
+
+ Saisi par
+
+
+ Saisi le
+
+
+ Victimes et sauvetages
+
+
+ Victime
+
+
+ Action au moment des faits
+
+
+ Cause de la blessure
+
+
+ Moment de survenue
+
+
+ Civil
+
+
+ Clore la demande
+
+
+ Close le
+
+
+ Sections conditionnelles
+
+
+ Type de construction
+
+
+ Perte du contenu
+
+
+ Valeur du contenu
+
+
+ Couverture de la table de correspondance
+
+
+ Chaque type d'appel local sans code NERIS devra être classé à la main le soir même.
+
+
+ Devise
+
+
+ Niveau de dommage
+
+
+ Certains décomptes n'ont pas pu être produits :
+
+
+ Définition
+
+
+ Détail
+
+
+ Demande d'accès aux documents
+
+
+ La demande d'accès a été close.
+
+
+ La demande d'accès a été enregistrée.
+
+
+ Une demande d'accès est soumise à un délai légal ; elle est donc suivie ici plutôt que traitée au cas par cas.
+
+
+ Cette demande a dépassé son délai légal.
+
+
+ Un dossier expurgé a été préparé.
+
+
+ Demandes d'accès
+
+
+ Un motif est requis pour clore une demande d'accès.
+
+
+ Le dossier a été remis au demandeur.
+
+
+ Le périmètre a été enregistré.
+
+
+ Accès aux documents
+
+
+ Motif de la décision
+
+
+ Brouillons
+
+
+ Service au moment des faits
+
+
+ Modifier la table de correspondance
+
+
+ Modifier l'analyse de l'incident
+
+
+ Erreur
+
+
+ Perte estimée
+
+
+ Valeur estimée
+
+
+ Preuves
+
+
+ La preuve a été saisie.
+
+
+ Qualifications au moment de l'intervention
+
+
+ Messages d'incident versés au dossier
+
+
+ Chaque preuve est un instantané borné, pris une seule fois, avec somme de contrôle et jamais modifié ; une correction est une nouvelle saisie.
+
+
+ Consommables et stupéfiants utilisés
+
+
+ Disponibilité au moment de l'appel
+
+
+ Un motif est requis pour verser une preuve à un dossier officiel.
+
+
+ Décision d'engagement
+
+
+ Source
+
+
+ Positions des engins
+
+
+ Cette source de preuve n'avait rien à saisir pour ce dossier.
+
+
+ Élément exposé
+
+
+ Éléments exposés
+
+
+ Mortelle
+
+
+ La finalisation écrit la révision immuable. Le dépôt attend l'identifiant NERIS de l'incident s'il n'en a pas encore.
+
+
+ Finalisé le
+
+
+ Propagation du feu
+
+
+ Sapeur-pompier
+
+
+ Genre
+
+
+ Cause générale
+
+
+ Analyse de l'incident
+
+
+ L'enquête incendie et matières dangereuses est déposée séparément de l'incident, une fois que le destinataire le détient déjà.
+
+
+ Rapports incomplets
+
+
+ Rapports d'incident pas encore finalisés
+
+
+ Inclure les entrées de journal héritées
+
+
+ Incomplet
+
+
+ Blessé
+
+
+ Types d'enquête
+
+
+ Éléments
+
+
+ Juridiction
+
+
+ Nature
+
+
+ Plaque d'immatriculation
+
+
+ Code local
+
+
+ Enregistrer une demande d'accès
+
+
+ Marque
+
+
+ Manifeste
+
+
+ correspondants
+
+
+ correspondances
+
+
+ Modèle
+
+
+ Année-modèle
+
+
+ Identifiant NERIS de l'analyse
+
+
+ Code NERIS
+
+
+ Aucune demande d'accès n'est enregistrée.
+
+
+ Aucune preuve n'a été saisie pour ce rapport.
+
+
+ Rien n'a encore été produit.
+
+
+ Aucune section conditionnelle ne s'applique tant qu'un type d'incident n'est pas choisi.
+
+
+ Ouvertes
+
+
+ Ouvrir l'analyse
+
+
+ Ouvrir les demandes d'accès
+
+
+ Ouvrir la file des incidents
+
+
+ Ouvrir la file des dossiers
+
+
+ Dossiers opérationnels
+
+
+ En retard
+
+
+ Obligations dont l'échéance est dépassée
+
+
+ Type de personne
+
+
+ Membre
+
+
+ Motorisation
+
+
+ Préparé le
+
+
+ Au dossier
+
+
+ Code principal
+
+
+ Produire
+
+
+ Un dossier produit est un nouvel artefact immuable ; une modification ultérieure ne peut pas changer ce qui a été remis.
+
+
+ Communicable
+
+
+ La somme de contrôle correspond toujours ; le dossier n'a pas été modifié.
+
+
+ La somme de contrôle ne correspond pas à ce qui a été enregistré.
+
+
+ Dossiers produits
+
+
+ Version du contrat
+
+
+ Biens
+
+
+ Quantité
+
+
+ Mettre le dépôt en file
+
+
+ En file
+
+
+ Origine ethnique
+
+
+ Grade
+
+
+ Reçue le
+
+
+ Dossiers
+
+
+ Tableau de bord des dossiers
+
+
+ Le module dossiers n'est pas encore activé pour ce service.
+
+
+ Profil d'expurgation
+
+
+ Rejetés
+
+
+ Rejetés par le destinataire et pas encore corrigés
+
+
+ Remettre
+
+
+ Remise le
+
+
+ Demande
+
+
+ Référence
+
+
+ Demandeur
+
+
+ Coordonnées
+
+
+ L'identité du demandeur est protégée et n'est pas affichée ici.
+
+
+ Nom du demandeur
+
+
+ Organisme
+
+
+ Obligatoire
+
+
+ Sauvetage
+
+
+ Niveau du sauvetage
+
+
+ Mode de sauvetage
+
+
+ Voie du sauvetage
+
+
+ Type de sauvetage
+
+
+ Ressource
+
+
+ Ressources
+
+
+ conservé au dossier du service seulement, jamais transmis à NERIS
+
+
+ Certains champs sont protégés et ne vous sont pas montrés.
+
+
+ Retournés pour correction
+
+
+ Enregistrer le périmètre
+
+
+ Périmètre
+
+
+ Le périmètre est figé car un dossier en a déjà été produit.
+
+
+ Objet de la demande
+
+
+ Résultat du périmètre
+
+
+ Davantage de dossiers correspondent que ceux listés ici.
+
+
+ Code secondaire
+
+
+ Batterie impliquée
+
+
+ Produit chimique libéré
+
+
+ Système d'extinction de cuisine
+
+
+ Tuyauterie gaz inox annelée
+
+
+ Risque électrique
+
+
+ Détails de l'incendie
+
+
+ Système d'alarme incendie
+
+
+ Système d'extinction
+
+
+ Situation dangereuse
+
+
+ Analyse de la situation dangereuse
+
+
+ Prise en charge du patient
+
+
+ Oxygène médical à domicile
+
+
+ Cette section ne s'applique plus aux types d'incident retenus.
+
+
+ Autre système d'alarme
+
+
+ Analyse de l'incendie extérieur
+
+
+ Lieu de l'incendie extérieur
+
+
+ Risque lié à la production d'électricité
+
+
+ Produit impliqué
+
+
+ Détecteur de fumée
+
+
+ Lieu de l'incendie de bâtiment
+
+
+ Origine de l'incendie de bâtiment
+
+
+ Envoyé
+
+
+ Jeu de valeurs
+
+
+ obsolètes
+
+
+ Démarrer l'analyse
+
+
+ États
+
+
+ Laissé vide, le délai légal du service le détermine.
+
+
+ Échéance légale
+
+
+ Étages hors sol
+
+
+ Étages en sous-sol
+
+
+ Déposer
+
+
+ Déposés
+
+
+ Recommandée
+
+
+ Remplacée
+
+
+ Intitulé
+
+
+ État d'occupation
+
+
+ Véhicules
+
+
+ Vérifier la somme de contrôle
+
+
+ Numéro de série (VIN)
+
+
+ Occupé au moment des faits
+
+
+ Année
+
+
+ Année de construction
+
+
+ Autre véhicule
+
+
+ De nouvelles informations d'identification sont requises lorsque le type d'octroi NERIS change.
+
diff --git a/Core/Resgrid.Localization/Areas/User/Records/Records.it.resx b/Core/Resgrid.Localization/Areas/User/Records/Records.it.resx
index 36704af2..b805460c 100644
--- a/Core/Resgrid.Localization/Areas/User/Records/Records.it.resx
+++ b/Core/Resgrid.Localization/Areas/User/Records/Records.it.resx
@@ -1,4 +1,4 @@
-
+
text/microsoft-resx
2.0
@@ -343,4 +343,625 @@
Coda di invio
Impostazioni NERIS salvate.
Invio in coda per NERIS.
+
+ Accettato
+
+
+ Tutte le definizioni
+
+
+ Analisi in attesa di invio
+
+
+ Questa analisi è finalizzata e verrà inviata non appena l'intervento stesso raggiungerà NERIS.
+
+
+ Sezioni dell'analisi
+
+
+ Si applica
+
+
+ Assegnato a
+
+
+ Autovettura
+
+
+ In attesa di revisione
+
+
+ Documenti inviati in revisione e non ancora approvati
+
+
+ Torna al rapporto d'intervento
+
+
+ Tipo di carrozzeria
+
+
+ Chiamata
+
+
+ Acquisisci
+
+
+ Motivo dell'acquisizione di questa prova
+
+
+ Acquisito da
+
+
+ Acquisito il
+
+
+ Feriti e salvataggi
+
+
+ Ferito
+
+
+ Attività al momento
+
+
+ Causa del ferimento
+
+
+ Momento in cui è avvenuto
+
+
+ Civile
+
+
+ Chiudi la richiesta
+
+
+ Chiusa il
+
+
+ Sezioni condizionali
+
+
+ Tipo di costruzione
+
+
+ Danno al contenuto
+
+
+ Valore del contenuto
+
+
+ Copertura della corrispondenza
+
+
+ Ogni tipo di chiamata locale senza codice NERIS dovrà essere classificato a mano durante l'intervento.
+
+
+ Valuta
+
+
+ Grado di danno
+
+
+ Alcuni conteggi non sono stati calcolati:
+
+
+ Definizione
+
+
+ Dettaglio
+
+
+ Richiesta di accesso agli atti
+
+
+ La richiesta di accesso è stata chiusa.
+
+
+ La richiesta di accesso è stata registrata.
+
+
+ Una richiesta di accesso ha un termine di legge, perciò viene tracciata qui e non evasa in modo estemporaneo.
+
+
+ Questa richiesta ha superato il termine di legge.
+
+
+ È stata preparata una versione con omissis.
+
+
+ Richieste di accesso
+
+
+ Per chiudere una richiesta di accesso è necessaria una motivazione.
+
+
+ Il materiale è stato rilasciato al richiedente.
+
+
+ L'ambito è stato salvato.
+
+
+ Accesso agli atti
+
+
+ Motivazione dell'esito
+
+
+ Bozze
+
+
+ Servizio al momento
+
+
+ Modifica la corrispondenza
+
+
+ Modifica l'analisi dell'intervento
+
+
+ Errore
+
+
+ Danno stimato
+
+
+ Valore stimato
+
+
+ Prove
+
+
+ La prova è stata acquisita.
+
+
+ Qualifiche al momento dell'intervento
+
+
+ Messaggi dell'intervento acquisiti
+
+
+ Ogni prova è un'istantanea circoscritta, acquisita una sola volta, con checksum e mai modificata; una correzione è una nuova acquisizione.
+
+
+ Materiali e sostanze controllate utilizzati
+
+
+ Prontezza al momento della chiamata
+
+
+ Per inserire una prova in un atto ufficiale è necessaria una motivazione.
+
+
+ Decisione di invio
+
+
+ Fonte
+
+
+ Posizioni delle squadre
+
+
+ Quella fonte di prova non aveva nulla da acquisire per questo documento.
+
+
+ Elemento esposto
+
+
+ Elementi esposti
+
+
+ Mortale
+
+
+ La finalizzazione scrive la revisione immutabile. L'invio attende l'identificativo NERIS dell'intervento se non è ancora presente.
+
+
+ Finalizzato il
+
+
+ Propagazione dell'incendio
+
+
+ Vigile del fuoco
+
+
+ Genere
+
+
+ Causa generale
+
+
+ Analisi dell'intervento
+
+
+ L'indagine su incendio e materiali pericolosi viene inviata separatamente dall'intervento, una volta che il destinatario lo possiede già.
+
+
+ Rapporti incompleti
+
+
+ Rapporti d'intervento non ancora finalizzati
+
+
+ Includi le voci del registro storico
+
+
+ Incompleto
+
+
+ Ferito
+
+
+ Tipi di indagine
+
+
+ Elementi
+
+
+ Giurisdizione
+
+
+ Tipologia
+
+
+ Targa
+
+
+ Codice locale
+
+
+ Registra una richiesta di accesso
+
+
+ Marca
+
+
+ Manifesto
+
+
+ corrispondenti
+
+
+ corrispondenze
+
+
+ Modello
+
+
+ Anno del modello
+
+
+ Identificativo NERIS dell'analisi
+
+
+ Codice NERIS
+
+
+ Non risultano richieste di accesso registrate.
+
+
+ Non è stata acquisita alcuna prova per questo rapporto.
+
+
+ Non è stato ancora prodotto nulla.
+
+
+ Nessuna sezione condizionale si applica finché non viene scelto un tipo di intervento.
+
+
+ Aperte
+
+
+ Apri l'analisi
+
+
+ Apri le richieste di accesso
+
+
+ Apri la coda degli interventi
+
+
+ Apri la coda dei documenti
+
+
+ Documenti operativi
+
+
+ In ritardo
+
+
+ Obblighi oltre la scadenza
+
+
+ Tipo di persona
+
+
+ Membro
+
+
+ Motorizzazione
+
+
+ Preparato il
+
+
+ Presente nel documento
+
+
+ Codice principale
+
+
+ Produci
+
+
+ Il materiale prodotto è un nuovo documento immutabile; una modifica successiva non può cambiare ciò che è stato rilasciato.
+
+
+ Rilasciabile
+
+
+ Il checksum corrisponde ancora; il materiale non è stato alterato.
+
+
+ Il checksum non corrisponde a quanto memorizzato.
+
+
+ Materiali prodotti
+
+
+ Versione del contratto
+
+
+ Immobili
+
+
+ Quantità
+
+
+ Metti in coda l'invio
+
+
+ In coda
+
+
+ Etnia
+
+
+ Grado
+
+
+ Ricevuta il
+
+
+ Documenti
+
+
+ Cruscotto dei documenti
+
+
+ Il modulo documenti non è ancora attivato per questo comando.
+
+
+ Profilo di omissis
+
+
+ Respinti
+
+
+ Respinti dal destinatario e non ancora corretti
+
+
+ Rilascia
+
+
+ Rilasciata il
+
+
+ Richiesta
+
+
+ Riferimento
+
+
+ Richiedente
+
+
+ Recapiti
+
+
+ L'identità del richiedente è riservata e non viene mostrata qui.
+
+
+ Nome del richiedente
+
+
+ Organizzazione
+
+
+ Obbligatoria
+
+
+ Salvataggio
+
+
+ Quota del salvataggio
+
+
+ Modalità di salvataggio
+
+
+ Percorso del salvataggio
+
+
+ Tipo di salvataggio
+
+
+ Risorsa
+
+
+ Risorse
+
+
+ conservate solo nel documento del comando, mai inviate a NERIS
+
+
+ Alcuni campi sono riservati e non le vengono mostrati.
+
+
+ Restituiti per correzione
+
+
+ Salva l'ambito
+
+
+ Ambito
+
+
+ L'ambito è congelato perché è già stato prodotto del materiale su di esso.
+
+
+ Oggetto della richiesta
+
+
+ Risultato dell'ambito
+
+
+ Corrispondono più documenti di quelli elencati qui.
+
+
+ Codice secondario
+
+
+ Batteria coinvolta
+
+
+ Sostanza rilasciata
+
+
+ Impianto di spegnimento in cucina
+
+
+ Tubazione gas in acciaio inox corrugato
+
+
+ Rischio elettrico
+
+
+ Dettagli dell'incendio
+
+
+ Impianto di allarme antincendio
+
+
+ Impianto di spegnimento
+
+
+ Situazione pericolosa
+
+
+ Analisi della situazione pericolosa
+
+
+ Assistenza al paziente
+
+
+ Ossigeno medicale domiciliare
+
+
+ Questa sezione non si applica più ai tipi di intervento scelti.
+
+
+ Altro allarme
+
+
+ Analisi dell'incendio all'aperto
+
+
+ Luogo dell'incendio all'aperto
+
+
+ Rischio da generazione elettrica
+
+
+ Prodotto coinvolto
+
+
+ Rilevatore di fumo
+
+
+ Luogo dell'incendio in edificio
+
+
+ Origine dell'incendio in edificio
+
+
+ Inviato
+
+
+ Insieme di valori
+
+
+ obsoleti
+
+
+ Avvia l'analisi
+
+
+ Stati
+
+
+ Se lasciato vuoto, lo imposta il termine di legge del comando.
+
+
+ Termine di legge
+
+
+ Piani fuori terra
+
+
+ Piani interrati
+
+
+ Invia
+
+
+ Inviati
+
+
+ Consigliata
+
+
+ Sostituita
+
+
+ Titolo
+
+
+ Stato di occupazione
+
+
+ Veicoli
+
+
+ Verifica il checksum
+
+
+ Numero di telaio
+
+
+ Occupato al momento
+
+
+ Anno
+
+
+ Anno di costruzione
+
+
+ Altro veicolo
+
+
+ Quando cambia il tipo di concessione NERIS sono necessarie nuove credenziali.
+
diff --git a/Core/Resgrid.Localization/Areas/User/Records/Records.pl.resx b/Core/Resgrid.Localization/Areas/User/Records/Records.pl.resx
index b4300514..5d6ca794 100644
--- a/Core/Resgrid.Localization/Areas/User/Records/Records.pl.resx
+++ b/Core/Resgrid.Localization/Areas/User/Records/Records.pl.resx
@@ -1,4 +1,4 @@
-
+
text/microsoft-resx
2.0
@@ -343,4 +343,625 @@
Kolejka wysyłek
Zapisano ustawienia NERIS.
Wysyłka do NERIS w kolejce.
+
+ Zaakceptowano
+
+
+ Wszystkie definicje
+
+
+ Analizy oczekujące na złożenie
+
+
+ Ta analiza jest sfinalizowana i zostanie złożona, gdy samo zdarzenie trafi do NERIS.
+
+
+ Sekcje analizy
+
+
+ Dotyczy
+
+
+ Przypisano do
+
+
+ Samochód osobowy
+
+
+ Oczekuje na przegląd
+
+
+ Dokumenty przekazane do przeglądu i jeszcze niezatwierdzone
+
+
+ Powrót do raportu zdarzenia
+
+
+ Typ nadwozia
+
+
+ Zgłoszenie
+
+
+ Zarejestruj
+
+
+ Powód zarejestrowania tego dowodu
+
+
+ Zarejestrował
+
+
+ Zarejestrowano
+
+
+ Poszkodowani i ratowani
+
+
+ Poszkodowany
+
+
+ Czynność w chwili zdarzenia
+
+
+ Przyczyna obrażeń
+
+
+ Moment wystąpienia
+
+
+ Osoba cywilna
+
+
+ Zamknij wniosek
+
+
+ Zamknięto
+
+
+ Sekcje warunkowe
+
+
+ Rodzaj konstrukcji
+
+
+ Strata zawartości
+
+
+ Wartość zawartości
+
+
+ Pokrycie mapowania kodów
+
+
+ Każdy lokalny typ zgłoszenia bez kodu NERIS trzeba będzie sklasyfikować ręcznie podczas akcji.
+
+
+ Waluta
+
+
+ Stopień zniszczenia
+
+
+ Nie udało się obliczyć niektórych liczników:
+
+
+ Definicja
+
+
+ Szczegół
+
+
+ Wniosek o udostępnienie akt
+
+
+ Wniosek o udostępnienie akt został zamknięty.
+
+
+ Wniosek o udostępnienie akt został zarejestrowany.
+
+
+ Wniosek o udostępnienie akt ma ustawowy termin, dlatego jest tu śledzony, a nie załatwiany doraźnie.
+
+
+ Ten wniosek przekroczył ustawowy termin.
+
+
+ Przygotowano wersję z utajnionymi danymi.
+
+
+ Wnioski o udostępnienie akt
+
+
+ Do zamknięcia wniosku wymagane jest uzasadnienie.
+
+
+ Materiały przekazano wnioskodawcy.
+
+
+ Zakres został zapisany.
+
+
+ Udostępnianie akt
+
+
+ Uzasadnienie rozstrzygnięcia
+
+
+ Wersje robocze
+
+
+ Rodzaj służby
+
+
+ Edytuj mapowanie kodów
+
+
+ Edytuj analizę zdarzenia
+
+
+ Błąd
+
+
+ Szacowana strata
+
+
+ Szacowana wartość
+
+
+ Materiał dowodowy
+
+
+ Dowód został zarejestrowany.
+
+
+ Uprawnienia w chwili zdarzenia
+
+
+ Przeniesione wiadomości ze zdarzenia
+
+
+ Każdy dowód to ograniczona migawka wykonana raz, z sumą kontrolną i nigdy niezmieniana; poprawka to nowa rejestracja.
+
+
+ Zużyte materiały i środki kontrolowane
+
+
+ Gotowość w chwili zgłoszenia
+
+
+ Dołączenie dowodu do dokumentu urzędowego wymaga uzasadnienia.
+
+
+ Decyzja o zadysponowaniu
+
+
+ Źródło
+
+
+ Pozycje jednostek
+
+
+ To źródło dowodów nie miało nic do zarejestrowania dla tego dokumentu.
+
+
+ Obiekt narażony
+
+
+ Obiekty narażone
+
+
+ Śmiertelne
+
+
+ Sfinalizowanie zapisuje niezmienną wersję. Złożenie czeka na identyfikator NERIS zdarzenia, jeśli jeszcze go nie ma.
+
+
+ Sfinalizowano
+
+
+ Rozprzestrzenienie ognia
+
+
+ Strażak
+
+
+ Płeć
+
+
+ Przyczyna ogólna
+
+
+ Analiza zdarzenia
+
+
+ Dochodzenie pożarowe i ratownictwa chemicznego składa się osobno od zdarzenia, gdy odbiorca już je posiada.
+
+
+ Niekompletne raporty
+
+
+ Raporty zdarzeń jeszcze niesfinalizowane
+
+
+ Uwzględnij wpisy z dawnego dziennika
+
+
+ Niekompletne
+
+
+ Ranny
+
+
+ Rodzaje dochodzenia
+
+
+ Pozycje
+
+
+ Jurysdykcja
+
+
+ Rodzaj
+
+
+ Numer rejestracyjny
+
+
+ Kod lokalny
+
+
+ Zarejestruj wniosek o akta
+
+
+ Marka
+
+
+ Wykaz
+
+
+ zmapowane
+
+
+ dopasowane
+
+
+ Model
+
+
+ Rocznik
+
+
+ Identyfikator analizy NERIS
+
+
+ Kod NERIS
+
+
+ Nie zarejestrowano żadnych wniosków o akta.
+
+
+ Do tego raportu nie zarejestrowano żadnych dowodów.
+
+
+ Nic jeszcze nie przygotowano.
+
+
+ Żadna sekcja warunkowa nie obowiązuje, dopóki nie wybrano typu zdarzenia.
+
+
+ Otwarte
+
+
+ Otwórz analizę
+
+
+ Otwórz wnioski o akta
+
+
+ Otwórz kolejkę zdarzeń
+
+
+ Otwórz kolejkę dokumentów
+
+
+ Dokumentacja operacyjna
+
+
+ Po terminie
+
+
+ Obowiązki po terminie
+
+
+ Rodzaj osoby
+
+
+ Członek
+
+
+ Napęd
+
+
+ Przygotowano
+
+
+ W dokumencie
+
+
+ Kod główny
+
+
+ Przygotuj materiały
+
+
+ Przygotowane materiały to nowy, niezmienny dokument; późniejsza zmiana nie zmieni tego, co wydano.
+
+
+ Do wydania
+
+
+ Suma kontrolna nadal się zgadza; materiały nie zostały zmienione.
+
+
+ Suma kontrolna nie zgadza się z zapisaną.
+
+
+ Wydane materiały
+
+
+ Wersja kontraktu
+
+
+ Nieruchomości
+
+
+ Ilość
+
+
+ Zakolejkuj złożenie
+
+
+ W kolejce
+
+
+ Pochodzenie etniczne
+
+
+ Stopień
+
+
+ Wpłynął
+
+
+ Dokumenty
+
+
+ Pulpit dokumentacji
+
+
+ Moduł dokumentacji nie jest jeszcze aktywny dla tej jednostki.
+
+
+ Profil utajniania
+
+
+ Odrzucone
+
+
+ Odrzucone przez odbiorcę i jeszcze niepoprawione
+
+
+ Wydaj
+
+
+ Wydano
+
+
+ Wniosek
+
+
+ Sygnatura
+
+
+ Wnioskodawca
+
+
+ Dane kontaktowe
+
+
+ Tożsamość wnioskodawcy jest chroniona i nie jest tu pokazywana.
+
+
+ Imię i nazwisko wnioskodawcy
+
+
+ Organizacja
+
+
+ Wymagana
+
+
+ Ratowanie
+
+
+ Poziom ratowania
+
+
+ Sposób ratowania
+
+
+ Droga ratowania
+
+
+ Rodzaj ratowania
+
+
+ Zasób
+
+
+ Zasoby
+
+
+ przechowywane tylko w dokumentacji jednostki, nigdy nie wysyłane do NERIS
+
+
+ Niektóre pola są chronione i nie są tu pokazywane.
+
+
+ Zwrócone do poprawy
+
+
+ Zapisz zakres
+
+
+ Zakres
+
+
+ Zakres jest zamrożony, bo przygotowano już na jego podstawie materiały.
+
+
+ Czego dotyczy wniosek
+
+
+ Wynik zakresu
+
+
+ Pasuje więcej dokumentów, niż tu wymieniono.
+
+
+ Kod dodatkowy
+
+
+ Akumulator, którego dotyczy zdarzenie
+
+
+ Uwolniona substancja
+
+
+ System gaśniczy w kuchni
+
+
+ Karbowana rura gazowa ze stali nierdzewnej
+
+
+ Zagrożenie elektryczne
+
+
+ Dane pożaru
+
+
+ System sygnalizacji pożarowej
+
+
+ System gaśniczy
+
+
+ Sytuacja niebezpieczna
+
+
+ Analiza sytuacji niebezpiecznej
+
+
+ Opieka nad pacjentem
+
+
+ Domowy tlen medyczny
+
+
+ Ta sekcja nie dotyczy już wybranych typów zdarzenia.
+
+
+ Inny alarm
+
+
+ Analiza pożaru na zewnątrz
+
+
+ Miejsce pożaru na zewnątrz
+
+
+ Zagrożenie od wytwarzania energii
+
+
+ Wyrób, którego dotyczy zdarzenie
+
+
+ Czujka dymu
+
+
+ Miejsce pożaru w budynku
+
+
+ Miejsce powstania pożaru budynku
+
+
+ Wysłano
+
+
+ Zbiór wartości
+
+
+ nieaktualne
+
+
+ Rozpocznij analizę
+
+
+ Stany
+
+
+ Pozostawione puste, ustala je ustawowy termin jednostki.
+
+
+ Termin ustawowy
+
+
+ Kondygnacje nadziemne
+
+
+ Kondygnacje podziemne
+
+
+ Złóż
+
+
+ Złożone
+
+
+ Zalecana
+
+
+ Zastąpiony
+
+
+ Tytuł
+
+
+ Stan użytkowania
+
+
+ Pojazdy
+
+
+ Sprawdź sumę kontrolną
+
+
+ Numer VIN nadwozia
+
+
+ Zajęty w chwili zdarzenia
+
+
+ Rok
+
+
+ Rok budowy
+
+
+ Inny pojazd
+
+
+ Zmiana typu uprawnienia NERIS wymaga podania nowych poświadczeń.
+
diff --git a/Core/Resgrid.Localization/Areas/User/Records/Records.sv.resx b/Core/Resgrid.Localization/Areas/User/Records/Records.sv.resx
index c3ecbd1c..a24a9126 100644
--- a/Core/Resgrid.Localization/Areas/User/Records/Records.sv.resx
+++ b/Core/Resgrid.Localization/Areas/User/Records/Records.sv.resx
@@ -1,4 +1,4 @@
-
+
text/microsoft-resx
2.0
@@ -343,4 +343,625 @@
Inlämningskö
NERIS-inställningar sparade.
Inlämning köad för NERIS.
+
+ Accepterad
+
+
+ Alla definitioner
+
+
+ Analyser som väntar på inlämning
+
+
+ Analysen är slutförd och skickas så snart själva händelsen når NERIS.
+
+
+ Analysavsnitt
+
+
+ Gäller
+
+
+ Tilldelad till
+
+
+ Personbil
+
+
+ Väntar på granskning
+
+
+ Poster som skickats för granskning och ännu inte godkänts
+
+
+ Tillbaka till händelserapporten
+
+
+ Karosserityp
+
+
+ Larm
+
+
+ Fånga
+
+
+ Skäl till att detta underlag fångas
+
+
+ Fångad av
+
+
+ Fångad
+
+
+ Skadade och räddade
+
+
+ Skadad
+
+
+ Aktivitet vid tillfället
+
+
+ Skadeorsak
+
+
+ När det inträffade
+
+
+ Civilperson
+
+
+ Avsluta begäran
+
+
+ Avslutad
+
+
+ Villkorade avsnitt
+
+
+ Byggnadstyp
+
+
+ Skada på lösöre
+
+
+ Värde på lösöre
+
+
+ Täckning för kodmappning
+
+
+ Varje lokal larmtyp utan NERIS-kod måste klassificeras för hand under insatsen.
+
+
+ Valuta
+
+
+ Skadegrad
+
+
+ Vissa värden kunde inte tas fram:
+
+
+ Definition
+
+
+ Detalj
+
+
+ Begäran om allmän handling
+
+
+ Begäran om allmän handling har avslutats.
+
+
+ Begäran om allmän handling har registrerats.
+
+
+ En begäran om allmän handling har en lagstadgad frist och följs därför upp här i stället för att besvaras ad hoc.
+
+
+ Denna begäran har passerat sin lagstadgade frist.
+
+
+ En maskad leverans har tagits fram.
+
+
+ Begäranden om allmän handling
+
+
+ Ett skäl krävs för att avsluta en begäran.
+
+
+ Leveransen har lämnats ut till den som begärt den.
+
+
+ Omfattningen har sparats.
+
+
+ Allmänna handlingar
+
+
+ Skäl till beslutet
+
+
+ Utkast
+
+
+ Tjänstgöring vid tillfället
+
+
+ Redigera kodmappningen
+
+
+ Redigera händelseanalysen
+
+
+ Fel
+
+
+ Uppskattad skada
+
+
+ Uppskattat värde
+
+
+ Underlag
+
+
+ Underlaget har fångats.
+
+
+ Behörigheter vid händelsetillfället
+
+
+ Överförda händelsemeddelanden
+
+
+ Varje underlag är en avgränsad ögonblicksbild som tas en gång, får en kontrollsumma och aldrig ändras; en rättelse är en ny fångst.
+
+
+ Förbrukat material och narkotikaklassade preparat
+
+
+ Beredskap vid larmtillfället
+
+
+ Ett skäl krävs för att föra in underlag i en officiell handling.
+
+
+ Utlarmningsbeslut
+
+
+ Källa
+
+
+ Enheternas positioner
+
+
+ Den underlagskällan hade inget att fånga för denna post.
+
+
+ Utsatt objekt
+
+
+ Utsatta objekt
+
+
+ Dödlig
+
+
+ Slutförandet skriver den oföränderliga versionen. Inlämningen väntar på händelsens NERIS-id om det saknas.
+
+
+ Slutförd
+
+
+ Brandspridning
+
+
+ Brandman
+
+
+ Kön
+
+
+ Allmän orsak
+
+
+ Händelseanalys
+
+
+ Brand- och farligt gods-utredningen lämnas in separat från händelsen, när mottagaren redan har den.
+
+
+ Ofullständiga rapporter
+
+
+ Händelserapporter som ännu inte slutförts
+
+
+ Inkludera äldre loggposter
+
+
+ Ofullständig
+
+
+ Skadad
+
+
+ Utredningstyper
+
+
+ Poster
+
+
+ Jurisdiktion
+
+
+ Slag
+
+
+ Registreringsnummer
+
+
+ Lokal kod
+
+
+ Registrera en begäran
+
+
+ Märke
+
+
+ Innehållsförteckning
+
+
+ mappade
+
+
+ träffar
+
+
+ Modell
+
+
+ Årsmodell
+
+
+ NERIS analys-id
+
+
+ NERIS-kod
+
+
+ Inga begäranden är registrerade.
+
+
+ Inget underlag har fångats för denna rapport.
+
+
+ Inget har tagits fram ännu.
+
+
+ Inga villkorade avsnitt gäller förrän en händelsetyp valts.
+
+
+ Öppna
+
+
+ Öppna analysen
+
+
+ Öppna begärandena
+
+
+ Öppna händelsekön
+
+
+ Öppna postkön
+
+
+ Operativa poster
+
+
+ Försenad
+
+
+ Skyldigheter som passerat sitt datum
+
+
+ Persontyp
+
+
+ Medlem
+
+
+ Drivlina
+
+
+ Framtagen
+
+
+ I posten
+
+
+ Primär kod
+
+
+ Ta fram leverans
+
+
+ En leverans är en ny oföränderlig handling; en senare ändring kan inte påverka det som lämnats ut.
+
+
+ Kan lämnas ut
+
+
+ Kontrollsumman stämmer fortfarande; leveransen har inte ändrats.
+
+
+ Kontrollsumman stämmer inte med det lagrade värdet.
+
+
+ Leveranser
+
+
+ Kontraktsversion
+
+
+ Fastigheter
+
+
+ Mängd
+
+
+ Köa inlämningen
+
+
+ Köad
+
+
+ Etnicitet
+
+
+ Grad
+
+
+ Mottagen
+
+
+ Poster
+
+
+ Översikt för poster
+
+
+ Postmodulen är ännu inte aktiverad för denna kår.
+
+
+ Maskeringsprofil
+
+
+ Avvisade
+
+
+ Avvisade av mottagaren och ännu inte rättade
+
+
+ Lämna ut
+
+
+ Utlämnad
+
+
+ Begäran
+
+
+ Referens
+
+
+ Sökande
+
+
+ Kontaktuppgifter
+
+
+ Vem som begärt uppgifterna är skyddat och visas inte här.
+
+
+ Sökandens namn
+
+
+ Organisation
+
+
+ Obligatorisk
+
+
+ Räddning
+
+
+ Räddningens nivå
+
+
+ Räddningssätt
+
+
+ Räddningsväg
+
+
+ Räddningstyp
+
+
+ Resurs
+
+
+ Resurser
+
+
+ sparas endast i kårens post, skickas aldrig till NERIS
+
+
+ Vissa fält är skyddade och visas inte för dig.
+
+
+ Återsända för rättelse
+
+
+ Spara omfattningen
+
+
+ Omfattning
+
+
+ Omfattningen är låst eftersom en leverans redan tagits fram utifrån den.
+
+
+ Vad som begärts
+
+
+ Vad omfattningen ger
+
+
+ Fler poster matchar än de som listas här.
+
+
+ Sekundär kod
+
+
+ Inblandat batteri
+
+
+ Utsläppt kemikalie
+
+
+ Släcksystem för kök
+
+
+ Korrugerad rostfri gasslang
+
+
+ Elrisk
+
+
+ Branduppgifter
+
+
+ Brandlarmsystem
+
+
+ Släcksystem
+
+
+ Farlig situation
+
+
+ Analys av farlig situation
+
+
+ Patientvård
+
+
+ Medicinsk syrgas i hemmet
+
+
+ Detta avsnitt gäller inte längre för de valda händelsetyperna.
+
+
+ Annat larm
+
+
+ Analys av utomhusbrand
+
+
+ Brandplats utomhus
+
+
+ Risk från elproduktion
+
+
+ Inblandad produkt
+
+
+ Brandvarnare
+
+
+ Brandplats i byggnad
+
+
+ Startpunkt för byggnadsbranden
+
+
+ Skickad
+
+
+ Värdemängd
+
+
+ föråldrade
+
+
+ Starta analysen
+
+
+ Statusar
+
+
+ Lämnas det tomt sätts det av kårens lagstadgade frist.
+
+
+ Lagstadgad frist
+
+
+ Våningar ovan mark
+
+
+ Våningar under mark
+
+
+ Lämna in
+
+
+ Inlämnade
+
+
+ Rekommenderad
+
+
+ Ersatt
+
+
+ Rubrik
+
+
+ Nyttjandestatus
+
+
+ Fordon
+
+
+ Verifiera kontrollsumman
+
+
+ Chassinummer
+
+
+ Upptaget vid tillfället
+
+
+ År
+
+
+ Byggår
+
+
+ Annat fordon
+
+
+ Nya inloggningsuppgifter krävs när NERIS-behörighetstypen ändras.
+
diff --git a/Core/Resgrid.Localization/Areas/User/Records/Records.uk.resx b/Core/Resgrid.Localization/Areas/User/Records/Records.uk.resx
index 375ce00d..49a0186a 100644
--- a/Core/Resgrid.Localization/Areas/User/Records/Records.uk.resx
+++ b/Core/Resgrid.Localization/Areas/User/Records/Records.uk.resx
@@ -1,4 +1,4 @@
-
+
text/microsoft-resx
2.0
@@ -343,4 +343,625 @@
Черга подань
Налаштування NERIS збережено.
Подання поставлено в чергу для NERIS.
+
+ Прийнято
+
+
+ Усі визначення
+
+
+ Аналізи, що очікують подання
+
+
+ Цей аналіз завершено; його буде подано, щойно сам виклик потрапить до NERIS.
+
+
+ Розділи аналізу
+
+
+ Застосовується
+
+
+ Призначено
+
+
+ Легковий автомобіль
+
+
+ Очікує на перевірку
+
+
+ Записи, подані на перевірку й ще не затверджені
+
+
+ Назад до звіту про виклик
+
+
+ Тип кузова
+
+
+ Виклик
+
+
+ Зафіксувати
+
+
+ Причина фіксації цього доказу
+
+
+ Зафіксував
+
+
+ Зафіксовано
+
+
+ Постраждалі та врятовані
+
+
+ Постраждалий
+
+
+ Дія на той момент
+
+
+ Причина травми
+
+
+ Коли це сталося
+
+
+ Цивільна особа
+
+
+ Закрити запит
+
+
+ Закрито
+
+
+ Умовні розділи
+
+
+ Тип конструкції
+
+
+ Втрати вмісту
+
+
+ Вартість вмісту
+
+
+ Покриття зіставлення кодів
+
+
+ Кожен місцевий тип виклику без коду NERIS доведеться класифікувати вручну під час події.
+
+
+ Валюта
+
+
+ Ступінь пошкодження
+
+
+ Деякі підрахунки не вдалося виконати:
+
+
+ Визначення
+
+
+ Подробиця
+
+
+ Запит на доступ до документів
+
+
+ Запит на доступ до документів закрито.
+
+
+ Запит на доступ до документів зареєстровано.
+
+
+ Запит на доступ до документів має встановлений законом строк, тому його відстежують тут, а не опрацьовують принагідно.
+
+
+ Цей запит прострочив встановлений законом строк.
+
+
+ Підготовлено відредаговану добірку.
+
+
+ Запити на доступ до документів
+
+
+ Щоб закрити запит, потрібно вказати причину.
+
+
+ Добірку передано заявникові.
+
+
+ Обсяг збережено.
+
+
+ Доступ до документів
+
+
+ Підстава рішення
+
+
+ Чернетки
+
+
+ Вид служби на той момент
+
+
+ Редагувати зіставлення кодів
+
+
+ Редагувати аналіз виклику
+
+
+ Помилка
+
+
+ Оцінені збитки
+
+
+ Оцінена вартість
+
+
+ Докази
+
+
+ Доказ зафіксовано.
+
+
+ Кваліфікації на час виклику
+
+
+ Долучені повідомлення з виклику
+
+
+ Кожен доказ — обмежений знімок, зроблений один раз, з контрольною сумою і без змін; виправлення — це нова фіксація.
+
+
+ Використані матеріали та підконтрольні речовини
+
+
+ Готовність на момент виклику
+
+
+ Щоб долучити доказ до офіційного запису, потрібно вказати причину.
+
+
+ Рішення про висилання
+
+
+ Джерело
+
+
+ Координати підрозділів
+
+
+ Це джерело доказів не мало чого зафіксувати для цього запису.
+
+
+ Об'єкт впливу
+
+
+ Об'єкти впливу
+
+
+ Смертельний
+
+
+ Завершення записує незмінну версію. Подання чекає на ідентифікатор NERIS виклику, якщо його ще немає.
+
+
+ Завершено
+
+
+ Поширення вогню
+
+
+ Пожежний
+
+
+ Стать
+
+
+ Загальна причина
+
+
+ Аналіз виклику
+
+
+ Розслідування пожежі та небезпечних речовин подають окремо від виклику, коли отримувач уже має його.
+
+
+ Незавершені звіти
+
+
+ Звіти про виклики, ще не завершені
+
+
+ Включати застарілі записи журналу
+
+
+ Незавершені
+
+
+ Травмовано
+
+
+ Види розслідування
+
+
+ Записи
+
+
+ Юрисдикція
+
+
+ Вид
+
+
+ Номерний знак
+
+
+ Локальний код
+
+
+ Зареєструвати запит
+
+
+ Марка
+
+
+ Опис вмісту
+
+
+ зіставлено
+
+
+ знайдено
+
+
+ Модель
+
+
+ Модельний рік
+
+
+ Ідентифікатор аналізу NERIS
+
+
+ Код NERIS
+
+
+ Запитів на доступ не зареєстровано.
+
+
+ До цього звіту не зафіксовано жодних доказів.
+
+
+ Ще нічого не підготовлено.
+
+
+ Умовні розділи не застосовуються, доки не обрано тип виклику.
+
+
+ Відкриті
+
+
+ Відкрити аналіз
+
+
+ Відкрити запити на доступ
+
+
+ Відкрити чергу викликів
+
+
+ Відкрити чергу записів
+
+
+ Оперативні записи
+
+
+ Прострочені
+
+
+ Обов'язки, строк яких минув
+
+
+ Тип особи
+
+
+ Член підрозділу
+
+
+ Силова установка
+
+
+ Підготовлено
+
+
+ У записі
+
+
+ Основний код
+
+
+ Підготувати добірку
+
+
+ Добірка — це новий незмінний документ; пізніші зміни не змінять того, що було видано.
+
+
+ Можна видати
+
+
+ Контрольна сума збігається; добірку не змінювали.
+
+
+ Контрольна сума не збігається зі збереженою.
+
+
+ Підготовлені добірки
+
+
+ Версія контракту
+
+
+ Об'єкти нерухомості
+
+
+ Кількість
+
+
+ Поставити подання в чергу
+
+
+ У черзі
+
+
+ Етнічна належність
+
+
+ Звання
+
+
+ Отримано
+
+
+ Записи
+
+
+ Панель записів
+
+
+ Модуль записів ще не активовано для цього підрозділу.
+
+
+ Профіль редагування
+
+
+ Відхилені
+
+
+ Відхилені отримувачем і ще не виправлені
+
+
+ Видати
+
+
+ Видано
+
+
+ Запит
+
+
+ Реєстраційний номер
+
+
+ Заявник
+
+
+ Контактні дані
+
+
+ Особу заявника захищено, і тут вона не показується.
+
+
+ Ім'я заявника
+
+
+ Організація
+
+
+ Обов'язковий
+
+
+ Рятування
+
+
+ Рівень рятування
+
+
+ Спосіб рятування
+
+
+ Шлях рятування
+
+
+ Тип рятування
+
+
+ Ресурс
+
+
+ Ресурси
+
+
+ зберігається лише в записі підрозділу, ніколи не надсилається до NERIS
+
+
+ Деякі поля обмежені й вам не показуються.
+
+
+ Повернуті на виправлення
+
+
+ Зберегти обсяг
+
+
+ Обсяг
+
+
+ Обсяг зафіксовано, бо на його основі вже підготовлено добірку.
+
+
+ Що саме запитано
+
+
+ Що охоплює обсяг
+
+
+ Відповідає більше записів, ніж перелічено тут.
+
+
+ Додатковий код
+
+
+ Задіяна батарея
+
+
+ Викинута хімічна речовина
+
+
+ Кухонна система пожежогасіння
+
+
+ Гофрована газова труба з нержавіючої сталі
+
+
+ Електрична небезпека
+
+
+ Дані про пожежу
+
+
+ Система пожежної сигналізації
+
+
+ Система пожежогасіння
+
+
+ Небезпечна ситуація
+
+
+ Аналіз небезпечної ситуації
+
+
+ Допомога пацієнту
+
+
+ Домашній медичний кисень
+
+
+ Цей розділ більше не стосується обраних типів виклику.
+
+
+ Інша сигналізація
+
+
+ Аналіз пожежі на відкритій місцевості
+
+
+ Місце пожежі на відкритій місцевості
+
+
+ Небезпека від генерації електроенергії
+
+
+ Задіяний виріб
+
+
+ Димовий сповіщувач
+
+
+ Місце пожежі в будівлі
+
+
+ Осередок пожежі в будівлі
+
+
+ Надіслано
+
+
+ Набір значень
+
+
+ застарілі
+
+
+ Розпочати аналіз
+
+
+ Статуси
+
+
+ Якщо залишити порожнім, дату визначить встановлений законом строк підрозділу.
+
+
+ Встановлений законом строк
+
+
+ Поверхів над рівнем землі
+
+
+ Поверхів нижче рівня землі
+
+
+ Подати
+
+
+ Подані
+
+
+ Рекомендований
+
+
+ Замінено
+
+
+ Назва
+
+
+ Стан заселеності
+
+
+ Транспортні засоби
+
+
+ Перевірити контрольну суму
+
+
+ Ідентифікаційний номер кузова
+
+
+ Був зайнятий на той момент
+
+
+ Рік
+
+
+ Рік побудови
+
+
+ Інший транспортний засіб
+
+
+ Після зміни типу надання доступу NERIS потрібні нові облікові дані.
+
diff --git a/Core/Resgrid.Model/Providers/INerisProviders.cs b/Core/Resgrid.Model/Providers/INerisProviders.cs
index 5f0ffdc6..baf1422e 100644
--- a/Core/Resgrid.Model/Providers/INerisProviders.cs
+++ b/Core/Resgrid.Model/Providers/INerisProviders.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@@ -43,6 +43,9 @@ public interface INerisMappingService
{
/// The exact IncidentPayload JSON the destination receives (the immutable submission artifact).
string BuildIncidentPayloadJson(NerisIncidentSnapshot snapshot, RmsNerisProfile profile);
+
+ /// The exact IncidentAnalysisPayload JSON for the separate fire/hazmat analysis filing (RMS-3).
+ string BuildIncidentAnalysisPayloadJson(NerisIncidentAnalysisSnapshot snapshot, RmsNerisProfile profile);
}
/// Local (offline) validation against the pinned contract's requiredness, value sets and time sequence; remote validation through the client.
@@ -50,6 +53,15 @@ public interface INerisValidationService
{
List ValidateLocal(NerisIncidentSnapshot snapshot, RmsNerisProfile profile);
+ /// Local validation of the separate incident-analysis filing (RMS-3); never blocks the incident.
+ List ValidateAnalysisLocal(NerisIncidentAnalysisSnapshot snapshot, RmsNerisProfile profile);
+
+ ///
+ /// The conditional sections a set of incident types demands or suggests (RMS-3 progressive section rules).
+ /// Exposed so the authoring surfaces render exactly what validation will enforce.
+ ///
+ IReadOnlyList GetSectionRequirements(IEnumerable incidentTypeCodes);
+
Task> ValidateRemoteAsync(RmsNerisProfile profile, string payloadJson, CancellationToken cancellationToken = default);
}
@@ -63,6 +75,13 @@ public interface INerisApiClient
Task UpdateIncidentAsync(RmsNerisProfile profile, NerisCredential credential, string nerisIncidentId, string payloadJson, CancellationToken cancellationToken = default);
Task GetStatusAsync(RmsNerisProfile profile, NerisCredential credential, string nerisIncidentId, CancellationToken cancellationToken = default);
+
+ // Incident analysis (RMS-3): a second filing against an incident the destination already holds.
+ Task CreateIncidentAnalysisAsync(RmsNerisProfile profile, NerisCredential credential, string nerisIncidentId, string payloadJson, CancellationToken cancellationToken = default);
+
+ Task UpdateIncidentAnalysisAsync(RmsNerisProfile profile, NerisCredential credential, string nerisAnalysisId, string payloadJson, CancellationToken cancellationToken = default);
+
+ Task GetIncidentAnalysisStatusAsync(RmsNerisProfile profile, NerisCredential credential, string nerisAnalysisId, CancellationToken cancellationToken = default);
}
///
@@ -75,5 +94,14 @@ public interface INerisSubmissionService
Task DeliverAsync(RmsNerisProfile profile, RmsSubmission submission, string existingNerisIncidentId, CancellationToken cancellationToken = default);
Task CheckStatusAsync(RmsNerisProfile profile, string nerisIncidentId, CancellationToken cancellationToken = default);
+
+ ///
+ /// Delivers the incident-analysis filing (RMS-3). is the incident the
+ /// analysis files against and is required for the first delivery;
+ /// switches the call to an update once the destination holds the analysis.
+ ///
+ Task DeliverAnalysisAsync(RmsNerisProfile profile, RmsSubmission submission, string nerisIncidentId, string existingNerisAnalysisId, CancellationToken cancellationToken = default);
+
+ Task CheckAnalysisStatusAsync(RmsNerisProfile profile, string nerisAnalysisId, CancellationToken cancellationToken = default);
}
}
diff --git a/Core/Resgrid.Model/Records/IncidentReportContracts.cs b/Core/Resgrid.Model/Records/IncidentReportContracts.cs
index cffe2943..f8aa8c33 100644
--- a/Core/Resgrid.Model/Records/IncidentReportContracts.cs
+++ b/Core/Resgrid.Model/Records/IncidentReportContracts.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
namespace Resgrid.Model
@@ -14,6 +14,14 @@ public class IncidentReportAggregate
public List Tactics { get; set; } = new List();
public RmsNarrative Narrative { get; set; }
public List Facts { get; set; } = new List();
+ /// RMS-3 conditional sections (fire, hazsit, alarms, suppression, emerging hazards, medical).
+ public List Modules { get; set; } = new List();
+ /// RMS-3 non-unit resources used on the incident.
+ public List Resources { get; set; } = new List();
+ /// RMS-3 restricted class: civilian and responder casualties and rescues.
+ public List Casualties { get; set; } = new List();
+ /// RMS-3: property other than the incident property that the incident damaged.
+ public List Exposures { get; set; } = new List();
public List Issues { get; set; } = new List();
public List Submissions { get; set; } = new List();
public List Signatures { get; set; } = new List();
@@ -117,6 +125,159 @@ public class IncidentReportDraftInput
public string OutcomeNarrative { get; set; }
public string SupplementalJson { get; set; }
public RmsOriginClient OriginClient { get; set; } = RmsOriginClient.Web;
+
+ // RMS-3 conditional sections. Null means "leave this section alone"; an empty list clears it. Draft saves
+ // from a client that does not render a section must not silently delete the section an officer authored on
+ // the Web, which is why absence and emptiness are different here and nowhere else in this input.
+ public List Modules { get; set; }
+ public List Resources { get; set; }
+ public List Casualties { get; set; }
+ public List Exposures { get; set; }
+ }
+
+ /// One conditional section instance being saved; is the contract-shaped body.
+ public class IncidentModuleInput
+ {
+ public RmsIncidentModuleKind Kind { get; set; }
+ public string PrimaryCode { get; set; }
+ public string SecondaryCode { get; set; }
+ public decimal? Quantity { get; set; }
+ public string QuantityUnit { get; set; }
+ public DateTime? OccurredOn { get; set; }
+ public string DetailJson { get; set; }
+ }
+
+ public class IncidentResourceInput
+ {
+ public string ResourceCode { get; set; }
+ public int? Quantity { get; set; }
+ public string Detail { get; set; }
+ }
+
+ ///
+ /// A casualty or rescue. Restricted fields are only accepted from a caller holding RecordRestricted_View; the
+ /// service drops them otherwise rather than failing the save, so a reviewer without the restricted grant can
+ /// still correct the unrestricted half of a report.
+ ///
+ public class IncidentCasualtyRescueInput
+ {
+ public RmsCasualtyRescueKind Kind { get; set; }
+ public string PersonType { get; set; }
+ public string PersonnelUserId { get; set; }
+ public string Rank { get; set; }
+ public decimal? YearsOfService { get; set; }
+ public string JobClassification { get; set; }
+ public string BirthMonthYear { get; set; }
+ public string Gender { get; set; }
+ public string Race { get; set; }
+ public bool? WasInjured { get; set; }
+ public string CasualtyCause { get; set; }
+ public string CasualtyAction { get; set; }
+ public string CasualtyTimeline { get; set; }
+ public string DutyType { get; set; }
+ public List Ppe { get; set; } = new List();
+ public string InjuryDetailJson { get; set; }
+ public bool WasFatal { get; set; }
+ public string RescueType { get; set; }
+ public List RescueActions { get; set; } = new List();
+ public List RescueImpediments { get; set; } = new List();
+ public string RescueMode { get; set; }
+ public string RescuePath { get; set; }
+ public string RescueElevation { get; set; }
+ public string PresenceKnown { get; set; }
+ public DateTime? OccurredOn { get; set; }
+ public string DetailJson { get; set; }
+ }
+
+ public class IncidentExposureInput
+ {
+ public string LocationKind { get; set; }
+ public string ItemType { get; set; }
+ public string DamageType { get; set; }
+ public string LocationUse { get; set; }
+ public bool? PeoplePresent { get; set; }
+ public int? DisplacementCount { get; set; }
+ public List DisplacementCauses { get; set; } = new List();
+ public string AddressText { get; set; }
+ public string Street { get; set; }
+ public string Municipality { get; set; }
+ public string State { get; set; }
+ public string PostalCode { get; set; }
+ public decimal? Latitude { get; set; }
+ public decimal? Longitude { get; set; }
+ public decimal? EstimatedValue { get; set; }
+ public decimal? EstimatedLoss { get; set; }
+ public string CurrencyCode { get; set; }
+ public string DetailJson { get; set; }
+ }
+
+ /// The incident-analysis filing as its authoring surface and the mapper read it (RMS-3).
+ public class IncidentAnalysisAggregate
+ {
+ public RmsIncidentAnalysis Analysis { get; set; }
+ /// The incident this analysis files against; needed for the destination id and the base block.
+ public RmsIncidentReport Report { get; set; }
+ public List Modules { get; set; } = new List();
+ public List Properties { get; set; } = new List();
+ public List Vehicles { get; set; } = new List();
+ public List Submissions { get; set; } = new List();
+ public List Revisions { get; set; } = new List();
+
+ public RmsIncidentAnalysisState State => (RmsIncidentAnalysisState)(Analysis?.State ?? 0);
+
+ /// The analysis can only be filed once the incident itself exists at the destination.
+ public bool IncidentIsFiled => !string.IsNullOrWhiteSpace(Report?.NerisIncidentId);
+ }
+
+ /// A draft save of the incident-analysis filing; every list replaces the draft rows wholesale.
+ public class IncidentAnalysisDraftInput
+ {
+ public string GeneralCause { get; set; }
+ public List InvestigationTypes { get; set; } = new List();
+ public string CurrencyCode { get; set; }
+ public List Modules { get; set; }
+ public List Properties { get; set; }
+ public List Vehicles { get; set; }
+ public RmsOriginClient OriginClient { get; set; } = RmsOriginClient.Web;
+ }
+
+ public class IncidentPropertyInput
+ {
+ public string LocationUse { get; set; }
+ public string ConstructionType { get; set; }
+ public string Foundation { get; set; }
+ public string ExteriorFinish { get; set; }
+ public string RoofMaterial { get; set; }
+ public int? StoriesAboveGrade { get; set; }
+ public int? StoriesBelowGrade { get; set; }
+ public int? YearBuilt { get; set; }
+ public string Vacancy { get; set; }
+ public string DamageType { get; set; }
+ public string FireSpread { get; set; }
+ public decimal? EstimatedValue { get; set; }
+ public decimal? EstimatedLoss { get; set; }
+ public decimal? ContentsValue { get; set; }
+ public decimal? ContentsLoss { get; set; }
+ public string DetailJson { get; set; }
+ }
+
+ /// VIN and plate are restricted; the service drops them from a caller without RecordRestricted_View.
+ public class IncidentVehicleInput
+ {
+ public string VehicleKind { get; set; }
+ public string Make { get; set; }
+ public string Model { get; set; }
+ public int? ModelYear { get; set; }
+ public string BodyStyle { get; set; }
+ public string Powertrain { get; set; }
+ public string DamageType { get; set; }
+ public string Vin { get; set; }
+ public string LicensePlate { get; set; }
+ public string LicenseState { get; set; }
+ public bool WasOccupied { get; set; }
+ public decimal? EstimatedValue { get; set; }
+ public decimal? EstimatedLoss { get; set; }
+ public string DetailJson { get; set; }
}
/// Stable provenance keys for the prefilled facts (RmsSourceFact.FactKey).
diff --git a/Core/Resgrid.Model/Records/NerisContracts.cs b/Core/Resgrid.Model/Records/NerisContracts.cs
index 289eb703..3fa46b8b 100644
--- a/Core/Resgrid.Model/Records/NerisContracts.cs
+++ b/Core/Resgrid.Model/Records/NerisContracts.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
namespace Resgrid.Model
@@ -22,6 +22,56 @@ public class NerisIncidentSnapshot
public List DispatchComments { get; set; } = new List();
/// NERIS special modifiers (MCI, declared disaster ...), value-set codes.
public List SpecialModifiers { get; set; } = new List();
+
+ /// RMS-3 conditional sections that ride the incident payload.
+ public List Modules { get; set; } = new List();
+
+ /// RMS-3 non-unit resources used on the incident.
+ public List Resources { get; set; } = new List();
+
+ /// RMS-3 casualties and rescues. Restricted, but they are reported facts and do enter the payload.
+ public List Casualties { get; set; } = new List();
+
+ /// RMS-3 exposures — property other than the incident property that the incident damaged.
+ public List Exposures { get; set; } = new List();
+ }
+
+ ///
+ /// Everything the incident-analysis mapping needs, read once and handed to the pure mapper (RMS-3). Carries the
+ /// incident's NERIS id because the analysis is posted against the incident, not against the department.
+ ///
+ public class NerisIncidentAnalysisSnapshot
+ {
+ public RmsIncidentAnalysis Analysis { get; set; }
+ public RmsIncidentReport Report { get; set; }
+ public List Modules { get; set; } = new List();
+ public List Properties { get; set; } = new List();
+ public List Vehicles { get; set; } = new List();
+ }
+
+ ///
+ /// One conditional section the selected incident types demand or suggest (RMS plan section 4.2, RMS-3). The
+ /// provider owns the rule; this is the shape the service and the clients read it in, so a client renders the
+ /// same progressive requirements the server validates against instead of keeping its own copy of the rules.
+ ///
+ public class NerisSectionRequirement
+ {
+ public RmsIncidentModuleKind Kind { get; set; }
+
+ /// True blocks finalization; false surfaces as a warning the author may answer or ignore.
+ public bool Required { get; set; }
+
+ /// Why the section applies, shown beside it in the authoring surface.
+ public string Reason { get; set; }
+
+ ///
+ /// Value set the section's headline code must belong to, or null when the section has no coded headline.
+ /// Carried here so an authoring surface builds its dropdown from the same rule validation enforces.
+ ///
+ public string PrimaryCodeSet { get; set; }
+
+ /// Value set the section's second reportable code must belong to, or null when it has none.
+ public string SecondaryCodeSet { get; set; }
}
public class NerisDispatchComment
diff --git a/Core/Resgrid.Model/Records/RecordsApiContracts.cs b/Core/Resgrid.Model/Records/RecordsApiContracts.cs
index b208705f..f3931795 100644
--- a/Core/Resgrid.Model/Records/RecordsApiContracts.cs
+++ b/Core/Resgrid.Model/Records/RecordsApiContracts.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
@@ -259,7 +259,13 @@ public interface IRecordAttachmentUploadService
/// Scoped idempotency for v4 Records commands: the same (department, user, key) replays the first outcome instead of re-running the transition.
public interface IRecordsApiIdempotencyService
{
- Task TryGetRecordIdAsync(int departmentId, string userId, string idempotencyKey);
- Task RememberAsync(int departmentId, string userId, string idempotencyKey, string recordId);
+ ///
+ /// The record a previous call under this key produced, or null. scopes the key to
+ /// one operation: a client that reuses a key across two different commands on the same record must not have
+ /// the second one silently replayed as a success.
+ ///
+ Task TryGetRecordIdAsync(int departmentId, string userId, string idempotencyKey, string command);
+
+ Task RememberAsync(int departmentId, string userId, string idempotencyKey, string command, string recordId);
}
}
diff --git a/Core/Resgrid.Model/Records/RmsCasualtyExposure.cs b/Core/Resgrid.Model/Records/RmsCasualtyExposure.cs
new file mode 100644
index 00000000..ff7b5020
--- /dev/null
+++ b/Core/Resgrid.Model/Records/RmsCasualtyExposure.cs
@@ -0,0 +1,234 @@
+using System;
+using System.Collections.Generic;
+
+namespace Resgrid.Model
+{
+ /// Who the casualty or rescue row is about, matching the contract's CasualtyRescuePayload.type.
+ public static class RmsCasualtyPersonTypes
+ {
+ /// A firefighter — responder injury and exposure reporting.
+ public const string Firefighter = "FF";
+
+ /// A civilian.
+ public const string Civilian = "NONFF";
+ }
+
+ /// Which half of the contract's casualty_rescues entry this row carries.
+ public enum RmsCasualtyRescueKind
+ {
+ /// An injury or a documented non-injury.
+ Casualty = 1,
+
+ /// A rescue, with or without removal.
+ Rescue = 2
+ }
+
+ ///
+ /// One civilian or responder casualty or rescue (RMS plan section 4.2, RMS-3; registry M0168; NERIS
+ /// incident.casualty_rescues[]).
+ ///
+ /// This is a restricted class end to end: demographics, injury detail and the person's identity require
+ /// RecordRestricted_View in detail, revision, diff, print and export, the row carries the inert
+ /// Protected Data envelope (plan 5.9.1), and its retention default is permanent (plan section 4.9). The
+ /// department's own personnel link is kept separately from the reported demographics so a responder injury
+ /// can be tied to a member without putting a member id into the destination payload.
+ ///
+ ///
+ public class RmsCasualtyRescue : IEntity
+ {
+ public string RmsCasualtyRescueId { get; set; }
+
+ public int DepartmentId { get; set; }
+
+ public string ProtectionId { get; set; }
+
+ /// The owning incident report.
+ public string RecordId { get; set; }
+
+ public string RevisionId { get; set; }
+
+ /// .
+ public int Kind { get; set; }
+
+ /// : FF or NONFF.
+ public string PersonType { get; set; }
+
+ /// Restricted: the department member when the person is one of ours; never sent to the destination.
+ public string PersonnelUserId { get; set; }
+
+ /// Restricted: rank of the firefighter, as reported.
+ public string Rank { get; set; }
+
+ public decimal? YearsOfService { get; set; }
+
+ /// NERIS job_classification code.
+ public string JobClassification { get; set; }
+
+ /// Restricted: NERIS birth_month_year, "YYYY-MM"; never a full date of birth.
+ public string BirthMonthYear { get; set; }
+
+ /// Restricted: NERIS gender code.
+ public string Gender { get; set; }
+
+ /// Restricted: NERIS race code.
+ public string Race { get; set; }
+
+ // Casualty half ------------------------------------------------------------------------------------
+
+ /// False records a documented non-injury (the contract's noinjury branch).
+ public bool? WasInjured { get; set; }
+
+ /// NERIS casualty_cause code.
+ public string CasualtyCause { get; set; }
+
+ /// NERIS casualty_action code — what the person was doing.
+ public string CasualtyAction { get; set; }
+
+ /// NERIS casualty_timeline code — when in the incident it happened.
+ public string CasualtyTimeline { get; set; }
+
+ /// NERIS duty code for a responder.
+ public string DutyType { get; set; }
+
+ /// Comma-separated NERIS casualty_ppe codes in use at the time.
+ public string PpeCsv { get; set; }
+
+ /// Restricted: injury narrative and body-area detail, contract-shaped.
+ public string InjuryDetailJson { get; set; }
+
+ /// True when the casualty was fatal; drives permanent retention and the restricted class.
+ public bool WasFatal { get; set; }
+
+ // Rescue half --------------------------------------------------------------------------------------
+
+ /// NERIS rescue type: RESCUED_BY_FIREFIGHTER, RESCUED_BY_FF_RIT, EVAC_ASSISTED_BY_FIREFIGHTER.
+ public string RescueType { get; set; }
+
+ /// Comma-separated NERIS rescue_action codes.
+ public string RescueActionsCsv { get; set; }
+
+ /// Comma-separated NERIS rescue_impediment codes.
+ public string RescueImpedimentsCsv { get; set; }
+
+ /// NERIS rescue_mode code.
+ public string RescueMode { get; set; }
+
+ /// NERIS rescue_path code.
+ public string RescuePath { get; set; }
+
+ /// NERIS rescue_elevation code.
+ public string RescueElevation { get; set; }
+
+ /// NERIS rescue_presence_known code — whether the person was known to be present.
+ public string PresenceKnown { get; set; }
+
+ /// Contract-shaped remainder of the entry.
+ public string DetailJson { get; set; }
+
+ public DateTime? OccurredOn { get; set; }
+
+ /// Inert Protected Data envelope (plan section 5.9.1); null until the department enrolls.
+ public string ProtectedEnvelope { get; set; }
+
+ public bool IsProtected { get; set; }
+
+ public int ProtectedCatalogVersion { get; set; }
+
+ public int Ordinal { get; set; }
+
+ public DateTime CreatedOn { get; set; }
+
+ public DateTime ModifiedOn { get; set; }
+
+ public long RowVersion { get; set; }
+
+ public object IdValue { get => RmsCasualtyRescueId; set => RmsCasualtyRescueId = (string)value; }
+ public string TableName => "RmsCasualtyRescues";
+ public string IdName => "RmsCasualtyRescueId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new string[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ ///
+ /// One exposure — property other than the incident property that the incident damaged (registry M0168; NERIS
+ /// incident.exposures[]). Damage rating, displacement and the exposure's own location are reported and
+ /// summed, so they are columns; the contract's internal/external discrimination and any remainder ride
+ /// .
+ ///
+ public class RmsExposure : IEntity
+ {
+ public string RmsExposureId { get; set; }
+
+ public int DepartmentId { get; set; }
+
+ public string ProtectionId { get; set; }
+
+ /// The owning incident report.
+ public string RecordId { get; set; }
+
+ public string RevisionId { get; set; }
+
+ /// INTERNAL when the exposure is inside the incident property, EXTERNAL when it is separate.
+ public string LocationKind { get; set; }
+
+ /// NERIS exposure_item code — structure, object, outdoor environment.
+ public string ItemType { get; set; }
+
+ /// NERIS exposure_damage rating; required by the contract.
+ public string DamageType { get; set; }
+
+ /// NERIS location_use code of the exposed property.
+ public string LocationUse { get; set; }
+
+ public bool? PeoplePresent { get; set; }
+
+ public int? DisplacementCount { get; set; }
+
+ /// Comma-separated NERIS displace_cause codes.
+ public string DisplacementCausesCsv { get; set; }
+
+ public string AddressText { get; set; }
+
+ public string Street { get; set; }
+
+ public string Municipality { get; set; }
+
+ public string State { get; set; }
+
+ public string PostalCode { get; set; }
+
+ public decimal? Latitude { get; set; }
+
+ public decimal? Longitude { get; set; }
+
+ public decimal? EstimatedValue { get; set; }
+
+ public decimal? EstimatedLoss { get; set; }
+
+ public string CurrencyCode { get; set; }
+
+ /// Contract-shaped remainder of the exposure entry.
+ public string DetailJson { get; set; }
+
+ /// Inert Protected Data envelope (plan section 5.9.1); null until the department enrolls.
+ public string ProtectedEnvelope { get; set; }
+
+ public bool IsProtected { get; set; }
+
+ public int ProtectedCatalogVersion { get; set; }
+
+ public int Ordinal { get; set; }
+
+ public DateTime CreatedOn { get; set; }
+
+ public DateTime ModifiedOn { get; set; }
+
+ public long RowVersion { get; set; }
+
+ public object IdValue { get => RmsExposureId; set => RmsExposureId = (string)value; }
+ public string TableName => "RmsExposures";
+ public string IdName => "RmsExposureId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new string[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+}
diff --git a/Core/Resgrid.Model/Records/RmsDisclosure.cs b/Core/Resgrid.Model/Records/RmsDisclosure.cs
new file mode 100644
index 00000000..81692c1b
--- /dev/null
+++ b/Core/Resgrid.Model/Records/RmsDisclosure.cs
@@ -0,0 +1,240 @@
+using System;
+using System.Collections.Generic;
+
+namespace Resgrid.Model
+{
+ ///
+ /// Where a public-records request stands (RMS plan section 4.7, RMS-3). Persisted as an integer; append-only.
+ ///
+ public enum RmsDisclosureState
+ {
+ /// Logged with a requester and a statutory clock running.
+ Received = 0,
+
+ /// The scope query is being settled with the requester.
+ Scoping = 1,
+
+ /// The result set is being reviewed and redacted.
+ InReview = 2,
+
+ /// A redacted production exists but has not been released.
+ Produced = 3,
+
+ /// Released to the requester; the produced set is frozen.
+ Released = 4,
+
+ /// Refused under an exemption, with the reason recorded.
+ Denied = 5,
+
+ /// The requester withdrew it.
+ Withdrawn = 6,
+
+ /// Closed without release for any other recorded reason.
+ Closed = 7
+ }
+
+ /// Named redaction profiles; a profile decides which classifications are withheld.
+ public static class RmsRedactionProfiles
+ {
+ /// Withholds restricted content only; the ordinary public-records answer.
+ public const string Standard = "Standard";
+
+ /// Withholds restricted content and every participant identity.
+ public const string NoPersonalIdentifiers = "NoPersonalIdentifiers";
+
+ /// Releases everything the department holds; used for an internal or litigation production.
+ public const string FullDisclosure = "FullDisclosure";
+ }
+
+ ///
+ /// A public-records or access-to-information request (RMS plan section 4.7, registry M0171).
+ ///
+ /// For a public agency this is a statutory obligation with a clock, which is why it is a record with a due
+ /// date rather than an ad-hoc export. The jurisdiction profile matters because U.S. state public-records law
+ /// and Canadian access-to-information regimes differ in what must be released and how quickly.
+ ///
+ ///
+ /// The requester's identity is restricted: in most jurisdictions who asked is not itself public, and it must
+ /// not leak into the produced packet.
+ ///
+ ///
+ public class RmsDisclosureRequest : IEntity
+ {
+ public string RmsDisclosureRequestId { get; set; }
+
+ public int DepartmentId { get; set; }
+
+ public string ProtectionId { get; set; }
+
+ /// Department-facing reference, assigned on create.
+ public string RequestNumber { get; set; }
+
+ /// Restricted: who asked.
+ public string RequesterName { get; set; }
+
+ /// Restricted: the organisation they asked on behalf of.
+ public string RequesterOrganization { get; set; }
+
+ /// Restricted: contact details, kept only to answer the request.
+ public string RequesterContact { get; set; }
+
+ public DateTime ReceivedOn { get; set; }
+
+ /// Computed from the department's statutory clock (setting 77) unless an administrator overrides it.
+ public DateTime? StatutoryDueOn { get; set; }
+
+ /// Which regime applies, e.g. US-IL or CA-ON; drives the clock and the exemptions.
+ public string JurisdictionProfile { get; set; }
+
+ /// What the requester asked for, in their words.
+ public string ScopeNarrative { get; set; }
+
+ /// The bounded RmsRecordQuery the scope resolves to; the same query the Records queue runs.
+ public string ScopeQueryJson { get; set; }
+
+ /// .
+ public int State { get; set; }
+
+ public string AssignedToUserId { get; set; }
+
+ /// Redaction profile applied to productions unless one names its own.
+ public string RedactionProfile { get; set; }
+
+ public DateTime? ClosedOn { get; set; }
+
+ public string ClosedByUserId { get; set; }
+
+ /// Why it closed the way it did — the exemption relied on, or the requester's withdrawal.
+ public string DispositionReason { get; set; }
+
+ public DateTime CreatedOn { get; set; }
+
+ public string CreatedByUserId { get; set; }
+
+ public DateTime ModifiedOn { get; set; }
+
+ public string ModifiedByUserId { get; set; }
+
+ public long RowVersion { get; set; }
+
+ public DateTime? DeletedOn { get; set; }
+
+ /// Past its statutory due date and not yet resolved.
+ public bool IsOverdue => StatutoryDueOn.HasValue && ClosedOn == null && StatutoryDueOn.Value < DateTime.UtcNow;
+
+ public object IdValue { get => RmsDisclosureRequestId; set => RmsDisclosureRequestId = (string)value; }
+ public string TableName => "RmsDisclosureRequests";
+ public string IdName => "RmsDisclosureRequestId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new string[] { "IdValue", "IdType", "TableName", "IdName", "IsOverdue" };
+ }
+
+ ///
+ /// One immutable produced set for a request (RMS plan section 4.7, registry M0171).
+ ///
+ /// A production is a new artifact, never a mutation of the source revisions — that is the whole point. It
+ /// freezes exactly which record and revision IDs were released, under which redaction profile, with a
+ /// checksum, so a later amendment to any of those records cannot silently change what the department is on
+ /// the hook for having released.
+ ///
+ ///
+ public class RmsDisclosureProduction : IEntity
+ {
+ public string RmsDisclosureProductionId { get; set; }
+
+ public int DepartmentId { get; set; }
+
+ public string ProtectionId { get; set; }
+
+ public string DisclosureRequestId { get; set; }
+
+ /// 1 for the first production, incrementing for supplemental ones.
+ public int ProductionNumber { get; set; }
+
+ /// actually applied.
+ public string RedactionProfile { get; set; }
+
+ ///
+ /// The produced-set snapshot: the record and revision IDs released with their checksums at the moment of
+ /// production. What makes "an amendment did not change what we released" provable.
+ ///
+ public string ProducedSetJson { get; set; }
+
+ /// The redacted content itself, with its manifest.
+ public string ArtifactJson { get; set; }
+
+ /// Lower-case hex SHA-256 of .
+ public string Checksum { get; set; }
+
+ public long ByteSize { get; set; }
+
+ public int RecordCount { get; set; }
+
+ /// Which fields were withheld and under what heading; the redaction log the requester may see.
+ public string WithheldFieldsJson { get; set; }
+
+ public int WithheldFieldCount { get; set; }
+
+ public string PreparedByUserId { get; set; }
+
+ public DateTime PreparedOn { get; set; }
+
+ public string ReleasedByUserId { get; set; }
+
+ public DateTime? ReleasedOn { get; set; }
+
+ public string ProtectedEnvelope { get; set; }
+
+ public bool IsProtected { get; set; }
+
+ public int ProtectedCatalogVersion { get; set; }
+
+ public DateTime CreatedOn { get; set; }
+
+ public DateTime ModifiedOn { get; set; }
+
+ public long RowVersion { get; set; }
+
+ public bool IsReleased => ReleasedOn.HasValue;
+
+ public object IdValue { get => RmsDisclosureProductionId; set => RmsDisclosureProductionId = (string)value; }
+ public string TableName => "RmsDisclosureProductions";
+ public string IdName => "RmsDisclosureProductionId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new string[] { "IdValue", "IdType", "TableName", "IdName", "IsReleased" };
+ }
+
+ /// One record in a disclosure scope preview, before anything is produced.
+ public class RmsDisclosureScopeItem
+ {
+ public string RecordId { get; set; }
+ public string RecordNumber { get; set; }
+ public string DefinitionKey { get; set; }
+ public string Summary { get; set; }
+ public DateTime? OccurredOn { get; set; }
+ public string CurrentRevisionId { get; set; }
+ /// False when the record is not finalized; a draft is not a public record and is never produced.
+ public bool Producible { get; set; }
+ public string NotProducibleReason { get; set; }
+ }
+
+ /// What a scope query resolves to, with the counts an officer needs before producing anything.
+ public class RmsDisclosureScopePreview
+ {
+ public int MatchedCount { get; set; }
+ public int ProducibleCount { get; set; }
+ public int WithheldWholeRecordCount { get; set; }
+ public bool Truncated { get; set; }
+ public List Items { get; set; } = new List();
+ }
+
+ /// One withheld field in a production's redaction log.
+ public class RmsRedactionEntry
+ {
+ public string RecordId { get; set; }
+ public string Section { get; set; }
+ public string Field { get; set; }
+ /// Why it was withheld — the classification or profile rule relied on.
+ public string Basis { get; set; }
+ }
+}
diff --git a/Core/Resgrid.Model/Records/RmsDueStateAndRetention.cs b/Core/Resgrid.Model/Records/RmsDueStateAndRetention.cs
new file mode 100644
index 00000000..598358f8
--- /dev/null
+++ b/Core/Resgrid.Model/Records/RmsDueStateAndRetention.cs
@@ -0,0 +1,202 @@
+using System;
+using System.Collections.Generic;
+
+namespace Resgrid.Model
+{
+ ///
+ /// What a Record is late for (RMS plan section 4.7, RMS-3). Persisted as an integer; append-only.
+ ///
+ public enum RmsRecordObligation
+ {
+ /// Submitted for review and not reviewed by its due time (notification 32, trigger 112).
+ Review = 1,
+
+ /// Returned for correction and not corrected — the record is sitting with its author.
+ Correction = 2,
+
+ /// Rejected by the reporting destination and not corrected and resubmitted.
+ Submission = 3
+ }
+
+ ///
+ /// Where an obligation stands. The evaluation emits only on the transition into , which
+ /// is what makes "at most once per record and due-state transition" true.
+ ///
+ public enum RmsDueState
+ {
+ NotDue = 0,
+ DueSoon = 1,
+ Overdue = 2,
+ /// The obligation was met (reviewed, corrected, resubmitted) or no longer applies.
+ Cleared = 3
+ }
+
+ ///
+ /// The persisted due state of one obligation on one Record (registry M0170, RMS-3).
+ ///
+ /// The plan is explicit that the "at most once per record/due-state transition" guarantee is carried by this
+ /// row and never inferred from the last worker run: a missed run must not skip an emission and a repeated run
+ /// must not double-emit. The worker compares the state it computes now against
+ /// and only emits when they differ.
+ ///
+ ///
+ public class RmsRecordDueState : IEntity
+ {
+ public string RmsRecordDueStateId { get; set; }
+
+ public int DepartmentId { get; set; }
+
+ /// The operational Record or incident report the obligation is on.
+ public string RecordId { get; set; }
+
+ /// .
+ public int RecordKind { get; set; }
+
+ /// .
+ public int Obligation { get; set; }
+
+ /// When the obligation falls due; a change to it re-arms emission for the new deadline.
+ public DateTime? DueOn { get; set; }
+
+ /// last emitted for this obligation and .
+ public int LastEmittedState { get; set; }
+
+ public DateTime? LastEmittedOn { get; set; }
+
+ /// Who the obligation currently rests with, snapshotted so the notification has a target.
+ public string ResponsibleUserId { get; set; }
+
+ /// How many times this obligation has gone overdue across its lifetime; reporting only.
+ public int OverdueCount { get; set; }
+
+ public DateTime CreatedOn { get; set; }
+
+ public DateTime ModifiedOn { get; set; }
+
+ public long RowVersion { get; set; }
+
+ public object IdValue { get => RmsRecordDueStateId; set => RmsRecordDueStateId = (string)value; }
+ public string TableName => "RmsRecordDueStates";
+ public string IdName => "RmsRecordDueStateId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new string[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ /// Why a hold exists; shown to administrators and carried into the audit when a purge is refused.
+ public static class RmsLegalHoldReasons
+ {
+ public const string Litigation = "Litigation";
+ public const string Investigation = "Investigation";
+ public const string PublicRecordsRequest = "PublicRecordsRequest";
+ public const string Other = "Other";
+ }
+
+ ///
+ /// A legal hold that suspends retention for a Record, a definition, or a whole department date range
+ /// (registry M0170, RMS-3). A hold never deletes and never edits; its only effect is that the retention sweep
+ /// refuses to purge what it covers, and that refusal is audited rather than silent.
+ ///
+ public class RmsRecordLegalHold : IEntity
+ {
+ public string RmsRecordLegalHoldId { get; set; }
+
+ public int DepartmentId { get; set; }
+
+ /// The specific Record held, or null when the hold is a definition/date-range hold.
+ public string RecordId { get; set; }
+
+ /// The definition held, or null when the hold names a single Record or the whole department.
+ public string DefinitionKey { get; set; }
+
+ /// Inclusive start of the held period, matched against the Record's started/created time.
+ public DateTime? PeriodStart { get; set; }
+
+ /// Inclusive end of the held period.
+ public DateTime? PeriodEnd { get; set; }
+
+ /// .
+ public string Reason { get; set; }
+
+ public string ReferenceNumber { get; set; }
+
+ public string Notes { get; set; }
+
+ public string PlacedByUserId { get; set; }
+
+ public DateTime PlacedOn { get; set; }
+
+ public string ReleasedByUserId { get; set; }
+
+ public DateTime? ReleasedOn { get; set; }
+
+ public string ReleaseNotes { get; set; }
+
+ public DateTime CreatedOn { get; set; }
+
+ public DateTime ModifiedOn { get; set; }
+
+ public long RowVersion { get; set; }
+
+ /// Active while it has not been released.
+ public bool IsActive => !ReleasedOn.HasValue;
+
+ /// Whether this hold covers a Record of a definition started at a time.
+ public bool Covers(string recordId, string definitionKey, DateTime? startedOn)
+ {
+ if (!IsActive)
+ return false;
+
+ if (!string.IsNullOrWhiteSpace(RecordId))
+ return string.Equals(RecordId, recordId, StringComparison.Ordinal);
+
+ if (!string.IsNullOrWhiteSpace(DefinitionKey) && !string.Equals(DefinitionKey, definitionKey, StringComparison.Ordinal))
+ return false;
+
+ // A hold with no period covers every date; one with a period needs a date to compare against, and a
+ // Record with no date is held rather than purged — the safe reading when the evidence is incomplete.
+ if (!PeriodStart.HasValue && !PeriodEnd.HasValue)
+ return true;
+ if (!startedOn.HasValue)
+ return true;
+
+ if (PeriodStart.HasValue && startedOn.Value < PeriodStart.Value)
+ return false;
+ if (PeriodEnd.HasValue && startedOn.Value > PeriodEnd.Value)
+ return false;
+
+ return true;
+ }
+
+ public object IdValue { get => RmsRecordLegalHoldId; set => RmsRecordLegalHoldId = (string)value; }
+ public string TableName => "RmsRecordLegalHolds";
+ public string IdName => "RmsRecordLegalHoldId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new string[] { "IdValue", "IdType", "TableName", "IdName", "IsActive" };
+ }
+
+ /// Result of one due-state evaluation sweep (worker 42).
+ public class RecordsDueStateSweepResult
+ {
+ public int DepartmentsEvaluated { get; set; }
+ public int RecordsEvaluated { get; set; }
+ public int BecameOverdue { get; set; }
+ public int Cleared { get; set; }
+ public int NotificationsSent { get; set; }
+ public int Errors { get; set; }
+ public string Message { get; set; }
+ }
+
+ /// Result of one retention and purge sweep (worker 43).
+ public class RecordsRetentionSweepResult
+ {
+ public int DepartmentsEvaluated { get; set; }
+ public int RecordsEvaluated { get; set; }
+ public int RecordsPurged { get; set; }
+ public int AttachmentsPurged { get; set; }
+ public int HeldByLegalHold { get; set; }
+ public int AttachmentsRescanned { get; set; }
+ public int AttachmentsRejectedOnRescan { get; set; }
+ public int Errors { get; set; }
+ public string Message { get; set; }
+ }
+}
diff --git a/Core/Resgrid.Model/Records/RmsEnums.cs b/Core/Resgrid.Model/Records/RmsEnums.cs
index d968eff1..091a2a42 100644
--- a/Core/Resgrid.Model/Records/RmsEnums.cs
+++ b/Core/Resgrid.Model/Records/RmsEnums.cs
@@ -13,7 +13,10 @@ public enum RmsRecordKind
Operational = 1,
/// RmsIncidentReport: the NERIS incident report aggregate (RMS-2).
- IncidentReport = 2
+ IncidentReport = 2,
+
+ /// RmsIncidentAnalysis: the separate NERIS fire/hazmat analysis filing for an incident (RMS-3).
+ IncidentAnalysis = 3
}
///
diff --git a/Core/Resgrid.Model/Records/RmsEvidenceArtifact.cs b/Core/Resgrid.Model/Records/RmsEvidenceArtifact.cs
new file mode 100644
index 00000000..074748fb
--- /dev/null
+++ b/Core/Resgrid.Model/Records/RmsEvidenceArtifact.cs
@@ -0,0 +1,244 @@
+using System;
+using System.Collections.Generic;
+
+namespace Resgrid.Model
+{
+ ///
+ /// The six evidence sources RMS-3 ships, none optional (RMS plan sections 4.5 and RMS-3). Persisted as an
+ /// integer; append-only.
+ ///
+ /// Every one of these captures an authorized, bounded, server-authored snapshot with provenance. None of them
+ /// hydrates or retains a live source: not a whole chat channel, not a unit's tracking history, not a source
+ /// record that can later change or expire underneath the filing.
+ ///
+ ///
+ public enum RmsEvidenceKind
+ {
+ /// Apparatus/equipment readiness at the time of the call — a checklist/work-order manifest.
+ ReadinessPacket = 1,
+
+ /// The recorded dispatch decision: card and version, alarm level, mode, selected resources, shortfall.
+ RunCardActivation = 2,
+
+ /// Bounded unit tracking fixes over a coverage window, captured before source retention purges them.
+ TrackingFix = 3,
+
+ /// Selected incident-chat messages promoted into the record by an authorized member.
+ ChatPromotion = 4,
+
+ /// Supplies and controlled-substance usage from the inventory ledger.
+ InventoryUsage = 5,
+
+ /// Participant certification/qualification validity at the incident time.
+ CertificationSnapshot = 6
+ }
+
+ ///
+ /// How far an artifact's content may travel. Classification is decided at capture and never widened later,
+ /// so an artifact captured as restricted stays restricted through print, export and disclosure.
+ ///
+ public enum RmsEvidenceClassification
+ {
+ /// Ordinary operational content; visible to anyone who can view the Record.
+ Unrestricted = 0,
+
+ /// Needs RecordRestricted_View wherever it is rendered.
+ Restricted = 1,
+
+ /// Protected-data candidate; the envelope columns carry it once a department enrolls (plan 5.9).
+ Protected = 2
+ }
+
+ ///
+ /// An immutable supporting artifact or manifest attached to a Record (RMS plan section 5.2, registry M0169).
+ ///
+ /// The point of storing an artifact rather than a link is that a link can change or expire: a readiness report
+ /// regenerated next year does not say what it said on the night of the fire. So the content is captured once,
+ /// checksummed, classified and retained with the Record — and never updated. A correction is a new artifact,
+ /// which is why there is no update path and why exists instead.
+ ///
+ ///
+ /// The per-source rows the artifact was built from ride inside . That is deliberate:
+ /// a manifest is the thing being attested to, and splitting it across a child table would let the two drift
+ /// while the checksum still claimed the artifact was intact.
+ ///
+ ///
+ public class RmsEvidenceArtifact : IEntity
+ {
+ public string RmsEvidenceArtifactId { get; set; }
+
+ public int DepartmentId { get; set; }
+
+ public string ProtectionId { get; set; }
+
+ /// The Record or incident report the artifact supports.
+ public string RecordId { get; set; }
+
+ /// .
+ public int RecordKind { get; set; }
+
+ ///
+ /// The revision the artifact was captured into, or null while it supports the working draft. A finalize
+ /// stamps the revision, which is what makes "the evidence as it stood at revision 3" answerable.
+ ///
+ public string RevisionId { get; set; }
+
+ /// .
+ public int Kind { get; set; }
+
+ /// Human title shown in the evidence list, server-authored.
+ public string Title { get; set; }
+
+ /// Why the capture happened; required, and written to the access audit.
+ public string CaptureReason { get; set; }
+
+ public string SourceSubsystem { get; set; }
+
+ public string SourceEntityType { get; set; }
+
+ /// Opaque, source-qualified identifier of the primary source row; never parsed for meaning.
+ public string SourceEntityId { get; set; }
+
+ public string IdentifierScheme { get; set; }
+
+ /// Version or schema of the source at capture time, where the source carries one.
+ public string SourceVersion { get; set; }
+
+ /// Start of the period the artifact covers (a tracking window, a readiness period).
+ public DateTime? CoverageStart { get; set; }
+
+ public DateTime? CoverageEnd { get; set; }
+
+ /// The bounded, server-authored snapshot and its per-source manifest. The artifact itself.
+ public string ManifestJson { get; set; }
+
+ /// Lower-case hex SHA-256 of ; what an auditor re-computes.
+ public string Checksum { get; set; }
+
+ public long ByteSize { get; set; }
+
+ /// How many source rows the manifest covers; shown without opening the artifact.
+ public int SourceItemCount { get; set; }
+
+ /// Reserved for an external blob location; null while the manifest is stored in-row.
+ public string StorageReference { get; set; }
+
+ /// , decided at capture and never widened.
+ public int Classification { get; set; }
+
+ ///
+ /// Retention in years for this artifact when it must outlive the Record's own policy; null inherits the
+ /// Record, and 0 is permanent. Legal holds are evaluated against the Record and cover its artifacts.
+ ///
+ public int? RetentionYears { get; set; }
+
+ public string CapturedByUserId { get; set; }
+
+ public DateTime CapturedOn { get; set; }
+
+ /// the capture came from.
+ public int OriginClient { get; set; }
+
+ /// Set when a later capture replaces this one; the original still stands and is still readable.
+ public string SupersededByArtifactId { get; set; }
+
+ public DateTime? SupersededOn { get; set; }
+
+ /// Inert Protected Data envelope (plan section 5.9.1); null until the department enrolls.
+ public string ProtectedEnvelope { get; set; }
+
+ public bool IsProtected { get; set; }
+
+ public int ProtectedCatalogVersion { get; set; }
+
+ public DateTime CreatedOn { get; set; }
+
+ public DateTime ModifiedOn { get; set; }
+
+ public long RowVersion { get; set; }
+
+ public DateTime? DeletedOn { get; set; }
+
+ /// A superseded artifact is history: readable, never the current evidence of its kind.
+ public bool IsCurrent => !SupersededOn.HasValue && !DeletedOn.HasValue;
+
+ public object IdValue { get => RmsEvidenceArtifactId; set => RmsEvidenceArtifactId = (string)value; }
+ public string TableName => "RmsEvidenceArtifacts";
+ public string IdName => "RmsEvidenceArtifactId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new string[] { "IdValue", "IdType", "TableName", "IdName", "IsCurrent" };
+ }
+
+ /// What a caller asks an evidence adapter to capture. The adapter decides what it can honour.
+ public class RecordEvidenceCaptureRequest
+ {
+ public int DepartmentId { get; set; }
+
+ public string RecordId { get; set; }
+
+ public RmsRecordKind RecordKind { get; set; } = RmsRecordKind.Operational;
+
+ public RmsEvidenceKind Kind { get; set; }
+
+ /// Required: why this evidence is being put into an official record.
+ public string CaptureReason { get; set; }
+
+ /// The Call the Record hangs off, where the source is call-scoped.
+ public int? CallId { get; set; }
+
+ /// Bounded window for time-series sources; the adapter clamps it to its own maximum.
+ public DateTime? CoverageStart { get; set; }
+
+ public DateTime? CoverageEnd { get; set; }
+
+ /// Explicit source ids the caller selected — chat messages, units, members.
+ public List SourceIds { get; set; } = new List();
+
+ public List UnitIds { get; set; } = new List();
+
+ public List UserIds { get; set; } = new List();
+
+ public string CapturedByUserId { get; set; }
+
+ public RmsOriginClient OriginClient { get; set; } = RmsOriginClient.Web;
+ }
+
+ /// What an adapter produced, before the service persists it.
+ public class RecordEvidenceCapture
+ {
+ public bool Available { get; set; } = true;
+
+ /// Why nothing was captured; shown to the author rather than failing silently.
+ public string UnavailableReason { get; set; }
+
+ public string Title { get; set; }
+
+ public string SourceSubsystem { get; set; }
+
+ public string SourceEntityType { get; set; }
+
+ public string SourceEntityId { get; set; }
+
+ public string IdentifierScheme { get; set; }
+
+ public string SourceVersion { get; set; }
+
+ public DateTime? CoverageStart { get; set; }
+
+ public DateTime? CoverageEnd { get; set; }
+
+ /// The manifest object; the service serializes it deterministically and checksums the result.
+ public object Manifest { get; set; }
+
+ public int SourceItemCount { get; set; }
+
+ public RmsEvidenceClassification Classification { get; set; } = RmsEvidenceClassification.Unrestricted;
+
+ public int? RetentionYears { get; set; }
+
+ public static RecordEvidenceCapture Unavailable(string reason)
+ {
+ return new RecordEvidenceCapture { Available = false, UnavailableReason = reason };
+ }
+ }
+}
diff --git a/Core/Resgrid.Model/Records/RmsIncidentModules.cs b/Core/Resgrid.Model/Records/RmsIncidentModules.cs
new file mode 100644
index 00000000..3bbfa603
--- /dev/null
+++ b/Core/Resgrid.Model/Records/RmsIncidentModules.cs
@@ -0,0 +1,495 @@
+using System;
+using System.Collections.Generic;
+
+namespace Resgrid.Model
+{
+ ///
+ /// The conditional sections a NERIS incident carries beyond the always-present base (RMS plan section 4.2,
+ /// RMS-3; registry M0167). Each value names exactly one payload location in the pinned contract, so a module
+ /// row is never a Resgrid invention — holds the mapping and the pinned
+ /// schema name that is validated against.
+ ///
+ /// Wildland/WUI and weather have no dedicated section in contract 1.4.78: outdoor fire carries acres burned
+ /// and fuel/spread facts inside , and weather is a destination-side lookup with no
+ /// submittable payload. The plan's list is "as required by the pinned NERIS profile", so they are represented
+ /// where the contract puts them rather than as tables the destination would reject.
+ ///
+ /// Persisted as an integer; append-only.
+ ///
+ public enum RmsIncidentModuleKind
+ {
+ /// incident.fire_detail — water supply, investigation need, suppression appliances.
+ Fire = 1,
+
+ /// incident.fire_detail.location_detail (STRUCTURE) — floor/room of origin, arrival condition, building damage.
+ StructureFireLocation = 2,
+
+ /// incident.fire_detail.location_detail (OUTSIDE) — acres burned and outdoor cause.
+ OutsideFireLocation = 3,
+
+ /// incident.hazsit_detail — evacuated count and hazmat disposition.
+ Hazsit = 4,
+
+ /// incident.hazsit_detail.chemicals[] — one released chemical.
+ Chemical = 5,
+
+ /// incident.medical_details[] — patient care evaluation, status and transport disposition.
+ Medical = 6,
+
+ /// incident.smoke_alarm — presence, type, operation and failure reason.
+ SmokeAlarm = 7,
+
+ /// incident.fire_alarm — presence, type, operation and failure reason.
+ FireAlarm = 8,
+
+ /// incident.other_alarm — CO/heat/gas alarm presence and operation.
+ OtherAlarm = 9,
+
+ /// incident.fire_suppression — automatic suppression presence, type and effectiveness.
+ FireSuppression = 10,
+
+ /// incident.cooking_fire_suppression — kitchen suppression presence and effectiveness.
+ CookingFireSuppression = 11,
+
+ /// incident.electric_hazards[] — one electrical/battery hazard.
+ ElectricHazard = 12,
+
+ /// incident.powergen_hazards[] — one PV or other power-generation hazard.
+ PowergenHazard = 13,
+
+ /// incident.csst_hazard — corrugated stainless steel tubing involvement.
+ CsstHazard = 14,
+
+ /// incident.medical_oxygen_hazard — home medical oxygen involvement.
+ MedicalOxygenHazard = 15,
+
+ /// incident_analysis.structure_fire_origin — origin, item first ignited, human factors.
+ StructureFireOrigin = 20,
+
+ /// incident_analysis.outside_fire — outdoor fire analysis.
+ OutsideFire = 21,
+
+ /// incident_analysis.hazsit — hazmat analysis with release factors.
+ HazsitAnalysis = 22,
+
+ /// incident_analysis.products[] — one product involved in ignition or spread.
+ Product = 23,
+
+ /// incident_analysis.batteries[] — one battery involved.
+ Battery = 24
+ }
+
+ /// Where a module lands in the pinned contract, and which aggregate owns it.
+ public sealed class RmsIncidentModuleDescriptor
+ {
+ public RmsIncidentModuleDescriptor(RmsIncidentModuleKind kind, string payloadPath, string schemaName, bool isCollection, bool belongsToAnalysis)
+ {
+ Kind = kind;
+ PayloadPath = payloadPath;
+ SchemaName = schemaName;
+ IsCollection = isCollection;
+ BelongsToAnalysis = belongsToAnalysis;
+ }
+
+ public RmsIncidentModuleKind Kind { get; }
+
+ /// Dotted path inside the owning payload, e.g. fire_detail.location_detail.
+ public string PayloadPath { get; }
+
+ /// The pinned contract schema DetailJson conforms to.
+ public string SchemaName { get; }
+
+ /// True when the path is an array and several rows of this kind may exist.
+ public bool IsCollection { get; }
+
+ /// True when the module rides the incident-analysis payload rather than the incident payload.
+ public bool BelongsToAnalysis { get; }
+ }
+
+ ///
+ /// The one place a module kind is bound to the pinned contract. Mapping, validation, print and export all read
+ /// it, so a contract upgrade changes this table and nothing else.
+ ///
+ public static class RmsIncidentModuleCatalog
+ {
+ private static readonly Dictionary Descriptors = Build();
+
+ private static Dictionary Build()
+ {
+ var map = new Dictionary();
+ void Add(RmsIncidentModuleKind kind, string path, string schema, bool collection, bool analysis = false)
+ => map[kind] = new RmsIncidentModuleDescriptor(kind, path, schema, collection, analysis);
+
+ Add(RmsIncidentModuleKind.Fire, "fire_detail", "FirePayload", false);
+ Add(RmsIncidentModuleKind.StructureFireLocation, "fire_detail.location_detail", "StructureFireLocationDetailPayload", false);
+ Add(RmsIncidentModuleKind.OutsideFireLocation, "fire_detail.location_detail", "OutsideFireLocationDetailPayload", false);
+ Add(RmsIncidentModuleKind.Hazsit, "hazsit_detail", "HazsitPayload", false);
+ Add(RmsIncidentModuleKind.Chemical, "hazsit_detail.chemicals", "ChemicalPayload", true);
+ Add(RmsIncidentModuleKind.Medical, "medical_details", "MedicalPayload", true);
+ Add(RmsIncidentModuleKind.SmokeAlarm, "smoke_alarm", "SmokeAlarmPayload", false);
+ Add(RmsIncidentModuleKind.FireAlarm, "fire_alarm", "FireAlarmPayload", false);
+ Add(RmsIncidentModuleKind.OtherAlarm, "other_alarm", "OtherAlarmPayload", false);
+ Add(RmsIncidentModuleKind.FireSuppression, "fire_suppression", "FireSuppressionPayload", false);
+ Add(RmsIncidentModuleKind.CookingFireSuppression, "cooking_fire_suppression", "CookingFireSuppressionPayload", false);
+ Add(RmsIncidentModuleKind.ElectricHazard, "electric_hazards", "ElectricHazardPayload", true);
+ Add(RmsIncidentModuleKind.PowergenHazard, "powergen_hazards", "PowergenHazardPayload", true);
+ Add(RmsIncidentModuleKind.CsstHazard, "csst_hazard", "CsstHazardPayload", false);
+ Add(RmsIncidentModuleKind.MedicalOxygenHazard, "medical_oxygen_hazard", "MedicalOxygenHazardPayload", false);
+
+ Add(RmsIncidentModuleKind.StructureFireOrigin, "structure_fire_origin", "StructureFireOriginPayload", false, true);
+ Add(RmsIncidentModuleKind.OutsideFire, "outside_fire", "OutsideFirePayload", false, true);
+ Add(RmsIncidentModuleKind.HazsitAnalysis, "hazsit", "HazsitWithReleaseFactorsPayload", false, true);
+ Add(RmsIncidentModuleKind.Product, "products", "ProductPayload", true, true);
+ Add(RmsIncidentModuleKind.Battery, "batteries", "BatteryPayload", true, true);
+
+ return map;
+ }
+
+ public static RmsIncidentModuleDescriptor Get(RmsIncidentModuleKind kind)
+ {
+ return Descriptors.TryGetValue(kind, out var descriptor) ? descriptor : null;
+ }
+
+ public static IReadOnlyCollection All => Descriptors.Values;
+
+ /// Modules that ride the incident payload (everything submitted with the incident itself).
+ public static IEnumerable IncidentModules()
+ {
+ foreach (var descriptor in Descriptors.Values)
+ {
+ if (!descriptor.BelongsToAnalysis)
+ yield return descriptor;
+ }
+ }
+
+ /// Modules that ride the incident-analysis payload (the separate fire/hazmat analysis filing).
+ public static IEnumerable AnalysisModules()
+ {
+ foreach (var descriptor in Descriptors.Values)
+ {
+ if (descriptor.BelongsToAnalysis)
+ yield return descriptor;
+ }
+ }
+ }
+
+ ///
+ /// One conditional section instance on an incident report or its analysis (registry M0167). The stable,
+ /// reportable facts are columns so queues, dashboards and reports never parse JSON; the section's full
+ /// contract-shaped body is , validated against in the pinned
+ /// contract before it is stored. Draft rows have a null ; a revision copies them.
+ ///
+ public class RmsIncidentModule : IEntity
+ {
+ public string RmsIncidentModuleId { get; set; }
+
+ public int DepartmentId { get; set; }
+
+ public string ProtectionId { get; set; }
+
+ /// The owning aggregate: an incident report id, or an incident analysis id for analysis modules.
+ public string RecordId { get; set; }
+
+ /// of the owner, carried for export and audit clarity.
+ public int RecordKind { get; set; }
+
+ public string RevisionId { get; set; }
+
+ /// .
+ public int ModuleKind { get; set; }
+
+ /// The pinned contract schema was validated against.
+ public string SchemaName { get; set; }
+
+ /// Pinned NERIS contract version this section was authored against.
+ public string ProfileVersion { get; set; }
+
+ /// The section's headline value-set code (fire cause, hazard disposition, alarm type, ...).
+ public string PrimaryCode { get; set; }
+
+ /// A second reportable code where the section has one (damage rating, operation outcome, ...).
+ public string SecondaryCode { get; set; }
+
+ /// The section's single reportable magnitude: acres burned, evacuated count, released amount.
+ public decimal? Quantity { get; set; }
+
+ /// Unit of where the contract carries one (a NERIS hazard_unit code).
+ public string QuantityUnit { get; set; }
+
+ public DateTime? OccurredOn { get; set; }
+
+ /// The contract-shaped section body; the only place section detail lives.
+ public string DetailJson { get; set; }
+
+ /// Inert Protected Data envelope (plan section 5.9.1); null until the department enrolls.
+ public string ProtectedEnvelope { get; set; }
+
+ public bool IsProtected { get; set; }
+
+ public int ProtectedCatalogVersion { get; set; }
+
+ public int Ordinal { get; set; }
+
+ public DateTime CreatedOn { get; set; }
+
+ public DateTime ModifiedOn { get; set; }
+
+ public long RowVersion { get; set; }
+
+ public object IdValue { get => RmsIncidentModuleId; set => RmsIncidentModuleId = (string)value; }
+ public string TableName => "RmsIncidentModules";
+ public string IdName => "RmsIncidentModuleId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new string[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ ///
+ /// A non-unit resource used on the incident (plan section 4.2 "resources"). Units are
+ /// ; this is everything else a department wants on the record — foam, a borrowed
+ /// tender, a contractor.
+ ///
+ /// Contract 1.4.78 has no incident-level resources field, so these rows are a department record only: they
+ /// print and export, and they are never mapped into a submission payload. The code is the department's own,
+ /// not a NERIS value-set member, and nothing validates it against one.
+ ///
+ ///
+ public class RmsIncidentResource : IEntity
+ {
+ public string RmsIncidentResourceId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string RecordId { get; set; }
+ public string RevisionId { get; set; }
+ /// NERIS resource value-set code.
+ public string ResourceCode { get; set; }
+ public int? Quantity { get; set; }
+ public string Detail { get; set; }
+ public int Ordinal { get; set; }
+ public DateTime CreatedOn { get; set; }
+ public DateTime ModifiedOn { get; set; }
+ public long RowVersion { get; set; }
+
+ public object IdValue { get => RmsIncidentResourceId; set => RmsIncidentResourceId = (string)value; }
+ public string TableName => "RmsIncidentResources";
+ public string IdName => "RmsIncidentResourceId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new string[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ /// Lifecycle of the separate incident-analysis filing; deliberately narrower than the incident's.
+ public enum RmsIncidentAnalysisState
+ {
+ /// Being authored; never submitted from here.
+ Draft = 0,
+
+ /// Finalized with the incident and eligible for submission once the incident exists at the destination.
+ Finalized = 1,
+
+ /// Queued or in flight to the destination.
+ Submitted = 2,
+
+ /// The destination accepted the analysis.
+ Accepted = 3,
+
+ /// The destination rejected it; correctable in place like a rejected incident.
+ Rejected = 4,
+
+ /// Withdrawn; retained as history, never submitted again.
+ Voided = 5
+ }
+
+ ///
+ /// The NERIS incident analysis (registry M0167): the fire/hazmat investigation filing that the contract posts
+ /// to /incident_analysis/{neris_id_incident} after the incident itself exists. It is a second
+ /// submittable artifact for the same incident, not a section of it, so it carries its own state, revisions,
+ /// submissions and idempotency key — and it can never be submitted before the incident has a NERIS id.
+ ///
+ public class RmsIncidentAnalysis : IEntity
+ {
+ public string RmsIncidentAnalysisId { get; set; }
+
+ public int DepartmentId { get; set; }
+
+ public string ProtectionId { get; set; }
+
+ /// The incident report this analysis belongs to (one per report).
+ public string IncidentReportId { get; set; }
+
+ public string ReportingEntityId { get; set; }
+
+ /// Pinned NERIS contract version the analysis was authored against.
+ public string ProfileVersion { get; set; }
+
+ /// .
+ public int State { get; set; }
+
+ /// General fire cause (NERIS fire_cause_general), the analysis's headline determination.
+ public string GeneralCause { get; set; }
+
+ /// Investigation types the department applied (comma-separated NERIS fire_invest codes).
+ public string InvestigationTypesCsv { get; set; }
+
+ /// Estimated total loss in whole currency units, department-reported.
+ public decimal? EstimatedLossTotal { get; set; }
+
+ /// Estimated pre-incident value in whole currency units.
+ public decimal? EstimatedValueTotal { get; set; }
+
+ public string CurrencyCode { get; set; }
+
+ public string AuthorUserId { get; set; }
+
+ public string OwnerUserId { get; set; }
+
+ public DateTime? FinalizedOn { get; set; }
+
+ public string FinalizedByUserId { get; set; }
+
+ public string CurrentRevisionId { get; set; }
+
+ public int RevisionCount { get; set; }
+
+ /// NERIS-assigned analysis id once the first create succeeded.
+ public string NerisAnalysisId { get; set; }
+
+ public string LastSubmissionId { get; set; }
+
+ /// of the latest analysis submission.
+ public int? LastSubmissionState { get; set; }
+
+ public DateTime? LastSubmittedOn { get; set; }
+
+ public DateTime? AcceptedOn { get; set; }
+
+ public DateTime? RejectedOn { get; set; }
+
+ /// Normalized, non-sensitive summary of the last rejection (codes and field paths only).
+ public string RejectionSummary { get; set; }
+
+ public DateTime? VoidedOn { get; set; }
+
+ public string VoidedByUserId { get; set; }
+
+ public string VoidReasonCode { get; set; }
+
+ public string VoidReasonText { get; set; }
+
+ public DateTime CreatedOn { get; set; }
+
+ public string CreatedByUserId { get; set; }
+
+ public DateTime ModifiedOn { get; set; }
+
+ public string ModifiedByUserId { get; set; }
+
+ public long RowVersion { get; set; }
+
+ public DateTime? DeletedOn { get; set; }
+
+ public object IdValue { get => RmsIncidentAnalysisId; set => RmsIncidentAnalysisId = (string)value; }
+ public string TableName => "RmsIncidentAnalyses";
+ public string IdName => "RmsIncidentAnalysisId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new string[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ ///
+ /// One property involved in the incident (incident_analysis.properties[]): use, damage, value and loss.
+ /// Typed rather than a module row because loss and value are summed by department reporting.
+ ///
+ public class RmsIncidentProperty : IEntity
+ {
+ public string RmsIncidentPropertyId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ /// The owning incident analysis.
+ public string RecordId { get; set; }
+ public string RevisionId { get; set; }
+ /// NERIS location_use code of the property.
+ public string LocationUse { get; set; }
+ /// NERIS construction type where the property is a structure.
+ public string ConstructionType { get; set; }
+ public string Foundation { get; set; }
+ public string ExteriorFinish { get; set; }
+ public string RoofMaterial { get; set; }
+ public int? StoriesAboveGrade { get; set; }
+ public int? StoriesBelowGrade { get; set; }
+ public int? YearBuilt { get; set; }
+ /// NERIS vacancy code.
+ public string Vacancy { get; set; }
+ /// NERIS fire_bldg_damage / exposure_damage rating.
+ public string DamageType { get; set; }
+ /// NERIS fire_spread code — how far the fire travelled.
+ public string FireSpread { get; set; }
+ public decimal? EstimatedValue { get; set; }
+ public decimal? EstimatedLoss { get; set; }
+ public decimal? ContentsValue { get; set; }
+ public decimal? ContentsLoss { get; set; }
+ public string CurrencyCode { get; set; }
+ /// Contract-shaped remainder of the property payload.
+ public string DetailJson { get; set; }
+ public string ProtectedEnvelope { get; set; }
+ public bool IsProtected { get; set; }
+ public int ProtectedCatalogVersion { get; set; }
+ public int Ordinal { get; set; }
+ public DateTime CreatedOn { get; set; }
+ public DateTime ModifiedOn { get; set; }
+ public long RowVersion { get; set; }
+
+ public object IdValue { get => RmsIncidentPropertyId; set => RmsIncidentPropertyId = (string)value; }
+ public string TableName => "RmsIncidentProperties";
+ public string IdName => "RmsIncidentPropertyId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new string[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ ///
+ /// One vehicle involved in the incident (incident_analysis.vehicles[]). VIN, plate and owner identity are
+ /// personally identifying, so the row carries the inert Protected Data envelope and is classified restricted
+ /// for per-field authorization inside detail, print, diff and export.
+ ///
+ public class RmsIncidentVehicle : IEntity
+ {
+ public string RmsIncidentVehicleId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ /// The owning incident analysis.
+ public string RecordId { get; set; }
+ public string RevisionId { get; set; }
+ /// AUTOMOBILE for the automobile payload, OTHER for the other-vehicle payload.
+ public string VehicleKind { get; set; }
+ /// NERIS auto_make code.
+ public string Make { get; set; }
+ public string Model { get; set; }
+ public int? ModelYear { get; set; }
+ /// NERIS auto_body_style code.
+ public string BodyStyle { get; set; }
+ /// NERIS powertrain code.
+ public string Powertrain { get; set; }
+ /// NERIS vehicle_damage rating.
+ public string DamageType { get; set; }
+ /// Restricted: vehicle identification number.
+ public string Vin { get; set; }
+ /// Restricted: registration plate.
+ public string LicensePlate { get; set; }
+ public string LicenseState { get; set; }
+ public bool WasOccupied { get; set; }
+ public decimal? EstimatedValue { get; set; }
+ public decimal? EstimatedLoss { get; set; }
+ public string CurrencyCode { get; set; }
+ public string DetailJson { get; set; }
+ public string ProtectedEnvelope { get; set; }
+ public bool IsProtected { get; set; }
+ public int ProtectedCatalogVersion { get; set; }
+ public int Ordinal { get; set; }
+ public DateTime CreatedOn { get; set; }
+ public DateTime ModifiedOn { get; set; }
+ public long RowVersion { get; set; }
+
+ public object IdValue { get => RmsIncidentVehicleId; set => RmsIncidentVehicleId = (string)value; }
+ public string TableName => "RmsIncidentVehicles";
+ public string IdName => "RmsIncidentVehicleId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new string[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+}
diff --git a/Core/Resgrid.Model/Records/RmsIncidentReport.cs b/Core/Resgrid.Model/Records/RmsIncidentReport.cs
index 2aacdcd9..91d3b6ac 100644
--- a/Core/Resgrid.Model/Records/RmsIncidentReport.cs
+++ b/Core/Resgrid.Model/Records/RmsIncidentReport.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using ProtoBuf;
@@ -219,6 +219,10 @@ public class RmsIncidentReport : IEntity
[ProtoMember(52)]
public DateTime? DeletedOn { get; set; }
+ /// When the retention sweep purged the content (RMS-3, worker 43); the row itself survives as a tombstone.
+ [ProtoMember(65)]
+ public DateTime? PurgedOn { get; set; }
+
public string RecordId => RmsIncidentReportId;
public RmsRecordKind RecordKind => RmsRecordKind.IncidentReport;
diff --git a/Core/Resgrid.Model/Records/RmsOperationalRecord.cs b/Core/Resgrid.Model/Records/RmsOperationalRecord.cs
index 22e61047..04ae647f 100644
--- a/Core/Resgrid.Model/Records/RmsOperationalRecord.cs
+++ b/Core/Resgrid.Model/Records/RmsOperationalRecord.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using Newtonsoft.Json;
@@ -125,6 +125,9 @@ public class RmsOperationalRecord : IEntity
/// Optimistic-concurrency counter (ETag). Incremented by the service on every draft save.
public long RowVersion { get; set; }
+ /// When the retention sweep purged the content (RMS-3, worker 43); the row itself survives as a tombstone.
+ public DateTime? PurgedOn { get; set; }
+
public DateTime? DeletedOn { get; set; }
[NotMapped]
diff --git a/Core/Resgrid.Model/Records/RmsSubmission.cs b/Core/Resgrid.Model/Records/RmsSubmission.cs
index 523175cb..dbdc62ee 100644
--- a/Core/Resgrid.Model/Records/RmsSubmission.cs
+++ b/Core/Resgrid.Model/Records/RmsSubmission.cs
@@ -20,6 +20,13 @@ public enum RmsSubmissionState
public static class RmsSubmissionDestinations
{
public const string Neris = "NERIS";
+
+ ///
+ /// The separate incident-analysis filing (RMS-3). It is its own destination string so an incident and its
+ /// analysis never collide on an idempotency key, and so worker 41 can tell which endpoint a claimed row
+ /// belongs to without reading the payload.
+ ///
+ public const string NerisIncidentAnalysis = "NERIS_ANALYSIS";
}
///
diff --git a/Core/Resgrid.Model/Records/SystemPrincipalRecordGrant.cs b/Core/Resgrid.Model/Records/SystemPrincipalRecordGrant.cs
new file mode 100644
index 00000000..ab4333a1
--- /dev/null
+++ b/Core/Resgrid.Model/Records/SystemPrincipalRecordGrant.cs
@@ -0,0 +1,130 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Resgrid.Model
+{
+ ///
+ /// One explicitly configured Record grant for a system principal (Identifier Allocation Registry
+ /// section 4.4). System principals — the SMTP relay key and the client_credentials service accounts —
+ /// are not people: they have no Permission rows, no roles and no group membership, so the
+ /// grant-everything fall-through that departments rely on must never reach them. A grant names a
+ /// department, a purpose that is written to the access audit on every read, and either department-wide
+ /// scope or the exact group ids the purpose covers, which is how "subject to the same group scope as a
+ /// user principal" is expressed for a principal that has no groups of its own.
+ ///
+ /// A grant conveys Record_View and nothing else. There is no configuration that produces a
+ /// mutating or restricted Record policy for a system principal; that is enforced at the two claim
+ /// issuance sites and asserted by SystemApiKeyRecordPolicyTests.
+ ///
+ ///
+ public sealed class SystemPrincipalRecordGrant
+ {
+ public const string DepartmentWideToken = "DepartmentWide";
+ public const string GroupsToken = "Groups";
+
+ public SystemPrincipalRecordGrant(int departmentId, string purpose, bool departmentWide, IEnumerable groupIds)
+ {
+ DepartmentId = departmentId;
+ Purpose = purpose;
+ DepartmentWide = departmentWide;
+ GroupIds = (groupIds ?? Enumerable.Empty()).Distinct().OrderBy(i => i).ToList();
+ }
+
+ public int DepartmentId { get; }
+
+ /// Why this principal may read Records; written to RmsRecordAccessAudit.Purpose.
+ public string Purpose { get; }
+
+ /// When true the principal sees the whole department; when false it sees only.
+ public bool DepartmentWide { get; }
+
+ /// The groups the purpose covers. Empty under a non-department-wide grant means the principal sees nothing.
+ public IReadOnlyList GroupIds { get; }
+
+ /// The visible-group filter to apply, or null for "the whole department" — the same shape
+ /// IRecordsAuthorizationService.GetVisibleGroupIdsAsync returns for a user.
+ public List VisibleGroupIds() => DepartmentWide ? null : GroupIds.ToList();
+
+ private static string _parsedFrom;
+ private static IReadOnlyList _parsed = Array.Empty();
+ private static readonly object _parseLock = new object();
+
+ /// Every configured grant. Parsed once per distinct configuration string.
+ public static IReadOnlyList All()
+ {
+ var raw = Config.RecordsSystemAccessConfig.Grants ?? string.Empty;
+
+ lock (_parseLock)
+ {
+ if (!string.Equals(raw, _parsedFrom, StringComparison.Ordinal))
+ {
+ _parsed = Parse(raw);
+ _parsedFrom = raw;
+ }
+
+ return _parsed;
+ }
+ }
+
+ /// Whether any system principal has been granted Record access at all.
+ public static bool AnyConfigured() => All().Count > 0;
+
+ /// The grant covering a department, or null when the principal has none there.
+ public static SystemPrincipalRecordGrant For(int departmentId)
+ {
+ if (departmentId <= 0)
+ return null;
+
+ return All().FirstOrDefault(g => g.DepartmentId == departmentId);
+ }
+
+ ///
+ /// Parses the configured grant string. A malformed entry is skipped rather than widened: a grant that
+ /// cannot be read is not a grant, so the principal is denied.
+ ///
+ public static IReadOnlyList Parse(string raw)
+ {
+ var grants = new List();
+
+ if (string.IsNullOrWhiteSpace(raw))
+ return grants;
+
+ foreach (var entry in raw.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
+ {
+ var parts = entry.Split('|');
+ if (parts.Length != 3)
+ continue;
+
+ if (!int.TryParse(parts[0].Trim(), out var departmentId) || departmentId <= 0)
+ continue;
+
+ var purpose = parts[1].Trim();
+ if (string.IsNullOrWhiteSpace(purpose))
+ continue;
+
+ var scope = parts[2].Trim();
+
+ if (string.Equals(scope, DepartmentWideToken, StringComparison.OrdinalIgnoreCase))
+ {
+ grants.Add(new SystemPrincipalRecordGrant(departmentId, purpose, true, null));
+ continue;
+ }
+
+ if (!scope.StartsWith(GroupsToken + ":", StringComparison.OrdinalIgnoreCase))
+ continue;
+
+ var groupIds = scope.Substring(GroupsToken.Length + 1)
+ .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
+ .Select(v => int.TryParse(v.Trim(), out var id) ? id : 0)
+ .Where(id => id > 0)
+ .ToList();
+
+ grants.Add(new SystemPrincipalRecordGrant(departmentId, purpose, false, groupIds));
+ }
+
+ // A department named twice is ambiguous; the first entry wins so the configuration is deterministic.
+ return grants.GroupBy(g => g.DepartmentId).Select(g => g.First()).ToList();
+ }
+ }
+}
diff --git a/Core/Resgrid.Model/Repositories/IRmsIncidentRepositories.cs b/Core/Resgrid.Model/Repositories/IRmsIncidentRepositories.cs
index ae9c2a20..d63c677a 100644
--- a/Core/Resgrid.Model/Repositories/IRmsIncidentRepositories.cs
+++ b/Core/Resgrid.Model/Repositories/IRmsIncidentRepositories.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@@ -13,6 +13,15 @@ public sealed class RmsIncidentReportQuery
public int? CallId { get; set; }
public string OwnerUserId { get; set; }
public int? StationGroupId { get; set; }
+
+ ///
+ /// When non-null, restricts to reports whose group scope intersects these ids or whose author, owner or
+ /// reviewer is — the same rule CanUserViewRecordAsync applies per record.
+ /// Filtering here rather than after paging is what keeps CountAsync and the page links honest.
+ ///
+ public IList VisibleGroupIds { get; set; }
+
+ public string ViewerUserId { get; set; }
public int Skip { get; set; }
public int Take { get; set; } = 50;
}
@@ -30,6 +39,8 @@ public interface IRmsIncidentReportsRepository : IRepository
Task> GetYearsAsync(int departmentId);
Task GetMaxRecordNumberSequenceAsync(int departmentId, string numberPrefix);
Task TryBumpRowVersionAsync(int departmentId, string reportId, long expectedRowVersion, CancellationToken cancellationToken = default);
+ /// Retention candidates (RMS-3, worker 43): live, closed reports finalized before the cutoff, oldest first.
+ Task> GetRetentionCandidatesAsync(int departmentId, DateTime cutoffUtc, int take);
}
/// Shared contract of every per-report child row set: a working draft (RevisionId null) and immutable revision copies.
@@ -47,6 +58,30 @@ public interface IRmsAidsRepository : IRmsIncidentChildRepository { }
public interface IRmsLocationsRepository : IRmsIncidentChildRepository { }
public interface IRmsNarrativesRepository : IRmsIncidentChildRepository { }
+ // RMS-3 conditional sections (registry M0167) and the restricted casualty/exposure classes (M0168). Each is
+ // the same draft/revision child shape, so nothing about revisioning, export or print needs a special case.
+ public interface IRmsIncidentModulesRepository : IRmsIncidentChildRepository
+ {
+ /// The draft rows of one module kind, in ordinal order; the authoring surface edits a kind at a time.
+ Task> GetForRecordByKindAsync(int departmentId, string recordId, string revisionId, RmsIncidentModuleKind kind);
+ }
+
+ public interface IRmsIncidentResourcesRepository : IRmsIncidentChildRepository { }
+ public interface IRmsCasualtyRescuesRepository : IRmsIncidentChildRepository { }
+ public interface IRmsExposuresRepository : IRmsIncidentChildRepository { }
+ public interface IRmsIncidentPropertiesRepository : IRmsIncidentChildRepository { }
+ public interface IRmsIncidentVehiclesRepository : IRmsIncidentChildRepository { }
+
+ public interface IRmsIncidentAnalysesRepository : IRepository
+ {
+ Task GetByIdForDepartmentAsync(int departmentId, string analysisId);
+ /// The analysis for an incident report; one per report, null when none has been started.
+ Task GetForReportAsync(int departmentId, string incidentReportId);
+ /// Analyses finalized but not yet filed because their incident had no NERIS id at the time.
+ Task> GetAwaitingIncidentAsync(int departmentId, int take);
+ Task CountByStateAsync(int departmentId, RmsIncidentAnalysisState state);
+ }
+
public interface IRmsValidationIssuesRepository : IRepository
{
Task> GetForRecordAsync(int departmentId, string recordId);
@@ -61,7 +96,8 @@ public interface IRmsSubmissionsRepository : IRepository
Task GetByIdempotencyKeyAsync(string idempotencyKey);
/// Leases due Queued/AwaitingDestination submissions across departments for one worker sweep (plan 5.3: no transaction across the destination call).
Task> ClaimDueBatchAsync(string leaseOwner, TimeSpan leaseDuration, int batchSize, DateTime utcNow, CancellationToken cancellationToken = default);
- Task CountByStateAsync(int state);
+ /// Queue depth for one department; the settings screen must never show another department's rows.
+ Task CountByStateAsync(int departmentId, int state);
/// Marks every non-terminal submission of the record Superseded (a new revision issued a new idempotency key).
Task SupersedeOpenForRecordAsync(int departmentId, string recordId, string exceptSubmissionId, DateTime utcNow, CancellationToken cancellationToken = default);
}
diff --git a/Core/Resgrid.Model/Repositories/IRmsRepositories.cs b/Core/Resgrid.Model/Repositories/IRmsRepositories.cs
index df50e01c..38f3f5a8 100644
--- a/Core/Resgrid.Model/Repositories/IRmsRepositories.cs
+++ b/Core/Resgrid.Model/Repositories/IRmsRepositories.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@@ -46,6 +46,8 @@ public interface IRmsOperationalRecordsRepository : IRepository> GetOpenAsync(int departmentId);
/// Live Finalized/Amended Records whose FinalizedOn is at or after the instant.
Task> GetFinalizedSinceAsync(int departmentId, DateTime sinceUtc);
+ /// Retention candidates (RMS-3, worker 43): live, closed Records finalized before the cutoff, oldest first.
+ Task> GetRetentionCandidatesAsync(int departmentId, DateTime cutoffUtc, int take);
/// Live Records with no RmsRecordGroupScope row: they stay department-wide under group scoping (plan 5.7.1).
Task CountWithoutGroupScopeAsync(int departmentId);
Task> GetYearsAsync(int departmentId);
@@ -91,6 +93,12 @@ public interface IRmsRecordAttachmentsRepository : IRepository> GetMetadataForRecordAsync(int departmentId, string recordId);
/// Loads Data; authorized per Record by the caller on every request.
Task GetByIdForDepartmentAsync(int departmentId, string attachmentId);
+ ///
+ /// Attachments still sitting at — stored because the scanner
+ /// was unreachable and the department chose availability over fail-closed. Worker 43 rescans them; without
+ /// this sweep a Pending attachment would stay unscanned forever (RMS-1 gap closed in RMS-3).
+ ///
+ Task> GetPendingScanAsync(int departmentId, int take);
}
public interface IRmsExternalReferencesRepository : IRepository
@@ -142,7 +150,12 @@ public interface IRmsRecordSearchProjectionsRepository : IRepository CountAsync(int departmentId, RmsRecordQuery query);
Task> GetYearsAsync(int departmentId);
/// Projections (including soft-deleted ones) modified after , oldest first; the search index catch-up feed.
- Task> GetModifiedSinceAsync(int departmentId, DateTime? since, int take);
+ ///
+ /// Rows after the (ModifiedOn, id) cursor, oldest first. The id is part of the cursor because several rows
+ /// routinely share a modified timestamp: a timestamp-only cursor skips whatever sat after the page break
+ /// inside that group, and an offline client never learns those rows changed.
+ ///
+ Task> GetModifiedSinceAsync(int departmentId, DateTime? since, int take, string sinceId = null);
/// Live projections by record id, for post-retrieval loading of search hits.
Task> GetByIdsAsync(int departmentId, IEnumerable recordIds);
}
@@ -166,4 +179,66 @@ public interface IRmsRecordSharesRepository : IRepository
{
Task> GetForRecordAsync(int departmentId, string recordId);
}
+
+ ///
+ /// Persisted due state per (Record, obligation) — registry M0170, RMS-3. The uniqueness of that pair is what
+ /// makes worker 42's "at most once per due-state transition" guarantee hold across missed and repeated runs.
+ ///
+ ///
+ /// Immutable evidence artifacts (registry M0169, RMS-3). There is no update path by design: a correction
+ /// supersedes an artifact rather than editing it, so the checksum of what was attested to stays true.
+ ///
+ public interface IRmsEvidenceArtifactsRepository : IRepository
+ {
+ Task GetByIdForDepartmentAsync(int departmentId, string artifactId);
+ /// null returns the working-draft artifacts.
+ Task> GetForRecordAsync(int departmentId, string recordId, string revisionId, bool includeSuperseded);
+ /// The current artifact of one kind on the draft, or null; capture supersedes it.
+ Task GetCurrentDraftOfKindAsync(int departmentId, string recordId, RmsEvidenceKind kind, string sourceEntityId);
+ /// Stamps every unbound draft artifact with the revision being written at finalize.
+ Task BindDraftToRevisionAsync(int departmentId, string recordId, string revisionId, DateTime utcNow, CancellationToken cancellationToken = default);
+ Task CountForRecordAsync(int departmentId, string recordId);
+ }
+
+ public interface IRmsRecordDueStatesRepository : IRepository
+ {
+ Task GetAsync(int departmentId, string recordId, RmsRecordObligation obligation);
+ Task> GetForRecordAsync(int departmentId, string recordId);
+ /// Open obligations (not yet cleared) for a department, oldest deadline first.
+ Task> GetOpenForDepartmentAsync(int departmentId, int take);
+ /// Count of obligations currently sitting overdue; the accountability view and dashboards read it.
+ Task CountOverdueAsync(int departmentId);
+ Task ClearForRecordAsync(int departmentId, string recordId, DateTime utcNow, CancellationToken cancellationToken = default);
+ }
+
+ /// Public-records requests (registry M0171, RMS-3); the statutory clock is what these are read by.
+ public interface IRmsDisclosureRequestsRepository : IRepository
+ {
+ Task GetByIdForDepartmentAsync(int departmentId, string requestId);
+ Task> GetForDepartmentAsync(int departmentId, IEnumerable states, int skip, int take);
+ Task CountByStateAsync(int departmentId, RmsDisclosureState state);
+ /// Open requests past their statutory due date; the number an officer is accountable for.
+ Task CountOverdueAsync(int departmentId, DateTime utcNow);
+ Task GetMaxRequestNumberSequenceAsync(int departmentId, string numberPrefix);
+ }
+
+ ///
+ /// Immutable produced sets (registry M0171, RMS-3). A production is never edited: a supplemental release is a
+ /// new production, so what was handed over stays exactly what was handed over.
+ ///
+ public interface IRmsDisclosureProductionsRepository : IRepository
+ {
+ Task GetByIdForDepartmentAsync(int departmentId, string productionId);
+ Task> GetForRequestAsync(int departmentId, string requestId);
+ Task GetMaxProductionNumberAsync(int departmentId, string requestId);
+ }
+
+ public interface IRmsRecordLegalHoldsRepository : IRepository
+ {
+ Task GetByIdForDepartmentAsync(int departmentId, string holdId);
+ /// Every hold still in force for the department; the retention sweep loads them once per pass.
+ Task> GetActiveForDepartmentAsync(int departmentId);
+ Task> GetForRecordAsync(int departmentId, string recordId);
+ Task> GetAllForDepartmentAsync(int departmentId);
+ }
}
diff --git a/Core/Resgrid.Model/Services/IIncidentAnalysisService.cs b/Core/Resgrid.Model/Services/IIncidentAnalysisService.cs
new file mode 100644
index 00000000..a1a1dcce
--- /dev/null
+++ b/Core/Resgrid.Model/Services/IIncidentAnalysisService.cs
@@ -0,0 +1,49 @@
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Resgrid.Model.Services
+{
+ ///
+ /// The NERIS incident-analysis filing (RMS-3, registry M0167): the fire/hazmat investigation the contract
+ /// posts to /incident_analysis/{neris_id_incident} after the incident itself exists.
+ ///
+ /// It is a second submittable artifact for the same incident, not a section of it, which is the whole reason
+ /// it has its own service: an analysis that will not validate must never block the incident report, and an
+ /// incident that is still in flight must not lose its analysis. Finalizing an analysis before its incident is
+ /// filed is allowed and expected — the submission simply waits for the incident's NERIS id.
+ ///
+ ///
+ public interface IIncidentAnalysisService
+ {
+ /// Starts (or returns) the analysis for an incident report; one per report.
+ Task StartForReportAsync(int departmentId, string userId, string incidentReportId, RmsOriginClient origin = RmsOriginClient.Web, CancellationToken cancellationToken = default);
+
+ Task GetAsync(int departmentId, string analysisId, bool includeHistory = false);
+
+ Task GetForReportAsync(int departmentId, string incidentReportId, bool includeHistory = false);
+
+ ///
+ /// ETag-guarded draft save. false keeps the stored VIN and plate on
+ /// each vehicle row rather than accepting or erasing them.
+ ///
+ Task SaveDraftAsync(int departmentId, string userId, string analysisId, long expectedRowVersion, IncidentAnalysisDraftInput input, bool canWriteRestricted = true, CancellationToken cancellationToken = default);
+
+ /// Local validation against the pinned contract; never touches the incident's own issue list.
+ Task> ValidateAsync(int departmentId, string analysisId, CancellationToken cancellationToken = default);
+
+ /// Writes the immutable revision and queues the filing when the incident is already at the destination.
+ Task FinalizeAsync(int departmentId, string userId, string analysisId, long expectedRowVersion, CancellationToken cancellationToken = default);
+
+ /// Queues (or re-queues) the current revision; used when the incident was filed after the analysis was finalized.
+ Task QueueSubmissionAsync(int departmentId, string userId, string analysisId, CancellationToken cancellationToken = default);
+
+ /// Queues every finalized analysis whose incident has since been filed; driven by worker 41.
+ Task QueueAwaitingIncidentAsync(int departmentId, CancellationToken cancellationToken = default);
+
+ Task VoidAsync(int departmentId, string userId, string analysisId, string reasonCode, string reasonText, CancellationToken cancellationToken = default);
+
+ /// The snapshot the mapper consumes, from the draft rows or from a revision's copies.
+ Task BuildSnapshotAsync(int departmentId, string analysisId, string revisionId = null);
+ }
+}
diff --git a/Core/Resgrid.Model/Services/IIncidentReportsService.cs b/Core/Resgrid.Model/Services/IIncidentReportsService.cs
index 7348ccd7..bf25691f 100644
--- a/Core/Resgrid.Model/Services/IIncidentReportsService.cs
+++ b/Core/Resgrid.Model/Services/IIncidentReportsService.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Resgrid.Model.Repositories;
@@ -19,7 +19,12 @@ public interface IIncidentReportsService
Task GetForCallAsync(int departmentId, int callId);
- Task SaveDraftAsync(int departmentId, string userId, string reportId, long expectedRowVersion, IncidentReportDraftInput input, CancellationToken cancellationToken = default);
+ ///
+ /// ETag-guarded draft save. false keeps the restricted halves of the
+ /// casualty rows as they stand instead of accepting or erasing them, so a reviewer without
+ /// RecordRestricted_View can still correct the rest of the report (RMS-3).
+ ///
+ Task SaveDraftAsync(int departmentId, string userId, string reportId, long expectedRowVersion, IncidentReportDraftInput input, bool canWriteRestricted = true, CancellationToken cancellationToken = default);
/// Runs local validation (and the destination's validate endpoint when asked and configured) and stores the issues on the report.
Task> ValidateAsync(int departmentId, string reportId, bool includeDestination, CancellationToken cancellationToken = default);
@@ -51,6 +56,12 @@ public interface IIncidentReportsService
Task> GetYearsAsync(int departmentId);
+ ///
+ /// The conditional sections this report's selected incident types demand or suggest (RMS-3). The authoring
+ /// surfaces render exactly this, so a client never keeps its own copy of the progressive rules.
+ ///
+ Task> GetSectionRequirementsAsync(int departmentId, string reportId);
+
/// The snapshot the mapper consumes, from the draft rows or from a revision's copies.
Task BuildSnapshotAsync(int departmentId, string reportId, string revisionId = null);
diff --git a/Core/Resgrid.Model/Services/IRecordsAuthorizationService.cs b/Core/Resgrid.Model/Services/IRecordsAuthorizationService.cs
index 3acdfdf8..7396060b 100644
--- a/Core/Resgrid.Model/Services/IRecordsAuthorizationService.cs
+++ b/Core/Resgrid.Model/Services/IRecordsAuthorizationService.cs
@@ -25,6 +25,14 @@ public interface IRecordsAuthorizationService
/// Per-Record check applied on every detail, attachment and deep-link read.
Task CanUserViewRecordAsync(string userId, string recordId, int departmentId);
+ ///
+ /// Per-Record check for a system principal reading under a configured grant (Identifier Allocation
+ /// Registry section 4.4). A system principal is nobody: none of the always-visible author/owner/
+ /// reviewer/participant cases apply to it, so a non-department-wide grant sees exactly the groups it
+ /// names and nothing else.
+ ///
+ Task CanSystemPrincipalViewRecordAsync(SystemPrincipalRecordGrant grant, string recordId);
+
/// What GroupScoped would hide, by group, before an administrator confirms it (plan 5.7.1 "Turning it on").
Task PreviewGroupScopingAsync(int departmentId);
}
diff --git a/Core/Resgrid.Model/Services/IRecordsDashboardService.cs b/Core/Resgrid.Model/Services/IRecordsDashboardService.cs
new file mode 100644
index 00000000..5b266a3c
--- /dev/null
+++ b/Core/Resgrid.Model/Services/IRecordsDashboardService.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Resgrid.Model.Services
+{
+ ///
+ /// The Records work queues an officer opens the module to look at (RMS plan RMS-3): incomplete, awaiting
+ /// review, rejected, accepted, overdue — plus the statutory disclosure clock and the crosswalk coverage that
+ /// decides whether a filing will map cleanly at all.
+ ///
+ /// Every count is department-scoped and group-scope-aware, so a dashboard never tells a member that records
+ /// exist which their queue will not show them.
+ ///
+ ///
+ public interface IRecordsDashboardService
+ {
+ Task GetAsync(int departmentId, string userId, CancellationToken cancellationToken = default);
+
+ ///
+ /// NERIS crosswalk coverage (RMS plan RMS-3, "crosswalk reporting"): which of the department's own call
+ /// types map to a NERIS incident type and which do not. An unmapped type is a filing that will need manual
+ /// classification on the night, so this is a gap report, not a statistic.
+ ///
+ Task GetCrosswalkCoverageAsync(int departmentId, CancellationToken cancellationToken = default);
+ }
+
+ /// Queue counts across both Records aggregates plus the obligations and requests that carry a clock.
+ public class RecordsDashboard
+ {
+ public DateTime GeneratedOn { get; set; } = DateTime.UtcNow;
+
+ /// Operational Records still being authored.
+ public int OperationalDrafts { get; set; }
+
+ public int OperationalAwaitingReview { get; set; }
+
+ public int OperationalReturned { get; set; }
+
+ /// Incident reports not yet finalized — the "incomplete" queue.
+ public int IncidentIncomplete { get; set; }
+
+ public int IncidentAwaitingReview { get; set; }
+
+ /// Finalized and queued or in flight to the destination.
+ public int IncidentSubmitted { get; set; }
+
+ public int IncidentAccepted { get; set; }
+
+ /// Rejected by the destination and not yet corrected; the queue that costs a department money.
+ public int IncidentRejected { get; set; }
+
+ /// Obligations currently sitting overdue (worker 42's persisted due states).
+ public int Overdue { get; set; }
+
+ /// Incident analyses finalized but not yet filed, usually waiting on their incident.
+ public int AnalysesAwaitingFiling { get; set; }
+
+ public int DisclosuresOpen { get; set; }
+
+ /// Open public-records requests past their statutory due date.
+ public int DisclosuresOverdue { get; set; }
+
+ /// Set when a count could not be produced; the dashboard degrades rather than failing whole.
+ public List Warnings { get; set; } = new List();
+ }
+
+ /// One local code and whether it maps to a NERIS value.
+ public class NerisCrosswalkCoverageItem
+ {
+ public string SetKey { get; set; }
+ public string LocalCode { get; set; }
+ public string NerisCode { get; set; }
+ public bool Mapped => !string.IsNullOrWhiteSpace(NerisCode);
+ }
+
+ /// Crosswalk gap report for a department.
+ public class NerisCrosswalkCoverage
+ {
+ public string ContractVersion { get; set; }
+ public int TotalLocalCodes { get; set; }
+ public int MappedCount { get; set; }
+ public int UnmappedCount { get; set; }
+
+ /// Mapped codes whose NERIS value is not in the pinned contract any more; a silent submission failure waiting to happen.
+ public int StaleMappingCount { get; set; }
+
+ public List Items { get; set; } = new List();
+
+ public List Warnings { get; set; } = new List();
+ }
+}
diff --git a/Core/Resgrid.Model/Services/IRecordsDisclosureService.cs b/Core/Resgrid.Model/Services/IRecordsDisclosureService.cs
new file mode 100644
index 00000000..05f80857
--- /dev/null
+++ b/Core/Resgrid.Model/Services/IRecordsDisclosureService.cs
@@ -0,0 +1,56 @@
+using System.Collections.Generic;
+using System.Threading;
+using Resgrid.Model.Repositories;
+using System.Threading.Tasks;
+
+namespace Resgrid.Model.Services
+{
+ ///
+ /// Public-records and access-to-information workflow (RMS plan section 4.7, registry M0171, RMS-3).
+ ///
+ /// Section 5.8 asks for public-records export and redaction as a control. For a public agency this is a
+ /// statutory obligation with a clock, so it is a tracked request rather than an export button: log the
+ /// request, resolve its scope through the same Records authorization path everything else uses, redact
+ /// against the classification catalog into a new immutable artifact, and release with a produced-set
+ /// snapshot so a later amendment cannot silently change what was handed over.
+ ///
+ ///
+ /// Callers must hold RecordDisclosure_Update; this service assumes the policy check already happened
+ /// at the controller and enforces the workflow rules, not the permission.
+ ///
+ ///
+ public interface IRecordsDisclosureService
+ {
+ Task CreateRequestAsync(int departmentId, string userId, RmsDisclosureRequest request, CancellationToken cancellationToken = default);
+
+ Task GetAsync(int departmentId, string requestId);
+
+ Task> QueryAsync(int departmentId, IEnumerable states, int skip = 0, int take = 50);
+
+ /// Saves the scope query and narrative; refused once a production exists, because the scope is what was produced against.
+ Task SaveScopeAsync(int departmentId, string userId, string requestId, string scopeNarrative, RmsRecordQuery scope, string redactionProfile, CancellationToken cancellationToken = default);
+
+ ///
+ /// What the scope resolves to right now, through the same authorization and group-scope path as the
+ /// Records queue. Drafts are listed but never producible: an unfinished report is not a public record.
+ ///
+ Task PreviewScopeAsync(int departmentId, string userId, string requestId, int take = 200);
+
+ ///
+ /// Builds a new immutable production: redacted content, the produced-set snapshot, a redaction log and a
+ /// checksum. Never mutates a source revision.
+ ///
+ Task ProduceAsync(int departmentId, string userId, string requestId, string redactionProfile = null, CancellationToken cancellationToken = default);
+
+ /// Releases a prepared production to the requester and closes the statutory clock.
+ Task ReleaseAsync(int departmentId, string userId, string productionId, CancellationToken cancellationToken = default);
+
+ Task> GetProductionsAsync(int departmentId, string requestId);
+
+ /// Closes a request without release — denied under an exemption, or withdrawn. A reason is required.
+ Task CloseAsync(int departmentId, string userId, string requestId, RmsDisclosureState disposition, string reason, CancellationToken cancellationToken = default);
+
+ /// Re-computes a production's checksum from its stored artifact; false means it was tampered with.
+ Task VerifyProductionAsync(int departmentId, string productionId);
+ }
+}
diff --git a/Core/Resgrid.Model/Services/IRecordsDueStateService.cs b/Core/Resgrid.Model/Services/IRecordsDueStateService.cs
new file mode 100644
index 00000000..6350c8b8
--- /dev/null
+++ b/Core/Resgrid.Model/Services/IRecordsDueStateService.cs
@@ -0,0 +1,42 @@
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Resgrid.Model.Services
+{
+ ///
+ /// Worker command 42 (RmsDueStateEvaluationCommand, RMS plan section 4.7 / RMS-3): once a day per activated
+ /// department, work out what every open Record is late for, and emit trigger 112 and notification 32 exactly
+ /// on the transition into overdue.
+ ///
+ /// The guarantee the plan asks for — at most once per record and due-state transition — is carried by the
+ /// persisted row, never inferred from when the worker last ran. A run that is
+ /// missed emits late rather than not at all; a run that repeats emits nothing the first one already did.
+ ///
+ ///
+ public interface IRecordsDueStateService
+ {
+ Task SweepAsync(CancellationToken cancellationToken = default);
+
+ /// Evaluates one department; public so a single department can be driven and tested directly.
+ Task EvaluateDepartmentAsync(int departmentId, CancellationToken cancellationToken = default);
+
+ /// Clears every open obligation on a Record — called when it is finalized, voided or cancelled.
+ Task ClearForRecordAsync(int departmentId, string recordId, CancellationToken cancellationToken = default);
+ }
+
+ ///
+ /// Worker command 43 (RmsRetentionAndPurgeCommand, RMS plan RMS-3): retention, legal hold and attachment
+ /// purge, plus the rescan pass for attachments the scanner could not reach when they were uploaded.
+ ///
+ /// A purge leaves a content-free tombstone (plan section 4.9): the Record row, its number and its lifecycle
+ /// history survive so a reference to it still resolves, and only the content goes. Nothing under an active
+ /// legal hold is purged, and the refusal is audited rather than silent.
+ ///
+ ///
+ public interface IRecordsRetentionService
+ {
+ Task SweepAsync(CancellationToken cancellationToken = default);
+
+ Task ProcessDepartmentAsync(int departmentId, CancellationToken cancellationToken = default);
+ }
+}
diff --git a/Core/Resgrid.Model/Services/IRecordsEvidenceService.cs b/Core/Resgrid.Model/Services/IRecordsEvidenceService.cs
new file mode 100644
index 00000000..ef3ca295
--- /dev/null
+++ b/Core/Resgrid.Model/Services/IRecordsEvidenceService.cs
@@ -0,0 +1,66 @@
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Resgrid.Model.Services
+{
+ ///
+ /// One evidence source's capture rule (RMS plan section 4.5, RMS-3). An adapter reads its own subsystem,
+ /// decides what an authorized snapshot of it looks like, and hands back a bounded manifest. It never writes,
+ /// never persists, and never returns a live handle to the source — owns
+ /// serialization, checksum, classification, retention and audit so those cannot vary per source.
+ ///
+ public interface IRecordEvidenceAdapter
+ {
+ RmsEvidenceKind Kind { get; }
+
+ ///
+ /// False when the source subsystem is not present in this build or not configured for the department.
+ /// The adapter still ships — the plan requires all six — and says why it has nothing rather than
+ /// pretending the evidence does not exist.
+ ///
+ Task IsAvailableAsync(int departmentId);
+
+ Task CaptureAsync(RecordEvidenceCaptureRequest request, CancellationToken cancellationToken = default);
+ }
+
+ ///
+ /// Capture and read of immutable evidence artifacts (RMS plan sections 4.5, 5.2; registry M0169).
+ ///
+ /// Every capture proves the same five things regardless of source, which is why they run through one service:
+ /// the caller was authorized, the provenance is recorded, the classification is decided at capture, the
+ /// content is checksummed, and the retention rule is attached. An artifact is never updated; a correction
+ /// supersedes it and both remain readable.
+ ///
+ ///
+ public interface IRecordsEvidenceService
+ {
+ /// Which of the six sources can actually produce evidence for this department right now.
+ Task> GetSourceStatesAsync(int departmentId);
+
+ ///
+ /// Captures one artifact. Throws when the Record is missing or terminal, when the reason is absent, or
+ /// when the caller lacks the restricted grant for a source that classifies restricted.
+ ///
+ Task CaptureAsync(RecordEvidenceCaptureRequest request, bool canCaptureRestricted = true, CancellationToken cancellationToken = default);
+
+ /// Artifacts on the working draft, or on a revision when one is named.
+ Task> GetForRecordAsync(int departmentId, string recordId, string revisionId = null, bool includeSuperseded = false);
+
+ Task GetAsync(int departmentId, string artifactId);
+
+ /// Binds the draft's artifacts to a revision at finalize; artifacts already bound are untouched.
+ Task BindToRevisionAsync(int departmentId, string recordId, string revisionId, CancellationToken cancellationToken = default);
+
+ /// Re-computes the checksum from the stored manifest; false means the artifact was tampered with.
+ Task VerifyAsync(int departmentId, string artifactId);
+ }
+
+ /// Whether one evidence source can produce anything for a department, and why not when it cannot.
+ public class RecordEvidenceSourceState
+ {
+ public RmsEvidenceKind Kind { get; set; }
+ public bool Available { get; set; }
+ public string Reason { get; set; }
+ }
+}
diff --git a/Core/Resgrid.Model/Services/IRecordsNotificationService.cs b/Core/Resgrid.Model/Services/IRecordsNotificationService.cs
index 4a775380..284e93e6 100644
--- a/Core/Resgrid.Model/Services/IRecordsNotificationService.cs
+++ b/Core/Resgrid.Model/Services/IRecordsNotificationService.cs
@@ -1,4 +1,4 @@
-using System.Threading;
+using System.Threading;
using System.Threading.Tasks;
namespace Resgrid.Model.Services
@@ -16,5 +16,12 @@ public interface IRecordsNotificationService
/// EventTypes 33: the destination rejected the author's incident report; codes and field paths only, plus a link.
Task NotifySubmissionRejectedAsync(int departmentId, string reportId, CancellationToken cancellationToken = default);
+
+ ///
+ /// EventTypes 32 (RMS-3, worker 42): an obligation on a Record has gone overdue. Targeted at whoever the
+ /// obligation rests with — the reviewer for a review, the author for a correction or a resubmission — and
+ /// carries the reference, the obligation and how late it is. Never record content.
+ ///
+ Task NotifyObligationOverdueAsync(int departmentId, string recordId, RmsRecordObligation obligation, CancellationToken cancellationToken = default);
}
}
diff --git a/Core/Resgrid.Model/Services/IRecordsService.cs b/Core/Resgrid.Model/Services/IRecordsService.cs
index 0c290551..e5bce371 100644
--- a/Core/Resgrid.Model/Services/IRecordsService.cs
+++ b/Core/Resgrid.Model/Services/IRecordsService.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@@ -61,7 +61,7 @@ public interface IRecordsService
Task> GetYearsAsync(int departmentId);
/// Delta cursor for clients (plan section 5.3): projections modified after , oldest first, including tombstones (cancelled, voided, deleted).
- Task> GetChangesSinceAsync(int departmentId, DateTime? since, int take);
+ Task> GetChangesSinceAsync(int departmentId, DateTime? since, int take, string sinceId = null);
Task AddAttachmentAsync(int departmentId, string userId, string recordId, string fileName, string contentType, byte[] data, string description, CancellationToken cancellationToken = default);
diff --git a/Core/Resgrid.Model/WorkflowTemplateVariableCatalog.cs b/Core/Resgrid.Model/WorkflowTemplateVariableCatalog.cs
index 2b9c507c..ffc14a3a 100644
--- a/Core/Resgrid.Model/WorkflowTemplateVariableCatalog.cs
+++ b/Core/Resgrid.Model/WorkflowTemplateVariableCatalog.cs
@@ -159,6 +159,17 @@ private static List GetCommon() =>
new TemplateVariableDescriptor("submission.completed_on", "When the submission reached a final state (UTC)", "datetime", false),
};
+ // obligation.* rides only on trigger 112 (RMS-3): what the record is late for and by how long. Nothing about
+ // the record's content — a workflow that chases an overdue report never needs to read one.
+ private static readonly List ObligationVariables = new List
+ {
+ new TemplateVariableDescriptor("obligation.type", "What the record is late for (Review, Correction, Submission)", "string", false),
+ new TemplateVariableDescriptor("obligation.due_on", "When the obligation fell due (UTC)", "datetime", false),
+ new TemplateVariableDescriptor("obligation.overdue_hours", "Hours past due at evaluation time", "int", false),
+ new TemplateVariableDescriptor("obligation.responsible_user_id", "Who the obligation rests with", "string", false),
+ new TemplateVariableDescriptor("obligation.overdue_count", "How many times this obligation has gone overdue", "int", false),
+ };
+
// review.* rides only on the two review-path triggers: review bookkeeping, never record content.
private static readonly List ReviewVariables = new List
{
@@ -669,6 +680,13 @@ public static IReadOnlyList GetVariableCatalog(Workf
list.AddRange(RecordChangeVariables);
list.AddRange(SubmissionVariables);
break;
+
+ case WorkflowTriggerEventType.RecordOverdue:
+ list.AddRange(RecordEventVariables);
+ list.AddRange(RecordVariables);
+ list.Add(new TemplateVariableDescriptor("record.kind", "Record kind (Operational or IncidentReport)", "string", false));
+ list.AddRange(ObligationVariables);
+ break;
}
return list.AsReadOnly();
diff --git a/Core/Resgrid.Model/WorkflowTriggerEventType.cs b/Core/Resgrid.Model/WorkflowTriggerEventType.cs
index 27eb4d66..6ac02931 100644
--- a/Core/Resgrid.Model/WorkflowTriggerEventType.cs
+++ b/Core/Resgrid.Model/WorkflowTriggerEventType.cs
@@ -99,7 +99,14 @@ public enum WorkflowTriggerEventType
RecordSubmissionRejected = 110,
///