Skip to content

[17.0][FIX] ni_patient, ni_observation, ni_questionnaire: forward-port of the 16.0 fixes - #182

Merged
piruin merged 6 commits into
nirun-life:17.0from
wasud:17.0-fwd-p1-fixes
Oct 30, 2026
Merged

piruin merged 6 commits into
nirun-life:17.0from
wasud:17.0-fwd-p1-fixes

Conversation

@wasud

@wasud wasud commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Refs #181 · Forward-port of #166, #176, #177 (16.0) · Epic #131

Summary (TH)

forward-port fix และ PERF ของ 16.0 ที่ merge หลัง stack Phase 1 มาที่ 17.0 สำหรับ ni_patient, ni_observation, ni_questionnaire (5 commits, cherry-pick จาก 16.0) ส่วน index message_main_attachment_id (item 5 บางส่วน และ item 6 ทั้งหมด) ไม่ได้ port เพราะตั้งแต่ 17.0 field นี้ไม่มีบน ni.patient, res.partner, survey.user_input แล้ว

Changes

16.0 commit Module Change Version
95ba2b1b ni_patient check_origin_date raises ValidationError, compares dates in the user's timezone; "Until" filter on period_end; Error Entry no longer archives the patient; 2 new test files 17.0.1.0.2
d6e53ef3 ni_observation _compute_observation uses rec.id; category parent_id ondelete="set null" 17.0.1.0.2
c8b6aff5 ni_observation latest-observation views use NOT EXISTS; README; tests (same)
13078601 ni_questionnaire index=True on survey_response_id 17.0.1.0.1
4ce40396 ni_patient btree_not_null index on ir.attachment.original_id only (same)
e7d9c3d4 ni_questionnaire not ported: survey.user_input has no message_main_attachment_id since 17.0 —
(new) ni_observation _compute_history uses rec and in: reading several observations gave each one the history of all their types; on 17+ the =-with-list domain logs a warning that fails CI. New test_observation_history.py. Same bug on 16.0 (same as above)

Each commit keeps the 16.0 subject and body plus (cherry picked from commit …).

Adapted for 17.0:

  • none beyond the manifest versions and README wrapping (17.0 READMEs wrap at 88).

Decisions to review

  • Items 5 and 6: only the original_id index; see the decision record on [MIG 19.0][P1-8] Forward-port the 16.0 fixes merged after the Phase 1 stacks to 17.0/18.0/19.0 #181. The orphan message_main_attachment_id columns stay on production after OpenUpgrade (with their FK and the hand-made indexes), so attachment deletes stay fast; dropping them is P6 cleanup.
  • ni_questionnaire README names the index ni_observation__survey_response_id_index (the name Odoo generates), not ni_observation_survey_response_id_index as on 16.0.

How tested

  • Fresh 17.0 DB with demo, -i ni_patient,ni_observation,ni_questionnaire --test-tags /ni_patient,/ni_observation,/ni_questionnaire: 0 failed, 0 errors of 108 tests (includes test_ni_encounter_entered_in_error.py, test_ni_encounter_origin_date.py, test_latest_observation.py).
  • ir_attachment__original_id_index and ni_observation__survey_response_id_index exist after install.
  • pre-commit clean on the changed files.
  • OCB: CI.

wasud and others added 5 commits October 29, 2026 15:11
…ntry

check_origin_date raised the translated message itself, a plain string, so
setting a transfer date without a transfer source failed with "exceptions must
derive from BaseException" instead of a validation error. It also compared the
transfer date (a Date) with the encounter start (a Datetime), which fails with
a TypeError on every encounter that has both, and on encounters without a start.
Raise ValidationError, and compare the transfer date with the start date in
the user's timezone, skipping the check when the encounter has no start.

The encounter search filter "Until" filtered on period_start; use period_end.

action_entered_in_error() wrote active=False. ni.encounter has no active field
of its own and inherits ni.patient.active through _inherits, so marking an
encounter as an error entry archived the patient. The state alone already marks
the encounter inactive (ENCOUNTER_INACTIVE_STATE).

Tests cover the transfer date and Error Entry.

Refs: nirun-life#135
(cherry picked from commit 95ba2b1)
…ondelete

ni.observation.report._compute_observation browsed self.id inside the loop, so
reading observation_id or the history of several latest rows at once (a list,
an export) raised "Expected singleton". Use rec.id. The test reads two rows of
the patient's latest observations together.

ni.observation.category.parent_id had ondelete="", which is not a valid
value. Set "set null", Odoo's default for a nullable Many2one and what the
column already used, so the database does not change.

Refs: nirun-life#135
(cherry picked from commit d6e53ef)
PostgreSQL pushes a WHERE clause into a DISTINCT ON subquery only when
it uses the DISTINCT ON columns. The ORM reads these views by id and
searches them by survey_response_id, so every call rebuilt the view
from the whole ni_observation table (up to ~100 s per read on
production). The NOT EXISTS form lets the planner start from the
primary key and anti-join through the (key, type_id, occurrence DESC,
id) indexes.

The anti-join cannot group NULLs the way DISTINCT ON does, so rows
without type_id or occurrence are left out, and the encounter view
leaves out observations without an encounter. Every caller filters
the encounter view by encounter_id, and the report model already
requires type_id.

Fixes nirun-life#175

(cherry picked from commit c8b6aff)
The latest-observation views are searched by survey_response_id about
a thousand times per tuning window. The index name matches the one
already created on production, so the upgrade leaves it in place.

Fixes nirun-life#175

(cherry picked from commit 1307860)

Forward-port: the README names the index as Odoo generates it,
ni_observation__survey_response_id_index.

Refs: nirun-life#181
Deleting an ir.attachment checks every ON DELETE SET NULL foreign key
that points at it. Without an index on message_main_attachment_id
(ni.patient, res.partner) and ir.attachment.original_id, each check
scans the whole table, which made a single delete take ~141 s on
production.

The btree_not_null field indexes generate the same names as the
indexes already created by hand on production, so -u is a no-op there.

Part of nirun-life#174

(cherry picked from commit 4ce4039)

Forward-port: only the ir.attachment.original_id index. Since 17.0,
message_main_attachment_id is defined by mail.thread.main.attachment,
which ni.patient and res.partner do not inherit, so the field does not
exist on these models.

Refs: nirun-life#181
_compute_history searched with self.patient_id and self.type_id inside
the loop, so reading the history of several observations at once (the
latest-observation list, an export) gave every row the history of all
their types together. On 17.0 and later the domain also compared
type_id with a list using "=", which logs a warning that fails the
test run. Use rec and "in".

The same bug is on 16.0.

Refs: nirun-life#181
@piruin
piruin merged commit d35ce45 into nirun-life:17.0 Oct 30, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants