v16 Manufacture Stock Entry `type` (Co-Product / Scrap) field vs `is_legacy_scrap_item`

Versions

  • ERPNext: 16.29.0
  • Frappe: 16.28.0
  • Perpetual inventory: enabled, valuation method FIFO
  • No BOMs in the system (production is recorded directly as Stock Entries)

Summary

In v15 we could tick “Is Scrap Item” on co-product / scrap rows of a Manufacture Stock Entry, and the finished-good rate was computed as a residual so that value_difference came out to 0.

In v16 that checkbox has been renamed to is_legacy_scrap_item and made read-only, and a new type Select field (Co-Product / By-Product / Scrap / Additional Finished Good) has been introduced in its place.

The problem: the finished-good valuation still reads is_legacy_scrap_item, not type. So a multi-output Manufacture entry built through the UI can no longer be balanced, because the only field that affects the calculation cannot be set from the UI.


Field metadata in v16 (Stock Entry Detail)

Field read_only depends_on
is_legacy_scrap_item 1 `is_legacy_sc
type 0 eval:parent.purpose == "Manufacture" && doc.t_warehouse && !doc.is_finished_item && !doc.is_legacy_scrap_item
set_basic_rate_manually 0 eval:parent.purpose==="Repack" && doc.t_warehouse

Two consequences:

  1. is_legacy_scrap_item is read-only and its depends_on refers to itself, so it is only rendered on rows where it is
    already 1. It can never be newly ticked from t
  2. set_basic_rate_manually is only rendered for Repack, so on a Manufacture entry there is also no way to override the
    computed rate manually.

is_scrap_item no longer exists on the doctype


The calculation

get_basic_rate_for_manufactured_item() compute

FG rate = (total_outgoing_value − scrap_items_cost) / fg_qty

scrap_items_cost = sum(basic_amount for rows where is_legacy_scrap_item == 1)

type does not appear in this sum. As far as we source, type only influences valuation viabom_secondary_item / cost_allocation_per, which requires a BOM. With no BOM, setting type = Scrap has no effect on
valuation at all.


Steps to reproduce

Create a Manufacture Stock Entry with three rows

Row Warehouse Item Qty Basic Rate
1 Source A 100 100.00
2 Target B (co-product) 20 50.00
3 Target C (finished good, `is_finished_it

Case 1 — is_legacy_scrap_item = 1 on row 2y unlocking the field)

scrap_items_cost = 1,000
FG rate  = (10,000 − 1,000) / 80 = 112.50
incoming = 1,000 + 9,000 = 10,000
outgoing =                  10,000
value_difference = 0.00          ✅

**Case 2 — type = "Scrap" on row 2, `is_legacyUI allows)

scrap_items_cost = 0             ← type not counted
FG rate  = (10,000 − 0) / 80 = 125.00
incoming = 1,000 + 10,000 = 11,000
outgoing =                   10,000
value_difference = 1,000.00      ❌

The difference is exactly the total of the co-pris counted twice: once in their own rows and again inside the finished good’s residual.


What we verified

  • A/B test on a test instance. We exposed is_legacy_scrap_item with a Client Script and toggled only that one field on
    the same document. Ticking it → difference 0. Une = Scrap` instead → difference reappears. Noother change.

  • The field itself still works correctly in v16. On our production instance, 71 multi-output Manufacture entries created
    via the REST API (with is_legacy_scrap_item = 1*and submitted** from the UI by other users afterthe v16 upgrade. In all 71, the flag survived and value_difference` stayed 0. So the server-side behaviour is intact — only UI
    access to the field has been removed.

  • The only way to get 0 from the UI on a mul co-product’s rate to 0, which balances theaccounts but assigns the co-product a zero valuation and pushes its entire cost onto the finished good. That is not an
    acceptable result.


Current workaround

A Client Script on Stock Entry re-exposes the fi

frappe.ui.form.on('Stock Entry', {
    refresh(frm) {
        const grid = frm.fields_dict.items && frm.fields_dict.items.grid;
        if (!grid) return;
        grid.update_docfield_property('is_legacy_scrap_item', 'read_only', 0);
        grid.update_docfield_property('is_legacy');
        grid.update_docfield_property('is_legacy_scrap_item', 'hidden', 0);
        frm.refresh_field('items');
    }
});

Note that Customize Form cannot be used for this — it rejects the change with “You cannot unset ‘Read Only’ for field Is
Legacy Scrap Item”
.


Questions

  1. Is type intended to replace `is_legacy_scravaluation, and is it a known gap that it currently does not?
  2. Is a BOM now mandatory for co-product / scrapthere a supported path for shop-floor productionthat is recorded directly as Stock Entries without BOMs?
  3. If is_legacy_scrap_item is still the field should it remain read-only in the UI? Right nowthe only field that affects valuation is the one users cannot set.

Happy to share document JSON or run further tests if that helps.

Hi @KaranIFL

Please avoid putting up AI written stuff as this much long question is of no one interest. I dont see anybody reading long questions and have time to answer them.

Fair point, next time I’ll keep it short.