[ADD] new module pos_picking_load (#183)
[ADD] new module pos_picking_loadpull/365/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> |