Models

app.models.get_missing_data_keys(data: dict[str, Any]) dict[str, bool][source]

Get a dictionary indicating whether each key in the input dictionary has missing data (empty or None).

Parameters:

data – The input dictionary to check for missing data.

Returns:

A dictionary with the same keys as the input dictionary, where the values are True if the corresponding value in the input dictionary is empty or None, and False otherwise.

class app.models.ActiveRecordMixin[source]
classmethod filter_by(session: Session, field: str, value: Any) Query[source]

Filter a model based on a field’s value.

Parameters:
  • session – The database session.

  • value – The field.

  • field – The field’s value.

Returns:

The query.

classmethod first_by(session: Session, field: str, value: Any) Self | None[source]

Get an existing instance based on a field’s value.

Parameters:
  • session – The database session.

  • value – The field.

  • field – The field’s value.

Returns:

The existing instance if found, otherwise None.

classmethod get(session: Session, id: int) Self[source]

Get an existing instance by its ID. Raise an exception if not found.

Parameters:
  • session – The database session.

  • id – The ID.

Returns:

The existing instance if found.

classmethod create(session: Session, **data: Any) Self[source]

Insert a new instance into the database.

If the model has a missing_data field, indicate which fields are missing in data.

Parameters:
  • session – The database session.

  • data – The initial instance data.

Returns:

The inserted instance.

update(session: Session, **data: Any) Self[source]

Update an existing instance in the database.

Parameters:
  • session – The database session.

  • data – The updated instance data.

Returns:

The updated instance.

class app.models.Application(*, uuid: str, primary_email: str = '', award_borrower_identifier: str = '', amount_requested: Annotated[Decimal | None, _PydanticGeneralMetadata(max_digits=16, decimal_places=2)], currency: str = 'COP', repayment_years: int | None, repayment_months: int | None, payment_start_date: datetime | None, calculator_data: dict[str, Any] = None, status: ApplicationStatus = ApplicationStatus.PENDING, pending_documents: bool = False, pending_email_confirmation: bool = False, expired_at: datetime | None, borrower_declined_at: datetime | None, borrower_declined_preferences_data: dict[str, Any] = None, borrower_declined_data: dict[str, Any] = None, borrower_accepted_at: datetime | None, borrower_credit_product_selected_at: datetime | None, borrower_submitted_at: datetime | None, borrower_accessed_external_onboarding_at: datetime | None, lender_started_at: datetime | None, information_requested_at: datetime | None, lender_rejected_at: datetime | None, lender_rejected_data: dict[str, Any] = None, lender_approved_at: datetime | None, lender_approved_data: dict[str, Any] = None, secop_data_verification: dict[str, Any] = None, disbursed_final_amount: Annotated[Decimal | None, _PydanticGeneralMetadata(max_digits=16, decimal_places=2)], completed_in_days: int | None, overdued_at: datetime | None, application_lapsed_at: datetime | None, archived_at: datetime | None, award_id: int, borrower_id: int, lender_id: int | None, credit_product_id: int | None, created_at: datetime = datetime.datetime(2025, 12, 16, 7, 17, 38, 400744), updated_at: datetime = datetime.datetime(2025, 12, 16, 7, 17, 38, 400795), confirmation_email_token: str = '', id: int | None = None)[source]
classmethod unarchived(session: Session) Query[source]

Return a query for unarchived applications.

classmethod pending_introduction_reminder(session: Session) Query[source]

Return a query for PENDING applications whose expiration date is within reminder_days_before_expiration days from now, and whose borrower hasn’t already received a reminder to accept and may receive Credere invitations.

classmethod pending_submission_reminder(session: Session) Query[source]

Return a query for ACCEPTED applications whose lapsed date is within reminder_days_before_lapsed days from now, and whose borrower hasn’t already received a reminder to submit.

classmethod pending_external_onboarding_reminder(session: Session) Query[source]

Return a query for SUBMITTED applications in which the lender uses external onboarding, whose lapsed date is within reminder_days_before_lapsed_for_external_onboarding days from now, and whose borrower hasn’t already received a reminder to start external onboarding.

