diff --git a/Core/Resgrid.Config/RecordsConnectorConfig.cs b/Core/Resgrid.Config/RecordsConnectorConfig.cs
index fef6e166..2c1997c9 100644
--- a/Core/Resgrid.Config/RecordsConnectorConfig.cs
+++ b/Core/Resgrid.Config/RecordsConnectorConfig.cs
@@ -5,7 +5,8 @@ namespace Resgrid.Config
/// switch is on and a credential passphrase is set: a connector holds an outbound credential encrypted under
/// the passphrase, so without one no connector can be created. Environment keys:
/// RESGRID:RecordsConnectorConfig:Enabled, :CredentialPassphrase, :TimeoutSeconds, :MaxFeedBytes,
- /// :MinPollIntervalMinutes, :DefaultMaxRequestsPerHour, :AllowHttp.
+ /// :MinPollIntervalMinutes, :DefaultMaxRequestsPerHour, :AllowHttp, :AllowedFeedHosts,
+ /// :AllowPrivateNetworkFeeds.
///
public static class RecordsConnectorConfig
{
@@ -28,6 +29,20 @@ public static class RecordsConnectorConfig
/// http feed roots are refused unless this is on (local development only).
public static bool AllowHttp = false;
+ ///
+ /// Hosts a connector may be pointed at, comma separated. A leading dot matches the domain and its
+ /// subdomains ("example.org, .ciffc.ca"). Empty allows any public host: the address checks below still
+ /// apply, so an empty list is not the same as no restriction.
+ ///
+ public static string AllowedFeedHosts = "";
+
+ ///
+ /// Whether a connector may address a loopback, link-local, private or otherwise internal address. Off in
+ /// every deployment: without it a department administrator can aim a connector at services the worker can
+ /// reach and read the answer back. On only for local development against a feed on the same machine.
+ ///
+ public static bool AllowPrivateNetworkFeeds = false;
+
/// Consecutive failures after which a connector is switched off until an administrator looks.
public static int DisableAfterConsecutiveFailures = 10;
diff --git a/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.ar.resx b/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.ar.resx
index c146dabc..8cd690bb 100644
--- a/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.ar.resx
+++ b/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.ar.resx
@@ -483,4 +483,10 @@
تعديل جهة الاتصال
+
+ أصبحت الخطط المسبقة لهذه الإدارة تُدار الآن كمبانٍ في السجلات. هذه الصفحة للقراءة فقط؛ عدّل المبنى من السجلات.
+
+
+ فتح المبنى
+
diff --git a/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.de.resx b/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.de.resx
index 916b1c8c..2db0a8ec 100644
--- a/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.de.resx
+++ b/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.de.resx
@@ -434,4 +434,10 @@
Edit Contact
+
+ Einsatzpläne dieser Organisation werden jetzt als Objekte in den Berichten gepflegt. Diese Seite ist schreibgeschützt; bearbeiten Sie das Objekt unter Berichte.
+
+
+ Objekt öffnen
+
diff --git a/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.el.resx b/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.el.resx
index 06d2a7dd..3bc6831c 100644
--- a/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.el.resx
+++ b/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.el.resx
@@ -504,4 +504,10 @@
Προαιρετική
+
+ Τα προσχέδια αυτής της υπηρεσίας διατηρούνται πλέον ως κτίρια στα Αρχεία. Η σελίδα είναι μόνο για ανάγνωση· επεξεργαστείτε το κτίριο στα Αρχεία.
+
+
+ Άνοιγμα κτιρίου
+
\ No newline at end of file
diff --git a/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.en.resx b/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.en.resx
index 275fe2dd..578104c4 100644
--- a/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.en.resx
+++ b/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.en.resx
@@ -504,4 +504,253 @@
Optional
-
\ No newline at end of file
+
+ Pre-Incident Plan
+
+
+ Pre-Plan
+
+
+ Site Files
+
+
+ Manage Files
+
+
+ Construction & Occupancy
+
+
+ Construction Type
+
+
+ Roof Type
+
+
+ Occupancy Type
+
+
+ Hours of Occupancy
+
+
+ e.g. Mon-Fri 08:00-17:00, staffed overnight
+
+
+ Occupant Load
+
+
+ Occupants Needing Assistance
+
+
+ Occupants on site may need evacuation assistance
+
+
+ Who, where and what assistance is needed
+
+
+ Occupancy Notes
+
+
+ Utility Shutoffs
+
+
+ Gas Shutoff
+
+
+ Electric Shutoff
+
+
+ Water Shutoff
+
+
+ Utility Notes
+
+
+ Water Supply
+
+
+ Nearest Hydrant
+
+
+ Required Fire Flow (GPM)
+
+
+ Water Supply Notes
+
+
+ Access
+
+
+ Knox Box Location
+
+
+ Gate Code
+
+
+ Stored encrypted. Shown to members who can view this contact and to responders on linked calls.
+
+
+ Alarm Panel Location
+
+
+ Alarm Company
+
+
+ Phone
+
+
+ Access Notes
+
+
+ On-Site Contacts
+
+
+ Emergency Contact
+
+
+ Secondary Contact
+
+
+ Hazards & Tactics
+
+
+ Hazmat On Site
+
+
+ Hazardous materials are stored or used on site
+
+
+ General Hazard Notes
+
+
+ Tactical Summary
+
+
+ Review Cycle
+
+
+ Last Reviewed
+
+
+ Never reviewed
+
+
+ Mark this pre-plan as reviewed now
+
+
+ Next Review Due
+
+
+ Save Pre-Plan
+
+
+ Premise Hazards
+
+
+ Typed hazards with a severity. Hazards marked as alerts are shown to dispatchers when this contact is added to a call.
+
+
+ Add Hazard
+
+
+ Edit Hazard
+
+
+ Save Hazard
+
+
+ Remove this hazard?
+
+
+ The hazard could not be saved.
+
+
+ A hazard needs a title.
+
+
+ Alert dispatchers when this contact is added to a call
+
+
+ Severity
+
+
+ Title
+
+
+ Location
+
+
+ Alert
+
+
+ No premise hazards recorded.
+
+
+ GPS Coordinates
+
+
+ The pre-plan review date has passed.
+
+
+ Pre-Plan Review Due
+
+
+ Pre-plans for this department are now maintained as Records occupancies. This page is read-only; edit the occupancy under Records.
+
+
+ Open occupancy
+
+
+ Create Pre-Plan
+
+
+ Edit Pre-Plan
+
+
+ No pre-incident plan has been recorded for this contact.
+
+
+ No files have been attached to this contact.
+
+
+ Upload File
+
+
+ Images, PDF, Office documents, text, CSV, DWG or DXF up to 30MB.
+
+
+ File Type
+
+
+ Title
+
+
+ Optional title (defaults to the file name)
+
+
+ File Name
+
+
+ Upload
+
+
+ Remove this file?
+
+
+ Download
+
+
+ Size
+
+
+ Added On
+
+
+ No
+
+
+ Calls
+
+
+ Notes
+
+
diff --git a/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.es.resx b/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.es.resx
index fed0f119..55cbff58 100644
--- a/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.es.resx
+++ b/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.es.resx
@@ -434,4 +434,10 @@
Editar contacto
+
+ Los planes previos de este departamento ahora se mantienen como ocupaciones en Registros. Esta página es de solo lectura; edite la ocupación en Registros.
+
+
+ Abrir ocupación
+
diff --git a/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.fr.resx b/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.fr.resx
index b47498b5..f1e30310 100644
--- a/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.fr.resx
+++ b/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.fr.resx
@@ -434,4 +434,10 @@
Edit Contact
+
+ Les plans d'intervention de ce service sont désormais gérés comme des occupations dans les Dossiers. Cette page est en lecture seule ; modifiez l'occupation dans les Dossiers.
+
+
+ Ouvrir l'occupation
+
diff --git a/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.it.resx b/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.it.resx
index ecb748ab..3cc366e7 100644
--- a/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.it.resx
+++ b/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.it.resx
@@ -434,4 +434,10 @@
Edit Contact
+
+ I piani preventivi di questo dipartimento sono ora gestiti come occupazioni nei Registri. Questa pagina è di sola lettura; modifica l'occupazione nei Registri.
+
+
+ Apri occupazione
+
diff --git a/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.pl.resx b/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.pl.resx
index 28018168..620ba685 100644
--- a/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.pl.resx
+++ b/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.pl.resx
@@ -434,4 +434,10 @@
Edit Contact
+
+ Plany operacyjne tej jednostki są teraz prowadzone jako obiekty w Rejestrach. Ta strona jest tylko do odczytu; edytuj obiekt w Rejestrach.
+
+
+ Otwórz obiekt
+
diff --git a/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.sv.resx b/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.sv.resx
index 91151d99..56c40671 100644
--- a/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.sv.resx
+++ b/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.sv.resx
@@ -434,4 +434,10 @@
Edit Contact
+
+ Insatsplaner för den här organisationen underhålls nu som objekt i Register. Sidan är skrivskyddad; redigera objektet under Register.
+
+
+ Öppna objekt
+
diff --git a/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.uk.resx b/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.uk.resx
index 7c2f346d..8683492f 100644
--- a/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.uk.resx
+++ b/Core/Resgrid.Localization/Areas/User/Contacts/Contacts.uk.resx
@@ -434,4 +434,10 @@
Edit Contact
+
+ Плани реагування цього підрозділу тепер ведуться як об'єкти в Записах. Ця сторінка лише для читання; редагуйте об'єкт у Записах.
+
+
+ Відкрити об'єкт
+
diff --git a/Core/Resgrid.Localization/Areas/User/Dispatch/Call.en.resx b/Core/Resgrid.Localization/Areas/User/Dispatch/Call.en.resx
index d37f729e..f634ef8d 100644
--- a/Core/Resgrid.Localization/Areas/User/Dispatch/Call.en.resx
+++ b/Core/Resgrid.Localization/Areas/User/Dispatch/Call.en.resx
@@ -751,4 +751,25 @@
Incident report
+
+ Site Info
+
+
+ No contacts with site information are linked to this call.
+
+
+ Premise Hazard
+
+
+ Premise Hazards
+
+
+ Alert Notes
+
+
+ No pre-incident plan has been recorded for this contact.
+
+
+ Site Files
+
diff --git a/Core/Resgrid.Localization/Areas/User/Records/Records.ar.resx b/Core/Resgrid.Localization/Areas/User/Records/Records.ar.resx
index c58f534f..fc08b209 100644
--- a/Core/Resgrid.Localization/Areas/User/Records/Records.ar.resx
+++ b/Core/Resgrid.Localization/Areas/User/Records/Records.ar.resx
@@ -1123,6 +1123,11 @@
تعيين الرقم
تسلسل لكل محطة
تسلسل لكل حادث
+ السجلات لكل نداء
+ عدة سجلات لكل نداء
+ سجل معتمد واحد لكل نداء
+ سجل واحد لكل موضوع لكل نداء
+ كم سجلاً من هذا التعريف يمكن أن يحمله النداء الواحد. يُطبَّق عند الإنشاء؛ والسجل المُلغى أو المتروك يحرّر مكانه.
إعادة تعيين سنويًا
التصنيف
الاحتفاظ (سنوات)
@@ -1418,4 +1423,414 @@
حالة المصدر متقدمة على التعيين المحلي
حالة المصدر متأخرة عن التعيين المحلي
يُدار بواسطة موصل
+ سجل الوصول
+ ملاحظات الوصول
+ إضافة دليل
+ إضافة خطر
+ إضافة عضو
+ إضافة ملاحظة
+ إضافة إحالة
+ إضافة مخالفة
+ الجهة
+ شركة الإنذار
+ لوحة الإنذار
+ جميع البرامج
+ التعديلات الموصى بها
+ مقدم الطلب
+ بريد مقدم الطلب
+ هاتف مقدم الطلب
+ تاريخ التقديم
+ تقديم الطلب
+ اعتماد النتائج
+ يجب أن يعتمد النتائج مراجع أو مسؤول غير كاتبها.
+ تمت إضافة المرفق.
+ اختر ملفًا لإرفاقه.
+ تمت إزالة المرفق.
+ الحضور
+ حالات رفض التفويض
+ متوسط الدرجة
+ حسب الكاتب
+ حسب المعيار
+ حسب التعريف
+ حسب الوحدة
+ إلغاء التفتيش
+ إلغاء هذا التفتيش؟ يبقى السجل في السجل التاريخي.
+ تم ربط المرشح.
+ تم رفض المرشح.
+ المرشحون
+ الوصول إلى هذه القضية مقصور على أعضائها وتُسجل كل قراءة.
+ تم إغلاق القضية.
+ أعضاء القضية
+ ملاحظات القضية
+ تم فتح القضية {0}.
+ أعيد فتح القضية.
+ تم حفظ القضية.
+ إصدار الفهرس
+ تصنيف السبب
+ تفاصيل السبب
+ قائمة التحقق
+ عنصر واحد في كل سطر: المفتاح | النص | إلزامي (y/n) | معرّف بند القانون.
+ بند التحقق
+ إغلاق القضية
+ إغلاق هذه القضية؟ تصبح الملاحظات للقراءة فقط.
+ إغلاق التفتيش
+ سبب الإغلاق
+ الإصدار
+ تم حفظ بند القانون.
+ نص البند
+ بنود القانون
+ تم حفظ مجموعة القوانين.
+ مجموعات القوانين
+ قوانين الحريق والبناء التي تفتش الإدارة وفقًا لها. تحمل البنود درجة خطورة ومهلة تصحيح افتراضيتين للمخالفات.
+ جُمع من
+ تاريخ الجمع
+ التعليقات
+ إكمال التفتيش
+ الشروط
+ قالب الشروط
+ معرّف جهة الاتصال
+ تم ربط جهة الاتصال.
+ تم فك ربط جهة الاتصال.
+ الإجراء التصحيحي
+ إنشاء مبنى جديد من هذا المصدر
+ المعايير
+ معيار واحد في كل سطر: المفتاح | النص | الوزن.
+ الدرجة (0-4)
+ الوزن
+ يعثر الجرد على الخطط المسبقة وجهات الاتصال ذات العناوين ونقاط الاهتمام، ويجمعها حسب العنوان والقرب، ويقترح المباني. احسم كل مرشح قبل نقل ملكية الكتابة إلى السجلات.
+ الحد من مخاطر المجتمع
+ تم حذف النشاط.
+ تم حفظ النشاط.
+ ملخص الفترة
+ الحافظ
+ سلسلة الحيازة
+ عمليات النقل تُضاف فقط؛ يذكر كل تسليم من سلّم ومن استلم والسبب والحالة الناتجة.
+ تم نقل الحيازة.
+ سبب القرار
+ أيام التصحيح
+ الخطورة الافتراضية
+ حذف النشاط
+ حذف هذا النشاط؟
+ حذف الصنبور
+ حذف هذا الصنبور؟ ستُحذف معه اختبارات التدفق وسجل الصيانة.
+ حذف المبنى
+ حذف هذا المبنى؟ تحتفظ عمليات التفتيش والتصاريح والمخاطر بسجلها لكنها تفقد العنصر الأصل.
+ موعد الاستحقاق
+ تعديل الصنبور
+ تعديل المبنى
+ تعديل التصريح
+ ساري من
+ قاطع الكهرباء
+ جهة اتصال الطوارئ
+ تمت إضافة الدليل.
+ الأدلة
+ رقم الدليل
+ تاريخ الانتهاء
+ اتركه فارغًا لاستخدام مدة صلاحية نوع التصريح من تاريخ الإصدار.
+ ينتهي قريبًا
+ تصدير الحزمة
+ غير مطابق
+ موقع وصلة الإطفاء
+ الرسوم
+ للإشارة فقط؛ تُسجل الفاتورة هنا ولا تُحصّل.
+ تاريخ سداد الرسوم
+ تم تسجيل الرسوم.
+ الملف
+ النتائج
+ تم اعتماد النتائج.
+ معتمدة
+ بانتظار الاعتماد، سُجلت
+ تم تسجيل النتائج وإرسالها للاعتماد.
+ أُعيدت النتائج إلى كاتبها.
+ إنذار الحريق
+ فئة التدفق
+ التدفق (غالون/دقيقة)
+ تحدّث اختبارات التدفق المسجلة هذه القيمة وفئة NFPA 291 تلقائيًا.
+ يُحسب التدفق كـ 29.83 × c × d² × √pitot ويُقرّب إلى 10 غالون/دقيقة؛ الفئة وفق NFPA 291.
+ تم تسجيل اختبار التدفق.
+ اختبارات التدفق
+ التكرار (بالأشهر)
+ من
+ قاطع الغاز
+ رمز البوابة
+ ملاحظات عامة عن المخاطر
+ إنشاء عمليات التفتيش المستحقة
+ تم إنشاء {0} عملية تفتيش.
+ تمت إزالة الخطر.
+ تم حفظ الخطر.
+ المخاطر
+ مواد خطرة في الموقع
+ الساعات
+ {0} صنبورًا، {1} خارج الخدمة، {2} يستحق اختبار تدفق.
+ تم حذف الصنبور.
+ الخريطة
+ يتبع اللون فئة التدفق NFPA 291؛ الأسود يعني خارج الخدمة.
+ رقم الصنبور
+ المالك
+ تم حفظ الصنبور.
+ صنابير الإطفاء
+ استيراد الصنابير
+ ملف CSV بصف عناوين: number, latitude, longitude, type, address, main_size, flow_gpm, owner. تُحدّث الأرقام الموجودة.
+ صفوف لم تُستورد
+ تمت قراءة {0} صفًا، أُنشئ {1}، حُدّث {2}، رُفض {3}.
+ استيراد البنود
+ ملف CSV بصف عناوين: section, title, text, severity (1-4), correction_days.
+ في الخدمة
+ تم ربط الحادث؛ المراجعة الحالية مثبتة.
+ ملخص الحادث
+ تم فك ربط الحادث.
+ تضمين المغلقة
+ تم إلغاء التفتيش.
+ تم إغلاق التفتيش.
+ اكتمل التفتيش؛ أنشأت البنود غير المطابقة مخالفات.
+ الملاحظات
+ رقم التفتيش
+ برامج التفتيش
+ يربط البرنامج قائمة تحقق بتكرار وأنواع المباني التي ينطبق عليها؛ وتُنشأ منه عمليات التفتيش المستحقة.
+ النتيجة
+ تمت جدولة التفتيش.
+ بدأ التفتيش.
+ عمليات التفتيش
+ المفتش
+ تاريخ الجرد
+ تم فحص {0} مصدرًا، أُنشئ {1} مرشحًا، حُدّث {2}، {3} محسومة مسبقًا.
+ التحقيقات
+ تُعرض فقط القضايا التي أنت عضو فيها. تُسجل كل قراءة لقضية في سجل الوصول.
+ مرجع الفاتورة
+ إصدار إشعار
+ تاريخ الإصدار
+ ملاحظة
+ الاختصاص
+ صندوق المفاتيح
+ آخر تفتيش
+ آخر صيانة
+ آخر مراجعة
+ آخر اختبار
+ المحقق الرئيسي
+ محاولات الكتابة في النظام القديم
+ ربط
+ ربط جهة اتصال
+ ربط حادث
+ جهات الاتصال المرتبطة
+ مرتبط
+ الحوادث المرتبطة
+ يثبّت الربط مراجعة الحادث في تلك اللحظة؛ لا تغيّر النتائج تقرير الحادث أبدًا.
+ قطر الأنبوب (بوصة)
+ سجل الصيانة
+ تم تسجيل الصيانة.
+ وضع علامة تمت المراجعة
+ درجة ثقة المطابقة
+ تمت إضافة العضو.
+ تمت إزالة العضو.
+ دمج هذا المبنى في المبنى الهدف؟ تنتقل المخاطر والروابط والسجل؛ ويصبح هذا السجل مؤشرًا.
+ دمج في
+ معرّف المبنى الهدف
+ أقرب صنبور
+ مجموعة قوانين جديدة
+ نشاط جديد
+ صنبور جديد
+ مبنى جديد
+ تصريح جديد
+ نوع تصريح جديد
+ برنامج جديد
+ معيار تقييم جديد
+ لا تنبيهات أو تحذيرات في هذه الفترة.
+ لا مرفقات.
+ لا مرشحين بانتظار القرار. شغّل الجرد للعثور على خطط مسبقة وجهات اتصال للمطابقة.
+ لا قضايا.
+ لا يحتوي هذا البرنامج على بنود تحقق.
+ لا أنشطة في هذه الفترة.
+ لا اختبارات تدفق مسجلة.
+ لا مخاطر مسجلة.
+ لا صنابير بعد.
+ لا عمليات تفتيش.
+ لا جهات اتصال مرتبطة.
+ لا صيانة مسجلة.
+ لا مبانٍ مطابقة.
+ لا مراجعات بانتظار التقييم.
+ لا تصاريح مطابقة.
+ لا دورات مراجعة مخططات بعد.
+ لا مراجعات مقيّمة في هذه الفترة.
+ لا معايير تقييم بعد. ينشئ مدير الإدارة المعيار الأول.
+ لا مخالفات.
+ غير منطبق
+ نص الملاحظة
+ تم حفظ الملاحظة.
+ الموضوع
+ تم إصدار الإشعار.
+ مرجع الإشعار
+ المباني
+ الوصول
+ {0} مبنى
+ تم حذف المبنى.
+ ساعات الإشغال
+ الهوية والموقع
+ تم دمج المبنى.
+ تم دمج هذا المبنى في
+ رقم المبنى
+ الحماية من الحريق والمرافق
+ تم وضع علامة تمت المراجعة على المبنى.
+ تم حفظ المبنى.
+ ابحث بالرقم أو الاسم أو العنوان
+ الهيكل
+ المخاطر والتكتيكات
+ نوع المبنى
+ ينطبق على أنواع المباني
+ أرقام الأنواع مفصولة بفواصل؛ الفراغ يعني كل الأنواع.
+ الحمل الإشغالي
+ شاغلون يحتاجون إلى مساعدة
+ فتح قضية
+ ستصبح المحقق الرئيسي. أضف الأعضاء بعد الفتح؛ الأعضاء فقط يمكنهم قراءة القضية.
+ المخالفات المفتوحة
+ تاريخ الفتح
+ وصف نقطة الاندلاع
+ خارج الخدمة
+ سبب الخروج من الخدمة
+ أحداث فاشلة
+ صندوق الأحداث الصادرة
+ الأقدم قيد الانتظار
+ أحداث قيد الانتظار
+ النتيجة
+ المخرج (بوصة)
+ اسم المالك
+ لا تزال الخطط المسبقة تُكتب ضمن جهات الاتصال. طابق جدول الربط لنقل ملكية الكتابة إلى المباني.
+ مباني السجلات تملك الخطط المسبقة. تقرأ صفحات جهات الاتصال والتطبيقات الإسقاطات من هنا.
+ تم نقل ملكية الكتابة إلى مباني السجلات.
+ رقم القطعة
+ مطابق
+ مراجعات للتقييم
+ تاريخ التنفيذ
+ الرمز
+ رقم التصريح
+ تم حفظ التصريح.
+ تم تحديث حالة التصريح.
+ نوع التصريح
+ تم حفظ نوع التصريح.
+ أنواع التصاريح
+ التصاريح
+ مراجعة مثبتة
+ بيتو (psi)
+ نتيجة المراجعة
+ تم تسجيل مراجعة المخططات.
+ مراجعة المخططات
+ معرّف نقطة الاهتمام
+ مطابقة الخطط المسبقة
+ ملكية كتابة الخطط المسبقة
+ انقضى موعد مراجعة هذا المبنى.
+ الوقاية
+ تم حفظ البرنامج.
+ المحتوى المحمي مخفي؛ اكشفه قبل هذا الإجراء.
+ حماية البيانات مفعّلة
+ مراجعة الجودة
+ يختار الاعتيان السجلات المكتملة بشكل حتمي لكل معيار؛ التقييم مرجّح ويغذي الاتجاهات.
+ التوصية بتعديل
+ يوصي بتعديل تقرير الحادث
+ لا تعدّل النتائج الحادث أبدًا. تُمرر التوصية عبر مسار تعديل السجل.
+ تسجيل الرسوم
+ تسجيل النتائج
+ تسجيل اختبار التدفق
+ تسجيل الصيانة
+ تسجيل مراجعة المخططات
+ سجّله
+ السجلات المنشأة
+ السجلات المكتملة
+ صحة الإصدار
+ قياسات أساسية لتفعيل السجلات: محاولات الكتابة في النظام القديم، تأخر صندوق الصادر، تشغيلات Workflow، الفحوص وعدادات الوقاية. يتحول كل مصدر إلى تحذير بدلاً من إفشال الصفحة.
+ السجلات مفعّلة
+ سجلات متأخرة عن المراجعة
+ الرقم المرجعي
+ تمت إضافة الإحالة.
+ تم تحديث الإحالة.
+ الإحالات
+ إعادة تفتيش لـ
+ رفض
+ إزالة هذا المرفق؟
+ إعادة فتح القضية
+ التدفق المطلوب (غالون/دقيقة)
+ يتطلب مراجعة المخططات
+ المتبقي (psi)
+ الحالة الناتجة
+ إعادة إلى الكاتب
+ أُعيد إلى الخدمة
+ المراجعات
+ الدورة
+ ملاحظة المراجع
+ ملاحظات المراجعة
+ مراجعة متأخرة
+ تم تقييم المراجعة.
+ تاريخ المراجعة
+ نوع السقف
+ تم حفظ معيار التقييم.
+ معايير التقييم
+ تشغيل الجرد
+ اعتيان
+ مكتملة
+ فاشلة
+ قيد التشغيل
+ متخطاة
+ تم اعتيان {0} سجلًا للمراجعة.
+ حجم العينة
+ عدد السجلات لكل عملية اعتيان؛ الاختيار حتمي للمعيار والفترة.
+ المعتانة
+ تاريخ الاعتيان
+ مرفقات بانتظار الفحص
+ مرفقات رفضها الفحص
+ الفحص
+ جدولة تفتيش
+ جدولة إعادة تفتيش
+ مجدولة
+ قيّم كل معيار من 0 إلى 4؛ يتحول المجموع المرجّح إلى نسبة مئوية.
+ تقييم المراجعة
+ المقيّمة
+ تاريخ التقييم
+ البند
+ تم استيراد {0} بندًا.
+ إعادة إلى الخدمة
+ إخراج من الخدمة
+ تنبيه الأطقم
+ اسم الموقّع
+ الاسم المكتوب للشخص الذي يشهد على التفتيش
+ كاشفات الدخان المركّبة
+ المرشات
+ قدم مربع
+ الطاقم
+ معرّفات المستخدمين مفصولة بفواصل للأعضاء المشاركين.
+ أنبوب قائم
+ بدء التفتيش
+ بدأت
+ الساكن (psi)
+ موقع التخزين
+ الطوابق
+ إرسالات قيد الانتظار
+ إرسالات فاشلة
+ تاريخ التقديم
+ المبنى المقترح
+ التبديل محظور حتى يُشغّل الجرد ويُحسم كل مرشح ولا تبقى خطة مسبقة غير مطابقة.
+ نقل ملكية الكتابة إلى السجلات
+ أفهم أن صفحات الخطط المسبقة في جهات الاتصال والتطبيقات ستصبح إسقاطات للقراءة فقط من المباني.
+ نقل ملكية الكتابة الآن؟ يتوقف تحرير الخطط المسبقة في جهات الاتصال فورًا.
+ بعد التبديل، تُحرر الخطط المسبقة كمبانٍ فقط. تستمر جهات الاتصال والتطبيقات في العمل من الإسقاطات؛ التراجع هو استعادة لقاعدة البيانات وليس مفتاحًا.
+ تاريخ التبديل
+ ملخص تكتيكي
+ النافذة الزمنية
+ اختبار مستحق
+ تاريخ الاختبار
+ نقل الحيازة
+ إلى
+ إلى جهة خارجية
+ تاريخ النقل
+ تغيير الحالة
+ الاتجاهات
+ منذ
+ فك الربط
+ خطط مسبقة غير مطابقة
+ تاريخ الرفع
+ ملاحظات المرافق
+ الصلاحية (أيام)
+ تم حفظ المخالفة.
+ تم تحديث المخالفة.
+ المخالفات
+ قاطع الماء
+ ملاحظات إمداد المياه
+ تشغيلات Workflow
diff --git a/Core/Resgrid.Localization/Areas/User/Records/Records.de.resx b/Core/Resgrid.Localization/Areas/User/Records/Records.de.resx
index 2083ab89..8c69e9f7 100644
--- a/Core/Resgrid.Localization/Areas/User/Records/Records.de.resx
+++ b/Core/Resgrid.Localization/Areas/User/Records/Records.de.resx
@@ -1123,6 +1123,11 @@
Nummer vergeben
Sequenz pro Wache
Sequenz pro Einsatz
+ Datensätze pro Einsatz
+ Mehrere pro Einsatz
+ Ein maßgeblicher pro Einsatz
+ Einer je Subjekt pro Einsatz
+ Wie viele Datensätze dieser Definition ein Einsatz haben darf. Beim Anlegen erzwungen; ein für ungültig erklärter oder abgebrochener Datensatz gibt seinen Platz frei.
Jährlich zurücksetzen
Klassifizierung
Aufbewahrung (Jahre)
@@ -1418,4 +1423,414 @@
Quellstatus ist der lokalen Besetzung voraus
Quellstatus liegt hinter der lokalen Besetzung
Von einem Konnektor gepflegt
+ Zugriffsprotokoll
+ Zugangshinweise
+ Beweismittel hinzufügen
+ Gefahr hinzufügen
+ Mitglied hinzufügen
+ Notiz hinzufügen
+ Weiterleitung hinzufügen
+ Verstoß hinzufügen
+ Behörde
+ Alarmfirma
+ Alarmzentrale
+ Alle Programme
+ Empfohlene Änderungen
+ Antragsteller
+ E-Mail des Antragstellers
+ Telefon des Antragstellers
+ Beantragt am
+ Antrag einreichen
+ Ergebnisse genehmigen
+ Ergebnisse müssen von einem Prüfer oder Leiter genehmigt werden, der nicht der Verfasser ist.
+ Anhang hinzugefügt.
+ Wählen Sie eine Datei zum Anhängen.
+ Anhang entfernt.
+ Teilnehmer
+ Abgelehnte Zugriffe
+ Durchschnittliche Punktzahl
+ Nach Verfasser
+ Nach Kriterium
+ Nach Definition
+ Nach Einheit
+ Prüfung abbrechen
+ Diese Prüfung abbrechen? Der Eintrag bleibt in der Historie.
+ Kandidat verknüpft.
+ Kandidat abgelehnt.
+ Kandidaten
+ Der Zugriff auf diesen Fall ist auf seine Mitglieder beschränkt; jeder Lesezugriff wird protokolliert.
+ Fall geschlossen.
+ Fallmitglieder
+ Fallnotizen
+ Fall {0} eröffnet.
+ Fall wieder eröffnet.
+ Fall gespeichert.
+ Katalogversion
+ Ursachenklassifikation
+ Ursachendetail
+ Checkliste
+ Ein Punkt pro Zeile: Schlüssel | Text | Pflicht (y/n) | ID des Vorschriftenabschnitts.
+ Prüfpunkt
+ Fall schließen
+ Diesen Fall schließen? Notizen werden schreibgeschützt.
+ Prüfung abschließen
+ Grund der Schließung
+ Ausgabe
+ Vorschriftenabschnitt gespeichert.
+ Abschnittstext
+ Vorschriftenabschnitte
+ Vorschriftensatz gespeichert.
+ Vorschriftensätze
+ Brandschutz- und Bauvorschriften, gegen die die Organisation prüft. Abschnitte tragen Standard-Schweregrad und Behebungsfrist für Verstöße.
+ Sichergestellt bei
+ Sichergestellt am
+ Kommentare
+ Prüfung abschließen und bewerten
+ Auflagen
+ Auflagenvorlage
+ Kontakt-ID
+ Kontakt verknüpft.
+ Kontaktverknüpfung entfernt.
+ Korrekturmaßnahme
+ Neues Objekt aus dieser Quelle anlegen
+ Kriterien
+ Ein Kriterium pro Zeile: Schlüssel | Text | Gewichtung.
+ Punkte (0-4)
+ Gewichtung
+ Die Bestandsaufnahme findet Einsatzpläne, Kontakte mit Adresse und POIs, gruppiert sie nach Adresse und Nähe und schlägt Objekte vor. Entscheiden Sie jeden Kandidaten, bevor Sie die Schreibhoheit an die Berichte übergeben.
+ Risikominderung in der Gemeinde
+ Aktivität gelöscht.
+ Aktivität gespeichert.
+ Zusammenfassung des Zeitraums
+ Verwahrer
+ Verwahrungskette
+ Übergaben sind nur anfügbar; jede Übergabe nennt Abgebenden, Empfänger, Grund und den resultierenden Zustand.
+ Verwahrung übergeben.
+ Entscheidungsgrund
+ Behebungsfrist (Tage)
+ Standard-Schweregrad
+ Aktivität löschen
+ Diese Aktivität löschen?
+ Hydrant löschen
+ Diesen Hydranten löschen? Durchflusstests und Wartungshistorie gehen mit.
+ Objekt löschen
+ Dieses Objekt löschen? Prüfungen, Genehmigungen und Gefahren behalten ihre Historie, verlieren aber das übergeordnete Objekt.
+ Fällig am
+ Hydrant bearbeiten
+ Objekt bearbeiten
+ Genehmigung bearbeiten
+ Gültig ab
+ Stromabschaltung
+ Notfallkontakt
+ Beweismittel hinzugefügt.
+ Beweismittel
+ Beweismittel-Nr.
+ Läuft ab am
+ Leer lassen, um die Gültigkeit des Genehmigungstyps ab Ausstellung zu verwenden.
+ Läuft bald ab
+ Fallpaket exportieren
+ Nicht bestanden
+ Standort Einspeisung (FDC)
+ Gebühr
+ Nur Referenz; die Rechnung wird hier erfasst, nicht eingezogen.
+ Gebühr bezahlt am
+ Gebühr erfasst.
+ Datei
+ Ergebnisse
+ Ergebnisse genehmigt.
+ Genehmigt
+ Warten auf Genehmigung, erfasst
+ Ergebnisse erfasst und zur Genehmigung gesendet.
+ Ergebnisse an den Verfasser zurückgegeben.
+ Brandmeldeanlage
+ Durchflussklasse
+ Durchfluss (gpm)
+ Erfasste Durchflusstests aktualisieren diesen Wert und die NFPA-291-Klasse automatisch.
+ Der Durchfluss wird als 29,83 × c × d² × √Pitot berechnet und auf 10 gpm gerundet; die Klasse folgt NFPA 291.
+ Durchflusstest erfasst.
+ Durchflusstests
+ Intervall (Monate)
+ Von
+ Gasabsperrung
+ Torcode
+ Allgemeine Gefahrenhinweise
+ Fällige Prüfungen erzeugen
+ {0} Prüfungen erzeugt.
+ Gefahr entfernt.
+ Gefahr gespeichert.
+ Gefahren
+ Gefahrstoffe vor Ort
+ Stunden
+ {0} Hydranten, {1} außer Betrieb, {2} mit fälligem Durchflusstest.
+ Hydrant gelöscht.
+ Karte
+ Die Farbe folgt der NFPA-291-Durchflussklasse; Schwarz bedeutet außer Betrieb.
+ Hydrant-Nr.
+ Eigentümer
+ Hydrant gespeichert.
+ Hydranten
+ Hydranten importieren
+ CSV mit Kopfzeile: number, latitude, longitude, type, address, main_size, flow_gpm, owner. Vorhandene Nummern werden aktualisiert.
+ Nicht importierte Zeilen
+ {0} Zeilen gelesen, {1} angelegt, {2} aktualisiert, {3} abgelehnt.
+ Abschnitte importieren
+ CSV mit Kopfzeile: section, title, text, severity (1-4), correction_days.
+ In Betrieb
+ Einsatz verknüpft; die aktuelle Revision ist fixiert.
+ Einsatzzusammenfassung
+ Einsatzverknüpfung entfernt.
+ Geschlossene einbeziehen
+ Prüfung abgebrochen.
+ Prüfung abgeschlossen.
+ Prüfung abgeschlossen; nicht bestandene Punkte wurden zu Verstößen.
+ Notizen
+ Prüfungs-Nr.
+ Prüfprogramme
+ Ein Programm verbindet eine Checkliste mit einem Intervall und den Objektarten, für die es gilt; fällige Prüfungen werden daraus erzeugt.
+ Ergebnis
+ Prüfung geplant.
+ Prüfung begonnen.
+ Prüfungen
+ Prüfer
+ Bestandsaufnahme am
+ {0} Quellen geprüft, {1} Kandidaten angelegt, {2} aktualisiert, {3} bereits entschieden.
+ Ermittlungen
+ Es werden nur Fälle angezeigt, in denen Sie Mitglied sind. Jeder Lesezugriff auf einen Fall wird protokolliert.
+ Rechnungsreferenz
+ Bescheid ausstellen
+ Ausgestellt am
+ Notiz
+ Zuständigkeitsbereich
+ Schlüsseldepot
+ Zuletzt geprüft
+ Zuletzt gewartet
+ Zuletzt überprüft
+ Zuletzt getestet
+ Leitender Ermittler
+ Schreibversuche auf Altsystem
+ Verknüpfen
+ Kontakt verknüpfen
+ Einsatz verknüpfen
+ Verknüpfte Kontakte
+ Verknüpft
+ Verknüpfte Einsätze
+ Die Verknüpfung fixiert die Einsatzrevision zu diesem Zeitpunkt; Ergebnisse ändern den Einsatzbericht nie.
+ Leitungsdurchmesser (Zoll)
+ Wartungsprotokoll
+ Wartung erfasst.
+ Als überprüft markieren
+ Übereinstimmung
+ Mitglied hinzugefügt.
+ Mitglied entfernt.
+ Dieses Objekt in das Ziel zusammenführen? Gefahren, Verknüpfungen und Historie werden übertragen; dieser Eintrag wird zum Verweis.
+ Zusammenführen in
+ ID des Zielobjekts
+ Nächster Hydrant
+ Neuer Vorschriftensatz
+ Neue Aktivität
+ Neuer Hydrant
+ Neues Objekt
+ Neue Genehmigung
+ Neuer Genehmigungstyp
+ Neues Programm
+ Neue Bewertungsvorlage
+ Keine Alarme oder Warnungen in diesem Zeitfenster.
+ Keine Anhänge.
+ Keine wartenden Kandidaten. Starten Sie die Bestandsaufnahme, um Einsatzpläne und Kontakte zum Abgleich zu finden.
+ Keine Fälle.
+ Dieses Programm hat keine Prüfpunkte.
+ Keine Aktivitäten in diesem Zeitraum.
+ Keine Durchflusstests erfasst.
+ Keine Gefahren erfasst.
+ Noch keine Hydranten.
+ Keine Prüfungen.
+ Keine verknüpften Kontakte.
+ Keine Wartung erfasst.
+ Keine passenden Objekte.
+ Keine Bewertungen ausstehend.
+ Keine passenden Genehmigungen.
+ Noch keine Planprüfungszyklen.
+ Keine bewerteten Prüfungen in diesem Zeitraum.
+ Noch keine Bewertungsvorlagen. Ein Administrator der Organisation legt die erste an.
+ Keine Verstöße.
+ k. A.
+ Notiztext
+ Notiz gespeichert.
+ Betreff
+ Bescheid ausgestellt.
+ Bescheid-Referenz
+ Objekte
+ Zugang
+ {0} Objekte
+ Objekt gelöscht.
+ Nutzungszeiten
+ Identität und Lage
+ Objekt zusammengeführt.
+ Dieses Objekt wurde zusammengeführt in
+ Objekt-Nr.
+ Brandschutz und Versorgung
+ Objekt als überprüft markiert.
+ Objekt gespeichert.
+ Nummer, Name oder Adresse suchen
+ Gebäude
+ Gefahren und Taktik
+ Nutzungsart
+ Gilt für Nutzungsarten
+ Typnummern durch Komma getrennt; leer bedeutet alle Typen.
+ Personenzahl
+ Hilfsbedürftige Personen
+ Fall eröffnen
+ Sie werden leitender Ermittler. Fügen Sie nach dem Eröffnen Mitglieder hinzu; nur Mitglieder können den Fall lesen.
+ Offene Verstöße
+ Eröffnet am
+ Beschreibung des Brandursprungs
+ Außer Betrieb
+ Grund der Außerbetriebnahme
+ Fehlgeschlagene Ereignisse
+ Ereignis-Postausgang
+ Ältestes ausstehendes
+ Ausstehende Ereignisse
+ Ergebnis
+ Auslass (Zoll)
+ Name des Eigentümers
+ Einsatzpläne werden weiterhin unter Kontakte gepflegt. Gleichen Sie den Abgleich ab, um die Schreibhoheit auf Objekte umzustellen.
+ Objekte in den Berichten besitzen die Einsatzpläne. Kontaktseiten und Apps lesen Projektionen von hier.
+ Schreibhoheit auf Objekte in den Berichten umgestellt.
+ Flurstücknummer
+ Bestanden
+ Zu bewertende Prüfungen
+ Durchgeführt am
+ Kürzel
+ Genehmigungs-Nr.
+ Genehmigung gespeichert.
+ Genehmigungsstatus aktualisiert.
+ Genehmigungstyp
+ Genehmigungstyp gespeichert.
+ Genehmigungstypen
+ Genehmigungen
+ fixierte Revision
+ Pitot (psi)
+ Ergebnis der Prüfung
+ Planprüfung erfasst.
+ Planprüfung
+ POI-ID
+ Einsatzplan-Abgleich
+ Schreibhoheit für Einsatzpläne
+ Das Überprüfungsdatum dieses Objekts ist überschritten.
+ Prävention
+ Programm gespeichert.
+ Geschützte Inhalte sind verborgen; machen Sie sie vor dieser Aktion sichtbar.
+ Datenschutz erzwungen
+ Qualitätsprüfung
+ Die Stichprobe wählt abgeschlossene Berichte je Vorlage deterministisch aus; die Bewertung ist gewichtet und fließt in die Trends ein.
+ Änderung empfehlen
+ Empfiehlt Änderung des Einsatzberichts
+ Ergebnisse ändern den Einsatz nie. Die Empfehlung läuft über den Änderungsprozess des Berichts.
+ Gebühr erfassen
+ Ergebnisse erfassen
+ Durchflusstest erfassen
+ Wartung erfassen
+ Planprüfung erfassen
+ Erfasst von
+ Angelegte Berichte
+ Abgeschlossene Berichte
+ Betriebszustand
+ Basistelemetrie für die Aktivierung der Berichte: Schreibversuche auf das Altsystem, Postausgangsverzögerung, Workflow-Läufe, Scans und Präventionszähler. Jede Quelle fällt auf eine Warnung zurück, statt die Seite scheitern zu lassen.
+ Berichte aktiviert
+ Überfällige Prüfungen
+ Referenznummer
+ Weiterleitung hinzugefügt.
+ Weiterleitung aktualisiert.
+ Weiterleitungen
+ Nachprüfung von
+ Ablehnen
+ Diesen Anhang entfernen?
+ Fall wieder eröffnen
+ Erforderlicher Löschwasserbedarf (gpm)
+ Erfordert Planprüfung
+ Restdruck (psi)
+ Resultierender Zustand
+ An Verfasser zurückgeben
+ Wieder in Betrieb
+ Bewertungen
+ Zyklus
+ Anmerkung des Prüfers
+ Prüfnotizen
+ Überprüfung überfällig
+ Bewertung gespeichert.
+ Geprüft am
+ Dachart
+ Bewertungsvorlage gespeichert.
+ Bewertungsvorlagen
+ Bestandsaufnahme starten
+ Stichprobe
+ Abgeschlossen
+ Fehlgeschlagen
+ Laufend
+ Übersprungen
+ {0} Berichte für die Bewertung ausgewählt.
+ Stichprobengröße
+ Berichte je Stichprobenlauf; die Auswahl ist je Vorlage und Zeitraum deterministisch.
+ Ausgewählt
+ Ausgewählt am
+ Anhänge mit ausstehendem Scan
+ Vom Scan abgelehnte Anhänge
+ Scan
+ Prüfung planen
+ Nachprüfung planen
+ Geplant
+ Bewerten Sie jedes Kriterium mit 0-4; die gewichtete Summe ergibt einen Prozentwert.
+ Bewertung vornehmen
+ Bewertet
+ Bewertet am
+ Abschnitt
+ {0} Abschnitte importiert.
+ Wieder in Betrieb nehmen
+ Außer Betrieb nehmen
+ Einsatzkräfte warnen
+ Name der Unterschrift
+ Eingegebener Name der Person, die die Prüfung bestätigt
+ Installierte Rauchmelder
+ Sprinkleranlage
+ Quadratfuß
+ Mitarbeitende
+ Durch Komma getrennte Benutzer-IDs der beteiligten Mitglieder.
+ Steigleitung
+ Prüfung beginnen
+ Begonnen
+ Statisch (psi)
+ Aufbewahrungsort
+ Stockwerke
+ Ausstehende Übermittlungen
+ Fehlgeschlagene Übermittlungen
+ Eingereicht am
+ Vorgeschlagenes Objekt
+ Die Umstellung ist blockiert, bis die Bestandsaufnahme gelaufen ist, jeder Kandidat entschieden wurde und kein Einsatzplan mehr unabgeglichen ist.
+ Schreibhoheit an Berichte übergeben
+ Ich verstehe, dass Einsatzplanseiten in Kontakte und die Apps zu schreibgeschützten Projektionen der Objekte werden.
+ Schreibhoheit jetzt umstellen? Die Bearbeitung von Einsatzplänen in Kontakte endet sofort.
+ Nach der Umstellung werden Einsatzpläne nur noch als Objekte bearbeitet. Kontakte und Apps arbeiten weiter mit Projektionen; ein Rollback ist eine Datenbankwiederherstellung, kein Schalter.
+ Umgestellt am
+ Taktische Zusammenfassung
+ Zeitfenster
+ Test fällig
+ Getestet am
+ Verwahrung übergeben
+ An
+ An externe Stelle
+ Übergeben am
+ Status ändern
+ Trends
+ Seit
+ Verknüpfung lösen
+ Unabgeglichene Einsatzpläne
+ Hochgeladen
+ Versorgungshinweise
+ Gültigkeit (Tage)
+ Verstoß gespeichert.
+ Verstoß aktualisiert.
+ Verstöße
+ Wasserabsperrung
+ Hinweise zur Löschwasserversorgung
+ Workflow-Läufe
diff --git a/Core/Resgrid.Localization/Areas/User/Records/Records.el.resx b/Core/Resgrid.Localization/Areas/User/Records/Records.el.resx
index ff416765..686aca8c 100644
--- a/Core/Resgrid.Localization/Areas/User/Records/Records.el.resx
+++ b/Core/Resgrid.Localization/Areas/User/Records/Records.el.resx
@@ -1123,6 +1123,11 @@
Ανάθεση αριθμού
Ακολουθία ανά σταθμό
Ακολουθία ανά συμβάν
+ Εγγραφές ανά κλήση
+ Πολλές ανά κλήση
+ Μία έγκυρη ανά κλήση
+ Μία ανά υποκείμενο ανά κλήση
+ Πόσες εγγραφές αυτού του ορισμού μπορεί να έχει μία κλήση. Επιβάλλεται κατά τη δημιουργία· μια ακυρωμένη ή εγκαταλελειμμένη εγγραφή απελευθερώνει τη θέση της.
Επαναφορά ετησίως
Ταξινόμηση
Διατήρηση (έτη)
@@ -1418,4 +1423,414 @@
Η κατάσταση της πηγής προηγείται της τοπικής κάλυψης
Η κατάσταση της πηγής υστερεί της τοπικής κάλυψης
Συντηρείται από σύνδεσμο
+ Έλεγχος πρόσβασης
+ Σημειώσεις πρόσβασης
+ Προσθήκη τεκμηρίου
+ Προσθήκη κινδύνου
+ Προσθήκη μέλους
+ Προσθήκη σημείωσης
+ Προσθήκη παραπομπής
+ Προσθήκη παράβασης
+ Υπηρεσία
+ Εταιρεία συναγερμού
+ Πίνακας συναγερμού
+ Όλα τα προγράμματα
+ Συνιστώμενες τροποποιήσεις
+ Αιτών
+ E-mail αιτούντος
+ Τηλέφωνο αιτούντος
+ Υποβλήθηκε
+ Υποβολή αίτησης
+ Έγκριση πορισμάτων
+ Τα πορίσματα πρέπει να εγκριθούν από ελεγκτή ή επικεφαλής διαφορετικό από τον συντάκτη τους.
+ Το συνημμένο προστέθηκε.
+ Επιλέξτε αρχείο για επισύναψη.
+ Το συνημμένο αφαιρέθηκε.
+ Κοινό
+ Απορρίψεις εξουσιοδότησης
+ Μέση βαθμολογία
+ Ανά συντάκτη
+ Ανά κριτήριο
+ Ανά ορισμό
+ Ανά μονάδα
+ Ακύρωση επιθεώρησης
+ Ακύρωση αυτής της επιθεώρησης; Η εγγραφή παραμένει στο ιστορικό.
+ Ο υποψήφιος συνδέθηκε.
+ Ο υποψήφιος απορρίφθηκε.
+ Υποψήφιοι
+ Η πρόσβαση στην υπόθεση περιορίζεται στα μέλη της και κάθε ανάγνωση καταγράφεται.
+ Η υπόθεση έκλεισε.
+ Μέλη υπόθεσης
+ Σημειώσεις υπόθεσης
+ Η υπόθεση {0} άνοιξε.
+ Η υπόθεση άνοιξε ξανά.
+ Η υπόθεση αποθηκεύτηκε.
+ Έκδοση καταλόγου
+ Ταξινόμηση αιτίας
+ Λεπτομέρεια αιτίας
+ Λίστα ελέγχου
+ Ένα στοιχείο ανά γραμμή: κλειδί | κείμενο | υποχρεωτικό (y/n) | id ενότητας κώδικα.
+ Στοιχείο ελέγχου
+ Κλείσιμο υπόθεσης
+ Κλείσιμο της υπόθεσης; Οι σημειώσεις γίνονται μόνο για ανάγνωση.
+ Κλείσιμο επιθεώρησης
+ Λόγος κλεισίματος
+ Έκδοση
+ Η ενότητα κώδικα αποθηκεύτηκε.
+ Κείμενο ενότητας
+ Ενότητες κώδικα
+ Το σύνολο κωδίκων αποθηκεύτηκε.
+ Σύνολα κωδίκων
+ Κώδικες πυρασφάλειας και δόμησης βάσει των οποίων επιθεωρεί η υπηρεσία. Οι ενότητες φέρουν προεπιλεγμένη σοβαρότητα και προθεσμία διόρθωσης.
+ Συλλέχθηκε από
+ Συλλέχθηκε στις
+ Σχόλια
+ Ολοκλήρωση επιθεώρησης
+ Όροι
+ Πρότυπο όρων
+ ID επαφής
+ Η επαφή συνδέθηκε.
+ Η επαφή αποσυνδέθηκε.
+ Διορθωτική ενέργεια
+ Δημιουργία νέου κτιρίου από αυτή την πηγή
+ Κριτήρια
+ Ένα κριτήριο ανά γραμμή: κλειδί | κείμενο | βάρος.
+ Βαθμός (0-4)
+ Βάρος
+ Η απογραφή εντοπίζει προσχέδια, επαφές με διεύθυνση και σημεία ενδιαφέροντος, τα ομαδοποιεί κατά διεύθυνση και εγγύτητα και προτείνει κτίρια. Αποφασίστε για κάθε υποψήφιο πριν μεταφέρετε την κυριότητα εγγραφής στα Αρχεία.
+ Μείωση κοινοτικού κινδύνου
+ Η δραστηριότητα διαγράφηκε.
+ Η δραστηριότητα αποθηκεύτηκε.
+ Σύνοψη περιόδου
+ Θεματοφύλακας
+ Αλυσίδα φύλαξης
+ Οι μεταβιβάσεις μόνο προστίθενται· κάθε παράδοση αναφέρει ποιος έδωσε, ποιος παρέλαβε, γιατί και την τελική κατάσταση.
+ Η φύλαξη μεταβιβάστηκε.
+ Αιτιολογία απόφασης
+ Ημέρες διόρθωσης
+ Προεπιλεγμένη σοβαρότητα
+ Διαγραφή δραστηριότητας
+ Διαγραφή αυτής της δραστηριότητας;
+ Διαγραφή κρουνού
+ Διαγραφή του κρουνού; Οι δοκιμές ροής και το ιστορικό συντήρησης χάνονται.
+ Διαγραφή κτιρίου
+ Διαγραφή του κτιρίου; Επιθεωρήσεις, άδειες και κίνδυνοι κρατούν το ιστορικό αλλά χάνουν τον γονέα.
+ Προθεσμία
+ Επεξεργασία κρουνού
+ Επεξεργασία κτιρίου
+ Επεξεργασία άδειας
+ Ισχύει από
+ Διακοπή ρεύματος
+ Επαφή έκτακτης ανάγκης
+ Το τεκμήριο προστέθηκε.
+ Τεκμήρια
+ Αρ. τεκμηρίου
+ Λήγει στις
+ Αφήστε κενό για να ισχύσει η διάρκεια του τύπου άδειας από την έκδοση.
+ Λήγει σύντομα
+ Εξαγωγή φακέλου
+ Απέτυχε
+ Θέση σύνδεσης πυροσβεστικής
+ Τέλος
+ Μόνο για αναφορά· η τιμολόγηση καταγράφεται εδώ, δεν εισπράττεται.
+ Τέλος πληρώθηκε στις
+ Το τέλος καταχωρήθηκε.
+ Αρχείο
+ Πορίσματα
+ Τα πορίσματα εγκρίθηκαν.
+ Εγκρίθηκαν
+ Αναμονή έγκρισης, καταχωρήθηκαν
+ Τα πορίσματα καταχωρήθηκαν και στάλθηκαν για έγκριση.
+ Τα πορίσματα επιστράφηκαν στον συντάκτη.
+ Συναγερμός πυρκαγιάς
+ Κλάση ροής
+ Ροή (gpm)
+ Οι καταχωρημένες δοκιμές ροής ενημερώνουν αυτόματα την τιμή και την κλάση NFPA 291.
+ Η ροή υπολογίζεται ως 29,83 × c × d² × √pitot και στρογγυλοποιείται στα 10 gpm· η κλάση ακολουθεί το NFPA 291.
+ Η δοκιμή ροής καταχωρήθηκε.
+ Δοκιμές ροής
+ Συχνότητα (μήνες)
+ Από
+ Διακοπή αερίου
+ Κωδικός πύλης
+ Γενικές σημειώσεις κινδύνων
+ Δημιουργία οφειλόμενων επιθεωρήσεων
+ Δημιουργήθηκαν {0} επιθεωρήσεις.
+ Ο κίνδυνος αφαιρέθηκε.
+ Ο κίνδυνος αποθηκεύτηκε.
+ Κίνδυνοι
+ Επικίνδυνα υλικά στον χώρο
+ Ώρες
+ {0} κρουνοί, {1} εκτός λειτουργίας, {2} με οφειλόμενη δοκιμή ροής.
+ Ο κρουνός διαγράφηκε.
+ Χάρτης
+ Το χρώμα ακολουθεί την κλάση ροής NFPA 291· το μαύρο σημαίνει εκτός λειτουργίας.
+ Αρ. κρουνού
+ Ιδιοκτήτης
+ Ο κρουνός αποθηκεύτηκε.
+ Πυροσβεστικοί κρουνοί
+ Εισαγωγή κρουνών
+ CSV με γραμμή κεφαλίδας: number, latitude, longitude, type, address, main_size, flow_gpm, owner. Οι υπάρχοντες αριθμοί ενημερώνονται.
+ Γραμμές που δεν εισήχθησαν
+ {0} γραμμές διαβάστηκαν, {1} δημιουργήθηκαν, {2} ενημερώθηκαν, {3} απορρίφθηκαν.
+ Εισαγωγή ενοτήτων
+ CSV με γραμμή κεφαλίδας: section, title, text, severity (1-4), correction_days.
+ Σε λειτουργία
+ Το συμβάν συνδέθηκε· η τρέχουσα αναθεώρηση καρφιτσώθηκε.
+ Σύνοψη συμβάντος
+ Το συμβάν αποσυνδέθηκε.
+ Συμπερίληψη κλειστών
+ Η επιθεώρηση ακυρώθηκε.
+ Η επιθεώρηση έκλεισε.
+ Η επιθεώρηση ολοκληρώθηκε· τα αποτυχημένα στοιχεία δημιούργησαν παραβάσεις.
+ Σημειώσεις
+ Αρ. επιθεώρησης
+ Προγράμματα επιθεώρησης
+ Ένα πρόγραμμα συνδυάζει λίστα ελέγχου με συχνότητα και τους τύπους κτιρίων που αφορά· από αυτό δημιουργούνται οι οφειλόμενες επιθεωρήσεις.
+ Αποτέλεσμα
+ Η επιθεώρηση προγραμματίστηκε.
+ Η επιθεώρηση ξεκίνησε.
+ Επιθεωρήσεις
+ Επιθεωρητής
+ Απογράφηκε στις
+ {0} πηγές σαρώθηκαν, {1} υποψήφιοι δημιουργήθηκαν, {2} ενημερώθηκαν, {3} ήδη αποφασισμένοι.
+ Έρευνες
+ Εμφανίζονται μόνο οι υποθέσεις στις οποίες είστε μέλος. Κάθε ανάγνωση υπόθεσης καταγράφεται στον έλεγχο πρόσβασης.
+ Αναφορά τιμολογίου
+ Έκδοση ειδοποίησης
+ Εκδόθηκε στις
+ Σημείωση
+ Δικαιοδοσία
+ Κλειδοθήκη
+ Τελευταία επιθεώρηση
+ Τελευταία συντήρηση
+ Τελευταία αναθεώρηση
+ Τελευταία δοκιμή
+ Επικεφαλής ερευνητής
+ Απόπειρες εγγραφής στο παλαιό σύστημα
+ Σύνδεση
+ Σύνδεση επαφής
+ Σύνδεση συμβάντος
+ Συνδεδεμένες επαφές
+ Συνδεδεμένα
+ Συνδεδεμένα συμβάντα
+ Η σύνδεση καρφιτσώνει την αναθεώρηση του συμβάντος εκείνη τη στιγμή· τα πορίσματα δεν αλλάζουν ποτέ την αναφορά.
+ Διάμετρος αγωγού (ίντσες)
+ Ημερολόγιο συντήρησης
+ Η συντήρηση καταχωρήθηκε.
+ Σήμανση ως αναθεωρημένο
+ Βεβαιότητα αντιστοίχισης
+ Το μέλος προστέθηκε.
+ Το μέλος αφαιρέθηκε.
+ Συγχώνευση του κτιρίου στον στόχο; Κίνδυνοι, σύνδεσμοι και ιστορικό μεταφέρονται· η εγγραφή γίνεται δείκτης.
+ Συγχώνευση σε
+ ID κτιρίου-στόχου
+ Πλησιέστερος κρουνός
+ Νέο σύνολο κωδίκων
+ Νέα δραστηριότητα
+ Νέος κρουνός
+ Νέο κτίριο
+ Νέα άδεια
+ Νέος τύπος άδειας
+ Νέο πρόγραμμα
+ Νέα κλίμακα
+ Καμία ειδοποίηση ή προειδοποίηση σε αυτό το διάστημα.
+ Χωρίς συνημμένα.
+ Δεν εκκρεμούν υποψήφιοι. Εκτελέστε την απογραφή για να βρείτε προσχέδια και επαφές προς συμφωνία.
+ Χωρίς υποθέσεις.
+ Το πρόγραμμα δεν έχει στοιχεία ελέγχου.
+ Καμία δραστηριότητα στην περίοδο.
+ Δεν έχουν καταχωρηθεί δοκιμές ροής.
+ Δεν έχουν καταχωρηθεί κίνδυνοι.
+ Δεν υπάρχουν κρουνοί ακόμη.
+ Χωρίς επιθεωρήσεις.
+ Χωρίς συνδεδεμένες επαφές.
+ Δεν έχει καταχωρηθεί συντήρηση.
+ Κανένα κτίριο δεν ταιριάζει.
+ Δεν εκκρεμούν αξιολογήσεις προς βαθμολόγηση.
+ Καμία άδεια δεν ταιριάζει.
+ Δεν υπάρχουν κύκλοι ελέγχου σχεδίων ακόμη.
+ Καμία βαθμολογημένη αξιολόγηση στην περίοδο.
+ Δεν υπάρχουν κλίμακες ακόμη. Ένας διαχειριστής της υπηρεσίας δημιουργεί την πρώτη.
+ Χωρίς παραβάσεις.
+ Δ/Ε
+ Κείμενο σημείωσης
+ Η σημείωση αποθηκεύτηκε.
+ Θέμα
+ Η ειδοποίηση εκδόθηκε.
+ Αναφορά ειδοποίησης
+ Κτίρια
+ Πρόσβαση
+ {0} κτίρια
+ Το κτίριο διαγράφηκε.
+ Ώρες χρήσης
+ Ταυτότητα και τοποθεσία
+ Το κτίριο συγχωνεύθηκε.
+ Το κτίριο συγχωνεύθηκε σε
+ Αρ. κτιρίου
+ Πυροπροστασία και δίκτυα
+ Το κτίριο σημάνθηκε ως αναθεωρημένο.
+ Το κτίριο αποθηκεύτηκε.
+ Αναζήτηση αριθμού, ονόματος ή διεύθυνσης
+ Κατασκευή
+ Κίνδυνοι και τακτική
+ Τύπος κτιρίου
+ Ισχύει για τύπους κτιρίων
+ Αριθμοί τύπων χωρισμένοι με κόμμα· κενό σημαίνει όλοι οι τύποι.
+ Χωρητικότητα
+ Ένοικοι που χρειάζονται βοήθεια
+ Άνοιγμα υπόθεσης
+ Γίνεστε επικεφαλής ερευνητής. Προσθέστε μέλη μετά το άνοιγμα· μόνο τα μέλη μπορούν να διαβάσουν την υπόθεση.
+ Ανοικτές παραβάσεις
+ Άνοιξε στις
+ Περιγραφή εστίας
+ Εκτός λειτουργίας
+ Λόγος εκτός λειτουργίας
+ Αποτυχημένα συμβάντα
+ Εξερχόμενα συμβάντα
+ Παλαιότερο σε εκκρεμότητα
+ Εκκρεμή συμβάντα
+ Έκβαση
+ Στόμιο (ίντσες)
+ Όνομα ιδιοκτήτη
+ Τα προσχέδια γράφονται ακόμη στις Επαφές. Συμφωνήστε την αντιστοίχιση για να μεταφέρετε την κυριότητα εγγραφής στα κτίρια.
+ Τα κτίρια των Αρχείων κατέχουν τα προσχέδια. Οι σελίδες Επαφών και οι εφαρμογές διαβάζουν προβολές από εδώ.
+ Η κυριότητα εγγραφής μεταφέρθηκε στα κτίρια των Αρχείων.
+ Αρ. οικοπέδου
+ Επιτυχία
+ Αξιολογήσεις προς βαθμολόγηση
+ Εκτελέστηκε στις
+ Κωδικός
+ Αρ. άδειας
+ Η άδεια αποθηκεύτηκε.
+ Η κατάσταση της άδειας ενημερώθηκε.
+ Τύπος άδειας
+ Ο τύπος άδειας αποθηκεύτηκε.
+ Τύποι αδειών
+ Άδειες
+ καρφιτσωμένη αναθεώρηση
+ Pitot (psi)
+ Αποτέλεσμα ελέγχου
+ Ο έλεγχος σχεδίων καταχωρήθηκε.
+ Έλεγχος σχεδίων
+ ID σημείου ενδιαφέροντος
+ Αντιστοίχιση προσχεδίων
+ Κυριότητα εγγραφής προσχεδίων
+ Η ημερομηνία αναθεώρησης του κτιρίου έχει παρέλθει.
+ Πρόληψη
+ Το πρόγραμμα αποθηκεύτηκε.
+ Το προστατευμένο περιεχόμενο είναι κρυφό· αποκαλύψτε το πριν από την ενέργεια.
+ Επιβολή προστασίας δεδομένων
+ Έλεγχος ποιότητας
+ Η δειγματοληψία επιλέγει ντετερμινιστικά οριστικοποιημένες εγγραφές ανά κλίμακα· η βαθμολόγηση είναι σταθμισμένη και τροφοδοτεί τις τάσεις.
+ Σύσταση τροποποίησης
+ Συνιστά τροποποίηση της αναφοράς συμβάντος
+ Τα πορίσματα δεν επεξεργάζονται ποτέ το συμβάν. Η σύσταση περνά από τη ροή τροποποίησης της εγγραφής.
+ Καταχώρηση τέλους
+ Καταχώρηση πορισμάτων
+ Καταχώρηση δοκιμής ροής
+ Καταχώρηση συντήρησης
+ Καταχώρηση ελέγχου σχεδίων
+ Καταχωρήθηκε από
+ Εγγραφές που δημιουργήθηκαν
+ Εγγραφές που οριστικοποιήθηκαν
+ Υγεία έκδοσης
+ Βασική τηλεμετρία για την ενεργοποίηση των Αρχείων: απόπειρες εγγραφής στο παλαιό σύστημα, καθυστέρηση εξερχομένων, εκτελέσεις Workflow, σαρώσεις και μετρητές πρόληψης. Κάθε πηγή υποβαθμίζεται σε προειδοποίηση αντί να αποτύχει η σελίδα.
+ Αρχεία ενεργοποιημένα
+ Εγγραφές με εκπρόθεσμη αναθεώρηση
+ Αριθμός αναφοράς
+ Η παραπομπή προστέθηκε.
+ Η παραπομπή ενημερώθηκε.
+ Παραπομπές
+ Επανεπιθεώρηση του
+ Απόρριψη
+ Αφαίρεση του συνημμένου;
+ Επανάνοιγμα υπόθεσης
+ Απαιτούμενη παροχή (gpm)
+ Απαιτεί έλεγχο σχεδίων
+ Υπολειπόμενη (psi)
+ Τελική κατάσταση
+ Επιστροφή στον συντάκτη
+ Επαναφορά σε λειτουργία
+ Αξιολογήσεις
+ Κύκλος
+ Σημείωση ελεγκτή
+ Σημειώσεις ελέγχου
+ Εκπρόθεσμη αναθεώρηση
+ Η αξιολόγηση βαθμολογήθηκε.
+ Ελέγχθηκε στις
+ Τύπος στέγης
+ Η κλίμακα αποθηκεύτηκε.
+ Κλίμακες
+ Εκτέλεση απογραφής
+ Δειγματοληψία
+ Ολοκληρώθηκαν
+ Απέτυχαν
+ Σε εξέλιξη
+ Παραλείφθηκαν
+ {0} εγγραφές επιλέχθηκαν για αξιολόγηση.
+ Μέγεθος δείγματος
+ Εγγραφές ανά εκτέλεση δειγματοληψίας· η επιλογή είναι ντετερμινιστική για την κλίμακα και την περίοδο.
+ Δειγματοληπτήθηκαν
+ Δειγματοληπτήθηκε στις
+ Συνημμένα σε αναμονή σάρωσης
+ Συνημμένα που απορρίφθηκαν από τη σάρωση
+ Σάρωση
+ Προγραμματισμός επιθεώρησης
+ Προγραμματισμός επανεπιθεώρησης
+ Προγραμματισμένη
+ Βαθμολογήστε κάθε κριτήριο 0-4· το σταθμισμένο σύνολο γίνεται ποσοστό.
+ Βαθμολόγηση αξιολόγησης
+ Βαθμολογήθηκαν
+ Βαθμολογήθηκε στις
+ Ενότητα
+ Εισήχθησαν {0} ενότητες.
+ Επαναφορά σε λειτουργία
+ Θέση εκτός λειτουργίας
+ Ειδοποίηση πληρωμάτων
+ Όνομα υπογραφής
+ Πληκτρολογημένο όνομα του ατόμου που βεβαιώνει την επιθεώρηση
+ Ανιχνευτές καπνού που εγκαταστάθηκαν
+ Καταιονιστήρες
+ Τετραγωνικά πόδια
+ Προσωπικό
+ Αναγνωριστικά χρηστών χωρισμένα με κόμμα για τα μέλη που συμμετείχαν.
+ Στήλη ανύψωσης
+ Έναρξη επιθεώρησης
+ Ξεκίνησε
+ Στατική (psi)
+ Θέση αποθήκευσης
+ Όροφοι
+ Υποβολές σε αναμονή
+ Αποτυχημένες υποβολές
+ Υποβλήθηκε στις
+ Προτεινόμενο κτίριο
+ Η αλλαγή είναι μπλοκαρισμένη μέχρι να εκτελεστεί η απογραφή, να αποφασιστεί κάθε υποψήφιος και να μη μείνει ασυμφώνητο προσχέδιο.
+ Μεταφορά κυριότητας εγγραφής στα Αρχεία
+ Κατανοώ ότι οι σελίδες προσχεδίων στις Επαφές και οι εφαρμογές γίνονται προβολές κτιρίων μόνο για ανάγνωση.
+ Μεταφορά κυριότητας εγγραφής τώρα; Η επεξεργασία προσχεδίων στις Επαφές σταματά αμέσως.
+ Μετά την αλλαγή, τα προσχέδια επεξεργάζονται μόνο ως κτίρια. Οι Επαφές και οι εφαρμογές συνεχίζουν με προβολές· η αναίρεση είναι επαναφορά βάσης δεδομένων, όχι διακόπτης.
+ Άλλαξε στις
+ Τακτική σύνοψη
+ Παράθυρο
+ οφειλόμενη δοκιμή
+ Δοκιμάστηκε στις
+ Μεταβίβαση φύλαξης
+ Προς
+ Σε εξωτερικό φορέα
+ Μεταβιβάστηκε στις
+ Αλλαγή κατάστασης
+ Τάσεις
+ Από
+ Αποσύνδεση
+ Ασυμφώνητα προσχέδια
+ Μεταφορτώθηκε
+ Σημειώσεις δικτύων
+ Ισχύς (ημέρες)
+ Η παράβαση αποθηκεύτηκε.
+ Η παράβαση ενημερώθηκε.
+ Παραβάσεις
+ Διακοπή νερού
+ Σημειώσεις υδροδότησης
+ Εκτελέσεις Workflow
diff --git a/Core/Resgrid.Localization/Areas/User/Records/Records.en.resx b/Core/Resgrid.Localization/Areas/User/Records/Records.en.resx
index c80b208e..a2678b1a 100644
--- a/Core/Resgrid.Localization/Areas/User/Records/Records.en.resx
+++ b/Core/Resgrid.Localization/Areas/User/Records/Records.en.resx
@@ -1123,6 +1123,11 @@
Assign number
Sequence per station
Sequence per incident
+ Records per call
+ Multiple per call
+ One authoritative per call
+ One per subject per call
+ How many records of this definition one call may have. Enforced on create; a voided or cancelled record releases its slot.
Reset yearly
Classification
Retention (years)
@@ -1418,4 +1423,414 @@
Source status is ahead of the local fill
Source status is behind the local fill
Maintained by a connector
+ Access audit
+ Access notes
+ Add evidence
+ Add hazard
+ Add member
+ Add note
+ Add referral
+ Add violation
+ Agency
+ Alarm company
+ Alarm panel
+ All programs
+ Amendments recommended
+ Applicant
+ Applicant e-mail
+ Applicant phone
+ Applied on
+ Submit application
+ Approve findings
+ Findings must be approved by a reviewer or lead other than their author.
+ Attachment added.
+ Choose a file to attach.
+ Attachment removed.
+ Audience
+ Authorization denials
+ Average score
+ By author
+ By criterion
+ By definition
+ By unit
+ Cancel inspection
+ Cancel this inspection? The record stays in history.
+ Candidate linked.
+ Candidate rejected.
+ Candidates
+ Access to this case is limited to its members and every read is logged.
+ Case closed.
+ Case members
+ Case notes
+ Case {0} opened.
+ Case reopened.
+ Case saved.
+ Catalog version
+ Cause classification
+ Cause detail
+ Checklist
+ One item per line: key | text | required (y/n) | code section id.
+ Checklist item
+ Close case
+ Close this case? Notes become read-only.
+ Close inspection
+ Closure reason
+ Edition
+ Code section saved.
+ Section text
+ Code sections
+ Code set saved.
+ Code sets
+ Fire and building codes the department inspects against. Sections carry a default severity and correction window for violations.
+ Collected from
+ Collected on
+ Comments
+ Complete inspection
+ Conditions
+ Conditions template
+ Contact ID
+ Contact linked.
+ Contact unlinked.
+ Corrective action
+ Create a new occupancy from this source
+ Criteria
+ One criterion per line: key | text | weight.
+ Score (0-4)
+ Weight
+ Inventory finds Contacts pre-plans, contacts with addresses and points of interest, groups them by address and proximity, and proposes occupancies. Decide every candidate before switching write ownership to Records.
+ Community risk reduction
+ Activity deleted.
+ Activity saved.
+ Summary for the period
+ Custodian
+ Chain of custody
+ Transfers are append-only; every hand-off names who gave, who received, why and the resulting state.
+ Custody transferred.
+ Decision reason
+ Correction days
+ Default severity
+ Delete activity
+ Delete this activity?
+ Delete hydrant
+ Delete this hydrant? Flow tests and maintenance history go with it.
+ Delete occupancy
+ Delete this occupancy? Inspections, permits and hazards keep their history but lose the parent.
+ Due on
+ Edit hydrant
+ Edit occupancy
+ Edit permit
+ Effective on
+ Electric shutoff
+ Emergency contact
+ Evidence added.
+ Evidence
+ Evidence #
+ Expires on
+ Leave blank to use the permit type validity from the issue date.
+ Expiring soon
+ Export packet
+ Failed
+ FDC location
+ Fee
+ Reference only; invoicing is recorded, not collected, here.
+ Fee paid on
+ Fee recorded.
+ File
+ Findings
+ Findings approved.
+ Approved
+ Awaiting approval, recorded
+ Findings recorded and sent for approval.
+ Findings returned to the author.
+ Fire alarm
+ Flow class
+ Flow (gpm)
+ Recorded flow tests update this value and the NFPA 291 class automatically.
+ Flow is computed as 29.83 × c × d² × √pitot and rounded to 10 gpm; the class follows NFPA 291.
+ Flow test recorded.
+ Flow tests
+ Frequency (months)
+ From
+ Gas shutoff
+ Gate code
+ General hazard notes
+ Generate due inspections
+ {0} inspections generated.
+ Hazard removed.
+ Hazard saved.
+ Hazards
+ Hazmat on site
+ Hours
+ {0} hydrants, {1} out of service, {2} due for a flow test.
+ Hydrant deleted.
+ Map
+ Colour follows the NFPA 291 flow class; black is out of service.
+ Hydrant #
+ Owner
+ Hydrant saved.
+ Hydrants
+ Import hydrants
+ CSV with a header row: number, latitude, longitude, type, address, main_size, flow_gpm, owner. Existing numbers are updated.
+ Rows not imported
+ {0} rows read, {1} created, {2} updated, {3} rejected.
+ Import sections
+ CSV with a header row: section, title, text, severity (1-4), correction_days.
+ In service
+ Incident linked; the current revision is pinned.
+ Incident summary
+ Incident unlinked.
+ Include closed
+ Inspection cancelled.
+ Inspection closed.
+ Inspection completed; failed items created violations.
+ Notes
+ Inspection #
+ Inspection programs
+ A program pairs a checklist with a frequency and the occupancy types it applies to; due inspections are generated from it.
+ Result
+ Inspection scheduled.
+ Inspection started.
+ Inspections
+ Inspector
+ Inventoried on
+ {0} sources scanned, {1} candidates created, {2} updated, {3} already decided.
+ Investigations
+ Only cases you are a member of are listed. Every read of a case is written to the access audit.
+ Invoice reference
+ Issue notice
+ Issued on
+ Note
+ Jurisdiction
+ Knox box
+ Last inspected
+ Last maintained
+ Last reviewed
+ Last tested
+ Lead investigator
+ Legacy write attempts
+ Link
+ Link contact
+ Link incident
+ Linked contacts
+ Linked
+ Linked incidents
+ Linking pins the incident revision at that moment; findings never change the incident report.
+ Main size (in)
+ Maintenance log
+ Maintenance recorded.
+ Mark reviewed
+ Match confidence
+ Member added.
+ Member removed.
+ Merge this occupancy into the target? Hazards, links and history move; this record becomes a pointer.
+ Merge into
+ Target occupancy ID
+ Nearest hydrant
+ New code set
+ New activity
+ New hydrant
+ New occupancy
+ New permit
+ New permit type
+ New program
+ New rubric
+ No alerts or warnings in this window.
+ No attachments.
+ No candidates waiting. Run the inventory to find pre-plans and contacts to reconcile.
+ No cases.
+ This program has no checklist items.
+ No activities in this period.
+ No flow tests recorded.
+ No hazards recorded.
+ No hydrants yet.
+ No inspections.
+ No linked contacts.
+ No maintenance recorded.
+ No occupancies match.
+ No reviews waiting to be scored.
+ No permits match.
+ No plan review cycles yet.
+ No scored reviews in this period.
+ No rubrics yet. A department administrator creates the first one.
+ No violations.
+ N/A
+ Note text
+ Note saved.
+ Subject
+ Notice issued.
+ Notice reference
+ Occupancies
+ Access
+ {0} occupancies
+ Occupancy deleted.
+ Occupancy hours
+ Identity and location
+ Occupancy merged.
+ This occupancy was merged into
+ Occupancy #
+ Fire protection and utilities
+ Occupancy marked reviewed.
+ Occupancy saved.
+ Search number, name or address
+ Structure
+ Hazards and tactics
+ Occupancy type
+ Applies to occupancy types
+ Comma-separated type numbers; blank means every type.
+ Occupant load
+ Occupants needing assistance
+ Open case
+ You become the lead investigator. Add members after opening; only members can read the case.
+ Open violations
+ Opened on
+ Origin description
+ Out of service
+ Out-of-service reason
+ Failed events
+ Event outbox
+ Oldest pending
+ Pending events
+ Outcome
+ Outlet (in)
+ Owner name
+ Pre-plans are still written under Contacts. Reconcile the crosswalk to switch write ownership to occupancies.
+ Records occupancies own pre-plans. Contacts pages and the apps read projections from here.
+ Write ownership switched to Records occupancies.
+ Parcel ID
+ Passed
+ Reviews to score
+ Performed on
+ Code
+ Permit #
+ Permit saved.
+ Permit state updated.
+ Permit type
+ Permit type saved.
+ Permit types
+ Permits
+ pinned revision
+ Pitot (psi)
+ Outcome
+ Plan review recorded.
+ Plan review
+ Point of interest ID
+ Pre-plan crosswalk
+ Pre-plan write ownership
+ The review date for this occupancy has passed.
+ Prevention
+ Program saved.
+ Protected content is concealed; reveal it before this action.
+ Protected data enforced
+ Quality review
+ Sampling picks finalized records deterministically per rubric; scoring is weighted and feeds the trends.
+ Recommend an amendment
+ Recommends amending the incident report
+ Findings never edit the incident. The recommendation is delivered through the record amendment flow.
+ Record fee
+ Record findings
+ Record flow test
+ Record maintenance
+ Record plan review
+ Recorded by
+ Records created
+ Records finalized
+ Release health
+ Baseline telemetry for the Records activation: legacy write attempts, outbox lag, Workflow runs, scans and prevention counters. Every source degrades to a warning instead of failing the page.
+ Records activated
+ Records overdue for review
+ Reference number
+ Referral added.
+ Referral updated.
+ Referrals
+ Re-inspection of
+ Reject
+ Remove this attachment?
+ Reopen case
+ Required fire flow (gpm)
+ Requires plan review
+ Residual (psi)
+ Resulting state
+ Return to author
+ Returned to service
+ Reviews
+ Cycle
+ Reviewer note
+ Review notes
+ Review overdue
+ Review scored.
+ Reviewed on
+ Roof type
+ Rubric saved.
+ Rubrics
+ Run inventory
+ Sample
+ Completed
+ Failed
+ Running
+ Skipped
+ {0} records sampled for review.
+ Sample size
+ Records per sampling run; selection is deterministic for the rubric and period.
+ Sampled
+ Sampled on
+ Attachments awaiting scan
+ Attachments rejected by scan
+ Scan
+ Schedule inspection
+ Schedule re-inspection
+ Scheduled
+ Score each criterion 0-4; the weighted total becomes a percentage.
+ Score review
+ Scored
+ Scored on
+ Section
+ {0} sections imported.
+ Return to service
+ Take out of service
+ Alert crews
+ Signature name
+ Typed name of the person attesting the inspection
+ Smoke alarms installed
+ Sprinklers
+ Square feet
+ Staff
+ Comma-separated user IDs of the members who took part.
+ Standpipe
+ Start inspection
+ Started
+ Static (psi)
+ Storage location
+ Stories
+ Submissions awaiting
+ Submissions failed
+ Submitted on
+ Suggested occupancy
+ The switch is blocked until the inventory has run, every candidate is decided and no pre-plan is unreconciled.
+ Switch write ownership to Records
+ I understand that Contacts pre-plan pages and the apps become read-only projections of occupancies.
+ Switch write ownership now? Contacts pre-plan editing stops immediately.
+ After the switch, pre-plans are edited only as occupancies. Contacts and the apps keep working from projections; rollback is a database restore, not a toggle.
+ Switched on
+ Tactical summary
+ Window
+ test due
+ Tested on
+ Transfer custody
+ To
+ To external party
+ Transferred on
+ Change state
+ Trends
+ Since
+ Unlink
+ Unreconciled pre-plans
+ Uploaded
+ Utility notes
+ Validity (days)
+ Violation saved.
+ Violation updated.
+ Violations
+ Water shutoff
+ Water supply notes
+ Workflow runs
diff --git a/Core/Resgrid.Localization/Areas/User/Records/Records.es.resx b/Core/Resgrid.Localization/Areas/User/Records/Records.es.resx
index e5a9c610..6b648730 100644
--- a/Core/Resgrid.Localization/Areas/User/Records/Records.es.resx
+++ b/Core/Resgrid.Localization/Areas/User/Records/Records.es.resx
@@ -1123,6 +1123,11 @@
Asignar número
Secuencia por estación
Secuencia por incidente
+ Registros por llamada
+ Varios por llamada
+ Uno autorizado por llamada
+ Uno por sujeto por llamada
+ Cuántos registros de esta definición puede tener una llamada. Se aplica al crear; un registro anulado o cancelado libera su lugar.
Reiniciar anualmente
Clasificación
Retención (años)
@@ -1418,4 +1423,414 @@
El estado de la fuente va por delante de la asignación local
El estado de la fuente va por detrás de la asignación local
Mantenido por un conector
+ Auditoría de acceso
+ Notas de acceso
+ Añadir evidencia
+ Añadir peligro
+ Añadir miembro
+ Añadir nota
+ Añadir derivación
+ Añadir infracción
+ Agencia
+ Empresa de alarmas
+ Panel de alarma
+ Todos los programas
+ Enmiendas recomendadas
+ Solicitante
+ Correo del solicitante
+ Teléfono del solicitante
+ Solicitado el
+ Presentar solicitud
+ Aprobar conclusiones
+ Las conclusiones deben aprobarlas un revisor o responsable distinto de su autor.
+ Adjunto añadido.
+ Elija un archivo para adjuntar.
+ Adjunto eliminado.
+ Asistentes
+ Denegaciones de autorización
+ Puntuación media
+ Por autor
+ Por criterio
+ Por definición
+ Por unidad
+ Cancelar inspección
+ ¿Cancelar esta inspección? El registro se conserva en el historial.
+ Candidato vinculado.
+ Candidato rechazado.
+ Candidatos
+ El acceso a este caso se limita a sus miembros y cada lectura queda registrada.
+ Caso cerrado.
+ Miembros del caso
+ Notas del caso
+ Caso {0} abierto.
+ Caso reabierto.
+ Caso guardado.
+ Versión del catálogo
+ Clasificación de la causa
+ Detalle de la causa
+ Lista de comprobación
+ Un elemento por línea: clave | texto | obligatorio (y/n) | id de sección de código.
+ Elemento de la lista
+ Cerrar caso
+ ¿Cerrar este caso? Las notas pasan a ser de solo lectura.
+ Cerrar inspección
+ Motivo de cierre
+ Edición
+ Sección de código guardada.
+ Texto de la sección
+ Secciones del código
+ Conjunto de códigos guardado.
+ Conjuntos de códigos
+ Códigos de incendios y edificación con los que inspecciona el departamento. Las secciones llevan una gravedad y un plazo de corrección predeterminados.
+ Recogido de
+ Recogido el
+ Comentarios
+ Completar inspección
+ Condiciones
+ Plantilla de condiciones
+ ID de contacto
+ Contacto vinculado.
+ Contacto desvinculado.
+ Acción correctiva
+ Crear una nueva ocupación a partir de esta fuente
+ Criterios
+ Un criterio por línea: clave | texto | peso.
+ Puntuación (0-4)
+ Peso
+ El inventario localiza planes previos, contactos con dirección y puntos de interés, los agrupa por dirección y proximidad y propone ocupaciones. Decida cada candidato antes de traspasar la propiedad de escritura a Registros.
+ Reducción de riesgos comunitarios
+ Actividad eliminada.
+ Actividad guardada.
+ Resumen del periodo
+ Custodio
+ Cadena de custodia
+ Las transferencias solo se añaden; cada entrega indica quién cedió, quién recibió, por qué y el estado resultante.
+ Custodia transferida.
+ Motivo de la decisión
+ Días de corrección
+ Gravedad predeterminada
+ Eliminar actividad
+ ¿Eliminar esta actividad?
+ Eliminar hidrante
+ ¿Eliminar este hidrante? Se pierden las pruebas de caudal y el historial de mantenimiento.
+ Eliminar ocupación
+ ¿Eliminar esta ocupación? Inspecciones, permisos y peligros conservan su historial pero pierden el padre.
+ Vence el
+ Editar hidrante
+ Editar ocupación
+ Editar permiso
+ Vigente desde
+ Corte eléctrico
+ Contacto de emergencia
+ Evidencia añadida.
+ Evidencias
+ N.º de evidencia
+ Caduca el
+ Déjelo en blanco para usar la validez del tipo de permiso desde la emisión.
+ Próximo a caducar
+ Exportar expediente
+ No conforme
+ Ubicación de la toma de bomberos
+ Tasa
+ Solo como referencia; aquí se registra la factura, no se cobra.
+ Tasa pagada el
+ Tasa registrada.
+ Archivo
+ Conclusiones
+ Conclusiones aprobadas.
+ Aprobadas
+ Pendientes de aprobación, registradas
+ Conclusiones registradas y enviadas para aprobación.
+ Conclusiones devueltas al autor.
+ Alarma de incendio
+ Clase de caudal
+ Caudal (gpm)
+ Las pruebas de caudal registradas actualizan este valor y la clase NFPA 291 automáticamente.
+ El caudal se calcula como 29,83 × c × d² × √pitot y se redondea a 10 gpm; la clase sigue NFPA 291.
+ Prueba de caudal registrada.
+ Pruebas de caudal
+ Frecuencia (meses)
+ De
+ Corte de gas
+ Código de la puerta
+ Notas generales de peligros
+ Generar inspecciones pendientes
+ {0} inspecciones generadas.
+ Peligro eliminado.
+ Peligro guardado.
+ Peligros
+ Materiales peligrosos en el sitio
+ Horas
+ {0} hidrantes, {1} fuera de servicio, {2} con prueba de caudal pendiente.
+ Hidrante eliminado.
+ Mapa
+ El color sigue la clase de caudal NFPA 291; el negro indica fuera de servicio.
+ N.º de hidrante
+ Propietario
+ Hidrante guardado.
+ Hidrantes
+ Importar hidrantes
+ CSV con fila de cabecera: number, latitude, longitude, type, address, main_size, flow_gpm, owner. Los números existentes se actualizan.
+ Filas no importadas
+ {0} filas leídas, {1} creadas, {2} actualizadas, {3} rechazadas.
+ Importar secciones
+ CSV con fila de cabecera: section, title, text, severity (1-4), correction_days.
+ En servicio
+ Incidente vinculado; la revisión actual queda fijada.
+ Resumen del incidente
+ Incidente desvinculado.
+ Incluir cerrados
+ Inspección cancelada.
+ Inspección cerrada.
+ Inspección completada; los elementos no conformes generaron infracciones.
+ Notas
+ N.º de inspección
+ Programas de inspección
+ Un programa combina una lista de comprobación con una frecuencia y los tipos de ocupación a los que aplica; de él se generan las inspecciones pendientes.
+ Resultado
+ Inspección programada.
+ Inspección iniciada.
+ Inspecciones
+ Inspector
+ Inventariado el
+ {0} fuentes analizadas, {1} candidatos creados, {2} actualizados, {3} ya decididos.
+ Investigaciones
+ Solo se listan los casos de los que es miembro. Cada lectura de un caso queda en la auditoría de acceso.
+ Referencia de factura
+ Emitir notificación
+ Emitido el
+ Nota
+ Jurisdicción
+ Caja de llaves
+ Última inspección
+ Último mantenimiento
+ Última revisión
+ Última prueba
+ Investigador principal
+ Intentos de escritura heredada
+ Vincular
+ Vincular contacto
+ Vincular incidente
+ Contactos vinculados
+ Vinculados
+ Incidentes vinculados
+ Al vincular se fija la revisión del incidente en ese momento; las conclusiones nunca modifican el informe.
+ Diámetro de la tubería (pulg.)
+ Registro de mantenimiento
+ Mantenimiento registrado.
+ Marcar como revisado
+ Confianza de coincidencia
+ Miembro añadido.
+ Miembro eliminado.
+ ¿Fusionar esta ocupación en la de destino? Peligros, vínculos e historial se trasladan; este registro pasa a ser un puntero.
+ Fusionar en
+ ID de la ocupación de destino
+ Hidrante más cercano
+ Nuevo conjunto de códigos
+ Nueva actividad
+ Nuevo hidrante
+ Nueva ocupación
+ Nuevo permiso
+ Nuevo tipo de permiso
+ Nuevo programa
+ Nueva rúbrica
+ Sin alertas ni avisos en este periodo.
+ Sin adjuntos.
+ No hay candidatos pendientes. Ejecute el inventario para hallar planes previos y contactos que conciliar.
+ Sin casos.
+ Este programa no tiene elementos en la lista.
+ Sin actividades en este periodo.
+ Sin pruebas de caudal registradas.
+ Sin peligros registrados.
+ Aún no hay hidrantes.
+ Sin inspecciones.
+ Sin contactos vinculados.
+ Sin mantenimiento registrado.
+ Ninguna ocupación coincide.
+ No hay revisiones pendientes de puntuar.
+ Ningún permiso coincide.
+ Aún no hay ciclos de revisión de planos.
+ Sin revisiones puntuadas en este periodo.
+ Aún no hay rúbricas. Un administrador del departamento crea la primera.
+ Sin infracciones.
+ N/D
+ Texto de la nota
+ Nota guardada.
+ Asunto
+ Notificación emitida.
+ Referencia de la notificación
+ Ocupaciones
+ Acceso
+ {0} ocupaciones
+ Ocupación eliminada.
+ Horario de ocupación
+ Identidad y ubicación
+ Ocupación fusionada.
+ Esta ocupación se fusionó en
+ N.º de ocupación
+ Protección contra incendios y suministros
+ Ocupación marcada como revisada.
+ Ocupación guardada.
+ Buscar número, nombre o dirección
+ Estructura
+ Peligros y tácticas
+ Tipo de ocupación
+ Aplica a tipos de ocupación
+ Números de tipo separados por comas; en blanco significa todos los tipos.
+ Aforo
+ Ocupantes que requieren asistencia
+ Abrir caso
+ Usted será el investigador principal. Añada miembros tras abrirlo; solo los miembros pueden leer el caso.
+ Infracciones abiertas
+ Abierto el
+ Descripción del origen
+ Fuera de servicio
+ Motivo de fuera de servicio
+ Eventos fallidos
+ Bandeja de salida de eventos
+ Pendiente más antiguo
+ Eventos pendientes
+ Resultado
+ Salida (pulg.)
+ Nombre del propietario
+ Los planes previos aún se editan en Contactos. Concilie el cruce para traspasar la propiedad de escritura a las ocupaciones.
+ Las ocupaciones de Registros son propietarias de los planes previos. Las páginas de Contactos y las apps leen proyecciones desde aquí.
+ Propiedad de escritura traspasada a las ocupaciones de Registros.
+ ID de parcela
+ Conforme
+ Revisiones por puntuar
+ Realizado el
+ Código
+ N.º de permiso
+ Permiso guardado.
+ Estado del permiso actualizado.
+ Tipo de permiso
+ Tipo de permiso guardado.
+ Tipos de permiso
+ Permisos
+ revisión fijada
+ Pitot (psi)
+ Resultado de la revisión
+ Revisión de planos registrada.
+ Revisión de planos
+ ID de punto de interés
+ Cruce de planes previos
+ Propiedad de escritura de planes previos
+ La fecha de revisión de esta ocupación ha pasado.
+ Prevención
+ Programa guardado.
+ El contenido protegido está oculto; revélelo antes de esta acción.
+ Protección de datos aplicada
+ Revisión de calidad
+ El muestreo elige registros finalizados de forma determinista por rúbrica; la puntuación es ponderada y alimenta las tendencias.
+ Recomendar una enmienda
+ Recomienda enmendar el informe del incidente
+ Las conclusiones nunca editan el incidente. La recomendación se tramita por el flujo de enmienda del registro.
+ Registrar tasa
+ Registrar conclusiones
+ Registrar prueba de caudal
+ Registrar mantenimiento
+ Registrar revisión de planos
+ Registrado por
+ Registros creados
+ Registros finalizados
+ Estado de la versión
+ Telemetría base de la activación de Registros: intentos de escritura heredada, retraso de la bandeja de salida, ejecuciones de Workflow, análisis y contadores de prevención. Cada fuente degrada a un aviso en lugar de fallar la página.
+ Registros activado
+ Registros con revisión vencida
+ Número de referencia
+ Derivación añadida.
+ Derivación actualizada.
+ Derivaciones
+ Reinspección de
+ Rechazar
+ ¿Eliminar este adjunto?
+ Reabrir caso
+ Caudal requerido (gpm)
+ Requiere revisión de planos
+ Residual (psi)
+ Estado resultante
+ Devolver al autor
+ Devuelto al servicio
+ Revisiones
+ Ciclo
+ Nota del revisor
+ Notas de revisión
+ Revisión vencida
+ Revisión puntuada.
+ Revisado el
+ Tipo de cubierta
+ Rúbrica guardada.
+ Rúbricas
+ Ejecutar inventario
+ Muestrear
+ Completadas
+ Fallidas
+ En ejecución
+ Omitidas
+ {0} registros muestreados para revisión.
+ Tamaño de la muestra
+ Registros por ejecución de muestreo; la selección es determinista para la rúbrica y el periodo.
+ Muestreados
+ Muestreado el
+ Adjuntos pendientes de análisis
+ Adjuntos rechazados por el análisis
+ Análisis
+ Programar inspección
+ Programar reinspección
+ Programada
+ Puntúe cada criterio de 0 a 4; el total ponderado se convierte en porcentaje.
+ Puntuar revisión
+ Puntuados
+ Puntuado el
+ Sección
+ {0} secciones importadas.
+ Devolver al servicio
+ Poner fuera de servicio
+ Alertar a las dotaciones
+ Nombre de la firma
+ Nombre escrito de quien certifica la inspección
+ Detectores de humo instalados
+ Rociadores
+ Pies cuadrados
+ Personal
+ IDs de usuario separados por comas de los miembros que participaron.
+ Columna seca
+ Iniciar inspección
+ Iniciada
+ Estática (psi)
+ Lugar de almacenamiento
+ Plantas
+ Envíos pendientes
+ Envíos fallidos
+ Presentado el
+ Ocupación sugerida
+ El traspaso está bloqueado hasta que se ejecute el inventario, se decida cada candidato y no quede ningún plan previo sin conciliar.
+ Traspasar la propiedad de escritura a Registros
+ Entiendo que las páginas de planes previos de Contactos y las apps pasan a ser proyecciones de solo lectura de las ocupaciones.
+ ¿Traspasar la propiedad de escritura ahora? La edición de planes previos en Contactos se detiene de inmediato.
+ Tras el traspaso, los planes previos solo se editan como ocupaciones. Contactos y las apps siguen funcionando con proyecciones; revertir es una restauración de base de datos, no un interruptor.
+ Traspasado el
+ Resumen táctico
+ Ventana
+ prueba pendiente
+ Probado el
+ Transferir custodia
+ A
+ A entidad externa
+ Transferido el
+ Cambiar estado
+ Tendencias
+ Desde
+ Desvincular
+ Planes previos sin conciliar
+ Subido
+ Notas de suministros
+ Validez (días)
+ Infracción guardada.
+ Infracción actualizada.
+ Infracciones
+ Corte de agua
+ Notas de suministro de agua
+ Ejecuciones de Workflow
diff --git a/Core/Resgrid.Localization/Areas/User/Records/Records.fr.resx b/Core/Resgrid.Localization/Areas/User/Records/Records.fr.resx
index 3152008d..e2f8e258 100644
--- a/Core/Resgrid.Localization/Areas/User/Records/Records.fr.resx
+++ b/Core/Resgrid.Localization/Areas/User/Records/Records.fr.resx
@@ -1123,6 +1123,11 @@
Attribuer le numéro
Séquence par caserne
Séquence par incident
+ Enregistrements par appel
+ Plusieurs par appel
+ Un seul faisant foi par appel
+ Un par sujet par appel
+ Combien d'enregistrements de cette définition un appel peut avoir. Appliqué à la création ; un enregistrement annulé ou abandonné libère sa place.
Réinitialiser chaque année
Classification
Conservation (années)
@@ -1418,4 +1423,414 @@
Le statut de la source est en avance sur l'affectation locale
Le statut de la source est en retard sur l'affectation locale
Maintenu par un connecteur
+ Journal d'accès
+ Notes d'accès
+ Ajouter une pièce
+ Ajouter un danger
+ Ajouter un membre
+ Ajouter une note
+ Ajouter un renvoi
+ Ajouter une infraction
+ Organisme
+ Société d'alarme
+ Centrale d'alarme
+ Tous les programmes
+ Modifications recommandées
+ Demandeur
+ Courriel du demandeur
+ Téléphone du demandeur
+ Demandé le
+ Soumettre la demande
+ Approuver les conclusions
+ Les conclusions doivent être approuvées par un relecteur ou un responsable autre que leur auteur.
+ Pièce jointe ajoutée.
+ Choisissez un fichier à joindre.
+ Pièce jointe supprimée.
+ Public touché
+ Refus d'autorisation
+ Score moyen
+ Par auteur
+ Par critère
+ Par définition
+ Par unité
+ Annuler l'inspection
+ Annuler cette inspection ? L'enregistrement reste dans l'historique.
+ Candidat lié.
+ Candidat rejeté.
+ Candidats
+ L'accès à ce dossier est limité à ses membres et chaque lecture est journalisée.
+ Dossier clos.
+ Membres du dossier
+ Notes du dossier
+ Dossier {0} ouvert.
+ Dossier rouvert.
+ Dossier enregistré.
+ Version du catalogue
+ Classification de la cause
+ Détail de la cause
+ Liste de contrôle
+ Un élément par ligne : clé | texte | obligatoire (y/n) | identifiant de section de code.
+ Élément de contrôle
+ Clore le dossier
+ Clore ce dossier ? Les notes deviennent en lecture seule.
+ Clore l'inspection
+ Motif de clôture
+ Édition
+ Section de code enregistrée.
+ Texte de la section
+ Sections de code
+ Recueil de codes enregistré.
+ Recueils de codes
+ Codes incendie et bâtiment servant de référence aux inspections. Les sections portent une gravité et un délai de correction par défaut.
+ Prélevé sur
+ Prélevé le
+ Commentaires
+ Terminer l'inspection
+ Conditions
+ Modèle de conditions
+ Identifiant du contact
+ Contact lié.
+ Contact dissocié.
+ Mesure corrective
+ Créer une nouvelle occupation à partir de cette source
+ Critères
+ Un critère par ligne : clé | texte | poids.
+ Score (0-4)
+ Poids
+ L'inventaire repère les plans d'intervention, les contacts avec adresse et les points d'intérêt, les regroupe par adresse et proximité et propose des occupations. Statuez sur chaque candidat avant de transférer la propriété en écriture aux Dossiers.
+ Réduction des risques communautaires
+ Activité supprimée.
+ Activité enregistrée.
+ Synthèse de la période
+ Dépositaire
+ Chaîne de possession
+ Les transferts sont en ajout seul ; chaque remise indique qui a remis, qui a reçu, pourquoi et l'état résultant.
+ Possession transférée.
+ Motif de la décision
+ Délai de correction (jours)
+ Gravité par défaut
+ Supprimer l'activité
+ Supprimer cette activité ?
+ Supprimer la borne
+ Supprimer cette borne ? Les essais de débit et l'historique de maintenance disparaissent.
+ Supprimer l'occupation
+ Supprimer cette occupation ? Inspections, permis et dangers conservent leur historique mais perdent leur parent.
+ Échéance
+ Modifier la borne
+ Modifier l'occupation
+ Modifier le permis
+ Effectif le
+ Coupure électrique
+ Contact d'urgence
+ Pièce ajoutée.
+ Pièces à conviction
+ N° de pièce
+ Expire le
+ Laisser vide pour appliquer la validité du type de permis à partir de l'émission.
+ Expire bientôt
+ Exporter le dossier
+ Non conforme
+ Emplacement du raccord pompiers
+ Redevance
+ Pour référence seulement ; la facturation est consignée ici, pas encaissée.
+ Redevance réglée le
+ Redevance enregistrée.
+ Fichier
+ Conclusions
+ Conclusions approuvées.
+ Approuvées
+ En attente d'approbation, enregistrées
+ Conclusions enregistrées et envoyées pour approbation.
+ Conclusions renvoyées à l'auteur.
+ Alarme incendie
+ Classe de débit
+ Débit (gpm)
+ Les essais de débit enregistrés mettent à jour cette valeur et la classe NFPA 291 automatiquement.
+ Le débit est calculé comme 29,83 × c × d² × √pitot et arrondi à 10 gpm ; la classe suit la NFPA 291.
+ Essai de débit enregistré.
+ Essais de débit
+ Fréquence (mois)
+ De
+ Coupure de gaz
+ Code du portail
+ Notes générales sur les dangers
+ Générer les inspections dues
+ {0} inspections générées.
+ Danger supprimé.
+ Danger enregistré.
+ Dangers
+ Matières dangereuses sur place
+ Heures
+ {0} bornes, {1} hors service, {2} avec essai de débit à faire.
+ Borne supprimée.
+ Carte
+ La couleur suit la classe de débit NFPA 291 ; le noir signale hors service.
+ N° de borne
+ Propriétaire
+ Borne enregistrée.
+ Bornes d'incendie
+ Importer des bornes
+ CSV avec ligne d'en-tête : number, latitude, longitude, type, address, main_size, flow_gpm, owner. Les numéros existants sont mis à jour.
+ Lignes non importées
+ {0} lignes lues, {1} créées, {2} mises à jour, {3} rejetées.
+ Importer des sections
+ CSV avec ligne d'en-tête : section, title, text, severity (1-4), correction_days.
+ En service
+ Incident lié ; la révision actuelle est figée.
+ Résumé de l'incident
+ Incident dissocié.
+ Inclure les dossiers clos
+ Inspection annulée.
+ Inspection close.
+ Inspection terminée ; les éléments non conformes ont créé des infractions.
+ Notes
+ N° d'inspection
+ Programmes d'inspection
+ Un programme associe une liste de contrôle à une fréquence et aux types d'occupation concernés ; les inspections dues en sont générées.
+ Résultat
+ Inspection planifiée.
+ Inspection commencée.
+ Inspections
+ Inspecteur
+ Inventorié le
+ {0} sources analysées, {1} candidats créés, {2} mis à jour, {3} déjà tranchés.
+ Enquêtes
+ Seuls les dossiers dont vous êtes membre sont listés. Chaque lecture d'un dossier est consignée dans le journal d'accès.
+ Référence de facture
+ Émettre un avis
+ Délivré le
+ Note
+ Juridiction
+ Boîte à clés
+ Dernière inspection
+ Dernière maintenance
+ Dernière revue
+ Dernier essai
+ Enquêteur principal
+ Tentatives d'écriture héritées
+ Lier
+ Lier un contact
+ Lier un incident
+ Contacts liés
+ Liés
+ Incidents liés
+ Le lien fige la révision de l'incident à cet instant ; les conclusions ne modifient jamais le rapport d'incident.
+ Diamètre de conduite (po)
+ Journal de maintenance
+ Maintenance enregistrée.
+ Marquer comme revu
+ Confiance de correspondance
+ Membre ajouté.
+ Membre retiré.
+ Fusionner cette occupation dans la cible ? Dangers, liens et historique sont déplacés ; cet enregistrement devient un renvoi.
+ Fusionner dans
+ Identifiant de l'occupation cible
+ Borne la plus proche
+ Nouveau recueil de codes
+ Nouvelle activité
+ Nouvelle borne
+ Nouvelle occupation
+ Nouveau permis
+ Nouveau type de permis
+ Nouveau programme
+ Nouvelle grille
+ Aucune alerte ni avertissement sur cette période.
+ Aucune pièce jointe.
+ Aucun candidat en attente. Lancez l'inventaire pour trouver les plans d'intervention et contacts à rapprocher.
+ Aucun dossier.
+ Ce programme n'a aucun élément de contrôle.
+ Aucune activité sur cette période.
+ Aucun essai de débit enregistré.
+ Aucun danger enregistré.
+ Aucune borne pour le moment.
+ Aucune inspection.
+ Aucun contact lié.
+ Aucune maintenance enregistrée.
+ Aucune occupation ne correspond.
+ Aucune revue en attente de notation.
+ Aucun permis ne correspond.
+ Aucun cycle d'examen des plans pour le moment.
+ Aucune revue notée sur cette période.
+ Aucune grille pour le moment. Un administrateur du service crée la première.
+ Aucune infraction.
+ S. O.
+ Texte de la note
+ Note enregistrée.
+ Objet
+ Avis émis.
+ Référence de l'avis
+ Occupations
+ Accès
+ {0} occupations
+ Occupation supprimée.
+ Horaires d'occupation
+ Identité et emplacement
+ Occupation fusionnée.
+ Cette occupation a été fusionnée dans
+ N° d'occupation
+ Protection incendie et réseaux
+ Occupation marquée comme revue.
+ Occupation enregistrée.
+ Rechercher un numéro, un nom ou une adresse
+ Structure
+ Dangers et tactique
+ Type d'occupation
+ S'applique aux types d'occupation
+ Numéros de type séparés par des virgules ; vide signifie tous les types.
+ Effectif admissible
+ Occupants nécessitant une assistance
+ Ouvrir un dossier
+ Vous devenez l'enquêteur principal. Ajoutez des membres après l'ouverture ; seuls les membres peuvent lire le dossier.
+ Infractions ouvertes
+ Ouvert le
+ Description de l'origine
+ Hors service
+ Motif de mise hors service
+ Événements en échec
+ Boîte d'envoi des événements
+ Plus ancien en attente
+ Événements en attente
+ Résultat
+ Sortie (po)
+ Nom du propriétaire
+ Les plans d'intervention sont encore rédigés sous Contacts. Rapprochez la table de correspondance pour transférer la propriété en écriture aux occupations.
+ Les occupations des Dossiers possèdent les plans d'intervention. Les pages Contacts et les applications lisent les projections depuis ici.
+ Propriété en écriture transférée aux occupations des Dossiers.
+ Identifiant cadastral
+ Conforme
+ Revues à noter
+ Effectué le
+ Code
+ N° de permis
+ Permis enregistré.
+ État du permis mis à jour.
+ Type de permis
+ Type de permis enregistré.
+ Types de permis
+ Permis
+ révision figée
+ Pitot (psi)
+ Résultat de l'examen
+ Examen des plans enregistré.
+ Examen des plans
+ Identifiant du point d'intérêt
+ Correspondance des plans d'intervention
+ Propriété en écriture des plans d'intervention
+ La date de revue de cette occupation est dépassée.
+ Prévention
+ Programme enregistré.
+ Le contenu protégé est masqué ; révélez-le avant cette action.
+ Protection des données appliquée
+ Revue qualité
+ L'échantillonnage sélectionne de façon déterministe des dossiers finalisés par grille ; la notation est pondérée et alimente les tendances.
+ Recommander une modification
+ Recommande de modifier le rapport d'incident
+ Les conclusions ne modifient jamais l'incident. La recommandation passe par le flux de modification du dossier.
+ Enregistrer la redevance
+ Enregistrer les conclusions
+ Enregistrer l'essai de débit
+ Enregistrer la maintenance
+ Enregistrer l'examen des plans
+ Enregistré par
+ Dossiers créés
+ Dossiers finalisés
+ Santé du déploiement
+ Télémétrie de référence pour l'activation des Dossiers : tentatives d'écriture héritées, retard de la boîte d'envoi, exécutions de Workflow, analyses et compteurs de prévention. Chaque source se dégrade en avertissement au lieu de faire échouer la page.
+ Dossiers activés
+ Dossiers en retard de revue
+ Numéro de référence
+ Renvoi ajouté.
+ Renvoi mis à jour.
+ Renvois
+ Réinspection de
+ Rejeter
+ Supprimer cette pièce jointe ?
+ Rouvrir le dossier
+ Débit requis (gpm)
+ Examen des plans requis
+ Résiduelle (psi)
+ État résultant
+ Renvoyer à l'auteur
+ Remis en service
+ Revues
+ Cycle
+ Note du relecteur
+ Notes d'examen
+ Revue en retard
+ Revue notée.
+ Examiné le
+ Type de toiture
+ Grille enregistrée.
+ Grilles
+ Lancer l'inventaire
+ Échantillonner
+ Terminées
+ En échec
+ En cours
+ Ignorées
+ {0} dossiers échantillonnés pour revue.
+ Taille de l'échantillon
+ Dossiers par passage d'échantillonnage ; la sélection est déterministe pour la grille et la période.
+ Échantillonnés
+ Échantillonné le
+ Pièces jointes en attente d'analyse
+ Pièces jointes rejetées par l'analyse
+ Analyse
+ Planifier une inspection
+ Planifier une réinspection
+ Planifiée
+ Notez chaque critère de 0 à 4 ; le total pondéré devient un pourcentage.
+ Noter la revue
+ Notés
+ Noté le
+ Section
+ {0} sections importées.
+ Remettre en service
+ Mettre hors service
+ Alerter les équipages
+ Nom du signataire
+ Nom saisi de la personne attestant l'inspection
+ Détecteurs de fumée installés
+ Sprinkleurs
+ Pieds carrés
+ Personnel
+ Identifiants utilisateur séparés par des virgules des membres ayant participé.
+ Colonne sèche
+ Commencer l'inspection
+ Commencée
+ Statique (psi)
+ Lieu de stockage
+ Niveaux
+ Soumissions en attente
+ Soumissions en échec
+ Soumis le
+ Occupation suggérée
+ Le transfert est bloqué tant que l'inventaire n'a pas été exécuté, que chaque candidat n'a pas été tranché et qu'un plan d'intervention reste non rapproché.
+ Transférer la propriété en écriture aux Dossiers
+ Je comprends que les pages de plans d'intervention des Contacts et les applications deviennent des projections en lecture seule des occupations.
+ Transférer la propriété en écriture maintenant ? La modification des plans d'intervention dans Contacts s'arrête immédiatement.
+ Après le transfert, les plans d'intervention ne sont modifiés que comme occupations. Contacts et les applications continuent via des projections ; le retour arrière est une restauration de base de données, pas un simple bouton.
+ Transféré le
+ Synthèse tactique
+ Fenêtre
+ essai à faire
+ Testé le
+ Transférer la possession
+ À
+ À un tiers
+ Transféré le
+ Changer l'état
+ Tendances
+ Depuis
+ Dissocier
+ Plans d'intervention non rapprochés
+ Téléversé
+ Notes sur les réseaux
+ Validité (jours)
+ Infraction enregistrée.
+ Infraction mise à jour.
+ Infractions
+ Coupure d'eau
+ Notes sur l'alimentation en eau
+ Exécutions de Workflow
diff --git a/Core/Resgrid.Localization/Areas/User/Records/Records.it.resx b/Core/Resgrid.Localization/Areas/User/Records/Records.it.resx
index 6d37df03..1210741b 100644
--- a/Core/Resgrid.Localization/Areas/User/Records/Records.it.resx
+++ b/Core/Resgrid.Localization/Areas/User/Records/Records.it.resx
@@ -1123,6 +1123,11 @@
Assegna numero
Sequenza per stazione
Sequenza per incidente
+ Record per chiamata
+ Più di uno per chiamata
+ Uno autorevole per chiamata
+ Uno per soggetto per chiamata
+ Quanti record di questa definizione può avere una chiamata. Applicato alla creazione; un record annullato o cancellato libera il suo posto.
Azzera ogni anno
Classificazione
Conservazione (anni)
@@ -1418,4 +1423,414 @@
Lo stato della fonte è più avanti dell'assegnazione locale
Lo stato della fonte è indietro rispetto all'assegnazione locale
Mantenuto da un connettore
+ Registro accessi
+ Note di accesso
+ Aggiungi reperto
+ Aggiungi pericolo
+ Aggiungi membro
+ Aggiungi nota
+ Aggiungi segnalazione
+ Aggiungi violazione
+ Ente
+ Società di allarme
+ Centrale allarme
+ Tutti i programmi
+ Modifiche consigliate
+ Richiedente
+ E-mail del richiedente
+ Telefono del richiedente
+ Richiesto il
+ Invia richiesta
+ Approva conclusioni
+ Le conclusioni devono essere approvate da un revisore o responsabile diverso dal loro autore.
+ Allegato aggiunto.
+ Scegli un file da allegare.
+ Allegato rimosso.
+ Pubblico
+ Autorizzazioni negate
+ Punteggio medio
+ Per autore
+ Per criterio
+ Per definizione
+ Per unità
+ Annulla ispezione
+ Annullare questa ispezione? Il record resta nello storico.
+ Candidato collegato.
+ Candidato rifiutato.
+ Candidati
+ L'accesso a questo caso è limitato ai suoi membri e ogni lettura viene registrata.
+ Caso chiuso.
+ Membri del caso
+ Note del caso
+ Caso {0} aperto.
+ Caso riaperto.
+ Caso salvato.
+ Versione catalogo
+ Classificazione della causa
+ Dettaglio della causa
+ Lista di controllo
+ Un elemento per riga: chiave | testo | obbligatorio (y/n) | id sezione di codice.
+ Voce di controllo
+ Chiudi caso
+ Chiudere questo caso? Le note diventano di sola lettura.
+ Chiudi ispezione
+ Motivo della chiusura
+ Edizione
+ Sezione di codice salvata.
+ Testo della sezione
+ Sezioni di codice
+ Raccolta di norme salvata.
+ Raccolte di norme
+ Norme antincendio ed edilizie usate per le ispezioni. Le sezioni hanno gravità e termine di correzione predefiniti.
+ Raccolto da
+ Raccolto il
+ Commenti
+ Completa ispezione
+ Condizioni
+ Modello di condizioni
+ ID contatto
+ Contatto collegato.
+ Contatto scollegato.
+ Azione correttiva
+ Crea una nuova occupazione da questa fonte
+ Criteri
+ Un criterio per riga: chiave | testo | peso.
+ Punteggio (0-4)
+ Peso
+ L'inventario trova i piani preventivi, i contatti con indirizzo e i punti di interesse, li raggruppa per indirizzo e vicinanza e propone occupazioni. Decidi ogni candidato prima di passare la proprietà in scrittura ai Registri.
+ Riduzione del rischio comunitario
+ Attività eliminata.
+ Attività salvata.
+ Riepilogo del periodo
+ Custode
+ Catena di custodia
+ I trasferimenti sono solo in aggiunta; ogni passaggio indica chi ha consegnato, chi ha ricevuto, il motivo e lo stato risultante.
+ Custodia trasferita.
+ Motivo della decisione
+ Giorni per la correzione
+ Gravità predefinita
+ Elimina attività
+ Eliminare questa attività?
+ Elimina idrante
+ Eliminare questo idrante? Prove di portata e storico manutenzione vengono rimossi.
+ Elimina occupazione
+ Eliminare questa occupazione? Ispezioni, permessi e pericoli mantengono lo storico ma perdono il collegamento.
+ Scadenza
+ Modifica idrante
+ Modifica occupazione
+ Modifica permesso
+ Valido dal
+ Interruzione elettrica
+ Contatto di emergenza
+ Reperto aggiunto.
+ Reperti
+ N. reperto
+ Scade il
+ Lascia vuoto per usare la validità del tipo di permesso dall'emissione.
+ In scadenza
+ Esporta fascicolo
+ Non superato
+ Posizione attacco motopompa
+ Tariffa
+ Solo di riferimento; qui la fattura viene registrata, non incassata.
+ Tariffa pagata il
+ Tariffa registrata.
+ File
+ Conclusioni
+ Conclusioni approvate.
+ Approvate
+ In attesa di approvazione, registrate
+ Conclusioni registrate e inviate per approvazione.
+ Conclusioni restituite all'autore.
+ Allarme antincendio
+ Classe di portata
+ Portata (gpm)
+ Le prove di portata registrate aggiornano automaticamente questo valore e la classe NFPA 291.
+ La portata è calcolata come 29,83 × c × d² × √pitot e arrotondata a 10 gpm; la classe segue NFPA 291.
+ Prova di portata registrata.
+ Prove di portata
+ Frequenza (mesi)
+ Da
+ Interruzione gas
+ Codice cancello
+ Note generali sui pericoli
+ Genera ispezioni dovute
+ {0} ispezioni generate.
+ Pericolo rimosso.
+ Pericolo salvato.
+ Pericoli
+ Materiali pericolosi in loco
+ Ore
+ {0} idranti, {1} fuori servizio, {2} con prova di portata dovuta.
+ Idrante eliminato.
+ Mappa
+ Il colore segue la classe di portata NFPA 291; il nero indica fuori servizio.
+ N. idrante
+ Proprietario
+ Idrante salvato.
+ Idranti
+ Importa idranti
+ CSV con riga di intestazione: number, latitude, longitude, type, address, main_size, flow_gpm, owner. I numeri esistenti vengono aggiornati.
+ Righe non importate
+ {0} righe lette, {1} create, {2} aggiornate, {3} rifiutate.
+ Importa sezioni
+ CSV con riga di intestazione: section, title, text, severity (1-4), correction_days.
+ In servizio
+ Incidente collegato; la revisione corrente è bloccata.
+ Riepilogo dell'incidente
+ Incidente scollegato.
+ Includi chiusi
+ Ispezione annullata.
+ Ispezione chiusa.
+ Ispezione completata; le voci non superate hanno generato violazioni.
+ Note
+ N. ispezione
+ Programmi di ispezione
+ Un programma abbina una lista di controllo a una frequenza e ai tipi di occupazione a cui si applica; le ispezioni dovute vengono generate da esso.
+ Esito
+ Ispezione pianificata.
+ Ispezione avviata.
+ Ispezioni
+ Ispettore
+ Inventariato il
+ {0} fonti analizzate, {1} candidati creati, {2} aggiornati, {3} già decisi.
+ Indagini
+ Sono elencati solo i casi di cui sei membro. Ogni lettura di un caso viene registrata nel registro accessi.
+ Riferimento fattura
+ Emetti avviso
+ Rilasciato il
+ Nota
+ Giurisdizione
+ Cassetta chiavi
+ Ultima ispezione
+ Ultima manutenzione
+ Ultima revisione
+ Ultima prova
+ Investigatore capo
+ Tentativi di scrittura legacy
+ Collega
+ Collega contatto
+ Collega incidente
+ Contatti collegati
+ Collegati
+ Incidenti collegati
+ Il collegamento blocca la revisione dell'incidente in quel momento; le conclusioni non modificano mai il rapporto.
+ Diametro condotta (pollici)
+ Registro manutenzione
+ Manutenzione registrata.
+ Segna come revisionato
+ Affidabilità corrispondenza
+ Membro aggiunto.
+ Membro rimosso.
+ Unire questa occupazione nella destinazione? Pericoli, collegamenti e storico vengono spostati; questo record diventa un rimando.
+ Unisci in
+ ID occupazione di destinazione
+ Idrante più vicino
+ Nuova raccolta di norme
+ Nuova attività
+ Nuovo idrante
+ Nuova occupazione
+ Nuovo permesso
+ Nuovo tipo di permesso
+ Nuovo programma
+ Nuova griglia
+ Nessun allarme o avviso in questo intervallo.
+ Nessun allegato.
+ Nessun candidato in attesa. Esegui l’inventario per trovare piani preventivi e contatti da riconciliare.
+ Nessun caso.
+ Questo programma non ha voci di controllo.
+ Nessuna attività nel periodo.
+ Nessuna prova di portata registrata.
+ Nessun pericolo registrato.
+ Nessun idrante ancora.
+ Nessuna ispezione.
+ Nessun contatto collegato.
+ Nessuna manutenzione registrata.
+ Nessuna occupazione corrisponde.
+ Nessuna revisione in attesa di punteggio.
+ Nessun permesso corrisponde.
+ Nessun ciclo di revisione progetti ancora.
+ Nessuna revisione valutata nel periodo.
+ Nessuna griglia ancora. Un amministratore del dipartimento crea la prima.
+ Nessuna violazione.
+ N/D
+ Testo della nota
+ Nota salvata.
+ Oggetto
+ Avviso emesso.
+ Riferimento avviso
+ Occupazioni
+ Accesso
+ {0} occupazioni
+ Occupazione eliminata.
+ Orari di occupazione
+ Identità e posizione
+ Occupazione unita.
+ Questa occupazione è stata unita in
+ N. occupazione
+ Protezione antincendio e utenze
+ Occupazione segnata come revisionata.
+ Occupazione salvata.
+ Cerca numero, nome o indirizzo
+ Struttura
+ Pericoli e tattica
+ Tipo di occupazione
+ Si applica ai tipi di occupazione
+ Numeri di tipo separati da virgola; vuoto significa tutti i tipi.
+ Affollamento massimo
+ Occupanti che necessitano assistenza
+ Apri caso
+ Diventi l'investigatore capo. Aggiungi membri dopo l'apertura; solo i membri possono leggere il caso.
+ Violazioni aperte
+ Aperto il
+ Descrizione dell'origine
+ Fuori servizio
+ Motivo del fuori servizio
+ Eventi falliti
+ Coda eventi in uscita
+ Più vecchio in attesa
+ Eventi in attesa
+ Esito
+ Uscita (pollici)
+ Nome del proprietario
+ I piani preventivi sono ancora scritti in Contatti. Riconcilia la corrispondenza per passare la proprietà in scrittura alle occupazioni.
+ Le occupazioni dei Registri possiedono i piani preventivi. Le pagine Contatti e le app leggono le proiezioni da qui.
+ Proprietà in scrittura passata alle occupazioni dei Registri.
+ Particella catastale
+ Superato
+ Revisioni da valutare
+ Eseguito il
+ Codice
+ N. permesso
+ Permesso salvato.
+ Stato del permesso aggiornato.
+ Tipo di permesso
+ Tipo di permesso salvato.
+ Tipi di permesso
+ Permessi
+ revisione bloccata
+ Pitot (psi)
+ Esito della revisione
+ Revisione progetti registrata.
+ Revisione progetti
+ ID punto di interesse
+ Corrispondenza piani preventivi
+ Proprietà in scrittura dei piani preventivi
+ La data di revisione di questa occupazione è passata.
+ Prevenzione
+ Programma salvato.
+ Il contenuto protetto è nascosto; rivelalo prima di questa azione.
+ Protezione dati applicata
+ Revisione qualità
+ Il campionamento seleziona in modo deterministico i record finalizzati per griglia; il punteggio è ponderato e alimenta le tendenze.
+ Consiglia una modifica
+ Consiglia di modificare il rapporto di incidente
+ Le conclusioni non modificano mai l'incidente. La raccomandazione passa dal flusso di modifica del record.
+ Registra tariffa
+ Registra conclusioni
+ Registra prova di portata
+ Registra manutenzione
+ Registra revisione progetti
+ Registrato da
+ Record creati
+ Record finalizzati
+ Stato del rilascio
+ Telemetria di base per l'attivazione dei Registri: tentativi di scrittura legacy, ritardo della coda in uscita, esecuzioni Workflow, scansioni e contatori di prevenzione. Ogni fonte degrada a un avviso invece di far fallire la pagina.
+ Registri attivati
+ Record in ritardo per la revisione
+ Numero di riferimento
+ Segnalazione aggiunta.
+ Segnalazione aggiornata.
+ Segnalazioni
+ Reispezione di
+ Rifiuta
+ Rimuovere questo allegato?
+ Riapri caso
+ Portata richiesta (gpm)
+ Richiede revisione progetti
+ Residua (psi)
+ Stato risultante
+ Restituisci all'autore
+ Rimesso in servizio
+ Revisioni
+ Ciclo
+ Nota del revisore
+ Note di revisione
+ Revisione scaduta
+ Revisione valutata.
+ Revisionato il
+ Tipo di tetto
+ Griglia salvata.
+ Griglie
+ Esegui inventario
+ Campiona
+ Completate
+ Fallite
+ In esecuzione
+ Saltate
+ {0} record campionati per la revisione.
+ Dimensione campione
+ Record per esecuzione di campionamento; la selezione è deterministica per griglia e periodo.
+ Campionati
+ Campionato il
+ Allegati in attesa di scansione
+ Allegati rifiutati dalla scansione
+ Scansione
+ Pianifica ispezione
+ Pianifica reispezione
+ Pianificata
+ Valuta ogni criterio da 0 a 4; il totale ponderato diventa una percentuale.
+ Valuta revisione
+ Valutati
+ Valutato il
+ Sezione
+ {0} sezioni importate.
+ Rimetti in servizio
+ Metti fuori servizio
+ Avvisa le squadre
+ Nome della firma
+ Nome digitato della persona che attesta l'ispezione
+ Rilevatori di fumo installati
+ Sprinkler
+ Piedi quadrati
+ Personale
+ ID utente separati da virgola dei membri che hanno partecipato.
+ Colonna idrica
+ Avvia ispezione
+ Avviata
+ Statica (psi)
+ Luogo di conservazione
+ Piani
+ Invii in attesa
+ Invii falliti
+ Presentato il
+ Occupazione suggerita
+ Il passaggio è bloccato finché l'inventario non è stato eseguito, ogni candidato deciso e nessun piano preventivo resta non riconciliato.
+ Passa la proprietà in scrittura ai Registri
+ Comprendo che le pagine dei piani preventivi in Contatti e le app diventano proiezioni di sola lettura delle occupazioni.
+ Passare ora la proprietà in scrittura? La modifica dei piani preventivi in Contatti si interrompe subito.
+ Dopo il passaggio, i piani preventivi si modificano solo come occupazioni. Contatti e app continuano a funzionare dalle proiezioni; il ripristino è un restore del database, non un interruttore.
+ Passato il
+ Sintesi tattica
+ Finestra
+ prova dovuta
+ Testato il
+ Trasferisci custodia
+ A
+ A soggetto esterno
+ Trasferito il
+ Cambia stato
+ Tendenze
+ Da
+ Scollega
+ Piani preventivi non riconciliati
+ Caricato
+ Note sulle utenze
+ Validità (giorni)
+ Violazione salvata.
+ Violazione aggiornata.
+ Violazioni
+ Interruzione acqua
+ Note sulla fornitura idrica
+ Esecuzioni Workflow
diff --git a/Core/Resgrid.Localization/Areas/User/Records/Records.pl.resx b/Core/Resgrid.Localization/Areas/User/Records/Records.pl.resx
index 17190f5b..98820e40 100644
--- a/Core/Resgrid.Localization/Areas/User/Records/Records.pl.resx
+++ b/Core/Resgrid.Localization/Areas/User/Records/Records.pl.resx
@@ -1123,6 +1123,11 @@
Przydziel numer
Sekwencja na stację
Numeracja na zdarzenie
+ Rekordy na wezwanie
+ Wiele na wezwanie
+ Jeden wiążący na wezwanie
+ Jeden na podmiot na wezwanie
+ Ile rekordów tej definicji może mieć jedno wezwanie. Wymuszane przy tworzeniu; rekord unieważniony lub anulowany zwalnia swoje miejsce.
Resetuj co rok
Klasyfikacja
Przechowywanie (lata)
@@ -1418,4 +1423,414 @@
Status źródła wyprzedza lokalną obsadę
Status źródła jest za lokalną obsadą
Utrzymywane przez łącznik
+ Dziennik dostępu
+ Uwagi o dostępie
+ Dodaj dowód
+ Dodaj zagrożenie
+ Dodaj członka
+ Dodaj notatkę
+ Dodaj skierowanie
+ Dodaj naruszenie
+ Instytucja
+ Firma alarmowa
+ Centrala alarmowa
+ Wszystkie programy
+ Zalecane poprawki
+ Wnioskodawca
+ E-mail wnioskodawcy
+ Telefon wnioskodawcy
+ Złożono
+ Złóż wniosek
+ Zatwierdź ustalenia
+ Ustalenia musi zatwierdzić recenzent lub prowadzący inny niż ich autor.
+ Załącznik dodany.
+ Wybierz plik do załączenia.
+ Załącznik usunięty.
+ Odbiorcy
+ Odmowy autoryzacji
+ Średni wynik
+ Według autora
+ Według kryterium
+ Według definicji
+ Według jednostki
+ Anuluj kontrolę
+ Anulować tę kontrolę? Wpis pozostanie w historii.
+ Kandydat powiązany.
+ Kandydat odrzucony.
+ Kandydaci
+ Dostęp do tej sprawy mają tylko jej członkowie, a każdy odczyt jest rejestrowany.
+ Sprawa zamknięta.
+ Członkowie sprawy
+ Notatki sprawy
+ Sprawa {0} otwarta.
+ Sprawa ponownie otwarta.
+ Sprawa zapisana.
+ Wersja katalogu
+ Klasyfikacja przyczyny
+ Szczegóły przyczyny
+ Lista kontrolna
+ Jeden punkt w wierszu: klucz | tekst | wymagany (y/n) | id sekcji przepisu.
+ Punkt kontrolny
+ Zamknij sprawę
+ Zamknąć tę sprawę? Notatki staną się tylko do odczytu.
+ Zamknij kontrolę
+ Powód zamknięcia
+ Wydanie
+ Sekcja przepisu zapisana.
+ Treść sekcji
+ Sekcje przepisów
+ Zbiór przepisów zapisany.
+ Zbiory przepisów
+ Przepisy przeciwpożarowe i budowlane, według których jednostka prowadzi kontrole. Sekcje mają domyślną wagę i termin usunięcia naruszeń.
+ Zebrane z
+ Zebrano
+ Komentarze
+ Zakończ kontrolę
+ Warunki
+ Szablon warunków
+ ID kontaktu
+ Kontakt powiązany.
+ Powiązanie kontaktu usunięte.
+ Działanie naprawcze
+ Utwórz nowy obiekt z tego źródła
+ Kryteria
+ Jedno kryterium w wierszu: klucz | tekst | waga.
+ Ocena (0-4)
+ Waga
+ Inwentaryzacja znajduje plany operacyjne, kontakty z adresem i punkty POI, grupuje je według adresu i odległości oraz proponuje obiekty. Rozstrzygnij każdego kandydata przed przekazaniem własności zapisu do Rejestrów.
+ Ograniczanie ryzyka w społeczności
+ Działanie usunięte.
+ Działanie zapisane.
+ Podsumowanie okresu
+ Depozytariusz
+ Łańcuch dowodowy
+ Przekazania można tylko dopisywać; każde wskazuje, kto przekazał, kto odebrał, dlaczego i jaki jest stan wynikowy.
+ Przekazano depozyt.
+ Uzasadnienie decyzji
+ Dni na usunięcie
+ Domyślna waga
+ Usuń działanie
+ Usunąć to działanie?
+ Usuń hydrant
+ Usunąć ten hydrant? Testy wydajności i historia konserwacji zostaną usunięte.
+ Usuń obiekt
+ Usunąć ten obiekt? Kontrole, zezwolenia i zagrożenia zachowają historię, ale stracą element nadrzędny.
+ Termin
+ Edytuj hydrant
+ Edytuj obiekt
+ Edytuj zezwolenie
+ Obowiązuje od
+ Wyłącznik prądu
+ Kontakt alarmowy
+ Dowód dodany.
+ Dowody
+ Nr dowodu
+ Wygasa
+ Pozostaw puste, aby użyć ważności typu zezwolenia od daty wydania.
+ Wkrótce wygasa
+ Eksportuj pakiet
+ Niezaliczone
+ Lokalizacja nasady tłocznej
+ Opłata
+ Tylko orientacyjnie; faktura jest tu rejestrowana, nie pobierana.
+ Opłata zapłacona
+ Opłata zarejestrowana.
+ Plik
+ Ustalenia
+ Ustalenia zatwierdzone.
+ Zatwierdzone
+ Oczekują na zatwierdzenie, zapisane
+ Ustalenia zapisane i przekazane do zatwierdzenia.
+ Ustalenia zwrócone autorowi.
+ Alarm pożarowy
+ Klasa wydajności
+ Wydajność (gpm)
+ Zarejestrowane testy wydajności automatycznie aktualizują tę wartość i klasę NFPA 291.
+ Wydajność liczona jest jako 29,83 × c × d² × √pitot i zaokrąglana do 10 gpm; klasa według NFPA 291.
+ Test wydajności zarejestrowany.
+ Testy wydajności
+ Częstotliwość (miesiące)
+ Od
+ Zawór gazu
+ Kod bramy
+ Ogólne uwagi o zagrożeniach
+ Wygeneruj należne kontrole
+ Wygenerowano {0} kontroli.
+ Zagrożenie usunięte.
+ Zagrożenie zapisane.
+ Zagrożenia
+ Materiały niebezpieczne na miejscu
+ Godziny
+ {0} hydrantów, {1} wyłączonych z użytku, {2} z należnym testem wydajności.
+ Hydrant usunięty.
+ Mapa
+ Kolor odpowiada klasie wydajności NFPA 291; czarny oznacza wyłączony z użytku.
+ Nr hydrantu
+ Właściciel
+ Hydrant zapisany.
+ Hydranty
+ Importuj hydranty
+ CSV z wierszem nagłówka: number, latitude, longitude, type, address, main_size, flow_gpm, owner. Istniejące numery są aktualizowane.
+ Wiersze nie zaimportowane
+ Odczytano {0} wierszy, utworzono {1}, zaktualizowano {2}, odrzucono {3}.
+ Importuj sekcje
+ CSV z wierszem nagłówka: section, title, text, severity (1-4), correction_days.
+ Sprawny
+ Zdarzenie powiązane; bieżąca wersja została przypięta.
+ Podsumowanie zdarzenia
+ Powiązanie zdarzenia usunięte.
+ Uwzględnij zamknięte
+ Kontrola anulowana.
+ Kontrola zamknięta.
+ Kontrola zakończona; niezaliczone punkty utworzyły naruszenia.
+ Uwagi
+ Nr kontroli
+ Programy kontroli
+ Program łączy listę kontrolną z częstotliwością i typami obiektów, których dotyczy; na jego podstawie generowane są należne kontrole.
+ Wynik
+ Kontrola zaplanowana.
+ Kontrola rozpoczęta.
+ Kontrole
+ Kontroler
+ Inwentaryzacja
+ Przeskanowano {0} źródeł, utworzono {1} kandydatów, zaktualizowano {2}, {3} już rozstrzygniętych.
+ Dochodzenia
+ Widoczne są tylko sprawy, których jesteś członkiem. Każdy odczyt sprawy trafia do dziennika dostępu.
+ Numer faktury
+ Wystaw wezwanie
+ Wydano
+ Uwaga
+ Jurysdykcja
+ Skrytka na klucze
+ Ostatnia kontrola
+ Ostatnia konserwacja
+ Ostatni przegląd
+ Ostatni test
+ Prowadzący dochodzenie
+ Próby zapisu do starego systemu
+ Powiąż
+ Powiąż kontakt
+ Powiąż zdarzenie
+ Powiązane kontakty
+ Powiązane
+ Powiązane zdarzenia
+ Powiązanie przypina wersję zdarzenia z tej chwili; ustalenia nigdy nie zmieniają raportu ze zdarzenia.
+ Średnica magistrali (cale)
+ Dziennik konserwacji
+ Konserwacja zarejestrowana.
+ Oznacz jako przejrzane
+ Pewność dopasowania
+ Członek dodany.
+ Członek usunięty.
+ Scalić ten obiekt z docelowym? Zagrożenia, powiązania i historia zostaną przeniesione; ten wpis stanie się odnośnikiem.
+ Scal z
+ ID obiektu docelowego
+ Najbliższy hydrant
+ Nowy zbiór przepisów
+ Nowe działanie
+ Nowy hydrant
+ Nowy obiekt
+ Nowe zezwolenie
+ Nowy typ zezwolenia
+ Nowy program
+ Nowa rubryka
+ Brak alertów i ostrzeżeń w tym oknie.
+ Brak załączników.
+ Brak oczekujących kandydatów. Uruchom inwentaryzację, aby znaleźć plany operacyjne i kontakty do uzgodnienia.
+ Brak spraw.
+ Ten program nie ma punktów kontrolnych.
+ Brak działań w tym okresie.
+ Brak zarejestrowanych testów wydajności.
+ Brak zarejestrowanych zagrożeń.
+ Brak hydrantów.
+ Brak kontroli.
+ Brak powiązanych kontaktów.
+ Brak zarejestrowanej konserwacji.
+ Brak pasujących obiektów.
+ Brak przeglądów oczekujących na ocenę.
+ Brak pasujących zezwoleń.
+ Brak cykli przeglądu projektu.
+ Brak ocenionych przeglądów w tym okresie.
+ Brak rubryk. Pierwszą tworzy administrator jednostki.
+ Brak naruszeń.
+ Nie dot.
+ Treść notatki
+ Notatka zapisana.
+ Temat
+ Wezwanie wystawione.
+ Numer wezwania
+ Obiekty
+ Dostęp
+ Obiekty: {0}
+ Obiekt usunięty.
+ Godziny użytkowania
+ Tożsamość i lokalizacja
+ Obiekt scalony.
+ Ten obiekt został scalony z
+ Nr obiektu
+ Ochrona przeciwpożarowa i media
+ Obiekt oznaczony jako przejrzany.
+ Obiekt zapisany.
+ Szukaj numeru, nazwy lub adresu
+ Konstrukcja
+ Zagrożenia i taktyka
+ Typ obiektu
+ Dotyczy typów obiektów
+ Numery typów rozdzielone przecinkami; puste oznacza wszystkie typy.
+ Liczba użytkowników
+ Osoby wymagające pomocy
+ Otwórz sprawę
+ Zostaniesz prowadzącym dochodzenie. Dodaj członków po otwarciu; tylko członkowie mogą czytać sprawę.
+ Otwarte naruszenia
+ Otwarto
+ Opis miejsca powstania
+ Wyłączony z użytku
+ Powód wyłączenia
+ Nieudane zdarzenia
+ Kolejka zdarzeń wychodzących
+ Najstarsze oczekujące
+ Oczekujące zdarzenia
+ Rezultat
+ Wylot (cale)
+ Nazwa właściciela
+ Plany operacyjne nadal są edytowane w Kontaktach. Uzgodnij powiązania, aby przekazać własność zapisu obiektom.
+ Obiekty w Rejestrach są właścicielami planów operacyjnych. Strony Kontaktów i aplikacje czytają stąd projekcje.
+ Własność zapisu przekazana obiektom w Rejestrach.
+ Numer działki
+ Zaliczone
+ Przeglądy do oceny
+ Wykonano
+ Kod
+ Nr zezwolenia
+ Zezwolenie zapisane.
+ Stan zezwolenia zaktualizowany.
+ Typ zezwolenia
+ Typ zezwolenia zapisany.
+ Typy zezwoleń
+ Zezwolenia
+ przypięta wersja
+ Pitot (psi)
+ Wynik przeglądu
+ Przegląd projektu zarejestrowany.
+ Przegląd projektu
+ ID punktu POI
+ Powiązania planów operacyjnych
+ Własność zapisu planów operacyjnych
+ Termin przeglądu tego obiektu minął.
+ Prewencja
+ Program zapisany.
+ Chronione treści są ukryte; odsłoń je przed tą operacją.
+ Ochrona danych wymuszona
+ Przegląd jakości
+ Próbkowanie wybiera sfinalizowane rekordy deterministycznie dla każdej rubryki; ocena jest ważona i zasila trendy.
+ Zalecam poprawkę
+ Zaleca poprawienie raportu ze zdarzenia
+ Ustalenia nigdy nie edytują zdarzenia. Zalecenie trafia do procesu poprawki rekordu.
+ Zarejestruj opłatę
+ Zapisz ustalenia
+ Zarejestruj test wydajności
+ Zarejestruj konserwację
+ Zarejestruj przegląd projektu
+ Zarejestrował
+ Utworzone rekordy
+ Sfinalizowane rekordy
+ Kondycja wdrożenia
+ Podstawowa telemetria aktywacji Rejestrów: próby zapisu do starego systemu, opóźnienie kolejki, uruchomienia Workflow, skany i liczniki prewencji. Każde źródło degraduje do ostrzeżenia zamiast psuć stronę.
+ Rejestry aktywne
+ Rekordy z zaległym przeglądem
+ Numer referencyjny
+ Skierowanie dodane.
+ Skierowanie zaktualizowane.
+ Skierowania
+ Ponowna kontrola
+ Odrzuć
+ Usunąć ten załącznik?
+ Otwórz ponownie
+ Wymagana wydajność (gpm)
+ Wymaga przeglądu projektu
+ Resztkowe (psi)
+ Stan wynikowy
+ Zwróć autorowi
+ Przywrócono do użytku
+ Przeglądy
+ Cykl
+ Uwaga recenzenta
+ Uwagi z przeglądu
+ Zaległy przegląd
+ Przegląd oceniony.
+ Przejrzano
+ Typ dachu
+ Rubryka zapisana.
+ Rubryki
+ Uruchom inwentaryzację
+ Próbkuj
+ Ukończone
+ Nieudane
+ W toku
+ Pominięte
+ Wylosowano {0} rekordów do przeglądu.
+ Wielkość próby
+ Rekordy na jedno próbkowanie; wybór jest deterministyczny dla rubryki i okresu.
+ Wylosowane
+ Wylosowano
+ Załączniki oczekujące na skan
+ Załączniki odrzucone przez skan
+ Skan
+ Zaplanuj kontrolę
+ Zaplanuj ponowną kontrolę
+ Zaplanowano
+ Oceń każde kryterium od 0 do 4; ważona suma staje się wartością procentową.
+ Oceń przegląd
+ Ocenione
+ Oceniono
+ Sekcja
+ Zaimportowano {0} sekcji.
+ Przywróć do użytku
+ Wyłącz z użytku
+ Ostrzegaj załogi
+ Imię i nazwisko podpisującego
+ Wpisane imię i nazwisko osoby potwierdzającej kontrolę
+ Zainstalowane czujki dymu
+ Instalacja tryskaczowa
+ Stopy kwadratowe
+ Personel
+ Rozdzielone przecinkami identyfikatory użytkowników, którzy brali udział.
+ Pion hydrantowy
+ Rozpocznij kontrolę
+ Rozpoczęto
+ Statyczne (psi)
+ Miejsce przechowywania
+ Kondygnacje
+ Oczekujące przesłania
+ Nieudane przesłania
+ Złożono
+ Sugerowany obiekt
+ Przełączenie jest zablokowane, dopóki nie uruchomiono inwentaryzacji, nie rozstrzygnięto każdego kandydata i pozostaje nieuzgodniony plan operacyjny.
+ Przekaż własność zapisu do Rejestrów
+ Rozumiem, że strony planów operacyjnych w Kontaktach i aplikacje staną się projekcjami obiektów tylko do odczytu.
+ Przekazać własność zapisu teraz? Edycja planów operacyjnych w Kontaktach natychmiast się zakończy.
+ Po przełączeniu plany operacyjne edytuje się tylko jako obiekty. Kontakty i aplikacje działają dalej na projekcjach; wycofanie to przywrócenie bazy danych, nie przełącznik.
+ Przełączono
+ Podsumowanie taktyczne
+ Okno
+ test należny
+ Testowano
+ Przekaż depozyt
+ Do
+ Do podmiotu zewnętrznego
+ Przekazano
+ Zmień stan
+ Trendy
+ Od
+ Usuń powiązanie
+ Nieuzgodnione plany operacyjne
+ Przesłano
+ Uwagi o mediach
+ Ważność (dni)
+ Naruszenie zapisane.
+ Naruszenie zaktualizowane.
+ Naruszenia
+ Zawór wody
+ Uwagi o zaopatrzeniu w wodę
+ Uruchomienia Workflow
diff --git a/Core/Resgrid.Localization/Areas/User/Records/Records.sv.resx b/Core/Resgrid.Localization/Areas/User/Records/Records.sv.resx
index b5b1fd40..4f42f0b2 100644
--- a/Core/Resgrid.Localization/Areas/User/Records/Records.sv.resx
+++ b/Core/Resgrid.Localization/Areas/User/Records/Records.sv.resx
@@ -1123,6 +1123,11 @@
Tilldela nummer
Sekvens per station
Sekvens per insats
+ Poster per larm
+ Flera per larm
+ En auktoritativ per larm
+ En per subjekt per larm
+ Hur många poster av den här definitionen ett larm får ha. Kontrolleras vid skapande; en ogiltigförklarad eller avbruten post frigör sin plats.
Återställ årligen
Klassificering
Bevarande (år)
@@ -1418,4 +1423,414 @@
Källans status ligger före den lokala tillsättningen
Källans status ligger efter den lokala tillsättningen
Underhålls av en koppling
+ Åtkomstlogg
+ Åtkomstanteckningar
+ Lägg till bevis
+ Lägg till fara
+ Lägg till medlem
+ Lägg till anteckning
+ Lägg till hänvisning
+ Lägg till överträdelse
+ Myndighet
+ Larmbolag
+ Larmcentral
+ Alla program
+ Rekommenderade ändringar
+ Sökande
+ Sökandens e-post
+ Sökandens telefon
+ Ansökt
+ Skicka ansökan
+ Godkänn slutsatser
+ Slutsatserna måste godkännas av en granskare eller ansvarig som inte är författaren.
+ Bilaga tillagd.
+ Välj en fil att bifoga.
+ Bilaga borttagen.
+ Publik
+ Nekade behörigheter
+ Genomsnittlig poäng
+ Per författare
+ Per kriterium
+ Per definition
+ Per enhet
+ Avbryt tillsyn
+ Avbryta denna tillsyn? Posten finns kvar i historiken.
+ Kandidat länkad.
+ Kandidat avvisad.
+ Kandidater
+ Åtkomst till ärendet är begränsad till dess medlemmar och varje läsning loggas.
+ Ärende stängt.
+ Ärendemedlemmar
+ Ärendeanteckningar
+ Ärende {0} öppnat.
+ Ärende återöppnat.
+ Ärende sparat.
+ Katalogversion
+ Orsaksklassificering
+ Orsaksdetalj
+ Checklista
+ Ett objekt per rad: nyckel | text | obligatorisk (y/n) | id för regelavsnitt.
+ Kontrollpunkt
+ Stäng ärende
+ Stänga ärendet? Anteckningarna blir skrivskyddade.
+ Avsluta tillsyn
+ Orsak till stängning
+ Utgåva
+ Regelavsnitt sparat.
+ Avsnittstext
+ Regelavsnitt
+ Regelverk sparat.
+ Regelverk
+ Brand- och byggregler som tillsynen utgår från. Avsnitten har standardallvarlighet och rättelsetid för överträdelser.
+ Insamlat från
+ Insamlat
+ Kommentarer
+ Slutför tillsyn
+ Villkor
+ Villkorsmall
+ Kontakt-ID
+ Kontakt länkad.
+ Kontakt avlänkad.
+ Åtgärd
+ Skapa ett nytt objekt från denna källa
+ Kriterier
+ Ett kriterium per rad: nyckel | text | vikt.
+ Poäng (0-4)
+ Vikt
+ Inventeringen hittar insatsplaner, kontakter med adress och intressepunkter, grupperar dem efter adress och närhet och föreslår objekt. Avgör varje kandidat innan skrivägandet flyttas till Register.
+ Riskminskning i samhället
+ Aktivitet borttagen.
+ Aktivitet sparad.
+ Sammanfattning för perioden
+ Förvarare
+ Spårbarhetskedja
+ Överlämningar kan bara läggas till; varje överlämning anger vem som lämnade, vem som tog emot, varför och resulterande tillstånd.
+ Förvaring överlämnad.
+ Beslutsmotivering
+ Rättelsedagar
+ Standardallvarlighet
+ Ta bort aktivitet
+ Ta bort aktiviteten?
+ Ta bort brandpost
+ Ta bort brandposten? Flödestester och underhållshistorik försvinner.
+ Ta bort objekt
+ Ta bort objektet? Tillsyner, tillstånd och faror behåller historiken men förlorar sin överordnade post.
+ Förfaller
+ Redigera brandpost
+ Redigera objekt
+ Redigera tillstånd
+ Gäller från
+ Elavstängning
+ Nödkontakt
+ Bevis tillagt.
+ Bevis
+ Bevisnr
+ Går ut
+ Lämna tomt för att använda tillståndstypens giltighet från utfärdandet.
+ Går snart ut
+ Exportera paket
+ Underkänd
+ Placering av stigarledning
+ Avgift
+ Endast referens; fakturering registreras här men drivs inte in.
+ Avgift betald
+ Avgift registrerad.
+ Fil
+ Slutsatser
+ Slutsatser godkända.
+ Godkända
+ Väntar på godkännande, registrerade
+ Slutsatser registrerade och skickade för godkännande.
+ Slutsatser återsända till författaren.
+ Brandlarm
+ Flödesklass
+ Flöde (gpm)
+ Registrerade flödestester uppdaterar värdet och NFPA 291-klassen automatiskt.
+ Flödet beräknas som 29,83 × c × d² × √pitot och avrundas till 10 gpm; klassen följer NFPA 291.
+ Flödestest registrerat.
+ Flödestester
+ Intervall (månader)
+ Från
+ Gasavstängning
+ Grindkod
+ Allmänna faroanteckningar
+ Skapa förfallna tillsyner
+ {0} tillsyner skapade.
+ Fara borttagen.
+ Fara sparad.
+ Faror
+ Farligt gods på plats
+ Timmar
+ {0} brandposter, {1} ur drift, {2} med förfallet flödestest.
+ Brandpost borttagen.
+ Karta
+ Färgen följer NFPA 291-flödesklassen; svart betyder ur drift.
+ Brandpostnr
+ Ägare
+ Brandpost sparad.
+ Brandposter
+ Importera brandposter
+ CSV med rubrikrad: number, latitude, longitude, type, address, main_size, flow_gpm, owner. Befintliga nummer uppdateras.
+ Rader som inte importerades
+ {0} rader lästa, {1} skapade, {2} uppdaterade, {3} avvisade.
+ Importera avsnitt
+ CSV med rubrikrad: section, title, text, severity (1-4), correction_days.
+ I drift
+ Incident länkad; nuvarande revision är låst.
+ Incidentsammanfattning
+ Incident avlänkad.
+ Inkludera stängda
+ Tillsyn avbruten.
+ Tillsyn avslutad.
+ Tillsyn slutförd; underkända punkter skapade överträdelser.
+ Anteckningar
+ Tillsynsnr
+ Tillsynsprogram
+ Ett program kopplar en checklista till ett intervall och de objekttyper det gäller; förfallna tillsyner skapas från det.
+ Resultat
+ Tillsyn planerad.
+ Tillsyn påbörjad.
+ Tillsyner
+ Inspektör
+ Inventerat
+ {0} källor genomsökta, {1} kandidater skapade, {2} uppdaterade, {3} redan avgjorda.
+ Utredningar
+ Bara ärenden du är medlem i visas. Varje läsning av ett ärende skrivs till åtkomstloggen.
+ Fakturareferens
+ Utfärda föreläggande
+ Utfärdat
+ Anteckning
+ Jurisdiktion
+ Nyckelskåp
+ Senast inspekterad
+ Senast underhållen
+ Senast granskad
+ Senast testad
+ Huvudutredare
+ Skrivförsök mot gamla systemet
+ Länka
+ Länka kontakt
+ Länka incident
+ Länkade kontakter
+ Länkade
+ Länkade incidenter
+ Länkningen låser incidentrevisionen vid det tillfället; slutsatser ändrar aldrig incidentrapporten.
+ Ledningsdimension (tum)
+ Underhållslogg
+ Underhåll registrerat.
+ Markera som granskad
+ Matchningssäkerhet
+ Medlem tillagd.
+ Medlem borttagen.
+ Slå ihop objektet med målet? Faror, länkar och historik flyttas; denna post blir en hänvisning.
+ Slå ihop med
+ Målobjektets ID
+ Närmaste brandpost
+ Nytt regelverk
+ Ny aktivitet
+ Ny brandpost
+ Nytt objekt
+ Nytt tillstånd
+ Ny tillståndstyp
+ Nytt program
+ Ny bedömningsmall
+ Inga larm eller varningar i detta fönster.
+ Inga bilagor.
+ Inga kandidater väntar. Kör inventeringen för att hitta insatsplaner och kontakter att stämma av.
+ Inga ärenden.
+ Programmet har inga kontrollpunkter.
+ Inga aktiviteter under perioden.
+ Inga flödestester registrerade.
+ Inga faror registrerade.
+ Inga brandposter ännu.
+ Inga tillsyner.
+ Inga länkade kontakter.
+ Inget underhåll registrerat.
+ Inga objekt matchar.
+ Inga granskningar väntar på poängsättning.
+ Inga tillstånd matchar.
+ Inga granskningsomgångar ännu.
+ Inga poängsatta granskningar under perioden.
+ Inga bedömningsmallar ännu. En administratör skapar den första.
+ Inga överträdelser.
+ Ej tillämpl.
+ Anteckningstext
+ Anteckning sparad.
+ Ämne
+ Föreläggande utfärdat.
+ Föreläggandereferens
+ Objekt
+ Åtkomst
+ {0} objekt
+ Objekt borttaget.
+ Verksamhetstider
+ Identitet och plats
+ Objekt sammanslaget.
+ Objektet slogs ihop med
+ Objektnr
+ Brandskydd och försörjning
+ Objekt markerat som granskat.
+ Objekt sparat.
+ Sök nummer, namn eller adress
+ Byggnad
+ Faror och taktik
+ Objekttyp
+ Gäller objekttyper
+ Typnummer avgränsade med komma; tomt betyder alla typer.
+ Personantal
+ Personer som behöver hjälp
+ Öppna ärende
+ Du blir huvudutredare. Lägg till medlemmar efter öppnandet; bara medlemmar kan läsa ärendet.
+ Öppna överträdelser
+ Öppnat
+ Beskrivning av startplats
+ Ur drift
+ Orsak till driftstopp
+ Misslyckade händelser
+ Händelseutkorg
+ Äldsta väntande
+ Väntande händelser
+ Utfall
+ Uttag (tum)
+ Ägarens namn
+ Insatsplaner skrivs fortfarande under Kontakter. Stäm av kopplingen för att flytta skrivägandet till objekt.
+ Objekt i Register äger insatsplanerna. Kontaktsidor och apparna läser projektioner härifrån.
+ Skrivägande flyttat till objekt i Register.
+ Fastighetsbeteckning
+ Godkänd
+ Granskningar att poängsätta
+ Utfört
+ Kod
+ Tillståndsnr
+ Tillstånd sparat.
+ Tillståndets status uppdaterad.
+ Tillståndstyp
+ Tillståndstyp sparad.
+ Tillståndstyper
+ Tillstånd
+ låst revision
+ Pitot (psi)
+ Granskningsutfall
+ Ritningsgranskning registrerad.
+ Ritningsgranskning
+ Intressepunkts-ID
+ Koppling av insatsplaner
+ Skrivägande för insatsplaner
+ Granskningsdatumet för objektet har passerat.
+ Förebyggande
+ Program sparat.
+ Skyddat innehåll är dolt; visa det innan denna åtgärd.
+ Dataskydd aktivt
+ Kvalitetsgranskning
+ Urvalet väljer slutförda poster deterministiskt per mall; poängen är viktad och matar trenderna.
+ Rekommendera ändring
+ Rekommenderar ändring av incidentrapporten
+ Slutsatser ändrar aldrig incidenten. Rekommendationen går via postens ändringsflöde.
+ Registrera avgift
+ Registrera slutsatser
+ Registrera flödestest
+ Registrera underhåll
+ Registrera ritningsgranskning
+ Registrerat av
+ Skapade poster
+ Slutförda poster
+ Driftstatus
+ Grundtelemetri för aktiveringen av Register: skrivförsök mot gamla systemet, utkorgsfördröjning, Workflow-körningar, skanningar och förebyggande räknare. Varje källa faller tillbaka till en varning i stället för att fälla sidan.
+ Register aktiverat
+ Poster försenade för granskning
+ Referensnummer
+ Hänvisning tillagd.
+ Hänvisning uppdaterad.
+ Hänvisningar
+ Omtillsyn av
+ Avvisa
+ Ta bort bilagan?
+ Återöppna ärende
+ Erforderligt släckvattenflöde (gpm)
+ Kräver ritningsgranskning
+ Resttryck (psi)
+ Resulterande tillstånd
+ Återsänd till författaren
+ Åter i drift
+ Granskningar
+ Omgång
+ Granskarens anteckning
+ Granskningsanteckningar
+ Försenad granskning
+ Granskning poängsatt.
+ Granskat
+ Taktyp
+ Bedömningsmall sparad.
+ Bedömningsmallar
+ Kör inventering
+ Ta stickprov
+ Slutförda
+ Misslyckade
+ Pågående
+ Överhoppade
+ {0} poster utvalda för granskning.
+ Urvalsstorlek
+ Poster per urvalskörning; urvalet är deterministiskt för mallen och perioden.
+ Utvalda
+ Utvald
+ Bilagor som väntar på skanning
+ Bilagor avvisade av skanning
+ Skanning
+ Planera tillsyn
+ Planera omtillsyn
+ Planerad
+ Poängsätt varje kriterium 0-4; den viktade summan blir en procentsats.
+ Poängsätt granskning
+ Poängsatta
+ Poängsatt
+ Avsnitt
+ {0} avsnitt importerade.
+ Åter i drift
+ Ta ur drift
+ Larma besättningar
+ Underskriftens namn
+ Inskrivet namn på den som intygar tillsynen
+ Installerade brandvarnare
+ Sprinkler
+ Kvadratfot
+ Personal
+ Kommaavgränsade användar-ID för de medlemmar som deltog.
+ Stigarledning
+ Starta tillsyn
+ Påbörjad
+ Statiskt (psi)
+ Förvaringsplats
+ Våningar
+ Väntande inskick
+ Misslyckade inskick
+ Inlämnat
+ Föreslaget objekt
+ Bytet är blockerat tills inventeringen körts, varje kandidat avgjorts och ingen insatsplan är oavstämd.
+ Flytta skrivägandet till Register
+ Jag förstår att insatsplansidorna i Kontakter och apparna blir skrivskyddade projektioner av objekt.
+ Flytta skrivägandet nu? Redigering av insatsplaner i Kontakter upphör omedelbart.
+ Efter bytet redigeras insatsplaner bara som objekt. Kontakter och apparna fortsätter via projektioner; återställning är en databasåterställning, inte en knapp.
+ Bytt
+ Taktisk sammanfattning
+ Fönster
+ test förfallet
+ Testad
+ Överlämna förvaring
+ Till
+ Till extern part
+ Överlämnat
+ Ändra status
+ Trender
+ Sedan
+ Avlänka
+ Oavstämda insatsplaner
+ Uppladdad
+ Anteckningar om försörjning
+ Giltighet (dagar)
+ Överträdelse sparad.
+ Överträdelse uppdaterad.
+ Överträdelser
+ Vattenavstängning
+ Anteckningar om vattenförsörjning
+ Workflow-körningar
diff --git a/Core/Resgrid.Localization/Areas/User/Records/Records.uk.resx b/Core/Resgrid.Localization/Areas/User/Records/Records.uk.resx
index 850355c9..6dde03de 100644
--- a/Core/Resgrid.Localization/Areas/User/Records/Records.uk.resx
+++ b/Core/Resgrid.Localization/Areas/User/Records/Records.uk.resx
@@ -1123,6 +1123,11 @@
Призначити номер
Послідовність на станцію
Послідовність за інцидентом
+ Записи на виклик
+ Кілька на виклик
+ Один авторитетний на виклик
+ Один на суб'єкта на виклик
+ Скільки записів цього визначення може мати один виклик. Перевіряється під час створення; анульований або скасований запис звільняє своє місце.
Скидати щороку
Класифікація
Зберігання (роки)
@@ -1418,4 +1423,414 @@
Статус джерела випереджає локальне заповнення
Статус джерела відстає від локального заповнення
Підтримується конектором
+ Журнал доступу
+ Примітки щодо доступу
+ Додати доказ
+ Додати небезпеку
+ Додати учасника
+ Додати нотатку
+ Додати передачу
+ Додати порушення
+ Установа
+ Охоронна компанія
+ Панель сигналізації
+ Усі програми
+ Рекомендовані виправлення
+ Заявник
+ Ел. пошта заявника
+ Телефон заявника
+ Подано
+ Подати заявку
+ Затвердити висновки
+ Висновки має затвердити рецензент або керівник, який не є їх автором.
+ Вкладення додано.
+ Виберіть файл для вкладення.
+ Вкладення видалено.
+ Аудиторія
+ Відмови в доступі
+ Середній бал
+ За автором
+ За критерієм
+ За визначенням
+ За підрозділом
+ Скасувати перевірку
+ Скасувати цю перевірку? Запис залишиться в історії.
+ Кандидата пов’язано.
+ Кандидата відхилено.
+ Кандидати
+ Доступ до цієї справи мають лише її учасники, кожне читання фіксується.
+ Справу закрито.
+ Учасники справи
+ Нотатки справи
+ Справу {0} відкрито.
+ Справу відновлено.
+ Справу збережено.
+ Версія каталогу
+ Класифікація причини
+ Деталі причини
+ Контрольний список
+ Один пункт у рядку: ключ | текст | обов’язковий (y/n) | id розділу норми.
+ Пункт перевірки
+ Закрити справу
+ Закрити цю справу? Нотатки стануть доступними лише для читання.
+ Закрити перевірку
+ Причина закриття
+ Видання
+ Розділ норми збережено.
+ Текст розділу
+ Розділи норм
+ Збірку норм збережено.
+ Збірки норм
+ Протипожежні та будівельні норми, за якими підрозділ проводить перевірки. Розділи мають типову серйозність і строк усунення порушень.
+ Зібрано з
+ Зібрано
+ Коментарі
+ Завершити перевірку
+ Умови
+ Шаблон умов
+ ID контакту
+ Контакт пов’язано.
+ Зв’язок з контактом видалено.
+ Коригувальна дія
+ Створити новий об’єкт з цього джерела
+ Критерії
+ Один критерій у рядку: ключ | текст | вага.
+ Бал (0-4)
+ Вага
+ Інвентаризація знаходить плани реагування, контакти з адресою та точки інтересу, групує їх за адресою і близькістю та пропонує об’єкти. Вирішіть кожного кандидата перед передачею права запису до Записів.
+ Зниження ризиків у громаді
+ Захід видалено.
+ Захід збережено.
+ Підсумок за період
+ Зберігач
+ Ланцюг зберігання
+ Передачі лише додаються; кожна вказує, хто передав, хто отримав, чому та кінцевий стан.
+ Зберігання передано.
+ Обґрунтування рішення
+ Днів на усунення
+ Типова серйозність
+ Видалити захід
+ Видалити цей захід?
+ Видалити гідрант
+ Видалити цей гідрант? Разом з ним зникнуть випробування витрати та історія обслуговування.
+ Видалити об’єкт
+ Видалити цей об’єкт? Перевірки, дозволи та небезпеки збережуть історію, але втратять батьківський запис.
+ Термін
+ Редагувати гідрант
+ Редагувати об’єкт
+ Редагувати дозвіл
+ Діє з
+ Вимкнення електрики
+ Контакт для екстрених випадків
+ Доказ додано.
+ Докази
+ № доказу
+ Закінчується
+ Залиште порожнім, щоб застосувати строк дії типу дозволу від дати видачі.
+ Незабаром закінчується
+ Експортувати пакет
+ Не пройдено
+ Розташування підключення насосів
+ Збір
+ Лише довідково; рахунок тут фіксується, а не стягується.
+ Збір сплачено
+ Збір зафіксовано.
+ Файл
+ Висновки
+ Висновки затверджено.
+ Затверджено
+ Очікують затвердження, зафіксовано
+ Висновки зафіксовано та надіслано на затвердження.
+ Висновки повернуто автору.
+ Пожежна сигналізація
+ Клас витрати
+ Витрата (гал/хв)
+ Зафіксовані випробування витрати автоматично оновлюють це значення та клас NFPA 291.
+ Витрата обчислюється як 29,83 × c × d² × √піто і округлюється до 10 гал/хв; клас за NFPA 291.
+ Випробування витрати зафіксовано.
+ Випробування витрати
+ Періодичність (місяці)
+ Від
+ Перекриття газу
+ Код воріт
+ Загальні примітки про небезпеки
+ Створити належні перевірки
+ Створено перевірок: {0}.
+ Небезпеку видалено.
+ Небезпеку збережено.
+ Небезпеки
+ Небезпечні матеріали на об’єкті
+ Години
+ Гідрантів: {0}, не працює: {1}, потребують випробування: {2}.
+ Гідрант видалено.
+ Карта
+ Колір відповідає класу витрати NFPA 291; чорний означає не працює.
+ № гідранта
+ Власник
+ Гідрант збережено.
+ Гідранти
+ Імпортувати гідранти
+ CSV із рядком заголовка: number, latitude, longitude, type, address, main_size, flow_gpm, owner. Наявні номери оновлюються.
+ Неімпортовані рядки
+ Прочитано рядків: {0}, створено: {1}, оновлено: {2}, відхилено: {3}.
+ Імпортувати розділи
+ CSV із рядком заголовка: section, title, text, severity (1-4), correction_days.
+ Працює
+ Інцидент пов’язано; поточну редакцію закріплено.
+ Опис інциденту
+ Зв’язок з інцидентом видалено.
+ Включно із закритими
+ Перевірку скасовано.
+ Перевірку закрито.
+ Перевірку завершено; непройдені пункти створили порушення.
+ Примітки
+ № перевірки
+ Програми перевірок
+ Програма поєднує контрольний список із періодичністю та типами об’єктів, до яких вона застосовується; з неї створюються належні перевірки.
+ Результат
+ Перевірку заплановано.
+ Перевірку розпочато.
+ Перевірки
+ Інспектор
+ Інвентаризовано
+ Переглянуто джерел: {0}, створено кандидатів: {1}, оновлено: {2}, уже вирішено: {3}.
+ Розслідування
+ Показано лише справи, учасником яких ви є. Кожне читання справи записується до журналу доступу.
+ Номер рахунку
+ Видати припис
+ Видано
+ Примітка
+ Юрисдикція
+ Ключовий сейф
+ Остання перевірка
+ Останнє обслуговування
+ Останній перегляд
+ Останнє випробування
+ Головний слідчий
+ Спроби запису в старий модуль
+ Пов’язати
+ Пов’язати контакт
+ Пов’язати інцидент
+ Пов’язані контакти
+ Пов’язано
+ Пов’язані інциденти
+ Пов’язування закріплює редакцію інциденту на той момент; висновки ніколи не змінюють звіт про інцидент.
+ Діаметр магістралі (дюйми)
+ Журнал обслуговування
+ Обслуговування зафіксовано.
+ Позначити переглянутим
+ Упевненість збігу
+ Учасника додано.
+ Учасника видалено.
+ Об’єднати цей об’єкт із цільовим? Небезпеки, зв’язки та історія переносяться; цей запис стає посиланням.
+ Об’єднати з
+ ID цільового об’єкта
+ Найближчий гідрант
+ Нова збірка норм
+ Новий захід
+ Новий гідрант
+ Новий об’єкт
+ Новий дозвіл
+ Новий тип дозволу
+ Нова програма
+ Нова рубрика
+ У цьому вікні немає сповіщень чи попереджень.
+ Немає вкладень.
+ Немає кандидатів. Запустіть інвентаризацію, щоб знайти плани реагування та контакти для узгодження.
+ Немає справ.
+ У цій програмі немає пунктів перевірки.
+ Немає заходів за цей період.
+ Випробувань витрати не зафіксовано.
+ Небезпек не зафіксовано.
+ Гідрантів ще немає.
+ Немає перевірок.
+ Немає пов’язаних контактів.
+ Обслуговування не зафіксовано.
+ Немає відповідних об’єктів.
+ Немає перевірок, що очікують оцінки.
+ Немає відповідних дозволів.
+ Циклів розгляду проєкту ще немає.
+ Немає оцінених перевірок за цей період.
+ Рубрик ще немає. Першу створює адміністратор підрозділу.
+ Немає порушень.
+ Н/З
+ Текст нотатки
+ Нотатку збережено.
+ Тема
+ Припис видано.
+ Номер припису
+ Об’єкти
+ Доступ
+ Об’єктів: {0}
+ Об’єкт видалено.
+ Години використання
+ Ідентифікація та місцезнаходження
+ Об’єкт об’єднано.
+ Цей об’єкт об’єднано з
+ № об’єкта
+ Протипожежний захист і комунікації
+ Об’єкт позначено переглянутим.
+ Об’єкт збережено.
+ Пошук за номером, назвою чи адресою
+ Будівля
+ Небезпеки й тактика
+ Тип об’єкта
+ Застосовується до типів об’єктів
+ Номери типів через кому; порожньо означає всі типи.
+ Місткість
+ Мешканці, які потребують допомоги
+ Відкрити справу
+ Ви станете головним слідчим. Додайте учасників після відкриття; читати справу можуть лише учасники.
+ Відкриті порушення
+ Відкрито
+ Опис місця виникнення
+ Не працює
+ Причина непрацездатності
+ Невдалі події
+ Черга вихідних подій
+ Найстаріша в очікуванні
+ Події в очікуванні
+ Результат
+ Вихід (дюйми)
+ Ім’я власника
+ Плани реагування досі ведуться в Контактах. Узгодьте відповідність, щоб передати право запису об’єктам.
+ Об’єкти в Записах володіють планами реагування. Сторінки Контактів і застосунки читають проєкції звідси.
+ Право запису передано об’єктам у Записах.
+ Кадастровий номер
+ Пройдено
+ Перевірки для оцінювання
+ Виконано
+ Код
+ № дозволу
+ Дозвіл збережено.
+ Стан дозволу оновлено.
+ Тип дозволу
+ Тип дозволу збережено.
+ Типи дозволів
+ Дозволи
+ закріплена редакція
+ Піто (psi)
+ Результат розгляду
+ Розгляд проєкту зафіксовано.
+ Розгляд проєкту
+ ID точки інтересу
+ Відповідність планів реагування
+ Право запису планів реагування
+ Дата перегляду цього об’єкта минула.
+ Профілактика
+ Програму збережено.
+ Захищений вміст приховано; розкрийте його перед цією дією.
+ Захист даних увімкнено
+ Перевірка якості
+ Вибірка детерміновано добирає завершені записи за рубрикою; оцінка зважена та формує тенденції.
+ Рекомендувати виправлення
+ Рекомендує виправити звіт про інцидент
+ Висновки ніколи не редагують інцидент. Рекомендація передається через процес виправлення запису.
+ Зафіксувати збір
+ Зафіксувати висновки
+ Зафіксувати випробування витрати
+ Зафіксувати обслуговування
+ Зафіксувати розгляд проєкту
+ Зафіксував
+ Створено записів
+ Завершено записів
+ Стан випуску
+ Базова телеметрія активації Записів: спроби запису в старий модуль, затримка черги подій, запуски Workflow, сканування та лічильники профілактики. Кожне джерело переходить у попередження замість помилки сторінки.
+ Записи активовано
+ Записи з простроченим переглядом
+ Номер посилання
+ Передачу додано.
+ Передачу оновлено.
+ Передачі
+ Повторна перевірка
+ Відхилити
+ Видалити це вкладення?
+ Відновити справу
+ Потрібна витрата води (гал/хв)
+ Потребує розгляду проєкту
+ Залишковий (psi)
+ Кінцевий стан
+ Повернути автору
+ Повернуто в роботу
+ Перевірки
+ Цикл
+ Примітка рецензента
+ Примітки розгляду
+ Прострочений перегляд
+ Перевірку оцінено.
+ Розглянуто
+ Тип даху
+ Рубрику збережено.
+ Рубрики
+ Запустити інвентаризацію
+ Вибірка
+ Завершено
+ Невдалі
+ Виконуються
+ Пропущено
+ Відібрано записів для перевірки: {0}.
+ Розмір вибірки
+ Записів на одну вибірку; добір детермінований для рубрики та періоду.
+ Відібрано
+ Відібрано
+ Вкладення, що очікують сканування
+ Вкладення, відхилені скануванням
+ Сканування
+ Запланувати перевірку
+ Запланувати повторну перевірку
+ Заплановано
+ Оцініть кожен критерій від 0 до 4; зважена сума стає відсотком.
+ Оцінити перевірку
+ Оцінено
+ Оцінено
+ Розділ
+ Імпортовано розділів: {0}.
+ Повернути в роботу
+ Вивести з роботи
+ Сповіщати екіпажі
+ Ім’я підписанта
+ Введене ім’я особи, що засвідчує перевірку
+ Встановлено димових сповіщувачів
+ Спринклери
+ Кв. футів
+ Персонал
+ ID користувачів через кому для учасників заходу.
+ Стояк
+ Розпочати перевірку
+ Розпочато
+ Статичний (psi)
+ Місце зберігання
+ Поверхи
+ Подання в очікуванні
+ Невдалі подання
+ Подано
+ Запропонований об’єкт
+ Перемикання заблоковано, доки не виконано інвентаризацію, не вирішено кожного кандидата і залишаються неузгоджені плани.
+ Передати право запису до Записів
+ Я розумію, що сторінки планів реагування в Контактах і застосунки стають проєкціями об’єктів лише для читання.
+ Передати право запису зараз? Редагування планів реагування в Контактах припиниться негайно.
+ Після перемикання плани реагування редагуються лише як об’єкти. Контакти й застосунки працюють з проєкцій; відкат означає відновлення бази даних, а не перемикач.
+ Перемкнуто
+ Тактичний підсумок
+ Вікно
+ потребує випробування
+ Випробувано
+ Передати зберігання
+ Кому
+ Зовнішній стороні
+ Передано
+ Змінити стан
+ Тенденції
+ З
+ Від’єднати
+ Неузгоджені плани реагування
+ Завантажено
+ Примітки про комунікації
+ Строк дії (днів)
+ Порушення збережено.
+ Порушення оновлено.
+ Порушення
+ Перекриття води
+ Примітки про водопостачання
+ Запуски Workflow
diff --git a/Core/Resgrid.Localization/Areas/User/Security/Security.ar.resx b/Core/Resgrid.Localization/Areas/User/Security/Security.ar.resx
index 2ce521d8..f657f845 100644
--- a/Core/Resgrid.Localization/Areas/User/Security/Security.ar.resx
+++ b/Core/Resgrid.Localization/Areas/User/Security/Security.ar.resx
@@ -390,4 +390,6 @@
من يمكنه فرض الحجز القانوني ورفعه، وهو ما يعلّق مدة الاحتفاظ ويمنع إبطال السجل.
إعادة إسناد مسودات السجلات
من يمكنه نقل مسودة سجل إلى مؤلف آخر، مثلاً عندما يكون المؤلف الأصلي غير متاح.
+ إدارة بيانات الوقاية
+ من يستطيع إنشاء وتعديل المباني وبرامج التفتيش ومجموعات القوانين وصنابير الإطفاء والتصاريح وأنشطة الحد من مخاطر المجتمع. تتطلب قراءة بيانات الوقاية الوصول إلى السجلات فقط؛ أما التحقيقات فتخضع لصلاحية السجلات المقيدة وعضوية القضية.
diff --git a/Core/Resgrid.Localization/Areas/User/Security/Security.de.resx b/Core/Resgrid.Localization/Areas/User/Security/Security.de.resx
index 615333ba..4f052996 100644
--- a/Core/Resgrid.Localization/Areas/User/Security/Security.de.resx
+++ b/Core/Resgrid.Localization/Areas/User/Security/Security.de.resx
@@ -992,4 +992,6 @@
Wer rechtliche Sperren setzen und aufheben darf; sie setzen die Aufbewahrungsfrist aus und verhindern das Annullieren eines Berichts.
Berichtsentwürfe neu zuweisen
Wer einen Berichtsentwurf einem anderen Verfasser zuweisen darf, etwa wenn der ursprüngliche Verfasser nicht verfügbar ist.
+ Präventionsdaten verwalten
+ Wer Objekte, Prüfprogramme und Vorschriftensätze, Hydranten, Genehmigungen und Aktivitäten zur Risikominderung anlegen und ändern darf. Das Lesen von Präventionsdaten erfordert nur Zugriff auf Berichte; Ermittlungen unterliegen der Berechtigung für eingeschränkte Berichte und der Fallmitgliedschaft.
diff --git a/Core/Resgrid.Localization/Areas/User/Security/Security.el.resx b/Core/Resgrid.Localization/Areas/User/Security/Security.el.resx
index 2cf68d63..46896601 100644
--- a/Core/Resgrid.Localization/Areas/User/Security/Security.el.resx
+++ b/Core/Resgrid.Localization/Areas/User/Security/Security.el.resx
@@ -437,6 +437,8 @@
Ποιος μπορεί να θέτει και να αίρει νομικές δεσμεύσεις, οι οποίες αναστέλλουν τη διατήρηση και εμποδίζουν την ακύρωση αναφοράς.
Ανάθεση πρόχειρων αναφορών σε άλλον
Ποιος μπορεί να μεταφέρει ένα πρόχειρο αναφοράς σε άλλον συντάκτη, για παράδειγμα όταν ο αρχικός συντάκτης δεν είναι διαθέσιμος.
+ Διαχείριση δεδομένων πρόληψης
+ Ποιος μπορεί να δημιουργεί και να αλλάζει κτίρια, προγράμματα επιθεώρησης και σύνολα κωδίκων, πυροσβεστικούς κρουνούς, άδειες και δράσεις μείωσης κινδύνου στην κοινότητα. Η ανάγνωση δεδομένων πρόληψης απαιτεί μόνο πρόσβαση στα Αρχεία· οι έρευνες διέπονται από το δικαίωμα περιορισμένων αρχείων και τη συμμετοχή στην υπόθεση.
diff --git a/Core/Resgrid.Localization/Areas/User/Security/Security.en.resx b/Core/Resgrid.Localization/Areas/User/Security/Security.en.resx
index dff663d5..04c8e071 100644
--- a/Core/Resgrid.Localization/Areas/User/Security/Security.en.resx
+++ b/Core/Resgrid.Localization/Areas/User/Security/Security.en.resx
@@ -437,6 +437,8 @@
Who can place and release legal holds, which suspend retention and prevent a record from being voided.
Reassign Draft Records
Who can move a draft record to a different author, for example when the original author is unavailable.
+ Manage Prevention Data
+ Who can create and change occupancies, inspection programs and code sets, hydrants, permits and community risk reduction activities. Reading prevention data needs only Records access; investigations are governed by the restricted-records permission plus case membership.
diff --git a/Core/Resgrid.Localization/Areas/User/Security/Security.es.resx b/Core/Resgrid.Localization/Areas/User/Security/Security.es.resx
index cb0c2a38..138829d2 100644
--- a/Core/Resgrid.Localization/Areas/User/Security/Security.es.resx
+++ b/Core/Resgrid.Localization/Areas/User/Security/Security.es.resx
@@ -396,6 +396,8 @@
Quién puede aplicar y levantar retenciones legales, que suspenden la retención e impiden anular un registro.
Reasignar borradores de registro
Quién puede trasladar un borrador de registro a otro autor, por ejemplo cuando el autor original no está disponible.
+ Gestionar datos de prevención
+ Quién puede crear y modificar ocupaciones, programas de inspección y conjuntos de códigos, hidrantes, permisos y actividades de reducción de riesgos comunitarios. Leer datos de prevención solo requiere acceso a Registros; las investigaciones se rigen por el permiso de registros restringidos y la pertenencia al caso.
diff --git a/Core/Resgrid.Localization/Areas/User/Security/Security.fr.resx b/Core/Resgrid.Localization/Areas/User/Security/Security.fr.resx
index 2e09bf98..1e295178 100644
--- a/Core/Resgrid.Localization/Areas/User/Security/Security.fr.resx
+++ b/Core/Resgrid.Localization/Areas/User/Security/Security.fr.resx
@@ -992,4 +992,6 @@
Qui peut poser et lever des conservations légales, qui suspendent la rétention et empêchent l'annulation d'un rapport.
Réattribuer les brouillons de rapport
Qui peut transférer un brouillon de rapport à un autre auteur, par exemple lorsque l'auteur d'origine est indisponible.
+ Gérer les données de prévention
+ Qui peut créer et modifier les occupations, les programmes d'inspection et les recueils de codes, les bornes d'incendie, les permis et les activités de réduction des risques communautaires. La lecture des données de prévention ne demande que l'accès aux dossiers ; les enquêtes relèvent de la permission des dossiers restreints et de l'appartenance au dossier.
diff --git a/Core/Resgrid.Localization/Areas/User/Security/Security.it.resx b/Core/Resgrid.Localization/Areas/User/Security/Security.it.resx
index 232dc51c..fd594503 100644
--- a/Core/Resgrid.Localization/Areas/User/Security/Security.it.resx
+++ b/Core/Resgrid.Localization/Areas/User/Security/Security.it.resx
@@ -992,4 +992,6 @@
Chi può applicare e rimuovere i vincoli legali, che sospendono la conservazione e impediscono l'invalidazione di un rapporto.
Riassegnare bozze di rapporto
Chi può trasferire una bozza di rapporto a un altro autore, ad esempio quando l'autore originale non è disponibile.
+ Gestire i dati di prevenzione
+ Chi può creare e modificare occupazioni, programmi di ispezione e raccolte di norme, idranti, permessi e attività di riduzione del rischio comunitario. La lettura dei dati di prevenzione richiede solo l'accesso ai Registri; le indagini sono regolate dal permesso sui registri riservati e dall'appartenenza al caso.
diff --git a/Core/Resgrid.Localization/Areas/User/Security/Security.pl.resx b/Core/Resgrid.Localization/Areas/User/Security/Security.pl.resx
index a43362f4..c6715970 100644
--- a/Core/Resgrid.Localization/Areas/User/Security/Security.pl.resx
+++ b/Core/Resgrid.Localization/Areas/User/Security/Security.pl.resx
@@ -992,4 +992,6 @@
Kto może nakładać i zdejmować blokady prawne, które wstrzymują retencję i uniemożliwiają unieważnienie raportu.
Przypisywanie wersji roboczych innym autorom
Kto może przekazać wersję roboczą raportu innemu autorowi, np. gdy pierwotny autor jest niedostępny.
+ Zarządzanie danymi prewencji
+ Kto może tworzyć i zmieniać obiekty, programy kontroli i zbiory przepisów, hydranty, zezwolenia oraz działania na rzecz ograniczania ryzyka w społeczności. Odczyt danych prewencji wymaga jedynie dostępu do Rejestrów; dochodzenia podlegają uprawnieniu do rejestrów zastrzeżonych i członkostwu w sprawie.
diff --git a/Core/Resgrid.Localization/Areas/User/Security/Security.sv.resx b/Core/Resgrid.Localization/Areas/User/Security/Security.sv.resx
index 76710dd2..21db8cac 100644
--- a/Core/Resgrid.Localization/Areas/User/Security/Security.sv.resx
+++ b/Core/Resgrid.Localization/Areas/User/Security/Security.sv.resx
@@ -992,4 +992,6 @@
Vem som får lägga och häva rättsliga spärrar, som pausar gallring och hindrar att en rapport ogiltigförklaras.
Omfördela rapportutkast
Vem som får flytta ett rapportutkast till en annan författare, till exempel när den ursprungliga författaren inte är tillgänglig.
+ Hantera förebyggande data
+ Vem som får skapa och ändra objekt, tillsynsprogram och regelverk, brandposter, tillstånd och aktiviteter för att minska risker i samhället. Att läsa förebyggande data kräver bara åtkomst till Register; utredningar styrs av behörigheten för begränsade register och medlemskap i ärendet.
diff --git a/Core/Resgrid.Localization/Areas/User/Security/Security.uk.resx b/Core/Resgrid.Localization/Areas/User/Security/Security.uk.resx
index 0bc30b0c..d45459ef 100644
--- a/Core/Resgrid.Localization/Areas/User/Security/Security.uk.resx
+++ b/Core/Resgrid.Localization/Areas/User/Security/Security.uk.resx
@@ -992,4 +992,6 @@
Хто може накладати та знімати юридичні утримання, які призупиняють строк зберігання та не дозволяють анулювати звіт.
Перепризначення чернеток звітів
Хто може передати чернетку звіту іншому автору, наприклад коли початковий автор недоступний.
+ Керування даними профілактики
+ Хто може створювати та змінювати об'єкти, програми перевірок і збірки норм, гідранти, дозволи та заходи зі зниження ризиків у громаді. Для читання даних профілактики достатньо доступу до Записів; розслідування регулюються дозволом на обмежені записи та членством у справі.
diff --git a/Core/Resgrid.Model/AuditLogTypes.cs b/Core/Resgrid.Model/AuditLogTypes.cs
index 7cdc342d..737d29a3 100644
--- a/Core/Resgrid.Model/AuditLogTypes.cs
+++ b/Core/Resgrid.Model/AuditLogTypes.cs
@@ -197,6 +197,12 @@ public enum AuditLogTypes
// Advanced Data Protection: a department releasing (or restoring) the step-up prompt for a
// client app. Weakening a protection control is exactly the kind of change that has to be
// answerable later, so it is audited with the before and after mask.
- DataProtectionStepUpExemptionsChanged
+ DataProtectionStepUpExemptionsChanged,
+ // Contact pre-plans and site attachments (Contacts plan Phase A, A7)
+ ContactPreplanAdded,
+ ContactPreplanUpdated,
+ ContactPreplanRemoved,
+ ContactAttachmentAdded,
+ ContactAttachmentRemoved
}
}
diff --git a/Core/Resgrid.Model/CallSiteInfo.cs b/Core/Resgrid.Model/CallSiteInfo.cs
new file mode 100644
index 00000000..bd9fa6db
--- /dev/null
+++ b/Core/Resgrid.Model/CallSiteInfo.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace Resgrid.Model
+{
+ ///
+ /// Everything a responder needs about the premises linked to a call, composed in one round trip
+ /// (Contacts plan Phase A, decision 3b). This is also the RMS NERIS authoring prefill source for
+ /// calls linked to a Contact (A8), so its shape is a consumed contract: additive changes only.
+ ///
+ public class CallSiteInfo
+ {
+ public int CallId { get; set; }
+ public int DepartmentId { get; set; }
+ public List Contacts { get; set; } = new List();
+ }
+
+ /// One linked contact's site knowledge: the contact, its pre-plan, hazards, live alert notes and file metadata.
+ public class CallSiteContactInfo
+ {
+ public Contact Contact { get; set; }
+
+ /// 0 = Primary, 1 = Additional (matches CallContact.CallContactType).
+ public int CallContactType { get; set; }
+
+ public ContactPreplan Preplan { get; set; }
+ public List Hazards { get; set; } = new List();
+
+ /// ShouldAlert notes that are not deleted and not expired.
+ public List AlertNotes { get; set; } = new List();
+
+ /// Attachment metadata only; is never loaded here.
+ public List Attachments { get; set; } = new List();
+ }
+
+ /// Lightweight per-call contact summary for list payloads (Contacts plan Phase A, decision 3a).
+ public class CallContactSummary
+ {
+ public Contact Contact { get; set; }
+ public int CallContactType { get; set; }
+ public bool HasPreplan { get; set; }
+ public int AlertNoteCount { get; set; }
+ public int HazardCount { get; set; }
+ }
+}
diff --git a/Core/Resgrid.Model/ContactAttachment.cs b/Core/Resgrid.Model/ContactAttachment.cs
new file mode 100644
index 00000000..47ee699c
--- /dev/null
+++ b/Core/Resgrid.Model/ContactAttachment.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using Newtonsoft.Json;
+
+namespace Resgrid.Model
+{
+ ///
+ /// A file attached to a Contact (site document, pre-plan PDF, floor plan, photo, drawing). Blob stored in the
+ /// row like CallAttachment/DispatchProtocolAttachment; list queries never load .
+ /// Contacts plan Phase A, decision 2.
+ ///
+ [Table("ContactAttachments")]
+ public class ContactAttachment : IEntity
+ {
+ /// Upload cap (30 MB), the same ceiling the protocol/call attachment uploads enforce.
+ public const int MaxSizeBytes = 30 * 1024 * 1024;
+
+ [Key]
+ [Required]
+ [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
+ public int ContactAttachmentId { get; set; }
+
+ [Required]
+ public string ContactId { get; set; }
+
+ [Required]
+ public int DepartmentId { get; set; }
+
+ public int ContactAttachmentType { get; set; }
+
+ /// User-facing title.
+ public string Name { get; set; }
+
+ public string FileName { get; set; }
+
+ /// MIME type.
+ public string FileType { get; set; }
+
+ public int Size { get; set; }
+
+ public byte[] Data { get; set; }
+
+ public bool IsDeleted { get; set; }
+ public DateTime AddedOn { get; set; }
+ public string AddedByUserId { get; set; }
+
+ /// ADP row marker (catalog v12): true once name, file name and bytes are enveloped.
+ public bool IsProtected { get; set; }
+
+ [NotMapped]
+ [JsonIgnore]
+ public object IdValue
+ {
+ get { return ContactAttachmentId; }
+ set { ContactAttachmentId = (int)value; }
+ }
+
+ [NotMapped]
+ public string TableName => "ContactAttachments";
+
+ [NotMapped]
+ public string IdName => "ContactAttachmentId";
+
+ [NotMapped]
+ public int IdType => 0;
+
+ [NotMapped]
+ public IEnumerable IgnoredProperties => new string[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+}
diff --git a/Core/Resgrid.Model/ContactAttachmentTypes.cs b/Core/Resgrid.Model/ContactAttachmentTypes.cs
new file mode 100644
index 00000000..af643a1f
--- /dev/null
+++ b/Core/Resgrid.Model/ContactAttachmentTypes.cs
@@ -0,0 +1,13 @@
+namespace Resgrid.Model
+{
+ /// Category of a file attached to a Contact (Contacts plan Phase A, decision 2). Append only.
+ public enum ContactAttachmentTypes
+ {
+ Document = 0,
+ PrePlan = 1,
+ FloorPlan = 2,
+ SitePhoto = 3,
+ SiteDrawing = 4,
+ Other = 5
+ }
+}
diff --git a/Core/Resgrid.Model/ContactPreplan.cs b/Core/Resgrid.Model/ContactPreplan.cs
new file mode 100644
index 00000000..6047baf4
--- /dev/null
+++ b/Core/Resgrid.Model/ContactPreplan.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using Newtonsoft.Json;
+
+namespace Resgrid.Model
+{
+ ///
+ /// Structured pre-incident plan for a Contact (NFPA 1620 core fields; Contacts plan Phase A, decision 1).
+ /// One live row per contact. The dispatch-facing structure master until the RMS occupancy master lands,
+ /// after which it becomes the lightweight projection (RMS plan section 4.3).
+ ///
+ public class ContactPreplan : IEntity
+ {
+ [Required]
+ public string ContactPreplanId { get; set; }
+
+ [Required]
+ public int DepartmentId { get; set; }
+
+ [Required]
+ public string ContactId { get; set; }
+
+ // Construction / occupancy
+ public int ConstructionType { get; set; }
+ public int RoofType { get; set; }
+ public int OccupancyType { get; set; }
+ public string OccupancyNotes { get; set; }
+ public string OccupancyHours { get; set; }
+ public int? OccupantLoad { get; set; }
+ public bool HasOccupantsNeedingAssistance { get; set; }
+ public string OccupantsNeedingAssistanceNotes { get; set; }
+
+ // Utilities
+ public string GasShutoffLocation { get; set; }
+ public string ElectricShutoffLocation { get; set; }
+ public string WaterShutoffLocation { get; set; }
+ public string UtilityNotes { get; set; }
+
+ // Access
+ public string KnoxBoxLocation { get; set; }
+
+ ///
+ /// ADP catalog v12 field (contactpreplans.gatecode): enveloped at rest in a protected department and
+ /// revealed only through the protected read with a current grant. Never written to search, workflow
+ /// payloads, or audit snapshots in clear.
+ ///
+ public string GateCode { get; set; }
+ public string AlarmPanelLocation { get; set; }
+ public string AlarmCompany { get; set; }
+ public string AlarmCompanyPhone { get; set; }
+ public string AccessNotes { get; set; }
+
+ // Water supply
+ public string NearestHydrantLocation { get; set; }
+ public int? RequiredFireFlowGpm { get; set; }
+ public string WaterSupplyNotes { get; set; }
+
+ // On-site contacts
+ public string EmergencyContactName { get; set; }
+ public string EmergencyContactPhone { get; set; }
+ public string SecondaryContactName { get; set; }
+ public string SecondaryContactPhone { get; set; }
+
+ // Hazards / tactics
+ public bool HazmatOnSite { get; set; }
+ public string GeneralHazardNotes { get; set; }
+ public string TacticalSummary { get; set; }
+
+ // Review cycle
+ public DateTime? LastReviewedOn { get; set; }
+ public string ReviewedByUserId { get; set; }
+ public DateTime? NextReviewDue { get; set; }
+
+ public bool IsDeleted { get; set; }
+ public DateTime AddedOn { get; set; }
+ public string AddedByUserId { get; set; }
+ public DateTime? EditedOn { get; set; }
+ public string EditedByUserId { get; set; }
+
+ /// ADP row marker (catalog v12): true once the cataloged text columns are enveloped.
+ public bool IsProtected { get; set; }
+
+ [NotMapped]
+ public List Hazards { get; set; }
+
+ [NotMapped]
+ public string TableName => "ContactPreplans";
+
+ [NotMapped]
+ public string IdName => "ContactPreplanId";
+
+ [NotMapped]
+ public int IdType => 1;
+
+ [NotMapped]
+ [JsonIgnore]
+ public object IdValue
+ {
+ get { return ContactPreplanId; }
+ set { ContactPreplanId = (string)value; }
+ }
+
+ [NotMapped]
+ public IEnumerable IgnoredProperties => new string[] { "IdValue", "IdType", "TableName", "IdName", "Hazards" };
+
+ /// True when a review date is set and has passed.
+ public bool IsReviewOverdue(DateTime utcNow)
+ {
+ return NextReviewDue.HasValue && NextReviewDue.Value < utcNow;
+ }
+ }
+}
diff --git a/Core/Resgrid.Model/ContactPreplanEnums.cs b/Core/Resgrid.Model/ContactPreplanEnums.cs
new file mode 100644
index 00000000..3f0b4651
--- /dev/null
+++ b/Core/Resgrid.Model/ContactPreplanEnums.cs
@@ -0,0 +1,80 @@
+namespace Resgrid.Model
+{
+ ///
+ /// Building construction classification for a contact pre-plan (Contacts plan Phase A, decision 28 / A8).
+ /// Values follow the IBC/NFPA 220 construction types so each maps 1:1 onto the NERIS structure value set
+ /// through the RMS-owned crosswalk; there is deliberately no combined bucket. Append only.
+ ///
+ public enum ContactPreplanConstructionTypes
+ {
+ Unknown = 0,
+ TypeIFireResistive = 1,
+ TypeIINonCombustible = 2,
+ TypeIIIOrdinary = 3,
+ TypeIVHeavyTimber = 4,
+ TypeVWoodFrame = 5,
+ ManufacturedOrMobile = 6,
+ Other = 7
+ }
+
+ /// Roof form for a contact pre-plan. Append only.
+ public enum ContactPreplanRoofTypes
+ {
+ Unknown = 0,
+ Flat = 1,
+ Gable = 2,
+ Hip = 3,
+ Gambrel = 4,
+ Mansard = 5,
+ Shed = 6,
+ BowstringTruss = 7,
+ LightweightTruss = 8,
+ Other = 9
+ }
+
+ ///
+ /// Occupancy classification for a contact pre-plan, following the IBC occupancy groups (with the
+ /// residential group split the way NERIS location use distinguishes it). Append only.
+ ///
+ public enum ContactPreplanOccupancyTypes
+ {
+ Unknown = 0,
+ ResidentialSingleFamily = 1,
+ ResidentialMultiFamily = 2,
+ ResidentialLodging = 3,
+ ResidentialCareFacility = 4,
+ Assembly = 5,
+ Business = 6,
+ Educational = 7,
+ FactoryIndustrial = 8,
+ HighHazard = 9,
+ Institutional = 10,
+ Mercantile = 11,
+ Storage = 12,
+ Utility = 13,
+ Agricultural = 14,
+ Vacant = 15,
+ Other = 16
+ }
+
+ /// Premise hazard classification. Append only.
+ public enum ContactPreplanHazardTypes
+ {
+ General = 0,
+ Hazmat = 1,
+ Structural = 2,
+ Electrical = 3,
+ Biological = 4,
+ Animal = 5,
+ Occupant = 6,
+ Other = 7
+ }
+
+ /// Premise hazard severity, in ascending order.
+ public enum ContactPreplanHazardSeverities
+ {
+ Info = 0,
+ Caution = 1,
+ Danger = 2
+ }
+}
diff --git a/Core/Resgrid.Model/ContactPreplanHazard.cs b/Core/Resgrid.Model/ContactPreplanHazard.cs
new file mode 100644
index 00000000..0ab812e0
--- /dev/null
+++ b/Core/Resgrid.Model/ContactPreplanHazard.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using Newtonsoft.Json;
+
+namespace Resgrid.Model
+{
+ ///
+ /// A repeating premise hazard on a contact pre-plan (Contacts plan Phase A, decision 1). Typed severity
+ /// and optional GPS; ShouldAlert rows surface in the dispatch alert banner alongside alert notes.
+ ///
+ public class ContactPreplanHazard : IEntity
+ {
+ [Required]
+ public string ContactPreplanHazardId { get; set; }
+
+ [Required]
+ public string ContactPreplanId { get; set; }
+
+ [Required]
+ public int DepartmentId { get; set; }
+
+ /// Denormalized so hazards can be listed by contact without a join.
+ [Required]
+ public string ContactId { get; set; }
+
+ public int HazardType { get; set; }
+ public int Severity { get; set; }
+
+ [Required]
+ public string Title { get; set; }
+ public string Description { get; set; }
+ public string LocationDescription { get; set; }
+
+ /// "lat,lng" like the rest of the platform.
+ public string GpsCoordinates { get; set; }
+
+ public bool ShouldAlert { get; set; }
+
+ public bool IsDeleted { get; set; }
+ public DateTime AddedOn { get; set; }
+ public string AddedByUserId { get; set; }
+ public DateTime? EditedOn { get; set; }
+ public string EditedByUserId { get; set; }
+
+ /// ADP row marker (catalog v12): true once the cataloged text columns are enveloped.
+ public bool IsProtected { get; set; }
+
+ [NotMapped]
+ public string TableName => "ContactPreplanHazards";
+
+ [NotMapped]
+ public string IdName => "ContactPreplanHazardId";
+
+ [NotMapped]
+ public int IdType => 1;
+
+ [NotMapped]
+ [JsonIgnore]
+ public object IdValue
+ {
+ get { return ContactPreplanHazardId; }
+ set { ContactPreplanHazardId = (string)value; }
+ }
+
+ [NotMapped]
+ public IEnumerable IgnoredProperties => new string[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+}
diff --git a/Core/Resgrid.Model/FeatureFlagKeys.cs b/Core/Resgrid.Model/FeatureFlagKeys.cs
index 2a65ad0a..2d609b03 100644
--- a/Core/Resgrid.Model/FeatureFlagKeys.cs
+++ b/Core/Resgrid.Model/FeatureFlagKeys.cs
@@ -54,5 +54,26 @@ public static class FeatureFlagKeys
/// Field Records surface in the Dispatch app. Depends on Records.System. Seeded off by M0152.
public const string RecordsFieldDispatch = "Records.Field.Dispatch";
+
+ /// RMS-5 occupancy/property master and the Contacts pre-plan crosswalk. Depends on Records.System. Seeded off by M0186.
+ public const string RecordsPreventionOccupancy = "Records.Prevention.Occupancy";
+
+ /// RMS-5 inspection programs, code sets, inspections and violations. Depends on Records.Prevention.Occupancy. Seeded off by M0186.
+ public const string RecordsPreventionInspections = "Records.Prevention.Inspections";
+
+ /// RMS-5 hydrants and water sources. Depends on Records.System. Seeded off by M0186.
+ public const string RecordsPreventionHydrants = "Records.Prevention.Hydrants";
+
+ /// RMS-5 permits and plan review. Depends on Records.Prevention.Occupancy. Seeded off by M0186.
+ public const string RecordsPreventionPermits = "Records.Prevention.Permits";
+
+ /// RMS-5 community risk reduction activities. Depends on Records.System. Seeded off by M0186.
+ public const string RecordsPreventionCrr = "Records.Prevention.Crr";
+
+ /// RMS-5 investigation cases (restricted, case-level authorization). Depends on Records.System. Seeded off by M0186.
+ public const string RecordsInvestigations = "Records.Investigations";
+
+ /// RMS-4 optional post-finalization quality review. Depends on Records.System. Seeded off by M0186.
+ public const string RecordsQualityReview = "Records.QualityReview";
}
}
diff --git a/Core/Resgrid.Model/PermissionTypes.cs b/Core/Resgrid.Model/PermissionTypes.cs
index d6238210..a049a39f 100644
--- a/Core/Resgrid.Model/PermissionTypes.cs
+++ b/Core/Resgrid.Model/PermissionTypes.cs
@@ -140,7 +140,15 @@ public enum PermissionTypes
ManageRecordLegalHold = 66,
/// Reassign an unfinalized draft to another author (Record_Reassign). No-row default: department and group admins.
- ReassignRecordDrafts = 67
+ ReassignRecordDrafts = 67,
+
+ ///
+ /// Manage prevention data: occupancies, inspection programs and code sets, hydrants, permits and CRR
+ /// (Record_PreventionAdmin). No-row default: department admins. RMS-5, registry value 69 (from the pool
+ /// released on 2026-08-27; 68 is Unified Search's ManageSearchIndex). Reading prevention data needs only
+ /// Record_View; investigations use ViewRestrictedRecords (59) plus case membership, never this value.
+ ///
+ RecordsPreventionAdmin = 69
}
}
diff --git a/Core/Resgrid.Model/Records/ExternalOrderFeed.cs b/Core/Resgrid.Model/Records/ExternalOrderFeed.cs
index 08e8f784..c0ebe720 100644
--- a/Core/Resgrid.Model/Records/ExternalOrderFeed.cs
+++ b/Core/Resgrid.Model/Records/ExternalOrderFeed.cs
@@ -80,6 +80,19 @@ public static string LocalStatusOf(RmsDeploymentFillStatus status)
}
}
+ ///
+ /// A value the source controls, made safe to repeat back. A parse problem is stored on the run and shown
+ /// to an administrator, so a source cannot use it to put arbitrary text or length in front of a person:
+ /// what comes back is a short token of plain characters, or a placeholder.
+ ///
+ private static string Safe(string sourceValue)
+ {
+ if (string.IsNullOrWhiteSpace(sourceValue))
+ return "(none)";
+ var kept = new string(sourceValue.Trim().Where(c => char.IsLetterOrDigit(c) || c == '.' || c == '-' || c == '_').Take(32).ToArray());
+ return kept.Length == 0 ? "(unreadable)" : kept;
+ }
+
/// Parses and validates one feed document. Problems are returned, never thrown, so a run can log them.
public static ExternalOrderFeed Parse(string json, out List problems)
{
@@ -108,7 +121,7 @@ public static ExternalOrderFeed Parse(string json, out List problems)
}
if (!string.Equals(feed.Contract, Version, StringComparison.Ordinal))
{
- problems.Add($"The feed declares contract '{feed.Contract}'; this connector speaks '{Version}'.");
+ problems.Add($"The feed declares contract '{Safe(feed.Contract)}'; this connector speaks '{Version}'.");
return null;
}
feed.Orders ??= new List();
diff --git a/Core/Resgrid.Model/Records/FieldRecordsContracts.cs b/Core/Resgrid.Model/Records/FieldRecordsContracts.cs
index 4bed5ab2..90e80483 100644
--- a/Core/Resgrid.Model/Records/FieldRecordsContracts.cs
+++ b/Core/Resgrid.Model/Records/FieldRecordsContracts.cs
@@ -46,10 +46,16 @@ public static class ExclusionReasons
public const string Retired = "retired";
public const string NotPublished = "not_published";
public const string ProtectedDataUnavailable = "protected_data_unavailable";
+
+ ///
+ /// The server could not read the catalog this time — a transient failure, not a decision about this app
+ /// or this member. A client retries; unlike every other refusal it is not grounds for discarding a cache.
+ ///
+ public const string CatalogUnavailable = "catalog_unavailable";
public static readonly IReadOnlyList All = new[]
{
OriginNotField, ModuleDisabled, RecordsNotUsable, AppDisabled, AppVersionTooOld, NotMember, SurfaceNotEnabled, ContextNotAllowed, ContextNotVerified,
- CapabilityUnsupported, Retired, NotPublished, ProtectedDataUnavailable
+ CapabilityUnsupported, Retired, NotPublished, ProtectedDataUnavailable, CatalogUnavailable
};
}
diff --git a/Core/Resgrid.Model/Records/OccupancyDispatchProjectionV1.cs b/Core/Resgrid.Model/Records/OccupancyDispatchProjectionV1.cs
new file mode 100644
index 00000000..a97eac0b
--- /dev/null
+++ b/Core/Resgrid.Model/Records/OccupancyDispatchProjectionV1.cs
@@ -0,0 +1,166 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Resgrid.Model
+{
+ ///
+ /// The additive-stable structure projection RMS exposes to Contacts and dispatch once it owns the occupancy master
+ /// (RMS plan section 4.3: "exposes an additive-stable projection to Contacts rather than duplicating structure
+ /// data"). Fields are only ever added; is bumped when they are. Protected values ride
+ /// the REDACTED sentinel for a caller without a grant and names them, exactly like the
+ /// Contacts Phase A pre-plan payload, so every existing consumer keeps its concealment logic.
+ ///
+ public class OccupancyDispatchProjectionV1
+ {
+ public const int CurrentContractVersion = 1;
+
+ public int ContractVersion { get; set; } = CurrentContractVersion;
+ public string OccupancyId { get; set; }
+ public string OccupancyNumber { get; set; }
+ public string Name { get; set; }
+ public int Status { get; set; }
+ public string AddressText { get; set; }
+ public decimal? Latitude { get; set; }
+ public decimal? Longitude { get; set; }
+
+ public int ConstructionType { get; set; }
+ public int RoofType { get; set; }
+ public int OccupancyType { get; set; }
+ public int? Stories { get; set; }
+ public int? OccupantLoad { get; set; }
+ public string OccupancyHours { get; set; }
+ public bool HasOccupantsNeedingAssistance { get; set; }
+ public string OccupantsNeedingAssistanceNotes { get; set; }
+
+ public int SprinklerType { get; set; }
+ public bool HasStandpipe { get; set; }
+ public bool HasFireAlarm { get; set; }
+ public string FdcLocation { get; set; }
+
+ public string GasShutoffLocation { get; set; }
+ public string ElectricShutoffLocation { get; set; }
+ public string WaterShutoffLocation { get; set; }
+ public string UtilityNotes { get; set; }
+
+ public string KnoxBoxLocation { get; set; }
+ public string GateCode { get; set; }
+ public string AlarmPanelLocation { get; set; }
+ public string AlarmCompany { get; set; }
+ public string AlarmCompanyPhone { get; set; }
+ public string AccessNotes { get; set; }
+
+ public string NearestHydrantId { get; set; }
+ public string NearestHydrantNumber { get; set; }
+ public string NearestHydrantLocation { get; set; }
+ public int? RequiredFireFlowGpm { get; set; }
+ public string WaterSupplyNotes { get; set; }
+
+ public string EmergencyContactName { get; set; }
+ public string EmergencyContactPhone { get; set; }
+
+ public bool HazmatOnSite { get; set; }
+ public string GeneralHazardNotes { get; set; }
+ public string TacticalSummary { get; set; }
+ public List Hazards { get; set; } = new List();
+ public List Contacts { get; set; } = new List();
+
+ public DateTime? LastReviewedOn { get; set; }
+ public DateTime? NextReviewDue { get; set; }
+ public bool IsReviewOverdue { get; set; }
+ public DateTime? LastInspectedOn { get; set; }
+ public int OpenViolationCount { get; set; }
+ /// Source kinds that supplied at least one field (provenance summary): ContactPreplan, Contact, Poi, Records.
+ public List Sources { get; set; } = new List();
+
+ public bool IsProtected { get; set; }
+ public string ProtectedReason { get; set; }
+ public List RedactedFields { get; set; } = new List();
+
+ ///
+ /// The same structure knowledge in the Contacts Phase A pre-plan shape, so the Call Site Info tab, the v4
+ /// GetCallSiteInfo payload and the four apps keep working unchanged after a department's structure writes move
+ /// to RMS. Hazards are returned separately because the Contacts shape carries them as a list.
+ ///
+ public ContactPreplan ToContactPreplanView(string contactId, int departmentId)
+ {
+ var view = new ContactPreplan
+ {
+ ContactPreplanId = "occ:" + OccupancyId,
+ DepartmentId = departmentId,
+ ContactId = contactId,
+ ConstructionType = ConstructionType,
+ RoofType = RoofType,
+ OccupancyType = OccupancyType,
+ OccupancyHours = OccupancyHours,
+ OccupantLoad = OccupantLoad,
+ HasOccupantsNeedingAssistance = HasOccupantsNeedingAssistance,
+ OccupantsNeedingAssistanceNotes = OccupantsNeedingAssistanceNotes,
+ GasShutoffLocation = GasShutoffLocation,
+ ElectricShutoffLocation = ElectricShutoffLocation,
+ WaterShutoffLocation = WaterShutoffLocation,
+ UtilityNotes = UtilityNotes,
+ KnoxBoxLocation = KnoxBoxLocation,
+ GateCode = GateCode,
+ AlarmPanelLocation = AlarmPanelLocation,
+ AlarmCompany = AlarmCompany,
+ AlarmCompanyPhone = AlarmCompanyPhone,
+ AccessNotes = AccessNotes,
+ NearestHydrantLocation = NearestHydrantLocation ?? NearestHydrantNumber,
+ RequiredFireFlowGpm = RequiredFireFlowGpm,
+ WaterSupplyNotes = WaterSupplyNotes,
+ EmergencyContactName = EmergencyContactName,
+ EmergencyContactPhone = EmergencyContactPhone,
+ HazmatOnSite = HazmatOnSite,
+ GeneralHazardNotes = GeneralHazardNotes,
+ TacticalSummary = TacticalSummary,
+ LastReviewedOn = LastReviewedOn,
+ NextReviewDue = NextReviewDue,
+ IsProtected = IsProtected,
+ AddedOn = LastReviewedOn ?? DateTime.UtcNow
+ };
+ view.Hazards = Hazards.Select(h => h.ToContactHazardView(view, departmentId)).ToList();
+ return view;
+ }
+ }
+
+ public class OccupancyDispatchHazardV1
+ {
+ public string HazardId { get; set; }
+ public int HazardType { get; set; }
+ public int Severity { get; set; }
+ public string Title { get; set; }
+ public string Description { get; set; }
+ public string LocationDescription { get; set; }
+ public string GpsCoordinates { get; set; }
+ public bool ShouldAlert { get; set; }
+ public List RedactedFields { get; set; } = new List();
+
+ public ContactPreplanHazard ToContactHazardView(ContactPreplan preplan, int departmentId)
+ {
+ return new ContactPreplanHazard
+ {
+ ContactPreplanHazardId = "occ:" + HazardId,
+ DepartmentId = departmentId,
+ ContactPreplanId = preplan.ContactPreplanId,
+ ContactId = preplan.ContactId,
+ HazardType = HazardType,
+ Severity = Severity,
+ Title = Title,
+ Description = Description,
+ LocationDescription = LocationDescription,
+ GpsCoordinates = GpsCoordinates,
+ ShouldAlert = ShouldAlert,
+ IsProtected = RedactedFields.Count > 0,
+ AddedOn = DateTime.UtcNow
+ };
+ }
+ }
+
+ public class OccupancyDispatchContactV1
+ {
+ public string ContactId { get; set; }
+ public int Role { get; set; }
+ public bool IsPrimary { get; set; }
+ }
+}
diff --git a/Core/Resgrid.Model/Records/RecordCardinalityException.cs b/Core/Resgrid.Model/Records/RecordCardinalityException.cs
new file mode 100644
index 00000000..27230b8a
--- /dev/null
+++ b/Core/Resgrid.Model/Records/RecordCardinalityException.cs
@@ -0,0 +1,27 @@
+using System;
+
+namespace Resgrid.Model
+{
+ ///
+ /// A definition's already has its Record for this Call (plan section 5.2.1).
+ /// The existing Record is carried on the exception rather than discarded, because the answer for the author is
+ /// "here is the one that exists, open it" — not an error page.
+ ///
+ public sealed class RecordCardinalityException : InvalidOperationException
+ {
+ public RecordCardinalityException(string existingRecordId, string definitionKey, RmsRecordCardinality cardinality, string message)
+ : base(message)
+ {
+ ExistingRecordId = existingRecordId;
+ DefinitionKey = definitionKey;
+ Cardinality = cardinality;
+ }
+
+ /// The Record that already holds the key; the caller opens this instead of creating another.
+ public string ExistingRecordId { get; }
+
+ public string DefinitionKey { get; }
+
+ public RmsRecordCardinality Cardinality { get; }
+ }
+}
diff --git a/Core/Resgrid.Model/Records/RecordPermissionCatalog.cs b/Core/Resgrid.Model/Records/RecordPermissionCatalog.cs
index f9db03f2..f39f40fa 100644
--- a/Core/Resgrid.Model/Records/RecordPermissionCatalog.cs
+++ b/Core/Resgrid.Model/Records/RecordPermissionCatalog.cs
@@ -64,11 +64,13 @@ public static class RecordPermissionCatalog
new RecordPermissionDescriptor(PermissionTypes.ManageRecordReports, PermissionActions.DepartmentAdminsOnly, false, "Manage saved Record reports", everyoneOffered: false),
new RecordPermissionDescriptor(PermissionTypes.ManageRecordDisclosures, PermissionActions.DepartmentAdminsOnly, false, "Manage public-records disclosures", everyoneOffered: false),
new RecordPermissionDescriptor(PermissionTypes.ManageRecordLegalHold, PermissionActions.DepartmentAdminsOnly, false, "Place and release legal holds", everyoneOffered: false),
- new RecordPermissionDescriptor(PermissionTypes.ReassignRecordDrafts, PermissionActions.DepartmentAndGroupAdmins, true, "Reassign draft Records")
+ new RecordPermissionDescriptor(PermissionTypes.ReassignRecordDrafts, PermissionActions.DepartmentAndGroupAdmins, true, "Reassign draft Records"),
+ new RecordPermissionDescriptor(PermissionTypes.RecordsPreventionAdmin, PermissionActions.DepartmentAdminsOnly, false, "Manage prevention data (occupancies, inspections, hydrants, permits, CRR)", everyoneOffered: false)
};
public const int FirstValue = 50;
- public const int LastValue = 67;
+ /// Highest RMS value. 68 (Unified Search's ManageSearchIndex) sits inside the range and is not a Records permission; iterate , never the range.
+ public const int LastValue = 69;
public static RecordPermissionDescriptor Get(PermissionTypes type)
{
diff --git a/Core/Resgrid.Model/Records/RecordsPreventionContracts.cs b/Core/Resgrid.Model/Records/RecordsPreventionContracts.cs
new file mode 100644
index 00000000..0092c181
--- /dev/null
+++ b/Core/Resgrid.Model/Records/RecordsPreventionContracts.cs
@@ -0,0 +1,168 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace Resgrid.Model
+{
+ /// The separately enabled RMS-5 modules and the feature flag that gates each (RMS plan section 6, RMS-5).
+ public enum RecordsPreventionModule
+ {
+ Occupancy = 1,
+ Inspections = 2,
+ Hydrants = 3,
+ Permits = 4,
+ Crr = 5,
+ Investigations = 6,
+ QualityReview = 7
+ }
+
+ public static class RecordsPreventionModules
+ {
+ public static string FlagKey(RecordsPreventionModule module)
+ {
+ switch (module)
+ {
+ case RecordsPreventionModule.Occupancy: return FeatureFlagKeys.RecordsPreventionOccupancy;
+ case RecordsPreventionModule.Inspections: return FeatureFlagKeys.RecordsPreventionInspections;
+ case RecordsPreventionModule.Hydrants: return FeatureFlagKeys.RecordsPreventionHydrants;
+ case RecordsPreventionModule.Permits: return FeatureFlagKeys.RecordsPreventionPermits;
+ case RecordsPreventionModule.Crr: return FeatureFlagKeys.RecordsPreventionCrr;
+ case RecordsPreventionModule.Investigations: return FeatureFlagKeys.RecordsInvestigations;
+ case RecordsPreventionModule.QualityReview: return FeatureFlagKeys.RecordsQualityReview;
+ default: throw new ArgumentOutOfRangeException(nameof(module));
+ }
+ }
+
+ public static readonly IReadOnlyList All = new[]
+ {
+ RecordsPreventionModule.Occupancy, RecordsPreventionModule.Inspections, RecordsPreventionModule.Hydrants,
+ RecordsPreventionModule.Permits, RecordsPreventionModule.Crr, RecordsPreventionModule.Investigations, RecordsPreventionModule.QualityReview
+ };
+ }
+
+ /// Thrown when a prevention module is not enabled for the department; surfaces as 404 on the API and Web.
+ public class RecordsModuleDisabledException : InvalidOperationException
+ {
+ public RecordsModuleDisabledException(RecordsPreventionModule module)
+ : base($"The Records {module} module is not enabled for this department.")
+ {
+ Module = module;
+ }
+
+ public RecordsPreventionModule Module { get; }
+ }
+
+ /// Address folding shared by the crosswalk inventory and the occupancy master so both sides match the same way.
+ public static class AddressNormalizer
+ {
+ private static readonly Regex NonAlphanumeric = new Regex("[^A-Z0-9 ]", RegexOptions.Compiled);
+ private static readonly Regex Whitespace = new Regex(" {2,}", RegexOptions.Compiled);
+ private static readonly Dictionary Abbreviations = new Dictionary(StringComparer.Ordinal)
+ {
+ ["STREET"] = "ST", ["AVENUE"] = "AVE", ["ROAD"] = "RD", ["DRIVE"] = "DR", ["BOULEVARD"] = "BLVD", ["LANE"] = "LN",
+ ["COURT"] = "CT", ["PLACE"] = "PL", ["HIGHWAY"] = "HWY", ["PARKWAY"] = "PKWY", ["NORTH"] = "N", ["SOUTH"] = "S",
+ ["EAST"] = "E", ["WEST"] = "W", ["SUITE"] = "STE", ["APARTMENT"] = "APT", ["UNIT"] = "UNIT", ["FIRST"] = "1ST",
+ ["SECOND"] = "2ND", ["THIRD"] = "3RD"
+ };
+
+ public static string Normalize(string address)
+ {
+ if (string.IsNullOrWhiteSpace(address))
+ return null;
+ var upper = address.Normalize(NormalizationForm.FormD).ToUpperInvariant();
+ var sb = new StringBuilder(upper.Length);
+ foreach (var c in upper)
+ if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
+ sb.Append(c == ',' || c == '.' || c == '-' || c == '#' ? ' ' : c);
+ var folded = NonAlphanumeric.Replace(sb.ToString(), " ");
+ var parts = Whitespace.Replace(folded, " ").Trim().Split(' ');
+ for (var i = 0; i < parts.Length; i++)
+ if (Abbreviations.TryGetValue(parts[i], out var abbreviation))
+ parts[i] = abbreviation;
+ var result = string.Join(" ", parts).Trim();
+ return result.Length == 0 ? null : result;
+ }
+ }
+
+ /// Result of an inventory pass over the department's structure sources.
+ public class OccupancyCrosswalkInventoryResult
+ {
+ public int SourcesScanned { get; set; }
+ public int CandidatesCreated { get; set; }
+ public int CandidatesUpdated { get; set; }
+ public int Groups { get; set; }
+ public int AlreadyDecided { get; set; }
+ }
+
+ public class OccupancyReconciliationStatus
+ {
+ public RmsOccupancyOwnershipState State { get; set; }
+ public DateTime? InventoriedOn { get; set; }
+ public DateTime? SwitchedOn { get; set; }
+ public int Candidates { get; set; }
+ public int Linked { get; set; }
+ public int Rejected { get; set; }
+ public int Occupancies { get; set; }
+ /// Contact pre-plans that exist but have no Linked or Rejected crosswalk row; each blocks the switch.
+ public int UnreconciledPreplans { get; set; }
+ public bool CanSwitchToRecords => State != RmsOccupancyOwnershipState.RecordsOwned && Candidates == 0 && UnreconciledPreplans == 0 && InventoriedOn.HasValue;
+ }
+
+ /// Lightweight map-layer row for hydrants (v4 and the web map); never carries notes.
+ public class HydrantMapPoint
+ {
+ public string HydrantId { get; set; }
+ public string HydrantNumber { get; set; }
+ public int Type { get; set; }
+ public decimal Latitude { get; set; }
+ public decimal Longitude { get; set; }
+ public int FlowClass { get; set; }
+ public int? FlowGpm { get; set; }
+ public bool InService { get; set; }
+ public decimal? MainSizeInches { get; set; }
+ }
+
+ /// One line of a hydrant CSV import; parsed leniently, validated strictly.
+ public class HydrantImportRow
+ {
+ public int Line { get; set; }
+ public string HydrantNumber { get; set; }
+ public decimal Latitude { get; set; }
+ public decimal Longitude { get; set; }
+ public string Type { get; set; }
+ public string Address { get; set; }
+ public string MainSize { get; set; }
+ public string FlowGpm { get; set; }
+ public string Owner { get; set; }
+ public string Error { get; set; }
+ }
+
+ public class HydrantImportResult
+ {
+ public int RowsRead { get; set; }
+ public int Created { get; set; }
+ public int Updated { get; set; }
+ public List Rejected { get; set; } = new List();
+ }
+
+ public class PreventionSummary
+ {
+ public int Occupancies { get; set; }
+ public int OccupanciesReviewOverdue { get; set; }
+ public int InspectionsScheduled { get; set; }
+ public int InspectionsDue { get; set; }
+ public int ViolationsOpen { get; set; }
+ public int ViolationsOverdue { get; set; }
+ public int Hydrants { get; set; }
+ public int HydrantsOutOfService { get; set; }
+ public int HydrantsTestDue { get; set; }
+ public int PermitsActive { get; set; }
+ public int PermitsExpiringSoon { get; set; }
+ public int PermitsAwaitingReview { get; set; }
+ public int CrrActivitiesLast90Days { get; set; }
+ public int CrrSmokeAlarmsLast90Days { get; set; }
+ public int InvestigationCasesOpen { get; set; }
+ }
+}
diff --git a/Core/Resgrid.Model/Records/RecordsReleaseTelemetry.cs b/Core/Resgrid.Model/Records/RecordsReleaseTelemetry.cs
new file mode 100644
index 00000000..b920ac74
--- /dev/null
+++ b/Core/Resgrid.Model/Records/RecordsReleaseTelemetry.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+
+namespace Resgrid.Model
+{
+ ///
+ /// The RMS-4 baseline telemetry (RMS plan section 6, RMS-4: "legacy-write attempts, outbox lag, Workflow
+ /// run/skip/retry counts, scope-leak alerts, protected-content scans — so a problem after release is visible
+ /// rather than reported by a customer"). Counts and ages only; nothing here is record content. One snapshot per
+ /// department per read; the daily worker logs a structured line so the numbers exist in the log store too.
+ ///
+ public class RecordsReleaseTelemetry
+ {
+ public int DepartmentId { get; set; }
+ public DateTime GeneratedOn { get; set; } = DateTime.UtcNow;
+ /// Window the rolling counters cover, in hours.
+ public int WindowHours { get; set; }
+
+ public bool RecordsActive { get; set; }
+ public DateTime? ActivatedOn { get; set; }
+
+ /// Denied legacy Log/UnitLog mutation attempts inside the window (RmsAccessAudits action LegacyWriteDenied).
+ public int LegacyWriteAttempts { get; set; }
+ /// Denied Records reads/actions inside the window (RmsAccessAudits action Denied) — the runtime face of the scope-leak suite.
+ public int AuthorizationDenials { get; set; }
+
+ public int OutboxPending { get; set; }
+ public int OutboxFailed { get; set; }
+ /// Age of the oldest undispatched outbox row; the section 5.12 alert threshold is 60 sustained seconds.
+ public double? OutboxOldestPendingSeconds { get; set; }
+ public bool OutboxLagAlert { get; set; }
+
+ public int WorkflowRunsCompleted { get; set; }
+ public int WorkflowRunsSkipped { get; set; }
+ public int WorkflowRunsFailed { get; set; }
+ public int WorkflowRunsRunning { get; set; }
+
+ public int AttachmentsScanPending { get; set; }
+ public int AttachmentsScanRejected { get; set; }
+
+ public int RecordsCreated { get; set; }
+ public int RecordsFinalized { get; set; }
+ public int RecordsOverdue { get; set; }
+ public int SubmissionsFailed { get; set; }
+ public int SubmissionsAwaiting { get; set; }
+
+ /// Prevention sweep counters from the last daily run, when the modules are enabled.
+ public int InspectionsDue { get; set; }
+ public int ViolationsOverdue { get; set; }
+ public int PermitsExpiringSoon { get; set; }
+ public int HydrantsOutOfService { get; set; }
+
+ /// Whether the Records search host is configured (SearchConfig.Enabled); the index sweep reports its own health on the Settings page.
+ public bool SearchEnabled { get; set; }
+ public bool ProtectionEnforced { get; set; }
+ public int ProtectedCatalogVersion { get; set; }
+
+ public List Alerts { get; set; } = new List();
+ public List Warnings { get; set; } = new List();
+ }
+
+ /// Outcome of one prevention sweep (worker 42, daily).
+ public class RecordsPreventionSweepResult
+ {
+ public int DepartmentsEvaluated { get; set; }
+ public int InspectionsGenerated { get; set; }
+ public int ViolationsBecameOverdue { get; set; }
+ public int PermitsExpiringNotified { get; set; }
+ public int PermitsExpired { get; set; }
+ public int HydrantTestsDue { get; set; }
+ public int Errors { get; set; }
+ }
+}
diff --git a/Core/Resgrid.Model/Records/RmsInvestigations.cs b/Core/Resgrid.Model/Records/RmsInvestigations.cs
new file mode 100644
index 00000000..1bf82a91
--- /dev/null
+++ b/Core/Resgrid.Model/Records/RmsInvestigations.cs
@@ -0,0 +1,282 @@
+using System;
+using System.Collections.Generic;
+
+namespace Resgrid.Model
+{
+ public enum RmsInvestigationCaseState
+ {
+ Open = 1,
+ Active = 2,
+ /// Findings recorded; awaiting approval by a reviewer who is not their author.
+ PendingReview = 3,
+ Closed = 4
+ }
+
+ /// Case-level role (RMS plan section 4.4: "restricted investigator roles and case-level authorization").
+ public enum RmsInvestigationRole
+ {
+ Lead = 1,
+ Investigator = 2,
+ /// May approve findings; may not author them.
+ Reviewer = 3,
+ ReadOnly = 4
+ }
+
+ /// NFPA 921 cause classification.
+ public enum RmsFireCauseClassification
+ {
+ UnderInvestigation = 0,
+ Accidental = 1,
+ Natural = 2,
+ Incendiary = 3,
+ Undetermined = 4
+ }
+
+ public enum RmsInvestigationNoteKind
+ {
+ SceneNote = 1,
+ Interview = 2,
+ Observation = 3,
+ Diagram = 4,
+ Timeline = 5,
+ Other = 6
+ }
+
+ public enum RmsInvestigationEvidenceKind
+ {
+ Physical = 1,
+ Photograph = 2,
+ Document = 3,
+ Digital = 4,
+ Sample = 5
+ }
+
+ public enum RmsEvidenceState
+ {
+ Collected = 1,
+ InStorage = 2,
+ Transferred = 3,
+ Released = 4,
+ Destroyed = 5
+ }
+
+ public enum RmsReferralState
+ {
+ Sent = 1,
+ Acknowledged = 2,
+ Declined = 3,
+ Closed = 4
+ }
+
+ ///
+ /// An investigation case (RMS plan section 4.4, RMS-5). Restricted end to end: reading any part of it needs
+ /// RecordRestricted_View plus membership on the case, department administrators included. Findings are
+ /// kept apart from the official NERIS incident revision; a discrepancy is recorded as a recommended amendment and
+ /// the incident report is changed only through its own explicit amendment path.
+ ///
+ public class RmsInvestigationCase : IEntity
+ {
+ public string RmsInvestigationCaseId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ /// INV-{year}-{sequence}.
+ public string CaseNumber { get; set; }
+ public string Title { get; set; }
+ /// .
+ public int State { get; set; }
+ public DateTime OpenedOn { get; set; }
+ public string OpenedByUserId { get; set; }
+ public string LeadInvestigatorUserId { get; set; }
+ public string RmsOccupancyId { get; set; }
+ public int? CallId { get; set; }
+ public string IncidentSummary { get; set; }
+ /// .
+ public int CauseClassification { get; set; }
+ public string CauseDetail { get; set; }
+ public string OriginDescription { get; set; }
+ public string Findings { get; set; }
+ public string FindingsAuthorUserId { get; set; }
+ public DateTime? FindingsRecordedOn { get; set; }
+ public DateTime? FindingsApprovedOn { get; set; }
+ public string FindingsApprovedByUserId { get; set; }
+ /// The investigation found the official incident revision needs correcting; the amendment itself is explicit and separate.
+ public bool RecommendsIncidentAmendment { get; set; }
+ public DateTime? ClosedOn { get; set; }
+ public string ClosedByUserId { get; set; }
+ public string ClosureReason { 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; }
+
+ public bool IsClosed => State == (int)RmsInvestigationCaseState.Closed;
+
+ public object IdValue { get => RmsInvestigationCaseId; set => RmsInvestigationCaseId = (string)value; }
+ public string TableName => "RmsInvestigationCases";
+ public string IdName => "RmsInvestigationCaseId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName", "IsClosed" };
+ }
+
+ /// An incident report linked to a case, pinned to the official revision current when the link was made.
+ public class RmsInvestigationCaseIncident : IEntity
+ {
+ public string RmsInvestigationCaseIncidentId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string RmsInvestigationCaseId { get; set; }
+ /// RmsIncidentReport id (the Record).
+ public string RecordId { get; set; }
+ public string PinnedRevisionId { get; set; }
+ public string RecordNumber { get; set; }
+ public DateTime LinkedOn { get; set; }
+ public string LinkedByUserId { get; set; }
+
+ public object IdValue { get => RmsInvestigationCaseIncidentId; set => RmsInvestigationCaseIncidentId = (string)value; }
+ public string TableName => "RmsInvestigationCaseIncidents";
+ public string IdName => "RmsInvestigationCaseIncidentId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ public class RmsInvestigationCaseMember : IEntity
+ {
+ public string RmsInvestigationCaseMemberId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string RmsInvestigationCaseId { get; set; }
+ public string UserId { get; set; }
+ /// .
+ public int Role { get; set; }
+ public DateTime AddedOn { get; set; }
+ public string AddedByUserId { get; set; }
+ public DateTime? RemovedOn { get; set; }
+ public string RemovedByUserId { get; set; }
+
+ public bool IsActive => RemovedOn == null;
+
+ public object IdValue { get => RmsInvestigationCaseMemberId; set => RmsInvestigationCaseMemberId = (string)value; }
+ public string TableName => "RmsInvestigationCaseMembers";
+ public string IdName => "RmsInvestigationCaseMemberId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName", "IsActive" };
+ }
+
+ /// Scene notes, interviews, observations. Locked when the case closes; never edited after that.
+ public class RmsInvestigationNote : IEntity
+ {
+ public string RmsInvestigationNoteId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string RmsInvestigationCaseId { get; set; }
+ /// .
+ public int Kind { get; set; }
+ public DateTime OccurredOn { get; set; }
+ public string AuthorUserId { get; set; }
+ /// Interview subject or note title; personal information when it names a witness.
+ public string Subject { get; set; }
+ public string Body { get; set; }
+ public bool IsLocked { 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; }
+
+ public object IdValue { get => RmsInvestigationNoteId; set => RmsInvestigationNoteId = (string)value; }
+ public string TableName => "RmsInvestigationNotes";
+ public string IdName => "RmsInvestigationNoteId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ public class RmsInvestigationEvidence : IEntity
+ {
+ public string RmsInvestigationEvidenceId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string RmsInvestigationCaseId { get; set; }
+ /// EV-{year}-{sequence}, unique per department.
+ public string EvidenceNumber { get; set; }
+ /// .
+ public int Kind { get; set; }
+ public string Description { get; set; }
+ public DateTime CollectedOn { get; set; }
+ public string CollectedByUserId { get; set; }
+ public string CollectedFrom { get; set; }
+ /// .
+ public int State { get; set; }
+ public string CurrentCustodianUserId { get; set; }
+ public string CurrentCustodianExternal { get; set; }
+ public string StorageLocation { 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; }
+
+ public object IdValue { get => RmsInvestigationEvidenceId; set => RmsInvestigationEvidenceId = (string)value; }
+ public string TableName => "RmsInvestigationEvidence";
+ public string IdName => "RmsInvestigationEvidenceId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ /// Chain of custody: append-only, one row per hand-off.
+ public class RmsInvestigationCustody : IEntity
+ {
+ public string RmsInvestigationCustodyId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string RmsInvestigationEvidenceId { get; set; }
+ public int Sequence { get; set; }
+ public DateTime TransferredOn { get; set; }
+ public string FromUserId { get; set; }
+ public string FromExternal { get; set; }
+ public string ToUserId { get; set; }
+ public string ToExternal { get; set; }
+ public string Reason { get; set; }
+ /// after this transfer.
+ public int ResultingState { get; set; }
+ public string RecordedByUserId { get; set; }
+ public DateTime CreatedOn { get; set; }
+ public bool IsProtected { get; set; }
+ public int ProtectedCatalogVersion { get; set; }
+
+ public object IdValue { get => RmsInvestigationCustodyId; set => RmsInvestigationCustodyId = (string)value; }
+ public string TableName => "RmsInvestigationCustody";
+ public string IdName => "RmsInvestigationCustodyId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ public class RmsInvestigationReferral : IEntity
+ {
+ public string RmsInvestigationReferralId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string RmsInvestigationCaseId { get; set; }
+ public string Agency { get; set; }
+ public DateTime ReferredOn { get; set; }
+ public string ReferredByUserId { get; set; }
+ public string Reason { get; set; }
+ public string ReferenceNumber { get; set; }
+ /// .
+ public int State { 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 object IdValue { get => RmsInvestigationReferralId; set => RmsInvestigationReferralId = (string)value; }
+ public string TableName => "RmsInvestigationReferrals";
+ public string IdName => "RmsInvestigationReferralId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+}
diff --git a/Core/Resgrid.Model/Records/RmsOccupancy.cs b/Core/Resgrid.Model/Records/RmsOccupancy.cs
new file mode 100644
index 00000000..5aaa04ae
--- /dev/null
+++ b/Core/Resgrid.Model/Records/RmsOccupancy.cs
@@ -0,0 +1,324 @@
+using System;
+using System.Collections.Generic;
+
+namespace Resgrid.Model
+{
+ /// Lifecycle of an occupancy/property master row (RMS plan section 4.3, RMS-5).
+ public enum RmsOccupancyStatus
+ {
+ Active = 1,
+ Vacant = 2,
+ Demolished = 3,
+ /// Folded into another occupancy; names the survivor.
+ Merged = 4
+ }
+
+ /// Role-separated Contact links on an occupancy (plan section 4.3: site, owner, emergency-contact and bill-to are different people).
+ public enum RmsOccupancyContactRole
+ {
+ Site = 1,
+ Owner = 2,
+ EmergencyContact = 3,
+ BillTo = 4,
+ Tenant = 5,
+ PropertyManager = 6
+ }
+
+ /// Where a crosswalk candidate came from.
+ public enum RmsOccupancyCrosswalkSourceKind
+ {
+ /// A Contacts Phase A pre-plan (ContactPreplans row); the dispatch-facing structure view RMS-5 absorbs.
+ ContactPreplan = 1,
+ /// A Contact with a site address or coordinates but no pre-plan.
+ Contact = 2,
+ /// A mapping point of interest.
+ Poi = 3
+ }
+
+ /// Decision state of one crosswalk candidate.
+ public enum RmsOccupancyCrosswalkState
+ {
+ /// Inventoried, not yet decided; blocks the write cutover.
+ Candidate = 1,
+ /// Bound to an occupancy; the source keeps projecting from that occupancy.
+ Linked = 2,
+ /// Not a structure this department tracks (a person, a duplicate, a mailing address).
+ Rejected = 3,
+ /// Linked to an occupancy that was later merged; follows the survivor.
+ Merged = 4
+ }
+
+ /// Which system owns structure/occupancy writes for a department (plan section 4.3, "do not leave two editable structure masters").
+ public enum RmsOccupancyOwnershipState
+ {
+ /// Contacts pre-plans are the editable structure master; RMS occupancy is empty or read-only staging.
+ ContactsOwned = 1,
+ /// Inventory has run; candidates are being decided. Both remain readable, Contacts still writes.
+ Reconciling = 2,
+ /// RMS occupancy is the system of record; Contacts pre-plan writes are refused and Contacts reads project from it.
+ RecordsOwned = 3
+ }
+
+ /// Fire protection present at the site.
+ public enum RmsSprinklerType
+ {
+ Unknown = 0,
+ None = 1,
+ Wet = 2,
+ Dry = 3,
+ PreAction = 4,
+ Deluge = 5,
+ Partial = 6
+ }
+
+ ///
+ /// The occupancy/property master (RMS plan section 4.3, RMS-5, registry M0186): the structure the department
+ /// pre-plans, inspects, permits and investigates. Access secrets, hazard text and contact names are ADP catalog
+ /// v13 fields; construction/occupancy codes, flags, counts and review dates stay plaintext so dispatch badges,
+ /// inspection scheduling and the NERIS crosswalk work without a grant.
+ ///
+ public class RmsOccupancy : IEntity
+ {
+ public string RmsOccupancyId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+
+ /// Department-facing number, OCC-{year}-{sequence}.
+ public string OccupancyNumber { get; set; }
+ public string Name { get; set; }
+ /// .
+ public int Status { get; set; }
+ public string MergedIntoOccupancyId { get; set; }
+
+ public string AddressText { get; set; }
+ public string City { get; set; }
+ public string StateProvince { get; set; }
+ public string PostalCode { get; set; }
+ public string Country { get; set; }
+ /// Address folded for matching: upper case, punctuation stripped, whitespace collapsed.
+ public string NormalizedAddress { get; set; }
+ public decimal? Latitude { get; set; }
+ public decimal? Longitude { get; set; }
+ public string ParcelId { get; set; }
+
+ /// Contacts plan ConstructionTypes / RoofTypes / OccupancyTypes values (shared enums).
+ public int ConstructionType { get; set; }
+ public int RoofType { get; set; }
+ public int OccupancyType { get; set; }
+ public int? Stories { get; set; }
+ public int? YearBuilt { get; set; }
+ public int? SquareFeet { get; set; }
+ public int? OccupantLoad { get; set; }
+ public string OccupancyHours { get; set; }
+ public bool HasOccupantsNeedingAssistance { get; set; }
+ public string OccupantsNeedingAssistanceNotes { get; set; }
+
+ /// .
+ public int SprinklerType { get; set; }
+ public bool HasStandpipe { get; set; }
+ public bool HasFireAlarm { get; set; }
+ public string FdcLocation { get; set; }
+
+ public string GasShutoffLocation { get; set; }
+ public string ElectricShutoffLocation { get; set; }
+ public string WaterShutoffLocation { get; set; }
+ public string UtilityNotes { get; set; }
+
+ public string KnoxBoxLocation { get; set; }
+ public string GateCode { get; set; }
+ public string AlarmPanelLocation { get; set; }
+ public string AlarmCompany { get; set; }
+ public string AlarmCompanyPhone { get; set; }
+ public string AccessNotes { get; set; }
+
+ public string NearestHydrantId { get; set; }
+ public int? RequiredFireFlowGpm { get; set; }
+ public string WaterSupplyNotes { get; set; }
+
+ public string EmergencyContactName { get; set; }
+ public string EmergencyContactPhone { get; set; }
+
+ public bool HazmatOnSite { get; set; }
+ public string GeneralHazardNotes { get; set; }
+ public string TacticalSummary { get; set; }
+
+ /// The mapping POI this structure was created from or is pinned to, when any.
+ public int? PoiId { get; set; }
+
+ public DateTime? LastReviewedOn { get; set; }
+ public string ReviewedByUserId { get; set; }
+ public DateTime? NextReviewDue { get; set; }
+ public DateTime? LastInspectedOn { get; set; }
+
+ public bool IsProtected { get; set; }
+ public int ProtectedCatalogVersion { 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 bool IsReviewOverdue(DateTime utcNow) => NextReviewDue.HasValue && NextReviewDue.Value < utcNow;
+
+ public object IdValue { get => RmsOccupancyId; set => RmsOccupancyId = (string)value; }
+ public string TableName => "RmsOccupancies";
+ public string IdName => "RmsOccupancyId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ /// A Contact playing a role at an occupancy. Roles are separate rows so one person can be owner and emergency contact.
+ public class RmsOccupancyContactLink : IEntity
+ {
+ public string RmsOccupancyContactLinkId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string RmsOccupancyId { get; set; }
+ public string ContactId { get; set; }
+ /// .
+ public int Role { get; set; }
+ public bool IsPrimary { get; set; }
+ public DateTime CreatedOn { get; set; }
+ public string CreatedByUserId { get; set; }
+ public DateTime ModifiedOn { get; set; }
+ public long RowVersion { get; set; }
+ public DateTime? DeletedOn { get; set; }
+
+ public object IdValue { get => RmsOccupancyContactLinkId; set => RmsOccupancyContactLinkId = (string)value; }
+ public string TableName => "RmsOccupancyContactLinks";
+ public string IdName => "RmsOccupancyContactLinkId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ /// A premise hazard on the occupancy master; mirrors ContactPreplanHazard so a linked pre-plan's hazards carry over 1:1.
+ public class RmsOccupancyHazard : IEntity
+ {
+ public string RmsOccupancyHazardId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string RmsOccupancyId { get; set; }
+ /// Contacts plan PreplanHazardTypes value.
+ public int HazardType { get; set; }
+ /// Contacts plan PreplanHazardSeverity value (1 low – 4 critical).
+ public int Severity { get; set; }
+ public string Title { get; set; }
+ public string Description { get; set; }
+ public string LocationDescription { get; set; }
+ public string GpsCoordinates { get; set; }
+ public bool ShouldAlert { get; set; }
+ /// The Contacts hazard this row was absorbed from, when any; keeps the link for provenance.
+ public string SourceContactPreplanHazardId { get; set; }
+ public bool IsProtected { get; set; }
+ public int ProtectedCatalogVersion { get; set; }
+ public DateTime CreatedOn { get; set; }
+ public string CreatedByUserId { get; set; }
+ public DateTime ModifiedOn { get; set; }
+ public long RowVersion { get; set; }
+ public DateTime? DeletedOn { get; set; }
+
+ public object IdValue { get => RmsOccupancyHazardId; set => RmsOccupancyHazardId = (string)value; }
+ public string TableName => "RmsOccupancyHazards";
+ public string IdName => "RmsOccupancyHazardId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ ///
+ /// One source identity (pre-plan, contact, POI) and its relationship to the occupancy master (plan section 4.3:
+ /// "create a stable occupancy identity and Contact/POI/address/geospatial crosswalk; inventory and merge duplicate
+ /// source candidates"). Every candidate must be decided before a department switches structure writes to RMS.
+ ///
+ public class RmsOccupancyCrosswalk : IEntity
+ {
+ public string RmsOccupancyCrosswalkId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ /// Null while a Candidate.
+ public string RmsOccupancyId { get; set; }
+ /// .
+ public int SourceKind { get; set; }
+ public string SourceId { get; set; }
+ /// The source's contact id when the source is a pre-plan or contact, so a Contacts read can find its occupancy in one lookup.
+ public string ContactId { get; set; }
+ public string SourceDisplayName { get; set; }
+ public string NormalizedAddress { get; set; }
+ public decimal? Latitude { get; set; }
+ public decimal? Longitude { get; set; }
+ /// 0–100; how confident the inventory was that this source describes the same structure as the suggested occupancy.
+ public int MatchConfidence { get; set; }
+ public string MatchReason { get; set; }
+ /// Occupancy the inventory suggested; the deciding administrator may pick another.
+ public string SuggestedOccupancyId { get; set; }
+ /// Other candidate ids the inventory grouped with this one (same address or within the proximity radius), comma separated.
+ public string GroupKey { get; set; }
+ /// .
+ public int State { get; set; }
+ public DateTime? DecidedOn { get; set; }
+ public string DecidedByUserId { get; set; }
+ public DateTime InventoriedOn { get; set; }
+ public DateTime CreatedOn { get; set; }
+ public DateTime ModifiedOn { get; set; }
+ public long RowVersion { get; set; }
+
+ public object IdValue { get => RmsOccupancyCrosswalkId; set => RmsOccupancyCrosswalkId = (string)value; }
+ public string TableName => "RmsOccupancyCrosswalks";
+ public string IdName => "RmsOccupancyCrosswalkId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ /// Field-level provenance on the occupancy master: which source supplied a field, when, and when a person last confirmed it.
+ public class RmsOccupancyFieldProvenance : IEntity
+ {
+ public string RmsOccupancyFieldProvenanceId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string RmsOccupancyId { get; set; }
+ /// Property name on (or "hazards" for the hazard set).
+ public string FieldKey { get; set; }
+ /// , or 0 for a value typed into RMS directly.
+ public int SourceKind { get; set; }
+ public string SourceId { get; set; }
+ public DateTime CapturedOn { get; set; }
+ public string CapturedByUserId { get; set; }
+ public DateTime? ReviewedOn { get; set; }
+ public string ReviewedByUserId { get; set; }
+
+ public object IdValue { get => RmsOccupancyFieldProvenanceId; set => RmsOccupancyFieldProvenanceId = (string)value; }
+ public string TableName => "RmsOccupancyFieldProvenances";
+ public string IdName => "RmsOccupancyFieldProvenanceId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ ///
+ /// One row per department: which system owns structure writes (plan section 4.3 write cutover). Written only by the
+ /// occupancy service through an audited administrative command; the Contacts service reads it on every pre-plan write.
+ ///
+ public class RmsOccupancyOwnership : IEntity
+ {
+ public string RmsOccupancyOwnershipId { get; set; }
+ public int DepartmentId { get; set; }
+ /// .
+ public int State { get; set; }
+ public DateTime? InventoriedOn { get; set; }
+ public DateTime? SwitchedOn { get; set; }
+ public string SwitchedByUserId { get; set; }
+ public string Reason { get; set; }
+ public int CandidateCount { get; set; }
+ public int LinkedCount { get; set; }
+ public int RejectedCount { get; set; }
+ public DateTime CreatedOn { get; set; }
+ public DateTime ModifiedOn { get; set; }
+ public long RowVersion { get; set; }
+
+ public object IdValue { get => RmsOccupancyOwnershipId; set => RmsOccupancyOwnershipId = (string)value; }
+ public string TableName => "RmsOccupancyOwnerships";
+ public string IdName => "RmsOccupancyOwnershipId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+}
diff --git a/Core/Resgrid.Model/Records/RmsOperationalRecord.cs b/Core/Resgrid.Model/Records/RmsOperationalRecord.cs
index da4a69ab..65c9cd74 100644
--- a/Core/Resgrid.Model/Records/RmsOperationalRecord.cs
+++ b/Core/Resgrid.Model/Records/RmsOperationalRecord.cs
@@ -109,6 +109,15 @@ public class RmsOperationalRecord : IEntity
public string CancelledByUserId { get; set; }
+ ///
+ /// The uniqueness key the definition's demands (plan section 5.2.1), or
+ /// null when the definition allows multiples, the Record has no Call, or the Record reached a terminal
+ /// state. A filtered unique index on (DepartmentId, CardinalityKey) is what actually enforces the rule;
+ /// the service checks first only so the author gets the existing Record instead of a database error.
+ /// Clearing it on Void/Cancel is deliberate — an abandoned Record must not block the replacement.
+ ///
+ public string CardinalityKey { get; set; }
+
/// Scoped idempotency key for create; unique per department when present.
public string IdempotencyKey { get; set; }
diff --git a/Core/Resgrid.Model/Records/RmsPrevention.cs b/Core/Resgrid.Model/Records/RmsPrevention.cs
new file mode 100644
index 00000000..28e9ecd9
--- /dev/null
+++ b/Core/Resgrid.Model/Records/RmsPrevention.cs
@@ -0,0 +1,628 @@
+using System;
+using System.Collections.Generic;
+
+namespace Resgrid.Model
+{
+ /// Lifecycle of an inspection (RMS plan section 4.3, RMS-5).
+ public enum RmsInspectionState
+ {
+ Scheduled = 1,
+ InProgress = 2,
+ Completed = 3,
+ /// Completed with open violations; a child re-inspection is expected by the violation due date.
+ ReinspectionRequired = 4,
+ Closed = 5,
+ Cancelled = 6
+ }
+
+ public enum RmsInspectionResult
+ {
+ NotRecorded = 0,
+ Pass = 1,
+ Fail = 2,
+ Conditional = 3
+ }
+
+ public enum RmsViolationState
+ {
+ Open = 1,
+ Corrected = 2,
+ Verified = 3,
+ Escalated = 4,
+ Waived = 5
+ }
+
+ public enum RmsViolationSeverity
+ {
+ Minor = 1,
+ Moderate = 2,
+ Serious = 3,
+ /// Imminent hazard; immediate correction or evacuation.
+ Critical = 4
+ }
+
+ public enum RmsHydrantType
+ {
+ DryBarrel = 1,
+ WetBarrel = 2,
+ Standpipe = 3,
+ Cistern = 4,
+ DraftingSite = 5,
+ Other = 6
+ }
+
+ public enum RmsHydrantOwnerKind
+ {
+ Municipal = 1,
+ Private = 2,
+ Department = 3,
+ Other = 4
+ }
+
+ /// NFPA 291 flow classification (colour of the bonnet/caps).
+ public enum RmsHydrantFlowClass
+ {
+ Unknown = 0,
+ /// 1500 gpm or more — light blue.
+ AA = 1,
+ /// 1000–1499 gpm — green.
+ A = 2,
+ /// 500–999 gpm — orange.
+ B = 3,
+ /// Under 500 gpm — red.
+ C = 4
+ }
+
+ public enum RmsHydrantMaintenanceKind
+ {
+ Inspection = 1,
+ Flush = 2,
+ Repair = 3,
+ Paint = 4,
+ Winterize = 5,
+ Other = 6
+ }
+
+ public enum RmsPermitState
+ {
+ Applied = 1,
+ UnderReview = 2,
+ Approved = 3,
+ Issued = 4,
+ Expired = 5,
+ Revoked = 6,
+ Denied = 7,
+ Closed = 8
+ }
+
+ public enum RmsPlanReviewOutcome
+ {
+ Pending = 0,
+ Approved = 1,
+ CorrectionsRequired = 2,
+ Rejected = 3
+ }
+
+ public enum RmsCrrActivityKind
+ {
+ PublicEducation = 1,
+ SmokeAlarmInstallation = 2,
+ HomeSafetyVisit = 3,
+ PublicEvent = 4,
+ SchoolProgram = 5,
+ MediaOutreach = 6,
+ Other = 7
+ }
+
+ /// Parent aggregate of a prevention attachment.
+ public enum RmsPreventionParentKind
+ {
+ Occupancy = 1,
+ Inspection = 2,
+ Violation = 3,
+ Hydrant = 4,
+ Permit = 5,
+ CrrActivity = 6,
+ /// Investigation photos and documents; always restricted.
+ InvestigationCase = 7,
+ InvestigationEvidence = 8
+ }
+
+ /// Sequence names used by .
+ public static class RmsPreventionNumberKinds
+ {
+ public const string Occupancy = "OCC";
+ public const string Inspection = "INSP";
+ public const string Permit = "PRM";
+ public const string Investigation = "INV";
+ public const string Evidence = "EV";
+ }
+
+ /// An adopted code set (e.g. IFC 2021 with local amendments).
+ public class RmsCodeSet : IEntity
+ {
+ public string RmsCodeSetId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string Name { get; set; }
+ public string Edition { get; set; }
+ public string Jurisdiction { get; set; }
+ public bool IsActive { get; set; }
+ public DateTime CreatedOn { get; set; }
+ public string CreatedByUserId { get; set; }
+ public DateTime ModifiedOn { get; set; }
+ public long RowVersion { get; set; }
+ public DateTime? DeletedOn { get; set; }
+
+ public object IdValue { get => RmsCodeSetId; set => RmsCodeSetId = (string)value; }
+ public string TableName => "RmsCodeSets";
+ public string IdName => "RmsCodeSetId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ /// One citable section of a code set.
+ public class RmsCodeSection : IEntity
+ {
+ public string RmsCodeSectionId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string RmsCodeSetId { get; set; }
+ public string SectionNumber { get; set; }
+ public string Title { get; set; }
+ public string Text { get; set; }
+ /// proposed when a violation cites this section.
+ public int DefaultSeverity { get; set; }
+ /// Default days to correct a violation citing this section.
+ public int DefaultCorrectionDays { get; set; }
+ public DateTime CreatedOn { get; set; }
+ public DateTime ModifiedOn { get; set; }
+ public long RowVersion { get; set; }
+ public DateTime? DeletedOn { get; set; }
+
+ public object IdValue { get => RmsCodeSectionId; set => RmsCodeSectionId = (string)value; }
+ public string TableName => "RmsCodeSections";
+ public string IdName => "RmsCodeSectionId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ ///
+ /// An inspection program: which occupancy types it applies to, how often, and the checklist an inspector walks.
+ /// The checklist is bounded JSON ( list) rather than an RMS definition
+ /// because an inspection item is pass/fail against a code citation, not a typed field.
+ ///
+ public class RmsInspectionProgram : IEntity
+ {
+ public string RmsInspectionProgramId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ /// Contacts plan OccupancyTypes values this program applies to, comma separated; empty = all.
+ public string OccupancyTypesCsv { get; set; }
+ /// Months between inspections; 0 = on demand only.
+ public int FrequencyMonths { get; set; }
+ public string RmsCodeSetId { get; set; }
+ public string ChecklistJson { get; set; }
+ public bool IsActive { get; set; }
+ public DateTime CreatedOn { get; set; }
+ public string CreatedByUserId { get; set; }
+ public DateTime ModifiedOn { get; set; }
+ public long RowVersion { get; set; }
+ public DateTime? DeletedOn { get; set; }
+
+ public object IdValue { get => RmsInspectionProgramId; set => RmsInspectionProgramId = (string)value; }
+ public string TableName => "RmsInspectionPrograms";
+ public string IdName => "RmsInspectionProgramId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ /// One item of an inspection program checklist (stored in ChecklistJson).
+ public class RmsInspectionChecklistItem
+ {
+ public string Key { get; set; }
+ public string Text { get; set; }
+ public string RmsCodeSectionId { get; set; }
+ public bool Required { get; set; }
+ public int Order { get; set; }
+ }
+
+ /// The inspector's answer to one checklist item (stored in RmsInspection.ItemsJson).
+ public class RmsInspectionItemResult
+ {
+ public string Key { get; set; }
+ /// true = compliant, false = violation, null = not inspected.
+ public bool? Passed { get; set; }
+ public string Note { get; set; }
+ }
+
+ public class RmsInspection : IEntity
+ {
+ public string RmsInspectionId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string RmsOccupancyId { get; set; }
+ public string RmsInspectionProgramId { get; set; }
+ /// INSP-{year}-{sequence}.
+ public string InspectionNumber { get; set; }
+ /// .
+ public int State { get; set; }
+ /// .
+ public int Result { get; set; }
+ public DateTime? ScheduledOn { get; set; }
+ public DateTime? StartedOn { get; set; }
+ public DateTime? CompletedOn { get; set; }
+ public string InspectorUserId { get; set; }
+ public string ItemsJson { get; set; }
+ public string Notes { get; set; }
+ /// Printed name of the occupant representative who signed the inspection, if any.
+ public string SignatureName { get; set; }
+ public DateTime? SignedOn { get; set; }
+ /// The inspection this one re-checks.
+ public string ParentInspectionId { get; set; }
+ public DateTime? NoticeIssuedOn { get; set; }
+ public string NoticeReference { get; set; }
+ public bool IsProtected { get; set; }
+ public int ProtectedCatalogVersion { get; set; }
+ public DateTime CreatedOn { get; set; }
+ public string CreatedByUserId { get; set; }
+ public DateTime ModifiedOn { get; set; }
+ public long RowVersion { get; set; }
+ public DateTime? DeletedOn { get; set; }
+
+ public object IdValue { get => RmsInspectionId; set => RmsInspectionId = (string)value; }
+ public string TableName => "RmsInspections";
+ public string IdName => "RmsInspectionId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ public class RmsViolation : IEntity
+ {
+ public string RmsViolationId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string RmsInspectionId { get; set; }
+ public string RmsOccupancyId { get; set; }
+ public string RmsCodeSetId { get; set; }
+ public string RmsCodeSectionId { get; set; }
+ public string ChecklistItemKey { get; set; }
+ public string Description { get; set; }
+ /// .
+ public int Severity { get; set; }
+ public string CorrectiveAction { get; set; }
+ public DateTime? DueOn { get; set; }
+ /// .
+ public int State { get; set; }
+ public DateTime? CorrectedOn { get; set; }
+ public DateTime? VerifiedOn { get; set; }
+ public string VerifiedByUserId { get; set; }
+ public string ReinspectionId { get; set; }
+ /// Set once the overdue event has been raised, so the sweep emits it exactly once (same rule as record due states).
+ public DateTime? OverdueEmittedOn { get; set; }
+ public bool IsProtected { get; set; }
+ public int ProtectedCatalogVersion { get; set; }
+ public DateTime CreatedOn { get; set; }
+ public string CreatedByUserId { get; set; }
+ public DateTime ModifiedOn { get; set; }
+ public long RowVersion { get; set; }
+ public DateTime? DeletedOn { get; set; }
+
+ public bool IsOpen => State == (int)RmsViolationState.Open || State == (int)RmsViolationState.Escalated;
+
+ public object IdValue { get => RmsViolationId; set => RmsViolationId = (string)value; }
+ public string TableName => "RmsViolations";
+ public string IdName => "RmsViolationId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName", "IsOpen" };
+ }
+
+ public class RmsHydrant : IEntity
+ {
+ public string RmsHydrantId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string HydrantNumber { get; set; }
+ /// .
+ public int Type { get; set; }
+ public decimal Latitude { get; set; }
+ public decimal Longitude { get; set; }
+ public string AddressText { get; set; }
+ /// .
+ public int OwnerKind { get; set; }
+ public string OwnerName { get; set; }
+ public decimal? MainSizeInches { get; set; }
+ public int? StaticPressurePsi { get; set; }
+ public int? ResidualPressurePsi { get; set; }
+ public int? FlowGpm { get; set; }
+ /// .
+ public int FlowClass { get; set; }
+ public bool InService { get; set; }
+ public string OutOfServiceReason { get; set; }
+ public DateTime? OutOfServiceSince { get; set; }
+ public DateTime? LastTestedOn { get; set; }
+ public DateTime? LastMaintainedOn { get; set; }
+ public string Notes { get; set; }
+ public int? PoiId { get; set; }
+ /// Where the row came from: manual, csv-import, poi.
+ public string Source { get; set; }
+ public DateTime CreatedOn { get; set; }
+ public string CreatedByUserId { get; set; }
+ public DateTime ModifiedOn { get; set; }
+ public long RowVersion { get; set; }
+ public DateTime? DeletedOn { get; set; }
+
+ public object IdValue { get => RmsHydrantId; set => RmsHydrantId = (string)value; }
+ public string TableName => "RmsHydrants";
+ public string IdName => "RmsHydrantId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ public class RmsHydrantFlowTest : IEntity
+ {
+ public string RmsHydrantFlowTestId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string RmsHydrantId { get; set; }
+ public DateTime TestedOn { get; set; }
+ public string TestedByUserId { get; set; }
+ public int StaticPressurePsi { get; set; }
+ public int ResidualPressurePsi { get; set; }
+ public int PitotPressurePsi { get; set; }
+ public decimal OutletDiameterInches { get; set; }
+ /// Discharge coefficient of the outlet (0.9 smooth, 0.8 square, 0.7 projecting).
+ public decimal Coefficient { get; set; }
+ /// Computed: 29.83 × c × d² × √p.
+ public int FlowGpm { get; set; }
+ /// derived from FlowGpm.
+ public int FlowClass { get; set; }
+ public string Notes { get; set; }
+ public DateTime CreatedOn { get; set; }
+
+ public object IdValue { get => RmsHydrantFlowTestId; set => RmsHydrantFlowTestId = (string)value; }
+ public string TableName => "RmsHydrantFlowTests";
+ public string IdName => "RmsHydrantFlowTestId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ public class RmsHydrantMaintenance : IEntity
+ {
+ public string RmsHydrantMaintenanceId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string RmsHydrantId { get; set; }
+ public DateTime PerformedOn { get; set; }
+ public string PerformedByUserId { get; set; }
+ /// .
+ public int Kind { get; set; }
+ public string Notes { get; set; }
+ public bool ReturnedToService { get; set; }
+ public DateTime CreatedOn { get; set; }
+
+ public object IdValue { get => RmsHydrantMaintenanceId; set => RmsHydrantMaintenanceId = (string)value; }
+ public string TableName => "RmsHydrantMaintenances";
+ public string IdName => "RmsHydrantMaintenanceId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ public class RmsPermitType : IEntity
+ {
+ public string RmsPermitTypeId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string Name { get; set; }
+ public string Code { get; set; }
+ public string Description { get; set; }
+ public int DefaultValidityDays { get; set; }
+ public bool RequiresPlanReview { get; set; }
+ public decimal? FeeAmount { get; set; }
+ /// Default conditions pre-filled on a new permit, one per line.
+ public string ConditionsTemplate { get; set; }
+ public bool IsActive { get; set; }
+ public DateTime CreatedOn { get; set; }
+ public string CreatedByUserId { get; set; }
+ public DateTime ModifiedOn { get; set; }
+ public long RowVersion { get; set; }
+ public DateTime? DeletedOn { get; set; }
+
+ public object IdValue { get => RmsPermitTypeId; set => RmsPermitTypeId = (string)value; }
+ public string TableName => "RmsPermitTypes";
+ public string IdName => "RmsPermitTypeId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ public class RmsPermit : IEntity
+ {
+ public string RmsPermitId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string RmsPermitTypeId { get; set; }
+ public string RmsOccupancyId { get; set; }
+ /// PRM-{year}-{sequence}.
+ public string PermitNumber { get; set; }
+ public string ApplicantContactId { get; set; }
+ public string ApplicantName { get; set; }
+ public string ApplicantPhone { get; set; }
+ public string ApplicantEmail { get; set; }
+ public string Description { get; set; }
+ /// .
+ public int State { get; set; }
+ public DateTime AppliedOn { get; set; }
+ public DateTime? ReviewedOn { get; set; }
+ public string ReviewedByUserId { get; set; }
+ public DateTime? IssuedOn { get; set; }
+ public string IssuedByUserId { get; set; }
+ public DateTime? EffectiveOn { get; set; }
+ public DateTime? ExpiresOn { get; set; }
+ /// Conditions of issue, one per line.
+ public string Conditions { get; set; }
+ public string ReviewNotes { get; set; }
+ public decimal? FeeAmount { get; set; }
+ public DateTime? FeePaidOn { get; set; }
+ /// Optional reference into the invoicing system (Contacts plan Phase B) — text only, never a join.
+ public string InvoiceReference { get; set; }
+ public string DecisionReason { get; set; }
+ /// Set once the expiring-soon event has been raised, so the sweep emits it exactly once.
+ public DateTime? ExpiringEmittedOn { get; set; }
+ public bool IsProtected { get; set; }
+ public int ProtectedCatalogVersion { get; set; }
+ public DateTime CreatedOn { get; set; }
+ public string CreatedByUserId { get; set; }
+ public DateTime ModifiedOn { get; set; }
+ public long RowVersion { get; set; }
+ public DateTime? DeletedOn { get; set; }
+
+ public object IdValue { get => RmsPermitId; set => RmsPermitId = (string)value; }
+ public string TableName => "RmsPermits";
+ public string IdName => "RmsPermitId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ public class RmsPlanReview : IEntity
+ {
+ public string RmsPlanReviewId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string RmsPermitId { get; set; }
+ public int CycleNumber { get; set; }
+ public DateTime SubmittedOn { get; set; }
+ public string ReviewerUserId { get; set; }
+ public DateTime? ReviewedOn { get; set; }
+ /// .
+ public int Outcome { get; set; }
+ public string Comments { 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 object IdValue { get => RmsPlanReviewId; set => RmsPlanReviewId = (string)value; }
+ public string TableName => "RmsPlanReviews";
+ public string IdName => "RmsPlanReviewId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ /// A community risk reduction activity (plan section 4.3). Carries no personal information about attendees, only counts.
+ public class RmsCrrActivity : IEntity
+ {
+ public string RmsCrrActivityId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ /// .
+ public int Kind { get; set; }
+ public DateTime OccurredOn { get; set; }
+ public string Title { get; set; }
+ public string Description { get; set; }
+ public string RmsOccupancyId { get; set; }
+ public string LocationText { get; set; }
+ public decimal? Latitude { get; set; }
+ public decimal? Longitude { get; set; }
+ public int AudienceCount { get; set; }
+ public int SmokeAlarmsInstalled { get; set; }
+ public decimal HoursSpent { get; set; }
+ /// Department members who staffed the activity, comma separated user ids.
+ public string StaffUserIdsCsv { get; set; }
+ public string Outcome { get; set; }
+ /// Reserved for the NERIS CRR secondary schema once it matures; JSON, additive only.
+ public string NerisSecondaryJson { get; set; }
+ public DateTime CreatedOn { get; set; }
+ public string CreatedByUserId { get; set; }
+ public DateTime ModifiedOn { get; set; }
+ public long RowVersion { get; set; }
+ public DateTime? DeletedOn { get; set; }
+
+ public object IdValue { get => RmsCrrActivityId; set => RmsCrrActivityId = (string)value; }
+ public string TableName => "RmsCrrActivities";
+ public string IdName => "RmsCrrActivityId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ ///
+ /// A file on a prevention or investigation aggregate. Goes through the same hygiene and scanner as record
+ /// attachments; the name, description and bytes are ADP catalog v13 fields. Investigation attachments are
+ /// restricted and readable only by case members.
+ ///
+ public class RmsPreventionAttachment : IEntity
+ {
+ public string RmsPreventionAttachmentId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ /// .
+ public int ParentKind { get; set; }
+ public string ParentId { get; set; }
+ public string FileName { get; set; }
+ public string ContentType { get; set; }
+ public long ByteSize { get; set; }
+ public string Checksum { get; set; }
+ public byte[] Data { get; set; }
+ public string Description { get; set; }
+ public string UploadedByUserId { get; set; }
+ public DateTime UploadedOn { get; set; }
+ /// .
+ public int ScanState { get; set; }
+ public bool MetadataStripped { get; set; }
+ /// : Restricted for every investigation attachment.
+ public int Classification { 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; }
+
+ public object IdValue { get => RmsPreventionAttachmentId; set => RmsPreventionAttachmentId = (string)value; }
+ public string TableName => "RmsPreventionAttachments";
+ public string IdName => "RmsPreventionAttachmentId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ /// Per-department, per-kind, per-year number sequence for the prevention aggregates (OCC/INSP/PRM/INV/EV).
+ public class RmsPreventionSequence : IEntity
+ {
+ public string RmsPreventionSequenceId { get; set; }
+ public int DepartmentId { get; set; }
+ public string Kind { get; set; }
+ public int Year { get; set; }
+ public int LastValue { get; set; }
+ public DateTime ModifiedOn { get; set; }
+
+ public object IdValue { get => RmsPreventionSequenceId; set => RmsPreventionSequenceId = (string)value; }
+ public string TableName => "RmsPreventionSequences";
+ public string IdName => "RmsPreventionSequenceId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ /// NFPA 291 hydrant flow arithmetic, pure so it is unit-testable and shared by web, API and import.
+ public static class HydrantFlowCalculator
+ {
+ /// Q = 29.83 × c × d² × √p (gpm), rounded to the nearest 10 as the standard reports.
+ public static int FlowGpm(decimal coefficient, decimal outletDiameterInches, int pitotPsi)
+ {
+ if (coefficient <= 0 || outletDiameterInches <= 0 || pitotPsi <= 0)
+ return 0;
+ var q = 29.83 * (double)coefficient * Math.Pow((double)outletDiameterInches, 2) * Math.Sqrt(pitotPsi);
+ return (int)(Math.Round(q / 10.0) * 10);
+ }
+
+ public static RmsHydrantFlowClass Classify(int? flowGpm)
+ {
+ if (!flowGpm.HasValue || flowGpm.Value <= 0) return RmsHydrantFlowClass.Unknown;
+ if (flowGpm.Value >= 1500) return RmsHydrantFlowClass.AA;
+ if (flowGpm.Value >= 1000) return RmsHydrantFlowClass.A;
+ if (flowGpm.Value >= 500) return RmsHydrantFlowClass.B;
+ return RmsHydrantFlowClass.C;
+ }
+ }
+}
diff --git a/Core/Resgrid.Model/Records/RmsProtectedFields.cs b/Core/Resgrid.Model/Records/RmsProtectedFields.cs
index 59eeb0f8..19bdc860 100644
--- a/Core/Resgrid.Model/Records/RmsProtectedFields.cs
+++ b/Core/Resgrid.Model/Records/RmsProtectedFields.cs
@@ -188,6 +188,85 @@ private static string TableOf() where T : IEntity
/// The rendered export artifact (RmsExportRuns.Data) is a generated copy of record content.
public static readonly string ExportRunDataFieldId = FieldId("RmsExportRuns", "Data");
+ // ---- RMS-5 prevention and investigations, catalog v13 ----------------------------------------------------
+
+ /// Occupancy master (RMS-5): access secrets, hazard/tactical text, utility notes, the on-site emergency contact. Structural codes and flags stay plaintext.
+ public static readonly IReadOnlyDictionary Get, Action Set)> Occupancies = Map(
+ ("OccupantsNeedingAssistanceNotes", o => o.OccupantsNeedingAssistanceNotes, (o, v) => o.OccupantsNeedingAssistanceNotes = v),
+ ("UtilityNotes", o => o.UtilityNotes, (o, v) => o.UtilityNotes = v),
+ ("KnoxBoxLocation", o => o.KnoxBoxLocation, (o, v) => o.KnoxBoxLocation = v),
+ ("GateCode", o => o.GateCode, (o, v) => o.GateCode = v),
+ ("AlarmPanelLocation", o => o.AlarmPanelLocation, (o, v) => o.AlarmPanelLocation = v),
+ ("AlarmCompany", o => o.AlarmCompany, (o, v) => o.AlarmCompany = v),
+ ("AlarmCompanyPhone", o => o.AlarmCompanyPhone, (o, v) => o.AlarmCompanyPhone = v),
+ ("AccessNotes", o => o.AccessNotes, (o, v) => o.AccessNotes = v),
+ ("WaterSupplyNotes", o => o.WaterSupplyNotes, (o, v) => o.WaterSupplyNotes = v),
+ ("EmergencyContactName", o => o.EmergencyContactName, (o, v) => o.EmergencyContactName = v),
+ ("EmergencyContactPhone", o => o.EmergencyContactPhone, (o, v) => o.EmergencyContactPhone = v),
+ ("GeneralHazardNotes", o => o.GeneralHazardNotes, (o, v) => o.GeneralHazardNotes = v),
+ ("TacticalSummary", o => o.TacticalSummary, (o, v) => o.TacticalSummary = v));
+
+ public static readonly IReadOnlyDictionary Get, Action Set)> OccupancyHazards = Map(
+ ("Description", h => h.Description, (h, v) => h.Description = v),
+ ("LocationDescription", h => h.LocationDescription, (h, v) => h.LocationDescription = v),
+ ("GpsCoordinates", h => h.GpsCoordinates, (h, v) => h.GpsCoordinates = v));
+
+ /// Inspection notes and the occupant representative's printed name.
+ public static readonly IReadOnlyDictionary Get, Action Set)> Inspections = Map(
+ ("Notes", i => i.Notes, (i, v) => i.Notes = v),
+ ("SignatureName", i => i.SignatureName, (i, v) => i.SignatureName = v));
+
+ public static readonly IReadOnlyDictionary Get, Action Set)> Violations = Map(
+ ("Description", x => x.Description, (x, v) => x.Description = v),
+ ("CorrectiveAction", x => x.CorrectiveAction, (x, v) => x.CorrectiveAction = v));
+
+ /// Permit applicant identity and the reviewer's notes.
+ public static readonly IReadOnlyDictionary Get, Action Set)> Permits = Map(
+ ("ApplicantName", p => p.ApplicantName, (p, v) => p.ApplicantName = v),
+ ("ApplicantPhone", p => p.ApplicantPhone, (p, v) => p.ApplicantPhone = v),
+ ("ApplicantEmail", p => p.ApplicantEmail, (p, v) => p.ApplicantEmail = v),
+ ("ReviewNotes", p => p.ReviewNotes, (p, v) => p.ReviewNotes = v));
+
+ public static readonly IReadOnlyDictionary Get, Action Set)> PlanReviews = Map(
+ ("Comments", p => p.Comments, (p, v) => p.Comments = v));
+
+ /// Investigation case narrative (Tier 1: restricted and encrypted).
+ public static readonly IReadOnlyDictionary Get, Action Set)> InvestigationCases = Map(
+ ("IncidentSummary", c => c.IncidentSummary, (c, v) => c.IncidentSummary = v),
+ ("CauseDetail", c => c.CauseDetail, (c, v) => c.CauseDetail = v),
+ ("OriginDescription", c => c.OriginDescription, (c, v) => c.OriginDescription = v),
+ ("Findings", c => c.Findings, (c, v) => c.Findings = v),
+ ("ClosureReason", c => c.ClosureReason, (c, v) => c.ClosureReason = v));
+
+ public static readonly IReadOnlyDictionary Get, Action Set)> InvestigationNotes = Map(
+ ("Subject", n => n.Subject, (n, v) => n.Subject = v),
+ ("Body", n => n.Body, (n, v) => n.Body = v));
+
+ public static readonly IReadOnlyDictionary Get, Action Set)> InvestigationEvidence = Map(
+ ("Description", e => e.Description, (e, v) => e.Description = v),
+ ("CollectedFrom", e => e.CollectedFrom, (e, v) => e.CollectedFrom = v),
+ ("CurrentCustodianExternal", e => e.CurrentCustodianExternal, (e, v) => e.CurrentCustodianExternal = v));
+
+ public static readonly IReadOnlyDictionary Get, Action Set)> InvestigationCustody = Map(
+ ("FromExternal", c => c.FromExternal, (c, v) => c.FromExternal = v),
+ ("ToExternal", c => c.ToExternal, (c, v) => c.ToExternal = v),
+ ("Reason", c => c.Reason, (c, v) => c.Reason = v));
+
+ public static readonly IReadOnlyDictionary Get, Action Set)> InvestigationReferrals = Map(
+ ("Reason", r => r.Reason, (r, v) => r.Reason = v));
+
+ /// QA findings and notes quote the record they review, so they inherit its sensitivity.
+ public static readonly IReadOnlyDictionary Get, Action Set)> QualityReviews = Map(
+ ("FindingsJson", q => q.FindingsJson, (q, v) => q.FindingsJson = v),
+ ("Note", q => q.Note, (q, v) => q.Note = v));
+
+ /// Prevention/investigation attachment text columns; the bytes ride .
+ public static readonly IReadOnlyDictionary Get, Action Set)> PreventionAttachments = Map(
+ ("FileName", a => a.FileName, (a, v) => a.FileName = v),
+ ("Description", a => a.Description, (a, v) => a.Description = v));
+
+ public static readonly string PreventionAttachmentDataFieldId = FieldId("RmsPreventionAttachments", "Data");
+
/// Every RMS field id the catalog must carry, for the pin test.
public static IEnumerable AllFieldIds()
{
@@ -195,6 +274,20 @@ public static IEnumerable AllFieldIds()
foreach (var k in Narratives.Keys) yield return k;
foreach (var k in Locations.Keys) yield return k;
foreach (var k in LocationCompanions.Keys) yield return k;
+ foreach (var k in Occupancies.Keys) yield return k;
+ foreach (var k in OccupancyHazards.Keys) yield return k;
+ foreach (var k in Inspections.Keys) yield return k;
+ foreach (var k in Violations.Keys) yield return k;
+ foreach (var k in Permits.Keys) yield return k;
+ foreach (var k in PlanReviews.Keys) yield return k;
+ foreach (var k in InvestigationCases.Keys) yield return k;
+ foreach (var k in InvestigationNotes.Keys) yield return k;
+ foreach (var k in InvestigationEvidence.Keys) yield return k;
+ foreach (var k in InvestigationCustody.Keys) yield return k;
+ foreach (var k in InvestigationReferrals.Keys) yield return k;
+ foreach (var k in QualityReviews.Keys) yield return k;
+ foreach (var k in PreventionAttachments.Keys) yield return k;
+ yield return PreventionAttachmentDataFieldId;
foreach (var k in SourceFacts.Keys) yield return k;
foreach (var k in Casualties.Keys) yield return k;
foreach (var k in Exposures.Keys) yield return k;
diff --git a/Core/Resgrid.Model/Records/RmsQualityReview.cs b/Core/Resgrid.Model/Records/RmsQualityReview.cs
new file mode 100644
index 00000000..b0881fe4
--- /dev/null
+++ b/Core/Resgrid.Model/Records/RmsQualityReview.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+
+namespace Resgrid.Model
+{
+ ///
+ /// A department QA rubric (RMS plan section 4.7, post-finalization quality review, RMS-4 optional module): the
+ /// criteria a reviewer scores a finalized Record against. Criteria are bounded JSON
+ /// ( list). Editing a rubric never changes a recorded review — each review
+ /// snapshots the criteria it was scored against.
+ ///
+ public class RmsQualityRubric : IEntity
+ {
+ public string RmsQualityRubricId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string Name { get; set; }
+ /// Definition key this rubric applies to; null = any definition.
+ public string DefinitionKey { get; set; }
+ public string CriteriaJson { get; set; }
+ /// Sample size per sampling run.
+ public int SampleSize { get; set; }
+ public bool IsActive { get; set; }
+ public DateTime CreatedOn { get; set; }
+ public string CreatedByUserId { get; set; }
+ public DateTime ModifiedOn { get; set; }
+ public long RowVersion { get; set; }
+ public DateTime? DeletedOn { get; set; }
+
+ public object IdValue { get => RmsQualityRubricId; set => RmsQualityRubricId = (string)value; }
+ public string TableName => "RmsQualityRubrics";
+ public string IdName => "RmsQualityRubricId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ public class RmsQualityCriterion
+ {
+ public string Key { get; set; }
+ public string Text { get; set; }
+ /// Relative weight; scores are weighted averages on a 0–100 scale.
+ public int Weight { get; set; } = 1;
+ }
+
+ /// The reviewer's score for one criterion (stored in RmsQualityReview.FindingsJson).
+ public class RmsQualityFinding
+ {
+ public string Key { get; set; }
+ /// 0–100.
+ public int Score { get; set; }
+ public string Note { get; set; }
+ }
+
+ ///
+ /// One QA review of one finalized revision. Non-mutating by construction: it references the record and revision,
+ /// never edits either, and a substantive correction is an amendment through the normal lifecycle.
+ ///
+ public class RmsQualityReview : IEntity
+ {
+ public string RmsQualityReviewId { get; set; }
+ public int DepartmentId { get; set; }
+ public string ProtectionId { get; set; }
+ public string RmsQualityRubricId { get; set; }
+ public string RecordId { get; set; }
+ /// .
+ public int RecordKind { get; set; }
+ public string RevisionId { get; set; }
+ public string DefinitionKey { get; set; }
+ public string RecordNumber { get; set; }
+ public string AuthorUserId { get; set; }
+ public int? UnitId { get; set; }
+ public string ReviewerUserId { get; set; }
+ public DateTime SampledOn { get; set; }
+ public DateTime? ScoredOn { get; set; }
+ /// Weighted 0–100; null until scored.
+ public int? Score { get; set; }
+ /// Snapshot of the rubric criteria at sampling time.
+ public string CriteriaJson { get; set; }
+ public string FindingsJson { get; set; }
+ public string Note { get; set; }
+ public bool AmendmentRecommended { 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 object IdValue { get => RmsQualityReviewId; set => RmsQualityReviewId = (string)value; }
+ public string TableName => "RmsQualityReviews";
+ public string IdName => "RmsQualityReviewId";
+ public int IdType => 1;
+ public IEnumerable IgnoredProperties => new[] { "IdValue", "IdType", "TableName", "IdName" };
+ }
+
+ /// Aggregate line of the QA trend report.
+ public class RecordsQualityTrendRow
+ {
+ public string Key { get; set; }
+ public string Label { get; set; }
+ public int Reviews { get; set; }
+ public double AverageScore { get; set; }
+ public int AmendmentsRecommended { get; set; }
+ }
+
+ public class RecordsQualityTrends
+ {
+ public DateTime Since { get; set; }
+ public int Sampled { get; set; }
+ public int Scored { get; set; }
+ public double AverageScore { get; set; }
+ public List ByAuthor { get; set; } = new List();
+ public List ByUnit { get; set; } = new List();
+ public List ByDefinition { get; set; } = new List();
+ public List ByCriterion { get; set; } = new List();
+ }
+}
diff --git a/Core/Resgrid.Model/Records/RmsRecordDefinitions.cs b/Core/Resgrid.Model/Records/RmsRecordDefinitions.cs
index be2b90ab..799a744e 100644
--- a/Core/Resgrid.Model/Records/RmsRecordDefinitions.cs
+++ b/Core/Resgrid.Model/Records/RmsRecordDefinitions.cs
@@ -145,6 +145,12 @@ public class RmsRecordDefinitionVersion : IEntity
public int Version { get; set; }
public int State { get; set; }
public int LifecyclePreset { get; set; }
+ ///
+ /// — how many Records of this definition may exist on one Call
+ /// (plan section 5.2.1). Immutable once published, like everything else on a version: a Record created
+ /// under the old rule is never retrospectively a duplicate.
+ ///
+ public int Cardinality { get; set; } = (int)RmsRecordCardinality.MultiplePerCall;
/// Comma-separated PersonnelRole ids that narrow Record_Review for this definition; empty = anyone holding it.
public string ReviewerRoleIds { get; set; }
/// Comma-separated PersonnelRole ids that narrow Record_Approve; empty = anyone holding it.
@@ -575,6 +581,8 @@ public class RecordDefinitionDraftInput
public string Description { get; set; }
public string PermittedSubjectTypes { get; set; }
public RmsLifecyclePreset LifecyclePreset { get; set; } = RmsLifecyclePreset.QuickEntry;
+ /// How many Records of this definition may exist on one Call (plan section 5.2.1).
+ public RmsRecordCardinality Cardinality { get; set; } = RmsRecordCardinality.MultiplePerCall;
public List ReviewerRoleIds { get; set; } = new List();
public List ApproverRoleIds { get; set; } = new List();
public int? ReviewDueHours { get; set; }
@@ -681,6 +689,7 @@ public class RecordDefinitionSummary
public int? DraftVersion { get; set; }
public bool Retired { get; set; }
public string LifecyclePreset { get; set; }
+ public string Cardinality { get; set; }
public string MinimumClientCapability { get; set; }
public string TemplateKey { get; set; }
public string JurisdictionProfileKey { get; set; }
diff --git a/Core/Resgrid.Model/Records/RmsTemplatePacks.cs b/Core/Resgrid.Model/Records/RmsTemplatePacks.cs
index a2f6028b..878211b3 100644
--- a/Core/Resgrid.Model/Records/RmsTemplatePacks.cs
+++ b/Core/Resgrid.Model/Records/RmsTemplatePacks.cs
@@ -138,6 +138,8 @@ public class RecordTemplateDefinition
public string Category { get; set; }
public string Description { get; set; }
public RmsLifecyclePreset LifecyclePreset { get; set; } = RmsLifecyclePreset.QuickEntry;
+ /// How many Records of this definition may exist on one Call (plan section 5.2.1).
+ public RmsRecordCardinality Cardinality { get; set; } = RmsRecordCardinality.MultiplePerCall;
public string NumberPrefix { get; set; }
/// Template default for ; ICS-style forms number per incident.
public bool PerIncidentSequence { get; set; }
diff --git a/Core/Resgrid.Model/Repositories/IContactPreplanRepository.cs b/Core/Resgrid.Model/Repositories/IContactPreplanRepository.cs
new file mode 100644
index 00000000..ecff806f
--- /dev/null
+++ b/Core/Resgrid.Model/Repositories/IContactPreplanRepository.cs
@@ -0,0 +1,42 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Resgrid.Model.Repositories
+{
+ /// Contact pre-plans (Contacts plan Phase A, A3).
+ public interface IContactPreplanRepository : IRepository
+ {
+ /// The live (non-deleted) pre-plan for a contact, or null.
+ Task GetPreplanByContactIdAsync(string contactId, int departmentId);
+
+ /// Live pre-plans for a set of contacts in one query.
+ Task> GetPreplansByContactIdsAsync(int departmentId, IEnumerable contactIds);
+
+ /// All live pre-plans for a department (review-currency index badge).
+ Task> GetPreplansByDepartmentIdAsync(int departmentId);
+ }
+
+ /// Repeating premise hazards on a contact pre-plan (Contacts plan Phase A, A3).
+ public interface IContactPreplanHazardRepository : IRepository
+ {
+ Task> GetHazardsByPreplanIdAsync(string contactPreplanId, int departmentId);
+
+ Task> GetHazardsByContactIdAsync(string contactId, int departmentId);
+
+ /// Live hazards for a set of contacts in one query.
+ Task> GetHazardsByContactIdsAsync(int departmentId, IEnumerable contactIds);
+ }
+
+ /// Contact site attachments (Contacts plan Phase A, A3). Metadata reads never load the blob.
+ public interface IContactAttachmentRepository : IRepository
+ {
+ /// Live attachment rows for a contact WITHOUT the Data column.
+ Task> GetAttachmentMetaByContactIdAsync(string contactId, int departmentId);
+
+ /// Live attachment rows for a set of contacts WITHOUT the Data column.
+ Task> GetAttachmentMetaByContactIdsAsync(int departmentId, IEnumerable contactIds);
+
+ /// One attachment including its blob.
+ Task GetAttachmentByIdAsync(int contactAttachmentId);
+ }
+}
diff --git a/Core/Resgrid.Model/Repositories/IRmsDefinitionRepositories.cs b/Core/Resgrid.Model/Repositories/IRmsDefinitionRepositories.cs
index b39c4166..7214eace 100644
--- a/Core/Resgrid.Model/Repositories/IRmsDefinitionRepositories.cs
+++ b/Core/Resgrid.Model/Repositories/IRmsDefinitionRepositories.cs
@@ -91,5 +91,11 @@ public interface IRmsExternalOrderFillsRepository : IRepositoryEvery fill of a set of orders in one pass; the deployment list would otherwise query once per order.
Task> GetForOrdersAsync(int departmentId, IEnumerable orderIds);
Task GetByIdForDepartmentAsync(int departmentId, string fillId);
+
+ ///
+ /// Claims the fill at . False when another writer moved first: the
+ /// in-memory check alone cannot stop two callers from both reading Requested and both writing.
+ ///
+ Task TryBumpRowVersionAsync(int departmentId, string fillId, long expectedVersion, CancellationToken cancellationToken = default);
}
}
diff --git a/Core/Resgrid.Model/Repositories/IRmsFieldRolloutRepository.cs b/Core/Resgrid.Model/Repositories/IRmsFieldRolloutRepository.cs
index ef983b77..16a8e9a2 100644
--- a/Core/Resgrid.Model/Repositories/IRmsFieldRolloutRepository.cs
+++ b/Core/Resgrid.Model/Repositories/IRmsFieldRolloutRepository.cs
@@ -9,7 +9,7 @@ namespace Resgrid.Model.Repositories
public interface IRmsFieldRolloutEventsRepository : IRepository
{
/// Every event in the window, oldest first. Bounded by so a dashboard cannot pull the archive.
- Task> GetForWindowAsync(int departmentId, DateTime sinceUtc, int take);
+ Task> GetForWindowAsync(int departmentId, DateTime sinceUtc, int take, CancellationToken cancellationToken = default);
/// Inserts a batch in one round trip; returns how many rows were written.
Task InsertBatchAsync(IEnumerable events, CancellationToken cancellationToken = default);
diff --git a/Core/Resgrid.Model/Repositories/IRmsPreventionRepositories.cs b/Core/Resgrid.Model/Repositories/IRmsPreventionRepositories.cs
new file mode 100644
index 00000000..979cca42
--- /dev/null
+++ b/Core/Resgrid.Model/Repositories/IRmsPreventionRepositories.cs
@@ -0,0 +1,259 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Resgrid.Model.Repositories
+{
+ /// Paged, filtered occupancy listing.
+ public sealed class RmsOccupancyQuery
+ {
+ public string Search { get; set; }
+ public int? Status { get; set; }
+ public int? OccupancyType { get; set; }
+ public bool? ReviewOverdue { get; set; }
+ public bool? HazmatOnSite { get; set; }
+ public int Skip { get; set; }
+ public int Take { get; set; } = 50;
+ }
+
+ public interface IRmsOccupanciesRepository : IRepository
+ {
+ Task GetByIdForDepartmentAsync(int departmentId, string occupancyId);
+ Task> GetByIdsAsync(int departmentId, IEnumerable occupancyIds);
+ Task> QueryAsync(int departmentId, RmsOccupancyQuery query);
+ Task CountAsync(int departmentId, RmsOccupancyQuery query);
+ Task> GetByNormalizedAddressAsync(int departmentId, string normalizedAddress);
+ Task> GetAllLiveAsync(int departmentId);
+ Task CountLiveAsync(int departmentId);
+ Task CountReviewOverdueAsync(int departmentId, DateTime utcNow);
+ Task TryBumpRowVersionAsync(int departmentId, string occupancyId, long expectedVersion, CancellationToken cancellationToken = default);
+ }
+
+ public interface IRmsOccupancyContactLinksRepository : IRepository
+ {
+ Task> GetForOccupancyAsync(int departmentId, string occupancyId);
+ Task> GetForContactAsync(int departmentId, string contactId);
+ Task> GetForContactsAsync(int departmentId, IEnumerable contactIds);
+ Task GetByIdForDepartmentAsync(int departmentId, string linkId);
+ }
+
+ public interface IRmsOccupancyHazardsRepository : IRepository
+ {
+ Task> GetForOccupancyAsync(int departmentId, string occupancyId);
+ Task> GetForOccupanciesAsync(int departmentId, IEnumerable occupancyIds);
+ Task GetByIdForDepartmentAsync(int departmentId, string hazardId);
+ }
+
+ public interface IRmsOccupancyCrosswalksRepository : IRepository
+ {
+ Task GetByIdForDepartmentAsync(int departmentId, string crosswalkId);
+ Task GetBySourceAsync(int departmentId, RmsOccupancyCrosswalkSourceKind sourceKind, string sourceId);
+ Task> GetByStateAsync(int departmentId, RmsOccupancyCrosswalkState state, int skip, int take);
+ Task> GetForOccupancyAsync(int departmentId, string occupancyId);
+ Task> GetForContactAsync(int departmentId, string contactId);
+ Task> GetForContactsAsync(int departmentId, IEnumerable contactIds);
+ Task> GetAllForDepartmentAsync(int departmentId);
+ Task CountByStateAsync(int departmentId, RmsOccupancyCrosswalkState state);
+ }
+
+ public interface IRmsOccupancyFieldProvenancesRepository : IRepository
+ {
+ Task> GetForOccupancyAsync(int departmentId, string occupancyId);
+ Task DeleteForOccupancyAsync(int departmentId, string occupancyId, CancellationToken cancellationToken = default);
+ }
+
+ public interface IRmsOccupancyOwnershipsRepository : IRepository
+ {
+ Task GetForDepartmentAsync(int departmentId);
+ }
+
+ public interface IRmsCodeSetsRepository : IRepository
+ {
+ Task GetByIdForDepartmentAsync(int departmentId, string codeSetId);
+ Task> GetForDepartmentAsync(int departmentId, bool includeInactive);
+ }
+
+ public interface IRmsCodeSectionsRepository : IRepository
+ {
+ Task GetByIdForDepartmentAsync(int departmentId, string sectionId);
+ Task> GetForCodeSetAsync(int departmentId, string codeSetId);
+ Task> GetByIdsAsync(int departmentId, IEnumerable sectionIds);
+ }
+
+ public interface IRmsInspectionProgramsRepository : IRepository
+ {
+ Task GetByIdForDepartmentAsync(int departmentId, string programId);
+ Task> GetForDepartmentAsync(int departmentId, bool includeInactive);
+ }
+
+ public sealed class RmsInspectionQuery
+ {
+ public string OccupancyId { get; set; }
+ public string ProgramId { get; set; }
+ public IList States { get; set; }
+ public string InspectorUserId { get; set; }
+ public DateTime? ScheduledBefore { get; set; }
+ public int Skip { get; set; }
+ public int Take { get; set; } = 50;
+ }
+
+ public interface IRmsInspectionsRepository : IRepository
+ {
+ Task GetByIdForDepartmentAsync(int departmentId, string inspectionId);
+ Task> QueryAsync(int departmentId, RmsInspectionQuery query);
+ Task CountAsync(int departmentId, RmsInspectionQuery query);
+ Task> GetForOccupancyAsync(int departmentId, string occupancyId);
+ /// Latest completed inspection per occupancy for a program; the scheduler's frequency anchor.
+ Task> GetLastCompletedByOccupancyAsync(int departmentId, string programId);
+ Task> GetOpenForProgramAsync(int departmentId, string programId);
+ Task TryBumpRowVersionAsync(int departmentId, string inspectionId, long expectedVersion, CancellationToken cancellationToken = default);
+ }
+
+ public interface IRmsViolationsRepository : IRepository
+ {
+ Task GetByIdForDepartmentAsync(int departmentId, string violationId);
+ Task> GetForInspectionAsync(int departmentId, string inspectionId);
+ Task> GetForOccupancyAsync(int departmentId, string occupancyId, bool openOnly);
+ Task> GetOpenAsync(int departmentId, int take);
+ Task> GetOverdueNotEmittedAsync(int departmentId, DateTime utcNow, int take);
+ Task CountOpenAsync(int departmentId);
+ Task CountOverdueAsync(int departmentId, DateTime utcNow);
+ Task> CountOpenByOccupancyAsync(int departmentId, IEnumerable occupancyIds);
+ }
+
+ public interface IRmsHydrantsRepository : IRepository
+ {
+ Task GetByIdForDepartmentAsync(int departmentId, string hydrantId);
+ Task GetByNumberAsync(int departmentId, string hydrantNumber);
+ Task> GetAllLiveAsync(int departmentId);
+ Task> GetByIdsAsync(int departmentId, IEnumerable hydrantIds);
+ Task> GetInBoundsAsync(int departmentId, decimal minLat, decimal maxLat, decimal minLon, decimal maxLon, int take);
+ Task CountLiveAsync(int departmentId);
+ Task CountOutOfServiceAsync(int departmentId);
+ Task CountTestDueAsync(int departmentId, DateTime cutoffUtc);
+ }
+
+ public interface IRmsHydrantFlowTestsRepository : IRepository
+ {
+ Task> GetForHydrantAsync(int departmentId, string hydrantId);
+ }
+
+ public interface IRmsHydrantMaintenancesRepository : IRepository
+ {
+ Task> GetForHydrantAsync(int departmentId, string hydrantId);
+ }
+
+ public interface IRmsPermitTypesRepository : IRepository
+ {
+ Task GetByIdForDepartmentAsync(int departmentId, string permitTypeId);
+ Task> GetForDepartmentAsync(int departmentId, bool includeInactive);
+ }
+
+ public sealed class RmsPermitQuery
+ {
+ public string OccupancyId { get; set; }
+ public string PermitTypeId { get; set; }
+ public IList States { get; set; }
+ public DateTime? ExpiresBefore { get; set; }
+ public int Skip { get; set; }
+ public int Take { get; set; } = 50;
+ }
+
+ public interface IRmsPermitsRepository : IRepository
+ {
+ Task GetByIdForDepartmentAsync(int departmentId, string permitId);
+ Task> QueryAsync(int departmentId, RmsPermitQuery query);
+ Task CountAsync(int departmentId, RmsPermitQuery query);
+ Task> GetForOccupancyAsync(int departmentId, string occupancyId);
+ Task> GetExpiringAsync(int departmentId, DateTime utcNow, DateTime horizonUtc, int take);
+ Task CountExpiringAsync(int departmentId, DateTime utcNow, DateTime horizonUtc);
+ Task TryBumpRowVersionAsync(int departmentId, string permitId, long expectedVersion, CancellationToken cancellationToken = default);
+ }
+
+ public interface IRmsPlanReviewsRepository : IRepository
+ {
+ Task> GetForPermitAsync(int departmentId, string permitId);
+ Task GetByIdForDepartmentAsync(int departmentId, string reviewId);
+ }
+
+ public interface IRmsCrrActivitiesRepository : IRepository
+ {
+ Task GetByIdForDepartmentAsync(int departmentId, string activityId);
+ Task> GetForRangeAsync(int departmentId, DateTime startUtc, DateTime endUtc, int take);
+ Task> GetForOccupancyAsync(int departmentId, string occupancyId);
+ }
+
+ public interface IRmsPreventionAttachmentsRepository : IRepository
+ {
+ Task GetByIdForDepartmentAsync(int departmentId, string attachmentId);
+ Task> GetMetadataForParentAsync(int departmentId, RmsPreventionParentKind parentKind, string parentId);
+ }
+
+ public interface IRmsPreventionSequencesRepository : IRepository
+ {
+ /// Atomically allocates the next number for a department/kind/year; safe under concurrent callers in either dialect.
+ Task NextAsync(int departmentId, string kind, int year, CancellationToken cancellationToken = default);
+ }
+
+ public interface IRmsInvestigationCasesRepository : IRepository
+ {
+ Task GetByIdForDepartmentAsync(int departmentId, string caseId);
+ Task> GetByIdsAsync(int departmentId, IEnumerable caseIds);
+ Task> GetForDepartmentAsync(int departmentId, bool includeClosed, int skip, int take);
+ Task CountOpenAsync(int departmentId);
+ Task