Browse Source

Introduce classes and automatic weight/destination based pricing

The user now simply chooses 'registered letter' or 'letter' and the
calculator determines whihc type of product and what amount of franking
is required.
for/master
Harald Welte 5 years ago
parent
commit
3cb3683a8b
  1. 117
      data/data.xml
  2. 29
      data/delivery_demo.xml
  3. 54
      models/dp_delivery_carrier.py
  4. 13
      models/dp_shipping_service.py
  5. 41
      views/dp_delivery_carrier.xml

117
data/data.xml

@ -7,7 +7,7 @@
<field name="code">20</field>
<field name="cost_price">0.70</field>
<field name="weight">0.020</field>
<field name="international">False</field>
<field name="international">0</field>
</record>
<record forcecreate="True" id="dp_service_natl_kb" model="delivery.carrier.dp.service">
<field name="name">Kompaktbrief</field>
@ -15,7 +15,7 @@
<field name="code">11</field>
<field name="cost_price">0.85</field>
<field name="weight">0.050</field>
<field name="international">False</field>
<field name="international">0</field>
</record>
<record forcecreate="True" id="dp_service_natl_gb" model="delivery.carrier.dp.service">
<field name="name">Großbrief</field>
@ -23,7 +23,7 @@
<field name="code">21</field>
<field name="cost_price">1.45</field>
<field name="weight">0.500</field>
<field name="international">False</field>
<field name="international">0</field>
</record>
<record forcecreate="True" id="dp_service_natl_mb1k" model="delivery.carrier.dp.service">
<field name="name">Maxibrief</field>
@ -31,7 +31,7 @@
<field name="code">31</field>
<field name="cost_price">2.60</field>
<field name="weight">1.000</field>
<field name="international">False</field>
<field name="international">0</field>
</record>
<record forcecreate="True" id="dp_service_natl_mb2k" model="delivery.carrier.dp.service">
<field name="name">Maxibrief bis 2000 g + Zusatzentgelt MBf</field>
@ -39,17 +39,25 @@
<field name="code">41</field>
<field name="cost_price">4.80</field>
<field name="weight">2.000</field>
<field name="international">False</field>
<field name="international">0</field>
</record>
<record forcecreate="True" id="dp_service_natl_kb_ein" model="delivery.carrier.dp.service">
<field name="name">Kompaktbrief Integral + EINSCHREIBEN</field>
<field name="short_name">Kompakt Natl EIN</field>
<field name="code">1017</field>
<field name="cost_price">3.95</field>
<field name="weight">0.050</field>
<field name="international">0</field>
</record>
<record forcecreate="True" id="dp_service_natl_gb_ein" model="delivery.carrier.dp.service">
<field name="name">Großbrief Integral + EINSCHREIBEN</field>
<field name="short_name">Gross Natl EIN</field>
<field name="code">1027</field>
<field name="cost_price">3.95</field>
<field name="weight">0.500</field>
<field name="international">False</field>
<field name="international">0</field>
</record>
<record forcecreate="True" id="dp_service_natl_mb1k_ein" model="delivery.carrier.dp.service">
<field name="name">Maxibrief Integral + EINSCHREIBEN</field>
@ -57,15 +65,25 @@
<field name="code">1037</field>
<field name="cost_price">5.10</field>
<field name="weight">1.000</field>
<field name="international">False</field>
<field name="international">0</field>
</record>
<record forcecreate="True" id="dp_service_natl_mb2k_ein" model="delivery.carrier.dp.service">
<field name="name">Maxibrief Integral + EINSCHREIBEN EINWURF + Zusatzentgelt MBf</field>
<field name="short_name">Maxi Natl 2kg EIN</field>
<field name="code">1042</field>
<field name="cost_price">6.95</field>
<field name="weight">2.000</field>
<field name="international">0</field>
</record>
<record forcecreate="True" id="dp_service_natl_gb_wurf" model="delivery.carrier.dp.service">
<field name="name">Großbrief Integral + EINSCHREIBEN EINWURF</field>
<field name="short_name">Gross Natl WURF</field>
<field name="code">1022</field>
<field name="cost_price">3.60</field>
<field name="weight">0.500</field>
<field name="international">False</field>
<field name="international">0</field>
</record>
<record forcecreate="True" id="dp_service_natl_mb1k_wurf" model="delivery.carrier.dp.service">
<field name="name">Maxibrief Integral + EINSCHREIBEN EINWURF</field>
@ -73,17 +91,65 @@
<field name="code">1032</field>
<field name="cost_price">4.75</field>
<field name="weight">1.000</field>
<field name="international">False</field>
<field name="international">0</field>
</record>
<record forcecreate="True" id="dp_service_intl_sb" model="delivery.carrier.dp.service">
<field name="name">Standardbrief Intern. GK Integral + EINSCHREIBEN</field>
<field name="short_name">Standart Intl EIN</field>
<field name="code">11006</field>
<field name="cost_price">3.40</field>
<field name="weight">0.020</field>
<field name="international">1</field>
</record>
<record forcecreate="True" id="dp_service_intl_kb" model="delivery.carrier.dp.service">
<field name="name">Kompaktbrief Intern. GK</field>
<field name="short_name">Kompakt Intl</field>
<field name="code">10011</field>
<field name="cost_price">1.50</field>
<field name="weight">0.050</field>
<field name="international">1</field>
</record>
<record forcecreate="True" id="dp_service_intl_gb" model="delivery.carrier.dp.service">
<field name="name">Großbrief Intern. GK</field>
<field name="short_name">Gross Intl</field>
<field name="code">10051</field>
<field name="cost_price">3.70</field>
<field name="weight">0.500</field>
<field name="international">1</field>
</record>
<record forcecreate="True" id="dp_service_intl_mb1k" model="delivery.carrier.dp.service">
<field name="name">Maxibrief Intern. bis 1.000g GK</field>
<field name="short_name">Maxi Intl 1kg</field>
<field name="code">10071</field>
<field name="cost_price">7.00</field>
<field name="weight">1.000</field>
<field name="international">1</field>
</record>
<record forcecreate="True" id="dp_service_intl_mb2k" model="delivery.carrier.dp.service">
<field name="name">Maxibrief Intern. bis 2.000g GK</field>
<field name="short_name">Maxi Intl 2kg</field>
<field name="code">10091</field>
<field name="cost_price">17.00</field>
<field name="weight">2.000</field>
<field name="international">1</field>
</record>
<record forcecreate="True" id="dp_service_intl_sb_ein" model="delivery.carrier.dp.service">
<field name="name">Standardbrief Intern. GK Integral + EINSCHREIBEN</field>
<field name="short_name">Standart Intl EIN</field>
<field name="code">11006</field>
<field name="cost_price">3.40</field>
<field name="weight">0.020</field>
<field name="international">1</field>
</record>
<record forcecreate="True" id="dp_service_intl_kb_ein" model="delivery.carrier.dp.service">
<field name="name">Kompaktbrief Intern. GK Integral + EINSCHREIBEN</field>
<field name="short_name">Kompakt Intl EIN</field>
<field name="code">11016</field>
<field name="cost_price">4.00</field>
<field name="weight">0.050</field>
<field name="international">True</field>
<field name="international">1</field>
</record>
<record forcecreate="True" id="dp_service_intl_gb_ein" model="delivery.carrier.dp.service">
<field name="name">Großbrief Intern. GK Integral + EINSCHREIBEN</field>
@ -91,7 +157,7 @@
<field name="code">11056</field>
<field name="cost_price">6.20</field>
<field name="weight">0.500</field>
<field name="international">True</field>
<field name="international">1</field>
</record>
<record forcecreate="True" id="dp_service_intl_mb1k_ein" model="delivery.carrier.dp.service">
<field name="name">Maxibrief Intern. bis 1.000g GK Integral + EINSCHREIBEN</field>
@ -99,7 +165,7 @@
<field name="code">11076</field>
<field name="cost_price">9.50</field>
<field name="weight">1.000</field>
<field name="international">True</field>
<field name="international">1</field>
</record>
<record forcecreate="True" id="dp_service_intl_mb2k_ein" model="delivery.carrier.dp.service">
<field name="name">Maxibrief Intern. bis 2.000g GK Integral + EINSCHREIBEN</field>
@ -107,8 +173,33 @@
<field name="code">11096</field>
<field name="cost_price">19.50</field>
<field name="weight">2.000</field>
<field name="international">True</field>
<field name="international">1</field>
</record>
<record forcecreate="True" id="dp_class_regular" model="delivery.carrier.dp.class">
<field name="name">Standard</field>
<field name="services_natl" eval="[(4, ref('dp_service_natl_sb')),
(4, ref('dp_service_natl_kb')),
(4, ref('dp_service_natl_gb')),
(4, ref('dp_service_natl_mb1k')),
(4, ref('dp_service_natl_mb2k'))]"/>
<field name="services_intl" eval="[(4, ref('dp_service_intl_sb')),
(4, ref('dp_service_intl_kb')),
(4, ref('dp_service_intl_gb')),
(4, ref('dp_service_intl_mb1k')),
(4, ref('dp_service_intl_mb2k'))]"/>
</record>
<record forcecreate="True" id="dp_class_registered" model="delivery.carrier.dp.class">
<field name="name">Registered</field>
<field name="services_natl" eval="[(4, ref('dp_service_natl_kb_ein')),
(4, ref('dp_service_natl_gb_ein')),
(4, ref('dp_service_natl_mb1k_ein')),
(4, ref('dp_service_natl_mb2k_ein'))]"/>
<field name="services_intl" eval="[(4, ref('dp_service_intl_sb_ein')),
(4, ref('dp_service_intl_kb_ein')),
(4, ref('dp_service_intl_gb_ein')),
(4, ref('dp_service_intl_mb1k_ein')),
(4, ref('dp_service_intl_mb2k_ein'))]"/>
</record>
</data>
</openerp>

