Files
account-financial-tools/account_move_batch_validate/models/account_move.py
2017-10-02 17:54:04 +02:00

102 lines
3.2 KiB
Python

# -*- coding: utf-8 -*-
# Copyright 2014 Camptocamp SA, 2017 ACSONE
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
from odoo import api, fields, models, _
from odoo.addons.queue_job.job import job, Job
_logger = logging.getLogger(__name__)
BLOCK_SIZE = 1000
class AccountMove(models.Model):
_inherit = 'account.move'
to_post = fields.Boolean(
string="Posting requested", readonly=True,
help="Check this box to mark the move for batch posting")
post_job_uuid = fields.Char(string="UUID of the Job to approve this move")
@job(default_channel='root.account_move_batch_validate')
def validate_one_move(self, move_id):
move = self.browse(move_id)
if move.exists():
move.post()
else:
return _(u"Nothing to do because the record has been deleted")
@api.model
def _delay_post_marked(self, eta=None):
"""
Create a job for every move marked for posting.
If some moves already have a job, they are skipped.
"""
AccountMoveObj = self.env[self._name]
moves = self.search([
('to_post', '=', True),
('post_job_uuid', '=', False),
('state', '=', 'draft'),
])
# maybe not creating too many dictionaries will make us a bit faster
values = {'post_job_uuid': None}
_logger.info(
"%s jobs for posting moves have been created.", len(moves))
for move in moves:
new_job = AccountMoveObj.with_delay(eta=eta).validate_one_move(
move.id)
values['post_job_uuid'] = new_job.uuid
move.write(values)
self.env.cr.commit() # pylint:disable=invalid-commit
@api.model
def _cancel_post_jobs(self):
"""
Find moves where the mark has been removed and cancel the jobs.
For the moves that are posted already it's too late: we skip them.
"""
moves = self.search([
('to_post', '=', False),
('post_job_uuid', '!=', False),
('state', '=', 'draft'),
])
for move in moves:
job_rec = Job.load(self.env, move.post_job_uuid)
if job_rec.state in ('pending', 'enqueued'):
job_rec.set_done(
result=_("Task set to Done because the "
"user unmarked the move."))
job_rec.store()
@api.multi
def mark_for_posting(self, eta=None):
"""
Mark a list of moves for delayed posting, and enqueue the jobs.
For massive amounts of moves, this becomes necessary to avoid
MemoryError's
"""
moves_count = len(self)
_logger.info("%s moves marked for posting.", moves_count)
values = {'to_post': True}
for index in xrange(0, moves_count, BLOCK_SIZE):
moves = self[index:index + BLOCK_SIZE]
moves.write(values)
# users like to see the flag sooner rather than later
self.env.cr.commit() # pylint:disable=invalid-commit
self._delay_post_marked(eta=eta)
@api.multi
def unmark_for_posting(self):
self.write({'to_post': False})
self._cancel_post_jobs()