Compare commits

...

16 commits
main ... 6.0

Author SHA1 Message Date
Frederik Jaeckel
5791a1f443 Etikett ver 6.0.4 zum Änderungssatz 58d134168fc9 hinzugefügt 2023-06-06 17:19:19 +02:00
Frederik Jaeckel
27860b60fb Version 6.0.4 2023-06-06 17:19:00 +02:00
Frederik Jaeckel
d9958b5ccf formatting, code optimized 2023-06-06 16:46:03 +02:00
Frederik Jaeckel
5c22c0fbb3 Etikett ver 6.0.3 zum Änderungssatz 217a7c0c5128 hinzugefügt 2023-02-14 10:53:42 +01:00
Frederik Jaeckel
40bde467fe Version 6.0.3 2023-02-14 10:53:34 +01:00
Frederik Jaeckel
875946c793 setup 2nd 2023-02-14 10:51:48 +01:00
Frederik Jaeckel
7aef8e2fad setup.py 2023-01-23 13:18:48 +01:00
Frederik Jaeckel
411d7e52ae Etikett ver 6.0.2 zum Änderungssatz af0201b6924a hinzugefügt 2023-01-23 13:13:36 +01:00
Frederik Jaeckel
9d0001f262 Version 6.0.2 2023-01-23 13:13:29 +01:00
Frederik Jaeckel
a149f46dbb line: show image in tab 'image/pdf' 2023-01-23 13:11:54 +01:00
Frederik Jaeckel
3750a4b0f6 depends korrigiert 2022-12-30 23:02:04 +01:00
Frederik Jaeckel
89ad435e72 Etikett ver 6.0.1 zum Änderungssatz d6834c950d17 hinzugefügt 2022-11-29 10:37:14 +01:00
Frederik Jaeckel
51934f46bc Version 6.0.1 2022-11-29 10:37:05 +01:00
Frederik Jaeckel
fa526fa69e fix: exception beim hochladen eines unbekannten bildtypes 2022-11-29 10:30:39 +01:00
Frederik Jaeckel
6aa9bb5325 Etikett ver 6.0.0 zum Änderungssatz 0e8cb36121b5 hinzugefügt 2022-10-14 15:30:18 +02:00
Frederik Jaeckel
1286fa6f2f Version 6.0.0 2022-10-14 15:30:08 +02:00
13 changed files with 144 additions and 74 deletions

View file

