mirror of
https://github.com/inventree/InvenTree.git
synced 2026-07-17 12:13:49 +00:00
[feature] Break apart assemblies (#12310)
* Implement API endpoint for stock disassembly * Add basic frontend implementation * Adjust required user permission * Add preFormContent * Read-only if serialized * Adjust location and status of each subcomponent * Handle null value * display installed items in frontend form * More unit tests * Traceability * Add docs * Exclude virtual / consumable stock * Additional docs * Added bundled items docs * More docs * more docs tweaks * Updated part docs * Add playwright tests * Robustify test * suppress certain warnings in schema * Adjust playwright tests * bug fix * Tweak playwright tests
This commit is contained in:
@@ -23,3 +23,9 @@ Read more about build orders in the [Build Order documentation](./build.md).
|
||||
InvenTree allows users to allocate stock items to specific build orders, ensuring that the required components are reserved for production. This helps to prevent stock shortages and ensures that the right parts are available when needed.
|
||||
|
||||
Read more about stock allocation in the [Stock Allocation documentation](./allocate.md).
|
||||
|
||||
### Disassembly
|
||||
|
||||
The reverse process is also supported - an assembled stock item can be broken back down into its component parts, based on its BOM. This is useful for reworking or scrapping an assembly, or for splitting a bundled "kit" product purchased from a supplier into its individual components.
|
||||
|
||||
Read more about this process in the [Stock Disassembly documentation](../stock/disassemble.md).
|
||||
|
||||
@@ -53,6 +53,8 @@ A *Template* part is one which can have *variants* which exist underneath it. [R
|
||||
|
||||
If a part is designated as an *Assembly* it can be created (or built) from other component parts. As an example, a circuit board assembly is made using multiple electronic components, which are tracked in the system. An *Assembly* Part has a Bill of Materials (BOM) which lists all the required sub-components. [Read further information about BOM management here](../manufacturing/bom.md).
|
||||
|
||||
An assembled stock item can also be broken back down into its component parts, using the [disassembly](../stock/disassemble.md) process.
|
||||
|
||||
### Component
|
||||
|
||||
If a part is designated as a *Component* it can be used as a sub-component of an *Assembly*. [Read further information about BOM management here](../manufacturing/bom.md)
|
||||
|
||||
@@ -7,7 +7,7 @@ title: Part Notifications
|
||||
Users can select to receive notifications when certain events occur.
|
||||
|
||||
!!! warning "Email Configuration Required"
|
||||
External notifications require correct [email configuration](../start/config.md#email-settings). They also need to be enabled in the settings under notifications`.
|
||||
External notifications require correct [email configuration](../start/config.md#email-settings). They also need to be enabled in the settings under *Notifications*.
|
||||
|
||||
!!! warning "Valid Email Address"
|
||||
Each user must have a valid email address associated with their account to receive email notifications
|
||||
|
||||
@@ -51,7 +51,7 @@ Each price range is calculated in the [Default Currency](../concepts/pricing.md#
|
||||
Price range data is [cached in the database](#price-data-caching) when underlying pricing information changes.
|
||||
|
||||
!!! tip "Refresh Pricing"
|
||||
While pricing data is [automatically updated](#data-updates), the user can also manually refresh the pricing calculations manually, by pressing the "Refresh" button in the overview section.
|
||||
While pricing data is [automatically updated](#pricing-updates), the user can also manually refresh the pricing calculations manually, by pressing the "Refresh" button in the overview section.
|
||||
|
||||
#### Overall Pricing
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ If this tab is not visible, ensure that the *Enable Stock History* [user setting
|
||||
|
||||
### Stocktake Entry Generation
|
||||
|
||||
By default, stocktake entries are generated automatically at regular intervals (see [settings](#stock-history-settings) below). However, users can generate a stocktake entry on demand, using the *Generate Stocktake Entry* button in the *Stock History* tab:
|
||||
By default, stocktake entries are generated automatically at regular intervals (see [settings](#stocktake-settings) below). However, users can generate a stocktake entry on demand, using the *Generate Stocktake Entry* button in the *Stock History* tab:
|
||||
|
||||
{{ image("part/part_stocktake_manual.png", "Generate stocktake entry") }}
|
||||
|
||||
@@ -95,7 +95,7 @@ Enable or disable stocktake functionality. Note that by default, stocktake funct
|
||||
|
||||
### Automatic Stocktake Period
|
||||
|
||||
Configure the number of days between generation of [automatic stocktake reports](#automatic-stocktake). If this value is set to zero, automatic stocktake reports will not be generated.
|
||||
Configure the number of days between generation of [automatic stocktake entries](#stocktake-entry-generation). If this value is set to zero, automatic stocktake entries will not be generated.
|
||||
|
||||
### Delete Old Stocktake Entries
|
||||
|
||||
|
||||
+17
-1
@@ -8,7 +8,7 @@ The Part detail view page provides a detailed view of a single part in the syste
|
||||
|
||||
### Category Breadcrumb List
|
||||
|
||||
The categories of each part is displayed on the top navigation bar as show in the above screenshot.
|
||||
The categories of each part is displayed on the top navigation bar.
|
||||
[Click here](./index.md#part-category) for more information about categories.
|
||||
|
||||
## Part Details
|
||||
@@ -83,6 +83,10 @@ The *Build Orders* tab shows a list of the builds for this part. It provides a v
|
||||
|
||||
The *Used In* tab displays a list of other parts that this part is used to make. This tab is only visible if the Part is a *component*.
|
||||
|
||||
### Part Pricing
|
||||
|
||||
The *Part Pricing* tab displays all available pricing information for the part, aggregated from multiple sources (internal pricing, supplier pricing, purchase history, BOM pricing, sale pricing, etc). Refer to the [part pricing documentation](./pricing.md) for further information.
|
||||
|
||||
### Suppliers
|
||||
|
||||
The *Suppliers* tab displays all the *Part Suppliers* and *Part Manufacturers* for the selected *Part*.
|
||||
@@ -101,6 +105,14 @@ This tab is only displayed if the part is marked as *Purchaseable*.
|
||||
|
||||
The *Sales Orders* tab shows a list of the sales orders for this part. It provides a view for important sales order information like customer, status, creation and shipment dates.
|
||||
|
||||
### Return Orders
|
||||
|
||||
The *Return Orders* tab shows a list of the [return orders](../sales/return_order.md) which reference this part. This tab is only visible if the Part is marked as *Salable*, and the return order feature is enabled.
|
||||
|
||||
### Transfer Orders
|
||||
|
||||
The *Transfer Orders* tab shows a list of the [transfer orders](../stock/transfer_order.md) which reference this part. This tab is hidden if the Part is marked as *Virtual*, or the transfer order feature is not enabled.
|
||||
|
||||
### Stock History
|
||||
|
||||
The *Stock History* tab provide historical stock level information. Refer to the [stock history documentation](./stocktake.md) for further information.
|
||||
@@ -109,6 +121,10 @@ The *Stock History* tab provide historical stock level information. Refer to the
|
||||
|
||||
If a part is marked as *testable*, the user can define tests which must be performed on any stock items which are instances of this part. [Read more about testing](./test.md).
|
||||
|
||||
### Test Results
|
||||
|
||||
The *Test Results* tab displays [test result](../stock/test.md) data uploaded against *any* stock item of this part, aggregated into a single table. This differs from the *Test Templates* tab, which configures the tests themselves rather than displaying recorded results. This tab is only visible if the part is marked as *testable*.
|
||||
|
||||
### Related Parts
|
||||
|
||||
Related Part denotes a relationship between two parts, when users want to show their usage is "related" to another part or simply emphasize a link between two parts.
|
||||
|
||||
@@ -135,6 +135,22 @@ The unit cost of the purchase order line item is transferred across to the creat
|
||||
|
||||
However, if the [Convert Currency](#purchase-order-settings) setting is enabled, the currency of the stock item will be converted to the [default currency](../concepts/pricing.md#default-currency) of the system. This may be useful when ordering stock in a different currency, to ensure that the unit cost of the stock item is converted to the base currency at the time of receipt.
|
||||
|
||||
## Bundled Items
|
||||
|
||||
Some suppliers only sell a group of components as a single bundled or "kit" product, rather than as individual purchasable line items - for example, a fastener kit containing an assortment of different screws, or a "starter kit" containing several components required for a particular use case.
|
||||
|
||||
Rather than receiving the bundle as a single opaque stock quantity, InvenTree allows the bundle to be modelled as an assembly, so that it can be broken apart into its individual components once required:
|
||||
|
||||
1. Create a part to represent the bundle itself, and mark it as an [assembly](../part/index.md#assembly)
|
||||
2. Link a [supplier part](./supplier.md#supplier-parts) to the bundle part, representing how it is purchased from the supplier
|
||||
3. Define a [Bill of Materials](../manufacturing/bom.md) for the bundle part, listing each of the individual components and the quantity contained within a single bundle
|
||||
4. Create and receive a purchase order against the bundle's supplier part, as normal - a single stock item is created for the bundle, retaining the purchase price and source purchase order of the order as a whole
|
||||
|
||||
Once the individual components are actually required, the received bundle stock item can be [disassembled](../stock/disassemble.md) into its component parts. The purchase price and traceability data (batch code, source purchase order) of the original bundle are automatically apportioned across the newly generated component stock items.
|
||||
|
||||
!!! tip "Pack Size vs Bundled Items"
|
||||
A supplier part with a [pack size](./supplier.md#supplier-part-pack-size) greater than one still represents multiple units of the *same* part - the pack size simply determines how many physical units are added to stock per unit ordered. A *bundled* item is different: a single supplier part represents an assortment of *different* components, which must be disassembled before the individual components can be used or sold separately.
|
||||
|
||||
## Complete Order
|
||||
|
||||
Once the quantity of all __received__ items is equal or above the quantity of all line items, the order will be automatically marked as __complete__.
|
||||
|
||||
@@ -89,3 +89,6 @@ Supplier parts can have a pack size defined. This value is defined when creating
|
||||
When buying parts, they are bought in packs. This is taken into account in Purchase Orders: if a supplier part with a pack size of 5 is bought in a quantity of 4, 20 parts will be added to stock when the parts are received.
|
||||
|
||||
When adding stock manually, the supplier part can be added in packs or in individual parts. This is to allow the addition of items in opened packages. Set the flag "Use pack size" (`use_pack_size` in the API) to True in order to add parts in packs.
|
||||
|
||||
!!! tip "Bundled Items"
|
||||
A pack size only ever represents multiple units of the *same* part. If a supplier instead sells a kit or assortment of *different* components as a single purchasable item, refer to the [bundled items](./purchase_order.md#bundled-items) documentation instead.
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
title: Stock Disassembly
|
||||
---
|
||||
|
||||
## Stock Disassembly
|
||||
|
||||
A stock item of an [assembly](../part/index.md#assembly) part can be *disassembled* back into its component parts, based on the [Bill of Materials](../manufacturing/bom.md) (BOM) for that part. This is the reverse of building an assembly - instead of consuming components to create an assembled item, the assembled item is broken back down into its constituent components.
|
||||
|
||||
This is useful in a number of scenarios, for example:
|
||||
|
||||
- An assembly is being reworked or scrapped, and the still-usable components need to be returned to stock
|
||||
- A supplier ships a "bundled" or "kit" product as a single line item, which needs to be split apart into its individual components before the parts can be used or sold separately (see below)
|
||||
- Correcting an assembly which was built or received in error
|
||||
|
||||
Disassembly is only available for a stock item whose part is marked as an *assembly*, and requires that the part has at least one [BOM line item](../manufacturing/bom.md#bom-line-items) defined.
|
||||
|
||||
To disassemble a stock item, navigate to the stock item detail page and select the *Disassemble* option from the actions menu. This requires that the user has the *Stock: Add* permission, and that the stock item is currently [in stock](./status.md).
|
||||
|
||||
{{ image("stock/stock_options.png", "Stock Options") }}
|
||||
|
||||
### Disassembly Form
|
||||
|
||||
The disassembly form is pre-populated with one line per BOM line item defined for the part, based on the quantity of assemblies being disassembled. Any line item marked as [consumable](../manufacturing/bom.md#consumable-bom-line-items) (whether the BOM line itself or its underlying part is marked consumable), or which points to a [virtual](../part/index.md) part, is excluded, as these components are not expected to be tracked as physical stock. This exclusion is enforced by the API - such a BOM line cannot be submitted for disassembly, even if referenced directly.
|
||||
|
||||
For each line, the following values may be adjusted:
|
||||
|
||||
| Field | Description |
|
||||
| --- | --- |
|
||||
| Quantity | The total quantity of the component part to generate. This is automatically scaled as the top-level *Quantity* field is changed, unless the user has manually edited it |
|
||||
| Location | An optional destination location for the generated stock item. If not specified, the component is placed in the same location as the disassembled item (or the default location specified at the top of the form) |
|
||||
| Status | An optional [stock status](./status.md) to apply to the generated stock item. If not specified, the component is created with the default *OK* status |
|
||||
| Unit Price | An optional purchase price to record against the generated stock item. If left blank, a price is calculated automatically (see below) |
|
||||
|
||||
A line item can be removed from the form entirely if that particular component is not required to be split out - for example, if it is being scrapped rather than returned to stock. A line cannot be removed if it has installed items associated with it (see below).
|
||||
|
||||
### Quantity
|
||||
|
||||
Only the *available* quantity of a stock item can be disassembled. A [serialized](./traceability.md#serial-numbers) stock item does not have an adjustable quantity - since it represents a single physical unit, it must always be disassembled in its entirety.
|
||||
|
||||
The original stock item is never deleted as a result of disassembly - its quantity is reduced by the disassembled amount, in order to preserve traceability. If a stock item is disassembled down to a zero quantity, it is retained in the database (in an *unavailable* state) rather than removed, even if the item has the [Delete on Deplete](./availability.md#delete-on-deplete) flag set. A serialized item cannot be reduced to a zero quantity, so in this case the original item is instead marked with a *Destroyed* status.
|
||||
|
||||
### Accounting for Installed Items
|
||||
|
||||
If the stock item being disassembled has other stock items [installed](../manufacturing/allocate.md#allocating-tracked-stock) within it (for example, tracked components that were installed during a build order), these installed items **must** be accounted for during disassembly:
|
||||
|
||||
- Each installed item is matched against a BOM line item, based on the component part (including any [substitute](../manufacturing/bom.md#substitute-bom-line-items) or [variant](../part/index.md#assembly) parts allowed for that line)
|
||||
- Matched installed items are *uninstalled* directly, rather than being discarded and re-created - this preserves the original stock item, including its own tracking history, batch code, and purchase price
|
||||
- The quantity requested for the matching BOM line is reduced by the quantity already covered by the installed item(s). A new stock item is only created for any remaining quantity - if the installed items fully cover the required quantity, no new stock item is created for that line
|
||||
- Any installed item which does *not* match one of the selected BOM lines is still uninstalled (it cannot be left "installed" inside a smaller or non-existent parent), but its quantity is **not** subtracted from any line
|
||||
|
||||
Because installed items cannot be partially accounted for, **a stock item with any installed items must be disassembled in its entirety** - a partial disassembly (disassembling less than the full available quantity) is rejected if any items are currently installed.
|
||||
|
||||
The disassembly form displays a count of installed items against each matching BOM line, and lists any "leftover" installed items (which do not match a BOM line) in a separate warning panel.
|
||||
|
||||
### Automatic Cost Allocation
|
||||
|
||||
If the original stock item has a recorded purchase price, and no explicit *Unit Price* has been entered for the generated lines, InvenTree attempts to automatically apportion that cost across the newly generated components:
|
||||
|
||||
- The total cost (unit purchase price × disassembled quantity) is split across the lines, weighted by the existing [pricing](../part/pricing.md) data (average of minimum and maximum overall price) for each component part
|
||||
- If pricing data is not available for *every* line, the cost is instead split evenly on a per-unit basis across all generated units
|
||||
- Cost is only allocated across newly *created* stock items - any matched installed items retain their own existing purchase price, and are excluded from the cost split entirely
|
||||
- If any line has an explicit *Unit Price* provided by the user, automatic cost allocation is skipped entirely, and prices are only applied where explicitly set
|
||||
|
||||
### Traceability
|
||||
|
||||
Disassembling a stock item generates a full audit trail:
|
||||
|
||||
- A `Disassembled into components` entry is added to the tracking history of the original stock item
|
||||
- Each newly created component stock item receives a `Created from disassembly` tracking entry, referencing the original stock item
|
||||
- The *batch code* and source *purchase order* of the original stock item are copied directly to each generated component
|
||||
- If the original stock item was generated by a build order, that build order cannot be directly copied to the new component (since the component was not actually built by that order) - instead, it is recorded as a reference within the `Created from disassembly` tracking entry
|
||||
|
||||
### Purchasing Bundled Items
|
||||
|
||||
Some suppliers only sell a group of components as a single bundled or "kit" product, rather than as individual purchasable line items. Such a bundle can be modelled as an assembly part, purchased and received as a single stock item, and later disassembled into its individual components - with purchase price and traceability data automatically apportioned across the generated components, as described above.
|
||||
|
||||
Refer to the [Bundled Items](../purchasing/purchase_order.md#bundled-items) documentation for a full description of how to set this up.
|
||||
|
||||
### Enforced Limitations
|
||||
|
||||
The following limitations are enforced when disassembling a stock item:
|
||||
|
||||
- The part associated with the stock item must be marked as an *assembly*
|
||||
- The stock item must currently be [in stock](./status.md) - for example, it cannot be allocated to a sales order, installed in another assembly, or already fully consumed
|
||||
- At least one BOM line item must be selected for disassembly
|
||||
- The disassembly quantity cannot exceed the available quantity of the stock item
|
||||
- A serialized stock item must be disassembled in its entirety (its quantity cannot be partially reduced)
|
||||
- Each BOM line may only be referenced once per disassembly operation
|
||||
- A selected BOM line must be a valid line item for the part associated with the stock item
|
||||
- If the stock item has any installed items, it must be disassembled in its entirety
|
||||
@@ -40,6 +40,31 @@ This view displays all tracking entries associated with any stock item linked to
|
||||
!!! info "Deleted Stock Items"
|
||||
Even if a stock item is deleted from the system, the associated stock tracking entries are retained for historical reference. They will be visible in the part tracking history, but not in the stock item tracking history (as the stock item itself has been deleted).
|
||||
|
||||
## Installed Stock Items
|
||||
|
||||
A stock item can be *installed* inside another stock item, forming a parent/child relationship between the two. This is used to represent physical assembly - for example, a serialized PCB assembly which has been fitted with a tracked sub-component, such as a wireless module or a pre-programmed IC.
|
||||
|
||||
An installed stock item is no longer available for regular stock actions (it cannot be moved, allocated to an order, or built into another assembly) while it remains installed - it is only accessible "through" its parent item.
|
||||
|
||||
### How Items Become Installed
|
||||
|
||||
There are two ways that a stock item can become installed inside another:
|
||||
|
||||
- **Tracked build allocation** - when a [tracked BOM item](../manufacturing/allocate.md#allocating-tracked-stock) is allocated to a build order and the build output is completed, the allocated stock item is automatically installed into the completed build output
|
||||
- **Manual installation** - from the *Stock Item Detail* page, a user can manually install one stock item into another, using the *Install Item* action. By default, the selected item's part must appear in the [Bill of Materials](../manufacturing/bom.md) of the parent item's part - this check can be disabled using the {{ globalsetting("STOCK_ENFORCE_BOM_INSTALLATION", short=True) }} setting
|
||||
|
||||
### Viewing Installed Items
|
||||
|
||||
Any stock items installed within a particular stock item are displayed on the *Installed Items* tab of the *Stock Item Detail* page.
|
||||
|
||||
By default, installed stock items are hidden from general stock item tables (as they are not directly available for use) - this can be changed using the {{ globalsetting("STOCK_SHOW_INSTALLED_ITEMS", short=True) }} setting.
|
||||
|
||||
### Removing Installed Items
|
||||
|
||||
An installed stock item can be removed (uninstalled) from its parent using the *Uninstall Item* action, which returns the item to a selected stock location and makes it available for regular stock actions once more.
|
||||
|
||||
Additionally, installed items are automatically uninstalled when the parent item is [disassembled](./disassemble.md#accounting-for-installed-items) into its component parts - refer to that page for a detailed description of how installed items are matched against Bill of Materials line items during disassembly.
|
||||
|
||||
## Stock Tracking Settings
|
||||
|
||||
There are a number of configuration options available for controlling the behavior of stock tracking functionality in the [system settings view](../settings/global.md):
|
||||
|
||||
@@ -146,6 +146,7 @@ nav:
|
||||
- Stock Tracking: stock/tracking.md
|
||||
- Stock Status: stock/status.md
|
||||
- Adjusting Stock: stock/adjust.md
|
||||
- Stock Disassembly: stock/disassemble.md
|
||||
- Stock Expiry: stock/expiry.md
|
||||
- Stock Ownership: stock/owner.md
|
||||
- Test Results: stock/test.md
|
||||
|
||||
Reference in New Issue
Block a user