Merge remote-tracking branch 'inventree/master' into partial-shipment

# Conflicts:
#	InvenTree/order/api.py
This commit is contained in:
Oliver 2021-12-04 09:35:54 +11:00
commit 35b3bc73cc
18 changed files with 4326 additions and 428 deletions

View File

@ -1,60 +0,0 @@
# Perform CI checks, and calculate code coverage
name: SQLite
on:
push:
branches-ignore:
- l10*
pull_request:
branches-ignore:
- l10*
jobs:
# Run tests on SQLite database
# These tests are used for code coverage analysis
coverage:
runs-on: ubuntu-latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INVENTREE_DB_NAME: './test_db.sqlite'
INVENTREE_DB_ENGINE: django.db.backends.sqlite3
INVENTREE_DEBUG: info
INVENTREE_MEDIA_ROOT: ./media
INVENTREE_STATIC_ROOT: ./static
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: 3.7
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install gettext
pip3 install invoke
invoke install
invoke static
- name: Coverage Tests
run: |
invoke coverage
- name: Data Import Export
run: |
invoke migrate
invoke import-fixtures
invoke export-records -f data.json
rm test_db.sqlite
invoke migrate
invoke import-records -f data.json
invoke import-records -f data.json
- name: Test Translations
run: invoke translate
- name: Check Migration Files
run: python3 ci/check_migration_files.py
- name: Upload Coverage Report
run: coveralls

View File