classmethod lapseable(session: Session) Query[source]

Return a query for unarchived() applications that have been waiting for the borrower to respond for days_to_change_to_lapsed days.

classmethod submitted(session: Session) Query[source]

Return query for unarchived() applications that have been submitted to any lender (not one of PENDING, DECLINED, ACCEPTED) and that aren’t LAPSED.

classmethod archivable(session: Session) Query[source]

Return query for unarchived() applications that have been in a final state (DECLINED, REJECTED, APPROVED, LAPSED) for days_to_erase_borrowers_data days.

property tz: tzinfo | None

Return the application’s time zone.

previous_awards(session: Session) list[Award][source]

Return the previous awards to the application’s borrower, in reverse time order by contract start date.

rejected_lenders(session: Session) list[Self][source]

Return the IDs of lenders who rejected applications from the application’s borrower, for the same award.

days_waiting_for_lender(session: Session) int[source]

Return the number of days that the application has been waiting for the lender to respond.

stage_as_rejected(lender_rejected_data: dict[str, Any]) None[source]

Assign fields related to marking the application as REJECTED.

stage_as_approved(disbursed_final_amount: Decimal | None, lender_approved_data: dict[str, Any]) None[source]

Assign fields related to marking the application as COMPLETED.

application_lapsed_at: datetime | None

The time at which the application transitioned to LAPSED.

archived_at: datetime | None

The time at which the application was archived.

award_borrower_identifier: str

The hashed borrower ID and award ID, for privacy-preserving long-term identification.

borrower_accepted_at: datetime | None

The time at which the application transitioned to ACCEPTED.

borrower_accessed_external_onboarding_at: datetime | None

The time at which the borrower clicked external_onboarding_url.

borrower_credit_product_selected_at: datetime | None

The time at which the borrower most recently selected a credit product.

borrower_declined_at: datetime | None

The time at which the application transitioned to DECLINED.

borrower_declined_data: dict[str, Any]

Whether the borrower declined only this invitation or all invitations.

borrower_declined_preferences_data: dict[str, Any]

The reason(s) for which the borrower declined the invitation.

borrower_submitted_at: datetime | None

The time at which the application transitioned from SUBMITTED.

completed_in_days: int | None

The total number of days waiting for the lender.

disbursed_final_amount: Decimal | None

The amount of the loan disbursed by the lender.

expired_at: datetime | None

The time at which the application expires.

information_requested_at: datetime | None

The time at which the application transitioned to INFORMATION_REQUESTED.

lender_approved_at: datetime | None

The time at which the application transitioned to APPROVED.

lender_approved_data: dict[str, Any]

The reason(s) for which the application was approved.

lender_rejected_at: datetime | None

The time at which the application transitioned to REJECTED.

lender_rejected_data: dict[str, Any]

The reason(s) for which the application was rejected.

lender_started_at: datetime | None

The time at which the application transitioned to STARTED, from SUBMITTED.

overdued_at: datetime | None

The time at which the application was most recently overdue (reset once approved).

pending_documents: bool

Whether the borrower has confirmed the credit product but not yet submitted the application, or the lender has requested information and the borrower has not yet uploaded documents.

pending_email_confirmation: bool

Whether the borrower has changed the primary email for the application, but hasn’t confirmed it.

primary_email: str

The email address at which the borrower is contacted.

secop_data_verification: dict[str, Any]

Whether the borrower fields (keys) have been verified (bool values) by the lender.

status: ApplicationStatus

The status of the application.

uuid: str

The secure identifier for the application, for passwordless login.

class app.models.BorrowerDocument(*, id: int | None = None, type: BorrowerDocumentType, verified: bool = False, name: str = '', submitted_at: datetime = datetime.datetime(2025, 12, 16, 7, 17, 38, 416559), application_id: int, created_at: datetime = datetime.datetime(2025, 12, 16, 7, 17, 38, 416637), updated_at: datetime = datetime.datetime(2025, 12, 16, 7, 17, 38, 416673), file: bytes)[source]
file: bytes

