diff --git a/pos_place/README.rst b/pos_place/README.rst new file mode 100644 index 00000000..b97c0917 --- /dev/null +++ b/pos_place/README.rst @@ -0,0 +1,4 @@ +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! diff --git a/pos_place/__init__.py b/pos_place/__init__.py new file mode 100644 index 00000000..bf588bc8 --- /dev/null +++ b/pos_place/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import report diff --git a/pos_place/__manifest__.py b/pos_place/__manifest__.py new file mode 100644 index 00000000..348258e0 --- /dev/null +++ b/pos_place/__manifest__.py @@ -0,0 +1,36 @@ +# Copyright (C) 2014 - 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': 'Point of Sale - Places', + 'summary': "Define places on PoS orders", + 'version': '12.0.1.0.0', + 'category': 'Point of Sale', + 'author': 'GRAP,Odoo Community Association (OCA)', + 'website': 'http://www.github.com/OCA/pos', + 'license': 'AGPL-3', + 'depends': [ + 'point_of_sale', + ], + 'data': [ + 'security/ir_module_category.xml', + 'security/ir_rule.xml', + 'security/res_groups.xml', + 'security/ir.model.access.csv', + 'views/templates.xml', + 'views/view_pos_place.xml', + 'views/view_pos_order.xml', + ], + 'qweb': [ + 'static/src/xml/pos_place.xml', + ], + 'demo': [ + 'demo/res_groups.xml', + 'demo/pos_place.xml', + ], + 'images': [ + 'static/description/pos_front_end_ui.png', + 'static/description/pos_config_form.png', + 'static/description/pos_order_search.png', + ], +} diff --git a/pos_place/demo/pos_place.xml b/pos_place/demo/pos_place.xml new file mode 100644 index 00000000..b4550d78 --- /dev/null +++ b/pos_place/demo/pos_place.xml @@ -0,0 +1,25 @@ + + + + + + MUL + La Mulatière (69350 - France) + + + + OBS + Montée de L'observance (69009 - France) + + + + GAR + Gare de Francheville (69340 - France) + + + + diff --git a/pos_place/demo/res_groups.xml b/pos_place/demo/res_groups.xml new file mode 100644 index 00000000..6e3c992b --- /dev/null +++ b/pos_place/demo/res_groups.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + diff --git a/pos_place/i18n/fr.po b/pos_place/i18n/fr.po new file mode 100644 index 00000000..fa1b5934 --- /dev/null +++ b/pos_place/i18n/fr.po @@ -0,0 +1,149 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_place +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-07-31 15:58+0000\n" +"PO-Revision-Date: 2019-07-31 15:58+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_place +#: model:ir.model.fields,field_description:pos_place.field_pos_place__active +msgid "Active" +msgstr "Actif" + +#. module: pos_place +#: model:ir.model.fields,field_description:pos_place.field_pos_place__code +#: model_terms:ir.ui.view,arch_db:pos_place.view_pos_place_form +msgid "Code" +msgstr "" + +#. module: pos_place +#: model:ir.model.fields,field_description:pos_place.field_pos_place__company_id +msgid "Company" +msgstr "Société" + +#. module: pos_place +#: model:ir.model.fields,field_description:pos_place.field_pos_place__create_uid +msgid "Created by" +msgstr "Créé par" + +#. module: pos_place +#: model:ir.model.fields,field_description:pos_place.field_pos_place__create_date +msgid "Created on" +msgstr "Créé le" + +#. module: pos_place +#: model:ir.model.fields,field_description:pos_place.field_pos_place__display_name +msgid "Display Name" +msgstr "Nom affiché" + +#. module: pos_place +#: model:ir.model.fields,field_description:pos_place.field_pos_place__id +msgid "ID" +msgstr "" + +#. module: pos_place +#: model:ir.model.fields,field_description:pos_place.field_pos_place____last_update +msgid "Last Modified on" +msgstr "Dernière modification le" + +#. module: pos_place +#: model:ir.model.fields,field_description:pos_place.field_pos_place__write_uid +msgid "Last Updated by" +msgstr "Dernière mise à jour par" + +#. module: pos_place +#: model:ir.model.fields,field_description:pos_place.field_pos_place__write_date +msgid "Last Updated on" +msgstr "Dernière mise à jour le" + +#. module: pos_place +#: model:res.groups,name:pos_place.group_pos_place_manager +msgid "Manager" +msgstr "Gestionnaire" + +#. module: pos_place +#: model:ir.model.fields,field_description:pos_place.field_pos_place__name +#: model_terms:ir.ui.view,arch_db:pos_place.view_pos_place_form +msgid "Name" +msgstr "Nom" + +#. module: pos_place +#. openerp-web +#: code:addons/pos_place/static/src/js/widget.js:40 +#: model:ir.model.fields,field_description:pos_place.field_pos_order__place_id +#: model:ir.model.fields,field_description:pos_place.field_report_pos_order__place_id +#, python-format +msgid "Place" +msgstr "Emplacement" + +#. module: pos_place +#. openerp-web +#: code:addons/pos_place/static/src/xml/pos_place.xml:28 +#: code:addons/pos_place/static/src/xml/pos_place.xml:41 +#, python-format +msgid "Place:" +msgstr "Emplacements : " + +#. module: pos_place +#: model:ir.actions.act_window,name:pos_place.action_pos_place +#: model:ir.ui.menu,name:pos_place.menu_pos_place +msgid "Places" +msgstr "Emplacements" + +#. module: pos_place +#: model:ir.module.category,name:pos_place.module_category_pos_place +msgid "Point of Sale - Places" +msgstr "Point de vente - Emplacements" + +#. module: pos_place +#: model:ir.model,name:pos_place.model_pos_config +msgid "Point of Sale Configuration" +msgstr "Paramétrage du point de vente" + +#. module: pos_place +#: model:ir.model,name:pos_place.model_pos_order +msgid "Point of Sale Orders" +msgstr "Commandes du point de vente" + +#. module: pos_place +#: model:ir.model,name:pos_place.model_report_pos_order +msgid "Point of Sale Orders Report" +msgstr "" + +#. module: pos_place +#: model:ir.model.fields,field_description:pos_place.field_pos_config__group_pos_place_user_id +msgid "Point of Sale Place User Group" +msgstr "" + +#. module: pos_place +#: model:ir.model,name:pos_place.model_pos_place +msgid "Point of Sale Places" +msgstr "Emplacement du Point de vente" + +#. module: pos_place +#. openerp-web +#: code:addons/pos_place/static/src/js/gui.js:31 +#, python-format +msgid "Select a Place" +msgstr "Choisir un emplacement" + +#. module: pos_place +#: model:ir.model.fields,help:pos_place.field_pos_config__group_pos_place_user_id +msgid "This field is there to pass the id of the pos place user group to the point of sale client." +msgstr "" + +#. module: pos_place +#: model:res.groups,name:pos_place.group_pos_place_user +msgid "User" +msgstr "Utilisateur" + diff --git a/pos_place/models/__init__.py b/pos_place/models/__init__.py new file mode 100644 index 00000000..cbfc7e72 --- /dev/null +++ b/pos_place/models/__init__.py @@ -0,0 +1,3 @@ +from . import pos_place +from . import pos_config +from . import pos_order diff --git a/pos_place/models/pos_config.py b/pos_place/models/pos_config.py new file mode 100644 index 00000000..924418e6 --- /dev/null +++ b/pos_place/models/pos_config.py @@ -0,0 +1,20 @@ +# Copyright (C) 2018 - 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 odoo import api, fields, models + + +class PosConfig(models.Model): + _inherit = 'pos.config' + + group_pos_place_user_id = fields.Many2one( + 'res.groups', string='Point of Sale Place User Group', + compute='_compute_group_pos_place_user_id', + help="This field is there to pass the id of the pos place user" + " group to the point of sale client.") + + @api.multi + def _compute_group_pos_place_user_id(self): + for config in self: + config.group_pos_place_user_id =\ + self.env.ref('pos_place.group_pos_place_user') diff --git a/pos_place/models/pos_order.py b/pos_place/models/pos_order.py new file mode 100644 index 00000000..c949b34b --- /dev/null +++ b/pos_place/models/pos_order.py @@ -0,0 +1,18 @@ +# Copyright (C) 2015 - 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 odoo import api, fields, models + + +class PosOrder(models.Model): + _inherit = 'pos.order' + + # Columns section + place_id = fields.Many2one( + string='Place', comodel_name='pos.place') + + @api.model + def _order_fields(self, ui_order): + res = super(PosOrder, self)._order_fields(ui_order) + res['place_id'] = ui_order.get('place_id', False) + return res diff --git a/pos_place/models/pos_place.py b/pos_place/models/pos_place.py new file mode 100644 index 00000000..fab217a5 --- /dev/null +++ b/pos_place/models/pos_place.py @@ -0,0 +1,25 @@ +# Copyright (C) 2015 - 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 odoo import models, fields + + +class PosPlace(models.Model): + _name = 'pos.place' + _description = 'Point of Sale Places' + + # Default section + def _default_company_id(self): + return self.env.user.company_id.id + + # Columns section + code = fields.Char(required=True, size=6) + + name = fields.Char(required=True) + + active = fields.Boolean(default=True) + + company_id = fields.Many2one( + string='Company', comodel_name='res.company', + default=_default_company_id) diff --git a/pos_place/readme/CONFIGURE.rst b/pos_place/readme/CONFIGURE.rst new file mode 100644 index 00000000..720fbacc --- /dev/null +++ b/pos_place/readme/CONFIGURE.rst @@ -0,0 +1,9 @@ +To configure this module, you need to: + +* Add your users to the new group 'Point of Sale - Places' (User or Manager) + +* Go to Point of Sale / Configuration / Places + +* Create your places + +.. figure:: ../static/description/pos_place_tree.png diff --git a/pos_place/readme/CONTRIBUTORS.rst b/pos_place/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..9f76a75b --- /dev/null +++ b/pos_place/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Sylvain LE GAL diff --git a/pos_place/readme/DESCRIPTION.rst b/pos_place/readme/DESCRIPTION.rst new file mode 100644 index 00000000..5cc0c167 --- /dev/null +++ b/pos_place/readme/DESCRIPTION.rst @@ -0,0 +1,5 @@ +This module extends the functionality of point of sale to support saling +in the street using the point of sale and to allow you to mention on the +pos order, the place where the seller is for the time being. + +For that purpose, it introduce a new model ``pos.place``. diff --git a/pos_place/readme/USAGE.rst b/pos_place/readme/USAGE.rst new file mode 100644 index 00000000..a2979330 --- /dev/null +++ b/pos_place/readme/USAGE.rst @@ -0,0 +1,16 @@ +To use this module, you need to + +* open the point of sale + +* Click on 'Place' Button and select the place where you are + +.. figure:: ../static/description/pos_front_end_ui.png + +* All the next Pos Order will be related to this place. + +.. figure:: ../static/description/pos_order_tree.png + + +* You can then, make statistic over best places + +.. figure:: ../static/description/report_pos_order_graph.png diff --git a/pos_place/report/__init__.py b/pos_place/report/__init__.py new file mode 100644 index 00000000..a22a0481 --- /dev/null +++ b/pos_place/report/__init__.py @@ -0,0 +1 @@ +from . import report_pos_order diff --git a/pos_place/report/report_pos_order.py b/pos_place/report/report_pos_order.py new file mode 100644 index 00000000..d0e9ecc3 --- /dev/null +++ b/pos_place/report/report_pos_order.py @@ -0,0 +1,16 @@ +# Copyright (C) 2019 - 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 odoo import fields, models + + +class PosOrderReport(models.Model): + _inherit = 'report.pos.order' + + place_id = fields.Many2one( + comodel_name='pos.place', string='Place', readonly=True) + + def _select(self): + res = super()._select() + res += ', s.place_id as place_id' + return res diff --git a/pos_place/security/ir.model.access.csv b/pos_place/security/ir.model.access.csv new file mode 100644 index 00000000..93150a6d --- /dev/null +++ b/pos_place/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_pos_place_user,PoS Places User,model_pos_place,group_pos_place_user,1,,, +access_pos_place_manager,PoS Places Manager,model_pos_place,group_pos_place_manager,1,1,1,1 diff --git a/pos_place/security/ir_module_category.xml b/pos_place/security/ir_module_category.xml new file mode 100644 index 00000000..7d0f11ac --- /dev/null +++ b/pos_place/security/ir_module_category.xml @@ -0,0 +1,14 @@ + + + + + + Point of Sale - Places + + + + diff --git a/pos_place/security/ir_rule.xml b/pos_place/security/ir_rule.xml new file mode 100644 index 00000000..85d6a1aa --- /dev/null +++ b/pos_place/security/ir_rule.xml @@ -0,0 +1,18 @@ + + + + + + Point of Sale Places + + + ['|', + ('company_id', '=', False), + ('company_id', '=', user.company_id.id)] + + + diff --git a/pos_place/security/res_groups.xml b/pos_place/security/res_groups.xml new file mode 100644 index 00000000..b5bd079b --- /dev/null +++ b/pos_place/security/res_groups.xml @@ -0,0 +1,21 @@ + + + + + + User + + + + + Manager + + + + + + diff --git a/pos_place/static/description/pos_front_end_ui.png b/pos_place/static/description/pos_front_end_ui.png new file mode 100644 index 00000000..46b66ed7 Binary files /dev/null and b/pos_place/static/description/pos_front_end_ui.png differ diff --git a/pos_place/static/description/pos_order_tree.png b/pos_place/static/description/pos_order_tree.png new file mode 100644 index 00000000..ad1e6174 Binary files /dev/null and b/pos_place/static/description/pos_order_tree.png differ diff --git a/pos_place/static/description/pos_place_tree.png b/pos_place/static/description/pos_place_tree.png new file mode 100644 index 00000000..98196916 Binary files /dev/null and b/pos_place/static/description/pos_place_tree.png differ diff --git a/pos_place/static/description/report_pos_order_graph.png b/pos_place/static/description/report_pos_order_graph.png new file mode 100644 index 00000000..3b450a53 Binary files /dev/null and b/pos_place/static/description/report_pos_order_graph.png differ diff --git a/pos_place/static/src/js/chrome.js b/pos_place/static/src/js/chrome.js new file mode 100644 index 00000000..f95d007d --- /dev/null +++ b/pos_place/static/src/js/chrome.js @@ -0,0 +1,26 @@ +/** +Copyright (C) 2015 - 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). +**/ + +odoo.define('pos_place.chrome', function (require) { + "use strict"; + + var chrome = require('point_of_sale.chrome'); + var pos_place_widget = require('pos_place.widgets'); + + chrome.Chrome.include({ + + init: function () { + this.widgets.push({ + 'name': 'place_name', + 'widget': pos_place_widget.PlaceNameWidget, + 'replace': '.placeholder-PlaceNameWidget', + }); + return this._super(arguments[0], {}); + }, + + }); + +}); diff --git a/pos_place/static/src/js/gui.js b/pos_place/static/src/js/gui.js new file mode 100644 index 00000000..a06eff2e --- /dev/null +++ b/pos_place/static/src/js/gui.js @@ -0,0 +1,56 @@ +/** +Copyright (C) 2015 - 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). +**/ + +odoo.define('pos_place.gui', function (require) { + "use strict"; + + var gui = require('point_of_sale.gui'); + var core = require('web.core'); + var _t = core._t; + + + gui.Gui.include({ + + select_place: function () { + var def = new $.Deferred(); + var current_place = this.pos.get_place(); + + var list = []; + for (var i = 0; i < this.pos.places.length; i++) { + var item = this.pos.places[i]; + list.push({ + 'label': item.code + " - " + item.name, + 'item': item, + }); + } + + this.show_popup('selection', { + title: _t("Select a Place"), + list: list, + confirm: function (place) { + def.resolve(place); + }, + cancel: function () { + def.resolve(null); + }, + is_selected: function (place) { + if (current_place) { + return place.id === current_place.id; + } + + return false; + + }, + }); + + return def.then(function (place) { + return place; + }); + }, + + }); + +}); diff --git a/pos_place/static/src/js/models.js b/pos_place/static/src/js/models.js new file mode 100644 index 00000000..28fd443f --- /dev/null +++ b/pos_place/static/src/js/models.js @@ -0,0 +1,51 @@ +/** +Copyright (C) 2015 - 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). +**/ + +odoo.define('pos_place.models', function (require) { + "use strict"; + + var models = require('point_of_sale.models'); + var _super_order = models.Order.prototype; + + // Load pos.place model + models.load_models({ + model: 'pos.place', + loaded: function (self, places) { + self.places = []; + for (var i = 0; i < places.length; i++) { + self.places.push(places[i]); + } + }, + }); + + // Make place persistent in the session + models.PosModel = models.PosModel.extend({ + get_place: function () { + return this.get('current_place') || + this.db.load('current_place'); + }, + set_place: function (place) { + this.set('current_place', place); + this.db.save('current_place', place || null); + }, + }); + + models.Order = models.Order.extend({ + export_for_printing: function () { + var res = _super_order.export_for_printing.apply(this, arguments); + res.place = this.pos.get_place(); + return res; + }, + + export_as_JSON: function () { + var json = _super_order.export_as_JSON.apply(this, arguments); + var place = this.pos.get_place(); + json.place_id = place ? place.id : false; + return json; + }, + }); + +}); diff --git a/pos_place/static/src/js/widget.js b/pos_place/static/src/js/widget.js new file mode 100644 index 00000000..e81944ec --- /dev/null +++ b/pos_place/static/src/js/widget.js @@ -0,0 +1,49 @@ +/** +Copyright (C) 2015 - 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). +**/ + +odoo.define('pos_place.widgets', function (require) { + "use strict"; + + var PosBaseWidget = require('point_of_sale.BaseWidget'); + var core = require('web.core'); + var _t = core._t; + + var PlaceNameWidget = PosBaseWidget.extend({ + template: 'PlaceNameWidget', + renderElement: function () { + var self = this; + this._super(); + + this.$el.click(function () { + self.click_place(); + }); + }, + click_place: function () { + var self = this; + this.gui.select_place({}).then(function (place) { + self.pos.set_place(place); + self.renderElement(); + }); + }, + is_visible: function () { + return this.pos.user.groups_id.indexOf( + this.pos.config.group_pos_place_user_id[0]) !== -1; + }, + get_name: function () { + var place = this.pos.get_place(); + if (place) { + return place.code; + } + return _t("Place"); + + }, + }); + + return { + PlaceNameWidget: PlaceNameWidget, + }; + +}); diff --git a/pos_place/static/src/xml/pos_place.xml b/pos_place/static/src/xml/pos_place.xml new file mode 100644 index 00000000..1da144ba --- /dev/null +++ b/pos_place/static/src/xml/pos_place.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + +
+ Place:
+
+
+
+
+ + + + + +
+
--------------------------------
+
Place:
+
+
+
+
+ +
diff --git a/pos_place/views/templates.xml b/pos_place/views/templates.xml new file mode 100644 index 00000000..e32d3b36 --- /dev/null +++ b/pos_place/views/templates.xml @@ -0,0 +1,11 @@ + + + + diff --git a/pos_place/views/view_pos_order.xml b/pos_place/views/view_pos_order.xml new file mode 100644 index 00000000..baaf7130 --- /dev/null +++ b/pos_place/views/view_pos_order.xml @@ -0,0 +1,29 @@ + + + + + + pos.order + + + + + + + + + + pos.order + + + + + + + + + diff --git a/pos_place/views/view_pos_place.xml b/pos_place/views/view_pos_place.xml new file mode 100644 index 00000000..447da623 --- /dev/null +++ b/pos_place/views/view_pos_place.xml @@ -0,0 +1,67 @@ + + + + + + pos.place + + + + + + + + + + + pos.place + +
+ +
+ +
+
+
+
+

+ +

+
+
+

+ +

+
+ + + + + +
+
+
+
+ + + Places + ir.actions.act_window + pos.place + form + tree,form + + + + +