From de8222dd52e423015165b3fbead67e30c61d632f Mon Sep 17 00:00:00 2001 From: Laetitia Gangloff Date: Wed, 9 Dec 2015 20:38:26 +0100 Subject: [PATCH 01/14] add module pos_cagnotte_coupon --- pos_cagnotte_coupon/README.rst | 18 +++ pos_cagnotte_coupon/__init__.py | 3 + pos_cagnotte_coupon/__openerp__.py | 22 +++ pos_cagnotte_coupon/i18n/fr.po | 99 +++++++++++++ pos_cagnotte_coupon/models/__init__.py | 4 + pos_cagnotte_coupon/models/account.py | 60 ++++++++ pos_cagnotte_coupon/models/point_of_sale.py | 52 +++++++ .../static/src/css/pos_cagnotte_coupon.css | 33 +++++ pos_cagnotte_coupon/static/src/js/main.js | 135 ++++++++++++++++++ pos_cagnotte_coupon/static/src/xml/pos.xml | 30 ++++ pos_cagnotte_coupon/views/pos_template.xml | 16 +++ pos_cagnotte_coupon/views/pos_views.xml | 38 +++++ 12 files changed, 510 insertions(+) create mode 100644 pos_cagnotte_coupon/README.rst create mode 100644 pos_cagnotte_coupon/__init__.py create mode 100644 pos_cagnotte_coupon/__openerp__.py create mode 100644 pos_cagnotte_coupon/i18n/fr.po create mode 100644 pos_cagnotte_coupon/models/__init__.py create mode 100644 pos_cagnotte_coupon/models/account.py create mode 100644 pos_cagnotte_coupon/models/point_of_sale.py create mode 100644 pos_cagnotte_coupon/static/src/css/pos_cagnotte_coupon.css create mode 100644 pos_cagnotte_coupon/static/src/js/main.js create mode 100644 pos_cagnotte_coupon/static/src/xml/pos.xml create mode 100644 pos_cagnotte_coupon/views/pos_template.xml create mode 100644 pos_cagnotte_coupon/views/pos_views.xml diff --git a/pos_cagnotte_coupon/README.rst b/pos_cagnotte_coupon/README.rst new file mode 100644 index 00000000..3d030bc9 --- /dev/null +++ b/pos_cagnotte_coupon/README.rst @@ -0,0 +1,18 @@ +=============== +POS Cagnotte Coupon +=============== + +This module add the possibility to buy coupon in Point of sale. +This module add the possibility to use coupon in Point of sale. + +Credits +======= + +Maintainer +---------- + +.. image:: https://www.acsone.eu/logo.png + :alt: ACSONE SA/NV + :target: http://www.acsone.eu + +This module is maintained by ACSONE SA/NV. \ No newline at end of file diff --git a/pos_cagnotte_coupon/__init__.py b/pos_cagnotte_coupon/__init__.py new file mode 100644 index 00000000..cde864ba --- /dev/null +++ b/pos_cagnotte_coupon/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import models diff --git a/pos_cagnotte_coupon/__openerp__.py b/pos_cagnotte_coupon/__openerp__.py new file mode 100644 index 00000000..9469b2c6 --- /dev/null +++ b/pos_cagnotte_coupon/__openerp__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# © 2015 Laetitia Gangloff, Acsone SA/NV (http://www.acsone.eu) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "POS Cagnotte Coupon", + "version": "8.0.1.0.0", + 'author': "Acsone SA/NV", + "category": "Point Of Sale,Accounting & Finance", + "website": "http://www.acsone.eu", + "depends": ["cagnotte_coupon", + "point_of_sale" + ], + "data": ["views/pos_views.xml", + "views/pos_template.xml", + ], + "qweb": ['static/src/xml/pos.xml', + ], + "license": "AGPL-3", + "installable": True, + "application": False, +} diff --git a/pos_cagnotte_coupon/i18n/fr.po b/pos_cagnotte_coupon/i18n/fr.po new file mode 100644 index 00000000..ea959729 --- /dev/null +++ b/pos_cagnotte_coupon/i18n/fr.po @@ -0,0 +1,99 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_cagnotte_coupon +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-12-08 17:27+0000\n" +"PO-Revision-Date: 2015-12-08 17:27+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_cagnotte_coupon +#: field:account.cagnotte,account_bank_statement_line_ids:0 +#: model:ir.model,name:pos_cagnotte_coupon.model_account_bank_statement +msgid "Bank Statement" +msgstr "Relevé bancaire" + +#. module: pos_cagnotte_coupon +#: model:ir.model,name:pos_cagnotte_coupon.model_account_bank_statement_line +msgid "Bank Statement Line" +msgstr "Ligne de relevé bancaire" + +#. module: pos_cagnotte_coupon +#: field:account.bank.statement.line,account_cagnotte_id:0 +#: field:pos.order.line,account_cagnotte_id:0 +msgid "Cagnotte" +msgstr "Cagnotte" + +#. module: pos_cagnotte_coupon +#. openerp-web +#: code:addons/pos_cagnotte_coupon/static/src/js/main.js:64 +#, python-format +msgid "Cagnotte without coupon" +msgstr "Cagnotte sans coupon" + +#. module: pos_cagnotte_coupon +#. openerp-web +#: code:addons/pos_cagnotte_coupon/static/src/xml/pos.xml:22 +#, python-format +msgid "Cancel" +msgstr "Annuler" + +#. module: pos_cagnotte_coupon +#. openerp-web +#: code:addons/pos_cagnotte_coupon/static/src/js/main.js:120 +#, python-format +msgid "Coupon not usable" +msgstr "Coupon non utilisable" + +#. module: pos_cagnotte_coupon +#: model:ir.model,name:pos_cagnotte_coupon.model_account_journal +msgid "Journal" +msgstr "Journal" + +#. module: pos_cagnotte_coupon +#: model:ir.model,name:pos_cagnotte_coupon.model_pos_order_line +msgid "Lines of Point of Sale" +msgstr "Lignes de Points de Vente" + +#. module: pos_cagnotte_coupon +#: model:ir.model,name:pos_cagnotte_coupon.model_pos_order +msgid "Point of Sale" +msgstr "Point de Vente" + +#. module: pos_cagnotte_coupon +#. openerp-web +#: code:addons/pos_cagnotte_coupon/static/src/xml/pos.xml:7 +#: code:addons/pos_cagnotte_coupon/static/src/xml/pos.xml:17 +#, python-format +msgid "Set Coupon Code" +msgstr "Mettre un code coupon" + +#. module: pos_cagnotte_coupon +#. openerp-web +#: code:addons/pos_cagnotte_coupon/static/src/js/main.js:121 +#, python-format +msgid "The coupon code is not usable" +msgstr "Le code coupon n'est pas utilisable" + +#. module: pos_cagnotte_coupon +#. openerp-web +#: code:addons/pos_cagnotte_coupon/static/src/xml/pos.xml:19 +#, python-format +msgid "Validate" +msgstr "Valider" + +#. module: pos_cagnotte_coupon +#. openerp-web +#: code:addons/pos_cagnotte_coupon/static/src/js/main.js:65 +#, python-format +msgid "You cannot use cagnotte without a coupon." +msgstr "Vous ne pouvez pas utiliser une cagnotte sans coupon" + diff --git a/pos_cagnotte_coupon/models/__init__.py b/pos_cagnotte_coupon/models/__init__.py new file mode 100644 index 00000000..80fa3978 --- /dev/null +++ b/pos_cagnotte_coupon/models/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- + +from . import point_of_sale +from . import account diff --git a/pos_cagnotte_coupon/models/account.py b/pos_cagnotte_coupon/models/account.py new file mode 100644 index 00000000..474e233f --- /dev/null +++ b/pos_cagnotte_coupon/models/account.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# © 2015 Laetitia Gangloff, Acsone SA/NV (http://www.acsone.eu) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import api, fields, models + + +class AccountJournal(models.Model): + _inherit = 'account.journal' + + has_cagnotte = fields.Boolean(compute="_compute_has_cagnotte") + + @api.multi + def _compute_has_cagnotte(self): + for journal in self: + cagnotte_type_count = self.env['cagnotte.type'].search_count( + [('journal_id', '=', journal.id), + ('with_coupon_code', '=', True)]) + journal.has_cagnotte = cagnotte_type_count > 0 + + +class AccountBankStatementLine(models.Model): + _inherit = 'account.bank.statement.line' + + account_cagnotte_id = fields.Many2one('account.cagnotte', 'Cagnotte') + + +class AccountBankStatement(models.Model): + _inherit = 'account.bank.statement' + + @api.model + def _prepare_move_line_vals( + self, st_line, move_id, debit, credit, currency_id=False, + amount_currency=False, account_id=False, partner_id=False): + res = super(AccountBankStatement, self)._prepare_move_line_vals( + st_line, move_id, debit, credit, currency_id=currency_id, + amount_currency=amount_currency, account_id=account_id, + partner_id=partner_id) + res['account_cagnotte_id'] = st_line.account_cagnotte_id.id + return res + + +class AccountCagnotte(models.Model): + _inherit = 'account.cagnotte' + + account_bank_statement_line_ids = fields.One2many( + "account.bank.statement.line", "account_cagnotte_id", + string="Bank Statement") + + @api.one + @api.depends('account_bank_statement_line_ids.journal_entry_id', + 'account_bank_statement_line_ids.amount') + def _compute_solde_cagnotte(self): + super(AccountCagnotte, self)._compute_solde_cagnotte() + solde_cagnotte = self.solde_cagnotte + # remove amount of statement not done + for bs_line in self.account_bank_statement_line_ids: + if not bs_line.journal_entry_id: + solde_cagnotte -= bs_line.amount + self.solde_cagnotte = solde_cagnotte diff --git a/pos_cagnotte_coupon/models/point_of_sale.py b/pos_cagnotte_coupon/models/point_of_sale.py new file mode 100644 index 00000000..2a490e90 --- /dev/null +++ b/pos_cagnotte_coupon/models/point_of_sale.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# © 2015 Laetitia Gangloff, Acsone SA/NV (http://www.acsone.eu) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import api, fields, models + + +class POSOrderLine(models.Model): + _inherit = "pos.order.line" + + account_cagnotte_id = fields.Many2one('account.cagnotte', 'Cagnotte') + + @api.model + def create(self, values): + if values.get('product_id') and not values.get('account_cagnotte_id'): + cagnotte_type = self.env['cagnotte.type'].search( + [('product_id', '=', values['product_id'])]) + if cagnotte_type: + # create cagnotte + values['account_cagnotte_id'] = \ + self.env['account.cagnotte'].create( + {'cagnotte_type_id': cagnotte_type.id}).id + return super(POSOrderLine, self).create(values) + + +class PosOrder(models.Model): + _inherit = "pos.order" + + def _get_product_key(self, values): + product_key = super(PosOrder, self)._get_product_key(values) + return product_key + (values['account_cagnotte_id'], ) + + @api.model + def _get_product_values(self, line, income_account, amount, tax_code_id, + tax_amount, order): + res = super(PosOrder, self)._get_product_values( + line, income_account, amount, tax_code_id, tax_amount, order) + res['account_cagnotte_id'] = line.account_cagnotte_id.id + return res + + @api.model + def _payment_fields(self, ui_paymentline): + res = super(PosOrder, self)._payment_fields(ui_paymentline) + res['account_cagnotte_id'] = ui_paymentline.get('account_cagnotte_id') + return res + + @api.model + def _add_custom_payment_line_info(self, order_id, data): + res = super(PosOrder, self)._add_custom_payment_line_info(order_id, + data) + res['account_cagnotte_id'] = data.get('account_cagnotte_id') + return res diff --git a/pos_cagnotte_coupon/static/src/css/pos_cagnotte_coupon.css b/pos_cagnotte_coupon/static/src/css/pos_cagnotte_coupon.css new file mode 100644 index 00000000..3b8634b5 --- /dev/null +++ b/pos_cagnotte_coupon/static/src/css/pos_cagnotte_coupon.css @@ -0,0 +1,33 @@ +.pos .set-coupon-code button { + width: 150px; + height: 60px; + font-size: 18px; + cursor: pointer; + text-align:center; + box-sizing: border-box; + -moz-box-sizing: border-box; + left: 105%; + bottom: 10px; + position: absolute; +} + +.pos .modal-dialog .popup-set-coupon-code{ + margin-left:0; + margin-top:0; + left:30%; + width: 20%; + top:25%; + height:15%; +} + +.pos .modal-dialog .popup-set-coupon-code .coupon-title{ + height: 25%; +} + +.pos .modal-dialog .popup-set-coupon-code .coupon-title #coupon-popup-ok{ + margin: -10px 3px 3px 3px; +} + +.pos .modal-dialog .popup-set-coupon-code .coupon-title #coupon-popup-cancel{ + margin: 40px -115px 3px 3px; +} diff --git a/pos_cagnotte_coupon/static/src/js/main.js b/pos_cagnotte_coupon/static/src/js/main.js new file mode 100644 index 00000000..c672e768 --- /dev/null +++ b/pos_cagnotte_coupon/static/src/js/main.js @@ -0,0 +1,135 @@ +/* + © 2015 Laetitia Gangloff, Acsone SA/NV (http://www.acsone.eu) + License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +*/ + + +openerp.pos_cagnotte_coupon = function (instance) { + var _t = instance.web._t, + _lt = instance.web._lt; + var QWeb = instance.web.qweb; + module = instance.point_of_sale; + + // Add information relative to cagnotte on payment line + var PaymentlineParent = module.Paymentline; + module.Paymentline = module.Paymentline.extend({ + initialize: function(attributes, options) { + PaymentlineParent.prototype.initialize.apply(this, arguments); + this.account_cagnotte_id = false; + }, + //sets the account_cagnotte_id on this payment line + set_coupon: function(coupon){ + this.account_cagnotte_id = coupon.id; + this.set_amount(coupon.solde_cagnotte); + }, + // returns the coupon on this paymentline + get_coupon: function(){ + return this.account_cagnotte_id; + }, + // returns the flag has_cagnotte from journal + has_cagnotte: function(){ + return this.cashregister.journal.has_cagnotte + }, + export_as_JSON: function(){ + var json = PaymentlineParent.prototype.export_as_JSON.apply(this,arguments); + json.account_cagnotte_id = this.get_coupon(); + return json; + }, + }); + + module.PaymentScreenWidget.include({ + // Add behaviour on Set coupon Code button on payment line + render_paymentline: function(line){ + el_node = this._super(line); + var self = this; + if (line.cashregister.journal.has_cagnotte){ + el_node.querySelector('.set-coupon-code') + .addEventListener('click', function(){ + self.pos.pos_widget.screen_selector.show_popup('set-coupon-code-popup', line);}); + } + return el_node; + }, + // Re-check coupoon usage + validate_order: function(options) { + var self = this; + var cagnotte_not_ok = false; + + var currentOrder = this.pos.get('selectedOrder'); + var plines = currentOrder.get('paymentLines').models; + for (var i = 0; i < plines.length; i++) { + // check cagnotte have coupon attached + if (plines[i].has_cagnotte()){ + if (! plines[i].get_coupon()) { + this.pos_widget.screen_selector.show_popup('error',{ + 'message': _t('Cagnotte without coupon'), + 'comment': _t('You cannot use cagnotte without a coupon.'), + }); + return; + } + } + } + this._super(options); + }, + }); + + module.PosWidget = module.PosWidget.extend({ + /* Overload Section */ + build_widgets: function(){ + this._super(); + this.set_coupon_code_popup = new module.SetCouponCodeWidget(this, {}); + this.set_coupon_code_popup.appendTo($(this.$el)); + this.screen_selector.popup_set['set-coupon-code-popup'] = this.set_coupon_code_popup; + // Hide the popup because all pop up are displayed at the + // beginning by default + this.set_coupon_code_popup.hide(); + }, + }); + + module.SetCouponCodeWidget = module.PopUpWidget.extend({ + template:'SetCouponCodeWidget', + initialize: function() { + this.line = false; + }, + start: function(){ + var self = this; + + // Add behaviour on Cancel Button + this.$('#coupon-popup-cancel').off('click').click(function(){ + this.parentElement.parentElement.children[1].value = null; + self.hide(); + }); + // Add behaviour on Validate Button + this.$('#coupon-popup-ok').off('click').click(function(){ + var input_coupon = this.parentElement.parentElement.children[1]; + var coupon_code = this.parentElement.parentElement.children[1].value; + var Cagnotte = new openerp.Model('account.cagnotte'); + Cagnotte.query(['solde_cagnotte']). + filter([['coupon_code','=',coupon_code], + ['solde_cagnotte', '>', 0]]). + first().then(function (coupon) { + if(coupon){ + var line = self.line; + if(line){ + line.set_coupon(coupon); + line.node.querySelector('input').value = coupon.solde_cagnotte; + } + input_coupon.value = null; + self.hide(); + }else{ + self.pos_widget.screen_selector.show_popup('error',{ + 'message': _t('Coupon not usable'), + 'comment': _t('The coupon code ' + coupon_code + ' is not usable'), + }); + return; + } + }); + }); + }, + show: function(line){ + var self = this; + this.line = line; + this._super(); + }, + }); + +}; diff --git a/pos_cagnotte_coupon/static/src/xml/pos.xml b/pos_cagnotte_coupon/static/src/xml/pos.xml new file mode 100644 index 00000000..7b262f13 --- /dev/null +++ b/pos_cagnotte_coupon/static/src/xml/pos.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + diff --git a/pos_cagnotte_coupon/views/pos_template.xml b/pos_cagnotte_coupon/views/pos_template.xml new file mode 100644 index 00000000..28690b87 --- /dev/null +++ b/pos_cagnotte_coupon/views/pos_template.xml @@ -0,0 +1,16 @@ + + + + + + + \ No newline at end of file diff --git a/pos_cagnotte_coupon/views/pos_views.xml b/pos_cagnotte_coupon/views/pos_views.xml new file mode 100644 index 00000000..1fcb2833 --- /dev/null +++ b/pos_cagnotte_coupon/views/pos_views.xml @@ -0,0 +1,38 @@ + + + + + + pos.order.form + pos.order + + + + + + + + + account.bank.statement.form + account.bank.statement + + + + + + + + + account.journal.form + account.journal + + + + + + + + + + + From ee4091668277268ae26df02daa1a91ac5bf73a07 Mon Sep 17 00:00:00 2001 From: Laetitia Gangloff Date: Fri, 11 Dec 2015 18:21:57 +0100 Subject: [PATCH 02/14] cagnotte : some fixes --- pos_cagnotte_coupon/static/src/js/main.js | 25 +++++++++++++++++++++- pos_cagnotte_coupon/static/src/xml/pos.xml | 10 +++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/pos_cagnotte_coupon/static/src/js/main.js b/pos_cagnotte_coupon/static/src/js/main.js index c672e768..30ea8e1f 100644 --- a/pos_cagnotte_coupon/static/src/js/main.js +++ b/pos_cagnotte_coupon/static/src/js/main.js @@ -10,6 +10,23 @@ openerp.pos_cagnotte_coupon = function (instance) { var QWeb = instance.web.qweb; module = instance.point_of_sale; + // Add information relative to cagnotte on order line + var OrderlineParent = module.Orderline; + module.Orderline = module.Orderline.extend({ + initialize: function(attributes, options) { + OrderlineParent.prototype.initialize.apply(this, arguments); + this.coupon_code = false; + }, + //sets the coupon code on this order line + set_coupon: function(coupon_code){ + this.coupon_code = coupon_code; + }, + // returns the coupon on this orderline + get_coupon: function(){ + return this.coupon_code; + }, + }); + // Add information relative to cagnotte on payment line var PaymentlineParent = module.Paymentline; module.Paymentline = module.Paymentline.extend({ @@ -49,7 +66,7 @@ openerp.pos_cagnotte_coupon = function (instance) { } return el_node; }, - // Re-check coupoon usage + // Re-check coupon usage validate_order: function(options) { var self = this; var cagnotte_not_ok = false; @@ -122,6 +139,12 @@ openerp.pos_cagnotte_coupon = function (instance) { }); return; } + }, function (err, event) { + event.preventDefault(); + self.pos_widget.screen_selector.show_popup('error',{ + message: _t('Impossible to check coupon'), + comment: _t('Check your internet connection and try again.'), + }); }); }); }, diff --git a/pos_cagnotte_coupon/static/src/xml/pos.xml b/pos_cagnotte_coupon/static/src/xml/pos.xml index 7b262f13..c2b6bc1c 100644 --- a/pos_cagnotte_coupon/static/src/xml/pos.xml +++ b/pos_cagnotte_coupon/static/src/xml/pos.xml @@ -27,4 +27,14 @@ + + + + + + + + + + From 4cc1f02dae2bcb744cda5ed829a55d7c1177ddb3 Mon Sep 17 00:00:00 2001 From: Laetitia Gangloff Date: Mon, 14 Dec 2015 17:50:38 +0100 Subject: [PATCH 03/14] pos_cagnotte_coupon : add coupon code on receipt / avoid to use more than allowed in pos --- pos_cagnotte_coupon/models/account.py | 14 ++++ pos_cagnotte_coupon/models/point_of_sale.py | 7 +- pos_cagnotte_coupon/static/src/js/main.js | 72 +++++++++++++++++++-- 3 files changed, 86 insertions(+), 7 deletions(-) diff --git a/pos_cagnotte_coupon/models/account.py b/pos_cagnotte_coupon/models/account.py index 474e233f..879d6415 100644 --- a/pos_cagnotte_coupon/models/account.py +++ b/pos_cagnotte_coupon/models/account.py @@ -5,6 +5,20 @@ from openerp import api, fields, models +class ProductProduct(models.Model): + _inherit = 'product.product' + + has_cagnotte = fields.Boolean(compute="_compute_has_cagnotte") + + @api.multi + def _compute_has_cagnotte(self): + for product in self: + cagnotte_type_count = self.env['cagnotte.type'].search_count( + [('product_id', '=', product.id), + ('with_coupon_code', '=', True)]) + product.has_cagnotte = cagnotte_type_count > 0 + + class AccountJournal(models.Model): _inherit = 'account.journal' diff --git a/pos_cagnotte_coupon/models/point_of_sale.py b/pos_cagnotte_coupon/models/point_of_sale.py index 2a490e90..6e5b6b5b 100644 --- a/pos_cagnotte_coupon/models/point_of_sale.py +++ b/pos_cagnotte_coupon/models/point_of_sale.py @@ -8,6 +8,7 @@ class POSOrderLine(models.Model): _inherit = "pos.order.line" + coupon_code = fields.Char() account_cagnotte_id = fields.Many2one('account.cagnotte', 'Cagnotte') @api.model @@ -17,9 +18,11 @@ def create(self, values): [('product_id', '=', values['product_id'])]) if cagnotte_type: # create cagnotte + cagnotte_vals = {'cagnotte_type_id': cagnotte_type.id} + if values.get('coupon_code'): + cagnotte_vals['coupon_code'] = values['coupon_code'] values['account_cagnotte_id'] = \ - self.env['account.cagnotte'].create( - {'cagnotte_type_id': cagnotte_type.id}).id + self.env['account.cagnotte'].create(cagnotte_vals).id return super(POSOrderLine, self).create(values) diff --git a/pos_cagnotte_coupon/static/src/js/main.js b/pos_cagnotte_coupon/static/src/js/main.js index 30ea8e1f..4f504a2f 100644 --- a/pos_cagnotte_coupon/static/src/js/main.js +++ b/pos_cagnotte_coupon/static/src/js/main.js @@ -10,6 +10,21 @@ openerp.pos_cagnotte_coupon = function (instance) { var QWeb = instance.web.qweb; module = instance.point_of_sale; + // add has_cagnotte flag on product to avoid merge on it + var _initialize_ = module.PosModel.prototype.initialize; + module.PosModel.prototype.initialize = function(session, attributes){ + self = this; + // Add the load of the field product_product.has_cagnotte + for (var i = 0 ; i < this.models.length; i++){ + if (this.models[i].model == 'product.product'){ + if (this.models[i].fields.indexOf('has_cagnotte') == -1) { + this.models[i].fields.push('has_cagnotte'); + } + } + } + return _initialize_.call(this, session, attributes); + }; + // Add information relative to cagnotte on order line var OrderlineParent = module.Orderline; module.Orderline = module.Orderline.extend({ @@ -17,13 +32,48 @@ openerp.pos_cagnotte_coupon = function (instance) { OrderlineParent.prototype.initialize.apply(this, arguments); this.coupon_code = false; }, - //sets the coupon code on this order line - set_coupon: function(coupon_code){ - this.coupon_code = coupon_code; + // returns the flag has_cagnotte from product + has_cagnotte: function(){ + return this.product.has_cagnotte; + }, + // we do not merge line with cagnotte + can_be_merged_with: function(orderline){ + if(this.has_cagnotte()){ + return false; + }else{ + return OrderlineParent.prototype.can_be_merged_with.apply(this, arguments); + } + }, + // Generates a public identification number for the coupon. + generateUniqueId: function(base) { + var d = new Date().getTime(); + if(window.performance && typeof window.performance.now === "function"){ + d += performance.now(); //use high-precision timer if available + } + var uuid = 'xxxxxxxxxxxx'.replace(/[x]/g, function(c) { + var r = (d + Math.random()*10)%10 | 0; + d = Math.floor(d/10); + return (r).toString(10); + }); + return uuid + base; }, // returns the coupon on this orderline - get_coupon: function(){ - return this.coupon_code; + get_coupon_code: function(){ + if(this.has_cagnotte()){ + if(this.has_cagnotte()){ + if(! this.coupon_code){ + this.coupon_code = this.generateUniqueId(this.pos.pos_session.id); + } + return this.coupon_code; + }else{ + return false; + } + } + }, + export_as_JSON: function(){ + var json = OrderlineParent.prototype.export_as_JSON.apply(this,arguments); + json.coupon_code = this.get_coupon_code(); + return json; }, }); @@ -33,16 +83,21 @@ openerp.pos_cagnotte_coupon = function (instance) { initialize: function(attributes, options) { PaymentlineParent.prototype.initialize.apply(this, arguments); this.account_cagnotte_id = false; + this.solde_cagnotte = 0; }, //sets the account_cagnotte_id on this payment line set_coupon: function(coupon){ this.account_cagnotte_id = coupon.id; + this.solde_cagnotte = coupon.solde_cagnotte; this.set_amount(coupon.solde_cagnotte); }, // returns the coupon on this paymentline get_coupon: function(){ return this.account_cagnotte_id; }, + get_solde_cagnotte: function(){ + return this.solde_cagnotte; + }, // returns the flag has_cagnotte from journal has_cagnotte: function(){ return this.cashregister.journal.has_cagnotte @@ -83,6 +138,13 @@ openerp.pos_cagnotte_coupon = function (instance) { }); return; } + if (plines[i].get_amount() > plines[i].get_solde_cagnotte()) { + this.pos_widget.screen_selector.show_popup('error',{ + 'message': _t('Cagnotte with too big amount'), + 'comment': _t('You cannot use cagnotte with amount too big.'), + }); + return; + } } } this._super(options); From d4a723e7d0b47cd1e5dcd88d25532fa53fabce70 Mon Sep 17 00:00:00 2001 From: Laetitia Gangloff Date: Fri, 18 Dec 2015 15:01:46 +0100 Subject: [PATCH 04/14] set minimum between cagnotte and amount on the line --- pos_cagnotte_coupon/static/src/js/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pos_cagnotte_coupon/static/src/js/main.js b/pos_cagnotte_coupon/static/src/js/main.js index 4f504a2f..52727e6c 100644 --- a/pos_cagnotte_coupon/static/src/js/main.js +++ b/pos_cagnotte_coupon/static/src/js/main.js @@ -89,7 +89,7 @@ openerp.pos_cagnotte_coupon = function (instance) { set_coupon: function(coupon){ this.account_cagnotte_id = coupon.id; this.solde_cagnotte = coupon.solde_cagnotte; - this.set_amount(coupon.solde_cagnotte); + this.set_amount(Math.min(coupon.solde_cagnotte, this.get_amount())); }, // returns the coupon on this paymentline get_coupon: function(){ @@ -190,7 +190,7 @@ openerp.pos_cagnotte_coupon = function (instance) { var line = self.line; if(line){ line.set_coupon(coupon); - line.node.querySelector('input').value = coupon.solde_cagnotte; + line.node.querySelector('input').value = line.get_amount(); } input_coupon.value = null; self.hide(); From ca1bf2d3060c615268e7084e1c5d9b70ed61e68e Mon Sep 17 00:00:00 2001 From: Laetitia Gangloff Date: Mon, 21 Dec 2015 18:09:20 +0100 Subject: [PATCH 05/14] update value to set on cagnotte line --- pos_cagnotte_coupon/static/src/js/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pos_cagnotte_coupon/static/src/js/main.js b/pos_cagnotte_coupon/static/src/js/main.js index 52727e6c..c638f24d 100644 --- a/pos_cagnotte_coupon/static/src/js/main.js +++ b/pos_cagnotte_coupon/static/src/js/main.js @@ -190,7 +190,7 @@ openerp.pos_cagnotte_coupon = function (instance) { var line = self.line; if(line){ line.set_coupon(coupon); - line.node.querySelector('input').value = line.get_amount(); + line.node.querySelector('input').value = line.amount.toFixed(self.pos.currency.decimals); } input_coupon.value = null; self.hide(); From be729e3ee15fbc372a4b121bf0e0f042b6f91eeb Mon Sep 17 00:00:00 2001 From: Laetitia Gangloff Date: Mon, 4 Jan 2016 14:05:04 +0100 Subject: [PATCH 06/14] pos_cagnotte_coupon : add flag to check amount used in pos or not --- pos_cagnotte_coupon/models/account.py | 17 +++++++++++++++++ pos_cagnotte_coupon/static/src/js/main.js | 20 +++++++++++++------- pos_cagnotte_coupon/views/pos_views.xml | 16 +++++++++------- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/pos_cagnotte_coupon/models/account.py b/pos_cagnotte_coupon/models/account.py index 879d6415..1d64e98a 100644 --- a/pos_cagnotte_coupon/models/account.py +++ b/pos_cagnotte_coupon/models/account.py @@ -23,6 +23,8 @@ class AccountJournal(models.Model): _inherit = 'account.journal' has_cagnotte = fields.Boolean(compute="_compute_has_cagnotte") + check_cagnotte_amount = fields.Boolean( + compute='_compute_check_cagnotte_amount') @api.multi def _compute_has_cagnotte(self): @@ -32,6 +34,15 @@ def _compute_has_cagnotte(self): ('with_coupon_code', '=', True)]) journal.has_cagnotte = cagnotte_type_count > 0 + @api.multi + def _compute_check_cagnotte_amount(self): + for journal in self: + cagnotte_type_count = self.env['cagnotte.type'].search_count( + [('journal_id', '=', journal.id), + ('with_coupon_code', '=', True), + ('check_cagnotte_amount', '=', True)]) + journal.check_cagnotte_amount = cagnotte_type_count > 0 + class AccountBankStatementLine(models.Model): _inherit = 'account.bank.statement.line' @@ -72,3 +83,9 @@ def _compute_solde_cagnotte(self): if not bs_line.journal_entry_id: solde_cagnotte -= bs_line.amount self.solde_cagnotte = solde_cagnotte + + +class CagnotteType(models.Model): + _inherit = 'cagnotte.type' + + check_cagnotte_amount = fields.Boolean() diff --git a/pos_cagnotte_coupon/static/src/js/main.js b/pos_cagnotte_coupon/static/src/js/main.js index c638f24d..6952afd1 100644 --- a/pos_cagnotte_coupon/static/src/js/main.js +++ b/pos_cagnotte_coupon/static/src/js/main.js @@ -102,6 +102,10 @@ openerp.pos_cagnotte_coupon = function (instance) { has_cagnotte: function(){ return this.cashregister.journal.has_cagnotte }, + // returns the flag has_cagnotte from journal + check_cagnotte_amount: function(){ + return this.cashregister.journal.check_cagnotte_amount + }, export_as_JSON: function(){ var json = PaymentlineParent.prototype.export_as_JSON.apply(this,arguments); json.account_cagnotte_id = this.get_coupon(); @@ -138,12 +142,14 @@ openerp.pos_cagnotte_coupon = function (instance) { }); return; } - if (plines[i].get_amount() > plines[i].get_solde_cagnotte()) { - this.pos_widget.screen_selector.show_popup('error',{ - 'message': _t('Cagnotte with too big amount'), - 'comment': _t('You cannot use cagnotte with amount too big.'), - }); - return; + if (plines[i].check_cagnotte_amount()){ + if (plines[i].get_amount() > plines[i].get_solde_cagnotte()) { + this.pos_widget.screen_selector.show_popup('error',{ + 'message': _t('Cagnotte with too big amount'), + 'comment': _t('You cannot use cagnotte with amount too big.'), + }); + return; + } } } } @@ -184,7 +190,7 @@ openerp.pos_cagnotte_coupon = function (instance) { var Cagnotte = new openerp.Model('account.cagnotte'); Cagnotte.query(['solde_cagnotte']). filter([['coupon_code','=',coupon_code], - ['solde_cagnotte', '>', 0]]). + '|', ['cagnotte_type_id.check_cagnotte_amount', '=', false],['solde_cagnotte', '>', 0]]). first().then(function (coupon) { if(coupon){ var line = self.line; diff --git a/pos_cagnotte_coupon/views/pos_views.xml b/pos_cagnotte_coupon/views/pos_views.xml index 1fcb2833..70eedc09 100644 --- a/pos_cagnotte_coupon/views/pos_views.xml +++ b/pos_cagnotte_coupon/views/pos_views.xml @@ -22,15 +22,17 @@ - - account.journal.form - account.journal - + + + cagnotte.type.form + cagnotte.type + + - - + + - + From aaf8f96e33cef572bfcaacb7a872b83b38e071a3 Mon Sep 17 00:00:00 2001 From: Laetitia Gangloff Date: Mon, 4 Jan 2016 16:15:50 +0100 Subject: [PATCH 07/14] pos_cagnotte_coupon : add journal in coupon search to avoid bad association coupon/journal --- pos_cagnotte_coupon/static/src/js/main.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pos_cagnotte_coupon/static/src/js/main.js b/pos_cagnotte_coupon/static/src/js/main.js index 6952afd1..8ee2fccd 100644 --- a/pos_cagnotte_coupon/static/src/js/main.js +++ b/pos_cagnotte_coupon/static/src/js/main.js @@ -190,7 +190,8 @@ openerp.pos_cagnotte_coupon = function (instance) { var Cagnotte = new openerp.Model('account.cagnotte'); Cagnotte.query(['solde_cagnotte']). filter([['coupon_code','=',coupon_code], - '|', ['cagnotte_type_id.check_cagnotte_amount', '=', false],['solde_cagnotte', '>', 0]]). + ['cagnotte_type_id.journal_id', '=', self.line.cashregister.journal_id[0]], + '|', ['cagnotte_type_id.check_cagnotte_amount', '=', false], ['solde_cagnotte', '>', 0]]). first().then(function (coupon) { if(coupon){ var line = self.line; @@ -203,7 +204,7 @@ openerp.pos_cagnotte_coupon = function (instance) { }else{ self.pos_widget.screen_selector.show_popup('error',{ 'message': _t('Coupon not usable'), - 'comment': _t('The coupon code ' + coupon_code + ' is not usable'), + 'comment': _t('The coupon code ' + coupon_code + ' is not usable with ' + self.line.cashregister.journal_id[1]), }); return; } From 9f3cfd236ce70b3f4b583ed6837983fc0c201464 Mon Sep 17 00:00:00 2001 From: Laetitia Gangloff Date: Tue, 5 Jan 2016 11:01:17 +0100 Subject: [PATCH 08/14] pos_cagnotte_coupon : check customer in pos is the same than customer on coupon --- pos_cagnotte_coupon/static/src/js/main.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pos_cagnotte_coupon/static/src/js/main.js b/pos_cagnotte_coupon/static/src/js/main.js index 8ee2fccd..4358eb4f 100644 --- a/pos_cagnotte_coupon/static/src/js/main.js +++ b/pos_cagnotte_coupon/static/src/js/main.js @@ -188,10 +188,16 @@ openerp.pos_cagnotte_coupon = function (instance) { var input_coupon = this.parentElement.parentElement.children[1]; var coupon_code = this.parentElement.parentElement.children[1].value; var Cagnotte = new openerp.Model('account.cagnotte'); + var currentOrder = self.pos.get('selectedOrder'); + var client_id = false; + if (currentOrder.get_client()){ + client_id = currentOrder.get_client().id; + } Cagnotte.query(['solde_cagnotte']). filter([['coupon_code','=',coupon_code], ['cagnotte_type_id.journal_id', '=', self.line.cashregister.journal_id[0]], - '|', ['cagnotte_type_id.check_cagnotte_amount', '=', false], ['solde_cagnotte', '>', 0]]). + '|', ['cagnotte_type_id.check_cagnotte_amount', '=', false], ['solde_cagnotte', '>', 0], + ['partner_id', '=', client_id]]). first().then(function (coupon) { if(coupon){ var line = self.line; @@ -204,7 +210,9 @@ openerp.pos_cagnotte_coupon = function (instance) { }else{ self.pos_widget.screen_selector.show_popup('error',{ 'message': _t('Coupon not usable'), - 'comment': _t('The coupon code ' + coupon_code + ' is not usable with ' + self.line.cashregister.journal_id[1]), + 'comment': _t('The coupon code ' + coupon_code + ' is not usable' + + '. Check payment method : ' + self.line.cashregister.journal_id[1] + + '. Check customer'), }); return; } From 6691fd458341060084a979a21737d9597c87380a Mon Sep 17 00:00:00 2001 From: Laetitia Gangloff Date: Tue, 5 Jan 2016 13:43:05 +0100 Subject: [PATCH 09/14] pos_coupon: if not check amount, keep the current amount / no partner on coupon is valid with pos with partner --- pos_cagnotte_coupon/static/src/js/main.js | 5 ++++- pos_cagnotte_coupon/views/pos_views.xml | 11 ++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/pos_cagnotte_coupon/static/src/js/main.js b/pos_cagnotte_coupon/static/src/js/main.js index 4358eb4f..6a0ad1ba 100644 --- a/pos_cagnotte_coupon/static/src/js/main.js +++ b/pos_cagnotte_coupon/static/src/js/main.js @@ -89,6 +89,9 @@ openerp.pos_cagnotte_coupon = function (instance) { set_coupon: function(coupon){ this.account_cagnotte_id = coupon.id; this.solde_cagnotte = coupon.solde_cagnotte; + if (coupon.solde_cagnotte <= 0){ + coupon.solde_cagnotte = this.get_amount(); + } this.set_amount(Math.min(coupon.solde_cagnotte, this.get_amount())); }, // returns the coupon on this paymentline @@ -197,7 +200,7 @@ openerp.pos_cagnotte_coupon = function (instance) { filter([['coupon_code','=',coupon_code], ['cagnotte_type_id.journal_id', '=', self.line.cashregister.journal_id[0]], '|', ['cagnotte_type_id.check_cagnotte_amount', '=', false], ['solde_cagnotte', '>', 0], - ['partner_id', '=', client_id]]). + '|', ['partner_id', '=', false], ['partner_id', '=', client_id]]). first().then(function (coupon) { if(coupon){ var line = self.line; diff --git a/pos_cagnotte_coupon/views/pos_views.xml b/pos_cagnotte_coupon/views/pos_views.xml index 70eedc09..b856d113 100644 --- a/pos_cagnotte_coupon/views/pos_views.xml +++ b/pos_cagnotte_coupon/views/pos_views.xml @@ -7,9 +7,14 @@ pos.order - - - + + + + + + + + From 89b5688572c253e31d5b1f12463b3a942db643a8 Mon Sep 17 00:00:00 2001 From: Laetitia Gangloff Date: Thu, 14 Jan 2016 11:03:42 +0100 Subject: [PATCH 10/14] pos_cagnotte_coupon : use pos decimal when set solde cagnotte --- pos_cagnotte_coupon/static/src/js/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pos_cagnotte_coupon/static/src/js/main.js b/pos_cagnotte_coupon/static/src/js/main.js index 6a0ad1ba..7f4cb451 100644 --- a/pos_cagnotte_coupon/static/src/js/main.js +++ b/pos_cagnotte_coupon/static/src/js/main.js @@ -88,9 +88,9 @@ openerp.pos_cagnotte_coupon = function (instance) { //sets the account_cagnotte_id on this payment line set_coupon: function(coupon){ this.account_cagnotte_id = coupon.id; - this.solde_cagnotte = coupon.solde_cagnotte; + this.solde_cagnotte = coupon.solde_cagnotte.toFixed(this.pos.currency.decimals); if (coupon.solde_cagnotte <= 0){ - coupon.solde_cagnotte = this.get_amount(); + coupon.solde_cagnotte = this.toFixed(this.pos.currency.decimals); } this.set_amount(Math.min(coupon.solde_cagnotte, this.get_amount())); }, From 0cdffb6676eebc6a5494b9bddf2d1a7ee0f4fc3e Mon Sep 17 00:00:00 2001 From: Laetitia Gangloff Date: Wed, 20 Jan 2016 16:11:23 +0100 Subject: [PATCH 11/14] correct display of the amount and round value to avoid decimal precision error when compare --- pos_cagnotte_coupon/static/src/js/main.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pos_cagnotte_coupon/static/src/js/main.js b/pos_cagnotte_coupon/static/src/js/main.js index 7f4cb451..4afaf0ee 100644 --- a/pos_cagnotte_coupon/static/src/js/main.js +++ b/pos_cagnotte_coupon/static/src/js/main.js @@ -8,6 +8,7 @@ openerp.pos_cagnotte_coupon = function (instance) { var _t = instance.web._t, _lt = instance.web._lt; var QWeb = instance.web.qweb; + var round_di = instance.web.round_decimals; module = instance.point_of_sale; // add has_cagnotte flag on product to avoid merge on it @@ -88,11 +89,11 @@ openerp.pos_cagnotte_coupon = function (instance) { //sets the account_cagnotte_id on this payment line set_coupon: function(coupon){ this.account_cagnotte_id = coupon.id; - this.solde_cagnotte = coupon.solde_cagnotte.toFixed(this.pos.currency.decimals); + this.solde_cagnotte = round_di(parseFloat(coupon.solde_cagnotte) || 0, this.pos.currency.decimals); if (coupon.solde_cagnotte <= 0){ - coupon.solde_cagnotte = this.toFixed(this.pos.currency.decimals); + coupon.solde_cagnotte = this.get_amount(); } - this.set_amount(Math.min(coupon.solde_cagnotte, this.get_amount())); + this.set_amount(Math.min(coupon.solde_cagnotte.toFixed(this.pos.currency.decimals), this.get_amount_str())); }, // returns the coupon on this paymentline get_coupon: function(){ From 54205af3adc1762b8e924a2202af3bf475f26de4 Mon Sep 17 00:00:00 2001 From: Laetitia Gangloff Date: Mon, 9 May 2016 16:07:06 +0200 Subject: [PATCH 12/14] pos_cagnotte : check coupon_code is not already use in this order --- pos_cagnotte_coupon/static/src/js/main.js | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/pos_cagnotte_coupon/static/src/js/main.js b/pos_cagnotte_coupon/static/src/js/main.js index 4afaf0ee..b5f1f051 100644 --- a/pos_cagnotte_coupon/static/src/js/main.js +++ b/pos_cagnotte_coupon/static/src/js/main.js @@ -85,6 +85,7 @@ openerp.pos_cagnotte_coupon = function (instance) { PaymentlineParent.prototype.initialize.apply(this, arguments); this.account_cagnotte_id = false; this.solde_cagnotte = 0; + this.coupon_code = ''; }, //sets the account_cagnotte_id on this payment line set_coupon: function(coupon){ @@ -93,12 +94,16 @@ openerp.pos_cagnotte_coupon = function (instance) { if (coupon.solde_cagnotte <= 0){ coupon.solde_cagnotte = this.get_amount(); } + this.coupon_code = coupon.coupon_code; this.set_amount(Math.min(coupon.solde_cagnotte.toFixed(this.pos.currency.decimals), this.get_amount_str())); }, // returns the coupon on this paymentline get_coupon: function(){ return this.account_cagnotte_id; }, + get_coupon_code: function(){ + return this.coupon_code; + }, get_solde_cagnotte: function(){ return this.solde_cagnotte; }, @@ -197,7 +202,21 @@ openerp.pos_cagnotte_coupon = function (instance) { if (currentOrder.get_client()){ client_id = currentOrder.get_client().id; } - Cagnotte.query(['solde_cagnotte']). + // Check coupon is not already set on another payment line + var plines = currentOrder.get('paymentLines').models; + for (var i = 0; i < plines.length; i++) { + // if it is cagnotte + if (plines[i].has_cagnotte()) { + if (plines[i].get_coupon_code() == coupon_code){ + self.pos_widget.screen_selector.show_popup('error',{ + 'message': _t('Coupon not reusable'), + 'comment': _t('The coupon code ' + coupon_code + ' is already use in this order.'), + }); + return; + } + } + } + Cagnotte.query(['solde_cagnotte', 'coupon_code']). filter([['coupon_code','=',coupon_code], ['cagnotte_type_id.journal_id', '=', self.line.cashregister.journal_id[0]], '|', ['cagnotte_type_id.check_cagnotte_amount', '=', false], ['solde_cagnotte', '>', 0], From 674842494b0017751a5cf68654e492527d6f145a Mon Sep 17 00:00:00 2001 From: Benjamin Willig Date: Wed, 14 Jun 2017 10:18:03 +0200 Subject: [PATCH 13/14] [10.0][MIG] pos_cagnotte_coupon migration --- pos_cagnotte_coupon/README.rst | 13 +- pos_cagnotte_coupon/__init__.py | 1 - pos_cagnotte_coupon/__manifest__.py | 27 ++ pos_cagnotte_coupon/__openerp__.py | 22 -- pos_cagnotte_coupon/models/__init__.py | 10 +- pos_cagnotte_coupon/models/account.py | 91 ------ .../models/account_bank_statement_line.py | 22 ++ .../models/account_cagnotte.py | 28 ++ pos_cagnotte_coupon/models/account_journal.py | 34 +++ pos_cagnotte_coupon/models/cagnotte_type.py | 11 + pos_cagnotte_coupon/models/point_of_sale.py | 55 ---- pos_cagnotte_coupon/models/pos_order.py | 39 +++ pos_cagnotte_coupon/models/pos_order_line.py | 29 ++ pos_cagnotte_coupon/models/product_product.py | 22 ++ .../static/src/css/pos_cagnotte_coupon.css | 58 ++-- pos_cagnotte_coupon/static/src/js/main.js | 258 ------------------ pos_cagnotte_coupon/static/src/js/models.js | 196 +++++++++++++ pos_cagnotte_coupon/static/src/js/popups.js | 111 ++++++++ pos_cagnotte_coupon/static/src/js/screens.js | 112 ++++++++ pos_cagnotte_coupon/static/src/xml/pos.xml | 50 ++-- .../views/account_bank_statement.xml | 13 + pos_cagnotte_coupon/views/cagnotte_type.xml | 19 ++ pos_cagnotte_coupon/views/pos_order.xml | 20 ++ pos_cagnotte_coupon/views/pos_template.xml | 41 ++- pos_cagnotte_coupon/views/pos_views.xml | 45 --- setup/pos_cagnotte_coupon/.eggs/README.txt | 6 + setup/pos_cagnotte_coupon/odoo/__init__.py | 1 + .../odoo/addons/__init__.py | 1 + .../odoo/addons/pos_cagnotte_coupon | 1 + setup/pos_cagnotte_coupon/setup.py | 6 + 30 files changed, 801 insertions(+), 541 deletions(-) create mode 100644 pos_cagnotte_coupon/__manifest__.py delete mode 100644 pos_cagnotte_coupon/__openerp__.py delete mode 100644 pos_cagnotte_coupon/models/account.py create mode 100644 pos_cagnotte_coupon/models/account_bank_statement_line.py create mode 100644 pos_cagnotte_coupon/models/account_cagnotte.py create mode 100644 pos_cagnotte_coupon/models/account_journal.py create mode 100644 pos_cagnotte_coupon/models/cagnotte_type.py delete mode 100644 pos_cagnotte_coupon/models/point_of_sale.py create mode 100644 pos_cagnotte_coupon/models/pos_order.py create mode 100644 pos_cagnotte_coupon/models/pos_order_line.py create mode 100644 pos_cagnotte_coupon/models/product_product.py delete mode 100644 pos_cagnotte_coupon/static/src/js/main.js create mode 100644 pos_cagnotte_coupon/static/src/js/models.js create mode 100644 pos_cagnotte_coupon/static/src/js/popups.js create mode 100644 pos_cagnotte_coupon/static/src/js/screens.js create mode 100644 pos_cagnotte_coupon/views/account_bank_statement.xml create mode 100644 pos_cagnotte_coupon/views/cagnotte_type.xml create mode 100644 pos_cagnotte_coupon/views/pos_order.xml delete mode 100644 pos_cagnotte_coupon/views/pos_views.xml create mode 100644 setup/pos_cagnotte_coupon/.eggs/README.txt create mode 100644 setup/pos_cagnotte_coupon/odoo/__init__.py create mode 100644 setup/pos_cagnotte_coupon/odoo/addons/__init__.py create mode 120000 setup/pos_cagnotte_coupon/odoo/addons/pos_cagnotte_coupon create mode 100644 setup/pos_cagnotte_coupon/setup.py diff --git a/pos_cagnotte_coupon/README.rst b/pos_cagnotte_coupon/README.rst index 3d030bc9..73710b0a 100644 --- a/pos_cagnotte_coupon/README.rst +++ b/pos_cagnotte_coupon/README.rst @@ -2,8 +2,15 @@ POS Cagnotte Coupon =============== -This module add the possibility to buy coupon in Point of sale. -This module add the possibility to use coupon in Point of sale. +This module add the possibility to buy/use coupon in Point of sale. + +Installation +============ + +At the moment, this modules depends on: +- https://github.com/odoo/odoo/pull/17580 +- https://github.com/odoo/odoo/pull/17596 +- https://github.com/odoo/odoo/pull/17598 Credits ======= @@ -13,6 +20,6 @@ Maintainer .. image:: https://www.acsone.eu/logo.png :alt: ACSONE SA/NV - :target: http://www.acsone.eu + :target: https://www.acsone.eu This module is maintained by ACSONE SA/NV. \ No newline at end of file diff --git a/pos_cagnotte_coupon/__init__.py b/pos_cagnotte_coupon/__init__.py index cde864ba..a0fdc10f 100644 --- a/pos_cagnotte_coupon/__init__.py +++ b/pos_cagnotte_coupon/__init__.py @@ -1,3 +1,2 @@ # -*- coding: utf-8 -*- - from . import models diff --git a/pos_cagnotte_coupon/__manifest__.py b/pos_cagnotte_coupon/__manifest__.py new file mode 100644 index 00000000..0f0cd852 --- /dev/null +++ b/pos_cagnotte_coupon/__manifest__.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# © 2015 Laetitia Gangloff, Acsone SA/NV (http://www.acsone.eu) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + 'name': "POS Cagnotte Coupon", + 'version': '10.0.1.0.0', + 'author': 'Acsone SA/NV', + 'category': "Point Of Sale,Accounting & Finance", + 'website': 'http://www.acsone.eu', + 'depends': [ + 'cagnotte_coupon', + 'point_of_sale' + ], + 'data': [ + 'views/account_bank_statement.xml', + 'views/cagnotte_type.xml', + 'views/pos_order.xml', + 'views/pos_template.xml', + ], + 'qweb': [ + 'static/src/xml/pos.xml', + ], + 'license': 'AGPL-3', + 'installable': True, + 'application': False, +} diff --git a/pos_cagnotte_coupon/__openerp__.py b/pos_cagnotte_coupon/__openerp__.py deleted file mode 100644 index 9469b2c6..00000000 --- a/pos_cagnotte_coupon/__openerp__.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2015 Laetitia Gangloff, Acsone SA/NV (http://www.acsone.eu) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -{ - "name": "POS Cagnotte Coupon", - "version": "8.0.1.0.0", - 'author': "Acsone SA/NV", - "category": "Point Of Sale,Accounting & Finance", - "website": "http://www.acsone.eu", - "depends": ["cagnotte_coupon", - "point_of_sale" - ], - "data": ["views/pos_views.xml", - "views/pos_template.xml", - ], - "qweb": ['static/src/xml/pos.xml', - ], - "license": "AGPL-3", - "installable": True, - "application": False, -} diff --git a/pos_cagnotte_coupon/models/__init__.py b/pos_cagnotte_coupon/models/__init__.py index 80fa3978..2c09581b 100644 --- a/pos_cagnotte_coupon/models/__init__.py +++ b/pos_cagnotte_coupon/models/__init__.py @@ -1,4 +1,8 @@ # -*- coding: utf-8 -*- - -from . import point_of_sale -from . import account +from . import account_bank_statement_line +from . import account_cagnotte +from . import account_journal +from . import cagnotte_type +from . import pos_order +from . import pos_order_line +from . import product_product diff --git a/pos_cagnotte_coupon/models/account.py b/pos_cagnotte_coupon/models/account.py deleted file mode 100644 index 1d64e98a..00000000 --- a/pos_cagnotte_coupon/models/account.py +++ /dev/null @@ -1,91 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2015 Laetitia Gangloff, Acsone SA/NV (http://www.acsone.eu) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -from openerp import api, fields, models - - -class ProductProduct(models.Model): - _inherit = 'product.product' - - has_cagnotte = fields.Boolean(compute="_compute_has_cagnotte") - - @api.multi - def _compute_has_cagnotte(self): - for product in self: - cagnotte_type_count = self.env['cagnotte.type'].search_count( - [('product_id', '=', product.id), - ('with_coupon_code', '=', True)]) - product.has_cagnotte = cagnotte_type_count > 0 - - -class AccountJournal(models.Model): - _inherit = 'account.journal' - - has_cagnotte = fields.Boolean(compute="_compute_has_cagnotte") - check_cagnotte_amount = fields.Boolean( - compute='_compute_check_cagnotte_amount') - - @api.multi - def _compute_has_cagnotte(self): - for journal in self: - cagnotte_type_count = self.env['cagnotte.type'].search_count( - [('journal_id', '=', journal.id), - ('with_coupon_code', '=', True)]) - journal.has_cagnotte = cagnotte_type_count > 0 - - @api.multi - def _compute_check_cagnotte_amount(self): - for journal in self: - cagnotte_type_count = self.env['cagnotte.type'].search_count( - [('journal_id', '=', journal.id), - ('with_coupon_code', '=', True), - ('check_cagnotte_amount', '=', True)]) - journal.check_cagnotte_amount = cagnotte_type_count > 0 - - -class AccountBankStatementLine(models.Model): - _inherit = 'account.bank.statement.line' - - account_cagnotte_id = fields.Many2one('account.cagnotte', 'Cagnotte') - - -class AccountBankStatement(models.Model): - _inherit = 'account.bank.statement' - - @api.model - def _prepare_move_line_vals( - self, st_line, move_id, debit, credit, currency_id=False, - amount_currency=False, account_id=False, partner_id=False): - res = super(AccountBankStatement, self)._prepare_move_line_vals( - st_line, move_id, debit, credit, currency_id=currency_id, - amount_currency=amount_currency, account_id=account_id, - partner_id=partner_id) - res['account_cagnotte_id'] = st_line.account_cagnotte_id.id - return res - - -class AccountCagnotte(models.Model): - _inherit = 'account.cagnotte' - - account_bank_statement_line_ids = fields.One2many( - "account.bank.statement.line", "account_cagnotte_id", - string="Bank Statement") - - @api.one - @api.depends('account_bank_statement_line_ids.journal_entry_id', - 'account_bank_statement_line_ids.amount') - def _compute_solde_cagnotte(self): - super(AccountCagnotte, self)._compute_solde_cagnotte() - solde_cagnotte = self.solde_cagnotte - # remove amount of statement not done - for bs_line in self.account_bank_statement_line_ids: - if not bs_line.journal_entry_id: - solde_cagnotte -= bs_line.amount - self.solde_cagnotte = solde_cagnotte - - -class CagnotteType(models.Model): - _inherit = 'cagnotte.type' - - check_cagnotte_amount = fields.Boolean() diff --git a/pos_cagnotte_coupon/models/account_bank_statement_line.py b/pos_cagnotte_coupon/models/account_bank_statement_line.py new file mode 100644 index 00000000..b4ac4b66 --- /dev/null +++ b/pos_cagnotte_coupon/models/account_bank_statement_line.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import models, fields, api + + +class AccountBankStatementLine(models.Model): + _inherit = 'account.bank.statement.line' + + account_cagnotte_id = fields.Many2one( + comodel_name='account.cagnotte', string="Cagnotte") + + @api.multi + def _prepare_reconciliation_move_line(self, move, amount): + self.ensure_one() + values = super(AccountBankStatementLine, self).\ + _prepare_reconciliation_move_line(move, amount) + account_cagnotte = self.account_cagnotte_id + if account_cagnotte: + values['account_cagnotte_id'] = account_cagnotte.id + return values diff --git a/pos_cagnotte_coupon/models/account_cagnotte.py b/pos_cagnotte_coupon/models/account_cagnotte.py new file mode 100644 index 00000000..bb1ee638 --- /dev/null +++ b/pos_cagnotte_coupon/models/account_cagnotte.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import models, fields, api + + +class AccountCagnotte(models.Model): + _inherit = 'account.cagnotte' + + account_bank_statement_line_ids = fields.One2many( + comodel_name='account.bank.statement.line', + inverse_name='account_cagnotte_id', + string="Bank Statement") + + @api.multi + @api.depends( + 'account_bank_statement_line_ids.journal_entry_ids', + 'account_bank_statement_line_ids.amount') + def _compute_solde_cagnotte(self): + super(AccountCagnotte, self)._compute_solde_cagnotte() + for rec in self: + solde_cagnotte = rec.solde_cagnotte + # remove amount of statement not done + for bs_line in rec.account_bank_statement_line_ids: + if not bs_line.journal_entry_ids: + solde_cagnotte -= bs_line.amount + rec.solde_cagnotte = solde_cagnotte diff --git a/pos_cagnotte_coupon/models/account_journal.py b/pos_cagnotte_coupon/models/account_journal.py new file mode 100644 index 00000000..ed00f80c --- /dev/null +++ b/pos_cagnotte_coupon/models/account_journal.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import models, fields, api + + +class AccountJournal(models.Model): + _inherit = 'account.journal' + + has_cagnotte = fields.Boolean(compute='_compute_has_cagnotte') + check_cagnotte_amount = fields.Boolean( + compute='_compute_check_cagnotte_amount') + + @api.multi + def _compute_has_cagnotte(self): + CagnotteTypeObj = self.env['cagnotte.type'] + for journal in self: + cagnotte_type_count = CagnotteTypeObj.search_count([ + ('journal_id', '=', journal.id), + ('with_coupon_code', '=', True) + ]) + journal.has_cagnotte = cagnotte_type_count > 0 + + @api.multi + def _compute_check_cagnotte_amount(self): + CagnotteTypeObj = self.env['cagnotte.type'] + for journal in self: + cagnotte_type_count = CagnotteTypeObj.search_count([ + ('journal_id', '=', journal.id), + ('with_coupon_code', '=', True), + ('check_cagnotte_amount', '=', True) + ]) + journal.check_cagnotte_amount = cagnotte_type_count > 0 diff --git a/pos_cagnotte_coupon/models/cagnotte_type.py b/pos_cagnotte_coupon/models/cagnotte_type.py new file mode 100644 index 00000000..41225d56 --- /dev/null +++ b/pos_cagnotte_coupon/models/cagnotte_type.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import models, fields + + +class CagnotteType(models.Model): + _inherit = 'cagnotte.type' + + check_cagnotte_amount = fields.Boolean() diff --git a/pos_cagnotte_coupon/models/point_of_sale.py b/pos_cagnotte_coupon/models/point_of_sale.py deleted file mode 100644 index 6e5b6b5b..00000000 --- a/pos_cagnotte_coupon/models/point_of_sale.py +++ /dev/null @@ -1,55 +0,0 @@ -# -*- coding: utf-8 -*- -# © 2015 Laetitia Gangloff, Acsone SA/NV (http://www.acsone.eu) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -from openerp import api, fields, models - - -class POSOrderLine(models.Model): - _inherit = "pos.order.line" - - coupon_code = fields.Char() - account_cagnotte_id = fields.Many2one('account.cagnotte', 'Cagnotte') - - @api.model - def create(self, values): - if values.get('product_id') and not values.get('account_cagnotte_id'): - cagnotte_type = self.env['cagnotte.type'].search( - [('product_id', '=', values['product_id'])]) - if cagnotte_type: - # create cagnotte - cagnotte_vals = {'cagnotte_type_id': cagnotte_type.id} - if values.get('coupon_code'): - cagnotte_vals['coupon_code'] = values['coupon_code'] - values['account_cagnotte_id'] = \ - self.env['account.cagnotte'].create(cagnotte_vals).id - return super(POSOrderLine, self).create(values) - - -class PosOrder(models.Model): - _inherit = "pos.order" - - def _get_product_key(self, values): - product_key = super(PosOrder, self)._get_product_key(values) - return product_key + (values['account_cagnotte_id'], ) - - @api.model - def _get_product_values(self, line, income_account, amount, tax_code_id, - tax_amount, order): - res = super(PosOrder, self)._get_product_values( - line, income_account, amount, tax_code_id, tax_amount, order) - res['account_cagnotte_id'] = line.account_cagnotte_id.id - return res - - @api.model - def _payment_fields(self, ui_paymentline): - res = super(PosOrder, self)._payment_fields(ui_paymentline) - res['account_cagnotte_id'] = ui_paymentline.get('account_cagnotte_id') - return res - - @api.model - def _add_custom_payment_line_info(self, order_id, data): - res = super(PosOrder, self)._add_custom_payment_line_info(order_id, - data) - res['account_cagnotte_id'] = data.get('account_cagnotte_id') - return res diff --git a/pos_cagnotte_coupon/models/pos_order.py b/pos_cagnotte_coupon/models/pos_order.py new file mode 100644 index 00000000..928c885f --- /dev/null +++ b/pos_cagnotte_coupon/models/pos_order.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import models, api + + +class PosOrder(models.Model): + _inherit = 'pos.order' + + def _get_account_move_line_product_key(self, values): + product_key = super(PosOrder, self).\ + _get_account_move_line_product_key(values) + account_cagnotte_id = values.get('account_cagnotte_id') + if account_cagnotte_id: + product_key += (values.get('account_cagnotte_id'), ) + return product_key + + @api.model + def _payment_fields(self, ui_paymentline): + res = super(PosOrder, self)._payment_fields(ui_paymentline) + res['account_cagnotte_id'] = ui_paymentline.get('account_cagnotte_id') + return res + + @api.multi + def _prepare_statement_line_payment_values(self, data): + values = super(PosOrder, self).\ + _prepare_statement_line_payment_values(data) + values['account_cagnotte_id'] = data.get('account_cagnotte_id') + return values + + @api.model + def _prepare_product_account_move_line(self, line, partner_id, account_id): + values = super(PosOrder, self)._prepare_product_account_move_line( + line, partner_id, account_id) + if not values.get('account_cagnotte_id'): + values['account_cagnotte_id'] = getattr( + line.account_cagnotte_id, 'id', False) + return values diff --git a/pos_cagnotte_coupon/models/pos_order_line.py b/pos_cagnotte_coupon/models/pos_order_line.py new file mode 100644 index 00000000..82826416 --- /dev/null +++ b/pos_cagnotte_coupon/models/pos_order_line.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import models, fields, api + + +class PosOrderLine(models.Model): + + _inherit = 'pos.order.line' + + coupon_code = fields.Char() + account_cagnotte_id = fields.Many2one( + comodel_name='account.cagnotte', string="Cagnotte") + + @api.model + def create(self, values): + if values.get('product_id') and not values.get('account_cagnotte_id'): + cagnotte_type = self.env['cagnotte.type'].search( + [('product_id', '=', values['product_id'])]) + if cagnotte_type: + # create cagnotte + cagnotte_vals = {'cagnotte_type_id': cagnotte_type.id} + if values.get('coupon_code'): + cagnotte_vals['coupon_code'] = values['coupon_code'] + values['account_cagnotte_id'] = \ + self.env['account.cagnotte'].create(cagnotte_vals).id + res = super(PosOrderLine, self).create(values) + return res diff --git a/pos_cagnotte_coupon/models/product_product.py b/pos_cagnotte_coupon/models/product_product.py new file mode 100644 index 00000000..f9642ec5 --- /dev/null +++ b/pos_cagnotte_coupon/models/product_product.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import models, fields, api + + +class ProductProduct(models.Model): + + _inherit = 'product.product' + + has_cagnotte = fields.Boolean(compute='_compute_has_cagnotte') + + @api.multi + def _compute_has_cagnotte(self): + CagnotteTypeObj = self.env['cagnotte.type'] + for product in self: + cagnotte_type_count = CagnotteTypeObj.search_count([ + ('product_id', '=', product.id), + ('with_coupon_code', '=', True) + ]) + product.has_cagnotte = cagnotte_type_count > 0 diff --git a/pos_cagnotte_coupon/static/src/css/pos_cagnotte_coupon.css b/pos_cagnotte_coupon/static/src/css/pos_cagnotte_coupon.css index 3b8634b5..5b288a4c 100644 --- a/pos_cagnotte_coupon/static/src/css/pos_cagnotte_coupon.css +++ b/pos_cagnotte_coupon/static/src/css/pos_cagnotte_coupon.css @@ -1,33 +1,33 @@ -.pos .set-coupon-code button { - width: 150px; - height: 60px; - font-size: 18px; - cursor: pointer; - text-align:center; - box-sizing: border-box; - -moz-box-sizing: border-box; - left: 105%; - bottom: 10px; - position: absolute; -} +/*.pos .set-coupon-code button {*/ + /*width: 150px;*/ + /*height: 60px;*/ + /*font-size: 18px;*/ + /*cursor: pointer;*/ + /*text-align:center;*/ + /*box-sizing: border-box;*/ + /*-moz-box-sizing: border-box;*/ + /*left: 105%;*/ + /*bottom: 10px;*/ + /*position: absolute;*/ +/*}*/ -.pos .modal-dialog .popup-set-coupon-code{ - margin-left:0; - margin-top:0; - left:30%; - width: 20%; - top:25%; - height:15%; -} +/*.pos .modal-dialog .popup-set-coupon-code{*/ + /*margin-left:0;*/ + /*margin-top:0;*/ + /*left:30%;*/ + /*width: 20%;*/ + /*top:25%;*/ + /*height:15%;*/ +/*}*/ -.pos .modal-dialog .popup-set-coupon-code .coupon-title{ - height: 25%; -} +/*.pos .modal-dialog .popup-set-coupon-code .coupon-title{*/ + /*height: 25%;*/ +/*}*/ -.pos .modal-dialog .popup-set-coupon-code .coupon-title #coupon-popup-ok{ - margin: -10px 3px 3px 3px; -} +/*.pos .modal-dialog .popup-set-coupon-code .coupon-title #coupon-popup-ok{*/ + /*margin: -10px 3px 3px 3px;*/ +/*}*/ -.pos .modal-dialog .popup-set-coupon-code .coupon-title #coupon-popup-cancel{ - margin: 40px -115px 3px 3px; -} +/*.pos .modal-dialog .popup-set-coupon-code .coupon-title #coupon-popup-cancel{*/ + /*margin: 40px -115px 3px 3px;*/ +/*}*/ diff --git a/pos_cagnotte_coupon/static/src/js/main.js b/pos_cagnotte_coupon/static/src/js/main.js deleted file mode 100644 index b5f1f051..00000000 --- a/pos_cagnotte_coupon/static/src/js/main.js +++ /dev/null @@ -1,258 +0,0 @@ -/* - © 2015 Laetitia Gangloff, Acsone SA/NV (http://www.acsone.eu) - License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -*/ - - -openerp.pos_cagnotte_coupon = function (instance) { - var _t = instance.web._t, - _lt = instance.web._lt; - var QWeb = instance.web.qweb; - var round_di = instance.web.round_decimals; - module = instance.point_of_sale; - - // add has_cagnotte flag on product to avoid merge on it - var _initialize_ = module.PosModel.prototype.initialize; - module.PosModel.prototype.initialize = function(session, attributes){ - self = this; - // Add the load of the field product_product.has_cagnotte - for (var i = 0 ; i < this.models.length; i++){ - if (this.models[i].model == 'product.product'){ - if (this.models[i].fields.indexOf('has_cagnotte') == -1) { - this.models[i].fields.push('has_cagnotte'); - } - } - } - return _initialize_.call(this, session, attributes); - }; - - // Add information relative to cagnotte on order line - var OrderlineParent = module.Orderline; - module.Orderline = module.Orderline.extend({ - initialize: function(attributes, options) { - OrderlineParent.prototype.initialize.apply(this, arguments); - this.coupon_code = false; - }, - // returns the flag has_cagnotte from product - has_cagnotte: function(){ - return this.product.has_cagnotte; - }, - // we do not merge line with cagnotte - can_be_merged_with: function(orderline){ - if(this.has_cagnotte()){ - return false; - }else{ - return OrderlineParent.prototype.can_be_merged_with.apply(this, arguments); - } - }, - // Generates a public identification number for the coupon. - generateUniqueId: function(base) { - var d = new Date().getTime(); - if(window.performance && typeof window.performance.now === "function"){ - d += performance.now(); //use high-precision timer if available - } - var uuid = 'xxxxxxxxxxxx'.replace(/[x]/g, function(c) { - var r = (d + Math.random()*10)%10 | 0; - d = Math.floor(d/10); - return (r).toString(10); - }); - return uuid + base; - }, - // returns the coupon on this orderline - get_coupon_code: function(){ - if(this.has_cagnotte()){ - if(this.has_cagnotte()){ - if(! this.coupon_code){ - this.coupon_code = this.generateUniqueId(this.pos.pos_session.id); - } - return this.coupon_code; - }else{ - return false; - } - } - }, - export_as_JSON: function(){ - var json = OrderlineParent.prototype.export_as_JSON.apply(this,arguments); - json.coupon_code = this.get_coupon_code(); - return json; - }, - }); - - // Add information relative to cagnotte on payment line - var PaymentlineParent = module.Paymentline; - module.Paymentline = module.Paymentline.extend({ - initialize: function(attributes, options) { - PaymentlineParent.prototype.initialize.apply(this, arguments); - this.account_cagnotte_id = false; - this.solde_cagnotte = 0; - this.coupon_code = ''; - }, - //sets the account_cagnotte_id on this payment line - set_coupon: function(coupon){ - this.account_cagnotte_id = coupon.id; - this.solde_cagnotte = round_di(parseFloat(coupon.solde_cagnotte) || 0, this.pos.currency.decimals); - if (coupon.solde_cagnotte <= 0){ - coupon.solde_cagnotte = this.get_amount(); - } - this.coupon_code = coupon.coupon_code; - this.set_amount(Math.min(coupon.solde_cagnotte.toFixed(this.pos.currency.decimals), this.get_amount_str())); - }, - // returns the coupon on this paymentline - get_coupon: function(){ - return this.account_cagnotte_id; - }, - get_coupon_code: function(){ - return this.coupon_code; - }, - get_solde_cagnotte: function(){ - return this.solde_cagnotte; - }, - // returns the flag has_cagnotte from journal - has_cagnotte: function(){ - return this.cashregister.journal.has_cagnotte - }, - // returns the flag has_cagnotte from journal - check_cagnotte_amount: function(){ - return this.cashregister.journal.check_cagnotte_amount - }, - export_as_JSON: function(){ - var json = PaymentlineParent.prototype.export_as_JSON.apply(this,arguments); - json.account_cagnotte_id = this.get_coupon(); - return json; - }, - }); - - module.PaymentScreenWidget.include({ - // Add behaviour on Set coupon Code button on payment line - render_paymentline: function(line){ - el_node = this._super(line); - var self = this; - if (line.cashregister.journal.has_cagnotte){ - el_node.querySelector('.set-coupon-code') - .addEventListener('click', function(){ - self.pos.pos_widget.screen_selector.show_popup('set-coupon-code-popup', line);}); - } - return el_node; - }, - // Re-check coupon usage - validate_order: function(options) { - var self = this; - var cagnotte_not_ok = false; - - var currentOrder = this.pos.get('selectedOrder'); - var plines = currentOrder.get('paymentLines').models; - for (var i = 0; i < plines.length; i++) { - // check cagnotte have coupon attached - if (plines[i].has_cagnotte()){ - if (! plines[i].get_coupon()) { - this.pos_widget.screen_selector.show_popup('error',{ - 'message': _t('Cagnotte without coupon'), - 'comment': _t('You cannot use cagnotte without a coupon.'), - }); - return; - } - if (plines[i].check_cagnotte_amount()){ - if (plines[i].get_amount() > plines[i].get_solde_cagnotte()) { - this.pos_widget.screen_selector.show_popup('error',{ - 'message': _t('Cagnotte with too big amount'), - 'comment': _t('You cannot use cagnotte with amount too big.'), - }); - return; - } - } - } - } - this._super(options); - }, - }); - - module.PosWidget = module.PosWidget.extend({ - /* Overload Section */ - build_widgets: function(){ - this._super(); - this.set_coupon_code_popup = new module.SetCouponCodeWidget(this, {}); - this.set_coupon_code_popup.appendTo($(this.$el)); - this.screen_selector.popup_set['set-coupon-code-popup'] = this.set_coupon_code_popup; - // Hide the popup because all pop up are displayed at the - // beginning by default - this.set_coupon_code_popup.hide(); - }, - }); - - module.SetCouponCodeWidget = module.PopUpWidget.extend({ - template:'SetCouponCodeWidget', - initialize: function() { - this.line = false; - }, - start: function(){ - var self = this; - - // Add behaviour on Cancel Button - this.$('#coupon-popup-cancel').off('click').click(function(){ - this.parentElement.parentElement.children[1].value = null; - self.hide(); - }); - // Add behaviour on Validate Button - this.$('#coupon-popup-ok').off('click').click(function(){ - var input_coupon = this.parentElement.parentElement.children[1]; - var coupon_code = this.parentElement.parentElement.children[1].value; - var Cagnotte = new openerp.Model('account.cagnotte'); - var currentOrder = self.pos.get('selectedOrder'); - var client_id = false; - if (currentOrder.get_client()){ - client_id = currentOrder.get_client().id; - } - // Check coupon is not already set on another payment line - var plines = currentOrder.get('paymentLines').models; - for (var i = 0; i < plines.length; i++) { - // if it is cagnotte - if (plines[i].has_cagnotte()) { - if (plines[i].get_coupon_code() == coupon_code){ - self.pos_widget.screen_selector.show_popup('error',{ - 'message': _t('Coupon not reusable'), - 'comment': _t('The coupon code ' + coupon_code + ' is already use in this order.'), - }); - return; - } - } - } - Cagnotte.query(['solde_cagnotte', 'coupon_code']). - filter([['coupon_code','=',coupon_code], - ['cagnotte_type_id.journal_id', '=', self.line.cashregister.journal_id[0]], - '|', ['cagnotte_type_id.check_cagnotte_amount', '=', false], ['solde_cagnotte', '>', 0], - '|', ['partner_id', '=', false], ['partner_id', '=', client_id]]). - first().then(function (coupon) { - if(coupon){ - var line = self.line; - if(line){ - line.set_coupon(coupon); - line.node.querySelector('input').value = line.amount.toFixed(self.pos.currency.decimals); - } - input_coupon.value = null; - self.hide(); - }else{ - self.pos_widget.screen_selector.show_popup('error',{ - 'message': _t('Coupon not usable'), - 'comment': _t('The coupon code ' + coupon_code + ' is not usable' + - '. Check payment method : ' + self.line.cashregister.journal_id[1] + - '. Check customer'), - }); - return; - } - }, function (err, event) { - event.preventDefault(); - self.pos_widget.screen_selector.show_popup('error',{ - message: _t('Impossible to check coupon'), - comment: _t('Check your internet connection and try again.'), - }); - }); - }); - }, - show: function(line){ - var self = this; - this.line = line; - this._super(); - }, - }); - -}; diff --git a/pos_cagnotte_coupon/static/src/js/models.js b/pos_cagnotte_coupon/static/src/js/models.js new file mode 100644 index 00000000..d71762cc --- /dev/null +++ b/pos_cagnotte_coupon/static/src/js/models.js @@ -0,0 +1,196 @@ +/* + © 2015 Laetitia Gangloff, Acsone SA/NV (http://www.acsone.eu) + License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +*/ + +odoo.define('pos_cagnotte_coupon.models', function (require) { +"use strict"; + + var core = require('web.core'); + var utils = require('web.utils'); + + var _t = core._t; + var round_di = utils.round_decimals; + + var PosModels = require('point_of_sale.models'); + + var PosModel = PosModels.PosModel; + var PosModelSuper = PosModel.prototype; + + var OrderLine = PosModels.Orderline; + var OrderLineSuper = OrderLine.prototype; + + var PaymentLine = PosModels.Paymentline; + var PaymentLineSuper = PaymentLine.prototype; + + // add has_cagnotte flag on product to avoid merge on it + + PosModels.PosModel = PosModel.extend({ + initialize: function(session, attributes) { + var self = this; + self.add_fields_to_read(); + return PosModelSuper.initialize.call(self, session, attributes); + }, + + get_fields_to_add_by_model: function() { + return { + 'product.product': [ + 'has_cagnotte' + ], + 'account.journal': [ + 'has_cagnotte', 'check_cagnotte_amount', + ] + } + }, + + add_fields_to_read: function() { + // Add fields to read + var self = this; + var fields_by_model = self.get_fields_to_add_by_model(); + + var model, model_name, fields_to_add; + for (var i = 0 ; i < self.models.length; i++) { + model = self.models[i]; + model_name = model.model; + + if (model_name in fields_by_model) { + fields_to_add = fields_by_model[model_name]; + _.each(fields_to_add, function(field_name) { + if (model.fields.indexOf(field_name) === -1) { + model.fields.push(field_name); + } + }); + } + } + } + }); + + PosModels.Orderline = OrderLine.extend({ + initialize: function(session, attributes) { + var self = this; + self.coupon_code = false; + return OrderLineSuper.initialize.call(self, session, attributes); + }, + + // returns the flag has_cagnotte from product + has_cagnotte: function() { + var self = this; + return self.product.has_cagnotte; + }, + + // we do not merge line with cagnotte + can_be_merged_with: function(orderline){ + var self = this; + if (self.has_cagnotte()) { + return false; + } else { + return OrderLineSuper.can_be_merged_with.call(self, orderline); + } + }, + + // Generates a public identification number for the coupon. + generateUniqueId: function(base) { + var self = this; + var d = new Date().getTime(); + if(window.performance && typeof window.performance.now === "function"){ + d += performance.now(); //use high-precision timer if available + } + var uuid = 'xxxxxxxxxxxx'.replace(/[x]/g, function(c) { + var r = (d + Math.random() * 10) % 10 | 0; + d = Math.floor(d / 10); + return (r).toString(10); + }); + return uuid + base; + }, + + // returns the coupon on this orderline + get_coupon_code: function() { + var self = this; + if (self.has_cagnotte()) { + if (self.has_cagnotte()) { + if (!self.coupon_code) { + self.coupon_code = self.generateUniqueId(self.pos.pos_session.id); + } + return self.coupon_code; + } + } + return false; + }, + + export_as_JSON: function() { + var self = this; + var json_repr = OrderLineSuper.export_as_JSON.call(self, arguments); + json_repr.coupon_code = self.get_coupon_code(); + return json_repr; + }, + + export_for_printing: function() { + var self = this; + var json_repr = OrderLineSuper.export_for_printing.call(self, arguments); + json_repr.coupon_code = self.get_coupon_code(); + return json_repr; + } + }); + + // Add information relative to cagnotte on payment line + PosModels.Paymentline = PaymentLine.extend({ + initialize: function(attributes, options) { + var self = this; + self.account_cagnotte_id = false; + self.solde_cagnotte = 0; + self.coupon_code = ''; + return PaymentLineSuper.initialize.call(self, attributes, options); + }, + + //sets the account_cagnotte_id on this payment line + set_coupon: function(coupon){ + var self = this; + self.account_cagnotte_id = coupon.id; + self.solde_cagnotte = round_di(parseFloat(coupon.solde_cagnotte) || 0, self.pos.currency.decimals); + if (coupon.solde_cagnotte <= 0){ + coupon.solde_cagnotte = self.get_amount(); + } + self.coupon_code = coupon.coupon_code; + self.set_amount(Math.min(coupon.solde_cagnotte.toFixed(self.pos.currency.decimals), self.pos.get_order().get_due(self))); + }, + + // returns the coupon on this paymentline + get_coupon: function() { + return this.account_cagnotte_id; + }, + + get_coupon_code: function() { + return this.coupon_code; + }, + + get_solde_cagnotte: function() { + return this.solde_cagnotte; + }, + + // returns the flag has_cagnotte from journal + has_cagnotte: function() { + return this.cashregister.journal.has_cagnotte; + }, + + // returns the flag has_cagnotte from journal + check_cagnotte_amount: function() { + return this.cashregister.journal.check_cagnotte_amount; + }, + + export_as_JSON: function() { + var self = this; + var json_repr = PaymentLineSuper.export_as_JSON.call(self, arguments); + json_repr.account_cagnotte_id = self.get_coupon(); + return json_repr; + }, + + export_for_printing: function() { + var self = this; + var json_repr = PaymentLineSuper.export_for_printing.call(self, arguments); + json_repr.account_cagnotte_id = self.get_coupon(); + return json_repr; + } + + }); + +}); diff --git a/pos_cagnotte_coupon/static/src/js/popups.js b/pos_cagnotte_coupon/static/src/js/popups.js new file mode 100644 index 00000000..ddc3217e --- /dev/null +++ b/pos_cagnotte_coupon/static/src/js/popups.js @@ -0,0 +1,111 @@ +odoo.define('pos_cagnotte_coupon.popups', function (require) { +"use strict"; + + var core = require('web.core'); + var Model = require('web.Model'); + var gui = require('point_of_sale.gui'); + var _t = core._t; + + var PopUpWidget = require('point_of_sale.popups'); + + var SetCouponCodeWidget = PopUpWidget.extend({ + template:'SetCouponCodeWidget', + events: { + 'click .close': 'close_popup', + 'click .validate-coupon': 'validate_coupon', + }, + + init: function() { + var self = this; + self._super.apply(self, arguments); + self.ModelCagnotte = new Model('account.cagnotte'); + }, + + close_popup: function() { + var self = this; + self.gui.close_popup(); + }, + + validate_coupon: function() { + var self = this; + var coupon_code = self.get_coupon_value(); + var current_order = self.pos.get('selectedOrder'); + var client_id = self.get_client_id_from_order(current_order); + var journal = self.line.cashregister.journal_id; + var journal_id = journal[0]; + var journal_name = journal[1]; + + var plines = current_order.paymentlines.models; + var pline; + for (var i = 0; i < plines.length; i++) { + pline = plines[i]; + if (pline.has_cagnotte()) { + if (pline.get_coupon_code() === coupon_code) { + self.gui.show_popup('error',{ + 'title': _t('Coupon not reusable'), + 'body': _t('The coupon code ' + coupon_code + ' is already use in this order.'), + }); + return; + } + } + } + + self.ModelCagnotte.query(['solde_cagnotte', 'coupon_code']). + filter([['coupon_code','=', coupon_code], + ['cagnotte_type_id.journal_id', '=', journal_id,], + '|', ['cagnotte_type_id.check_cagnotte_amount', '=', false], ['solde_cagnotte', '>', 0], + '|', ['partner_id', '=', false], ['partner_id', '=', client_id]]). + first().then(function(coupon) { + if (coupon){ + var line = self.line; + if (line) { + line.set_coupon(coupon); + self.payment_screen.reset_input(); + self.payment_screen.order_changes(); + self.payment_screen.render_paymentlines(); + } + self.close_popup(); + } else { + self.gui.show_popup('error',{ + 'title': _t('Coupon not usable'), + 'body': _t('The coupon code ' + coupon_code + ' is not usable' + + '. Check payment method : ' + journal_name + + '. Check customer'), + }); + return; + } + }, function (err, event) { + event.preventDefault(); + self.gui.show_popup('error',{ + title: _t('Impossible to check coupon'), + body: _t('Check your internet connection and try again.'), + }); + }); + + }, + + get_client_id_from_order: function(order) { + var self = this; + var client = order.get_client(); + return !client ? false : client.id; + }, + + get_coupon_value: function() { + var self = this; + return self.$('input.payment-coupon-code').val(); + }, + + show: function(options){ + var self = this; + self.line = options.line; + self.payment_screen = options.payment_screen; + self._super.apply(self, arguments); + }, + }); + + gui.define_popup({name:'set-coupon-code', widget: SetCouponCodeWidget}); + + return { + SetCouponCodeWidget: SetCouponCodeWidget, + } +}); \ No newline at end of file diff --git a/pos_cagnotte_coupon/static/src/js/screens.js b/pos_cagnotte_coupon/static/src/js/screens.js new file mode 100644 index 00000000..398aa52e --- /dev/null +++ b/pos_cagnotte_coupon/static/src/js/screens.js @@ -0,0 +1,112 @@ +odoo.define('pos_cagnotte_coupon.screens', function (require) { +"use strict"; + + var core = require('web.core'); + var _t = core._t; + + var PosScreens = require('point_of_sale.screens'); + var PaymentScreenWidget = PosScreens.PaymentScreenWidget; + + PaymentScreenWidget.include({ + + init: function() { + var self = this; + self._super.apply(self, arguments); + + var keyboard_handler = self.keyboard_handler; + var keyboard_keydown_handler = self.keyboard_keydown_handler; + + // Very dirty but all keydown/keypress events are overriden + // when payment screen is shown + self.keyboard_handler = function(event) { + if(self.allow_custom_keyboard_handler(event)) { + keyboard_handler(event) + } + }; + self.keyboard_keydown_handler = function(event) { + if(self.allow_custom_keyboard_handler(event)) { + keyboard_keydown_handler(event) + } + }; + }, + + allow_custom_keyboard_handler: function(event) { + /* + If coupon popup is open and if current target is the payment + coupon code input, we don't allow the custom keyboard handler. + */ + var self = this; + var allow = true; + if (self.is_coupon_dialog_open()) { + allow = !$(event.target).is('input.payment-coupon-code'); + } + return allow; + }, + + is_coupon_dialog_open: function() { + return !$('div.set-coupon-code-dialog').hasClass('oe_hidden'); + }, + + // Add behavior on Set coupon Code button on payment line + render_paymentlines: function(){ + var self = this; + self._super.apply(self, arguments); + + self.$('.paymentlines-container .set-coupon-code').click(function() { + var $button = $(this); + var line_id = $button.data('cid'); + self.gui.show_popup('set-coupon-code', { + line: self.get_payment_line_by_id(line_id), + payment_screen: self, + }); + }); + }, + + get_payment_line_by_id: function(line_id) { + var self = this; + var currentOrder = self.pos.get('selectedOrder'); + var plines = currentOrder.paymentlines.models; + var line; + for(var i=0; i < plines.length; i++) { + line = plines[i]; + if(line_id === line.cid) { + return line; + } + } + return false; + }, + + validate_order: function(force_validation) { + var self = this; + + var currentOrder = self.pos.get('selectedOrder'); + var plines = currentOrder.paymentlines.models; + var pline; + for (var i = 0; i < plines.length; i++) { + pline = plines[i]; + // check cagnotte have coupon attached + if (pline.has_cagnotte()){ + if (!pline.get_coupon()) { + self.gui.show_popup('error', { + 'title': _t('Cagnotte without coupon'), + 'body': _t('You cannot use cagnotte without a coupon.'), + }); + return; + } + if (pline.check_cagnotte_amount()){ + if (pline.get_amount() > pline.get_solde_cagnotte()) { + self.gui.show_popup('error',{ + 'title': _t('Cagnotte with too big amount'), + 'body': _t('You cannot use cagnotte with amount too big.'), + }); + return; + } + } + } + } + self._super(); + }, + + }); + +}); \ No newline at end of file diff --git a/pos_cagnotte_coupon/static/src/xml/pos.xml b/pos_cagnotte_coupon/static/src/xml/pos.xml index c2b6bc1c..f12983c5 100644 --- a/pos_cagnotte_coupon/static/src/xml/pos.xml +++ b/pos_cagnotte_coupon/static/src/xml/pos.xml @@ -1,34 +1,46 @@ - - - - - - - + + + + + + + + + + - + + + + + + + + + + + -