diff --git a/.claude/launch.json b/.claude/launch.json new file mode 100644 index 0000000..66208b1 --- /dev/null +++ b/.claude/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.0.1", + "configurations": [ + { + "name": "docs-serve", + "runtimeExecutable": "npx", + "runtimeArgs": ["docusaurus", "serve", "--port", "3111", "--no-open"], + "port": 3111 + } + ] +} diff --git a/docs/apps/dispatch.md b/docs/apps/dispatch.md index 30ec8a8..701cb78 100644 --- a/docs/apps/dispatch.md +++ b/docs/apps/dispatch.md @@ -164,6 +164,10 @@ Dispatch is the reference chat client: all channels, incident channels per call, With `Records.Field.Dispatch` enabled, dispatchers can start the NERIS incident report or a run record directly from the call. See [Records](../web-app/records/overview). +### Deployments and pre-plans + +Dispatchers see the department's **deployments** read-only (roster, window, identifiers, time-report status) so a call's crew and assignment are in view; time reports, usage and F-42 drafting are done from the Responder and Unit apps. A call's contact shows its **pre-plan** and **alert hazards** in the dispatch alert and on the Site Info tab. See [Deployment Finance](../web-app/business-ops/deployment-finance) and [Contacts](../web-app/contacts). + ## Settings & Configuration | Setting | Description | diff --git a/docs/apps/responder.md b/docs/apps/responder.md index a029ab1..0acfe0e 100644 --- a/docs/apps/responder.md +++ b/docs/apps/responder.md @@ -114,6 +114,16 @@ Personal and assigned checks (start-of-shift, personal gear, station duties) run When `Records.Field.Responder` is enabled, members author Records in the field (run reports, training records, department definitions such as SAR clue reports or damage assessments) with offline drafts, attachments and sync; finalisation can be handed to the web app. See [Records](../web-app/records/overview). +### Deployments + +With `Operations.Deployments` enabled the **Deployments** entry in the sidebar lists every deployment the member is rostered on (status, finance mode, window, incident and request numbers). Per deployment the member can: + +- **Time** — start the day's **daily time report** and add their own entries (*Deployment / Standby / Travel*, from–to, unpaid break, notes); the app checks for overlaps and end-before-start before **Submit report**. Approval stays on the web. +- **Usage** — record **odometer, engine hours and fuel** readings for a unit by phase (*Mobilization, Standby, Incident, Return*); conflicting readings are marked *Needs review*. +- **F-42** (Cal OES MARS, cost-recovery deployments) — draft the F-42 from the submitted time reports and **Validate** it against the portal rules; the handoff and every observation are web-only. + +Contacts attached to a call show the **pre-plan** (construction, shutoffs, water supply, access, hazards) and **site files** on the call's Site Info tab. See [Deployment Finance](../web-app/business-ops/deployment-finance), [Cal OES MARS](../web-app/business-ops/cal-oes-mars) and [Contacts](../web-app/contacts). + ## Settings & Configuration | Setting | Description | diff --git a/docs/apps/unit.md b/docs/apps/unit.md index 631c98e..48311b3 100644 --- a/docs/apps/unit.md +++ b/docs/apps/unit.md @@ -151,6 +151,10 @@ Unit-targeted checklists (apparatus daily / weekly, SCBA, equipment checks) run With `Records.Field.Unit` enabled the crew authors **Unit activity** and run records from the app, with the unit's times prefilled from status changes. See [Records](../web-app/records/overview). +### Deployments + +With `Operations.Deployments` enabled the hidden **Deployments** tab lists the deployments the active unit is rostered on. The crew files the **daily time report** for the whole crew (every seat plus the unit itself: *Deployment / Standby / Travel*, from–to, unpaid break), records **usage readings** (odometer, engine hours, fuel) per phase, and — on Cal OES cost-recovery deployments — drafts and validates the **F-42**. Submitted reports are approved on the web and feed [Contractor Billing](../web-app/business-ops/contractor-billing) or [Cal OES MARS](../web-app/business-ops/cal-oes-mars). See [Deployment Finance](../web-app/business-ops/deployment-finance). + ### Hardware GPS trackers Vehicles with a hardware tracker report position alongside (or instead of) the app; the web administrator sets the source priority. See [Hardware GPS Tracking](../web-app/unit-tracking). diff --git a/docs/intro.md b/docs/intro.md index 6aabf74..8e6369b 100644 --- a/docs/intro.md +++ b/docs/intro.md @@ -49,6 +49,15 @@ Screenshots in this documentation were taken from the current web application wi - **Inventory** — bulk and serialized stock, lots and expiry, issuance, kits, counts, alerts, purchasing and controlled-substance witnessing. [Inventory](web-app/inventory) - **Resource orders and department links** — mutual aid between departments. [Resource Orders](web-app/resource-orders) · [Department Links](web-app/department-links) +### Workforce and business operations + +- **Certifications** — a typed catalog of credentials for people and units, expiry dashboard, role requirements with warn-or-enforce, continuing-education credits and a compliance report (free). [Certifications](web-app/business-ops/certifications) +- **Deployment finance** — rosters, daily time reports, expenses, files and manifests for strike teams, contract work and mutual aid, captured in the apps (free). [Deployment Finance](web-app/business-ops/deployment-finance) +- **Invoicing and online payments** — billing profiles, rate cards, invoices from calls, PDFs and e-mail, payments through your own Stripe account, AR aging (Business Ops add-on). [Invoicing](web-app/business-ops/invoicing) +- **Contractor billing** — rate schedules, contracts with compliance documents, bids that become deployments, and invoices generated from approved time reports (Business Ops add-on). [Contractor Billing](web-app/business-ops/contractor-billing) +- **Cal OES MARS** — California mutual-aid reimbursement preparation, from F-5 and annual rates to F-42s, expense claims and invoice reconciliation (Business Ops add-on). [Cal OES MARS](web-app/business-ops/cal-oes-mars) +- **Workforce, field costing and pay data** — protected compensation and pay facts, resource cost profiles, cost runs with margin, and the California CRD pay data report (Business Ops add-on). [Workforce](web-app/business-ops/workforce) + ### Automation, security and integration - **Workflows** — event-driven automation with email, SMS, chat, webhook, API and file actions. [Workflows](web-app/workflows) @@ -58,7 +67,7 @@ Screenshots in this documentation were taken from the current web application wi ## Who uses it -Fire departments (volunteer, combination, career), EMS agencies, search and rescue teams, emergency management agencies and EOCs, incident management teams, CERT and community response programs, private security and campus security, industrial fire brigades and plant ERTs, delivery, transit and field-service operators, and the dispatch centres that serve several of them. Each has a [setup guide](setup-guides/overview). +Fire departments (volunteer, combination, career), EMS agencies, search and rescue teams, emergency management agencies and EOCs, incident management teams, CERT and community response programs, private security and campus security, industrial fire brigades and plant ERTs, delivery, transit and field-service operators, contract service providers (wildland contractors, private fire protection, private ambulance), and the dispatch centres that serve several of them. Each has a [setup guide](setup-guides/overview). ## Contributing to the documentation diff --git a/docs/reference/feature-flags.md b/docs/reference/feature-flags.md index 57ecfb2..3e92cc4 100644 --- a/docs/reference/feature-flags.md +++ b/docs/reference/feature-flags.md @@ -47,6 +47,15 @@ Writes go through the feature-toggle service, so caches are invalidated and an a | `Records.QualityReview` | Quality review rubrics and sampling. | `Records.System` | M0186 | | `Records.Analytics` | Records analytics dashboards. | `Records.System` | M0187 | | `Security.DepartmentProtectedDataEnrollment` | Platform-wide admission gate for **new** Advanced Data Protection enrollments (operator-managed; never affects departments already enrolled). | — | M0126 | +| `Business.Operations` | Master switch for every paid [Business Ops](../web-app/business-ops/overview) surface; the purchase itself is the Business Ops add-on. | — | M0211 (off) | +| `Invoicing.CustomerInvoicing` | Invoicing: billing profiles, rate cards, invoices, payments, aging. Also needs the Business Operations module switch and the add-on. | `Business.Operations` | M0211 (off) | +| `Payments.StripeConnect` | Operator-only per-region kill switch for online payment collection (on in the US cluster, off in the EU cluster at launch). Departments cannot override it. | — | M0212 (off, permanent) | +| `Invoicing.OnlinePayments` | Customers pay invoices through the department's own Stripe account. | `Invoicing.CustomerInvoicing`, `Payments.StripeConnect` | M0212 (off) | +| `Operations.Deployments` | Deployment Finance: deployments, rosters, daily time reports, expenses, files, external-order link. **Free** — no add-on. | — | M0219 (off) | +| `Invoicing.ContractorBilling` | Rate schedules, contracts, bids, the deployment wizard and invoice generation from time reports. | `Business.Operations` | M0219 (off) | +| `CostRecovery.CalOesMars` | Cal OES MARS cost recovery. | `Business.Operations` | M0219 (off) | +| `Workforce.InternalCosting` | Workforce compensation, work entries, resource costing and cost runs. | `Business.Operations` | M0224 (off) | +| `Compliance.CaliforniaPayDataReporting` | California CRD pay data report wizard and demographic self-identification; the department's Advanced Data Protection state must also be *Enabled*. | `Business.Operations` | M0224 (off) | ## Other gates @@ -54,8 +63,8 @@ Besides flags, a page can be hidden by: | Gate | Where | |---|---| -| **Module switches** (Messaging, Mapping, Shifts, Logs/Records, Reports, Documents, Calendar, Notes, Training, Inventory, Checklists, Maintenance) | Department Settings → Module Settings (`DepartmentModuleSettings`) | -| **Plan and add-ons** (PTT, ADP, Readiness Pro, Enterprise SSO) | Subscription & Billing; entitlement checked against the billing API (`SubscriptionsService`, `ReadinessAccessService`) | +| **Module switches** (Messaging, Mapping, Shifts, Logs/Records, Reports, Documents, Calendar, Notes, Training, Inventory, Checklists, Maintenance, Business Operations) | Department Settings → Module Settings (`DepartmentModuleSettings`) | +| **Plan and add-ons** (PTT, ADP, Readiness Pro, Business Ops, Enterprise SSO) | Subscription & Billing; entitlement checked against the billing API (`SubscriptionsService`, `ReadinessAccessService`, `BusinessOperationsAccessService`) | | **Permissions** | Security & Permissions | | **Records activation** | Records → Activate (`RmsDepartmentCutover`) | | **Installation config** | e.g. NERIS submission switched off system-wide, external connectors off, tracker gateway disabled | diff --git a/docs/setup-guides/_category_.json b/docs/setup-guides/_category_.json index 39c24ec..ecd7b00 100644 --- a/docs/setup-guides/_category_.json +++ b/docs/setup-guides/_category_.json @@ -3,6 +3,6 @@ "position": 5, "link": { "type": "generated-index", - "description": "Step-by-step configuration recipes for the kinds of organizations that run Resgrid: fire departments, EMS, search and rescue, emergency management, incident management teams, CERT, security companies, industrial emergency response teams, delivery and transit operators, and multi-agency dispatch centres." + "description": "Step-by-step configuration recipes for the kinds of organizations that run Resgrid: fire departments, EMS, search and rescue, emergency management, incident management teams, CERT, security companies, industrial emergency response teams, delivery and transit operators, multi-agency dispatch centres, and contract services providers." } } diff --git a/docs/setup-guides/cert-community-response.md b/docs/setup-guides/cert-community-response.md index 52aa6f8..f00599b 100644 --- a/docs/setup-guides/cert-community-response.md +++ b/docs/setup-guides/cert-community-response.md @@ -58,9 +58,17 @@ Enable Records and use the **CERT Operations Pack**: *CERT Damage Assessment* (p - Workflows: *Call created* → email the sponsoring agency; *Certification expiring (background check)* → member + coordinator. - **Connect** public profile for class schedules and recruitment. +## 8 — Workforce & Business Ops + +- **Certifications** (free): CERT basic training as a custom type, First Aid/CPR/AED, ICS-100 and IS-700 from the gallery; role requirements on *Team member* in **Warn only** with holder notifications so volunteers renew CPR on time. +- **Deployment Finance** (free, optional): a deployment per activation you are reimbursed or credited for (*Operational only*); volunteer hours from the daily time reports for grant and Points of Light reporting via the time CSV. + +See the [Workforce & Business Ops overview](../web-app/business-ops/overview) for what is free and what needs the add-on. + ## First-week checklist - [ ] Roster invited; ≥ 80 % verified email and mobile - [ ] Calendar types and the next three trainings entered with RSVP - [ ] A test deployment call received by everyone - [ ] CERT Damage Assessment definition published +- [ ] CERT basic and CPR types added; volunteers asked to enter their cards diff --git a/docs/setup-guides/contract-services-provider.md b/docs/setup-guides/contract-services-provider.md new file mode 100644 index 0000000..34215cf --- /dev/null +++ b/docs/setup-guides/contract-services-provider.md @@ -0,0 +1,88 @@ +--- +sidebar_position: 12 +title: Contract Services Provider +--- + +# Setting Up a Contract Services Provider + +For companies that send people and equipment out **under contract and get paid for it**: wildland fire contractors (engines, hand crews, water tenders, dozers), private fire-protection and standby companies, private ambulance and event-medical providers, and specialized rescue or safety contractors. The operational side (calls, units, personnel, statuses, checklists, records) follows the [fire](fire-department), [EMS](ems-agency) or [security](security-and-facilities) guide; this guide covers the **business** side that runs on the [Workforce & Business Ops](../web-app/business-ops/overview) modules. + +In Resgrid a **customer or agency is a contact with a billing profile**, a **resource order or event is a bid**, the work is a **deployment with a call**, each day is a **daily time report**, and payment is an **invoice with a packet**. + +## What you will end up with + +| Piece | You will have | +|---|---| +| Certifications | Every crew member's qualifications with expiry, enforced on the roles that seat them. | +| Rate schedules | Your rate tables per season / customer, explicit dollars per band. | +| Contracts | One per agency or client, with document requirements and compliance documents kept current. | +| Bids → deployments | A quote that becomes the call, the deployment and the roster in one step. | +| Time and expenses | Crews file daily time reports and receipts from the apps; an approver signs them off. | +| Invoices | Generated from approved time, sent with the packet, paid by cheque, ACH or online. | +| Costs | What each job cost you and the margin it made. | + +## 1 — Department settings and add-on + +| Setting | Value | +|---|---| +| Time zone | Your home base; deployments carry their own incident time zone. | +| Modules | Shifts, Checklists, Inventory, Records on; **Business Operations on**. | +| Add-on | **Subscription and Billing → Business Operations → Buy** (managing member). Certifications and Deployment Finance are free; everything else here needs it. | +| Flags | `Operations.Deployments`, `Business.Operations`, `Invoicing.CustomerInvoicing`, `Invoicing.ContractorBilling` (and `Invoicing.OnlinePayments` if you want pay links) — hosted customers ask support; self-hosted operators use `Resgrid.Console --FeatureFlags`. | +| Permissions | *Manage deployments* and *Approve time reports* → operations managers; *Manage bids* / *Manage contracts* / *Manage invoicing* → the office; *View invoicing* → owners. | +| Billing settings | Invoicing → Billing settings: legal name, remit-to address, tax registration(s), SAM UEI / CAGE / workers' comp account, invoice footer. | + +## 2 — Certifications + +- **Types** from the template gallery: wildland — NWCG FFT2/FFT1/CRWB/ENGB/DIVS, Red Card, RT-130, WCT, First Aid/CPR; private fire — FF1/FF2, DO-Pumper, Hazmat Ops; ambulance — NREMT + state licences, BLS/ACLS; all — CDL where drivers need it, DOT medical, MVR review. Units: DOT inspection, registration, insurance, pump test. +- **Role requirements**: *Crew member* = FFT2 + RT-130 + WCT; *Crew boss* = CRWB; *Engine boss* = ENGB; *Paramedic* = NREMT-P + state licence. **Enforce** with a short grace — an agency will refuse an unqualified seat and the deployment wizard flags it in red. +- Settings: notify holders 60/30/14/7 days and the office with the nightly digest; *Certification Expiring* workflow → training coordinator. + +## 3 — Customers, contracts and compliance + +- **Contacts**: each agency or client as a *Location or Company* contact with the AP e-mail; **billing profile** with terms (net 30–45), tax treatment (GST + PST components for Canadian agencies), the default rate card for ad-hoc work and the **default rate schedule**. +- **Compliance documents**: COI (annual, 30-day alert), workers' comp clearance, SAM registration and CAGE code, business licence, bonds — the contracts list warns before they lapse. +- **Contracts**: one *Standing arrangement* per agency (VIPR region, BCWS, state forestry, municipality) with the season's rate schedule, terms, **invoice submission e-mail**, max deployment days, response time and point of hire; document requirements: COI + WCB at *Deployment start*, signed DTR at *Daily time report*, packet at *Invoice submission*. Activate it. + +## 4 — Rate schedules + +One schedule per season or per agency rate agreement (**clone** last season's and change *effective on*): + +- **Policy**: 30-minute rounding, overtime basis *consecutive hours*, 4-hour cancellation minimum, unsafe stand-down 8 h, travel cap 12 h/day, no-clear-8 carry-over on, portal-to-portal only where the contract says so, fuel deduction per litre if the agency supplies fuel. +- **Premiums**: *Night*, *Hazard*, *Lead* as flat hourly adders per band. +- **Entries**: personnel per certification code (FFT2, FFT1, CRWB, ENGB, EMT, PARAMEDIC) with deployment 0–8 h, OT1 8–14 h, OT2 14 h+; crew family `type2-crew` sizes 4/6/8 with daily tiers and required certifications; vehicles (engine, tender, dozer, ambulance) daily + mileage with free km; equipment (chainsaw, pump, monitor) daily; service lines (mobilization fee). + +## 5 — Bids and deployments + +1. **Bid** per resource order or event: customer, contract, lines from the schedule (crew × hours/day × days, engine, mileage), valid until, requested window, delivery location; **Send bid** as PDF. +2. **Mark as accepted** → **Schedule deployment call**: the wizard sets the call, ticks the units, seats the crew (certification colours and overlapping deployments visible), equipment, rates & premiums, and creates the call + deployment + roster + calendar item. +3. Agency-ordered work without a bid: **Deployment Finance → New Deployment** (*Billable*, contact, contract, identifiers) or **Create from external order** when the order came through Records. + +## 6 — Time, expenses and approval + +- Crews use the **Responder** app (own row) or the **Unit** app (whole crew) to file the **daily time report** each day — deployment / standby / travel entries, breaks, km, no-clear-8 and stand-down flags — and to log **usage** (odometer, engine hours, fuel) and **expenses** with receipts (per diems with meal codes, accommodation, fuel, ferry). +- The crew boss **signs as contractor** and records the **customer signer name** from the paper DTR. +- An operations manager with *Approve time reports* approves each report (or voids it with a reason); *Time Report Submitted* workflow → approver channel. +- Files: signed service requests, agency forms and manifests on the deployment's **Files** tab; **File manifest PDF** at mobilization. + +## 7 — Invoicing and collection + +- **Billing tab → Charge preview** weekly (or at demobilization): fix anything listed as unpriced, then **Generate invoice**; review the draft, **Send with packet** to the contract's submission e-mail. +- Ad-hoc jobs: **Invoicing → New invoice → Add call** with the rate card. +- **Record payment** for cheques / ACH; connect **Stripe** under Billing settings → Online payments so private clients pay from the link. +- **Aging** weekly; workflow *Invoice Overdue* → owner; the deployment-finance digest lists approved time unbilled for 21 days. + +## 8 — Costs and margin + +- **Workforce**: employee compensation profiles (hourly base, OT multipliers, per-OT-hour components, employer costs) or a department default for estimates; **resource cost profiles** for every engine and tender (acquisition cost, life, fuel per mile, maintenance from work orders). +- **Cost runs**: *Estimate bid cost* before quoting; *Calculate deployment cost* with revenue source *Customer invoice* before sending the invoice — the **Internal cost** tab on the deployment shows estimate vs. actual. + +## First-week checklist + +- [ ] Business Ops add-on active; billing settings filled in +- [ ] Certification types added; role requirements enforced; every crew member's cards entered +- [ ] Compliance documents uploaded with alert leads +- [ ] One contract active with its rate schedule; a second schedule cloned for the next season +- [ ] Bid → accept → wizard → deployment tested; crew filed a DTR from the app; report approved +- [ ] Charge preview checked; invoice generated and sent with packet to yourself +- [ ] Stripe connected (if collecting online); a test pay link opened diff --git a/docs/setup-guides/delivery-transit-field-service.md b/docs/setup-guides/delivery-transit-field-service.md index 45cb7b9..040d352 100644 --- a/docs/setup-guides/delivery-transit-field-service.md +++ b/docs/setup-guides/delivery-transit-field-service.md @@ -64,6 +64,15 @@ From the **Operational report templates** pack: *Delivery Run Report* (Quick ent - Workflows: *Call closed (Delivery)* → email the customer contact with the proof-of-delivery export; *Record finalized (Run report)* → upload to the ERP SFTP; *Work order overdue* → Slack. - Weather alerts for winter operations. +## 9 — Workforce & Business Ops + +- **Certifications** (free): drivers — CDL-A/B and endorsements, DOT medical certificate, annual MVR review, FMCSA Clearinghouse query, drug & alcohol program, ELDT, road test, school-bus permit; vehicles — DOT annual inspection, registration, insurance, IFTA. Role requirements *Driver* = CDL + DOT medical + D&A program in **Enforce** (DOT compliance); unit certifications drive the *Vehicle out of service* decision. +- **Invoicing** (Business Ops): rate card *Service job* (flat per call), *Labour hour* (hourly personnel), *Mileage*, *Parts* (material); billing profiles per customer with GST/PST components where needed; online payments so customers pay from the invoice link; *Invoice Overdue* workflow to the office. +- **Contracts & rate schedules** (Business Ops, field-service contracts): a contract per client with a rate schedule (technician hourly bands, vehicle day rate) so recurring service deployments bill from daily time reports. +- **Field costing** (Business Ops): vehicle cost profiles (fuel per mile, maintenance from work orders, depreciation) and usage readings from the Unit app; call cost runs to price routes. + +See the [Workforce & Business Ops overview](../web-app/business-ops/overview) for what is free and what needs the add-on. + ## First-week checklist - [ ] Every vehicle as a unit with a tracker binding @@ -71,3 +80,5 @@ From the **Operational report templates** pack: *Delivery Run Report* (Quick ent - [ ] One route built and run end-to-end in the Unit app - [ ] Pre-trip checklist scheduled per vehicle with out-of-service on failure - [ ] Delivery Run Report definition published and exported via workflow +- [ ] CDL / DOT medical / inspection types enforced; vehicles carry their inspection records +- [ ] Rate card and one billing profile created; test invoice sent diff --git a/docs/setup-guides/emergency-management.md b/docs/setup-guides/emergency-management.md index fa6fd77..07007f5 100644 --- a/docs/setup-guides/emergency-management.md +++ b/docs/setup-guides/emergency-management.md @@ -69,6 +69,15 @@ From the **EOC Coordination Pack**: *EOC Duty / Shift Log* (Quick entry, one per - **Big Board** on the EOC wall; **Incident Command app** for the EOC manager. - **Connect** public profile for community preparedness posts. +## 9 — Workforce & Business Ops + +- **Certifications** (free): ICS-100/200/300/400, IS-700/800, CEM/AEM for staff and ESF partners in your department; role requirements on *EOC section chief* (ICS-300 + IS-800) in **Warn only**. +- **Deployment Finance** (free): every EMAC or state deployment your county sends or receives as a deployment (*Cost recovery*), created from the Records external order; daily time reports and expenses with receipts build the reimbursement package; the time CSV feeds the finance section. +- **Cal OES MARS** (Business Ops, California operational areas): agency profile, agreements and F-42s for fire and rescue resources dispatched through the mutual-aid system; the readiness dashboard before fire season. +- **Contacts**: shelter operators, ESF partners and vendors with pre-plans (occupant loads, shutoffs) and site files (floor plans of shelters). + +See the [Workforce & Business Ops overview](../web-app/business-ops/overview) for what is free and what needs the add-on. + ## First-week checklist - [ ] Sections and ESFs as groups; leads as group admins @@ -77,3 +86,5 @@ From the **EOC Coordination Pack**: *EOC Duty / Shift Log* (Quick entry, one per - [ ] EOC Duty Log and ESF Status Report definitions published - [ ] Warehouse inventory initialised; one resource order run end-to-end - [ ] Department links to partner agencies established +- [ ] ICS course types added from the template gallery +- [ ] Deployment created from an external order and a time report approved diff --git a/docs/setup-guides/ems-agency.md b/docs/setup-guides/ems-agency.md index acc1070..974be74 100644 --- a/docs/setup-guides/ems-agency.md +++ b/docs/setup-guides/ems-agency.md @@ -83,6 +83,15 @@ Assigned 12-hour or 24-hour shifts per station; supervisors approve trades. Turn - Workflows: *Call created* → API call to billing/ePCR; *Checklist failed (narcotics)* → email medical director; *Record finalized* → export template to the medical director weekly. - Chat: incident channels for handoffs; images off in general channels unless ADP is on. +## 11 — Workforce & Business Ops + +- **Certifications** (free): NREMT EMT/AEMT/Paramedic **and** state licences as separate types (both mandatory on the *Paramedic* role), BLS/ACLS/PALS, annual MVR review; units: state ambulance permit, DOT inspection, registration, insurance. **Enforce** with a 0-day grace on licences — an expired licence must not run calls. +- **Invoicing** (Business Ops): rate card *BLS transport*, *ALS transport* (flat per call), *Loaded mileage*, *Standby — event* (hourly unit); billing profiles per facility and event organizer (net 30, PO number noted, tax exempt where applicable); online payments through the company Stripe account; workflow *Invoice Overdue* → billing manager. +- **Deployment Finance / bids** (Business Ops): event medical standby as a bid (ALS unit crew line × hours × days) → wizard → deployment; crews file time in the Responder app; generate the invoice after the event. +- **Workforce & pay data** (Business Ops + ADP): employer, establishments and job assignments for California agencies with 100+ employees; run the CRD report each spring. + +See the [Workforce & Business Ops overview](../web-app/business-ops/overview) for what is free and what needs the add-on. + ## First-week checklist - [ ] Every ambulance created with two required roles and a Unit tablet @@ -91,3 +100,5 @@ Assigned 12-hour or 24-hour shifts per station; supervisors approve trades. Turn - [ ] Narcotics checklist with witness runs each shift - [ ] Medication lots with expiry entered; expiration alert reviewed - [ ] ADP decision made and, if enrolled, verification prompt tested on the Dispatch console +- [ ] Paramedic and EMT licence types enforced on the roles +- [ ] Rate card and one billing profile created; a test invoice sent to yourself diff --git a/docs/setup-guides/fire-department.md b/docs/setup-guides/fire-department.md index cfce1e3..b30e22c 100644 --- a/docs/setup-guides/fire-department.md +++ b/docs/setup-guides/fire-department.md @@ -113,6 +113,16 @@ Assign roles and stations; enter certifications with expiry dates. - **Communication tests**: monthly all-call page test. - **Chat**: department and station channels; incident channels are automatic. +## 13 — Workforce & Business Ops + +- **Certifications** (free): add FF1/FF2, Driver/Operator, Hazmat Ops, FO1, NREMT/state EMT and BLS from the template gallery plus NFPA 1911 pump and aerial tests for apparatus; role requirements *Firefighter* = FF1 + Hazmat Ops + (EMT **or** Paramedic), *Engineer* = DO-Pumper; start in **Warn only**, notify 60/30/14/7 days, move to **Enforce** after a year. +- **Deployment Finance** (free): every strike team or mutual-aid assignment as a deployment (*Cost recovery*), created from the Records external order; crews file daily time reports in the Responder / Unit apps, an officer approves them, the DTR PDFs and time CSV go into the reimbursement package. +- **Cal OES MARS** (Business Ops, California): agency profile verified each January, F-5 drafted from units, Salary Survey and Administrative Rate submissions, agreements per classification, one F-42 per request after each assignment, expense claims for lodging and meals, reconcile every MARS invoice. +- **Invoicing** (Business Ops): a rate card for cost recovery — *Hazmat response* (hourly unit, hazmat units, 2-hour minimum), *False alarm fee*, *Standby* — billing profiles for businesses and property managers; online payments if the treasury allows. +- **Field costing** (Business Ops): resource cost profiles for apparatus, role-default compensation per rank; a cost run after each deployment to compare with the reimbursement. + +See the [Workforce & Business Ops overview](../web-app/business-ops/overview) for what is free and what needs the add-on. + ## First-week checklist - [ ] Every member verified email + mobile and installed Responder @@ -122,3 +132,5 @@ Assign roles and stations; enter certifications with expiry dates. - [ ] Daily apparatus checklist scheduled and running - [ ] Records activated; one Run record finalized end-to-end - [ ] Security permissions reviewed; 2FA on for admins +- [ ] Certification types added and role requirements set (Warn only) +- [ ] One deployment created from a Records external order with a test time report approved diff --git a/docs/setup-guides/incident-management-team.md b/docs/setup-guides/incident-management-team.md index 309c41f..841528a 100644 --- a/docs/setup-guides/incident-management-team.md +++ b/docs/setup-guides/incident-management-team.md @@ -60,9 +60,20 @@ Use *Review required* for the IAP forms (planning section chief reviews), *Quick - Workflows: *Call created (Incident)* → email the team roster and post to the team Slack; *Record finalized (ICS 209)* → email the agency administrator. - Voice: PTT channels for Command and Operations. +## 8 — Workforce & Business Ops + +- **Certifications** (free): NWCG position qualifications (FFT1, CRWB, ENGB, DIVS), Red Card, RT-130, Work Capacity Test, ICS-300/400 and IS courses for every team member; role requirements per ICS position in **Warn only**; the compliance report before each season. +- **Deployment Finance** (free): every team deployment (IROC / EMAC order) as a deployment created from the Records external order, with the roster prefilled from accepted fills; members file daily time reports in the Responder app; the finance/admin unit leader approves them and exports the time CSV and DTR PDFs for the incident's cost package. +- **Cal OES MARS** (Business Ops, California): F-42 per request from the deployment, expense claims for travel, portal handoff by the authorized representative. +- **Field costing** (Business Ops): a cost run per deployment for the after-action financial summary. + +See the [Workforce & Business Ops overview](../web-app/business-ops/overview) for what is free and what needs the add-on. + ## First-week checklist - [ ] Roles = ICS positions; certifications entered - [ ] Command definition templates built and tested in the Incident Command app - [ ] ICS 202/204/205/206/214 definitions published with per-incident numbering - [ ] One exercise incident run end-to-end: call, command board, forms, AAR +- [ ] NWCG / ICS types added; positions carry requirements +- [ ] Deployment created from an external order with roster prefilled diff --git a/docs/setup-guides/industrial-emergency-response.md b/docs/setup-guides/industrial-emergency-response.md index 0bfe0e4..4978fcb 100644 --- a/docs/setup-guides/industrial-emergency-response.md +++ b/docs/setup-guides/industrial-emergency-response.md @@ -57,6 +57,15 @@ From the **Industrial Operations and Process Safety Pack**: *Operator / Control- - Workflows: *Call created (Level 2+)* → email site management + SMS the municipal FD liaison; *Work order safety hold applied* → Teams post to maintenance; *Record finalized (Near miss)* → export to the EHS system nightly. - **Weather alerts** for wind (release modelling) and lightning. +## 8 — Workforce & Business Ops + +- **Certifications** (free): HAZWOPER 40 + 8-hour refresher, confined space entry, lockout/tagout, respirator fit test, hearing conservation, bloodborne pathogens, first aid/CPR/AED, NCCCO crane where relevant; unit inspections for plant apparatus (pump tests, equipment annual inspections). Role requirements *ERT member* = HAZWOPER + respirator fit + first aid in **Enforce** — OSHA compliance depends on it; the compliance report to EHS monthly. +- **Deployment Finance** (free): plant turnarounds and mutual-aid responses to neighbouring sites as deployments (*Operational only* or *Cost recovery*); time reports and expenses for internal chargebacks. +- **Workforce & field costing** (Business Ops): workers per shift, establishments per plant, labor contractors for contract crews, compensation profiles and resource cost profiles for apparatus; call and deployment cost runs for chargebacks and budget justification. California sites with 100+ employees: employer profile, job assignments and the CRD pay data report (needs Advanced Data Protection). +- **Invoicing** (Business Ops, optional): bill standby (*Confined-space standby*, *Fire watch*) to internal cost centres or neighbouring plants. + +See the [Workforce & Business Ops overview](../web-app/business-ops/overview) for what is free and what needs the add-on. + ## First-week checklist - [ ] All ERT members with certifications and fit-test expiry dates @@ -64,3 +73,4 @@ From the **Industrial Operations and Process Safety Pack**: *Operator / Control- - [ ] Gas monitor and rescue equipment checklists scheduled with work-order-on-failure - [ ] Hazardous-work work order run through hold → release with an independent reviewer - [ ] Shift Handover and Near Miss definitions published +- [ ] OSHA training types enforced on the ERT role; compliance report scheduled to EHS diff --git a/docs/setup-guides/multi-agency-dispatch-center.md b/docs/setup-guides/multi-agency-dispatch-center.md index 22db0df..3eba1b7 100644 --- a/docs/setup-guides/multi-agency-dispatch-center.md +++ b/docs/setup-guides/multi-agency-dispatch-center.md @@ -44,6 +44,14 @@ Use **Orders** for cross-agency moves: the centre (or an agency) raises an order Records stay per agency (each agency's NERIS identity and definitions). The centre uses **Reports → Active calls and resources** and its own Run records for centre activity; for regional statistics ask agencies to schedule **report exports** to a shared mailbox, or use **saved reports** per agency. +## 7 — Workforce & Business Ops + +- **Certifications** (free): dispatcher credentials (EMD, CPR, state telecommunicator certification as custom types) with role requirements on *Dispatcher* in **Warn only**; the compliance report for accreditation. +- **Deployment Finance** (free): if the centre coordinates mutual-aid strike teams for member agencies, the sending agency owns the deployment in its own department; the centre only links the Records external order. +- **Invoicing** (Business Ops): bill member agencies per call or per month with a rate card (*Dispatched call* flat per call, *Dispatcher hour*) and billing profiles per agency contact; aging for the board. + +See the [Workforce & Business Ops overview](../web-app/business-ops/overview) for what is free and what needs the add-on. + ## Setup checklist - [ ] Centre department created; dispatchers with the Dispatcher role and Dispatch app login permission @@ -51,3 +59,4 @@ Records stay per agency (each agency's NERIS identity and definitions). The cent - [ ] Regional call type / priority naming agreed and applied in every agency - [ ] Big Board running with linked units visible - [ ] One resource order filled and returned end-to-end +- [ ] Dispatcher certification types added; agency billing profiles created if you invoice members diff --git a/docs/setup-guides/overview.md b/docs/setup-guides/overview.md index bc6fe59..d875271 100644 --- a/docs/setup-guides/overview.md +++ b/docs/setup-guides/overview.md @@ -23,6 +23,7 @@ Every guide assumes you have already created your department (hosted at [resgrid | Industrial fire brigade, plant emergency response team | [Industrial emergency response](industrial-emergency-response) | Dispatch, units, hazmat protocols, checklists, work orders with safety holds, inventory (serialized), records (industrial pack), indoor maps | | Delivery, courier, field service, bus / transit operator | [Delivery, transit & field service](delivery-transit-field-service) | Units as vehicles, routes, calls as jobs, records (delivery run / route EOD), hardware GPS tracking | | Central dispatch centre serving several agencies | [Multi-agency dispatch centre](multi-agency-dispatch-center) | Department links, resource orders, run cards, Dispatch app, Big Board | +| Wildland fire contractor, private fire protection, private ambulance / event medical, rescue or safety contractor | [Contract services provider](contract-services-provider) | Certifications, rate schedules, contracts, bids → deployments, daily time reports, contractor billing, invoicing, online payments, field costing | ## The order that works for everyone @@ -38,6 +39,7 @@ Whatever the guide, this order avoids rework: 8. **Security & permissions** — tighten what the defaults leave open (delete calls, view PII). 9. **Dispatch settings** — how groups/units/shifts dispatch; email/SMS import; run cards. 10. **Everything else** — records, checklists, inventory, shifts, calendar, workflows, notifications — one module at a time, with a champion for each. +11. **Workforce & Business Ops** — certifications first (free), then deployments, and — with the Business Ops add-on — invoicing, contracts and bids, Cal OES MARS, workforce and field costing; every guide ends with a section on it. ## Which app for whom diff --git a/docs/setup-guides/search-and-rescue.md b/docs/setup-guides/search-and-rescue.md index e58045e..9166aa7 100644 --- a/docs/setup-guides/search-and-rescue.md +++ b/docs/setup-guides/search-and-rescue.md @@ -71,6 +71,14 @@ Enable Records and create definitions from the **SAR Mission Pack**: *SAR Missio - Workflows: *Call created* → email the sheriff's dispatch a confirmation; *Message sent (poll)* → webhook to a roster sheet. - Voice: PTT channels per team where radio coverage is poor. +## 10 — Workforce & Business Ops + +- **Certifications** (free): SARTECH I–III, WFR/WFA, rope and swiftwater technician, avalanche, K9 team, helicopter operations, ICS-100/200; role requirements *Field team member* = SARTECH II **or** III, *Team leader* = SARTECH I; **Warn only** with holder notifications 60/30/7 days; the compliance report to the training officer quarterly. +- **Deployment Finance** (free): mutual-aid missions (state or EMAC deployments) as *Operational only* or *Cost recovery* deployments; volunteer hours per member from the daily time reports and the time CSV for grant reporting; expenses with receipts for reimbursement claims. +- **Field costing** (Business Ops, optional): resource cost profiles for UTVs, boats and drones to value in-kind contributions in grant applications. + +See the [Workforce & Business Ops overview](../web-app/business-ops/overview) for what is free and what needs the add-on. + ## First-week checklist - [ ] Roles match your capability matrix; certifications entered @@ -78,3 +86,4 @@ Enable Records and create definitions from the **SAR Mission Pack**: *SAR Missio - [ ] Test callout by SMS import received by all - [ ] Search-area layers loaded on the map and in Responder - [ ] SAR Mission Summary definition published; a training mission recorded end-to-end +- [ ] SARTECH and first-aid types added; team roles carry requirements diff --git a/docs/setup-guides/security-and-facilities.md b/docs/setup-guides/security-and-facilities.md index 61e4f84..a5184ba 100644 --- a/docs/setup-guides/security-and-facilities.md +++ b/docs/setup-guides/security-and-facilities.md @@ -69,6 +69,17 @@ From the **Operational report templates** pack: *Security Patrol Log* (Quick ent - Workflows: *Call closed* → email the client contact a summary from a Records export; *Form submitted (incident statement)* → create a work order via API. - **Communication tests** quarterly. +## 10 — Workforce & Business Ops + +- **Certifications** (free): guard card / security licence, first aid/CPR, use of force, armed endorsement and firearm requalification, forklift for facilities staff; role requirements *Security officer* = guard card, *Armed officer* = endorsement + requalification; **Enforce** with 0-day grace on the licence. +- **Contracts & compliance** (Business Ops): one *Standing arrangement* contract per client site and a *Project* contract per event, each with the client's rate schedule, terms and document requirements (guard roster at deployment start); compliance documents: company licence, COI, bond. +- **Rate schedules** (Business Ops): *Client rates* with personnel entries GUARD and SUPERVISOR (hourly, OT after 8 h), vehicle patrol hourly, premiums *Night* and *Holiday*, 15-minute rounding and a 4-hour call-out minimum. +- **Bids → wizard → deployments** (Business Ops): event work as bids (guard lines by hours/day × days, set-up fee); accept → wizard seats officers on posts (units) and creates the call; officers file daily time reports in the Responder app; generate the invoice after the event. +- **Invoicing & online payments** (Business Ops): rate card for ad-hoc work (*Alarm response* flat per call, *Officer hour*), billing profiles per client with net-30 terms; connect the company Stripe account so clients pay from the invoice link; *Invoice Paid* workflow → account manager. +- **Workforce & field costing** (Business Ops): employee compensation profiles with overtime multipliers, cost runs per client site per month to see the margin; California companies with 100+ employees run the CRD pay data report. + +See the [Workforce & Business Ops overview](../web-app/business-ops/overview) for what is free and what needs the add-on. + ## First-week checklist - [ ] Client and site groups with geofences; officers assigned; SSO tested @@ -76,3 +87,5 @@ From the **Operational report templates** pack: *Security Patrol Log* (Quick ent - [ ] Alarm-response run card tested with *Run Test* - [ ] Patrol Log and Incident Report definitions published; group scoping on - [ ] Start-of-shift checklist scheduled per vehicle +- [ ] Guard licence type enforced on the officer role +- [ ] Contract, rate schedule and one bid → deployment → invoice tested end to end diff --git a/docs/web-app/business-ops/_category_.json b/docs/web-app/business-ops/_category_.json new file mode 100644 index 0000000..60651eb --- /dev/null +++ b/docs/web-app/business-ops/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Workforce & Business Ops", + "position": 21, + "link": { + "type": "generated-index", + "description": "Customer invoicing and online payments, certifications, deployment finance (rosters, daily time reports, expenses), contractor billing (rate schedules, contracts, bids), Cal OES MARS cost recovery, workforce pay data, field costing and California pay data reporting." + } +} diff --git a/docs/web-app/business-ops/bids-and-deployment-wizard.md b/docs/web-app/business-ops/bids-and-deployment-wizard.md new file mode 100644 index 0000000..d05de2a --- /dev/null +++ b/docs/web-app/business-ops/bids-and-deployment-wizard.md @@ -0,0 +1,81 @@ +--- +sidebar_position: 8 +title: Bids & Deployment Wizard +--- + +# Bids & the Deployment Wizard + +A **bid** is a priced estimate for a customer — an engine and crew for a 10-day fire assignment, four guards for a festival weekend, an ALS unit on standby for a race. Its lines snapshot rates from the customer's [rate schedule](rate-schedules), it goes out as a PDF, and when the customer accepts, **Schedule deployment call** runs the **deployment wizard** that creates the call, the [deployment](deployment-finance) and the roster in one step — seats checked against certifications and other deployments. + +Business Ops add-on with `Invoicing.ContractorBilling`. Menu: **Workforce & Business Ops → Bids** (administrators and holders of *Manage bids*). + +![Bids](/img/web-app/bids/index.png) + +## Creating a bid + +**New bid**: pick the **customer** (the bid is addressed to its billing profile), an optional **contract** (supplies the rate schedule, discount and terms) and a title. **Create draft** allocates the next bid number. + +![Edit bid](/img/web-app/bids/edit.png) + +| Field group | Fields | +|---|---| +| **Header** | Title, description, contract, **rate schedule** (lines snapshot their rate from it), **valid until** (a submitted bid past this date is expired automatically), incident number, **requested start / end**, delivery location, **discount %** (cascades: contract → billing profile), notes, terms text. | +| **Lines** | Pick a **rate entry** to snapshot its rate (or type a free-form line): line type, crew size, **quantity × rate × hours/day × days**, premiums, taxable. With no schedule every line needs a typed rate. | +| **Estimate** | Subtotal, discount, **tax (estimated** from the billing profile) and estimated total. Actual charges follow the daily time reports. | + +**Preview** shows the customer-facing document; **PDF** downloads it. + +![Bid preview](/img/web-app/bids/preview.png) + +## Bid lifecycle + +![Bid](/img/web-app/bids/view.png) + +| Action | Effect | +|---|---| +| **Send bid** | E-mails the PDF to the customer (or another address) and marks it *Submitted*; **Resend bid** later. | +| **Mark as submitted** | Same without e-mailing (you sent it another way). | +| **Mark as accepted** / **Mark as declined** (with a reason) | Customer's answer. | +| **Reopen** | Puts a declined or expired bid back to *Submitted* so it can be accepted or resent. | +| **Withdraw** | You pulled a draft or submitted bid. | +| **Schedule deployment call** | Opens the wizard (accepted bids). | +| **Delete** | Draft bids only. | + +Statuses: **Draft, Submitted, Accepted, Declined, Expired, Withdrawn**. The bid page also links the **deployment** and **call** it was converted to. Workflow triggers: *Bid Created / Sent / Accepted / Declined / Expired*. + +## The deployment wizard + +Six steps on one page; nothing is written until the last one. + +![Deployment wizard](/img/web-app/bids/wizard.png) + +1. **Call details** — call name and nature, call type and priority, incident # and service request #, address, **start / end**, max deployment days, point of hire, *Out of province / state*, *Travel via air*, *Add to the department calendar*, notes. The call is created with these values so dispatch, the apps and Records see the assignment like any other call. +2. **Units** — tick the units to deploy, give each a call sign and map it to a **bid crew line**; the line's crew family sets the rate. +3. **Crew seats** — fill each unit's seats from the roster. Per person you see status, staffing, roles and typed certifications: **expired or suspended certifications are red**, those **expiring inside the window amber**, a **role not held** and **overlapping deployments** are flagged. Partial crews bill at the filled size. **Unassigned personnel** (no unit seat) bill under their own certification entry. +4. **Equipment** — per unit, free-text items or inventory assets with a daily-rate entry. +5. **Rates & premiums** — confirm the certification entry and premiums per person, the crew family per unit, the entry per equipment item; the **estimated customer charge per day** updates as you go. +6. **Review & create** — **Create call and deployment** writes the call, the deployment (*Billable*, linked to the bid and contract, identifiers copied from the bid), the roster with rate entries and premiums, and the calendar item. + +Afterwards the bid shows *Converted to a deployment*; the crew files daily time reports on the deployment and [Contractor Billing](contractor-billing) takes over. + +## Setup examples + +| Organization | Bids | +|---|---| +| **Wildland contractor** | One bid per resource request: crew line `type2-crew` size 6 × 12 h/day × 14 days, engine line, mileage; valid 48 h; wizard seats keyed on FFT1/FFT2 codes with RT-130 flagged. | +| **Fire protection company** | Annual standby bid per municipality under the master contract; accept → wizard creates a long-running call and deployment. | +| **Security company** | Event bids: guard lines by hours/day × days, supervisor premium, set-up fee service line; wizard assigns officers to posts (units). | +| **Private ambulance** | Event medical standby: ALS unit crew line × hours × days; wizard checks paramedic licences before seating. | +| **Industrial services** | Fire-watch or rescue standby for a plant turnaround: personnel lines by certification, equipment lines for monitors. | + +## Technical reference + +| Item | Value | +|---|---| +| Routes | `/User/Bids/{Index,New,Edit,View,Preview,Pdf}`; POST `Create`, `Save`, `Send`, `SetStatus`, `Delete`; `/User/DeploymentWizard/Index?bidId=` (GET) and `Create` (one POST with `RequestJson`) | +| Model | `Bid` (status, number, contract, schedule, discount, validity, requested window), `BidLineItem` (type, entry snapshot, crew size, qty, hours/day, days, rate, premiums), `DeploymentWizardRequest` | +| Services | `IBidsService` (`ConvertBidToDeploymentAsync` — transactional call + deployment + roster + calendar), `IDeploymentService.GetWindowConflictsAsync` | +| Permission | *Manage bids* (116) — grants view and edit; department administrators always | +| Worker | 31 `BidExpirationLogic`, daily: submitted bids past *valid until* → Expired | +| Workflow triggers | 74–78 | +| API | `api/v4/Bids/*` | diff --git a/docs/web-app/business-ops/cal-oes-mars.md b/docs/web-app/business-ops/cal-oes-mars.md new file mode 100644 index 0000000..b7ba1e0 --- /dev/null +++ b/docs/web-app/business-ops/cal-oes-mars.md @@ -0,0 +1,112 @@ +--- +sidebar_position: 10 +title: Cal OES MARS +--- + +# Cal OES MARS — Mutual-Aid Reimbursement + +California fire agencies that respond under the **California Fire Assistance Agreement (CFAA)** are reimbursed through Cal OES's **Mutual Aid Reimbursement System (MARS)**: an annual **Salary Survey**, **Administrative Rate** and **Attachment A** submission, an **F-5 resource inventory**, then an **F-42** and expense claim per resource order, an invoice Cal OES generates, and a payment from the paying entity. This module prepares all of it from the [deployment](deployment-finance)'s roster, daily time reports and expenses, checks it against the portal's rules, and gives you a **side-by-side handoff view** to type into MARS. + +:::info Resgrid never touches the portal +Resgrid stores no MARS credentials, MFA tokens or browser sessions and **never writes to MARS**. Submission is a manual, audited step you perform in the portal; afterwards a manager records what the portal shows (*Observed in MARS*). Cal OES determines the allowed amount — the *expected reimbursement* here is an estimate from the rates and agreement in effect at dispatch. +::: + +Business Ops add-on with `CostRecovery.CalOesMars`. Menu: **Workforce & Business Ops → Cal OES MARS**. Managers (administrators or *Manage Cal OES MARS reimbursement*) get the readiness dashboard; rostered members get their own **action queue** and can draft an F-42 for a deployment they are on. + +![Readiness dashboard](/img/web-app/cal-oes-mars/index.png) + +## Readiness dashboard + +Pick a **check date** (a dispatch date) and the dashboard lists **blockers** (stop new F-42s from reaching *Ready for portal*) and **warnings**, each with a **Fix** link: no agency profile or an unverified one, no annual submission covering the date, no agreement, F-5 mismatches, an authority profile that no longer covers the date. Below: the **annual submissions in effect**, the **agency** card (*Edit agency*, *Mark verified today*), **at-a-glance counts** (F-5 resources and mismatches, agreements, open work items, returned items, invoices awaiting local approval) and links to the **official sources** and the MARS portal. + +## Setting up (once a year) + +### 1. Agency profile + +**Cal OES MARS → Agency**: agency name, **MACS designator**, category, contact, address, **FEIN**, **SAM UEI**, SAM registration, **FI$Cal supplier**, portal role and a label for the portal account (never a password). These values are copied onto every F-42 and claim. **Mark verified** after comparing with the agency record in MARS; changing an identifier clears the verification and the dashboard warns after a year. + +![Agency profile](/img/web-app/cal-oes-mars/agency.png) + +### 2. F-5 resource inventory + +**Cal OES MARS → Resources**: the crosswalk from your units and assets to their MARS / F-5 identity. **Draft from units** copies each unit's name, plate and VIN; add the **resource type**, kind, designator, serial, **ownership** (local agency, Cal OES, CAL FIRE, private, rental), effective window and, once the portal shows it, the **MARS resource id** via **Record observation**. Review states: *Draft → Reviewed → Observed*, or *Mismatch* when what MARS shows differs. The F-42 flags apparatus that is *Not in the F-5 resource inventory*. + +![F-5 resources](/img/web-app/cal-oes-mars/resources.png) + +### 3. Annual rates + +**Cal OES MARS → Rates**: one **submission** per type and year — *Salary Survey*, *Attachment A (non-suppression)*, *Administrative Rate*, *Cal OES Rate Letter*, *Special Equipment / FEMA codes* — with its effective window, source URL/date/checksum and status **Draft → Reviewed → Signed locally → Submitted in MARS → Accepted** (or *Superseded* by a newer snapshot). An earlier dispatch keeps the submission in effect when it started. + +![Annual rate submission](/img/web-app/cal-oes-mars/rate-edit.png) + +| Panel | Use | +|---|---| +| **Rate lines** | Salary lines need a **classification**; equipment lines a resource or FEMA code; each has a basis (hourly, daily, per mile, percent, flat), **straight** and **overtime** rate, portal-to-portal and overtime eligibility, and whether workers' comp / unemployment insurance are included. **Build from workforce pay data** (with the [Workforce](workforce) module) fills the straight and overtime rates with the mean of the approved individual hourly rates per classification — aggregates only, a review aid; the authorized representative still signs in MARS. **Cal OES base rate accepted** skips your own survey rows. | +| **Administrative-rate inputs** | Prior-year actuals by function and category, classified *direct / indirect / unallowable*, with a *billed directly to an incident* exclusion and a *possible double count* marker that must be resolved. Budgets never enter here. | +| **Administrative-rate worksheet** | **Build administrative rate**: allowable indirect ÷ allowable direct from the accepted inputs, compared with the **de-minimis** option (10 %); choose the method. | + +### 4. Agreements + +**Cal OES MARS → Agreements**: the approved **MOU / MOA / GBR** compensation methods — *actual hours* or *portal-to-portal*, overtime after 8 or 12 hours or per agreement — per classification or department-wide, with a window and optionally the signed document uploaded as a deployment attachment. An F-42 selects the agreement in effect at initial dispatch; an agreement referenced by a submitted record is immutable (editing creates a new version). + +![Agreements](/img/web-app/cal-oes-mars/agreements.png) + +## Per incident + +### 5. The action queue + +**Cal OES MARS → Queue**: F-42s, expense claims and MARS invoices grouped by deployment with their local state, checklist result, observed status, expected amount and age. **Prepare a record** picks a *cost-recovery* deployment and builds an **F-42** — one per ordered resource / request (give the request or fill id when a Records order has several); a redispatch supersedes the earlier one — or an **expense claim** linked to an F-42 or on the *travel-only* path. + +![Action queue](/img/web-app/cal-oes-mars/queue.png) + +### 6. The F-42 work item + +![F-42 work item](/img/web-app/cal-oes-mars/work-item.png) + +The page follows the **official box order**: responding agency (MACS designator), incident (order number, request number, *redispatch of*, resource type, strike team / task force, reporting location, overhead position), **dispatch / commitment** and **return / redispatch** times (*release is not return* — the F-42 needs the return or redispatch time), apparatus / support vehicles / equipment (kind, designator, resource code, hours, miles, odometer), **personnel** (name, rank, classification, committed hours and actual hours from the DTRs), crew rotations with approval attachments, comments / loss-damage / supply numbers, **signatures** (responding agency signer, incident / AREP authorizer, or **Documentation only**) and attachments. Every value links to the immutable deployment facts it came from. + +Then, in order: + +| Step | What happens | +|---|---| +| **Run checklist** | Validates against the portal rules (missing return time, unsigned F-42 attachment, no agreement, apparatus not in F-5 …). A clean checklist moves the record to **Ready for portal**; errors leave it at *Needs review*. | +| **Calculate** | **Expected reimbursement** from the rates and agreement in effect at initial dispatch; a missing rate becomes an *Excluded* line with the reason, never a silent zero. No internal cost enters these lines. | +| **Open handoff view** | After ticking the attestation (*I am the authorized person entering this record in MARS*), a **side-by-side copy view** — box, value, source, *Copy* — for manual entry in the portal. Not stored, not cached, not a submission; opening it writes an audit entry only. **Evidence packet** downloads the supporting documents as a zip (it is *not* a MARS import file). | +| **Record submission observed in MARS** | The MARS record id and observed status → **Observed in MARS (Cal OES review)**. Later observations move it to *Returned for agency review* (closes the revision and opens a new one with the reviewer's comment), *Approved*, *Pending local agency approval*, *Pending paying entity* or *Paid*. | +| **Close** | Archives a finished item. | + +Field crews can draft and validate the F-42 from the [Responder, Unit and Incident Command apps](../../apps/responder#deployments); the handoff and every observation stay on the web. + +### 7. Invoices and payments + +**Cal OES MARS → Reconciliation**: **Record a MARS invoice** as you see it in the portal — MARS invoice id, date, invoiced total, paying entity, observed status and the submitted records it covers. The invoice page compares **expected versus observed** with the variance, takes the **local decision** (approve, or reject with a comment, by name / title — recorded here, entered in MARS by you), and **Record payment** (paid on, reference, paying-entity status) marks the invoice and its records **Paid** — only ever from an observed payment. + +![Reconciliation](/img/web-app/cal-oes-mars/reconciliation.png) + +A MARS invoice is a work item, never a customer invoice: no invoice number, no aging, no e-mail or online payment. + +## Reminders + +The daily reminder digest to administrators covers: annual Salary Survey / Administrative Rate submissions expiring, agreements expiring, resources released without a ready or submitted F-42 (due 14 days after release by default), expense claims missing evidence, records returned for review, and MARS invoices awaiting local approval. It never submits, approves, picks a rate or changes an observed state. + +## Setup examples + +| Organization | How to use it | +|---|---| +| **California municipal / county fire** | Full cycle: agency profile verified each January, F-5 drafted from units, Salary Survey built from Workforce pay data, agreements per classification, F-42 per strike-team request, expense claims for lodging and meals, reconciliation of every MARS invoice. | +| **California fire district (volunteer)** | Same, with *Cal OES base rate accepted* instead of a survey and *Documentation only* F-42s for non-reimbursable responses. | +| **CAL FIRE cooperator / contract county** | Attachment A (non-suppression) submissions; agreements per MOU. | +| **Out-of-state agency on a California assignment** | Not MARS — use the deployment's DTR PDFs and time CSV for the EMAC reimbursement package. | + +## Technical reference + +| Item | Value | +|---|---| +| Routes | `/User/CalOesMars/{Index,Agency,Resources,Rates,Rate,Agreements,Queue,WorkItem,Handoff,Print,Packet,Reconciliation,Invoice}` and their POST actions (`SaveAgency`, `VerifyAgency`, `BuildResources`, `ObserveResource`, `SaveRate`, `SaveRateLines`, `SaveAdministrativeInputs`, `BuildAdministrativeRate`, `BuildSalarySurvey`, `SetRateStatus`, `ObserveRate`, `SaveAgreement`, `ObserveAgreement`, `BuildF42`, `BuildExpense`, `SaveF42`, `Validate`, `Calculate`, `ObserveSubmission`, `ObserveStatus`, `RecordInvoice`, `DecideInvoice`, `RecordPayment`, `Close`) | +| Model | `Core/Resgrid.Model/CostRecovery/CalOesMars/` — agency profile, resource profiles (F-5), rate profiles + lines + administrative inputs, agreement snapshots, work items (F-42, expense claim, generated invoice) with revisions; `CalOesMarsAuthorityProfile` (reviewed code/data contract `CFAA-2026-08-21`: box order, request prefixes, status maps, 10 % de-minimis) | +| States | `CalOesMarsLocalStates`: Draft, NeedsReview, ReadyForPortal, SubmittedExternal, ReturnedForAgencyReview, Approved, DocumentationOnly, PendingLocalAgencyApproval, LocalAgencyRejected, PendingPayingEntityApproval, Paid, Closed | +| Permission | *Manage Cal OES MARS reimbursement* (79; claim actions view / update / submit / reconcile); rostered members prepare their own drafts without it | +| Config | `CostRecoveryConfig`: `CalOesMarsPortalUrl`, `F42DueDaysAfterRelease` 14, `AnnualDeadlineLeadDays` 45, `AgreementExpiryLeadDays` 30, `HandoffAttestationRequired` | +| Worker | 32 `DeploymentFinanceReminderLogic` MARS duties (daily) | +| Services | `ICalOesMarsService`, pure `ICalOesMarsReimbursementCalculator`, `ManualCalOesMarsGateway` (zero external writes) | +| API | `api/v4/CalOesMars/*` (queue, F-42 draft/validate for the apps) | diff --git a/docs/web-app/business-ops/certifications.md b/docs/web-app/business-ops/certifications.md new file mode 100644 index 0000000..8605586 --- /dev/null +++ b/docs/web-app/business-ops/certifications.md @@ -0,0 +1,133 @@ +--- +sidebar_position: 4 +title: Certifications +--- + +# Certifications + +**Certifications** tracks every credential your department relies on — firefighter and officer certifications, EMT / paramedic registry and state licences, CPR cards, NWCG red cards, guard cards, CDLs and DOT medical certificates for people; pump tests, aerial certifications, DOT inspections, registration, insurance and ambulance permits for **units** — with expiry dates, verification, continuing-education credits and **role requirements** that can warn or even remove a member from a role when a mandatory certification lapses. + +Free for every department. Menu: **Workforce & Business Ops → Certifications** (administrators and members with *View certifications*). Every member sees and manages **their own** certifications under **Profile → Certifications**. + +![Certification dashboard](/img/web-app/certifications/dashboard.png) + +## The pages + +| Tab | What it is for | +|---|---| +| **Dashboard** | Who holds what, what is expiring and what has lapsed — for **People** or **Units**, filtered by category, group and role; **Export CSV**. | +| **Certification types** | The catalog: your own types and a **template gallery** of 90+ common credentials. | +| **Settings** | Enforcement mode, grace period, expiry notification days. | +| **Compliance report** | Printable / exportable report of role requirements versus what members hold (under Reports). | + +## Setting up + +### 1. Certification types + +**Certifications → Certification types.** A type has a stable **code** (used by role requirements, rate schedules and integrations — it cannot change once a role requirement references it), a **category** (Fire, EMS, SAR, Wildland, Emergency management, Industrial, Security, Medical, Driver, Vehicle, Other), a scope (**Person** or **Unit**), an **issuing authority**, a **default validity in months** or *Never expires*, **credit hours per renewal** for con-ed cycles, and **Requires supervisor verification** (new records stay *Pending verification* until someone with *Manage certifications* signs them off). + +![Certification types](/img/web-app/certifications/types.png) + +The fastest start is the **Template gallery**: filter, tick the credentials you track and **Add selected**. Each template becomes a type your department owns and can edit. + +![Template gallery](/img/web-app/certifications/types-template-gallery.png) + +Highlights: + +| Category | Templates | +|---|---| +| **Fire** | Firefighter I/II, Driver/Operator Pumper and Aerial, Hazmat Operations and Technician (12 months), Fire Officer I/II, Instructor I, Inspector I, Fire con-ed (24 months, 24 credit hours) | +| **EMS / Medical** | NREMT EMR / EMT / AEMT / Paramedic (24 months with 16–60 credit hours), State EMT / AEMT / Paramedic licences, BLS, ACLS, PALS, PHTLS, medical-director skills verification, First Aid/CPR/AED, Wilderness First Aid / First Responder | +| **SAR** | SARTECH I–III, rope and swiftwater technician, avalanche, K9 team, helicopter operations | +| **Wildland** | NWCG FFT2 / FFT1 / CRWB / ENGB / DIVS, Red Card, RT-130 annual refresher, Work Capacity Test | +| **Emergency management** | ICS-100/200/300/400, IS-700/800, CEM, AEM | +| **Industrial** | OSHA 10/30, HAZWOPER 40 and 8-hour refresher, forklift, confined space, lockout/tagout, respirator fit test, hearing conservation, bloodborne pathogens, TWIC, NCCCO crane | +| **Security** | Guard card, armed endorsement, firearm requalification, baton/OC permit, use of force, PI licence, BC security worker licence | +| **Driver** | CDL A/B and P/S/H/N/T endorsements, DOT medical certificate, annual MVR review, Clearinghouse query, ELDT, road test, drug & alcohol program, school-bus permit | +| **Vehicle (units)** | DOT annual inspection, registration, insurance, IFTA, state ambulance permit, NFPA 1911 pump test, aerial and ground-ladder tests, crane/hoist and equipment annual inspections | + +**Show inactive** reveals retired types; a type with records can be deactivated but not deleted. + +### 2. Settings + +**Certifications → Settings.** + +![Certification settings](/img/web-app/certifications/settings.png) + +| Setting | Meaning | +|---|---| +| **Enforcement mode** | **Off** — requirements are informational (default). **Warn only** — role changes are allowed, warnings are shown and notifications sent. **Enforce** — adding an unqualified member to a role is blocked and members are **removed** from a role after the grace period once a mandatory certification lapses (audited; the member is notified). Switching to Enforce asks you to confirm how many mandatory requirements exist. | +| **Grace period (days)** | Days after a mandatory certification lapses before removal (default 30); each requirement can override it. | +| **Treat records pending verification as valid** | Whether an unverified record satisfies a requirement. | +| **Notify (days before expiry)** | Comma-separated lead days, e.g. `60,30,14,7,1`; one notice per record per listed day. | +| **Notify the holder directly** / **Send department administrators a nightly digest** | Who hears about expiring and expired certifications. Group audiences for the *Certification Expiring / Expired / Role Removed* and *Unit Certification* events are configured under [Notifications](../notifications). | + +### 3. Role requirements + +**Personnel → Roles → *role* → Required certifications** (or **Certifications → Certification types → Requirements**). + +![Role requirements](/img/web-app/certifications/role-requirements.png) + +Add one row per certification type: **Mandatory** (blocks or removes under *Enforce*; optional rows only show as *Optional missing*), an **Any-of group** number (rows sharing a number are alternatives — *EMT or AEMT or Paramedic*), **Allow trainee** and a **grace override**. The **Member eligibility** table below shows every member of the role as *Qualified*, *Optional missing* or *Not qualified* with the removal date under Enforce. + +## Day to day + +### Personal certifications + +**Profile → Certifications** (yours) or **Personnel → member → Certifications**: **Add Certification** with the name, **type**, number, valid area, issuing authority, issued and expiry dates and an attachment (PDF, image or office document up to 10 MB). Records typed with a type that *requires verification* wait for sign-off. + +![Personal certifications](/img/web-app/certifications/profile-certifications.png) + +Open a record for the full **certification record** page: **Verify**, **Renew** (new expiry and optionally a new number — reactivates an expired record), **Suspend / Revoke / Mark trainee / Reinstate** with a reason, and **continuing-education credits** (date, hours, category, description, file) with progress toward the hours the type needs per renewal. + +![Certification record](/img/web-app/certifications/record.png) + +| Status | Meaning | +|---|---| +| **Active** | Valid; counts toward requirements. | +| **Pending verification** | Entered but not yet signed off. | +| **Trainee** | Working toward the credential; satisfies a requirement only where *Allow trainee* is ticked. | +| **Expired** | Past the expiry date (set nightly by the worker); renew to reactivate. | +| **Suspended / Revoked** | Withdrawn by the department with a reason. | + +### Unit certifications and inspections + +**Units → unit → Certifications & inspections** (or the dashboard's **Units** scope): registration, insurance, permits, pump and ladder tests and annual inspections with number, issuer, issued/expiry dates, notes and a file. Units can be **suspended** (with a reason) and reinstated; the dashboard flags expiring and expired unit records the same way as people. + +![Unit certifications](/img/web-app/certifications/unit.png) + +### Dashboard and report + +The dashboard cards count **Expired**, **Expiring within N days**, **Suspended or revoked** and **Pending verification**; the grid below is one row per person (or unit) and one column per type, coloured *Valid / Expiring soon / Expired, suspended or revoked*. **Export CSV** downloads the grid. The **Compliance report** (Reports → Certification Compliance) lists role requirements against holders for auditors and accreditation. + +![Compliance report](/img/web-app/certifications/compliance-report.png) + +## Notifications and workflows + +The certification worker runs once a day per department (in the department's time zone): it expires records, sends the lead-day notices, and under *Enforce* removes members whose grace period has ended. [Workflow](../workflows) triggers: **Certification Expiring, Added, Renewed, Expired, Role Removed, Status Changed, Removed, Credit Added** and **Unit Certification Added / Expiring / Expired / Status Changed / Removed**. + +## Setup examples + +| Organization | Types | Requirements | Enforcement | +|---|---|---|---| +| **Career fire** | FF1/FF2, DO-Pumper/Aerial, Hazmat Ops, FO1, NREMT-EMT + state licence, BLS; units: NFPA 1911 pump test, aerial cert, registration, insurance. | *Firefighter*: FF1 + Hazmat Ops + (EMT or Paramedic any-of group); *Engineer*: DO-Pumper; *Lieutenant*: FO1. | Warn only for a year, then Enforce with 30-day grace. | +| **Volunteer fire** | FF1, Hazmat Awareness/Ops, BLS, DO-Pumper. | *Interior firefighter*: FF1 (allow trainee); *Driver*: DO-Pumper. | Off or Warn only; notify holders 60/30/7 days. | +| **EMS agency** | NREMT-EMT/AEMT/P, state licences, BLS/ACLS/PALS, driver MVR; units: ambulance permit, DOT inspection. | *Paramedic*: NREMT-P **and** state paramedic licence (two mandatory rows), ACLS. | Enforce — an expired licence must not run calls. | +| **SAR team** | SARTECH II, WFR, rope, swiftwater, K9, ICS-100/200. | *Field team member*: SARTECH II or III; *Team leader*: SARTECH I. | Warn only. | +| **Wildland contractor** | NWCG FFT2/FFT1/CRWB/ENGB, RT-130, WCT, Red Card, First Aid. | *Crew member*: FFT2 + RT-130 + WCT; *Crew boss*: CRWB. Rate schedule entries key on the same codes. | Enforce; the deployment wizard flags expiring cards. | +| **Security company** | Guard card, first aid/CPR, use of force, armed endorsement + requalification. | *Security officer*: guard card; *Armed officer*: armed endorsement + requalification. | Enforce; 0-day grace for the guard card. | +| **Industrial ERT** | HAZWOPER 40 + 8-hour refresher, confined space, respirator fit, first aid. | *ERT member*: HAZWOPER (annual refresher) + respirator fit. | Enforce. | +| **Delivery / transit** | CDL-A/B, DOT medical, MVR review, Clearinghouse query, drug & alcohol program; units: DOT inspection, registration, insurance, IFTA. | *Driver*: CDL + DOT medical + D&A program. | Enforce — DOT compliance. | + +## Technical reference + +| Item | Value | +|---|---| +| Routes | `/User/Certifications/{Index,DashboardCsv,Types,EditType,AddFromTemplate,Settings,RoleRequirements,Unit,Record}`; POST `SetStatus`, `Verify`, `Renew`, `AddCredit`, `DeleteCredit`, `SaveUnitCertification`, `SetUnitStatus`; `/User/Profile/{Certifications,AddCertification,EditCertification}`; `/User/Reports/CertificationComplianceReport` | +| Model | `DepartmentCertificationType` (code, category, applies-to, validity, verification, credit hours), `PersonnelCertification` (+ status, verification, type), `PersonnelCertificationCredit`, `UnitCertification`, `PersonnelRoleCertificationRequirement`, `DepartmentCertificationSettings`; template catalog `CertificationTypeTemplateCatalog` (93 templates) | +| Permissions | *Manage certifications* (42), *View certifications* (43), *Manage certification setup* (44) — default department administrators; members always see their own records | +| Worker | 34 `CertificationExpiryLogic` — hourly tick, one sweep per department per local day at `CertificationConfig.SweepLocalHour` | +| Notifications | Event types 25–29 (*Certification Expiring / Expired / Role Removed / Unit Certification Expiring / Expired*) through department notifications | +| Workflow triggers | 23, 87–93, 180–184 | +| Data protection | Certification name/number/issuer, unit certification fields, credits and status reasons are ADP-protected (catalog 26/27) when the department is enrolled | +| API | `api/v4/Certifications/*` | diff --git a/docs/web-app/business-ops/contractor-billing.md b/docs/web-app/business-ops/contractor-billing.md new file mode 100644 index 0000000..ec067f7 --- /dev/null +++ b/docs/web-app/business-ops/contractor-billing.md @@ -0,0 +1,74 @@ +--- +sidebar_position: 9 +title: Contractor Billing +--- + +# Contractor Billing + +**Contractor billing** turns the **approved daily time reports** of a *billable* [deployment](deployment-finance) into a customer [invoice](invoicing): one line per billing day per person, unit and equipment item, priced from the [rate schedule](rate-schedules) bands, with premiums, per diems, mileage and billable expenses, the contract's discount and the customer's tax — plus a **packet** (invoice PDF, time-report PDFs, receipts, compliance documents) ready for the agency's accounts-payable inbox. + +Business Ops add-on with `Invoicing.ContractorBilling`. Lives on the deployment page's **Billing** tab (administrators and holders of *Manage deployments*). + +![Billing tab](/img/web-app/deployment-finance/view-billing.png) + +## The billing tab + +| Panel | What it shows | +|---|---| +| **Charge preview** | Every approved, unbilled time report through the **through date**, expanded into charge lines: date, description (subject, band, DTR number), quantity, rate, amount; then subtotal, discount and total before tax. Subjects the engine cannot price are listed with the reason — *No personnel rate entry for certification 'X'*, *No crew or vehicle rate entry is pinned to this unit* — so you fix the roster or schedule before billing. | +| **Compliance checklist** | The contract's document requirements for this deployment and whether each is satisfied (current compliance document, uploaded attachment) or missing; optional rows are marked. | +| **Invoices** | Invoices already generated from this deployment. | +| **Generate invoice** | Creates a **draft invoice** from the preview; the billed time reports move to **Billed** and each invoice line remembers its time report. Review, edit and send it from Invoicing like any other invoice. | + +Generate as often as you like — weekly billing on a long assignment is normal; each run only takes the reports not yet billed. + +## How the engine prices a day + +For each approved time report and each subject on it: + +1. **Rounding** — the day's minutes are rounded up to the policy increment. +2. **Entry** — a person bills under the rate entry whose **certification code** matches their roster row; a unit bills under the **crew family** entry whose size equals the seats **actually filled that day** (a partial crew takes the nearest lower size); vehicles and equipment bill under the entry pinned to their roster row. +3. **Bands** — *Deployment* hours are split across the entry's *Deployment / Overtime 1 / Overtime 2* thresholds (consecutive hours or daily total, per the policy). *Standby* bills at the standby band. *Travel* bills flat at the deployment rate and never earns overtime unless the policy is **portal to portal**; the **travel cap** still applies. A **No clear 8** report starts the next day in the overtime band when the policy carries it over. +4. **Minimums** — the daily guarantee, cancellation minimum and unsafe stand-down hours lift the day's deployment hours; the lift bills at the deployment band. On a cancellation day people always get the full day; vehicles and equipment only if the policy says so. +5. **Adders** — each premium assigned to a person adds its per-band amount per hour; **out-of-province** deployments add the per-person daily band; vehicles add **mileage** above the free units per day and subtract agency-supplied fuel at the per-litre rate. +6. **Expenses** — expenses marked *Billable* pass through at cost (with receipts in the packet); per diems outside their meal window are warned, not blocked. +7. **Discount and tax** — the contract's discount (else the billing profile's) and the profile's tax rate or components are applied on the invoice. + +Every figure comes from a table you can see — there is no hidden formula. + +## The invoice and packet + +The generated invoice shows *Billed from this daily time report* on each line, **Open deployment** and **Download packet**. **Send with packet** e-mails the invoice PDF with the DTR PDFs, receipts and the compliance documents the contract requires at *Invoice submission* as one zip, to the contract's **invoice submission e-mail** by default. + +![Deployment invoice](/img/web-app/invoicing/view-deployment-invoice.png) + +The deployment-finance reminder digest tells administrators about approved time unbilled for more than 21 days. + +## Setup checklist + +1. Rate schedule with entries for every certification code, crew size, vehicle and equipment you deploy. +2. Contract (or billing-profile default schedule) for the customer, with document requirements. +3. Compliance documents current. +4. Deployment in *Billable* mode with the roster carrying certification codes and pinned entries (the wizard does this for you). +5. Daily time reports submitted by the crew and **approved** by someone with *Approve time reports*. +6. Billing tab → check the preview → **Generate invoice** → send with packet. + +## Setup examples + +| Organization | Billing rhythm | +|---|---| +| **Wildland contractor** | Weekly: approve the week's DTRs on Friday, generate the invoice, send with packet to the agency AP mailbox; reconcile the *Billed* reports against the agency's payment. | +| **Fire protection company** | Monthly per municipality: one deployment per contract year, invoice through the last day of the month. | +| **Security company** | Per event: approve DTRs after the event, generate one invoice, online pay link on. | +| **Private ambulance** | Per event or per month for recurring standby. | + +## Technical reference + +| Item | Value | +|---|---| +| Routes | `/User/Deployments/View?tab=billing`; POST `GenerateInvoice`; `/User/Invoicing/Packet`, `SendPacket` | +| Services | `IContractorBillingEngine` (`PreviewAsync`, `GenerateInvoiceAsync` → `LinkInvoiceToDeploymentAsync` + `MarkTimeReportsBilledAsync`, packet zip), pure `ContractorChargeCalculator` (rounding, band split, minimums, premiums, per diems, mileage/fuel, expenses) | +| Model | `ContractorChargeSet` / `ContractorChargeLine`; `Invoice.DeploymentId`, `InvoiceLineItem.CallId` / `DeploymentTimeReportId` | +| Permission | *Manage deployments* (118) plus the contractor-billing entitlement; approvals need *Approve time reports* (119) | +| Worker | 32 unbilled-time reminder digest (daily) | +| API | `api/v4/Deployments/GetDeploymentCharges`, `GenerateDeploymentInvoice` | diff --git a/docs/web-app/business-ops/contracts-and-compliance.md b/docs/web-app/business-ops/contracts-and-compliance.md new file mode 100644 index 0000000..34dd006 --- /dev/null +++ b/docs/web-app/business-ops/contracts-and-compliance.md @@ -0,0 +1,80 @@ +--- +sidebar_position: 7 +title: Contracts & Compliance +--- + +# Contracts & Compliance Documents + +A **service contract** fixes, for one customer, the [rate schedule](rate-schedules), discount, payment terms, where invoices are submitted and which **documents** the customer expects at each stage — so every bid, deployment and invoice under it inherits the same rules. **Compliance documents** are your own certificate of insurance, workers' compensation clearance, SAM registration, business licence, CAGE code, tax registration and bonds, kept with expiry alerts so a contract requirement is satisfied automatically and the right papers ride along in the invoice packet. + +Business Ops add-on with `Invoicing.ContractorBilling`. Menu: **Workforce & Business Ops → Contracts** (administrators and holders of *Manage contracts*). + +![Contracts](/img/web-app/contracts/index.png) + +## Contracts + +**New contract**: + +![Edit contract](/img/web-app/contracts/edit.png) + +| Field | Use | +|---|---| +| **Customer** | The contact (its billing profile receives the invoices). | +| **Name**, **Contract number**, **Contract type** | *Standing arrangement* (call-when-needed / VIPR-style), *Project*, *Master services*, *Other*. | +| **Start** / **End** | The contract window; a contract past its end is swept to *Expired* and *Contract Expiring* fires 30 days before. | +| **Rate schedule** | Fixed for every bid and deployment under the contract, or *Use the default schedule* (contact profile default → first active). | +| **Discount %**, **Terms (net days)** | Override the billing profile for contract invoices. | +| **Invoice submission e-mail** | Where deployment invoices and their packet are sent by default (an agency's AP mailbox or portal address). | +| **Max deployment days**, **Response time (minutes)**, **Point of hire** | Commercial terms copied onto deployments created under the contract. | +| **Document template** | A free-text key naming the document layout the customer expects (leave empty for *Generic*); stored with the contract for your own reference and for integrations — the built-in bid and invoice PDFs use one layout in this release. | +| **Activate now** | Save as *Active* instead of *Draft*. | + +**Document requirements** (bottom of the form): one row per document the customer expects, with the **stage** (*Bid submission*, *Deployment start*, *Daily time report*, *Invoice submission*), the **document type** and **Mandatory**. A compliance-document type is satisfied by a current department document; any other type is checked per deployment as an attachment. + +### Contract statuses + +**Draft → Active → Suspended / Expired / Terminated.** Change them from the contract page; only *Active* contracts can be picked for bids and deployments. *Contract Status Changed* and *Contract Expiring* are workflow triggers. + +### The contract page + +![Contract](/img/web-app/contracts/view.png) + +Shows the terms, the **document requirements** with their live state (*Satisfied* with expiry, *Missing*, or *checked per deployment*), and the linked **bids**, **deployments** and **invoices**. **New bid** starts a bid under the contract. + +## Compliance documents + +**Contracts → Compliance documents.** + +![Compliance documents](/img/web-app/contracts/compliance.png) + +| Field | Use | +|---|---| +| **Document type** | *Insurance certificate, Workers' comp clearance, SAM registration, Business licence, CAGE code, Tax registration, Bond, Other*. | +| **Name**, **Document number**, **Issuer** | Printed on the compliance checklist and in packets. | +| **Effective on** / **Expires** | Only a current document satisfies a requirement. | +| **Alert lead (days)** | Department administrators are notified when the document enters the window and again when it lapses (daily sweep). | +| **File** | PDF or image up to 30 MB; leave empty on edit to keep the stored file. | + +The contracts list shows a banner when any document is expiring or expired. Documents are attached to the invoice packet when the contract requires them at *Invoice submission*. + +## Setup examples + +| Organization | Contracts | Compliance documents | +|---|---|---| +| **Wildland contractor** | One *Standing arrangement* per agency (BCWS, USFS VIPR region, state forestry) with the season schedule, agency AP mailbox, max 14 deployment days, response time 120 min; requirements: COI + WCB at *Deployment start*, signed DTR at *Daily time report*, invoice packet at *Invoice submission*. | COI (annual, 30-day alert), WCB clearance (quarterly), SAM registration, CAGE code. | +| **Fire protection company** | *Master services* per municipality, 5-year window, net 45, discount 0. | COI, business licence, state fire-protection licence (as *Other*). | +| **Security company** | *Project* per event and *Standing arrangement* per client site; requirement guard-licence roster at *Deployment start*. | Security company licence, COI, bond. | +| **Private ambulance** | *Standing arrangement* per hospital group with PO required on the billing profile. | State ambulance service licence, COI. | +| **Municipal fire (cost recovery)** | Usually none — MARS and mutual-aid claims use agreements, not contracts. | COI where a neighbouring jurisdiction requires it. | + +## Technical reference + +| Item | Value | +|---|---| +| Routes | `/User/Contracts/{Index,New,Edit,View,Compliance}`; POST `Save`, `SetStatus`, `Delete`, `SaveComplianceDocument`, `DeleteComplianceDocument`; `ComplianceFile` download | +| Model | `ServiceContract` (type, status, schedule, terms, submission e-mail, `DocumentTemplateKey`, requirements JSON), `ServiceContractDocumentRequirement`, `DepartmentComplianceDocument` | +| Enums | `ServiceContractTypes`, `ServiceContractStatuses`, `DocumentRequirementStages`, `ComplianceDocumentTypes` | +| Permission | *Manage contracts* (117) — grants view and edit; department administrators always | +| Worker | 33 compliance expiry (daily): lapsed contracts → Expired, *Contract Expiring* ≤ 30 days once per day, compliance-document lead-window digest to administrators | +| Workflow triggers | 79 Contract Status Changed, 80 Contract Expiring | +| API | `api/v4/ServiceContracts/*` | diff --git a/docs/web-app/business-ops/deployment-finance.md b/docs/web-app/business-ops/deployment-finance.md new file mode 100644 index 0000000..5fbedc1 --- /dev/null +++ b/docs/web-app/business-ops/deployment-finance.md @@ -0,0 +1,114 @@ +--- +sidebar_position: 5 +title: Deployment Finance +--- + +# Deployment Finance + +A **deployment** is the money-and-time record of the units, personnel and equipment you sent somewhere: a strike team on a wildland assignment, an engine under contract at a film shoot, a crew loaned through EMAC, a medical team at a festival. It carries the **roster**, one **daily time report** (DTR) per day, **expenses** with receipts, **files** and a **manifest**, and it feeds — depending on its *finance mode* — nothing more than the record, a [Cal OES MARS](cal-oes-mars) claim, or a customer invoice through [Contractor Billing](contractor-billing). + +Free for every department behind the `Operations.Deployments` flag. Menu: **Workforce & Business Ops → Deployment Finance**. Administrators and holders of *Manage deployments* see every deployment; everyone else sees **My Deployments** — the ones they are rostered on — and can file time on them. + +![Deployments](/img/web-app/deployment-finance/index.png) + +:::note Two kinds of "deployment" +[Records → Deployments](../records/deployments) tracks the **external resource order** (IROC, EMAC, CIFFC) and its fills. Deployment Finance tracks what it **cost and earned**. Use **Create from external order** to link the two. +::: + +## Creating a deployment + +Three ways: + +| Start from | When | +|---|---| +| **New Deployment** | Anything you organize yourself. | +| **Create from external order** | A Records mutual-aid order is open: pick it, choose the finance mode and contact, optionally **prefill the roster from accepted fills** and **also create a call**. The order stays in Records. | +| **Bid → Schedule deployment call** | Contract work: the [deployment wizard](bids-and-deployment-wizard) creates the call, the deployment and the roster in one step. | + +![New deployment](/img/web-app/deployment-finance/new.png) + +| Field group | Fields | +|---|---| +| **Deployment** | Name; **Finance mode** — *Operational only* (time and expenses for the record), *Cost recovery* (feeds a reimbursement claim such as Cal OES MARS), *Billable* (feeds a customer invoice); **Contact** (the customer or requesting agency); **Call #** (optional — one deployment per call); **Window** start/end and **Max days**; notes. | +| **Agency identifiers** | Incident number, service request number, **resource order #**, **request #**, **cost code**, **point of hire** — whatever the ordering agency (VIPR, FEMA, BCWS, Cal OES) assigns; printed on time reports and invoices. | +| **Jurisdiction** | Home and host country / state-province, **time zone** (incident-local time for time reports; blank uses the department's), currency, **Out of province / state** and **Travel via air** (drive per-diem and travel rules in the rate schedule). | + +Statuses: **Planned → Standby → Active → Demobilizing → Completed** (or **Cancelled**); change them from the deployment page. Workflows fire on *Deployment Created* and *Deployment Status Changed*. + +## The deployment page + +![Deployment roster](/img/web-app/deployment-finance/view-roster.png) + +The header shows the identifiers, window, contact, call and external order; the **Summary** cards count units, personnel, time reports, personnel hours and expenses. Tabs: + +### Roster + +- **Units** — pick a unit and an optional call sign; the crew column shows how many seats are filled (this is the *crew size* that contract rates key on). +- **Equipment** — free-text items or inventory assets, issued to a unit or on their own, with **Return** when it comes back. +- **Personnel** — pick a member, a **seat** (a unit role; seats marked * require that personnel role and check its [certification requirements](certifications) — expiring certifications are flagged) and a **certification code** (which contract rate entry the person bills under). **Seat even when a requirement fails** overrides a failed check on purpose, audited. + +### Time reports + +One **daily time report** per day (**New time report** with the report date). Entries are prefilled from the roster with a default window you adjust. + +![Time report](/img/web-app/deployment-finance/time-report.png) + +| Element | Meaning | +|---|---| +| **Header** | Incident, resource order, request, cost code and point of hire copied from the deployment; **No clear 8** (overtime carries into the next shift) and **Unsafe conditions stand-down** flags for the billing policy. | +| **Time entries** | Subject (person, unit or equipment), **entry type** (*Deployment*, *Standby*, *Travel*), start and end (incident-local), paid and unpaid break minutes, km, notes. A subject cannot appear twice on the same report and only one report exists per day. | +| **Signatures** | **Sign as contractor** and the **customer signer name** — the agency representative who signed the paper DTR. | +| **Expenses** | Expenses attached to this day. | +| **Actions** | **Save**, **Save and submit** (entries lock once approved), **Approve** (needs *Approve time reports*), **Void** with a reason (kept for the record, dropped from billing), **PDF** and **File PDF on deployment** (stores the PDF under Files). | + +Report statuses: **Draft → Submitted → Approved → Billed** (set by the billing engine), or **Void**. Crews can create and submit their own DTRs from the [mobile apps](../../apps/responder#deployments); approval happens on the web. **Export time CSV** on the deployment page downloads every entry. + +### Expenses + +![Expenses](/img/web-app/deployment-finance/view-expenses.png) + +Date, **type** (*Per-diem meal, Accommodation, Private accommodation, Ferry, Fuel, Supply restock, Other*), amount and currency, description, city, **meal code** (B/L/D for per-diem windows), **receipt** upload, **Pre-approved** and **Billable**. Billable expenses pass through to the invoice; receipts ride along in the invoice packet and the MARS evidence packet. + +### Files + +Uploads by type — receipts, signed service request, time-report PDFs, manifest, certifications, external order, signed or paper F-42, ICS-213 approvals, crew rotation approvals, loss/damage, MARS evidence and invoices. **Preview manifest** renders the roster manifest; **File manifest PDF** stores it. + +### Billing (billable deployments, Business Ops add-on) + +Charge preview, compliance checklist, invoices and **Generate invoice** — see [Contractor Billing](contractor-billing). + +![Billing tab](/img/web-app/deployment-finance/view-billing.png) + +### Internal cost (Workforce entitlement) + +Estimate versus actual internal cost and the cost runs for this deployment — see [Field Costing](field-costing). + +![Costs tab](/img/web-app/deployment-finance/view-costs.png) + +## Reminders and workflows + +The deployment-finance reminder worker sends department administrators one digest a day listing billable deployments whose approved time reports have been unbilled for more than 21 days (or completed deployments with any unbilled report). It never generates or sends an invoice. Workflow triggers: **Deployment Created / Status Changed / Roster Changed / Expense Added / Attachment Added**, **Time Report Created / Submitted / Approved / Voided**. + +## Setup examples + +| Organization | Finance mode | Notes | +|---|---|---| +| **Municipal fire — strike team** | Cost recovery | Create from the Records external order; prefill roster; DTRs per day; Cal OES F-42 from the deployment (California) or the DTR PDFs for an EMAC / state reimbursement package. | +| **Wildland contractor** | Billable | Wizard from an accepted bid; seats keyed on NWCG codes; DTRs signed by the agency rep each day; generate the invoice and packet weekly. | +| **Private ambulance — event medical** | Billable | Manual deployment linked to the standby call; crews file time in the Responder app; expenses for supplies. | +| **SAR / CERT** | Operational only | Mission deployments for after-action documentation; hours per volunteer for grant reporting via the time CSV export. | +| **Security company — event** | Billable | One deployment per event contract; guard hours per DTR; supervisor premium from the rate schedule. | +| **Industrial ERT — plant turnaround** | Operational only or Cost recovery | Internal chargeback: time CSV plus a cost run. | + +## Technical reference + +| Item | Value | +|---|---| +| Routes | `/User/Deployments/{Index,New,Edit,View?tab=roster\|time\|expenses\|files\|billing\|costs,FromExternalOrder,TimeReport}`; POST `SetStatus`, `AddUnit/RemoveUnit`, `AddPersonnel/RemovePersonnel`, `AddEquipment/ReturnEquipment`, `NewTimeReport`, `SaveTimeReport`, `SignTimeReport`, `ApproveTimeReport`, `VoidTimeReport`, `SaveExpense`, `UploadAttachment`, `GenerateManifest`, `ExportTimeEntries`, `GenerateInvoice` | +| Model | `Deployment` (finance mode, status, identifiers, jurisdiction, `RmsExternalOrderId`), `DeploymentUnit`, `DeploymentPersonnel`, `DeploymentEquipment`, `DeploymentTimeReport` (pre-numbered per department), `DeploymentTimeEntry`, `DeploymentExpense`, `DeploymentAttachment` | +| Permissions | *Manage deployments* (118), *Approve time reports* (119) — default department administrators; rostered members see their own deployments and file DTRs without either | +| Flag | `Operations.Deployments` (free); `Records.System` needed for *Create from external order* | +| Worker | 32 `DeploymentFinanceReminderLogic`, daily | +| Time zones | DTR times are incident-local (`Deployment.LocalTimeZoneId`, else the department zone) and stored UTC | +| Data protection | `Deployment.Notes` is the only ADP-protected field (reveal on view/edit); DTRs, expenses and attachments are not protected because customers read them | +| API | `api/v4/Deployments/*`, `api/v4/TimeReports/*` (mobile DTR capture) | diff --git a/docs/web-app/business-ops/field-costing.md b/docs/web-app/business-ops/field-costing.md new file mode 100644 index 0000000..a1efa39 --- /dev/null +++ b/docs/web-app/business-ops/field-costing.md @@ -0,0 +1,67 @@ +--- +sidebar_position: 12 +title: Field Costing +--- + +# Field Costing + +**Field costing** answers "what did that job actually cost us?" — and, for a bid, "what will it cost?" A **cost run** adds up personnel (from [Workforce](workforce) compensation profiles and the hours on time reports or work entries), resources (from **resource cost profiles** and **usage readings** — depreciation, fuel, maintenance, tires, insurance), consumables, expenses and overhead into a **total loaded cost**, sets it against the revenue you observed (a bid's estimate, a customer invoice, a Cal OES expected / approved / paid amount) and shows the **contribution margin** and **break-even revenue**. + +Business Ops add-on with `Workforce.InternalCosting`. Menu: **Workforce & Business Ops → Workforce → Field costing** (administrators or *View internal costs*). Summaries are aggregate categories only; **lines** (who, what rate) need *View workforce compensation* and a Protected Data Grant. + +## Resource cost profiles + +**Workforce → Resource costs**: what a unit, inventory asset or **external resource class** costs to run. Plain numeric data (no person is priced here). + +![Resource costs](/img/web-app/workforce/resource-costs.png) + +| Panel | Fields | +|---|---| +| **Profile** | Subject (*Unit*, *Inventory asset*, or an *external resource key* — a rate schedule entry id lets bid estimates price vehicle and equipment lines by class), name, effective / expiry, currency, **allocation basis** (*mile, kilometre, engine hour, operating hour, day*), **expected annual utilization** (spreads fixed annual components and time-based depreciation), approved. | +| **Depreciation** | Acquisition cost and date, salvage value, useful life in allocation units or months: straight-line = (cost − salvage) ÷ life. | +| **Cost components** | *Fuel / energy* (a rate, or consumption × unit price), *Maintenance* (manual, or a **rolling work-order actual** over a meter window from [Work Orders](../work-orders)), tires, insurance / licensing, lease, storage, fixed overhead, consumables, other — per mile / km / engine hour / operating hour / idle hour / day / deployment or fixed annual. | + +## Usage readings + +**Resource usage** (from a cost run's *Resource usage* button, or **Workforce → Cost runs → Usage** for a deployment or call): odometer, engine meter, operating and idle hours, deployed / standby days and fuel per unit and day, tagged with the **phase** (*mobilization, standby, incident, return*) and the deployment or call. Distance is stored in miles (kilometres are converted). Readings come from the apps (crews record them on the deployment), from DTRs, GPS, hardware trackers or imports; a reading that conflicts with another by more than 10 % is queued for **review**. + +![Usage](/img/web-app/workforce/usage.png) + +## Cost runs + +**Workforce → Cost runs**: + +![Cost runs](/img/web-app/workforce/cost-runs.png) + +| Run | Inputs | Revenue | +|---|---|---| +| **Calculate deployment cost** (*actual*) | Approved daily time reports, usage readings and expenses through the **through date**. | The customer invoice, or the Cal OES MARS expected / approved / paid amount — your choice of **revenue source**. | +| **Estimate bid cost** (*estimate*) | Bid lines × department-default compensation and class resource profiles. | The bid's estimated total. | +| **Calculate call cost** (*actual*) | Work entries and usage readings recorded against the call. | None. | + +![Cost run](/img/web-app/workforce/cost-run.png) + +A run shows the **summary** by category (personnel, resources, consumables, expenses, overhead), total loaded cost, revenue, margin, break-even and **missing inputs** (a unit with no cost profile, a person with no compensation profile — priced with the fallback and flagged *estimated* / *fallback profile*), **estimate vs. actual** for deployments that started from a bid, and the **lines**. **Freeze** makes a run immutable; a later recalculation supersedes it. Statuses: *Draft, Needs review, Frozen, Superseded*. + +The same numbers appear as a **cost card** on the bid page and on the deployment's **Internal cost** tab. + +## Setup examples + +| Organization | Profiles | Runs | +|---|---|---| +| **Municipal fire** | Engines and trucks with acquisition cost, 15-year life, fuel per mile, rolling maintenance from work orders; role-default compensation per rank. | Deployment runs after every strike-team assignment to compare with the reimbursement; call runs for cost-recovery ordinance justification. | +| **Wildland contractor** | Engines, water tenders, chainsaws and pumps per engine hour or day; employee compensation with OT multipliers. | Bid estimate before quoting; deployment actual before invoicing to check the margin. | +| **Private ambulance** | Ambulances per mile; paramedic / EMT profiles. | Call cost for contract renewals; event deployment actual vs. bid. | +| **Security company** | Patrol vehicles per mile; officer profiles. | Bid estimate per event; deployment actual per client site per month. | +| **Industrial site** | Plant apparatus per operating hour. | Call cost for internal chargebacks. | + +## Technical reference + +| Item | Value | +|---|---| +| Routes | `/User/Workforce/{ResourceCosts,Usage,CostRuns,CostRun}`; POST `SaveResourceCost`, `DeleteResourceCost`, `SaveUsage`, `DeleteUsage`, `RunDeploymentCost`, `RunBidEstimate`, `RunCallCost`, `FreezeCostRun`, `DeleteCostRun` | +| Model | `ResourceCostProfile` + components, `ResourceUsageEntry`, `FieldCostRun` + lines (`FieldCostContextTypes` Bid / Call / Deployment, `FieldCostRunTypes` Estimate / Actual, `RevenueSources`, `FieldCostCategories`) | +| Permissions | *View internal costs* (74) for profiles, usage and summaries; *View workforce compensation* (76) + grant for lines | +| Services | `IFieldCostingService`, pure `FieldCostCalculator`; MARS revenue via `ICalOesMarsService` | +| Apps | Usage readings captured in the Responder and Unit apps' deployment screens | +| API | `api/v4/FieldCost/*` (aggregate summaries, rostered usage) | diff --git a/docs/web-app/business-ops/invoicing.md b/docs/web-app/business-ops/invoicing.md new file mode 100644 index 0000000..dfae375 --- /dev/null +++ b/docs/web-app/business-ops/invoicing.md @@ -0,0 +1,151 @@ +--- +sidebar_position: 2 +title: Invoicing +--- + +# Invoicing + +**Invoicing** bills the people and organizations you serve: a business for a hazmat clean-up, a facility for standby coverage, a municipality for contracted fire protection, an event organizer for medical cover, a client site for security hours. You keep a **billing profile** per customer, a **rate card** of what you charge, create **invoices** whose lines can be generated from the calls you ran, send them as PDF, record payments (or let the customer [pay online](online-payments)) and watch the **accounts-receivable aging**. + +Needs the **Business Ops** add-on, the *Business Operations* module switch and the `Invoicing.CustomerInvoicing` flag — see the [overview](overview#turning-it-on). Menu: **Workforce & Business Ops → Invoicing**. + +![Invoicing](/img/web-app/invoicing/index.png) + +## The pages + +| Tab | What it is for | +|---|---| +| **Invoices** | Outstanding and overdue balances, the invoice list with a status filter, **New invoice**. | +| **Rate Cards** | What you charge per call: hourly unit or personnel time, flat fees, mileage, materials. | +| **Aging** | Open balances grouped by how far past due they are. | +| **Billing settings** | Your legal name, remit-to address, registrations, invoice footer and the **Online payments** tab. | + +## Setting up + +### 1. Billing settings (once) + +**Invoicing → Billing settings.** Everything here is printed on every invoice and PDF. + +![Billing settings](/img/web-app/invoicing/settings.png) + +| Field | Use | +|---|---| +| **Legal business name**, **Remit-to address** | The header and the *remit to* block of the PDF. | +| **Tax registration number**, **Secondary tax registration** | Sales-tax / VAT / GST and PST numbers; a second registration prints beside the first (Canada). | +| **SAM UEI**, **CAGE code**, **Workers' comp account** | Federal-contract identifiers many agencies require on the invoice itself. | +| **Invoice footer** | Payment instructions, thank-you note or legal text printed under the totals. | +| **Pay link expiry (days)**, **Show a "Pay online" link on invoices** | Online-payment options (see [Online Payments](online-payments)). | + +### 2. Rate cards + +**Invoicing → Rate Cards → New rate card.** A rate card lists what you charge; mark one card as the **department default** and pin a different one on a customer's billing profile when that customer has negotiated rates. + +![Rate card](/img/web-app/invoicing/rate-card-edit.png) + +Save the card, then add **items**: + +| Item type | How the line is generated when you add a call | +|---|---| +| **Hourly unit** | One line per unit that was on the call: hours from the unit's first *On scene* status to its next status (or the whole call window if the unit never reported on scene). Optional **Unit type** filter (only engines, only ambulances …). | +| **Hourly personnel** | A line with the rate pre-filled and **quantity 0** — personnel hours on scene are not tracked per call, so the clerk types them. | +| **Flat per call** | Quantity 1 × rate. | +| **Fixed fee** | Quantity 1 × rate (administrative fee, report fee). | +| **Mileage**, **Material** | Rate pre-filled, quantity 0 for the clerk to enter. | + +Per item: **Rate**, **Unit label** (hour, mile, each), **Minimum charge**, **Minimum minutes** and **Round up to (minutes)** for hourly items (a 47-minute call with a 60-minute minimum and 30-minute rounding bills 1 h; 75 minutes bills 1.5 h), **Taxable**, **Sort order**, and a **description** printed on the invoice line. + +### 3. Billing profiles + +Open the customer's contact → **Billing** tab → **Set up billing profile** (or **Invoicing → New invoice → Set up billing profile**). Without a profile a contact cannot be invoiced. + +![Billing profile](/img/web-app/invoicing/billing-profile.png) + +| Field | Use | +|---|---| +| **Billing e-mail** | Where invoices are e-mailed; defaults to the contact's e-mail. | +| **Terms (net days)** | Due date = issue date + net days (30 if empty). A contract's terms override it for contract invoices. | +| **Default discount %** | Applied to every invoice for this customer (bids and deployment invoices inherit it when no contract sets one). | +| **Rate card** | Pin a card, or *Use the department default*. | +| **Default rate schedule** | Contractor billing only: the [rate schedule](rate-schedules) used for this customer's bids and deployments when no contract names one. | +| **Purchase order number required on invoices** | A reminder for billing staff that this customer expects a PO number — put it in the invoice notes; it is not enforced when sending. | +| **Active** | Untick to stop new invoices without deleting history. | +| **Billing address** | Printed on the invoice; tick *Use the contact's mailing address* to reuse it. | +| **Tax** | **Tax exempt**, a flat **Tax rate %**, or up to three named **tax components** (e.g. GST 5 % + PST 7 %) each with its own registration number printed on the invoice. | + +The profile page also lists the customer's invoices. + +## Creating and sending an invoice + +1. **Invoicing → New invoice**: pick the customer (contacts with a billing profile are listed first) and the currency. **Create draft** allocates the next invoice number for the department. + + ![New invoice](/img/web-app/invoicing/new.png) + +2. **Edit the draft**: currency, due date (leave empty to use the profile terms), discount %, notes and terms text; **line items** with description, quantity, rate and taxable flag. Totals — subtotal, discount, tax, total — are recalculated when you save. + + ![Edit invoice](/img/web-app/invoicing/edit.png) + +3. **Add call** opens the picker with every call linked to this customer (the call's contact). Choose a rate card; lines are generated as described above and added to the draft for you to correct before saving. A call already on this invoice is marked *On this invoice*. + + ![Add call](/img/web-app/invoicing/edit-call-picker.png) + +4. **Preview & send** opens the invoice page. **Download PDF** to check it, then **Send invoice** e-mails the PDF to the billing e-mail (you can change the address) and moves the invoice from *Draft* to *Sent*. **Mark as sent (no e-mail)** does the same without e-mailing — for invoices you post or upload to a customer portal. **Send with packet** (deployment invoices) attaches the daily time report PDFs, receipts and the compliance documents the contract requires as one zip. + + ![Invoice](/img/web-app/invoicing/view.png) + +A sent invoice can no longer be edited. **Re-send invoice** sends it again. + +## Payments + +**Record payment** (manual payments only — online payments record themselves): amount, paid-on date, method (*Check, Cash, ACH, Card (external), Other*), reference and notes. The status follows the balance: + +![Partially paid invoice](/img/web-app/invoicing/view-paid.png) + +| Status | Meaning | +|---|---| +| **Draft** | Editable; not yet issued. | +| **Sent** | Issued and awaiting payment. | +| **Partially paid** | Some payment recorded, balance open. | +| **Paid** | Balance settled (paid-on date = last payment). | +| **Overdue** | Sent or partially paid and past the due date — set automatically every 15 minutes by the invoice maintenance worker. | +| **Void** | Cancelled with a reason. Keeps its number; cannot be edited or paid. **Void** is hidden once a payment exists. | + +Online payments that are **refunded** or **disputed** reduce the effective amount paid and reopen the balance; see [Online Payments](online-payments). + +## Accounts-receivable aging + +**Invoicing → Aging**: every open invoice in buckets **Current**, **1–30**, **31–60**, **61–90** and **90+ days past due**, with totals per currency (balances in different currencies are never added together). Click a number to open the invoice. + +![Aging](/img/web-app/invoicing/aging.png) + +## Invoices from deployments + +Contract work is billed through [Contractor Billing](contractor-billing): the engine drafts the invoice from approved daily time reports, and the invoice page shows which report each line came from (*Billed from this daily time report*), **Open deployment** and **Download packet**. + +![Deployment invoice](/img/web-app/invoicing/view-deployment-invoice.png) + +## Notifications and workflows + +[Workflows](../workflows) can fire on **Invoice Created, Sent, Payment Recorded, Paid, Overdue, Voided, Payment Refunded** and **Payment Disputed** — for example, post an overdue invoice to a finance channel or push a paid invoice to your accounting system with the *API call* action. + +## Setup examples + +| Organization | Rate card | Profiles | +|---|---|---| +| **Municipal fire — cost recovery** | *Hazmat response* (hourly unit, hazmat units only, 2-hour minimum, 30-minute rounding), *False alarm fee* (flat per call), *Report copy* (fixed fee), *Absorbent / foam* (material). | Businesses and property managers; tax exempt off; net 30. | +| **Private ambulance** | *BLS transport* and *ALS transport* (flat per call), *Loaded mileage* (mileage), *Standby — event* (hourly unit). | Facilities and event organizers; net 30; PO required for the hospital group. | +| **Fire protection company** | *Engine standby* (hourly unit, 4-hour minimum), *Firefighter hour* (hourly personnel), *Admin fee* (fixed fee). | One profile per municipality with the negotiated rate card pinned. | +| **Security company** | *Officer hour* (hourly personnel), *Supervisor hour*, *Vehicle patrol* (hourly unit), *Alarm response* (flat per call). | One profile per client site; online payments on; GST/PST components for Canadian clients. | +| **Industrial / plant brigade** | *Confined-space standby* (hourly unit), *Fire watch* (hourly personnel). | Internal cost centres as company contacts; discount 100 % for internal reporting. | + +## Technical reference + +| Item | Value | +|---|---| +| Routes | `/User/Invoicing/{Index,New,Edit,View,RateCards,EditRateCard,Aging,Settings,BillingProfile}`; POST `Save`, `Send`, `MarkSent`, `Void`, `RecordPayment`, `Pdf`, `Packet`, `SendPacket`, `CallsForInvoice`, `PreviewCallLines`, `SaveRateCard(Item)`, `DeleteRateCard(Item)` | +| Model | `Invoice` (status enum Draft/Sent/PartiallyPaid/Paid/Overdue/Void), `InvoiceLineItem`, `InvoicePayment`, `RateCard`, `RateCardItem`, `CustomerBillingProfile`, `DepartmentBillingIdentity`, `InvoiceNumberSequence` | +| Permissions | *Manage invoicing* (40), *View invoicing* (41) — default department administrators | +| Gates | Flag `Invoicing.CustomerInvoicing` (child of `Business.Operations`), module switch, active add-on (every POST answers 402 *AddonRequired* when lapsed) | +| Worker | 29 `InvoiceMaintenanceLogic` every 15 minutes: overdue transitions, payment-request reconciliation, connection re-verification, webhook purge | +| E-mail | Postmark template `InvoiceDelivery` via `IEmailService.SendInvoiceAsync` (PDF attachment; optional packet zip) | +| API | `api/v4/Invoices/*` | +| Data protection | Invoices, line items, payments, billing profiles and billing identity are **not** ADP-protected (customers read them without a login); the contact row itself may be. | diff --git a/docs/web-app/business-ops/online-payments.md b/docs/web-app/business-ops/online-payments.md new file mode 100644 index 0000000..349b9ef --- /dev/null +++ b/docs/web-app/business-ops/online-payments.md @@ -0,0 +1,70 @@ +--- +sidebar_position: 3 +title: Online Payments +--- + +# Online Payments + +**Online payments** let a customer pay an [invoice](invoicing) with a card, wallet or US bank debit from a link on the invoice — without you handling card numbers. The money goes to **your department's own Stripe account**: Resgrid never holds the funds, takes no fee and cannot issue refunds. You connect the account once, and every invoice can then carry a **Pay online** link. + +Needs the Business Ops add-on, the `Invoicing.OnlinePayments` flag and the operator's regional switch (`Payments.StripeConnect`). Stripe is the only provider in this release. + +## Connecting your Stripe account + +**Invoicing → Billing settings → Online payments** (department administrators only). + +1. **Connect with Stripe** — you are sent to Stripe, sign in to (or create) your Stripe account and allow Resgrid to create payment pages on it. Resgrid stores your Stripe **account id** only, never your Stripe credentials or keys. +2. Back in Resgrid the panel shows the **connected account** (business name, live or sandbox mode, connected on, last verified, capabilities such as *card* and *us_bank_account*, last error if Stripe reported one). +3. **Collection settings**: tick **Offer online payment on invoices** and choose the **accepted payment methods** — *Cards and wallets* and/or *Bank debit (ACH, US accounts)*. A method your Stripe account cannot accept is not offered even if ticked. +4. Under **Billing identity** set the **pay link expiry (days)** and whether to **show a "Pay online" link on invoices** (printed on the PDF and included in the e-mail). + +**Disconnect** stops new pay links immediately; open links stop working. **Reconnect with Stripe** repeats the authorization (for example after changing Stripe accounts). + +If the panel says *Online payments are not yet enabled for your department*, ask Resgrid support to turn the flag on; *Online payment collection is suspended by the operator in this region* means the regional switch is off — your connection is kept and links resume when it is re-enabled. + +## What the customer sees + +The invoice e-mail and PDF carry the pay link (`/pay/`). The page shows the department name, invoice number, **amount due** and due date, and a **Pay** button that opens Stripe's hosted checkout. Card or bank details are entered on Stripe's page only. Afterwards the customer sees *Thanks — your payment is being confirmed* (or *Payment cancelled — nothing was charged* if they backed out); Stripe e-mails its own receipt. + +A link is valid for the expiry you set; **Refresh payment page** on the invoice issues a fresh one. Paying twice is not possible — a second click on the link resumes the open payment page. + +## What you see + +On the invoice page the **Pay online** panel shows the link (**Copy link**), the current **payment request** with its status and expiry, and buttons to **Open payment page now** or **Refresh payment page**. Online payments appear under **Payments** with method *Online*, the Stripe **fee**, a **receipt** link and a **payment status**. + +| Request status | Meaning | +|---|---| +| Created / Opened | Link issued / customer opened the page. | +| Processing | Bank debit initiated; funds not yet confirmed (can take a few business days). | +| Completed | Paid — the payment is recorded and the invoice status updates. | +| Expired / Cancelled / Failed | Nothing charged; refresh the payment page to try again. | + +| Payment status | Effect on the invoice | +|---|---| +| Succeeded | Counts toward the balance. | +| Refunded / Partially refunded | Reduces the amount paid; the balance reopens (refunds are issued in your Stripe dashboard, never from Resgrid). | +| Disputed / Dispute lost | The amount is held back from the balance while the dispute is open and removed if it is lost. | + +Invoice status changes come only from Stripe's confirmation (webhook or the 15-minute reconciliation), never from the customer returning to the page. + +## Setup examples + +| Organization | Recommendation | +|---|---| +| **Private ambulance / fire protection company** | Connect the company Stripe account; cards + ACH; 30-day link expiry; *Show "Pay online"* on. | +| **Municipal fire** | Usually off — municipalities collect through the treasury; if on, connect the city's Stripe account and restrict to cards. | +| **Security / facilities company** | On, cards + ACH; net-30 profiles; workflow *Invoice Paid* → notify the account manager. | +| **EU departments** | Online collection is switched off at the operator level in the EU region in this release; invoicing itself works. | + +## Technical reference + +| Item | Value | +|---|---| +| Flags | `Payments.StripeConnect` (operator-only, per cluster, prerequisite) and `Invoicing.OnlinePayments` (child of `Invoicing.CustomerInvoicing`) | +| Config | `PaymentConnectConfig` (Connect client id/secret, `PublicBaseUrl`, `WebhookPath`, `RequestReconcileAfterMinutes`, `EventRetentionDays`, `WebhookStaleAfterHours`) — separate from the SaaS-billing `PaymentProviderConfig` | +| Provider | `Providers/Resgrid.Providers.Payments` — Stripe Connect **OAuth** (Standard accounts), direct charges with the `Stripe-Account` header, one Checkout Session per attempt | +| Tables | `DepartmentPaymentConnections`, `InvoicePaymentRequests`, `PaymentConnectEvents` (webhook idempotency; payer PII minimized) | +| Endpoints | `/pay/{token}` (`PayController`, anonymous, `_RecoveryLayout`), `api/PaymentWebhooks/stripe` on the API host, v4 `Invoices/GetOnlinePaymentsStatus`, `GetPaymentConnections`, `CreatePaymentLink` | +| Health | `api/v4/Health/GetCurrent` → `Payments*` block and `PaymentsWebhookHealthy` (value-free) | +| Worker | 29 passes 2–4: reconcile open requests, close expired ones, re-verify connections weekly, purge old webhook bodies | +| Non-goals in this release | Platform fees, surcharges, partial online payments, refunds from Resgrid, saved payment methods, Square / PayPal / Authorize.net (reserved) | diff --git a/docs/web-app/business-ops/overview.md b/docs/web-app/business-ops/overview.md new file mode 100644 index 0000000..92bb21e --- /dev/null +++ b/docs/web-app/business-ops/overview.md @@ -0,0 +1,104 @@ +--- +sidebar_position: 1 +title: Overview +--- + +# Workforce & Business Ops — Overview + +**Workforce & Business Ops** is the group of modules that handle the *business* side of running a department or company: billing customers, keeping certifications current, sending crews and apparatus out under contract or mutual aid and getting paid for it, recovering costs from Cal OES, and knowing what your people and resources actually cost. Fire departments use it for cost recovery and mutual-aid reimbursement, private ambulance and fire-protection companies for invoicing, wildland and security contractors for bids, contracts and daily time reports, and any employer for certification tracking. + +![Workforce & Business Ops in the sidebar](/img/web-app/business-ops/navigation.png) + +## The modules + +| Module | What it does | Free or add-on | +|---|---|---| +| [Certifications](certifications) | Catalog of certifications, licences, inspections and permits for **people and units**, expiry dashboard, role requirements with optional enforcement, continuing-education credits, compliance report. | Free | +| [Deployment Finance](deployment-finance) | A **deployment** wraps the units, personnel and equipment sent to an incident with daily time reports (DTRs), expenses, files and a manifest — for an operational record, a cost-recovery claim or a customer invoice. | Free | +| [Invoicing](invoicing) | Customer billing profiles, rate cards, invoices with line items generated from calls, PDF and e-mail delivery, payments, accounts-receivable aging. | **Business Ops** add-on | +| [Online Payments](online-payments) | Customers pay invoices online through the department's **own Stripe account**; Resgrid never holds the money. | Business Ops add-on | +| [Rate Schedules](rate-schedules), [Contracts & Compliance](contracts-and-compliance), [Bids & Deployment Wizard](bids-and-deployment-wizard), [Contractor Billing](contractor-billing) | Explicit per-band contractor rate tables, service contracts with document requirements, priced bids that become a scheduled deployment call, and the billing engine that turns approved DTRs into an invoice and packet. | Business Ops add-on | +| [Cal OES MARS](cal-oes-mars) | California mutual-aid reimbursement: agency profile, F-5 resource inventory, annual rate submissions, agreements, F-42 and expense-claim preparation, portal handoff, invoice and payment reconciliation. | Business Ops add-on | +| [Workforce](workforce) | Employer identity, establishments, workers, employment periods, job assignments, compensation profiles, work entries and annual pay facts — all protected data. | Business Ops add-on | +| [Field Costing](field-costing) | Resource cost profiles, usage readings and **cost runs** that give the internal loaded cost and margin of a bid, call or deployment. | Business Ops add-on | +| [Pay Data Reporting](pay-data-reporting) | The California CRD (Government Code §12999) pay data report wizard and voluntary demographic self-identification. | Business Ops add-on **+ Advanced Data Protection** | +| [Contacts](../contacts) | Customers, key-holders and agencies; the **billing profile**, pre-incident plan and site files hang off the contact. | Free (billing profile needs the add-on) | + +## Where to find it + +The left sidebar has a collapsible **Workforce & Business Ops** group. Inside it you see only what your department has turned on and what you are allowed to use: + +| Menu item | Appears when | +|---|---| +| **Workforce** | Business Operations module on, Workforce or Pay Data entitlement, and you are an administrator or hold a workforce permission. Members who only need to answer their own demographic questionnaire see **My demographic response** instead. | +| **Certifications** | You are an administrator or hold *View certifications*. | +| **Invoicing** | *View invoicing* permission, the **Business Operations module switch** on and the `Invoicing.CustomerInvoicing` flag. A lapsed add-on still shows the pages, read-only. | +| **Deployment Finance** | The `Operations.Deployments` flag. Members see only deployments they are rostered on. | +| **Bids** / **Contracts** | Administrator or *Manage bids* / *Manage contracts*, module switch on and an active add-on with the `Invoicing.ContractorBilling` flag. | +| **Cal OES MARS** | Module switch on and an active add-on with the `CostRecovery.CalOesMars` flag. Managers open the readiness dashboard; rostered members open their own action queue. | + +Deployment Finance is deliberately **not** the same page as [Records → Deployments](../records/deployments): the Records page tracks the *external resource order* (IROC, EMAC, CIFFC); Deployment Finance tracks the *money and time* of the crew you sent. A Deployment Finance deployment can be created **from** a Records external order so the two stay linked. + +## Turning it on + +Four different switches gate these pages. Work through them in order when something is missing: + +1. **Feature flags** (hosted: Resgrid staff; self-hosted: `Resgrid.Console --FeatureFlags --Key= --DepartmentId=N --On`). `Business.Operations` is the master flag for every paid surface; `Operations.Deployments` is free. See [Feature flags](../../reference/feature-flags). +2. **Module switch** — **Department menu → Department Settings → Module Settings → Business Operations**. Turn it off to hide invoicing, contractor billing, MARS and workforce for the whole department without cancelling the add-on. + + ![Module settings](/img/web-app/business-ops/module-settings.png) + +3. **The Business Ops add-on** — **Department menu → Subscription and Billing → Business Operations**. A monthly add-on (USD 250 / EUR 295 per month at the time of writing) that only the department's **managing member** can buy or cancel. When it lapses every page stays readable, but every create, edit, send or payment is refused with *This needs an active Business Operations add-on*. See [Subscription & Billing](../subscription-billing#business-ops-add-on). + + ![Business Operations add-on](/img/web-app/business-ops/addon.png) + +4. **Permissions** — **Department menu → Security and Permissions**. Every new permission defaults to *department administrators only*; open it up to the people who bill, approve time or manage certifications. See [Security & Permissions](../security-permissions#workforce--business-ops). + +:::tip Self-hosted +The add-on entitlement is read from the Billing API. On a self-hosted installation with no Billing API the paid surfaces stay off unless your licence includes them; ask Resgrid for a licence that enables `PlanAddonTypes.BusinessOperations`. +::: + +## How the pieces fit together + +| From | To | How | +|---|---|---| +| Contact | Billing profile → Invoice | Terms, discount, tax and rate card come from the profile; **Add call** builds lines from the rate card. | +| Invoice | Payment | Manual payment, or a **pay link** through your Stripe account. | +| Contact + rate schedule + contract | Bid | The bid snapshots rates from the schedule the contract names. | +| Accepted bid | Deployment + call | The **deployment wizard** creates both, with the roster seated and priced. | +| Deployment | Daily time reports, expenses | Filed by crews in the apps or on the web, approved by a manager. | +| Approved time reports | Invoice + packet | The **contractor billing engine** drafts the invoice; reports move to *Billed*. | +| Cost-recovery deployment | F-42 / expense claim | Cal OES MARS prepares the claim for the portal. | +| Time reports + usage + expenses | Cost run | Field costing prices them against workforce compensation and resource cost profiles. | + +- A **customer** is a *contact* with a **billing profile** (terms, discount, tax, rate card, rate schedule). +- **Simple per-call billing** uses a **rate card** (hourly unit or personnel time, flat fees, mileage, materials): open an invoice, *Add call*, send. +- **Contract work** uses a **rate schedule** (bands, crews, premiums, policy), a **contract** (terms, document requirements) and a **bid**; accepting the bid runs the **deployment wizard**, which creates the call and the deployment with its roster. Crews file **daily time reports** in the apps or on the web; once approved the **billing engine** drafts the invoice and packet. +- **Mutual aid in California** uses the same deployment in *cost recovery* mode and prepares the **F-42** and expense claim for the MARS portal instead of an invoice. +- **Field costing** reads the same time reports, usage readings and expenses against **workforce** compensation and resource cost profiles to show what the job actually cost. + +## Setup examples + +| Organization | Typical set-up | +|---|---| +| **Municipal / county fire** | Certifications (NFPA, EMS, driver), role requirements *Warn only*; Deployment Finance for strike teams; Cal OES MARS if in California; invoicing of hazmat clean-ups, false-alarm fees and standby with a rate card. | +| **Volunteer / combination fire** | Certifications with expiry notifications and a monthly compliance report; Deployment Finance in *operational only* mode for mutual-aid documentation; Field costing to justify budgets. | +| **Private ambulance / EMS** | Invoicing with a per-call rate card (transport flat fee, mileage, standby), billing profiles per facility with net-30 terms and tax exemption, online payments; NREMT and state-licence certifications enforced. | +| **Wildland / private fire contractor** | Rate schedules per season (crew bands, engine and equipment day rates, OT thresholds), contracts per agency with COI / WCB / SAM document requirements, bids → wizard → deployment → DTRs → invoice packet; NWCG certifications on every seat. | +| **SAR / CERT / emergency management** | Certifications (SARTECH, ICS, first aid), Deployment Finance for EMAC or state deployments in *cost recovery* mode, F-42s if California. | +| **Security company / facilities** | Contracts per client site, rate schedules (guard hour bands, supervisor premium), bids for events, invoicing with online pay links, guard-card certifications enforced. | +| **Industrial emergency response** | Certifications (OSHA, HAZWOPER, confined space, respirator fit) with *Enforce*, unit inspections; Workforce and Field costing for internal chargebacks; Pay data reporting if a California employer with 100+ employees. | +| **Delivery / transit / field service** | Driver and vehicle certifications (CDL, DOT medical, annual inspection, registration, insurance) on units and people; invoicing of service jobs from calls. | + +## Technical reference + +| Item | Value | +|---|---| +| Controllers | `Invoicing`, `Certifications`, `Deployments`, `DeploymentWizard`, `RateSchedules`, `Contracts`, `Bids`, `CalOesMars`, `Workforce`, `BusinessOperationsBilling` (all `/User/...`); public `PayController` (`/pay/{token}`) | +| Entitlement | `IBusinessOperationsAccessService.CanUse{Invoicing,ContractorBilling,CostRecovery,Workforce,PayDataReporting}Async` — master flag `Business.Operations` + capability flag + module switch (`DepartmentModuleSettings.BusinessOperationsDisabled`) + an active `PaymentAddons` row of type `BusinessOperations` (4); fails closed, no grace | +| Flags | `Business.Operations`, `Invoicing.CustomerInvoicing`, `Invoicing.OnlinePayments`, `Payments.StripeConnect` (operator only), `Operations.Deployments`, `Invoicing.ContractorBilling`, `CostRecovery.CalOesMars`, `Workforce.InternalCosting`, `Compliance.CaliforniaPayDataReporting` | +| Permissions | 40–41 invoicing, 42–44 certifications, 74–78 workforce, 79 Cal OES MARS, 116–119 deployments / bids / contracts / time reports | +| Workers | 29 invoice maintenance (every 15 min), 31 bid expiration, 32 deployment-finance + MARS reminders, 33 compliance expiry (all daily, early morning), 34 certification expiry (hourly tick, one sweep per department-local day), 49 pay-data readiness (daily) | +| Workflow triggers | Invoices 52–57 and 94–95, contractor 74–86, certifications 23 and 87–93, 180–187 | +| API | `api/v4/Invoices`, `Certifications`, `Deployments`, `TimeReports`, `RateSchedules`, `ServiceContracts`, `Bids`, `CalOesMars`, `FieldCost` | +| Search | Invoices, rate cards, bids, contracts, deployments and certification types are indexed in [unified search](../search); MARS, workforce and time-report data are not | diff --git a/docs/web-app/business-ops/pay-data-reporting.md b/docs/web-app/business-ops/pay-data-reporting.md new file mode 100644 index 0000000..0f93283 --- /dev/null +++ b/docs/web-app/business-ops/pay-data-reporting.md @@ -0,0 +1,66 @@ +--- +sidebar_position: 13 +title: Pay Data Reporting (California) +--- + +# Pay Data Reporting (California CRD) + +California employers with **100 or more employees** (or 100 or more workers hired through labor contractors) must file an annual **pay data report** with the Civil Rights Department (CRD) under Government Code §12999: employee counts and pay bands by **job category, race/ethnicity and sex**, per establishment. This module prepares the **Payroll Employee** and **Labor Contractor Employee** reports from your [Workforce](workforce) data and each member's **voluntary self-identification**, validates them against the reviewed CRD template, and exports the CSV / XLSX files and a **portal worksheet**. You file in the CRD portal yourself. + +:::info Resgrid prepares and exports; it never files +It never decides whether you are covered and never certifies. Every input and output here is a protected field served *no-store*; the department must have [Advanced Data Protection](../data-protection) **enabled** (not just purchased) before these pages open. +::: + +Business Ops add-on with `Compliance.CaliforniaPayDataReporting` **and** Advanced Data Protection enabled. Menu: **Workforce & Business Ops → Workforce → Pay data reporting** (administrators, *Manage California pay data reporting*, *Export California pay data reports*). Every member sees **My demographic response** while the flag is on. + +## Before the first run + +1. **Workforce → Employer**: legal name, FEIN, SEIN, CA SOS number, NAICS, addresses, filing contact and the **coverage status** you declare. +2. **Establishments** with NAICS and *reported in the prior year*. +3. **Workers → employments → job assignments** with the **CRD job category**, establishment and work mode for every California employee; **labor contractors** and their employees for the second report. +4. **Annual pay facts** for the reporting year (import the payroll export; approve). +5. **Demographic responses** — ask every member to answer **My demographic response**; a compliance officer records the rest from employment records. + +## My demographic response + +Every member's own page (**Workforce & Business Ops → My demographic response** or from the profile menu): *Hispanic or Latino* (yes / no / no answer), **race / ethnicity** (select every category that applies — two or more are reported as multiracial — or *Decline to state*) and **sex** (or decline). Answers are stored separately from the personnel record, encrypted, used only for the aggregate report and never shown on any other screen. Answering is voluntary; *Decline to state* is a valid answer and is reported as such. The page explains *why we ask*. + +A compliance officer with *Manage California pay data reporting* can open a worker's **Demographic record** for someone who has not self-identified: **collection source** (*employment record*, *other reliable record*, or — as a last resort — *observer perception*, which is flagged on every report run), a required **reason** (audited), and the same answers. Responses are versioned. + +## The report run + +**Workforce → Pay data reporting** shows the **readiness** for the year: due date, the reviewed **schema profile** (`CRD-RY2025` in this release), coverage status, open runs, unresolved exceptions, demographic responses missing, annual pay facts missing, and **demographic completeness** (self-identified / declined / observer perception). **New run**: report type, reporting year and the **snapshot period** (a single pay period between the dates the CRD allows). + +A run is a four-step wizard, then attestation: + +| Step | What happens | +|---|---| +| **1. Build snapshots** | One row per California employee in the snapshot period: worker, establishment, CRD job category, demographic code, **pay band** (from annual pay facts), hours, hourly rate and work mode, with *Included* yes/no. **Override** a snapshot (category, work mode, inclusion) with a reason — audited. Demographic responses are matched as they stand today, not as of the snapshot date. | +| **2. Aggregate rows** | Counts per establishment × job category × demographic code × pay band, plus mean and median hourly rates and the non-remote / remote-in-CA / remote-outside-CA split. | +| **3. Validate** | Errors block freezing (missing job category, employee with no pay facts …); warnings do not. **Clarifying remarks** (up to 500 characters) are required when Box 1 earnings were used or an exempt-hours proxy applies. | +| **4. Freeze and export** | A frozen run is immutable; the **CSV** and **XLSX** files in the CRD template column order (checksum-stable for unchanged input) are downloadable — no-store, audited — until purged after the retention window (30 days by default). The **Portal worksheet** lists the employer-level values you type into the portal beside the upload. | +| **Attest in the portal** | Certify in the CRD portal, then **Record certification** here with the portal's reference → *Certified externally*. | + +**Create correction** after filing marks the exported run *Correction* and opens a new draft; **Void** discards a run and purges its files. Run statuses: *Draft, Validated, Frozen for export, Exported, Certified externally, Correction, Void*. + +During the filing season (January–May) administrators receive a daily **readiness digest** — due date, run state and counts of unresolved exceptions, missing responses and missing pay facts — never a name, code, rate or earnings figure. + +## Setup examples + +| Organization | Applies? | +|---|---| +| **California city / county fire or EMS with 100+ employees** | Yes — both reports if you also use labor contractors (e.g. contract dispatchers). Run the wizard in April; certify in the CRD portal by the deadline. | +| **California private ambulance / security company with 100+ workers** | Yes — usually the payroll report only; labor contractor report if you use staffing agencies. | +| **Smaller California employers, volunteer departments, employers outside California** | No filing duty — leave the flag off; the demographic questionnaire stays hidden. | + +## Technical reference + +| Item | Value | +|---|---| +| Routes | `/User/Workforce/{PayData,PayDataRun?tab=snapshots\|rows\|validation\|artifacts,Worksheet,MyDemographics,WorkerDemographics}`; POST `CreatePayDataRun`, `BuildSnapshots`, `OverrideSnapshot`, `AggregateRows`, `SaveRemarks`, `ValidateRun`, `FreezeAndExport`, `MarkCertified`, `CreateCorrection`, `VoidRun`, `SaveMyDemographics`, `SaveWorkerDemographics`; `DownloadArtifact` | +| Model | `PayDataEntities` — report runs, employee snapshots, aggregate rows, validation, export artifacts (protected binary), demographic responses (versioned, `DemographicCollectionSources`); `CaPayDataSchemaProfile` `CRD-RY2025` (source checksum pinned by the reviewer) | +| Permissions | *Manage California pay data reporting* (77), *Export California pay data reports* (78); members always answer their own response | +| Gates | Flag `Compliance.CaliforniaPayDataReporting` + `DepartmentDataProtectionState.Enabled` (`CanUsePayDataReportingAsync`) | +| Worker | 49 `PayDataReportingReadinessLogic`, daily: filing-season digest and artifact purge | +| Services | `IPayDataDemographicsService`, `ICaPayDataReportingService`, pure `PayDataAggregator` (dependency-free XLSX writer) | +| Config | `WorkforceConfig.ExportArtifactRetentionDays` 30, `FilingSeasonStartMonth`–`EndMonth` (1–5) | diff --git a/docs/web-app/business-ops/rate-schedules.md b/docs/web-app/business-ops/rate-schedules.md new file mode 100644 index 0000000..fcf8e3a --- /dev/null +++ b/docs/web-app/business-ops/rate-schedules.md @@ -0,0 +1,82 @@ +--- +sidebar_position: 6 +title: Rate Schedules +--- + +# Rate Schedules + +A **rate schedule** is a contractor's rate table: what a firefighter with a given certification, a 4-person versus an 8-person crew, an engine, a water tender or a chainsaw earns per **band** — standby, deployment, overtime 1, overtime 2, daily tiers, out-of-province per diems, mileage — plus the **billing policy** (rounding, minimums, overtime basis, travel caps) the [contractor billing engine](contractor-billing) applies to every daily time report. It is the contract-work counterpart of the simple per-call [rate card](invoicing#2-rate-cards). + +Rates are always **explicit dollars per band** — never a formula — because an 8-person crew is not twice a 4-person crew and an overtime premium is a flat adder, not a multiplier. Business Ops add-on with `Invoicing.ContractorBilling`. Menu: **Workforce & Business Ops → Contracts → Rate schedules**. + +![Rate schedules](/img/web-app/rate-schedules/index.png) + +## Which schedule applies + +For a bid or deployment the engine picks, in order: the **contract's** schedule → the customer billing profile's **default rate schedule** → the first active schedule current on the date (by *effective on*). **Clone** a schedule for the next season and give it a new *effective on* date; the old one keeps billing earlier deployments. + +## Building a schedule + +**New rate schedule**: name, description, currency, active, **effective on** / **expires**. Save, then fill in the three panels. + +![Edit rate schedule](/img/web-app/rate-schedules/edit.png) + +### Billing policy + +| Policy | Meaning | +|---|---| +| **Round up to (minutes)** | Each entry's daily time is rounded up to this increment (30 is common). | +| **Overtime basis** | *Consecutive hours* (overtime starts after N hours on the shift) or *Daily total hours*. | +| **Cancellation minimum (hours)** | Hours billed when a resource is ordered and stood down (4 h is typical). | +| **Daily guarantee (hours)** | Minimum hours per deployment day (VIPR / CFAA portal-to-portal guarantees). | +| **Unsafe stand-down (hours)** | Hours billed on a day flagged *Unsafe conditions stand-down*. | +| **Travel cap per day (hours)** | Travel above the cap is not billed (or comes off the day under portal-to-portal). | +| **Fuel deduction per litre** | Deducted per litre of agency-supplied fuel recorded on the DTR. | +| **Continuous-run gap (minutes)** | Entries closer than this are joined into one run for overtime purposes. | +| **Vehicles bill a full day on a cancellation day** | Whether apparatus, like people, gets the full day when cancelled after mobilizing. | +| **Portal to portal** | Travel bills as deployment time and earns overtime. | +| **No-clear-8 carry-over** | A DTR flagged *No clear 8* starts the next day in the overtime band. | +| **Meal eligibility** | JSON windows per meal code (e.g. `[{"MealCode":"B","StartsBeforeMinutes":420}]`); a per diem outside its window is warned, not blocked. | + +### Premiums + +Flat **hourly adders** by code (night, hazard, lead, out-of-region) with a separate amount for the *Standby*, *Deployment*, *Overtime 1* and *Overtime 2* bands. Premiums **stack and never multiply**; they are assigned per person on the roster or in the wizard. + +### Rate entries + +One entry per thing you charge for: + +| Entry type | Matched by | Typical bands | +|---|---|---| +| **Personnel certification** | The person's **certification code** on the roster (FFT1, ENGB, EMT-P, GUARD …). | Hourly standby / deployment / OT1 / OT2 with **From (h)** / **To (h)** thresholds (e.g. deployment 0–8, OT1 8–14, OT2 14+). | +| **Crew** | **Group key** (`type6-crew`) + **crew size** — one entry per size in the family. The unit bills at the crew size **actually filled that day**; a partial crew takes the nearest lower size. **Required certifications** JSON lists code + minimum count the crew must carry. | Daily standby / daily deployment tiers (**Tier min/max (h)**), hourly bands. | +| **Vehicle** | Unit type; pinned to the roster unit. | Daily deployment / standby, **mileage per km** with **free units per day**, fuel. | +| **Equipment** | Inventory item, pinned to the roster row. | Daily rate. | +| **Service** | Free-form line (mobilization fee, admin). | Fixed. | + +Every entry has a **billing basis** (*Hourly, Daily, Per person per day, Per kilometre, Fixed*) and a list of **bands**: band type, rate, thresholds or tier bounds, free units, **Air** (applies only when the deployment travels by air), **meal code** and label. **Multiplier prefill** drafts the hourly bands from a base rate plus standby and overtime multipliers — the stored values are still plain dollars you can edit. + +### Export, import, clone + +**Export JSON** downloads the schedule without ids; **Import JSON** on the list page creates a new schedule from a file or pasted JSON — the way to share a schedule between departments or keep it under version control. **Clone** copies every entry, band and premium into a new schedule. + +## Setup examples + +| Organization | Schedule | +|---|---| +| **Wildland contractor (BC / western US)** | *Season 2026*: personnel entries FFT2, FFT1, CRWB, ENGB with deployment 0–8 h, OT1 8–14 h (rate + adder), OT2 14 h+; crew family `type2-crew` sizes 4/6/8 with daily tiers; engine (Vehicle) daily + mileage after 250 free km; night and hazard premiums; policy 30-min rounding, 4-h cancellation, unsafe 8 h, no-clear-8 on, portal-to-portal off. | +| **Fire protection company (municipal contract)** | *Standing contract 2026*: engine + 3-person crew as a crew family with daily deployment tiers; personnel entries by FF1/FO1; policy daily guarantee 12 h, portal-to-portal on. | +| **Security company** | *Client rates*: personnel entries GUARD (hourly, OT1 after 8 h), SUPERVISOR; vehicle patrol (Vehicle, hourly); premiums *Night* and *Holiday*; 15-min rounding, 4-h minimum call-out. | +| **Private ambulance (event standby)** | *Events*: crew family `als-unit` size 2 hourly; personnel EMT / Paramedic hourly; service line *Set-up fee*. | +| **Industrial standby (fire watch / confined space)** | *Plant rates*: personnel FIRE-WATCH hourly with OT after 10 h; equipment entries for gas monitors and rescue tripods per day. | + +## Technical reference + +| Item | Value | +|---|---| +| Routes | `/User/RateSchedules/{Index?all=true,New,Edit}`; POST `Save`, `Delete`, `Clone`, `SaveEntry`, `DeleteEntry`, `SavePremium`, `DeletePremium`, `Export`, `Import` | +| Model | `RateSchedule` (+ `PolicyJson` = `RateSchedulePolicy`), `RateScheduleEntry` (type, basis, group key, crew size, certification code, unit type, inventory item, `RequiredCertificationsJson`, `BandsJson`), `RateScheduleEntryBand`, `RatePremium` | +| Enums | `RateEntryTypes`, `BillingBases`, `RateBandTypes` (Standby, Deployment, Overtime1, Overtime2, DailyStandby, DailyDeployment, OutOfProvincePerPersonDaily, MileagePerKm, PerDiemMeal, PrivateAccommodationDaily, Custom), `OvertimeBases` | +| Service | `IRateScheduleService` (`ResolveForContactAsync` cascade, `Clone`, `Export/Import`, `PrefillHourlyBands`) | +| Permission | *Manage contracts* (117) or department administrator | +| API | `api/v4/RateSchedules/*` | diff --git a/docs/web-app/business-ops/workforce.md b/docs/web-app/business-ops/workforce.md new file mode 100644 index 0000000..4b49cd5 --- /dev/null +++ b/docs/web-app/business-ops/workforce.md @@ -0,0 +1,94 @@ +--- +sidebar_position: 11 +title: Workforce +--- + +# Workforce + +**Workforce** is where a department that is also an **employer** keeps what its people cost: the employer identity and **establishments** (physical locations), **workers** with their employment periods and job assignments, **compensation profiles** (base pay, differentials, employer costs), **work entries** (hours per day from payroll, deployments and calls) and **annual pay facts** (W-2 earnings, hours, weeks). It feeds [Field Costing](field-costing) (what a bid, call or deployment really costs), the Cal OES MARS **Salary Survey**, and [Pay Data Reporting](pay-data-reporting). + +Business Ops add-on with `Workforce.InternalCosting`. Menu: **Workforce & Business Ops → Workforce** (administrators and holders of a workforce permission). + +:::caution Protected data +Identifiers, addresses, pay rates, earnings, demographic responses and export files are [Advanced Data Protection](../data-protection) fields. They render **REDACTED** without a current Protected Data Grant (verify with your authenticator), are never cached or logged, and a *REDACTED* value left unchanged on a form keeps what is stored. Enrol the department in ADP before entering real pay data. +::: + +![Workforce](/img/web-app/workforce/index.png) + +## The pages + +The workforce home shows three panels — **Employer**, **Field costing** and **Pay data reporting** — with counts and links. + +### Employer + +**Workforce → Employer**: the legal entity the CRD report is filed under — legal name, **FEIN**, **SEIN (EDD)**, CA Secretary of State number, NAICS, EDD and headquarters addresses, filing contact, **coverage status** (*Not covered, Covered — payroll, Covered — labor contractor, Covered — both*; declared by you after reading the CRD guidance — Resgrid never decides whether you must file), US and California employee counts and whether you are part of an **integrated enterprise** (then list the **affiliated entities**). + +![Employer](/img/web-app/workforce/employer.png) + +### Establishments + +**Workforce → Establishments**: every physical location employees are assigned to — code, name, street address, city, state, ZIP, NAICS, major activity, affiliate, active window, time zone, **Headquarters** and **Reported in the prior year**. The CRD report is filed per establishment; a fire department's stations are usually one establishment each unless payroll treats them as one. + +![Establishments](/img/web-app/workforce/establishments.png) + +### Labor contractors + +**Workforce → Contractors**: firms that supply **labor contractor employees** (covered by the second CRD report) — legal name, ownership, DBA, FEIN or other identifier, contact details, relationship window and where the identity came from (contract, W-9, portal record). + +### Workers, employments, job assignments + +**Workforce → Workers**: every person you pay or report on. **Add worker** from a department member, or an **external worker** by payroll key and label (both protected). Open a worker: + +![Worker](/img/web-app/workforce/worker.png) + +| Section | Fields | +|---|---| +| **Employments** (never overlap) | **Worker kind** (*Payroll employee, Labor contractor employee, Volunteer, Independent contractor*), start/end, employment type (full-time, part-time, intermittent), exemption status, **California basis** (assigned to a California establishment, works in California, both, not California), default establishment, **personnel role** (used to pick a role-default compensation profile), labor contractor, affiliate. | +| **Job assignments** (per employment, over time) | Job title, **CRD job category** (one of the ten categories of the reviewed schema profile), SOC code and version, establishment, work mode (*non-remote, remote within California, remote outside California assigned to a California establishment*), work country / state, **Cal OES MARS classification** and authority profile, mapping provenance. | +| **Compensation** | Link to the worker's compensation profiles. | +| **Demographic record** | For a compliance officer to record a worker who has not self-identified (see [Pay Data Reporting](pay-data-reporting)). | + +### Compensation + +**Workforce → Compensation** (from a worker's page or the *Compensation* tab): **employee profiles**, **role defaults** and a **department default**. Estimates use the employee profile, then the role default, then the department default; the payroll system's approved cost always wins. + +![Compensation profile](/img/web-app/workforce/compensation-profile.png) + +| Panel | Fields | +|---|---| +| **Profile** | Scope, effective/expiry, **pay basis** (*hourly, salary, daily, shift, stipend*), currency, **base amount**, regular hourly equivalent (optional override), standard hours per day / week / year, **rate multipliers** JSON by pay code (defaults 1.5 overtime, 2 double time), source. | +| **Pay components** | Differentials, incentives, longevity, education, EMS, hazmat, USAR, specialty pay — per hour, percent of base, per shift, per pay period or fixed annual, with eligible pay codes and *per OT hour*. | +| **Employer cost components** | Payroll taxes, workers' compensation, pension, health and other benefits, fixed labor cost, allocated overhead — percent of eligible pay, per hour / shift / day or fixed annual, with an optional cap. | +| **Approval** | **Approve profile**: unapproved profiles still price estimates but flag every line for review; any rate change removes the approval. The **loaded cost of a regular 8-hour day** is previewed. | + +### Work entries + +**Workforce → Work entries**: hours per worker and day — **hours type** (*regular, overtime, double time, standby, travel, paid leave, other*), establishment, work mode and location, the call or deployment they belong to, and the **approved payroll cost** (when present it replaces any estimate for that day). Entries can come from payroll (external source and id), from deployments' time reports or be typed. + +### Annual pay facts + +**Workforce → Annual pay facts** (per reporting year and report type): **W-2 Box 5** (or **Box 1** as fallback), client-allocated earnings for labor contractors, actual worked hours, paid-leave hours, days worked, an **exempt-hours proxy** method (actual + paid leave, or days × average hours), weeks worked, reconciliation flag and approval. Facts are **immutable and versioned** — correcting one creates a new version. **Import (CSV)** takes the payroll export in the canonical column order: a **dry run** validates and reconciles every row before **Commit import**; imported facts arrive unapproved. + +![Annual pay facts](/img/web-app/workforce/annual-facts.png) + +## Setup examples + +| Organization | What to set up | +|---|---| +| **Career fire department (California)** | Employer + one establishment per station, every member as a worker with role-default compensation per rank, work entries fed from deployments, annual pay facts imported from payroll each January → CRD report and MARS Salary Survey. | +| **Career fire / EMS outside California** | Employer and establishments optional; compensation profiles per role and employer cost components so deployment cost runs and bid estimates are realistic. | +| **Volunteer / combination department** | Workers as *Volunteer* with stipend profiles; work entries per call to value volunteer hours for grants; no pay data reporting. | +| **Wildland / security contractor** | Employee profiles per crew member with overtime multipliers and per-OT-hour components; department default for bid estimates before the roster is known. | +| **Industrial site** | Workers per shift, establishments per plant, labor contractors for contract crews; compensation profiles for internal chargebacks. | + +## Technical reference + +| Item | Value | +|---|---| +| Routes | `/User/Workforce/{Index,Employer,Establishments,Contractors,Workers,Worker,Compensation,CompensationProfile,WorkEntries,AnnualFacts}` and their `Save*/Delete*` POSTs; `ImportAnnualFacts` (dry run / commit) | +| Model | `Core/Resgrid.Model/Workforce/` — employer profile, affiliated entities, establishments, labor contractors, workers, employments, job assignments, compensation profiles + pay / cost components, work entries, annual pay facts (versioned); `WorkforceProtectedFields` = ADP catalog 28 (41 columns; decimals stored as protected text) | +| Permissions | *Manage workforce and compensation* (75), *View workforce compensation* (76) — plus a current Protected Data Grant to read values | +| Flag | `Workforce.InternalCosting` (child of `Business.Operations`) | +| Config | `WorkforceConfig` (overtime threshold 8 h/day, usage conflict 10 %, export retention 30 days, filing season Jan–May) | +| Services | `IWorkforceService`, `IWorkforceImportService`, `ICompensationCostService` (employee → role → department fallback; approval dropped on rate edit) | +| Search | Workforce data is never indexed | diff --git a/docs/web-app/contacts.md b/docs/web-app/contacts.md index 4f178d8..44a2093 100644 --- a/docs/web-app/contacts.md +++ b/docs/web-app/contacts.md @@ -5,149 +5,106 @@ title: Contacts # Contacts -**Contacts** are the people and organisations *outside* your department that you deal with on calls and in business: property owners, key-holders, businesses, mutual-aid agencies, vendors, patients' next of kin, clients. Contacts carry addresses, phone numbers, **notes** (including *alert notes* that pop up when the contact is attached to a call), attachments, categories and — for premises — legacy **pre-plan** data. +**Contacts** are the people and organizations *outside* your department that you deal with on calls and in business: property owners and key-holders, businesses and facilities, mutual-aid agencies, vendors, patients' next of kin, **customers you invoice**. A contact carries addresses, phone numbers, social links, **notes** (including *alert notes* that pop up when the contact is attached to a call), a **pre-incident plan** with **premise hazards**, **site files** (floor plans, photos, drawings), and — with the Business Ops add-on — a **billing profile** and its invoices. -**Left menu → Contacts.** Categories and contact note types are managed from the page and under **Department → Types**. Suppliers in [Inventory purchasing](inventory#purchasing) and occupancies in [Records](records/occupancies) link to contacts. +**Left menu → Contacts.** Categories are managed from the page; contact note types under **Department → Types**. Suppliers in [Inventory purchasing](inventory#purchasing), occupancies in [Records](records/occupancies), customers in [Invoicing](business-ops/invoicing) and bids/contracts in [Contractor Billing](business-ops/contracts-and-compliance) all point at contacts. ![Contacts](/img/web-app/contacts/index.png) -## Contact List +## The contact list -**Authorization:** `Contacts_View` policy +The list is a tree: **All Contacts**, **No Category** and one node per **category**. Categories carry a colour, a map icon and *Display on map* so key premises show on the [map](mapping). A category with contacts cannot be deleted — reassign them first. -Displays all contacts organized in a tree structure: -- **All Contacts** — Root node -- **No Category** — Contacts without a category -- **Per-Category** — Contacts grouped by category +![Categories](/img/web-app/contacts/categories.png) -## Contact Types +## Adding and editing a contact -The system supports two contact types: - -| Type | Required Fields | -|------|----------------| -| **Person** (0) | First name, Last name | -| **Company** (1) | Company name | - -## Creating Contacts - -**Authorization:** `Contacts_Create` policy +**Add Contact** (permission *Who can edit contacts*): ![Add contact](/img/web-app/contacts/add.png) -### Contact Fields - -| Field | Required | Description | -|-------|----------|-------------| -| Contact Type | Yes | Person or Company | -| First/Last Name | Yes (Person) | Person's name | -| Company Name | Yes (Company) | Organization name | -| Category | No | Classification category | -| Email | No | Contact email | -| Phone | No | Contact phone | - -### Address Management - -Contacts support two addresses: - -| Address Type | Description | -|-------------|-------------| -| **Physical Address** | Primary location | -| **Mailing Address** | Postal address (can be same as physical) | - -Both addresses include full fields (street, city, state, zip, country). - -### GPS Coordinates - -Contacts can have three sets of coordinates: -- **Location** — Primary contact location -- **Entrance** — Entrance point -- **Exit** — Exit point - -All coordinates are validated for proper decimal format. - -### Audit Trail -Creates `AuditEvent` on creation with IP address and user agent. - -## Editing Contacts - -**Authorization:** `Contacts_Create` policy - -Full edit with same validation as creation. Updates or creates addresses as needed. - -Creates `AuditEvent` with before/after JSON snapshots. - -## Deleting Contacts +| Group | Fields | +|---|---| +| **Type** | **Person** (first, middle, last, other name) or **Location or Company** (company / location name). Category. | +| **Contact info** | E-mail, cell, home, fax and office phone; website; Twitter, Facebook, LinkedIn, Instagram, Threads, Bluesky, Mastodon. | +| **Other data** | Description and other info. | +| **Location info** | **GPS location**, **entrance GPS** and **exit GPS** (decimal notation) — the map and the apps use them for premises. | +| **Physical address** and **Mailing address** (or *same as physical*) | Street, city, state / province, postal code, country. | +| **Custom fields** | [User Defined Fields](user-defined-fields) of type *Contact*. | -**Authorization:** `Contacts_Create` policy + `CanUserDeleteContactAsync` runtime check +Every create, edit and delete writes an audit event with before / after snapshots. A contact that has any non-void invoice cannot be deleted. -Creates `AuditEvent` on deletion. +## The contact page -## Contact Notes +![Contact](/img/web-app/contacts/view.png) -### Adding Notes +| Tab | What it holds | +|---|---| +| **Contact Details** | Everything above, created / updated stamps. | +| **Notes** | Notes with a **type** (colour-coded), optional **expiry** and the **alert** flag — alert notes are highlighted and shown to dispatchers when the contact is added to a call. Search and filter. | +| **Calls** | Every call linked to this contact with priority and type. | +| **Pre-Plan** | The pre-incident plan summary and **premise hazards**; *Create / Edit Pre-Plan*. A banner warns when the review date has passed. | +| **Site Files** | Uploaded floor plans, photos and drawings; *Manage Files*. | +| **Billing** | The billing profile summary and the customer's invoices (Business Ops add-on) — *Set up billing profile*, *New invoice*, *All invoices for this customer*. | +| **Routes** | Route stops that reference this contact (delivery / transit / patrol routes). | -![Contact detail](/img/web-app/contacts/view.png) +## Pre-incident plan (NFPA 1620) -Notes can be added to contacts with: +**Contact → Pre-Plan → Create Pre-Plan.** The plan follows the NFPA 1620 sections and is what responders see on the call's **Site Info** tab in the apps. -| Field | Description | -|-------|-------------| -| Note Text | Note content | -| Alert Flag | Whether this note should be displayed as an alert | -| Note Type | Classification type (color-coded) | -| Expiration | Optional expiry date | +![Pre-incident plan](/img/web-app/contacts/preplan.png) -Alert-flagged notes are highlighted with a yellow background and appear prominently when the contact is referenced in calls. +| Section | Fields | +|---|---| +| **Construction & occupancy** | Construction type (Type I fire-resistive … Type V wood frame, manufactured), roof type (flat, gable, hip, bowstring truss, lightweight truss …), occupancy type (residential, assembly, business, educational, factory, high hazard, institutional, mercantile, storage …), hours of occupancy, occupant load, **occupants needing assistance** with notes, occupancy notes. | +| **Utility shutoffs** | Gas, electric and water shutoff locations, utility notes. | +| **Water supply** | Nearest hydrant, required fire flow (GPM), notes. | +| **Access** | Knox box location, **gate code** (stored encrypted; shown to members who can view the contact and to responders on linked calls), alarm panel location, alarm company and phone, access notes. | +| **On-site contacts** | Emergency and secondary contact name and phone. | +| **Hazards & tactics** | Hazmat on site, general hazard notes, tactical summary. | +| **Review cycle** | Last reviewed, *Mark this pre-plan as reviewed now*, next review due. | + +**Premise hazards** are typed rows — *General, Hazmat, Structural, Electrical, Biological, Animal, Occupant, Other* — with a severity (*Info, Caution, Danger*), title, location, description, GPS and **Alert dispatchers when this contact is added to a call** (the hazard appears in the dispatch alert modal). + +:::note When Records owns pre-plans +Once a department enables Records [occupancies](records/occupancies), pre-plans are maintained there and this page becomes **read-only** with an *Open occupancy* link. The contact page still shows the summary and hazards. +::: -### Viewing Notes +Pre-plan text, gate code and site files are [Advanced Data Protection](data-protection) fields when the department is enrolled. -The `GetNotesJson` endpoint returns notes with: -- Note text and type name -- Created-by user name -- Alert background styling -- Note type color +## Site files -## Contact Categories +**Contact → Site Files → Upload File**: file type (*Document, Pre-plan, Floor plan, Site photo, Site drawing, Other*), optional title and the file — images, PDF, Office documents, text, CSV, **DWG / DXF** up to 30 MB. Files download from the contact page and from the call's Site Info tab in the apps. -### Managing Categories +![Site files](/img/web-app/contacts/attachments.png) -| Action | Authorization | Description | -|--------|---------------|-------------| -| List Categories | `Contacts_Create` | View all categories | -| Add Category | `Contacts_Create` | Create new category | -| Edit Category | `Contacts_Create` | Modify category | -| Delete Category | `Contacts_Delete` | Remove category (blocked if contacts exist) | +## Billing -:::warning Category Deletion Protection -A category **cannot be deleted** if contacts are assigned to it. Reassign or remove contacts first. -::: +With the Business Ops add-on the **Billing** tab holds the customer's [billing profile](business-ops/invoicing#3-billing-profiles) — billing e-mail, terms, default discount, rate card, rate schedule, tax treatment — and lists the invoices. Bids and contracts are addressed to the same contact. -## Call Integration +## Call integration -The `GetCallsJson` endpoint returns all calls linked to a contact with: -- Call name and type -- Priority name and color -- Timestamp +Dispatchers attach a contact (and additional contacts) to a call; the call shows the contact's alert notes and alert hazards in the dispatch alert, and the apps show the pre-plan on the **Site Info** tab. Records uses `GetCallSiteInfo` to prefill occupancy, water and hazmat facts on incident reports. ## Setup examples | Department type | How to set it up | |---|---| -| **Fire** | Categories: Key holders, Businesses, Mutual aid, Vendors; alert notes for aggressive dogs, oxygen in use, access issues; pre-plan data moves to Records occupancies when enabled. | -| **EMS** | Categories: Facilities (nursing homes with charge-nurse numbers), Hospitals, Frequent patients (with ADP enrolled). | +| **Fire** | Categories: Key holders, Businesses, Mutual aid, Vendors, Customers; pre-plans for target hazards with hazards marked *Alert*; site files with floor plans; billing profiles for cost-recovery customers. | +| **EMS** | Categories: Facilities (nursing homes with charge-nurse numbers), Hospitals, Frequent patients (ADP enrolled), Customers (event organizers, facilities you bill). | | **SAR** | Categories: Agencies (sheriff, park service), Landowners, Helicopter providers, Subjects (restricted). | -| **Emergency management** | Categories: ESF partners, Shelter operators, Utilities, Media; distribution lists built from contacts. | -| **Security** | Categories: Clients, Site contacts, Alarm companies, Police liaison; per-client visibility via group scoping. | -| **Delivery / transit** | Customers and stops as contacts; link to route stops. | +| **Emergency management** | Categories: ESF partners, Shelter operators (with pre-plans and occupant loads), Utilities, Media; distribution lists built from contacts. | +| **Security** | Categories: Clients (with billing profiles and contracts), Site contacts, Alarm companies, Police liaison; per-client visibility via group scoping; gate codes and alarm panels in the pre-plan. | +| **Delivery / transit** | Customers and stops as contacts; link to route stops; billing profiles for invoiced customers. | +| **Industrial** | Plant areas as *Location* contacts with pre-plans (shutoffs, hazmat), contractors as companies. | ## Technical reference -`ContactsController`; routes `/User/Contacts/{Index,Add,View,Edit,Delete,Categories,AddCategory,EditCategory,Preplan,Attachments}?contactId=`; permissions `ContactView`, `ContactEdit`, `ContactDelete`, `ViewProtectedContactData`; contact details are ADP-protected fields. - -### Interactions with Other Modules -| Module | Interaction | -|--------|-------------| -| **Dispatch** | Contacts linked to calls; alert notes displayed during dispatch | -| **Types** | Contact note types managed in Types controller | -| **Calls** | Calls reference contacts | +| Item | Value | +|---|---| +| Routes | `/User/Contacts/{Index,Add,View,Edit,Delete,Categories,AddCategory,EditCategory,ViewCategory,Preplan,Attachments}?contactId=`; `AddNote`, `SaveHazard`, `DeleteHazard`, `UploadAttachment`, `DeleteAttachment`, `GetContactAttachment`, `GetNotesJson`, `GetCallsJson`, `GetHazardsJson` | +| Model | `Contact`, `ContactNote`, `ContactCategory`, `ContactPreplan` (NFPA 1620 fields, `ContactPreplanHazard`), `ContactAttachment` (`ContactAttachmentTypes`), `CustomerBillingProfile` | +| Permissions | *Who can view / edit / delete contacts*, *View protected contact data* | +| Data protection | Contact details, pre-plan text, gate code and site files are ADP catalog fields (`ProtectedFieldCatalog.ContactPreplansCatalogVersion`) | +| API | `api/v4/Contacts/*` (+ `*Preplan`, `*Hazard`), `ContactFiles`, `Calls/GetCallSiteInfo` | +| Interactions | Dispatch (alert notes / hazards, Site Info), Records occupancies (pre-plan ownership), Inventory suppliers, Invoicing / bids / contracts (customer), Routes (stops) | diff --git a/docs/web-app/department-settings.md b/docs/web-app/department-settings.md index 46c0c4f..992d3ee 100644 --- a/docs/web-app/department-settings.md +++ b/docs/web-app/department-settings.md @@ -45,7 +45,7 @@ The department's own address (a station or district office) is used to locate th ## Module settings -`/User/Department/ModuleSettings` — switch modules on or off for the whole department: Messaging, Mapping, Shifts, Logs / Records, Reports, Documents, Calendar, Notes, Training, Inventory, **Checklists**, **Maintenance** (work orders). Switching a module off hides it from the menu and the apps; data is kept. +`/User/Department/ModuleSettings` — switch modules on or off for the whole department: Messaging, Mapping, Shifts, Logs / Records, Reports, Documents, Calendar, Notes, Training, Inventory, **Checklists**, **Maintenance** (work orders), **Business Operations** (invoicing, contractor billing, Cal OES MARS, workforce — the pages also need the [Business Ops add-on](business-ops/overview)). Switching a module off hides it from the menu and the apps; data is kept. ![Module settings](/img/web-app/department/module-settings.png) diff --git a/docs/web-app/navigation.md b/docs/web-app/navigation.md index 5499e14..aab9e22 100644 --- a/docs/web-app/navigation.md +++ b/docs/web-app/navigation.md @@ -11,7 +11,7 @@ title: Navigation | Region | What is there | |---|---| -| **Left sidebar** | The modules: Home, Calls, Personnel, Units, Contacts, Mapping, Shifts, Records (or Logs), Reports, Documents, Calendar, Notes, Trainings, Work Orders, Checklists, Inventory. Modules that are switched off or that you lack permission for are hidden. Collapse the sidebar with the hamburger icon on small screens. | +| **Left sidebar** | The modules: Home, Calls, Personnel, Units, Contacts, Mapping, Shifts, **Records** (a collapsible group, or Logs), Reports, Documents, Calendar, Notes, Trainings, Inventory, **Readiness** (Work Orders, Checklists) and **Workforce & Business Ops** (Workforce, Certifications, Invoicing, Deployment Finance, Bids, Contracts, Cal OES MARS). Groups expand in place; modules that are switched off or that you lack permission for are hidden. Collapse the sidebar with the hamburger icon on small screens. | | **Your name (top-left)** | Profile menu: **Profile** (edit your details, contact methods, notification preferences), **Mailbox**, **Chat**, **Your Departments** (switch between departments you belong to), **Two-Factor Authentication**, **Logout**. | | **Top bar** | Unread **messages** and **active calls** icons, the **search box**, the **Department menu**, **Help**, language flag and logout. | | **Department menu (department name, top-right)** | Everything an administrator configures — see below. | @@ -38,7 +38,7 @@ Only administrators (and group administrators for a few items) see this menu. | User Defined Fields | [User Defined Fields](user-defined-fields) | | Security and Permissions | [Security & Permissions](security-permissions) (permissions, audit log, SSO, security policy, data protection) | | Chat Moderation | [Chat moderation](chat#moderation) | -| Subscription and Billing | [Subscription & Billing](subscription-billing) | +| Subscription and Billing | [Subscription & Billing](subscription-billing) — plan, PTT, Advanced Data Protection, Readiness Pro and [Business Ops](business-ops/overview) add-ons | | Connect | [Connect](connect) | | Audio / Push-to-Talk | [Voice & Audio](voice-audio) | | Orders | [Resource Orders](resource-orders) | @@ -50,7 +50,7 @@ Only administrators (and group administrators for a few items) see this menu. ## Search -The search box finds calls, personnel, units, contacts, notes, documents, records and pages by name or number. Type at least two characters; results open in place. Records narrative search is included when your department's search index allows it. +The search box finds calls, personnel, units, contacts, notes, documents, records, invoices, bids, contracts, deployments and pages by name or number. Type at least two characters; results open in place. Records narrative search is included when your department's search index allows it. ![Search results](/img/web-app/home/search-results.png) diff --git a/docs/web-app/overview.md b/docs/web-app/overview.md index 5fd57f9..d80b149 100644 --- a/docs/web-app/overview.md +++ b/docs/web-app/overview.md @@ -19,6 +19,7 @@ The four mobile apps — **Responder**, **Unit**, **Dispatch** and **Incident Co | **People & apparatus** | [Personnel](personnel) · [Units](units) · [Hardware GPS Tracking](unit-tracking) · [Groups & Stations](groups-stations) · [Custom Statuses](custom-statuses) · [Contacts](contacts) · [Shifts](shifts) · [Workshifts](workshifts) · [Calendar](calendar) | *Personnel* | | **Records & reporting** | [Records (RMS)](records/overview) · [Logs (legacy)](logs) · [Reports](reports) · [Documents](documents) · [Notes](notes) · [Trainings](trainings) | *Records overview* | | **Readiness & logistics** | [Checklists](checklists) · [Work Orders](work-orders) · [Inventory](inventory) · [Resource Orders](resource-orders) · [Communication Tests](communication-tests) | *Checklists* | +| **Workforce & Business Ops** | [Overview](business-ops/overview) · [Invoicing](business-ops/invoicing) · [Online Payments](business-ops/online-payments) · [Certifications](business-ops/certifications) · [Deployment Finance](business-ops/deployment-finance) · [Rate Schedules](business-ops/rate-schedules) · [Contracts & Compliance](business-ops/contracts-and-compliance) · [Bids & Deployment Wizard](business-ops/bids-and-deployment-wizard) · [Contractor Billing](business-ops/contractor-billing) · [Cal OES MARS](business-ops/cal-oes-mars) · [Workforce](business-ops/workforce) · [Field Costing](business-ops/field-costing) · [Pay Data Reporting](business-ops/pay-data-reporting) | *Business Ops overview* | | **Communication** | [Messages](messages) · [Chat](chat) · [Notifications](notifications) · [Distribution Lists](distribution-lists) · [Connect](connect) | *Messages* | | **Configuration** | [Department Settings](department-settings) · [Types & Configuration](types-configuration) · [Templates](templates) · [Protocols](protocols) · [Forms](forms) · [User Defined Fields](user-defined-fields) · [Workflows](workflows) · [Command Definitions](command-definitions) · [Department Links](department-links) · [Call Check-in Timers](call-checkin-timers) | *Department Settings* | | **Security & account** | [Security & Permissions](security-permissions) · [Advanced Data Protection](data-protection) · [Account Security](account-security) · [Profile & Account](profile-account) · [Subscription & Billing](subscription-billing) · [Help & Setup](help-setup) | *Security & Permissions* | @@ -29,9 +30,9 @@ New to Resgrid? Read [Navigation](navigation) first, then follow the [department Not every module appears for every department: -- **Module switches** — administrators can hide Messaging, Mapping, Shifts, Logs/Records, Reports, Documents, Calendar, Notes, Training, Inventory, Checklists and Maintenance under **Department Settings → Module Settings**. -- **Feature flags** — some newer modules (Records, Checklists, Work Orders, Run Cards, Chat) are switched on per department by Resgrid (hosted) or by the operator (self-hosted) using the `Resgrid.Console --FeatureFlags` command. -- **Plan and add-ons** — Work Orders need the **Readiness Pro** add-on; push-to-talk needs the **PTT** add-on; encryption needs the **Advanced Data Protection** add-on; SSO/SCIM need the Enterprise tier. +- **Module switches** — administrators can hide Messaging, Mapping, Shifts, Logs/Records, Reports, Documents, Calendar, Notes, Training, Inventory, Checklists, Maintenance and Business Operations under **Department Settings → Module Settings**. +- **Feature flags** — some newer modules (Records, Checklists, Work Orders, Run Cards, Chat, Deployment Finance and the Business Ops modules) are switched on per department by Resgrid (hosted) or by the operator (self-hosted) using the `Resgrid.Console --FeatureFlags` command. +- **Plan and add-ons** — Work Orders need the **Readiness Pro** add-on; invoicing, contractor billing, Cal OES MARS, workforce and field costing need the **Business Ops** add-on; push-to-talk needs the **PTT** add-on; encryption (and pay data reporting) needs the **Advanced Data Protection** add-on; SSO/SCIM need the Enterprise tier. - **Permissions** — most pages check a permission (view, create, edit, delete) that administrators configure under Security & Permissions; if you cannot see something, that is usually why. ## How the pages are organised diff --git a/docs/web-app/personnel.md b/docs/web-app/personnel.md index d2ae0ab..bfeee1a 100644 --- a/docs/web-app/personnel.md +++ b/docs/web-app/personnel.md @@ -39,7 +39,7 @@ New accounts start with every contact method **pending verification**; the membe ## Viewing and editing a person -**View** shows the profile, group, roles, department flags (admin, disabled, hidden), current staffing and status, certifications, events and — where enabled — the equipment issued to them. **Edit** (or the person's profile page) changes: +**View** shows the profile, group, roles, department flags (admin, disabled, hidden), current staffing and status, [certifications](business-ops/certifications) (with expiry, verification and credits), events and — where enabled — the equipment issued to them. **Edit** (or the person's profile page) changes: | Section | Fields | |---|---| @@ -71,8 +71,9 @@ From the personnel list (or the [Dashboard](dashboard)) you can set a member's * - **Add Role** — name, description and initial members. - **Edit / View Role** — members in role; **Delete** removes the role (assignments are dropped). +- **Required certifications** — which [certification](business-ops/certifications) types a member must hold for the role, with any-of groups and a grace period; enforcement (off / warn / enforce) is set under Certifications → Settings. -Roles are used by call dispatch (dispatch to a role), [run cards](run-cards) (role requirements), [notifications](notifications) (low-availability alerts), [shifts](shifts) (role quotas), [checklists](checklists) and [work orders](work-orders) (assignment), security permissions (*Admins + selected roles*) and reports. +Roles are used by call dispatch (dispatch to a role), [run cards](run-cards) (role requirements), [notifications](notifications) (low-availability alerts), [shifts](shifts) (role quotas), [checklists](checklists) and [work orders](work-orders) (assignment), [certification requirements](business-ops/certifications#3-role-requirements), deployment seats, security permissions (*Admins + selected roles*) and reports. ## Ranks diff --git a/docs/web-app/records/deployments.md b/docs/web-app/records/deployments.md index 9db67b6..b104d8e 100644 --- a/docs/web-app/records/deployments.md +++ b/docs/web-app/records/deployments.md @@ -7,6 +7,8 @@ title: Deployments & Connectors **Deployments** track the external resource orders your department fills — a strike team sent on a wildland assignment through IROC, a crew loaned under EMAC, a Canadian request through CIFFC — from the order through mobilization, release and close-out. The ordering system stays authoritative: the order document is stored as an **immutable, checksummed snapshot** and nothing is ever written back. +To track the **time, expenses and billing** of the crew you send on an order, create a [Deployment Finance](../business-ops/deployment-finance) deployment from it (**Deployment Finance → Create from external order**); the order stays here. + :::note Preview feature Deployments and connectors are a **Preview** feature. Fixtures were built from published IROC, CIFFC and EMAC documentation, not live integrations. Verify against your ordering system. ::: diff --git a/docs/web-app/reports.md b/docs/web-app/reports.md index 32d4f43..66aa76d 100644 --- a/docs/web-app/reports.md +++ b/docs/web-app/reports.md @@ -57,6 +57,12 @@ Lists all certifications across the department: - Expiry date - Area of certification +### Certification Compliance Report + +The typed-catalog counterpart of the certifications report, built from the [Certifications](business-ops/certifications) dashboard: one grid for **people** and one for **units**, a column per certification type, cells coloured valid / expiring within the notification window / expired, with the *run on* date for auditors and accreditation files. Respects the personnel visibility matrix; can be scheduled like any other report. + +![Certification compliance report](/img/web-app/certifications/compliance-report.png) + ### Log Report **Parameters:** Log ID @@ -159,7 +165,7 @@ All parameter pages respect the **visibility matrix** — only showing personnel | Department type | How to set it up | |---|---| -| **Volunteer fire** | Schedule the *Personnel hours* and *Call summary* reports monthly to the chief and treasurer (LOSAP points, run reimbursements); *Certifications* quarterly to the training officer. | +| **Volunteer fire** | Schedule the *Personnel hours* and *Call summary* reports monthly to the chief and treasurer (LOSAP points, run reimbursements); *Certification compliance* quarterly to the training officer. | | **Career fire** | *Unit state history* and *Personnel staffing history* for payroll reconciliation; *Upcoming shift readiness* each morning. | | **EMS** | *Call summary* by type for the medical director; *Event attendance* for CE credit. | | **SAR** | *Personnel hours* per mission for volunteer-hour grants; *Department activity* YTD for the board. | @@ -168,7 +174,7 @@ All parameter pages respect the **visibility matrix** — only showing personnel ## Technical reference -`ReportsController` (+ `ChecklistReportsController`); routes `/User/Reports/{Index,PersonnelReport,StaffingReport,CertificationsReport,UpcomingShiftReadinessReport,DepartmentActivityReport,PersonnelHoursReportParams,PersonnelStaffingHistoryReportParams,UnitStateHistoryReportParams,ActionLogsParams,CallSummaryReportParams,ActiveCallsResourcesReport,FlaggedCallNotesReportParams,EventAttendanceReportParams,ChecklistComplianceReport,LogReport}`; scheduled delivery via `ProfileController.Reporting` and the worker; module switch `ReportsDisabled`. +`ReportsController` (+ `ChecklistReportsController`); routes `/User/Reports/{Index,PersonnelReport,StaffingReport,CertificationsReport,CertificationComplianceReport,UpcomingShiftReadinessReport,DepartmentActivityReport,PersonnelHoursReportParams,PersonnelStaffingHistoryReportParams,UnitStateHistoryReportParams,ActionLogsParams,CallSummaryReportParams,ActiveCallsResourcesReport,FlaggedCallNotesReportParams,EventAttendanceReportParams,ChecklistComplianceReport,LogReport}`; scheduled delivery via `ProfileController.Reporting` and the worker; module switch `ReportsDisabled`. ### Internal Report Generation The `InternalRunReport` endpoint is an **anonymous access** endpoint intended for system-internal use (e.g., scheduled report delivery). It supports generating: diff --git a/docs/web-app/security-permissions.md b/docs/web-app/security-permissions.md index 7d76af7..a22a4fd 100644 --- a/docs/web-app/security-permissions.md +++ b/docs/web-app/security-permissions.md @@ -69,6 +69,21 @@ Some visibility permissions have a **Group only** option that restricts what a m | View restricted sections · View legacy logs · View records from other groups | | | Manage record definitions · Publish record definitions · Manage record reports · Manage record disclosures · Manage legal holds · Reassign draft records · Manage prevention data | Dept admins | +### Workforce & Business Ops + +All default to *department administrators*. See the [Workforce & Business Ops overview](business-ops/overview). + +| Permission | Controls | +|---|---| +| Manage invoicing / View invoicing | Create, edit, send and void invoices, record payments, rate cards and billing profiles / read-only invoices, aging and PDFs. | +| Manage certifications / View certifications / Manage certification setup | Other members' certification records, credits and unit records / the expiry dashboard / types, role requirements and settings. Members always see their own records. | +| Manage deployments / Approve time reports | Deployments, rosters, equipment, expenses, files and status; see every deployment / approve and void submitted daily time reports. Rostered members always see their own deployments and file time. | +| Manage bids / Manage contracts | Bids and the deployment wizard / service contracts, document requirements and compliance documents. | +| Manage Cal OES MARS reimbursement | Agency, F-5, annual rates, agreements, handoff, observed statuses, invoice approval and payment reconciliation. Rostered members prepare their own F-42 and expense drafts without it. | +| View internal costs | Aggregate field-cost summaries, resource cost profiles and usage readings (never a person's rate). | +| Manage workforce and compensation / View workforce compensation | Employer, establishments, workers, employments, compensation profiles, work entries and pay-fact imports / read-only. Values also need a Protected Data Grant. | +| Manage California pay data reporting / Export California pay data reports | The CRD report wizard and demographic records / freezing a run and downloading its files. Members always answer their own demographic response. | + ### Advanced Data Protection | Permission | Purpose | diff --git a/docs/web-app/subscription-billing.md b/docs/web-app/subscription-billing.md index 13ac6ea..d6b167d 100644 --- a/docs/web-app/subscription-billing.md +++ b/docs/web-app/subscription-billing.md @@ -5,7 +5,7 @@ title: Subscription & Billing # Subscription & Billing -**Subscription & Billing** shows the department's plan (Free, Standard, Premium, Ultimate, Enterprise), what it includes and its limits (personnel, units, features), lets the **managing user** upgrade, change billing details, buy **add-ons** (Push-to-Talk, Advanced Data Protection, Readiness Pro) and download invoices. Self-hosted installations show the plan they are licensed for. +**Subscription & Billing** shows the department's plan (Free, Standard, Premium, Ultimate, Enterprise), what it includes and its limits (personnel, units, features), lets the **managing user** upgrade, change billing details, buy **add-ons** (Push-to-Talk, Advanced Data Protection, Readiness Pro, Business Ops) and download invoices. Self-hosted installations show the plan they are licensed for. **Department menu → Subscription and Billing.** Only the managing user can purchase or cancel. @@ -93,6 +93,14 @@ Manage the PTT addon subscription: - Add PTT addon (modifies subscription quantity) - Cancel PTT addon by type +### Business Ops add-on + +![Business Operations add-on](/img/web-app/business-ops/addon.png) + +**Subscription and Billing → Business Operations** opens the add-on page for the [Workforce & Business Ops](business-ops/overview) modules: customer invoicing, rate cards, payments and AR aging; contractor rate schedules, contracts and cost recovery (Cal OES MARS); workforce pay data and field costing. It is a **monthly** add-on (USD 250 on Stripe / EUR 295 on Paddle at the time of writing), and only the department's **managing member** can **Buy** or **Cancel subscription**. The page shows the price, whether the add-on is active, the paid-through date and a cancelled flag; checkout runs on Stripe Checkout or Paddle and never on this page. + +When the add-on lapses nothing is deleted: every Business Ops page stays readable and every change is refused until it is bought again. Certifications and Deployment Finance are free and unaffected. Turn the whole area off for the department without cancelling under **Department Settings → Module Settings → Business Operations**. + ### Other Addons The `BuyAddon` action supports purchasing plan addons: - View addon plan details @@ -116,13 +124,13 @@ Displays invoice details with deserialized Stripe `Charge` data. | Department type | How to set it up | |---|---| | **Small volunteer department** | Free or Standard covers dispatch, personnel and units; add PTT if you use the apps as radios. | -| **Career fire / EMS** | Premium/Ultimate for voice alerting, shifts and records; Readiness Pro for work orders; ADP if patient data is stored. | +| **Career fire / EMS** | Premium/Ultimate for voice alerting, shifts and records; Readiness Pro for work orders; ADP if patient data is stored; Business Ops for cost recovery, Cal OES MARS and invoicing. | | **Multi-agency / government** | Enterprise for SSO/SCIM and security policy; department links for shared dispatch. | -| **Business / industrial** | Standard plus Readiness Pro (maintenance) and PTT. | +| **Business / industrial** | Standard plus Readiness Pro (maintenance) and PTT; Business Ops for invoicing, contracts, bids and workforce costing. | ## Technical reference -`SubscriptionController`, `ReadinessProBillingController`; routes `/User/Subscription/{Index,UpdateBillingInfo,Cancel,BuyAddon,ManagePTTAddon,BuyAdpAddon,ManageAdpAddon,PaymentHistory,ViewInvoice,SelectRegistrationPlan}`; payments through Stripe or Paddle; plan limits cached 14 days (`SubscriptionsService`, `LimitsService`); addon entitlements checked live (`ReadinessAccessService`). +`SubscriptionController`, `ReadinessProBillingController`, `BusinessOperationsBillingController` (`/User/BusinessOperationsBilling/{Index,Checkout,CancelRenewal}`, Billing API `api/BusinessOperationsBilling/{Status,Checkout,CancelRenewal}`, `PlanAddonTypes.BusinessOperations = 4`); routes `/User/Subscription/{Index,UpdateBillingInfo,Cancel,BuyAddon,ManagePTTAddon,BuyAdpAddon,ManageAdpAddon,PaymentHistory,ViewInvoice,SelectRegistrationPlan}`; payments through Stripe or Paddle; plan limits cached 14 days (`SubscriptionsService`, `LimitsService`); addon entitlements checked live (`ReadinessAccessService`, `BusinessOperationsAccessService`). ### Interactions with Other Modules | Module | Interaction | diff --git a/docs/web-app/types-configuration.md b/docs/web-app/types-configuration.md index 84d60db..be73e65 100644 --- a/docs/web-app/types-configuration.md +++ b/docs/web-app/types-configuration.md @@ -80,6 +80,8 @@ Define categories for personnel certifications (EMT-B, Paramedic, Firefighter I, |-------|-------------| | Type Name | Certification type name (required, unique) | +The **Manage typed catalog** button opens the full [Certifications](business-ops/certifications) module, where each type also gets a stable code, category, person/unit scope, default validity, verification and credit-hour rules, and where you can add 90+ common credentials from the template gallery. Types created here appear in that catalog too; open them there to add the code, scope and rules. + ## Document Categories Categorize department documents: diff --git a/docs/web-app/units.md b/docs/web-app/units.md index b3a8c27..6c4f8be 100644 --- a/docs/web-app/units.md +++ b/docs/web-app/units.md @@ -44,7 +44,7 @@ Set a unit's status from the list, the [Dashboard](dashboard), the Unit app or t ## Equipment, checklists and tracking -From a unit you also reach its **equipment** (everything issued to it in [Inventory](inventory)), its [checklists](checklists) (target type *Unit*), its [work orders](work-orders) and its **hardware GPS tracking** bindings. +From a unit you also reach its **equipment** (everything issued to it in [Inventory](inventory)), its [checklists](checklists) (target type *Unit*), its [work orders](work-orders), its **certifications & inspections** (registration, insurance, pump and ladder tests, DOT inspections — see [Certifications](business-ops/certifications#unit-certifications-and-inspections)) and its **hardware GPS tracking** bindings. ## Setup examples diff --git a/docs/web-app/workflows.md b/docs/web-app/workflows.md index 13f8dc5..d7a0170 100644 --- a/docs/web-app/workflows.md +++ b/docs/web-app/workflows.md @@ -133,6 +133,13 @@ Workflows can subscribe to any of the following system events: | **Personnel Role Changed** | User role assignment changed | | **Group Added** | Department group created | | **Group Updated** | Department group updated | +| **Invoice Created / Sent / Payment Recorded / Paid / Overdue / Voided / Payment Refunded / Payment Disputed** | [Invoicing](business-ops/invoicing) lifecycle | +| **Bid Created / Sent / Accepted / Declined / Expired** | [Bids](business-ops/bids-and-deployment-wizard) | +| **Contract Status Changed / Contract Expiring** | [Service contracts](business-ops/contracts-and-compliance) (expiring = 30 days before the end date) | +| **Deployment Created / Status Changed / Roster Changed / Expense Added / Attachment Added** | [Deployment Finance](business-ops/deployment-finance) | +| **Time Report Created / Submitted / Approved / Voided** | Daily time reports | +| **Certification Added / Renewed / Expired / Role Removed / Status Changed / Removed / Credit Added** | [Certifications](business-ops/certifications) (people) | +| **Unit Certification Added / Expiring / Expired / Status Changed / Removed** | Certifications (units) | ## Action Types diff --git a/docusaurus.config.js b/docusaurus.config.js index bd3d626..c030931 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -97,6 +97,9 @@ const config = { {type: 'doc', docId: 'web-app/checklists', label: 'Checklists'}, {type: 'doc', docId: 'web-app/work-orders', label: 'Work Orders'}, {type: 'doc', docId: 'web-app/inventory', label: 'Inventory'}, + {type: 'doc', docId: 'web-app/business-ops/overview', label: 'Workforce & Business Ops'}, + {type: 'doc', docId: 'web-app/business-ops/certifications', label: 'Certifications'}, + {type: 'doc', docId: 'web-app/business-ops/invoicing', label: 'Invoicing'}, {type: 'doc', docId: 'web-app/chat', label: 'Chat & Assistant'}, {type: 'doc', docId: 'web-app/workflows', label: 'Workflows'}, {type: 'doc', docId: 'web-app/reports', label: 'Reports'}, diff --git a/src/components/HomepageFeatures/Icons.js b/src/components/HomepageFeatures/Icons.js index 9fe6775..7e06afd 100644 --- a/src/components/HomepageFeatures/Icons.js +++ b/src/components/HomepageFeatures/Icons.js @@ -56,6 +56,13 @@ const paths = { ), zap: , + briefcase: ( + <> + + + + + ), smartphone: ( <> diff --git a/src/components/HomepageFeatures/index.js b/src/components/HomepageFeatures/index.js index 79de50f..dae4406 100644 --- a/src/components/HomepageFeatures/index.js +++ b/src/components/HomepageFeatures/index.js @@ -129,6 +129,29 @@ const FeatureAreas = [ {label: 'Dashboard', to: '/web-app/dashboard'}, ], }, + { + key: 'business', + title: 'Workforce & Business Ops', + icon: 'briefcase', + tone: 'teal', + description: + 'Certifications, deployments and daily time reports, invoicing and online payments, contracts and bids, Cal OES MARS, workforce costing and pay data.', + items: [ + {label: 'Overview', to: '/web-app/business-ops/overview'}, + {label: 'Certifications', to: '/web-app/business-ops/certifications'}, + {label: 'Deployment Finance', to: '/web-app/business-ops/deployment-finance'}, + {label: 'Invoicing', to: '/web-app/business-ops/invoicing'}, + {label: 'Online Payments', to: '/web-app/business-ops/online-payments'}, + {label: 'Rate Schedules', to: '/web-app/business-ops/rate-schedules'}, + {label: 'Contracts & Compliance', to: '/web-app/business-ops/contracts-and-compliance'}, + {label: 'Bids & Deployment Wizard', to: '/web-app/business-ops/bids-and-deployment-wizard'}, + {label: 'Contractor Billing', to: '/web-app/business-ops/contractor-billing'}, + {label: 'Cal OES MARS', to: '/web-app/business-ops/cal-oes-mars'}, + {label: 'Workforce', to: '/web-app/business-ops/workforce'}, + {label: 'Field Costing', to: '/web-app/business-ops/field-costing'}, + {label: 'Pay Data Reporting', to: '/web-app/business-ops/pay-data-reporting'}, + ], + }, { key: 'automation', title: 'Automation, Security & Integration', diff --git a/static/CNAME b/static/CNAME new file mode 100644 index 0000000..c6537ba --- /dev/null +++ b/static/CNAME @@ -0,0 +1 @@ +docs.resgrid.com diff --git a/static/img/web-app/bids/edit.png b/static/img/web-app/bids/edit.png new file mode 100644 index 0000000..e6db33e Binary files /dev/null and b/static/img/web-app/bids/edit.png differ diff --git a/static/img/web-app/bids/index.png b/static/img/web-app/bids/index.png new file mode 100644 index 0000000..feab830 Binary files /dev/null and b/static/img/web-app/bids/index.png differ diff --git a/static/img/web-app/bids/new-for-contact.png b/static/img/web-app/bids/new-for-contact.png new file mode 100644 index 0000000..83a09f9 Binary files /dev/null and b/static/img/web-app/bids/new-for-contact.png differ diff --git a/static/img/web-app/bids/new.png b/static/img/web-app/bids/new.png new file mode 100644 index 0000000..79d0d4c Binary files /dev/null and b/static/img/web-app/bids/new.png differ diff --git a/static/img/web-app/bids/preview.png b/static/img/web-app/bids/preview.png new file mode 100644 index 0000000..b3ded7f Binary files /dev/null and b/static/img/web-app/bids/preview.png differ diff --git a/static/img/web-app/bids/view.png b/static/img/web-app/bids/view.png new file mode 100644 index 0000000..e6db33e Binary files /dev/null and b/static/img/web-app/bids/view.png differ diff --git a/static/img/web-app/bids/wizard.png b/static/img/web-app/bids/wizard.png new file mode 100644 index 0000000..219d54d Binary files /dev/null and b/static/img/web-app/bids/wizard.png differ diff --git a/static/img/web-app/business-ops/addon.png b/static/img/web-app/business-ops/addon.png new file mode 100644 index 0000000..8ba09fe Binary files /dev/null and b/static/img/web-app/business-ops/addon.png differ diff --git a/static/img/web-app/business-ops/module-settings.png b/static/img/web-app/business-ops/module-settings.png new file mode 100644 index 0000000..29ec9b7 Binary files /dev/null and b/static/img/web-app/business-ops/module-settings.png differ diff --git a/static/img/web-app/business-ops/navigation.png b/static/img/web-app/business-ops/navigation.png new file mode 100644 index 0000000..761365e Binary files /dev/null and b/static/img/web-app/business-ops/navigation.png differ diff --git a/static/img/web-app/business-ops/subscription.png b/static/img/web-app/business-ops/subscription.png new file mode 100644 index 0000000..2af8d20 Binary files /dev/null and b/static/img/web-app/business-ops/subscription.png differ diff --git a/static/img/web-app/cal-oes-mars/agency.png b/static/img/web-app/cal-oes-mars/agency.png new file mode 100644 index 0000000..8382554 Binary files /dev/null and b/static/img/web-app/cal-oes-mars/agency.png differ diff --git a/static/img/web-app/cal-oes-mars/agreements.png b/static/img/web-app/cal-oes-mars/agreements.png new file mode 100644 index 0000000..e1bd2f1 Binary files /dev/null and b/static/img/web-app/cal-oes-mars/agreements.png differ diff --git a/static/img/web-app/cal-oes-mars/index.png b/static/img/web-app/cal-oes-mars/index.png new file mode 100644 index 0000000..27de6c5 Binary files /dev/null and b/static/img/web-app/cal-oes-mars/index.png differ diff --git a/static/img/web-app/cal-oes-mars/invoice.png b/static/img/web-app/cal-oes-mars/invoice.png new file mode 100644 index 0000000..21fb55f Binary files /dev/null and b/static/img/web-app/cal-oes-mars/invoice.png differ diff --git a/static/img/web-app/cal-oes-mars/print.png b/static/img/web-app/cal-oes-mars/print.png new file mode 100644 index 0000000..bd36894 Binary files /dev/null and b/static/img/web-app/cal-oes-mars/print.png differ diff --git a/static/img/web-app/cal-oes-mars/queue.png b/static/img/web-app/cal-oes-mars/queue.png new file mode 100644 index 0000000..b88de4e Binary files /dev/null and b/static/img/web-app/cal-oes-mars/queue.png differ diff --git a/static/img/web-app/cal-oes-mars/rate-edit.png b/static/img/web-app/cal-oes-mars/rate-edit.png new file mode 100644 index 0000000..5e7a82e Binary files /dev/null and b/static/img/web-app/cal-oes-mars/rate-edit.png differ diff --git a/static/img/web-app/cal-oes-mars/rate-new.png b/static/img/web-app/cal-oes-mars/rate-new.png new file mode 100644 index 0000000..9c5373b Binary files /dev/null and b/static/img/web-app/cal-oes-mars/rate-new.png differ diff --git a/static/img/web-app/cal-oes-mars/rates.png b/static/img/web-app/cal-oes-mars/rates.png new file mode 100644 index 0000000..d805f06 Binary files /dev/null and b/static/img/web-app/cal-oes-mars/rates.png differ diff --git a/static/img/web-app/cal-oes-mars/reconciliation.png b/static/img/web-app/cal-oes-mars/reconciliation.png new file mode 100644 index 0000000..7f46800 Binary files /dev/null and b/static/img/web-app/cal-oes-mars/reconciliation.png differ diff --git a/static/img/web-app/cal-oes-mars/resources.png b/static/img/web-app/cal-oes-mars/resources.png new file mode 100644 index 0000000..6349906 Binary files /dev/null and b/static/img/web-app/cal-oes-mars/resources.png differ diff --git a/static/img/web-app/cal-oes-mars/work-item.png b/static/img/web-app/cal-oes-mars/work-item.png new file mode 100644 index 0000000..80df8b7 Binary files /dev/null and b/static/img/web-app/cal-oes-mars/work-item.png differ diff --git a/static/img/web-app/certifications/compliance-report.png b/static/img/web-app/certifications/compliance-report.png new file mode 100644 index 0000000..ddcd7f6 Binary files /dev/null and b/static/img/web-app/certifications/compliance-report.png differ diff --git a/static/img/web-app/certifications/dashboard-units.png b/static/img/web-app/certifications/dashboard-units.png new file mode 100644 index 0000000..9b33247 Binary files /dev/null and b/static/img/web-app/certifications/dashboard-units.png differ diff --git a/static/img/web-app/certifications/dashboard.png b/static/img/web-app/certifications/dashboard.png new file mode 100644 index 0000000..5bacc46 Binary files /dev/null and b/static/img/web-app/certifications/dashboard.png differ diff --git a/static/img/web-app/certifications/profile-add-certification.png b/static/img/web-app/certifications/profile-add-certification.png new file mode 100644 index 0000000..7f4d1c1 Binary files /dev/null and b/static/img/web-app/certifications/profile-add-certification.png differ diff --git a/static/img/web-app/certifications/profile-certifications.png b/static/img/web-app/certifications/profile-certifications.png new file mode 100644 index 0000000..7b20f35 Binary files /dev/null and b/static/img/web-app/certifications/profile-certifications.png differ diff --git a/static/img/web-app/certifications/record.png b/static/img/web-app/certifications/record.png new file mode 100644 index 0000000..b4ceed4 Binary files /dev/null and b/static/img/web-app/certifications/record.png differ diff --git a/static/img/web-app/certifications/role-requirements.png b/static/img/web-app/certifications/role-requirements.png new file mode 100644 index 0000000..08fd6ff Binary files /dev/null and b/static/img/web-app/certifications/role-requirements.png differ diff --git a/static/img/web-app/certifications/settings.png b/static/img/web-app/certifications/settings.png new file mode 100644 index 0000000..ad4d437 Binary files /dev/null and b/static/img/web-app/certifications/settings.png differ diff --git a/static/img/web-app/certifications/type-edit.png b/static/img/web-app/certifications/type-edit.png new file mode 100644 index 0000000..94d17fe Binary files /dev/null and b/static/img/web-app/certifications/type-edit.png differ diff --git a/static/img/web-app/certifications/type-new.png b/static/img/web-app/certifications/type-new.png new file mode 100644 index 0000000..cddd827 Binary files /dev/null and b/static/img/web-app/certifications/type-new.png differ diff --git a/static/img/web-app/certifications/types-inactive.png b/static/img/web-app/certifications/types-inactive.png new file mode 100644 index 0000000..b5e9e27 Binary files /dev/null and b/static/img/web-app/certifications/types-inactive.png differ diff --git a/static/img/web-app/certifications/types-template-gallery.png b/static/img/web-app/certifications/types-template-gallery.png new file mode 100644 index 0000000..d0455ce Binary files /dev/null and b/static/img/web-app/certifications/types-template-gallery.png differ diff --git a/static/img/web-app/certifications/types.png b/static/img/web-app/certifications/types.png new file mode 100644 index 0000000..9577f11 Binary files /dev/null and b/static/img/web-app/certifications/types.png differ diff --git a/static/img/web-app/certifications/unit.png b/static/img/web-app/certifications/unit.png new file mode 100644 index 0000000..9cc20cc Binary files /dev/null and b/static/img/web-app/certifications/unit.png differ diff --git a/static/img/web-app/contacts/add.png b/static/img/web-app/contacts/add.png index 25fb307..5320e36 100644 Binary files a/static/img/web-app/contacts/add.png and b/static/img/web-app/contacts/add.png differ diff --git a/static/img/web-app/contacts/attachments.png b/static/img/web-app/contacts/attachments.png index 24e7cf7..17887cc 100644 Binary files a/static/img/web-app/contacts/attachments.png and b/static/img/web-app/contacts/attachments.png differ diff --git a/static/img/web-app/contacts/categories.png b/static/img/web-app/contacts/categories.png index 8e265a8..1f50874 100644 Binary files a/static/img/web-app/contacts/categories.png and b/static/img/web-app/contacts/categories.png differ diff --git a/static/img/web-app/contacts/edit.png b/static/img/web-app/contacts/edit.png index e487332..22f4693 100644 Binary files a/static/img/web-app/contacts/edit.png and b/static/img/web-app/contacts/edit.png differ diff --git a/static/img/web-app/contacts/index.png b/static/img/web-app/contacts/index.png index 1baee09..56f60bd 100644 Binary files a/static/img/web-app/contacts/index.png and b/static/img/web-app/contacts/index.png differ diff --git a/static/img/web-app/contacts/preplan.png b/static/img/web-app/contacts/preplan.png index 4d319b2..6e4c45a 100644 Binary files a/static/img/web-app/contacts/preplan.png and b/static/img/web-app/contacts/preplan.png differ diff --git a/static/img/web-app/contacts/view-person.png b/static/img/web-app/contacts/view-person.png new file mode 100644 index 0000000..d692d67 Binary files /dev/null and b/static/img/web-app/contacts/view-person.png differ diff --git a/static/img/web-app/contacts/view.png b/static/img/web-app/contacts/view.png index e54a20b..248bc35 100644 Binary files a/static/img/web-app/contacts/view.png and b/static/img/web-app/contacts/view.png differ diff --git a/static/img/web-app/contracts/compliance.png b/static/img/web-app/contracts/compliance.png new file mode 100644 index 0000000..0375219 Binary files /dev/null and b/static/img/web-app/contracts/compliance.png differ diff --git a/static/img/web-app/contracts/edit.png b/static/img/web-app/contracts/edit.png new file mode 100644 index 0000000..07a5a03 Binary files /dev/null and b/static/img/web-app/contracts/edit.png differ diff --git a/static/img/web-app/contracts/index.png b/static/img/web-app/contracts/index.png new file mode 100644 index 0000000..36675bb Binary files /dev/null and b/static/img/web-app/contracts/index.png differ diff --git a/static/img/web-app/contracts/new.png b/static/img/web-app/contracts/new.png new file mode 100644 index 0000000..9eae73b Binary files /dev/null and b/static/img/web-app/contracts/new.png differ diff --git a/static/img/web-app/contracts/view.png b/static/img/web-app/contracts/view.png new file mode 100644 index 0000000..99e3ae1 Binary files /dev/null and b/static/img/web-app/contracts/view.png differ diff --git a/static/img/web-app/deployment-finance/edit.png b/static/img/web-app/deployment-finance/edit.png new file mode 100644 index 0000000..71f2cb3 Binary files /dev/null and b/static/img/web-app/deployment-finance/edit.png differ diff --git a/static/img/web-app/deployment-finance/from-external-order.png b/static/img/web-app/deployment-finance/from-external-order.png new file mode 100644 index 0000000..e9b42ab Binary files /dev/null and b/static/img/web-app/deployment-finance/from-external-order.png differ diff --git a/static/img/web-app/deployment-finance/index-all.png b/static/img/web-app/deployment-finance/index-all.png new file mode 100644 index 0000000..9f0af73 Binary files /dev/null and b/static/img/web-app/deployment-finance/index-all.png differ diff --git a/static/img/web-app/deployment-finance/index.png b/static/img/web-app/deployment-finance/index.png new file mode 100644 index 0000000..50c18d5 Binary files /dev/null and b/static/img/web-app/deployment-finance/index.png differ diff --git a/static/img/web-app/deployment-finance/new.png b/static/img/web-app/deployment-finance/new.png new file mode 100644 index 0000000..873dcdd Binary files /dev/null and b/static/img/web-app/deployment-finance/new.png differ diff --git a/static/img/web-app/deployment-finance/time-report-billable.png b/static/img/web-app/deployment-finance/time-report-billable.png new file mode 100644 index 0000000..07af590 Binary files /dev/null and b/static/img/web-app/deployment-finance/time-report-billable.png differ diff --git a/static/img/web-app/deployment-finance/time-report.png b/static/img/web-app/deployment-finance/time-report.png new file mode 100644 index 0000000..d2c82a3 Binary files /dev/null and b/static/img/web-app/deployment-finance/time-report.png differ diff --git a/static/img/web-app/deployment-finance/view-billing.png b/static/img/web-app/deployment-finance/view-billing.png new file mode 100644 index 0000000..5faa568 Binary files /dev/null and b/static/img/web-app/deployment-finance/view-billing.png differ diff --git a/static/img/web-app/deployment-finance/view-costs.png b/static/img/web-app/deployment-finance/view-costs.png new file mode 100644 index 0000000..82e829f Binary files /dev/null and b/static/img/web-app/deployment-finance/view-costs.png differ diff --git a/static/img/web-app/deployment-finance/view-expenses.png b/static/img/web-app/deployment-finance/view-expenses.png new file mode 100644 index 0000000..dd6c93e Binary files /dev/null and b/static/img/web-app/deployment-finance/view-expenses.png differ diff --git a/static/img/web-app/deployment-finance/view-files.png b/static/img/web-app/deployment-finance/view-files.png new file mode 100644 index 0000000..dae13c9 Binary files /dev/null and b/static/img/web-app/deployment-finance/view-files.png differ diff --git a/static/img/web-app/deployment-finance/view-manual.png b/static/img/web-app/deployment-finance/view-manual.png new file mode 100644 index 0000000..45b2266 Binary files /dev/null and b/static/img/web-app/deployment-finance/view-manual.png differ diff --git a/static/img/web-app/deployment-finance/view-roster.png b/static/img/web-app/deployment-finance/view-roster.png new file mode 100644 index 0000000..cf956a4 Binary files /dev/null and b/static/img/web-app/deployment-finance/view-roster.png differ diff --git a/static/img/web-app/deployment-finance/view-time.png b/static/img/web-app/deployment-finance/view-time.png new file mode 100644 index 0000000..038f570 Binary files /dev/null and b/static/img/web-app/deployment-finance/view-time.png differ diff --git a/static/img/web-app/invoicing/aging.png b/static/img/web-app/invoicing/aging.png new file mode 100644 index 0000000..516bce7 Binary files /dev/null and b/static/img/web-app/invoicing/aging.png differ diff --git a/static/img/web-app/invoicing/billing-profile.png b/static/img/web-app/invoicing/billing-profile.png new file mode 100644 index 0000000..0036a1f Binary files /dev/null and b/static/img/web-app/invoicing/billing-profile.png differ diff --git a/static/img/web-app/invoicing/edit-call-picker.png b/static/img/web-app/invoicing/edit-call-picker.png new file mode 100644 index 0000000..035d2de Binary files /dev/null and b/static/img/web-app/invoicing/edit-call-picker.png differ diff --git a/static/img/web-app/invoicing/edit.png b/static/img/web-app/invoicing/edit.png new file mode 100644 index 0000000..2cdc484 Binary files /dev/null and b/static/img/web-app/invoicing/edit.png differ diff --git a/static/img/web-app/invoicing/index-draft.png b/static/img/web-app/invoicing/index-draft.png new file mode 100644 index 0000000..966e841 Binary files /dev/null and b/static/img/web-app/invoicing/index-draft.png differ diff --git a/static/img/web-app/invoicing/index.png b/static/img/web-app/invoicing/index.png new file mode 100644 index 0000000..53c885e Binary files /dev/null and b/static/img/web-app/invoicing/index.png differ diff --git a/static/img/web-app/invoicing/new-for-contact.png b/static/img/web-app/invoicing/new-for-contact.png new file mode 100644 index 0000000..336ba84 Binary files /dev/null and b/static/img/web-app/invoicing/new-for-contact.png differ diff --git a/static/img/web-app/invoicing/new.png b/static/img/web-app/invoicing/new.png new file mode 100644 index 0000000..5601d54 Binary files /dev/null and b/static/img/web-app/invoicing/new.png differ diff --git a/static/img/web-app/invoicing/rate-card-edit.png b/static/img/web-app/invoicing/rate-card-edit.png new file mode 100644 index 0000000..a900a82 Binary files /dev/null and b/static/img/web-app/invoicing/rate-card-edit.png differ diff --git a/static/img/web-app/invoicing/rate-card-new.png b/static/img/web-app/invoicing/rate-card-new.png new file mode 100644 index 0000000..3cccd94 Binary files /dev/null and b/static/img/web-app/invoicing/rate-card-new.png differ diff --git a/static/img/web-app/invoicing/rate-cards.png b/static/img/web-app/invoicing/rate-cards.png new file mode 100644 index 0000000..384166b Binary files /dev/null and b/static/img/web-app/invoicing/rate-cards.png differ diff --git a/static/img/web-app/invoicing/settings.png b/static/img/web-app/invoicing/settings.png new file mode 100644 index 0000000..6a97db6 Binary files /dev/null and b/static/img/web-app/invoicing/settings.png differ diff --git a/static/img/web-app/invoicing/view-deployment-invoice.png b/static/img/web-app/invoicing/view-deployment-invoice.png new file mode 100644 index 0000000..d58712c Binary files /dev/null and b/static/img/web-app/invoicing/view-deployment-invoice.png differ diff --git a/static/img/web-app/invoicing/view-paid.png b/static/img/web-app/invoicing/view-paid.png new file mode 100644 index 0000000..e334c08 Binary files /dev/null and b/static/img/web-app/invoicing/view-paid.png differ diff --git a/static/img/web-app/invoicing/view.png b/static/img/web-app/invoicing/view.png new file mode 100644 index 0000000..cd1daf4 Binary files /dev/null and b/static/img/web-app/invoicing/view.png differ diff --git a/static/img/web-app/rate-schedules/edit.png b/static/img/web-app/rate-schedules/edit.png new file mode 100644 index 0000000..b84df01 Binary files /dev/null and b/static/img/web-app/rate-schedules/edit.png differ diff --git a/static/img/web-app/rate-schedules/index-all.png b/static/img/web-app/rate-schedules/index-all.png new file mode 100644 index 0000000..2f78305 Binary files /dev/null and b/static/img/web-app/rate-schedules/index-all.png differ diff --git a/static/img/web-app/rate-schedules/index.png b/static/img/web-app/rate-schedules/index.png new file mode 100644 index 0000000..2e1c1f3 Binary files /dev/null and b/static/img/web-app/rate-schedules/index.png differ diff --git a/static/img/web-app/rate-schedules/new.png b/static/img/web-app/rate-schedules/new.png new file mode 100644 index 0000000..d2ee99f Binary files /dev/null and b/static/img/web-app/rate-schedules/new.png differ diff --git a/static/img/web-app/workforce/annual-facts.png b/static/img/web-app/workforce/annual-facts.png new file mode 100644 index 0000000..47634f6 Binary files /dev/null and b/static/img/web-app/workforce/annual-facts.png differ diff --git a/static/img/web-app/workforce/compensation-profile.png b/static/img/web-app/workforce/compensation-profile.png new file mode 100644 index 0000000..a44a747 Binary files /dev/null and b/static/img/web-app/workforce/compensation-profile.png differ diff --git a/static/img/web-app/workforce/compensation.png b/static/img/web-app/workforce/compensation.png new file mode 100644 index 0000000..269ff30 Binary files /dev/null and b/static/img/web-app/workforce/compensation.png differ diff --git a/static/img/web-app/workforce/contractors.png b/static/img/web-app/workforce/contractors.png new file mode 100644 index 0000000..0959195 Binary files /dev/null and b/static/img/web-app/workforce/contractors.png differ diff --git a/static/img/web-app/workforce/cost-run.png b/static/img/web-app/workforce/cost-run.png new file mode 100644 index 0000000..859f841 Binary files /dev/null and b/static/img/web-app/workforce/cost-run.png differ diff --git a/static/img/web-app/workforce/cost-runs.png b/static/img/web-app/workforce/cost-runs.png new file mode 100644 index 0000000..9db9e33 Binary files /dev/null and b/static/img/web-app/workforce/cost-runs.png differ diff --git a/static/img/web-app/workforce/employer.png b/static/img/web-app/workforce/employer.png new file mode 100644 index 0000000..6a4eb59 Binary files /dev/null and b/static/img/web-app/workforce/employer.png differ diff --git a/static/img/web-app/workforce/establishments.png b/static/img/web-app/workforce/establishments.png new file mode 100644 index 0000000..ef70557 Binary files /dev/null and b/static/img/web-app/workforce/establishments.png differ diff --git a/static/img/web-app/workforce/index.png b/static/img/web-app/workforce/index.png new file mode 100644 index 0000000..139016a Binary files /dev/null and b/static/img/web-app/workforce/index.png differ diff --git a/static/img/web-app/workforce/resource-costs.png b/static/img/web-app/workforce/resource-costs.png new file mode 100644 index 0000000..aa1c972 Binary files /dev/null and b/static/img/web-app/workforce/resource-costs.png differ diff --git a/static/img/web-app/workforce/usage.png b/static/img/web-app/workforce/usage.png new file mode 100644 index 0000000..f46c252 Binary files /dev/null and b/static/img/web-app/workforce/usage.png differ diff --git a/static/img/web-app/workforce/work-entries.png b/static/img/web-app/workforce/work-entries.png new file mode 100644 index 0000000..2466932 Binary files /dev/null and b/static/img/web-app/workforce/work-entries.png differ diff --git a/static/img/web-app/workforce/worker.png b/static/img/web-app/workforce/worker.png new file mode 100644 index 0000000..8c08900 Binary files /dev/null and b/static/img/web-app/workforce/worker.png differ diff --git a/static/img/web-app/workforce/workers.png b/static/img/web-app/workforce/workers.png new file mode 100644 index 0000000..53fd821 Binary files /dev/null and b/static/img/web-app/workforce/workers.png differ