The content of the document.

name: str

The filename of the document.

submitted_at: datetime

The time at which the document was most recently uploaded by the borrower.

type: BorrowerDocumentType

The type of document.

verified: bool

Whether the document has been verified by the lender.

class app.models.Lender(*, name: str = '', email_group: str = '', type: str = '', logo_filename: str = '', sla_days: int | None, external_onboarding_url: str = '', id: int | None = None, status: str = '', deleted_at: datetime | None, created_at: datetime = datetime.datetime(2025, 12, 16, 7, 17, 38, 375201), updated_at: datetime = datetime.datetime(2025, 12, 16, 7, 17, 38, 375363))[source]
status: str

Unused.

deleted_at: datetime | None

Unused.

email_group: str

An email address of the lender, for sharing with borrowers.

external_onboarding_url: str

A URL pointing to the lender’s own onboarding system. If set, a custom email is sent to the borrower after the application is submitted, indicating that the process should continue in the lender’s system.

logo_filename: str

The filename of the logo of the lender, in credere-frontend.

name: str

The name of the lender.

sla_days: int | None

The number of days within which the lender agrees to respond to application changes.

type: str

The type of the lender, from the LENDER_TYPES enum in credere-frontend. (Unused.)

class app.models.CreditProduct(*, borrower_size: BorrowerSize, borrower_types: dict[str, bool] = None, lower_limit: Annotated[Decimal, _PydanticGeneralMetadata(max_digits=16, decimal_places=2)], upper_limit: Annotated[Decimal, _PydanticGeneralMetadata(max_digits=16, decimal_places=2)], procurement_category_to_exclude: str = '', type: CreditType, required_document_types: dict[str, bool] = None, interest_rate: str = '', additional_information: str = '', other_fees_total_amount: Annotated[Decimal, _PydanticGeneralMetadata(max_digits=16, decimal_places=2)], other_fees_description: str = '', more_info_url: str = '', lender_id: int, id: int | None = None, created_at: datetime = datetime.datetime(2025, 12, 16, 7, 17, 38, 381880), updated_at: datetime = datetime.datetime(2025, 12, 16, 7, 17, 38, 381947))[source]
borrower_size: BorrowerSize

The size of the borrower to which this credit product is applicable. (The same credit product can be configured for each applicable borrower size.)

borrower_types: dict[str, bool]

The types of borrower to which this credit product is applicable.

lower_limit: Decimal

The lower limit for the amount requested, below which this credit product is inapplicable.

procurement_category_to_exclude: str

A single procurement category, to which this credit product is inapplicable.

required_document_types: dict[str, bool]

The document types that the borrower is prompted to upload.

type: CreditType

The type of credit product, which mainly controls which descriptive fields are displayed.

upper_limit: Decimal

The upper limit for the amount requested, above which this credit product is inapplicable.

class app.models.Message(*, id: int | None = None, type: MessageType, external_message_id: str = '', body: str = '', application_id: int, lender_id: int | None = None, created_at: datetime = datetime.datetime(2025, 12, 16, 7, 17, 38, 420720), updated_at: datetime = datetime.datetime(2025, 12, 16, 7, 17, 38, 420772))[source]
type: MessageType

The type of email message.

external_message_id: str

The SES MessageId.

body: str

The body of the email message, if directly provided by a lender.

classmethod application_by_type(message_type: MessageType) Select[source]

Return the IDs of applications that sent messages of the provided type.

class app.models.User(*, id: int | None = None, type: UserType = UserType.FI, language: str = 'es', email: str, notification_preferences: dict[str, bool] = None, name: str = '', external_id: str = '', lender_id: int | None = None, created_at: datetime = datetime.datetime(2025, 12, 16, 7, 17, 38, 425925))[source]
email: str

The email address with which the user logs in and is contacted.

external_id: str

The Cognito Username.

language: str

Unused.

name: str

The name by which the user is addressed in emails and identified in application action histories.

notification_preferences: dict[str, bool]

The MessageType the user wants to receive notifications about. The supported types are:

type: UserType

The authorization group of the user.

