diff --git a/ietf/stats/management/commands/find_meetingregistration_person_issues.py b/ietf/stats/management/commands/find_meetingregistration_person_issues.py new file mode 100644 index 000000000..5dd6919e5 --- /dev/null +++ b/ietf/stats/management/commands/find_meetingregistration_person_issues.py @@ -0,0 +1,37 @@ +# Copyright The IETF Trust 2021, All Rights Reserved + +import debug # pyflakes:ignore + +from django.core.management.base import BaseCommand, CommandError + +from ietf.stats.utils import find_meetingregistration_person_issues + +class Command(BaseCommand): + help = "Find possible Person/Email objects to repair based on MeetingRegistration objects" + + def add_arguments(self, parser): + parser.add_argument('--meeting',action='append') + + def handle(self, *args, **options): + meetings = options['meeting'] or None + summary = find_meetingregistration_person_issues(meetings) + + print(f'{summary.ok_records} records are OK') + + for msg in summary.could_be_fixed: + print(msg) + + for msg in summary.maybe_address: + print(msg) + + for msg in summary.different_person: + print(msg) + + for msg in summary.no_person: + print(msg) + + for msg in summary.maybe_person: + print(msg) + + for msg in summary.no_email: + print(msg) diff --git a/ietf/stats/management/commands/repair_meetingregistration_person.py b/ietf/stats/management/commands/repair_meetingregistration_person.py new file mode 100644 index 000000000..450054c09 --- /dev/null +++ b/ietf/stats/management/commands/repair_meetingregistration_person.py @@ -0,0 +1,18 @@ +# Copyright The IETF Trust 2021, All Rights Reserved + +import debug # pyflakes:ignore + +from django.core.management.base import BaseCommand, CommandError + +from ietf.stats.utils import repair_meetingregistration_person + +class Command(BaseCommand): + help = "Repair MeetingRegistration objects that have no person but an email matching a person" + + def add_arguments(self, parser): + parser.add_argument('--meeting',action='append') + + def handle(self, *args, **options): + meetings = options['meeting'] or None + repaired = repair_meetingregistration_person(meetings) + print(f'Repaired {repaired} MeetingRegistration objects') \ No newline at end of file diff --git a/ietf/stats/utils.py b/ietf/stats/utils.py index e91a3d737..704e8a4ef 100644 --- a/ietf/stats/utils.py +++ b/ietf/stats/utils.py @@ -346,47 +346,56 @@ def get_meeting_registration_data(meeting): meeting.save() return num_created, num_processed, num_total -# Might abandon this as too ambitious - if fixed things for 128 people in ietf 100 - 110 though, and that's probably worth doing. -# Yeah - experiments say it _must_ be done. Probably need this as a management command. def repair_meetingregistration_person(meetings=None): - maybe_address = set() - different_person = set() - no_person = set() - maybe_person = set() - no_email = set() - ok_records = 0 - skipped = 0 repaired_records = 0 + qs = MeetingRegistration.objects.all() + if meetings: + qs = qs.filter(meeting__number__in=meetings) + for mr in qs: + if mr.email and not mr.person: + email_person = Person.objects.filter(email__address=mr.email).first() + if email_person: + mr.person = email_person + mr.save() + repaired_records += 1 + return repaired_records +class MeetingRegistrationIssuesSummary(object): + pass -# for mr in MeetingRegistration.objects.exclude(person__email__address=F('email')): - for mr in MeetingRegistration.objects.all(): - if meetings and mr.meeting.number not in meetings: - skipped += 1 - continue +def find_meetingregistration_person_issues(meetings=None): + summary = MeetingRegistrationIssuesSummary() + + summary.could_be_fixed = set() + summary.maybe_address = set() + summary.different_person = set() + summary.no_person = set() + summary.maybe_person = set() + summary.no_email = set() + summary.ok_records = 0 + + qs = MeetingRegistration.objects.all() + if meetings: + qs = qs.filter(meeting__number__in=meetings) + for mr in qs: if mr.person and mr.email and mr.email in mr.person.email_set.values_list('address',flat=True): - ok_records += 1 - continue - if mr.email: + summary.ok_records += 1 + elif mr.email: email_person = Person.objects.filter(email__address=mr.email).first() if mr.person: if not email_person: - maybe_address.add(f'{mr.email} is not present in any Email object. The MeetingRegistration object implies this is an address for {mr.person} ({mr.person.pk})') + summary.maybe_address.add(f'{mr.email} is not present in any Email object. The MeetingRegistration object implies this is an address for {mr.person} ({mr.person.pk})') elif email_person != mr.person: - different_person.add(f'{mr} ({mr.pk}) has person {mr.person} ({mr.person.pk}) but an email {mr.email} attached to a different person {email_person} ({email_person.pk}).') + summary.different_person.add(f'{mr} ({mr.pk}) has person {mr.person} ({mr.person.pk}) but an email {mr.email} attached to a different person {email_person} ({email_person.pk}).') elif email_person: - mr.person = email_person - mr.save() - repaired_records += 1 + summary.could_be_fixed.add(f'{mr} ({mr.pk}) has no person, but email {mr.email} matches {email_person} ({email_person.pk})') else: maybe_person_qs = Person.objects.filter(name__icontains=mr.last_name).filter(name__icontains=mr.first_name) -# if not maybe_person_qs.exists(): -# maybe_person_qs = Person.objects.filter(name__icontains=mr.last_name) - if maybe_person_qs: - maybe_person.add(f'{mr} ({mr.pk}) has email address {mr.email} which cannot be associated with any Person. Consider these possible people {[(p,p.pk) for p in maybe_person_qs]}') + if maybe_person_qs.exists(): + summary.maybe_person.add(f'{mr} ({mr.pk}) has email address {mr.email} which cannot be associated with any Person. Consider these possible people {[(p,p.pk) for p in maybe_person_qs]}') else: - no_person.add(f'{mr} ({mr.pk}) has email address {mr.email} which cannot be associated with any Person') + summary.no_person.add(f'{mr} ({mr.pk}) has email address {mr.email} which cannot be associated with any Person') else: - no_email.add(f'{mr} ({mr.pk}) provides no email address') + summary.no_email.add(f'{mr} ({mr.pk}) provides no email address') - return ok_records, repaired_records, skipped, maybe_address, different_person, maybe_person, no_person, no_email + return summary