Skip to content

Commit

Permalink
Merge branch 'main' into andrew/fix-import-2
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew-Dickinson authored Jul 6, 2024
2 parents 66a726c + 76ab45b commit c2b3e84
Show file tree
Hide file tree
Showing 10 changed files with 108 additions and 4 deletions.
2 changes: 2 additions & 0 deletions src/meshapi/admin/member.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class MemberAdmin(admin.ModelAdmin):
"stripe_email_address__icontains",
"additional_email_addresses__icontains",
"phone_number__icontains",
"additional_phone_numbers__icontains",
"slack_handle__icontains",
# Search by building details
"installs__building__street_address__icontains",
Expand Down Expand Up @@ -71,6 +72,7 @@ class MemberAdmin(admin.ModelAdmin):
{
"fields": [
"phone_number",
"additional_phone_numbers",
"slack_handle",
]
},
Expand Down
1 change: 1 addition & 0 deletions src/meshapi/management/commands/scramble_members.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def handle(self, *args: Any, **options: Any) -> None:
member.stripe_email_address = ""
member.additional_email_addresses = []
member.phone_number = fake.phone_number()
member.additional_phone_numbers = [] if randint(0, 100) > 0 else [fake.phone_number()]
member.slack_handle = ""
member.notes = fake.text()
member.save()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Generated by Django 4.2.10 on 2024-06-01 23:49

import django_jsonform.models.fields
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("meshapi", "0008_alter_building_notes_alter_install_notes_and_more"),
]

operations = [
migrations.AddField(
model_name="member",
name="additional_phone_numbers",
field=django_jsonform.models.fields.ArrayField(
base_field=models.CharField(),
blank=True,
default=list,
help_text="Any additional phone numbers used by this member",
null=True,
size=None,
),
),
migrations.AlterField(
model_name="member",
name="phone_number",
field=models.CharField(
blank=True, default=None, help_text="A primary contact phone number for this member", null=True
),
),
]
22 changes: 21 additions & 1 deletion src/meshapi/models/member.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,14 @@ class Member(models.Model):
help_text="Any additional email addresses associated with this member",
)
phone_number = models.CharField(
default=None, blank=True, null=True, help_text="A contact phone number for this member"
default=None, blank=True, null=True, help_text="A primary contact phone number for this member"
)
additional_phone_numbers = JSONFormArrayField(
models.CharField(),
default=list,
null=True,
blank=True,
help_text="Any additional phone numbers used by this member",
)
slack_handle = models.CharField(default=None, blank=True, null=True, help_text="The member's slack handle")
notes = models.TextField(
Expand Down Expand Up @@ -55,3 +62,16 @@ def all_email_addresses(self) -> List[str]:
all_emails.append(email)

return all_emails

@property
def all_phone_numbers(self) -> List[str]:
all_phone_numbers = []
if self.phone_number and self.phone_number not in all_phone_numbers:
all_phone_numbers.append(self.phone_number)

if self.additional_phone_numbers:
for phone_number in self.additional_phone_numbers:
if phone_number not in all_phone_numbers:
all_phone_numbers.append(phone_number)

return all_phone_numbers
1 change: 1 addition & 0 deletions src/meshapi/serializers/model_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class Meta:
fields = "__all__"

all_email_addresses: serializers.ReadOnlyField = serializers.ReadOnlyField()
all_phone_numbers: serializers.ReadOnlyField = serializers.ReadOnlyField()
installs: serializers.PrimaryKeyRelatedField = serializers.PrimaryKeyRelatedField(many=True, read_only=True)


Expand Down
4 changes: 4 additions & 0 deletions src/meshapi/serializers/query_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class Meta:
"zip_code",
"name",
"phone_number",
"additional_phone_numbers",
"primary_email_address",
"stripe_email_address",
"additional_email_addresses",
Expand All @@ -36,6 +37,9 @@ class Meta:

name = serializers.CharField(source="member.name")
phone_number = serializers.CharField(source="member.phone_number")
additional_phone_numbers = serializers.ListField(
source="member.additional_phone_numbers", child=serializers.CharField()
)

network_number = serializers.IntegerField(source="node.network_number", allow_null=True)

Expand Down
14 changes: 14 additions & 0 deletions src/meshapi/tests/test_lookups.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def setUp(self):
stripe_email_address="[email protected]",
additional_email_addresses=["[email protected]"],
phone_number="555-555-6666",
additional_phone_numbers=["123-555-8888"],
)
m2.save()

