Repository navigation
[17.0][MIG] ni_observation: Migration to 17.0 - #156
Merged
Merged
Conversation
wasud
force-pushed
the
17.0-mig-p1-observation
branch
from
October 14, 2026 01:39
66a1999 to
17b88a5
Compare
This was referenced Oct 14, 2026
wasud
force-pushed
the
17.0-mig-p1-observation
branch
from
October 16, 2026 02:27
d9cb19b to
f799211
Compare
2 tasks done
piruin
reviewed
Oct 19, 2026
piruin
left a comment
Contributor
There was a problem hiding this comment.
Review
No blockers.
Checked, OK
read_group→_read_group(..., ["__count"])reads the tuple results correctly (patient, encounter, type).- The
_compute_display_nameoverride inni_patientwith@api.depends("blood_group")works: Odoo merges the depends of every override, soni_patient'sdepends_contextkeys still apply. - The wizard domain fix (
parent_id→patient_id, string domains) is correct. - The encounter compute now assigns values instead of calling
write(). - The list widget is re-ported with field descriptors,
@odoo/owlimports,isNewanduseEffecton the edited record. - The latest-observation
[FIX]was done the epic's way: fixed on 16.0 in #163 (merged), then carried forward. - CI is green, and the series ends with
[IMP] pre-commit auto fixes+[MIG].
Minor
report/still usesSELECT DISTINCT ON … *, as noted in the PR body.
wasud
force-pushed
the
17.0-mig-p1-observation
branch
from
October 19, 2026 05:09
f799211 to
315d1f6
Compare
- Add search view for ref-range, ob-type - Remove graph stat btn on ob-sheet - Hide patient & encounter on ob-sheet if default is set
Took 16 minutes
Took 3 minutes
* [IMP] ni_device: Update required field * [IMP] ni_device: add devie_usage_log * [IMP] ni_community_care: update usage log views * [IMP] ni_community_care: update usage log views * [IMP] ni_careplan: multi company rule * [IMP] ni_community_care: update approval careplan report * [IMP] ni_community_care: update cron id for Create Backfill Approvals * [IMP] ni_community_care: improve approval report template to avoid printing reports with no data * [IMP] ni_observation: Add Observation wizard for better UX * [IMP] ni_observation: remove ni_observation_value_code.type_id use only type_ids * [IMP] ni_community_care: update approval_category_report_template * [FIX] ni_careplan: not deleted on form * [FIX] ni_careplan: resource created by careplan not check period_start * [IMP] ni_community_care: add pivot view * [IMP] ni_observation: add parent_id for observation category * [IMP] ni_observation: observation wizard action from patient * [FIX] ni_observation: error on select blood_abo * [FIX] ni_observation: invalid domain for blood_rh Took 16 minutes * [IMP] ni_community_care_attendance: optimize get_employee_dashboard * [IMP] ni_device: update manifest * [IMP] ni_device,ni_observation: update device logs * [IMP] ni_device: update device logs * [IMP] ni_observation,ni_device: update device logs * [IMP] ni_observation,ni_device: update device logs * [IMP] ni_device,ni_observation: update device usage * [IMP] ni_device,ni_observation: update device usage * [IMP] ni_device: update ni_device_usage_view_kanban re-direct to res_model form * [IMP] ni_device: add ni_device_definition * [IMP] ni_device: update ni_device_definition * [IMP] ni_device: update device_label_layout_template * [IMP] ni_device: add compute fields and update views * [IMP] ni_device : add tracking important fields, add report device lost workflow * [IMP] ni_device : add employee search by device name, identifier, serial_number * [FIX] ni_device : fix holder not updated when submitting request_hold * [IMP] ni_device: All text has been translated into English. * [IMP] ni_device: All text has been translated into English. * [IMP] ni_device: translated into Thai and add active_repair_state * [IMP] ni_device: translated into Thai * [IMP] ni_device: Update required field * [IMP] ni_device: add devie_usage_log * [IMP] ni_community_care: update usage log views * [IMP] ni_community_care: update usage log views * [IMP] ni_device: update manifest * [IMP] ni_observation,ni_device: update device logs * [IMP] ni_device,ni_observation: update device usage * [IMP] ni_device,ni_observation: update device usage * [IMP] ni_device: add ni_device_definition * [IMP] ni_device: update ni_device_definition * [IMP] ni_device: update ni_observation_sheet_view_form_inherit * [IMP] ni_device: rebased 16.0-device branch * [IMP] ni_device: Update from Thai to English. * [IMP] ni_device: update device usage log * [ADD] ni_community_care_device: add commu device to update ni_patient_view_form_simp * [IMP] ni_device: Update from Thai to English. * [IMP] ni_community_care: update device kanban * [IMP] ni_community_care: polish device views * [IMP] ni_device: Update from Thai to English. * [IMP] ni_device: Translate thai * [IMP] ni_device: update ni_device_usage_view_kanban * [IMP] ni_community_care: fix pre-commit failed * [IMP] ni_community_care_device: remove init models --------- Co-authored-by: Piruin P. <piruin.p@gmail.com> Co-authored-by: BesTinG <79839187+bestiing@users.noreply.github.com>
Use int(float(value)) so that strings like "42.5" are accepted and truncated to 42, instead of raising ValueError. Add unit tests for _inverse_value covering all value types. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… social history categories with reference ranges Adds 22 new observation types across lipid panel (CHOL, LDL, HDL, TG), CBC (WBC, RBC, Hb, Hct, PLT), kidney function (Cr, BUN, eGFR, UA), liver enzymes (ALT, AST, ALP), electrolytes (Na, K, Cl), GCS (exam), and smoking/alcohol status (social history). Includes 96 reference ranges with gender-specific splits where clinically relevant, plus 6 new UOM categories and units. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… unit tests
- Set body-weight and body-height as children of type_bmi so _eval_compute_types
resolves them via child_ids (consistent with the BP pattern)
- Apply textwrap.dedent + strip before safe_eval so multi-line / indented code
stored in XML text nodes evaluates without IndentationError
- Add TestComputeCode: 11 tests covering float/char results, update-on-write,
no-duplicate idempotency, empty-input skip, None result, missing assignment,
exception safety, and seeded BP/BMI integration tests
Adds a compute_code Text field on ni.observation.type that lets users write
Python expressions (via ace editor) to derive a type's value from its child
component observations — analogous to ir.cron's code field.
Evaluation logic lives in ObservationSheet._eval_compute_types(), triggered
after ni.observation create/write on value fields. The skip_compute_eval
context flag prevents recursion when writing back the computed result.
Seeds compute_code on type_bp ("SYS / DIA") and type_bmi as reference examples.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…de tests; link input observations as child_ids on computed observation
Replace fragile parent_id mutations on shared fixtures with child_ids in the
create call, and give each edge-case test its own isolated input type.
_eval_compute_types now sets child_ids on the computed ni.observation record
to the component observations used in the calculation. This lets callers verify
which inputs drove a given computed value (e.g. bp_s/bp_d for BP, weight/height
for BMI).
Also fixes three bugs in the partial ni.observation parent/child field definitions:
- ondelete="" → ondelete="set null"
- child_ids pointed to wrong model "ni.patient.observation" → "ni.observation"
- @api.depends("child_count") → @api.depends("child_ids")
- Missing _ in imports
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
type_body_weight and type_body_height referenced type_bmi via parent_id before it was defined, causing a forward-reference error on module load. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
parent_id/parent_path follow the same pattern already used by ni.observation.category and ni.condition.category, enabling real child_of/parent_of matching against coded observation values (e.g. ni_goal targets) instead of a flat set. Took 1 hour 49 minutes Took 15 minutes
…'s event/request id WorkflowMixin._to_workflow() wrote the parent record's own id into ni.workflow.event.parent_id / ni.workflow.request.parent_id, but those fields reference other ni.workflow.event/request rows, not the source model's own id. This either raised a foreign key violation or silently linked to an unrelated workflow row, depending on whether the id happened to collide with an existing workflow row. Surfaced via ni_observation: an observation type with a computed parent (e.g. Systolic/Diastolic Blood Pressure -> Blood Pressure) hit this as soon as both child values were saved, since ni.observation.sheet links the children to the newly computed parent via child_ids, which re-writes each child's parent_id and re-triggers the workflow mirror write. Fixes nirun-life#109. Also fixes ni_device's test_requires_supported_observation_type, which tried to clear a device's observation_type_ids via its definition + recompute, but _compute_from_definition only ever fills a device's observation_type_ids from a non-empty definition and never clears it.
`default=fields.Datetime.now()` (and, in ni_reception, the stdlib `fields.datetime.now()`) is evaluated once when the model class is defined, freezing every record's default to that one moment instead of the actual creation time. Pass the bare callable so it evaluates per record. Affected: ni_observation (observation wizard), ni_document_ref, ni_medication (suggest wizard), ni_reception, and ni_patient's ni.workflow.event.mixin (shared by every clinical event model: procedures, immunizations, medication dispenses, etc).
`ref_range__hba1c__HU` spanned 6.4-100.0 while `ref_range__hba1c__HH` spanned 7.0-100.0, so any HbA1c >= 7.0 matched both "Significantly High" and "Critical High" at once. Cap HU at 7.0 so it hands off to HH, matching the boundary-continuity pattern every other multi-tier range in this file follows.
The observation_ids editable tree relied on field-level context (default_sheet_id, default_patient_id, default_encounter_id, default_occurrence) to fill a manually-added line, but the web client only applies context defaults for fields declared in that tree's own arch. Declare them as invisible fields so a new line stays linked to the sheet/patient being edited.
The form had three inner groups inside a two-column outer group, so the
third one wrapped onto a second row and left the cell beside it empty - a
hole in the middle of the form with nothing to put in it.
Two columns now: what was measured on the left, who it was measured on -
and, for the layers that add them, with which device and where - on the
right.
The value row printed the number twice ("128.0 128.00 mmHg"): `value`
is the Char computed from the typed field beside it and had no modifier,
so both showed. It stays in the arch for the case where value_type is
empty, and for the inverse that writes the typed field back.
Occurrence joins the form, readonly once the reading belongs to a sheet -
_check_occurrence() puts the sheet's own back, so an edit there would be
silently undone. user_id is read from the sheet, so a reading opened on
its own still says who took it.
On small screens the x2many falls back to kanban, and the sheet only had an inline tree, so readings were cramped on phones. Inline kanban and form give each reading a card: numbers stack value over unit, text and choices get a full-width line clamped to 3 lines, and the type icon falls back per value type when none is set. Took 3 hours 23 minutes
The latest-observation views keep one row per patient (or encounter) and type with DISTINCT ON, ordered by occurrence only. When two observations of a type share an occurrence (created in the same transaction, for example by two questionnaires mapped to the same type), PostgreSQL may return either row. The patient and encounter forms then read a row that the next query no longer returns, and fail with "records ... cannot be found". Break the tie by id. Found by the Phase 1 data migration pilot (nirun-life#141); 16.0 has the same views.
wasud
force-pushed
the
17.0-mig-p1-observation
branch
from
October 21, 2026 01:40
315d1f6 to
7d4318b
Compare
This was referenced Oct 21, 2026
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Decisions to review
ob_section_and_note_one2manyis re-ported from coreaccount17section_and_note_fields_backend(registry descriptors,@odoo/owl,useEffecton the edited record), not patched from the 16 port. The Nirun parts are kept: category sections and the value columns.badge:ni_observationinstalls and validates on a fresh DB withoutweb_notebook_advance; only the counter on the Vital Signs/Laboratory tabs is missing. Kept as a soft dependency and noted in the README.ni.observation.wizard.encounter_idusedparent_id, which does not exist onni.encounter, through a Field object, so it never filtered. It now filters onpatient_id.What changed
ni_observationhistory replayed, then[IMP]pre-commit and[MIG] ni_observation: Migration to 17.0.name_get→_compute_display_nameon reference range and sheet (depends_context("show_occurrence"))._name_get()extension now has@api.depends("blood_group").read_group→_read_group(..., ["__count"])with the tuple results (patient, encounter, type).states="1"/"2"→invisibleexpressions.company_idadded to the line list, which 17 requires for thecheck_companydomain onencounter_id.write().attrs→ expressions (migrator).column_invisible.always_reloaddropped.company_idsits next to the group-restricted one.[False]asdefault_category_idswhen no category is selected. 17 tried to create a nameless category.fields.Datetime.now.<odoo noupdate>without<data>./.th.poregenerated, 16.0 translations merged back, UI terms filled (lab test names and units stay in English, as in Thai clinical use).Why
Part of #139 (P1-4, epic #131).
Migration notes
attrsin 11 view files.states=in the wizard;name_getandread_group;column_invisible;invisible="1"in a list hides only the cells; the column header still shows. The same issue was inni_coding,ni_patientandsurvey_grading, fixed in [17.0][MIG] ni_period, ni_identifier, ni_coding, partner_age, partner_gender, partner_religion, uom_alias: Migration to 17.0 #147–[19.0][MIG] ni_patient: Migration to 19.0 #155.check_companydomains in embedded lists, socompany_idmust be in the view.default_x_ids: [False]creates an empty record in 17.How tested
ni_observation), plus 57 withni_coding,ni_patient,ni_observation.show_occurrence, reference rangeType [low-high].pre-commitclean onni_observation(two eslint warnings that come from the coreaccountcode).Documentation
README.mdupdated (17.0, display names, list widget, D8 soft dependency)Notes for reviewer
Added after review started (P1-6 pilot, [MIG 19.0][P1-6] Data migration pilot: OpenUpgrade 16→17→18→19 on Phase 1 modules #141):
[FIX] ni_observation: pick the latest observation deterministically. The latest-observation views (ni.patient.observation,ni.encounter.observation) usedDISTINCT ON ... ORDER BY occurrence DESCwith no tie-breaker. Two observations of a type with the same occurrence made the patient and encounter forms fail ("records ... cannot be found") on the pilot DB. Nowoccurrence DESC, id DESC, withtests/test_latest_observation.py(fails without the fix). 16.0 has the same views.Fix (2026-10-14):
odoo-module-migrate17 rewrote Thai text in XML (comments,string,placeholder) as&#NNNN;entities, and prettier then split one of them with spaces. The Thai text is back as UTF-8.Stacked on [17.0][MIG] ni_patient: Migration to 17.0 #153 (P1-2 17.0), which is stacked on [17.0][MIG] ni_period, ni_identifier, ni_coding, partner_age, partner_gender, partner_religion, uom_alias: Migration to 17.0 #147. Merge those first.
Not changed yet: the SQL views in
report/still useSELECT DISTINCT ON … *. They work on 17; the explicit column list andSQL()come with 19.0.