diff --git a/s_attendance/__manifest__.py b/s_attendance/__manifest__.py
index d0d1113c70d945343894e75d2aa401cd3ec7e03d..6fbec0d1d4f6c7188c07a8ee5a9dd6d0209751a7 100644
--- a/s_attendance/__manifest__.py
+++ b/s_attendance/__manifest__.py
@@ -36,6 +36,7 @@
     'assets': {
         'web.assets_backend': [
             's_attendance/static/src/css/custom.css',
+            's_attendance/static/src/js/map_update.js',
         ],
     },
     'images': ['static/description/banner.jpg'],
diff --git a/s_attendance/controllers/attendance_api.py b/s_attendance/controllers/attendance_api.py
index e3a21ae7a4a4843f34651f4c1e719c6a6c84e88b..043aab3bf8418e05060fea8e90fe159e0fa867a4 100644
--- a/s_attendance/controllers/attendance_api.py
+++ b/s_attendance/controllers/attendance_api.py
@@ -10,6 +10,7 @@ import numpy as np
 from .utils import get_message
 from ..utils.distance import caculate_distance
 from ..utils.compare_utils import findCosineDistance
+from odoo.http import Controller, route
 
 _logger = logging.getLogger(__name__)
 
@@ -169,3 +170,8 @@ class TimeKeepingAttendance(odoo.http.Controller):
         if employee_ids and onsite_id and onsite_id.employee_id.id in employee_ids.ids:
             return onsite_id, onsite_id.employee_id
         return None
