Example #1
0
    def handle(self, *args, **options):
        try:
            logger.info('Running command {}'.format(__name__))
            today = timezone.localtime(timezone.now()).date()
            # today = today + relativedelta(days=70)

            # Pick up all the remediation actions which are close to due and no notifications sent yet
            ras = RemediationAction.objects.filter(Q(due_date__lt=today) & Q(status=RemediationAction.STATUS_OPEN)). \
                exclude(notifications__in=RemediationActionNotification.objects.filter(type=RemediationActionNotification.TYPE_OVERDUE))

            for ra in ras:
                print(ra)

            # Send email (to: offender, bcc: officers)
            for ra in ras:
                try:
                    with transaction.atomic():
                        # Create new comms log entry
                        data = {'sanction_outcome': ra.sanction_outcome.id}
                        serializer = SanctionOutcomeCommsLogEntrySerializer(
                            data=data)
                        serializer.is_valid(raise_exception=True)
                        workflow_entry = serializer.save()

                        to_address = [
                            ra.sanction_outcome.get_offender()[0].email,
                        ]
                        cc = None
                        bcc = [
                            ra.sanction_outcome.responsible_officer.email
                        ] if ra.sanction_outcome.responsible_officer else [
                            member.email for member in
                            ra.sanction_outcome.allocated_group.members
                        ]
                        attachments = []
                        email_data = send_notification_overdue_remediation_action(
                            to_address, ra.sanction_outcome, cc, bcc,
                            attachments)

                        # Record in the RemediationActionNotification
                        data = {
                            'remediation_action_id': ra.id,
                            'sanction_outcome_comms_log_entry_id':
                            workflow_entry.id,
                            'type': RemediationActionNotification.TYPE_OVERDUE,
                        }
                        serializer = RemediationActionNotificationCreateSerializer(
                            data=data)
                        serializer.is_valid(raise_exception=True)
                        ran = serializer.save()

                        # Set remediation action status to the 'overdue'
                        serializer = RemediationActionUpdateStatusSerializer(
                            ra,
                            data={'status': RemediationAction.STATUS_OVERDUE},
                        )
                        serializer.is_valid(raise_exception=True)
                        serializer.save()

                        # Comms log
                        if email_data:
                            serializer = SanctionOutcomeCommsLogEntrySerializer(
                                workflow_entry, data=email_data, partial=True)
                            serializer.is_valid(raise_exception=True)
                            serializer.save()

                        # Action log, status has been changed to the 'overdue', record it as an action
                        ra.sanction_outcome.log_user_action(
                            SanctionOutcomeUserAction.
                            ACTION_REMEDIATION_ACTION_OVERDUE.format(
                                ra.remediation_action_id))
                except Exception as e:
                    logger.error('Error command {}'.format(__name__))

            logger.info('Command {} completed'.format(__name__))

        except Exception as e:
            logger.error('Error command {}'.format(__name__))
    def handle(self, *args, **options):
        try:
            with transaction.atomic():
                logger.info('Running command {}'.format(__name__))
                today = timezone.localtime(timezone.now()).date()

                # Retrieve quersyset of SanctionOutcomes
                # type == 'infringement_notice'
                # is_parking_offence == True
                # status == 'with_dot'
                # details not sent to the DoT yet
                acos = AllegedCommittedOffence.objects.filter(Q(sanction_outcome__type=SO_TYPE_INFRINGEMENT_NOTICE) &
                                                              Q(sanction_outcome__status=SanctionOutcome.STATUS_WITH_DOT) &
                                                              Q(sanction_outcome__offender=None) &
                                                              Q(sanction_outcome__dot_request_files=None) &
                                                              Q(included=True) &
                                                              Q(alleged_offence__removed=False) &
                                                              Q(alleged_offence__section_regulation__is_parking_offence=True)).\
                                                        exclude(sanction_outcome__payment_status=SanctionOutcome.PAYMENT_STATUS_PAID)

                count = acos.count()
                logger.info(
                    '{} parking infringement notice(s) found to process.'.
                    format(str(count)))

                for aco in acos:
                    print(aco.sanction_outcome.id)

                if count:
                    file_for_dot = DotRequestFile()
                    file_for_dot.save(
                    )  # Create the object to save manytomany fields

                    index = 1
                    for aco in acos:
                        try:
                            file_for_dot.contents += aco.sanction_outcome.registration_number + ',' + str(
                                index
                            ).zfill(
                                2
                            ) + ',' + aco.sanction_outcome.offence_occurrence_date.strftime(
                                "%d%m%Y") + '\r\n'
                            file_for_dot.sanction_outcomes.add(
                                aco.sanction_outcome)
                        except Exception as e:
                            logger.error('Error command {}'.format(__name__))

                    if not file_for_dot.sanction_outcomes.count():
                        return

                    file_for_dot.filename = 'DPaw-' + datetime.date.today(
                    ).strftime("%d%b%Y") + '-Request.txt'
                    file_for_dot.save()

                    # Determine the bcc
                    members = get_infringement_notice_coordinators()
                    recipients = [
                        member.email for member in members
                    ] if members else [settings.NOTIFICATION_EMAIL]

                    # Email
                    to_address = recipients
                    cc = None
                    bcc = None
                    attachments = [
                        (file_for_dot.filename, file_for_dot.contents,
                         'text/plain'),
                    ]
                    email_data = email_detais_to_department_of_transport(
                        to_address, attachments, cc, bcc)

                    # # Add communication log
                    if email_data:
                        for so in file_for_dot.sanction_outcomes.all():
                            email_data['sanction_outcome'] = so.id
                            serializer = SanctionOutcomeCommsLogEntrySerializer(
                                data=email_data, partial=True)
                            serializer.is_valid(raise_exception=True)
                            serializer.save()

                    # Record action log per infringement notice
                    for so in file_for_dot.sanction_outcomes.all():
                        so.log_user_action(
                            SanctionOutcomeUserAction.ACTION_SEND_TO_DOT.
                            format(so.lodgement_number))
                        so.status = SanctionOutcome.STATUS_WITH_DOT  # probably already WITH_DOT
                        so.save()

                logger.info('Command {} completed'.format(__name__))

        except Exception as e:
            logger.error('Error command {}'.format(__name__))
    def handle(self, *args, **options):
        try:
            with transaction.atomic():
                logger.info('Running command {}'.format(__name__))
                today = timezone.localtime(timezone.now()).date()

                # Retrieve sanction outcomes whose type is Infringement Notice and which is unpaid
                sanction_outcomes_base = SanctionOutcome.objects.filter(
                    Q(type=SanctionOutcome.TYPE_INFRINGEMENT_NOTICE) &
                    Q(status=SanctionOutcome.STATUS_AWAITING_PAYMENT) &
                    Q(payment_status=SanctionOutcome.PAYMENT_STATUS_UNPAID))\
                    .filter(due_dates__in=SanctionOutcomeDueDate.objects.filter(Q(due_date_2nd__lt=today) & Q(due_date_term_currently_applied='2nd')))

                if DEBUG:
                    # For debugging purpose, infringement notice which has the string '__overdue2nd__' in the description field is also selected.
                    logger.info('DEBUG = True')
                    sanction_outcomes_debug = SanctionOutcome.objects.filter(
                        Q(type=SanctionOutcome.TYPE_INFRINGEMENT_NOTICE) &
                        # Q(status=SanctionOutcome.STATUS_AWAITING_PAYMENT) &
                        # Q(payment_status=SanctionOutcome.PAYMENT_STATUS_UNPAID) &
                        Q(description__icontains='__overdue2nd__'))
                    # .filter(due_dates__in=SanctionOutcomeDueDate.objects.filter(Q(due_date_term_currently_applied='2nd')))

                # Merge querysets
                sanction_outcomes = (sanction_outcomes_base
                                     | sanction_outcomes_debug).distinct()

                count = sanction_outcomes.count()
                logger.info(
                    '{} overdue (1st) infringement notice(s) found.'.format(
                        str(count)))

                if count:
                    # Create record first to generate filename based on the ID
                    uin_file = UnpaidInfringementFile()
                    uin_file.save()

                    # Construct header
                    uin_header = UnpaidInfringementFileHeader()
                    uin_header.agency_code.set('DPW')
                    uin_header.uin_file_reference.set(uin_file.filename)
                    uin_header.date_created.set(datetime.date.today())
                    uin_header.responsible_officer.set('')
                    content_header = uin_header.get_content()

                    # Construct body
                    content_body = ''
                    penalty_amount_total = 0
                    for so in sanction_outcomes:
                        try:
                            content_body += so.get_content_for_uin()
                            penalty_amount_total += so.penalty_amount_2nd
                        except Exception as e:
                            logger.error(
                                'Error command {} for the sanction outcome: {}'
                                .format(__name__, str(so.id)))

                    # Construct trailer
                    uin_trailer = UnpaidInfringementFileTrailer()
                    uin_trailer.number_of_records.set(
                        sanction_outcomes.count())
                    uin_trailer.total_penalty_amount.set(penalty_amount_total)
                    uin_trailer.first_additional_cost_code.set('')
                    uin_trailer.first_additional_cost_total.set('')
                    uin_trailer.second_additional_cost_code.set('')
                    uin_trailer.second_additional_cost_total.set('')
                    content_trailer = uin_trailer.get_content()

                    # Construct file contents
                    contents_to_attach = content_header + content_body + content_trailer

                    # Save contents in the DB, too
                    uin_file.contents = contents_to_attach
                    uin_file.save()

                    # Determine the recipients
                    members = get_infringement_notice_coordinators()

                    # Emailing

                    to_address = [
                        member.email for member in members
                    ] if members else [settings.NOTIFICATION_EMAIL]
                    cc = None
                    bcc = None
                    attachments = [
                        (uin_file.filename, contents_to_attach, 'text/plain'),
                    ]
                    email_data = send_unpaid_infringements_file(
                        to_address, cc, bcc, attachments)

                    # # Add communication log
                    if email_data:
                        for so in sanction_outcomes:
                            email_data['sanction_outcome'] = so.id
                            serializer = SanctionOutcomeCommsLogEntrySerializer(
                                data=email_data, partial=True)
                            serializer.is_valid(raise_exception=True)
                            serializer.save()

                    # Record action log per infringement notice
                    # for dict_item in due_dates:
                    for so in sanction_outcomes:
                        so.log_user_action(
                            SanctionOutcomeUserAction.
                            ACTION_SEND_DETAILS_TO_INFRINGEMENT_NOTICE_COORDINATOR
                            .format(so.lodgement_number))
                        so.status = SanctionOutcome.STATUS_OVERDUE
                        so.save()

                        # Create new due_date record
                        data = {}
                        data['due_date_1st'] = None
                        data['due_date_2nd'] = None
                        data['reason_for_extension'] = 'Overdue 2nd due date'
                        data['extended_by_id'] = None
                        data['sanction_outcome_id'] = so.id
                        data['due_date_term_currently_applied'] = 'overdue'
                        serializer = SaveSanctionOutcomeDueDateSerializer(
                            data=data)
                        serializer.is_valid(raise_exception=True)
                        serializer.save()

                logger.info('Command {} completed'.format(__name__))

        except Exception as e:
            logger.error('Error command {}'.format(__name__))
Example #4
0
    def handle(self, *args, **options):
        try:
            logger.info('Running command {}'.format(__name__))
            today = timezone.localtime(timezone.now()).date()
            one_week_before = today + relativedelta(days=7)

            # Pick up all the remediation actions which are close to due and no notifications sent yet
            ras = RemediationAction.objects\
                .filter(
                    Q(due_date__lt=one_week_before) &
                    Q(status=RemediationAction.STATUS_OPEN))\
                .exclude(notifications__in=RemediationActionNotification.objects.filter(type=RemediationActionNotification.TYPE_CLOSE_TO_DUE))

            for ra in ras:
                print(ra)

            # Send email (to: offender, bcc: officers)
            for ra in ras:
                try:
                    with transaction.atomic():
                        data = {'sanction_outcome': ra.sanction_outcome.id}
                        serializer = SanctionOutcomeCommsLogEntrySerializer(
                            data=data)
                        serializer.is_valid(raise_exception=True)
                        workflow_entry = serializer.save()

                        to_address = [
                            ra.sanction_outcome.get_offender()[0].email,
                        ]
                        cc = None
                        bcc = [
                            member.email for member in
                            ra.sanction_outcome.allocated_group.members
                        ]
                        attachments = []
                        email_data = send_notification_close_to_due_remediation_action(
                            to_address, ra.sanction_outcome, workflow_entry,
                            cc, bcc, attachments)

                        # Record in the RemediationActionNotification
                        data = {
                            'remediation_action_id':
                            ra.id,
                            'sanction_outcome_comms_log_entry_id':
                            workflow_entry.id,
                            'type':
                            RemediationActionNotification.TYPE_CLOSE_TO_DUE,
                        }
                        serializer = RemediationActionNotificationCreateSerializer(
                            data=data)
                        serializer.is_valid(raise_exception=True)
                        ran = serializer.save()

                        # Comms log
                        if email_data:
                            serializer = SanctionOutcomeCommsLogEntrySerializer(
                                workflow_entry, data=email_data, partial=True)
                            serializer.is_valid(raise_exception=True)
                            serializer.save()

                        # Action log: sending reminder mail doesn't require an action log entry
                except Exception as e:
                    logger.error('Error command {}'.format(__name__))

            logger.info('Command {} completed'.format(__name__))

        except Exception as e:
            logger.error('Error command {}'.format(__name__))