diff --git a/docsource/modules140-150.rst b/docsource/modules140-150.rst
index b5bcd799e0e3..be2786b9b97b 100644
--- a/docsource/modules140-150.rst
+++ b/docsource/modules140-150.rst
@@ -170,7 +170,7 @@ Module coverage 14.0 -> 15.0
+-------------------------------------------------+----------------------+-------------------------------------------------+
| google_spreadsheet | | |
+-------------------------------------------------+----------------------+-------------------------------------------------+
-| hr | | |
+| hr | Done | |
+-------------------------------------------------+----------------------+-------------------------------------------------+
| hr_attendance | | |
+-------------------------------------------------+----------------------+-------------------------------------------------+
diff --git a/openupgrade_scripts/scripts/hr/15.0.1.1/noupdate_changes.xml b/openupgrade_scripts/scripts/hr/15.0.1.1/noupdate_changes.xml
index 76b50c2f7f31..7e7ea87b145a 100644
--- a/openupgrade_scripts/scripts/hr/15.0.1.1/noupdate_changes.xml
+++ b/openupgrade_scripts/scripts/hr/15.0.1.1/noupdate_changes.xml
@@ -4,7 +4,7 @@
-
+
diff --git a/openupgrade_scripts/scripts/hr/15.0.1.1/post-migration.py b/openupgrade_scripts/scripts/hr/15.0.1.1/post-migration.py
new file mode 100644
index 000000000000..e36b7f709289
--- /dev/null
+++ b/openupgrade_scripts/scripts/hr/15.0.1.1/post-migration.py
@@ -0,0 +1,62 @@
+from openupgradelib import openupgrade
+
+
+def _map_hr_employee_work_location_to_work_location_id(env):
+ openupgrade.logged_query(
+ env.cr,
+ """
+ WITH work_location_tmp AS (
+ INSERT INTO hr_work_location AS hwl (name, company_id, address_id,
+ active, create_uid, write_uid, create_date, write_date)
+ SELECT emp.work_location, emp.company_id, emp.address_id, TRUE,
+ min(emp.create_uid), min(emp.write_uid), min(emp.create_date),
+ min(emp.write_date)
+ FROM hr_employee emp
+ WHERE emp.address_id IS NOT NULL AND emp.work_location IS NOT NULL
+ GROUP BY emp.work_location, emp.company_id, emp.address_id
+ RETURNING hwl.id, hwl.name, hwl.address_id, hwl.company_id
+ )
+ UPDATE hr_employee emp
+ SET work_location_id = wlt.id
+ FROM work_location_tmp as wlt
+ WHERE wlt.name = emp.work_location
+ AND wlt.address_id = emp.address_id
+ AND wlt.company_id = emp.company_id""",
+ )
+ openupgrade.logged_query(
+ env.cr,
+ """
+ UPDATE hr_work_location hwl
+ SET active = FALSE
+ WHERE hwl.id NOT IN (
+ SELECT DISTINCT emp.work_location_id
+ FROM hr_employee emp
+ WHERE emp.work_location_id IS NOT NULL
+ AND emp.active)""",
+ )
+
+
+def _map_hr_employee_departure_reason_to_departure_reason_id(env):
+ openupgrade.logged_query(
+ env.cr,
+ """
+ UPDATE hr_employee
+ SET departure_reason_id = CASE
+ WHEN departure_reason = 'fired' THEN %s
+ WHEN departure_reason = 'resigned' THEN %s
+ WHEN departure_reason = 'retired' THEN %s
+ END
+ WHERE departure_reason IN ('fired', 'resigned', 'retired')
+ """,
+ (
+ env.ref("hr.departure_fired").id,
+ env.ref("hr.departure_resigned").id,
+ env.ref("hr.departure_retired").id,
+ ),
+ )
+
+
+@openupgrade.migrate()
+def migrate(env, version):
+ _map_hr_employee_work_location_to_work_location_id(env)
+ _map_hr_employee_departure_reason_to_departure_reason_id(env)
diff --git a/openupgrade_scripts/scripts/hr/15.0.1.1/pre-migration.py b/openupgrade_scripts/scripts/hr/15.0.1.1/pre-migration.py
new file mode 100644
index 000000000000..829a352691c7
--- /dev/null
+++ b/openupgrade_scripts/scripts/hr/15.0.1.1/pre-migration.py
@@ -0,0 +1,9 @@
+from openupgradelib import openupgrade
+
+
+@openupgrade.migrate()
+def migrate(env, version):
+ openupgrade.convert_field_to_html(
+ env.cr, "hr_employee", "departure_description", "departure_description"
+ )
+ openupgrade.convert_field_to_html(env.cr, "hr_job", "description", "description")
diff --git a/openupgrade_scripts/scripts/hr/15.0.1.1/upgrade_analysis_work.txt b/openupgrade_scripts/scripts/hr/15.0.1.1/upgrade_analysis_work.txt
new file mode 100644
index 000000000000..de97c20b484a
--- /dev/null
+++ b/openupgrade_scripts/scripts/hr/15.0.1.1/upgrade_analysis_work.txt
@@ -0,0 +1,73 @@
+---Models in module 'hr'---
+new model hr.departure.reason
+new model hr.work.location
+---Fields in module 'hr'---
+hr / hr.department / total_employee (integer) : previously in module hr_holidays
+# NOTHING TO DO: has compute and not store
+
+hr / hr.departure.reason / name (char) : NEW required
+hr / hr.departure.reason / sequence (integer) : NEW hasdefault
+# NOTHING TO DO: new records will be created by hr_data.xml
+
+hr / hr.employee / departure_description (text) : type is now 'html' ('text')
+# DONE post-migration: convert to html
+
+hr / hr.employee / departure_reason (selection) : DEL selection_keys: ['fired', 'resigned', 'retired']
+hr / hr.employee / departure_reason_id (many2one): NEW relation: hr.departure.reason
+# DONE post-migration: map departure_reason with hr.deprture.reason on hr.employee model
+
+hr / hr.employee / driving_license (binary) : NEW attachment: True
+hr / hr.employee / employee_type (selection) : NEW required, selection_keys: ['contractor', 'employee', 'freelance', 'student', 'trainee'], req_default: function, hasdefault
+hr / hr.employee / has_work_permit (binary) : NEW attachment: True
+hr / hr.employee / id_card (binary) : NEW attachment: True
+# NOTHING TO DO: new fields
+
+hr / hr.employee / work_location (char) : DEL
+hr / hr.employee / work_location_id (many2one) : NEW relation: hr.work.location, isfunction: function, stored
+# DONE post-migration: create hr.work.location
+
+hr / hr.employee / work_permit_expiration_date (date): NEW
+hr / hr.employee / work_permit_scheduled_activity (boolean): NEW hasdefault
+hr / hr.job / _order : _order is now 'sequence' ('id')
+# NOTHING TO DO
+
+hr / hr.job / description (text) : type is now 'html' ('text')
+# DONE post-migration: convert to html
+
+hr / hr.job / sequence (integer) : NEW hasdefault
+# NOTHING TO DO
+
+hr / hr.work.location / active (boolean) : NEW hasdefault
+hr / hr.work.location / address_id (many2one) : NEW relation: res.partner, required
+hr / hr.work.location / company_id (many2one) : NEW relation: res.company, required, req_default: function, hasdefault
+hr / hr.work.location / location_number (char) : NEW
+hr / hr.work.location / name (char) : NEW required
+# DONE post-migration: create new records
+
+hr / res.partner / employee_ids (one2many) : NEW relation: hr.employee
+# NOTHING TO DO
+
+---XML records in module 'hr'---
+NEW hr.departure.reason: hr.departure_fired (noupdate)
+NEW hr.departure.reason: hr.departure_resigned (noupdate)
+NEW hr.departure.reason: hr.departure_retired (noupdate)
+NEW ir.actions.act_window: hr.hr_departure_reason_action
+NEW ir.actions.act_window: hr.hr_work_location_action
+NEW ir.cron: hr.ir_cron_data_check_work_permit_validity (noupdate)
+NEW ir.model.access: hr.access_hr_departure_reason
+NEW ir.model.access: hr.access_hr_work_location_manager
+NEW ir.model.access: hr.access_hr_work_location_user
+DEL ir.model.constraint: hr.constraint_hr_employee_barcode_uniq
+DEL ir.model.constraint: hr.constraint_hr_employee_category_name_uniq
+DEL ir.model.constraint: hr.constraint_hr_employee_user_uniq
+DEL ir.model.constraint: hr.constraint_hr_job_name_company_uniq
+NEW ir.ui.menu: hr.menu_hr_departure_reason_tree
+NEW ir.ui.menu: hr.menu_hr_work_location_tree
+NEW ir.ui.view: hr.hr_departure_reason_view_form
+NEW ir.ui.view: hr.hr_departure_reason_view_list
+NEW ir.ui.view: hr.hr_work_location_form_view
+NEW ir.ui.view: hr.hr_work_location_tree_view
+NEW ir.ui.view: hr.res_partner_view_form
+DEL ir.ui.view: hr.assets_backend
+DEL ir.ui.view: hr.qunit_suite
+# NOTHING TO DO