✨(contacts) add notes & force full_name
We make the full name mandatory and add a field to allow user to store personnal notes on the contact. This also make the "base" contact not mandatory because user may want to create new contacts out of the blue.
This commit is contained in:
@@ -8,6 +8,10 @@ and this project adheres to
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- ✨(contacts) add notes & force full_name #565
|
||||
|
||||
## [1.7.1] - 2024-11-28
|
||||
|
||||
## [1.7.0] - 2024-11-28
|
||||
|
||||
@@ -17,10 +17,14 @@ class ContactSerializer(serializers.ModelSerializer):
|
||||
"base",
|
||||
"data",
|
||||
"full_name",
|
||||
"notes",
|
||||
"owner",
|
||||
"short_name",
|
||||
]
|
||||
read_only_fields = ["id", "owner"]
|
||||
extra_kwargs = {
|
||||
"base": {"required": False},
|
||||
}
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
"""Make "base" field readonly but only for update/patch."""
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# Generated by Django 5.1.3 on 2024-11-28 09:37
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0005_add_serviceprovider'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='contact',
|
||||
name='notes',
|
||||
field=models.TextField(blank=True, default='', verbose_name='notes'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='contact',
|
||||
name='full_name',
|
||||
field=models.CharField(default='-', max_length=150, verbose_name='full name'),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
||||
@@ -113,11 +113,11 @@ class Contact(BaseModel):
|
||||
null=True,
|
||||
blank=True,
|
||||
)
|
||||
full_name = models.CharField(_("full name"), max_length=150, null=True, blank=True)
|
||||
full_name = models.CharField(_("full name"), max_length=150)
|
||||
short_name = models.CharField(_("short name"), max_length=30, null=True, blank=True)
|
||||
|
||||
# avatar =
|
||||
# notes =
|
||||
notes = models.TextField(_("notes"), blank=True, default="")
|
||||
data = models.JSONField(
|
||||
_("contact information"),
|
||||
help_text=_("A JSON object containing the contact information"),
|
||||
@@ -151,7 +151,7 @@ class Contact(BaseModel):
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return self.full_name or self.short_name
|
||||
return self.full_name
|
||||
|
||||
def clean(self):
|
||||
"""Validate fields."""
|
||||
|
||||
@@ -97,6 +97,7 @@ def test_api_contacts_list_authenticated_no_query():
|
||||
"owner": str(contact2.owner.id),
|
||||
"data": contact2.data,
|
||||
"full_name": contact2.full_name,
|
||||
"notes": "",
|
||||
"short_name": contact2.short_name,
|
||||
},
|
||||
]
|
||||
@@ -271,6 +272,7 @@ def test_api_contacts_retrieve_authenticated_owned():
|
||||
"owner": str(contact.owner.id),
|
||||
"data": contact.data,
|
||||
"full_name": contact.full_name,
|
||||
"notes": "",
|
||||
"short_name": contact.short_name,
|
||||
}
|
||||
|
||||
@@ -293,6 +295,7 @@ def test_api_contacts_retrieve_authenticated_public():
|
||||
"owner": None,
|
||||
"data": contact.data,
|
||||
"full_name": contact.full_name,
|
||||
"notes": "",
|
||||
"short_name": contact.short_name,
|
||||
}
|
||||
|
||||
@@ -328,7 +331,7 @@ def test_api_contacts_create_anonymous_forbidden():
|
||||
|
||||
|
||||
def test_api_contacts_create_authenticated_missing_base():
|
||||
"""Anonymous users should be able to create users."""
|
||||
"""Authenticated user should be able to create contact without override."""
|
||||
user = factories.UserFactory(profile_contact=None)
|
||||
|
||||
client = APIClient()
|
||||
@@ -339,13 +342,23 @@ def test_api_contacts_create_authenticated_missing_base():
|
||||
{
|
||||
"full_name": "David Bowman",
|
||||
"short_name": "Dave",
|
||||
"data": {},
|
||||
},
|
||||
format="json",
|
||||
)
|
||||
assert response.status_code == 400
|
||||
assert models.Contact.objects.exists() is False
|
||||
assert response.status_code == 201
|
||||
|
||||
assert response.json() == {"base": ["This field is required."]}
|
||||
new_contact = models.Contact.objects.get(owner=user)
|
||||
|
||||
assert response.json() == {
|
||||
"base": None,
|
||||
"data": {},
|
||||
"full_name": "David Bowman",
|
||||
"id": str(new_contact.pk),
|
||||
"notes": "",
|
||||
"owner": str(user.pk),
|
||||
"short_name": "Dave",
|
||||
}
|
||||
|
||||
|
||||
def test_api_contacts_create_authenticated_successful():
|
||||
@@ -379,6 +392,7 @@ def test_api_contacts_create_authenticated_successful():
|
||||
"base": str(base_contact.id),
|
||||
"data": CONTACT_DATA,
|
||||
"full_name": "David Bowman",
|
||||
"notes": "",
|
||||
"owner": str(user.id),
|
||||
"short_name": "Dave",
|
||||
}
|
||||
@@ -408,6 +422,7 @@ def test_api_contacts_create_authenticated_existing_override():
|
||||
{
|
||||
"base": str(base_contact.id),
|
||||
"full_name": "David Bowman",
|
||||
"notes": "",
|
||||
"short_name": "Dave",
|
||||
"data": CONTACT_DATA,
|
||||
},
|
||||
@@ -422,6 +437,45 @@ def test_api_contacts_create_authenticated_existing_override():
|
||||
}
|
||||
|
||||
|
||||
def test_api_contacts_create_authenticated_successful_with_notes():
|
||||
"""Authenticated users should be able to create contacts with notes."""
|
||||
user = factories.UserFactory(profile_contact=None)
|
||||
|
||||
client = APIClient()
|
||||
client.force_login(user)
|
||||
|
||||
response = client.post(
|
||||
"/api/v1.0/contacts/",
|
||||
{
|
||||
"full_name": "David Bowman",
|
||||
"short_name": "Dave",
|
||||
"data": CONTACT_DATA,
|
||||
"notes": "This is a note",
|
||||
},
|
||||
format="json",
|
||||
)
|
||||
|
||||
assert response.status_code == 201
|
||||
assert models.Contact.objects.count() == 1
|
||||
|
||||
contact = models.Contact.objects.get(owner=user)
|
||||
assert response.json() == {
|
||||
"id": str(contact.id),
|
||||
"base": None,
|
||||
"data": CONTACT_DATA,
|
||||
"full_name": "David Bowman",
|
||||
"notes": "This is a note",
|
||||
"owner": str(user.id),
|
||||
"short_name": "Dave",
|
||||
}
|
||||
|
||||
assert contact.full_name == "David Bowman"
|
||||
assert contact.short_name == "Dave"
|
||||
assert contact.data == CONTACT_DATA
|
||||
assert contact.owner == user
|
||||
assert contact.notes == "This is a note"
|
||||
|
||||
|
||||
def test_api_contacts_update_anonymous():
|
||||
"""Anonymous users should not be allowed to update a contact."""
|
||||
contact = factories.ContactFactory()
|
||||
|
||||
@@ -17,12 +17,6 @@ def test_models_contacts_str_full_name():
|
||||
assert str(contact) == "David Bowman"
|
||||
|
||||
|
||||
def test_models_contacts_str_short_name():
|
||||
"""The str representation should be the contact's short name if full name is not set."""
|
||||
contact = factories.ContactFactory(full_name=None, short_name="Dave")
|
||||
assert str(contact) == "Dave"
|
||||
|
||||
|
||||
def test_models_contacts_base_self():
|
||||
"""A contact should not point to itself as a base contact."""
|
||||
contact = factories.ContactFactory()
|
||||
|
||||
Reference in New Issue
Block a user