diff --git a/addons/delivery_mondialrelay/__init__.py b/addons/delivery_mondialrelay/__init__.py new file mode 100644 index 00000000000..35e7c9600c5 --- /dev/null +++ b/addons/delivery_mondialrelay/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- + +from . import models +from . import wizard diff --git a/addons/delivery_mondialrelay/__manifest__.py b/addons/delivery_mondialrelay/__manifest__.py new file mode 100644 index 00000000000..65302a814ba --- /dev/null +++ b/addons/delivery_mondialrelay/__manifest__.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +{ + 'name': "delivery_mondialrelay", + 'summary': """ Let's choose a Point Relais® as shipping address """, + + 'description': """ + This module allow your customer to choose a Point Relais® and use it as shipping address. + This module doesn't implement the WebService. It is only the integration of the widget. + + Delivery price pre-configured is an example, you need to adapt the pricing's rules. + """, + 'category': 'Inventory/Delivery', + 'version': '0.1', + 'depends': ['delivery'], + 'data': [ + 'data/data.xml', + 'views/views.xml', + 'wizard/choose_delivery_carrier_views.xml', + ], + 'assets': { + 'web.assets_backend': [ + 'delivery_mondialrelay/static/src/js/mondialrelay.js', + 'delivery_mondialrelay/static/src/scss/mondialrelay.scss', + ], + }, + 'license': 'LGPL-3', +} diff --git a/addons/delivery_mondialrelay/data/data.xml b/addons/delivery_mondialrelay/data/data.xml new file mode 100644 index 00000000000..826aea363b1 --- /dev/null +++ b/addons/delivery_mondialrelay/data/data.xml @@ -0,0 +1,88 @@ + + + + + + Mondial Relay + MR + service + + + + 5 + order + + + + Mondial Relay + 30 + base_on_rule + rate + + + + + + + + + + + >= + + + + + + Mondial Relay + 31 + base_on_rule + rate + + + + + + + + + + + + + + + + + >= + + + + + + Mondial Relay + 32 + base_on_rule + rate + + + + + + + + + + + + + + + + + >= + + + + + diff --git a/addons/delivery_mondialrelay/models/__init__.py b/addons/delivery_mondialrelay/models/__init__.py new file mode 100644 index 00000000000..35f8120f52d --- /dev/null +++ b/addons/delivery_mondialrelay/models/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- + +from . import delivery_carrier +from . import res_partner +from . import sale_order diff --git a/addons/delivery_mondialrelay/models/delivery_carrier.py b/addons/delivery_mondialrelay/models/delivery_carrier.py new file mode 100644 index 00000000000..2c8b6a69210 --- /dev/null +++ b/addons/delivery_mondialrelay/models/delivery_carrier.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models, api + + +class DeliveryCarrierMondialRelay(models.Model): + _inherit = 'delivery.carrier' + + is_mondialrelay = fields.Boolean(compute='_compute_is_mondialrelay') + mondialrelay_brand = fields.Char(string='Brand Code', default='BDTEST ', groups="base.group_system") + mondialrelay_packagetype = fields.Char(default="24R", groups="base.group_system") # Advanced + + @api.depends('product_id.default_code') + def _compute_is_mondialrelay(self): + for c in self: + c.is_mondialrelay = c.product_id.default_code == "MR" + + def fixed_get_tracking_link(self, picking): + return self.base_on_rule_get_tracking_link(picking) + + def base_on_rule_get_tracking_link(self, picking): + if self.is_mondialrelay: + return 'https://www.mondialrelay.com/public/permanent/tracking.aspx?ens=%(brand)s&exp=%(track)s&language=%(lang)s' % { + 'brand': picking.carrier_id.mondialrelay_brand, + 'track': picking.carrier_tracking_ref, + 'lang': (picking.partner_id.lang or 'fr').split('_')[0], + } + return super().based_on_rule_get_tracking_link(picking) diff --git a/addons/delivery_mondialrelay/models/res_partner.py b/addons/delivery_mondialrelay/models/res_partner.py new file mode 100644 index 00000000000..8952d9e5c5b --- /dev/null +++ b/addons/delivery_mondialrelay/models/res_partner.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models, api + + +class ResPartnerMondialRelay(models.Model): + _inherit = 'res.partner' + + is_mondialrelay = fields.Boolean(compute='_compute_is_mondialrelay') + + @api.depends('ref') + def _compute_is_mondialrelay(self): + for p in self: + p.is_mondialrelay = p.ref and p.ref.startswith('MR#') + + @api.model + def _mondialrelay_search_or_create(self, data): + ref = 'MR#%s' % data['id'] + partner = self.search([ + ('id', 'child_of', self.commercial_partner_id.ids), + ('ref', '=', ref), + # fast check that address always the same + ('street', '=', data['street']), + ('zip', '=', data['zip']), + ]) + if not partner: + partner = self.create({ + 'ref': ref, + 'name': data['name'], + 'street': data['street'], + 'street2': data['street2'], + 'zip': data['zip'], + 'city': data['city'], + 'country_id': self.env.ref('base.%s' % data['country_code']).id, + 'type': 'delivery', + 'parent_id': self.id, + }) + return partner diff --git a/addons/delivery_mondialrelay/models/sale_order.py b/addons/delivery_mondialrelay/models/sale_order.py new file mode 100644 index 00000000000..c492e31fc57 --- /dev/null +++ b/addons/delivery_mondialrelay/models/sale_order.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import models, _ +from odoo.exceptions import UserError + + +class SaleOrderMondialRelay(models.Model): + _inherit = 'sale.order' + + def action_confirm(self): + unmatch = self.filtered(lambda so: so.carrier_id.is_mondialrelay != so.partner_shipping_id.is_mondialrelay) + if unmatch: + error = _('Mondial Relay mismatching between delivery method and shipping address.') + if len(self) > 1: + error += ' (%s)' % ','.join(unmatch.mapped('name')) + raise UserError(error) + return super().action_confirm() diff --git a/addons/delivery_mondialrelay/static/src/img/truck_mr.png b/addons/delivery_mondialrelay/static/src/img/truck_mr.png new file mode 100644 index 00000000000..1810acdcca1 Binary files /dev/null and b/addons/delivery_mondialrelay/static/src/img/truck_mr.png differ diff --git a/addons/delivery_mondialrelay/static/src/js/mondialrelay.js b/addons/delivery_mondialrelay/static/src/js/mondialrelay.js new file mode 100644 index 00000000000..bbb6fd6061a --- /dev/null +++ b/addons/delivery_mondialrelay/static/src/js/mondialrelay.js @@ -0,0 +1,70 @@ +/** @odoo-module **/ + +import AbstractField from 'web.AbstractField'; +import fieldRegistry from 'web.field_registry'; + + +var MondialRelayWidget = AbstractField.extend({ + resetOnAnyFieldChange: true, + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @override + * @private + */ + _render: function () { + if (this.recordData.is_mondialrelay) { + if (!this.mondialRelayInitialized) { + const script = document.createElement('script'); + script.src = "https://widget.mondialrelay.com/parcelshop-picker/jquery.plugin.mondialrelay.parcelshoppicker.min.js"; + script.onload = () => { + this.mondialRelayInitialized = true; + this._loadWidget(); + }; + document.body.appendChild(script); + } else { + this._loadWidget(); + } + } else { + this.$el.hide(); + } + }, + + /** + * + * @private + */ + _loadWidget: function () { + const params = { + Target: "", // required but handled by OnParcelShopSelected + Brand: this.recordData.mondialrelay_brand, + ColLivMod: this.recordData.mondial_realy_colLivMod, + AllowedCountries: this.recordData.mondialrelay_allowed_countries, + PostCode: this.recordData.shipping_zip || '', + Country: this.recordData.shipping_country_code || '', + Responsive: true, + ShowResultsOnMap: true, + AutoSelect: this.recordData.mondialrelay_last_selected_id, + OnParcelShopSelected: (RelaySelected) => { + const values = JSON.stringify({ + 'id': RelaySelected.ID, + 'name': RelaySelected.Nom, + 'street': RelaySelected.Adresse1, + 'street2': RelaySelected.Adresse2, + 'zip': RelaySelected.CP, + 'city': RelaySelected.Ville, + 'country': RelaySelected.Pays, + }); + this._setValue(values); + }, + }; + this.$el.show(); + this.$el.MR_ParcelShopPicker(params); + this.$el.trigger("MR_RebindMap"); + }, + +}); + +fieldRegistry.add("mondialrelay_relay", MondialRelayWidget); diff --git a/addons/delivery_mondialrelay/static/src/scss/mondialrelay.scss b/addons/delivery_mondialrelay/static/src/scss/mondialrelay.scss new file mode 100644 index 00000000000..00e7ed919c5 --- /dev/null +++ b/addons/delivery_mondialrelay/static/src/scss/mondialrelay.scss @@ -0,0 +1,5 @@ +.MRW-Search .MRW-Container { + input.iArg0, input.Arg2 { + display: inline !important, + } +} diff --git a/addons/delivery_mondialrelay/views/views.xml b/addons/delivery_mondialrelay/views/views.xml new file mode 100644 index 00000000000..56566676f51 --- /dev/null +++ b/addons/delivery_mondialrelay/views/views.xml @@ -0,0 +1,41 @@ + + + + + delivery.carrier.form.provider.mondialrelay + delivery.carrier + + + + + + + + + + + delivery.carrier.tree.provider.mondialrelay + delivery.carrier + + + + + + + + + + view_partner_form_mondialrelay + res.partner + + + + + + + + + + + + diff --git a/addons/delivery_mondialrelay/wizard/__init__.py b/addons/delivery_mondialrelay/wizard/__init__.py new file mode 100644 index 00000000000..718862762ba --- /dev/null +++ b/addons/delivery_mondialrelay/wizard/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import choose_delivery_carrier diff --git a/addons/delivery_mondialrelay/wizard/choose_delivery_carrier.py b/addons/delivery_mondialrelay/wizard/choose_delivery_carrier.py new file mode 100644 index 00000000000..70507e63822 --- /dev/null +++ b/addons/delivery_mondialrelay/wizard/choose_delivery_carrier.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models, api, _ +from odoo.tools.json import scriptsafe as json_safe +from odoo.exceptions import ValidationError + + +class ChooseDeliveryCarrier(models.TransientModel): + _inherit = 'choose.delivery.carrier' + + shipping_zip = fields.Char(related='order_id.partner_shipping_id.zip') + shipping_country_code = fields.Char(related='order_id.partner_shipping_id.country_id.code') + + is_mondialrelay = fields.Boolean(compute='_compute_is_mondialrelay') + mondialrelay_last_selected = fields.Char(string="Last Relay Selected") + mondialrelay_last_selected_id = fields.Char(compute='_compute_mr_last_selected_id') + mondialrelay_brand = fields.Char(related='carrier_id.mondialrelay_brand') + mondialrelay_colLivMod = fields.Char(related='carrier_id.mondialrelay_packagetype') + mondialrelay_allowed_countries = fields.Char(compute='_compute_mr_allowed_countries') + + @api.depends('carrier_id') + def _compute_is_mondialrelay(self): + self.ensure_one() + self.is_mondialrelay = self.carrier_id.product_id.default_code == "MR" + + @api.depends('carrier_id', 'order_id.partner_shipping_id') + def _compute_mr_last_selected_id(self): + self.ensure_one() + if self.order_id.partner_shipping_id.is_mondialrelay: + self.mondialrelay_last_selected_id = '%s-%s' % ( + self.shipping_country_code, + self.order_id.partner_shipping_id.ref.lstrip('MR#'), + ) + else: + self.mondialrelay_last_selected_id = '' + + @api.depends('carrier_id') + def _compute_mr_allowed_countries(self): + self.ensure_one() + self.mondialrelay_allowed_countries = ','.join(self.carrier_id.country_ids.mapped('code')).upper() or '' + + def button_confirm(self): + if self.carrier_id.is_mondialrelay: + if not self.mondialrelay_last_selected: + raise ValidationError(_('Please, choose a Parcel Point')) + data = json_safe.loads(self.mondialrelay_last_selected) + partner_shipping = self.order_id.partner_id._mondialrelay_search_or_create({ + 'id': data['id'], + 'name': data['name'], + 'street': data['street'], + 'street2': data['street2'], + 'zip': data['zip'], + 'city': data['city'], + 'country_code': data['country'][:2].lower(), + }) + if partner_shipping != self.order_id.partner_shipping_id: + self.order_id.partner_shipping_id = partner_shipping + self.order_id.onchange_partner_shipping_id() + + return super().button_confirm() diff --git a/addons/delivery_mondialrelay/wizard/choose_delivery_carrier_views.xml b/addons/delivery_mondialrelay/wizard/choose_delivery_carrier_views.xml new file mode 100644 index 00000000000..1333fbc10d4 --- /dev/null +++ b/addons/delivery_mondialrelay/wizard/choose_delivery_carrier_views.xml @@ -0,0 +1,21 @@ + + + + choose.delivery.carrier.form + choose.delivery.carrier + + +
+ +
+ + + + + + + + + + + diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index 86025f97846..53c584c4e78 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -739,6 +739,7 @@ class WebsiteSale(http.Controller): order.partner_shipping_id = partner_id # TDE FIXME: don't ever do this + # -> TDE: you are the guy that did what we should never do in commit e6f038a order.message_partner_ids = [(4, partner_id), (3, request.website.partner_id.id)] if not errors: return request.redirect(kw.get('callback') or '/shop/confirm_order') diff --git a/addons/website_sale/views/templates.xml b/addons/website_sale/views/templates.xml index 978876e343f..839dc9f8cc0 100644 --- a/addons/website_sale/views/templates.xml +++ b/addons/website_sale/views/templates.xml @@ -1223,6 +1223,7 @@ +
@@ -1238,20 +1239,20 @@ -
+
- +
@@ -1287,7 +1288,7 @@
- +