Skip to content

Commit bdb38c1

Browse files
committed
Added IFF round creation management command
1 parent fa43912 commit bdb38c1

File tree

1 file changed

+131
-0
lines changed

1 file changed

+131
-0
lines changed
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import argparse
2+
import datetime
3+
from typing import Tuple
4+
from django.core.exceptions import ValidationError
5+
from django.core.management.base import BaseCommand
6+
from django.db import transaction
7+
8+
from hypha.apply.users.models import User
9+
from hypha.apply.funds.models import FundType, Round
10+
11+
12+
def get_next_month_start_end() -> Tuple[datetime.date, datetime.date]:
13+
next_month_start = (datetime.date.today().replace(day=1) + datetime.timedelta(days=32)).replace(day=1)
14+
following_month = next_month_start + datetime.timedelta(days=32)
15+
next_month_end = (following_month - datetime.timedelta(days=following_month.day))
16+
return (next_month_start, next_month_end)
17+
18+
19+
def check_not_negative(value) -> int:
20+
"""Used to validate `older_than_days` argument
21+
22+
Args:
23+
value: Argument to be validated
24+
25+
Returns:
26+
int: Valid non-negative value
27+
28+
Raises:
29+
argparse.ArgumentTypeError: if not non-negative integer
30+
"""
31+
try:
32+
ivalue = int(value)
33+
except ValueError:
34+
ivalue = -1
35+
36+
if ivalue < 0:
37+
raise argparse.ArgumentTypeError(
38+
f'"{value}" is an invalid non-negative integer value'
39+
)
40+
return ivalue
41+
42+
class Command(BaseCommand):
43+
help = (
44+
"Automatically create a new IFF round for the next month"
45+
)
46+
47+
def add_arguments(self, parser):
48+
parser.add_argument(
49+
"days_before_month_start",
50+
action="store",
51+
type=check_not_negative,
52+
help="Time in days when the new round should be created",
53+
)
54+
55+
parser.add_argument(
56+
"iff_fund_id",
57+
action="store",
58+
type=int,
59+
help="The ID of the IFF fund",
60+
)
61+
62+
parser.add_argument(
63+
"program_specialist_ids",
64+
action="store",
65+
type=str,
66+
help="the IDs of the program specialists to be made lead",
67+
)
68+
69+
@transaction.atomic
70+
def handle(self, *args, **options):
71+
fund_id = options["iff_fund_id"]
72+
days_before_month_start = options["days_before_month_start"]
73+
ps_ids = [int(id) for id in options["program_specialist_ids"].split(",")]
74+
75+
fund = FundType.objects.get(id=fund_id)
76+
77+
next_month_start, next_month_end = get_next_month_start_end()
78+
79+
print("DAYS")
80+
print(days_before_month_start)
81+
print((next_month_start - datetime.date.today()).days > days_before_month_start)
82+
83+
if (next_month_start - datetime.date.today()).days > days_before_month_start:
84+
self.stdout.write("Current date difference is not less than or equal to days_before_months_start, thus a new IFF round will not be created.")
85+
return
86+
87+
current_title = f"IFF-{datetime.date.today().year}-{datetime.date.today().month}"
88+
next_title = f"IFF-{next_month_start.year}-{next_month_start.month}"
89+
90+
91+
leads = []
92+
93+
for id in ps_ids:
94+
try:
95+
leads.append(User.objects.get(id=id))
96+
except User.DoesNotExist:
97+
self.stdout.write(f"Failed to find a user with ID of: {id}")
98+
99+
if leads:
100+
try:
101+
current_round = Round.objects.get(title=current_title)
102+
103+
# Alternate round leads, whoever was last shouldn't be it this time
104+
lead = next(lead for lead in leads if lead != current_round.lead)
105+
except Round.DoesNotExist:
106+
import random
107+
108+
lead = random.choice(leads)
109+
110+
next_round = Round(
111+
title=next_title,
112+
lead=lead,
113+
start_date=next_month_start,
114+
end_date=next_month_end
115+
)
116+
117+
try:
118+
fund.add_child(instance=next_round)
119+
120+
next_round._copy_forms("forms")
121+
next_round._copy_forms("review_forms")
122+
next_round._copy_forms("external_review_forms")
123+
next_round._copy_forms("determination_forms")
124+
125+
self.stdout.write(f"A new IFF round has been created with the title: \"{next_title}\"")
126+
except ValidationError: # If the round already exists, don't do anything else
127+
self.stdout.write(
128+
f"An IFF round already exists for this time and a new one will not be created!"
129+
)
130+
else:
131+
self.stdout.write(f"No valid leads were found thus IFF round \"{next_title}\" will not be created")

0 commit comments

Comments
 (0)