Skip to content

Conversation

@nishkagosalia
Copy link
Contributor

@nishkagosalia nishkagosalia commented Jan 5, 2026

This adds the feature: #39030

By this feature we now allow the items to be closed at individual level in sales order. It ensures the following things:

  1. Ensuring closed items do not reflect in other doctype that get created from sales order
  2. Updating close items is not permitted
  3. We can Re-open individual items as well

no-docs

@codecov
Copy link

codecov bot commented Jan 5, 2026

Codecov Report

❌ Patch coverage is 93.33333% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.12%. Comparing base (344572c) to head (361e3c9).
⚠️ Report is 34 commits behind head on develop.

Files with missing lines Patch % Lines
erpnext/selling/doctype/sales_order/sales_order.py 88.23% 4 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop   #51485      +/-   ##
===========================================
+ Coverage    79.10%   79.12%   +0.01%     
===========================================
  Files         1179     1179              
  Lines       121362   121414      +52     
===========================================
+ Hits         96007    96064      +57     
+ Misses       25355    25350       -5     
Files with missing lines Coverage Δ
...cturing/doctype/production_plan/production_plan.py 84.64% <ø> (ø)
...ext/manufacturing/doctype/work_order/work_order.py 80.50% <ø> (ø)
...xt/selling/doctype/sales_order/test_sales_order.py 99.27% <100.00%> (+0.01%) ⬆️
...lling/doctype/sales_order_item/sales_order_item.py 85.71% <ø> (ø)
...item_wise_sales_history/item_wise_sales_history.py 23.52% <ø> (ø)
...eport/sales_order_analysis/sales_order_analysis.py 79.38% <ø> (ø)
erpnext/stock/stock_balance.py 56.96% <ø> (ø)
erpnext/selling/doctype/sales_order/sales_order.py 78.73% <88.23%> (+0.71%) ⬆️

... and 12 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@szufisher
Copy link
Contributor

  1. Also close reason in sales order item needed?
  2. also consider get sales order data for production planning
  3. also consider validate sales order in work order
  4. also consider sales order transaction level related report, adding this new is_closed column?

@nishkagosalia nishkagosalia force-pushed the gh-39030 branch 3 times, most recently from d7ff5d8 to 9a8d9e0 Compare January 5, 2026 15:53
@nishkagosalia nishkagosalia marked this pull request as ready for review January 6, 2026 04:44
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 6, 2026

📝 Walkthrough

Walkthrough

Adds item-level closing for Sales Order items by introducing an is_closed Check field on Sales Order Item and exposing it in reports. Introduces backend logic and a public function to close/reopen selected items, updates reserved quantities and status transitions, and adds a data-migration patch to mark items closed when their parent Sales Order is Closed. UI changes add dialog-driven "Close selected items" and "Re-open selected items" actions. Filters across manufacturing and stock code paths and client utilities are updated to exclude closed items. Tests added for item-level closing behavior.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Suggested labels

selling, needs-tests

Suggested reviewers

  • ruthra-kumar
  • rohitwaghchaure
  • mihir-kandoi

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main feature: allowing closing of individual items in sales orders, which directly aligns with the primary changes across all modified files.
Description check ✅ Passed The pull request description clearly relates to the changeset, explaining the feature being implemented and its key objectives.
✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI Agents
In @erpnext/selling/doctype/sales_order/sales_order.py:
- Around line 2081-2114: In close_or_reopen_selected_items, the subcontracted
Sales Order check (so.is_subcontracted) must run immediately after loading the
Sales Order (so = frappe.get_doc(...)) and before any modifications, saving
(so.save()) or calls to so.update_reserved_qty(), so move the existing
frappe.throw(_("Cannot close items in a subcontracted Sales Order")) to right
after the so variable is created and return/throw early to prevent changing
rows, saving the doc, or updating reserved quantities for subcontracted orders.
- Line 1967: The code erroneously calls so.get("items", {"is_closed": 0})
treating the second arg as a filter; replace this by retrieving the items list
(e.g. so_items = so.get("items", []) or set so.items = so.get("items") ) and
apply the filter when iterating: loop over so_items and skip entries where
getattr(item, "is_closed", 0) is truthy (use getattr(item, "is_closed", 0) to
safely handle packed_items that may lack the field); ensure subsequent logic
uses the filtered list or skips closed items rather than relying on get() to
filter.

