Repository navigation
[17.0][MIG] ni_patient: Migration to 17.0 - #153
Conversation
a600dbb to
9588204
Compare
9588204 to
0af76bd
Compare
[FIX] ni_patient: lazy error [IMP] ni_patient: add 'user_id' for encounter_participant [IMP] ni_patient: Add chief complaint [IMP] ni_patient: Remove participant page [IMP] ni_patient: No duplicate encounter [IMP] ni_patient: use `color_picker` [IMP] ni_patient: lock state for CC [IMP] ni_patient: better CC
[IMP] ni_patient: rename `ni.encounter.cls` to `ni.encounter.class` [IMP] ni_patient: check datetime instead of date on every 'ni.patient.res' [IMP] ni_patient: priority value as char and show as badge on list view [MIG] ni_patient: cascade on delete Encounter [FIX] ni_patient: migration error [IMP] ni_patient_birthdate_est: `Medical` category
[IMP] ni_patient: implement create in batch [IMP] ni_patient: fix type
…d model -fix typo of priority's routine -discharge wizard call action_close() on encounter
[IMP] ni_patient: set name attribute for oe_chatter (xml) [IMP] ni_patient: location history as server action
…'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.
…irun-life#123) ## Why The departure wizard was reachable from exactly one view: the community care "simp" patient form, the only one carrying `js_class="ni_patient_form"`. Archive from anywhere else — the base form, any patient list — wrote `active=False` directly and lost the reason, date and note the wizard exists to collect. ## What - `js_class="ni_patient_form"` on the base patient form, `js_class="ni_patient_list"` on the base tree - New `PatientListController` so a multi-selection archives through the wizard too - Wizard takes `patient_ids` instead of `patient_id` and writes one reason set to every selected patient - One patient still renders as the big heading; several render as tags on a normal field label - `toggle_active` / `no_wizard` removed — nothing ever read `no_wizard`, and `write(active=False)` does the same work ## Deploy order Ships with nirun-life/nirun-dop#13, which imports `PatientListController` from this branch. **This repo must go out first** or the community care patient list fails to register its view type. ## Testing - `ni_patient/tests/test_ni_patient_archive_wizard.py` covers both the single and multi cases - Full `ni_patient` suite on a scratch DB: `0 failed, 0 error(s) of 20 tests` - Verified server-side: rendered arch carries both `js_class` values, `default_patient_ids` normalises to `Command.SET`, and the Thai field label resolves to `ผู้รับบริการ` - Not yet clicked through in a browser — worth one pass on the list and the form --------- Co-authored-by: Nutcha <nutcha.noonmomo@gmail.com>
…e#124) `ni.location._name_search` matched on `display_name`, which is neither stored nor given a search method. The ORM logs `Non-stored field ... cannot be searched` and quietly turns that leaf into `TRUE`, so every location autocomplete — and every `('<m2o to a location>', 'ilike', ...)` leaf — returned the whole table. Typing a community name into the house map's search bar brought back all five communities and, through them, every house in the database. ### What changes The override goes away. `_rec_names_search = ["name", "alias"]` states the same thing as a class attribute, and core's `_name_search` (`odoo/models.py:1633-1666`) does the rest — the same aggregator on `NEGATIVE_TERM_OPERATORS`, the same leaf shape, plus dotted paths, `convert_to_write` with a `ValueError` skip, and a warning rather than a `[None]` leaf when `_rec_name` is missing. Net -25 lines. ### Scope Nothing in the codebase calls `name_search` directly, so the change is confined to autocompletes and `ilike` leaves, which now filter instead of returning everything. Opening a dropdown without typing still lists all locations — core's `not (name == '' and operator in ('like', 'ilike'))` guard skips the domain entirely. No model inheriting `ni.location` overrides `_name_search`, so nothing resolves `super()` through the deleted method. `ni.location.commu` declares its own `_rec_names_search = ["name", "code"]`; it needs `"alias"` added there if community aliases should stay matchable. ### Tests `ni_patient/tests/test_ni_location_name_search.py`, two cases: `ilike` filters instead of matching everything, and `alias` is still matched. Both scope their `name_search` to the records they create — unscoped, the pre-fix `TRUE` leaf returns an arbitrary 100 rows that need not include the others, and the assertion would pass against the bug it guards. Verified they fail against the original bug — `_rec_names_search = ["display_name", "alias"]` reproduces it: ``` FAIL: test_ilike_filters_instead_of_matching_everything AssertionError: ni.location(22, 23, 24) != ni.location(22,) FAIL: test_alias_is_still_matched AssertionError: ni.location(22, 23, 24) != ni.location(23,) ``` `ni_patient` suite: 20 tests, 0 failed. --------- Co-authored-by: Nutcha <nutcha.noonmomo@gmail.com>
ni.encounter previously only received references from other resources' workflow events, never producing its own. Since its state selection is incompatible with ni.workflow.event.mixin, write to ni.workflow.event directly instead of inheriting the mixin, so start/discharge/cancel transitions show up in the patient timeline. Took 12 minutes
Encounter form gains a "Workflow Timeline" action-menu entry, alongside Location/Participant History, opening ni.workflow.line filtered to that encounter. Also default-groups the generic timeline by date, adds a company filter to its searchpanel, and drops the unused static/src/views/*.xml asset glob (no such templates exist). th.po gains the reference line the new action's name field needs to pick up the existing translation, and fills the previously blank encounter start-date validation message. Took 17 minutes
`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).
Odoo's view validator warns on every <i class="fa ..."> and icon button without a title, since screen readers have nothing to announce. The titles name what the icon stands for (Occurrence, Patient, Encounter, Location, ...) so they double as tooltips. Took 4 minutes
0af76bd to
8b7a78f
Compare
piruin
left a comment
There was a problem hiding this comment.
Review
Fix before merge: the private-address restore misses some masked columns.
OpenUpgrade 17 (base/17.0.1.3/pre-migration.py, _handle_partner_private_type) overwrites these columns with *****: street, street2, city, zip, vat, function, phone, mobile, email, website, comment. It also clears country_id and state_id.
migrations/17.0.1.0.0/post-migration.py doesn't restore vat, function, website or comment, so those stay ***** on the restored patient addresses. comment (the address notes) is the one most likely to hold real data. Please add the four columns to the SET clause.
The migration snapshot (#143) doesn't hash other_address_id fields, so it would not catch this. The "verified" claim rests on a manual check only.
Minor
tests/test_ni_coding_default_views.pylives inni_patientbut testsni_codingbehaviour.
Checked, OK
- Each of the 25 field-level
states=locks from 16.0 that is still on the encounter form now has an equivalentreadonly=there. The other three (name,location_history_ids,participant_ids) aren't on any form. - The
privatepage name on the patient form is kept, so theni_related_personxpath still matches. _compute_display_namehas the rightdepends_contextkeys,_rec_names_searchis set, andres.partner._name_searchuses the 17 signature.- The discharge wizard uses a computed domain field instead of returning a domain from the onchange.
- CI is green, and the commit series ends with
[IMP] pre-commit auto fixes+[MIG].
Note: #154 and #155 replay this branch, so any code change here needs to be replayed forward (except the 17.0 migration script, which exists only on 17.0).
8b7a78f to
44b8bc1
Compare
|
Thanks. Fixed in the
The 17.0 observation and questionnaire stacks were rebased on top; their content is unchanged. |
Decisions to review
privatepartners into contacts and overwrites their address, phone, email, VAT, job position, website and notes with*****(and clears country/state); the originals survive only in itsou_res_partner_privatetable.migrations/17.0.1.0.0/post-migration.pyrestores every masked column of the patient/encounter "other addresses" (street,street2,city,zip,state_id,country_id,phone,mobile,email,vat,function,website,comment) from that copy and sets them totype='other'. Checked by hand on a real OpenUpgrade 16→17 run (the patient's address comes back complete, unrelated private partners stay masked), plus a seeded check in a rolled-back transaction forvat/function/website/comment, since that run had no data in them. The migration snapshot ([16.0][ADD] tools: migration data snapshot script #143) does not hashother_address_idfields, so it would not catch this.ni_patient.res_partner_view_form_addressreplacesbase.res_partner_view_form_private(deprecated in 17, removed in 19).*.esm.jsto match the OCA eslint config, so downstream imports change to@ni_patient/views/list_view.esm.What changed
ni_patienthistory replayed, then[IMP]pre-commit and[MIG] ni_patient: Migration to 17.0.ni.patient._rec_name = "name", so patients display by name, not HN._compute_display_namewithdepends_contexton patient, encounter and location;_name_get()kept as the extension seam forni_observation._rec_names_searchon patient and encounter;res.partner._name_searchuses the new signature.type='other'domains and form context, compact address form, post-migration.getStaticActionMenuItems()replacesgetActionMenuItems().@odoo/owlimport and_timport.states=moved into the form asreadonly="state ..."(25 fields);ni.workflowintent/priority losestates=(documented for downstream forms).discharge_disposition_domaininstead.quick_create.file_path;from odoo import Command.write()inside an onchange.test_ni_patient_display_name.py(D1)test_ni_patient_address.py(D2)ni_coding/tests/test_ni_coding_default_views.py([MIG 19.0][P1-1] Foundation: ni_period, ni_identifier, ni_coding, partner_age, partner_gender, partner_religion, uom_alias #136 acceptance; lives inni_coding, the module it tests)th.poregenerated; translations dropped by the export restored from 16.0.Why
Part of #137 (P1-2, epic #131).
Migration notes
attrsin 16 view files.states=(fields, groups).name_get/_name_search, private partners, JS.ni_patientinstalled becauseni_patient_portal_templates.xmlreadsencounter.performer_id(ani_practitionerfield). This already happens on 16.0, so it is not fixed here; it belongs in P0-4 ([MIG 19.0][P0-4][FIX] Pre-existing bugs found during the 19.0 migration scan (16.0) #135).How tested
type='other';Form);/my/homeand/my/patients.pre-commitclean onni_patient.Documentation
README.mdupdated (display names, addresses, encounter locking, JS seam, tests)Notes for reviewer
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.invisible="1"on a list field only hides the cells, so the column header still shows. Hidden list fields now usecolumn_invisible="1". Found in the browser check ofni_observation([MIG 19.0][P1-4] ni_observation #139).