示例#1
0
    def rating_identifier_formatted(self):
        """An identifier that follows the rating through its
        live span."""

        # Preliminary ratings have their own ID's
        if self.rating_decision.is_preliminary:
            b = 'P_'
        else:
            b = ''

        b += (format_reference_number(number=self.rating_identifier,
                                      object_type='rating_decision') + '_' +
              self.qtratingaction.qtratinginfo.get_time_horizon_display())

        try:
            # This is an issue rating, add issuer suffic
            if self.qtratingaction.qtratinginfo.qtinstrumentinfo.\
                    instrument_internal_code:

                b += '_' + self.qtratingaction.qtratinginfo.\
                    qtinstrumentinfo.instrument_internal_code
        except:  # noqa: E722
            #  todo: catch RelatedObjectDoesNotExist
            pass

        return b
示例#2
0
    def preliminary_rating_identifier(self):
        """ESMA-specified unique identifier for preliminary rating.

        If instrument is true, return instrument identifier,
        else rating identifier."""

        if self.preceding_preliminary_rating_flag:
            b = 'P_'

            b += format_reference_number(
                number=self.rating_info.rating_action.rating_create_data.
                rating_decision.esma_rating_identifier,
                object_type='rating_decision',
            )

            b += self.rating_info.rating_action.\
                qtratinginfo.get_time_horizon_display()

            try:
                b += self.rating_info.qtinstrumentinfo.instrument_internal_code
            except:  # noqa: E722
                pass

            return b
示例#3
0
 def instrument_internal_code(self):
     """Internal ID for the issue."""
     return format_reference_number(number=self.issue.pk,
                                    object_type='issue')
示例#4
0
 def rating_scale_code(self):
     """A code used internally by ESMA"""
     return format_reference_number(number=self.rating_scale.pk,
                                    object_type='rating_scale')
示例#5
0
 def issuer_internal_code(self):
     """A unique identifier for this record?."""
     return format_reference_number(
         number=self.rating_info.rating_action.rating_create_data.
         rating_decision.issuer.pk,
         object_type='issuer')
