[8.0] [ADD] pos order to sale order (w/o picking) (#188)
* [ADD] new module pos_order_to_sale_orderpull/441/head
-
135pos_order_to_sale_order/README.rst
-
2pos_order_to_sale_order/__init__.py
-
26pos_order_to_sale_order/__openerp__.py
-
19pos_order_to_sale_order/demo/product_template.xml
-
7pos_order_to_sale_order/demo/res_groups.xml
-
51pos_order_to_sale_order/demo/sale_order.xml
-
7pos_order_to_sale_order/demo/stock_picking_type.xml
-
168pos_order_to_sale_order/i18n/fr.po
-
3pos_order_to_sale_order/models/__init__.py
-
27pos_order_to_sale_order/models/pos_config.py
-
60pos_order_to_sale_order/models/sale_order.py
-
BINpos_order_to_sale_order/static/description/icon.png
-
BINpos_order_to_sale_order/static/description/pos_config_form.png
-
BINpos_order_to_sale_order/static/description/pos_create_picking_confirm.png
-
BINpos_order_to_sale_order/static/description/pos_create_picking_option_1.png
-
BINpos_order_to_sale_order/static/description/pos_create_picking_option_2.png
-
BINpos_order_to_sale_order/static/description/pos_create_picking_option_3.png
-
171pos_order_to_sale_order/static/src/js/pos_order_to_sale_order.js
-
13pos_order_to_sale_order/static/src/xml/pos_order_to_sale_order.xml
-
11pos_order_to_sale_order/views/pos_order_to_sale_order.xml
-
16pos_order_to_sale_order/views/view_pos_config.xml
@ -0,0 +1,135 @@ |
|||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg |
|||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html |
|||
:alt: License: AGPL-3 |
|||
|
|||
|
|||
======================= |
|||
POS Order To Sale Order |
|||
======================= |
|||
|
|||
|
|||
This module extends the functionality of point of sale to allow sale orders |
|||
creation from the Point of Sale. |
|||
|
|||
|
|||
In the POS UI, buttons has been added to create a sale order and discard |
|||
the current POS order. |
|||
|
|||
This module is usefull in many cases, for exemple : |
|||
|
|||
* take orders with a very simple interface |
|||
|
|||
* if you have some customers that come every day in your shop, but want to |
|||
have a unique invoice at the end of the month. With that module, you can |
|||
create a sale order and deliver products every time to keep your stock value |
|||
correct, and to create a unique invoice, when you want. |
|||
|
|||
|
|||
Three options are available: |
|||
|
|||
#. '**Create a draft Order**' |
|||
A new sale order in a draft mode will be created that can be changed later. |
|||
|
|||
.. figure:: static/description/pos_create_picking_option_1.png |
|||
:width: 800 px |
|||
|
|||
#. '**Create a Confirmed Order**' |
|||
A new sale order will be created and confirmed. |
|||
|
|||
.. figure:: static/description/pos_create_picking_option_2.png |
|||
:width: 800 px |
|||
|
|||
#. '**Create Delivered Picking**' (by default) |
|||
A new sale order will be created and confirmed. the associated picking |
|||
will be marked as delivered. |
|||
|
|||
.. figure:: static/description/pos_create_picking_option_3.png |
|||
:width: 800 px |
|||
|
|||
Configuration |
|||
============= |
|||
|
|||
To configure this module, you need to: |
|||
|
|||
#. Go to Point Of Sale / Configuration / Point of Sale |
|||
#. Check the box 'Create Sale Orders' |
|||
#. Select the desired default behaviour |
|||
|
|||
.. figure:: static/description/pos_config_form.png |
|||
:width: 800 px |
|||
|
|||
Usage |
|||
===== |
|||
|
|||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas |
|||
:alt: Try me on Runbot |
|||
:target: https://runbot.odoo-community.org/runbot/184/8.0 |
|||
|
|||
Technical Notes |
|||
=============== |
|||
|
|||
* Some hooks are defined in the JS file, to define custom behaviour after |
|||
having created the sale order (and the stock picking). |
|||
|
|||
* Some prepare functions are available in the sale.order model, to overload |
|||
the creation of the sale order. |
|||
|
|||
* You could be interested by another module, pos_sale_order, that completely |
|||
alter Point of Sale module, avoiding creating Pos Orders, and creating |
|||
allways Sale Orders. |
|||
This module is a WIP state, and is available here: |
|||
https://github.com/OCA/pos/pull/35 |
|||
|
|||
Known issues / Roadmap |
|||
====================== |
|||
|
|||
* Because of the poor design of the Odoo Point of Sale, some basic features |
|||
are not available by default, like pricelist, fiscal position, etc ... |
|||
For that reason, unit price will be recomputed by default, when creating the |
|||
sale order, and the unit price of the current bill will not be used. |
|||
We could imagine to create an option 'Use Pos Order Unit Price' in a setting. |
|||
|
|||
For more information about that point, you could check pos_pricelist OCA |
|||
module. (same repository). |
|||
|
|||
.. figure:: static/description/pos_create_picking_confirm.png |
|||
:width: 800 px |
|||
|
|||
|
|||
Bug Tracker |
|||
=========== |
|||
|
|||
Bugs are tracked on `GitHub Issues |
|||
<https://github.com/OCA/pos/issues>`_. In case of trouble, please |
|||
check there if your issue has already been reported. If you spotted it first, |
|||
help us smash it by providing detailed and welcomed feedback. |
|||
|
|||
Credits |
|||
======= |
|||
|
|||
Contributors |
|||
------------ |
|||
|
|||
* Sylvain Le Gal (https://twitter.com/legalsylvain) |
|||
|
|||
Funders |
|||
------- |
|||
|
|||
The development of this module has been financially supported by: |
|||
|
|||
* GRAP, Groupement Régional Alimentaire de Proximité (http://www.grap.coop) |
|||
|
|||
Maintainer |
|||
---------- |
|||
|
|||
.. image:: https://odoo-community.org/logo.png |
|||
:alt: Odoo Community Association |
|||
:target: https://odoo-community.org |
|||
|
|||
This module is maintained by the OCA. |
|||
|
|||
OCA, or the Odoo Community Association, is a nonprofit organization whose |
|||
mission is to support the collaborative development of Odoo features and |
|||
promote its widespread use. |
|||
|
|||
To contribute to this module, please visit https://odoo-community.org. |
@ -0,0 +1,2 @@ |
|||
# -*- coding: utf-8 -*- |
|||
from . import models |
@ -0,0 +1,26 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright (C) 2017 - Today: GRAP (http://www.grap.coop) |
|||
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
{ |
|||
'name': 'PoS Order To Sale Order', |
|||
'version': '8.0.1.0.0', |
|||
'author': 'GRAP,Odoo Community Association (OCA)', |
|||
'category': 'Point Of Sale', |
|||
'license': 'AGPL-3', |
|||
'depends': [ |
|||
'point_of_sale', |
|||
], |
|||
'website': 'https://odoo-community.org/', |
|||
'data': [ |
|||
'views/view_pos_config.xml', |
|||
'views/pos_order_to_sale_order.xml', |
|||
], |
|||
'demo': [ |
|||
'demo/res_groups.xml', |
|||
], |
|||
'qweb': [ |
|||
'static/src/xml/pos_order_to_sale_order.xml', |
|||
], |
|||
} |
@ -0,0 +1,19 @@ |
|||
<openerp><data> |
|||
|
|||
<record id="product.product_product_4_product_template" model="product.template"> |
|||
<field name="available_in_pos" eval="True"/> |
|||
</record> |
|||
|
|||
<record id="product.product_product_7_product_template" model="product.template"> |
|||
<field name="available_in_pos" eval="True"/> |
|||
</record> |
|||
|
|||
<record id="product.product_product_9_product_template" model="product.template"> |
|||
<field name="available_in_pos" eval="True"/> |
|||
</record> |
|||
|
|||
<record id="product.product_product_24_product_template" model="product.template"> |
|||
<field name="available_in_pos" eval="True"/> |
|||
</record> |
|||
|
|||
</data></openerp> |
@ -0,0 +1,7 @@ |
|||
<openerp><data> |
|||
|
|||
<record id="sale.group_discount_per_so_line" model="res.groups"> |
|||
<field name="users" eval="[(4, ref('base.user_root'))]"/> |
|||
</record> |
|||
|
|||
</data></openerp> |
@ -0,0 +1,51 @@ |
|||
<openerp><data> |
|||
|
|||
<!-- Sale Order 1--> |
|||
<record id="sale_order_1" model="sale.order"> |
|||
<field name="partner_id" ref="base.res_partner_2"/> |
|||
<field name="order_policy">picking</field> |
|||
</record> |
|||
|
|||
<record id="sale_order_line_11" model="sale.order.line"> |
|||
<field name="order_id" ref="sale_order_1"/> |
|||
<field name="product_id" ref="product.product_product_7"/> |
|||
<field name="product_uom_qty">5</field> |
|||
</record> |
|||
|
|||
<record id="sale_order_line_12" model="sale.order.line"> |
|||
<field name="order_id" ref="sale_order_1"/> |
|||
<field name="product_id" ref="product.product_product_9"/> |
|||
<field name="product_uom_qty">3</field> |
|||
</record> |
|||
|
|||
<workflow action="order_confirm" model="sale.order" ref="sale_order_1"/> |
|||
|
|||
<!-- Sale Order 2--> |
|||
<record id="sale_order_2" model="sale.order"> |
|||
<field name="partner_id" ref="base.res_partner_13"/> |
|||
<field name="order_policy">picking</field> |
|||
</record> |
|||
|
|||
<record id="sale_order_line_21" model="sale.order.line"> |
|||
<field name="order_id" ref="sale_order_2"/> |
|||
<field name="product_id" ref="product.product_product_7"/> |
|||
<field name="product_uom_qty">15</field> |
|||
<field name="discount">10</field> |
|||
</record> |
|||
|
|||
<record id="sale_order_line_22" model="sale.order.line"> |
|||
<field name="order_id" ref="sale_order_2"/> |
|||
<field name="product_id" ref="product.product_product_4"/> |
|||
<field name="product_uom_qty">1</field> |
|||
</record> |
|||
|
|||
<record id="sale_order_line_23" model="sale.order.line"> |
|||
<field name="order_id" ref="sale_order_2"/> |
|||
<field name="product_id" ref="product.product_product_24"/> |
|||
<field name="product_uom_qty">3</field> |
|||
<field name="price_unit">555</field> |
|||
</record> |
|||
|
|||
<workflow action="order_confirm" model="sale.order" ref="sale_order_2"/> |
|||
|
|||
</data></openerp> |
@ -0,0 +1,7 @@ |
|||
<openerp><data> |
|||
|
|||
<record id="stock.picking_type_out" model="stock.picking.type"> |
|||
<field name="available_in_pos" eval="True" /> |
|||
</record> |
|||
|
|||
</data></openerp> |
@ -0,0 +1,168 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * pos_order_to_sale_order |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: Odoo Server 8.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2018-01-06 10:02+0000\n" |
|||
"PO-Revision-Date: 2018-01-06 10:02+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_order_to_sale_order |
|||
#. openerp-web |
|||
#: code:addons/pos_order_to_sale_order/static/src/js/pos_order_to_sale_order.js:112 |
|||
#, python-format |
|||
msgid "Check your internet connection and try again." |
|||
msgstr "Veuillez vérifier votre connexion internet et essayer de nouveau." |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#. openerp-web |
|||
#: code:addons/pos_order_to_sale_order/static/src/js/pos_order_to_sale_order.js:33 |
|||
#, python-format |
|||
msgid "Create Confirmed Order" |
|||
msgstr "Créer une vente confirmée" |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#. openerp-web |
|||
#: code:addons/pos_order_to_sale_order/static/src/js/pos_order_to_sale_order.js:34 |
|||
#, python-format |
|||
msgid "Create Confirmed Sale Order and discard the current PoS Order?" |
|||
msgstr "Créer une vente confirmée, et supprimer le ticket de caisse en cours ?" |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#: field:pos.config,iface_create_confirmed_sale_order:0 |
|||
msgid "Create Confirmed Sale Orders" |
|||
msgstr "Créer des ventes confirmées" |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#. openerp-web |
|||
#: code:addons/pos_order_to_sale_order/static/src/js/pos_order_to_sale_order.js:38 |
|||
#, python-format |
|||
msgid "Create Delivered Order" |
|||
msgstr "Créer une vente livrée" |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#. openerp-web |
|||
#: code:addons/pos_order_to_sale_order/static/src/js/pos_order_to_sale_order.js:39 |
|||
#, python-format |
|||
msgid "Create Delivered Sale Order and discard the current PoS Order?" |
|||
msgstr "Créer une vente livrée, et supprimer le ticket de caisse en cours ?" |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#: field:pos.config,iface_create_delivered_sale_order:0 |
|||
msgid "Create Delivered Sale Orders" |
|||
msgstr "Créer des ventes livrées" |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#. openerp-web |
|||
#: code:addons/pos_order_to_sale_order/static/src/js/pos_order_to_sale_order.js:28 |
|||
#, python-format |
|||
msgid "Create Draft Order" |
|||
msgstr "Créer un devis en brouillon" |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#. openerp-web |
|||
#: code:addons/pos_order_to_sale_order/static/src/js/pos_order_to_sale_order.js:29 |
|||
#, python-format |
|||
msgid "Create Draft Sale Order and discard the current PoS Order?" |
|||
msgstr "Créer une vente en brouillon, et supprimer le ticket de caisse en cours ?" |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#: field:pos.config,iface_create_draft_sale_order:0 |
|||
msgid "Create Draft Sale Orders" |
|||
msgstr "Créer des ventes en brouillon" |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#. openerp-web |
|||
#: code:addons/pos_order_to_sale_order/static/src/js/pos_order_to_sale_order.js:52 |
|||
#, python-format |
|||
msgid "Empty Order" |
|||
msgstr "Commande vide" |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#: help:pos.config,iface_create_confirmed_sale_order:0 |
|||
msgid "If checked, the cashier will have the possibility to create a confirmed Sale Order, based on the current draft PoS Order." |
|||
msgstr "En cochant la case, le caissier aura la possibilité de créer une vente confirmée, à partir du ticket de caisse en cours." |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#: help:pos.config,iface_create_delivered_sale_order:0 |
|||
msgid "If checked, the cashier will have the possibility to create a confirmed sale Order, based on the current draft PoS Order.\n" |
|||
" the according picking will be marked as delivered. Only invoices process will be possible." |
|||
msgstr "En cochant la case, le caissier aura la possibilité de créer une vente confirmée, à partir du ticket de caisse en cours.\n" |
|||
" Le bon de livraison correspondant sera marqué comme livré. Seul le processus de facturation sera possible." |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#: help:pos.config,iface_create_draft_sale_order:0 |
|||
msgid "If checked, the cashier will have the possibility to create a draft Sale Order, based on the current draft PoS Order." |
|||
msgstr "En cochant la case, le caissier aura la possibilité de créer une vente en brouillon, à partir du ticket de caisse en cours." |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#. openerp-web |
|||
#: code:addons/pos_order_to_sale_order/static/src/js/pos_order_to_sale_order.js:60 |
|||
#, python-format |
|||
msgid "No customer defined" |
|||
msgstr "Pas de client défini" |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#: code:addons/pos_order_to_sale_order/models/sale_order.py:19 |
|||
#, python-format |
|||
msgid "Point of Sale %s" |
|||
msgstr "Point de vente %s" |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#: model:ir.model,name:pos_order_to_sale_order.model_sale_order |
|||
msgid "Sales Order" |
|||
msgstr "Commande de ventes" |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#. openerp-web |
|||
#: code:addons/pos_order_to_sale_order/static/src/js/pos_order_to_sale_order.js:111 |
|||
#, python-format |
|||
msgid "The order could not be sent" |
|||
msgstr "La commande n'a pas pu être envoyée" |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#. openerp-web |
|||
#: code:addons/pos_order_to_sale_order/static/src/js/pos_order_to_sale_order.js:53 |
|||
#, python-format |
|||
msgid "There must be at least one product in your order to create Sale Order." |
|||
msgstr "Il doit y avoir au moins un produit dans votre commande pour créer une vente" |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#. openerp-web |
|||
#: code:addons/pos_order_to_sale_order/static/src/js/pos_order_to_sale_order.js:35 |
|||
#, python-format |
|||
msgid "This operation will permanently discard the current PoS Order and create a confirmed Sale Order, based on the current order lines. Note if you have manually changed unit prices for some products, this changes will not been taken into account in the sale order, and should be done manually on the invoice again." |
|||
msgstr "Cette opération va supprimer définitivement le ticket de caisse en cours, et créer une vente confirmée, en se basant sur les lignes du ticket en cours. Remarque : si vous aviez changé le prix unitaire de certains produits, ces changements ne seront pas pris en compte dans la vente, et devront être refait manuellement sur la facture." |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#. openerp-web |
|||
#: code:addons/pos_order_to_sale_order/static/src/js/pos_order_to_sale_order.js:40 |
|||
#, python-format |
|||
msgid "This operation will permanently discard the current PoS Order and create a confirmed Sale Order, based on the current order lines. The according picking will be marked as delivered.\n" |
|||
" Note if you have manually changed unit prices for some products, this changes will not been taken into account in the sale order, and should be done manually on the invoice again." |
|||
msgstr "Cette opération va supprimer définitivement le ticket de caisse en cours, et créer une vente confirmée, en se basant sur les lignes du ticket en cours. Le bone de livraison correspondant sera marqué comme livré. \n" |
|||
"Remarque : si vous aviez changé le prix unitaire de certains produits, ces changements ne seront pas pris en compte dans la vente, et devront être refait manuellement sur la facture." |
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#. openerp-web |
|||
#: code:addons/pos_order_to_sale_order/static/src/js/pos_order_to_sale_order.js:30 |
|||
#, python-format |
|||
msgid "This operation will permanently discard the current PoS Order and create a draft Sale Order, based on the current order lines. Note if you have manually changed unit prices for some products, this changes will not been taken into account in the sale order." |
|||
msgstr "Cette opération va supprimer définitivement le ticket de caisse en cours, et créer une vente en brouillon, en se basant sur les lignes du ticket en cours. Remarque : si vous aviez changé le prix unitaire de certains produits, ces changements ne seront pas pris en compte dans la vente." |
|||
|
|||
|
|||
#. module: pos_order_to_sale_order |
|||
#. openerp-web |
|||
#: code:addons/pos_order_to_sale_order/static/src/js/pos_order_to_sale_order.js:61 |
|||
#, python-format |
|||
msgid "You should select a customer in order to create a Sale Order. Please select one by clicking the order tab." |
|||
msgstr "Vous devez sélectionner un client, afin de créer une vente. Veuillez en sélectionner un en cliquant sur l'onglet de la commande." |
|||
|
@ -0,0 +1,3 @@ |
|||
# -*- coding: utf-8 -*- |
|||
from . import sale_order |
|||
from . import pos_config |
@ -0,0 +1,27 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright (C) 2017 - Today: GRAP (http://www.grap.coop) |
|||
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from openerp import models, fields |
|||
|
|||
|
|||
class PosConfig(models.Model): |
|||
_inherit = 'pos.config' |
|||
|
|||
iface_create_draft_sale_order = fields.Boolean( |
|||
string='Create Draft Sale Orders', default=True, |
|||
help="If checked, the cashier will have the possibility to create" |
|||
" a draft Sale Order, based on the current draft PoS Order.") |
|||
|
|||
iface_create_confirmed_sale_order = fields.Boolean( |
|||
string='Create Confirmed Sale Orders', default=True, |
|||
help="If checked, the cashier will have the possibility to create" |
|||
" a confirmed Sale Order, based on the current draft PoS Order.") |
|||
|
|||
iface_create_delivered_sale_order = fields.Boolean( |
|||
string='Create Delivered Sale Orders', default=True, |
|||
help="If checked, the cashier will have the possibility to create" |
|||
" a confirmed sale Order, based on the current draft PoS Order.\n" |
|||
" the according picking will be marked as delivered. Only invoices" |
|||
" process will be possible.") |
@ -0,0 +1,60 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright (C) 2017 - Today: GRAP (http://www.grap.coop) |
|||
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from openerp import models, api, _ |
|||
|
|||
|
|||
class SaleOrder(models.Model): |
|||
_inherit = 'sale.order' |
|||
|
|||
@api.model |
|||
def _prepare_order_field_from_pos(self, order_data): |
|||
session_obj = self.env['pos.session'] |
|||
session = session_obj.browse(order_data['pos_session_id']) |
|||
res = self.onchange_partner_id(order_data['partner_id'])['value'] |
|||
res.update({ |
|||
'partner_id': order_data['partner_id'] or False, |
|||
'origin': _("Point of Sale %s") % (session.name), |
|||
'client_order_ref': order_data['name'], |
|||
'user_id': order_data['user_id'] or False, |
|||
'order_line': [], |
|||
}) |
|||
for line_data in order_data['lines']: |
|||
res['order_line'].append([ |
|||
0, False, self._prepare_order_line_field_from_pos( |
|||
line_data[2], res)]) |
|||
return res |
|||
|
|||
@api.model |
|||
def _prepare_order_line_field_from_pos(self, line_data, order_data): |
|||
line_obj = self.env['sale.order.line'] |
|||
res = line_obj.product_id_change( |
|||
order_data['pricelist_id'], line_data['product_id'], |
|||
qty=line_data['qty'], partner_id=order_data['partner_id'])['value'] |
|||
res.update({ |
|||
'product_id': line_data['product_id'], |
|||
'product_uom_qty': line_data['qty'], |
|||
'discount': line_data['discount'], |
|||
}) |
|||
return res |
|||
|
|||
@api.model |
|||
def create_order_from_pos(self, order_data): |
|||
# Create Draft Sale order |
|||
sale_order = self.create( |
|||
self._prepare_order_field_from_pos(order_data)) |
|||
|
|||
# Confirm Sale Order |
|||
if order_data['sale_order_state'] in ['confirmed', 'delivered']: |
|||
sale_order.action_button_confirm() |
|||
|
|||
# mark picking as delivered |
|||
if order_data['sale_order_state'] == 'delivered': |
|||
sale_order.picking_ids.force_assign() |
|||
sale_order.picking_ids.do_transfer() |
|||
|
|||
return { |
|||
'sale_order_id': sale_order.id, |
|||
} |
After Width: 180 | Height: 180 | Size: 19 KiB |
After Width: 841 | Height: 427 | Size: 38 KiB |
After Width: 513 | Height: 423 | Size: 28 KiB |
After Width: 420 | Height: 277 | Size: 20 KiB |
After Width: 415 | Height: 274 | Size: 21 KiB |
After Width: 422 | Height: 279 | Size: 20 KiB |
@ -0,0 +1,171 @@ |
|||
/****************************************************************************** |
|||
Copyright (C) 2017 - Today: GRAP (http://www.grap.coop)
|
|||
@author: Sylvain LE GAL (https://twitter.com/legalsylvain)
|
|||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|||
*****************************************************************************/ |
|||
|
|||
openerp.pos_order_to_sale_order = function(instance, local) { |
|||
|
|||
"use strict"; |
|||
|
|||
var module = instance.point_of_sale; |
|||
var _t = instance.web._t; |
|||
|
|||
/************************************************************************* |
|||
New Widget CreateSaleOrderButtonWidget: |
|||
* On click, check if there is a customer defined, |
|||
ask confirmation call server to create sale order, and delete |
|||
the current order. |
|||
*/ |
|||
module.CreateSaleOrderButtonWidget = module.PosBaseWidget.extend({ |
|||
template: 'CreateSaleOrderButtonWidget', |
|||
|
|||
init: function(parent, options){ |
|||
this._super(parent, options); |
|||
this.sale_order_state = options.sale_order_state; |
|||
if (this.sale_order_state == 'draft') { |
|||
this.display_text = _t("Create Draft Order"); |
|||
this.confirmation_message = _t('Create Draft Sale Order and discard the current PoS Order?'); |
|||
this.confirmation_comment = _t("This operation will permanently discard the current PoS Order and create a draft Sale Order, based on the current order lines. Note if you have manually changed unit prices for some products, this changes will not been taken into account in the sale order."); |
|||
} |
|||
else if (options.sale_order_state == 'confirmed') { |
|||
this.display_text = _t("Create Confirmed Order"); |
|||
this.confirmation_message = _t('Create Confirmed Sale Order and discard the current PoS Order?'); |
|||
this.confirmation_comment = _t("This operation will permanently discard the current PoS Order and create a confirmed Sale Order, based on the current order lines. Note if you have manually changed unit prices for some products, this changes will not been taken into account in the sale order, and should be done manually on the invoice again."); |
|||
} |
|||
else if (options.sale_order_state == 'delivered') { |
|||
this.display_text = _t("Create Delivered Order"); |
|||
this.confirmation_message = _t('Create Delivered Sale Order and discard the current PoS Order?'); |
|||
this.confirmation_comment = _t("This operation will permanently discard the current PoS Order and create a confirmed Sale Order, based on the current order lines. The according picking will be marked as delivered.\n Note if you have manually changed unit prices for some products, this changes will not been taken into account in the sale order, and should be done manually on the invoice again."); |
|||
} |
|||
}, |
|||
|
|||
renderElement: function() { |
|||
var self = this; |
|||
this._super(); |
|||
this.$el.click(function(){ |
|||
var current_order = self.pos.get('selectedOrder'); |
|||
// Prevent empty delivery order
|
|||
if (current_order.get('orderLines').length == 0){ |
|||
self.pos_widget.screen_selector.show_popup('error',{ |
|||
'message': _t('Empty Order'), |
|||
'comment': _t('There must be at least one product in your order to create Sale Order.'), |
|||
}); |
|||
return; |
|||
} |
|||
// Check Customer
|
|||
if (!current_order.get('client')){ |
|||
self.pos_widget.screen_selector.show_popup('error',{ |
|||
'message': _t('No customer defined'), |
|||
'comment': _t('You should select a customer in order to create a Sale Order. Please select one by clicking the order tab.'), |
|||
}); |
|||
return; |
|||
} |
|||
self.pos.pos_widget.screen_selector.show_popup('confirm', { |
|||
message: self.confirmation_message, |
|||
comment: self.confirmation_comment, |
|||
confirm: function(){ |
|||
var SaleOrderModel = new instance.web.Model('sale.order'); |
|||
current_order.sale_order_state = self.sale_order_state; |
|||
SaleOrderModel.call('create_order_from_pos', [self.prepare_create_sale_order(current_order)] |
|||
).then(function (result) { |
|||
self.hook_create_sale_order_success(result); |
|||
}).fail(function (error, event){ |
|||
self.hook_create_sale_order_error(error, event); |
|||
}); |
|||
|
|||
}, |
|||
}); |
|||
}); |
|||
}, |
|||
|
|||
// Overload This function to send custom sale order data to server
|
|||
prepare_create_sale_order: function(order) { |
|||
var res = order.export_as_JSON(); |
|||
res.sale_order_state = this.sale_order_state; |
|||
return res; |
|||
}, |
|||
|
|||
// Overload this function to make custom action after Sale order
|
|||
// Creation success
|
|||
hook_create_sale_order_success: function(result) { |
|||
this.pos.get('selectedOrder').destroy(); |
|||
}, |
|||
|
|||
// Overload this function to make custom action after Sale order
|
|||
// Creation fail
|
|||
hook_create_sale_order_error: function(error, event) { |
|||
event.preventDefault(); |
|||
if(error.code === 200 ){ |
|||
// Business Logic Error, not a connection problem
|
|||
this.pos_widget.screen_selector.show_popup('error-traceback',{ |
|||
message: error.data.message, |
|||
comment: error.data.debug, |
|||
}); |
|||
} |
|||
else{ |
|||
// connexion problem
|
|||
this.pos_widget.screen_selector.show_popup('error',{ |
|||
message: _t('The order could not be sent'), |
|||
comment: _t('Check your internet connection and try again.'), |
|||
}); |
|||
} |
|||
|
|||
}, |
|||
|
|||
}); |
|||
|
|||
|
|||
/************************************************************************* |
|||
Extend PosWidget: |
|||
* Create new buttons, depending of the configuration |
|||
*/ |
|||
module.PosWidget = module.PosWidget.extend({ |
|||
build_widgets: function() { |
|||
this._super(); |
|||
if (this.pos.config.iface_create_draft_sale_order){ |
|||
this.create_draft_sale_order_button = new module.CreateSaleOrderButtonWidget( |
|||
this, {'sale_order_state': 'draft'}); |
|||
this.create_draft_sale_order_button.appendTo(this.pos_widget.$('ul.orderlines')); |
|||
} |
|||
if (this.pos.config.iface_create_confirmed_sale_order){ |
|||
this.create_confirmed_sale_order_button = new module.CreateSaleOrderButtonWidget( |
|||
this, {'sale_order_state': 'confirmed'}); |
|||
this.create_confirmed_sale_order_button.appendTo(this.pos_widget.$('ul.orderlines')); |
|||
} |
|||
if (this.pos.config.iface_create_delivered_sale_order){ |
|||
this.create_delivered_sale_order_button = new module.CreateSaleOrderButtonWidget( |
|||
this, {'sale_order_state': 'delivered'}); |
|||
this.create_delivered_sale_order_button.appendTo(this.pos_widget.$('ul.orderlines')); |
|||
} |
|||
}, |
|||
}); |
|||
|
|||
|
|||
/************************************************************************* |
|||
Extend OrderWidget: |
|||
Overload renderElement, to display buttons when the order change. |
|||
*/ |
|||
module.OrderWidget = module.OrderWidget.extend({ |
|||
renderElement: function(scrollbottom){ |
|||
this._super(scrollbottom); |
|||
if (this.pos_widget.create_draft_sale_order_button) { |
|||
this.pos_widget.create_draft_sale_order_button.appendTo( |
|||
this.pos_widget.$('ul.orderlines') |
|||
); |
|||
} |
|||
if (this.pos_widget.create_confirmed_sale_order_button) { |
|||
this.pos_widget.create_confirmed_sale_order_button.appendTo( |
|||
this.pos_widget.$('ul.orderlines') |
|||
); |
|||
} |
|||
if (this.pos_widget.create_delivered_sale_order_button) { |
|||
this.pos_widget.create_delivered_sale_order_button.appendTo( |
|||
this.pos_widget.$('ul.orderlines') |
|||
); |
|||
} |
|||
|
|||
} |
|||
}); |
|||
|
|||
}; |
@ -0,0 +1,13 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<template> |
|||
|
|||
<t t-name="CreateSaleOrderButtonWidget"> |
|||
<br /> |
|||
<div style="text-align: center"> |
|||
<button class="input-button"> |
|||
<t t-esc="widget.display_text"/> |
|||
</button> |
|||
</div> |
|||
</t> |
|||
|
|||
</template> |
@ -0,0 +1,11 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
|
|||
<openerp><data> |
|||
|
|||
<template id="assets_backend" name="pos_order_to_sale_order assets" inherit_id="web.assets_backend"> |
|||
<xpath expr="." position="inside"> |
|||
<script type="text/javascript" src="/pos_order_to_sale_order/static/src/js/pos_order_to_sale_order.js"></script> |
|||
</xpath> |
|||
</template> |
|||
|
|||
</data></openerp> |
@ -0,0 +1,16 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp><data> |
|||
|
|||
<record id="view_pos_config_form" model="ir.ui.view"> |
|||
<field name="model">pos.config</field> |
|||
<field name="inherit_id" ref="point_of_sale.view_pos_config_form"/> |
|||
<field name="arch" type="xml"> |
|||
<field name="iface_invoicing" position="after"> |
|||
<field name="iface_create_draft_sale_order" /> |
|||
<field name="iface_create_confirmed_sale_order" /> |
|||
<field name="iface_create_delivered_sale_order" /> |
|||
</field> |
|||
</field> |
|||
</record> |
|||
|
|||
</data></openerp> |