mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-17 04:25:42 +00:00
Merge remote-tracking branch 'inventree/master'
This commit is contained in:
@ -2,11 +2,15 @@
|
|||||||
|
|
||||||
|
|
||||||
# InvenTree API version
|
# InvenTree API version
|
||||||
INVENTREE_API_VERSION = 66
|
INVENTREE_API_VERSION = 67
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Increment this API version number whenever there is a significant change to the API that any clients need to know about
|
Increment this API version number whenever there is a significant change to the API that any clients need to know about
|
||||||
|
|
||||||
|
v67 -> 2022-07-25 : https://github.com/inventree/InvenTree/pull/3395
|
||||||
|
- Adds a 'requirements' endpoint for Part instance
|
||||||
|
- Provides information on outstanding order requirements for a given part
|
||||||
|
|
||||||
v66 -> 2022-07-24 : https://github.com/inventree/InvenTree/pull/3393
|
v66 -> 2022-07-24 : https://github.com/inventree/InvenTree/pull/3393
|
||||||
- Part images can now be downloaded from a remote URL via the API
|
- Part images can now be downloaded from a remote URL via the API
|
||||||
- Company images can now be downloaded from a remote URL via the API
|
- Company images can now be downloaded from a remote URL via the API
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -326,7 +326,7 @@ class PurchaseOrderComplete(PurchaseOrderContextMixin, CreateAPI):
|
|||||||
|
|
||||||
|
|
||||||
class PurchaseOrderIssue(PurchaseOrderContextMixin, CreateAPI):
|
class PurchaseOrderIssue(PurchaseOrderContextMixin, CreateAPI):
|
||||||
"""API endpoint to 'complete' a purchase order."""
|
"""API endpoint to 'issue' (send) a purchase order."""
|
||||||
|
|
||||||
queryset = models.PurchaseOrder.objects.all()
|
queryset = models.PurchaseOrder.objects.all()
|
||||||
|
|
||||||
|
@ -567,6 +567,40 @@ class PartScheduling(RetrieveAPI):
|
|||||||
return Response(schedule)
|
return Response(schedule)
|
||||||
|
|
||||||
|
|
||||||
|
class PartRequirements(RetrieveAPI):
|
||||||
|
"""API endpoint detailing 'requirements' information for aa particular part.
|
||||||
|
|
||||||
|
This endpoint returns information on upcoming requirements for:
|
||||||
|
|
||||||
|
- Sales Orders
|
||||||
|
- Build Orders
|
||||||
|
- Total requirements
|
||||||
|
|
||||||
|
As this data is somewhat complex to calculate, is it not included in the default API
|
||||||
|
"""
|
||||||
|
|
||||||
|
queryset = Part.objects.all()
|
||||||
|
|
||||||
|
def retrieve(self, request, *args, **kwargs):
|
||||||
|
"""Construct a response detailing Part requirements"""
|
||||||
|
|
||||||
|
part = self.get_object()
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"available_stock": part.available_stock,
|
||||||
|
"on_order": part.on_order,
|
||||||
|
"required_build_order_quantity": part.required_build_order_quantity(),
|
||||||
|
"allocated_build_order_quantity": part.build_order_allocation_count(),
|
||||||
|
"required_sales_order_quantity": part.required_sales_order_quantity(),
|
||||||
|
"allocated_sales_order_quantity": part.sales_order_allocation_count(pending=True),
|
||||||
|
}
|
||||||
|
|
||||||
|
data["allocated"] = data["allocated_build_order_quantity"] + data["allocated_sales_order_quantity"]
|
||||||
|
data["required"] = data["required_build_order_quantity"] + data["required_sales_order_quantity"]
|
||||||
|
|
||||||
|
return Response(data)
|
||||||
|
|
||||||
|
|
||||||
class PartMetadata(RetrieveUpdateAPI):
|
class PartMetadata(RetrieveUpdateAPI):
|
||||||
"""API endpoint for viewing / updating Part metadata."""
|
"""API endpoint for viewing / updating Part metadata."""
|
||||||
|
|
||||||
@ -1997,6 +2031,8 @@ part_api_urls = [
|
|||||||
# Endpoint for future scheduling information
|
# Endpoint for future scheduling information
|
||||||
re_path(r'^scheduling/', PartScheduling.as_view(), name='api-part-scheduling'),
|
re_path(r'^scheduling/', PartScheduling.as_view(), name='api-part-scheduling'),
|
||||||
|
|
||||||
|
re_path(r'^requirements/', PartRequirements.as_view(), name='api-part-requirements'),
|
||||||
|
|
||||||
# Endpoint for duplicating a BOM for the specific Part
|
# Endpoint for duplicating a BOM for the specific Part
|
||||||
re_path(r'^bom-copy/', PartCopyBOM.as_view(), name='api-part-bom-copy'),
|
re_path(r'^bom-copy/', PartCopyBOM.as_view(), name='api-part-bom-copy'),
|
||||||
|
|
||||||
|
@ -817,7 +817,7 @@ function orderParts(parts_list, options={}) {
|
|||||||
|
|
||||||
var thumb = thumbnailImage(part.thumbnail || part.image);
|
var thumb = thumbnailImage(part.thumbnail || part.image);
|
||||||
|
|
||||||
// The "quantity" field should have been provided for each part
|
// Default quantity value
|
||||||
var quantity = part.quantity || 1;
|
var quantity = part.quantity || 1;
|
||||||
|
|
||||||
if (quantity < 0) {
|
if (quantity < 0) {
|
||||||
@ -1017,6 +1017,29 @@ function orderParts(parts_list, options={}) {
|
|||||||
return '{% trans "No matching purchase orders" %}';
|
return '{% trans "No matching purchase orders" %}';
|
||||||
}
|
}
|
||||||
}, null, opts);
|
}, null, opts);
|
||||||
|
|
||||||
|
// Request 'requirements' information for each part
|
||||||
|
inventreeGet(`/api/part/${part.pk}/requirements/`, {}, {
|
||||||
|
success: function(response) {
|
||||||
|
var required = response.required || 0;
|
||||||
|
var allocated = response.allocated || 0;
|
||||||
|
var available = response.available_stock || 0;
|
||||||
|
|
||||||
|
// Based on what we currently 'have' on hand, what do we need to order?
|
||||||
|
var deficit = Math.max(required - allocated, 0);
|
||||||
|
|
||||||
|
if (available < deficit) {
|
||||||
|
var q = deficit - available;
|
||||||
|
|
||||||
|
updateFieldValue(
|
||||||
|
`quantity_${part.pk}`,
|
||||||
|
q,
|
||||||
|
{},
|
||||||
|
opts
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add callback for "add to purchase order" button
|
// Add callback for "add to purchase order" button
|
||||||
|
1
tasks.py
1
tasks.py
@ -105,6 +105,7 @@ def install(c):
|
|||||||
print("Installing required python packages from 'requirements.txt'")
|
print("Installing required python packages from 'requirements.txt'")
|
||||||
|
|
||||||
# Install required Python packages with PIP
|
# Install required Python packages with PIP
|
||||||
|
c.run('pip3 install --upgrade pip')
|
||||||
c.run('pip3 install --no-cache-dir --disable-pip-version-check -U -r requirements.txt')
|
c.run('pip3 install --no-cache-dir --disable-pip-version-check -U -r requirements.txt')
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user