diff --git a/sale_planner_delivery_route/README.rst b/sale_planner_delivery_route/README.rst
new file mode 100644
index 00000000..5d6c252c
--- /dev/null
+++ b/sale_planner_delivery_route/README.rst
@@ -0,0 +1,15 @@
+**************************************************
+Hibou - Sale Planner with Warehouse Delivery Route
+**************************************************
+
+Calculates the closest delivery route during order planning.
+
+For more information and add-ons, visit `Hibou.io `_.
+
+
+=======
+License
+=======
+
+Please see `LICENSE `_.
+Copyright Hibou Corp. 2018
\ No newline at end of file
diff --git a/sale_planner_delivery_route/__init__.py b/sale_planner_delivery_route/__init__.py
new file mode 100644
index 00000000..134df274
--- /dev/null
+++ b/sale_planner_delivery_route/__init__.py
@@ -0,0 +1,2 @@
+from . import wizard
+from . import models
diff --git a/sale_planner_delivery_route/__manifest__.py b/sale_planner_delivery_route/__manifest__.py
new file mode 100644
index 00000000..41a57804
--- /dev/null
+++ b/sale_planner_delivery_route/__manifest__.py
@@ -0,0 +1,29 @@
+{
+ 'name': 'Sale Order Planner - Delivery Route',
+ 'summary': 'Plans to the closest delivery route.',
+ 'version': '11.0.1.0.0',
+ 'author': "Hibou Corp.",
+ 'category': 'Sale',
+ 'license': 'AGPL-3',
+ 'complexity': 'expert',
+ 'images': [],
+ 'website': "https://hibou.io",
+ 'description': """
+Sale Order Planner - Delivery Route
+===================================
+
+Plans to the closest delivery route.
+
+""",
+ 'depends': [
+ 'stock_delivery_route',
+ 'sale_planner',
+ ],
+ 'demo': [],
+ 'data': [
+ 'wizard/order_planner_views.xml',
+ 'views/stock_views.xml',
+ ],
+ 'auto_install': True,
+ 'installable': True,
+}
diff --git a/sale_planner_delivery_route/models/__init__.py b/sale_planner_delivery_route/models/__init__.py
new file mode 100644
index 00000000..12bab770
--- /dev/null
+++ b/sale_planner_delivery_route/models/__init__.py
@@ -0,0 +1 @@
+from . import stock
diff --git a/sale_planner_delivery_route/models/stock.py b/sale_planner_delivery_route/models/stock.py
new file mode 100644
index 00000000..50d6212c
--- /dev/null
+++ b/sale_planner_delivery_route/models/stock.py
@@ -0,0 +1,8 @@
+from odoo import fields, models
+
+
+class DeliveryRoute(models.Model):
+ _inherit = 'stock.warehouse.delivery.route'
+
+ latitude = fields.Float(string='Latitude', digits=(12, 6))
+ longitude = fields.Float(string='Longitude', digits=(12, 6))
diff --git a/sale_planner_delivery_route/tests/__init__.py b/sale_planner_delivery_route/tests/__init__.py
new file mode 100644
index 00000000..25366b57
--- /dev/null
+++ b/sale_planner_delivery_route/tests/__init__.py
@@ -0,0 +1 @@
+from . import test_planner
diff --git a/sale_planner_delivery_route/tests/test_planner.py b/sale_planner_delivery_route/tests/test_planner.py
new file mode 100644
index 00000000..246f865a
--- /dev/null
+++ b/sale_planner_delivery_route/tests/test_planner.py
@@ -0,0 +1,34 @@
+from odoo.addons.sale_planner.tests.test_planner import TestPlanner
+
+
+class TestPlannerRoute(TestPlanner):
+ def setUp(self):
+ super(TestPlannerRoute, self).setUp()
+ self.route_near = self.env['stock.warehouse.delivery.route'].create({
+ 'name': 'Route 1',
+ 'warehouse_id': self.warehouse_1.id,
+ 'latitude': 48.02995,
+ 'longitude': -122.14771,
+ })
+ self.route_far = self.env['stock.warehouse.delivery.route'].create({
+ 'name': 'Route Far',
+ 'warehouse_id': self.warehouse_1.id,
+ 'latitude': 47.82093,
+ 'longitude': -122.31513,
+ })
+
+ def test_planner_creation(self):
+ self.env['sale.order.line'].create({
+ 'order_id': self.so.id,
+ 'product_id': self.product_1.id,
+ 'name': 'demo',
+ })
+ both_wh_ids = self.both_wh_ids()
+ planner = self.env['sale.order.make.plan'].with_context(warehouse_domain=[('id', 'in', both_wh_ids)],
+ skip_plan_shipping=True).create({'order_id': self.so.id})
+ self.assertTrue(planner.planning_option_ids, 'Must have one or more plans.')
+ self.assertEqual(planner.planning_option_ids.delivery_route_id, self.route_near)
+ self.so.partner_id.partner_latitude = 47.82093
+ planner = self.env['sale.order.make.plan'].with_context(warehouse_domain=[('id', 'in', both_wh_ids)],
+ skip_plan_shipping=True).create({'order_id': self.so.id})
+ self.assertEqual(planner.planning_option_ids.delivery_route_id, self.route_far)
diff --git a/sale_planner_delivery_route/views/stock_views.xml b/sale_planner_delivery_route/views/stock_views.xml
new file mode 100644
index 00000000..8fe6a528
--- /dev/null
+++ b/sale_planner_delivery_route/views/stock_views.xml
@@ -0,0 +1,18 @@
+
+
+
+ stock.warehouse.inherit
+ stock.warehouse
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sale_planner_delivery_route/wizard/__init__.py b/sale_planner_delivery_route/wizard/__init__.py
new file mode 100644
index 00000000..235b12a8
--- /dev/null
+++ b/sale_planner_delivery_route/wizard/__init__.py
@@ -0,0 +1 @@
+from . import order_planner
diff --git a/sale_planner_delivery_route/wizard/order_planner.py b/sale_planner_delivery_route/wizard/order_planner.py
new file mode 100644
index 00000000..9bd34833
--- /dev/null
+++ b/sale_planner_delivery_route/wizard/order_planner.py
@@ -0,0 +1,38 @@
+from odoo import api, fields, models
+from odoo.addons.sale_planner.wizard.order_planner import distance
+
+
+class SaleOrderMakePlan(models.TransientModel):
+ _inherit = 'sale.order.make.plan'
+
+ def generate_base_option(self, order_fake):
+ option = super(SaleOrderMakePlan, self).generate_base_option(order_fake)
+ option['delivery_route_id'] = self.find_closest_route(option, order_fake)
+ return option
+
+ def find_closest_route(self, option, order_fake):
+ warehouse = self.env['stock.warehouse'].browse(option['warehouse_id'])
+ if warehouse.delivery_route_ids:
+ partner = order_fake.partner_shipping_id
+ if not partner.date_localization:
+ partner.geo_localize()
+ return self._find_closest_route_id(warehouse.delivery_route_ids,
+ partner.partner_latitude,
+ partner.partner_longitude)
+ return False
+
+ def _find_closest_route_id(self, routes, latitude, longitude):
+ distances = {distance(latitude, longitude, route.latitude, route.longitude): route.id for route in routes}
+ route_id = distances[min(distances)]
+ return route_id
+
+ def _order_fields_for_option(self, option):
+ vals = super(SaleOrderMakePlan, self)._order_fields_for_option(option)
+ vals['delivery_route_id'] = option.delivery_route_id.id
+ return vals
+
+
+class SaleOrderPlanningOption(models.TransientModel):
+ _inherit = 'sale.order.planning.option'
+
+ delivery_route_id = fields.Many2one('stock.warehouse.delivery.route', string='Delivery Route')
diff --git a/sale_planner_delivery_route/wizard/order_planner_views.xml b/sale_planner_delivery_route/wizard/order_planner_views.xml
new file mode 100644
index 00000000..e394a02e
--- /dev/null
+++ b/sale_planner_delivery_route/wizard/order_planner_views.xml
@@ -0,0 +1,13 @@
+
+
+
+ view.plan.sale.order.inherit
+ sale.order.make.plan
+
+
+
+
+
+
+
+
\ No newline at end of file