Save a tech-profile again if it has not been modified (needed to force re-sync)

Change-Id: Id4a360595bdef006d4fc338f495cf48df8400d5d
diff --git a/VERSION b/VERSION
index bdbe651..530cdd9 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.2.4-dev
+2.2.4
diff --git a/xos/synchronizer/models/models.py b/xos/synchronizer/models/models.py
index 5198db2..d5a3cc5 100644
--- a/xos/synchronizer/models/models.py
+++ b/xos/synchronizer/models/models.py
@@ -30,6 +30,7 @@
 
 import json
 
+
 class VOLTService(VOLTService_decl):
     class Meta:
         proxy = True
@@ -72,6 +73,7 @@
         """
         return TechnologyProfile.objects.get(technology=technology, profile_id=profile_id)
 
+
 class OLTDevice(OLTDevice_decl):
     class Meta:
         proxy = True
@@ -114,6 +116,7 @@
 
         super(OLTDevice, self).delete(*args, **kwargs)
 
+
 class ONUDevice(ONUDevice_decl):
     class Meta:
         proxy = True
@@ -125,6 +128,7 @@
 
         super(ONUDevice, self).delete(*args, **kwargs)
 
+
 class TechnologyProfile(TechnologyProfile_decl):
     class Meta:
         proxy = True
@@ -137,7 +141,7 @@
 
         # only synchronizer is allowed to update the model
         if not self.is_new and caller_kind != "synchronizer":
-            if not self.deleted:
+            if not self.deleted and len(self.diff.keys()) > 0:
                 existing = TechnologyProfile.objects.filter(id=self.id)
                 raise XOSValidationError('Modification operation is not allowed on Technology Profile [/%s/%s]. Delete it and add again' % (existing[0].technology, existing[0].profile_id))
 
diff --git a/xos/synchronizer/models/test_models.py b/xos/synchronizer/models/test_models.py
index 5c62143..91e6b2e 100644
--- a/xos/synchronizer/models/test_models.py
+++ b/xos/synchronizer/models/test_models.py
@@ -133,6 +133,7 @@
                          'ONU "1234" can\'t be deleted as it has subscribers associated with it')
         self.models_decl.OLTDevice_decl.delete.assert_not_called()
 
+
 class TestTechnologyProfileModel(unittest.TestCase):
 
     def setUp(self):
@@ -170,10 +171,20 @@
         self.technology_profile.save()
         self.models_decl.TechnologyProfile_decl.save.assert_called()
 
+    def test_allow_save_if_nohing_changed(self):
+        self.technology_profile.is_new = False
+        self.technology_profile.id = 1
+        self.technology_profile.profile_value = '{"name": "someValue", "profile_type": "someValue"}'
+        self.technology_profile.diff.keys.return_value = []
+
+        self.technology_profile.save()
+        self.models_decl.TechnologyProfile_decl.save.assert_called()
+
     def test_prevent_modify(self):
         self.technology_profile.is_new = False
         self.technology_profile.id = 1
         self.technology_profile.profile_value = '{"name": "someValue", "profile_type": "someValue"}'
+        self.technology_profile.diff.keys.return_value = ["some"]
 
         self.models_decl.TechnologyProfile_decl.objects.filter.return_value = [self.technology_profile]