Skip to content

Commit

Permalink
Merge pull request #730 from lingxiaoyang/fix_717
Browse files Browse the repository at this point in the history
Fixed #717: Enhance client scheduled status change
  • Loading branch information
lingxiaoyang committed Jun 12, 2017
2 parents 7e4fafc + acda830 commit 5730399
Show file tree
Hide file tree
Showing 17 changed files with 557 additions and 197 deletions.
60 changes: 35 additions & 25 deletions src/frontend/js/member.js
Expand Up @@ -5,17 +5,34 @@ $(function() {
var today = new Date();

$('.ui.dropdown.member.status > .menu > .item').click(function () {
var value = $(this).data('value');
var modalCtntURL = $('.ui.dropdown.status').attr('data-url');
$.get(modalCtntURL, {status:value}, function(data, modalCtntURL){
$('.ui.modal.status').html(data).modal("setting", {
// Don't change the dropdown content. There's a bug with two labels.
// This prevents the default behavior.
return false;
});
$('.ui.dropdown.member.status > .menu > .item.member-view-upcoming-changes').click(function () {
location.replace($(this).data('url'));
});
$('.ui.dropdown.member.status > .menu > .item.member-cancel-this-upcoming-change').click(function () {
var $form = $(this).find('form');
if (window.confirm($(this).data('prompt'))) {
$form.submit();
}
});

$('.ui.dropdown.member.status > .menu > .item.member-update-status, .ui.dropdown.member.status > .menu > .item.member-reschedule-this-upcoming-change').click(function () {
var modalCtntURL = $(this).data('url');
var modalTarget = $(this).data('modalTarget').toString();

$.get(modalCtntURL, function (data) {
$(modalTarget).html(data).modal("setting", {
closable: false,
// Inside modal init
onVisible: function () {
var $modal = $(this);
// Enable status confirmation dropdown
$('.ui.status_to.dropdown').dropdown();
$modal.find('.ui.status_to.dropdown').dropdown();
// Init dates field (start and end)
$('#rangestart').calendar({
$modal.find('#rangestart').calendar({
type: 'date',
on: 'click',
minDate: today,
Expand All @@ -24,40 +41,40 @@ $(function() {
return date ? dateFormat(date, 'yyyy-mm-dd') : '';
}
},
endCalendar: $('#rangeend'),
endCalendar: $modal.find('#rangeend')
});
$('#rangeend').calendar({
$modal.find('#rangeend').calendar({
type: 'date',
formatter: {
date: function (date, settings) {
return date ? dateFormat(date, 'yyyy-mm-dd') : '';
}
},
startCalendar: $('#rangestart'),
startCalendar: $modal.find('#rangestart')
});
},
// When approvind modal, submit form
onApprove: function($element, modalCtntURL) {
onApprove: function () {
var $modal = $(this);
$.ajax({
type: 'POST',
url: $('.ui.dropdown.status').attr('data-url'),
data: $('#change-status-form').serialize(),
url: modalCtntURL,
data: $modal.find('#change-status-form').serialize(),
success: function (xhr, ajaxOptions, thrownError) {
if ( $(xhr).find('.errorlist').length > 0 ) {
$('.ui.modal.status').html(xhr);
$('.ui.status_to.dropdown').dropdown();
$modal.html(xhr);
$modal.find('.ui.status_to.dropdown').dropdown();
} else {
$('.ui.modal.status').modal("hide");
$modal.modal("hide");
location.reload();
}
},
});
return false; // don't hide modal until we have the response
},
// When denying modal, restore default value for status dropdown
onDeny: function($element) {
$('.ui.dropdown.status').dropdown('restore defaults');
$('.ui.modal.status').modal("hide");
onDeny: function () {
location.reload();
}
}).modal('setting', 'autofocus', false).modal("show");
});
Expand All @@ -73,13 +90,6 @@ $(function() {
},
});

var removeStatusConfirmationModal = $('#remove-status-confirmation');
$('a.remove-status').click(function (e) {
e.preventDefault();
removeStatusConfirmationModal.load(this.href);
removeStatusConfirmationModal.modal('show');
});

if($('#dietary_restriction-delivery_type select').val() == 'E') {
$('#form-meals-schedule').hide();
} else {
Expand Down
3 changes: 2 additions & 1 deletion src/member/admin.py
Expand Up @@ -3,7 +3,7 @@
from member.models import (
Member, Client, Contact, Address,
Route, Option, Relationship,
DeliveryHistory
DeliveryHistory, ClientScheduledStatus
)


Expand Down Expand Up @@ -79,6 +79,7 @@ class RelationshipAdmin(admin.ModelAdmin):

admin.site.register(Member, MemberAdmin)
admin.site.register(Client, ClientAdmin)
admin.site.register(ClientScheduledStatus)
admin.site.register(Route)
admin.site.register(DeliveryHistory)
admin.site.register(Contact, ContactAdmin)
Expand Down
5 changes: 1 addition & 4 deletions src/member/apps.py
Expand Up @@ -5,7 +5,4 @@ class MemberConfig(AppConfig):
name = 'member'

def ready(self):
# import signal handlers
# (every models imported inside handlers will be instantiated as
# soon as the registry is fully populated.)
import member.signals.handlers # noqa
pass
79 changes: 55 additions & 24 deletions src/member/forms.py
Expand Up @@ -2,6 +2,7 @@

from django import forms
from django.core.exceptions import ObjectDoesNotExist
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _

from member.formsfield import CAPhoneNumberExtField
Expand Down Expand Up @@ -581,28 +582,58 @@ def __init__(self, *args, **kwargs):
help_text=_('Format: YYYY-MM-DD'),
)

def save(self, commit=True):
if commit:
instance = super().save(commit)
end_date = self.cleaned_data.get('end_date')

# Immediate status update (schedule and process)
if self.cleaned_data.get('change_date') == date.today():
instance.process()

if end_date:
# Schedule a time range during which status will be different,
# then back to current (double schedule)
ClientScheduledStatus.objects.create(
client=instance.client,
status_from=instance.status_to,
status_to=instance.status_from,
reason=instance.reason,
change_date=end_date,
change_state=ClientScheduledStatus.END,
operation_status=ClientScheduledStatus.TOBEPROCESSED,
pair=instance
)
def save(self, *args, **kwargs):
"""
Override the default behavior of a ModelForm.
We may have two ClientScheduledStatus instances to save. The .save()
method is not expressive enough for what we want to do.
Thus, we raise an error when trying to call form.save() to remind
other people of using the custom save method.
"""
raise NotImplementedError(
"This method is intentionally bypassed. Please use "
"save_scheduled_statuses method.")

return instance
return super().save(commit)
def save_scheduled_statuses(self, callback_add_message=lambda m: None):
"""
Create one or two ClientScheduledStatus instances according to
`self.cleaned_data`.
"""
if not hasattr(self, 'cleaned_data') or self.errors:
raise ValueError("The form data doesn't validate.")
data = self.cleaned_data
today = timezone.datetime.date(timezone.datetime.today())

# Save and process instance(s)
c1 = ClientScheduledStatus.objects.create(
client=data['client'],
status_from=data['status_from'],
status_to=data['status_to'],
reason=data['reason'],
change_date=data['change_date'],
change_state=ClientScheduledStatus.END,
operation_status=ClientScheduledStatus.TOBEPROCESSED
)
if data['change_date'] == today:
c1.process()
callback_add_message(_("The client status has been changed."))
else:
callback_add_message(_("This status change has been scheduled."))

if data.get('end_date'):
c2 = ClientScheduledStatus.objects.create(
client=data['client'],
status_from=data['status_to'],
status_to=data['status_from'],
reason=data['reason'],
change_date=data['end_date'],
change_state=ClientScheduledStatus.END,
operation_status=ClientScheduledStatus.TOBEPROCESSED,
pair=c1
)
if data.get('end_date') == today:
c2.process()
callback_add_message(_("The client status has been changed."))
else:
callback_add_message(_("The end date of this status change "
"has been scheduled."))
60 changes: 49 additions & 11 deletions src/member/locale/fr/LC_MESSAGES/django.po
Expand Up @@ -294,6 +294,22 @@ msgstr "Au moins un contact d'urgence est requis."
msgid "This field is required for a referent relationship."
msgstr "Ce champ est requis sauf si vous souhaitez ajouter un nouveau membre."

#: member/forms.py
#, fuzzy
#| msgid "The status has been changed"
msgid "The client status has been changed."
msgstr "Le statut a été changé"

#: member/forms.py
#, fuzzy
#| msgid "The status has been changed"
msgid "This status change has been scheduled."
msgstr "Le statut a été changé"

#: member/forms.py
msgid "The end date of this status change has been scheduled."
msgstr ""

#: member/models.py
msgid "Female"
msgstr "Femme"
Expand Down Expand Up @@ -574,10 +590,6 @@ msgstr "Erreur"
msgid "Client Scheduled Status Pair"
msgstr "Paire de Statut Planifié du Client"

#: member/models.py
msgid "All"
msgstr "Tout"

#: member/models.py
msgid "Search by name"
msgstr "Recherche par nom"
Expand Down Expand Up @@ -645,6 +657,30 @@ msgstr ""
"\n"
"Client depuis %(created_at)s"

#: member/templates/client/base.html
msgid "Client status scheduler may not work properly. Please verify."
msgstr ""

#: member/templates/client/base.html
msgid "Upcoming change"
msgstr ""

#: member/templates/client/base.html
msgid "View upcoming changes"
msgstr ""

#: member/templates/client/base.html
msgid "This cannot be undone. Are you sure?"
msgstr ""

#: member/templates/client/base.html
msgid "Cancel this upcoming change"
msgstr ""

#: member/templates/client/base.html
msgid "Reschedule this upcoming change"
msgstr ""

#: member/templates/client/base.html
msgid "Important notice"
msgstr "Remarque importante"
Expand Down Expand Up @@ -1351,10 +1387,6 @@ msgstr "Statut"
msgid "No status modification."
msgstr "Aucun changement de statut."

#: member/templates/client/view/status.html
msgid "Remove"
msgstr "Supprimer"

#: member/templates/client/view/summary.html
msgid "Home"
msgstr "Domicile"
Expand Down Expand Up @@ -1579,6 +1611,10 @@ msgstr "^voir/(?P<pk>\\d+)/statut$"
msgid "^client/(?P<pk>\\d+)/status/scheduler$"
msgstr "^client/(?P<pk>\\d+)/statut/planificateur$"

#: member/urls.py
msgid "^client/(?P<pk>\\d+)/status/scheduler/reschedule/(?P<scheduled_status_1_pk>\\d+),(?P<scheduled_status_2_pk>\\d+)?/$"
msgstr "^client/(?P<pk>\\d+)/statut/planificateur/replanifier/(?P<scheduled_status_1_pk>\\d+),(?P<scheduled_status_2_pk>\\d+)?/$"

#: member/urls.py
msgid "^restriction/(?P<pk>\\d+)/delete/$"
msgstr "^restriction/(?P<pk>\\d+)/supprimer/$"
Expand Down Expand Up @@ -1628,9 +1664,11 @@ msgstr "Le client a été crée"
msgid "The client has been updated"
msgstr "Le client a été mis à jour"

#: member/views.py
msgid "The status has been changed"
msgstr "Le statut a été changé"
#~ msgid "All"
#~ msgstr "Tout"

#~ msgid "Remove"
#~ msgstr "Supprimer"

#: member/views.py
#, python-format
Expand Down
16 changes: 9 additions & 7 deletions src/member/models.py
Expand Up @@ -876,15 +876,17 @@ def add_note_to_client(self, author=None):
)
note.save()

@property
def needs_attention(self):
"""
Return True if the status is ERROR or the scheduled date has passed.
"""
return (self.operation_status == self.ERROR) or (
self.change_date <= timezone.datetime.date(
timezone.datetime.today()))

class ClientScheduledStatusFilter(FilterSet):

ALL = 'ALL'

operation_status = ChoiceFilter(
choices=((ALL, _('All')),) + ClientScheduledStatus.OPERATION_STATUS,
# initial=ClientScheduledStatus.PROCESSED
)
class ClientScheduledStatusFilter(FilterSet):

class Meta:
model = ClientScheduledStatus
Expand Down

0 comments on commit 5730399

Please sign in to comment.