Merge branch 'master' of https://github.com/inventree/InvenTree into pr/ChristianSchindler/6305

This commit is contained in:
Matthias Mair 2024-04-03 19:02:05 +02:00
commit 785aff0ae2
No known key found for this signature in database
GPG Key ID: A593429DDA23B66A
3331 changed files with 1456 additions and 1420 deletions

View File

@ -16,6 +16,7 @@ services:
inventree: inventree:
build: build:
context: .. context: ..
dockerfile: ../InvenTree/contrib/container/Dockerfile
target: dev target: dev
args: args:
base_image: "mcr.microsoft.com/vscode/devcontainers/base:alpine-3.18" base_image: "mcr.microsoft.com/vscode/devcontainers/base:alpine-3.18"

3
.git-blame-ignore-revs Normal file
View File

@ -0,0 +1,3 @@
# .git-blame-ignore-revs
# Code Structure refactor https://github.com/inventree/InvenTree/pull/5582
0bace3f3afaa213c63b5dcc70103f0d232637a9a

11
.github/CODEOWNERS vendored
View File

@ -1,2 +1,13 @@
# General owner is the maintainers team # General owner is the maintainers team
* @SchrodingersGat * @SchrodingersGat
# plugins are co-owned
/src/backend/InvenTree/plugin/ @SchrodingersGat @matmair
/src/backend/InvenTree/plugins/ @SchrodingersGat @matmair
# Installer functions
.pkgr.yml @matmair
Procfile @matmair
runtime.txt @matmair
/contrib/installer @matmair
/contrib/packager.io @matmair

View File

@ -11,7 +11,7 @@ runs:
invoke migrate invoke migrate
invoke import-fixtures invoke import-fixtures
invoke export-records -f data.json invoke export-records -f data.json
python3 ./InvenTree/manage.py flush --noinput python3 ./src/backend/InvenTree/manage.py flush --noinput
invoke migrate invoke migrate
invoke import-records -f data.json invoke import-records -f data.json
invoke import-records -f data.json invoke import-records -f data.json

View File

@ -65,10 +65,11 @@ runs:
with: with:
node-version: ${{ env.node_version }} node-version: ${{ env.node_version }}
cache: 'npm' cache: 'npm'
cache-dependency-path: src/backend/package-lock.json
- name: Install npm packages - name: Install npm packages
if: ${{ inputs.npm == 'true' }} if: ${{ inputs.npm == 'true' }}
shell: bash shell: bash
run: npm install run: cd src/backend && npm install
# OS installs # OS installs
- name: Install OS Dependencies - name: Install OS Dependencies
@ -77,12 +78,13 @@ runs:
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install ${{ inputs.apt-dependency }} sudo apt-get install ${{ inputs.apt-dependency }}
sudo apt-get install ${{ inputs.apt-dependency }}
# Invoke commands # Invoke commands
- name: Install dev requirements - name: Install dev requirements
if: ${{ inputs.dev-install == 'true' ||inputs.install == 'true' }} if: ${{ inputs.dev-install == 'true' ||inputs.install == 'true' }}
shell: bash shell: bash
run: uv pip install -r requirements-dev.txt run: uv pip install -r src/backend/requirements-dev.txt
- name: Run invoke install - name: Run invoke install
if: ${{ inputs.install == 'true' }} if: ${{ inputs.install == 'true' }}
shell: bash shell: bash

View File

@ -3,34 +3,34 @@ updates:
- package-ecosystem: github-actions - package-ecosystem: github-actions
directory: / directory: /
schedule: schedule:
interval: daily interval: weekly
- package-ecosystem: docker - package-ecosystem: docker
directory: / directory: /contrib/container
schedule: schedule:
interval: daily interval: weekly
- package-ecosystem: pip - package-ecosystem: pip
directory: /docker directory: /contrib/container
schedule: schedule:
interval: daily interval: weekly
- package-ecosystem: pip - package-ecosystem: pip
directory: /docs directory: /docs
schedule: schedule:
interval: daily interval: weekly
- package-ecosystem: npm - package-ecosystem: npm
directory: / directory: /src/backend
schedule: schedule:
interval: daily interval: weekly
- package-ecosystem: pip - package-ecosystem: pip
directory: / directory: /src/backend
schedule: schedule:
interval: daily interval: weekly
- package-ecosystem: npm - package-ecosystem: npm
directory: /src/frontend directory: /src/frontend
schedule: schedule:
interval: daily interval: weekly

View File

@ -92,7 +92,9 @@ def check_version_number(version_string, allow_duplicate=False):
if __name__ == '__main__': if __name__ == '__main__':
if 'only_version' in sys.argv: if 'only_version' in sys.argv:
here = Path(__file__).parent.absolute() here = Path(__file__).parent.absolute()
version_file = here.joinpath('..', 'InvenTree', 'InvenTree', 'api_version.py') version_file = here.joinpath(
'..', '..', 'src', 'backend', 'InvenTree', 'InvenTree', 'api_version.py'
)
text = version_file.read_text() text = version_file.read_text()
results = re.findall(r"""INVENTREE_API_VERSION = (.*)""", text) results = re.findall(r"""INVENTREE_API_VERSION = (.*)""", text)
print(results[0]) print(results[0])
@ -114,7 +116,9 @@ if __name__ == '__main__':
print(f'GITHUB_BASE_REF: {GITHUB_BASE_REF}') print(f'GITHUB_BASE_REF: {GITHUB_BASE_REF}')
here = Path(__file__).parent.absolute() here = Path(__file__).parent.absolute()
version_file = here.joinpath('..', 'InvenTree', 'InvenTree', 'version.py') version_file = here.joinpath(
'..', '..', 'src', 'backend', 'InvenTree', 'InvenTree', 'version.py'
)
version = None version = None

View File

@ -40,4 +40,4 @@ jobs:
- name: Test Translations - name: Test Translations
run: invoke translate run: invoke translate
- name: Check Migration Files - name: Check Migration Files
run: python3 ci/check_migration_files.py run: python3 .github/scripts/check_migration_files.py

View File

@ -78,26 +78,26 @@ jobs:
run: | run: |
pip install requests==2.31.0 pip install requests==2.31.0
pip install pyyaml==6.0.1 pip install pyyaml==6.0.1
python3 ci/version_check.py python3 .github/scripts/version_check.py
echo "git_commit_hash=$(git rev-parse --short HEAD)" >> $GITHUB_ENV echo "git_commit_hash=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
echo "git_commit_date=$(git show -s --format=%ci)" >> $GITHUB_ENV echo "git_commit_date=$(git show -s --format=%ci)" >> $GITHUB_ENV
- name: Test Docker Image - name: Test Docker Image
id: test-docker id: test-docker
run: | run: |
docker build . --target production --tag inventree-test docker build . --target production --tag inventree-test -f contrib/container/Dockerfile
docker run --rm inventree-test invoke --version docker run --rm inventree-test invoke --version
docker run --rm inventree-test invoke --list docker run --rm inventree-test invoke --list
docker run --rm inventree-test gunicorn --version docker run --rm inventree-test gunicorn --version
docker run --rm inventree-test pg_dump --version docker run --rm inventree-test pg_dump --version
- name: Build Docker Image - name: Build Docker Image
# Build the development docker image (using docker-compose.yml) # Build the development docker image (using docker-compose.yml)
run: docker-compose build --no-cache run: docker compose --project-directory . -f contrib/container/dev-docker-compose.yml build --no-cache
- name: Update Docker Image - name: Update Docker Image
run: | run: |
docker-compose run inventree-dev-server invoke update docker compose --project-directory . -f contrib/container/dev-docker-compose.yml run inventree-dev-server invoke update
docker-compose run inventree-dev-server invoke setup-dev docker compose --project-directory . -f contrib/container/dev-docker-compose.yml run inventree-dev-server invoke setup-dev
docker-compose up -d docker compose --project-directory . -f contrib/container/dev-docker-compose.yml up -d
docker-compose run inventree-dev-server invoke wait docker compose --project-directory . -f contrib/container/dev-docker-compose.yml run inventree-dev-server invoke wait
- name: Check Data Directory - name: Check Data Directory
# The following file structure should have been created by the docker image # The following file structure should have been created by the docker image
run: | run: |
@ -112,10 +112,10 @@ jobs:
test -f data/secret_key.txt test -f data/secret_key.txt
- name: Run Unit Tests - name: Run Unit Tests
run: | run: |
echo "GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}" >> docker.dev.env echo "GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}" >> contrib/container/docker.dev.env
docker-compose run inventree-dev-server invoke test --disable-pty docker compose --project-directory . -f contrib/container/dev-docker-compose.yml run inventree-dev-server invoke test --disable-pty
docker-compose run inventree-dev-server invoke test --migrations --disable-pty docker compose --project-directory . -f contrib/container/dev-docker-compose.yml run inventree-dev-server invoke test --migrations --disable-pty
docker-compose down docker compose --project-directory . -f contrib/container/dev-docker-compose.yml down
- name: Clean up test folder - name: Clean up test folder
run: | run: |
rm -rf InvenTree/_testfolder rm -rf InvenTree/_testfolder
@ -166,6 +166,7 @@ jobs:
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # pin@v5.3.0 uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # pin@v5.3.0
with: with:
context: . context: .
file: ./contrib/container/Dockerfile
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
push: true push: true
sbom: true sbom: true