def populate_rating_scale(xml_file):
    """Scan original model and return change reason as well as change type."""

    create_record = False
    esma_record = None

    create_or_update_id = []

    reporting_reason_dict = {}
    reporting_type_dict = {}
    change_reason_dict = {}
    """Rating scale."""
    for rating_scale in RatingScaleOrig.objects.order_by('id').all():
        """Do a field by field comparison"""
        # Unique identifier for this model
        unique_identifier_rating_scale = format_reference_number(
            object_type='rating_scale', number=rating_scale.id)

        try:
            esma_record = RatingScaleESMA.objects.filter(
                rating_scale_code=unique_identifier_rating_scale,
                xml_file__status_code=1).order_by('-id').all()[0]

        except (IndexError, RatingScaleESMA.DoesNotExist):
            """There is no record in the ESMA model, create it."""

            create_record = True

            # Create a list of IDs that should be inserted
            create_or_update_id.append(rating_scale.id)

            reporting_type_dict[rating_scale.id] = 1  # 1=NEW

            # must be list
            reporting_reason_dict[rating_scale.id] = [STRING_NEW_ITEM]

        if not create_record:
            """There is an existing parent, check for differences and if
            differences, generate change reason and change."""

            reporting_reason_dict[rating_scale.id] = []

            for compare_obj in RSCALE_COMPARE_FIELDS:
                """Compare value of field in base model with ESMA record."""
                if (getattr(rating_scale, compare_obj['field_orig']) !=
                        getattr(esma_record, compare_obj['field_esma'])):

                    create_or_update_id.append(rating_scale.id)

                    reporting_type_dict[
                        rating_scale.id] = compare_obj['reporting_type']
                    change_reason_dict[
                        rating_scale.id] = compare_obj['change_reason']
                    reporting_reason_dict[rating_scale.id].append(
                        compare_obj['reporting_reason'])
            """Scope."""
            for orig_scope_record in RatingScopeOrig.objects.filter(
                    rating_scale=rating_scale).order_by('-id').all():

                unique_identifier_rating_scope = format_reference_number(
                    object_type='rating_scope', number=orig_scope_record.id)

                esma_record_scope = RatingScopeESMA.objects.filter(
                    rating_scope_code=unique_identifier_rating_scope).order_by(
                        '-id')[0]

                for compare_obj in RSCOPE_COMPARE_FIELDS:
                    """Compare value of field in base model with
                    ESMA record."""
                    if (getattr(orig_scope_record, compare_obj['field_orig'])
                            != getattr(esma_record_scope,
                                       compare_obj['field_esma'])):

                        # Should be top level id
                        create_or_update_id.append(rating_scale.id)

                        reporting_type_dict[
                            rating_scale.id] = compare_obj['reporting_type']
                        change_reason_dict[
                            rating_scale.id] = compare_obj['change_reason']
                        reporting_reason_dict[rating_scale.id].append(
                            compare_obj['reporting_reason'])
            """Category."""
            for orig_category_record in RatingCategoryOrig.objects.filter(
                    rating_scale=rating_scale).order_by('-id').all():

                unique_identifier_rating_category = format_reference_number(
                    object_type='rating_category',
                    number=orig_category_record.id)

                esma_record_category = RatingCategoryESMA.objects.filter(
                    rating_category_code=unique_identifier_rating_category
                ).order_by('-id')[0]

                for compare_obj in RCATEGORY_COMPARE_FIELDS:
                    """Compare value of field in base model with ESMA
                    record."""
                    if (getattr(orig_category_record,
                                compare_obj['field_orig']) != getattr(
                                    esma_record_category,
                                    compare_obj['field_esma'])):

                        # Should be top level id
                        create_or_update_id.append(rating_scale.id)

                        reporting_type_dict[
                            rating_scale.id] = compare_obj['reporting_type']
                        change_reason_dict[
                            rating_scale.id] = compare_obj['change_reason']
                        reporting_reason_dict[rating_scale.id].append(
                            compare_obj['reporting_reason'])
                    """Notch."""
                    for orig_notch_record in RatingNotchOrig.objects.filter(
                            rating_category=orig_category_record).order_by(
                                '-id').all():

                        unique_identifier_rating_notch = \
                            format_reference_number(
                                object_type='rating_notch',
                                number=orig_notch_record.id)

                        esma_record_notch = RatingNotchESMA.objects.filter(
                            rating_notch_code=unique_identifier_rating_notch
                        ).order_by('-id')[0]

                        for compare_obj in RNOTCH_COMPARE_FIELDS:
                            """Compare value of field in base model with
                            ESMA record."""
                            if (getattr(orig_notch_record,
                                        compare_obj['field_orig']) != getattr(
                                            esma_record_notch,
                                            compare_obj['field_esma'])):

                                # Should be top level id
                                create_or_update_id.append(rating_scale.id)

                                reporting_type_dict[
                                    rating_scale.
                                    id] = compare_obj['reporting_type']
                                change_reason_dict[
                                    rating_scale.
                                    id] = compare_obj['change_reason']
                                reporting_reason_dict[rating_scale.id].append(
                                    compare_obj['reporting_reason'])

            # Looks like nothing happened with this record, delete it
            if len(reporting_reason_dict[rating_scale.id]) == 0:
                del reporting_reason_dict[rating_scale.id]

    for rating_scale_orig in RatingScaleOrig.objects.filter(
            pk__in=create_or_update_id).all():

        reporting_type = reporting_type_dict[rating_scale_orig.id]
        reporting_reason = reporting_reason_dict[rating_scale_orig.id]

        try:
            change_reason = change_reason_dict[rating_scale_orig.id]
        except KeyError:
            change_reason = None

        unique_identifier_rating_scale = format_reference_number(
            object_type='rating_scale', number=rating_scale_orig.id)

        # Create a new ReportingTypeInfo record
        reporting_type_info, _ = get_or_create_reporting_type_info(
            reporting_type=reporting_type,
            change_reason=change_reason,
            reporting_reason_text=create_reporting_reason_string(
                reporting_reason),
            hash_string=create_hash_string(unique_identifier_rating_scale,
                                           reporting_type))

        # Create a new record
        rating_scale_esma = RatingScaleESMA.objects.create(
            reporting_type_info=reporting_type_info,
            xml_file=xml_file,

            # Insert all model fields below here
            rating_scale_code=unique_identifier_rating_scale,
            start_date=rating_scale_orig.start_date,
            end_date=rating_scale_orig.end_date,
            description=rating_scale_orig.description,
        )

        for rating_scope_orig in RatingScopeOrig.objects.filter(
                rating_scale=rating_scale_orig).order_by('id').all():

            unique_identifier_rating_scope = format_reference_number(
                object_type='rating_scope', number=rating_scope_orig.id)

            # Create a new record
            RatingScopeESMA.objects.create(
                rating_scale=rating_scale_esma,

                # Insert all model fields below here
                rating_scope_code=unique_identifier_rating_scope,
                time_horizon=rating_scope_orig.time_horizon,
                rating_type=rating_scope_orig.rating_type,
                rating_scale_scope=rating_scope_orig.rating_scale_scope,
                relevant_for_cerep_flag=rating_scope_orig.
                relevant_for_cerep_flag,
                start_date=rating_scope_orig.start_date,
                end_date=rating_scope_orig.end_date,
            )

        for rating_category_orig in RatingCategoryOrig.objects.filter(
                rating_scale=rating_scale_orig).order_by('id').all():

            unique_identifier_rating_category = format_reference_number(
                object_type='rating_category', number=rating_category_orig.id)

            # Create a new record
            rating_category_esma = RatingCategoryESMA.objects.create(
                rating_scale=rating_scale_esma,

                # Insert all model fields below here
                rating_category_code=unique_identifier_rating_category,
                value=rating_category_orig.value,
                label=rating_category_orig.label,
                description=rating_category_orig.description,
            )

            for rating_notch_orig in RatingNotchOrig.objects.filter(
                    rating_category=rating_category_orig).order_by('id').all():

                unique_identifier_rating_notch = format_reference_number(
                    object_type='rating_notch', number=rating_notch_orig.id)

                # Create a new record
                RatingNotchESMA.objects.create(
                    rating_category=rating_category_esma,

                    # Insert all model fields below here
                    rating_notch_code=unique_identifier_rating_notch,
                    value=rating_notch_orig.value,
                    label=rating_notch_orig.label,
                    description=rating_notch_orig.description,
                )
示例#7
0
 def rating_action_identifier(self):
     """A unique identifier for this record?."""
     return format_reference_number(number=self.pk,
                                    object_type='rating_action')
