Skip to content

Commit

Permalink
Merge pull request #421 from dimagi/pkv/payment-unit-start-end-dates
Browse files Browse the repository at this point in the history
Payment Unit: Start/End Dates
  • Loading branch information
pxwxnvermx authored Nov 27, 2024
2 parents 0189b50 + 0d7b358 commit 362dd42
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 8 deletions.
14 changes: 7 additions & 7 deletions commcare_connect/form_receiver/processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ def process_deliver_unit(user, xform: XForm, app: CommCareApp, opportunity: Oppo
claim = OpportunityClaim.objects.get(opportunity_access=access)
entity_id = deliver_unit_block.get("entity_id")
entity_name = deliver_unit_block.get("entity_name")
payment_unit = deliver_unit.payment_unit
user_visit = UserVisit(
opportunity=opportunity,
user=user,
Expand All @@ -260,26 +261,25 @@ def process_deliver_unit(user, xform: XForm, app: CommCareApp, opportunity: Oppo
location=xform.metadata.location,
)
completed_work_needs_save = False
if opportunity.start_date > datetime.date.today():
today = datetime.date.today()
if opportunity.start_date > today or (payment_unit.start_date and payment_unit.start_date > today):
completed_work = None
user_visit.status = VisitValidationStatus.trial
else:
completed_work, _ = CompletedWork.objects.get_or_create(
opportunity_access=access,
entity_id=entity_id,
payment_unit=deliver_unit.payment_unit,
payment_unit=payment_unit,
defaults={
"entity_name": entity_name,
},
)
user_visit.completed_work = completed_work
claim_limit = OpportunityClaimLimit.objects.get(
opportunity_claim=claim, payment_unit=completed_work.payment_unit
)
claim_limit = OpportunityClaimLimit.objects.get(opportunity_claim=claim, payment_unit=payment_unit)
if (
counts["daily"] >= deliver_unit.payment_unit.max_daily
counts["daily"] >= payment_unit.max_daily
or counts["total"] >= claim_limit.max_visits
or datetime.date.today() > claim.end_date
or (today > claim.end_date or (claim_limit.end_date and today > claim_limit.end_date))
):
user_visit.status = VisitValidationStatus.over_limit
if not completed_work.status == CompletedWorkStatus.over_limit:
Expand Down
24 changes: 24 additions & 0 deletions commcare_connect/form_receiver/tests/test_receiver_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from uuid import uuid4

import pytest
from django.utils.timezone import now
from rest_framework.test import APIClient

from commcare_connect.form_receiver.tests.test_receiver_endpoint import add_credentials
Expand Down Expand Up @@ -602,6 +603,29 @@ def test_receiver_visit_review_status(
assert visit.review_status == review_status


@pytest.mark.parametrize(
"opportunity, paymentunit_options, visit_status",
[
({}, {"start_date": now().date()}, VisitValidationStatus.approved),
({}, {"start_date": now() + datetime.timedelta(days=2)}, VisitValidationStatus.trial),
({}, {"end_date": now().date()}, VisitValidationStatus.approved),
({}, {"end_date": now() - datetime.timedelta(days=2)}, VisitValidationStatus.over_limit),
({"opp_options": {"start_date": now().date()}}, {}, VisitValidationStatus.approved),
({"opp_options": {"start_date": now() + datetime.timedelta(days=2)}}, {}, VisitValidationStatus.trial),
({"opp_options": {"end_date": now().date()}}, {}, VisitValidationStatus.approved),
],
indirect=["opportunity"],
)
def test_receiver_visit_payment_unit_dates(
mobile_user_with_connect_link: User, api_client: APIClient, opportunity: Opportunity, visit_status
):
form_json = get_form_json_for_payment_unit(opportunity.paymentunit_set.first())
form_json["metadata"]["timeStart"] = now() - datetime.timedelta(minutes=2)
make_request(api_client, form_json, mobile_user_with_connect_link)
visit = UserVisit.objects.get(user=mobile_user_with_connect_link)
assert visit.status == visit_status


def get_form_json_for_payment_unit(payment_unit):
deliver_unit = DeliverUnitFactory(app=payment_unit.opportunity.deliver_app, payment_unit=payment_unit)
stub = DeliverUnitStubFactory(id=deliver_unit.slug)
Expand Down
13 changes: 12 additions & 1 deletion commcare_connect/opportunity/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,15 @@ def __init__(self, *args, **kwargs):
class PaymentUnitForm(forms.ModelForm):
class Meta:
model = PaymentUnit
fields = ["name", "description", "amount", "max_total", "max_daily"]
fields = ["name", "description", "amount", "max_total", "max_daily", "start_date", "end_date"]
help_texts = {
"start_date": "Optional. If not specified opportunity start date applies to form submissions.",
"end_date": "Optional. If not specified opportunity end date applies to form submissions.",
}
widgets = {
"start_date": forms.DateInput(attrs={"type": "date", "class": "form-input"}),
"end_date": forms.DateInput(attrs={"type": "date", "class": "form-input"}),
}

def __init__(self, *args, **kwargs):
deliver_units = kwargs.pop("deliver_units", [])
Expand All @@ -627,6 +635,7 @@ def __init__(self, *args, **kwargs):
Row(Field("name")),
Row(Field("description")),
Row(Field("amount")),
Row(Column("start_date"), Column("end_date")),
Row(Field("required_deliver_units")),
Row(Field("optional_deliver_units")),
Row(Field("payment_units")),
Expand Down Expand Up @@ -687,6 +696,8 @@ def clean(self):
"optional_deliver_units",
error=f"{deliver_unit_obj.name} cannot be marked both Required and Optional",
)
if cleaned_data["end_date"] and cleaned_data["end_date"] < now().date():
self.add_error("end_date", "Please provide a valid end date.")
return cleaned_data


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 4.2.5 on 2024-10-30 14:11

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("opportunity", "0060_completedwork_payment_date"),
]

operations = [
migrations.AddField(
model_name="opportunityclaimlimit",
name="end_date",
field=models.DateField(blank=True, null=True),
),
migrations.AddField(
model_name="paymentunit",
name="end_date",
field=models.DateField(blank=True, null=True),
),
migrations.AddField(
model_name="paymentunit",
name="start_date",
field=models.DateField(blank=True, null=True),
),
]
4 changes: 4 additions & 0 deletions commcare_connect/opportunity/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,8 @@ class PaymentUnit(models.Model):
blank=True,
null=True,
)
start_date = models.DateField(null=True, blank=True)
end_date = models.DateField(null=True, blank=True)

def __str__(self):
return self.name
Expand Down Expand Up @@ -596,6 +598,7 @@ class OpportunityClaimLimit(models.Model):
opportunity_claim = models.ForeignKey(OpportunityClaim, on_delete=models.CASCADE)
payment_unit = models.ForeignKey(PaymentUnit, on_delete=models.CASCADE)
max_visits = models.IntegerField()
end_date = models.DateField(null=True, blank=True)

class Meta:
unique_together = [
Expand Down Expand Up @@ -625,6 +628,7 @@ def create_claim_limits(cls, opportunity: Opportunity, claim: OpportunityClaim):
opportunity_claim=claim,
payment_unit=payment_unit,
defaults={"max_visits": min(remaining, payment_unit.max_total)},
end_date=payment_unit.end_date,
)


Expand Down

0 comments on commit 362dd42

Please sign in to comment.