@ -1,3 +1,6 @@
syntax: glob syntax: glob
__pycache__/* __pycache__/*
locale/convert_de2en.py locale/convert_de2en.py
build/*
mds_cashbook_media.egg-info/*
dist/*

View file

@ -14,6 +14,23 @@ Requires
Changes Changes
======= =======
*6.0.4 - 06.06.2023*
- code optimized
*6.0.3 - 14.02.2023*
- updt: setup.py
*6.0.2 - 23.01.2023*
- add: show image in tab 'image/pdf'
*6.0.1 - 29.11.2022*
- fix: exception when image type unknown
*6.0.0 - 14.10.2022* *6.0.0 - 14.10.2022*
- init - init

View file

@ -6,6 +6,7 @@
from trytond.pool import Pool from trytond.pool import Pool
from .line import Line from .line import Line
def register(): def register():
Pool.register( Pool.register(
Line, Line,

60
line.py
View file

@ -3,13 +3,13 @@
# The COPYRIGHT file at the top level of this repository contains the # The COPYRIGHT file at the top level of this repository contains the
# full copyright notices and license terms. # full copyright notices and license terms.
import mimetypes, magic import mimetypes
import magic
from io import BytesIO from io import BytesIO
from PIL import Image from PIL import Image, UnidentifiedImageError
from trytond.model import fields from trytond.model import fields
from trytond.pool import Pool, PoolMeta from trytond.pool import PoolMeta
from trytond.config import config from trytond.config import config
from trytond.transaction import Transaction
from trytond.exceptions import UserError from trytond.exceptions import UserError
from trytond.i18n import gettext from trytond.i18n import gettext
from trytond.pyson import Eval, Bool from trytond.pyson import Eval, Bool
@ -24,24 +24,44 @@ try :
image_limit = 100 image_limit = 100
if image_limit > 10000: if image_limit > 10000:
image_limit = 10000 image_limit = 10000
except : except Exception:
image_limit = 2000 image_limit = 2000
STATES2 = {}
STATES2.update(STATES)
DEPENDS2 = []
DEPENDS2.extend(DEPENDS)
class Line(metaclass=PoolMeta): class Line(metaclass=PoolMeta):
__name__ = 'cashbook.line' __name__ = 'cashbook.line'
media = fields.Binary(string='Image of PDF', filename='media_name', media = fields.Binary(
file_id='media_id', store_prefix=store_prefix, string='Image of PDF', filename='media_name', file_id='media_id',
states=STATES, depends=DEPENDS) store_prefix=store_prefix, states=STATES2, depends=DEPENDS2)
media_name = fields.Char(string='File name', media_name = fields.Char(
string='File name',
states={ states={
'required': Bool(Eval('media')), 'required': Bool(Eval('media')),
'readonly': STATES['readonly'], 'readonly': STATES2['readonly'],
}, depends=DEPENDS) }, depends=DEPENDS2)
media_id = fields.Char(string='File ID', readonly=True) media_id = fields.Char(string='File ID', readonly=True)
media_mime = fields.Char(string='MIME', readonly=True) media_mime = fields.Char(string='MIME', readonly=True)
media_size = fields.Integer(string='File size', readonly=True) media_size = fields.Integer(string='File size', readonly=True)
media_image = fields.Function(fields.Binary(
string='Image', readonly=True,
states={
'invisible': ~Eval('media_mime', '').in_([
'image/png', 'image/jpg', 'image/jpeg']),
}, depends=['media_mime']), 'on_change_with_media_image')
@fields.depends('media', 'media_mime')
def on_change_with_media_image(self, name=True):
""" return binary if its a image
"""
if (self.media_mime or '-').startswith('image/'):
return self.media
@classmethod @classmethod
def _identify_file(cls, data, mime=True): def _identify_file(cls, data, mime=True):
@ -65,7 +85,10 @@ class Line(metaclass=PoolMeta):
""" """
image_data2 = None image_data2 = None
with BytesIO(image_data) as fhdl: with BytesIO(image_data) as fhdl:
try:
image = Image.open(fhdl, 'r') image = Image.open(fhdl, 'r')
except UnidentifiedImageError:
raise UserError(gettext('cashbook_media.msg_file_unknown_type'))
(width, height) = image.size (width, height) = image.size
if (width > image_limit) or (height > image_limit): if (width > image_limit) or (height > image_limit):
@ -98,12 +121,14 @@ class Line(metaclass=PoolMeta):
else: else:
values['media_mime'] = cls._identify_file(values['media'][:1024]) values['media_mime'] = cls._identify_file(values['media'][:1024])
# if its a image, resize it to fit in (image_limit x image_limit) pixel # if its a image, resize it to fit
# in (image_limit x image_limit) pixel
if values['media_mime'].startswith('image'): if values['media_mime'].startswith('image'):
new_image = cls.resize_image_file(values['media']) new_image = cls.resize_image_file(values['media'])
if new_image is not None: if new_image is not None:
values['media'] = new_image values['media'] = new_image
values['media_mime'] = cls._identify_file(values['media'][:1024]) values['media_mime'] = cls._identify_file(
values['media'][:1024])
values['media_size'] = len(values['media']) values['media_size'] = len(values['media'])
file_ext = mimetypes.guess_extension(values['media_mime']) file_ext = mimetypes.guess_extension(values['media_mime'])
@ -126,15 +151,14 @@ class Line(metaclass=PoolMeta):
if line.media_size > 1024*1024*5: if line.media_size > 1024*1024*5:
raise UserError(gettext( raise UserError(gettext(
'cashbook_media.msg_file_too_big', 'cashbook_media.msg_file_too_big',
recname = line.rec_name, recname=line.rec_name))
)) if line.media_mime not in [
if not line.media_mime in ['application/pdf', 'application/pdf',
'image/png', 'image/jpg', 'image/jpeg']: 'image/png', 'image/jpg', 'image/jpeg']:
raise UserError(gettext( raise UserError(gettext(
'cashbook_media.msg_file_invalid_mime', 'cashbook_media.msg_file_invalid_mime',
recname=line.rec_name, recname=line.rec_name,
fmime = line.media_mime, fmime=line.media_mime))
))
@classmethod @classmethod
def create(cls, vlist): def create(cls, vlist):

View file

@ -14,6 +14,10 @@ msgctxt "model:ir.message,text:msg_file_invalid_mime"
msgid "The file type '%(fmime)s' of the record '%(recname)s' is not allowed. (allowed: PNG, JPG, PDF)" msgid "The file type '%(fmime)s' of the record '%(recname)s' is not allowed. (allowed: PNG, JPG, PDF)"
msgstr "Der Dateityp '%(fmime)s' des Datensatzes '%(recname)s' ist nicht zugelassen. (erlaubt: PNG, JPG, PDF)" msgstr "Der Dateityp '%(fmime)s' des Datensatzes '%(recname)s' ist nicht zugelassen. (erlaubt: PNG, JPG, PDF)"
msgctxt "model:ir.message,text:msg_file_unknown_type"
msgid "cannot identify image file"
msgstr "Bilddatei kann nicht identifiziert werden"
################# #################
# cashbook.line # # cashbook.line #
@ -42,3 +46,6 @@ msgctxt "field:cashbook.line,media_size:"
msgid "File size" msgid "File size"
msgstr "Dateigröße" msgstr "Dateigröße"
msgctxt "field:cashbook.line,media_image:"
msgid "Image"
msgstr "Bild"

View file

@ -10,6 +10,10 @@ msgctxt "model:ir.message,text:msg_file_invalid_mime"
msgid "The file type '%(fmime)s' of the record '%(recname)s' is not allowed. (allowed: PNG, JPG, PDF)" msgid "The file type '%(fmime)s' of the record '%(recname)s' is not allowed. (allowed: PNG, JPG, PDF)"
msgstr "The file type '%(fmime)s' of the record '%(recname)s' is not allowed. (allowed: PNG, JPG, PDF)" msgstr "The file type '%(fmime)s' of the record '%(recname)s' is not allowed. (allowed: PNG, JPG, PDF)"
msgctxt "model:ir.message,text:msg_file_unknown_type"
msgid "cannot identify image file"
msgstr "cannot identify image file"
msgctxt "view:cashbook.line:" msgctxt "view:cashbook.line:"
msgid "Image/PDF" msgid "Image/PDF"
msgstr "Image/PDF" msgstr "Image/PDF"

View file

@ -11,6 +11,9 @@ full copyright notices and license terms. -->
<record model="ir.message" id="msg_file_invalid_mime"> <record model="ir.message" id="msg_file_invalid_mime">
<field name="text">The file type '%(fmime)s' of the record '%(recname)s' is not allowed. (allowed: PNG, JPG, PDF)</field> <field name="text">The file type '%(fmime)s' of the record '%(recname)s' is not allowed. (allowed: PNG, JPG, PDF)</field>
</record> </record>
<record model="ir.message" id="msg_file_unknown_type">
<field name="text">cannot identify image file</field>
</record>
</data> </data>
</tryton> </tryton>

View file

@ -2,7 +2,7 @@
""" """
# Always prefer setuptools over distutils # Always prefer setuptools over distutils
from setuptools import setup, find_packages from setuptools import setup
# To use a consistent encoding # To use a consistent encoding
from codecs import open from codecs import open
from os import path from os import path
@ -51,23 +51,32 @@ for dep in info.get('depends', []):
prefix = modversion[dep]['prefix'] prefix = modversion[dep]['prefix']
if len(modversion[dep]['max']) > 0: if len(modversion[dep]['max']) > 0:
requires.append('%s_%s >= %s, <= %s' % requires.append(
(prefix, dep, modversion[dep]['min'], modversion[dep]['max'])) '%s_%s >= %s, <= %s' %
(prefix, dep,
modversion[dep]['min'],
modversion[dep]['max']))
else: else:
requires.append('%s_%s >= %s' % requires.append(
'%s_%s >= %s' %
(prefix, dep, modversion[dep]['min'])) (prefix, dep, modversion[dep]['min']))
else: else:
requires.append('%s_%s >= %s.%s, < %s.%s' % requires.append(
('trytond', dep, major_version, minor_version, '%s_%s >= %s.%s, < %s.%s' % (
'trytond', dep, major_version, minor_version,
major_version, minor_version + 1)) major_version, minor_version + 1))
requires.append('trytond >= %s.%s, < %s.%s' % requires.append(
(major_version, minor_version, major_version, minor_version + 1)) 'trytond >= %s.%s, < %s.%s' % (
major_version, minor_version, major_version, minor_version + 1))
setup(name='%s_%s' % (PREFIX, MODULE), setup(
name='%s_%s' % (PREFIX, MODULE),
version=info.get('version', '0.0.1'), version=info.get('version', '0.0.1'),
description='Tryton module to add a file-field to cashbook.', description='Tryton module to add a file-field to cashbook.',
long_description=long_description, long_description=long_description,
long_description_content_type='text/x-rst',
url='https://www.m-ds.de/', url='https://www.m-ds.de/',
download_url='https://scmdev.m-ds.de/Tryton/Extra/cashbook_media',
author='martin-data services', author='martin-data services',
author_email='service@m-ds.de', author_email='service@m-ds.de',
license='GPL-3', license='GPL-3',
@ -95,7 +104,8 @@ setup(name='%s_%s' % (PREFIX, MODULE),
'trytond.modules.%s' % MODULE, 'trytond.modules.%s' % MODULE,
], ],
package_data={ package_data={
'trytond.modules.%s' % MODULE: (info.get('xml', []) 'trytond.modules.%s' % MODULE: (
info.get('xml', [])
+ ['tryton.cfg', 'locale/*.po', 'tests/*.py', + ['tryton.cfg', 'locale/*.po', 'tests/*.py',
'view/*.xml', 'versiondep.txt', 'README.rst']), 'view/*.xml', 'versiondep.txt', 'README.rst']),
}, },

View file

@ -4,21 +4,14 @@
import trytond.tests.test_tryton import trytond.tests.test_tryton
import unittest import unittest
from trytond.modules.cashbook_media.tests.test_line import LineTestCase from .test_line import LineTestCase
__all__ = ['suite'] __all__ = ['suite']
class CashbookTestCase(\
LineTestCase,
):
'Test cashbook module'
module = 'cashbook_media'
# end CashbookTestCase
def suite(): def suite():
suite = trytond.tests.test_tryton.suite() suite = trytond.tests.test_tryton.suite()
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(CashbookTestCase)) suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
LineTestCase))
return suite return suite

View file

@ -5,11 +5,10 @@
from io import BytesIO from io import BytesIO
from PIL import Image from PIL import Image
from trytond.tests.test_tryton import ModuleTestCase, with_transaction from trytond.tests.test_tryton import with_transaction
from trytond.pool import Pool from trytond.pool import Pool
from trytond.transaction import Transaction
from trytond.exceptions import UserError from trytond.exceptions import UserError
from trytond.modules.cashbook.tests import CashbookTestCase from trytond.modules.cashbook.tests.test_module import CashbookTestCase
from datetime import date from datetime import date
from decimal import Decimal from decimal import Decimal
from .img_data import img_data_png, dok_data_pdf, text_data from .img_data import img_data_png, dok_data_pdf, text_data
@ -126,8 +125,11 @@ class LineTestCase(CashbookTestCase):
self.assertEqual(book.state, 'open') self.assertEqual(book.state, 'open')
# add invalid file # add invalid file
self.assertRaisesRegex(UserError, self.assertRaisesRegex(
"The file type 'text/plain' of the record '05/02/2022|Rev|1.00 usd|Text 2 [Cat1]' is not allowed. (allowed: PNG, JPG, PDF)", UserError,
"The file type 'text/plain' of the record " +
"'05/02/2022|Rev|1.00 usd|Text 2 [Cat1]' is not allowed. " +
"(allowed: PNG, JPG, PDF)",
Book.write, Book.write,
*[ *[
[book], [book],
@ -146,8 +148,11 @@ class LineTestCase(CashbookTestCase):
]) ])
# replace image at line-1 by invalid file # replace image at line-1 by invalid file
self.assertRaisesRegex(UserError, self.assertRaisesRegex(
"The file type 'text/plain' of the record '05/02/2022|Rev|1.00 usd|Text 2 [Cat1]' is not allowed. (allowed: PNG, JPG, PDF)", UserError,
"The file type 'text/plain' of the record " +
"'05/02/2022|Rev|1.00 usd|Text 2 [Cat1]' is not allowed. " +
"(allowed: PNG, JPG, PDF)",
Lines.write, Lines.write,
*[ *[
[book.lines[0]], [book.lines[0]],
@ -163,7 +168,6 @@ class LineTestCase(CashbookTestCase):
""" """
pool = Pool() pool = Pool()
Book = pool.get('cashbook.book') Book = pool.get('cashbook.book')
Lines = pool.get('cashbook.line')
types = self.prep_type() types = self.prep_type()
category = self.prep_category(cattype='in') category = self.prep_category(cattype='in')
@ -226,3 +230,6 @@ class LineTestCase(CashbookTestCase):
self.assertEqual(img2.size, (2000, 837)) self.assertEqual(img2.size, (2000, 837))
# end LineTestCase # end LineTestCase
del CashbookTestCase

View file

@ -1,7 +1,8 @@
[tryton] [tryton]
version=6.0.0 version=6.0.4
depends: depends:
cashbook cashbook
xml: xml:
message.xml message.xml
line.xml line.xml

View file

@ -1 +1 @@
cashbook;6.0.18;6.0.999;mds cashbook;6.0.28;6.0.999;mds

View file

@ -13,10 +13,10 @@ full copyright notices and license terms. -->
<label name="media_name"/> <label name="media_name"/>
<field name="media_name"/> <field name="media_name"/>
<label name="media_mime"/> <label name="media_mime"/>
<field name="media_mime"/> <field name="media_mime"/>
<field name="media_image" readonly="1" colspan="4" widget="image" xexpand="1" yexpand="1"/>
</page> </page>
</xpath> </xpath>