fix(drims): DRIMS issues and improvements (#651)#224
Conversation
- #967: require beneficiary_count via the view (asterisk + pre-save check) - #961: auto-create stock.lot from donation_line.lot_number on action_stock, with friendly UserErrors for missing-lot + serial-qty>1; expose Lot/Batch + Expiry Date columns by default on donation items - #964: fall back to quantity_pledged when quantity_received is 0; relax wizard equality check to splits-only so a single line is treated as the user reporting the final received quantity - #968: hide New + Delete on the DRIMS Dispatches list via a primary-mode inherited view pinned to the action - #1026: wire the donation form's Inspect button to action_open_inspection_wizard instead of the raw action_inspect state-flip
The form view used widget="badge" which rendered priority_id as a read-only colored pill with no input control. Drop the badge widget (and the decoration-* attributes that only render under badge) so the field becomes a normal Many2one dropdown. List + kanban views keep widget="badge" for compact display.
…t (#966) Reject button on the request form called action_reject directly with no parameter, leaving rejection_reason empty — the audit trail lost the rationale. Adds a single-record reject wizard with a required reason field; the form button now opens the wizard, which writes the reason and invokes action_reject. A red banner above the title surfaces the reason on rejected requests. - New spp.drims.request.reject.wizard TransientModel + form view - New action_open_reject_wizard on spp.drims.request (guards approval state, raises on non-pending requests) - Reject button wired to the wizard; confirm dialog removed since the wizard handles confirmation - ACL for approver + manager roles - 4 new tests cover wizard action, only-pending guard, happy path, and blank-reason rejection
OP#967 — Estimated Beneficiaries Reached field now visually marks itself as required when value is 0. Odoo 19's _checkValidity (record.js:430) explicitly skips boolean/float/integer/monetary types from required-empty validation, so a required Integer with value 0 never gets the o_field_invalid class or the asterisk on its label. The model-side button_validate check rejects 0 on save but the form is silent until then. Adds a reusable 'integer_positive_required' field widget to spp_base_common. It plugs into Odoo's visual-feedback pipeline via the field config's isValid hook (fieldVisualFeedback calls field.isValid BEFORE record.isFieldInvalid). Returns false when value <= 0 AND the required modifier evaluates true, which adds o_field_invalid → pink highlight + asterisk on the label. Any module can opt in: widget="integer_positive_required". spp_drims uses it on beneficiary_count, with the same required="drims_type == 'request_dispatch'" modifier as beneficiary_area_id. OP#968 — Form-toolbar New button now hidden when opening a dispatch picking from the DRIMS Dispatches action. The earlier round only set create="0" on the list view; Odoo 19's form view ignores list-level create attributes for the toolbar button. Action-context 'create': False is also unreliable in Odoo 19. spp_base_common already exposes a hideFormCreateButton flag via its custom_list_create_template.xml — set it on a FormController instance to skip the New button. New patch in spp_drims sets the flag when the form is opened for stock.picking with the dispatch action's context key (default_drims_type=request_dispatch). The standard stock.picking form on Inventory > Operations is unaffected because the discriminator is the context, not the model. Also adds spp_base_common as an explicit dep of spp_drims (was transitive via other modules).
…MS pickings (#970) The dispatch form already exposes a DRIMS-specific Print Waybill (via spp_drims.action_report_drims_waybill) and Create Return (via the DRIMS return wizard) in the header. The standard stock module's Print + Return buttons stayed visible alongside them, producing visible duplicates that confused users. Added three xpath rules to spp_drims's view_picking_form_drims that extend the existing 'invisible' clauses on the standard buttons with `or drims_type_id`, so they hide on any picking carrying a DRIMS type. Standard buttons stay untouched on non-DRIMS pickings. The action-button names (e.g. %(action_report_delivery)d) get resolved to numeric IDs at view-parse time and xpath cannot match them by name. Used data-hotkey + contains(@invisible, 'done') as the discriminator instead.
…se error (#970) Odoo's view-loader runs the %(xmlid)d resolution regex over the arch_db string before storing it, and the regex does not skip XML comments. The previous comment in view_picking_form_drims contained the literal %(action_report_delivery)d sequence, which Odoo interpreted as a real reference and tried to resolve as spp_drims.action_report_delivery — that xmlid lives in the stock module, not spp_drims, so module upgrade failed with: ValueError: External ID not found in the system: spp_drims.action_report_delivery Rewrote the comment to describe the sigil in prose instead of including the literal character sequence.
… for Dispatch (#969) Users couldn't sort approved requests by what's needed next — there was no visual separation between requests waiting for allocation vs. those waiting for dispatch. The states already existed in the state-machine (approved → allocated → dispatched) but were exposed under the same generic labels as the underlying codes. Changes: - vocabulary_codes.xml: rename display strings on two existing codes — 'approved' → 'Ready for Allocation', 'allocated' → 'Ready for Dispatch'. Wrapped in <data noupdate="0"> so the rename propagates on subsequent module upgrades (the parent element has noupdate=1). - request_views.xml list view: new Fulfillment State badge column showing the relabeled state_id, with decoration-info for pre-allocation states, decoration-success for post-allocation, decoration-danger for rejected/cancelled. Optional='show' so it appears by default. - request_views.xml search view: two new named filters — 'Ready for Allocation' (approval_state='approved' AND state not past allocated) and 'Ready for Dispatch' (state='allocated'). Also added the fulfillment state to the searchpanel (with counters) and a 'Fulfillment State' group-by.
…only (#962) Donation lines' 'Received' quantity was editable during BOTH 'announced' and 'received' states. That allowed users to enter a received quantity at pledge/announcement time, which then silently flowed through action_mark_received (the auto-copy only fills zero values) and drove the stock picking with pre-entered values the user hadn't necessarily confirmed. Tightens the view-level readonly to permit edits only in the 'received' state. The auto-copy of pledged → received during the announced→received transition is unaffected because that path writes the line via Python, not via the field. Out of scope: edits in the 'received' state after the stock picking exists still don't update the picking — that picking-sync question needs a separate decision and should be tracked as a follow-up.
…arehouse form (#959) The DRIMS warehouse form was missing the documented tier field (docs/DATA_MODEL.md:185-195 specifies Selection central/regional/mobile) and never actually showed the gis_location point even though the model field existed. - models/stock_warehouse.py: new tier Selection(central/regional/mobile), indexed for filter performance. - views/stock_warehouse_views.xml form: replace the existing position='inside' xpath on the standard notebook with a new un-gated notebook anchored before it. The standard <notebook> on stock.view_warehouse is groups='stock.group_adv_location, stock.group_stock_multi_warehouses', so attaching the DRIMS Configuration page inside it hides the entire page for admins who don't hold those advanced inventory roles — which was exactly what was happening here (existing capacity / area / emergency contact fields were also invisible). Page layout: Active Response at the top, full-width (field carries colspan=2 to span both sub-columns of the group; colspan on the group itself would be a no-op at page level). Below that, two-column row of Disaster Response Configuration (incl. tier + drims_capacity + area_id + gis_location with the geo_point widget) and Emergency Contact. - views/stock_warehouse_views.xml list: surfaces tier as an optional badge column. - views/stock_warehouse_views.xml search: tier search field, three preset filters (Central / Regional / Mobile), and a Tier group-by. - views/stock_warehouse_views.xml GIS: new <gis> view for stock.warehouse — the geo_point widget on the form requires one (without it the form errors with 'No GIS view defined for the model stock.warehouse'). Plus the matching spp.gis.data.layer (warehouse location point) and spp.gis.raster.layer (OSM tile base) records — without the raster layer the GIS view errors with 'No raster layer for view stock.warehouse.gis.drims'. 228 spp_drims tests pass.
…e (#960)
The statusbar widget was configured with options="{'clickable': '1'}"
which let users click a state badge to fire the corresponding write to
state_id directly. That bypasses the header buttons (Mark Received /
Inspect Items / Stock Items / Reject / Cancel) which run validation,
trigger side-effects (auto-create stock picking on receive, open the
inspection wizard, etc.), and enforce the state-machine transitions.
Dropping the clickable option turns the statusbar into a read-only
display indicator and forces state changes through the proper actions.
…Allocation (#1032) When a user allocated an approved request against a warehouse with zero available stock, _allocate_stock_fifo was a no-op (0 across all lines) but action_allocate still advanced the request to allocated (Ready for Dispatch). The Create Dispatch button then became available against a request with nothing allocated, allowing an empty / invalid stock picking to be created. Same path through the allocation-preview wizard: action_confirm_allocation would write 0 across all request lines and still advance state. Both paths now raise a UserError with the message: "No stock available in the selected warehouse. Please ensure the source warehouse has sufficient items before allocating." when the total allocation is 0. The request state stays at approved (Ready for Allocation) so the user can pick a different warehouse. Partial allocation (some lines have stock, others don't) is still allowed — the check is total <= 0. Updated test_allocate_with_warehouse to seed stock first (otherwise it would now fail). Added test_allocate_blocked_when_warehouse_has_no_stock and test_confirm_blocked_when_zero_stock for the negative cases. 230 spp_drims tests pass.
…s (#963) Replace the read-only-list + per-item popup flow with a single inline-editable list. Condition and Action are picked directly on each row; "+ Add split" creates an indented child row for products with mixed conditions. The parent row of a split carries no decision — its qty mirrors the running sum of its children — and the old InspectionItemWizard / popup view are removed entirely.
Each Create Dispatch call now creates a picking covering only the not-yet-dispatched allocated balance (quantity_allocated - quantity_dispatched) per line. The request stays in Ready for Dispatch until every line reaches quantity_dispatched >= quantity_requested, at which point it advances to Dispatched. The Allocate Stock button stays available while the request is allocated so the operator can top up the allocation between dispatches as more stock arrives.
…1030) action_stock now cancels moves whose donation line carries a disposition of return / dispose / quarantine before validating the receipt picking, so damaged or returnable units never enter usable inventory. A sticky warning notification lists the excluded units. If every move on a picking is excluded, the picking is cancelled outright instead of validated empty. stock.move._prepare_merge_moves_distinct_fields now keeps drims_donation_line_id and drims_request_line_id distinct so Odoo's automatic move-merge does not collapse multi-line donations of the same product into one move (which would have lost the per-disposition link). Also fixes a related grouping bug in the inspection wizard's confirm step: two separate donation lines for the same product were being treated as splits of each other. Confirm now groups wizard lines by donation_line_id, so independent donation lines aren't subject to the split-totals safety net.
QA round 2 feedback addressed: - Custom OWL Float widget (qty_split_progress) renders parent rows as "X / Y" inside a single Qty column — X green when matched, red otherwise — driven by a live read of children from the wizard's One2many. Child rows keep the standard editable float; a useEffect mirrors the running sum onto the parent record via record.update so the parent's display reactively refreshes on every child qty edit. - Condition/Action become read-only on split parents; the dropdown caret + "Select" affordance are now always visible on editable cells and hidden on read-only split parents. - Children quantities are clamped so the running total never exceeds the donation line's received quantity. - _order on the wizard line model groups parent + children together with parent first; child rows get an indent + "↳" arrow prefix. - Expected column value hidden on child rows (parent already shows it). - "+ Add split" hidden when the running split matches expected (uses CSS :has() against the widget's own .text-success render so the gate reacts live without depending on Odoo's editable-list cross-record reactivity). - Group/field colspan tweaks so the table and notes fill the form width. All ListRenderer / widget / view changes are scoped to the inspection wizard list via the o_drims_inspection_list class.
- "+ Add split" now creates the new split child with qty=0 instead of
pre-filling the remaining capacity. The operator has to enter the split
amount explicitly, which avoids the "added a split but forgot to fill it"
footgun.
- "+ Add split" is hidden whenever the parent already has a 0-qty child
pending, via a dynamically-applied o_split_parent_has_zero row class.
The operator must fill the new split before opening another.
- Condition + Action dropdowns now use options="{'no_create': True,
'no_open': True}" so the external-link arrow is suppressed (no extra
affordance to confuse the operator).
…30 r2) The round 1 implementation relied on per-move drims_donation_line_id to decide which moves to cancel. That fails whenever Odoo's standard move-merge logic collapses multiple donation lines for the same product into a single move — the surviving move references only one line, so the others' dispositions are invisible. action_stock now computes the accept vs non-accept received quantities per product directly from the donation lines, then walks the picking's moves for each affected product, keeping moves up to the per-product accept total and cancelling/reducing the excess. Works whether the moves got merged or not. Adds a regression test covering the bug screenshot scenario: two donation lines for the same product with partial receive (200 + 300) and mixed Accept/Return dispositions — only the 200 accepted units should land in the warehouse.
Adds two stored fields on the inspection wizard — `can_confirm` (Boolean) and `confirm_message` (Text) — and wires the qty widget's useEffect to recompute them from live line data on every row edit. Three gating conditions are evaluated together and the failed-reason messages stack, so the operator sees the union of everything still blocking Confirm: - C1: Parent rows with splits must have their children sum to the expected quantity. - C2: Every non-parent line must have both Condition and Action set. - C3: No split child may have qty 0. When can_confirm is False the form swaps the primary "Confirm Inspection" button for a disabled-looking placeholder and renders the confirm_message in a yellow warning alert above the items list. As soon as the conditions clear, the message hides and the active button comes back. Server-side validation in action_confirm_inspection stays in place as a final safety net.
Round 1 of the partial-dispatch work let the operator click Allocate Stock against the same warehouse repeatedly, ratcheting up quantity_allocated until it matched quantity_requested while the physical stock hadn't moved. Cause: _get_available_quantity returned the raw stock.quant on-hand and ignored other DRIMS request lines that had already been allocated against the same warehouse but not yet dispatched. action_confirm_allocation only consumes stock at dispatch time (it sets quantity_allocated on the request line but doesn't move quants), so the wizard needs to deduct those in-flight allocations itself. Net available now equals: sum(quant.quantity - quant.reserved_quantity) - sum(max(0, line.quantity_allocated - line.quantity_dispatched)) across all request lines pointing to this warehouse for this product. Floored at 0. Re-opening the wizard after a partial allocation now correctly shows available=0 / shortfall=remaining, and confirming an empty allocation raises the existing "No stock available" UserError. Adds a regression test reproducing the QA repro: 1000 physical units, request for 5000, first allocation consumes the 1000 → second wizard open must show available=0, to_allocate=0, and confirming must raise without bumping quantity_allocated.
When validating a dispatch picking without the required beneficiary fields,
the error toast now spells out where to fill them in ("under the DRIMS
tab") so the operator doesn't have to hunt for the field. Same hint added
to both the beneficiary_count and beneficiary_area_id guards.
The Stock Items button on a donation returns a display_notification action when non-accept dispositions are excluded. Without a `next` step the Odoo client renders the toast but doesn't re-read the underlying record, so the operator has to manually refresh to see the state flip to "Stocked" and the picking smart-button update. Add `next: ir.actions.act_window_close` to the notification params (same pattern the allocation preview wizard already uses), which closes the action chain and lets the donation form re-read once the toast is shown.
… (#963)
When inspectors mark every line as Return / Dispose / Quarantine the donation
has nothing left to stock, but the **Stock Items** button still showed in the
header — clicking it just cancelled every move and transitioned to ``stocked``
with no inventory change, which read as a bug to reviewers.
Compute a non-stored Boolean ``has_acceptable_items`` on ``spp.drims.donation``
that returns True when at least one line has ``quantity_received > 0`` and a
disposition outside the ``("return", "dispose", "quarantine")`` set (factored
out as the module-level constant ``NON_ACCEPT_DISPOSITIONS`` and reused by the
existing ``_exclude_non_accept_moves``). A line with no disposition yet is
treated as acceptable so Stock stays available mid-inspection.
In the donation form:
- ``Stock Items`` is now ``invisible="state != 'inspected' or not has_acceptable_items"``.
- A new info alert above the sheet ("Nothing to Stock. … Click Reject to close
this donation.") shows on the inverse condition so the user knows why Stock
disappeared and what action to take instead.
- ``Reject`` is unchanged — visible whenever ``state == 'inspected'``.
Two unit tests lock the field's behaviour (all non-accept → False, one accept
mixed with non-accept → True).
…ments # Conflicts: # spp_base_common/__manifest__.py
There was a problem hiding this comment.
Code Review
This pull request introduces several enhancements to the DRIMS module, including a new inline-editable single-screen flow for the donation inspection wizard, support for partial dispatches, a single-record request rejection wizard to capture rejection reasons, and warehouse tiering with GIS mapping support. It also prevents empty stock allocations and excludes non-acceptable items from entering usable inventory. The reviewer feedback highlights critical improvements: guarding against undefined fields in the new integer widget to prevent runtime crashes, querying remaining split lines before unlinking to avoid Odoo cache issues, removing eager quantity clamping in the onchange method to improve user experience, and using robust XML ID-based XPath expressions instead of fragile hotkey attributes.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| const required = evaluateBooleanExpr( | ||
| fieldInfo.required, | ||
| record.evalContextWithVirtualIds | ||
| ); |
There was a problem hiding this comment.
If fieldInfo.required is not defined on the field (which is common for optional fields), passing undefined to evaluateBooleanExpr will cause a runtime JavaScript error and crash the form view. We should guard this evaluation by checking if fieldInfo.required is present.
const required = fieldInfo.required
? evaluateBooleanExpr(fieldInfo.required, record.evalContextWithVirtualIds)
: false;| def action_remove_split(self): | ||
| """Remove a split child line and refresh the wizard.""" | ||
| self.ensure_one() | ||
| if not self.is_split: | ||
| raise UserError(_("Only split lines can be removed this way.")) | ||
| wizard_id = self.wizard_id.id | ||
| root_line = self.parent_line_id | ||
| self.unlink() | ||
|
|
||
| remaining_children = root_line.wizard_id.line_ids.filtered(lambda line: line.parent_line_id == root_line) | ||
| if not remaining_children: | ||
| # Reset parent back to the full expected quantity and clear the | ||
| # split flag so the row reverts to a normal (editable) row. | ||
| root_line.quantity = root_line.quantity_expected | ||
| root_line.has_splits = False | ||
| else: | ||
| self._refresh_parent_quantity(root_line) | ||
|
|
||
| if self.quantity < 0: | ||
| raise UserError(_("Quantity cannot be negative.")) | ||
|
|
||
| if self.remaining_qty <= 0: | ||
| raise UserError(_("No remaining quantity to split. Adjust the quantity first.")) | ||
|
|
||
| # Update current line | ||
| self.inspection_line_id.write( | ||
| { | ||
| "quantity": self.quantity, | ||
| "condition_id": self.condition_id.id, | ||
| "disposition_id": self.disposition_id.id, | ||
| "notes": self.notes, | ||
| "is_inspected": True, | ||
| } | ||
| ) | ||
|
|
||
| # Create new line for remaining quantity | ||
| new_line = self.env["spp.drims.inspection.wizard.line"].create( | ||
| { | ||
| "wizard_id": self.wizard_id.id, | ||
| "donation_line_id": self.inspection_line_id.donation_line_id.id, | ||
| "product_id": self.product_id.id, | ||
| "uom_id": self.uom_id.id, | ||
| "quantity_expected": self.quantity_expected, | ||
| "quantity": self.remaining_qty, | ||
| "is_inspected": False, # New split needs to be inspected | ||
| } | ||
| ) | ||
| return { | ||
| "type": "ir.actions.act_window", | ||
| "res_model": "spp.drims.inspection.wizard", | ||
| "res_id": wizard_id, | ||
| "view_mode": "form", | ||
| "target": "new", | ||
| } |
There was a problem hiding this comment.
Calling self.unlink() before querying root_line.wizard_id.line_ids can lead to a MissingError or cache inconsistency in Odoo. If the One2many cache still contains the unlinked record, Odoo may attempt to read or flush it, causing a crash. It is a best practice to identify the remaining children and perform any calculations before unlinking the record.
def action_remove_split(self):
"""Remove a split child line and refresh the wizard."""
self.ensure_one()
if not self.is_split:
raise UserError(_("Only split lines can be removed this way."))
wizard_id = self.wizard_id.id
root_line = self.parent_line_id
# Identify remaining children before unlinking to avoid MissingError/cache issues
remaining_children = root_line.wizard_id.line_ids.filtered(
lambda line: line.parent_line_id == root_line and line != self
)
self.unlink()
if not remaining_children:
# Reset parent back to the full expected quantity and clear the
# split flag so the row reverts to a normal (editable) row.
root_line.quantity = root_line.quantity_expected
root_line.has_splits = False
else:
root_line.quantity = sum(remaining_children.mapped("quantity"))
return {
"type": "ir.actions.act_window",
"res_model": "spp.drims.inspection.wizard",
"res_id": wizard_id,
"view_mode": "form",
"target": "new",
}| @api.onchange("quantity") | ||
| def _onchange_quantity_update_parent(self): | ||
| """Keep the parent row qty in sync with the running sum of its children. | ||
|
|
||
| Also clamps the current child's quantity if the new value would push | ||
| the running total over the parent's ``quantity_expected``: the qty is | ||
| snapped to ``expected - sum(other_children)`` so the split totals | ||
| never exceed the donation line's received quantity. | ||
| """ | ||
| if not self.parent_line_id: | ||
| return | ||
| siblings = self.wizard_id.line_ids.filtered( | ||
| lambda line: line.parent_line_id == self.parent_line_id and line != self | ||
| ) | ||
| others_sum = sum(siblings.mapped("quantity")) | ||
| expected = self.parent_line_id.quantity_expected | ||
| max_allowed = expected - others_sum | ||
| if self.quantity and self.quantity > max_allowed: | ||
| self.quantity = max(0.0, max_allowed) | ||
| total = others_sum + (self.quantity or 0.0) | ||
| self.parent_line_id.quantity = total |
There was a problem hiding this comment.
Eagerly clamping the quantity in the @api.onchange method creates a frustrating user experience. If a user wants to adjust split quantities (e.g., changing splits of 500/500 to 400/600), they will be blocked from increasing any line first because it will be immediately clamped back to the remaining allowed amount. The user would be forced to always decrease a line before increasing another. Since the wizard already has robust validation on confirmation (both in JS via can_confirm and in Python via action_confirm_inspection), we should remove the clamping logic and allow the user to freely edit the quantities during the drafting phase.
| @api.onchange("quantity") | |
| def _onchange_quantity_update_parent(self): | |
| """Keep the parent row qty in sync with the running sum of its children. | |
| Also clamps the current child's quantity if the new value would push | |
| the running total over the parent's ``quantity_expected``: the qty is | |
| snapped to ``expected - sum(other_children)`` so the split totals | |
| never exceed the donation line's received quantity. | |
| """ | |
| if not self.parent_line_id: | |
| return | |
| siblings = self.wizard_id.line_ids.filtered( | |
| lambda line: line.parent_line_id == self.parent_line_id and line != self | |
| ) | |
| others_sum = sum(siblings.mapped("quantity")) | |
| expected = self.parent_line_id.quantity_expected | |
| max_allowed = expected - others_sum | |
| if self.quantity and self.quantity > max_allowed: | |
| self.quantity = max(0.0, max_allowed) | |
| total = others_sum + (self.quantity or 0.0) | |
| self.parent_line_id.quantity = total | |
| @api.onchange("quantity") | |
| def _onchange_quantity_update_parent(self): | |
| """Keep the parent row qty in sync with the running sum of its children.""" | |
| if not self.parent_line_id: | |
| return | |
| siblings = self.wizard_id.line_ids.filtered( | |
| lambda line: line.parent_line_id == self.parent_line_id and line != self | |
| ) | |
| others_sum = sum(siblings.mapped("quantity")) | |
| total = others_sum + (self.quantity or 0.0) | |
| self.parent_line_id.quantity = total |
| <xpath | ||
| expr="//header/button[@data-hotkey='o' and contains(@invisible, 'done')]" | ||
| position="attributes" | ||
| > | ||
| <attribute name="invisible">state != 'done' or drims_type_id</attribute> | ||
| </xpath> |
There was a problem hiding this comment.
Relying on data-hotkey and contains(@invisible, ...) in XPath expressions is fragile and prone to breaking if Odoo core updates the hotkeys or modifier expressions, or if other installed modules modify them.
In Odoo, the view inheritance processor resolves XML ID sigils (like %(xml_id)d) dynamically during view compilation. This means you can safely and robustly target action buttons directly by their XML ID in your XPath expressions (e.g., name="%(stock.act_stock_return_picking)d").
| <xpath | |
| expr="//header/button[@data-hotkey='o' and contains(@invisible, 'done')]" | |
| position="attributes" | |
| > | |
| <attribute name="invisible">state != 'done' or drims_type_id</attribute> | |
| </xpath> | |
| <xpath | |
| expr="//header/button[@name='%(stock.act_stock_return_picking)d']" | |
| position="attributes" | |
| > | |
| <attribute name="invisible">state != 'done' or drims_type_id</attribute> | |
| </xpath> |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## 19.0 #224 +/- ##
==========================================
+ Coverage 73.06% 73.12% +0.05%
==========================================
Files 1069 1070 +1
Lines 62120 62216 +96
==========================================
+ Hits 45390 45495 +105
+ Misses 16730 16721 -9
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
|
@gonzalesedwin1123 ready for your review. CI statusAll DRIMS-specific checks are green — The single red check is pre-commit, and it is not introduced by this PR. The only failing hook is the OCA README generator ( ScopeDRIMS fixes for OP#651 (children #959–#1038): warehouse tier + GIS location/map, read-only donation status bar, inspection wizard redesign with line splits + non-accept/damaged exclusion, request Priority / reject-reason / beneficiaries UX + post-approval lanes, dispatch auto-generate + button cleanup, allocation guard + multiple partial dispatches, and module menu icons. Local validation
|
The oca-gen-addon-readme hook was failing (also red on 19.0) because the committed README.rst / static/description/index.html for several modules were stale vs the generator. Regenerated via the CI toolchain so the hook passes.
|
@gonzalesedwin1123 — ready for your review. CI status
Scope (OP#651 children #959–#1038)Warehouse tier + GIS location/map, read-only donation status bar, inspection wizard redesign with line splits + non-accept/damaged exclusion, request Priority / reject-reason / beneficiaries UX + post-approval lanes, dispatch auto-generate + button cleanup, allocation guard + multiple partial dispatches, module menu icons. Local validation
|
…ew (#651) - integer_positive_required: guard fieldInfo.required before evaluateBooleanExpr — an undefined required modifier was passed straight to the evaluator and crashed the form view. - action_remove_split: compute the remaining children before unlink() so the One2many cache never reads the unlinked record (MissingError). - _onchange_quantity_update_parent: drop the eager quantity clamping so the operator can freely rebalance split quantities while drafting; an over/under-split total is still rejected at confirm time. - stock_picking_views: target the done-state delivery Print and the Return header buttons by action XML ID instead of the fragile data-hotkey / contains(@invisible) xpath.
The first '+ Add split' on an inspection line now divides it into two empty child rows (a split produces at least two pieces); each later '+ Add split' appends one more. All new rows start at qty 0 so the operator must enter each amount explicitly. Update the wizard split tests to the two-children-first behaviour.
Why is this change needed?
Umbrella fix for the DRIMS issues + improvements tracked in OP#651. Each numbered item from the original report was split into its own child ticket; this PR bundles the implemented fixes for the closed children (#959–#1038).
How was the change implemented?
Changes are in
spp_drims(plus a small reusable positive-integer-required field widget inspp_base_common). Highlights:New unit tests
Added/expanded tests across
spp_drims/tests/(donation, request, inspection wizard, allocation preview) covering inspection splits, non-accept exclusion, allocation/dispatch flows, the reject wizard, and state transitions.Unit tests executed by the author
spp_drimssuite: 247 tests, 0 failed / 0 errorsHow to test manually
Install
spp_drims, load the DRIMS demo, then:Per-item QA guides are on the child tickets under OP#651.
Related links
🤖 Generated with Claude Code