[ADD] (website_sale_)delivery_mondialrelay: allow to use MondialRelay

This commit let you choose a Point Relais® as your shipping address.
It instantiates the Widget only.
It will not handle the print label.

Part-of: odoo/odoo#75281
This commit is contained in:
Jeremy Kersten
2021-08-26 10:21:16 +00:00
parent bd851a24ca
commit e9a33a436f
28 changed files with 736 additions and 14 deletions
+4
View File
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
from . import models
from . import wizard
@@ -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',
}
@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="product_product_delivery_mondialrelay" model="product.product">
<field name="name">Mondial Relay</field>
<field name="default_code">MR</field>
<field name="type">service</field>
<field name="categ_id" ref="delivery.product_category_deliveries"/>
<field name="sale_ok" eval="False"/>
<field name="purchase_ok" eval="False"/>
<field name="list_price">5</field>
<field name="invoice_policy">order</field>
</record>
<record id="delivery_carrier_mondialrelay_be_lu" model="delivery.carrier">
<field name="name">Mondial Relay</field>
<field name="sequence">30</field>
<field name="delivery_type">base_on_rule</field>
<field name="integration_level">rate</field>
<field name="country_ids" eval="[(6, 0, [ref('base.be'), ref('base.lu')])]"/>
<field name="product_id" ref="delivery_mondialrelay.product_product_delivery_mondialrelay"/>
</record>
<record id="delivery_price_rule1" model="delivery.price.rule">
<field name="carrier_id" ref="delivery_carrier_mondialrelay_be_lu"/>
<field name="max_value" eval="10"/>
<field name="list_base_price" eval="4"/>
</record>
<record id="delivery_price_rule2" model="delivery.price.rule">
<field name="carrier_id" ref="delivery_carrier_mondialrelay_be_lu"/>
<field name="operator">&gt;=</field>
<field name="max_value" eval="10"/>
<field name="list_base_price" eval="5"/>
</record>
<record id="delivery_carrier_mondialrelay_fr_nl" model="delivery.carrier">
<field name="name">Mondial Relay</field>
<field name="sequence">31</field>
<field name="delivery_type">base_on_rule</field>
<field name="integration_level">rate</field>
<field name="country_ids" eval="[(6, 0, [ref('base.fr'), ref('base.nl')])]"/>
<field name="product_id" ref="delivery_mondialrelay.product_product_delivery_mondialrelay"/>
</record>
<record id="delivery_price_rule_fr_nl_1" model="delivery.price.rule">
<field name="carrier_id" ref="delivery_carrier_mondialrelay_fr_nl"/>
<field name="max_value" eval="1"/>
<field name="list_base_price" eval="6"/>
</record>
<record id="delivery_price_rule_fr_nl_2" model="delivery.price.rule">
<field name="carrier_id" ref="delivery_carrier_mondialrelay_fr_nl"/>
<field name="max_value" eval="10"/>
<field name="list_base_price" eval="10"/>
</record>
<record id="delivery_price_rule_fr_nl_3" model="delivery.price.rule">
<field name="carrier_id" ref="delivery_carrier_mondialrelay_fr_nl"/>
<field name="operator">&gt;=</field>
<field name="max_value" eval="10"/>
<field name="list_base_price" eval="20"/>
</record>
<record id="delivery_carrier_mondialrelay_es" model="delivery.carrier">
<field name="name">Mondial Relay</field>
<field name="sequence">32</field>
<field name="delivery_type">base_on_rule</field>
<field name="integration_level">rate</field>
<field name="country_ids" eval="[(6, 0, [ref('base.es')])]"/>
<field name="product_id" ref="delivery_mondialrelay.product_product_delivery_mondialrelay"/>
</record>
<record id="delivery_price_rule_es_1" model="delivery.price.rule">
<field name="carrier_id" ref="delivery_carrier_mondialrelay_es"/>
<field name="max_value" eval="3"/>
<field name="list_base_price" eval="10"/>
</record>
<record id="delivery_price_rule_es_2" model="delivery.price.rule">
<field name="carrier_id" ref="delivery_carrier_mondialrelay_es"/>
<field name="max_value" eval="7"/>
<field name="list_base_price" eval="15"/>
</record>
<record id="delivery_price_rule_es_3" model="delivery.price.rule">
<field name="carrier_id" ref="delivery_carrier_mondialrelay_es"/>
<field name="operator">&gt;=</field>
<field name="max_value" eval="10"/>
<field name="list_base_price" eval="28"/>
</record>
</data>
</odoo>
@@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
from . import delivery_carrier
from . import res_partner
from . import sale_order
@@ -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)
@@ -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
@@ -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()
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