+
+    @route('/get_api_key', type='http', auth='public', cors='*')
+    def get_api_key(self):
+        api_key = request.env['ir.config_parameter'].sudo().get_param('s_attendance.revgeocode_key')
+        return json.dumps({'api_key': api_key})
diff --git a/s_attendance/static/src/html/here_map.html b/s_attendance/static/src/html/here_map.html
new file mode 100644
index 0000000000000000000000000000000000000000..76a260c724efd377fdcb57a35b35700ce4fa278d
--- /dev/null
+++ b/s_attendance/static/src/html/here_map.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
+    <title>Here Map Integration</title>
+    <script src="https://js.api.here.com/v3/3.1/mapsjs-core.js"></script>
+    <script src="https://js.api.here.com/v3/3.1/mapsjs-service.js"></script>
+    <script src="https://js.api.here.com/v3/3.1/mapsjs-mapevents.js"></script>
+    <script src="https://js.api.here.com/v3/3.1/mapsjs-ui.js"></script>
+    <script src="https://js.api.here.com/v3/3.1/mapsjs-places.js"></script>
+    <style>
+        body {
+          font-family: Arial, sans-serif;
+          margin: 0;
+          padding: 0;
+        }
+        #map {
+          width: 100%;
+          height: 100vh;
+        }
+    </style>
+</head>
+<body>
+<div id="map"></div>
+
+<script type="text/javascript" src='/s_attendance/static/src/js/here_map.js'></script>
+</body>
+</html>
diff --git a/s_attendance/static/src/js/here_map.js b/s_attendance/static/src/js/here_map.js
new file mode 100644
index 0000000000000000000000000000000000000000..d74d78143207fc21b73f1dcc7dd458d734ac4564
--- /dev/null
+++ b/s_attendance/static/src/js/here_map.js
@@ -0,0 +1,92 @@
+async function getApiKey() {
+    try {
+        const baseUrl = window.location.origin;
+        const response = await fetch(`${baseUrl}/get_api_key`, {
+            method: 'GET',
+            headers: {'Content-Type': 'application/json',},
+        });
+        const data = await response.json();
+        return data.api_key;
+    } catch (error) {
+        console.error('Error fetching API key:', error);
+    }
+}
+
+function getQueryParameter(name) {
+    const urlParams = new URLSearchParams(window.location.search);
+    return urlParams.get(name);
+}
+
+const lat = parseFloat(getQueryParameter('lat')) || 0.0;
+const lng = parseFloat(getQueryParameter('lng')) || 0.0;
+
+function addDraggableMarker(map, behavior) {
+    var marker = new H.map.Marker(
+        { lat: lat, lng: lng },
+        {
+            volatility: true,
+        }
+    );
+    marker.draggable = true;
+    map.addObject(marker);
+
+    map.addEventListener('dragstart', function (ev) {
+        var target = ev.target,
+            pointer = ev.currentPointer;
+        if (target instanceof H.map.Marker) {
+            var targetPosition = map.geoToScreen(target.getGeometry());
+            target['offset'] = new H.math.Point(
+                pointer.viewportX - targetPosition.x,
+                pointer.viewportY - targetPosition.y
+            );
+            behavior.disable();
+        }
+    }, false);
+
+    map.addEventListener('dragend', function (ev) {
+        var target = ev.target;
+        if (target instanceof H.map.Marker) {
+            behavior.enable();
+            const position = target.getGeometry();
+            const message = `Marker position: Latitude: ${position.lat}, Longitude: ${position.lng}`;
+            console.log(`${message}`);
+            window.parent.postMessage({ lat: position.lat, lng: position.lng }, '*');
+        }
+    }, false);
+
+    map.addEventListener('drag', function (ev) {
+        var target = ev.target,
+            pointer = ev.currentPointer;
+        if (target instanceof H.map.Marker) {
+            target.setGeometry(
+                map.screenToGeo(
+                    pointer.viewportX - target['offset'].x,
+                    pointer.viewportY - target['offset'].y
+                )
+            );
+        }
+    }, false);
+}
+
+var platform = new H.service.Platform({
+    apikey: getApiKey(),
+});
+
+var defaultLayers = platform.createDefaultLayers();
+
+var map = new H.Map(
+    document.getElementById('map'),
+    defaultLayers.vector.normal.map,
+    {
+        center: { lat: lat, lng: lng },
+        zoom: 12,
+        pixelRatio: window.devicePixelRatio || 1,
+    }
+);
+
+window.addEventListener('resize', () => map.getViewPort().resize());
+
+var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
+var ui = H.ui.UI.createDefault(map, defaultLayers, 'en-US');
+
+addDraggableMarker(map, behavior);
diff --git a/s_attendance/static/src/js/map_update.js b/s_attendance/static/src/js/map_update.js
new file mode 100644
index 0000000000000000000000000000000000000000..67473d90fb1df29484a09fb2e2341748ddc0a919
--- /dev/null
+++ b/s_attendance/static/src/js/map_update.js
@@ -0,0 +1,64 @@
+/** @odoo-module */
+
+import { patch } from "@web/core/utils/patch";
+import { FormController } from "@web/views/form/form_controller";
+import { onWillRender, onMounted } from "@odoo/owl";
+
+patch(FormController.prototype, {
+    setup() {
+        super.setup(...arguments);
+
+        window.addEventListener('message', this._onIframeMessage.bind(this));
+        onMounted(() => this.onWillLoadRoot(this.props.configuration));
+    },
+
+    async onWillLoadRoot() {
+        if (this.props.resModel === "request.onsite") {
+            const latField = document.getElementById("latitude_0")
+            const lngField = document.getElementById("longitude_0")
+            const iframe = document.getElementById("map-iframe")
+
+            if (latField && lngField && iframe) {
+                const lat = parseFloat(latField.value) || 0.0;
+                const lng = parseFloat(lngField.value) || 0.0;
+                iframe.src = `/s_attendance/static/src/html/here_map.html?lat=${lat}&lng=${lng}`;
+            }
+        }
+    },
+
+    async _onIframeMessage(event) {
+        const { lat, lng } = event.data;
+        if (lat && lng) {
+            const model = this.props.resModel;
+
+            const url = await this.orm.call("ir.config_parameter", "get_param", ["s_attendance.revgeocode_url"]);
+            const key = await this.orm.call("ir.config_parameter", "get_param", ["s_attendance.revgeocode_key"]);
+
+            const settings = {
+                url: `${url}?at=${lat},${lng}&lang=vi&apiKey=${key}`,
+                method: "GET",
+                timeout: 0,
+            };
+
+            try {
+                const response = await $.ajax(settings);
+                const title = response.items[0].title;
+
+                const value = {
+                    longitude: lng,
+                    latitude: lat,
+                    address: title
+                };
+
+                await this.orm.write(model, [this.props.context.params.id], value);
+
+                document.getElementById("longitude_0").value = lng;
+                document.getElementById("latitude_0").value = lat;
+                document.getElementById("address_0").value = title;
+
+            } catch (error) {
+                console.error("Error fetching address:", error);
+            }
+        }
+    }
+});
diff --git a/s_attendance/views/request_onsite_view.xml b/s_attendance/views/request_onsite_view.xml
index e7c5df9c8be7dac5df35c0a64dabe3deb1e59062..97d086f8210dddc01f936d65cee3610206f0fb40 100644
--- a/s_attendance/views/request_onsite_view.xml
+++ b/s_attendance/views/request_onsite_view.xml
@@ -67,31 +67,46 @@
                             </group>
                         </group>
                         <group string="Geolocation">
-                            <field name="address" placeholder="Eg. 145 Ngọc Hồi, 10000 Hà Nội, Hà Nội, Vietnam"/>
-                            <label for="date_localization" string="Geo Location"/>
-                            <div>
-                                <span>
-                                    <label for="longitude"/>
-                                    <field name="longitude" nolabel="1" class="oe_inline"/>
-                                </span>
-                                <br/>
-                                <span>
-                                    <label for="latitude"/>
-                                    <field name="latitude" nolabel="1" class="oe_inline"/>
-                                </span>
-                                <br/>
-                                <span modifiers="{'invisible': [('date_localization', '=', False)]}">Updated on:
-                                    <field name="date_localization" nolabel="1" readonly="1" class="oe_inline"/>
+                            <group string="Geolocation">
+                                <field name="address" placeholder="Eg. 145 Ngọc Hồi, 10000 Hà Nội, Hà Nội, Vietnam"/>
+                                <label for="date_localization" string="Geo Location"/>
+                                <div>
+                                    <span>
+                                        <label for="longitude"/>
+                                        <field name="longitude" nolabel="1" class="oe_inline"/>
+                                    </span>
                                     <br/>
-                                </span>
-                                <button modifiers="{'invisible': ['|', ('latitude', '!=', 0), ('longitude', '!=', 0)]}"
-                                        icon="fa-gear" string="Compute based on address" title="Compute Localization"
-                                        name="geo_localize" type="object" class="btn btn-link p-0"/>
-                                <button modifiers="{'invisible': [('latitude', '=', 0), ('longitude', '=', 0)]}"
-                                        icon="fa-refresh" string="Refresh" title="Refresh Localization"
-                                        name="geo_localize" type="object" class="btn btn-link p-0"/>
-                            </div>
+                                    <span>
+                                        <label for="latitude"/>
+                                        <field name="latitude" nolabel="1" class="oe_inline"/>
+                                    </span>
+                                    <br/>
+                                    <span modifiers="{'invisible': [('date_localization', '=', False)]}">Updated on:
+                                        <field name="date_localization" nolabel="1" readonly="1" class="oe_inline"/>
+                                        <br/>
+                                    </span>
+                                    <button modifiers="{'invisible': ['|', ('latitude', '!=', 0), ('longitude', '!=', 0)]}"
+                                            icon="fa-gear" string="Compute based on address"
+                                            title="Compute Localization"
+                                            name="geo_localize" type="object" class="btn btn-link p-0"/>
+                                    <button modifiers="{'invisible': [('latitude', '=', 0), ('longitude', '=', 0)]}"
+                                            icon="fa-refresh" string="Refresh" title="Refresh Localization"
+                                            name="geo_localize" type="object" class="btn btn-link p-0"/>
+                                </div>
+                            </group>
+                            <group string="Maps">
+                                <iframe
+                                        id="map-iframe"
+                                        src="/s_attendance/static/src/html/here_map.html"
+                                        width="600"
+                                        height="450"
+                                        style="border:0;"
+                                        allowfullscreen=""
+                                        loading="lazy"
+                                        referrerpolicy="no-referrer-when-downgrade"/>
+                            </group>
                         </group>
+
                         <group string="Attendance">
                             <field name="attendance_ids" widget="one2many" readonly="0" nolabel="1" colspan="2">
                                 <tree string="Attendance"