-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Push notification messages #181
Conversation
21bb688
to
d5bea57
Compare
54d55eb
to
c8057dc
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few questions. Overall code looks fine, just curious about various requirements mostly
@celery_app.task() | ||
def send_notification_inactive_users(opportunity_id: int): | ||
opportunity = Opportunity.objects.get(opportunity_id=opportunity_id) | ||
opportunity_accesses = OpportunityAccess.objects.filter(opportunity_id=opportunity_id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can do this in one line. You can access the Opportunity
object from the OpportunityAccess
one with opportunity_access.opportunity
and you can have it fetch both in one query with
OpportunityAccess.objects.filter(opportunity_id=opportunity_id).select_related("opportunity")
) | ||
has_started_deliver = OpportunityClaim.objects.exists(access=access) | ||
if ( | ||
last_user_learn_module.date <= datetime.date.today() - datetime.timedelta(days=3) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where does 3 come from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It comes from the mobile user stories doc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe make these constants. You could also make a small helper:
date_before(last_user_learn_module.date, TWO_DAYS)
# or
date_before(last_user_learn_module.date, days=2)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made a helper to check for dates. 0e83ab2
UserVisit.objects.filter(user=access.user, opportunity_id=opportunity_id).order_by("visit_date").last() | ||
) | ||
if ( | ||
last_user_deliver_visit.visit_date <= datetime.date.today() - datetime.timedelta(days=2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where does 2 come from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It comes fromthe mobile user stories doc.
title=gettext(f"Resume your job for {opportunity.name}"), | ||
body=gettext( | ||
f"You have not completed your delivery visits for {opportunity.name}." | ||
"Please complete all the deliver visits to avail the payment." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there somewhere these messages are coming from. The language is little harsh
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The body of the messages comes from me, that could be the reason they look a little unrefined. Any suggestions on how to improved these messages?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe:
All deliver visits must be completed before payment can be released.
Not sure if deliver visits
is the correct term. Also I thought there was payment along the way and not just at the end?
Option 2:
To maximise your payout complete all the required service delivery.
@@ -86,6 +89,14 @@ def get_form_kwargs(self): | |||
def form_valid(self, form: OpportunityCreationForm) -> HttpResponse: | |||
response = super().form_valid(form) | |||
create_learn_modules_and_deliver_units.delay(self.object.id) | |||
interval = IntervalSchedule.objects.get_or_create(every=1, period=IntervalSchedule.DAYS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the recommended way to do periodic tasks? I would have imagined it was simpler to make one task and have it iterate over all opportunities, but I am not sure how to schedule that. In HQ we would use the @periodic_task
decorator and give it a schedule. The other advantage of one task rather than one per domain is that it could quickly end up a very large number of tasks and clog celery.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for the one task approach. You can create the schedule with a Django migration or using the post_migrate
signal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a migration to create the periodic task. b79b62c
@@ -86,6 +89,14 @@ def get_form_kwargs(self): | |||
def form_valid(self, form: OpportunityCreationForm) -> HttpResponse: | |||
response = super().form_valid(form) | |||
create_learn_modules_and_deliver_units.delay(self.object.id) | |||
interval = IntervalSchedule.objects.get_or_create(every=1, period=IntervalSchedule.DAYS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for the one task approach. You can create the schedule with a Django migration or using the post_migrate
signal.
title=gettext(f"Resume your job for {opportunity.name}"), | ||
body=gettext( | ||
f"You have not completed your delivery visits for {opportunity.name}." | ||
"Please complete all the deliver visits to avail the payment." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe:
All deliver visits must be completed before payment can be released.
Not sure if deliver visits
is the correct term. Also I thought there was payment along the way and not just at the end?
Option 2:
To maximise your payout complete all the required service delivery.
) | ||
has_started_deliver = OpportunityClaim.objects.exists(access=access) | ||
if ( | ||
last_user_learn_module.date <= datetime.date.today() - datetime.timedelta(days=3) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe make these constants. You could also make a small helper:
date_before(last_user_learn_module.date, TWO_DAYS)
# or
date_before(last_user_learn_module.date, days=2)
usernames=[access.user.username], | ||
title=gettext(f"Resume your learning journey for {opportunity.name}"), | ||
body=gettext( | ||
f"You have not completed your learning for {opportunity.name}." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if they have completed all the modules but haven't yet claimed the opportunity? I think we're only checking when the last module was done and not whether they have done them all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
has_started_deliver indicates that if the Opportunity Claim exists or not. I have also added this check in both of the if blocks. If user has a opportunity claim then we dont need to check the learn modules.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, but it could also be the case that the user has completed the learning modules but has not yet claimed the opportunity right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added this case, and refactored the code to make testing easier. f629e9e
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few small comments but otherwise looking good.
|
||
|
||
def create_send_inactive_notification_periodic_task(apps, schema_editor): | ||
interval, _ = IntervalSchedule.objects.get_or_create(every=1, period=IntervalSchedule.DAYS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just thought of this now. I think it would be better to use a cron schedule so that it fires at a consistent time each day, probably around 7am UTC I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. 471037d
message = _get_deliver_message(access) | ||
else: | ||
message = _get_learn_message(access) | ||
if isinstance(message, Message): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The possible types for message are either Message
or None so I think it would be clearer to use if messages
otherwise it gives the impression that there may be other types being returned.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed. f629e9e
…ed but not claimed case
Ticket