@@ -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);
@@ -0,0 +1,5 @@
.MRW-Search .MRW-Container {
input.iArg0, input.Arg2 {
display: inline !important,
}
}
@@ -0,0 +1,41 @@
<odoo>
<data>
<record id="view_delivery_carrier_form_provider_mondialrelay" model="ir.ui.view">
<field name="name">delivery.carrier.form.provider.mondialrelay</field>
<field name="model">delivery.carrier</field>
<field name="inherit_id" ref="delivery.view_delivery_carrier_form"/>
<field name="arch" type="xml">
<field name="product_id" position="after">
<field name="is_mondialrelay" invisible="1" />
<field name="mondialrelay_brand" attrs="{'required': [('is_mondialrelay', '=', True)], 'invisible': [('is_mondialrelay', '!=', True)]}" />
</field>
</field>
</record>
<record id="view_delivery_carrier_tree_provider_mondialrelay" model="ir.ui.view">
<field name="name">delivery.carrier.tree.provider.mondialrelay</field>
<field name="model">delivery.carrier</field>
<field name="inherit_id" ref="delivery.view_delivery_carrier_tree"/>
<field name="arch" type="xml">
<field name="company_id" position="after">
<field name="country_ids" widget="many2many_tags" />
</field>
</field>
</record>
<record id="view_partner_form_mondialrelay" model="ir.ui.view">
<field name="name">view_partner_form_mondialrelay</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<xpath expr="//page[@name='contact_addresses']//kanban/field[@name='display_name']" position="after">
<field name="is_mondialrelay"/>
</xpath>
<xpath expr="//t[@t-set='delivery_icon_path']" position="after">
<t t-set="delivery_icon_path" t-if="record.is_mondialrelay.raw_value" t-value="'/delivery_mondialrelay/static/src/img/truck_mr.png'"/>
</xpath>
</field>
</record>
</data>
</odoo>
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import choose_delivery_carrier
@@ -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()
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="choose_delivery_carrier_view_form" model="ir.ui.view">
<field name="name">choose.delivery.carrier.form</field>
<field name="model">choose.delivery.carrier</field>
<field name="inherit_id" ref="delivery.choose_delivery_carrier_view_form"/>
<field name="arch" type="xml">
<form position="inside">
<field name="is_mondialrelay" invisible="1"/>
<div class="o_zone_widget" attrs="{'invisible': [('is_mondialrelay', '=', False)]}"/>
<field name="mondialrelay_last_selected" widget="mondialrelay_relay"/>
<field name="mondialrelay_last_selected_id" invisible="1"/>
<field name="mondialrelay_brand" invisible="1"/>
<field name="mondialrelay_colLivMod" invisible="1"/>
<field name="mondialrelay_allowed_countries" invisible="1"/>
<field name="shipping_zip" invisible="1"/>
<field name="shipping_country_code" invisible="1"/>
</form>
</field>
</record>
</odoo>
+1
View File
@@ -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')
+24 -11
View File
@@ -1223,6 +1223,7 @@
<t t-set='contact' t-value="order.partner_id"/>
<t t-set='selected' t-value="1"/>
<t t-set='readonly' t-value="1"/>
<t t-set='allow_edit' t-value="1"/>
</t>
</div>
</div>
@@ -1238,20 +1239,20 @@
<div class="col-md-12 col-lg-12 one_kanban">
<form action="/shop/address" method="post" class=''>
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" />
<a role="button" href="#" class='a-submit btn btn-secondary mb16 btn-block'>
<a role="button" href="#" class='a-submit btn btn-secondary mb-2 btn-block'>
<i class="fa fa-plus-square"/>
<span>Add an address</span>
</a>
</form>
</div>
<t t-foreach="shippings" t-as="ship">
<div class="col-md-12 col-lg-6 one_kanban">
<div class="col-md-12 col-lg-6 one_kanban mb-2">
<t t-call="website_sale.address_kanban">
<t t-set="actual_partner" t-value="order.partner_id" />
<t t-set='contact' t-value="ship"/>
<t t-set='selected' t-value="order.partner_shipping_id==ship"/>
<t t-set='readonly' t-value="bool(len(shippings)==1)"/>
<t t-set='edit_billing' t-value="bool(ship==order.partner_id)"/>
<t t-set="allow_edit" t-value="not order.partner_id or (ship.id in order.partner_id.child_ids.ids)" />
</t>
</div>
</t>
@@ -1287,7 +1288,7 @@
</form>
<div t-attf-class="card #{selected and 'border border-primary' or 'js_change_shipping'}">
<div class='card-body' style='min-height: 130px;'>
<a t-if="not actual_partner or (ship.id in actual_partner.child_ids.ids)" href="#" class="btn btn-link float-right p-0 js_edit_address no-decoration" role="button" title="Edit this address" aria-label="Edit this address"><i class='fa fa-edit'/></a>
<a t-if="allow_edit" href="#" class="btn btn-link float-right p-0 js_edit_address no-decoration" role="button" title="Edit this address" aria-label="Edit this address"><i class='fa fa-edit'/></a>
<t t-esc="contact" t-options="dict(widget='contact', fields=['name', 'address'], no_marker=True)"/>
</div>
<div class='card-footer' t-if='not readonly'>
@@ -1476,6 +1477,23 @@
</xpath>
</template>
<template id="address_on_payment" name="Address on payment">
<div class="card">
<div class="card-body" id="shipping_and_billing">
<a class="float-right no-decoration" href="/shop/checkout"><i class="fa fa-edit"/> Edit</a>
<t t-set="same_shipping" t-value="bool(order.partner_shipping_id==order.partner_id or only_services)" />
<div>
<b>Billing<t t-if="same_shipping and not only_services"> &amp; Shipping</t>: </b>
<span t-esc="order.partner_id" t-options="dict(widget='contact', fields=['address'], no_marker=True, separator=', ')" class="address-inline"/>
</div>
<div t-if="not same_shipping and not only_services" groups="sale.group_delivery_invoice_address">
<b>Shipping: </b>
<span t-esc="order.partner_shipping_id" t-options="dict(widget='contact', fields=['address'], no_marker=True, separator=', ')" class="address-inline"/>
</div>
</div>
</div>
</template>
<template id="payment" name="Payment">
<t t-call="website.layout">
<t t-set="additional_title">Shop - Select Payment Acquirer</t>
@@ -1503,13 +1521,8 @@
<t t-call="website_sale.cart_summary"/>
</div>
<div class="col-12 col-xl order-xl-1 oe_cart">
<div class="card">
<div class="card-body" id="shipping_and_billing">
<a class='float-right no-decoration' href='/shop/checkout'><i class="fa fa-edit"/> Edit</a>
<t t-set="same_shipping" t-value="bool(order.partner_shipping_id==order.partner_id or only_services)" />
<div><b>Billing<t t-if="same_shipping and not only_services"> &amp; Shipping</t>: </b><span t-esc='order.partner_id' t-options="dict(widget='contact', fields=['address'], no_marker=True, separator=', ')" class="address-inline"/></div>
<div t-if="not same_shipping and not only_services" groups="sale.group_delivery_invoice_address"><b>Shipping: </b><span t-esc='order.partner_shipping_id' t-options="dict(widget='contact', fields=['address'], no_marker=True, separator=', ')" class="address-inline"/></div>
</div>
<div id='address_on_payment'>
<t t-call="website_sale.address_on_payment"/>
</div>
<div class="oe_structure clearfix mt-3" id="oe_structure_website_sale_payment_1"/>
@@ -36,7 +36,7 @@
</t>
</template>
<template id="payment_delivery" name="Delivery Costs" inherit_id="website_sale.payment">
<template id="payment_delivery_shipping_method" name="Delivery Shipping method" inherit_id="website_sale.address_on_payment">
<xpath expr="//div[@id='shipping_and_billing']" position="inside">
<t t-set="delivery_nb" t-value="deliveries and len(deliveries)"/>
<div t-if="delivery_nb == 1" id="delivery_carrier" class="mt4">
@@ -46,6 +46,9 @@
</t>
</div>
</xpath>
</template>
<template id="payment_delivery" name="Delivery Costs" inherit_id="website_sale.payment">
<xpath expr="//div[@id='payment_method']" position="before">
<div t-if="deliveries" id="delivery_carrier">
<t t-set="delivery_nb" t-value="len(deliveries)"/>
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
from . import controllers
from . import models
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
{
'name': "website_sale_delivery_mondialrelay",
'summary': """ Let's choose Point Relais® on your ecommerce """,
'description': """
This module allow your customer to choose a Point Relais® and use it as shipping address.
""",
'category': 'Website/Website',
'version': '0.1',
'depends': ['website_sale_delivery', 'delivery_mondialrelay'],
'data': [
'views/templates.xml',
],
'assets': {
'web.assets_frontend': [
'website_sale_delivery_mondialrelay/static/src/js/website_sale_delivery_mondialrelay.js',
],
},
'license': 'LGPL-3',
'auto_install': True,
}
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import controllers
@@ -0,0 +1,87 @@
# -*- coding: utf-8 -*-
from odoo import http, _
from odoo.addons.website_sale.controllers.main import WebsiteSale, PaymentPortal
from odoo.addons.website_sale_delivery.controllers.main import WebsiteSaleDelivery
from odoo.exceptions import AccessDenied, ValidationError, UserError
from odoo.http import request
class MondialRelay(http.Controller):
@http.route(['/website_sale_delivery_mondialrelay/update_shipping'], type='json', auth="public", website=True)
def mondial_relay_update_shipping(self, **data):
order = request.website.sale_get_order()
if order.partner_id == request.website.user_id.sudo().partner_id:
raise AccessDenied('Customer of the order cannot be the public user at this step.')
if order.carrier_id.country_ids:
country_is_allowed = data['Pays'][:2].upper() in order.carrier_id.country_ids.mapped(lambda c: c.code.upper())
assert country_is_allowed, _("%s is not allowed for this delivery carrier.", data['Pays'])
partner_shipping = order.partner_id.sudo()._mondialrelay_search_or_create({
'id': data['ID'],
'name': data['Nom'],
'street': data['Adresse1'],
'street2': data['Adresse2'],
'zip': data['CP'],
'city': data['Ville'],
'country_code': data['Pays'][:2].lower(),
})
if order.partner_shipping_id != partner_shipping:
order.partner_shipping_id = partner_shipping
order.onchange_partner_shipping_id()
return {
'address': request.env['ir.qweb']._render('website_sale.address_on_payment', {
'order': order,
'only_services': order and order.only_services,
}),
'new_partner_shipping_id': order.partner_shipping_id.id,
}
class WebsiteSaleMondialrelay(WebsiteSale):
@http.route()
def address(self, **kw):
res = super().address(**kw)
Partner_sudo = request.env['res.partner'].sudo()
partner_id = res.qcontext.get('partner_id', 0)
if partner_id > 0 and Partner_sudo.browse(partner_id).is_mondialrelay:
raise UserError(_('You cannot edit the address of a Point Relais®.'))
return res
class WebsiteSaleDeliveryMondialrelay(WebsiteSaleDelivery):
def _update_website_sale_delivery_return(self, order, **post):
res = super()._update_website_sale_delivery_return(order, **post)
if order.carrier_id.is_mondialrelay:
res['mondial_relay'] = {
'brand': order.carrier_id.mondialrelay_brand,
'col_liv_mod': order.carrier_id.mondialrelay_packagetype,
'partner_zip': order.partner_shipping_id.zip,
'partner_country_code': order.partner_shipping_id.country_id.code.upper(),
'allowed_countries': ','.join(order.carrier_id.country_ids.mapped('code')).upper(),
}
if order.partner_shipping_id.is_mondialrelay:
res['mondial_relay']['current'] = '%s-%s' % (
res['mondial_relay']['partner_country_code'],
order.partner_shipping_id.ref.lstrip('MR#'),
)
return res
class PaymentPortalMondialRelay(PaymentPortal):
@http.route()
def shop_payment_transaction(self, *args, **kwargs):
order = request.website.sale_get_order()
if order.partner_shipping_id.is_mondialrelay and not order.carrier_id.is_mondialrelay:
raise ValidationError(_('Point Relais® can only be used with the delivery method Mondial Relay.'))
elif not order.partner_shipping_id.is_mondialrelay and order.carrier_id.is_mondialrelay:
raise ValidationError(_('Delivery method Mondial Relay can only ship to Point Relais®.'))
return super().shop_payment_transaction(*args, **kwargs)
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import website
@@ -0,0 +1,17 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models
class WebsiteMondialRelay(models.Model):
_inherit = 'website'
def _prepare_sale_order_values(self, partner, pricelist):
self.ensure_one()
values = super()._prepare_sale_order_values(partner, pricelist)
# never use Mondial Relay shipping address as default.
shipping_address = self.env['res.partner'].browse(values['partner_shipping_id'])
if shipping_address.id != values['partner_invoice_id'] and shipping_address.is_mondialrelay:
values['partner_shipping_id'] = values['partner_invoice_id']
return values
Binary file not shown.