class app.models.Borrower(*, id: int | None = None, borrower_identifier: str = '', declined_at: datetime | None, legal_name: str = '', email: str = '', address: str = '', legal_identifier: str = '', type: str = '', is_msme: bool = True, missing_data: dict[str, bool] = None, size: BorrowerSize = BorrowerSize.NOT_INFORMED, sector: str = '', annual_revenue: Annotated[Decimal | None, _PydanticGeneralMetadata(max_digits=16, decimal_places=2)], currency: str = 'COP', created_at: datetime = datetime.datetime(2025, 12, 16, 7, 17, 38, 386688), updated_at: datetime = datetime.datetime(2025, 12, 16, 7, 17, 38, 386743), source_data: dict[str, Any] = None, status: BorrowerStatus = BorrowerStatus.ACTIVE)[source]

Most fields are derived from the data source. In terms of application logic, those fields are (or can be) used in emails to the borrower, like the legal_identifier and legal_name.

source_data: dict[str, Any]
status: BorrowerStatus

The status of the borrower.

applications: Mapped[list[Application]]
awards: Mapped[list[Award]]
address: str

The registered address of the borrower in the data source.

annual_revenue: Decimal | None

The annual revenue of the borrower.

borrower_identifier: str

The hashed borrower ID, for privacy-preserving long-term identification.

created_at: datetime
currency: str

The currency of the annual revenue of the borrower.

declined_at: datetime | None

The time at which the borrower opted out of Credere entirely.

email: str

The email address with which the application’s primary_email is initialized.

id: int | None
is_msme: bool

Whether the borrower is a MSME in the data source.

legal_identifier: str

The ID of the borrower in the data source.

legal_name: str

The name of the borrower in the data source.

missing_data: dict[str, bool]
sector: str

The industrial sector of the borrower.

size: BorrowerSize
type: str

The type of the borrower in the data source.

updated_at: datetime
class app.models.Award(*, id: int | None = None, source_contract_id: str = '', title: str = '', description: str = '', award_date: datetime | None, award_amount: Annotated[Decimal, _PydanticGeneralMetadata(max_digits=16, decimal_places=2)], award_currency: str = 'COP', contractperiod_startdate: datetime | None, contractperiod_enddate: datetime | None, payment_method: dict[str, Any] = None, buyer_name: str = '', source_url: str = '', entity_code: str = '', contract_status: str = '', source_last_updated_at: datetime | None, previous: bool = False, procurement_method: str = '', contracting_process_id: str = '', procurement_category: str = '', missing_data: dict[str, bool] = None, borrower_id: int | None, source_data_contracts: dict[str, Any] = None, source_data_awards: dict[str, Any] = None, created_at: datetime = datetime.datetime(2025, 12, 16, 7, 17, 38, 395110), updated_at: datetime = datetime.datetime(2025, 12, 16, 7, 17, 38, 395191))[source]

All fields, other than relationships and timestamps, are derived from the data source. In terms of application logic, the fields are (or can be) used in emails to identify the award, like the buyer_name and title.

source_data_contracts: dict[str, Any]
source_data_awards: dict[str, Any]
applications: Mapped[list[Application]]
borrower: Mapped[Borrower | None]
created_at: datetime
updated_at: datetime
classmethod last_updated(session: Session) datetime | None[source]

Return the most recent source_last_updated_at value.

award_amount: Decimal
award_currency: str
award_date: datetime | None
borrower_id: int | None
buyer_name: str
contract_status: str
contracting_process_id: str
contractperiod_enddate: datetime | None
contractperiod_startdate: datetime | None
description: str
entity_code: str
id: int | None
missing_data: dict[str, bool]
payment_method: dict[str, Any]
previous: bool

Whether this award was retrieved when the invitation was accepted (to display to the lender, as context), or is related to an archived application (again, to display in future applications).

procurement_category: str
procurement_method: str
source_contract_id: str

The ID of the award (contract) in the data source.

source_last_updated_at: datetime | None

The time at which the award was last updated in the data source.

source_url: str

The human-readable web page of the award.

title: str