diff --git a/account_move_batch_validate/__init__.py b/account_move_batch_validate/__init__.py
new file mode 100644
index 000000000..df1a591bd
--- /dev/null
+++ b/account_move_batch_validate/__init__.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+###############################################################################
+# #
+# Author: Leonardo Pistone
+# Copyright 2014 Camptocamp SA
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU Affero General Public License as #
+# published by the Free Software Foundation, either version 3 of the #
+# License, or (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU Affero General Public License for more details. #
+# #
+# You should have received a copy of the GNU Affero General Public License #
+# along with this program. If not, see . #
+# #
+###############################################################################
+"""Account Move Batch Validate."""
+
+from . import account # noqa
+from . import wizard # noqa
diff --git a/account_move_batch_validate/__openerp__.py b/account_move_batch_validate/__openerp__.py
new file mode 100644
index 000000000..e2d3fba83
--- /dev/null
+++ b/account_move_batch_validate/__openerp__.py
@@ -0,0 +1,80 @@
+# -*- coding: utf-8 -*-
+###############################################################################
+# #
+# Author: Leonardo Pistone
+# Copyright 2014 Camptocamp SA
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU Affero General Public License as #
+# published by the Free Software Foundation, either version 3 of the #
+# License, or (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU Affero General Public License for more details. #
+# #
+# You should have received a copy of the GNU Affero General Public License #
+# along with this program. If not, see . #
+# #
+###############################################################################
+{
+ 'name': "Account Move Batch Validate",
+ 'version': '0.1',
+ 'author': 'Camptocamp',
+ 'maintainer': 'Camptocamp',
+ 'category': 'Finance',
+ 'complexity': 'normal',
+ 'depends': [
+ 'account',
+ 'account_default_draft_move',
+ 'connector',
+ ],
+ 'description': """
+ Account Move Batch Validate
+
+ This module provides a wizard to post many Journal Entries in batch. it
+ uses the queue system introduced by the OpenERP Connector to handle a
+ big quantity of moves in batch.
+
+ The module account_default_draft_move introdoces a workflow where the
+ Journal Entries are always entered in OpenERP in draft state, and the
+ posting happens later, for example at the end of the period. The core
+ account module provides a wizard to post all the moves in the period,
+ but that is problematic when there are many moves.
+
+ The posting of a move takes some time, and doing that synchronously,
+ in one transaction is problematic.
+
+ In this module, we leverage the power of the queue system of the
+ OpenERP Connector, that can be very well used without other concepts
+ like Backends and Bindings.
+
+ This approach provides many advantages, similar to the ones we get
+ using that connector for e-commerce:
+
+ - Asynchronous: the operation is done in background, and users can
+ continue to work.
+ - Dedicated workers: the queued jobs are performed by specific workers
+ (processes). This is good for a long task, since the main workers are
+ busy handling HTTP requests and can be killed if operations take
+ too long, for example.
+ - Multiple transactions: this is an operation that doesn't need to be
+ atomic, and if a line out of 100,000 fails, it is possible to catch
+ it, see the error message, and fix the situation. Meanwhile, all
+ other jobs can proceed.
+
+ """,
+ 'website': 'http://www.camptocamp.com',
+ 'data': [
+ 'account_view.xml',
+ 'wizard/move_marker_view.xml',
+ ],
+ 'test': [
+ 'test/batch_validate.yml',
+ 'test/batch_validate_then_unmark.yml',
+ ],
+ 'installable': True,
+ 'images': [],
+ 'license': 'AGPL-3',
+}
diff --git a/account_move_batch_validate/account.py b/account_move_batch_validate/account.py
new file mode 100644
index 000000000..ea0620418
--- /dev/null
+++ b/account_move_batch_validate/account.py
@@ -0,0 +1,134 @@
+# -*- coding: utf-8 -*-
+###############################################################################
+# #
+# Author: Leonardo Pistone
+# Copyright 2014 Camptocamp SA
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU Affero General Public License as #
+# published by the Free Software Foundation, either version 3 of the #
+# License, or (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU Affero General Public License for more details. #
+# #
+# You should have received a copy of the GNU Affero General Public License #
+# along with this program. If not, see . #
+# #
+###############################################################################
+"""Accounting customisation for delayed posting."""
+
+from openerp.osv import fields, orm
+from openerp.tools.translate import _
+
+from openerp.addons.connector.queue.job import job
+from openerp.addons.connector.session import ConnectorSession
+from openerp.addons.connector.queue.job import OpenERPJobStorage
+
+# do a massive write on account moves BLOCK_SIZE at a time
+BLOCK_SIZE = 1000
+
+
+class account_move(orm.Model):
+
+ """We modify the account move to allow delayed posting."""
+
+ _name = 'account.move'
+ _inherit = 'account.move'
+
+ _columns = {
+ 'to_post': fields.boolean(
+ 'Posting Requested',
+ readonly=True,
+ help='Check this box to mark the move for batch posting'
+ ),
+ 'post_job_uuid': fields.char(
+ 'UUID of the Job to approve this move'
+ ),
+ }
+
+ def _delay_post_marked(self, cr, uid, eta=None, context=None):
+ """Create a job for every move marked for posting.
+
+ If some moves already have a job, they are skipped.
+
+ """
+
+ if context is None:
+ context = {}
+
+ session = ConnectorSession(cr, uid, context=context)
+
+ move_ids = self.search(cr, uid, [
+ ('to_post', '=', True),
+ ('post_job_uuid', '=', False),
+ ('state', '=', 'draft'),
+ ], context=context)
+
+ for move_id in move_ids:
+ job_uuid = validate_one_move.delay(session, self._name, move_id,
+ eta=eta)
+ self.write(cr, uid, [move_id], {
+ 'post_job_uuid': job_uuid
+ })
+
+ def _cancel_jobs(self, cr, uid, context=None):
+ """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.
+
+ """
+
+ if context is None:
+ context = {}
+
+ session = ConnectorSession(cr, uid, context=context)
+ storage = OpenERPJobStorage(session)
+
+ move_ids = self.search(cr, uid, [
+ ('to_post', '=', False),
+ ('post_job_uuid', '!=', False),
+ ('state', '=', 'draft'),
+ ], context=context)
+
+ for move in self.browse(cr, uid, move_ids, context=context):
+ job = storage.load(move.post_job_uuid)
+ if job.state in (u'pending', u'enqueued'):
+ job.set_done(result=_(
+ u'Task set to Done because the user unmarked the move'
+ ))
+ storage.store(job)
+
+ def mark_for_posting(self, cr, uid, move_ids, eta=None, context=None):
+ """Mark a list of moves for delayed posting, and enqueue the jobs."""
+ if context is None:
+ context = {}
+ # For massive amounts of moves, this becomes necessary to avoid
+ # MemoryError's
+ for start in xrange(0, len(move_ids), BLOCK_SIZE):
+ self.write(
+ cr,
+ uid,
+ move_ids[start:start + BLOCK_SIZE],
+ {'to_post': True},
+ context=context)
+ self._delay_post_marked(cr, uid, eta=eta, context=context)
+
+ def unmark_for_posting(self, cr, uid, move_ids, context=None):
+ """Unmark moves for delayed posting, and cancel the jobs."""
+ if context is None:
+ context = {}
+ self.write(cr, uid, move_ids, {'to_post': False}, context=context)
+ self._cancel_jobs(cr, uid, context=context)
+
+
+@job
+def validate_one_move(session, model_name, move_id):
+ """Validate a move, and leave the job reference in place."""
+ session.pool['account.move'].button_validate(
+ session.cr,
+ session.uid,
+ [move_id]
+ )
diff --git a/account_move_batch_validate/account_view.xml b/account_move_batch_validate/account_view.xml
new file mode 100644
index 000000000..1f5a60af9
--- /dev/null
+++ b/account_move_batch_validate/account_view.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+ view.move.to_post.tree
+ account.move
+
+
+
+
+
+
+
+
+
+ view.move.to_post.form
+ account.move
+
+
+
+
+
+
+
+
+
+
diff --git a/account_move_batch_validate/i18n/account_move_batch_validate.pot b/account_move_batch_validate/i18n/account_move_batch_validate.pot
new file mode 100644
index 000000000..d979d1c72
--- /dev/null
+++ b/account_move_batch_validate/i18n/account_move_batch_validate.pot
@@ -0,0 +1,191 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * account_move_batch_validate
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2014-01-17 14:17+0000\n"
+"PO-Revision-Date: 2014-01-17 14:17+0000\n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: account_move_batch_validate
+#: field:account.move,post_job_uuid:0
+msgid "UUID of the Job to approve this move"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: help:account.move,to_post:0
+msgid "Check this box to mark the move for batch posting"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: code:addons/account_move_batch_validate/account.py:95
+#, python-format
+msgid "Task set to Done because the user unmarked the move"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: view:account.move.marker:0
+msgid "Mark"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: selection:account.move.marker,action:0
+msgid "Unmark for posting"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: field:account.move,to_post:0
+msgid "To Post"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,company_id:0
+msgid "Company"
+msgstr "Société"
+
+#. module: account_move_batch_validate
+#: model:ir.actions.act_window,name:account_move_batch_validate.action_account_move_marker
+#: model:ir.ui.menu,name:account_move_batch_validate.menu_account_move_marker
+msgid "Mark Journal Items for Batch Posting"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: selection:account.move.marker,filter:0
+msgid "Date"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,chart_account_id:0
+msgid "Chart of Account"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: view:account.move.marker:0
+#: field:account.move.marker,journal_ids:0
+msgid "Journals"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,target_move:0
+msgid "Target Moves"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: view:account.move.marker:0
+msgid "Report Options"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: view:account.move.marker:0
+#: selection:account.move.marker,filter:0
+msgid "Periods"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,date_to:0
+msgid "End Date"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: view:account.move.marker:0
+msgid "Dates"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,period_from:0
+msgid "Start Period"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,eta:0
+msgid "Seconds to wait before starting the jobs"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: selection:account.move.marker,target_move:0
+msgid "All Posted Entries"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: help:account.move.marker,fiscalyear_id:0
+msgid "Keep empty for all open fiscal year"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,period_to:0
+msgid "End Period"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,fiscalyear_id:0
+msgid "Fiscal Year"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: selection:account.move.marker,filter:0
+msgid "No Filters"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,action:0
+msgid "Action"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: model:ir.model,name:account_move_batch_validate.model_account_move
+msgid "Account Entry"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: selection:account.move.marker,action:0
+msgid "Mark for posting"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: model:ir.model,name:account_move_batch_validate.model_account_move_marker
+msgid "Mark Journal Items for batch posting"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: view:account.move.marker:0
+msgid "Filters"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: view:account.move.marker:0
+msgid "Cancel"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,date_from:0
+msgid "Start Date"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: help:account.move.marker,chart_account_id:0
+msgid "Select Charts of Accounts"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,filter:0
+msgid "Filter by"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: view:account.move.marker:0
+msgid "or"
+msgstr ""
+
+#. module: account_move_batch_validate
+#: selection:account.move.marker,target_move:0
+msgid "All Entries"
+msgstr ""
+
diff --git a/account_move_batch_validate/i18n/fr.po b/account_move_batch_validate/i18n/fr.po
new file mode 100644
index 000000000..8da8ab826
--- /dev/null
+++ b/account_move_batch_validate/i18n/fr.po
@@ -0,0 +1,185 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * account_move_batch_validate
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2014-02-19 10:51+0000\n"
+"PO-Revision-Date: 2014-02-19 10:51+0000\n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: account_move_batch_validate
+#: field:account.move,post_job_uuid:0
+msgid "UUID of the Job to approve this move"
+msgstr "UUID du Job pour approuver cette move"
+
+#. module: account_move_batch_validate
+#: help:account.move,to_post:0
+msgid "Check this box to mark the move for batch posting"
+msgstr "Check this box to mark the move for batch posting"
+
+#. module: account_move_batch_validate
+#: view:account.move.marker:0
+msgid "Mark"
+msgstr "Mark"
+
+#. module: account_move_batch_validate
+#: selection:account.move.marker,action:0
+msgid "Unmark for posting"
+msgstr "Unmark for posting"
+
+#. module: account_move_batch_validate
+#: field:account.move,to_post:0
+msgid "To Post"
+msgstr "Validation demandée"
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,company_id:0
+msgid "Company"
+msgstr "Société"
+
+#. module: account_move_batch_validate
+#: model:ir.actions.act_window,name:account_move_batch_validate.action_account_move_marker
+#: model:ir.ui.menu,name:account_move_batch_validate.menu_account_move_marker
+msgid "Mark Jornal Items for Batch Posting"
+msgstr "Sélectionner Ecritures comptables à Valider en batch"
+
+#. module: account_move_batch_validate
+#: selection:account.move.marker,filter:0
+msgid "Date"
+msgstr "Date"
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,chart_account_id:0
+msgid "Chart of Account"
+msgstr "Plan Comptable"
+
+#. module: account_move_batch_validate
+#: view:account.move.marker:0
+#: field:account.move.marker,journal_ids:0
+msgid "Journals"
+msgstr "Journaux"
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,target_move:0
+msgid "Target Moves"
+msgstr "Target Moves"
+
+#. module: account_move_batch_validate
+#: view:account.move.marker:0
+msgid "Report Options"
+msgstr "Report Options"
+
+#. module: account_move_batch_validate
+#: view:account.move.marker:0
+#: selection:account.move.marker,filter:0
+msgid "Periods"
+msgstr "Periods"
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,date_to:0
+msgid "End Date"
+msgstr "End Date"
+
+#. module: account_move_batch_validate
+#: view:account.move.marker:0
+msgid "Dates"
+msgstr "Dates"
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,period_from:0
+msgid "Start Period"
+msgstr "Période de debut"
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,eta:0
+msgid "Seconds to wait before starting the jobs"
+msgstr "Seconds to wait before starting the jobs"
+
+#. module: account_move_batch_validate
+#: selection:account.move.marker,target_move:0
+msgid "All Posted Entries"
+msgstr "Toutes les écritures passées"
+
+#. module: account_move_batch_validate
+#: help:account.move.marker,fiscalyear_id:0
+msgid "Keep empty for all open fiscal year"
+msgstr "Keep empty for all open fiscal year"
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,period_to:0
+msgid "End Period"
+msgstr "Période de fin"
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,fiscalyear_id:0
+msgid "Fiscal Year"
+msgstr "Exercice"
+
+#. module: account_move_batch_validate
+#: selection:account.move.marker,filter:0
+msgid "No Filters"
+msgstr "Aucun filtre"
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,action:0
+msgid "Action"
+msgstr "Action"
+
+#. module: account_move_batch_validate
+#: model:ir.model,name:account_move_batch_validate.model_account_move
+msgid "Account Entry"
+msgstr "Pièce comptable"
+
+#. module: account_move_batch_validate
+#: selection:account.move.marker,action:0
+msgid "Mark for posting"
+msgstr "Sélectionner pour validation"
+
+#. module: account_move_batch_validate
+#: model:ir.model,name:account_move_batch_validate.model_account_move_marker
+msgid "Mark Journal Items for batch posting"
+msgstr "Sélectionner Ecritures comptables à Valider en batch"
+
+#. module: account_move_batch_validate
+#: view:account.move.marker:0
+msgid "Filters"
+msgstr "Filtres"
+
+#. module: account_move_batch_validate
+#: view:account.move.marker:0
+msgid "Cancel"
+msgstr "Annuler"
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,date_from:0
+msgid "Start Date"
+msgstr "Date de début"
+
+#. module: account_move_batch_validate
+#: help:account.move.marker,chart_account_id:0
+msgid "Select Charts of Accounts"
+msgstr "Sélectionner Plan Comptable"
+
+#. module: account_move_batch_validate
+#: field:account.move.marker,filter:0
+msgid "Filter by"
+msgstr "Filtrer par"
+
+#. module: account_move_batch_validate
+#: view:account.move.marker:0
+msgid "or"
+msgstr "ou"
+
+#. module: account_move_batch_validate
+#: selection:account.move.marker,target_move:0
+msgid "All Entries"
+msgstr "Toutes les écritures"
+
diff --git a/account_move_batch_validate/test/batch_validate.yml b/account_move_batch_validate/test/batch_validate.yml
new file mode 100644
index 000000000..c95ea3ec4
--- /dev/null
+++ b/account_move_batch_validate/test/batch_validate.yml
@@ -0,0 +1,48 @@
+-
+ I create a move
+-
+ !record {model: account.move, id: move1}:
+ journal_id: account.sales_journal
+ line_id:
+ - name: Receivable line
+ account_id: account.a_recv
+ debit: 1000.0
+ - name: Sales line
+ account_id: account.a_sale
+ credit: 1000.0
+-
+ I check that the move is still draft
+-
+ !assert {model: account.move, id: move1}:
+ - state == 'draft'
+-
+ I create a wizard
+-
+ !record {model: account.move.marker, id: wiz_marker1}:
+ action: mark
+-
+ I run the wizard
+-
+ !python {model: account.move.marker}: |
+ self.button_mark(
+ cr, uid, [ref('wiz_marker1')], context=context
+ )
+-
+ I read the UUID from the move, I dequeue the job and run it
+-
+ !python {model: account.move}: |
+ from openerp.addons.connector.queue.job import OpenERPJobStorage
+ from openerp.addons.connector.session import ConnectorSession
+
+ move = self.browse(cr, uid, ref('move1'), context=context)
+ uuid = move.post_job_uuid
+ session = ConnectorSession(cr, uid, context=context)
+ storage = OpenERPJobStorage(session)
+
+ myjob = storage.load(uuid)
+ myjob.perform(session)
+-
+ I check that the move is now approved
+-
+ !assert {model: account.move, id: move1}:
+ - state == 'posted'
diff --git a/account_move_batch_validate/test/batch_validate_then_unmark.yml b/account_move_batch_validate/test/batch_validate_then_unmark.yml
new file mode 100644
index 000000000..0f5523f40
--- /dev/null
+++ b/account_move_batch_validate/test/batch_validate_then_unmark.yml
@@ -0,0 +1,62 @@
+-
+ I create a move
+-
+ !record {model: account.move, id: move2}:
+ journal_id: account.sales_journal
+ line_id:
+ - name: Receivable line
+ account_id: account.a_recv
+ debit: 2000.0
+ - name: Sales line
+ account_id: account.a_sale
+ credit: 2000.0
+-
+ I check that the move is still draft
+-
+ !assert {model: account.move, id: move2}:
+ - state == 'draft'
+-
+ I create a wizard with a long ETA
+-
+ !record {model: account.move.marker, id: wiz_marker2}:
+ action: mark
+ eta: 10000
+-
+ I run the wizard
+-
+ !python {model: account.move.marker}: |
+ self.button_mark(
+ cr, uid, [ref('wiz_marker2')], context=context
+ )
+-
+ Now I change my mind and I create a wizard to unmark the moves
+-
+ !record {model: account.move.marker, id: wiz_unmarker3}:
+ action: unmark
+-
+ I run the wizard
+-
+ !python {model: account.move.marker}: |
+ self.button_mark(
+ cr, uid, [ref('wiz_unmarker3')], context=context
+ )
+-
+ Now I checked that my job is done, and the move is still draft
+-
+ !python {model: account.move}: |
+ from openerp.addons.connector.queue.job import OpenERPJobStorage
+ from openerp.addons.connector.session import ConnectorSession
+
+ session = ConnectorSession(cr, uid, context=context)
+ storage = OpenERPJobStorage(session)
+
+ move = self.browse(cr, uid, ref('move2'), context=context)
+ myjob = storage.load(move.post_job_uuid)
+ assert myjob.state == 'done', 'Job is in state {0}, should be done'.format(
+ myjob.state
+ )
+-
+ I check that the move is still draft
+-
+ !assert {model: account.move, id: move2}:
+ - state == 'draft'
diff --git a/account_move_batch_validate/wizard/__init__.py b/account_move_batch_validate/wizard/__init__.py
new file mode 100644
index 000000000..f13b63cb0
--- /dev/null
+++ b/account_move_batch_validate/wizard/__init__.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+###############################################################################
+# #
+# Author: Leonardo Pistone
+# Copyright 2014 Camptocamp SA
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU Affero General Public License as #
+# published by the Free Software Foundation, either version 3 of the #
+# License, or (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU Affero General Public License for more details. #
+# #
+# You should have received a copy of the GNU Affero General Public License #
+# along with this program. If not, see . #
+# #
+###############################################################################
+"""Wizard to mark account moves for batch posting."""
+from . import move_marker # noqa
diff --git a/account_move_batch_validate/wizard/move_marker.py b/account_move_batch_validate/wizard/move_marker.py
new file mode 100644
index 000000000..c4805fe55
--- /dev/null
+++ b/account_move_batch_validate/wizard/move_marker.py
@@ -0,0 +1,89 @@
+# -*- coding: utf-8 -*-
+###############################################################################
+# #
+# Author: Leonardo Pistone
+# Copyright 2014 Camptocamp SA
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU Affero General Public License as #
+# published by the Free Software Foundation, either version 3 of the #
+# License, or (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU Affero General Public License for more details. #
+# #
+# You should have received a copy of the GNU Affero General Public License #
+# along with this program. If not, see . #
+# #
+###############################################################################
+"""Wizards for batch posting."""
+
+from openerp.osv import fields, orm
+
+
+class AccountMoveMarker(orm.TransientModel):
+
+ """Wizard to mark account moves for batch posting."""
+
+ _name = "account.move.marker"
+ _inherit = "account.common.report"
+ _description = "Mark Journal Items for batch posting"
+
+ _columns = {
+ 'action': fields.selection([
+ ('mark', 'Mark for posting'),
+ ('unmark', 'Unmark for posting'),
+ ], "Action", required=True),
+ 'eta': fields.integer('Seconds to wait before starting the jobs')
+ }
+
+ _defaults = {
+ 'action': 'mark',
+ }
+
+ def button_mark(self, cr, uid, ids, context=None):
+ """Mark/unmark lines and update the queue. Return action."""
+
+ for wiz in self.browse(cr, uid, ids, context=context):
+
+ move_obj = self.pool['account.move']
+
+ domain = [('state', '=', 'draft')]
+
+ if wiz.filter == 'filter_period':
+ period_pool = self.pool['account.period']
+ period_ids = period_pool.search(cr, uid, [
+ ('date_start', '>=', wiz.period_from.date_start),
+ ('date_stop', '<=', wiz.period_to.date_stop),
+ ], context=context)
+
+ domain.append((
+ 'period_id',
+ 'in',
+ period_ids
+ ))
+ elif wiz.filter == 'filter_date':
+ domain += [
+ ('date', '>=', wiz.date_from),
+ ('date', '<=', wiz.date_to),
+ ]
+
+ if wiz.journal_ids:
+ domain.append((
+ 'journal_id',
+ 'in',
+ [journal.id for journal in wiz.journal_ids]
+ ))
+
+ move_ids = move_obj.search(cr, uid, domain, context=context)
+
+ if wiz.action == 'mark':
+ move_obj.mark_for_posting(cr, uid, move_ids, eta=wiz.eta,
+ context=context)
+
+ elif wiz.action == 'unmark':
+ move_obj.unmark_for_posting(cr, uid, move_ids, context=context)
+
+ return {'type': 'ir.actions.act_window_close'}
diff --git a/account_move_batch_validate/wizard/move_marker_view.xml b/account_move_batch_validate/wizard/move_marker_view.xml
new file mode 100644
index 000000000..2cd395873
--- /dev/null
+++ b/account_move_batch_validate/wizard/move_marker_view.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+ Mark Jornal Items for Batch Posting
+ account.move.marker
+
+
+
+
+
+
+ Mark Jornal Items for Batch Posting
+ ir.actions.act_window
+ account.move.marker
+ form
+ form
+ new
+
+
+
+
+
+
+
+
+