mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-16 03:55:41 +00:00
Merge remote-tracking branch 'inventree/master'
This commit is contained in:
16
.github/workflows/docker.yaml
vendored
16
.github/workflows/docker.yaml
vendored
@ -26,7 +26,8 @@ jobs:
|
|||||||
# Build the docker image
|
# Build the docker image
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
@ -56,13 +57,22 @@ jobs:
|
|||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
uses: docker/setup-buildx-action@v1
|
uses: docker/setup-buildx-action@v1
|
||||||
|
- name: Set up cosign
|
||||||
|
uses: sigstore/cosign-installer@48866aa521d8bf870604709cd43ec2f602d03ff2
|
||||||
- name: Login to Dockerhub
|
- name: Login to Dockerhub
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v1
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
- name: Extract Docker metadata
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@69f6fc9d46f2f8bf0d5491e4aabe0bb8c6a4678a
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
inventree/inventree
|
||||||
- name: Build and Push
|
- name: Build and Push
|
||||||
|
id: build-and-push
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
uses: docker/build-push-action@v2
|
uses: docker/build-push-action@v2
|
||||||
with:
|
with:
|
||||||
@ -74,6 +84,10 @@ jobs:
|
|||||||
build-args: |
|
build-args: |
|
||||||
commit_hash=${{ env.git_commit_hash }}
|
commit_hash=${{ env.git_commit_hash }}
|
||||||
commit_date=${{ env.git_commit_date }}
|
commit_date=${{ env.git_commit_date }}
|
||||||
|
- name: Sign the published image
|
||||||
|
env:
|
||||||
|
COSIGN_EXPERIMENTAL: "true"
|
||||||
|
run: cosign sign ${{ steps.meta.outputs.tags }}@${{ steps.build-and-push.outputs.digest }}
|
||||||
- name: Push to Stable Branch
|
- name: Push to Stable Branch
|
||||||
uses: ad-m/github-push-action@master
|
uses: ad-m/github-push-action@master
|
||||||
if: env.stable_release == 'true'
|
if: env.stable_release == 'true'
|
||||||
|
13
Dockerfile
13
Dockerfile
@ -127,20 +127,9 @@ FROM base as dev
|
|||||||
|
|
||||||
ENV INVENTREE_DEBUG=True
|
ENV INVENTREE_DEBUG=True
|
||||||
|
|
||||||
ENV INVENTREE_DEV_DIR="${INVENTREE_HOME}/dev"
|
|
||||||
|
|
||||||
# Location for python virtual environment
|
# Location for python virtual environment
|
||||||
# If the INVENTREE_PY_ENV variable is set, the entrypoint script will use it!
|
# If the INVENTREE_PY_ENV variable is set, the entrypoint script will use it!
|
||||||
ENV INVENTREE_PY_ENV="${INVENTREE_DEV_DIR}/env"
|
ENV INVENTREE_PY_ENV="${INVENTREE_DATA_DIR}/env"
|
||||||
|
|
||||||
# Override default path settings
|
|
||||||
ENV INVENTREE_STATIC_ROOT="${INVENTREE_DEV_DIR}/static"
|
|
||||||
ENV INVENTREE_MEDIA_ROOT="${INVENTREE_DEV_DIR}/media"
|
|
||||||
ENV INVENTREE_PLUGIN_DIR="${INVENTREE_DEV_DIR}/plugins"
|
|
||||||
|
|
||||||
ENV INVENTREE_CONFIG_FILE="${INVENTREE_DEV_DIR}/config.yaml"
|
|
||||||
ENV INVENTREE_SECRET_KEY_FILE="${INVENTREE_DEV_DIR}/secret_key.txt"
|
|
||||||
ENV INVENTREE_PLUGIN_FILE="${INVENTREE_DEV_DIR}/plugins.txt"
|
|
||||||
|
|
||||||
WORKDIR ${INVENTREE_HOME}
|
WORKDIR ${INVENTREE_HOME}
|
||||||
|
|
||||||
|
@ -114,9 +114,9 @@ C) Look for default key file "secret_key.txt"
|
|||||||
d) Create "secret_key.txt" if it does not exist
|
d) Create "secret_key.txt" if it does not exist
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if os.getenv("INVENTREE_SECRET_KEY"):
|
if secret_key := os.getenv("INVENTREE_SECRET_KEY"):
|
||||||
# Secret key passed in directly
|
# Secret key passed in directly
|
||||||
SECRET_KEY = os.getenv("INVENTREE_SECRET_KEY").strip() # pragma: no cover
|
SECRET_KEY = secret_key.strip() # pragma: no cover
|
||||||
logger.info("SECRET_KEY loaded by INVENTREE_SECRET_KEY") # pragma: no cover
|
logger.info("SECRET_KEY loaded by INVENTREE_SECRET_KEY") # pragma: no cover
|
||||||
else:
|
else:
|
||||||
# Secret key passed in by file location
|
# Secret key passed in by file location
|
||||||
|
@ -691,7 +691,7 @@ class TestSettings(helpers.InvenTreeTestCase):
|
|||||||
|
|
||||||
valid = [
|
valid = [
|
||||||
'inventree/config.yaml',
|
'inventree/config.yaml',
|
||||||
'inventree/dev/config.yaml',
|
'inventree/data/config.yaml',
|
||||||
]
|
]
|
||||||
|
|
||||||
self.assertTrue(any([opt in config.get_config_file().lower() for opt in valid]))
|
self.assertTrue(any([opt in config.get_config_file().lower() for opt in valid]))
|
||||||
@ -706,7 +706,7 @@ class TestSettings(helpers.InvenTreeTestCase):
|
|||||||
|
|
||||||
valid = [
|
valid = [
|
||||||
'inventree/plugins.txt',
|
'inventree/plugins.txt',
|
||||||
'inventree/dev/plugins.txt',
|
'inventree/data/plugins.txt',
|
||||||
]
|
]
|
||||||
|
|
||||||
self.assertTrue(any([opt in config.get_plugin_file().lower() for opt in valid]))
|
self.assertTrue(any([opt in config.get_plugin_file().lower() for opt in valid]))
|
||||||
|
@ -813,6 +813,14 @@ class Build(MPTTModel, ReferenceIndexingMixin):
|
|||||||
interchangeable = kwargs.get('interchangeable', False)
|
interchangeable = kwargs.get('interchangeable', False)
|
||||||
substitutes = kwargs.get('substitutes', True)
|
substitutes = kwargs.get('substitutes', True)
|
||||||
|
|
||||||
|
def stock_sort(item, bom_item, variant_parts):
|
||||||
|
if item.part == bom_item.sub_part:
|
||||||
|
return 1
|
||||||
|
elif item.part in variant_parts:
|
||||||
|
return 2
|
||||||
|
else:
|
||||||
|
return 3
|
||||||
|
|
||||||
# Get a list of all 'untracked' BOM items
|
# Get a list of all 'untracked' BOM items
|
||||||
for bom_item in self.untracked_bom_items:
|
for bom_item in self.untracked_bom_items:
|
||||||
|
|
||||||
@ -859,15 +867,7 @@ class Build(MPTTModel, ReferenceIndexingMixin):
|
|||||||
|
|
||||||
This ensures that allocation priority is first given to "direct" parts
|
This ensures that allocation priority is first given to "direct" parts
|
||||||
"""
|
"""
|
||||||
def stock_sort(item):
|
available_stock = sorted(available_stock, key=lambda item, b=bom_item, v=variant_parts: stock_sort(item, b, v))
|
||||||
if item.part == bom_item.sub_part:
|
|
||||||
return 1
|
|
||||||
elif item.part in variant_parts:
|
|
||||||
return 2
|
|
||||||
else:
|
|
||||||
return 3
|
|
||||||
|
|
||||||
available_stock = sorted(available_stock, key=stock_sort)
|
|
||||||
|
|
||||||
if len(available_stock) == 0:
|
if len(available_stock) == 0:
|
||||||
# No stock items are available
|
# No stock items are available
|
||||||
|
@ -495,7 +495,7 @@ class PurchaseOrderLineItemList(APIDownloadMixin, ListCreateAPI):
|
|||||||
search_fields = [
|
search_fields = [
|
||||||
'part__part__name',
|
'part__part__name',
|
||||||
'part__part__description',
|
'part__part__description',
|
||||||
'part__MPN',
|
'part__manufacturer_part__MPN',
|
||||||
'part__SKU',
|
'part__SKU',
|
||||||
'reference',
|
'reference',
|
||||||
]
|
]
|
||||||
|
@ -168,23 +168,16 @@
|
|||||||
{% if order.status == PurchaseOrderStatus.PENDING %}
|
{% if order.status == PurchaseOrderStatus.PENDING %}
|
||||||
$('#new-po-line').click(function() {
|
$('#new-po-line').click(function() {
|
||||||
|
|
||||||
var fields = poLineItemFields({
|
createPurchaseOrderLineItem({{ order.pk }}, {
|
||||||
order: {{ order.pk }},
|
|
||||||
{% if order.supplier %}
|
{% if order.supplier %}
|
||||||
supplier: {{ order.supplier.pk }},
|
supplier: {{ order.supplier.pk }},
|
||||||
{% if order.supplier.currency %}
|
{% if order.supplier.currency %}
|
||||||
currency: '{{ order.supplier.currency }}',
|
currency: '{{ order.supplier.currency }}',
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
});
|
|
||||||
|
|
||||||
constructForm('{% url "api-po-line-list" %}', {
|
|
||||||
fields: fields,
|
|
||||||
method: 'POST',
|
|
||||||
title: '{% trans "Add Line Item" %}',
|
|
||||||
onSuccess: function() {
|
onSuccess: function() {
|
||||||
$('#po-line-table').bootstrapTable('refresh');
|
$('#po-line-table').bootstrapTable('refresh');
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -252,18 +252,19 @@ class APICallMixinTest(BaseMixinDefinition, TestCase):
|
|||||||
self.assertEqual(result.reason, 'OK')
|
self.assertEqual(result.reason, 'OK')
|
||||||
|
|
||||||
# api_call with full url
|
# api_call with full url
|
||||||
result = self.mixin.api_call('https://api.github.com/orgs/inventree', endpoint_is_url=True)
|
result = self.mixin.api_call('orgs/inventree')
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
|
|
||||||
# api_call with post and data
|
# api_call with post and data
|
||||||
result = self.mixin.api_call(
|
result = self.mixin.api_call(
|
||||||
'repos/inventree/InvenTree',
|
'https://reqres.in/api/users/',
|
||||||
method='GET'
|
data={"name": "morpheus", "job": "leader"},
|
||||||
|
method='POST',
|
||||||
|
endpoint_is_url=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
self.assertEqual(result['name'], 'InvenTree')
|
self.assertEqual(result['name'], 'morpheus')
|
||||||
self.assertEqual(result['html_url'], 'https://github.com/inventree/InvenTree')
|
|
||||||
|
|
||||||
# api_call with filter
|
# api_call with filter
|
||||||
result = self.mixin.api_call('repos/inventree/InvenTree/stargazers', url_args={'page': '2'})
|
result = self.mixin.api_call('repos/inventree/InvenTree/stargazers', url_args={'page': '2'})
|
||||||
|
@ -102,10 +102,14 @@ function editManufacturerPart(part, options={}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function supplierPartFields() {
|
function supplierPartFields(options={}) {
|
||||||
|
|
||||||
return {
|
var fields = {
|
||||||
part: {},
|
part: {
|
||||||
|
filters: {
|
||||||
|
purchaseable: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
manufacturer_part: {
|
manufacturer_part: {
|
||||||
filters: {
|
filters: {
|
||||||
part_detail: true,
|
part_detail: true,
|
||||||
@ -128,6 +132,12 @@ function supplierPartFields() {
|
|||||||
icon: 'fa-box',
|
icon: 'fa-box',
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (options.part) {
|
||||||
|
fields.manufacturer_part.filters.part = options.part;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -135,10 +145,11 @@ function supplierPartFields() {
|
|||||||
*/
|
*/
|
||||||
function createSupplierPart(options={}) {
|
function createSupplierPart(options={}) {
|
||||||
|
|
||||||
var fields = supplierPartFields();
|
var fields = supplierPartFields({
|
||||||
|
part: options.part,
|
||||||
|
});
|
||||||
|
|
||||||
if (options.part) {
|
if (options.part) {
|
||||||
fields.manufacturer_part.filters.part = options.part;
|
|
||||||
fields.part.hidden = true;
|
fields.part.hidden = true;
|
||||||
fields.part.value = options.part;
|
fields.part.value = options.part;
|
||||||
}
|
}
|
||||||
|
@ -255,15 +255,20 @@ function renderOwner(name, data, parameters={}, options={}) {
|
|||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
function renderPurchaseOrder(name, data, parameters={}, options={}) {
|
function renderPurchaseOrder(name, data, parameters={}, options={}) {
|
||||||
|
|
||||||
var html = `<span>${data.reference}</span>`;
|
var html = '';
|
||||||
|
|
||||||
var thumbnail = null;
|
|
||||||
|
|
||||||
if (data.supplier_detail) {
|
if (data.supplier_detail) {
|
||||||
thumbnail = data.supplier_detail.thumbnail || data.supplier_detail.image;
|
thumbnail = data.supplier_detail.thumbnail || data.supplier_detail.image;
|
||||||
|
|
||||||
html += ' - ' + select2Thumbnail(thumbnail);
|
html += select2Thumbnail(thumbnail);
|
||||||
html += `<span>${data.supplier_detail.name}</span>`;
|
}
|
||||||
|
|
||||||
|
html += `<span>${data.reference}</span>`;
|
||||||
|
|
||||||
|
var thumbnail = null;
|
||||||
|
|
||||||
|
if (data.supplier_detail) {
|
||||||
|
html += ` - <span>${data.supplier_detail.name}</span>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.description) {
|
if (data.description) {
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
renderLink,
|
renderLink,
|
||||||
salesOrderStatusDisplay,
|
salesOrderStatusDisplay,
|
||||||
setupFilterList,
|
setupFilterList,
|
||||||
|
supplierPartFields,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* exported
|
/* exported
|
||||||
@ -25,6 +26,8 @@
|
|||||||
completePurchaseOrder,
|
completePurchaseOrder,
|
||||||
completeShipment,
|
completeShipment,
|
||||||
completePendingShipments,
|
completePendingShipments,
|
||||||
|
createPurchaseOrder,
|
||||||
|
createPurchaseOrderLineItem,
|
||||||
createSalesOrder,
|
createSalesOrder,
|
||||||
createSalesOrderShipment,
|
createSalesOrderShipment,
|
||||||
editPurchaseOrderLineItem,
|
editPurchaseOrderLineItem,
|
||||||
@ -539,6 +542,26 @@ function createPurchaseOrder(options={}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Create a new PurchaseOrderLineItem
|
||||||
|
function createPurchaseOrderLineItem(order, options={}) {
|
||||||
|
|
||||||
|
var fields = poLineItemFields({
|
||||||
|
order: order,
|
||||||
|
supplier: options.supplier,
|
||||||
|
currency: options.currency,
|
||||||
|
});
|
||||||
|
|
||||||
|
constructForm('{% url "api-po-line-list" %}', {
|
||||||
|
fields: fields,
|
||||||
|
method: 'POST',
|
||||||
|
title: '{% trans "Add Line Item" %}',
|
||||||
|
onSuccess: function(response) {
|
||||||
|
handleFormSuccess(response, options);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Construct a set of fields for the SalesOrderLineItem form */
|
/* Construct a set of fields for the SalesOrderLineItem form */
|
||||||
function soLineItemFields(options={}) {
|
function soLineItemFields(options={}) {
|
||||||
|
|
||||||
@ -590,13 +613,40 @@ function poLineItemFields(options={}) {
|
|||||||
|
|
||||||
var fields = {
|
var fields = {
|
||||||
order: {
|
order: {
|
||||||
hidden: true,
|
filters: {
|
||||||
|
supplier_detail: true,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
part: {
|
part: {
|
||||||
filters: {
|
filters: {
|
||||||
part_detail: true,
|
part_detail: true,
|
||||||
supplier_detail: true,
|
supplier_detail: true,
|
||||||
supplier: options.supplier,
|
supplier: options.supplier,
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
method: 'POST',
|
||||||
|
title: '{% trans "Add Supplier Part" %}',
|
||||||
|
fields: function(data) {
|
||||||
|
var fields = supplierPartFields({
|
||||||
|
part: data.part,
|
||||||
|
});
|
||||||
|
|
||||||
|
fields.supplier.value = options.supplier;
|
||||||
|
|
||||||
|
// Adjust manufacturer part query based on selected part
|
||||||
|
fields.manufacturer_part.adjustFilters = function(query, opts) {
|
||||||
|
|
||||||
|
var part = getFormFieldValue('part', {}, opts);
|
||||||
|
|
||||||
|
if (part) {
|
||||||
|
query.part = part;
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
};
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
quantity: {},
|
quantity: {},
|
||||||
@ -610,6 +660,7 @@ function poLineItemFields(options={}) {
|
|||||||
|
|
||||||
if (options.order) {
|
if (options.order) {
|
||||||
fields.order.value = options.order;
|
fields.order.value = options.order;
|
||||||
|
fields.order.hidden = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.currency) {
|
if (options.currency) {
|
||||||
|
@ -22,7 +22,7 @@ services:
|
|||||||
inventree-dev-db:
|
inventree-dev-db:
|
||||||
container_name: inventree-dev-db
|
container_name: inventree-dev-db
|
||||||
image: postgres:13
|
image: postgres:13
|
||||||
ports:
|
expose:
|
||||||
- ${INVENTREE_DB_PORT:-5432}/tcp
|
- ${INVENTREE_DB_PORT:-5432}/tcp
|
||||||
environment:
|
environment:
|
||||||
- PGDATA=/var/lib/postgresql/data/dev/pgdb
|
- PGDATA=/var/lib/postgresql/data/dev/pgdb
|
||||||
|
@ -42,4 +42,7 @@ INVENTREE_CACHE_PORT=6379
|
|||||||
# Enable plugins?
|
# Enable plugins?
|
||||||
INVENTREE_PLUGINS_ENABLED=False
|
INVENTREE_PLUGINS_ENABLED=False
|
||||||
|
|
||||||
|
# Image tag that should be used
|
||||||
|
INVENTREE_TAG=stable
|
||||||
|
|
||||||
COMPOSE_PROJECT_NAME=inventree-production
|
COMPOSE_PROJECT_NAME=inventree-production
|
||||||
|
@ -45,7 +45,7 @@ services:
|
|||||||
inventree-db:
|
inventree-db:
|
||||||
container_name: inventree-db
|
container_name: inventree-db
|
||||||
image: postgres:13
|
image: postgres:13
|
||||||
ports:
|
expose:
|
||||||
- ${INVENTREE_DB_PORT:-5432}/tcp
|
- ${INVENTREE_DB_PORT:-5432}/tcp
|
||||||
environment:
|
environment:
|
||||||
- PGDATA=/var/lib/postgresql/data/pgdb
|
- PGDATA=/var/lib/postgresql/data/pgdb
|
||||||
@ -65,16 +65,16 @@ services:
|
|||||||
- inventree-db
|
- inventree-db
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
ports:
|
expose:
|
||||||
- ${INVENTREE_CACHE_PORT:-6379}:6379
|
- ${INVENTREE_CACHE_PORT:-6379}
|
||||||
restart: unless-stopped
|
restart: always
|
||||||
|
|
||||||
# InvenTree web server services
|
# InvenTree web server services
|
||||||
# Uses gunicorn as the web server
|
# Uses gunicorn as the web server
|
||||||
inventree-server:
|
inventree-server:
|
||||||
container_name: inventree-server
|
container_name: inventree-server
|
||||||
# If you wish to specify a particular InvenTree version, do so here
|
# If you wish to specify a particular InvenTree version, do so here
|
||||||
image: inventree/inventree:stable
|
image: inventree/inventree:${INVENTREE_TAG:-stable}
|
||||||
expose:
|
expose:
|
||||||
- 8000
|
- 8000
|
||||||
depends_on:
|
depends_on:
|
||||||
@ -85,13 +85,14 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
# Data volume must map to /home/inventree/data
|
# Data volume must map to /home/inventree/data
|
||||||
- inventree_data:/home/inventree/data
|
- inventree_data:/home/inventree/data
|
||||||
|
- inventree_plugins:/home/inventree/InvenTree/plugins
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
# Background worker process handles long-running or periodic tasks
|
# Background worker process handles long-running or periodic tasks
|
||||||
inventree-worker:
|
inventree-worker:
|
||||||
container_name: inventree-worker
|
container_name: inventree-worker
|
||||||
# If you wish to specify a particular InvenTree version, do so here
|
# If you wish to specify a particular InvenTree version, do so here
|
||||||
image: inventree/inventree:stable
|
image: inventree/inventree:${INVENTREE_TAG:-stable}
|
||||||
command: invoke worker
|
command: invoke worker
|
||||||
depends_on:
|
depends_on:
|
||||||
- inventree-server
|
- inventree-server
|
||||||
@ -100,6 +101,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
# Data volume must map to /home/inventree/data
|
# Data volume must map to /home/inventree/data
|
||||||
- inventree_data:/home/inventree/data
|
- inventree_data:/home/inventree/data
|
||||||
|
- inventree_plugins:/home/inventree/InvenTree/plugins
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
# nginx acts as a reverse proxy
|
# nginx acts as a reverse proxy
|
||||||
@ -126,7 +128,6 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
# NOTE: Change /path/to/data to a directory on your local machine
|
|
||||||
# Persistent data, stored external to the container(s)
|
# Persistent data, stored external to the container(s)
|
||||||
inventree_data:
|
inventree_data:
|
||||||
driver: local
|
driver: local
|
||||||
@ -135,3 +136,10 @@ volumes:
|
|||||||
o: bind
|
o: bind
|
||||||
# This directory specified where InvenTree data are stored "outside" the docker containers
|
# This directory specified where InvenTree data are stored "outside" the docker containers
|
||||||
device: ${INVENTREE_EXT_VOLUME:?You must specify the 'INVENTREE_EXT_VOLUME' variable in the .env file!}
|
device: ${INVENTREE_EXT_VOLUME:?You must specify the 'INVENTREE_EXT_VOLUME' variable in the .env file!}
|
||||||
|
inventree_plugins:
|
||||||
|
driver: local
|
||||||
|
driver_opts:
|
||||||
|
type: none
|
||||||
|
o: bind
|
||||||
|
# This directory specified where the optional local plugin directory is stored "outside" the docker containers
|
||||||
|
device: ${INVENTREE_EXT_PLUGINS:-./}
|
||||||
|
14
tasks.py
14
tasks.py
@ -406,7 +406,13 @@ def import_fixtures(c):
|
|||||||
|
|
||||||
|
|
||||||
# Execution tasks
|
# Execution tasks
|
||||||
@task(help={'address': 'Server address:port (default=127.0.0.1:8000)'})
|
@task
|
||||||
|
def wait(c):
|
||||||
|
"""Wait until the database connection is ready."""
|
||||||
|
return manage(c, "wait_for_db")
|
||||||
|
|
||||||
|
|
||||||
|
@task(pre=[wait], help={'address': 'Server address:port (default=127.0.0.1:8000)'})
|
||||||
def server(c, address="127.0.0.1:8000"):
|
def server(c, address="127.0.0.1:8000"):
|
||||||
"""Launch a (deveopment) server using Django's in-built webserver.
|
"""Launch a (deveopment) server using Django's in-built webserver.
|
||||||
|
|
||||||
@ -415,12 +421,6 @@ def server(c, address="127.0.0.1:8000"):
|
|||||||
manage(c, "runserver {address}".format(address=address), pty=True)
|
manage(c, "runserver {address}".format(address=address), pty=True)
|
||||||
|
|
||||||
|
|
||||||
@task
|
|
||||||
def wait(c):
|
|
||||||
"""Wait until the database connection is ready."""
|
|
||||||
return manage(c, "wait_for_db")
|
|
||||||
|
|
||||||
|
|
||||||
@task(pre=[wait])
|
@task(pre=[wait])
|
||||||
def worker(c):
|
def worker(c):
|
||||||
"""Run the InvenTree background worker process."""
|
"""Run the InvenTree background worker process."""
|
||||||
|
Reference in New Issue
Block a user