@ -1,54 +0,0 @@
# Check javascript template files
name: HTML Templates
on:
push:
branches:
- master
pull_request:
branches-ignore:
- l10*
jobs:
html:
runs-on: ubuntu-latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INVENTREE_DB_ENGINE: sqlite3
INVENTREE_DB_NAME: inventree
INVENTREE_MEDIA_ROOT: ./media
INVENTREE_STATIC_ROOT: ./static
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Install node.js
uses: actions/setup-node@v2
with:
node-version: '16'
- run: npm install
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: 3.7
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install gettext
pip3 install invoke
invoke install
invoke static
- name: Check HTML Files
run: |
npx markuplint InvenTree/build/templates/build/*.html
npx markuplint InvenTree/company/templates/company/*.html
npx markuplint InvenTree/order/templates/order/*.html
npx markuplint InvenTree/part/templates/part/*.html
npx markuplint InvenTree/stock/templates/stock/*.html
npx markuplint InvenTree/templates/*.html
npx markuplint InvenTree/templates/InvenTree/*.html
npx markuplint InvenTree/templates/InvenTree/settings/*.html

View File

@ -1,51 +0,0 @@
# Check javascript template files
name: Javascript Templates
on:
push:
branches:
- master
pull_request:
branches-ignore:
- l10*
jobs:
javascript:
runs-on: ubuntu-latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INVENTREE_DB_ENGINE: sqlite3
INVENTREE_DB_NAME: inventree
INVENTREE_MEDIA_ROOT: ./media
INVENTREE_STATIC_ROOT: ./static
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Install node.js
uses: actions/setup-node@v2
with:
node-version: '16'
- run: npm install
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: 3.7
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install gettext
pip3 install invoke
invoke install
invoke static
- name: Check Templated Files
run: |
cd ci
python check_js_templates.py
- name: Lint Javascript Files
run: |
invoke render-js-files
npx eslint js_tmp/*.js

View File

@ -1,67 +0,0 @@
# MySQL Unit Testing
name: MySQL
on:
push:
branches-ignore:
- l10*
pull_request:
branches-ignore:
- l10*
jobs:
test:
runs-on: ubuntu-latest
env:
# Database backend configuration
INVENTREE_DB_ENGINE: django.db.backends.mysql
INVENTREE_DB_NAME: inventree
INVENTREE_DB_USER: root
INVENTREE_DB_PASSWORD: password
INVENTREE_DB_HOST: '127.0.0.1'
INVENTREE_DB_PORT: 3306
INVENTREE_DEBUG: info
INVENTREE_MEDIA_ROOT: ./media
INVENTREE_STATIC_ROOT: ./static
services:
mysql:
image: mysql:latest
env:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: inventree
MYSQL_USER: inventree
MYSQL_PASSWORD: password
MYSQL_ROOT_PASSWORD: password
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
ports:
- 3306:3306
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: 3.7
- name: Install Dependencies
run: |
sudo apt-get install mysql-server libmysqlclient-dev
pip3 install invoke
pip3 install mysqlclient
invoke install
- name: Run Tests
run: invoke test
- name: Data Import Export
run: |
invoke migrate
python3 ./InvenTree/manage.py flush --noinput
invoke import-fixtures
invoke export-records -f data.json
python3 ./InvenTree/manage.py flush --noinput
invoke import-records -f data.json
invoke import-records -f data.json

View File

@ -1,70 +0,0 @@
# PostgreSQL Unit Testing
name: PostgreSQL
on:
push:
branches-ignore:
- l10*
pull_request:
branches-ignore:
- l10*
jobs:
test:
runs-on: ubuntu-latest
env:
# Database backend configuration
INVENTREE_DB_ENGINE: django.db.backends.postgresql
INVENTREE_DB_NAME: inventree
INVENTREE_DB_USER: inventree
INVENTREE_DB_PASSWORD: password
INVENTREE_DB_HOST: '127.0.0.1'
INVENTREE_DB_PORT: 5432
INVENTREE_DEBUG: info
INVENTREE_MEDIA_ROOT: ./media
INVENTREE_STATIC_ROOT: ./static
INVENTREE_CACHE_HOST: localhost
services:
postgres:
image: postgres
env:
POSTGRES_USER: inventree
POSTGRES_PASSWORD: password
ports:
- 5432:5432
redis:
image: redis
ports:
- 6379:6379
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: 3.7
- name: Install Dependencies
run: |
sudo apt-get install libpq-dev
pip3 install invoke
pip3 install psycopg2
pip3 install django-redis>=5.0.0
invoke install
- name: Run Tests
run: invoke test
- name: Data Import Export
run: |
invoke migrate
python3 ./InvenTree/manage.py flush --noinput
invoke import-fixtures
invoke export-records -f data.json
python3 ./InvenTree/manage.py flush --noinput
invoke import-records -f data.json
invoke import-records -f data.json

View File

@ -1,49 +0,0 @@
# Run python library tests whenever code is pushed to master
name: Python Bindings
on:
push:
branches:
- master
pull_request:
branches-ignore:
- l10*
jobs:
python:
runs-on: ubuntu-latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INVENTREE_DB_NAME: './test_db.sqlite'
INVENTREE_DB_ENGINE: 'sqlite3'
INVENTREE_DEBUG: info
INVENTREE_MEDIA_ROOT: ./media
INVENTREE_STATIC_ROOT: ./static
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Install InvenTree
run: |
sudo apt-get update
sudo apt-get install python3-dev python3-pip python3-venv
pip3 install invoke
invoke install
invoke migrate
- name: Download Python Code
run: |
git clone --depth 1 https://github.com/inventree/inventree-python ./inventree-python
- name: Start Server
run: |
invoke import-records -f ./inventree-python/test/test_data.json
invoke server -a 127.0.0.1:8000 &
sleep 60
- name: Run Tests
run: |
cd inventree-python
invoke test

312
.github/workflows/qc_checks.yaml vendored Normal file
View File

@ -0,0 +1,312 @@
# Checks for each PR / push
name: QC checks
on:
push:
branches-ignore:
- l10*
pull_request:
branches-ignore:
- l10*
env:
python_version: 3.7
node_version: 16
server_start_sleep: 60
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INVENTREE_DB_ENGINE: sqlite3
INVENTREE_DB_NAME: inventree
INVENTREE_MEDIA_ROOT: ./media
INVENTREE_STATIC_ROOT: ./static
jobs:
check_version:
name: version number
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Check version number
run: |
python3 ci/check_version_number.py --branch ${{ github.base_ref }}
pep_style:
name: PEP style (python)
needs: check_version
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Python ${{ env.python_version }}
uses: actions/setup-python@v2
with:
python-version: ${{ env.python_version }}
cache: 'pip'
- name: Install deps
run: |
pip install flake8==3.8.3
pip install pep8-naming==0.11.1
- name: flake8
run: |
flake8 InvenTree
javascript:
name: javascript template files
needs: pep_style
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Install node.js ${{ env.node_version }}
uses: actions/setup-node@v2
with:
node-version: ${{ env.node_version }}
cache: 'npm'
- run: npm install
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: ${{ env.python_version }}
cache: 'pip'
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install gettext
pip3 install invoke
invoke install
invoke static
- name: Check Templated Files
run: |
cd ci
python check_js_templates.py
- name: Lint Javascript Files
run: |
invoke render-js-files
npx eslint js_tmp/*.js
html:
name: html template files
needs: pep_style
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Install node.js ${{ env.node_version }}
uses: actions/setup-node@v2
with:
node-version: ${{ env.node_version }}
cache: 'npm'
- run: npm install
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: ${{ env.python_version }}
cache: 'pip'
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install gettext
pip3 install invoke
invoke install
invoke static
- name: Check HTML Files
run: |
npx markuplint InvenTree/build/templates/build/*.html
npx markuplint InvenTree/company/templates/company/*.html
npx markuplint InvenTree/order/templates/order/*.html
npx markuplint InvenTree/part/templates/part/*.html
npx markuplint InvenTree/stock/templates/stock/*.html
npx markuplint InvenTree/templates/*.html
npx markuplint InvenTree/templates/InvenTree/*.html
npx markuplint InvenTree/templates/InvenTree/settings/*.html
python:
name: python bindings
needs: pep_style
runs-on: ubuntu-latest
env:
wrapper_name: inventree-python
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Install InvenTree
run: |
sudo apt-get update
sudo apt-get install python3-dev python3-pip python3-venv
pip3 install invoke
invoke install
invoke migrate
- name: Download Python Code
run: |
git clone --depth 1 https://github.com/inventree/${{ env.wrapper_name }} ./${{ env.wrapper_name }}
- name: Start Server
run: |
invoke import-records -f ./${{ env.wrapper_name }}/test/test_data.json
invoke server -a 127.0.0.1:8000 &
sleep ${{ env.server_start_sleep }}
- name: Run Tests
run: |
cd ${{ env.wrapper_name }}
invoke test
coverage:
name: Sqlite / coverage
needs: ['javascript', 'html']
runs-on: ubuntu-latest
env:
INVENTREE_DB_NAME: ./inventree.sqlite
INVENTREE_DB_ENGINE: sqlite3
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Setup Python ${{ env.python_version }}
uses: actions/setup-python@v2
with:
python-version: ${{ env.python_version }}
cache: 'pip'
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install gettext
pip3 install invoke
invoke install
invoke static
- name: Coverage Tests
run: |
invoke coverage
- name: Data Import Export
run: |
invoke migrate
invoke import-fixtures
invoke export-records -f data.json
rm inventree.sqlite
invoke migrate
invoke import-records -f data.json
invoke import-records -f data.json
- name: Test Translations
run: invoke translate
- name: Check Migration Files
run: python3 ci/check_migration_files.py
- name: Upload Coverage Report
run: coveralls
postgres:
name: Postgres
needs: ['javascript', 'html']
runs-on: ubuntu-latest
env:
INVENTREE_DB_ENGINE: django.db.backends.postgresql
INVENTREE_DB_USER: inventree
INVENTREE_DB_PASSWORD: password
INVENTREE_DB_HOST: '127.0.0.1'
INVENTREE_DB_PORT: 5432
INVENTREE_DEBUG: info
INVENTREE_CACHE_HOST: localhost
services:
postgres:
image: postgres
env:
POSTGRES_USER: inventree
POSTGRES_PASSWORD: password
ports:
- 5432:5432
redis:
image: redis
ports:
- 6379:6379
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Setup Python ${{ env.python_version }}
uses: actions/setup-python@v2
with:
python-version: ${{ env.python_version }}
cache: 'pip'
- name: Install Dependencies
run: |
sudo apt-get install libpq-dev
pip3 install invoke
pip3 install psycopg2
pip3 install django-redis>=5.0.0
invoke install
- name: Run Tests
run: invoke test
- name: Data Import Export
run: |
invoke migrate
python3 ./InvenTree/manage.py flush --noinput
invoke import-fixtures
invoke export-records -f data.json
python3 ./InvenTree/manage.py flush --noinput
invoke import-records -f data.json
invoke import-records -f data.json
mysql:
name: MySql
needs: ['javascript', 'html']
runs-on: ubuntu-latest
env:
# Database backend configuration
INVENTREE_DB_ENGINE: django.db.backends.mysql
INVENTREE_DB_USER: root
INVENTREE_DB_PASSWORD: password
INVENTREE_DB_HOST: '127.0.0.1'
INVENTREE_DB_PORT: 3306
INVENTREE_DEBUG: info
services:
mysql:
image: mysql:latest
env:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: ${{ env.INVENTREE_DB_NAME }}
MYSQL_USER: inventree
MYSQL_PASSWORD: password
MYSQL_ROOT_PASSWORD: password
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
ports:
- 3306:3306
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Setup Python ${{ env.python_version }}
uses: actions/setup-python@v2
with:
python-version: ${{ env.python_version }}
cache: 'pip'
- name: Install Dependencies
run: |
sudo apt-get install mysql-server libmysqlclient-dev
pip3 install invoke
pip3 install mysqlclient
invoke install
- name: Run Tests
run: invoke test
- name: Data Import Export
run: |
invoke migrate
python3 ./InvenTree/manage.py flush --noinput
invoke import-fixtures
invoke export-records -f data.json
python3 ./InvenTree/manage.py flush --noinput
invoke import-records -f data.json
invoke import-records -f data.json

View File

@ -1,34 +0,0 @@
name: Style Checks
on:
push:
branches-ignore:
- l10*
pull_request:
branches-ignore:
- l10*
jobs:
style:
runs-on: ubuntu-latest
strategy:
max-parallel: 4
matrix:
python-version: [3.7]
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install deps
run: |
pip install flake8==3.8.3
pip install pep8-naming==0.11.1
- name: flake8
run: |
flake8 InvenTree

View File

@ -1,20 +0,0 @@
# Check that the version number format matches the current branch
name: Version Numbering
on:
pull_request:
branches-ignore:
- l10*
jobs:
check:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Check version number
run: |
python3 ci/check_version_number.py --branch ${{ github.base_ref }}

1
.gitignore vendored
View File

@ -77,5 +77,4 @@ dev/
locale_stats.json
# node.js
package-lock.json
node_modules/

View File

@ -12,14 +12,18 @@ import common.models
INVENTREE_SW_VERSION = "0.6.0 dev"
# InvenTree API version
INVENTREE_API_VERSION = 19
INVENTREE_API_VERSION = 21
"""
Increment this API version number whenever there is a significant change to the API that any clients need to know about
v19 -> 2021-11-16
v21 -> 2021-12-04
- Adds support for multiple "Shipments" against a SalesOrder
- Refactors process for stock allocation against a SalesOrder
v20 -> 2021-12-03
- Adds ability to filter POLineItem endpoint by "base_part"
- Adds optional "order_detail" to POLineItem list endpoint
v19 -> 2021-12-02
- Adds the ability to filter the StockItem API by "part_tree"
- Returns only stock items which match a particular part.tree_id field

View File

@ -293,6 +293,7 @@ class POLineItemList(generics.ListCreateAPIView):
try:
kwargs['part_detail'] = str2bool(self.request.query_params.get('part_detail', False))
kwargs['order_detail'] = str2bool(self.request.query_params.get('order_detail', False))
except AttributeError:
pass
@ -300,6 +301,28 @@ class POLineItemList(generics.ListCreateAPIView):
return self.serializer_class(*args, **kwargs)
def filter_queryset(self, queryset):
"""
Additional filtering options
"""
params = self.request.query_params
queryset = super().filter_queryset(queryset)
base_part = params.get('base_part', None)
if base_part:
try:
base_part = Part.objects.get(pk=base_part)
queryset = queryset.filter(part__part=base_part)
except (ValueError, Part.DoesNotExist):
pass
return queryset
filter_backends = [
rest_filters.DjangoFilterBackend,
filters.SearchFilter,

View File

@ -141,12 +141,17 @@ class POLineItemSerializer(InvenTreeModelSerializer):
part_detail = kwargs.pop('part_detail', False)
order_detail = kwargs.pop('order_detail', False)
super().__init__(*args, **kwargs)
if part_detail is not True:
self.fields.pop('part_detail')
self.fields.pop('supplier_part_detail')
if order_detail is not True:
self.fields.pop('order_detail')
quantity = serializers.FloatField(default=1)
received = serializers.FloatField(default=0)
@ -168,6 +173,8 @@ class POLineItemSerializer(InvenTreeModelSerializer):
help_text=_('Purchase price currency'),
)
order_detail = POSerializer(source='order', read_only=True, many=False)
class Meta:
model = order.models.PurchaseOrderLineItem
@ -177,6 +184,7 @@ class POLineItemSerializer(InvenTreeModelSerializer):
'reference',
'notes',
'order',
'order_detail',
'part',
'part_detail',
'supplier_part_detail',

View File

@ -73,7 +73,7 @@
<div class='panel-content'>
<div id='po-button-bar'>
<div class='button-toolbar container-fluid' style='float: right;'>
{% include "filter_list.html" with id="purchaseorder" %}
{% include "filter_list.html" with id="partpurchaseorders" %}
</div>
</div>
@ -703,12 +703,10 @@
});
onPanelLoad("purchase-orders", function() {
loadPurchaseOrderTable($("#purchase-order-table"), {
url: "{% url 'api-po-list' %}",
params: {
part: {{ part.id }},
},
});
loadPartPurchaseOrderTable(
"#purchase-order-table",
{{ part.pk }},
);
});
onPanelLoad("sales-orders", function() {

View File

@ -808,6 +808,13 @@ function loadPurchaseOrderTable(table, options) {
var html = renderLink(value, `/order/purchase-order/${row.pk}/`);
html += purchaseOrderStatusDisplay(
row.status,
{
classes: 'float-right',
}
);
if (row.overdue) {
html += makeIconBadge('fa-calendar-times icon-red', '{% trans "Order is overdue" %}');
}
@ -832,14 +839,6 @@ function loadPurchaseOrderTable(table, options) {
field: 'description',
title: '{% trans "Description" %}',
},
{
field: 'status',
title: '{% trans "Status" %}',
sortable: true,
formatter: function(value, row) {
return purchaseOrderStatusDisplay(row.status, row.status_text);
}
},
{
field: 'creation_date',
title: '{% trans "Date" %}',
@ -1149,7 +1148,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) {
field: 'buttons',
title: '',
formatter: function(value, row, index, field) {
var html = `<div class='btn-group'>`;
var html = `<div class='btn-group' role='group'>`;
var pk = row.pk;

View File

@ -29,6 +29,7 @@
loadParametricPartTable,
loadPartCategoryTable,
loadPartParameterTable,
loadPartPurchaseOrderTable,
loadPartTable,
loadPartTestTemplateTable,
loadPartVariantTable,
@ -712,6 +713,180 @@ function loadPartParameterTable(table, url, options) {
}
/*
* Construct a table showing a list of purchase orders for a given part.
*
* This requests API data from the PurchaseOrderLineItem endpoint
*/
function loadPartPurchaseOrderTable(table, part_id, options={}) {
options.params = options.params || {};
// Construct API filterset
options.params.base_part = part_id;
options.params.part_detail = true;
options.params.order_detail = true;
var filters = loadTableFilters('partpurchaseorders');
for (var key in options.params) {
filters[key] = options.params[key];
}
setupFilterList('purchaseorderlineitem', $(table), '#filter-list-partpurchaseorders');
$(table).inventreeTable({
url: '{% url "api-po-line-list" %}',
queryParams: filters,
name: 'partpurchaseorders',
original: options.params,
showColumns: true,
uniqueId: 'pk',
formatNoMatches: function() {
return '{% trans "No purchase orders found" %}';
},
onPostBody: function() {
$(table).find('.button-line-receive').click(function() {
var pk = $(this).attr('pk');
var line_item = $(table).bootstrapTable('getRowByUniqueId', pk);
if (!line_item) {
console.log('WARNING: getRowByUniqueId returned null');
return;
}
receivePurchaseOrderItems(
line_item.order,
[
line_item,
],
{
success: function() {
$(table).bootstrapTable('refresh');
}
}
);
});
},
columns: [
{
field: 'order',
title: '{% trans "Purchase Order" %}',
switchable: false,
formatter: function(value, row) {
var order = row.order_detail;
if (!order) {
return '-';
}
var ref = global_settings.PURCHASEORDER_REFERENCE_PREFIX + order.reference;
var html = renderLink(ref, `/order/purchase-order/${order.pk}/`);
html += purchaseOrderStatusDisplay(
order.status,
{
classes: 'float-right',
}
);
return html;
},
},
{
field: 'supplier',
title: '{% trans "Supplier" %}',
switchable: true,
formatter: function(value, row) {
if (row.supplier_part_detail && row.supplier_part_detail.supplier_detail) {
var supp = row.supplier_part_detail.supplier_detail;
var html = imageHoverIcon(supp.thumbnail || supp.image);
html += ' ' + renderLink(supp.name, `/company/${supp.pk}/`);
return html;
} else {
return '-';
}
}
},
{
field: 'sku',
title: '{% trans "SKU" %}',
switchable: true,
formatter: function(value, row) {
if (row.supplier_part_detail) {
var supp = row.supplier_part_detail;
return renderLink(supp.SKU, `/supplier-part/${supp.pk}/`);
} else {
return '-';
}
},
},
{
field: 'mpn',
title: '{% trans "MPN" %}',
switchable: true,
formatter: function(value, row) {
if (row.supplier_part_detail && row.supplier_part_detail.manufacturer_part_detail) {
var manu = row.supplier_part_detail.manufacturer_part_detail;
return renderLink(manu.MPN, `/manufacturer-part/${manu.pk}/`);
}
}
},
{
field: 'quantity',
title: '{% trans "Quantity" %}',
},
{
field: 'received',
title: '{% trans "Received" %}',
switchable: true,
},
{
field: 'purchase_price',
title: '{% trans "Price" %}',
switchable: true,
formatter: function(value, row) {
var formatter = new Intl.NumberFormat(
'en-US',
{
style: 'currency',
currency: row.purchase_price_currency,
}
);
return formatter.format(row.purchase_price);
}
},
{
field: 'actions',
title: '',
formatter: function(value, row) {
if (row.received >= row.quantity) {
// Already recevied
return `<span class='badge bg-success rounded-pill'>{% trans "Received" %}</span>`;
} else {
var html = `<div class='btn-group' role='group'>`;
var pk = row.pk;
html += makeIconButton('fa-sign-in-alt', 'button-line-receive', pk, '{% trans "Receive line item" %}');
html += `</div>`;
return html;
}
}
}
],
});
}
function loadRelatedPartsTable(table, part_id, options={}) {
/*
* Load table of "related" parts

View File

@ -6,10 +6,7 @@
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Coverage Status](https://coveralls.io/repos/github/inventree/InvenTree/badge.svg)](https://coveralls.io/github/inventree/InvenTree)
[![Crowdin](https://badges.crowdin.net/inventree/localized.svg)](https://crowdin.com/project/inventree)
![PEP](https://github.com/inventree/inventree/actions/workflows/style.yaml/badge.svg)
![SQLite](https://github.com/inventree/inventree/actions/workflows/coverage.yaml/badge.svg)
![MySQL](https://github.com/inventree/inventree/actions/workflows/mysql.yaml/badge.svg)
![PostgreSQL](https://github.com/inventree/inventree/actions/workflows/postgresql.yaml/badge.svg)
![CI](https://github.com/inventree/inventree/actions/workflows/qc_checks.yaml/badge.svg)
InvenTree is an open-source Inventory Management System which provides powerful low-level stock control and part tracking. The core of the InvenTree system is a Python/Django database backend which provides an admin interface (web-based) and a JSON API for interaction with external interfaces and applications.

3788
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff