Skip to content
Permalink
Browse files

[ADD] account: cron to post draft entries

Task 193992
The cron is used to post draft entries such as those created by the module account_asset
Also add an inverse to account.move.amount
Also add a reverse compute on amount, and adapt its value according to the currency
  • Loading branch information...
william-andre committed Feb 26, 2019
1 parent cb5d836 commit d8221eeeee99cba411201589b53468855203a68f
@@ -56,7 +56,7 @@
'data/payment_receipt_data.xml',
'wizard/setup_wizards_view.xml',
'views/account_onboarding_templates.xml',
'data/service_cron_reverse.xml',
'data/service_cron.xml',
'views/account_fiscal_year_view.xml',
'views/account_incoterms_view.xml',
'data/account_incoterms_data.xml',
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="ir_cron_auto_post_draft_entry" model="ir.cron">
<field name="name">Account; Post draft entries with auto_post set to True up to today</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="nextcall" eval="(DateTime.now().replace(hour=2, minute=0) + timedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S')" />
<field name="doall" eval="False"/>
<field name="model_id" ref="model_account_move"/>
<field name="code">model._run_post_draft_to_post()</field>
<field name="state">code</field>
</record>
</odoo>

This file was deleted.

Oops, something went wrong.
@@ -42,13 +42,38 @@ def name_get(self):
return result

@api.multi
@api.depends('line_ids.debit', 'line_ids.credit')
@api.depends('line_ids.debit', 'line_ids.credit', 'line_ids.amount_currency', 'line_ids.currency_id')
def _amount_compute(self):
for move in self:
total = 0.0
for line in move.line_ids:
total_currency = 0.0
currency_id = move.line_ids and move.line_ids[0].currency_id.id or False
for line in move.line_ids.filtered(lambda l: l.debit):
total += line.debit
move.amount = total
if currency_id and line.currency_id.id == currency_id:
total_currency += line.amount_currency
elif currency_id:
currency_id = False

if currency_id and total_currency:
move.amount = total_currency
move.currency_id = currency_id
else:
move.currency_id = move.company_id.currency_id or self.env.user.company_id.currency_id
move.amount = total

@api.multi
def _set_amount(self):
for move in self:
if len(move.line_ids) == 2 and move.amount != 0:
amount_in_company_currency = move.amount
if move.currency_id and move.currency_id != move.company_id.currency_id:
amount_in_company_currency = move.currency_id._convert(move.amount, move.company_id.currency_id, move.company_id, move.date)
for line in move.line_ids:
line.amount_currency = line.debit and move.amount or -move.amount
for line in move.with_context(check_move_validity=False).line_ids:
line.debit = line.debit and amount_in_company_currency or 0.0
line.credit = line.credit and amount_in_company_currency or 0.0

@api.depends('line_ids.debit', 'line_ids.credit', 'line_ids.matched_debit_ids.amount', 'line_ids.matched_credit_ids.amount', 'line_ids.account_id.user_type_id.type')
def _compute_matched_percentage(self):
@@ -87,11 +112,6 @@ def _search_reconcile_model(self, operator, operand):
return [('id', 'in', rmi.ids)]
return [('id', '=', False)]

@api.one
@api.depends('company_id')
def _compute_currency(self):
self.currency_id = self.company_id.currency_id or self.env.user.company_id.currency_id

@api.multi
def _get_default_journal(self):
if self.env.context.get('default_journal_type'):
@@ -116,7 +136,6 @@ def _onchange_date(self):
ref = fields.Char(string='Reference', copy=False)
date = fields.Date(required=True, states={'posted': [('readonly', True)]}, index=True, default=fields.Date.context_today)
journal_id = fields.Many2one('account.journal', string='Journal', required=True, states={'posted': [('readonly', True)]}, default=_get_default_journal)
currency_id = fields.Many2one('res.currency', compute='_compute_currency', store=True, string="Currency")
state = fields.Selection([('draft', 'Unposted'), ('posted', 'Posted')], string='Status',
required=True, readonly=True, copy=False, default='draft',
help='All manually created new journal entries are usually in the status \'Unposted\', '
@@ -127,7 +146,8 @@ def _onchange_date(self):
line_ids = fields.One2many('account.move.line', 'move_id', string='Journal Items',
states={'posted': [('readonly', True)]}, copy=True)
partner_id = fields.Many2one('res.partner', compute='_compute_partner_id', string="Partner", store=True, readonly=True)
amount = fields.Monetary(compute='_amount_compute', store=True)
amount = fields.Monetary(compute='_amount_compute', inverse="_set_amount", store=True)
currency_id = fields.Many2one('res.currency', compute='_amount_compute', store=True, string="Currency")
narration = fields.Text(string='Internal Note')
company_id = fields.Many2one('res.company', related='journal_id.company_id', string='Company', store=True, readonly=True)
matched_percentage = fields.Float('Percentage Matched', compute='_compute_matched_percentage', digits=0, store=True, readonly=True, help="Technical field used in cash basis method")
@@ -139,13 +159,12 @@ def _onchange_date(self):
string='Tax Cash Basis Entry of',
help="Technical field used to keep track of the tax cash basis reconciliation. "
"This is needed when cancelling the source: it will post the inverse journal entry to cancel that part too.")
auto_reverse = fields.Boolean(string='Reverse Automatically', default=False, help='If this checkbox is ticked, this entry will be automatically reversed at the reversal date you defined.')
reverse_date = fields.Date(string='Reversal Date', help='Date of the reverse accounting entry.')
auto_post = fields.Boolean(string='Post Automatically', default=False, help='If this checkbox is ticked, this entry will be automatically posted at its date.')
reverse_entry_id = fields.Many2one('account.move', String="Reverse entry", store=True, readonly=True)
to_check = fields.Boolean(string='To Check', default=False, help='If this checkbox is ticked, it means that the user was not sure of all the related informations at the time of the creation of the move and that the move needs to be checked again.')
tax_type_domain = fields.Char(store=False, help='Technical field used to have a dynamic taxes domain on the form view.')

@api.constrains('line_ids', 'journal_id', 'auto_reverse', 'reverse_date')
@api.constrains('line_ids', 'journal_id')
def _validate_move_modification(self):
if 'posted' in self.mapped('line_ids.payment_id.state'):
raise ValidationError(_("You cannot modify a journal entry linked to a posted payment."))
@@ -314,6 +333,9 @@ def post(self):
# Create the analytic lines in batch is faster as it leads to less cache invalidation.
self.mapped('line_ids').create_analytic_lines()
for move in self:
if move.auto_post and move.date > fields.Date.today():
raise UserError(_("This move is configured to be auto-posted on {}".format(move.date.strftime(self.env['res.lang']._lang_get(self.env.user.lang).date_format))))

if move.name == '/':
new_name = False
journal = move.journal_id
@@ -416,14 +438,14 @@ def assert_balanced(self):
return True

@api.multi
def _reverse_move(self, date=None, journal_id=None, auto=False):
def _reverse_move(self, date=None, journal_id=None):
self.ensure_one()
with self.env.norecompute():
reversed_move = self.copy(default={
'date': date,
'journal_id': journal_id.id if journal_id else self.journal_id.id,
'ref': (_('Automatic reversal of: %s') if auto else _('Reversal of: %s')) % (self.name),
'auto_reverse': False})
'ref': _('Reversal of: %s') % (self.name),
})
for acm_line in reversed_move.line_ids.with_context(check_move_validity=False):
acm_line.write({
'debit': acm_line.credit,
@@ -435,16 +457,14 @@ def _reverse_move(self, date=None, journal_id=None, auto=False):
return reversed_move

@api.multi
def reverse_moves(self, date=None, journal_id=None, auto=False):
def reverse_moves(self, date=None, journal_id=None):
date = date or fields.Date.today()
reversed_moves = self.env['account.move']
for ac_move in self:
#unreconcile all lines reversed
aml = ac_move.line_ids.filtered(lambda x: x.account_id.reconcile or x.account_id.internal_type == 'liquidity')
aml.remove_move_reconcile()
reversed_move = ac_move._reverse_move(date=date,
journal_id=journal_id,
auto=auto)
reversed_move = ac_move._reverse_move(date=date, journal_id=journal_id)
reversed_moves |= reversed_move
#reconcile together the reconcilable (or the liquidity aml) and their newly created counterpart
for account in set([x.account_id for x in aml]):
@@ -475,18 +495,17 @@ def action_duplicate(self):
return action

@api.model
def _run_reverses_entries(self):
''' This method is called from a cron job. '''
def _run_post_draft_to_post(self):
''' This method is called from a cron job.
It is used to post entries such as those created by the module
account_asset.
'''
records = self.search([
('state', '=', 'posted'),
('auto_reverse', '=', True),
('reverse_date', '<=', fields.Date.today()),
('reverse_entry_id', '=', False)])
for move in records:
date = None
if move.reverse_date and (not self.env.user.company_id.period_lock_date or move.reverse_date > self.env.user.company_id.period_lock_date):
date = move.reverse_date
move.reverse_moves(date=date, auto=True)
('state', '=', 'draft'),
('date', '<=', fields.Date.today()),
('auto_post', '=', True),
])
records.post()

@api.multi
def action_view_reverse_entry(self):
@@ -227,7 +227,7 @@ def test_statement_usd_invoice_chf_transaction_chf(self):
{'debit': 10.74, 'credit': 0.0, 'account_id': self.diff_expense_account.id},
{'debit': 0.0, 'credit': 10.74, 'account_id': self.account_rcv.id},
])

