[tryton-commits] changeset in trytond:default Add validate option to trytond-admin

2021-01-25 Thread Cédric Krier
changeset d27b905106dd in trytond:default
details: https://hg.tryton.org/trytond?cmd=changeset;node=d27b905106dd
description:
Add validate option to trytond-admin

It validates a percentage of the listed models or all and report the 
errors.

issue9782
review312751002
diffstat:

 CHANGELOG  |   1 +
 trytond/admin.py   |  39 +++
 trytond/commandline.py |   5 +
 3 files changed, 45 insertions(+), 0 deletions(-)

diffs (76 lines):

diff -r 32cd371b3e9c -r d27b905106dd CHANGELOG
--- a/CHANGELOG Wed Jan 20 00:52:07 2021 +0100
+++ b/CHANGELOG Mon Jan 25 22:56:02 2021 +0100
@@ -1,3 +1,4 @@
+* Add validate option to trytond-admin
 * Refresh pool of other processes
 * Add clear_all method to Cache
 * Support Genshi element directives in HTML editor
diff -r 32cd371b3e9c -r d27b905106dd trytond/admin.py
--- a/trytond/admin.py  Wed Jan 20 00:52:07 2021 +0100
+++ b/trytond/admin.py  Mon Jan 25 22:56:02 2021 +0100
@@ -3,6 +3,7 @@
 import sys
 import os
 import logging
+import random
 from getpass import getpass
 
 from sql import Table, Literal
@@ -119,3 +120,41 @@
 if options.hostname is not None:
 configuration.hostname = options.hostname or None
 configuration.save()
+with Transaction().start(db_name, 0, readonly=True):
+if options.validate is not None:
+validate(options.validate, options.validate_percentage)
+
+
+def validate(models, percentage=100):
+from trytond.model import ModelStorage, ModelSingleton
+from trytond.model.exceptions import ValidationError
+logger = logging.getLogger('validate')
+pool = Pool()
+if not models:
+models = sorted([n for n, _ in pool.iterobject()])
+ratio = min(100, percentage) / 100
+in_max = Transaction().database.IN_MAX
+for name in models:
+logger.info("validate: %s", name)
+Model = pool.get(name)
+if not issubclass(Model, ModelStorage):
+continue
+offset = 0
+limit = in_max
+while True:
+records = Model.search(
+[], order=[('id', 'ASC')], offset=offset, limit=limit)
+if not records:
+break
+records = Model.browse(
+random.sample(records, int(len(records) * ratio)))
+for record in records:
+try:
+Model._validate([record])
+except ValidationError as exception:
+logger.error("%s: KO '%s'", record, exception)
+else:
+logger.info("%s: OK", record)
+if issubclass(Model, ModelSingleton):
+break
+offset += limit
diff -r 32cd371b3e9c -r d27b905106dd trytond/commandline.py
--- a/trytond/commandline.pyWed Jan 20 00:52:07 2021 +0100
+++ b/trytond/commandline.pyMon Jan 25 22:56:02 2021 +0100
@@ -90,6 +90,11 @@
 default=[], metavar='CODE', help="Load language translations")
 parser.add_argument("--hostname", dest="hostname", default=None,
 help="Limit database listing to the hostname")
+parser.add_argument("--validate", dest="validate", nargs='*',
+metavar='MODEL', help="validate records of models")
+parser.add_argument("--validate-percentage", dest="validate_percentage",
+type=float, default=100, metavar="PERCENTAGE",
+help="percentage of records to validate (default: 100)")
 
 parser.epilog = ('The first time a database is initialized '
 'or when the password is set, the admin password is read '



[tryton-commits] changeset in tryton:default Execute report asynchronously

2021-01-25 Thread Cédric Krier
changeset 8e13d64f983f in tryton:default
details: https://hg.tryton.org/tryton?cmd=changeset;node=8e13d64f983f
description:
Execute report asynchronously

Some reports may be long to generate so it is better to display the 
watch
cursor.

issue8845
review349111003
diffstat:

 CHANGELOG |   1 +
 tryton/action/main.py |  36 ++--
 2 files changed, 19 insertions(+), 18 deletions(-)

diffs (62 lines):

diff -r 42d0c1e001a1 -r 8e13d64f983f CHANGELOG
--- a/CHANGELOG Sun Jan 24 20:59:46 2021 +0100
+++ b/CHANGELOG Mon Jan 25 22:13:11 2021 +0100
@@ -1,3 +1,4 @@
+* Execute report asynchronously
 * Add support for Python 3.9
 * Support empty value for timedelta converter
 * Add interactive search on tree view
diff -r 42d0c1e001a1 -r 8e13d64f983f tryton/action/main.py
--- a/tryton/action/main.py Sun Jan 24 20:59:46 2021 +0100
+++ b/tryton/action/main.py Mon Jan 25 22:13:11 2021 +0100
@@ -4,7 +4,7 @@
 import webbrowser
 
 import tryton.rpc as rpc
-from tryton.common import RPCProgress, RPCExecute, RPCException
+from tryton.common import RPCExecute, RPCException
 from tryton.common import message, selection, file_write, file_open
 from tryton.config import CONFIG
 from tryton.pyson import PYSONDecoder
@@ -18,24 +18,24 @@
 def exec_report(name, data, direct_print=False, context=None):
 if context is None:
 context = {}
-data = data.copy()
-ctx = rpc.CONTEXT.copy()
-ctx.update(context)
-ctx['direct_print'] = direct_print
-args = ('report', name, 'execute', data.get('ids', []), data, ctx)
-try:
-res = RPCProgress('execute', args).run()
-except RPCException:
-return False
-if not res:
-return False
-(type, data, print_p, name) = res
-if not print_p and direct_print:
-print_p = True
+else:
+context = context.copy()
+context['direct_print'] = direct_print
+ids = data.get('ids', [])
 
-fp_name = file_write((name, type), data)
-file_open(fp_name, type, print_p=print_p)
-return True
+def callback(result):
+try:
+result = result()
+except RPCException:
+return
+type, data, print_p, name = result
+if not print_p and direct_print:
+print_p = True
+fp_name = file_write((name, type), data)
+file_open(fp_name, type, print_p=print_p)
+RPCExecute(
+'report', name, 'execute', ids, data, context=context,
+callback=callback)
 
 @staticmethod
 def execute(action, data, context=None, keyword=False):



[tryton-commits] changeset in modules/sale_payment:default Avoid duplicate record...

2021-01-25 Thread Sergi Almacellas Abellana
changeset fe5699894b9f in modules/sale_payment:default
details: 
https://hg.tryton.org/modules/sale_payment?cmd=changeset;node=fe5699894b9f
description:
Avoid duplicate records when confirming sale payments

issue9969
review322971002
diffstat:

 account.py |  4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diffs (14 lines):

diff -r 009610ee7f1c -r fe5699894b9f account.py
--- a/account.pyFri Jan 22 01:16:37 2021 +0100
+++ b/account.pyMon Jan 25 16:36:22 2021 +0100
@@ -18,8 +18,8 @@
 
 result = func(cls, payments, *args, **kwargs)
 
-sales = [p.origin for p in payments
-if isinstance(p.origin, Sale)]
+sales = {p.origin for p in payments
+if isinstance(p.origin, Sale)}
 sales = Sale.browse(sales)  # optimize cache
 Sale.payment_confirm(sales)
 



[tryton-commits] changeset in sao:default Keep empty string attribute of label no...

2021-01-25 Thread Nicolas Évrard
changeset 668481952aca in sao:default
details: https://hg.tryton.org/sao?cmd=changeset;node=668481952aca
description:
Keep empty string attribute of label node when necessary

issue10022
review339691009
diffstat:

 src/view.js |  3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diffs (13 lines):

diff -r 7c5827774384 -r 668481952aca src/view.js
--- a/src/view.js   Fri Jan 22 01:15:24 2021 +0100
+++ b/src/view.js   Mon Jan 25 15:32:57 2021 +0100
@@ -132,7 +132,8 @@
 if (!node_attrs.widget) {
 node_attrs.widget = field.type;
 }
-if ((node.tagName == 'label') && (!node_attrs.string)) {
+if ((node.tagName == 'label') &&
+(node_attrs.string === undefined)) {
 node_attrs.string = field.string + Sao.i18n.gettext(':');
 }
 if ((node.tagName == 'field') && (!node_attrs.help)) {