mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-28 11:36:44 +00:00
Remove references to old setting (#8018)
* Remove references to old setting - Now offloaded to plugins * Remove REPORT_ENABLE_TEST_REPORT setting * Cleanup * Add new boolean setting to control whether reports are attached automatically * Attach generated report to model instance * Update unit testing * Bump API version
This commit is contained in:
parent
9f92475af0
commit
07fac28b76
@ -1,13 +1,16 @@
|
|||||||
"""InvenTree API version information."""
|
"""InvenTree API version information."""
|
||||||
|
|
||||||
# InvenTree API version
|
# InvenTree API version
|
||||||
INVENTREE_API_VERSION = 250
|
INVENTREE_API_VERSION = 251
|
||||||
|
|
||||||
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
|
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
|
||||||
|
|
||||||
|
|
||||||
INVENTREE_API_TEXT = """
|
INVENTREE_API_TEXT = """
|
||||||
|
|
||||||
|
v251 - 2024-09-06 : https://github.com/inventree/InvenTree/pull/8018
|
||||||
|
- Adds "attach_to_model" field to the ReporTemplate model
|
||||||
|
|
||||||
v250 - 2024-09-04 : https://github.com/inventree/InvenTree/pull/8069
|
v250 - 2024-09-04 : https://github.com/inventree/InvenTree/pull/8069
|
||||||
- Fixes 'revision' field definition in Part serializer
|
- Fixes 'revision' field definition in Part serializer
|
||||||
|
|
||||||
|
@ -1704,20 +1704,6 @@ class InvenTreeSetting(BaseInvenTreeSetting):
|
|||||||
'default': 'A4',
|
'default': 'A4',
|
||||||
'choices': report.helpers.report_page_size_options,
|
'choices': report.helpers.report_page_size_options,
|
||||||
},
|
},
|
||||||
'REPORT_ENABLE_TEST_REPORT': {
|
|
||||||
'name': _('Enable Test Reports'),
|
|
||||||
'description': _('Enable generation of test reports'),
|
|
||||||
'default': True,
|
|
||||||
'validator': bool,
|
|
||||||
},
|
|
||||||
'REPORT_ATTACH_TEST_REPORT': {
|
|
||||||
'name': _('Attach Test Reports'),
|
|
||||||
'description': _(
|
|
||||||
'When printing a Test Report, attach a copy of the Test Report to the associated Stock Item'
|
|
||||||
),
|
|
||||||
'default': False,
|
|
||||||
'validator': bool,
|
|
||||||
},
|
|
||||||
'SERIAL_NUMBER_GLOBALLY_UNIQUE': {
|
'SERIAL_NUMBER_GLOBALLY_UNIQUE': {
|
||||||
'name': _('Globally Unique Serials'),
|
'name': _('Globally Unique Serials'),
|
||||||
'description': _('Serial numbers for stock items must be globally unique'),
|
'description': _('Serial numbers for stock items must be globally unique'),
|
||||||
|
@ -228,9 +228,6 @@ class SettingsTest(InvenTreeTestCase):
|
|||||||
report_size_obj = InvenTreeSetting.get_setting_object(
|
report_size_obj = InvenTreeSetting.get_setting_object(
|
||||||
'REPORT_DEFAULT_PAGE_SIZE'
|
'REPORT_DEFAULT_PAGE_SIZE'
|
||||||
)
|
)
|
||||||
report_test_obj = InvenTreeSetting.get_setting_object(
|
|
||||||
'REPORT_ENABLE_TEST_REPORT'
|
|
||||||
)
|
|
||||||
|
|
||||||
# check settings base fields
|
# check settings base fields
|
||||||
self.assertEqual(instance_obj.name, 'Server Instance Name')
|
self.assertEqual(instance_obj.name, 'Server Instance Name')
|
||||||
@ -260,7 +257,6 @@ class SettingsTest(InvenTreeTestCase):
|
|||||||
|
|
||||||
# check setting_type
|
# check setting_type
|
||||||
self.assertEqual(instance_obj.setting_type(), 'string')
|
self.assertEqual(instance_obj.setting_type(), 'string')
|
||||||
self.assertEqual(report_test_obj.setting_type(), 'boolean')
|
|
||||||
self.assertEqual(stale_days.setting_type(), 'integer')
|
self.assertEqual(stale_days.setting_type(), 'integer')
|
||||||
|
|
||||||
# check as_int
|
# check as_int
|
||||||
@ -269,9 +265,6 @@ class SettingsTest(InvenTreeTestCase):
|
|||||||
instance_obj.as_int(), 'InvenTree'
|
instance_obj.as_int(), 'InvenTree'
|
||||||
) # not an int -> return default
|
) # not an int -> return default
|
||||||
|
|
||||||
# check as_bool
|
|
||||||
self.assertEqual(report_test_obj.as_bool(), True)
|
|
||||||
|
|
||||||
# check to_native_value
|
# check to_native_value
|
||||||
self.assertEqual(stale_days.to_native_value(), 0)
|
self.assertEqual(stale_days.to_native_value(), 0)
|
||||||
|
|
||||||
|
@ -350,6 +350,15 @@ class ReportPrint(GenericAPIView):
|
|||||||
|
|
||||||
output = template.render(instance, request)
|
output = template.render(instance, request)
|
||||||
|
|
||||||
|
if template.attach_to_model:
|
||||||
|
# Attach the generated report to the model instance
|
||||||
|
data = output.get_document().write_pdf()
|
||||||
|
instance.create_attachment(
|
||||||
|
attachment=ContentFile(data, report_name),
|
||||||
|
comment=_('Report saved at time of printing'),
|
||||||
|
upload_user=request.user,
|
||||||
|
)
|
||||||
|
|
||||||
# Provide generated report to any interested plugins
|
# Provide generated report to any interested plugins
|
||||||
for plugin in registry.with_mixin('report'):
|
for plugin in registry.with_mixin('report'):
|
||||||
try:
|
try:
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 4.2.15 on 2024-09-05 23:18
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('report', '0027_alter_labeltemplate_model_type_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='labeltemplate',
|
||||||
|
name='attach_to_model',
|
||||||
|
field=models.BooleanField(default=False, help_text='Save report output as an attachment against linked model instance when printing', verbose_name='Attach to Model on Print'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='reporttemplate',
|
||||||
|
name='attach_to_model',
|
||||||
|
field=models.BooleanField(default=False, help_text='Save report output as an attachment against linked model instance when printing', verbose_name='Attach to Model on Print'),
|
||||||
|
),
|
||||||
|
]
|
@ -163,6 +163,14 @@ class ReportTemplateBase(MetadataMixin, InvenTree.models.InvenTreeModel):
|
|||||||
editable=False,
|
editable=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
attach_to_model = models.BooleanField(
|
||||||
|
default=False,
|
||||||
|
verbose_name=_('Attach to Model on Print'),
|
||||||
|
help_text=_(
|
||||||
|
'Save report output as an attachment against linked model instance when printing'
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
def generate_filename(self, context, **kwargs):
|
def generate_filename(self, context, **kwargs):
|
||||||
"""Generate a filename for this report."""
|
"""Generate a filename for this report."""
|
||||||
template_string = Template(self.filename_pattern)
|
template_string = Template(self.filename_pattern)
|
||||||
|
@ -42,6 +42,7 @@ class ReportSerializerBase(InvenTreeModelSerializer):
|
|||||||
'filename_pattern',
|
'filename_pattern',
|
||||||
'enabled',
|
'enabled',
|
||||||
'revision',
|
'revision',
|
||||||
|
'attach_to_model',
|
||||||
]
|
]
|
||||||
|
|
||||||
template = InvenTreeAttachmentSerializerField(required=True)
|
template = InvenTreeAttachmentSerializerField(required=True)
|
||||||
|
@ -555,8 +555,16 @@ class TestReportTest(PrintTestMixins, ReportTest):
|
|||||||
template = ReportTemplate.objects.filter(
|
template = ReportTemplate.objects.filter(
|
||||||
enabled=True, model_type='stockitem'
|
enabled=True, model_type='stockitem'
|
||||||
).first()
|
).first()
|
||||||
|
|
||||||
self.assertIsNotNone(template)
|
self.assertIsNotNone(template)
|
||||||
|
|
||||||
|
# Ensure that the 'attach_to_model' attribute is initially False
|
||||||
|
template.attach_to_model = False
|
||||||
|
template.save()
|
||||||
|
template.refresh_from_db()
|
||||||
|
|
||||||
|
self.assertFalse(template.attach_to_model)
|
||||||
|
|
||||||
url = reverse(self.print_url)
|
url = reverse(self.print_url)
|
||||||
|
|
||||||
# Try to print without providing a valid StockItem
|
# Try to print without providing a valid StockItem
|
||||||
@ -568,18 +576,37 @@ class TestReportTest(PrintTestMixins, ReportTest):
|
|||||||
# Now print with a valid StockItem
|
# Now print with a valid StockItem
|
||||||
item = StockItem.objects.first()
|
item = StockItem.objects.first()
|
||||||
|
|
||||||
|
n = item.attachments.count()
|
||||||
|
|
||||||
response = self.post(
|
response = self.post(
|
||||||
url, {'template': template.pk, 'items': [item.pk]}, expected_code=201
|
url, {'template': template.pk, 'items': [item.pk]}, expected_code=201
|
||||||
)
|
)
|
||||||
|
|
||||||
# There should be a link to the generated PDF
|
# There should be a link to the generated PDF
|
||||||
self.assertEqual(response.data['output'].startswith('/media/report/'), True)
|
self.assertTrue(response.data['output'].startswith('/media/report/'))
|
||||||
|
self.assertTrue(response.data['output'].endswith('.pdf'))
|
||||||
|
|
||||||
# By default, this should *not* have created an attachment against this stockitem
|
# By default, this should *not* have created an attachment against this stockitem
|
||||||
|
self.assertEqual(n, item.attachments.count())
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
Attachment.objects.filter(model_id=item.pk, model_type='stockitem').exists()
|
Attachment.objects.filter(model_id=item.pk, model_type='stockitem').exists()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Now try again, but attach the generated PDF to the StockItem
|
||||||
|
template.attach_to_model = True
|
||||||
|
template.save()
|
||||||
|
|
||||||
|
response = self.post(
|
||||||
|
url, {'template': template.pk, 'items': [item.pk]}, expected_code=201
|
||||||
|
)
|
||||||
|
|
||||||
|
# A new attachment should have been created
|
||||||
|
self.assertEqual(n + 1, item.attachments.count())
|
||||||
|
attachment = item.attachments.order_by('-pk').first()
|
||||||
|
|
||||||
|
# The attachment should be a PDF
|
||||||
|
self.assertTrue(attachment.attachment.name.endswith('.pdf'))
|
||||||
|
|
||||||
def test_mdl_build(self):
|
def test_mdl_build(self):
|
||||||
"""Test the Build model."""
|
"""Test the Build model."""
|
||||||
self.run_print_test(Build, 'build', label=False)
|
self.run_print_test(Build, 'build', label=False)
|
||||||
|
@ -54,19 +54,15 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<!-- Document / label menu -->
|
<!-- Document / label menu -->
|
||||||
{% if test_report_enabled or labels_enabled %}
|
|
||||||
<div class='btn-group' role='group'>
|
<div class='btn-group' role='group'>
|
||||||
<button id='document-options' title='{% trans "Printing actions" %}' class='btn btn-outline-secondary dropdown-toggle' type='button' data-bs-toggle='dropdown'><span class='fas fa-print'></span> <span class='caret'></span></button>
|
<button id='document-options' title='{% trans "Printing actions" %}' class='btn btn-outline-secondary dropdown-toggle' type='button' data-bs-toggle='dropdown'><span class='fas fa-print'></span> <span class='caret'></span></button>
|
||||||
<ul class='dropdown-menu' role='menu'>
|
<ul class='dropdown-menu' role='menu'>
|
||||||
{% if labels_enabled %}
|
{% if labels_enabled %}
|
||||||
<li><a class='dropdown-item' href='#' id='print-label'><span class='fas fa-tag'></span> {% trans "Print Label" %}</a></li>
|
<li><a class='dropdown-item' href='#' id='print-label'><span class='fas fa-tag'></span> {% trans "Print Label" %}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if test_report_enabled %}
|
<li><a class='dropdown-item' href='#' id='stock-test-report'><span class='fas fa-file-pdf'></span> {% trans "Print Report" %}</a></li>
|
||||||
<li><a class='dropdown-item' href='#' id='stock-test-report'><span class='fas fa-file-pdf'></span> {% trans "Test Report" %}</a></li>
|
|
||||||
{% endif %}
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<!-- Stock adjustment menu -->
|
<!-- Stock adjustment menu -->
|
||||||
{% if user_owns_item %}
|
{% if user_owns_item %}
|
||||||
|
@ -18,8 +18,6 @@
|
|||||||
{% include "InvenTree/settings/setting.html" with key="REPORT_DEFAULT_PAGE_SIZE" icon="fa-print" %}
|
{% include "InvenTree/settings/setting.html" with key="REPORT_DEFAULT_PAGE_SIZE" icon="fa-print" %}
|
||||||
{% include "InvenTree/settings/setting.html" with key="REPORT_DEBUG_MODE" icon="fa-laptop-code" %}
|
{% include "InvenTree/settings/setting.html" with key="REPORT_DEBUG_MODE" icon="fa-laptop-code" %}
|
||||||
{% include "InvenTree/settings/setting.html" with key="REPORT_LOG_ERRORS" icon="fa-exclamation-circle" %}
|
{% include "InvenTree/settings/setting.html" with key="REPORT_LOG_ERRORS" icon="fa-exclamation-circle" %}
|
||||||
{% include "InvenTree/settings/setting.html" with key="REPORT_ENABLE_TEST_REPORT" icon="fa-vial" %}
|
|
||||||
{% include "InvenTree/settings/setting.html" with key="REPORT_ATTACH_TEST_REPORT" icon="fa-file-upload" %}
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
{% plugins_enabled as plugins_enabled %}
|
{% plugins_enabled as plugins_enabled %}
|
||||||
{% settings_value 'BARCODE_ENABLE' as barcodes %}
|
{% settings_value 'BARCODE_ENABLE' as barcodes %}
|
||||||
{% settings_value 'REPORT_ENABLE_TEST_REPORT' as test_report_enabled %}
|
|
||||||
{% settings_value 'RETURNORDER_ENABLED' as return_order_enabled %}
|
{% settings_value 'RETURNORDER_ENABLED' as return_order_enabled %}
|
||||||
{% settings_value "REPORT_ENABLE" as report_enabled %}
|
{% settings_value "REPORT_ENABLE" as report_enabled %}
|
||||||
{% settings_value "SERVER_RESTART_REQUIRED" as server_restart_required %}
|
{% settings_value "SERVER_RESTART_REQUIRED" as server_restart_required %}
|
||||||
|
@ -21,6 +21,12 @@ export default function ReportTemplateTable() {
|
|||||||
modelRenderer: (instance: any) => (
|
modelRenderer: (instance: any) => (
|
||||||
<YesNoButton value={instance.landscape} />
|
<YesNoButton value={instance.landscape} />
|
||||||
)
|
)
|
||||||
|
},
|
||||||
|
attach_to_model: {
|
||||||
|
label: t`Attach to Model`,
|
||||||
|
modelRenderer: (instance: any) => (
|
||||||
|
<YesNoButton value={instance.attach_to_model} />
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
@ -161,9 +161,7 @@ export default function SystemSettings() {
|
|||||||
'REPORT_ENABLE',
|
'REPORT_ENABLE',
|
||||||
'REPORT_DEFAULT_PAGE_SIZE',
|
'REPORT_DEFAULT_PAGE_SIZE',
|
||||||
'REPORT_DEBUG_MODE',
|
'REPORT_DEBUG_MODE',
|
||||||
'REPORT_LOG_ERRORS',
|
'REPORT_LOG_ERRORS'
|
||||||
'REPORT_ENABLE_TEST_REPORT',
|
|
||||||
'REPORT_ATTACH_TEST_REPORT'
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
7
tasks.py
7
tasks.py
@ -1184,7 +1184,7 @@ def frontend_build(c):
|
|||||||
|
|
||||||
|
|
||||||
@task
|
@task
|
||||||
def frontend_dev(c):
|
def frontend_server(c):
|
||||||
"""Start frontend development server.
|
"""Start frontend development server.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -1447,7 +1447,7 @@ def clear_generated(c):
|
|||||||
development = Collection(
|
development = Collection(
|
||||||
delete_data,
|
delete_data,
|
||||||
docs_server,
|
docs_server,
|
||||||
frontend_dev,
|
frontend_server,
|
||||||
gunicorn,
|
gunicorn,
|
||||||
import_fixtures,
|
import_fixtures,
|
||||||
schema,
|
schema,
|
||||||
@ -1458,6 +1458,7 @@ development = Collection(
|
|||||||
test_translations,
|
test_translations,
|
||||||
translate,
|
translate,
|
||||||
)
|
)
|
||||||
|
|
||||||
internal = Collection(
|
internal = Collection(
|
||||||
clean_settings,
|
clean_settings,
|
||||||
clear_generated,
|
clear_generated,
|
||||||
@ -1474,6 +1475,7 @@ internal = Collection(
|
|||||||
translate_stats,
|
translate_stats,
|
||||||
worker,
|
worker,
|
||||||
)
|
)
|
||||||
|
|
||||||
ns = Collection(
|
ns = Collection(
|
||||||
backup,
|
backup,
|
||||||
export_records,
|
export_records,
|
||||||
@ -1490,5 +1492,6 @@ ns = Collection(
|
|||||||
version,
|
version,
|
||||||
wait,
|
wait,
|
||||||
)
|
)
|
||||||
|
|
||||||
ns.add_collection(development, 'dev')
|
ns.add_collection(development, 'dev')
|
||||||
ns.add_collection(internal, 'int')
|
ns.add_collection(internal, 'int')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user