In @erpnext/selling/doctype/sales_order/test_sales_order.py:
- Around line 64-66: The test uses incorrect non-boolean integers for the
boolean Check field is_stock_item; update the three make_item calls
(make_item("_Test SO Item Level Closing 1", {"is_stock_item": 4}),
make_item("_Test SO Item Level Closing 2", {"is_stock_item": 5}),
make_item("_Test SO Item Level Closing 3", {"is_stock_item": 6})) to use the
correct boolean/Check value of 1 (or True) for is_stock_item so the items are
properly treated as stock items.
🧹 Nitpick comments (4)
erpnext/stock/stock_balance.py (1)

140-140: Minor formatting inconsistency in SQL.

The logic correctly filters out closed items, but the spacing around the equals operator should be consistent with the rest of the SQL query.

🔎 Suggested formatting fix
-					and so_item.is_closed=0 and so.status not in ('On Hold', 'Closed')))
+					and so_item.is_closed = 0 and so.status not in ('On Hold', 'Closed')))
erpnext/patches/v16_0/update_sales_order_item_status.py (1)

9-15: Minor optimization: remove redundant WHERE condition.

Line 12 duplicates the JOIN condition from line 9 (sales_order.name == sales_order_item.parent). This redundancy doesn't affect correctness but adds unnecessary overhead during patch execution.

🔎 Suggested optimization
 frappe.qb.update(sales_order_item).join(sales_order).on(sales_order.name == sales_order_item.parent).set(
 	sales_order_item.is_closed, 1
 ).where(
-	(sales_order.name == sales_order_item.parent)
-	& (sales_order.status == "Closed")
+	(sales_order.status == "Closed")
 	& (sales_order_item.is_closed == 0)
 ).run()
erpnext/selling/doctype/sales_order/sales_order.js (2)

1794-1866: Translate dialog title.

The dialog title at line 1824 should be wrapped in the translation function for internationalization.