Expand Down Expand Up @@ -105,6 +106,19 @@ def test_member_phone_search(self):
self.assertEqual(len(response_objs), 1)
self.assertEqual(response_objs[0]["name"], "Donald Smith")

def test_member_additional_phone_search(self):
response = self.c.get("/api/v1/members/lookup/?phone_number=8888")
code = 200
self.assertEqual(
code,
response.status_code,
f"status code incorrect. Should be {code}, but got {response.status_code}",
)

response_objs = json.loads(response.content)["results"]
self.assertEqual(len(response_objs), 1)
self.assertEqual(response_objs[0]["name"], "Donald Smith")

def test_member_combined_search(self):
response = self.c.get("/api/v1/members/lookup/?phone_number=555&email_address=smith&name=don")
code = 200
Expand Down
24 changes: 24 additions & 0 deletions src/meshapi/tests/test_member.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,30 @@ def test_member_all_emails_field(self):
["[email protected]", "[email protected]", "[email protected]", "[email protected]"],
)

def test_member_all_phone_numbers_field(self):
test_member = Member(
name="Stacy Fakename",
primary_email_address="[email protected]",
phone_number="+1 123-555-5555",
additional_phone_numbers=["+1 456-555-6666"],
)
test_member.save()

response = self.c.get(f"/api/v1/members/{test_member.id}/")
code = 200
self.assertEqual(
code,
response.status_code,
f"status code incorrect. Should be {code}, but got {response.status_code}",
)

response_obj = json.loads(response.content)
self.assertEqual(response_obj["name"], "Stacy Fakename")
self.assertEqual(response_obj["primary_email_address"], "[email protected]")
self.assertEqual(response_obj["phone_number"], "+1 123-555-5555")
self.assertEqual(response_obj["additional_phone_numbers"], ["+1 456-555-6666"])
self.assertEqual(response_obj["all_phone_numbers"], ["+1 123-555-5555", "+1 456-555-6666"])

def test_broken_member(self):
err_member = {
"id": "Error",
Expand Down
7 changes: 5 additions & 2 deletions src/meshapi/views/lookups.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def get(self, request: Request, *args: Any, **kwargs: Any) -> Response:
class MemberFilter(filters.FilterSet):
name = filters.CharFilter(field_name="name", lookup_expr="icontains")
email_address = filters.CharFilter(method="filter_on_all_emails")
phone_number = filters.CharFilter(field_name="phone_number", lookup_expr="icontains")
phone_number = filters.CharFilter(method="filter_on_all_phone_numbers")

def filter_on_all_emails(self, queryset: QuerySet[Member], field_name: str, value: str) -> QuerySet[Member]:
return queryset.filter(
Expand All @@ -50,6 +50,9 @@ def filter_on_all_emails(self, queryset: QuerySet[Member], field_name: str, valu
| Q(additional_email_addresses__icontains=value)
)

def filter_on_all_phone_numbers(self, queryset: QuerySet[Member], field_name: str, value: str) -> QuerySet[Member]:
return queryset.filter(Q(phone_number__icontains=value) | Q(additional_phone_numbers__icontains=value))

class Meta:
model = Member
fields: List[Any] = []
Expand Down Expand Up @@ -78,7 +81,7 @@ class Meta:
"phone_number",
OpenApiTypes.STR,
OpenApiParameter.QUERY,
description="Filter members by the phone_number field using case-insensitve substring matching",
description="Filter members by any of the phone number fields using case-insensitve substring matching",
required=False,
),
],
Expand Down
5 changes: 4 additions & 1 deletion src/meshapi/views/query_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
class QueryMemberFilter(filters.FilterSet):
name = filters.CharFilter(field_name="member.name", lookup_expr="icontains")
email_address = filters.CharFilter(method="filter_on_all_emails")
phone_number = filters.CharFilter(field_name="member.phone_number", lookup_expr="icontains")
phone_number = filters.CharFilter(method="filter_on_all_phone_numbers")

def filter_on_all_emails(self, queryset: QuerySet[Member], field_name: str, value: str) -> QuerySet[Member]:
return queryset.filter(
Expand All @@ -31,6 +31,9 @@ def filter_on_all_emails(self, queryset: QuerySet[Member], field_name: str, valu
| Q(member__additional_email_addresses__icontains=value)
)

def filter_on_all_phone_numbers(self, queryset: QuerySet[Member], name: str, value: str) -> QuerySet[Member]:
return queryset.filter(Q(phone_number__icontains=value) | Q(additional_phone_numbers__icontains=value))

class Meta:
model = Install
fields: List[str] = []
Expand Down

0 comments on commit c2b3e84

Please sign in to comment.