mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge remote-tracking branch 'inventree/master' into partial-shipment
# Conflicts: # InvenTree/order/api.py
This commit is contained in:
commit
35b3bc73cc
60
.github/workflows/coverage.yaml
vendored
60
.github/workflows/coverage.yaml
vendored
@ -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
|
|
54
.github/workflows/html.yaml
vendored
54
.github/workflows/html.yaml
vendored
@ -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
|
|
||||||
|
|
51
.github/workflows/javascript.yaml
vendored
51
.github/workflows/javascript.yaml
vendored
@ -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
|
|
67
.github/workflows/mysql.yaml
vendored
67
.github/workflows/mysql.yaml
vendored
@ -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
|
|
70
.github/workflows/postgresql.yaml
vendored
70
.github/workflows/postgresql.yaml
vendored
@ -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
|
|
49
.github/workflows/python.yaml
vendored
49
.github/workflows/python.yaml
vendored
@ -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
312
.github/workflows/qc_checks.yaml
vendored
Normal 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
|
34
.github/workflows/style.yaml
vendored
34
.github/workflows/style.yaml
vendored
@ -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
|
|
20
.github/workflows/version.yaml
vendored
20
.github/workflows/version.yaml
vendored
@ -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
1
.gitignore
vendored
@ -77,5 +77,4 @@ dev/
|
|||||||
locale_stats.json
|
locale_stats.json
|
||||||
|
|
||||||
# node.js
|
# node.js
|
||||||
package-lock.json
|
|
||||||
node_modules/
|
node_modules/
|
@ -12,14 +12,18 @@ import common.models
|
|||||||
INVENTREE_SW_VERSION = "0.6.0 dev"
|
INVENTREE_SW_VERSION = "0.6.0 dev"
|
||||||
|
|
||||||
# InvenTree API version
|
# 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
|
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
|
- Adds support for multiple "Shipments" against a SalesOrder
|
||||||
- Refactors process for stock allocation 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
|
v19 -> 2021-12-02
|
||||||
- Adds the ability to filter the StockItem API by "part_tree"
|
- Adds the ability to filter the StockItem API by "part_tree"
|
||||||
- Returns only stock items which match a particular part.tree_id field
|
- Returns only stock items which match a particular part.tree_id field
|
||||||
|
@ -293,6 +293,7 @@ class POLineItemList(generics.ListCreateAPIView):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
kwargs['part_detail'] = str2bool(self.request.query_params.get('part_detail', False))
|
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:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -300,6 +301,28 @@ class POLineItemList(generics.ListCreateAPIView):
|
|||||||
|
|
||||||
return self.serializer_class(*args, **kwargs)
|
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 = [
|
filter_backends = [
|
||||||
rest_filters.DjangoFilterBackend,
|
rest_filters.DjangoFilterBackend,
|
||||||
filters.SearchFilter,
|
filters.SearchFilter,
|
||||||
|
@ -141,12 +141,17 @@ class POLineItemSerializer(InvenTreeModelSerializer):
|
|||||||
|
|
||||||
part_detail = kwargs.pop('part_detail', False)
|
part_detail = kwargs.pop('part_detail', False)
|
||||||
|
|
||||||
|
order_detail = kwargs.pop('order_detail', False)
|
||||||
|
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
if part_detail is not True:
|
if part_detail is not True:
|
||||||
self.fields.pop('part_detail')
|
self.fields.pop('part_detail')
|
||||||
self.fields.pop('supplier_part_detail')
|
self.fields.pop('supplier_part_detail')
|
||||||
|
|
||||||
|
if order_detail is not True:
|
||||||
|
self.fields.pop('order_detail')
|
||||||
|
|
||||||
quantity = serializers.FloatField(default=1)
|
quantity = serializers.FloatField(default=1)
|
||||||
received = serializers.FloatField(default=0)
|
received = serializers.FloatField(default=0)
|
||||||
|
|
||||||
@ -168,6 +173,8 @@ class POLineItemSerializer(InvenTreeModelSerializer):
|
|||||||
help_text=_('Purchase price currency'),
|
help_text=_('Purchase price currency'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
order_detail = POSerializer(source='order', read_only=True, many=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = order.models.PurchaseOrderLineItem
|
model = order.models.PurchaseOrderLineItem
|
||||||
|
|
||||||
@ -177,6 +184,7 @@ class POLineItemSerializer(InvenTreeModelSerializer):
|
|||||||
'reference',
|
'reference',
|
||||||
'notes',
|
'notes',
|
||||||
'order',
|
'order',
|
||||||
|
'order_detail',
|
||||||
'part',
|
'part',
|
||||||
'part_detail',
|
'part_detail',
|
||||||
'supplier_part_detail',
|
'supplier_part_detail',
|
||||||
|
@ -73,7 +73,7 @@
|
|||||||
<div class='panel-content'>
|
<div class='panel-content'>
|
||||||
<div id='po-button-bar'>
|
<div id='po-button-bar'>
|
||||||
<div class='button-toolbar container-fluid' style='float: right;'>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -703,12 +703,10 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
onPanelLoad("purchase-orders", function() {
|
onPanelLoad("purchase-orders", function() {
|
||||||
loadPurchaseOrderTable($("#purchase-order-table"), {
|
loadPartPurchaseOrderTable(
|
||||||
url: "{% url 'api-po-list' %}",
|
"#purchase-order-table",
|
||||||
params: {
|
{{ part.pk }},
|
||||||
part: {{ part.id }},
|
);
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onPanelLoad("sales-orders", function() {
|
onPanelLoad("sales-orders", function() {
|
||||||
|
@ -808,6 +808,13 @@ function loadPurchaseOrderTable(table, options) {
|
|||||||
|
|
||||||
var html = renderLink(value, `/order/purchase-order/${row.pk}/`);
|
var html = renderLink(value, `/order/purchase-order/${row.pk}/`);
|
||||||
|
|
||||||
|
html += purchaseOrderStatusDisplay(
|
||||||
|
row.status,
|
||||||
|
{
|
||||||
|
classes: 'float-right',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if (row.overdue) {
|
if (row.overdue) {
|
||||||
html += makeIconBadge('fa-calendar-times icon-red', '{% trans "Order is overdue" %}');
|
html += makeIconBadge('fa-calendar-times icon-red', '{% trans "Order is overdue" %}');
|
||||||
}
|
}
|
||||||
@ -832,14 +839,6 @@ function loadPurchaseOrderTable(table, options) {
|
|||||||
field: 'description',
|
field: 'description',
|
||||||
title: '{% trans "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',
|
field: 'creation_date',
|
||||||
title: '{% trans "Date" %}',
|
title: '{% trans "Date" %}',
|
||||||
@ -1149,7 +1148,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) {
|
|||||||
field: 'buttons',
|
field: 'buttons',
|
||||||
title: '',
|
title: '',
|
||||||
formatter: function(value, row, index, field) {
|
formatter: function(value, row, index, field) {
|
||||||
var html = `<div class='btn-group'>`;
|
var html = `<div class='btn-group' role='group'>`;
|
||||||
|
|
||||||
var pk = row.pk;
|
var pk = row.pk;
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
loadParametricPartTable,
|
loadParametricPartTable,
|
||||||
loadPartCategoryTable,
|
loadPartCategoryTable,
|
||||||
loadPartParameterTable,
|
loadPartParameterTable,
|
||||||
|
loadPartPurchaseOrderTable,
|
||||||
loadPartTable,
|
loadPartTable,
|
||||||
loadPartTestTemplateTable,
|
loadPartTestTemplateTable,
|
||||||
loadPartVariantTable,
|
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={}) {
|
function loadRelatedPartsTable(table, part_id, options={}) {
|
||||||
/*
|
/*
|
||||||
* Load table of "related" parts
|
* Load table of "related" parts
|
||||||
|
@ -6,10 +6,7 @@
|
|||||||
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
|
[![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)
|
[![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)
|
[![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)
|
![CI](https://github.com/inventree/inventree/actions/workflows/qc_checks.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)
|
|
||||||
|
|
||||||
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.
|
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
3788
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user