示例#8
0
def pending_confirm_parameter(request, action, rating_decision_pk):
    """Update steps in the rating process model Process."""

    hash = None

    if action:

        rating_decision_obj = RatingDecision.objects.get(pk=rating_decision_pk)

        rating_process_obj, created = Process.objects.get_or_create(
                rating_decision=rating_decision_obj)

        rating_job_id = format_reference_number(number=rating_decision_obj.id,
                                                object_type='rating_decision',)

        if action == 'setup_done':
            hash = 'setup_step_2'

            rating_decision_obj.process_step = 2
            rating_process_obj.setup_done = timezone.now()

            to_list = [
                rating_decision_obj.chair.email
            ]

            # Notify analysts and relationship manager
            cc_list = [
                rating_decision_obj.issuer.analyst.
                primary_analyst.email,
                rating_decision_obj.issuer.analyst.
                secondary_analyst.email,
                rating_decision_obj.issuer.relationship_manager.email,
            ]

            # We want to notify Compliance in production
            if os.environ['ENVIRONMENT_MODE'] == 'PROD':
                cc_list.append('*****@*****.**')

            header = SETUP_HEADER.format(
                rating_decision_obj.issuer,
                rating_job_id,
            )
            body = SETUP_BODY % rating_decision_obj.chair.first_name

            # Send notification to chair
            send_email.delay(
                header=header,
                body=body,
                to=to_list,
                from_sender=None,
                cc=cc_list)

        elif action == 'pre_committee_done':
            hash = 'setup_step_3'

            rating_decision_obj.process_step = 3
            rating_process_obj.pre_committee_done = timezone.now()
            rating_decision_obj.chair_confirmed = True
            rating_decision_obj.date_time_committee_confirmed = True

            to_list = [
                rating_decision_obj.issuer.analyst.
                primary_analyst.email,
                rating_decision_obj.issuer.analyst.
                secondary_analyst.email,
            ]
            cc_list = [
                rating_decision_obj.issuer.relationship_manager.email,
                rating_decision_obj.chair.email,
            ]

            # We want to notify Compliance in production
            if os.environ['ENVIRONMENT_MODE'] == 'PROD':
                cc_list.append('*****@*****.**')

            header = PRE_COMMITTEE_HEADER.format(
                rating_decision_obj.issuer,
                rating_decision_obj.chair.get_full_name(),
                rating_job_id,
            )

            # Send notification
            send_email.delay(
                header=header,
                body=PRE_COMMITTEE_BODY % rating_decision_obj.issuer.analyst.
                primary_analyst.first_name,
                to=to_list,
                from_sender=None,
                cc=cc_list,)

        elif action == 'analytical_phase_done':
            hash = 'setup_step_4'

            rating_decision_obj.process_step = 4
            rating_process_obj.analytical_phase_done = timezone.now()

            # Send notification to chair and members of committee
            to_list = [
                rating_decision_obj.issuer.analyst.primary_analyst.email,
                rating_decision_obj.issuer.analyst.secondary_analyst.email,
                rating_decision_obj.chair.email,
            ]
            cc_list = [
                rating_decision_obj.issuer.relationship_manager.email,
            ]

            # We want to notify Compliance in production
            if os.environ['ENVIRONMENT_MODE'] == 'PROD':
                cc_list.append('*****@*****.**')

            # Get all members
            committee_members = list(
                JobMember.objects.confirmed_members().filter(
                    rating_decision=rating_decision_obj,
                    group_id=1))
            for item in committee_members:
                to_list.append(item.member.email)

            local_dt = timezone.localtime(
                rating_decision_obj.date_time_committee,
                timezone.get_fixed_timezone(60))

            header = ANALYTICAL_PHASE_HEADER.format(
                rating_decision_obj.issuer,
                local_dt.strftime('%Y-%m-%d %H:%M'),
                rating_job_id,
            )

            send_email.delay(
                header=header,
                body=ANALYTICAL_PHASE_BODY,
                to=to_list,
                cc=cc_list,
                from_sender=None)

        elif action == 'post_committee_done':
            hash = 'setup_step_5'

            rating_decision_obj.process_step = 5
            rating_process_obj.post_committee_done = timezone.now()

            # Contains the name and email of the editor
            editor_obj = JobMember.objects.get(
                rating_decision=rating_decision_obj,
                group=Group.objects.get(pk=2))

            to_list = [
                editor_obj.member.email,
            ]
            cc_list = [
                rating_decision_obj.issuer.analyst.primary_analyst.email,
                rating_decision_obj.issuer.analyst.secondary_analyst.email,
                rating_decision_obj.chair.email,
                rating_decision_obj.issuer.relationship_manager.email,
            ]

            # We want to notify Compliance in production
            if os.environ['ENVIRONMENT_MODE'] == 'PROD':
                cc_list.append('*****@*****.**')

            header = EDITOR_HEADER.format(
                rating_decision_obj.issuer,
                rating_job_id,
            )

            # Send email with link to admin control to editor
            send_email.delay(header=header,
                             body=EDITOR_EMAIL % (
                                 editor_obj.member.first_name,
                                 rating_decision_obj.issuer.analyst.
                                 primary_analyst.first_name),
                             to=to_list,
                             cc=cc_list,
                             from_sender=None,)

        elif action == 'editor_phase_done':
            """Here, we're sending the draft report to the issuer."""

            hash = 'setup_step_6'

            rating_decision_obj.process_step = 6

            # External analysis
            send_public_report(rating_decision_obj)

            # Send notification to chair
            to_list = [
                rating_decision_obj.issuer.relationship_manager.email,
            ]

            header = "{} | the draft report has been sent to the " \
                     "issuer".format(rating_decision_obj.issuer,)

            send_email.delay(
                header=header,
                body=' ',
                to=to_list,
                from_sender=None,)

            # Set a timestamp when se sent the report to the issuer
            rating_decision_obj.date_time_communicated_issuer = timezone.now()
            rating_process_obj.editor_review_done = timezone.now()

        elif action == 'issuer_confirmation_phase_done':
            hash = 'setup_step_7'

            rating_decision_obj.process_step = 7

            to_list = [
                rating_decision_obj.chair.email,
                rating_decision_obj.issuer.analyst.primary_analyst.email,
                rating_decision_obj.issuer.analyst.secondary_analyst.email,
                rating_decision_obj.issuer.relationship_manager.email,
            ]

            # We want to notify Compliance in production
            if os.environ['ENVIRONMENT_MODE'] == 'PROD':
                to_list.append('*****@*****.**')

            header = "{} | The issuer has confirmed the accuracy of the " \
                     "draft report for rating job {}".format(
                        rating_decision_obj.issuer,
                        rating_job_id, )

            # Send notification
            send_email.delay(
                header=header,
                body='',
                to=to_list,
                from_sender=None,)

            rating_process_obj.issuer_confirmation_done = timezone.now()

        elif action == 'analyst_final_approval_phase_done':
            hash = 'setup_step_8'

            rating_process_obj.final_sign_off_analyst_done = timezone.now()
            rating_decision_obj.process_step = 8

            to_list = [
                rating_decision_obj.issuer.analyst.primary_analyst.email,
            ]
            cc_list = [
                rating_decision_obj.chair.email,
                rating_decision_obj.issuer.analyst.secondary_analyst.email,
                rating_decision_obj.issuer.relationship_manager.email,
            ]

            # We want to notify Compliance in production
            if os.environ['ENVIRONMENT_MODE'] == 'PROD':
                cc_list.append('*****@*****.**')

            header = ANALYST_FINAL_APPROVAL_HEADER.format(
                rating_decision_obj.issuer
            )

            # Send notification to chair
            send_email.delay(
                header=header,
                body=ANALYST_FINAL_APPROVAL_BODY %
                rating_decision_obj.issuer.analyst.
                primary_analyst.first_name,
                to=to_list,
                from_sender=None,
                cc=cc_list)

        elif action == 'chair_final_approval_phase_done':
            hash = 'setup_step_9'

            rating_decision_obj.process_step = 9
            rating_process_obj.final_sign_off_chair_done = timezone.now()

            to_list = [
                rating_decision_obj.issuer.analyst.primary_analyst.email,
                rating_decision_obj.issuer.analyst.secondary_analyst.email,
            ]
            cc_list = [
                rating_decision_obj.chair.email,
                rating_decision_obj.issuer.relationship_manager.email,
            ]

            # We want to notify Compliance in production
            if os.environ['ENVIRONMENT_MODE'] == 'PROD':
                cc_list.append('*****@*****.**')

            header = CHAIR_FINAL_APPROVAL_HEADER.format(
                rating_decision_obj.issuer
            )

            # Send notification to analyst
            send_email.delay(header=header,
                             body=CHAIR_FINAL_APPROVAL_BODY %
                             rating_decision_obj.issuer.analyst.
                             primary_analyst.first_name,
                             to=to_list,
                             from_sender=None,
                             cc=cc_list,)

        elif action == 'publishing_phase_done':
            hash = ""

            rating_decision_obj.date_time_published = timezone.now()

            to_list = [
                rating_decision_obj.issuer.analyst.primary_analyst.email,
                rating_decision_obj.issuer.analyst.secondary_analyst.email,
                rating_decision_obj.chair.email,
                rating_decision_obj.issuer.relationship_manager.email,
            ]

            # We want to notify Compliance in production
            if os.environ['ENVIRONMENT_MODE'] == 'PROD':
                to_list.append('*****@*****.**')

            header = "{} | the rating job has been finalized".format(
                rating_decision_obj.issuer
            )

            # Send notification
            send_email.delay(header=header,
                             body='If this a public rating, the publishing '
                                  'process will now commence.',
                             to=to_list,
                             from_sender=None,)

            """If there is a previous decision, flag it as non-current."""
            try:
                RatingDecision.objects.filter(
                    pk=rating_decision_obj.previous_rating.pk).update(
                    is_current=False,)
            except AttributeError:
                pass

            rating_decision_obj.is_current = True
            rating_process_obj.process_ended = timezone.now()

            # Create a DecisionAttribute object that
            # summarizes the rating decision
            refresh_decision_attributes(rating_decision_obj)

            # Create decisions on the issue level
            update_issue_rating(rating_decision_obj)

            # Create a draft campaign with MailChimp
            if rating_decision_obj.rating_type.id == 1:
                run_create_campaign.delay(rating_decision_obj.id)

            rating_decision_obj.process_step = 10

        # Save changes
        rating_process_obj.save()
        rating_decision_obj.save()

    redirect_url = request.META.get('HTTP_REFERER', '/') + '#' + hash

    return http.HttpResponseRedirect(redirect_url)