29
data/delivery_demo.xml

@ -15,21 +15,38 @@
<field name="standard_price">0.0</field>
<field name="list_price">0.0</field>
</record>
<record id="dp_delivery_carrier" model="delivery.carrier">
<field name="name">Deutsche Post Brief</field>
<record id="dp_delivery_carrier_regular" model="delivery.carrier">
<field name="name">Deutsche Post Letter</field>
<field name="normal_price">0</field>
<field name="delivery_type">dp</field>
<field name="partner_id" ref="res_partner_dp"/>
<field name="product_id" ref="product_product_delivery_dp"/>
<field name="dp_service_type" ref=""/>
<field name="dp_service_class" ref="dp_class_regular"/>
<field name="environment">test</field>
<field name="extra_service_price">0</field>
<field name="address_validator">False</field>
<field name="genrate_label">True</field>
<field name="void_shipment">False</field>
<field name="address_validator">0</field>
<field name="genrate_label">1</field>
<field name="void_shipment">0</field>
<field name="uom_id" ref="product.product_uom_kgm"/>
<field name="delivery_uom">KG</field>
<!-- <field name="image" type="base64" file="dp_delivery_carrier/static/src/img/logo-dp.png"/> -->
</record>
<record id="dp_delivery_carrier_registered" model="delivery.carrier">
<field name="name">Deutsche Post Registered Letter</field>
<field name="normal_price">0</field>
<field name="delivery_type">dp</field>
<field name="partner_id" ref="res_partner_dp"/>
<field name="product_id" ref="product_product_delivery_dp"/>
<field name="dp_service_class" ref="dp_class_registered"/>
<field name="environment">test</field>
<field name="extra_service_price">0</field>
<field name="address_validator">0</field>
<field name="genrate_label">1</field>
<field name="void_shipment">0</field>
<field name="uom_id" ref="product.product_uom_kgm"/>
<field name="delivery_uom">KG</field>
<!-- <field name="image" type="base64" file="dp_delivery_carrier/static/src/img/logo-dp.png"/> -->
</record>
</data>
</openerp>