View File

@ -42,9 +42,9 @@ jobs:
with: with:
filters: | filters: |
server: server:
- 'InvenTree/**' - 'src/backend/InvenTree/**'
- 'requirements.txt' - 'src/backend/requirements.txt'
- 'requirements-dev.txt' - 'src/backend/requirements-dev.txt'
migrations: migrations:
- '**/migrations/**' - '**/migrations/**'
- '.github/workflows**' - '.github/workflows**'
@ -68,12 +68,12 @@ jobs:
install: true install: true
- name: Check Templated JS Files - name: Check Templated JS Files
run: | run: |
cd ci cd .github/scripts
python3 check_js_templates.py python3 check_js_templates.py
- name: Lint Javascript Files - name: Lint Javascript Files
run: | run: |
python InvenTree/manage.py prerender python src/backend/InvenTree/manage.py prerender
npx eslint InvenTree/InvenTree/static_i18n/i18n/*.js npx eslint src/backend/InvenTree/InvenTree/static_i18n/i18n/*.js
pre-commit: pre-commit:
name: Style [pre-commit] name: Style [pre-commit]
@ -93,7 +93,7 @@ jobs:
- name: Check Version - name: Check Version
run: | run: |
pip install requests==2.31.0 pip install requests==2.31.0
python3 ci/version_check.py python3 .github/scripts/version_check.py
mkdocs: mkdocs:
name: Style [Documentation] name: Style [Documentation]
@ -147,17 +147,17 @@ jobs:
dev-install: true dev-install: true
update: true update: true
- name: Export API Documentation - name: Export API Documentation
run: invoke schema --ignore-warnings --filename InvenTree/schema.yml run: invoke schema --ignore-warnings --filename src/backend/InvenTree/schema.yml
- name: Upload schema - name: Upload schema
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # pin@v4.3.1 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # pin@v4.3.1
with: with:
name: schema.yml name: schema.yml
path: InvenTree/schema.yml path: src/backend/InvenTree/schema.yml
- name: Download public schema - name: Download public schema
if: needs.paths-filter.outputs.api == 'false' if: needs.paths-filter.outputs.api == 'false'
run: | run: |
pip install requests==2.31.0 >/dev/null 2>&1 pip install requests==2.31.0 >/dev/null 2>&1
version="$(python3 ci/version_check.py only_version 2>&1)" version="$(python3 .github/scripts/version_check.py only_version 2>&1)"
echo "Version: $version" echo "Version: $version"
url="https://raw.githubusercontent.com/inventree/schema/main/export/${version}/api.yaml" url="https://raw.githubusercontent.com/inventree/schema/main/export/${version}/api.yaml"
echo "URL: $url" echo "URL: $url"
@ -166,8 +166,8 @@ jobs:
- name: Check for differences in API Schema - name: Check for differences in API Schema
if: needs.paths-filter.outputs.api == 'false' if: needs.paths-filter.outputs.api == 'false'
run: | run: |
diff --color -u InvenTree/schema.yml api.yaml diff --color -u src/backend/InvenTree/schema.yml api.yaml
diff -u InvenTree/schema.yml api.yaml && echo "no difference in API schema " || exit 2 diff -u src/backend/InvenTree/schema.yml api.yaml && echo "no difference in API schema " || exit 2
- name: Check schema - including warnings - name: Check schema - including warnings
run: invoke schema run: invoke schema
continue-on-error: true continue-on-error: true
@ -176,7 +176,7 @@ jobs:
if: github.ref == 'refs/heads/master' && needs.paths-filter.outputs.api == 'true' if: github.ref == 'refs/heads/master' && needs.paths-filter.outputs.api == 'true'
run: | run: |
pip install requests==2.31.0 >/dev/null 2>&1 pip install requests==2.31.0 >/dev/null 2>&1
version="$(python3 ci/version_check.py only_version 2>&1)" version="$(python3 .github/scripts/version_check.py only_version 2>&1)"
echo "Version: $version" echo "Version: $version"
echo "version=$version" >> "$GITHUB_OUTPUT" echo "version=$version" >> "$GITHUB_OUTPUT"
@ -273,13 +273,15 @@ jobs:
- name: Test Translations - name: Test Translations
run: invoke translate run: invoke translate
- name: Check Migration Files - name: Check Migration Files
run: python3 ci/check_migration_files.py run: python3 .github/scripts/check_migration_files.py
- name: Coverage Tests - name: Coverage Tests
run: invoke test --coverage run: invoke test --coverage
- name: Upload Coverage Report - name: Upload Coverage Report
uses: coverallsapp/github-action@3dfc5567390f6fa9267c0ee9c251e4c8c3f18949 # pin@v2.2.3 uses: coverallsapp/github-action@3dfc5567390f6fa9267c0ee9c251e4c8c3f18949 # pin@v2.2.3
with: with:
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
flag-name: backend
parallel: true
postgres: postgres:
name: Tests - DB [PostgreSQL] name: Tests - DB [PostgreSQL]
@ -471,6 +473,7 @@ jobs:
INVENTREE_DB_NAME: /home/runner/work/InvenTree/db.sqlite3 INVENTREE_DB_NAME: /home/runner/work/InvenTree/db.sqlite3
INVENTREE_DEBUG: True INVENTREE_DEBUG: True
INVENTREE_PLUGINS_ENABLED: false INVENTREE_PLUGINS_ENABLED: false
VITE_COVERAGE: true
steps: steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # pin@v4.1.1 - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # pin@v4.1.1
@ -487,13 +490,31 @@ jobs:
- name: Install Playwright Browsers - name: Install Playwright Browsers
run: cd src/frontend && npx playwright install --with-deps run: cd src/frontend && npx playwright install --with-deps
- name: Run Playwright tests - name: Run Playwright tests
run: cd src/frontend && npx playwright test run: cd src/frontend && npx nyc playwright test
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # pin@v4.3.1 - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # pin@v4.3.1
name: Upload playwright report
if: always() if: always()
with: with:
name: playwright-report name: playwright-report
path: src/frontend/playwright-report/ path: src/frontend/playwright-report/
retention-days: 30 retention-days: 30
- name: Report coverage
if: always()
run: cd src/frontend && npx nyc report --report-dir ./coverage --temp-dir .nyc_output --reporter=lcov --exclude-after-remap false
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # pin@v4.3.1
name: Upload coverage report
if: always()
with:
name: coverage
path: src/frontend/coverage/
retention-days: 30
- name: Upload Coverage Report
if: always()
uses: coverallsapp/github-action@3dfc5567390f6fa9267c0ee9c251e4c8c3f18949 # pin@v2.2.3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
flag-name: pui
parallel: true
platform_ui_build: platform_ui_build:
name: Build - UI Platform name: Build - UI Platform
@ -512,9 +533,23 @@ jobs:
run: cd src/frontend && npm run compile && npm run build run: cd src/frontend && npm run compile && npm run build
- name: Zip frontend - name: Zip frontend
run: | run: |
cd InvenTree/web/static cd src/backend/InvenTree/web/static
zip -r frontend-build.zip web/ zip -r frontend-build.zip web/
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # pin@v4.3.1 - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # pin@v4.3.1
with: with:
name: frontend-build name: frontend-build
path: InvenTree/web/static/web path: src/backend/InvenTree/web/static/web
finish_coverage:
name: Finish Coverage
runs-on: ubuntu-20.04
needs: ["platform_ui", "coverage", "paths-filter"]
if: needs.paths-filter.outputs.server == 'true' || needs.paths-filter.outputs.frontend == 'true'
steps:
- name: Finish coverage reporting
uses: coverallsapp/github-action@3dfc5567390f6fa9267c0ee9c251e4c8c3f18949 # pin@v2.2.3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
carryforward: "pui,backend"
parallel-finished: true

View File

@ -20,7 +20,7 @@ jobs:
- name: Version Check - name: Version Check
run: | run: |
pip install requests==2.31.0 pip install requests==2.31.0
python3 ci/version_check.py python3 .github/scripts/version_check.py
- name: Push to Stable Branch - name: Push to Stable Branch
uses: ad-m/github-push-action@d91a481090679876dfc4178fef17f286781251df # pin@v0.8.0 uses: ad-m/github-push-action@d91a481090679876dfc4178fef17f286781251df # pin@v0.8.0
if: env.stable_release == 'true' if: env.stable_release == 'true'
@ -43,12 +43,12 @@ jobs:
run: cd src/frontend && npm run compile && npm run build run: cd src/frontend && npm run compile && npm run build
- name: Zip frontend - name: Zip frontend
run: | run: |
cd InvenTree/web/static/web cd src/backend/InvenTree/web/static/web
zip -r ../frontend-build.zip * zip -r ../frontend-build.zip *
- uses: svenstaro/upload-release-action@04733e069f2d7f7f0b4aebc4fbdbce8613b03ccd # pin@2.9.0 - uses: svenstaro/upload-release-action@04733e069f2d7f7f0b4aebc4fbdbce8613b03ccd # pin@2.9.0
with: with:
repo_token: ${{ secrets.GITHUB_TOKEN }} repo_token: ${{ secrets.GITHUB_TOKEN }}
file: InvenTree/web/static/frontend-build.zip file: src/backend/InvenTree/web/static/frontend-build.zip
asset_name: frontend-build.zip asset_name: frontend-build.zip
tag: ${{ github.ref }} tag: ${{ github.ref }}
overwrite: true overwrite: true

5
.gitignore vendored
View File

@ -84,7 +84,7 @@ data/
env/ env/
# Locale stats file # Locale stats file
locale_stats.json src/backend/InvenTree/InvenTree/locale_stats.json
# node.js # node.js
node_modules/ node_modules/
@ -93,7 +93,7 @@ node_modules/
maintenance_mode_state.txt maintenance_mode_state.txt
# plugin dev directory # plugin dev directory
InvenTree/plugins/ src/backend/InvenTree/plugins/
# Compiled translation files # Compiled translation files
*.mo *.mo
@ -103,6 +103,7 @@ messages.ts
api.yaml api.yaml
# web frontend (static files) # web frontend (static files)
src/backend/InvenTree/web/static
InvenTree/web/static InvenTree/web/static
# Generated docs files # Generated docs files

View File

@ -2,12 +2,11 @@
# See https://pre-commit.com/hooks.html for more hooks # See https://pre-commit.com/hooks.html for more hooks
exclude: | exclude: |
(?x)^( (?x)^(
InvenTree/InvenTree/static/.*| src/backend/InvenTree/InvenTree/static/.*|
InvenTree/locale/.*| src/backend/InvenTree/locale/.*|
src/frontend/src/locales/.*| src/frontend/src/locales/.* |
.*/migrations/.* | .*/migrations/.* |
src/frontend/yarn.lock | src/frontend/yarn.lock
yarn.lock
)$ )$
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
@ -32,12 +31,12 @@ repos:
hooks: hooks:
- id: pip-compile - id: pip-compile
name: pip-compile requirements-dev.in name: pip-compile requirements-dev.in
args: [requirements-dev.in, -o, requirements-dev.txt, --python-version=3.9, --no-strip-extras] args: [src/backend/requirements-dev.in, -o, src/backend/requirements-dev.txt, --python-version=3.9, --no-strip-extras]
files: ^requirements-dev\.(in|txt)$ files: src/backend/requirements-dev\.(in|txt)$
- id: pip-compile - id: pip-compile
name: pip-compile requirements.txt name: pip-compile requirements.txt
args: [requirements.in, -o, requirements.txt,--python-version=3.9, --no-strip-extras] args: [src/backend/requirements.in, -o, src/backend/requirements.txt,--python-version=3.9, --no-strip-extras]
files: ^requirements\.(in|txt)$ files: src/backend/requirements\.(in|txt)$
- repo: https://github.com/Riverside-Healthcare/djLint - repo: https://github.com/Riverside-Healthcare/djLint
rev: v1.34.1 rev: v1.34.1
hooks: hooks:

4
.vscode/launch.json vendored
View File

@ -8,7 +8,7 @@
"name": "InvenTree Server", "name": "InvenTree Server",
"type": "python", "type": "python",
"request": "launch", "request": "launch",
"program": "${workspaceFolder}/InvenTree/manage.py", "program": "${workspaceFolder}/src/backend/InvenTree/manage.py",
"args": ["runserver"], "args": ["runserver"],
"django": true, "django": true,
"justMyCode": true "justMyCode": true
@ -17,7 +17,7 @@
"name": "InvenTree Server - 3rd party", "name": "InvenTree Server - 3rd party",
"type": "python", "type": "python",
"request": "launch", "request": "launch",
"program": "${workspaceFolder}/InvenTree/manage.py", "program": "${workspaceFolder}/src/backend/InvenTree/manage.py",
"args": ["runserver"], "args": ["runserver"],
"django": true, "django": true,
"justMyCode": false "justMyCode": false

View File

@ -3,4 +3,48 @@
Hi there, thank you for your interest in contributing! Hi there, thank you for your interest in contributing!
Please read our contribution guidelines, before submitting your first pull request to the InvenTree codebase. Please read our contribution guidelines, before submitting your first pull request to the InvenTree codebase.
### Project File Structure
The InvenTree project is split into two main components: frontend and backend. This source is located in the `src` directory. All other files are used for project management, documentation, and testing.
```bash
InvenTree/
├─ .devops/ # Files for Azure DevOps
├─ .github/ # Files for GitHub
│ ├─ actions/ # Reused actions
│ ├─ ISSUE_TEMPLATE/ # Templates for issues and pull requests
│ ├─ workflows/ # CI/CD flows
│ ├─ scripts/ # CI scripts
├─ .vscode/ # Settings for Visual Code IDE
├─ assets/ # General project assets
├─ contrib/ # Files needed for deployments
│ ├─ container/ # Files related to building container images
│ ├─ installer/ # Files needed to build single-file installer
│ ├─ packager.io/ # Files needed for Debian/Ubuntu packages
├─ docs/ # Directory for documentation / General helper files
│ ├─ ci/ # CI for documentation
│ ├─ docs/ # Source for documentation
├─ src/ # Source for application
│ ├─ backend/ # Directory for backend parts
│ │ ├─ InvenTree/ # Source for backend
│ │ ├─ requirements.txt # Dependencies for backend
│ │ ├─ package.json # Dependencies for backend HTML linting
│ ├─ frontend/ # Directory for frontend parts
│ │ ├─ src/ # Source for frontend
│ │ │ ├─ main.tsx # Entry point for frontend
│ │ ├─ tests/ # Tests for frontend
│ │ ├─ netlify.toml # Settings for frontend previews (Netlify)
│ │ ├─ package.json # Dependencies for frontend
│ │ ├─ playwright.config.ts # Settings for frontend tests
│ │ ├─ tsconfig.json # Settings for frontend compilation
├─ .pkgr.yml # Build definition for Debian/Ubuntu packages
├─ .pre-commit-config.yaml # Code formatter/linter configuration
├─ CONTRIBUTING.md # Contirbution guidelines and overview
├─ Procfile # Process definition for Debian/Ubuntu packages
├─ README.md # General project information and overview
├─ runtime.txt # Python runtime settings for Debian/Ubuntu packages build
├─ SECURITY.md # Project security policy
├─ tasks.py # Action definitions for development, testing and deployment
```
Refer to our [contribution guidelines](https://docs.inventree.org/en/latest/develop/contributing/) for more information! Refer to our [contribution guidelines](https://docs.inventree.org/en/latest/develop/contributing/) for more information!

View File

@ -1,7 +1,7 @@
# Web process: gunicorn # Web process: gunicorn
web: env/bin/gunicorn --chdir $APP_HOME/InvenTree -c InvenTree/gunicorn.conf.py InvenTree.wsgi -b 0.0.0.0:$PORT web: env/bin/gunicorn --chdir $APP_HOME/src/backend/InvenTree -c src/backend/InvenTree/gunicorn.conf.py InvenTree.wsgi -b 0.0.0.0:$PORT
# Worker process: qcluster # Worker process: qcluster
worker: env/bin/python InvenTree/manage.py qcluster worker: env/bin/python src/backendInvenTree/manage.py qcluster
# Invoke commands # Invoke commands
invoke: echo "" | echo "" && . env/bin/activate && invoke invoke: echo "" | echo "" && . env/bin/activate && invoke
# CLI: Provided for backwards compatibility # CLI: Provided for backwards compatibility

View File

@ -1,5 +1,5 @@
<div align="center"> <div align="center">
<img src="images/logo/inventree.png" alt="InvenTree logo" width="200" height="auto" /> <img src="assets/images/logo/inventree.png" alt="InvenTree logo" width="200" height="auto" />
<h1>InvenTree</h1> <h1>InvenTree</h1>
<p>Open Source Inventory Management System </p> <p>Open Source Inventory Management System </p>

View File

Before

Width:  |  Height:  |  Size: 198 KiB

After

Width:  |  Height:  |  Size: 198 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 341 KiB

After

Width:  |  Height:  |  Size: 341 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1,31 +0,0 @@
"""Test that the root API endpoint is available."""
import json
import requests
# We expect the server to be running on the local host
url = 'http://localhost:8000/api/'
print('Testing InvenTree API endpoint')
response = requests.get(url)
assert response.status_code == 200
print('- Response 200 OK')
data = json.loads(response.text)
required_keys = ['server', 'version', 'apiVersion', 'worker_running']
for key in required_keys:
assert key in data
print(f"- Found key '{key}'")
# Check that the worker is running
assert data['worker_running']
print('- Background worker is operational')
print('API Endpoint Tests Passed OK')

View File

@ -1,27 +0,0 @@
"""Check that there are no database migration files which have not been committed."""
import subprocess
import sys
print('Checking for uncommitted locale files...')
cmd = ['git', 'status']
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate()
locales = []
for line in str(out.decode()).split('\n'):
# Check for any compiled translation files that have not been committed
if 'modified:' in line and '/locale/' in line and 'django.po' in line:
locales.append(line)
if len(locales) > 0:
print('There are {n} unstaged locale files:'.format(n=len(locales)))
for lang in locales:
print(' - {l}'.format(l=lang))
sys.exit(len(locales))

View File

@ -27,7 +27,6 @@ ENV INVENTREE_DOCKER="true"
# InvenTree paths # InvenTree paths
ENV INVENTREE_HOME="/home/inventree" ENV INVENTREE_HOME="/home/inventree"
ENV INVENTREE_MNG_DIR="${INVENTREE_HOME}/InvenTree"
ENV INVENTREE_DATA_DIR="${INVENTREE_HOME}/${data_dir}" ENV INVENTREE_DATA_DIR="${INVENTREE_HOME}/${data_dir}"
ENV INVENTREE_STATIC_ROOT="${INVENTREE_DATA_DIR}/static" ENV INVENTREE_STATIC_ROOT="${INVENTREE_DATA_DIR}/static"
ENV INVENTREE_MEDIA_ROOT="${INVENTREE_DATA_DIR}/media" ENV INVENTREE_MEDIA_ROOT="${INVENTREE_DATA_DIR}/media"
@ -75,9 +74,9 @@ EXPOSE 8000
RUN mkdir -p ${INVENTREE_HOME} RUN mkdir -p ${INVENTREE_HOME}
WORKDIR ${INVENTREE_HOME} WORKDIR ${INVENTREE_HOME}
COPY ./docker/requirements.txt base_requirements.txt COPY contrib/container/requirements.txt base_requirements.txt
COPY ./requirements.txt ./ COPY src/backend/requirements.txt ./
COPY ./docker/install_build_packages.sh . COPY contrib/container/install_build_packages.sh .
RUN chmod +x install_build_packages.sh RUN chmod +x install_build_packages.sh
# For ARMv7 architecture, add the piwheels repo (for cryptography library) # For ARMv7 architecture, add the piwheels repo (for cryptography library)
@ -87,7 +86,7 @@ RUN if [ `apk --print-arch` = "armv7" ]; then \
printf "[global]\nextra-index-url=https://www.piwheels.org/simple\n" > /etc/pip.conf ; \ printf "[global]\nextra-index-url=https://www.piwheels.org/simple\n" > /etc/pip.conf ; \
fi fi
COPY tasks.py docker/gunicorn.conf.py docker/init.sh ./ COPY tasks.py contrib/container/gunicorn.conf.py contrib/container/init.sh ./
RUN chmod +x init.sh RUN chmod +x init.sh
ENTRYPOINT ["/bin/ash", "./init.sh"] ENTRYPOINT ["/bin/ash", "./init.sh"]
@ -102,12 +101,11 @@ RUN ./install_build_packages.sh --no-cache --virtual .build-deps && \
# Frontend builder image: # Frontend builder image:
FROM prebuild AS frontend FROM prebuild AS frontend
RUN apk add --no-cache --update nodejs npm && npm install -g yarn@v1.22.22 RUN apk add --no-cache --update nodejs npm && npm install -g yarn@v1.22.22 --ignore-scripts
RUN yarn config set network-timeout 600000 -g RUN yarn config set network-timeout 600000 -g
COPY InvenTree ${INVENTREE_HOME}/InvenTree
COPY src ${INVENTREE_HOME}/src COPY src ${INVENTREE_HOME}/src
COPY tasks.py ${INVENTREE_HOME}/tasks.py COPY tasks.py ${INVENTREE_HOME}/tasks.py
RUN cd ${INVENTREE_HOME}/InvenTree && inv frontend-compile RUN cd ${INVENTREE_HOME} && inv frontend-compile
COPY docker/execute.sh ${INVENTREE_HOME}/execute.sh COPY docker/execute.sh ${INVENTREE_HOME}/execute.sh
RUN chmod +x ${INVENTREE_HOME}/execute.sh RUN chmod +x ${INVENTREE_HOME}/execute.sh
@ -129,15 +127,19 @@ ENV INVENTREE_COMMIT_DATE="${commit_date}"
ENV PATH=/root/.local/bin:$PATH ENV PATH=/root/.local/bin:$PATH
COPY --from=prebuild /root/.local /root/.local COPY --from=prebuild /root/.local /root/.local
ENV INVENTREE_BACKEND_DIR="${INVENTREE_HOME}"
# Copy source code # Copy source code
COPY InvenTree ./InvenTree COPY src/backend/InvenTree ./InvenTree
COPY --from=frontend ${INVENTREE_HOME}/InvenTree/web/static/web ./InvenTree/web/static/web COPY --from=frontend ${INVENTREE_HOME}/src/backend/InvenTree/web/static/web ./src/backend/InvenTree/web/static/web
# Launch the production server # Launch the production server
CMD gunicorn -c ./gunicorn.conf.py InvenTree.wsgi -b 0.0.0.0:8000 --chdir ./InvenTree CMD gunicorn -c ./gunicorn.conf.py InvenTree.wsgi -b 0.0.0.0:8000 --chdir ./InvenTree
FROM inventree_base AS dev FROM inventree_base AS dev
ENV INVENTREE_BACKEND_DIR="${INVENTREE_HOME}/src/backend"
# Vite server (for local frontend development) # Vite server (for local frontend development)
EXPOSE 5173 EXPOSE 5173
@ -148,7 +150,7 @@ RUN pip install uv==0.1.26 --no-cache-dir && pip install -r base_requirements.tx
# Install nodejs / npm / yarn # Install nodejs / npm / yarn
RUN apk add --no-cache --update nodejs npm && npm install -g yarn@v1.22.22 RUN apk add --no-cache --update nodejs npm && npm install -g yarn@v1.22.22 --ignore-scripts
RUN yarn config set network-timeout 600000 -g RUN yarn config set network-timeout 600000 -g
# The development image requires the source code to be mounted to /home/inventree/ # The development image requires the source code to be mounted to /home/inventree/
@ -163,7 +165,7 @@ ENV INVENTREE_PY_ENV="${INVENTREE_DATA_DIR}/env"
WORKDIR ${INVENTREE_HOME} WORKDIR ${INVENTREE_HOME}
# Entrypoint ensures that we are running in the python virtual environment # Entrypoint ensures that we are running in the python virtual environment
ENTRYPOINT ["/bin/ash", "./docker/init.sh"] ENTRYPOINT ["/bin/ash", "./contrib/container/init.sh"]
# Launch the development server # Launch the development server
CMD ["invoke", "server", "-a", "${INVENTREE_WEB_ADDR}:${INVENTREE_WEB_PORT}"] CMD ["invoke", "server", "-a", "${INVENTREE_WEB_ADDR}:${INVENTREE_WEB_PORT}"]

View File

@ -40,6 +40,7 @@ services:
- inventree-dev-db - inventree-dev-db
build: &build_config build: &build_config
context: . context: .
dockerfile: contrib/container/Dockerfile
target: dev target: dev
# Cache the built image to be used by the inventree-dev-worker process # Cache the built image to be used by the inventree-dev-worker process
image: inventree-dev-image image: inventree-dev-image
@ -50,7 +51,7 @@ services:
# Mount local source directory to /home/inventree # Mount local source directory to /home/inventree
- ./:/home/inventree:z - ./:/home/inventree:z
env_file: env_file:
- docker.dev.env - contrib/container/docker.dev.env
restart: unless-stopped restart: unless-stopped
# Background worker process handles long-running or periodic tasks # Background worker process handles long-running or periodic tasks
@ -64,5 +65,5 @@ services:
# Mount local source directory to /home/inventree # Mount local source directory to /home/inventree
- ./:/home/inventree:z - ./:/home/inventree:z
env_file: env_file:
- docker.dev.env - contrib/container/docker.dev.env
restart: unless-stopped restart: unless-stopped

View File

@ -28,8 +28,8 @@ fi
if test -f "$INVENTREE_CONFIG_FILE"; then if test -f "$INVENTREE_CONFIG_FILE"; then
echo "Loading config file : $INVENTREE_CONFIG_FILE" echo "Loading config file : $INVENTREE_CONFIG_FILE"
else else
echo "Copying config file to $INVENTREE_CONFIG_FILE" echo "Copying config file from $INVENTREE_BACKEND_DIR/InvenTree/config_template.yml to $INVENTREE_CONFIG_FILE"
cp $INVENTREE_HOME/InvenTree/config_template.yaml $INVENTREE_CONFIG_FILE cp $INVENTREE_BACKEND_DIR/InvenTree/config_template.yaml $INVENTREE_CONFIG_FILE
fi fi
# Setup a python virtual environment # Setup a python virtual environment

View File

@ -2,7 +2,7 @@
"append_commit_message": false "append_commit_message": false
files: files:
- source: /InvenTree/locale/en/LC_MESSAGES/django.po - source: /src/backend/InvenTree/locale/en/LC_MESSAGES/django.po
translation: /InvenTree/locale/%two_letters_code%/LC_MESSAGES/%original_file_name% translation: /src/backend/InvenTree/locale/%two_letters_code%/LC_MESSAGES/%original_file_name%
- source: /src/frontend/src/locales/en/messages.po - source: /src/frontend/src/locales/en/messages.po
translation: /src/frontend/src/locales/%two_letters_code%/%original_file_name% translation: /src/frontend/src/locales/%two_letters_code%/%original_file_name%

View File

@ -9,8 +9,8 @@ The InvenTree server code supports an extensible plugin architecture, allowing c
Plugins can be added from multiple sources: Plugins can be added from multiple sources:
- Plugins can be installed in InvenTrees venv via PIP (python package manager) - Plugins can be installed in InvenTrees venv via PIP (python package manager)
- Custom plugins should be placed in the directory `./InvenTree/plugins`. - Custom plugins should be placed in the directory `./src/backend/InvenTree/plugins`.
- InvenTree built-in plugins are located in the directory `./InvenTree/plugin/builtin`. - InvenTree built-in plugins are located in the directory `./src/backend/InvenTree/plugin/builtin`.
For further information, read more about [installing plugins](./plugins/install.md). For further information, read more about [installing plugins](./plugins/install.md).
@ -28,7 +28,7 @@ Please read all release notes and watch out for warnings - we generally provide
#### Plugins #### Plugins
General classes and mechanisms are provided under the `plugin` [namespaces](https://github.com/inventree/InvenTree/blob/master/InvenTree/plugin/__init__.py). These include: General classes and mechanisms are provided under the `plugin` [namespaces](https://github.com/inventree/InvenTree/blob/master/src/backend/InvenTree/plugin/__init__.py). These include:
```python ```python
# Management objects # Management objects
@ -44,7 +44,7 @@ MixinNotImplementedError # Is raised if a mixin was not implemented (core mec
#### Mixins #### Mixins
Mixins are split up internally to keep the source tree clean and enable better testing separation. All public APIs that should be used are exposed under `plugin.mixins`. These include all built-in mixins and notification methods. An up-to-date reference can be found in the source code (current master can be [found here](https://github.com/inventree/InvenTree/blob/master/InvenTree/plugin/mixins/__init__.py)). Mixins are split up internally to keep the source tree clean and enable better testing separation. All public APIs that should be used are exposed under `plugin.mixins`. These include all built-in mixins and notification methods. An up-to-date reference can be found in the source code (current master can be [found here](https://github.com/inventree/InvenTree/blob/master/src/backend/InvenTree/plugin/mixins/__init__.py)).
#### Models and other internal InvenTree APIs #### Models and other internal InvenTree APIs
@ -72,7 +72,7 @@ MIN_VERSION = None # Lowest InvenTree version number that is supported by the p
MAX_VERSION = None # Highest InvenTree version number that is supported by the plugin MAX_VERSION = None # Highest InvenTree version number that is supported by the plugin
``` ```
Refer to the [sample plugins](https://github.com/inventree/InvenTree/tree/master/InvenTree/plugin/samples) for further examples. Refer to the [sample plugins](https://github.com/inventree/InvenTree/tree/master/src/backend/InvenTree/plugin/samples) for further examples.
### Plugin Config ### Plugin Config

View File

@ -15,4 +15,4 @@ POST {
} }
``` ```
For an example of a very simple action plugin, refer to `/InvenTree/plugin/samples/integratoni/simpleactionplugin.py` For an example of a very simple action plugin, refer to `/src/backend/InvenTree/plugin/samples/integratoni/simpleactionplugin.py`

View File

@ -6,7 +6,7 @@ title: Barcode Mixin
InvenTree supports decoding of arbitrary barcode data via a **Barcode Plugin** interface. Barcode data POSTed to the `/api/barcode/` endpoint will be supplied to all loaded barcode plugins, and the first plugin to successfully interpret the barcode data will return a response to the client. InvenTree supports decoding of arbitrary barcode data via a **Barcode Plugin** interface. Barcode data POSTed to the `/api/barcode/` endpoint will be supplied to all loaded barcode plugins, and the first plugin to successfully interpret the barcode data will return a response to the client.
InvenTree can generate native QR codes to represent database objects (e.g. a single StockItem). This barcode can then be used to perform quick lookup of a stock item or location in the database. A client application (for example the InvenTree mobile app) scans a barcode, and sends the barcode data to the InvenTree server. The server then uses the **InvenTreeBarcodePlugin** (found at `/InvenTree/plugins/barcode/inventree.py`) to decode the supplied barcode data. InvenTree can generate native QR codes to represent database objects (e.g. a single StockItem). This barcode can then be used to perform quick lookup of a stock item or location in the database. A client application (for example the InvenTree mobile app) scans a barcode, and sends the barcode data to the InvenTree server. The server then uses the **InvenTreeBarcodePlugin** (found at `/src/backend/InvenTree/plugins/barcode/inventree.py`) to decode the supplied barcode data.
Any third-party barcodes can be decoded by writing a matching plugin to decode the barcode data. These plugins could then perform a server-side action or render a JSON response back to the client for further action. Any third-party barcodes can be decoded by writing a matching plugin to decode the barcode data. These plugins could then perform a server-side action or render a JSON response back to the client for further action.

View File

@ -34,7 +34,7 @@ In certain container environments (such as docker), plugins are installed into a
#### Builtin Plugins #### Builtin Plugins
Builtin plugins ship in `src/InvenTree/plugin/builtin`. To achieve full unit-testing for all mixins there are some sample implementations in `src/InvenTree/plugin/samples`. Builtin plugins ship in `src/backend/InvenTree/plugin/builtin`. To achieve full unit-testing for all mixins there are some sample implementations in `src/backend/InvenTree/plugin/samples`.
!!! success "Builtin Plugins" !!! success "Builtin Plugins"
Builtin plugins are always enabled, as they are required for core InvenTree functionality Builtin plugins are always enabled, as they are required for core InvenTree functionality
@ -77,7 +77,7 @@ Admin users can install plugins directly from the web interface, via the "Plugin
Custom plugins can be placed in the `src/InvenTree/plugins/` directory, where they will be automatically discovered. This can be useful for developing and testing plugins, but can prove more difficult in production (e.g. when using Docker). Custom plugins can be placed in the `src/InvenTree/plugins/` directory, where they will be automatically discovered. This can be useful for developing and testing plugins, but can prove more difficult in production (e.g. when using Docker).
!!! info "Git Tracking" !!! info "Git Tracking"
The `src/InvenTree/plugins/` directory is excluded from Git version tracking - any plugin files here will be hidden from Git The `src/backend/InvenTree/plugins/` directory is excluded from Git version tracking - any plugin files here will be hidden from Git
!!! warning "Not Recommended For Production" !!! warning "Not Recommended For Production"
Loading plugins via the local *plugins* directory is not recommended for production. If you cannot use PIP installation (above), specify a custom plugin directory (below) or use a [VCS](https://pip.pypa.io/en/stable/topics/vcs-support/) as a plugin install source. Loading plugins via the local *plugins* directory is not recommended for production. If you cannot use PIP installation (above), specify a custom plugin directory (below) or use a [VCS](https://pip.pypa.io/en/stable/topics/vcs-support/) as a plugin install source.

View File

@ -28,4 +28,4 @@ If a locate plugin is installed and activated, the [InvenTree mobile app](../../
### Implementation ### Implementation
Refer to the [InvenTree source code](https://github.com/inventree/InvenTree/blob/master/InvenTree/plugin/samples/locate/locate_sample.py) for a simple implementation example. Refer to the [InvenTree source code](https://github.com/inventree/InvenTree/blob/master/src/backend/InvenTree/plugin/samples/locate/locate_sample.py) for a simple implementation example.

View File

@ -16,7 +16,7 @@ Additionally the `add_label_context` method, allowing custom context data to be
### Example ### Example
A sample plugin which provides additional context data to the report templates can be found [in the InvenTree source code](https://github.com/inventree/InvenTree/blob/master/InvenTree/plugin/samples/integration/report_plugin_sample.py): A sample plugin which provides additional context data to the report templates can be found [in the InvenTree source code](https://github.com/inventree/InvenTree/blob/master/src/backend/InvenTree/plugin/samples/integration/report_plugin_sample.py):
```python ```python
"""Sample plugin for extending reporting functionality""" """Sample plugin for extending reporting functionality"""

View File

@ -59,4 +59,4 @@ class ScheduledTaskPlugin(ScheduleMixin, SettingsMixin, InvenTreePlugin):
``` ```
!!! info "More Info" !!! info "More Info"
For more information on any of the methods described below, refer to the InvenTree source code. [A working example is available as a starting point](https://github.com/inventree/InvenTree/blob/master/InvenTree/plugin/samples/integration/scheduled_task.py). For more information on any of the methods described below, refer to the InvenTree source code. [A working example is available as a starting point](https://github.com/inventree/InvenTree/blob/master/src/backend/InvenTree/plugin/samples/integration/scheduled_task.py).

View File

@ -9,7 +9,7 @@ The `ValidationMixin` class enables plugins to perform custom validation of obje
Any of the methods described below can be implemented in a custom plugin to provide functionality as required. Any of the methods described below can be implemented in a custom plugin to provide functionality as required.
!!! info "More Info" !!! info "More Info"
For more information on any of the methods described below, refer to the InvenTree source code. [A working example is available as a starting point](https://github.com/inventree/InvenTree/blob/master/InvenTree/plugin/samples/integration/validation_sample.py). For more information on any of the methods described below, refer to the InvenTree source code. [A working example is available as a starting point](https://github.com/inventree/InvenTree/blob/master/src/backend/InvenTree/plugin/samples/integration/validation_sample.py).
!!! info "Multi Plugin Support" !!! info "Multi Plugin Support"
It is possible to have multiple plugins loaded simultaneously which support validation methods. For example when validating a field, if one plugin returns a null value (`None`) then the *next* plugin (if available) will be queried. It is possible to have multiple plugins loaded simultaneously which support validation methods. For example when validating a field, if one plugin returns a null value (`None`) then the *next* plugin (if available) will be queried.

View File

@ -183,4 +183,4 @@ Finally added a `{% raw %}|floatformat:0{% endraw %}` to the quantity that remov
A default *BOM Report* template is provided out of the box, which is useful for generating simple test reports. Furthermore, it may be used as a starting point for developing custom BOM reports: A default *BOM Report* template is provided out of the box, which is useful for generating simple test reports. Furthermore, it may be used as a starting point for developing custom BOM reports:
View the [source code](https://github.com/inventree/InvenTree/blob/master/InvenTree/report/templates/report/inventree_bill_of_materials_report.html) for the default test report template. View the [source code](https://github.com/inventree/InvenTree/blob/master/src/backend/InvenTree/report/templates/report/inventree_bill_of_materials_report.html) for the default test report template.

View File

@ -321,4 +321,4 @@ This will result a report page like this:
A default *Build Report* template is provided out of the box, which is useful for generating simple test reports. Furthermore, it may be used as a starting point for developing custom BOM reports: A default *Build Report* template is provided out of the box, which is useful for generating simple test reports. Furthermore, it may be used as a starting point for developing custom BOM reports:
View the [source code](https://github.com/inventree/InvenTree/blob/master/InvenTree/report/templates/report/inventree_build_order_base.html) for the default build report template. View the [source code](https://github.com/inventree/InvenTree/blob/master/src/backend/InvenTree/report/templates/report/inventree_build_order_base.html) for the default build report template.

View File

@ -12,7 +12,7 @@ Some common functions are provided for use in custom report and label templates.
``` ```
!!! tip "Use the Source, Luke" !!! tip "Use the Source, Luke"
To see the full range of available helper functions, refer to the source file [report.py](https://github.com/inventree/InvenTree/blob/master/InvenTree/report/templatetags/report.py) where these functions are defined! To see the full range of available helper functions, refer to the source file [report.py](https://github.com/inventree/InvenTree/blob/master/src/backend/InvenTree/report/templatetags/report.py) where these functions are defined!
## Assigning Variables ## Assigning Variables

View File

@ -62,4 +62,4 @@ Price: {% render_currency line.total_line_price %}
A default *Purchase Order Report* template is provided out of the box, which is useful for generating simple test reports. Furthermore, it may be used as a starting point for developing custom BOM reports: A default *Purchase Order Report* template is provided out of the box, which is useful for generating simple test reports. Furthermore, it may be used as a starting point for developing custom BOM reports:
View the [source code](https://github.com/inventree/InvenTree/blob/master/InvenTree/report/templates/report/inventree_po_report_base.html) for the default purchase order report template. View the [source code](https://github.com/inventree/InvenTree/blob/master/src/backend/InvenTree/report/templates/report/inventree_po_report_base.html) for the default purchase order report template.

View File

@ -159,7 +159,7 @@ InvenTree supports the following reporting functionality:
InvenTree is supplied with a number of default templates "out of the box". These are generally quite simple, but serve as a starting point for building custom reports to suit a specific need. InvenTree is supplied with a number of default templates "out of the box". These are generally quite simple, but serve as a starting point for building custom reports to suit a specific need.
!!! tip "Read the Source" !!! tip "Read the Source"
The source code for the default reports is [available on GitHub](https://github.com/inventree/InvenTree/tree/master/InvenTree/report/templates/report). Use this as a guide for generating your own reports! The source code for the default reports is [available on GitHub](https://github.com/inventree/InvenTree/tree/master/src/backend/InvenTree/report/templates/report). Use this as a guide for generating your own reports!
## Creating Reports ## Creating Reports

View File

@ -23,4 +23,4 @@ In addition to the default report context variables, the following context varia
A default report template is provided out of the box, which can be used as a starting point for developing custom return order report templates. A default report template is provided out of the box, which can be used as a starting point for developing custom return order report templates.
View the [source code](https://github.com/inventree/InvenTree/blob/master/InvenTree/report/templates/report/inventree_return_order_report_base.html) for the default return order report template. View the [source code](https://github.com/inventree/InvenTree/blob/master/src/backend/InvenTree/report/templates/report/inventree_return_order_report_base.html) for the default return order report template.

View File

@ -28,4 +28,4 @@ In addition to the default report context variables, the following variables are
A default *Sales Order Report* template is provided out of the box, which is useful for generating simple test reports. Furthermore, it may be used as a starting point for developing custom BOM reports: A default *Sales Order Report* template is provided out of the box, which is useful for generating simple test reports. Furthermore, it may be used as a starting point for developing custom BOM reports:
View the [source code](https://github.com/inventree/InvenTree/blob/master/InvenTree/report/templates/report/inventree_so_report_base.html) for the default sales order report template. View the [source code](https://github.com/inventree/InvenTree/blob/master/src/backend/InvenTree/report/templates/report/inventree_so_report_base.html) for the default sales order report template.

View File

@ -84,4 +84,4 @@ A default *Test Report* template is provided out of the box, which is useful for
{% include "img.html" %} {% include "img.html" %}
{% endwith %} {% endwith %}
View the [source code](https://github.com/inventree/InvenTree/blob/master/InvenTree/report/templates/report/inventree_test_report_base.html) for the default test report template. View the [source code](https://github.com/inventree/InvenTree/blob/master/src/backend/InvenTree/report/templates/report/inventree_test_report_base.html) for the default test report template.

View File

@ -72,7 +72,7 @@ sudo apt-get install supervisor
Copy the supervisor configuration file: Copy the supervisor configuration file:
``` ```
sudo cp /home/inventree/src/deploy/supervisord.conf /etc/supervisord.conf sudo cp /home/inventree/src/contrib/deploy/supervisord.conf /etc/supervisord.conf
``` ```
### Start Supervisor Daemon ### Start Supervisor Daemon

View File

@ -22,7 +22,7 @@ The InvenTree server tries to locate the `config.yaml` configuration file on sta
!!! tip "Config File Location" !!! tip "Config File Location"
When the InvenTree server boots, it will report the location where it expects to find the configuration file When the InvenTree server boots, it will report the location where it expects to find the configuration file
The configuration file *template* can be found on [GitHub](https://github.com/inventree/InvenTree/blob/master/InvenTree/config_template.yaml) The configuration file *template* can be found on [GitHub](https://github.com/inventree/InvenTree/blob/master/src/backend/InvenTree/config_template.yaml)
!!! info "Template File" !!! info "Template File"
The default configuration file (as defined by the template linked above) will be copied to the specified configuration file location on first run, if a configuration file is not found in that location. The default configuration file (as defined by the template linked above) will be copied to the specified configuration file location on first run, if a configuration file is not found in that location.

View File

@ -125,8 +125,8 @@ def generate_index_file(version: str):
f.write(output) f.write(output)
def extract_refs(data: dict, components: dict) -> list: def extract_refs(data: dict, components: dict) -> dict:
"""Extract a list of refs from the provided paths dict. """Extract a dict of refs from the provided paths dict.
The refs are located like so: The refs are located like so:
<path>:<method>:responses:<status>:content:application/json:schema:$ref <path>:<method>:responses:<status>:content:application/json:schema:$ref

View File

@ -246,7 +246,7 @@ plugins:
handlers: handlers:
python: python:
paths: paths:
- ../InvenTree - ../src/backend/InvenTree
options: options:
show_symbol_type_heading: true show_symbol_type_heading: true
show_symbol_type_toc: true show_symbol_type_toc: true
@ -273,7 +273,7 @@ markdown_extensions:
# Global Variables # Global Variables
extra: extra:
static_folder_source: ./InvenTree/InvenTree/static/ static_folder_source: ./src/backend/InvenTree/InvenTree/static/
static_folder_local_default: ./inventree_static/ static_folder_local_default: ./inventree_static/
# Site Analytics # Site Analytics

View File

@ -11,8 +11,9 @@ exclude = [
"env", "env",
".venv", ".venv",
".env", ".env",
"src/backend/plugins/*",
] ]
src = ["InvenTree"] src = ["src/backend/InvenTree"]
# line-length = 120 # line-length = 120
[tool.ruff.extend-per-file-ignores] [tool.ruff.extend-per-file-ignores]
@ -69,13 +70,13 @@ skip-magic-trailing-comma = true
line-ending = "auto" line-ending = "auto"
[tool.coverage.run] [tool.coverage.run]
source = ["InvenTree", ] source = ["src/backend/InvenTree", "InvenTree"]
[tool.djlint] [tool.djlint]
ignore = "D018,H006,H008,H020,H021,H023,H025,H030,H031,T002" ignore = "D018,H006,H008,H020,H021,H023,H025,H030,H031,T002"
[tool.isort] [tool.isort]
src_paths=["InvenTree", "../InvenTree"] src_paths=["src/backend/InvenTree", ]
skip_glob ="*/migrations/*.py" skip_glob ="*/migrations/*.py"
known_django="django" known_django="django"
sections=["FUTURE","STDLIB","DJANGO","THIRDPARTY","FIRSTPARTY","LOCALFOLDER"] sections=["FUTURE","STDLIB","DJANGO","THIRDPARTY","FIRSTPARTY","LOCALFOLDER"]

View File

@ -6,7 +6,7 @@ mkdocs:
python: python:
install: install:
- requirements: docs/requirements.txt - requirements: docs/requirements.txt
- requirements: requirements.txt - requirements: src/backend/requirements.txt
build: build:
os: "ubuntu-22.04" os: "ubuntu-22.04"

View File

@ -1,353 +1,3 @@
# This file was autogenerated by uv via the following command: # Dummy requirements file to trigger the package pipeline
# uv pip compile requirements.in -o requirements.txt --python-version=3.9 --no-strip-extras # The new requirements file is located in src/backend/requirements.txt
asgiref==3.8.0 #
# via
# django
# django-cors-headers
async-timeout==4.0.3
# via redis
attrs==23.2.0
# via
# jsonschema
# referencing
babel==2.14.0
# via py-moneyed
bleach[css]==6.1.0
# via django-markdownify
brotli==1.1.0
# via fonttools
certifi==2024.2.2
# via
# requests
# sentry-sdk
cffi==1.16.0
# via
# cryptography
# weasyprint
charset-normalizer==3.3.2
# via requests
coreapi==2.3.3
coreschema==0.0.4
# via coreapi
cryptography==42.0.5
# via
# djangorestframework-simplejwt
# pyjwt
cssselect2==0.7.0
# via weasyprint
defusedxml==0.7.1
# via
# odfpy
# python3-openid
deprecated==1.2.14
# via
# opentelemetry-api
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-exporter-otlp-proto-http
diff-match-patch==20230430
# via django-import-export
dj-rest-auth==5.0.2
django==4.2.11
# via
# dj-rest-auth
# django-allauth
# django-allauth-2fa
# django-cors-headers
# django-dbbackup
# django-error-report-2
# django-filter
# django-flags
# django-formtools
# django-ical
# django-import-export
# django-js-asset
# django-markdownify
# django-money
# django-otp
# django-picklefield
# django-q2
# django-recurrence
# django-redis
# django-sesame
# django-sql-utils
# django-sslserver
# django-stdimage
# django-taggit
# django-user-sessions
# django-weasyprint
# django-xforwardedfor-middleware
# djangorestframework
# djangorestframework-simplejwt
# drf-spectacular
django-allauth==0.61.1
# via django-allauth-2fa
django-allauth-2fa==0.11.1
django-cleanup==8.1.0
django-cors-headers==4.3.1
django-crispy-forms==1.14.0
django-dbbackup==4.1.0
django-error-report-2==0.4.2
django-filter==24.1
django-flags==5.0.13
django-formtools==2.5.1
django-ical==1.9.2
django-import-export==3.3.7
django-js-asset==2.2.0
# via django-mptt
django-maintenance-mode==0.21.1
django-markdownify==0.9.3
django-money==3.2.0
django-mptt==0.16.0
django-otp==1.3.0
# via django-allauth-2fa
django-picklefield==3.1
# via django-q2
django-q-sentry==0.1.6
django-q2==1.6.2
django-recurrence==1.11.1
# via django-ical
django-redis==5.4.0
django-sesame==3.2.2
django-sql-utils==0.7.0
django-sslserver==0.22
django-stdimage==6.0.2
django-taggit==5.0.1
django-user-sessions==2.0.0
django-weasyprint==2.3.0
django-xforwardedfor-middleware==2.0
djangorestframework==3.14.0
# via
# dj-rest-auth
# djangorestframework-simplejwt
# drf-spectacular
djangorestframework-simplejwt[crypto]==5.3.1
drf-spectacular==0.27.1
dulwich==0.21.7
et-xmlfile==1.1.0
# via openpyxl
feedparser==6.0.11
fonttools[woff]==4.50.0
# via weasyprint
googleapis-common-protos==1.63.0
# via
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-exporter-otlp-proto-http
grpcio==1.62.1
# via opentelemetry-exporter-otlp-proto-grpc
gunicorn==21.2.0
html5lib==1.1
# via weasyprint
icalendar==5.0.12
# via django-ical
idna==3.6
# via requests
importlib-metadata==6.11.0
# via
# django-q2
# markdown
# opentelemetry-api
inflection==0.5.1
# via drf-spectacular
itypes==1.2.0
# via coreapi
jinja2==3.1.3
# via coreschema
jsonschema==4.21.1
# via drf-spectacular
jsonschema-specifications==2023.12.1
# via jsonschema
markdown==3.6
# via django-markdownify
markuppy==1.14
# via tablib
markupsafe==2.1.5
# via jinja2
oauthlib==3.2.2
# via requests-oauthlib
odfpy==1.4.1
# via tablib
openpyxl==3.1.2
# via tablib
opentelemetry-api==1.23.0
# via
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-exporter-otlp-proto-http
# opentelemetry-instrumentation
# opentelemetry-instrumentation-django
# opentelemetry-instrumentation-redis
# opentelemetry-instrumentation-requests
# opentelemetry-instrumentation-wsgi
# opentelemetry-sdk
opentelemetry-exporter-otlp==1.23.0
opentelemetry-exporter-otlp-proto-common==1.23.0
# via
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-exporter-otlp-proto-http
opentelemetry-exporter-otlp-proto-grpc==1.23.0
# via opentelemetry-exporter-otlp
opentelemetry-exporter-otlp-proto-http==1.23.0
# via opentelemetry-exporter-otlp
opentelemetry-instrumentation==0.44b0
# via
# opentelemetry-instrumentation-django
# opentelemetry-instrumentation-redis
# opentelemetry-instrumentation-requests
# opentelemetry-instrumentation-wsgi
opentelemetry-instrumentation-django==0.44b0
opentelemetry-instrumentation-redis==0.44b0
opentelemetry-instrumentation-requests==0.44b0
opentelemetry-instrumentation-wsgi==0.44b0
# via opentelemetry-instrumentation-django
opentelemetry-proto==1.23.0
# via
# opentelemetry-exporter-otlp-proto-common
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-exporter-otlp-proto-http
opentelemetry-sdk==1.23.0
# via
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-exporter-otlp-proto-http
opentelemetry-semantic-conventions==0.44b0
# via
# opentelemetry-instrumentation-django
# opentelemetry-instrumentation-redis
# opentelemetry-instrumentation-requests
# opentelemetry-instrumentation-wsgi
# opentelemetry-sdk
opentelemetry-util-http==0.44b0
# via
# opentelemetry-instrumentation-django
# opentelemetry-instrumentation-requests
# opentelemetry-instrumentation-wsgi
packaging==24.0
# via gunicorn
pdf2image==1.17.0
pillow==10.2.0
# via
# django-stdimage
# pdf2image
# python-barcode
# qrcode
# weasyprint
pint==0.21
protobuf==4.25.3
# via
# googleapis-common-protos
# opentelemetry-proto
py-moneyed==3.0
# via django-money
pycparser==2.21
# via cffi
pydyf==0.9.0
# via weasyprint
pyjwt[crypto]==2.8.0
# via
# django-allauth
# djangorestframework-simplejwt
pyphen==0.14.0
# via weasyprint
pypng==0.20220715.0
# via qrcode
python-barcode[images]==0.15.1
python-dateutil==2.9.0.post0
# via
# django-recurrence
# icalendar
python-dotenv==1.0.1
python-fsutil==0.14.1
# via django-maintenance-mode
python3-openid==3.2.0
# via django-allauth
pytz==2024.1
# via
# django-dbbackup
# djangorestframework
# icalendar
pyyaml==6.0.1
# via
# drf-spectacular
# tablib
qrcode[pil]==7.4.2
# via django-allauth-2fa
rapidfuzz==3.6.2
redis==5.0.3
# via django-redis
referencing==0.34.0
# via
# jsonschema
# jsonschema-specifications
regex==2023.12.25
requests==2.31.0
# via
# coreapi
# django-allauth
# opentelemetry-exporter-otlp-proto-http
# requests-oauthlib
requests-oauthlib==1.4.0
# via django-allauth
rpds-py==0.18.0
# via
# jsonschema
# referencing
sentry-sdk==1.43.0
# via django-q-sentry
setuptools==69.2.0
# via
# django-money
# opentelemetry-instrumentation
sgmllib3k==1.0.0
# via feedparser
six==1.16.0
# via
# bleach
# html5lib
# python-dateutil
sqlparse==0.4.4
# via
# django
# django-sql-utils
tablib[html, ods, xls, xlsx, yaml]==3.5.0
# via django-import-export
tinycss2==1.2.1
# via
# bleach
# cssselect2
# weasyprint
typing-extensions==4.10.0
# via
# asgiref
# drf-spectacular
# opentelemetry-sdk
# py-moneyed
# qrcode
uritemplate==4.1.1
# via
# coreapi
# drf-spectacular
urllib3==2.2.1
# via
# dulwich
# requests
# sentry-sdk
weasyprint==61.2
# via django-weasyprint
webencodings==0.5.1
# via
# bleach
# cssselect2
# html5lib
# tinycss2
whitenoise==6.6.0
wrapt==1.16.0
# via
# deprecated
# opentelemetry-instrumentation
# opentelemetry-instrumentation-redis
xlrd==2.0.1
# via tablib
xlwt==1.3.0
# via tablib
zipp==3.18.1
# via importlib-metadata
zopfli==0.2.3
# via fonttools

View File

@ -91,9 +91,12 @@ class InvenTreeResource(ModelResource):
""" """
# We can automatically determine which fields might need such a conversion # We can automatically determine which fields might need such a conversion
for field in self.Meta.model._meta.fields: for field in self.Meta.model._meta.fields:
if isinstance(field, CharField): if (
if field.blank and not field.null: isinstance(field, CharField)
if field.name not in self.CONVERT_NULL_FIELDS: and field.blank
and not field.null
and field.name not in self.CONVERT_NULL_FIELDS
):
self.CONVERT_NULL_FIELDS.append(field.name) self.CONVERT_NULL_FIELDS.append(field.name)
for field in self.CONVERT_NULL_FIELDS: for field in self.CONVERT_NULL_FIELDS:

View File

@ -443,10 +443,10 @@ def get_frontend_settings(debug=True):
if 'environment' not in settings: if 'environment' not in settings:
settings['environment'] = 'development' if debug else 'production' settings['environment'] = 'development' if debug else 'production'
if debug and 'show_server_selector' not in settings: if (debug and 'show_server_selector' not in settings) or len(
settings['server_list']
) == 0:
# In debug mode, show server selector by default # In debug mode, show server selector by default
settings['show_server_selector'] = True
elif len(settings['server_list']) == 0:
# If no servers are specified, show server selector # If no servers are specified, show server selector
settings['show_server_selector'] = True settings['show_server_selector'] = True

View File

@ -38,8 +38,7 @@ class InvenTreeRestURLField(RestURLField):
'INVENTREE_STRICT_URLS', True, cache=False 'INVENTREE_STRICT_URLS', True, cache=False
) )
if not strict_urls and data is not empty: if not strict_urls and data is not empty and '://' not in data:
if '://' not in data:
# Validate as if there were a schema provided # Validate as if there were a schema provided
data = 'http://' + data data = 'http://' + data

View File

@ -458,8 +458,7 @@ class ReferenceIndexingMixin(models.Model):
reference_int = InvenTree.helpers.extract_int(reference) reference_int = InvenTree.helpers.extract_int(reference)
if validate: if validate and reference_int > models.BigIntegerField.MAX_BIGINT:
if reference_int > models.BigIntegerField.MAX_BIGINT:
raise ValidationError({'reference': _('Reference number is too large')}) raise ValidationError({'reference': _('Reference number is too large')})
return reference_int return reference_int

Some files were not shown because too many files have changed in this diff Show More