diff --git a/taiga/projects/history/mixins.py b/taiga/projects/history/mixins.py index 6131adb7..fef14c9e 100644 --- a/taiga/projects/history/mixins.py +++ b/taiga/projects/history/mixins.py @@ -6,7 +6,7 @@ # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # -# This program is distributed in the hope that it will be useful, +# This program is distributed in the hope that it will be useful,60 # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. @@ -67,7 +67,7 @@ class HistoryResourceMixin(object): self.__object_saved = True def post_save(self, obj, created=False): - self.persist_history_snapshot(obj) + self.persist_history_snapshot(obj=obj) super().post_save(obj, created=created) def pre_delete(self, obj): diff --git a/taiga/projects/milestones/serializers.py b/taiga/projects/milestones/serializers.py index c82d90b9..b5f5e188 100644 --- a/taiga/projects/milestones/serializers.py +++ b/taiga/projects/milestones/serializers.py @@ -25,9 +25,22 @@ from . import models class MilestoneSerializer(serializers.ModelSerializer): user_stories = UserStorySerializer(many=True, required=False) - closed_points = serializers.FloatField(source='closed_points', required=False) - client_increment_points = serializers.FloatField(source='client_increment_points', required=False) - team_increment_points = serializers.FloatField(source='team_increment_points', required=False) + total_points = serializers.SerializerMethodField('get_total_points') + closed_points = serializers.SerializerMethodField('get_closed_points') + client_increment_points = serializers.SerializerMethodField('get_client_increment_points') + team_increment_points = serializers.SerializerMethodField('get_team_increment_points') class Meta: model = models.Milestone + + def get_total_points(self, obj): + return sum(obj.total_points.values()) + + def get_closed_points(self, obj): + return sum(obj.closed_points.values()) + + def get_client_increment_points(self, obj): + return sum(obj.client_increment_points.values()) + + def get_team_increment_points(self, obj): + return sum(obj.team_increment_points.values()) diff --git a/taiga/projects/occ/mixins.py b/taiga/projects/occ/mixins.py index e10bf386..95ac8b1c 100644 --- a/taiga/projects/occ/mixins.py +++ b/taiga/projects/occ/mixins.py @@ -28,7 +28,8 @@ class OCCResourceMixin(object): def pre_save(self, obj): current_version = obj.version param_version = self.request.DATA.get('version', None) - if current_version != param_version: + + if obj.id is not None and current_version != param_version: raise exc.WrongArguments({"version": "The version doesn't match with the current one"}) if obj.id: diff --git a/tests/integration/test_occ.py b/tests/integration/test_occ.py index 8433d5aa..e5ed1ee8 100644 --- a/tests/integration/test_occ.py +++ b/tests/integration/test_occ.py @@ -29,6 +29,7 @@ from .. import factories as f pytestmark = pytest.mark.django_db + def test_invalid_concurrent_save_for_issue(client): user = f.UserFactory.create() project = f.ProjectFactory.create(owner=user) @@ -99,6 +100,22 @@ def test_invalid_concurrent_save_for_us(client): response = client.patch(url, json.dumps(data), content_type="application/json") assert response.status_code == 400 +def test_valid_us_creation(client): + user = f.UserFactory.create() + project = f.ProjectFactory.create(owner=user) + membership = f.MembershipFactory.create(project=project, user=user) + + client.login(user) + + url = reverse("userstories-list") + data = { + 'project': project.id, + 'subject': 'test', + } + + response = client.post(url, json.dumps(data), content_type="application/json") + assert response.status_code == 201 + def test_valid_concurrent_save_for_us(client): user = f.UserFactory.create() project = f.ProjectFactory.create(owner=user)