mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge branch 'master' of https://github.com/inventree/InvenTree into plugin-2037
This commit is contained in:
commit
b4faaa7a46
7
.github/workflows/postgresql.yaml
vendored
7
.github/workflows/postgresql.yaml
vendored
@ -27,6 +27,7 @@ jobs:
|
||||
INVENTREE_DEBUG: info
|
||||
INVENTREE_MEDIA_ROOT: ./media
|
||||
INVENTREE_STATIC_ROOT: ./static
|
||||
INVENTREE_CACHE_HOST: localhost
|
||||
|
||||
services:
|
||||
postgres:
|
||||
@ -37,6 +38,11 @@ jobs:
|
||||
ports:
|
||||
- 5432:5432
|
||||
|
||||
redis:
|
||||
image: redis
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v2
|
||||
@ -49,6 +55,7 @@ jobs:
|
||||
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
|
||||
|
@ -15,6 +15,7 @@ import logging
|
||||
|
||||
import os
|
||||
import random
|
||||
import socket
|
||||
import string
|
||||
import shutil
|
||||
import sys
|
||||
@ -378,30 +379,6 @@ REST_FRAMEWORK = {
|
||||
|
||||
WSGI_APPLICATION = 'InvenTree.wsgi.application'
|
||||
|
||||
background_workers = os.environ.get('INVENTREE_BACKGROUND_WORKERS', None)
|
||||
|
||||
if background_workers is not None:
|
||||
try:
|
||||
background_workers = int(background_workers)
|
||||
except ValueError:
|
||||
background_workers = None
|
||||
|
||||
if background_workers is None:
|
||||
# Sensible default?
|
||||
background_workers = 4
|
||||
|
||||
# django-q configuration
|
||||
Q_CLUSTER = {
|
||||
'name': 'InvenTree',
|
||||
'workers': background_workers,
|
||||
'timeout': 90,
|
||||
'retry': 120,
|
||||
'queue_limit': 50,
|
||||
'bulk': 10,
|
||||
'orm': 'default',
|
||||
'sync': False,
|
||||
}
|
||||
|
||||
"""
|
||||
Configure the database backend based on the user-specified values.
|
||||
|
||||
@ -579,12 +556,84 @@ DATABASES = {
|
||||
}
|
||||
|
||||
|
||||
CACHES = {
|
||||
'default': {
|
||||
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||
},
|
||||
_cache_config = CONFIG.get("cache", {})
|
||||
_cache_host = _cache_config.get("host", os.getenv("INVENTREE_CACHE_HOST"))
|
||||
_cache_port = _cache_config.get(
|
||||
"port", os.getenv("INVENTREE_CACHE_PORT", "6379")
|
||||
)
|
||||
|
||||
if _cache_host:
|
||||
# We are going to rely upon a possibly non-localhost for our cache,
|
||||
# so don't wait too long for the cache as nothing in the cache should be
|
||||
# irreplacable. Django Q Cluster will just try again later.
|
||||
_cache_options = {
|
||||
"CLIENT_CLASS": "django_redis.client.DefaultClient",
|
||||
"SOCKET_CONNECT_TIMEOUT": int(os.getenv("CACHE_CONNECT_TIMEOUT", "2")),
|
||||
"SOCKET_TIMEOUT": int(os.getenv("CACHE_SOCKET_TIMEOUT", "2")),
|
||||
"CONNECTION_POOL_KWARGS": {
|
||||
"socket_keepalive": _is_true(
|
||||
os.getenv("CACHE_TCP_KEEPALIVE", "1")
|
||||
),
|
||||
"socket_keepalive_options": {
|
||||
socket.TCP_KEEPCNT: int(
|
||||
os.getenv("CACHE_KEEPALIVES_COUNT", "5")
|
||||
),
|
||||
socket.TCP_KEEPIDLE: int(
|
||||
os.getenv("CACHE_KEEPALIVES_IDLE", "1")
|
||||
),
|
||||
socket.TCP_KEEPINTVL: int(
|
||||
os.getenv("CACHE_KEEPALIVES_INTERVAL", "1")
|
||||
),
|
||||
socket.TCP_USER_TIMEOUT: int(
|
||||
os.getenv("CACHE_TCP_USER_TIMEOUT", "1000")
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
CACHES = {
|
||||
# Connection configuration for Django Q Cluster
|
||||
"worker": {
|
||||
"BACKEND": "django_redis.cache.RedisCache",
|
||||
"LOCATION": f"redis://{_cache_host}:{_cache_port}/0",
|
||||
"OPTIONS": _cache_options,
|
||||
},
|
||||
"default": {
|
||||
"BACKEND": "django_redis.cache.RedisCache",
|
||||
"LOCATION": f"redis://{_cache_host}:{_cache_port}/1",
|
||||
"OPTIONS": _cache_options,
|
||||
},
|
||||
}
|
||||
else:
|
||||
CACHES = {
|
||||
"default": {
|
||||
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
|
||||
},
|
||||
}
|
||||
|
||||
try:
|
||||
# 4 background workers seems like a sensible default
|
||||
background_workers = int(os.environ.get('INVENTREE_BACKGROUND_WORKERS', 4))
|
||||
except ValueError:
|
||||
background_workers = 4
|
||||
|
||||
# django-q configuration
|
||||
Q_CLUSTER = {
|
||||
'name': 'InvenTree',
|
||||
'workers': background_workers,
|
||||
'timeout': 90,
|
||||
'retry': 120,
|
||||
'queue_limit': 50,
|
||||
'bulk': 10,
|
||||
'orm': 'default',
|
||||
'sync': False,
|
||||
}
|
||||
|
||||
if _cache_host:
|
||||
# If using external redis cache, make the cache the broker for Django Q
|
||||
# as well
|
||||
Q_CLUSTER["django_redis"] = "worker"
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
|
||||
|
||||
|
@ -34,6 +34,7 @@ src="{% static 'img/blank_image.png' %}"
|
||||
{% include "admin_button.html" with url=url %}
|
||||
{% endif %}
|
||||
<!-- Printing options -->
|
||||
{% if report_enabled %}
|
||||
<div class='btn-group'>
|
||||
<button id='print-options' title='{% trans "Print actions" %}' class='btn btn-outline-secondary dropdown-toggle' type='button' data-bs-toggle='dropdown'>
|
||||
<span class='fas fa-print'></span> <span class='caret'></span>
|
||||
@ -42,6 +43,7 @@ src="{% static 'img/blank_image.png' %}"
|
||||
<li><a class='dropdown-item' href='#' id='print-build-report'><span class='fas fa-file-pdf'></span> {% trans "Print build order report" %}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
<!-- Build actions -->
|
||||
{% if roles.build.change %}
|
||||
<div class='btn-group'>
|
||||
@ -224,9 +226,11 @@ src="{% static 'img/blank_image.png' %}"
|
||||
{% endif %}
|
||||
});
|
||||
|
||||
{% if report_enabled %}
|
||||
$('#print-build-report').click(function() {
|
||||
printBuildReports([{{ build.pk }}]);
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
$("#build-delete").on('click', function() {
|
||||
launchModalForm(
|
||||
|
@ -27,6 +27,7 @@
|
||||
<div class='button-toolbar container-fluid' style='float: right;'>
|
||||
<div class='btn-group' role='group'>
|
||||
|
||||
{% if report_enabled %}
|
||||
<div class='btn-group' role='group'>
|
||||
<!-- Print actions -->
|
||||
<button id='build-print-options' class='btn btn-primary dropdown-toggle' data-bs-toggle='dropdown'>
|
||||
@ -38,6 +39,7 @@
|
||||
</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
<!-- Buttons to switch between list and calendar views -->
|
||||
<button class='btn btn-outline-secondary' type='button' id='view-calendar' title='{% trans "Display calendar view" %}'>
|
||||
<span class='fas fa-calendar-alt'></span>
|
||||
@ -181,6 +183,7 @@ loadBuildTable($("#build-table"), {
|
||||
url: "{% url 'api-build-list' %}",
|
||||
});
|
||||
|
||||
{% if report_enabled %}
|
||||
$('#multi-build-print').click(function() {
|
||||
var rows = $("#build-table").bootstrapTable('getSelections');
|
||||
|
||||
@ -192,5 +195,6 @@ $('#multi-build-print').click(function() {
|
||||
|
||||
printBuildReports(build_ids);
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
@ -791,6 +791,13 @@ class InvenTreeSetting(BaseInvenTreeSetting):
|
||||
'validator': InvenTree.validators.validate_part_name_format
|
||||
},
|
||||
|
||||
'REPORT_ENABLE': {
|
||||
'name': _('Enable Reports'),
|
||||
'description': _('Enable generation of reports'),
|
||||
'default': False,
|
||||
'validator': bool,
|
||||
},
|
||||
|
||||
'REPORT_DEBUG_MODE': {
|
||||
'name': _('Debug Mode'),
|
||||
'description': _('Generate reports in debug mode (HTML output)'),
|
||||
|
@ -29,7 +29,9 @@
|
||||
<span class='fas fa-print'></span> <span class='caret'></span>
|
||||
</button>
|
||||
<ul class='dropdown-menu' role='menu'>
|
||||
{% if report_enabled %}
|
||||
<li><a class='dropdown-item' href='#' id='print-order-report'><span class='fas fa-file-pdf'></span> {% trans "Print purchase order report" %}</a></li>
|
||||
{% endif %}
|
||||
<li><a class='dropdown-item' href='#' id='export-order'><span class='fas fa-file-download'></span> {% trans "Export order to file" %}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -169,9 +171,11 @@ $("#place-order").click(function() {
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
{% if report_enabled %}
|
||||
$('#print-order-report').click(function() {
|
||||
printPurchaseOrderReports([{{ order.pk }}]);
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
$("#edit-order").click(function() {
|
||||
|
||||
|
@ -26,10 +26,11 @@
|
||||
<div id='table-buttons'>
|
||||
<div class='button-toolbar container-fluid' style='float: right;'>
|
||||
<div class='btn-group' role='group'>
|
||||
|
||||
{% if report_enabled %}
|
||||
<button id='order-print' class='btn btn-outline-secondary' title='{% trans "Print Order Reports" %}'>
|
||||
<span class='fas fa-print'></span>
|
||||
</button>
|
||||
{% endif %}
|
||||
<button class='btn btn-outline-secondary' type='button' id='view-calendar' title='{% trans "Display calendar view" %}'>
|
||||
<span class='fas fa-calendar-alt'></span>
|
||||
</button>
|
||||
@ -169,6 +170,7 @@ $("#view-list").click(function() {
|
||||
$("#view-calendar").show();
|
||||
});
|
||||
|
||||
{% if report_enabled %}
|
||||
$("#order-print").click(function() {
|
||||
var rows = $("#purchase-order-table").bootstrapTable('getSelections');
|
||||
|
||||
@ -180,6 +182,7 @@ $("#order-print").click(function() {
|
||||
|
||||
printPurchaseOrderReports(orders);
|
||||
})
|
||||
{% endif %}
|
||||
|
||||
$("#po-create").click(function() {
|
||||
createPurchaseOrder();
|
||||
|
@ -39,7 +39,9 @@ src="{% static 'img/blank_image.png' %}"
|
||||
<span class='fas fa-print'></span> <span class='caret'></span>
|
||||
</button>
|
||||
<ul class='dropdown-menu' role='menu'>
|
||||
{% if report_enabled %}
|
||||
<li><a class='dropdown-item' href='#' id='print-order-report'><span class='fas fa-file-pdf'></span> {% trans "Print sales order report" %}</a></li>
|
||||
{% endif %}
|
||||
<li><a class='dropdown-item' href='#' id='export-order'><span class='fas fa-file-download'></span> {% trans "Export order to file" %}</a></li>
|
||||
<!--
|
||||
<li><a class='dropdown-item' href='#' id='print-packing-list'><span class='fas fa-clipboard-list'></span>{% trans "Print packing list" %}</a></li>
|
||||
@ -206,9 +208,11 @@ $("#ship-order").click(function() {
|
||||
});
|
||||
});
|
||||
|
||||
{% if report_enabled %}
|
||||
$('#print-order-report').click(function() {
|
||||
printSalesOrderReports([{{ order.pk }}]);
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
$('#export-order').click(function() {
|
||||
exportOrder('{% url "so-export" order.id %}');
|
||||
|
@ -29,10 +29,11 @@
|
||||
<div id='table-buttons'>
|
||||
<div class='button-toolbar container-fluid' style='float: right;'>
|
||||
<div class='btn-group'>
|
||||
|
||||
{% if report_enabled %}
|
||||
<button id='order-print' class='btn btn-outline-secondary' title='{% trans "Print Order Reports" %}'>
|
||||
<span class='fas fa-print'></span>
|
||||
</button>
|
||||
{% endif %}
|
||||
<button class='btn btn-outline-secondary' type='button' id='view-calendar' title='{% trans "Display calendar view" %}'>
|
||||
<span class='fas fa-calendar-alt'></span>
|
||||
</button>
|
||||
@ -173,6 +174,7 @@ loadSalesOrderTable("#sales-order-table", {
|
||||
url: "{% url 'api-so-list' %}",
|
||||
});
|
||||
|
||||
{% if report_enabled %}
|
||||
$("#order-print").click(function() {
|
||||
var rows = $("#sales-order-table").bootstrapTable('getSelections');
|
||||
|
||||
@ -184,6 +186,7 @@ $("#order-print").click(function() {
|
||||
|
||||
printSalesOrderReports(orders);
|
||||
})
|
||||
{% endif %}
|
||||
|
||||
$("#so-create").click(function() {
|
||||
createSalesOrder();
|
||||
|
@ -164,7 +164,9 @@
|
||||
<li><a class='dropdown-item' href='#' id='multi-part-category' title='{% trans "Set category" %}'>{% trans "Set Category" %}</a></li>
|
||||
{% endif %}
|
||||
<li><a class='dropdown-item' href='#' id='multi-part-order' title='{% trans "Order parts" %}'>{% trans "Order Parts" %}</a></li>
|
||||
{% if report_enabled %}
|
||||
<li><a class='dropdown-item' href='#' id='multi-part-print-label' title='{% trans "Print Labels" %}'>{% trans "Print Labels" %}</a></li>
|
||||
{% endif %}
|
||||
<li><a class='dropdown-item' href='#' id='multi-part-export' title='{% trans "Export" %}'>{% trans "Export Data" %}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -373,7 +373,9 @@
|
||||
</button>
|
||||
<ul class='dropdown-menu' role='menu'>
|
||||
<li><a class='dropdown-item' href='#' id='download-bom'><span class='fas fa-file-download'></span> {% trans "Export BOM" %}</a></li>
|
||||
{% if report_enabled %}
|
||||
<li><a class='dropdown-item' href='#' id='print-bom-report'><span class='fas fa-file-pdf'></span> {% trans "Print BOM Report" %}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
<!-- Actions menu -->
|
||||
@ -766,9 +768,11 @@
|
||||
);
|
||||
});
|
||||
|
||||
{% if report_enabled %}
|
||||
$("#print-bom-report").click(function() {
|
||||
printBomReports([{{ part.pk }}]);
|
||||
});
|
||||
{% endif %}
|
||||
});
|
||||
|
||||
// Load the "related parts" tab
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
<table class='table table-striped table-condensed'>
|
||||
<tbody>
|
||||
{% include "InvenTree/settings/setting.html" with key="REPORT_ENABLE" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="REPORT_DEFAULT_PAGE_SIZE" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="REPORT_DEBUG_MODE" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="REPORT_ENABLE_TEST_REPORT" %}
|
||||
|
@ -5,6 +5,9 @@
|
||||
{% load inventree_extras %}
|
||||
{% load plugin_extras %}
|
||||
|
||||
{% block breadcrumb_list %}
|
||||
{% endblock %}
|
||||
|
||||
{% block page_title %}
|
||||
{% inventree_title %} | {% trans "Settings" %}
|
||||
{% endblock %}
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
{% settings_value 'BARCODE_ENABLE' as barcodes %}
|
||||
{% settings_value 'REPORT_ENABLE_TEST_REPORT' as test_report_enabled %}
|
||||
{% settings_value "REPORT_ENABLE" as report_enabled %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
@ -11,3 +11,6 @@ psycopg2>=2.9.1
|
||||
mysqlclient>=2.0.3
|
||||
pgcli>=3.1.0
|
||||
mariadb>=1.0.7
|
||||
|
||||
# Cache
|
||||
django-redis>=5.0.0
|
||||
|
Loading…
Reference in New Issue
Block a user