Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
23674bf
feat: Updated incident-contracts to incorporate more fields supportin…
chetanr25 Jul 17, 2026
7acd3f9
Merge pull request #616 from chetanr25/incident-schema
marcvergees Jul 22, 2026
890992f
feat: redesign extraction contract for grouped calls and readiness. …
chetanr25 Jul 23, 2026
53e2147
feat: rework form generation around incidents and templates. Issue #619
chetanr25 Jul 23, 2026
e74469e
feat: add field catalog endpoint and template-record schema
chetanr25 Jul 23, 2026
7285fe9
feat: add field catalog job type and template field mapping schema
chetanr25 Jul 24, 2026
b2a340c
Updated description for incident and attached time to the incident da…
chetanr25 Jul 24, 2026
4a273bb
feat: register pipeline C endpoints in the master openapi contract
chetanr25 Jul 24, 2026
3c4803c
Merge pull request #618 from chetanr25/extraction_api_contract_update
marcvergees Jul 27, 2026
7c7cdf7
Merge pull request #620 from chetanr25/form_api_contract_update
marcvergees Jul 27, 2026
f087ca4
Merge pull request #622 from chetanr25/template_registry_maping
marcvergees Jul 27, 2026
7d5227d
Merge pull request #623 from chetanr25/openapi_master_contract
marcvergees Jul 27, 2026
23576cc
feat(extraction): add FieldSource enum for field gap sources (#624)
chetanr25 Jul 30, 2026
ffe6ff3
feat(incidents): store incident contract and promoted analytics colum…
chetanr25 Jul 30, 2026
5a8d248
feat(db): add migration 003 moving the incident contract onto incidents
chetanr25 Jul 30, 2026
e82eaac
test: update model and migration tests for the contract-on-incident s…
chetanr25 Jul 30, 2026
a109528
fixed tests for migrations changes
chetanr25 Jul 30, 2026
94d267e
Updated makefile to add migration version number
chetanr25 Jul 30, 2026
8f36e46
Merge pull request #632 from chetanr25/fieldsource-enum-extraction
marcvergees Jul 30, 2026
eec558e
Merge pull request #633 from chetanr25/contract-on-incidents-migration
marcvergees Jul 30, 2026
df32a99
Merge pull request #635 from chetanr25/migration_script_update
marcvergees Jul 30, 2026
b3bba89
feat(enums): sync IncidentCategory and InjurySeverity members to cont…
chetanr25 Jul 31, 2026
9cb6af5
feat(contract): add generator + make target for incident contract models
chetanr25 Jul 31, 2026
252abc2
feat(contract): generate Pydantic models for incident contract
chetanr25 Jul 31, 2026
8135ae1
Added test cases for incident contract models
chetanr25 Jul 31, 2026
3bbd6b5
Merge pull request #643 from chetanr25/generated-contract-models
marcvergees Aug 1, 2026
e1ce6cf
feat(extraction): add request and response schemas for the extraction…
chetanr25 Aug 1, 2026
8448854
added tests for extraction layer schema
chetanr25 Aug 1, 2026
94873c5
Merge pull request #644 from chetanr25/extraction-schemas
marcvergees Aug 3, 2026
4076fb9
feat(extraction): add extraction/incident repositories and analytics …
chetanr25 Aug 3, 2026
0c5447d
added tests for database operations - extraction repositry
chetanr25 Aug 3, 2026
23d8da0
Merge pull request #647 from chetanr25/extraction-repositories-promote
marcvergees Aug 4, 2026
e172527
feat(extraction): add config, repo lookup, 202 schema, ollama check a…
chetanr25 Aug 4, 2026
87284ed
feat(extraction): add POST/GET extract endpoints. validation handler …
chetanr25 Aug 4, 2026
69879ca
service layer for extraction, fixed error handling for ultra long inp…
chetanr25 Aug 4, 2026
f42d2c6
test(extraction): cover every status path for both extract endpoints
chetanr25 Aug 4, 2026
ad59c71
Updated and pinned ruff latest version. Created ruff.toml
chetanr25 Aug 5, 2026
8635eb9
ci: run lint and tests on development-* PR bases
chetanr25 Aug 5, 2026
925e7e5
Merge pull request #648 from chetanr25/feat/extraction-endpoints
marcvergees Aug 5, 2026
ffdd7e2
feat(contract): add extraction tier and trigger metadata
chetanr25 Aug 9, 2026
594cf93
fix(codegen): stop date fields shadowing the date type
chetanr25 Aug 9, 2026
6c6e43a
refactor(extraction): split the service into a package
chetanr25 Aug 9, 2026
9160f37
feat(extraction): ollama client and its config
chetanr25 Aug 9, 2026
a2ac439
Add envs to existing compose file and updated dockerfile to include c…
chetanr25 Aug 9, 2026
5767340
feat(extraction): contract-driven chunk routing and prompts
chetanr25 Aug 9, 2026
c8cad85
feat(extraction): run the chunks and write the draft incident
chetanr25 Aug 9, 2026
91582db
added tests for extraction worker and updated extraction test file
chetanr25 Aug 9, 2026
01bbe63
Merge pull request #657 from chetanr25/feat/chunked-extraction-worker
marcvergees Aug 9, 2026
63b095c
feat(extraction): added ValidationAppError, updated the body of the A…
chetanr25 Aug 10, 2026
6254895
feat(extraction): PATCH /extract applies a merge patch to the inciden…
chetanr25 Aug 10, 2026
17b6fcc
test(extraction): cover the merge rules, the audit trail and every er…
chetanr25 Aug 10, 2026
0d2ee9e
feat(templates): store the registry and PDF drafts, with migration 004
chetanr25 Aug 11, 2026
e19d2f3
feat(templates): describe fields by where their value comes from
chetanr25 Aug 11, 2026
5ec4e81
feat(system): expose the incident contract as a searchable field catalog
chetanr25 Aug 11, 2026
69828e4
feat(templates): detect fields on a PDF and suggest their mappings
chetanr25 Aug 11, 2026
7ba409b
feat(templates): serve the v1 registry, replacing the prototype routes
chetanr25 Aug 11, 2026
697aa55
test: cover the registry, the field catalog and field detection
chetanr25 Aug 11, 2026
b3e5ea4
fix(templates): pad one-page PDFs for detection, 409 on a taken form_…
chetanr25 Aug 12, 2026
849c219
Merge pull request #596 from chetanr25/template_registry
marcvergees Aug 13, 2026
430e7b8
Merge pull request #661 from chetanr25/feat/extraction-corrections
marcvergees Aug 13, 2026
9b8059a
contract: report the LLM provider in health, add LLM_RATE_LIMITED to …
chetanr25 Aug 13, 2026
5ebc667
config: add LLM provider settings, swap the ollama dependency for openai
chetanr25 Aug 13, 2026
9f0180f
feat(llm): one module for every provider, with 429 retries and an ext…
chetanr25 Aug 13, 2026
cf46a20
feat(llm): stop the API and the worker on a bad provider configuration
chetanr25 Aug 13, 2026
a1a4516
refactor(extraction): run chunks through the LLM module, keep partial…
chetanr25 Aug 13, 2026
aebd5e3
refactor(forms): move the fill loop off the LLM class, hand the fille…
chetanr25 Aug 13, 2026
b52bcf3
feat(system): report the llm component in health, serve models from t…
chetanr25 Aug 13, 2026
ef2ab0a
test: cover the LLM module and move the existing suites onto it
chetanr25 Aug 13, 2026
a3a5e8c
Merge pull request #666 from chetanr25/llm-service-providers
vharkins1 Aug 14, 2026
4afb0ce
feat(contract): validate returns 409 when not completed
chetanr25 Aug 15, 2026
e6c7011
feat(extraction): readiness engine over template field lists
chetanr25 Aug 15, 2026
6271154
feat(extraction): serve readiness and validate for an extraction
chetanr25 Aug 15, 2026
9764207
test(extraction): cover the gap rules and both endpoints
chetanr25 Aug 15, 2026
e9a8c68
Merge pull request #669 from chetanr25/feat/extraction-readiness
marcvergees Aug 15, 2026
aaf4ca4
Fix Form model and add migration for #552 (model + migration + repo)
abhishek-8081 Aug 17, 2026
42fd829
Merge pull request #673 from abhishek-8081/issue-552-form-model-migra…
marcvergees Aug 17, 2026
60e503b
fix(docker): load the env file into the app and worker containers
chetanr25 Aug 18, 2026
aa7581d
feat(extraction): allow re-running an extraction on the same input
chetanr25 Aug 18, 2026
ef5167f
Add form generation endpoint, fill task, and retrieval endpoints (#55…
abhishek-8081 Aug 18, 2026
ebfff1a
Merge pull request #675 from chetanr25/fix/extraction-rerun-flag
marcvergees Aug 21, 2026
1b2d3d0
Merge pull request #676 from chetanr25/fix/compose-env-file
marcvergees Aug 21, 2026
fd88a4f
Merge pull request #677 from abhishek-8081/issue-552-generate-endpoint
marcvergees Aug 21, 2026
e465bd1
fix(contracts): rename GET /incidents filter to incident_category
chetanr25 Aug 22, 2026
07a9f91
fix(incidents): promote incident_name and incident_type from the cont…
chetanr25 Aug 22, 2026
9edf44d
feat(incidents): index incidents for listing, drop unused incident_date
chetanr25 Aug 22, 2026
0c8290e
feat(incidents): add list, number lookup and form count queries
chetanr25 Aug 22, 2026
bbb20b9
feat(incidents): add the five incident CRUD endpoints
chetanr25 Aug 22, 2026
8786f92
test(incidents): cover the five CRUD endpoints
chetanr25 Aug 22, 2026
a95944d
Merge pull request #678 from chetanr25/feat/incidents-crud
marcvergees Aug 23, 2026
530788f
contract(forms): add 202 and 500 to the form JSON download
chetanr25 Aug 23, 2026
ecfc7ce
fix(forms): name PDF downloads properly, align JSON download responses
chetanr25 Aug 23, 2026
3b3cfd9
updated tests for pdf form download
chetanr25 Aug 23, 2026
7e921d3
contract(forms): add 500 to batch download, clarify download_url
chetanr25 Aug 23, 2026
63c44a6
feat(forms): add batch zip download and fill in download_url
chetanr25 Aug 23, 2026
53f6b6e
Updated tests for batch form generation
chetanr25 Aug 23, 2026
1a3b958
Merge pull request #679 from chetanr25/pdf_json_download
marcvergees Aug 23, 2026
abeaa9d
Merge pull request #680 from chetanr25/feat/batch-form-generation
marcvergees Aug 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches: [main,development]
pull_request:
branches: [main,development]
branches: [main, development, 'development-*']

jobs:
lint:
Expand All @@ -23,7 +23,7 @@ jobs:
uses: astral-sh/setup-uv@v6

- name: Install linter
run: uv pip install --system ruff
run: uv pip install --system ruff==0.16.1

- name: Run linter
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
- 'alembic.ini'
- '.github/workflows/tests.yml'
pull_request:
branches: [main,development]
branches: [main, development, 'development-*']
paths:
- '**.py'
- 'requirements.txt'
Expand Down
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ help:
@echo "make docs - Serve interactive API docs from the OpenAPI contract"
@echo "make migrate - Run pending Alembic migrations"
@echo "make migration - Generate new migration (msg='description')"
@echo "make generate-contract-models - Regenerate Pydantic models from the incident contract"
@echo "make clean - Stop containers (preserves volumes)"
@echo "make super-clean - [CAUTION] Stop containers, delete volumes, prune Docker"

Expand Down Expand Up @@ -114,7 +115,11 @@ migrate:
@$(COMPOSE) exec -T app alembic upgrade head

migration:
@$(COMPOSE) exec -T app alembic revision --autogenerate -m "$(msg)"
@test -n "$(rev)" || { echo "rev is required, e.g. make migration rev=003 msg=\"...\""; exit 1; }
@$(COMPOSE) exec -T app alembic revision --autogenerate --rev-id "$(rev)" -m "$(msg)"

generate-contract-models:
@$(COMPOSE) exec -T app sh -c "uv pip install --system -r requirements-dev.txt && python3 scripts/generate_contract_models.py"

clean:
@$(COMPOSE) down
Expand Down
73 changes: 73 additions & 0 deletions alembic/versions/003_move_incident_contract_onto_incident_row.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""move incident contract onto incident row

Revision ID: 003
Revises: 002
Create Date: 2026-07-30 09:26:53.879663

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa
import sqlmodel
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision: str = '003'
down_revision: Union[str, None] = '002'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('extractions', sa.Column('partial_result', sa.JSON(), nullable=True))
op.drop_column('extractions', 'incident_contract')
op.add_column('incidents', sa.Column('incident_contract', sa.JSON(), nullable=True))
op.add_column('incidents', sa.Column('incident_category', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
op.add_column('incidents', sa.Column('incident_datetime', sa.DateTime(), nullable=True))
op.add_column('incidents', sa.Column('city', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
op.add_column('incidents', sa.Column('state', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
op.add_column('incidents', sa.Column('country', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
op.add_column('incidents', sa.Column('civilian_injuries', sa.Integer(), nullable=True))
op.add_column('incidents', sa.Column('civilian_fatalities', sa.Integer(), nullable=True))
op.add_column('incidents', sa.Column('responder_injuries', sa.Integer(), nullable=True))
op.add_column('incidents', sa.Column('responder_fatalities', sa.Integer(), nullable=True))
op.add_column('incidents', sa.Column('people_rescued', sa.Integer(), nullable=True))
op.add_column('incidents', sa.Column('people_evacuated', sa.Integer(), nullable=True))
op.add_column('incidents', sa.Column('structures_destroyed', sa.Integer(), nullable=True))
op.add_column('incidents', sa.Column('area_burned_ha', sa.Float(), nullable=True))
op.add_column('incidents', sa.Column('total_loss_amount', sa.Float(), nullable=True))
op.add_column('incidents', sa.Column('total_loss_currency', sqlmodel.sql.sqltypes.AutoString(), nullable=True))
op.add_column('incidents', sa.Column('call_to_arrival_seconds', sa.Integer(), nullable=True))
op.add_column('incidents', sa.Column('turnout_seconds_first_unit', sa.Integer(), nullable=True))
op.add_column('incidents', sa.Column('travel_seconds_first_unit', sa.Integer(), nullable=True))
op.add_column('incidents', sa.Column('on_scene_duration_seconds', sa.Integer(), nullable=True))
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('incidents', 'on_scene_duration_seconds')
op.drop_column('incidents', 'travel_seconds_first_unit')
op.drop_column('incidents', 'turnout_seconds_first_unit')
op.drop_column('incidents', 'call_to_arrival_seconds')
op.drop_column('incidents', 'total_loss_currency')
op.drop_column('incidents', 'total_loss_amount')
op.drop_column('incidents', 'area_burned_ha')
op.drop_column('incidents', 'structures_destroyed')
op.drop_column('incidents', 'people_evacuated')
op.drop_column('incidents', 'people_rescued')
op.drop_column('incidents', 'responder_fatalities')
op.drop_column('incidents', 'responder_injuries')
op.drop_column('incidents', 'civilian_fatalities')
op.drop_column('incidents', 'civilian_injuries')
op.drop_column('incidents', 'country')
op.drop_column('incidents', 'state')
op.drop_column('incidents', 'city')
op.drop_column('incidents', 'incident_datetime')
op.drop_column('incidents', 'incident_category')
op.drop_column('incidents', 'incident_contract')
op.add_column('extractions', sa.Column('incident_contract', postgresql.JSON(astext_type=sa.Text()), autoincrement=False, nullable=True))
op.drop_column('extractions', 'partial_result')
# ### end Alembic commands ###
78 changes: 78 additions & 0 deletions alembic/versions/004_form_templates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"""form templates registry and pdf upload drafts

Revision ID: 004
Revises: 003
Create Date: 2026-08-10

Two tables, both new in the contract Layer 6 template work.

`form_templates` is the registry, keyed by `form_type` and distinct from the
legacy `template` table (int PK + uploaded PDF). Its `fields` JSON column holds
the TemplateField list, each with a nested `layout`. `form_type` stays a plain
VARCHAR rather than a Postgres enum, because jurisdictions register their own
form types and those are not part of the built-in FormType enum.

`template_uploads` holds the drafts behind the PDF authoring flow: the stored
blank PDF, its page geometry, and the fields commonforms detected. Rows here
are working state, not templates. Registering a template copies the edited
fields across and keeps only the `pdf_template_ref` pointing back.

Both JSON columns use sa.JSON for consistency with migrations 001-003 and for
the SQLite test harness.
"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa
import sqlmodel


# revision identifiers, used by Alembic.
revision: str = '004'
down_revision: Union[str, None] = '003'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('form_templates',
sa.Column('template_id', sa.Uuid(), nullable=False),
sa.Column('form_type', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.Column('display_name', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.Column('jurisdiction', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column('agency_type', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column('fields', sa.JSON(), nullable=False),
sa.Column('source_standard', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column('pdf_template_ref', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column('version', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.Column('status', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=False),
sa.Column('updated_at', sa.DateTime(), nullable=False),
sa.PrimaryKeyConstraint('template_id')
)
op.create_index(op.f('ix_form_templates_form_type'), 'form_templates', ['form_type'], unique=True)
op.create_table('template_uploads',
sa.Column('upload_id', sa.Uuid(), nullable=False),
sa.Column('status', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.Column('pdf_path', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.Column('pdf_template_ref', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.Column('original_filename', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column('page_count', sa.Integer(), nullable=False),
sa.Column('pages', sa.JSON(), nullable=False),
sa.Column('detected_fields', sa.JSON(), nullable=True),
sa.Column('detection_error', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column('job_id', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column('created_at', sa.DateTime(), nullable=False),
sa.Column('updated_at', sa.DateTime(), nullable=False),
sa.PrimaryKeyConstraint('upload_id')
)
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('template_uploads')
op.drop_index(op.f('ix_form_templates_form_type'), table_name='form_templates')
op.drop_table('form_templates')
# ### end Alembic commands ###
59 changes: 59 additions & 0 deletions alembic/versions/005_form_incident_template_batch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"""forms: key by template, require incident, group by batch, drop extract_id

Revision ID: 005
Revises: 004
Create Date: 2026-08-17

Form generation (contract Layer 3, #552) keys a form by which template filled
it and reaches the extraction through the incident rather than a direct link
(incidents already FK the extraction, so extract_id was a redundant hop).
Batching is a grouping key only — batch_id has no Batch table, batch status is
derived on the fly from the Form rows that share an id.

No route or repository writes a v1 Form row yet (form generation itself is
still unimplemented), so the forms table is empty in every environment and
the NOT NULL adds below are safe — there is no existing data to backfill.

FK constraints are named explicitly, matching Postgres' own default
`<table>_<column>_fkey` pattern, so downgrade can drop them by name. The same
naming_convention is handed to batch_alter_table so SQLite's reflect-and-
recreate path (needed for the incident_id nullable flip and the extract_id
drop, neither of which SQLite can ALTER in place) assigns identical names.
"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = '005'
down_revision: Union[str, None] = '004'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None

NAMING_CONVENTION = {"fk": "%(table_name)s_%(column_0_name)s_fkey"}


def upgrade() -> None:
with op.batch_alter_table('forms', naming_convention=NAMING_CONVENTION) as batch_op:
batch_op.add_column(sa.Column('template_id', sa.Uuid(), nullable=False))
batch_op.create_foreign_key(
'forms_template_id_fkey', 'form_templates', ['template_id'], ['template_id']
)
batch_op.add_column(sa.Column('batch_id', sa.Uuid(), nullable=True))
batch_op.drop_constraint('forms_extract_id_fkey', type_='foreignkey')
batch_op.drop_column('extract_id')
batch_op.alter_column('incident_id', existing_type=sa.Uuid(), nullable=False)


def downgrade() -> None:
with op.batch_alter_table('forms', naming_convention=NAMING_CONVENTION) as batch_op:
batch_op.alter_column('incident_id', existing_type=sa.Uuid(), nullable=True)
batch_op.add_column(sa.Column('extract_id', sa.Uuid(), nullable=False))
batch_op.create_foreign_key(
'forms_extract_id_fkey', 'extractions', ['extract_id'], ['extract_id']
)
batch_op.drop_constraint('forms_template_id_fkey', type_='foreignkey')
batch_op.drop_column('template_id')
batch_op.drop_column('batch_id')
35 changes: 35 additions & 0 deletions alembic/versions/006_incidents_crud_indexes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""incidents crud indexes

Revision ID: 006
Revises: 005
Create Date: 2026-08-22 06:49:34.422095

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa
import sqlmodel


# revision identifiers, used by Alembic.
revision: str = '006'
down_revision: Union[str, None] = '005'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_index('ix_incidents_live_datetime', 'incidents', ['deleted_at', 'incident_datetime'], unique=False)
op.create_index('ix_incidents_number_live', 'incidents', ['incident_number'], unique=True, postgresql_where=sa.text('incident_number IS NOT NULL AND deleted_at IS NULL'), sqlite_where=sa.text('incident_number IS NOT NULL AND deleted_at IS NULL'))
op.drop_column('incidents', 'incident_date')
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('incidents', sa.Column('incident_date', sa.DATE(), autoincrement=False, nullable=True))
op.drop_index('ix_incidents_number_live', table_name='incidents', postgresql_where=sa.text('incident_number IS NOT NULL AND deleted_at IS NULL'), sqlite_where=sa.text('incident_number IS NOT NULL AND deleted_at IS NULL'))
op.drop_index('ix_incidents_live_datetime', table_name='incidents')
# ### end Alembic commands ###
26 changes: 23 additions & 3 deletions app/api/router.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,33 @@
from fastapi import APIRouter

from app.api.routes import forms, input, jobs, system, templates, weather, zipcode
from app.api.routes import (
extraction,
form_generation,
forms,
form_templates,
incidents,
input,
jobs,
system,
weather,
zipcode,
)
from app.core.config import API_PREFIX

api_router = APIRouter()
api_router.include_router(templates.router, prefix=API_PREFIX)
api_router.include_router(form_templates.router, prefix=API_PREFIX)
api_router.include_router(forms.router, prefix=API_PREFIX)
# v1 form generation — same "/forms" prefix as the legacy router above, kept
# in a separate file/router rather than added to forms.py. Included AFTER
# `forms` on purpose: the legacy router's literal GET paths (/forms/models,
# /forms/submissions, ...) must be matched before this router's catch-all
# GET /forms/{form_id}, same reasoning form_templates.py uses for /pdf vs
# /{template_id} — otherwise "models"/"submissions" would be read as a form_id.
api_router.include_router(form_generation.router, prefix=API_PREFIX)
api_router.include_router(system.router, prefix=API_PREFIX)
api_router.include_router(jobs.router, prefix=API_PREFIX)
api_router.include_router(weather.router, prefix=API_PREFIX)
api_router.include_router(zipcode.router, prefix=API_PREFIX)
api_router.include_router(input.router, prefix=API_PREFIX)
api_router.include_router(input.router, prefix=API_PREFIX)
api_router.include_router(extraction.router, prefix=API_PREFIX)
api_router.include_router(incidents.router, prefix=API_PREFIX)
4 changes: 2 additions & 2 deletions app/api/routes/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from . import templates, forms
from . import form_templates, forms

__all__ = ["templates", "forms"]
__all__ = ["form_templates", "forms"]
Loading