Add issue milestones signals

stable
Álex Hermida 2018-12-28 14:09:39 +01:00 committed by Alex Hermida
parent 18e97be27c
commit a4256c3f09
3 changed files with 81 additions and 1 deletions

View File

@ -25,6 +25,11 @@ def connect_issues_signals():
from taiga.projects.tagging import signals as tagging_handlers from taiga.projects.tagging import signals as tagging_handlers
from . import signals as handlers from . import signals as handlers
# Cached prev object version
signals.pre_save.connect(handlers.cached_prev_issue,
sender=apps.get_model("issues", "Issue"),
dispatch_uid="cached_prev_issue")
# Finished date # Finished date
signals.pre_save.connect(handlers.set_finished_date_when_edit_issue, signals.pre_save.connect(handlers.set_finished_date_when_edit_issue,
sender=apps.get_model("issues", "Issue"), sender=apps.get_model("issues", "Issue"),
@ -35,6 +40,14 @@ def connect_issues_signals():
sender=apps.get_model("issues", "Issue"), sender=apps.get_model("issues", "Issue"),
dispatch_uid="tags_normalization_issue") dispatch_uid="tags_normalization_issue")
# Open/Close US and Milestone
signals.post_save.connect(handlers.try_to_close_or_open_milestone_when_create_or_edit_issue,
sender=apps.get_model("issues", "Issue"),
dispatch_uid="try_to_close_or_open_milestone_when_create_or_edit_issue")
signals.post_delete.connect(handlers.try_to_close_milestone_when_delete_issue,
sender=apps.get_model("issues", "Issue"),
dispatch_uid="try_to_close_milestone_when_delete_issue")
def connect_issues_custom_attributes_signals(): def connect_issues_custom_attributes_signals():
from taiga.projects.custom_attributes import signals as custom_attributes_handlers from taiga.projects.custom_attributes import signals as custom_attributes_handlers
@ -50,11 +63,19 @@ def connect_all_issues_signals():
def disconnect_issues_signals(): def disconnect_issues_signals():
signals.pre_save.disconnect(sender=apps.get_model("issues", "Issue"),
dispatch_uid="cached_prev_issue")
signals.pre_save.disconnect(sender=apps.get_model("issues", "Issue"), signals.pre_save.disconnect(sender=apps.get_model("issues", "Issue"),
dispatch_uid="set_finished_date_when_edit_issue") dispatch_uid="set_finished_date_when_edit_issue")
signals.pre_save.disconnect(sender=apps.get_model("issues", "Issue"), signals.pre_save.disconnect(sender=apps.get_model("issues", "Issue"),
dispatch_uid="tags_normalization_issue") dispatch_uid="tags_normalization_issue")
signals.post_save.disconnect(sender=apps.get_model("issues", "Issue"),
dispatch_uid="try_to_close_or_open_milestone_when_create_or_edit_issue")
signals.post_delete.disconnect(sender=apps.get_model("issues", "Issue"),
dispatch_uid="try_to_close_milestone_when_delete_issue")
def disconnect_issues_custom_attributes_signals(): def disconnect_issues_custom_attributes_signals():
signals.post_save.disconnect(sender=apps.get_model("issues", "Issue"), signals.post_save.disconnect(sender=apps.get_model("issues", "Issue"),

View File

@ -16,9 +16,22 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from contextlib import suppress
from django.core.exceptions import ObjectDoesNotExist
from django.utils import timezone from django.utils import timezone
####################################
# Signals for cached prev task
####################################
# Define the previous version of the task for use it on the post_save handler
def cached_prev_issue(sender, instance, **kwargs):
instance.prev = None
if instance.id:
instance.prev = sender.objects.get(id=instance.id)
#################################### ####################################
# Signals for set finished date # Signals for set finished date
#################################### ####################################
@ -30,3 +43,48 @@ def set_finished_date_when_edit_issue(sender, instance, **kwargs):
instance.finished_date = timezone.now() instance.finished_date = timezone.now()
elif not instance.status.is_closed and instance.finished_date: elif not instance.status.is_closed and instance.finished_date:
instance.finished_date = None instance.finished_date = None
def try_to_close_or_open_milestone_when_create_or_edit_issue(sender, instance, created, **kwargs):
if instance._importing:
return
_try_to_close_or_open_milestone_when_create_or_edit_issue(instance)
def try_to_close_milestone_when_delete_issue(sender, instance, **kwargs):
if instance._importing:
return
_try_to_close_milestone_when_delete_issue(instance)
# Milestone
def _try_to_close_or_open_milestone_when_create_or_edit_issue(instance):
if instance._importing:
return
from taiga.projects.milestones import services as milestone_service
if instance.milestone_id:
if milestone_service.calculate_milestone_is_closed(instance.milestone):
milestone_service.close_milestone(instance.milestone)
else:
milestone_service.open_milestone(instance.milestone)
if instance.prev and instance.prev.milestone_id and instance.prev.milestone_id != instance.milestone_id:
if milestone_service.calculate_milestone_is_closed(instance.prev.milestone):
milestone_service.close_milestone(instance.prev.milestone)
else:
milestone_service.open_milestone(instance.prev.milestone)
def _try_to_close_milestone_when_delete_issue(instance):
if instance._importing:
return
from taiga.projects.milestones import services as milestone_service
with suppress(ObjectDoesNotExist):
if instance.milestone_id and milestone_service.calculate_milestone_is_closed(instance.milestone):
milestone_service.close_milestone(instance.milestone)

View File

@ -30,7 +30,8 @@ from . import models
def calculate_milestone_is_closed(milestone): def calculate_milestone_is_closed(milestone):
return (milestone.user_stories.all().count() > 0 and return (milestone.user_stories.all().count() > 0 and
all([task.status is not None and task.status.is_closed for task in milestone.tasks.all()]) and all([task.status is not None and task.status.is_closed for task in milestone.tasks.all()]) and
all([user_story.is_closed for user_story in milestone.user_stories.all()])) all([user_story.is_closed for user_story in milestone.user_stories.all()]) or
all([issue.is_closed for issue in milestone.issues.all()]))
def close_milestone(milestone): def close_milestone(milestone):