mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge remote-tracking branch 'inventree/master'
This commit is contained in:
commit
ff5846732c
@ -1,3 +1,6 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ from .models import ReportSnippet, TestReport, ReportAsset
|
|||||||
|
|
||||||
class ReportTemplateAdmin(admin.ModelAdmin):
|
class ReportTemplateAdmin(admin.ModelAdmin):
|
||||||
|
|
||||||
list_display = ('name', 'description', 'template', 'filters', 'enabled')
|
list_display = ('name', 'description', 'template', 'filters', 'enabled', 'revision')
|
||||||
|
|
||||||
|
|
||||||
class ReportSnippetAdmin(admin.ModelAdmin):
|
class ReportSnippetAdmin(admin.ModelAdmin):
|
||||||
|
18
InvenTree/report/migrations/0009_testreport_revision.py
Normal file
18
InvenTree/report/migrations/0009_testreport_revision.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 3.0.7 on 2021-02-05 00:53
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('report', '0008_auto_20210204_2100'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='testreport',
|
||||||
|
name='revision',
|
||||||
|
field=models.PositiveIntegerField(default=1, help_text='Report revision number (auto-increments)', verbose_name='Revision'),
|
||||||
|
),
|
||||||
|
]
|
18
InvenTree/report/migrations/0010_auto_20210205_1201.py
Normal file
18
InvenTree/report/migrations/0010_auto_20210205_1201.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 3.0.7 on 2021-02-05 01:01
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('report', '0009_testreport_revision'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='testreport',
|
||||||
|
name='revision',
|
||||||
|
field=models.PositiveIntegerField(default=1, editable=False, help_text='Report revision number (auto-increments)', verbose_name='Revision'),
|
||||||
|
),
|
||||||
|
]
|
@ -7,12 +7,14 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import logging
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
from django.core.files.storage import FileSystemStorage
|
||||||
from django.core.validators import FileExtensionValidator
|
from django.core.validators import FileExtensionValidator
|
||||||
|
|
||||||
import stock.models
|
import stock.models
|
||||||
@ -29,6 +31,35 @@ except OSError as err:
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ReportFileUpload(FileSystemStorage):
|
||||||
|
"""
|
||||||
|
Custom implementation of FileSystemStorage class.
|
||||||
|
|
||||||
|
When uploading a report (or a snippet / asset / etc),
|
||||||
|
it is often important to ensure the filename is not arbitrarily *changed*,
|
||||||
|
if the name of the uploaded file is identical to the currently stored file.
|
||||||
|
|
||||||
|
For example, a snippet or asset file is referenced in a template by filename,
|
||||||
|
and we do not want that filename to change when we upload a new *version*
|
||||||
|
of the snippet or asset file.
|
||||||
|
|
||||||
|
This uploader class performs the following pseudo-code function:
|
||||||
|
|
||||||
|
- If the model is *new*, proceed as normal
|
||||||
|
- If the model is being updated:
|
||||||
|
a) If the new filename is *different* from the existing filename, proceed as normal
|
||||||
|
b) If the new filename is *identical* to the existing filename, we want to overwrite the existing file
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get_available_name(self, name, max_length=None):
|
||||||
|
|
||||||
|
print("Name:", name)
|
||||||
|
return super().get_available_name(name, max_length)
|
||||||
|
|
||||||
|
|
||||||
def rename_template(instance, filename):
|
def rename_template(instance, filename):
|
||||||
|
|
||||||
return instance.rename_file(filename)
|
return instance.rename_file(filename)
|
||||||
@ -62,6 +93,13 @@ class ReportBase(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
|
||||||
|
# Increment revision number
|
||||||
|
self.revision += 1
|
||||||
|
|
||||||
|
super().save()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "{n} - {d}".format(n=self.name, d=self.description)
|
return "{n} - {d}".format(n=self.name, d=self.description)
|
||||||
|
|
||||||
@ -113,6 +151,13 @@ class ReportBase(models.Model):
|
|||||||
help_text=_("Report template description")
|
help_text=_("Report template description")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
revision = models.PositiveIntegerField(
|
||||||
|
default=1,
|
||||||
|
verbose_name=_("Revision"),
|
||||||
|
help_text=_("Report revision number (auto-increments)"),
|
||||||
|
editable=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ReportTemplateBase(ReportBase):
|
class ReportTemplateBase(ReportBase):
|
||||||
"""
|
"""
|
||||||
@ -145,6 +190,7 @@ class ReportTemplateBase(ReportBase):
|
|||||||
|
|
||||||
context['report_name'] = self.name
|
context['report_name'] = self.name
|
||||||
context['report_description'] = self.description
|
context['report_description'] = self.description
|
||||||
|
context['report_revision'] = self.revision
|
||||||
context['request'] = request
|
context['request'] = request
|
||||||
context['user'] = request.user
|
context['user'] = request.user
|
||||||
context['date'] = datetime.datetime.now().date()
|
context['date'] = datetime.datetime.now().date()
|
||||||
@ -220,7 +266,19 @@ def rename_snippet(instance, filename):
|
|||||||
|
|
||||||
filename = os.path.basename(filename)
|
filename = os.path.basename(filename)
|
||||||
|
|
||||||
return os.path.join('report', 'snippets', filename)
|
path = os.path.join('report', 'snippets', filename)
|
||||||
|
|
||||||
|
# If the snippet file is the *same* filename as the one being uploaded,
|
||||||
|
# delete the original one from the media directory
|
||||||
|
if str(filename) == str(instance.snippet):
|
||||||
|
fullpath = os.path.join(settings.MEDIA_ROOT, path)
|
||||||
|
fullpath = os.path.abspath(fullpath)
|
||||||
|
|
||||||
|
if os.path.exists(fullpath):
|
||||||
|
logger.info(f"Deleting existing snippet file: '{filename}'")
|
||||||
|
os.remove(fullpath)
|
||||||
|
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
class ReportSnippet(models.Model):
|
class ReportSnippet(models.Model):
|
||||||
@ -244,7 +302,19 @@ def rename_asset(instance, filename):
|
|||||||
|
|
||||||
filename = os.path.basename(filename)
|
filename = os.path.basename(filename)
|
||||||
|
|
||||||
return os.path.join('report', 'assets', filename)
|
path = os.path.join('report', 'assets', filename)
|
||||||
|
|
||||||
|
# If the asset file is the *same* filename as the one being uploaded,
|
||||||
|
# delete the original one from the media directory
|
||||||
|
if str(filename) == str(instance.asset):
|
||||||
|
fullpath = os.path.join(settings.MEDIA_ROOT, path)
|
||||||
|
fullpath = os.path.abspath(fullpath)
|
||||||
|
|
||||||
|
if os.path.exists(fullpath):
|
||||||
|
logger.info(f"Deleting existing asset file: '{filename}'")
|
||||||
|
os.remove(fullpath)
|
||||||
|
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
class ReportAsset(models.Model):
|
class ReportAsset(models.Model):
|
||||||
|
@ -52,7 +52,7 @@ function selectTestReport(reports, items, options={}) {
|
|||||||
<form method='post' action='' class='js-modal-form' enctype='multipart/form-data'>
|
<form method='post' action='' class='js-modal-form' enctype='multipart/form-data'>
|
||||||
<div class='form-group'>
|
<div class='form-group'>
|
||||||
<label class='control-label requiredField' for='id_report'>
|
<label class='control-label requiredField' for='id_report'>
|
||||||
{% trans "Select Label" %}
|
{% trans "Select Report Template" %}
|
||||||
</label>
|
</label>
|
||||||
<div class='controls'>
|
<div class='controls'>
|
||||||
<select id='id_report' class='select form-control name='report'>
|
<select id='id_report' class='select form-control name='report'>
|
||||||
|
Loading…
Reference in New Issue
Block a user