示例#9
0
def populate_cra_info(xml_file):
    """Scan original model and insert into ESMA model if required.
    This function does a field-by-field comparison against"""

    for orig_record in OrigModel.objects.all():

        # As a default, don't do anything
        change_reason = None
        reporting_type = None
        reporting_reason = []
        create_record = False

        # Unique identifier for this model
        unique_identifier = format_reference_number(
            object_type='cra_info',
            number=orig_record.id)

        try:
            esma_record = ESMAModel.objects.last_valid_record()[0]

            for compare_obj in COMPARE_FIELDS:

                """Compare value of field in base model with ESMA record."""
                if (getattr(orig_record, compare_obj['field_orig']) !=
                        getattr(esma_record, compare_obj['field_esma'])):

                    # Something has changed, create a new entry in ESMA-table.
                    create_record = True

                    reporting_type = compare_obj['reporting_type']
                    change_reason = compare_obj['change_reason']
                    reporting_reason.append(
                        compare_obj['reporting_reason'])

        except (IndexError, ESMAModel.DoesNotExist):
            """The object is not existing in the ESMA table:
            create it."""

            create_record = True
            reporting_type = 1  # 1=NEW
            reporting_reason.append(STRING_NEW_ITEM)

        if create_record:
            # Create a new ReportingTypeInfo record
            reporting_type_info, _ = get_or_create_reporting_type_info(
                reporting_type=reporting_type,
                change_reason=change_reason,
                reporting_reason_text=create_reporting_reason_string(
                    reporting_reason),
                hash_string=create_hash_string(
                    unique_identifier,
                    reporting_type)
            )

            # Because of the long variable name
            a = orig_record.\
                solicited_unsolicited_rating_policy_description

            # Create a new record
            ESMAModel.objects.create(
                xml_file=xml_file,
                reporting_type_info=reporting_type_info,

                # Insert all model fields below here
                cra_info_code=unique_identifier,
                cra_name=orig_record.cra_name,
                cra_description=orig_record.cra_description,
                cra_methodology=orig_record.cra_methodology,
                cra_methodology_webpage_link=orig_record.
                cra_methodology_webpage_link,
                solicited_unsolicited_rating_policy_description=a,
                subsidiary_rating_policy=orig_record.
                subsidiary_rating_policy,
                global_reporting_scope_flag=orig_record.
                global_reporting_scope_flag,
                definition_default=orig_record.definition_default,
                cra_website_link=orig_record.cra_website_link,
            )
示例#10
0
 def rating_scale_code(self):
     return format_reference_number(number=self.pk,
                                    object_type='rating_scale')
示例#11
0
def populate_issue_program(xml_file):
    """Scan original model and insert into ESMA model if required."""

    for orig_record in OrigModel.objects.all():

        # As a default, don't do anything
        change_reason = None
        reporting_type = None
        reporting_reason = []
        create_record = False

        # Unique identifier for this model
        unique_identifier = format_reference_number(
            object_type='issue_program', number=orig_record.id)

        try:
            esma_record = ESMAModel.objects.last_valid_record().filter(
                program_code=unique_identifier)[0]

            for compare_obj in COMPARE_FIELDS:
                """Compare value of field in base model with ESMA record."""
                if (getattr(orig_record, compare_obj['field_orig']) != getattr(
                        esma_record, compare_obj['field_esma'])):

                    create_record = True

                    reporting_type = compare_obj['reporting_type']
                    change_reason = compare_obj['change_reason']
                    reporting_reason.append(compare_obj['reporting_reason'])

        except (IndexError, ESMAModel.DoesNotExist):
            """The rating scale is not existing in the ESMA table,
            create it."""

            create_record = True

            reporting_type = 1  # 1=NEW
            reporting_reason.append(STRING_NEW_ITEM)

        if create_record:

            # Create a new ReportingTypeInfo record
            reporting_type_info, _ = get_or_create_reporting_type_info(
                reporting_type=reporting_type,
                change_reason=change_reason,
                reporting_reason_text=create_reporting_reason_string(
                    reporting_reason),
                #  Change the unique identifiere here
                hash_string=create_hash_string(unique_identifier,
                                               reporting_type))

            # Create a new record
            ESMAModel.objects.create(
                xml_file=xml_file,
                reporting_type_info=reporting_type_info,

                # Insert all model fields below here
                program_code=unique_identifier,
                program_name=orig_record.name,
                program_description=orig_record.description,
                program_start_date=orig_record.start_date,
                program_end_date=orig_record.end_date,
            )
def create_campaign(**kwargs):
    """This function creates a campaign in MailChimp through their API."""

    client = MailChimp(
        mc_user=djangoSettings.MC_USER,
        mc_api=djangoSettings.MC_API_KEY,
    )

    # Set properties for campaign
    rating_job_id = kwargs['rating_job_id']
    header = kwargs['header']
    body = kwargs['body']
    campaign_title = format_reference_number(
        number=rating_job_id,
        object_type='rating_decision',
    ) + ' - ' + header
    template_id = kwargs['template_id']
    issuer_type_id = kwargs['issuer_type_id']

    list_id = '801d23f631'  # Web site signup
    folder_id = '7024652103'  # Rating
    saved_segment_id = None

    if issuer_type_id == 1:
        # Corporate
        saved_segment_id = 29557

    elif issuer_type_id == 2:
        # Financial

        saved_segment_id = 29565

    elif issuer_type_id == 3:
        # Real estate

        saved_segment_id = 29569

    # Override these settings in test environment
    if os.environ['ENVIRONMENT_MODE'] != 'PROD':
        folder_id = '53b0a3465b'
        list_id = '42a98c90a0'
        saved_segment_id = 29573

    data = {
        'recipients': {
            'list_id': list_id,
            'segment_opts': {
                'saved_segment_id': saved_segment_id,
            }
        },
        'settings': {
            'title': campaign_title,
            'from_name': 'Nordic Credit Rating',
            'reply_to': '*****@*****.**',
            'template_id': template_id,

            # Mail headline
            # No more than 150 chars according to specs
            'subject_line': header[0:150],

            # No more than 150 chars according to specs
            'preview_text': strip_tags(body[0:150]),
            'folder_id': folder_id,
        },
        'type': 'regular',
    }

    return client.campaigns.create(data)
示例#13
0
def populate_rating_decision(issues=False):
    """Check today's decisions."""

    # Check if the decision has been sent already
    # Ordering is important!
    # there is a constant in CONST defining how long to look back
    if issues:
        decision_backlog = IssueDecision.objects.esma()

    else:
        decision_backlog = RatingDecision.objects.esma()

    if issues:
        # Only the long-term perspective is relevant for issues
        PERSPECTIVES = [
            1,  # Long-term
        ]

    else:
        PERSPECTIVES = [
            1,  # Long-term
            2,  # Short-term
        ]

    # Loop through each record from the past n days
    for x in decision_backlog:

        logger.info("   analyzing decision: " + str(x))

        # Pick up the decision attributes
        attributes = get_attributes(issues, x)

        # Reset the values
        iss = None

        debt_classification_code = None
        issuer_rating_type_code = None

        # Store previous rating decision, if available
        try:
            previous_rating = x.previous_rating
        except Exception:
            previous_rating = False

        if issues:
            # Issue instance
            iss = x

            # Rating decision instance
            dec = x.rating_decision_issue.rating_decision
        else:

            # Rating decision instance
            dec = x

        # Assume there is no previous rating
        prev_rating_preliminary = False

        if issues:
            rated_object = 2  # 2 = Issue

            # Should be seniority
            debt_classification_code = format_reference_number(
                number=iss.issue.seniority.id, object_type='debt_class')

        else:
            rated_object = 1  # 1 = Issuer
            issuer_rating_type_code = format_reference_number(
                number=1, object_type='rating_type')

        # 2 is financial institution
        if dec.issuer.issuer_type.id == 2:
            industry = 1
        else:
            industry = 3

        # Public rating not exclusively
        # produced for and disclosed
        # to investors for a fee
        if dec.rating_type.id == 1:
            type_of_rating_for_erp = 1
        else:
            type_of_rating_for_erp = 2

        # Logic as provided by ESMA during a call
        # Preliminary issuer ratings and issue ratings should not have
        # this flag
        if dec.decisionattributes.is_new_preliminary or rated_object != 1:
            relevant_for_cerep = False
        else:
            relevant_for_cerep = True

        # Loop through long-term and short-term
        for perspective in PERSPECTIVES:

            logger.info("       perspective: " + str(perspective))

            # There's some unknown error going on
            # try to catch it
            try:

                TEMP = {}
                TEMP_L = {}
                action_type_list = []

                # TODO: not implemented
                # Default these values to NULL in db
                owsd_status = None
                outlook_trend = None
                watch_review = None
                withdrawal_reason_type = None

                ############################################
                # MISC VARIABLES
                ############################################
                if perspective == 1:  # Long-term
                    rating_value = x.decided_lt
                else:
                    rating_value = x.decided_st

                ############################################
                # NEW PRELIMINARY RATING
                ############################################
                # We have to create a new preliminary rating
                # and place an outlook

                if attributes.is_new_preliminary:
                    action_type_list.append(2)

                    # Place an outlook for long-term ratings
                    # Issues dont have outlooks
                    if perspective == 1 and not issues:
                        action_type_list.append(10)

                        TEMP[dec.id] = {
                            10: {
                                'owsd_status':
                                1,  # place
                                'outlook_trend':
                                get_outlook_trend(dec),
                                'validity_date':
                                x.date_time_published + timedelta(minutes=1),
                            }
                        }

                ############################################
                # NEW RATING
                ############################################
                # We have to create a new rating and place
                # an outlook
                elif attributes.is_new:
                    action_type_list.append(3)

                    # Place an outlook for long-term ratings
                    # Issues dont have outlooks
                    if perspective == 1 and not issues:
                        action_type_list.append(10)

                        TEMP[dec.id] = {
                            10: {
                                'owsd_status':
                                1,  # place
                                'outlook_trend':
                                get_outlook_trend(dec),
                                'validity_date':
                                x.date_time_published + timedelta(minutes=1),
                            }
                        }
                    """Check if previous rating was preliminary."""
                    try:
                        if issues:
                            if iss.previous_rating.issuedecisionattributes. \
                                    is_new_preliminary:
                                prev_rating_preliminary = True
                        else:
                            if dec.previous_rating.decisionattributes. \
                                    is_new_preliminary:
                                prev_rating_preliminary = True

                    except AttributeError:
                        pass

                ############################################
                # RATING SCALES
                ############################################
                if attributes.is_new_preliminary:
                    if perspective == 1:
                        # Scale for long-term ratings
                        rating_scale_id = 3

                    else:
                        # Scale for short-term ratings
                        rating_scale_id = 4

                else:
                    if perspective == 1:

                        # Scale for long-term ratings
                        rating_scale_id = 1
                    else:

                        # Scale for short-term ratings
                        rating_scale_id = 2

                ############################################
                # LONG-TERM UPGRADED
                ############################################
                if attributes.is_lt_upgrade and perspective == 1:
                    action_type_list.append(4)

                ############################################
                # LONG-TERM DOWNGRADED
                ############################################
                if attributes.is_lt_downgrade and perspective == 1:
                    action_type_list.append(5)

                ############################################
                # LONG-TERM AFFIRMED
                ############################################
                if attributes.is_lt_affirmation and perspective == 1:
                    action_type_list.append(6)

                ############################################
                # SHORT-TERM UPGRADED
                ############################################
                # Not valid for issue ratings, hence the
                # try/catch
                try:
                    if attributes.is_st_upgrade and perspective == 2:
                        action_type_list.append(4)
                except AttributeError:
                    pass

                ############################################
                # SHORT-TERM DOWNGRADED
                ############################################
                # Not valid for issue ratings, hence the
                # try/catch
                try:
                    if attributes.is_st_downgrade and perspective == 2:
                        action_type_list.append(5)

                except AttributeError:
                    pass

                ############################################
                # SHORT-TERM AFFIRMED
                ############################################
                # Not valid for issue ratings, hence the
                # try/catch
                try:
                    if attributes.is_st_affirmation and perspective == 2:
                        action_type_list.append(6)
                except AttributeError:
                    pass

                ############################################
                # DEFAULTS
                ############################################
                # Regular default
                if attributes.is_default:
                    action_type_list.append(7)

                if attributes.is_default:
                    default_flag = True
                else:
                    default_flag = False

                # Selective default
                if attributes.is_selective_default:
                    action_type_list.append(7)

                ############################################
                # RATING SUSPENDED
                ############################################
                if attributes.is_suspension:
                    action_type_list.append(8)

                ############################################
                # RATING WITHDRAWN
                ############################################
                # Note from ESMA: don't withdraw preliminary
                # ratings
                if attributes.is_withdrawal:

                    action_type_list.append(9)

                    try:
                        if attributes.is_matured:
                            TEMP[dec.id] = {
                                9: {
                                    'action_type': 9,
                                    'withdrawal_reason_type': 4,
                                }
                            }

                    except AttributeError:
                        pass

                ############################################
                # RATING OUTLOOK CHANGED
                ############################################
                # Outlook has changed
                # Only check this for long-term perspective
                # According to ESMA you first place an outlook
                # Then you remove the old outlook and place a new one
                try:
                    # 1 = long-term and only for issuer ratings
                    if perspective == 1 and not issues:

                        if attributes.is_outlook_change:

                            # Remove current outlook
                            # Place outlook
                            action_type_list.append(10)
                            action_type_list.append(10)

                            TEMP_L[dec.id] = {
                                10: [
                                    {
                                        'owsd_status':
                                        3,  # remove
                                        'outlook_trend':
                                        get_outlook_trend(previous_rating),
                                        'is_parsed':
                                        False,
                                    },
                                    {
                                        'owsd_status': 1,  # Place
                                        'outlook_trend':
                                        get_outlook_trend(dec),
                                        'is_parsed': False,
                                    }
                                ]
                            }

                        # Place a maintain
                        # But not on a new rating
                        elif not attributes.is_new and not \
                                attributes.is_new_preliminary:

                            # Maintain current outlook
                            action_type_list.append(10)
                            TEMP[dec.id] = {
                                10: {
                                    'owsd_status': 2,  # Maintain
                                    'outlook_trend': get_outlook_trend(dec),
                                }
                            }

                except AttributeError:
                    pass

                ############################################
                # RATING WATCH
                ############################################
                try:
                    if attributes.is_watch:
                        # TODO: implement OSWD_status
                        action_type_list.append(11)

                except AttributeError:
                    pass

            except Exception as e:
                logger.info("Error: " + str(e))

            # Run through all action types from above
            for t in action_type_list:

                logger.info("           action type: " + str(ACTION_TYPE[t]))

                # Defined as list to make sure order is maintained
                hash_input = [
                    x.date_time_published.strftime('%Y-%m-%d'), x.id, t,
                    perspective
                ]
                hash_key = create_hash(*hash_input)

                # A list of action types has been sent,
                # TODO: this is not pretty, but I'm out of time
                try:

                    if type(TEMP_L[dec.id][t]) == list:

                        if not TEMP_L[dec.id][t][0]['is_parsed']:
                            try:
                                owsd_status = TEMP_L[
                                    dec.id][t][0]['owsd_status']
                            except KeyError:
                                pass

                            try:
                                outlook_trend = TEMP_L[
                                    dec.id][t][0]['outlook_trend']
                            except KeyError:
                                pass

                            try:
                                watch_review = TEMP_L[
                                    dec.id][t][0]['watch_review']
                            except KeyError:
                                pass

                            try:
                                withdrawal_reason_type = TEMP_L[
                                    dec.id][t][0]['withdrawal_reason_type']
                            except KeyError:
                                pass

                            try:
                                validity_date = TEMP_L[
                                    dec.id][t][0]['validity_date']
                            except KeyError:
                                # Standard time used in reporting
                                # There is a special case to report outlooks
                                # on new ratings as informed in an email
                                # from ESMA on 2018-10-31, 14.43 with the
                                # validity datetime of the OT action later than
                                # the NW action (e.g. 1 minute later validity
                                # datetime).

                                validity_date = x.date_time_published

                            TEMP_L[dec.id][t][0]['is_parsed'] = True

                        elif not TEMP_L[dec.id][t][1]['is_parsed']:

                            try:
                                owsd_status = TEMP_L[
                                    dec.id][t][1]['owsd_status']
                            except KeyError:
                                pass

                            try:
                                outlook_trend = TEMP_L[
                                    dec.id][t][1]['outlook_trend']
                            except KeyError:
                                pass

                            try:
                                watch_review = TEMP_L[
                                    dec.id][t][1]['watch_review']
                            except KeyError:
                                pass

                            try:
                                withdrawal_reason_type = TEMP_L[
                                    dec.id][t][1]['withdrawal_reason_type']
                            except KeyError:
                                pass

                            try:
                                validity_date = TEMP_L[
                                    dec.id][t][1]['validity_date']
                            except KeyError:
                                # Standard time used in reporting
                                # There is a special case to report outlooks
                                # on new ratings as informed in an email
                                # from ESMA on 2018-10-31, 14.43 with the
                                # validity datetime of the OT action later
                                # than the NW action (e.g. 1 minute later
                                # validity datetime).

                                validity_date = x.date_time_published

                            TEMP_L[dec.id][t][1]['is_parsed'] = True

                    else:

                        try:
                            owsd_status = TEMP[dec.id][t]['owsd_status']
                        except KeyError:
                            pass

                        try:
                            outlook_trend = TEMP[dec.id][t]['outlook_trend']
                        except KeyError:
                            pass

                        try:
                            watch_review = TEMP[dec.id][t]['watch_review']
                        except KeyError:
                            pass

                        try:
                            withdrawal_reason_type = TEMP[
                                dec.id][t]['withdrawal_reason_type']
                        except KeyError:
                            pass

                        try:
                            validity_date = TEMP[dec.id][t]['validity_date']
                        except KeyError:
                            # Standard time used in reporting
                            # There is a special case to report outlooks on
                            # new ratings as informed in an email from ESMA
                            # on 2018-10-31, 14.43 with the validity datetime
                            # of the OT action later than the NW action
                            # (e.g. 1 minute later validity datetime).

                            validity_date = x.date_time_published

                except KeyError:

                    try:
                        owsd_status = TEMP[dec.id][t]['owsd_status']
                    except KeyError:
                        pass

                    try:
                        outlook_trend = TEMP[dec.id][t]['outlook_trend']
                    except KeyError:
                        pass

                    try:
                        watch_review = TEMP[dec.id][t]['watch_review']
                    except KeyError:
                        pass

                    try:
                        withdrawal_reason_type = TEMP[
                            dec.id][t]['withdrawal_reason_type']
                    except KeyError:
                        pass

                    try:
                        validity_date = TEMP[dec.id][t]['validity_date']
                    except KeyError:
                        # Standard time used in reporting
                        # There is a special case to report outlooks on
                        # new ratings as informed in an email from ESMA
                        # on 2018-10-31, 14.43 with the validity datetime
                        # of the OT action later than the NW action
                        # (e.g. 1 minute later validity datetime).

                        validity_date = x.date_time_published

                logger.info("           inserting records in db")

                # If this data point has already been inserted successfully,
                # skip to the next step
                if QTRatingCreateData.objects.filter(
                        hash=hash_key, xml_file__status_code=1).exists():

                    # We have already reported this successfully
                    # work on next file instead
                    continue

                else:

                    create_rating_decision_xml_objects(
                        hash_key,
                        dec,
                        x,
                        validity_date,
                        t,
                        owsd_status,
                        outlook_trend,
                        watch_review,
                        withdrawal_reason_type,
                        rating_scale_id,
                        rating_value,
                        default_flag,
                        rated_object,
                        perspective,
                        issuer_rating_type_code,
                        debt_classification_code,
                        industry,
                        type_of_rating_for_erp,
                        relevant_for_cerep,
                        prev_rating_preliminary,
                        issues,
                        iss,
                        attributes,
                    )
def populate_debt_classification(xml_file):
    """Scan original model and insert into ESMA model if required."""

    for orig_record in OrigModel.objects.all():

        # As a default, don't do anything
        change_reason = None
        reporting_type = None
        reporting_reason = []
        create_record = False

        # Unique identifier for this model
        unique_identifier = format_reference_number(object_type='debt_class',
                                                    number=orig_record.id)

        try:
            esma_record = ESMAModel.objects.last_valid_record().filter(
                debt_classification_code=unique_identifier)[0]

            for compare_obj in COMPARE_FIELDS:
                """Compare value of field in base model with ESMA record."""
                if (getattr(orig_record, compare_obj['field_orig']) != getattr(
                        esma_record, compare_obj['field_esma'])):

                    create_record = True

                    reporting_type = compare_obj['reporting_type']
                    change_reason = compare_obj['change_reason']
                    reporting_reason.append(compare_obj['reporting_reason'])

            # Custom comparison of seniority due to the OrigModel
            # being a bit different
            if orig_record.seniority_level.id != esma_record.seniority:
                create_record = True

                reporting_type = 2  # 2=CHG
                change_reason = 1  # 2=U: Consider this to be an an update
                reporting_reason.append('seniority level')

        except (IndexError, ESMAModel.DoesNotExist):
            """The rating scale is not existing in the ESMA table,
            create it."""

            create_record = True

            reporting_type = 1  # 1=NEW
            reporting_reason.append(STRING_NEW_ITEM)

        if create_record:

            # Create a new ReportingTypeInfo record
            reporting_type_info, _ = get_or_create_reporting_type_info(
                reporting_type=reporting_type,
                change_reason=change_reason,
                reporting_reason_text=create_reporting_reason_string(
                    reporting_reason),
                hash_string=create_hash_string(unique_identifier,
                                               reporting_type))

            # Create a new record
            ESMAModel.objects.create(
                xml_file=xml_file,
                reporting_type_info=reporting_type_info,

                # Insert all model fields below here
                debt_classification_code=unique_identifier,
                debt_classification_name=orig_record.name,
                debt_classification_description=orig_record.description,
                seniority=orig_record.seniority_level.id,
                debt_classification_start_date=orig_record.start_date,
                debt_classification_end_date=orig_record.end_date,
            )