After

Width:  |  Height:  |  Size: 985 B

@@ -0,0 +1,105 @@
/** @odoo-module **/
import publicWidget from "web.public.widget";
import "website_sale_delivery.checkout";
import {qweb as QWeb} from "web.core";
const WebsiteSaleDeliveryWidget = publicWidget.registry.websiteSaleDelivery;
WebsiteSaleDeliveryWidget.include({
xmlDependencies: (WebsiteSaleDeliveryWidget.prototype.xmlDependencies || []).concat([
'/website_sale_delivery_mondialrelay/static/src/xml/website_sale_delivery_mondialrelay.xml',
]),
events: _.extend({
"click #btn_confirm_relay": "_onClickBtnConfirmRelay",
}, WebsiteSaleDeliveryWidget.prototype.events),
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* Loads Mondial Relay the first time, else show it.
*
* @override
*/
_handleCarrierUpdateResult: function (result) {
this._super(...arguments);
if (result.mondial_relay) {
if (!$('#modal_mondialrelay').length) {
this._loadMondialRelayModal(result);
} else {
this.$modal_mondialrelay.find('#btn_confirm_relay').toggleClass('disabled', !result.mondial_relay.current);
this.$modal_mondialrelay.modal('show');
}
}
},
/**
* This method render the modal, and inject it in dom with the Modial Relay Widgets script.
* Once script loaded, it initialize the widget pre-configured with the information of result
*
* @private
*
* @param {Object} result: dict returned by call of _update_website_sale_delivery_return (python)
*/
_loadMondialRelayModal: function (result) {
// add modal to body and bind 'save' button
$(QWeb.render('website_sale_delivery_mondialrelay', {})).appendTo('body');
this.$modal_mondialrelay = $('#modal_mondialrelay');
this.$modal_mondialrelay.find('#btn_confirm_relay').on('click', this._onClickBtnConfirmRelay.bind(this));
// load mondial relay script
const script = document.createElement('script');
script.src = "https://widget.mondialrelay.com/parcelshop-picker/jquery.plugin.mondialrelay.parcelshoppicker.min.js";
script.onload = () => {
// instanciate MondialRelay widget
const params = {
Target: "", // required but handled by OnParcelShopSelected
Brand: result.mondial_relay.brand,
ColLivMod: result.mondial_relay.col_liv_mod,
AllowedCountries: result.mondial_relay.allowed_countries,
Country: result.mondial_relay.partner_country_code,
PostCode: result.mondial_relay.partner_zip,
Responsive: true,
ShowResultsOnMap: true,
AutoSelect: result.mondial_relay.current,
OnParcelShopSelected: (RelaySelected) => {
this.lastRelaySelected = RelaySelected;
this.$modal_mondialrelay.find('#btn_confirm_relay').removeClass('disabled');
},
};
this.$modal_mondialrelay.find('#o_zone_widget').MR_ParcelShopPicker(params);
this.$modal_mondialrelay.modal('show');
this.$modal_mondialrelay.find('#o_zone_widget').trigger("MR_RebindMap");
};
document.body.appendChild(script);
},
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
/**
* Update the shipping address on the order and refresh the UI.
*
* @private
*
*/
_onClickBtnConfirmRelay: function () {
if (!this.lastRelaySelected) {
return;
}
this._rpc({
route: '/website_sale_delivery_mondialrelay/update_shipping',
params: {
...this.lastRelaySelected,
},
}).then((o) => {
$('#address_on_payment').html(o.address);
this.$modal_mondialrelay.modal('hide');
});
},
});
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-name="website_sale_delivery_mondialrelay">
<div class="modal fade" id="modal_mondialrelay" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<div class="h5 modal-title">Choose your Parcel Point</div>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span>×</span>
</button>
</div>
<div class="modal-body">
<div class="w-100" id="o_zone_widget">
<!-- here will be instancied the Widget -->
</div>
</div>
<footer class="modal-footer">
<button type="button" id="btn_confirm_relay" class="btn btn-primary disabled" aria-label="Choose this Parcel Point">Send to this Parcel Point</button>
<button type="button" class="btn" data-dismiss="modal" aria-label="Cancel">Cancel</button>
</footer>
</div>
</div>
</div>
</t>
</templates>
@@ -0,0 +1,25 @@
<odoo>
<data>
<template id="website_sale_delivery_mondialrelay_address_on_payment" inherit_id="website_sale.address_on_payment">
<xpath expr="//span[@t-esc='order.partner_shipping_id']" position="before">
<t t-if="order.partner_shipping_id.is_mondialrelay" >
<img src="/website_sale_delivery_mondialrelay/static/src/img/logo.png" title="Mondial Relay" height="20px" />
</t>
</xpath>
</template>
<template id="website_sale_delivery_mondialrelay_checkout" inherit_id="website_sale.checkout">
<xpath expr="//t[@t-set='allow_edit']" position="after">
<t t-set="allow_edit" t-value="allow_edit and not contact.is_mondialrelay"/>
</xpath>
</template>
<template id="website_sale_delivery_mondialrelay_address_kanban" inherit_id="website_sale.address_kanban">
<xpath expr="//t[@t-esc='contact']" position="before">
<t t-if="contact.is_mondialrelay">
<img class="float-right" title="Mondial Relay" height="20px" src="/website_sale_delivery_mondialrelay/static/src/img/logo.png" />
</t>
</xpath>
</template>
</data>
</odoo>
+4 -2
View File
@@ -271,8 +271,10 @@
<div class="o_kanban_image">
<img alt="Contact image" t-if="record.image_128.raw_value" t-att-src="kanban_image('res.partner', 'image_128', record.id.raw_value)"/>
<t t-if="!record.image_128.raw_value">
<img alt="Delivery" t-if="record.type.raw_value === 'delivery'" t-att-src='_s + "/base/static/img/truck.png"'/>
<img alt="Invoice" t-if="record.type.raw_value === 'invoice'" t-att-src='_s + "/base/static/img/money.png"'/>
<t t-set="delivery_icon_path" t-value="'/base/static/img/truck.png'"/>
<t t-set="invoice_icon_path" t-value="'/base/static/img/money.png'"/>
<img alt="Delivery" t-if="record.type.raw_value === 'delivery'" t-att-src='_s + delivery_icon_path'/>
<img alt="Invoice" t-if="record.type.raw_value === 'invoice'" t-att-src='_s + invoice_icon_path'/>
<t t-if="record.type.raw_value !== 'invoice' &amp;&amp; record.type.raw_value !== 'delivery'">
<img alt="Logo" t-if="record.is_company.raw_value === true" t-att-src='_s + "/base/static/img/company_image.png"'/>
<img alt="Avatar" t-if="record.is_company.raw_value === false" t-att-src='_s + "/base/static/img/avatar_grey.png"'/>