[REF] account_check_printing: Speed-up payment creation
The method constraint to validate the Check Number is slow
1. Analyzing the following query:
```sql
SELECT
payment.check_number,
move.journal_id
FROM
account_payment payment
JOIN account_move move ON move.id = payment.move_id
JOIN account_journal journal ON journal.id = move.journal_id,
account_payment other_payment
JOIN account_move other_move ON other_move.id = other_payment.move_id
WHERE
payment.check_number::integer = other_payment.check_number::integer
AND move.journal_id = other_move.journal_id
AND payment.id != other_payment.id
AND payment.id IN (1085159)
AND move.state = 'posted'
AND other_move.state = 'posted';
```
The output is:
Planning Time: 3.354 ms
Execution Time: 2514.660 ms
Discarding null values
```diff
AND other_move.state = 'posted';
+ AND payment.check_number IS NOT NULL
+ AND other_payment.check_number IS NOT NULL
```
The output is
Planning Time: 3.216 ms
Execution Time: 0.140 ms
2. The constraint is computed even if the payment is not a check (check_number is empty)
Returning early save useless extra computating
It is not needed to compare falsy values for duplicated for whole table
3. The validation to check is it not a number is not optimal
It is transforming the string -> integer -> string to check if the string is not a number
but it is enough using only string -> integer not needed to transform to string again
python3 -m timeit -u msec -s "check_numbers = [str(i) for i in range(1000000)]" "[str(int(i)) for i in check_numbers]"
> 1 loop, best of 5: 323 msec per loop
python3 -m timeit -u msec -s "check_numbers = [str(i) for i in range(1000000)]" "[int(i) for i in check_numbers]"
> 2 loops, best of 5: 135 msec per loop
It is better but not enough, using `str.isdigit` method is 5x faster than original approach
python3 -m timeit -u msec -s "check_numbers = [str(i) for i in range(1000000)]" "[i.isdecimal() for i in check_numbers]"
> 5 loops, best of 5: 64 msec per loop
closes odoo/odoo#83851
X-original-commit: 31e0ed8c957e8a6af7f6bd5d449b450967206eab
Signed-off-by: Olivier Colson <oco@odoo.com>
This commit is contained in:
committed by
Moisés López
parent
e830953570
commit
088b9c2398
@@ -46,12 +46,12 @@ class AccountPayment(models.Model):
|
||||
|
||||
@api.constrains('check_number', 'journal_id')
|
||||
def _constrains_check_number(self):
|
||||
if not self:
|
||||
payment_checks = self.filtered('check_number')
|
||||
if not payment_checks:
|
||||
return
|
||||
try:
|
||||
self.mapped(lambda p: str(int(p.check_number)))
|
||||
except ValueError:
|
||||
raise ValidationError(_('Check numbers can only consist of digits'))
|
||||
for payment_check in payment_checks:
|
||||
if not payment_check.check_number.isdecimal():
|
||||
raise ValidationError(_('Check numbers can only consist of digits'))
|
||||
self.flush()
|
||||
self.env.cr.execute("""
|
||||
SELECT payment.check_number, move.journal_id
|
||||
@@ -66,8 +66,10 @@ class AccountPayment(models.Model):
|
||||
AND payment.id IN %(ids)s
|
||||
AND move.state = 'posted'
|
||||
AND other_move.state = 'posted'
|
||||
AND payment.check_number IS NOT NULL
|
||||
AND other_payment.check_number IS NOT NULL
|
||||
""", {
|
||||
'ids': tuple(self.ids),
|
||||
'ids': tuple(payment_checks.ids),
|
||||
})
|
||||
res = self.env.cr.dictfetchall()
|
||||
if res:
|
||||
|
||||
Reference in New Issue
Block a user