diff --git a/pos_picking_delayed/README.rst b/pos_picking_delayed/README.rst
new file mode 100644
index 00000000..21cd7854
--- /dev/null
+++ b/pos_picking_delayed/README.rst
@@ -0,0 +1,21 @@
+**This file is going to be generated by oca-gen-addon-readme.**
+
+*Manual changes will be overwritten.*
+
+Please provide content in the ``readme`` directory:
+
+* **DESCRIPTION.rst** (required)
+* INSTALL.rst (optional)
+* CONFIGURE.rst (optional)
+* **USAGE.rst** (optional, highly recommended)
+* DEVELOP.rst (optional)
+* ROADMAP.rst (optional)
+* HISTORY.rst (optional, recommended)
+* **CONTRIBUTORS.rst** (optional, highly recommended)
+* CREDITS.rst (optional)
+
+Content of this README will also be drawn from the addon manifest,
+from keys such as name, authors, maintainers, development_status,
+and license.
+
+A good, one sentence summary in the manifest is also highly recommended.
diff --git a/pos_picking_delayed/__init__.py b/pos_picking_delayed/__init__.py
new file mode 100644
index 00000000..042e239e
--- /dev/null
+++ b/pos_picking_delayed/__init__.py
@@ -0,0 +1,2 @@
+# coding: utf-8
+from . import models
diff --git a/pos_picking_delayed/__manifest__.py b/pos_picking_delayed/__manifest__.py
new file mode 100644
index 00000000..b215b527
--- /dev/null
+++ b/pos_picking_delayed/__manifest__.py
@@ -0,0 +1,26 @@
+# coding: utf-8
+# Copyright 2018 - Today Sylvain LE GAL (https://twitter.com/legalsylvain)
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+
+{
+ 'name': 'Point of Sale - Picking Creation Delayed',
+ 'summary': 'Delay the creation of the picking when PoS order is created',
+ 'version': '10.0.1.0.0',
+ 'category': 'Point Of Sale',
+ 'author': 'GRAP, '
+ 'Odoo Community Association (OCA)',
+ 'license': 'AGPL-3',
+ 'website': 'https://www.github.com/OCA/pos',
+ 'depends': [
+ 'point_of_sale',
+ ],
+ 'data': [
+ 'data/ir_cron.xml',
+ 'views/view_pos_config.xml',
+ 'views/view_pos_order.xml',
+ ],
+ 'images': [
+ 'static/description/pos_order_tree.png',
+ ],
+ 'installable': True,
+}
diff --git a/pos_picking_delayed/data/ir_cron.xml b/pos_picking_delayed/data/ir_cron.xml
new file mode 100644
index 00000000..d0d71607
--- /dev/null
+++ b/pos_picking_delayed/data/ir_cron.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+ Create Delayed PoS Picking
+
+ 1
+ minutes
+ -1
+
+ pos.order
+ create_delayed_picking
+ ()
+
+
+
diff --git a/pos_picking_delayed/i18n/fr.po b/pos_picking_delayed/i18n/fr.po
new file mode 100644
index 00000000..4c28aae6
--- /dev/null
+++ b/pos_picking_delayed/i18n/fr.po
@@ -0,0 +1,47 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * pos_picking_delayed
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 10.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-10-17 11:06+0000\n"
+"PO-Revision-Date: 2018-10-17 11:06+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: pos_picking_delayed
+#: model:ir.model.fields,help:pos_picking_delayed.field_pos_config_picking_creation_delayed
+msgid "Check this box if you want to delay the creation of the picking created by the PoS orders. If checked, the pickings will be created later, by a cron task."
+msgstr "Cochez cette case si vous souhaitez retarder la création des transferts de stock liés au commandes de point de vente. Si la case est cochée, ceux-ci seront créés ultérieurement, par une tâche de fond."
+
+#. module: pos_picking_delayed
+#: model:ir.model.fields,field_description:pos_picking_delayed.field_pos_order_has_picking_delayed
+msgid "Has picking delayed"
+msgstr "A un transfert de stock retardé"
+
+#. module: pos_picking_delayed
+#: model:ir.model.fields,field_description:pos_picking_delayed.field_pos_config_picking_creation_delayed
+msgid "Picking Creation Delayed"
+msgstr "Retarder la création des transferts de stock"
+
+#. module: pos_picking_delayed
+#: model:ir.model,name:pos_picking_delayed.model_pos_order
+msgid "Point of Sale Orders"
+msgstr "Commandes du point de vente"
+
+#. module: pos_picking_delayed
+#: model:ir.model.fields,help:pos_picking_delayed.field_pos_order_has_picking_delayed
+msgid "This checkbox is checked if the generation of the picking has been delayed. The picking will be created by cron."
+msgstr "Cette case est cochée si la génération du transfert de stock a été retardée. Celui ci sera créé par une tâche de fond."
+
+#. module: pos_picking_delayed
+#: model:ir.model,name:pos_picking_delayed.model_pos_config
+msgid "pos.config"
+msgstr "pos.config"
+
diff --git a/pos_picking_delayed/models/__init__.py b/pos_picking_delayed/models/__init__.py
new file mode 100644
index 00000000..527a57a5
--- /dev/null
+++ b/pos_picking_delayed/models/__init__.py
@@ -0,0 +1,4 @@
+# coding: utf-8
+
+from . import pos_config
+from . import pos_order
diff --git a/pos_picking_delayed/models/pos_config.py b/pos_picking_delayed/models/pos_config.py
new file mode 100644
index 00000000..73a637da
--- /dev/null
+++ b/pos_picking_delayed/models/pos_config.py
@@ -0,0 +1,16 @@
+# coding: utf-8
+# Copyright 2018 - Today Sylvain LE GAL (https://twitter.com/legalsylvain)
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+
+
+from odoo import fields, models
+
+
+class PosConfig(models.Model):
+ _inherit = 'pos.config'
+
+ picking_creation_delayed = fields.Boolean(
+ string='Picking Creation Delayed', default=True,
+ help="Check this box if you want to delay the creation of the picking"
+ " created by the PoS orders. If checked, the pickings will"
+ " be created later, by a cron task.")
diff --git a/pos_picking_delayed/models/pos_order.py b/pos_picking_delayed/models/pos_order.py
new file mode 100644
index 00000000..c32d89fb
--- /dev/null
+++ b/pos_picking_delayed/models/pos_order.py
@@ -0,0 +1,57 @@
+# coding: utf-8
+# Copyright 2018 - Today Sylvain LE GAL (https://twitter.com/legalsylvain)
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+
+import logging
+
+from odoo import api, fields, models
+
+_logger = logging.getLogger(__name__)
+
+
+class PosOrder(models.Model):
+ _inherit = 'pos.order'
+
+ has_picking_delayed = fields.Boolean(
+ default=False, help="This checkbox is checked if the generation of"
+ " the picking has been delayed. The picking will be created by cron.")
+
+ # Overload Section
+ @api.model
+ def create_from_ui(self, orders):
+ PosSession = self.env['pos.session']
+ for order_data in orders:
+ session_id = order_data.get('data').get('pos_session_id')
+ session = PosSession.browse(session_id)
+ order_data['data']['has_picking_delayed'] =\
+ session.config_id.picking_creation_delayed
+ return super(PosOrder, self.with_context(
+ create_from_ui=True)).create_from_ui(orders)
+
+ def create_picking(self):
+ if self.env.context.get('create_from_ui', False):
+ orders = self.filtered(lambda x: not x.has_picking_delayed)
+ else:
+ orders = self
+ res = super(PosOrder, orders).create_picking()
+ orders.write({'has_picking_delayed': False})
+ return res
+
+ @api.model
+ def _order_fields(self, ui_order):
+ res = super(PosOrder, self)._order_fields(ui_order)
+ res['has_picking_delayed'] = ui_order['has_picking_delayed']
+ return res
+
+ # Custom Section
+ @api.model
+ def create_delayed_picking(self):
+ orders = self.search([
+ ('state', '!=', 'draft'),
+ ('has_picking_delayed', '=', True),
+ ], order='date_order')
+ for order in orders:
+ order.sudo(order.user_id.id).with_context(
+ force_company=order.company_id.id).create_picking()
+ if orders:
+ _logger.info("Pickings handled for %d PoS Orders" % (len(orders)))
diff --git a/pos_picking_delayed/readme/CONFIGURE.rst b/pos_picking_delayed/readme/CONFIGURE.rst
new file mode 100644
index 00000000..03835268
--- /dev/null
+++ b/pos_picking_delayed/readme/CONFIGURE.rst
@@ -0,0 +1,5 @@
+* Go to 'Point of Sale' / 'Configuration' / 'Point of Sale'
+* Select your Point of Sale
+* Set the value in the field 'Picking Creation Delayed'. (Checked by default)
+
+.. image:: /pos_picking_delayed/static/description/pos_config_form.png
diff --git a/pos_picking_delayed/readme/CONTRIBUTORS.rst b/pos_picking_delayed/readme/CONTRIBUTORS.rst
new file mode 100644
index 00000000..9f76a75b
--- /dev/null
+++ b/pos_picking_delayed/readme/CONTRIBUTORS.rst
@@ -0,0 +1 @@
+* Sylvain LE GAL
diff --git a/pos_picking_delayed/readme/CREDITS.rst b/pos_picking_delayed/readme/CREDITS.rst
new file mode 100644
index 00000000..0a9ea638
--- /dev/null
+++ b/pos_picking_delayed/readme/CREDITS.rst
@@ -0,0 +1,4 @@
+The development of this module has been financially supported by:
+
+* GRAP, Groupement Régional Alimentaire de Proximité (www.grap.coop)
+* Mind & Go, (https://mind-and-go.com/)
diff --git a/pos_picking_delayed/readme/DESCRIPTION.rst b/pos_picking_delayed/readme/DESCRIPTION.rst
new file mode 100644
index 00000000..b5e6f70d
--- /dev/null
+++ b/pos_picking_delayed/readme/DESCRIPTION.rst
@@ -0,0 +1,23 @@
+This module extends the functionality of odoo Point Of Sale to reduce creation
+time of the PoS orders, via the front UI.
+
+For that purpose, it delays the creation of the picking associated, that will
+be created later, by cron. (set by default to run each minute).
+
+Technical information
+---------------------
+
+A log will be generated to mention the creation of the pickings by cron.
+
+``2018-09-28 07:47:18,300 163 INFO db odoo.addons.base.ir.ir_cron: Starting job `Create Delayed PoS Picking.``
+
+``2018-09-28 07:47:19,168 163 INFO db odoo.addons.pos_picking_delayed.models.pos_order: Pickings created for 3 PoS Orders``
+
+This module is interesting specially in a context of Synchroneous Point Of
+Sale that is introduced by certification modules like 'l10n_fr_pos_cert' because
+in such cases, the bill will be printed only when the pos order is created (
+after the call of the function create_from_ui) and the creation of the picking
+is the process that takes the most time.
+
+See https://github.com/odoo/odoo/pull/26314#issuecomment-422949266
+for more information.
diff --git a/pos_picking_delayed/readme/ROADMAP.rst b/pos_picking_delayed/readme/ROADMAP.rst
new file mode 100644
index 00000000..d3eba886
--- /dev/null
+++ b/pos_picking_delayed/readme/ROADMAP.rst
@@ -0,0 +1,5 @@
+* Make this module depend on the module OCA `queue_job` job module.
+
+* In the cron job (or the future queue job), improvment can be done, limiting
+ the quantity of environments, grouping orders by company, and changing
+ context once.
diff --git a/pos_picking_delayed/readme/USAGE.rst b/pos_picking_delayed/readme/USAGE.rst
new file mode 100644
index 00000000..be46510c
--- /dev/null
+++ b/pos_picking_delayed/readme/USAGE.rst
@@ -0,0 +1,4 @@
+* Use your Point of Sale as usual. when validating an order, the order will
+ be in a different color until the cron is executed
+
+.. image:: /pos_picking_delayed/static/description/pos_order_tree.png
diff --git a/pos_picking_delayed/static/description/pos_config_form.png b/pos_picking_delayed/static/description/pos_config_form.png
new file mode 100644
index 00000000..a23f4db4
Binary files /dev/null and b/pos_picking_delayed/static/description/pos_config_form.png differ
diff --git a/pos_picking_delayed/static/description/pos_order_tree.png b/pos_picking_delayed/static/description/pos_order_tree.png
new file mode 100644
index 00000000..a8781e7f
Binary files /dev/null and b/pos_picking_delayed/static/description/pos_order_tree.png differ
diff --git a/pos_picking_delayed/tests/__init__.py b/pos_picking_delayed/tests/__init__.py
new file mode 100644
index 00000000..e46a9f76
--- /dev/null
+++ b/pos_picking_delayed/tests/__init__.py
@@ -0,0 +1,3 @@
+# coding: utf-8
+
+from . import test_module
diff --git a/pos_picking_delayed/tests/test_module.py b/pos_picking_delayed/tests/test_module.py
new file mode 100644
index 00000000..0f7a6c6e
--- /dev/null
+++ b/pos_picking_delayed/tests/test_module.py
@@ -0,0 +1,106 @@
+# -*- coding: utf-8 -*-
+# Copyright 2018 - Today Sylvain LE GAL (https://twitter.com/legalsylvain)
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+
+from odoo import fields
+from odoo.tests.common import TransactionCase
+
+
+class TestModule(TransactionCase):
+
+ def setUp(self):
+ super(TestModule, self).setUp()
+ self.pos_order_obj = self.env['pos.order']
+ self.pos_picking_cron = self.env.ref(
+ 'pos_picking_delayed.cron_create_delayed_pos_picking')
+ self.pos_config = self.env.ref('point_of_sale.pos_config_main')
+ self.carotte_product = self.env.ref('point_of_sale.carotte')
+
+ def test_01_picking_delayed_enabled(self):
+ # Disable Cron
+ self.pos_picking_cron.active = False
+
+ # Enable feature
+ self.pos_config.picking_creation_delayed = True
+
+ order = self._open_session_create_order()
+
+ self.assertEqual(
+ order.picking_id.id, False,
+ "Creating order via UI should not generate a picking if"
+ " feature is enabled")
+
+ # run cron and test if picking is now created
+ self.pos_picking_cron.method_direct_trigger()
+
+ self.assertNotEqual(
+ order.picking_id.id, False,
+ "Run PoS picking Cron should generate picking for PoS Orders"
+ " without picking")
+
+ def test_02_picking_delayed_disabled(self):
+ # Disable Cron
+ self.pos_picking_cron.active = False
+
+ # Disable feature
+ self.pos_config.picking_creation_delayed = False
+
+ order = self._open_session_create_order()
+
+ picking_id = order.picking_id.id
+ self.assertNotEqual(
+ picking_id, False,
+ "Creating order via UI should generate a picking if"
+ " feature is disabled")
+
+ # run cron and test if picking is now created
+ self.pos_picking_cron.method_direct_trigger()
+
+ self.assertEqual(
+ order.picking_id.id, picking_id,
+ "Run PoS picking Cron should not regenerate picking for"
+ " PoS Orders that have already a picking created.")
+
+ def _open_session_create_order(self):
+ # Create order
+ self.pos_config.open_session_cb()
+ order_data = {
+ 'id': u'0006-001-0010',
+ 'to_invoice': False,
+ 'data': {
+ 'user_id': 1,
+ 'name': 'Order 0006-001-0010',
+ 'partner_id': False,
+ 'amount_paid': 0.9,
+ 'pos_session_id': self.pos_config.current_session_id.id,
+ 'lines': [[0, 0, {
+ 'id': 1,
+ 'product_id': self.carotte_product.id,
+ 'tax_ids': [[6, False, []]],
+ 'price_unit': 0.9,
+ 'qty': 1,
+ 'pack_lot_ids': [],
+ 'discount': 0,
+ }]],
+ 'statement_ids': [[0, 0, {
+ 'journal_id': self.pos_config.journal_ids[0].id,
+ 'amount': 0.9,
+ 'name': fields.Datetime.now(),
+ 'account_id':
+ self.env.user.partner_id.property_account_receivable_id.id,
+ 'statement_id':
+ self.pos_config.current_session_id.statement_ids[0].id,
+ }]],
+ 'creation_date': u'2018-09-27 15:51:03',
+ 'amount_tax': 0,
+ 'fiscal_position_id': False,
+ 'uid': u'00001-001-0001',
+ 'amount_return': 0,
+ 'sequence_number': 1,
+ 'amount_total': 0.9,
+ }}
+
+ # Test if picking is not created
+ result = self.pos_order_obj.create_from_ui([order_data])
+ order = self.pos_order_obj.browse(result[0])
+ return order
diff --git a/pos_picking_delayed/views/view_pos_config.xml b/pos_picking_delayed/views/view_pos_config.xml
new file mode 100644
index 00000000..9405a9e0
--- /dev/null
+++ b/pos_picking_delayed/views/view_pos_config.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+ pos.config
+
+
+
+
+
+
+
+
+
diff --git a/pos_picking_delayed/views/view_pos_order.xml b/pos_picking_delayed/views/view_pos_order.xml
new file mode 100644
index 00000000..13f83aa8
--- /dev/null
+++ b/pos_picking_delayed/views/view_pos_order.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+ pos.order
+
+
+
+ has_picking_delayed == True
+
+
+
+
+
+
+
+
+ pos.order
+
+
+
+
+
+
+
+
+