🔎 Suggested fix
 		var d = new frappe.ui.Dialog({
-			title: "Re-open Selected Items",
+			title: __("Re-open Selected Items"),
 			size: "large",

1868-1962: Translate dialog title.

The dialog title at line 1898 should be wrapped in the translation function for internationalization.

🔎 Suggested fix
 		var d = new frappe.ui.Dialog({
-			title: "Close Selected Items",
+			title: __("Close Selected Items"),
 			size: "large",
📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between afc5dda and 9a8d9e0.

📒 Files selected for processing (13)
  • erpnext/manufacturing/doctype/production_plan/production_plan.py
  • erpnext/manufacturing/doctype/work_order/work_order.py
  • erpnext/patches.txt
  • erpnext/patches/v16_0/update_sales_order_item_status.py
  • erpnext/public/js/utils.js
  • erpnext/selling/doctype/sales_order/sales_order.js
  • erpnext/selling/doctype/sales_order/sales_order.py
  • erpnext/selling/doctype/sales_order/test_sales_order.py
  • erpnext/selling/doctype/sales_order_item/sales_order_item.json
  • erpnext/selling/doctype/sales_order_item/sales_order_item.py
  • erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
  • erpnext/selling/report/sales_order_analysis/sales_order_analysis.py
  • erpnext/stock/stock_balance.py
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-12-16T05:33:58.723Z
Learnt from: Abdeali099
Repo: frappe/erpnext PR: 51078
File: erpnext/accounts/doctype/financial_report_template/financial_report_engine.py:486-491
Timestamp: 2025-12-16T05:33:58.723Z
Learning: In ERPNext/Frappe codebase, query.run(as_dict=True) returns frappe._dict objects that support both dict-style access (obj["key"]) and attribute-style access (obj.key). Therefore, attribute access on query results is valid and will not raise AttributeError. When reviewing Python code, prefer attribute access (obj.key) for readability where the key is known to exist, but ensure existence checks or fallback handling if there is any doubt about missing keys.

Applied to files:

  • erpnext/patches/v16_0/update_sales_order_item_status.py
  • erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
  • erpnext/selling/report/sales_order_analysis/sales_order_analysis.py
  • erpnext/manufacturing/doctype/production_plan/production_plan.py
  • erpnext/manufacturing/doctype/work_order/work_order.py
  • erpnext/selling/doctype/sales_order/sales_order.py
  • erpnext/selling/doctype/sales_order_item/sales_order_item.py
  • erpnext/stock/stock_balance.py
  • erpnext/selling/doctype/sales_order/test_sales_order.py
📚 Learning: 2025-09-30T11:04:46.510Z
Learnt from: rohitwaghchaure
Repo: frappe/erpnext PR: 49766
File: erpnext/manufacturing/doctype/production_plan/production_plan.py:1717-1717
Timestamp: 2025-09-30T11:04:46.510Z
Learning: In the Production Plan's `get_items_for_material_requests` function in `erpnext/manufacturing/doctype/production_plan/production_plan.py`, always use `data.get("sales_order")` instead of `doc.get("sales_order")` when iterating over `po_items`. This ensures raw materials are correctly grouped by each production item's respective Sales Order, not a global document-level Sales Order.

Applied to files:

  • erpnext/selling/doctype/sales_order/sales_order.js
  • erpnext/manufacturing/doctype/production_plan/production_plan.py
📚 Learning: 2025-08-12T22:10:55.921Z
Learnt from: LewisMojica
Repo: frappe/erpnext PR: 49108
File: erpnext/accounts/doctype/pos_invoice/pos_invoice.py:929-953
Timestamp: 2025-08-12T22:10:55.921Z
Learning: In ERPNext stock management, there's a critical distinction between availability and reservation calculations: availability functions (like get_bundle_availability) should filter by current status (disabled=0) to determine what can be sold now, while reservation functions (like get_bundle_pos_reserved_qty) should include all historical transactions regardless of current bundle status to accurately reflect stock that was actually consumed. This prevents stock accounting errors when bundle configurations change after sales.

Applied to files:

  • erpnext/selling/doctype/sales_order/sales_order.py
  • erpnext/stock/stock_balance.py
📚 Learning: 2025-08-12T21:33:27.483Z
Learnt from: LewisMojica
Repo: frappe/erpnext PR: 49108
File: erpnext/accounts/doctype/pos_invoice/pos_invoice.py:871-871
Timestamp: 2025-08-12T21:33:27.483Z
Learning: In ERPNext Product Bundle configurations, items can have qty = 0, which causes division by zero errors in POS bundle availability calculations. The fix is to use a high fallback value (like 1000000) instead of 0 when item.qty is zero, so these items don't constrain bundle availability.

Applied to files:

  • erpnext/selling/doctype/sales_order/sales_order.py
🧬 Code graph analysis (1)
erpnext/selling/doctype/sales_order/test_sales_order.py (1)
erpnext/selling/doctype/sales_order/sales_order.py (1)
  • close_or_reopen_selected_items (2082-2114)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Summary
🔇 Additional comments (21)
erpnext/patches.txt (1)

459-459: LGTM!

The patch entry is correctly placed and follows the standard naming convention for v16_0 patches.

erpnext/selling/doctype/sales_order_item/sales_order_item.py (1)

50-50: LGTM!

The type hint for the new is_closed field is correctly added in the TYPE_CHECKING block and properly formatted.

erpnext/manufacturing/doctype/production_plan/production_plan.py (1)

1545-1545: LGTM!

The filter correctly excludes closed Sales Order Items from production planning queries, aligning with the PR's item-level closure feature.

erpnext/manufacturing/doctype/work_order/work_order.py (1)

392-406: Consider adding item-level closure filter to the Sales Order query.

The query_sales_order function filters out Sales Orders with status "Closed" but does not check the is_closed field on individual Sales Order Items. Since this autocomplete uses or_filters to match the production_item against Sales Order Items, a Sales Order Item with is_closed = 1 would still be returned. Adding a filter to exclude closed items would align with the item-level closure feature introduced in this PR.

erpnext/selling/report/sales_order_analysis/sales_order_analysis.py (2)

81-82: LGTM!

The addition of soi.is_closed to the SELECT query is clean and correctly retrieves the new field for reporting.


330-335: LGTM!

The "Is Closed" column definition follows the established pattern and correctly exposes the item-level closure status in the report UI.

erpnext/public/js/utils.js (1)

613-637: LGTM!

The filtering logic correctly excludes closed Sales Order items from the update dialog, preventing accidental modifications while leaving other document types unaffected. This provides good UX defense-in-depth alongside backend validations.

erpnext/selling/doctype/sales_order_item/sales_order_item.json (1)

1015-1022: LGTM!

The is_closed field definition is well-structured:

  • allow_on_submit: 1 correctly enables closing/reopening after SO submission
  • in_list_view: 1 provides necessary visibility in the items grid
  • Check fieldtype is appropriate for this boolean flag
erpnext/selling/doctype/sales_order/test_sales_order.py (5)

102-108: LGTM!

Good test coverage for validating that fully delivered items cannot be closed, preventing data inconsistency.


111-128: LGTM!

Excellent validation that closing an item correctly releases its reserved quantity in the Bin, ensuring inventory accuracy.


131-146: LGTM!

Good test coverage ensuring that closed items cannot be updated via update_child_qty_rate, maintaining data integrity.


149-151: LGTM!

Well-designed test verifying that pick lists correctly exclude closed items, showing only the remaining open item for picking.


153-167: LGTM!

Comprehensive test validating that reopening a closed item correctly restores its reserved quantity, ensuring the close/reopen workflow is fully reversible.

erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py (1)

127-133: LGTM! Column integration looks correct.

The "Is Closed" column is properly added to the report with correct field type (Check), and the data flow from query → row dict → column display is consistent.

Also applies to: 169-169, 218-218

erpnext/selling/doctype/sales_order/sales_order.js (2)

1000-1010: LGTM! Button placement is appropriate.

The "Close selected items" and "Re-open selected items" buttons are correctly placed under the Status dropdown when the order has pending delivery or billing.


1724-1724: LGTM! Correctly excludes closed items.

The additional !d.is_closed check properly prevents closed items from being included in the pending quantity calculation for Purchase Order creation.

erpnext/selling/doctype/sales_order/sales_order.py (5)

594-599: LGTM! Status update integration is correct.

The integration with close_or_reopen_selected_items properly handles item-level state changes when the Sales Order status is updated to Draft (reopen) or Closed.


1080-1081: LGTM! Correctly excludes closed items from Material Request.

The added condition properly prevents closed Sales Order items from being included in Material Request generation.


1197-1200: LGTM! Correctly excludes closed items from Delivery Note.

The condition properly filters out closed items during Delivery Note creation.


1439-1443: LGTM! Correctly excludes closed items from Sales Invoice.

The condition properly prevents closed items from being included in Sales Invoice generation.


1890-1890: LGTM! Correctly excludes closed items from Pick List.

The condition properly prevents closed items from being included in Pick List creation.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
erpnext/patches/v16_0/update_sales_order_item_status.py (1)

4-17: Preserve and restore the original auto_commit_on_many_writes setting.

The patch hardcodes the reset to 0 at line 17, but this will incorrectly change the setting if it was already 1 before the patch ran.

🔎 Proposed fix
 def execute():
+	original_auto_commit = frappe.db.auto_commit_on_many_writes
 	frappe.db.auto_commit_on_many_writes = 1
 	sales_order = frappe.qb.DocType("Sales Order")
 	sales_order_item = frappe.qb.DocType("Sales Order Item")
 
 	frappe.qb.update(sales_order_item).join(sales_order).on(sales_order.name == sales_order_item.parent).set(
 		sales_order_item.is_closed, 1
 	).where(
 		(sales_order.name == sales_order_item.parent)
 		& (sales_order.status == "Closed")
 		& (sales_order_item.is_closed == 0)
 	).run()
 
-	frappe.db.auto_commit_on_many_writes = 0
+	frappe.db.auto_commit_on_many_writes = original_auto_commit
erpnext/selling/doctype/sales_order/sales_order.py (1)

2083-2117: Consider streamlining the status update when all items are closed.

At lines 2114-2116, when all items are closed via selective closing, the code calls so.update_status("Closed"), which in turn (at line 597) invokes close_or_reopen_selected_items(self.name, "Close", all_items_closed=True) again. Since all items are already marked closed and saved at line 2108, this second call performs redundant iteration over the items without changing their state. While not incorrect, this results in a minor inefficiency.

💡 Alternative approach

Consider directly updating the status and calling the necessary hooks without re-invoking close_or_reopen_selected_items:

 	if not all_items_closed and all(d.is_closed for d in so.items):
 		so.status = "Closed"
-		so.update_status("Closed")
+		so.set_status(update=True, status="Closed")
+		so.update_subcontracting_order_status()
+		so.notify_update()
+		clear_doctype_notifications(so)
 	return True

Note: This mirrors the logic in update_status() but avoids the redundant call to close_or_reopen_selected_items.

erpnext/selling/doctype/sales_order/sales_order.js (1)

1868-1962: Implementation is correct, but consider UX refinement for the "Select all" checkbox.

The method is technically sound and correctly handles all scenarios. However, the "Select all items" checkbox defaulting to checked (line 1905) might lead to confusion:

  • Users clicking "Close" without reviewing will close the entire Sales Order, not individual items
  • The hidden table when "Select all" is checked reduces visibility into what will happen

Consider one of these UX improvements:

  1. Default the checkbox to unchecked to encourage explicit selection
  2. Add a warning message when "Select all" is checked explaining it will close the entire SO
  3. Show a different dialog for "close all" vs "close selected"

That said, the implementation correctly handles the logic: closing all items properly triggers the full SO closure, which is the right behavior.

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9a8d9e0 and 361e3c9.

📒 Files selected for processing (13)
  • erpnext/manufacturing/doctype/production_plan/production_plan.py
  • erpnext/manufacturing/doctype/work_order/work_order.py
  • erpnext/patches.txt
  • erpnext/patches/v16_0/update_sales_order_item_status.py
  • erpnext/public/js/utils.js
  • erpnext/selling/doctype/sales_order/sales_order.js
  • erpnext/selling/doctype/sales_order/sales_order.py
  • erpnext/selling/doctype/sales_order/test_sales_order.py
  • erpnext/selling/doctype/sales_order_item/sales_order_item.json
  • erpnext/selling/doctype/sales_order_item/sales_order_item.py
  • erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
  • erpnext/selling/report/sales_order_analysis/sales_order_analysis.py
  • erpnext/stock/stock_balance.py
🚧 Files skipped from review as they are similar to previous changes (9)
  • erpnext/patches.txt
  • erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
  • erpnext/selling/doctype/sales_order_item/sales_order_item.json
  • erpnext/stock/stock_balance.py
  • erpnext/manufacturing/doctype/work_order/work_order.py
  • erpnext/manufacturing/doctype/production_plan/production_plan.py
  • erpnext/public/js/utils.js
  • erpnext/selling/report/sales_order_analysis/sales_order_analysis.py
  • erpnext/selling/doctype/sales_order_item/sales_order_item.py
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-12-16T05:33:58.723Z
Learnt from: Abdeali099
Repo: frappe/erpnext PR: 51078
File: erpnext/accounts/doctype/financial_report_template/financial_report_engine.py:486-491
Timestamp: 2025-12-16T05:33:58.723Z
Learning: In ERPNext/Frappe codebase, query.run(as_dict=True) returns frappe._dict objects that support both dict-style access (obj["key"]) and attribute-style access (obj.key). Therefore, attribute access on query results is valid and will not raise AttributeError. When reviewing Python code, prefer attribute access (obj.key) for readability where the key is known to exist, but ensure existence checks or fallback handling if there is any doubt about missing keys.

Applied to files:

  • erpnext/selling/doctype/sales_order/test_sales_order.py
  • erpnext/selling/doctype/sales_order/sales_order.py
  • erpnext/patches/v16_0/update_sales_order_item_status.py
📚 Learning: 2025-09-30T11:04:46.510Z
Learnt from: rohitwaghchaure
Repo: frappe/erpnext PR: 49766
File: erpnext/manufacturing/doctype/production_plan/production_plan.py:1717-1717
Timestamp: 2025-09-30T11:04:46.510Z
Learning: In the Production Plan's `get_items_for_material_requests` function in `erpnext/manufacturing/doctype/production_plan/production_plan.py`, always use `data.get("sales_order")` instead of `doc.get("sales_order")` when iterating over `po_items`. This ensures raw materials are correctly grouped by each production item's respective Sales Order, not a global document-level Sales Order.

Applied to files:

  • erpnext/selling/doctype/sales_order/sales_order.py
  • erpnext/selling/doctype/sales_order/sales_order.js
📚 Learning: 2025-08-12T22:10:55.921Z
Learnt from: LewisMojica
Repo: frappe/erpnext PR: 49108
File: erpnext/accounts/doctype/pos_invoice/pos_invoice.py:929-953
Timestamp: 2025-08-12T22:10:55.921Z
Learning: In ERPNext stock management, there's a critical distinction between availability and reservation calculations: availability functions (like get_bundle_availability) should filter by current status (disabled=0) to determine what can be sold now, while reservation functions (like get_bundle_pos_reserved_qty) should include all historical transactions regardless of current bundle status to accurately reflect stock that was actually consumed. This prevents stock accounting errors when bundle configurations change after sales.

Applied to files:

  • erpnext/selling/doctype/sales_order/sales_order.py
📚 Learning: 2025-08-12T21:33:27.483Z
Learnt from: LewisMojica
Repo: frappe/erpnext PR: 49108
File: erpnext/accounts/doctype/pos_invoice/pos_invoice.py:871-871
Timestamp: 2025-08-12T21:33:27.483Z
Learning: In ERPNext Product Bundle configurations, items can have qty = 0, which causes division by zero errors in POS bundle availability calculations. The fix is to use a high fallback value (like 1000000) instead of 0 when item.qty is zero, so these items don't constrain bundle availability.

Applied to files:

  • erpnext/selling/doctype/sales_order/sales_order.py
🧬 Code graph analysis (2)
erpnext/selling/doctype/sales_order/test_sales_order.py (1)
erpnext/selling/doctype/sales_order/sales_order.py (1)
  • close_or_reopen_selected_items (2084-2117)
erpnext/selling/doctype/sales_order/sales_order.js (2)
erpnext/stock/doctype/stock_entry/stock_entry.js (5)
  • d (345-378)
  • d (399-399)
  • d (709-712)
  • d (727-727)
  • values (714-714)
erpnext/accounts/doctype/sales_invoice/sales_invoice.js (3)
  • d (1064-1118)
  • me (75-75)
  • me (409-409)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Patch Test
  • GitHub Check: Python Unit Tests (2)
  • GitHub Check: Python Unit Tests (1)
  • GitHub Check: Python Unit Tests (3)
  • GitHub Check: Python Unit Tests (4)
  • GitHub Check: Summary
🔇 Additional comments (4)
erpnext/selling/doctype/sales_order/test_sales_order.py (1)

61-168: Excellent test coverage for item-level closing feature.

The test comprehensively validates:

  • Prevention of closing fully delivered items
  • Reserved quantity updates on closing/reopening
  • Prevention of updating closed items
  • Pick list creation excluding closed items
  • Proper state restoration on reopening

The test structure is clear and follows existing patterns in the file.

erpnext/selling/doctype/sales_order/sales_order.js (3)

999-1010: LGTM! UI buttons properly integrated.

The "Close selected items" and "Re-open selected items" buttons are correctly placed in the Status group with appropriate visibility conditions. The implementation follows existing patterns in the file.


1724-1724: Correct logic to exclude closed items from Purchase Order creation.

The added condition && !d.is_closed properly filters out closed Sales Order items when determining which items should be included in the Purchase Order dialog. This aligns with the expected behavior where closed items should not be ordered.


1794-1866: Well-implemented dialog for reopening selected items.

The method correctly:

  • Filters to show only closed items
  • Presents a clear dialog for item selection
  • Validates user input before making server call
  • Provides appropriate feedback on success

The implementation follows established patterns in the codebase.

items = []
so = frappe.get_doc("Sales Order", sales_order)
if so.is_subcontracted:
frappe.throw(_("Cannot close items in a subcontracted Sales Order"))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If subcontracting order has created then the users should not be able to close the sales order, otherwise they can close the sales order

@rohitwaghchaure
Copy link
Collaborator

Screenshot 2026-01-07 at 2 23 40 PM
  • Remove the Is Closed from the grid view
  • Show indicator for closed items (Maybe red color)
  • for production plan, added the sales order manually and clicked on the "Get Finished Goods" which has fetched the closed item. Should not fetch the closed items in the production plan

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants