diff --git a/addons/stock/models/stock_move_line.py b/addons/stock/models/stock_move_line.py
index 1ca78466f3fa82d3fff208db5813551cfa973640..93b194eb44581d6509cc0705320cca539fff29a1 100644
--- a/addons/stock/models/stock_move_line.py
+++ b/addons/stock/models/stock_move_line.py
@@ -600,6 +600,7 @@ class StockMoveLine(models.Model):
             product_id, location_id, lot_id=lot_id, package_id=package_id, owner_id=owner_id, strict=True
         )
         if quantity > available_quantity:
+            quantity = quantity - available_quantity
             # We now have to find the move lines that reserved our now unavailable quantity. We
             # take care to exclude ourselves and the move lines were work had already been done.
             outdated_move_lines_domain = [
diff --git a/addons/stock/tests/test_move2.py b/addons/stock/tests/test_move2.py
index c95175829f2da5957a2f9a77986931a047226d63..d0161415d1b5c903087201e477bfebfa06d945ee 100644
--- a/addons/stock/tests/test_move2.py
+++ b/addons/stock/tests/test_move2.py
@@ -104,6 +104,43 @@ class TestPickShip(TestStockCommon):
         })
         return picking_pick, picking_pack, picking_ship
 
+    def test_unreserve_only_required_quantity(self):
+        product_unreserve = self.env['product.product'].create({
+            'name': 'product unreserve',
+            'type': 'product',
+            'categ_id': self.env.ref('product.product_category_all').id,
+        })
+        stock_location = self.env['stock.location'].browse(self.stock_location)
+        self.env['stock.quant']._update_available_quantity(product_unreserve, stock_location, 4.0)
+        quants = self.env['stock.quant']._gather(product_unreserve, stock_location, strict=True)
+        self.assertEqual(quants[0].reserved_quantity, 0)
+        move = self.MoveObj.create({
+            'name': product_unreserve.name,
+            'product_id': product_unreserve.id,
+            'product_uom_qty': 3,
+            'product_uom': product_unreserve.uom_id.id,
+            'state': 'confirmed',
+            'location_id': self.stock_location,
+            'location_dest_id': self.customer_location,
+        })
+        move._action_assign()
+        self.assertEqual(quants[0].reserved_quantity, 3)
+        move_2 = self.MoveObj.create({
+            'name': product_unreserve.name,
+            'product_id': product_unreserve.id,
+            'product_uom_qty': 2,
+            'quantity_done':2,
+            'product_uom': product_unreserve.uom_id.id,
+            'state': 'confirmed',
+            'location_id': self.stock_location,
+            'location_dest_id': self.customer_location,
+        })
+        move_2._action_assign()
+        move_2._action_done()
+        quants = self.env['stock.quant']._gather(product_unreserve, stock_location, strict=True)
+        self.assertEqual(quants[0].reserved_quantity, 2)
+
+
     def test_mto_moves(self):
         """
             10 in stock, do pick->ship and check ship is assigned when pick is done, then backorder of ship
diff --git a/doc/cla/corporate/stesiconsultingsrl.md b/doc/cla/corporate/stesiconsultingsrl.md
new file mode 100644
index 0000000000000000000000000000000000000000..e4c18fffd31dedd14200c175edea137175c57bd5
--- /dev/null
+++ b/doc/cla/corporate/stesiconsultingsrl.md
@@ -0,0 +1,17 @@
+Italy, 07/03/2023
+
+STeSI Consulting srl agrees to the terms of the Odoo Corporate Contributor License
+Agreement v1.0.
+
+I declare that I am authorized and able to make this agreement and sign this
+declaration.
+
+Signed,
+
+Francesco Moccia moccia.f@stesi.eu https://github.com/stesifrancesco
+
+List of contributors:
+
+Michele Di Croce dicroce.m@stesi.eu https://github.com/micheledic
+Francesco Moccia moccia.f@stesi.eu https://github.com/stesifrancesco
+Arcadio Pinto pinto.a@stesi.eu https://github.com/ArcadioPinto