[ADD] new module pos_picking_load (#183)
[ADD] new module pos_picking_loadpull/190/head
-
178pos_picking_load/README.rst
-
2pos_picking_load/__init__.py
-
32pos_picking_load/__openerp__.py
-
19pos_picking_load/demo/product_template.xml
-
7pos_picking_load/demo/res_groups.xml
-
51pos_picking_load/demo/sale_order.xml
-
7pos_picking_load/demo/stock_picking_type.xml
-
196pos_picking_load/i18n/fr.po
-
6pos_picking_load/models/__init__.py
-
12pos_picking_load/models/pos_config.py
-
55pos_picking_load/models/pos_order.py
-
14pos_picking_load/models/sale_order.py
-
72pos_picking_load/models/stock_picking.py
-
15pos_picking_load/models/stock_picking_type.py
-
BINpos_picking_load/static/description/load_picking_01.png
-
BINpos_picking_load/static/description/load_picking_02.png
-
BINpos_picking_load/static/description/load_picking_03.png
-
BINpos_picking_load/static/description/load_picking_04.png
-
BINpos_picking_load/static/description/load_picking_05.png
-
BINpos_picking_load/static/description/load_picking_06.png
-
BINpos_picking_load/static/description/pos_config_form.png
-
BINpos_picking_load/static/description/stock_picking_type_form.png
-
40pos_picking_load/static/src/css/pos_picking_load.css
-
329pos_picking_load/static/src/js/pos_picking_load.js
-
85pos_picking_load/static/src/xml/pos_picking_load.xml
-
18pos_picking_load/views/pos_picking_load.xml
-
14pos_picking_load/views/view_pos_config.xml
-
14pos_picking_load/views/view_sale_order.xml
-
14pos_picking_load/views/view_stock_picking.xml
-
14pos_picking_load/views/view_stock_picking_type.xml
@ -0,0 +1,178 @@ |
|||
.. 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 Picking Load |
|||
================ |
|||
|
|||
|
|||
This module extends the functionality of point of sale to allow you to |
|||
load your pickings in the Point of Sale, in order to add / remove products |
|||
and so create a PoS Order and mark it as paid. |
|||
|
|||
Detailled Use Case |
|||
================== |
|||
|
|||
This module is usefull for the following use case |
|||
|
|||
* You have many Sale Orders that have generated pickings. Typically if you have |
|||
connected your Odoo instance to an online store like Shop Invader, |
|||
Prestashop, Magento, or if you use light Odoo shop (```website_sale``` |
|||
module). |
|||
* Once the order validated, you prepare your pickings |
|||
* The customer come in your shop to recover his order |
|||
* the customer add (or remove) some products |
|||
* the customer pay his order, based on the real delivered products list. |
|||
|
|||
Configuration |
|||
============= |
|||
|
|||
To configure this module, you need to: |
|||
|
|||
#. Go to Warehouse / Configuration / Types of Operation |
|||
#. Select the picking type(s) you want to see in the point of sale |
|||
#. Check the box 'Available in Point of Sale' |
|||
|
|||
.. figure:: static/description/stock_picking_type_form.png |
|||
:width: 800 px |
|||
|
|||
Note: This box is NOT enabled by default except in demo data for the type |
|||
'Delivery Orders' of the demo company 'YourCompany'. |
|||
|
|||
#. Go to Point of Sale / Configuration / Point of Sales |
|||
#. Select the Point(s) of Sales witch those you want to enable the feature |
|||
#. Check the box 'Load Pickings'. |
|||
|
|||
.. figure:: static/description/pos_config_form.png |
|||
:width: 800 px |
|||
|
|||
Note: This box is enabled by default |
|||
|
|||
Usage |
|||
===== |
|||
|
|||
To use this module, you need to: |
|||
|
|||
* Launch the point of sale |
|||
* On a new order (without lines), click on the 'Load Picking' button. |
|||
|
|||
.. figure:: static/description/load_picking_01.png |
|||
:width: 800 px |
|||
|
|||
* Point of sale will load available pickings. (About displayed pickings, see |
|||
'Technical Notes' below). |
|||
|
|||
.. figure:: static/description/load_picking_02.png |
|||
:width: 800 px |
|||
|
|||
* Click on a picking will display the content of the moves (as PoS Order Lines) |
|||
|
|||
.. figure:: static/description/load_picking_03.png |
|||
:width: 800 px |
|||
|
|||
The price and the discount will be the sale price and the discount set in |
|||
the according Sale Order Line, if it was found. Otherwise, discount will be to |
|||
0, and unit price will be the unit price of the product when it has been |
|||
loaded in the Point of Sale. |
|||
|
|||
**Related Sale Order:** |
|||
|
|||
.. figure:: static/description/load_picking_04.png |
|||
:width: 800 px |
|||
|
|||
**Related Picking:** |
|||
|
|||
.. figure:: static/description/load_picking_05.png |
|||
:width: 800 px |
|||
|
|||
* Confirm the selection, by clicking on 'Select' button. |
|||
|
|||
* Finally, you can add / remove products or change quantity and collect the |
|||
payment. |
|||
|
|||
When, the order is marked as paid, the original picking will be cancelled, |
|||
because Point Of Sale generates a new picking related to the real delivered |
|||
products and the original Sale Order will pass to the state 'Done'. (Delivery |
|||
exception is ignored). |
|||
(See 'Technical Notes' below). |
|||
|
|||
Some warning messages can appear: |
|||
|
|||
* if some products are not available in the Point of Sale. |
|||
|
|||
.. figure:: static/description/load_picking_06.png |
|||
:width: 800 px |
|||
|
|||
.. 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 |
|||
=============== |
|||
|
|||
* By default, the following filters are applied on the pickings displayed: |
|||
* 'State' should be 'Waiting Availability', 'Partially Available' or |
|||
'Ready to Transfer'. |
|||
* 'Invoice Control' should be 'To be invoiced'. |
|||
You can change this filter by overloading the ```_prepare_filter_for_pos``` |
|||
function of the model ```stock.picking``` |
|||
|
|||
* By default, original Picking is cancelled and the Sale order is set to the |
|||
state 'Done'. You can change this behaviour by overloading |
|||
```_handle_orders_with_original_picking``` function of the model |
|||
```pos.order```. |
|||
|
|||
Known issues / Roadmap |
|||
====================== |
|||
|
|||
* This module will try to get original unit price from the sale order and not |
|||
use the Current unit price of the product. (The price at which you pledged |
|||
to sell the product). |
|||
Some VAT troubles will occure if a product is set with VAT marked as |
|||
'VAT included' and if in the sale order line, there are some VAT marked as |
|||
'VAT excluded'. **The VAT settings should be consistent**. |
|||
|
|||
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 |
|||
======= |
|||
|
|||
Images |
|||
------ |
|||
|
|||
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_. |
|||
|
|||
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,32 @@ |
|||
# -*- 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 Picking Load', |
|||
'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/view_sale_order.xml', |
|||
'views/view_stock_picking.xml', |
|||
'views/view_stock_picking_type.xml', |
|||
'views/pos_picking_load.xml', |
|||
], |
|||
'demo': [ |
|||
'demo/res_groups.xml', |
|||
'demo/product_template.xml', |
|||
'demo/sale_order.xml', |
|||
'demo/stock_picking_type.xml', |
|||
], |
|||
'qweb': [ |
|||
'static/src/xml/pos_picking_load.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,196 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * pos_picking_load |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: Odoo Server 8.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2017-06-21 13:48+0000\n" |
|||
"PO-Revision-Date: 2017-06-21 13:48+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_load |
|||
#. openerp-web |
|||
#: code:addons/pos_picking_load/static/src/xml/pos_picking_load.xml:74 |
|||
#, python-format |
|||
msgid "--------------------------------" |
|||
msgstr "--------------------------------" |
|||
|
|||
#. module: pos_picking_load |
|||
#: field:stock.picking.type,available_in_pos:0 |
|||
msgid "Available in Point Of Sale" |
|||
msgstr "Disponible dans le point de vente" |
|||
|
|||
#. module: pos_picking_load |
|||
#. openerp-web |
|||
#: code:addons/pos_picking_load/static/src/js/pos_picking_load.js:264 |
|||
#: code:addons/pos_picking_load/static/src/js/pos_picking_load.js:290 |
|||
#, python-format |
|||
msgid "Can not execute this action because the POS is currently offline" |
|||
msgstr "Impossible de réaliser cette action car le point de vente est actuellement hors ligne" |
|||
|
|||
#. module: pos_picking_load |
|||
#. openerp-web |
|||
#: code:addons/pos_picking_load/static/src/xml/pos_picking_load.xml:22 |
|||
#, python-format |
|||
msgid "Cancel" |
|||
msgstr "Annuler" |
|||
|
|||
#. module: pos_picking_load |
|||
#. openerp-web |
|||
#: code:addons/pos_picking_load/static/src/js/pos_picking_load.js:263 |
|||
#: code:addons/pos_picking_load/static/src/js/pos_picking_load.js:289 |
|||
#, python-format |
|||
msgid "Connection error" |
|||
msgstr "Erreur de connexion" |
|||
|
|||
#. module: pos_picking_load |
|||
#. openerp-web |
|||
#: code:addons/pos_picking_load/static/src/xml/pos_picking_load.xml:54 |
|||
#, python-format |
|||
msgid "Customer" |
|||
msgstr "Client" |
|||
|
|||
#. module: pos_picking_load |
|||
#: field:sale.order,final_pos_order_id:0 |
|||
#: field:stock.picking,final_pos_order_id:0 |
|||
msgid "Final PoS Order" |
|||
msgstr "Commande Finale" |
|||
|
|||
#. module: pos_picking_load |
|||
#: help:stock.picking.type,available_in_pos:0 |
|||
msgid "If checked, associated pickings will be available in the point of sale, to be changed and paid in it" |
|||
msgstr "Si la case est cochée, toutes les bons de livraisons associés seront disponible dans le point de vente, pour ere changé et payé au sein de celui-ci" |
|||
|
|||
#. module: pos_picking_load |
|||
#. openerp-web |
|||
#: code:addons/pos_picking_load/static/src/xml/pos_picking_load.xml:5 |
|||
#, python-format |
|||
msgid "Load Picking" |
|||
msgstr "Charger un bon de livraison" |
|||
|
|||
#. module: pos_picking_load |
|||
#: field:pos.config,iface_load_picking:0 |
|||
msgid "Load Pickings" |
|||
msgstr "Charger des bons de livraison" |
|||
|
|||
#. module: pos_picking_load |
|||
#. openerp-web |
|||
#: code:addons/pos_picking_load/static/src/xml/pos_picking_load.xml:53 |
|||
#, python-format |
|||
msgid "Name" |
|||
msgstr "Nom" |
|||
|
|||
#. module: pos_picking_load |
|||
#: field:pos.order,origin_picking_id:0 |
|||
msgid "Origin Picking" |
|||
msgstr "Livraison d'origine" |
|||
|
|||
#. module: pos_picking_load |
|||
#. openerp-web |
|||
#: code:addons/pos_picking_load/static/src/xml/pos_picking_load.xml:75 |
|||
#: code:addons/pos_picking_load/static/src/xml/pos_picking_load.xml:83 |
|||
#, python-format |
|||
msgid "Origin Picking:" |
|||
msgstr "BL d'origine:" |
|||
|
|||
#. module: pos_picking_load |
|||
#: model:ir.model,name:pos_picking_load.model_stock_picking |
|||
msgid "Picking List" |
|||
msgstr "Bon de livraison" |
|||
|
|||
#. module: pos_picking_load |
|||
#: model:ir.model,name:pos_picking_load.model_pos_order |
|||
msgid "Point of Sale" |
|||
msgstr "Point de Vente" |
|||
|
|||
#. module: pos_picking_load |
|||
#: model:ir.model,name:pos_picking_load.model_sale_order |
|||
msgid "Sales Order" |
|||
msgstr "Commande de ventes" |
|||
|
|||
#. module: pos_picking_load |
|||
#. openerp-web |
|||
#: code:addons/pos_picking_load/static/src/xml/pos_picking_load.xml:55 |
|||
#, python-format |
|||
msgid "Scheduled Date" |
|||
msgstr "Date prévue" |
|||
|
|||
#. module: pos_picking_load |
|||
#. openerp-web |
|||
#: code:addons/pos_picking_load/static/src/xml/pos_picking_load.xml:30 |
|||
#, python-format |
|||
msgid "Search Picking" |
|||
msgstr "Chercher un bon de livraison" |
|||
|
|||
#. module: pos_picking_load |
|||
#. openerp-web |
|||
#: code:addons/pos_picking_load/static/src/xml/pos_picking_load.xml:26 |
|||
#, python-format |
|||
msgid "Select" |
|||
msgstr "Sélectionner" |
|||
|
|||
#. module: pos_picking_load |
|||
#. openerp-web |
|||
#: code:addons/pos_picking_load/static/src/xml/pos_picking_load.xml:56 |
|||
#, python-format |
|||
msgid "Source Document" |
|||
msgstr "Document d'origine" |
|||
|
|||
#. module: pos_picking_load |
|||
#: model:ir.model,name:pos_picking_load.model_stock_picking_type |
|||
msgid "The picking type determines the picking view" |
|||
msgstr "Le type de préparation détermine la vue de préparation" |
|||
|
|||
#. module: pos_picking_load |
|||
#: help:sale.order,final_pos_order_id:0 |
|||
msgid "This Sale Order has beend replaced by this PoS Order" |
|||
msgstr "Ce bon de commande a été remplacé par cette commande via le point de vente" |
|||
|
|||
#. module: pos_picking_load |
|||
#: help:stock.picking,final_pos_order_id:0 |
|||
msgid "This picking has been canceled, because it has been replaced by this PoS Order" |
|||
msgstr "Ce bon de livraison a été annulé, car il a été remplacé par cette commande via le point de vente" |
|||
|
|||
#. module: pos_picking_load |
|||
#. openerp-web |
|||
#: code:addons/pos_picking_load/static/src/js/pos_picking_load.js:228 |
|||
#, python-format |
|||
msgid "Unable to load some picking lines because the products are not available in the POS cache.\n" |
|||
"\n" |
|||
"Please check that lines :\n" |
|||
"\n" |
|||
" * " |
|||
msgstr "Impossible de charger certaines lignes du bon de livraison car certains produits ne sont pas disponibles dans le point de vente.\n" |
|||
"\n" |
|||
"Merci de vérifier les lignes suivantes :\n" |
|||
"\n" |
|||
" * " |
|||
|
|||
#. module: pos_picking_load |
|||
#. openerp-web |
|||
#: code:addons/pos_picking_load/static/src/js/pos_picking_load.js:239 |
|||
#, python-format |
|||
msgid "Unable to load this picking because the partner is not known in the Point Of Sale as a customer" |
|||
msgstr "Impossible de charger ce bon de livraison car ce partenaire n'est pas reconnu dans le point de vente comme un client" |
|||
|
|||
#. module: pos_picking_load |
|||
#. openerp-web |
|||
#: code:addons/pos_picking_load/static/src/js/pos_picking_load.js:238 |
|||
#, python-format |
|||
msgid "Unknown Partner" |
|||
msgstr "Partenaire inconnu" |
|||
|
|||
#. module: pos_picking_load |
|||
#. openerp-web |
|||
#: code:addons/pos_picking_load/static/src/js/pos_picking_load.js:227 |
|||
#, python-format |
|||
msgid "Unknown Products" |
|||
msgstr "Produits inconnus" |
|||
|
@ -0,0 +1,6 @@ |
|||
# -*- coding: utf-8 -*- |
|||
from . import sale_order |
|||
from . import stock_picking |
|||
from . import stock_picking_type |
|||
from . import pos_config |
|||
from . import pos_order |
@ -0,0 +1,12 @@ |
|||
# -*- 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_load_picking = fields.Boolean(string='Load Pickings', default=True) |
@ -0,0 +1,55 @@ |
|||
# -*- 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, fields |
|||
|
|||
|
|||
class PosOrder(models.Model): |
|||
_inherit = 'pos.order' |
|||
|
|||
# Field Section |
|||
origin_picking_id = fields.Many2one( |
|||
string='Origin Picking', comodel_name='stock.picking', |
|||
readonly=True) |
|||
|
|||
# Overloadable Section |
|||
@api.multi |
|||
def _handle_orders_with_original_picking(self): |
|||
"""By default, the module cancel original stock picking and sale |
|||
order. Overload / Overwrite this function if you want another |
|||
behaviour""" |
|||
sale_order_obj = self.env['sale.order'] |
|||
for order in self: |
|||
# Cancel Picking |
|||
order.origin_picking_id.action_cancel() |
|||
order.origin_picking_id.write({'final_pos_order_id': order.id}) |
|||
|
|||
# Ignore Delivery exception of the Sale Order |
|||
sale_orders = sale_order_obj.search([ |
|||
('procurement_group_id', '=', |
|||
order.origin_picking_id.group_id.id)]) |
|||
# sale_orders.action_ignore_delivery_exception() |
|||
sale_orders.signal_workflow('ship_corrected') |
|||
sale_orders.write({'final_pos_order_id': order.id}) |
|||
|
|||
# Overload Section |
|||
@api.model |
|||
def create_from_ui(self, orders): |
|||
"""Cancel the original picking, when the pos order is done""" |
|||
res = super(PosOrder, self).create_from_ui(orders) |
|||
orders_with_original_picking = self.search([ |
|||
('id', 'in', res), ('origin_picking_id', '!=', False), |
|||
('state', 'not in', [('draft')])]) |
|||
|
|||
orders_with_original_picking._handle_orders_with_original_picking() |
|||
|
|||
return res |
|||
|
|||
@api.model |
|||
def _order_fields(self, ui_order): |
|||
res = super(PosOrder, self)._order_fields(ui_order) |
|||
if 'origin_picking_id' in ui_order: |
|||
res['origin_picking_id'] = ui_order['origin_picking_id'] |
|||
return res |
@ -0,0 +1,14 @@ |
|||
# -*- 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 SaleOrder(models.Model): |
|||
_inherit = 'sale.order' |
|||
|
|||
final_pos_order_id = fields.Many2one( |
|||
string='Final PoS Order', comodel_name='pos.order', readonly=True, |
|||
help="This Sale Order has beend replaced by this PoS Order") |
@ -0,0 +1,72 @@ |
|||
# -*- 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, fields |
|||
|
|||
|
|||
class StockPicking(models.Model): |
|||
_inherit = 'stock.picking' |
|||
|
|||
# Field Section |
|||
final_pos_order_id = fields.Many2one( |
|||
string='Final PoS Order', comodel_name='pos.order', readonly=True, |
|||
help="This picking has been canceled, because it has been replaced by" |
|||
" this PoS Order") |
|||
|
|||
# Custom Section |
|||
@api.model |
|||
def _prepare_filter_for_pos(self): |
|||
return [ |
|||
('state', 'in', ['confirmed', 'partially_available', 'assigned']), |
|||
('invoice_state', '=', '2binvoiced'), |
|||
] |
|||
|
|||
@api.model |
|||
def _prepare_fields_for_pos_list(self): |
|||
return ['name', 'partner_id', 'min_date', 'origin'] |
|||
|
|||
@api.model |
|||
def search_pickings_for_pos(self, query): |
|||
# Get Picking Types available for PoS |
|||
picking_type_obj = self.env['stock.picking.type'] |
|||
picking_types = picking_type_obj.search( |
|||
[('available_in_pos', '=', True)]) |
|||
condition = self._prepare_filter_for_pos() + [ |
|||
('picking_type_id', 'in', picking_types.ids), |
|||
'|', '|', |
|||
('name', 'ilike', query), |
|||
('origin', 'ilike', query), |
|||
('partner_id', 'ilike', query) |
|||
] |
|||
fields = self._prepare_fields_for_pos_list() |
|||
return self.search_read(condition, fields, limit=10) |
|||
|
|||
@api.model |
|||
def _prepare_pos_order(self, picking): |
|||
pickinglines = [] |
|||
for line in picking.move_lines.filtered(lambda x: x.state != 'cancel'): |
|||
picking_line = { |
|||
'name': line.name, |
|||
'product_id': line.product_id.id, |
|||
'quantity': line.product_uom_qty, |
|||
} |
|||
sale_order_line =\ |
|||
line.procurement_id and line.procurement_id.sale_line_id |
|||
if sale_order_line: |
|||
# Get price and discount of the order if available |
|||
picking_line['price_unit'] = sale_order_line.price_unit |
|||
picking_line['discount'] = sale_order_line.discount |
|||
pickinglines.append(picking_line) |
|||
return { |
|||
'id': picking.id, |
|||
'name': picking.name, |
|||
'partner_id': picking.partner_id.id, |
|||
'line_ids': pickinglines, |
|||
} |
|||
|
|||
@api.model |
|||
def load_picking_for_pos(self, picking_id): |
|||
picking = self.browse(picking_id) |
|||
return self._prepare_pos_order(picking) |
@ -0,0 +1,15 @@ |
|||
# -*- 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 StockPickingType(models.Model): |
|||
_inherit = 'stock.picking.type' |
|||
|
|||
available_in_pos = fields.Boolean( |
|||
string='Available in Point Of Sale', help="If checked, associated" |
|||
" pickings will be available in the point of sale, to be changed and" |
|||
" paid in it") |
After Width: 421 | Height: 205 | Size: 8.9 KiB |
After Width: 855 | Height: 222 | Size: 26 KiB |
After Width: 415 | Height: 306 | Size: 26 KiB |
After Width: 837 | Height: 495 | Size: 43 KiB |
After Width: 839 | Height: 298 | Size: 33 KiB |
After Width: 511 | Height: 426 | Size: 14 KiB |
After Width: 637 | Height: 160 | Size: 12 KiB |
After Width: 785 | Height: 251 | Size: 31 KiB |
@ -0,0 +1,40 @@ |
|||
.pos .pickinglist-screen .button.picking-button { |
|||
width: 150px; |
|||
} |
|||
|
|||
.pos .pickinglist-screen .button.cancel { |
|||
margin-left: -180px; |
|||
} |
|||
|
|||
.pos .pickinglist-screen .picking-list{ |
|||
font-size: 16px; |
|||
width: 100%; |
|||
line-height: 40px; |
|||
} |
|||
|
|||
.pos .pickinglist-screen .picking-list th, |
|||
.pos .pickinglist-screen .picking-list td { |
|||
padding: 0px 8px; |
|||
} |
|||
|
|||
.pos .pickinglist-screen .picking-list tbody > tr{ |
|||
background: rgb(230,230,230); |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.pos .pickinglist-screen .picking-list thead > tr, |
|||
.pos .pickinglist-screen .picking-list tr:nth-child(even) { |
|||
background: rgb(247,247,247); |
|||
} |
|||
|
|||
.pos .pickinglist-screen .picking-list tbody > tr:hover { |
|||
background: rgb(220,220,220); |
|||
} |
|||
|
|||
.pos .pickinglist-screen .searchbox{ |
|||
margin-top:8px; |
|||
} |
|||
|
|||
.pos .pickinglist-screen .searchbox input{ |
|||
width: 150px; |
|||
} |
@ -0,0 +1,329 @@ |
|||
/****************************************************************************** |
|||
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_picking_load = function(instance, local) { |
|||
|
|||
|
|||
module = instance.point_of_sale; |
|||
var QWeb = instance.web.qweb; |
|||
var _t = instance.web._t; |
|||
var round_pr = instance.web.round_precision; |
|||
|
|||
/************************************************************************* |
|||
Extend Model Order: |
|||
* Add getter and setter function for field 'origin_picking_id'; |
|||
*/ |
|||
var moduleOrderParent = module.Order; |
|||
module.Order = module.Order.extend({ |
|||
|
|||
set_origin_picking_id: function(id) { |
|||
this.set({ |
|||
origin_picking_id: id, |
|||
}); |
|||
}, |
|||
|
|||
set_origin_picking_name: function(name) { |
|||
this.set({ |
|||
origin_picking_name: name, |
|||
}); |
|||
}, |
|||
|
|||
export_for_printing: function(attributes){ |
|||
var order = moduleOrderParent.prototype.export_for_printing.apply(this, arguments); |
|||
order['origin_picking_name'] = this.get('origin_picking_name'); |
|||
return order; |
|||
}, |
|||
|
|||
export_as_JSON: function() { |
|||
var order = moduleOrderParent.prototype.export_as_JSON.apply(this, arguments); |
|||
order['origin_picking_id'] = this.get('origin_picking_id'); |
|||
return order; |
|||
}, |
|||
|
|||
}); |
|||
|
|||
|
|||
/************************************************************************* |
|||
New Widget LoadPickingButtonWidget: |
|||
* On click, display a new screen to select a picking; |
|||
*/ |
|||
module.LoadPickingButtonWidget = module.PosBaseWidget.extend({ |
|||
template: 'LoadPickingButtonWidget', |
|||
|
|||
renderElement: function() { |
|||
var self = this; |
|||
this._super(); |
|||
this.$el.click(function(){ |
|||
var ss = self.pos.pos_widget.screen_selector; |
|||
ss.set_current_screen('pickinglist'); |
|||
}); |
|||
}, |
|||
}); |
|||
|
|||
|
|||
/************************************************************************* |
|||
Extend PosWidget: |
|||
* Create new screen; |
|||
* Add load and save button; |
|||
*/ |
|||
module.PosWidget = module.PosWidget.extend({ |
|||
build_widgets: function() { |
|||
this._super(); |
|||
|
|||
if (this.pos.config.iface_load_picking){ |
|||
// New Screen to select a picking
|
|||
this.pickinglist_screen = new module.PickingListScreenWidget(this, {}); |
|||
this.pickinglist_screen.appendTo(this.$('.screens')); |
|||
this.pickinglist_screen.hide(); |
|||
this.screen_selector.screen_set.pickinglist = this.pickinglist_screen; |
|||
|
|||
// Add button
|
|||
this.search_picking_button = new module.LoadPickingButtonWidget(this,{}); |
|||
this.search_picking_button.appendTo(this.pos_widget.$('li.orderline.empty')); |
|||
} |
|||
}, |
|||
}); |
|||
|
|||
|
|||
/************************************************************************* |
|||
Extend OrderWidget: |
|||
*/ |
|||
module.OrderWidget = module.OrderWidget.extend({ |
|||
renderElement: function(scrollbottom){ |
|||
this._super(scrollbottom); |
|||
if (this.pos_widget.search_picking_button) { |
|||
this.pos_widget.search_picking_button.appendTo( |
|||
this.pos_widget.$('li.orderline.empty') |
|||
); |
|||
} |
|||
} |
|||
}); |
|||
|
|||
|
|||
/************************************************************************* |
|||
New ScreenWidget PickingListScreenWidget: |
|||
* On show, display all pickings; |
|||
* on click on a picking, display the content; |
|||
* on click on 'validate', allow to use this picking; |
|||
* on click on 'cancel', display the preview screen; |
|||
*/ |
|||
module.PickingListScreenWidget = module.ScreenWidget.extend({ |
|||
template: 'PickingListScreenWidget', |
|||
show_leftpane: true, |
|||
model: 'stock.picking', |
|||
current_picking_id: false, |
|||
current_picking_name: false, |
|||
|
|||
// Base functions
|
|||
init: function(parent, options){ |
|||
this._super(parent, options); |
|||
}, |
|||
|
|||
start: function() { |
|||
var self = this; |
|||
this._super(); |
|||
|
|||
// Bind click buttons
|
|||
this.$el.find('span.button.cancel').click(_.bind(this.clickCancelButton, this)); |
|||
this.$el.find('span.button.validate').click(_.bind(this.clickValidateButton, this)); |
|||
|
|||
// manage Search Box
|
|||
var search_timeout = null; |
|||
this.$('.searchbox input').on('keyup',function(event){ |
|||
clearTimeout(search_timeout); |
|||
var query = this.value; |
|||
search_timeout = setTimeout(function(){ |
|||
self.perform_search(query); |
|||
},70); |
|||
}); |
|||
|
|||
this.$('.searchbox .search-clear').click(function(){ |
|||
self.clear_search(); |
|||
}); |
|||
}, |
|||
|
|||
show: function() { |
|||
this._super(); |
|||
var ss = this.pos.pos_widget.screen_selector; |
|||
this.pos_widget.numpad.hide(); |
|||
this.pos_widget.paypad.hide(); |
|||
this.search_pickings(); |
|||
this.$el.find('span.button.validate').hide(); |
|||
}, |
|||
|
|||
prepare_order: function(order, picking) { |
|||
var partner = this.pos.db.get_partner_by_id(picking.partner_id); |
|||
order.set_client(partner || undefined); |
|||
return order; |
|||
}, |
|||
|
|||
prepare_orderline: function(product, pickingline) { |
|||
return { |
|||
quantity: pickingline.qty, |
|||
price: pickingline.price_unit || product.price, |
|||
discount: pickingline.discount || 0.0, |
|||
}; |
|||
}, |
|||
|
|||
// User Event
|
|||
clickCancelButton: function(event) { |
|||
order = this.pos.get('selectedOrder'); |
|||
order.set_client(undefined); |
|||
order.set_origin_picking_id(undefined); |
|||
order.set_origin_picking_name(undefined); |
|||
order.get('orderLines').reset(); |
|||
this.pos_widget.order_widget.change_selected_order(); |
|||
var ss = this.pos.pos_widget.screen_selector; |
|||
ss.set_current_screen('products'); |
|||
this.pos_widget.numpad.show(); |
|||
this.pos_widget.paypad.show(); |
|||
}, |
|||
|
|||
clickValidateButton: function(event) { |
|||
order = this.pos.get('selectedOrder'); |
|||
order.set_origin_picking_id(this.current_picking_id); |
|||
order.set_origin_picking_name(this.current_picking_name); |
|||
var ss = this.pos.pos_widget.screen_selector; |
|||
ss.set_current_screen('products'); |
|||
this.pos_widget.numpad.show(); |
|||
this.pos_widget.paypad.show(); |
|||
}, |
|||
|
|||
load_picking: function(origin_picking_id) { |
|||
var self = this; |
|||
var pickingModel = new instance.web.Model(this.model); |
|||
return pickingModel.call('load_picking_for_pos', [origin_picking_id]) |
|||
.then(function (picking) { |
|||
self.current_picking_id = origin_picking_id; |
|||
self.current_picking_name = picking.name; |
|||
var picking_selectable = true; |
|||
var order = self.pos.get('selectedOrder'); |
|||
order = self.prepare_order(order, picking); |
|||
order.get('orderLines').reset(); |
|||
var pickinglines = picking.line_ids || []; |
|||
var unknown_products = []; |
|||
for (var i=0, len=pickinglines.length; i<len; i++) { |
|||
// check if product are available in pos
|
|||
var pickingline = pickinglines[i]; |
|||
var line_name = pickingline.name; |
|||
var product = self.pos.db.get_product_by_id(pickingline.product_id); |
|||
if (_.isUndefined(product)) { |
|||
unknown_products.push(line_name); |
|||
continue; |
|||
} |
|||
// Create new line and add it to the current order
|
|||
orderline = self.prepare_orderline(product, pickingline); |
|||
order.addProduct(product, orderline); |
|||
last_orderline = order.getLastOrderline(); |
|||
last_orderline = jQuery.extend(last_orderline, orderline); |
|||
} |
|||
// Forbid POS Order loading if some products are unknown
|
|||
if (unknown_products.length > 0){ |
|||
self.pos_widget.screen_selector.show_popup( |
|||
'error-traceback', { |
|||
message: _t('Unknown Products'), |
|||
comment: _t('Unable to load some picking lines because the ' + |
|||
'products are not available in the POS cache.\n\n' + |
|||
'Please check that lines :\n\n * ') + unknown_products.join("; \n *") |
|||
}); |
|||
picking_selectable = false; |
|||
} |
|||
// Check if the partner is unknown
|
|||
if (_.isUndefined(order.get_client)) { |
|||
self.pos_widget.screen_selector.show_popup( |
|||
'error-traceback', { |
|||
message: _t('Unknown Partner'), |
|||
comment: _t('Unable to load this picking because the partner' + |
|||
' is not known in the Point Of Sale as a customer') |
|||
}); |
|||
picking_selectable = false; |
|||
} |
|||
|
|||
if (picking_selectable){ |
|||
self.$el.find('span.button.validate').show(); |
|||
} |
|||
else{ |
|||
self.$el.find('span.button.validate').hide(); |
|||
} |
|||
|
|||
}).fail(function (error, event){ |
|||
if (parseInt(error.code) === 200) { |
|||
// Business Logic Error, not a connection problem
|
|||
self.pos_widget.screen_selector.show_popup( |
|||
'error-traceback', { |
|||
message: error.data.message, |
|||
comment: error.data.debug |
|||
}); |
|||
} |
|||
else{ |
|||
self.pos_widget.screen_selector.show_popup('error',{ |
|||
message: _t('Connection error'), |
|||
comment: _t('Can not execute this action because the POS is currently offline'), |
|||
}); |
|||
} |
|||
event.preventDefault(); |
|||
}); |
|||
}, |
|||
|
|||
search_pickings: function(query) { |
|||
var self = this; |
|||
var pickingModel = new instance.web.Model(this.model); |
|||
return pickingModel.call('search_pickings_for_pos', [query || '']) |
|||
.then(function (result) { |
|||
self.render_list(result); |
|||
}).fail(function (error, event){ |
|||
if (parseInt(error.code) === 200) { |
|||
// Business Logic Error, not a connection problem
|
|||
self.pos_widget.screen_selector.show_popup( |
|||
'error-traceback', { |
|||
message: error.data.message, |
|||
comment: error.data.debug |
|||
} |
|||
); |
|||
} |
|||
else{ |
|||
self.pos_widget.screen_selector.show_popup('error',{ |
|||
message: _t('Connection error'), |
|||
comment: _t('Can not execute this action because the POS is currently offline'), |
|||
}); |
|||
} |
|||
event.preventDefault(); |
|||
}); |
|||
}, |
|||
|
|||
on_click_picking: function(event){ |
|||
this.load_picking(parseInt(event.target.parentNode.dataset.pickingId, 10)); |
|||
}, |
|||
|
|||
render_list: function(pickings){ |
|||
var self = this; |
|||
var contents = this.$el[0].querySelector('.picking-list-contents'); |
|||
contents.innerHTML = ""; |
|||
var line_list = document.createDocumentFragment(); |
|||
_.each(pickings, function(picking){ |
|||
var picking_line_html = QWeb.render('LoadPickingLine',{widget: this, picking:picking}); |
|||
var picking_line = document.createElement('tbody'); |
|||
picking_line.innerHTML = picking_line_html; |
|||
picking_line = picking_line.childNodes[1]; |
|||
picking_line.addEventListener('click', self.on_click_picking); |
|||
line_list.appendChild(picking_line); |
|||
}); |
|||
contents.appendChild(line_list); |
|||
}, |
|||
|
|||
perform_search: function(query){ |
|||
this.search_pickings(query); |
|||
}, |
|||
|
|||
clear_search: function(){ |
|||
this.search_pickings(); |
|||
this.$('.searchbox input')[0].value = ''; |
|||
this.$('.searchbox input').focus(); |
|||
}, |
|||
|
|||
}); |
|||
|
|||
}; |
@ -0,0 +1,85 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<template> |
|||
|
|||
<t t-name="LoadPickingButtonWidget"> |
|||
<br/><button class="input-button">Load Picking</button> |
|||
</t> |
|||
|
|||
<t t-name="LoadPickingLine"> |
|||
<tr class="picking-line" t-att-data-picking-id="picking.id"> |
|||
<td><t t-esc="picking.name"/></td> |
|||
<td><t t-esc="picking.partner_id[1]"/></td> |
|||
<td><t t-esc="picking.min_date"/></td> |
|||
<td><t t-esc="picking.origin"/></td> |
|||
</tr> |
|||
</t> |
|||
|
|||
<t t-name="PickingListScreenWidget"> |
|||
<div class="pickinglist-screen screen"> |
|||
<div class="screen-content"> |
|||
<section class="top-content"> |
|||
<span class="button cancel picking-button"> |
|||
<i class="fa fa-times"></i> |
|||
Cancel |
|||
</span> |
|||
<span class="button validate picking-button"> |
|||
<i class="fa fa-arrow-circle-o-left"></i> |
|||
Select |
|||
</span> |
|||
<span class="searchbox"> |
|||
<input placeholder="Search Picking" /> |
|||
<span class="search-clear"></span> |
|||
</span> |
|||
<span class="searchbox"></span> |
|||
</section> |
|||
<section class="full-content"> |
|||
<div class="window"> |
|||
<section class="subwindow collapsed"> |
|||
<div class="subwindow-container"> |
|||
<div class="subwindow-container-fix"> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
<section class="subwindow"> |
|||
<div class="subwindow-container"> |
|||
<div class="subwindow-container-fix touch-scrollable scrollable-y"> |
|||
<table class="picking-list"> |
|||
<thead> |
|||
<tr> |
|||
<th>Name</th> |
|||
<th>Customer</th> |
|||
<th>Scheduled Date</th> |
|||
<th>Source Document</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody class="picking-list-contents"> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
</div> |
|||
</section> |
|||
</div> |
|||
</div> |
|||
</t> |
|||
|
|||
<t t-extend="XmlReceipt"> |
|||
<t t-jquery="[t-if='receipt.cashier']" t-operation="after"> |
|||
<t t-if="receipt.origin_picking_name"> |
|||
<div>--------------------------------</div> |
|||
<div>Origin Picking: <t t-esc='receipt.origin_picking_name' /></div> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
|
|||
<t t-extend="PosTicket"> |
|||
<t t-jquery="[t-esc='widget.pos.shop.name']" t-operation="after"> |
|||
<t t-if="order.get('origin_picking_name')"> |
|||
<br /><br />Origin Picking: <t t-esc="order.get('origin_picking_name')"/> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
|
|||
|
|||
</template> |
@ -0,0 +1,18 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- vim:fdn=3: |
|||
--> |
|||
<openerp> |
|||
<data> |
|||
<template id="assets_backend" name="pos_picking_load assets" inherit_id="web.assets_backend"> |
|||
<xpath expr="." position="inside"> |
|||
<script type="text/javascript" src="/pos_picking_load/static/src/js/pos_picking_load.js"></script> |
|||
</xpath> |
|||
</template> |
|||
<template id="index_pos_picking_load" name="POS Index Picking Load" inherit_id="point_of_sale.index"> |
|||
<xpath expr="//head" position="inside"> |
|||
<link rel="stylesheet" href="/pos_picking_load/static/src/css/pos_picking_load.css"/> |
|||
</xpath> |
|||
</template> |
|||
</data> |
|||
</openerp> |
|||
|
@ -0,0 +1,14 @@ |
|||
<?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_load_picking" /> |
|||
</field> |
|||
</field> |
|||
</record> |
|||
|
|||
</data></openerp> |
@ -0,0 +1,14 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp><data> |
|||
|
|||
<record id="view_sale_order_form" model="ir.ui.view"> |
|||
<field name="model">sale.order</field> |
|||
<field name="inherit_id" ref="sale_stock.view_order_form_inherit"/> |
|||
<field name="arch" type="xml"> |
|||
<field name="picking_policy" position="before"> |
|||
<field name="final_pos_order_id" /> |
|||
</field> |
|||
</field> |
|||
</record> |
|||
|
|||
</data></openerp> |
@ -0,0 +1,14 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp><data> |
|||
|
|||
<record id="view_stock_picking_form" model="ir.ui.view"> |
|||
<field name="model">stock.picking</field> |
|||
<field name="inherit_id" ref="stock_account.view_picking_inherit_form2"/> |
|||
<field name="arch" type="xml"> |
|||
<field name="invoice_state" position="after"> |
|||
<field name="final_pos_order_id" /> |
|||
</field> |
|||
</field> |
|||
</record> |
|||
|
|||
</data></openerp> |
@ -0,0 +1,14 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp><data> |
|||
|
|||
<record id="view_stock_picking_type_form" model="ir.ui.view"> |
|||
<field name="model">stock.picking.type</field> |
|||
<field name="inherit_id" ref="stock.view_picking_type_form"/> |
|||
<field name="arch" type="xml"> |
|||
<field name="return_picking_type_id" position="after"> |
|||
<field name="available_in_pos" /> |
|||
</field> |
|||
</field> |
|||
</record> |
|||
|
|||
</data></openerp> |