54
models/dp_delivery_carrier.py

@ -77,17 +77,46 @@ class DPDeliveryCarrier(models.Model):
last = last,
address = addr)
def get_services_by_country(self, service_class, country_code):
if country_code == 'DE':
return service_class.services_natl
else:
return service_class.services_intl
# determine lowest-matching-max-weight service within same class
def get_service_by_class(self, recipient, weight, service_class):
services = self.get_services_by_country(service_class, recipient.country_id.code)
lowest_max_weight = 100000
lowest_service = None
for s in services:
if s.weight >= weight and s.weight < lowest_max_weight:
lowest_max_weight = s.weight
lowest_service = s
return lowest_service
# determine the maximum weight (in kg) of any service in this class
def get_class_max_weight(self, service_class):
services = self.get_services_by_country(service_class, recipient.country_id.code)
highest_weight = 0
for s in services:
if highest_weight > hightest_weight:
highest_weight = s.weight
return highest_weight
@api.one
def dp_send_shipping(self, pickings):
config = self._get_config()
order = self.env['sale.order'].search([('name','=',pickings.origin)])
recipient = pickings.partner_id
warehouse = pickings.picking_type_id.warehouse_id.partner_id
service = self.sudo().dp_service_type
weight = self._get_weight(order, pickings)
service = self.get_service_by_class(recipient, weight, self.sudo().dp_service_class)
if not service:
raise Warning("Service not available for weight!")
im = self.conn_auth_im()
im_recipient = self.build_im_addr(im, recipient)
im_sender = self.build_im_addr(im, warehouse)
service = self.sudo().dp_service_type
im.clear_positions()
position = im.build_position(service.code, im_sender, im_recipient)
im.add_position(position)
r = im.checkoutPNG()
@ -107,12 +136,31 @@ class DPDeliveryCarrier(models.Model):
return result
def dp_get_shipping_price_from_so(self, order):
price = 0
config = self._get_config()
recipient = order.partner_shipping_id if order.partner_shipping_id else order.partner_id
warehouse = order.warehouse_id.partner_id
service = self.sudo().dp_service_type
service_class = self.sudo().dp_service_class
# single-package implementation
weight = self._get_weight(order)
service = self.get_service_by_class(recipient, weight, service_class)
if not service:
raise Warning("Service not available for weight!")
return service.cost_price
# compute the maximum weight of any service within class
#class_max_weight = self.get_class_max_weight(service_class)
# compute number of packages and each weight
#weight, weight_limit, last_package, limits = self.get_package_count(class_max_weight, order)
# iterate over list of packages
#for line in range(1, limits+1):
# if last_package and line == limits:
# weight_limit = last_package
# service = self.get_service_by_class(recipient, weight, service_class)
# price += service.cost_price
#return price
@api.one
def dp_get_tracking_link(self, pickings):
return TRACKING_URL