self.assertRecordValues(supplier_move_lines, [
{'debit': 0.0, 'credit': 27.47, 'amount_currency': -42, 'currency_id': self.currency_usd_id},
{'debit': 27.47, 'credit': 0.0, 'amount_currency': 50, 'currency_id': self.currency_swiss_id},
@@ -249,7 +249,7 @@ def test_statement_eur_invoice_usd_transaction_usd(self):
{'debit': 0.0, 'credit': 7.30, 'account_id': self.diff_income_account.id},
{'debit': 7.30, 'credit': 0.0, 'account_id': self.account_rcv.id},
])

self.assertRecordValues(supplier_move_lines, [
{'debit': 0.0, 'credit': 40.0, 'amount_currency': -50, 'currency_id': self.currency_usd_id},
{'debit': 40.0, 'credit': 0.0, 'amount_currency': 50, 'currency_id': self.currency_usd_id},
@@ -643,12 +643,12 @@ def test_partial_reconcile_currencies_01(self):
'currency_id': self.currency_usd_id,
'company_id': self.env.ref('base.main_company').id})

self.env['res.currency.rate'].create({'name': time.strftime('%Y') + '-' + '08' + '-01',
self.env['res.currency.rate'].create({'name': time.strftime('%Y') + '-' + '08' + '-01',
'rate': 0.75,
'currency_id': self.currency_usd_id,
'company_id': self.env.ref('base.main_company').id})

self.env['res.currency.rate'].create({'name': time.strftime('%Y') + '-' + '09' + '-01',
self.env['res.currency.rate'].create({'name': time.strftime('%Y') + '-' + '09' + '-01',
'rate': 0.80,
'currency_id': self.currency_usd_id,
'company_id': self.env.ref('base.main_company').id})
@@ -1520,18 +1520,18 @@ def test_reconciliation_cash_basis02(self):
expected['tax_10']
)
index += 1

def test_reconciliation_to_check(self):
partner = self.env['res.partner'].create({'name': 'UncertainPartner'})
currency = self.env.user.company_id.currency_id
invoice = self.create_invoice_partner(currency_id=currency.id, partner_id=partner.id)
journal = self.env['account.journal'].create({'name': 'Bank', 'type': 'bank', 'code': 'THE', 'update_posted':True})

statement = self.make_payment(invoice, journal, 50)
st_line = statement.line_ids
previous_move_lines = st_line.journal_entry_ids.ids
previous_name = st_line.move_name

with self.assertRaises(UserError): #you need edition mode to be able to change it
st_line.with_context(edition_mode=False).process_reconciliation(
counterpart_aml_dicts=[],
@@ -1542,7 +1542,7 @@ def test_reconciliation_to_check(self):
'account_id': self.diff_income_account.id
}],
)

st_line.with_context(edition_mode=True).process_reconciliation(
counterpart_aml_dicts=[],
new_aml_dicts = [{
@@ -1697,8 +1697,7 @@ def test_reconciliation_cash_basis_fx_01(self):
self.assertEqual(len(cash_basis_aml_ids), 4)

# check amounts
cash_basis_move1 = cash_basis_moves.filtered(
lambda m: m.amount == 123936.31)
cash_basis_move1 = cash_basis_moves.filtered(lambda m: m.currency_id.is_zero(sum(line.credit for line in m.line_ids) - 123936.31))

self.assertTrue(cash_basis_move1.exists())

@@ -1893,8 +1892,7 @@ def test_reconciliation_cash_basis_fx_02(self):
self.assertEqual(len(cash_basis_aml_ids), 4)

# check amounts
cash_basis_move1 = cash_basis_moves.filtered(
lambda m: m.amount == 123936.31)
cash_basis_move1 = cash_basis_moves.filtered(lambda m: m.currency_id.is_zero(sum(line.credit for line in m.line_ids) - 123936.31))

self.assertTrue(cash_basis_move1.exists())

@@ -328,7 +328,7 @@
<group>
<field name="journal_id" options="{'no_open': True, 'no_create': True}"/>
<field name="company_id" required="1" groups="base.group_multi_company"/>
<field name="amount" invisible="1"/>
<field name="amount" invisible="1" readonly="1"/>
<field name="currency_id" invisible="1"/>
</group>
</group>
@@ -363,8 +363,7 @@
</page>
<page string="Other Info">
<group>
<field name="auto_reverse" attrs="{'readonly':[('reverse_entry_id', '!=', False)]}"/>
<field name="reverse_date" attrs="{'invisible':[('auto_reverse', '=', False)], 'required':[('auto_reverse', '=', True)],'readonly':[('reverse_entry_id', '!=', False)]}"/>
<field name="auto_post" attrs="{'readonly':[('reverse_entry_id', '!=', False)]}"/>
<field name="reverse_entry_id" attrs="{'invisible':True}"/>
<field name="to_check"/>
</group>

0 comments on commit d8221ee

Please sign in to comment.
You can’t perform that action at this time.