diff --git a/method/resources/Entities/Attributes.py b/method/resources/Entities/Attributes.py new file mode 100644 index 0000000..21a063a --- /dev/null +++ b/method/resources/Entities/Attributes.py @@ -0,0 +1,56 @@ +from typing import TypedDict, Optional, Literal, List + +from method.resource import MethodResponse, Resource +from method.configuration import Configuration +from method.errors import ResourceError + + +EntityAttributesResponseStatusLiterals = Literal[ + 'completed', + 'in_progress', + 'pending', + 'failed' +] + + +CreditHealthAttributeRating = Literal[ + 'excellent', + 'good', + 'fair', + 'needs_work' +] + + +class CreditHealthAttribute(TypedDict): + value: int + rating: CreditHealthAttributeRating + + +class EntityAttributesType(TypedDict): + credit_health_credit_card_usage: CreditHealthAttribute + credit_health_derogatory_marks: CreditHealthAttribute + credit_health_hard_inquiries: CreditHealthAttribute + credit_health_total_accounts: CreditHealthAttribute + credit_health_credit_age: CreditHealthAttribute + credit_health_payment_history: CreditHealthAttribute + + +class EntityAttributes(TypedDict): + id: str + entity_id: str + status: EntityAttributesResponseStatusLiterals + attributes: Optional[List[EntityAttributesType]] + error: Optional[ResourceError] + created_at: str + updated_at: str + + +class EntityAttributesResource(Resource): + def __init__(self, config: Configuration): + super(EntityAttributesResource, self).__init__(config.add_path('attributes')) + + def retrieve(self, attr_id: str) -> MethodResponse[EntityAttributes]: + return super(EntityAttributesResource, self)._get_with_id(attr_id) + + def create(self) -> MethodResponse[EntityAttributes]: + return super(EntityAttributesResource, self)._create({}) diff --git a/method/resources/Entities/Entity.py b/method/resources/Entities/Entity.py index 516a162..c8e1017 100644 --- a/method/resources/Entities/Entity.py +++ b/method/resources/Entities/Entity.py @@ -3,6 +3,7 @@ from method.resource import MethodResponse, Resource, RequestOpts, ResourceListOpts from method.configuration import Configuration from method.errors import ResourceError +from method.resources.Entities.Attributes import EntityAttributesResource from method.resources.Entities.Types import EntityTypesLiterals, EntityCapabilitiesLiterals, EntityStatusesLiterals, \ CreditReportBureausLiterals, EntityIndividual, EntityCorporation, EntityAddress from method.resources.Entities.Connect import EntityConnectResource @@ -105,6 +106,7 @@ class Entity(TypedDict): class EntitySubResources: + attributes: EntityAttributesResource connect: EntityConnectResource credit_scores: EntityCreditScoresResource identities: EntityIdentityResource @@ -114,6 +116,7 @@ class EntitySubResources: verification_sessions: EntityVerificationSessionResource def __init__(self, _id: str, config: Configuration): + self.attributes = EntityAttributesResource(config.add_path(_id)) self.connect = EntityConnectResource(config.add_path(_id)) self.credit_scores = EntityCreditScoresResource(config.add_path(_id)) self.identities = EntityIdentityResource(config.add_path(_id)) diff --git a/method/resources/Entities/Products.py b/method/resources/Entities/Products.py index 036c3a5..de44554 100644 --- a/method/resources/Entities/Products.py +++ b/method/resources/Entities/Products.py @@ -24,6 +24,7 @@ class EntityProduct(TypedDict): class EntityProductListResponse(TypedDict): + attribute: Optional[EntityProduct] connect: Optional[EntityProduct] credit_score: Optional[EntityProduct] identity: Optional[EntityProduct] diff --git a/setup.py b/setup.py index a5fd700..d617c8c 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name='method-python', - version='1.1.0', + version='1.1.1', description='Python library for the Method API', long_description='Python library for the Method API', long_description_content_type='text/x-rst', diff --git a/test/resources/Entity_test.py b/test/resources/Entity_test.py index 9dc88a5..56a245f 100644 --- a/test/resources/Entity_test.py +++ b/test/resources/Entity_test.py @@ -1,4 +1,5 @@ import os +from method.resources.Entities.Attributes import EntityAttributes import pytest from method import Method from dotenv import load_dotenv @@ -26,6 +27,7 @@ entities_account_list_response = None entities_account_ids = None entities_create_credit_score_response = None +entities_create_attribute_response = None entities_create_idenitity_response = None entities_retrieve_product_list_response = None entities_create_connect_subscription_response = None @@ -86,6 +88,7 @@ def test_create_entity(): }, 'connect': None, 'credit_score': None, + 'attribute': None, 'products': [], 'restricted_products': entities_create_response['restricted_products'], 'subscriptions': [], @@ -148,6 +151,7 @@ def test_retrieve_entity(): }, 'connect': None, 'credit_score': None, + 'attribute': None, 'products': [], 'restricted_products': entities_retrieve_response['restricted_products'], 'subscriptions': [], @@ -218,8 +222,9 @@ def test_update_entity(): }, 'connect': None, 'credit_score': None, + 'attribute': None, 'products': [ 'identity' ], - 'restricted_products': [ 'connect', 'credit_score' ].sort(), + 'restricted_products': entities_update_response['restricted_products'], 'subscriptions': [], 'available_subscriptions': [], 'restricted_subscriptions': [ 'connect', 'credit_score' ].sort(), @@ -378,6 +383,44 @@ def get_credit_score(): assert credit_score_retrieve_response == expect_results +# ENTITY ATTRIBUTE TESTS + +def test_create_entity_attribute(): + global entities_create_attribute_response + entities_create_attribute_response = method.entities(entities_create_response['id']).attributes.create() + + expect_results: EntityAttributes = { + 'id': entities_create_attribute_response['id'], + 'entity_id': entities_create_response['id'], + 'status': 'completed', + 'attributes': entities_create_attribute_response.attributes, + 'error': None, + 'created_at': entities_create_attribute_response['created_at'], + 'updated_at': entities_create_attribute_response['updated_at'] + } + + assert entities_create_attribute_response == expect_results + +@pytest.mark.asyncio +async def test_retrieve_entity_attribute(): + def get_attribute(): + return method.entities(entities_create_response['id']).attributes.retrieve(entities_create_attribute_response['id']) + + attribute_retrieve_response = await await_results(get_attribute) + + expect_results: EntityAttributes = { + 'id': attribute_retrieve_response['id'], + 'entity_id': entities_create_response['id'], + 'status': 'completed', + 'attributes': attribute_retrieve_response.attributes, + 'error': None, + 'created_at': attribute_retrieve_response['created_at'], + 'updated_at': attribute_retrieve_response['updated_at'] + } + + assert attribute_retrieve_response == expect_results + + # ENTITY IDENTITY TESTS def test_create_entity_identity(): @@ -517,6 +560,16 @@ def test_retrieve_entity_product_list(): 'is_subscribable': False, 'created_at': entities_retrieve_product_list_response.get('identity', {}).get('created_at', ''), 'updated_at': entities_retrieve_product_list_response.get('identity', {}).get('updated_at', ''), + }, + 'attribute': { + 'id': entities_retrieve_product_list_response.get('attribute', {}).get('id', ''), + 'name': 'attribute', + 'status': 'available', + 'status_error': None, + 'latest_request_id': entities_retrieve_product_list_response.get('attribute', {}).get('latest_request_id', None), + 'is_subscribable': False, + 'created_at': entities_retrieve_product_list_response.get('attribute', {}).get('created_at', ''), + 'updated_at': entities_retrieve_product_list_response.get('attribute', {}).get('updated_at', ''), } } @@ -554,6 +607,17 @@ def test_retrieve_entity_product(): 'updated_at': entity_credit_score_product_response['updated_at'] } + expect_attribute_results: EntityProduct = { + 'id': entities_retrieve_product_list_response.get('attribute', {}).get('id', ''), + 'name': 'attribute', + 'status': 'available', + 'status_error': None, + 'latest_request_id': entities_retrieve_product_list_response.get('attribute', {}).get('latest_request_id', None), + 'is_subscribable': False, + 'created_at': entities_retrieve_product_list_response.get('attribute', {}).get('created_at', ''), + 'updated_at': entities_retrieve_product_list_response.get('attribute', {}).get('updated_at', ''), + } + expect_identity_results: EntityProduct = { 'id': entity_identity_product_id, 'name': 'identity',