Skip to content

Commit e7254e4

Browse files
jho426shahanneda
andauthored
Add editing of meal donations. (#126)
Co-authored-by: Shahan Neda <shahan.neda@gmail.com>
1 parent 8d7ddf7 commit e7254e4

File tree

17 files changed

+783
-1514
lines changed

17 files changed

+783
-1514
lines changed

backend/app/graphql/meal_request.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,58 @@ def mutate(
102102
return CreateMealRequests(meal_requests=result)
103103

104104

105+
class UpdateMealRequestDonation(Mutation):
106+
class Arguments:
107+
requestor_id = graphene.ID(required=True)
108+
meal_request_id = graphene.ID(required=True)
109+
meal_description = graphene.String()
110+
additional_info = graphene.String()
111+
donor_onsite_contacts = graphene.List(graphene.String)
112+
113+
meal_request = graphene.Field(MealRequestResponse)
114+
115+
def mutate(
116+
self,
117+
info,
118+
requestor_id: str,
119+
meal_request_id,
120+
meal_description,
121+
additional_info,
122+
donor_onsite_contacts,
123+
):
124+
user_service = services["user_service"]
125+
requestor_auth_id = user_service.get_auth_id_by_user_id(requestor_id)
126+
requestor_role = user_service.get_user_role_by_auth_id(requestor_auth_id)
127+
128+
try:
129+
meal_request = services["meal_request_service"].get_meal_request_by_id(
130+
meal_request_id
131+
)
132+
133+
if not meal_request:
134+
raise Exception("Meal request not found")
135+
136+
if (
137+
requestor_role != "Admin"
138+
and meal_request.donation_info["donor"]["id"] != requestor_id
139+
):
140+
raise Exception(
141+
"Requestor is not an admin or the donor of the meal request."
142+
)
143+
144+
result = services["meal_request_service"].update_meal_request_donation(
145+
requestor_id=requestor_id,
146+
meal_request_id=meal_request_id,
147+
meal_description=meal_description,
148+
additional_info=additional_info,
149+
donor_onsite_contacts=donor_onsite_contacts,
150+
)
151+
except Exception as e:
152+
raise GraphQLError(str(e))
153+
154+
return UpdateMealRequest(meal_request=result)
155+
156+
105157
class UpdateMealRequest(Mutation):
106158
class Arguments:
107159
meal_request_id = graphene.ID(required=True)
@@ -237,6 +289,7 @@ def mutate(self, info, meal_request_id, requestor_id):
237289
class MealRequestMutations(MutationList):
238290
create_meal_request = CreateMealRequests.Field()
239291
update_meal_request = UpdateMealRequest.Field()
292+
update_meal_request_donation = UpdateMealRequestDonation.Field()
240293
commit_to_meal_request = CommitToMealRequest.Field()
241294
cancel_donation = CancelDonation.Field()
242295
delete_meal_request = DeleteMealRequest.Field()

backend/app/models/meal_request.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,20 +88,14 @@ def to_serializable_dict(self):
8888
id = meal_request_dict.pop("_id", None)
8989
meal_request_dict["id"] = str(id)
9090

91-
contacts = [contact.to_mongo().to_dict() for contact in self.onsite_contacts]
92-
for contact in contacts:
93-
id = contact.pop("_id")
94-
contact["id"] = id
91+
contacts = [contact.to_serializable_dict() for contact in self.onsite_contacts]
9592
meal_request_dict["onsite_contacts"] = contacts
9693

9794
if self.donation_info and self.donation_info.donor_onsite_contacts:
9895
contacts = [
99-
contact.to_mongo().to_dict()
96+
contact.to_serializable_dict()
10097
for contact in self.donation_info.donor_onsite_contacts
10198
]
102-
for contact in contacts:
103-
id = contact.pop("_id")
104-
contact["id"] = id
10599
meal_request_dict["donation_info"]["donor_onsite_contacts"] = contacts
106100

107101
return meal_request_dict

backend/app/services/implementations/meal_request_service.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,37 @@ def update_meal_request(
129129

130130
return meal_request_dto
131131

132+
def update_meal_request_donation(
133+
self,
134+
requestor_id: str,
135+
meal_request_id,
136+
meal_description: str,
137+
additional_info: str,
138+
donor_onsite_contacts: List[str],
139+
):
140+
original_meal_request = MealRequest.objects(id=meal_request_id).first()
141+
if not original_meal_request:
142+
raise Exception(f'Meal request "{meal_request_id}" not found')
143+
144+
if not original_meal_request.donation_info:
145+
raise Exception("No donation info found")
146+
147+
original_meal_request.donation_info = DonationInfo(
148+
donor=original_meal_request.donation_info.donor,
149+
commitment_date=original_meal_request.donation_info.commitment_date,
150+
meal_description=meal_description,
151+
additional_info=additional_info,
152+
donor_onsite_contacts=donor_onsite_contacts,
153+
)
154+
155+
# Does validation,
156+
meal_request_dto = original_meal_request.to_dto()
157+
158+
original_meal_request.validate_onsite_contacts()
159+
original_meal_request.save()
160+
161+
return meal_request_dto
162+
132163
def commit_to_meal_request(
133164
self,
134165
donor_id: str,

backend/app/services/interfaces/meal_request_service.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,17 @@ def update_meal_request(
4343
):
4444
pass
4545

46+
@abstractmethod
47+
def update_meal_request_donation(
48+
self,
49+
requestor_id: str,
50+
meal_request_id,
51+
meal_description: str,
52+
additional_info: str,
53+
donor_onsite_contacts: List[str],
54+
):
55+
pass
56+
4657
@abstractmethod
4758
def commit_to_meal_request(
4859
self,

backend/package-lock.json

Lines changed: 0 additions & 6 deletions
This file was deleted.

backend/tests/graphql/conftest.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,25 +89,34 @@ def meal_request_setup(user_setup):
8989
def onsite_contact_setup(user_setup):
9090
asp, donor, _ = user_setup
9191
asp_onsite_contact = OnsiteContact(
92-
name="Sample Contact",
92+
name="Sample ASP Contact",
9393
email="sample@test.com",
9494
phone="123-456-7890",
9595
organization_id=asp.id,
9696
).save()
9797
asp_onsite_contact2 = OnsiteContact(
98-
name="Sample Contact 2",
98+
name="Sample ASP Contact 2",
9999
email="sample2@test.com",
100100
phone="123-456-7890",
101101
organization_id=asp.id,
102102
).save()
103103
donor_onsite_contact = OnsiteContact(
104-
name="Sample Contact 2",
104+
name="Sample Donor Contact 1",
105+
email="sample2@test.com",
106+
phone="123-333-7890",
107+
organization_id=donor.id,
108+
).save()
109+
donor_onsite_contact2 = OnsiteContact(
110+
name="Sample Donor 2",
105111
email="sample2@test.com",
106112
phone="123-333-7890",
107113
organization_id=donor.id,
108114
).save()
109115

110-
yield asp, donor, [asp_onsite_contact, asp_onsite_contact2], donor_onsite_contact
116+
yield asp, donor, [asp_onsite_contact, asp_onsite_contact2], [
117+
donor_onsite_contact,
118+
donor_onsite_contact2,
119+
]
111120
asp_onsite_contact.delete()
112121
donor_onsite_contact.delete()
113122

backend/tests/graphql/test_meal_request.py

Lines changed: 100 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def test_create_meal_request(meal_request_setup, onsite_contact_setup):
2424
asp,
2525
donor,
2626
[asp_onsite_contact, asp_onsite_contact2],
27-
donor_onsite_contact,
27+
[donor_onsite_contact, donor_onsite_contact2],
2828
) = onsite_contact_setup
2929

3030
mutation = f"""
@@ -110,7 +110,12 @@ def test_create_meal_request(meal_request_setup, onsite_contact_setup):
110110
def test_create_meal_request_fails_invalid_onsite_contact(
111111
meal_request_setup, onsite_contact_setup
112112
):
113-
asp, donor, asp_onsite_contact, donor_onsite_contact = onsite_contact_setup
113+
(
114+
asp,
115+
donor,
116+
[asp_onsite_contact, asp_onsite_contact2],
117+
[donor_onsite_contact, donor_onsite_contact2],
118+
) = onsite_contact_setup
114119

115120
counter_before = MealRequest.objects().count()
116121
mutation = f"""
@@ -153,6 +158,90 @@ def test_create_meal_request_fails_invalid_onsite_contact(
153158
assert counter_before == counter_after
154159

155160

161+
def test_update_meal_request_donation(meal_request_setup, onsite_contact_setup):
162+
_, donor, meal_request = meal_request_setup
163+
164+
test_commit_to_meal_request(meal_request_setup)
165+
(
166+
_,
167+
donor,
168+
[asp_onsite_contact, asp_onsite_contact2],
169+
[donor_onsite_contact, donor_onsite_contact2],
170+
) = onsite_contact_setup
171+
172+
mutation = f"""
173+
mutation testUpdateMealRequestDonation {{
174+
updateMealRequestDonation(
175+
requestorId: "{str(donor.id)}",
176+
mealRequestId: "{str(meal_request.id)}",
177+
mealDescription: "potato chicken nugget",
178+
additionalInfo: "kimchi fried rice"
179+
donorOnsiteContacts: ["{str(donor_onsite_contact.id)}", "{str(donor_onsite_contact2.id)}"]
180+
)
181+
{{
182+
mealRequest {{
183+
id
184+
requestor {{
185+
id
186+
}}
187+
status
188+
dropOffDatetime
189+
dropOffLocation
190+
mealInfo {{
191+
portions
192+
dietaryRestrictions
193+
}}
194+
onsiteContacts {{
195+
name
196+
email
197+
phone
198+
}}
199+
dateCreated
200+
dateUpdated
201+
deliveryInstructions
202+
donationInfo {{
203+
donor {{
204+
id
205+
}}
206+
commitmentDate
207+
mealDescription
208+
additionalInfo
209+
}}
210+
}}
211+
}}
212+
}}
213+
"""
214+
215+
result = graphql_schema.execute(mutation)
216+
217+
assert result.errors is None
218+
219+
meal_request_in_db = (
220+
MealRequest.objects(id=meal_request.id).first().to_serializable_dict()
221+
)
222+
223+
assert (
224+
meal_request_in_db["donation_info"]["meal_description"]
225+
== "potato chicken nugget"
226+
)
227+
assert meal_request_in_db["donation_info"]["additional_info"] == "kimchi fried rice"
228+
assert meal_request_in_db["donation_info"]["donor"] == donor.id
229+
meal_request_donor_onsite_contacts = meal_request_in_db["donation_info"][
230+
"donor_onsite_contacts"
231+
]
232+
in_db_contacts_sorted_by_id = sorted(
233+
meal_request_donor_onsite_contacts, key=lambda x: x["id"]
234+
)
235+
expected_contacts_sorted_by_id = sorted(
236+
[
237+
donor_onsite_contact.to_serializable_dict(),
238+
donor_onsite_contact2.to_serializable_dict(),
239+
],
240+
key=lambda x: x["id"],
241+
)
242+
assert in_db_contacts_sorted_by_id == expected_contacts_sorted_by_id
243+
244+
156245
# If a meal request is created with a date that is the
157246
# same as a previous meal request, an error is thrown
158247
def test_create_meal_request_fails_repeat_date(
@@ -162,7 +251,7 @@ def test_create_meal_request_fails_repeat_date(
162251
asp,
163252
donor,
164253
[asp_onsite_contact, asp_onsite_contact2],
165-
donor_onsite_contact,
254+
[donor_onsite_contact, donor_onsite_contact2],
166255
) = onsite_contact_setup
167256
_, _, meal_request = meal_request_setup
168257

@@ -347,7 +436,7 @@ def test_commit_to_meal_request_fails_for_non_donor(
347436
meal_request_setup, onsite_contact_setup
348437
):
349438
_, donor, meal_request = meal_request_setup
350-
requestor, _, asp_onsite_contacts, donor_onsite_contact = onsite_contact_setup
439+
requestor, _, asp_onsite_contacts, donor_onsite_contacts = onsite_contact_setup
351440

352441
# All user info roles except for "Donor"
353442
INVALID_USERINFO_ROLES = [UserInfoRole.ADMIN.value, UserInfoRole.ASP.value]
@@ -418,7 +507,7 @@ def test_commit_to_meal_request_fails_if_not_open(meal_request_setup):
418507

419508

420509
def test_update_meal_request(onsite_contact_setup, meal_request_setup):
421-
requestor, _, asp_onsite_contacts, donor_onsite_contact = onsite_contact_setup
510+
requestor, _, asp_onsite_contacts, donor_onsite_contacts = onsite_contact_setup
422511
_, _, meal_request = meal_request_setup
423512

424513
onsite_contact1 = asp_onsite_contacts[0]
@@ -862,7 +951,12 @@ def test_delete_meal_request_as_non_admin_fails_if_donor(meal_request_setup):
862951
def test_get_meal_request_by_donor_id(meal_request_setup, onsite_contact_setup):
863952
_, donor, meal_request = meal_request_setup
864953

865-
asp, donor, asp_onsite_contact, donor_onsite_contact = onsite_contact_setup
954+
(
955+
asp,
956+
donor,
957+
[asp_onsite_contact, asp_onsite_contact2],
958+
[donor_onsite_contact, donor_onsite_contact2],
959+
) = onsite_contact_setup
866960

867961
commit = graphql_schema.execute(
868962
f"""mutation testCommitToMealRequest {{

backend/tests/graphql/test_onsite_contact.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,13 @@ def test_create_onsite_contact(onsite_contact_setup):
5454

5555

5656
def test_update_onsite_contact(onsite_contact_setup):
57-
asp, donor, asp_onsite_contacts, donor_onsite_contact = onsite_contact_setup
57+
asp, donor, asp_onsite_contacts, donor_onsite_contacts = onsite_contact_setup
5858

5959
# Test for the update mutation
6060
mutation = f"""
6161
mutation u{{
6262
updateOnsiteContact(
63-
id: "{donor_onsite_contact.id}",
63+
id: "{donor_onsite_contacts[0].id}",
6464
name: "Updated Bob Cat",
6565
email: "updated_bob@test.com",
6666
phone: "604-433-2222",
@@ -78,7 +78,7 @@ def test_update_onsite_contact(onsite_contact_setup):
7878
result = graphql_schema.execute(mutation)
7979
assert result.errors is None
8080
updated_result_contact = result.data["updateOnsiteContact"]["onsiteContact"]
81-
updated_db_result = OnsiteContact.objects(id=donor_onsite_contact["id"]).first()
81+
updated_db_result = OnsiteContact.objects(id=donor_onsite_contacts[0]["id"]).first()
8282

8383
for contact in [updated_result_contact, updated_db_result]:
8484
assert contact["name"] == "Updated Bob Cat"

0 commit comments

Comments
 (0)