13
models/dp_shipping_service.py

@ -4,7 +4,18 @@ from openerp import api, fields, models
class SMCShippingDp(models.Model):
_inherit="delivery.carrier"
delivery_type = fields.Selection(selection_add=[('dp','Deutsche Post')])
dp_service_type = fields.Many2one(comodel_name = 'delivery.carrier.dp.service', string = 'DP Service')
dp_service_class = fields.Many2one(comodel_name = 'delivery.carrier.dp.class', string = 'DP Service Class')
# New model for DP Classes (regular mail, registered mail, ...)
class SMCShippingDpClass(models.Model):
_name = "delivery.carrier.dp.class"
name = fields.Char(string="Name", required=1)
# list of services in this class for national delivery
services_natl = fields.Many2many(comodel_name = 'delivery.carrier.dp.service',
relation = 'dp_class_natl_services_rel')
# list of services in this class for international delivery
services_intl = fields.Many2many(comodel_name = 'delivery.carrier.dp.service',
relation = 'dp_class_intl_services_rel')
# New model for DP Products/Services (from ProdWS)
class SMCShippingDpService(models.Model):

41
views/dp_delivery_carrier.xml

@ -11,6 +11,7 @@
</xpath>
</field>
</record>
<record id="shipping_dp_form" model="ir.ui.view">
<field name="name">shipping.dp.form</field>
<field name="model">delivery.carrier</field>
@ -19,12 +20,13 @@
<field name="arch" type="xml">
<xpath expr="//group[@name='Delivery Setting']" col='2' position="after">
<group string="DP Shipping Infomation " attrs="{'invisible':[('delivery_type', '!=', 'dp')]}">
<field name="dp_service_type" attrs="{'required':[('delivery_type', '==', 'dp')]}" />
<field name="dp_service_class" attrs="{'required':[('delivery_type', '==', 'dp')]}" />
</group>
</xpath>
</field>
</record>
<!-- Service Type table derived from ProdWS -->
<record id="delivery_carrier_dp_service_form" model="ir.ui.view">
<field name="name">delivery.carrier.dp.service.form</field>
<field name="model">delivery.carrier.dp.service</field>
@ -69,6 +71,35 @@
</tree>
</field>
</record>
<!-- Service Classes -->
<record id="delivery_carrier_dp_class_form" model="ir.ui.view">
<field name="name">delivery.carrier.dp.class.tree</field>
<field name="model">delivery.carrier.dp.class</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form>
<sheet>
<field name="name"/>
<field name="services_natl"/>
<field name="services_intl"/>
</sheet>
</form>
</field>
</record>
<record id="delivery_carrier_dp_class_tree" model="ir.ui.view">
<field name="name">delivery.carrier.dp.class.tree</field>
<field name="model">delivery.carrier.dp.class</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="package">
<field name="name"/>
<field name="services_natl"/>
<field name="services_intl"/>
</tree>
</field>
</record>
<record id="view_dp_shipping_search" model="ir.ui.view">
<field name="name">stock.picking.dp.shipping.search</field>
<field name="model">stock.picking</field>
@ -86,7 +117,15 @@
<field name="view_mode">tree,form</field>
<field name="view_id" ref="delivery_carrier_dp_service_tree"/>
</record>
<record model="ir.actions.act_window" id="action_delivery_carrier_dp_class">
<field name="name">DP Class List</field>
<field name="res_model">delivery.carrier.dp.class</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="delivery_carrier_dp_class_tree"/>
</record>
<menuitem id="menu_shipping_dp" name="DP Services" parent="delivery.menu_delivery" string="Deutsche Post" />
<menuitem id="menu_shipping_dp_service" parent="menu_shipping_dp" string="Service Type" action="action_delivery_carrier_dp_service"/>
<menuitem id="menu_shipping_dp_class" parent="menu_shipping_dp" string="Service Class" action="action_delivery_carrier_dp_class"/>
</data>
</openerp>

Loading…
Cancel
Save