Closed hbto closed 2 years ago
@moylop260
This PR Tries to address issue 7881
This will not fix the issue but in the long term will avoid it.
The problem is not the algorithm in https://git.vauxoo.com/vauxoo/mexico/blob/85753e311bccd9bd8b39613e89cce05b907bb85f/l10n_mx_avoid_reversal_entry/models/account_move.py#L48
The problem is odoo:
Let us have 4 invoices with 200 lines each one. Do a payment. This creates a CABA Entry with 4 x (200 x 2 + 2) = 808 Caba lines.
Unreconcile the Payment. It has now to delete 808 Caba lines plus all the checks needed for deletions.
cc/ @nhomar
cc/ @luistorresm & @carlosrve
@hbto Could you add the video url?
@JulioSerna your review here is so important
FYI I'm using this branch:
1) Cancel the lodi payment 11819 2) Set to draft 3) Confirm
Result:
File "/home/odoo/enterprise/l10n_mx_edi/models/account_payment.py", line 96, in post
l10n_mx_edi_manual_reconciliation=False)).post()
File "/home/odoo/odoo-11.0/addons/account/models/account_payment.py", line 531, in post
move = rec._create_payment_entry(amount)
File "/home/odoo/odoo-11.0/addons/account/models/account_payment.py", line 604, in _create_payment_entry
self.invoice_ids.register_payment(counterpart_aml)
File "/home/odoo/odoo-11.0/addons/account/models/account_invoice.py", line 941, in register_payment
return (line_to_reconcile + payment_line).reconcile(writeoff_acc_id, writeoff_journal_id)
File "/home/odoo/enterprise/l10n_mx_edi/models/account_move.py", line 12, in reconcile
writeoff_acc_id, writeoff_journal_id)
File "/home/odoo/odoo-11.0/addons/account/models/account_move.py", line 1092, in reconcile
remaining_moves = self.auto_reconcile_lines()
File "/home/odoo/odoo-11.0/addons/account/models/account_move.py", line 1062, in auto_reconcile_lines
'currency_id': currency,
File "/home/odoo/odoo-11.0/addons/account/models/account_move.py", line 2014, in create
res.create_tax_cash_basis_entry(percentage_before_rec)
File "/.repo_requirements/virtualenv/python3.6/lib/python3.6/site-packages/line_profiler/line_profiler.py", line 122, in wrapper
result = func(*args, **kwds)
File "/home/odoo/odoo-11.0/addons/account/models/account_move.py", line 1898, in create_tax_cash_basis_entry
self._create_tax_cash_basis_base_line(caba_keys, caba_amount_dict, caba_amount_currency_dict, newly_created_move)
File "/home/odoo/odoo-11.0/addons/account/models/account_move.py", line 1803, in _create_tax_cash_basis_base_line
base_line = self._get_tax_cash_basis_base_line(key)
TypeError: _get_tax_cash_basis_base_line() missing 1 required positional argument: 'new_move'
So I just applied the following patch:
diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py
index 66f5ffeef..16480ed8d 100644
--- a/addons/account/models/account_move.py
+++ b/addons/account/models/account_move.py
@@ -1233,7 +1233,7 @@ class AccountMoveLine(models.Model):
'exchange_move_id': exchange_move.id if exchange_move else False,
})
- @api.multi
+ @profile
def remove_move_reconcile(self):
""" Undo a reconciliation """
if not self:
@@ -1800,7 +1800,7 @@ class AccountPartialReconcile(models.Model):
def _create_tax_cash_basis_base_line(self, keys, amount_dict, amount_currency_dict, new_move):
for key in keys:
- base_line = self._get_tax_cash_basis_base_line(key)
+ base_line = self._get_tax_cash_basis_base_line(key, new_move)
rounded_amt = amount_dict[key]
amount_currency = amount_currency_dict[key]
aml_obj = self.env['account.move.line'].with_context(check_move_validity=False)
@@ -1816,6 +1816,7 @@ class AccountPartialReconcile(models.Model):
amount_currency=-amount_currency,
tax_ids=[]))
+ @profile
def create_tax_cash_basis_entry(self, percentage_before_rec):
self.ensure_one()
move_date = self.debit_move_id.date
Total time: 21.1804 s
File: /home/odoo/odoo-11.0/addons/account/models/account_move.py
Function: create_tax_cash_basis_entry at line 1784
Line # Hits Time Per Hit % Time Line Contents
==============================================================
1784 @profile
1785 def create_tax_cash_basis_entry(self, percentage_before_rec):
1786 1 61.0 61.0 0.0 self.ensure_one()
1787 1 307.0 307.0 0.0 move_date = self.debit_move_id.date
1788 1 72.0 72.0 0.0 newly_created_move = self.env['account.move']
1789 1 34.0 34.0 0.0 with self.env.norecompute():
1790 # We use a set here in case the reconciled lines belong to the same move (it happens with POS)
1791 3 167.0 55.7 0.0 for move in {self.debit_move_id.move_id, self.credit_move_id.move_id}:
1792 #move_date is the max of the 2 reconciled items
1793 2 55.0 27.5 0.0 if move_date < move.date:
1794 1 26.0 26.0 0.0 move_date = move.date
1795 206 5062.0 24.6 0.0 for line in move.line_ids:
1796 #TOCHECK: normal and cash basis taxes shoudn't be mixed together (on the same invoice line for example) as it will
1797 # create reporting issues. Not sure of the behavior to implement in that case, though.
1798 204 7698.0 37.7 0.0 if not line.tax_exigible:
1799 65 1731.0 26.6 0.0 percentage_before = percentage_before_rec[move.id]
1800 65 1805523.0 27777.3 8.5 percentage_after = line._get_matched_percentage()[move.id]
1801 #amount is the current cash_basis amount minus the one before the reconciliation
1802 65 3731.0 57.4 0.0 amount = line.balance * percentage_after - line.balance * percentage_before
1803 65 153119.0 2355.7 0.7 rounded_amt = self._get_amount_tax_cash_basis(amount, line)
1804 65 6618.0 101.8 0.0 if float_is_zero(rounded_amt, precision_rounding=line.company_id.currency_id.rounding):
1805 continue
1806 65 3225.0 49.6 0.0 if line.tax_line_id and line.tax_line_id.tax_exigibility == 'on_payment':
1807 1 16.0 16.0 0.0 if not newly_created_move:
1808 newly_created_move = self._create_tax_basis_move()
1809 #create cash basis entry for the tax line
1810 1 96.0 96.0 0.0 to_clear_aml = self.env['account.move.line'].with_context(check_move_validity=False).create({
1811 1 50.0 50.0 0.0 'name': line.move_id.name,
1812 1 13.0 13.0 0.0 'debit': abs(rounded_amt) if rounded_amt < 0 else 0.0,
1813 1 11.0 11.0 0.0 'credit': rounded_amt if rounded_amt > 0 else 0.0,
1814 1 40.0 40.0 0.0 'account_id': line.account_id.id,
1815 # DO NOT FORWARD-PORT!!! ONLY FOR v11
1816 1 38.0 38.0 0.0 'analytic_account_id': line.analytic_account_id.id,
1817 1 43634.0 43634.0 0.2 'analytic_tag_ids': line.analytic_tag_ids.ids,
1818 1 13.0 13.0 0.0 'tax_exigible': True,
1819 1 31.0 31.0 0.0 'amount_currency': line.amount_currency and line.currency_id.round(-line.amount_currency * amount / line.balance) or 0.0,
1820 1 42.0 42.0 0.0 'currency_id': line.currency_id.id,
1821 1 18.0 18.0 0.0 'move_id': newly_created_move.id,
1822 1 72951.0 72951.0 0.3 'partner_id': line.partner_id.id,
1823 })
1824 # Group by cash basis account and tax
1825 1 98.0 98.0 0.0 self.env['account.move.line'].with_context(check_move_validity=False).create({
1826 1 33.0 33.0 0.0 'name': line.name,
1827 1 13.0 13.0 0.0 'debit': rounded_amt if rounded_amt > 0 else 0.0,
1828 1 13.0 13.0 0.0 'credit': abs(rounded_amt) if rounded_amt < 0 else 0.0,
1829 1 65.0 65.0 0.0 'account_id': line.tax_line_id.cash_basis_account.id,
1830 # DO NOT FORWARD-PORT!!! ONLY FOR v11
1831 1 38.0 38.0 0.0 'analytic_account_id': line.analytic_account_id.id,
1832 1 44.0 44.0 0.0 'analytic_tag_ids': line.analytic_tag_ids.ids,
1833 1 37.0 37.0 0.0 'tax_line_id': line.tax_line_id.id,
1834 1 12.0 12.0 0.0 'tax_exigible': True,
1835 1 26.0 26.0 0.0 'amount_currency': line.amount_currency and line.currency_id.round(line.amount_currency * amount / line.balance) or 0.0,
1836 1 39.0 39.0 0.0 'currency_id': line.currency_id.id,
1837 1 17.0 17.0 0.0 'move_id': newly_created_move.id,
1838 1 85321.0 85321.0 0.4 'partner_id': line.partner_id.id,
1839 })
1840 1 63.0 63.0 0.0 if line.account_id.reconcile:
1841 #setting the account to allow reconciliation will help to fix rounding errors
1842 1 58.0 58.0 0.0 to_clear_aml |= line
1843 1 575563.0 575563.0 2.7 to_clear_aml.reconcile()
1844
1845 65 160377.0 2467.3 0.8 if any([tax.tax_exigibility == 'on_payment' for tax in line.tax_ids]):
1846 64 1014.0 15.8 0.0 if not newly_created_move:
1847 1 101909.0 101909.0 0.5 newly_created_move = self._create_tax_basis_move()
1848 #create cash basis entry for the base
1849 128 4131.0 32.3 0.0 for tax in line.tax_ids:
1850 64 4334.0 67.7 0.0 account_id = self._get_tax_cash_basis_base_account(line, tax)
1851 64 7490.0 117.0 0.0 self.env['account.move.line'].with_context(check_move_validity=False).create({
1852 64 1903.0 29.7 0.0 'name': line.name,
1853 64 841.0 13.1 0.0 'debit': rounded_amt > 0 and rounded_amt or 0.0,
1854 64 856.0 13.4 0.0 'credit': rounded_amt < 0 and abs(rounded_amt) or 0.0,
1855 64 1368.0 21.4 0.0 'account_id': account_id.id,
1856 64 800.0 12.5 0.0 'tax_exigible': True,
1857 64 1148.0 17.9 0.0 'tax_ids': [(6, 0, [tax.id])],
1858 64 1117.0 17.5 0.0 'move_id': newly_created_move.id,
1859 64 2850.0 44.5 0.0 'currency_id': line.currency_id.id,
1860 64 1914.0 29.9 0.0 'amount_currency': self.amount_currency and line.currency_id.round(line.amount_currency * amount / line.balance) or 0.0,
1861 64 5694620.0 88978.4 26.9 'partner_id': line.partner_id.id,
1862 })
1863 64 8012.0 125.2 0.0 self.env['account.move.line'].with_context(check_move_validity=False).create({
1864 64 2480.0 38.8 0.0 'name': line.name,
1865 64 899.0 14.0 0.0 'credit': rounded_amt > 0 and rounded_amt or 0.0,
1866 64 929.0 14.5 0.0 'debit': rounded_amt < 0 and abs(rounded_amt) or 0.0,
1867 64 1391.0 21.7 0.0 'account_id': account_id.id,
1868 64 732.0 11.4 0.0 'tax_exigible': True,
1869 64 1446.0 22.6 0.0 'move_id': newly_created_move.id,
1870 64 4546.0 71.0 0.0 'currency_id': line.currency_id.id,
1871 64 2352.0 36.8 0.0 'amount_currency': self.amount_currency and line.currency_id.round(-line.amount_currency * amount / line.balance) or 0.0,
1872 64 4741943.0 74092.9 22.4 'partner_id': line.partner_id.id,
1873 })
1874 1 6959096.0 6959096.0 32.9 self.recompute()
1875 1 17.0 17.0 0.0 if newly_created_move:
1876 1 2482.0 2482.0 0.0 if move_date > (self.company_id.period_lock_date or '0000-00-00') and newly_created_move.date != move_date:
1877 # The move date should be the maximum date between payment and invoice (in case
1878 # of payment in advance). However, we should make sure the move date is not
1879 # recorded before the period lock date as the tax statement for this period is
1880 # probably already sent to the estate.
1881 1 142992.0 142992.0 0.7 newly_created_move.write({'date': move_date})
1882 # post move
1883 1 558623.0 558623.0 2.6 newly_created_move.post()
Total time: 474.708 s
File: /home/odoo/odoo-11.0/addons/account/models/account_move.py
Function: remove_move_reconcile at line 1236
Line # Hits Time Per Hit % Time Line Contents
==============================================================
1236 @profile
1237 def remove_move_reconcile(self):
1238 """ Undo a reconciliation """
1239 1 19.0 19.0 0.0 if not self:
1240 return True
1241 1 45.0 45.0 0.0 rec_move_ids = self.env['account.partial.reconcile']
1242 3 69.0 23.0 0.0 for account_move_line in self:
1243 4 309.0 77.2 0.0 for invoice in account_move_line.payment_id.invoice_ids:
1244 2 46.0 23.0 0.0 if invoice.id == self.env.context.get('invoice_id') and account_move_line in invoice.payment_move_line_ids:
1245 account_move_line.payment_id.write({'invoice_ids': [(3, invoice.id, None)]})
1246 2 6919.0 3459.5 0.0 rec_move_ids += account_move_line.matched_debit_ids
1247 2 3320.0 1660.0 0.0 rec_move_ids += account_move_line.matched_credit_ids
1248 1 14.0 14.0 0.0 if self.env.context.get('invoice_id'):
1249 current_invoice = self.env['account.invoice'].browse(self.env.context['invoice_id'])
1250 aml_to_keep = current_invoice.move_id.line_ids | current_invoice.move_id.line_ids.mapped('full_reconcile_id.exchange_move_id.line_ids')
1251 rec_move_ids = rec_move_ids.filtered(
1252 lambda r: (r.debit_move_id + r.credit_move_id) & aml_to_keep
1253 )
1254 1 474696767.0 474696767.0 100.0 return rec_move_ids.unlink()
Total time: 4.3248 s
File: /home/odoo/odoo-11.0/addons/account/models/account_move.py
Function: create_tax_cash_basis_entry at line 1819
Line # Hits Time Per Hit % Time Line Contents
==============================================================
1819 @profile
1820 def create_tax_cash_basis_entry(self, percentage_before_rec):
1821 1 24.0 24.0 0.0 self.ensure_one()
1822 1 110.0 110.0 0.0 move_date = self.debit_move_id.date
1823 1 48.0 48.0 0.0 newly_created_move = self.env['account.move']
1824 1 60.0 60.0 0.0 caba_amount_dict = {}
1825 1 13.0 13.0 0.0 caba_amount_currency_dict = {}
1826 1 19.0 19.0 0.0 caba_keys = set()
1827 1 44.0 44.0 0.0 with self.env.norecompute():
1828 # We use a set here in case the reconciled lines belong to the same move (it happens with POS)
1829 3 263.0 87.7 0.0 for move in {self.debit_move_id.move_id, self.credit_move_id.move_id}:
1830 #move_date is the max of the 2 reconciled items
1831 2 58.0 29.0 0.0 if move_date < move.date:
1832 1 25.0 25.0 0.0 move_date = move.date
1833 206 3981.0 19.3 0.1 for line in move.line_ids:
1834 #TOCHECK: normal and cash basis taxes shoudn't be mixed together (on the same invoice line for example) as it will
1835 # create reporting issues. Not sure of the behavior to implement in that case, though.
1836 204 4950.0 24.3 0.1 if not line.tax_exigible:
1837 65 1112.0 17.1 0.0 percentage_before = percentage_before_rec[move.id]
1838 65 873727.0 13442.0 20.2 percentage_after = line._get_matched_percentage()[move.id]
1839 #amount is the current cash_basis amount minus the one before the reconciliation
1840 65 3124.0 48.1 0.1 amount = line.balance * percentage_after - line.balance * percentage_before
1841 65 91278.0 1404.3 2.1 rounded_amt = self._get_amount_tax_cash_basis(amount, line)
1842 65 5675.0 87.3 0.1 if float_is_zero(rounded_amt, precision_rounding=line.company_id.currency_id.rounding):
1843 continue
1844 65 2598.0 40.0 0.1 if line.tax_line_id and line.tax_line_id.tax_exigibility == 'on_payment':
1845 1 12.0 12.0 0.0 if not newly_created_move:
1846 newly_created_move = self._create_tax_basis_move()
1847 #create cash basis entry for the tax line
1848 1 118.0 118.0 0.0 to_clear_aml = self.env['account.move.line'].with_context(check_move_validity=False).create({
1849 1 37.0 37.0 0.0 'name': line.move_id.name,
1850 1 10.0 10.0 0.0 'debit': abs(rounded_amt) if rounded_amt < 0 else 0.0,
1851 1 9.0 9.0 0.0 'credit': rounded_amt if rounded_amt > 0 else 0.0,
1852 1 30.0 30.0 0.0 'account_id': line.account_id.id,
1853 # DO NOT FORWARD-PORT!!! ONLY FOR v11
1854 1 34.0 34.0 0.0 'analytic_account_id': line.analytic_account_id.id,
1855 1 14737.0 14737.0 0.3 'analytic_tag_ids': line.analytic_tag_ids.ids,
1856 1 9.0 9.0 0.0 'tax_exigible': True,
1857 1 25.0 25.0 0.0 'amount_currency': line.amount_currency and line.currency_id.round(-line.amount_currency * amount / line.balance) or 0.0,
1858 1 31.0 31.0 0.0 'currency_id': line.currency_id.id,
1859 1 13.0 13.0 0.0 'move_id': newly_created_move.id,
1860 1 44101.0 44101.0 1.0 'partner_id': line.partner_id.id,
1861 })
1862 # Group by cash basis account and tax
1863 1 108.0 108.0 0.0 self.env['account.move.line'].with_context(check_move_validity=False).create({
1864 1 46.0 46.0 0.0 'name': line.name,
1865 1 13.0 13.0 0.0 'debit': rounded_amt if rounded_amt > 0 else 0.0,
1866 1 14.0 14.0 0.0 'credit': abs(rounded_amt) if rounded_amt < 0 else 0.0,
1867 1 75.0 75.0 0.0 'account_id': line.tax_line_id.cash_basis_account.id,
1868 # DO NOT FORWARD-PORT!!! ONLY FOR v11
1869 1 42.0 42.0 0.0 'analytic_account_id': line.analytic_account_id.id,
1870 1 53.0 53.0 0.0 'analytic_tag_ids': line.analytic_tag_ids.ids,
1871 1 37.0 37.0 0.0 'tax_line_id': line.tax_line_id.id,
1872 1 11.0 11.0 0.0 'tax_exigible': True,
1873 1 27.0 27.0 0.0 'amount_currency': line.amount_currency and line.currency_id.round(line.amount_currency * amount / line.balance) or 0.0,
1874 1 49.0 49.0 0.0 'currency_id': line.currency_id.id,
1875 1 17.0 17.0 0.0 'move_id': newly_created_move.id,
1876 1 38859.0 38859.0 0.9 'partner_id': line.partner_id.id,
1877 })
1878 1 56.0 56.0 0.0 if line.account_id.reconcile:
1879 #setting the account to allow reconciliation will help to fix rounding errors
1880 1 56.0 56.0 0.0 to_clear_aml |= line
1881 1 135885.0 135885.0 3.1 to_clear_aml.reconcile()
1882
1883 65 34072.0 524.2 0.8 if any([tax.tax_exigibility == 'on_payment' for tax in line.tax_ids]):
1884 64 1016.0 15.9 0.0 if not newly_created_move:
1885 1 11323.0 11323.0 0.3 newly_created_move = self._create_tax_basis_move()
1886 #create cash basis entry for the base
1887 128 6942.0 54.2 0.2 for tax in line.tax_ids.filtered(lambda t: t.tax_exigibility == 'on_payment'):
1888 64 7783.0 121.6 0.2 key = self._get_tax_cash_basis_hash(tax, move, line)
1889 64 781.0 12.2 0.0 caba_keys.add(key)
1890 64 882.0 13.8 0.0 caba_amount_dict.setdefault(key, 0)
1891 64 797.0 12.5 0.0 caba_amount_dict[key] += rounded_amt
1892 64 927.0 14.5 0.0 caba_amount_currency_dict.setdefault(key, 0)
1893 64 1946.0 30.4 0.0 caba_amount_currency_dict[key] += line.currency_id.round(line.amount_currency * amount / line.balance) if self.amount_currency else 0.0
1894
1895 1 9.0 9.0 0.0 if caba_keys:
1896 1 11.0 11.0 0.0 if not newly_created_move:
1897 newly_created_move = self._create_tax_basis_move()
1898 1 145190.0 145190.0 3.4 self._create_tax_cash_basis_base_line(caba_keys, caba_amount_dict, caba_amount_currency_dict, newly_created_move)
1899 1 2738138.0 2738138.0 63.3 self.recompute()
1900 1 17.0 17.0 0.0 if newly_created_move:
1901 1 2386.0 2386.0 0.1 if move_date > (self.company_id.period_lock_date or '0000-00-00') and newly_created_move.date != move_date:
1902 # The move date should be the maximum date between payment and invoice (in case
1903 # of payment in advance). However, we should make sure the move date is not
1904 # recorded before the period lock date as the tax statement for this period is
1905 # probably already sent to the estate.
1906 1 40127.0 40127.0 0.9 newly_created_move.write({'date': move_date})
1907 # post move
1908 1 110833.0 110833.0 2.6 newly_created_move.post()
Total time: 37.286 s
File: /home/odoo/odoo-11.0/addons/account/models/account_move.py
Function: remove_move_reconcile at line 1236
Line # Hits Time Per Hit % Time Line Contents
==============================================================
1236 @profile
1237 def remove_move_reconcile(self):
1238 """ Undo a reconciliation """
1239 1 45.0 45.0 0.0 if not self:
1240 return True
1241 1 43.0 43.0 0.0 rec_move_ids = self.env['account.partial.reconcile']
1242 3 50.0 16.7 0.0 for account_move_line in self:
1243 4 269.0 67.2 0.0 for invoice in account_move_line.payment_id.invoice_ids:
1244 2 35.0 17.5 0.0 if invoice.id == self.env.context.get('invoice_id') and account_move_line in invoice.payment_move_line_ids:
1245 account_move_line.payment_id.write({'invoice_ids': [(3, invoice.id, None)]})
1246 2 7758.0 3879.0 0.0 rec_move_ids += account_move_line.matched_debit_ids
1247 2 3609.0 1804.5 0.0 rec_move_ids += account_move_line.matched_credit_ids
1248 1 12.0 12.0 0.0 if self.env.context.get('invoice_id'):
1249 current_invoice = self.env['account.invoice'].browse(self.env.context['invoice_id'])
1250 aml_to_keep = current_invoice.move_id.line_ids | current_invoice.move_id.line_ids.mapped('full_reconcile_id.exchange_move_id.line_ids')
1251 rec_move_ids = rec_move_ids.filtered(
1252 lambda r: (r.debit_move_id + r.credit_move_id) & aml_to_keep
1253 )
1254 1 37274201.0 37274201.0 100.0 return rec_move_ids.unlink()
action | original time | patch time | Faster |
---|---|---|---|
confirm | 21.18s | 4.32s | 5x |
cancel | 474.70s | 37.28s | 13x |
Main
Odoo does not economize on resources when creating CABA Entries.
This PR deals with the creation of a more Slimmed way of creating the CABA Entries. After this PR you will end up with
-- 1 Entry line per tax collected. -- 1 Entry line per tax to be collected. -- 2 Entry lines for the base, one debit, one credit.
chances are that this could be increased but the algorithm tries only to group by a set of keys.
Regards.
YouTube
https://youtu.be/njXJDJLOFWc
Zoom
Grabación despues de aplicar el fix. https://zoom.us/rec/share/ypBlI4zcqERJTJXisU_webUsJqr0X6a81XJI_PRczhufQPE0zor1bM7fWrNzCDlo
-- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr