From 70eae271e6fde288f7d9690049355279b0d16cee Mon Sep 17 00:00:00 2001 From: geomer198 Date: Sat, 20 May 2023 23:10:46 +0300 Subject: [PATCH] [ADD] pos_partner_location_map: Add Module. --- pos_partner_location_map/README.rst | 0 pos_partner_location_map/__init__.py | 1 + pos_partner_location_map/__manifest__.py | 22 ++++ pos_partner_location_map/models/__init__.py | 2 + .../models/pos_session.py | 22 ++++ .../models/res_partner.py | 7 ++ .../readme/CONTRIBUTORS.rst | 2 + .../readme/DESCRIPTION.rst | 2 + pos_partner_location_map/readme/USAGE.rst | 3 + .../static/src/css/map_popup.css | 15 +++ .../static/src/js/PartnerDetailsEdit.esm.js | 53 +++++++++ .../static/src/js/PartnerMapEdit.esm.js | 104 ++++++++++++++++++ .../static/src/js/googleMapInit.esm.js | 16 +++ .../static/src/xml/PartnerDetailsEdit.xml | 53 +++++++++ .../static/src/xml/PartnerMapEdit.xml | 30 +++++ .../views/res_partner_views.xml | 15 +++ .../odoo/addons/pos_partner_location_map | 1 + setup/pos_partner_location_map/setup.py | 6 + 18 files changed, 354 insertions(+) create mode 100644 pos_partner_location_map/README.rst create mode 100644 pos_partner_location_map/__init__.py create mode 100644 pos_partner_location_map/__manifest__.py create mode 100644 pos_partner_location_map/models/__init__.py create mode 100644 pos_partner_location_map/models/pos_session.py create mode 100644 pos_partner_location_map/models/res_partner.py create mode 100644 pos_partner_location_map/readme/CONTRIBUTORS.rst create mode 100644 pos_partner_location_map/readme/DESCRIPTION.rst create mode 100644 pos_partner_location_map/readme/USAGE.rst create mode 100644 pos_partner_location_map/static/src/css/map_popup.css create mode 100644 pos_partner_location_map/static/src/js/PartnerDetailsEdit.esm.js create mode 100644 pos_partner_location_map/static/src/js/PartnerMapEdit.esm.js create mode 100644 pos_partner_location_map/static/src/js/googleMapInit.esm.js create mode 100644 pos_partner_location_map/static/src/xml/PartnerDetailsEdit.xml create mode 100644 pos_partner_location_map/static/src/xml/PartnerMapEdit.xml create mode 100644 pos_partner_location_map/views/res_partner_views.xml create mode 120000 setup/pos_partner_location_map/odoo/addons/pos_partner_location_map create mode 100644 setup/pos_partner_location_map/setup.py diff --git a/pos_partner_location_map/README.rst b/pos_partner_location_map/README.rst new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pos_partner_location_map/__init__.py b/pos_partner_location_map/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/pos_partner_location_map/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/pos_partner_location_map/__manifest__.py b/pos_partner_location_map/__manifest__.py new file mode 100644 index 0000000000..dac31d50c7 --- /dev/null +++ b/pos_partner_location_map/__manifest__.py @@ -0,0 +1,22 @@ +{ + "name": "Point of Sale - Customer Screen", + "version": "16.0.1.0.0", + "category": "Point Of Sale", + "summary": "Point of Sale - Customers can easily interact with point of sale", + "author": "Cetmix,Odoo Community Association (OCA)", + "maintainers": ["geomer198", "CetmixGitDrone"], + "website": "https://github.com/OCA/pos", + "license": "AGPL-3", + "depends": ["base_geolocalize", "point_of_sale"], + "data": [ + "views/res_partner_views.xml", + ], + "assets": { + "point_of_sale.assets": [ + "pos_partner_location_map/static/src/css/*.css", + "pos_partner_location_map/static/src/js/*.esm.js", + "pos_partner_location_map/static/src/xml/*.xml", + ], + }, + "installable": True, +} diff --git a/pos_partner_location_map/models/__init__.py b/pos_partner_location_map/models/__init__.py new file mode 100644 index 0000000000..3d937eb7aa --- /dev/null +++ b/pos_partner_location_map/models/__init__.py @@ -0,0 +1,2 @@ +from . import pos_session +from . import res_partner diff --git a/pos_partner_location_map/models/pos_session.py b/pos_partner_location_map/models/pos_session.py new file mode 100644 index 0000000000..a3ab2e5ac5 --- /dev/null +++ b/pos_partner_location_map/models/pos_session.py @@ -0,0 +1,22 @@ +from odoo import api, models + + +class PosSession(models.Model): + _inherit = "pos.session" + + def _loader_params_res_partner(self): + res = super()._loader_params_res_partner() + res["search_params"]["fields"] += [ + "map_partner_address", + "partner_latitude", + "partner_longitude", + ] + return res + + @api.model + def get_google_map_api_key(self): + return ( + self.env["ir.config_parameter"] + .sudo() + .get_param("base_geolocalize.google_map_api_key", False) + ) diff --git a/pos_partner_location_map/models/res_partner.py b/pos_partner_location_map/models/res_partner.py new file mode 100644 index 0000000000..a80e6d3b9f --- /dev/null +++ b/pos_partner_location_map/models/res_partner.py @@ -0,0 +1,7 @@ +from odoo import fields, models + + +class ResPartner(models.Model): + _inherit = "res.partner" + + map_partner_address = fields.Char() diff --git a/pos_partner_location_map/readme/CONTRIBUTORS.rst b/pos_partner_location_map/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..85f8f88f73 --- /dev/null +++ b/pos_partner_location_map/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +In General Settings -> Integrations enable the Geo Localisation checkbox. +Select provided and add API key. NB: only google maps are currently supported. diff --git a/pos_partner_location_map/readme/DESCRIPTION.rst b/pos_partner_location_map/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..cc9579c1f7 --- /dev/null +++ b/pos_partner_location_map/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +This module allows to select partner address directly on map. +For this Google Maps are used. diff --git a/pos_partner_location_map/readme/USAGE.rst b/pos_partner_location_map/readme/USAGE.rst new file mode 100644 index 0000000000..4e88eb8c07 --- /dev/null +++ b/pos_partner_location_map/readme/USAGE.rst @@ -0,0 +1,3 @@ +In POS open customer list, select a customer and click "Details". +On the customer form click on the "globe" icon and select a location on map. +Click "Save" to save the location. diff --git a/pos_partner_location_map/static/src/css/map_popup.css b/pos_partner_location_map/static/src/css/map_popup.css new file mode 100644 index 0000000000..07ad053314 --- /dev/null +++ b/pos_partner_location_map/static/src/css/map_popup.css @@ -0,0 +1,15 @@ +.partner-map-popup { + max-width: 90% !important; + height: 100% !important; +} + +.partner-map-body { + height: 80% !important; + padding: 0.5rem; +} + +.map-addr-input { + float: left; + margin-top: 10px; + margin-left: 10px; +} diff --git a/pos_partner_location_map/static/src/js/PartnerDetailsEdit.esm.js b/pos_partner_location_map/static/src/js/PartnerDetailsEdit.esm.js new file mode 100644 index 0000000000..29a48309bf --- /dev/null +++ b/pos_partner_location_map/static/src/js/PartnerDetailsEdit.esm.js @@ -0,0 +1,53 @@ +odoo.define("pos_partner_location_map.PartnerDetailsEdit", function (require) { + const PartnerDetailsEdit = require("point_of_sale.PartnerDetailsEdit"); + const Registries = require("point_of_sale.Registries"); + const { + ConnectionLostError, + ConnectionAbortedError, + } = require("@web/core/network/rpc_service"); + const {identifyError} = require("point_of_sale.utils"); + + const PartnerDetailsMapEdit = (PartnerDetailsEdit) => + class PartnerDetailsMapEdit extends PartnerDetailsEdit { + async openMap() { + try { + const {confirmed, payload} = await this.showPopup( + "PartnerMapEdit", + { + partner: this.props.partner, + } + ); + if (confirmed) { + for (const [key, value] of Object.entries(payload)) { + this.props.partner[key] = value; + this.changes[key] = value; + } + this.render(this); + } + } catch (e) { + if ( + identifyError(e) instanceof ConnectionLostError || + ConnectionAbortedError + ) { + this.showPopup("OfflineErrorPopup", { + title: this.env._t("Network Error"), + body: this.env._t( + "Cannot access product information screen if offline." + ), + }); + } else { + this.showPopup("ErrorPopup", { + title: this.env._t("Unknown error"), + body: this.env._t( + "An unknown error prevents us from loading product information." + ), + }); + } + } + } + }; + + Registries.Component.extend(PartnerDetailsEdit, PartnerDetailsMapEdit); + + return PartnerDetailsMapEdit; +}); diff --git a/pos_partner_location_map/static/src/js/PartnerMapEdit.esm.js b/pos_partner_location_map/static/src/js/PartnerMapEdit.esm.js new file mode 100644 index 0000000000..fc973fb1c4 --- /dev/null +++ b/pos_partner_location_map/static/src/js/PartnerMapEdit.esm.js @@ -0,0 +1,104 @@ +odoo.define("pos_partner_location_map.PartnerMapEdit", function (require) { + require("pos_partner_location_map.googleMapInit"); + + const AbstractAwaitablePopup = require("point_of_sale.AbstractAwaitablePopup"); + const Registries = require("point_of_sale.Registries"); + const {useRef, onMounted} = owl; + + /* eslint no-undef: "warn"*/ + class PartnerMapEdit extends AbstractAwaitablePopup { + setup() { + super.setup(); + this.partner = this.props.partner; + this.lat = parseFloat(this.partner.partner_latitude) || 0; + this.lng = parseFloat(this.partner.partner_longitude) || 0; + this.address = this.partner.map_partner_address || ""; + this.mapContainerRef = useRef("map-container"); + this.addrInput = useRef("addr-input"); + this.state = { + mapIsShow: false, + }; + this.geocoder = new google.maps.Geocoder(); + onMounted(() => this.googleMapConfigure()); + } + + googleMapConfigure() { + // Default latLng + const latLng = new google.maps.LatLng(this.lat, this.lng); + this.setAddressByLatLng(this.lat, this.lng); + // Config + const mapOptions = { + zoom: 12, + center: latLng, + }; + // Show Map + this.map = new google.maps.Map(this.mapContainerRef.el, mapOptions); + this.marker = new google.maps.Marker({ + position: latLng, + map: this.map, + draggable: true, + }); + this.addrInput.el.value = this.partner.map_partner_address; + + this.map.addListener("click", (event) => { + const lat = event.latLng.lat(); + const lng = event.latLng.lng(); + this.update_marker(lat, lng); + this.setAddressByLatLng(lat, lng); + }); + } + + setAddressByLatLng(lat, lng) { + if (lat && lng) { + const latLng = new google.maps.LatLng(lat, lng); + this.geocoder.geocode({location: latLng}, (results, status) => { + if (status === google.maps.GeocoderStatus.OK) { + this.address = results[0].formatted_address; + this.addrInput.el.value = this.address; + } + }); + } + } + + update_marker(lat, lng) { + this.lat = lat; + this.lng = lng; + const latLng = new google.maps.LatLng(lat, lng); + this.map.setCenter(latLng); + this.marker.setPosition(latLng); + google.maps.event.trigger(this.map, "resize"); + } + + async getPayload() { + return { + partner_latitude: this.lat, + partner_longitude: this.lng, + map_partner_address: this.address, + }; + } + + setAddressByLocation(address) { + if (address) { + this.geocoder.geocode({address: address}, (results, status) => { + if (status === google.maps.GeocoderStatus.OK) { + this.lat = results[0].geometry.location.lat(); + this.lng = results[0].geometry.location.lng(); + this.address = results[0].formatted_address; + this.addrInput.el.value = this.address; + this.update_marker(this.lat, this.lng); + } + }); + } + } + + inputChange(event) { + this.setAddressByLocation(event.target.value); + } + } + + PartnerMapEdit.template = "PartnerMapEdit"; + + Registries.Component.add(PartnerMapEdit); + + return PartnerMapEdit; +}); diff --git a/pos_partner_location_map/static/src/js/googleMapInit.esm.js b/pos_partner_location_map/static/src/js/googleMapInit.esm.js new file mode 100644 index 0000000000..28c1318b1d --- /dev/null +++ b/pos_partner_location_map/static/src/js/googleMapInit.esm.js @@ -0,0 +1,16 @@ +odoo.define("pos_partner_location_map.googleMapInit", function (require) { + const rpc = require("web.rpc"); + const {loadJS} = require("@web/core/assets"); + + rpc.query({ + model: "pos.session", + method: "get_google_map_api_key", + args: [], + }).then((response) => { + loadJS( + "https://maps.googleapis.com/maps/api/js?key=" + + response + + "&libraries=places" + ); + }); +}); diff --git a/pos_partner_location_map/static/src/xml/PartnerDetailsEdit.xml b/pos_partner_location_map/static/src/xml/PartnerDetailsEdit.xml new file mode 100644 index 0000000000..0f4f54924a --- /dev/null +++ b/pos_partner_location_map/static/src/xml/PartnerDetailsEdit.xml @@ -0,0 +1,53 @@ + + + + + + + + + +
+ Map Address + +
+
+ Lat/Long + + +
+
+
+ +
diff --git a/pos_partner_location_map/static/src/xml/PartnerMapEdit.xml b/pos_partner_location_map/static/src/xml/PartnerMapEdit.xml new file mode 100644 index 0000000000..c188ecd84f --- /dev/null +++ b/pos_partner_location_map/static/src/xml/PartnerMapEdit.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/pos_partner_location_map/views/res_partner_views.xml b/pos_partner_location_map/views/res_partner_views.xml new file mode 100644 index 0000000000..38b6aaf1bb --- /dev/null +++ b/pos_partner_location_map/views/res_partner_views.xml @@ -0,0 +1,15 @@ + + + + + res.partner.location.map.form + res.partner + + +
+ +
+
+
+ +
diff --git a/setup/pos_partner_location_map/odoo/addons/pos_partner_location_map b/setup/pos_partner_location_map/odoo/addons/pos_partner_location_map new file mode 120000 index 0000000000..4b1dc4d9fe --- /dev/null +++ b/setup/pos_partner_location_map/odoo/addons/pos_partner_location_map @@ -0,0 +1 @@ +../../../../pos_partner_location_map \ No newline at end of file diff --git a/setup/pos_partner_location_map/setup.py b/setup/pos_partner_location_map/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/pos_partner_location_map/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)