From 78137e7fc82240ed7d9ddfcbb61f9e7c8a7e007c Mon Sep 17 00:00:00 2001 From: Rafael Cabral Date: Fri, 12 Jun 2026 16:31:55 -0300 Subject: [PATCH 1/4] Add BusinessIdentity and BusinessAttachment resources --- CHANGELOG.md | 2 + README.md | 241 ++++++++++++++++++ starkinfra/__init__.py | 6 + .../__businessattachment.py | 149 +++++++++++ starkinfra/businessattachment/__init__.py | 3 + starkinfra/businessattachment/log/__init__.py | 1 + starkinfra/businessattachment/log/__log.py | 96 +++++++ .../businessidentity/__businessidentity.py | 178 +++++++++++++ starkinfra/businessidentity/__init__.py | 5 + .../businessidentity/feedback/__feedback.py | 124 +++++++++ .../businessidentity/feedback/__init__.py | 1 + starkinfra/businessidentity/log/__init__.py | 1 + starkinfra/businessidentity/log/__log.py | 96 +++++++ tests/sdk/testBusinessAttachment.py | 62 +++++ tests/sdk/testBusinessAttachmentLog.py | 26 ++ tests/sdk/testBusinessIdentity.py | 64 +++++ tests/sdk/testBusinessIdentityFeedback.py | 36 +++ tests/sdk/testBusinessIdentityLog.py | 25 ++ tests/utils/businessIdentity.py | 19 ++ 19 files changed, 1135 insertions(+) create mode 100644 starkinfra/businessattachment/__businessattachment.py create mode 100644 starkinfra/businessattachment/__init__.py create mode 100644 starkinfra/businessattachment/log/__init__.py create mode 100644 starkinfra/businessattachment/log/__log.py create mode 100644 starkinfra/businessidentity/__businessidentity.py create mode 100644 starkinfra/businessidentity/__init__.py create mode 100644 starkinfra/businessidentity/feedback/__feedback.py create mode 100644 starkinfra/businessidentity/feedback/__init__.py create mode 100644 starkinfra/businessidentity/log/__init__.py create mode 100644 starkinfra/businessidentity/log/__log.py create mode 100644 tests/sdk/testBusinessAttachment.py create mode 100644 tests/sdk/testBusinessAttachmentLog.py create mode 100644 tests/sdk/testBusinessIdentity.py create mode 100644 tests/sdk/testBusinessIdentityFeedback.py create mode 100644 tests/sdk/testBusinessIdentityLog.py create mode 100644 tests/utils/businessIdentity.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 5359ff3..b134f9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ Given a version number MAJOR.MINOR.PATCH, increment: ## [Unreleased] +### Added +- BusinessIdentity and BusinessAttachment resources ## [0.25.0] - 2026-04-08 ### Added diff --git a/README.md b/README.md index d5fb6fd..fc33fe9 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,8 @@ This SDK version is compatible with the Stark Infra API v2. - [IndividualDocument](#create-individualdocuments): Create individual documents - [IndividualAccountRequest](#create-individualaccountrequests): Create individual account requests - [AccountRequestAttachment](#create-accountrequestattachments): Create account request attachments + - [BusinessIdentity](#create-businessidentities): Create business identities + - [BusinessAttachment](#create-businessattachments): Create business attachments - [Webhook](#webhook): - [Webhook](#create-a-webhook-subscription): Configure your webhook endpoints and subscriptions - [WebhookEvents](#process-webhook-events): Manage Webhook events @@ -3413,6 +3415,245 @@ log = starkinfra.accountrequestattachment.log.get("5155165527080960") print(log) ``` +### Create BusinessIdentities + +You can create a BusinessIdentity to verify the identity of a company (PJ) by its tax ID (CNPJ). + +```python +import starkinfra + +identities = starkinfra.businessidentity.create([ + starkinfra.BusinessIdentity( + tax_id="20.018.183/0001-80", + tags=["onboarding-123"] + ) +]) + +for identity in identities: + print(identity) +``` + +**Note**: Instead of using BusinessIdentity objects, you can also pass each element in dictionary format + +### Query BusinessIdentities + +You can query multiple business identities according to filters. + +```python +import starkinfra +from datetime import date + +identities = starkinfra.businessidentity.query( + limit=10, + after=date(2020, 1, 1), + before=date(2020, 4, 1), + status="success", + tags=["onboarding-123"], +) + +for identity in identities: + print(identity) +``` + +### Get a BusinessIdentity + +After its creation, information on a business identity may be retrieved by its id. + +```python +import starkinfra + +identity = starkinfra.businessidentity.get("5155165527080960") + +print(identity) +``` + +### Update a BusinessIdentity + +You can update a specific business identity by passing its id. Send it to processing by passing 'processing' in the status (the identity must have attachments). + +```python +import starkinfra + +identity = starkinfra.businessidentity.update("5155165527080960", status="processing") + +print(identity) +``` + +### Cancel a BusinessIdentity + +You can cancel a business identity by passing its id, while it is in the 'created' or 'pending' status. + +```python +import starkinfra + +identity = starkinfra.businessidentity.cancel("5155165527080960") + +print(identity) +``` + +### Query BusinessIdentity logs + +You can query business identity logs to better understand business identity life cycles. + +```python +import starkinfra +from datetime import date + +logs = starkinfra.businessidentity.log.query( + limit=50, + after=date(2022, 1, 1), + before=date(2022, 1, 20), +) + +for log in logs: + print(log) +``` + +### Get a BusinessIdentity log + +You can also get a specific log by its id. + +```python +import starkinfra + +log = starkinfra.businessidentity.log.get("5155165527080960") + +print(log) +``` + +### Create BusinessIdentity feedbacks + +You can register feedback (positive/negative) about sections of a business identity analysis. + +```python +import starkinfra + +feedbacks = starkinfra.businessidentity.feedback.create([ + starkinfra.businessidentity.Feedback( + business_identity_id="5155165527080960", + option="negative", + session="qsa", + content="Partner divergent from the articles of incorporation" + ) +]) + +for feedback in feedbacks: + print(feedback) +``` + +### Query BusinessIdentity feedbacks + +You can query multiple business identity feedbacks according to filters. + +```python +import starkinfra + +feedbacks = starkinfra.businessidentity.feedback.query( + limit=10, + business_identity_id="5155165527080960", +) + +for feedback in feedbacks: + print(feedback) +``` + +### Create BusinessAttachments + +You can create a BusinessAttachment to attach a document (e.g. articles of incorporation) to a specific BusinessIdentity. +You must reference the desired business identity by its id. A BusinessIdentity accepts at most 2 attachments. + +```python +import starkinfra + +attachments = starkinfra.businessattachment.create([ + starkinfra.BusinessAttachment( + name="articles-of-incorporation.pdf", + content="data:application/pdf;base64,JVBERi0xLjQ...", + identity_id="5155165527080960", + tags=["doc-principal"] + ) +]) + +for attachment in attachments: + print(attachment) +``` + +**Note**: Instead of using BusinessAttachment objects, you can also pass each element in dictionary format + +### Query BusinessAttachments + +You can query multiple business attachments according to filters. + +```python +import starkinfra +from datetime import date + +attachments = starkinfra.businessattachment.query( + limit=10, + after=date(2020, 1, 1), + before=date(2020, 4, 1), + status="approved", + tags=["doc-principal"], +) + +for attachment in attachments: + print(attachment) +``` + +### Get a BusinessAttachment + +After its creation, information on a business attachment may be retrieved by its id. Pass `expand=["content"]` to also retrieve the document content. + +```python +import starkinfra + +attachment = starkinfra.businessattachment.get("5155165527080960", expand=["content"]) + +print(attachment) +``` + +### Cancel a BusinessAttachment + +You can cancel a business attachment by passing its id, while it is in the 'created' status. + +```python +import starkinfra + +attachment = starkinfra.businessattachment.cancel("5155165527080960") + +print(attachment) +``` + +### Query BusinessAttachment logs + +You can query business attachment logs to better understand business attachment life cycles. + +```python +import starkinfra +from datetime import date + +logs = starkinfra.businessattachment.log.query( + limit=50, + after=date(2022, 1, 1), + before=date(2022, 1, 20), +) + +for log in logs: + print(log) +``` + +### Get a BusinessAttachment log + +You can also get a specific log by its id. + +```python +import starkinfra + +log = starkinfra.businessattachment.log.get("5155165527080960") + +print(log) +``` + ## Webhook ### Create a webhook subscription diff --git a/starkinfra/__init__.py b/starkinfra/__init__.py index e77ce55..8c2e402 100644 --- a/starkinfra/__init__.py +++ b/starkinfra/__init__.py @@ -84,6 +84,12 @@ from . import accountrequestattachment from .accountrequestattachment.__accountrequestattachment import AccountRequestAttachment +from . import businessidentity +from .businessidentity.__businessidentity import BusinessIdentity + +from . import businessattachment +from .businessattachment.__businessattachment import BusinessAttachment + from . import dynamicbrcode from .dynamicbrcode.__dynamicbrcode import DynamicBrcode diff --git a/starkinfra/businessattachment/__businessattachment.py b/starkinfra/businessattachment/__businessattachment.py new file mode 100644 index 0000000..6b1f670 --- /dev/null +++ b/starkinfra/businessattachment/__businessattachment.py @@ -0,0 +1,149 @@ +from base64 import b64encode +from ..utils import rest +from starkcore.utils.resource import Resource +from starkcore.utils.checks import check_datetime, check_date + + +class BusinessAttachment(Resource): + """# BusinessAttachment object + A BusinessAttachment represents a document (articles of incorporation, bylaws, etc.) sent + to a BusinessIdentity. You must reference the desired BusinessIdentity by its id. + A BusinessIdentity accepts at most 2 attachments. + When you initialize a BusinessAttachment, the entity will not be automatically + created in the Stark Infra API. The 'create' function sends the objects + to the Stark Infra API and returns the list of created objects. + ## Parameters (required): + - name [string]: name of the document. Must be unique among the identity's "created" attachments. ex: "articles-of-incorporation.pdf" + - content [string]: Base64 data url of the document. ex: data:application/pdf;base64,JVBERi0xLjQ... + - identity_id [string]: unique id of the BusinessIdentity this attachment belongs to. Sent as "identityId" on creation and returned as "businessIdentityId". ex: "5656565656565656" + ## Parameters (optional): + - content_type [string, default None]: content MIME type. This parameter is required as input only. ex: "application/pdf", "image/png" or "image/jpeg" + - tags [list of strings, default []]: list of strings for reference when searching for BusinessAttachments. ex: ["doc-principal"] + ## Attributes (return-only): + - id [string]: unique id returned when the BusinessAttachment is created. ex: "5656565656565656" + - attachment_id [string]: id of the document in the external ms-attachment. ex: "5104320788332544" + - status [string]: current status of the BusinessAttachment. ex: "created", "canceled", "approved", "denied" + - created [datetime.datetime]: creation datetime for the BusinessAttachment. ex: datetime.datetime(2020, 3, 10, 10, 30, 0, 0) + - updated [datetime.datetime]: latest update datetime for the BusinessAttachment. ex: datetime.datetime(2020, 3, 10, 10, 30, 0, 0) + """ + + def __init__(self, name, content, identity_id=None, content_type=None, tags=None, id=None, + business_identity_id=None, attachment_id=None, status=None, created=None, updated=None): + Resource.__init__(self, id=id) + + self.name = name + self.content = content + # the API expects "identityId" on creation but returns "businessIdentityId"; expose a single attribute + self.identity_id = identity_id if identity_id is not None else business_identity_id + self.tags = tags + self.attachment_id = attachment_id + self.status = status + self.created = check_datetime(created) + self.updated = check_datetime(updated) + + if content_type: + if not content: + raise ValueError("content is required when content_type is provided") + if isinstance(content, bytes): + content = b64encode(content).decode() + self.content = "data:" + content_type + ";base64," + content + + +_resource = {"class": BusinessAttachment, "name": "BusinessAttachment"} + + +def create(attachments, user=None): + """# Create BusinessAttachments + Send a list of BusinessAttachment objects for creation at the Stark Infra API + ## Parameters (required): + - attachments [list of BusinessAttachment objects]: list of BusinessAttachment objects to be created in the API + ## Parameters (optional): + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. + ## Return: + - list of BusinessAttachment objects with updated attributes + """ + return rest.post_multi(resource=_resource, entities=attachments, user=user) + + +def get(id, expand=None, user=None): + """# Retrieve a specific BusinessAttachment + Receive a single BusinessAttachment object previously created in the Stark Infra API by its id + ## Parameters (required): + - id [string]: object unique id. ex: "5656565656565656" + ## Parameters (optional): + - expand [list of strings, default None]: fields to expand information. ex: ["content"] + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. + ## Return: + - BusinessAttachment object with updated attributes + """ + return rest.get_id(resource=_resource, id=id, expand=expand, user=user) + + +def query(limit=None, after=None, before=None, status=None, tags=None, ids=None, user=None): + """# Retrieve BusinessAttachments + Receive a generator of BusinessAttachment objects previously created in the Stark Infra API + ## Parameters (optional): + - limit [integer, default None]: maximum number of objects to be retrieved. Unlimited if None. ex: 35 + - after [datetime.date or string, default None] date filter for objects created only after specified date. ex: datetime.date(2020, 3, 10) + - before [datetime.date or string, default None] date filter for objects created only before specified date. ex: datetime.date(2020, 3, 10) + - status [list of strings, default None]: filter for status of retrieved objects. ex: ["created", "canceled", "approved", "denied"] + - tags [list of strings, default None]: tags to filter retrieved objects. ex: ["tony", "stark"] + - ids [list of strings, default None]: list of ids to filter retrieved objects. ex: ["5656565656565656", "4545454545454545"] + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. + ## Return: + - generator of BusinessAttachment objects with updated attributes + """ + return rest.get_stream( + resource=_resource, + limit=limit, + after=check_date(after), + before=check_date(before), + status=status, + tags=tags, + ids=ids, + user=user, + ) + + +def page(cursor=None, limit=None, after=None, before=None, status=None, tags=None, ids=None, user=None): + """# Retrieve paged BusinessAttachments + Receive a list of up to 100 BusinessAttachment objects previously created in the Stark Infra API and the cursor to the next page. + Use this function instead of query if you want to manually page your requests. + ## Parameters (optional): + - cursor [string, default None]: cursor returned on the previous page function call + - limit [integer, default 100]: maximum number of objects to be retrieved. It must be an integer between 1 and 100. ex: 50 + - after [datetime.date or string, default None] date filter for objects created only after specified date. ex: datetime.date(2020, 3, 10) + - before [datetime.date or string, default None] date filter for objects created only before specified date. ex: datetime.date(2020, 3, 10) + - status [list of strings, default None]: filter for status of retrieved objects. ex: ["created", "canceled", "approved", "denied"] + - tags [list of strings, default None]: tags to filter retrieved objects. ex: ["tony", "stark"] + - ids [list of strings, default None]: list of ids to filter retrieved objects. ex: ["5656565656565656", "4545454545454545"] + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. + ## Return: + - list of BusinessAttachment objects with updated attributes + - cursor to retrieve the next page of BusinessAttachment objects + """ + return rest.get_page( + resource=_resource, + cursor=cursor, + limit=limit, + after=check_date(after), + before=check_date(before), + status=status, + tags=tags, + ids=ids, + user=user, + ) + + +def cancel(id, user=None): + """# Cancel a BusinessAttachment entity + Cancel a BusinessAttachment entity previously created in the Stark Infra API. Only attachments + in the 'created' status can be canceled. + ## Parameters (required): + - id [string]: BusinessAttachment unique id. ex: "5656565656565656" + ## Parameters (optional): + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. + ## Return: + - canceled BusinessAttachment object + """ + return rest.delete_id(resource=_resource, id=id, user=user) diff --git a/starkinfra/businessattachment/__init__.py b/starkinfra/businessattachment/__init__.py new file mode 100644 index 0000000..c2b5b13 --- /dev/null +++ b/starkinfra/businessattachment/__init__.py @@ -0,0 +1,3 @@ +from .__businessattachment import create, get, query, page, cancel +from .log.__log import Log +from . import log diff --git a/starkinfra/businessattachment/log/__init__.py b/starkinfra/businessattachment/log/__init__.py new file mode 100644 index 0000000..a8a69ba --- /dev/null +++ b/starkinfra/businessattachment/log/__init__.py @@ -0,0 +1 @@ +from .__log import query, page, get diff --git a/starkinfra/businessattachment/log/__log.py b/starkinfra/businessattachment/log/__log.py new file mode 100644 index 0000000..3cf7c5a --- /dev/null +++ b/starkinfra/businessattachment/log/__log.py @@ -0,0 +1,96 @@ +from ...utils import rest +from starkcore.utils.resource import Resource +from starkcore.utils.checks import check_datetime, check_date +from starkcore.utils.api import from_api_json +from ..__businessattachment import _resource as _business_attachment_resource + + +class Log(Resource): + """# businessattachment.Log object + Every time a BusinessAttachment entity is updated, a corresponding businessattachment.Log + is generated for the entity. This log is never generated by the + user, but it can be retrieved to check additional information + on the BusinessAttachment. + ## Attributes (return-only): + - id [string]: unique id returned when the log is created. ex: "5656565656565656" + - attachment [BusinessAttachment]: BusinessAttachment entity to which the log refers to. + - errors [list of strings]: list of errors linked to this BusinessAttachment event + - type [string]: type of the BusinessAttachment event which triggered the log creation. ex: "created", "canceled", "approved", "denied" + - created [datetime.datetime]: creation datetime for the log. ex: datetime.datetime(2020, 3, 10, 10, 30, 0, 0) + """ + + def __init__(self, id, created, type, errors, attachment): + Resource.__init__(self, id=id) + + self.created = check_datetime(created) + self.type = type + self.errors = errors + self.attachment = from_api_json(_business_attachment_resource, attachment) + + +_resource = {"class": Log, "name": "BusinessAttachmentLog"} + + +def get(id, user=None): + """# Retrieve a specific businessattachment.Log + Receive a single businessattachment.Log object previously created by the Stark Infra API by its id + ## Parameters (required): + - id [string]: object unique id. ex: "5656565656565656" + ## Parameters (optional): + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. + ## Return: + - businessattachment.Log object with updated attributes + """ + return rest.get_id(resource=_resource, id=id, user=user) + + +def query(limit=None, after=None, before=None, types=None, attachment_ids=None, user=None): + """# Retrieve businessattachment.Logs + Receive a generator of businessattachment.Log objects previously created in the Stark Infra API + ## Parameters (optional): + - limit [integer, default None]: maximum number of objects to be retrieved. Unlimited if None. ex: 35 + - after [datetime.date or string, default None] date filter for objects created only after specified date. ex: datetime.date(2020, 3, 10) + - before [datetime.date or string, default None] date filter for objects created only before specified date. ex: datetime.date(2020, 3, 10) + - types [list of strings, default None]: filter for log event types. ex: ["created", "canceled", "approved", "denied"] + - attachment_ids [list of strings, default None]: list of BusinessAttachment ids to filter logs. ex: ["5656565656565656", "4545454545454545"] + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. + ## Return: + - generator of businessattachment.Log objects with updated attributes + """ + return rest.get_stream( + resource=_resource, + limit=limit, + after=check_date(after), + before=check_date(before), + types=types, + attachment_ids=attachment_ids, + user=user, + ) + + +def page(cursor=None, limit=None, after=None, before=None, types=None, attachment_ids=None, user=None): + """# Retrieve paged businessattachment.Logs + Receive a list of up to 100 businessattachment.Log objects previously created in the Stark Infra API and the cursor to the next page. + Use this function instead of query if you want to manually page your requests. + ## Parameters (optional): + - cursor [string, default None]: cursor returned on the previous page function call + - limit [integer, default 100]: maximum number of objects to be retrieved. It must be an integer between 1 and 100. ex: 50 + - after [datetime.date or string, default None] date filter for objects created only after specified date. ex: datetime.date(2020, 3, 10) + - before [datetime.date or string, default None] date filter for objects created only before specified date. ex: datetime.date(2020, 3, 10) + - types [list of strings, default None]: filter for log event types. ex: ["created", "canceled", "approved", "denied"] + - attachment_ids [list of strings, default None]: list of BusinessAttachment ids to filter logs. ex: ["5656565656565656", "4545454545454545"] + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. + ## Return: + - list of businessattachment.Log objects with updated attributes + - cursor to retrieve the next page of businessattachment.Log objects + """ + return rest.get_page( + resource=_resource, + cursor=cursor, + limit=limit, + after=check_date(after), + before=check_date(before), + types=types, + attachment_ids=attachment_ids, + user=user, + ) diff --git a/starkinfra/businessidentity/__businessidentity.py b/starkinfra/businessidentity/__businessidentity.py new file mode 100644 index 0000000..7ba8ec5 --- /dev/null +++ b/starkinfra/businessidentity/__businessidentity.py @@ -0,0 +1,178 @@ +from ..utils import rest +from starkcore.utils.resource import Resource +from starkcore.utils.checks import check_datetime, check_date +from starkcore.utils.api import api_json, from_api_json + + +class BusinessIdentity(Resource): + """# BusinessIdentity object + A BusinessIdentity represents the identity verification of a company (PJ), identified by + its tax ID (CNPJ). It holds the company's registration data, the list of representatives, + the attached documents, the extracted signature rules and the final verification status. + When you initialize a BusinessIdentity, the entity will not be automatically + created in the Stark Infra API. The 'create' function sends the objects + to the Stark Infra API and returns the list of created objects. + ## Parameters (required): + - tax_id [string]: company's tax ID (CNPJ). ex: "20.018.183/0001-80" + ## Parameters (optional): + - tags [list of strings, default []]: list of strings for reference when searching for BusinessIdentities. ex: ["onboarding-123"] + ## Attributes (return-only): + - id [string]: unique id returned when the BusinessIdentity is created. ex: "5656565656565656" + - name [string]: company's legal name, filled from the bureau. ex: "STARK BANK S.A." + - tax_id_status [string]: status of the CNPJ at the bureau. ex: "active", "blocked", "pending" + - insight_tax_id [string]: tax ID extracted from the document by the insight. ex: "20.018.183/0001-80" + - insight_document_type [string]: document type detected by the insight. ex: "articles-of-incorporation" + - num_pages [integer]: number of pages of the document. ex: 5 + - representatives [string]: JSON string of the company's representatives. ex: "[{\"name\": \"Edward Stark\", \"qualification\": \"Diretor\"}]" + - attachments [list of strings]: list of attached documents references. ex: ["attachment/5656565656565656"] + - rules [string]: JSON string of the complemented signature rules. + - status [string]: current status of the BusinessIdentity. ex: "created", "pending", "canceled", "processing", "success", "failed" + - created [datetime.datetime]: creation datetime for the BusinessIdentity. ex: datetime.datetime(2020, 3, 10, 10, 30, 0, 0) + - updated [datetime.datetime]: latest update datetime for the BusinessIdentity. ex: datetime.datetime(2020, 3, 10, 10, 30, 0, 0) + """ + + def __init__(self, tax_id, tags=None, id=None, name=None, tax_id_status=None, insight_tax_id=None, + insight_document_type=None, num_pages=None, representatives=None, attachments=None, rules=None, + status=None, created=None, updated=None): + Resource.__init__(self, id=id) + + self.tax_id = tax_id + self.tags = tags + self.name = name + self.tax_id_status = tax_id_status + self.insight_tax_id = insight_tax_id + self.insight_document_type = insight_document_type + self.num_pages = num_pages + self.representatives = representatives + self.attachments = attachments + self.rules = rules + self.status = status + self.created = check_datetime(created) + self.updated = check_datetime(updated) + + +_resource = {"class": BusinessIdentity, "name": "BusinessIdentity"} + + +def create(identities, user=None): + """# Create BusinessIdentities + Send a list of BusinessIdentity objects for creation at the Stark Infra API + ## Parameters (required): + - identities [list of BusinessIdentity objects]: list of BusinessIdentity objects to be created in the API + ## Parameters (optional): + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. + ## Return: + - list of BusinessIdentity objects with updated attributes + """ + # the create route uses a non-standard request wrapper ("businessIdentities") while the + # response keeps the conventional one ("identities"), so we build the request manually. + payload = {"businessIdentities": [api_json(identity) for identity in identities]} + json = rest.post_raw(path="business-identity", payload=payload, user=user).json() + entities = json.get("identities", json.get("businessIdentities", [])) + return [from_api_json(_resource, identity) for identity in entities] + + +def get(id, user=None): + """# Retrieve a specific BusinessIdentity + Receive a single BusinessIdentity object previously created in the Stark Infra API by its id + ## Parameters (required): + - id [string]: object unique id. ex: "5656565656565656" + ## Parameters (optional): + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. + ## Return: + - BusinessIdentity object with updated attributes + """ + return rest.get_id(resource=_resource, id=id, user=user) + + +def query(limit=None, after=None, before=None, status=None, tags=None, ids=None, tax_ids=None, user=None): + """# Retrieve BusinessIdentities + Receive a generator of BusinessIdentity objects previously created in the Stark Infra API + ## Parameters (optional): + - limit [integer, default None]: maximum number of objects to be retrieved. Unlimited if None. ex: 35 + - after [datetime.date or string, default None] date filter for objects created only after specified date. ex: datetime.date(2020, 3, 10) + - before [datetime.date or string, default None] date filter for objects created only before specified date. ex: datetime.date(2020, 3, 10) + - status [list of strings, default None]: filter for status of retrieved objects. ex: ["created", "pending", "canceled", "processing", "success", "failed"] + - tags [list of strings, default None]: tags to filter retrieved objects. ex: ["tony", "stark"] + - ids [list of strings, default None]: list of ids to filter retrieved objects. ex: ["5656565656565656", "4545454545454545"] + - tax_ids [list of strings, default None]: list of company tax IDs (CNPJ) to filter retrieved objects. ex: ["20.018.183/0001-80"] + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. + ## Return: + - generator of BusinessIdentity objects with updated attributes + """ + return rest.get_stream( + resource=_resource, + limit=limit, + after=check_date(after), + before=check_date(before), + status=status, + tags=tags, + ids=ids, + tax_ids=tax_ids, + user=user, + ) + + +def page(cursor=None, limit=None, after=None, before=None, status=None, tags=None, ids=None, tax_ids=None, user=None): + """# Retrieve paged BusinessIdentities + Receive a list of up to 100 BusinessIdentity objects previously created in the Stark Infra API and the cursor to the next page. + Use this function instead of query if you want to manually page your requests. + ## Parameters (optional): + - cursor [string, default None]: cursor returned on the previous page function call + - limit [integer, default 100]: maximum number of objects to be retrieved. It must be an integer between 1 and 100. ex: 50 + - after [datetime.date or string, default None] date filter for objects created only after specified date. ex: datetime.date(2020, 3, 10) + - before [datetime.date or string, default None] date filter for objects created only before specified date. ex: datetime.date(2020, 3, 10) + - status [list of strings, default None]: filter for status of retrieved objects. ex: ["created", "pending", "canceled", "processing", "success", "failed"] + - tags [list of strings, default None]: tags to filter retrieved objects. ex: ["tony", "stark"] + - ids [list of strings, default None]: list of ids to filter retrieved objects. ex: ["5656565656565656", "4545454545454545"] + - tax_ids [list of strings, default None]: list of company tax IDs (CNPJ) to filter retrieved objects. ex: ["20.018.183/0001-80"] + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. + ## Return: + - list of BusinessIdentity objects with updated attributes + - cursor to retrieve the next page of BusinessIdentity objects + """ + return rest.get_page( + resource=_resource, + cursor=cursor, + limit=limit, + after=check_date(after), + before=check_date(before), + status=status, + tags=tags, + ids=ids, + tax_ids=tax_ids, + user=user, + ) + + +def update(id, status=None, tags=None, user=None): + """# Update BusinessIdentity entity + Update a BusinessIdentity by passing id. + ## Parameters (required): + - id [string]: BusinessIdentity id. ex: '5656565656565656' + ## Parameters (optional): + - status [string]: You may send the BusinessIdentity to processing by passing 'processing' in the status. The identity must have attachments. + - tags [list of strings]: list of strings for reference when searching for BusinessIdentities. ex: ["onboarding-123"] + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. + ## Return: + - target BusinessIdentity with updated attributes + """ + payload = { + "status": status, + "tags": tags, + } + return rest.patch_id(resource=_resource, id=id, user=user, payload=payload) + + +def cancel(id, user=None): + """# Cancel a BusinessIdentity entity + Cancel a BusinessIdentity entity previously created in the Stark Infra API. Only identities + in the 'created' or 'pending' status can be canceled. + ## Parameters (required): + - id [string]: BusinessIdentity unique id. ex: "5656565656565656" + ## Parameters (optional): + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. + ## Return: + - canceled BusinessIdentity object + """ + return rest.delete_id(resource=_resource, id=id, user=user) diff --git a/starkinfra/businessidentity/__init__.py b/starkinfra/businessidentity/__init__.py new file mode 100644 index 0000000..f5d3719 --- /dev/null +++ b/starkinfra/businessidentity/__init__.py @@ -0,0 +1,5 @@ +from .__businessidentity import create, get, query, page, update, cancel +from .log.__log import Log +from . import log +from .feedback.__feedback import Feedback +from . import feedback diff --git a/starkinfra/businessidentity/feedback/__feedback.py b/starkinfra/businessidentity/feedback/__feedback.py new file mode 100644 index 0000000..f3e180c --- /dev/null +++ b/starkinfra/businessidentity/feedback/__feedback.py @@ -0,0 +1,124 @@ +from ...utils import rest +from starkcore.utils.resource import Resource +from starkcore.utils.checks import check_datetime, check_date +from starkcore.utils.api import api_json, from_api_json + + +# The feedback routes are nested under business-identity (POST/GET /business-identity/feedback). +# starkcore's endpoint() only nests "-log"/"-attempt", so we hit the path explicitly with raw requests. +_path = "business-identity/feedback" + + +class Feedback(Resource): + """# businessidentity.Feedback object + A businessidentity.Feedback registers an evaluation (positive/negative) about a section of + the analysis of a BusinessIdentity. When you initialize a Feedback, the entity will not be + automatically created in the Stark Infra API. The 'create' function sends the objects + to the Stark Infra API and returns the list of created objects. + ## Parameters (required): + - option [string]: feedback option. Options: "positive", "negative" + - session [string]: section of the analysis the feedback refers to. Options: "basicData", "qsa", "rules" + - business_identity_id [string]: unique id of the BusinessIdentity the feedback refers to. ex: "5656565656565656" + ## Parameters (optional): + - content [string, default None]: free text content of the feedback. ex: "Partner divergent from the articles of incorporation" + ## Attributes (return-only): + - id [string]: unique id returned when the Feedback is created. ex: "5656565656565656" + - created [datetime.datetime]: creation datetime for the Feedback. ex: datetime.datetime(2020, 3, 10, 10, 30, 0, 0) + - updated [datetime.datetime]: latest update datetime for the Feedback. ex: datetime.datetime(2020, 3, 10, 10, 30, 0, 0) + """ + + def __init__(self, option, session, business_identity_id, content=None, id=None, created=None, updated=None): + Resource.__init__(self, id=id) + + self.option = option + self.session = session + self.business_identity_id = business_identity_id + self.content = content + self.created = check_datetime(created) + self.updated = check_datetime(updated) + + +_resource = {"class": Feedback, "name": "BusinessIdentityFeedback"} + + +def create(feedbacks, user=None): + """# Create businessidentity.Feedbacks + Send a list of businessidentity.Feedback objects for creation at the Stark Infra API + ## Parameters (required): + - feedbacks [list of businessidentity.Feedback objects]: list of Feedback objects to be created in the API + ## Parameters (optional): + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. + ## Return: + - list of businessidentity.Feedback objects with updated attributes + """ + payload = {"feedbacks": [api_json(feedback) for feedback in feedbacks]} + json = rest.post_raw(path=_path, payload=payload, user=user).json() + return [from_api_json(_resource, feedback) for feedback in json.get("feedbacks", [])] + + +def query(limit=None, after=None, before=None, ids=None, business_identity_id=None, user=None): + """# Retrieve businessidentity.Feedbacks + Receive a generator of businessidentity.Feedback objects previously created in the Stark Infra API + ## Parameters (optional): + - limit [integer, default None]: maximum number of objects to be retrieved. Unlimited if None. ex: 35 + - after [datetime.date or string, default None] date filter for objects created only after specified date. ex: datetime.date(2020, 3, 10) + - before [datetime.date or string, default None] date filter for objects created only before specified date. ex: datetime.date(2020, 3, 10) + - ids [list of strings, default None]: list of ids to filter retrieved objects. ex: ["5656565656565656", "4545454545454545"] + - business_identity_id [string, default None]: filter for feedbacks of a specific BusinessIdentity. ex: "5656565656565656" + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. + ## Return: + - generator of businessidentity.Feedback objects with updated attributes + """ + cursor = None + while True: + feedbacks, cursor = page( + cursor=cursor, + limit=min(limit, 100) if limit else limit, + after=after, + before=before, + ids=ids, + business_identity_id=business_identity_id, + user=user, + ) + for feedback in feedbacks: + yield feedback + + if limit: + limit -= 100 + if limit <= 0: + break + + if not cursor: + break + + +def page(cursor=None, limit=None, after=None, before=None, ids=None, business_identity_id=None, user=None): + """# Retrieve paged businessidentity.Feedbacks + Receive a list of up to 100 businessidentity.Feedback objects previously created in the Stark Infra API and the cursor to the next page. + Use this function instead of query if you want to manually page your requests. + ## Parameters (optional): + - cursor [string, default None]: cursor returned on the previous page function call + - limit [integer, default 100]: maximum number of objects to be retrieved. It must be an integer between 1 and 100. ex: 50 + - after [datetime.date or string, default None] date filter for objects created only after specified date. ex: datetime.date(2020, 3, 10) + - before [datetime.date or string, default None] date filter for objects created only before specified date. ex: datetime.date(2020, 3, 10) + - ids [list of strings, default None]: list of ids to filter retrieved objects. ex: ["5656565656565656", "4545454545454545"] + - business_identity_id [string, default None]: filter for feedbacks of a specific BusinessIdentity. ex: "5656565656565656" + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. + ## Return: + - list of businessidentity.Feedback objects with updated attributes + - cursor to retrieve the next page of businessidentity.Feedback objects + """ + json = rest.get_raw( + path=_path, + query={ + "cursor": cursor, + "limit": limit, + "after": check_date(after), + "before": check_date(before), + "ids": ids, + "business_identity_id": business_identity_id, + }, + user=user, + ).json() + feedbacks = [from_api_json(_resource, feedback) for feedback in json.get("feedbacks", [])] + return feedbacks, json.get("cursor") diff --git a/starkinfra/businessidentity/feedback/__init__.py b/starkinfra/businessidentity/feedback/__init__.py new file mode 100644 index 0000000..60d8030 --- /dev/null +++ b/starkinfra/businessidentity/feedback/__init__.py @@ -0,0 +1 @@ +from .__feedback import create, query, page diff --git a/starkinfra/businessidentity/log/__init__.py b/starkinfra/businessidentity/log/__init__.py new file mode 100644 index 0000000..a8a69ba --- /dev/null +++ b/starkinfra/businessidentity/log/__init__.py @@ -0,0 +1 @@ +from .__log import query, page, get diff --git a/starkinfra/businessidentity/log/__log.py b/starkinfra/businessidentity/log/__log.py new file mode 100644 index 0000000..03aed03 --- /dev/null +++ b/starkinfra/businessidentity/log/__log.py @@ -0,0 +1,96 @@ +from ...utils import rest +from starkcore.utils.resource import Resource +from starkcore.utils.checks import check_datetime, check_date +from starkcore.utils.api import from_api_json +from ..__businessidentity import _resource as _business_identity_resource + + +class Log(Resource): + """# businessidentity.Log object + Every time a BusinessIdentity entity is updated, a corresponding businessidentity.Log + is generated for the entity. This log is never generated by the + user, but it can be retrieved to check additional information + on the BusinessIdentity. + ## Attributes (return-only): + - id [string]: unique id returned when the log is created. ex: "5656565656565656" + - identity [BusinessIdentity]: BusinessIdentity entity to which the log refers to. + - errors [list of strings]: list of errors linked to this BusinessIdentity event + - type [string]: type of the BusinessIdentity event which triggered the log creation. ex: "created", "updated", "canceled", "processing", "success", "failed" + - created [datetime.datetime]: creation datetime for the log. ex: datetime.datetime(2020, 3, 10, 10, 30, 0, 0) + """ + + def __init__(self, id, created, type, errors, identity): + Resource.__init__(self, id=id) + + self.created = check_datetime(created) + self.type = type + self.errors = errors + self.identity = from_api_json(_business_identity_resource, identity) + + +_resource = {"class": Log, "name": "BusinessIdentityLog"} + + +def get(id, user=None): + """# Retrieve a specific businessidentity.Log + Receive a single businessidentity.Log object previously created by the Stark Infra API by its id + ## Parameters (required): + - id [string]: object unique id. ex: "5656565656565656" + ## Parameters (optional): + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. + ## Return: + - businessidentity.Log object with updated attributes + """ + return rest.get_id(resource=_resource, id=id, user=user) + + +def query(limit=None, after=None, before=None, types=None, identity_ids=None, user=None): + """# Retrieve businessidentity.Logs + Receive a generator of businessidentity.Log objects previously created in the Stark Infra API + ## Parameters (optional): + - limit [integer, default None]: maximum number of objects to be retrieved. Unlimited if None. ex: 35 + - after [datetime.date or string, default None] date filter for objects created only after specified date. ex: datetime.date(2020, 3, 10) + - before [datetime.date or string, default None] date filter for objects created only before specified date. ex: datetime.date(2020, 3, 10) + - types [list of strings, default None]: filter for log event types. ex: ["created", "updated", "canceled", "processing", "success", "failed"] + - identity_ids [list of strings, default None]: list of BusinessIdentity ids to filter logs. ex: ["5656565656565656", "4545454545454545"] + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. + ## Return: + - generator of businessidentity.Log objects with updated attributes + """ + return rest.get_stream( + resource=_resource, + limit=limit, + after=check_date(after), + before=check_date(before), + types=types, + identity_ids=identity_ids, + user=user, + ) + + +def page(cursor=None, limit=None, after=None, before=None, types=None, identity_ids=None, user=None): + """# Retrieve paged businessidentity.Logs + Receive a list of up to 100 businessidentity.Log objects previously created in the Stark Infra API and the cursor to the next page. + Use this function instead of query if you want to manually page your requests. + ## Parameters (optional): + - cursor [string, default None]: cursor returned on the previous page function call + - limit [integer, default 100]: maximum number of objects to be retrieved. It must be an integer between 1 and 100. ex: 50 + - after [datetime.date or string, default None] date filter for objects created only after specified date. ex: datetime.date(2020, 3, 10) + - before [datetime.date or string, default None] date filter for objects created only before specified date. ex: datetime.date(2020, 3, 10) + - types [list of strings, default None]: filter for log event types. ex: ["created", "updated", "canceled", "processing", "success", "failed"] + - identity_ids [list of strings, default None]: list of BusinessIdentity ids to filter logs. ex: ["5656565656565656", "4545454545454545"] + - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. + ## Return: + - list of businessidentity.Log objects with updated attributes + - cursor to retrieve the next page of businessidentity.Log objects + """ + return rest.get_page( + resource=_resource, + cursor=cursor, + limit=limit, + after=check_date(after), + before=check_date(before), + types=types, + identity_ids=identity_ids, + user=user, + ) diff --git a/tests/sdk/testBusinessAttachment.py b/tests/sdk/testBusinessAttachment.py new file mode 100644 index 0000000..6247ab5 --- /dev/null +++ b/tests/sdk/testBusinessAttachment.py @@ -0,0 +1,62 @@ +import starkinfra +from unittest import TestCase, main +from tests.utils.user import exampleProject + + +starkinfra.user = exampleProject + + +class TestBusinessAttachmentPost(TestCase): + + def test_success(self): + identities = list(starkinfra.businessidentity.query(status="pending", limit=1)) + self.assertTrue(len(identities) > 0) + attachments = starkinfra.businessattachment.create([ + starkinfra.BusinessAttachment( + identity_id=identities[0].id, + name="articles-of-incorporation.png", + content="iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==", + content_type="image/png", + ) + ]) + for attachment in attachments: + self.assertIsNotNone(attachment.id) + + +class TestBusinessAttachmentQuery(TestCase): + + def test_success(self): + attachments = list(starkinfra.businessattachment.query(limit=1)) + for attachment in attachments: + print(attachment) + print("Number of attachments:", len(attachments)) + + +class TestBusinessAttachmentPage(TestCase): + + def test_success(self): + cursor = None + ids = [] + for _ in range(2): + attachments, cursor = starkinfra.businessattachment.page(limit=2, cursor=cursor) + for attachment in attachments: + print(attachment) + self.assertFalse(attachment.id in ids) + ids.append(attachment.id) + if cursor is None: + break + self.assertEqual(len(ids), 4) + + +class TestBusinessAttachmentInfoGet(TestCase): + + def test_success(self): + attachments = starkinfra.businessattachment.query(limit=3) + for attachment in attachments: + attachment_id = attachment.id + attachment_new = starkinfra.businessattachment.get(attachment_id, expand=["content"]) + self.assertEqual(attachment_new.id, attachment_id) + + +if __name__ == '__main__': + main() diff --git a/tests/sdk/testBusinessAttachmentLog.py b/tests/sdk/testBusinessAttachmentLog.py new file mode 100644 index 0000000..182e5a4 --- /dev/null +++ b/tests/sdk/testBusinessAttachmentLog.py @@ -0,0 +1,26 @@ +import starkinfra +from unittest import TestCase, main +from tests.utils.user import exampleProject + +starkinfra.user = exampleProject + + +class TestBusinessAttachmentLogQuery(TestCase): + + def test_success(self): + logs = starkinfra.businessattachment.log.query(limit=10) + for log in logs: + self.assertEqual(log.id, str(log.id)) + + +class TestBusinessAttachmentLogGet(TestCase): + + def test_success(self): + logs = starkinfra.businessattachment.log.query(limit=1) + print(next(logs)) + log = starkinfra.businessattachment.log.get(id=next(logs).id) + self.assertEqual(log.id, str(log.id)) + + +if __name__ == '__main__': + main() diff --git a/tests/sdk/testBusinessIdentity.py b/tests/sdk/testBusinessIdentity.py new file mode 100644 index 0000000..47574da --- /dev/null +++ b/tests/sdk/testBusinessIdentity.py @@ -0,0 +1,64 @@ +import starkinfra +from unittest import TestCase, main +from tests.utils.user import exampleProject +from tests.utils.businessIdentity import generateExampleBusinessIdentityJson + + +starkinfra.user = exampleProject + + +class TestBusinessIdentityPost(TestCase): + + def test_success(self): + identities = generateExampleBusinessIdentityJson(n=1) + identities = starkinfra.businessidentity.create(identities) + for identity in identities: + self.assertIsNotNone(identity.id) + + +class TestBusinessIdentityQuery(TestCase): + + def test_success(self): + identities = list(starkinfra.businessidentity.query(limit=1)) + for identity in identities: + print(identity) + print("Number of identities:", len(identities)) + + +class TestBusinessIdentityPage(TestCase): + + def test_success(self): + cursor = None + ids = [] + for _ in range(2): + identities, cursor = starkinfra.businessidentity.page(limit=2, cursor=cursor) + for identity in identities: + print(identity) + self.assertFalse(identity.id in ids) + ids.append(identity.id) + if cursor is None: + break + self.assertEqual(len(ids), 4) + + +class TestBusinessIdentityInfoGet(TestCase): + + def test_success(self): + identities = starkinfra.businessidentity.query(limit=3) + for identity in identities: + identity_id = identity.id + identity_new = starkinfra.businessidentity.get(identity_id) + self.assertEqual(identity_new.id, identity_id) + + +class TestBusinessIdentityUpdate(TestCase): + + def test_success(self): + identities = starkinfra.businessidentity.query(limit=1) + for identity in identities: + identity = starkinfra.businessidentity.update(id=identity.id, tags=identity.tags) + self.assertIsNotNone(identity.id) + + +if __name__ == '__main__': + main() diff --git a/tests/sdk/testBusinessIdentityFeedback.py b/tests/sdk/testBusinessIdentityFeedback.py new file mode 100644 index 0000000..8a057be --- /dev/null +++ b/tests/sdk/testBusinessIdentityFeedback.py @@ -0,0 +1,36 @@ +import starkinfra +from unittest import TestCase, main +from tests.utils.user import exampleProject + + +starkinfra.user = exampleProject + + +class TestBusinessIdentityFeedbackPost(TestCase): + + def test_success(self): + identities = list(starkinfra.businessidentity.query(limit=1)) + self.assertTrue(len(identities) > 0) + feedbacks = starkinfra.businessidentity.feedback.create([ + starkinfra.businessidentity.Feedback( + business_identity_id=identities[0].id, + option="negative", + session="qsa", + content="Partner divergent from the articles of incorporation", + ) + ]) + for feedback in feedbacks: + self.assertIsNotNone(feedback.id) + + +class TestBusinessIdentityFeedbackQuery(TestCase): + + def test_success(self): + feedbacks = list(starkinfra.businessidentity.feedback.query(limit=1)) + for feedback in feedbacks: + print(feedback) + print("Number of feedbacks:", len(feedbacks)) + + +if __name__ == '__main__': + main() diff --git a/tests/sdk/testBusinessIdentityLog.py b/tests/sdk/testBusinessIdentityLog.py new file mode 100644 index 0000000..2bde7b9 --- /dev/null +++ b/tests/sdk/testBusinessIdentityLog.py @@ -0,0 +1,25 @@ +import starkinfra +from unittest import TestCase, main +from tests.utils.user import exampleProject + +starkinfra.user = exampleProject + + +class TestBusinessIdentityLogQuery(TestCase): + + def test_success(self): + logs = starkinfra.businessidentity.log.query(limit=10) + for log in logs: + self.assertEqual(log.id, str(log.id)) + + +class TestBusinessIdentityLogGet(TestCase): + + def test_success(self): + logs = starkinfra.businessidentity.log.query(limit=1) + log = starkinfra.businessidentity.log.get(id=next(logs).id) + self.assertEqual(log.id, str(log.id)) + + +if __name__ == '__main__': + main() diff --git a/tests/utils/businessIdentity.py b/tests/utils/businessIdentity.py new file mode 100644 index 0000000..9bcbed1 --- /dev/null +++ b/tests/utils/businessIdentity.py @@ -0,0 +1,19 @@ +# coding=utf-8 +from copy import deepcopy +from starkinfra import BusinessIdentity + + +# A real CNPJ is required: the API looks the company up in the bureau and rejects +# it if no representatives are found, so a randomly generated tax ID would not work. +def _generateBusinessIdentity(): + return BusinessIdentity( + tax_id="20.018.183/0001-80", + tags=["test", "testing"], + ) + + +def generateExampleBusinessIdentityJson(n=1): + identities = [] + for _ in range(n): + identities.append(deepcopy(_generateBusinessIdentity())) + return identities From 049a33c60f503baefcd78655cc1fcc12008d8f6b Mon Sep 17 00:00:00 2001 From: Rafael Cabral Date: Fri, 12 Jun 2026 16:37:23 -0300 Subject: [PATCH 2/4] Remove business Identity feedback --- README.md | 36 ----- starkinfra/businessidentity/__init__.py | 2 - .../businessidentity/feedback/__feedback.py | 124 ------------------ .../businessidentity/feedback/__init__.py | 1 - tests/sdk/testBusinessIdentityFeedback.py | 36 ----- 5 files changed, 199 deletions(-) delete mode 100644 starkinfra/businessidentity/feedback/__feedback.py delete mode 100644 starkinfra/businessidentity/feedback/__init__.py delete mode 100644 tests/sdk/testBusinessIdentityFeedback.py diff --git a/README.md b/README.md index fc33fe9..6fe7eef 100644 --- a/README.md +++ b/README.md @@ -3521,42 +3521,6 @@ log = starkinfra.businessidentity.log.get("5155165527080960") print(log) ``` -### Create BusinessIdentity feedbacks - -You can register feedback (positive/negative) about sections of a business identity analysis. - -```python -import starkinfra - -feedbacks = starkinfra.businessidentity.feedback.create([ - starkinfra.businessidentity.Feedback( - business_identity_id="5155165527080960", - option="negative", - session="qsa", - content="Partner divergent from the articles of incorporation" - ) -]) - -for feedback in feedbacks: - print(feedback) -``` - -### Query BusinessIdentity feedbacks - -You can query multiple business identity feedbacks according to filters. - -```python -import starkinfra - -feedbacks = starkinfra.businessidentity.feedback.query( - limit=10, - business_identity_id="5155165527080960", -) - -for feedback in feedbacks: - print(feedback) -``` - ### Create BusinessAttachments You can create a BusinessAttachment to attach a document (e.g. articles of incorporation) to a specific BusinessIdentity. diff --git a/starkinfra/businessidentity/__init__.py b/starkinfra/businessidentity/__init__.py index f5d3719..d438e0c 100644 --- a/starkinfra/businessidentity/__init__.py +++ b/starkinfra/businessidentity/__init__.py @@ -1,5 +1,3 @@ from .__businessidentity import create, get, query, page, update, cancel from .log.__log import Log from . import log -from .feedback.__feedback import Feedback -from . import feedback diff --git a/starkinfra/businessidentity/feedback/__feedback.py b/starkinfra/businessidentity/feedback/__feedback.py deleted file mode 100644 index f3e180c..0000000 --- a/starkinfra/businessidentity/feedback/__feedback.py +++ /dev/null @@ -1,124 +0,0 @@ -from ...utils import rest -from starkcore.utils.resource import Resource -from starkcore.utils.checks import check_datetime, check_date -from starkcore.utils.api import api_json, from_api_json - - -# The feedback routes are nested under business-identity (POST/GET /business-identity/feedback). -# starkcore's endpoint() only nests "-log"/"-attempt", so we hit the path explicitly with raw requests. -_path = "business-identity/feedback" - - -class Feedback(Resource): - """# businessidentity.Feedback object - A businessidentity.Feedback registers an evaluation (positive/negative) about a section of - the analysis of a BusinessIdentity. When you initialize a Feedback, the entity will not be - automatically created in the Stark Infra API. The 'create' function sends the objects - to the Stark Infra API and returns the list of created objects. - ## Parameters (required): - - option [string]: feedback option. Options: "positive", "negative" - - session [string]: section of the analysis the feedback refers to. Options: "basicData", "qsa", "rules" - - business_identity_id [string]: unique id of the BusinessIdentity the feedback refers to. ex: "5656565656565656" - ## Parameters (optional): - - content [string, default None]: free text content of the feedback. ex: "Partner divergent from the articles of incorporation" - ## Attributes (return-only): - - id [string]: unique id returned when the Feedback is created. ex: "5656565656565656" - - created [datetime.datetime]: creation datetime for the Feedback. ex: datetime.datetime(2020, 3, 10, 10, 30, 0, 0) - - updated [datetime.datetime]: latest update datetime for the Feedback. ex: datetime.datetime(2020, 3, 10, 10, 30, 0, 0) - """ - - def __init__(self, option, session, business_identity_id, content=None, id=None, created=None, updated=None): - Resource.__init__(self, id=id) - - self.option = option - self.session = session - self.business_identity_id = business_identity_id - self.content = content - self.created = check_datetime(created) - self.updated = check_datetime(updated) - - -_resource = {"class": Feedback, "name": "BusinessIdentityFeedback"} - - -def create(feedbacks, user=None): - """# Create businessidentity.Feedbacks - Send a list of businessidentity.Feedback objects for creation at the Stark Infra API - ## Parameters (required): - - feedbacks [list of businessidentity.Feedback objects]: list of Feedback objects to be created in the API - ## Parameters (optional): - - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. - ## Return: - - list of businessidentity.Feedback objects with updated attributes - """ - payload = {"feedbacks": [api_json(feedback) for feedback in feedbacks]} - json = rest.post_raw(path=_path, payload=payload, user=user).json() - return [from_api_json(_resource, feedback) for feedback in json.get("feedbacks", [])] - - -def query(limit=None, after=None, before=None, ids=None, business_identity_id=None, user=None): - """# Retrieve businessidentity.Feedbacks - Receive a generator of businessidentity.Feedback objects previously created in the Stark Infra API - ## Parameters (optional): - - limit [integer, default None]: maximum number of objects to be retrieved. Unlimited if None. ex: 35 - - after [datetime.date or string, default None] date filter for objects created only after specified date. ex: datetime.date(2020, 3, 10) - - before [datetime.date or string, default None] date filter for objects created only before specified date. ex: datetime.date(2020, 3, 10) - - ids [list of strings, default None]: list of ids to filter retrieved objects. ex: ["5656565656565656", "4545454545454545"] - - business_identity_id [string, default None]: filter for feedbacks of a specific BusinessIdentity. ex: "5656565656565656" - - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. - ## Return: - - generator of businessidentity.Feedback objects with updated attributes - """ - cursor = None - while True: - feedbacks, cursor = page( - cursor=cursor, - limit=min(limit, 100) if limit else limit, - after=after, - before=before, - ids=ids, - business_identity_id=business_identity_id, - user=user, - ) - for feedback in feedbacks: - yield feedback - - if limit: - limit -= 100 - if limit <= 0: - break - - if not cursor: - break - - -def page(cursor=None, limit=None, after=None, before=None, ids=None, business_identity_id=None, user=None): - """# Retrieve paged businessidentity.Feedbacks - Receive a list of up to 100 businessidentity.Feedback objects previously created in the Stark Infra API and the cursor to the next page. - Use this function instead of query if you want to manually page your requests. - ## Parameters (optional): - - cursor [string, default None]: cursor returned on the previous page function call - - limit [integer, default 100]: maximum number of objects to be retrieved. It must be an integer between 1 and 100. ex: 50 - - after [datetime.date or string, default None] date filter for objects created only after specified date. ex: datetime.date(2020, 3, 10) - - before [datetime.date or string, default None] date filter for objects created only before specified date. ex: datetime.date(2020, 3, 10) - - ids [list of strings, default None]: list of ids to filter retrieved objects. ex: ["5656565656565656", "4545454545454545"] - - business_identity_id [string, default None]: filter for feedbacks of a specific BusinessIdentity. ex: "5656565656565656" - - user [Organization/Project object, default None]: Organization or Project object. Not necessary if starkinfra.user was set before function call. - ## Return: - - list of businessidentity.Feedback objects with updated attributes - - cursor to retrieve the next page of businessidentity.Feedback objects - """ - json = rest.get_raw( - path=_path, - query={ - "cursor": cursor, - "limit": limit, - "after": check_date(after), - "before": check_date(before), - "ids": ids, - "business_identity_id": business_identity_id, - }, - user=user, - ).json() - feedbacks = [from_api_json(_resource, feedback) for feedback in json.get("feedbacks", [])] - return feedbacks, json.get("cursor") diff --git a/starkinfra/businessidentity/feedback/__init__.py b/starkinfra/businessidentity/feedback/__init__.py deleted file mode 100644 index 60d8030..0000000 --- a/starkinfra/businessidentity/feedback/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .__feedback import create, query, page diff --git a/tests/sdk/testBusinessIdentityFeedback.py b/tests/sdk/testBusinessIdentityFeedback.py deleted file mode 100644 index 8a057be..0000000 --- a/tests/sdk/testBusinessIdentityFeedback.py +++ /dev/null @@ -1,36 +0,0 @@ -import starkinfra -from unittest import TestCase, main -from tests.utils.user import exampleProject - - -starkinfra.user = exampleProject - - -class TestBusinessIdentityFeedbackPost(TestCase): - - def test_success(self): - identities = list(starkinfra.businessidentity.query(limit=1)) - self.assertTrue(len(identities) > 0) - feedbacks = starkinfra.businessidentity.feedback.create([ - starkinfra.businessidentity.Feedback( - business_identity_id=identities[0].id, - option="negative", - session="qsa", - content="Partner divergent from the articles of incorporation", - ) - ]) - for feedback in feedbacks: - self.assertIsNotNone(feedback.id) - - -class TestBusinessIdentityFeedbackQuery(TestCase): - - def test_success(self): - feedbacks = list(starkinfra.businessidentity.feedback.query(limit=1)) - for feedback in feedbacks: - print(feedback) - print("Number of feedbacks:", len(feedbacks)) - - -if __name__ == '__main__': - main() From 23094ba45e52e2ede3601699195c7a7fe01c1fa2 Mon Sep 17 00:00:00 2001 From: Rafael Cabral Date: Fri, 12 Jun 2026 16:54:38 -0300 Subject: [PATCH 3/4] Add webhook event --- README.md | 4 ++++ starkinfra/event/__event.py | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6fe7eef..5147020 100644 --- a/README.md +++ b/README.md @@ -3631,6 +3631,7 @@ webhook = starkinfra.webhook.create( url="https://webhook.site/dd784f26-1d6a-4ca6-81cb-fda0267761ec", subscriptions=[ "credit-note", + "business-identity", "issuing-card", "issuing-invoice", "issuing-purchase", "pix-request.in", "pix-request.out", "pix-reversal.in", "pix-reversal.out", "pix-claim", "pix-key", "pix-chargeback", "pix-infraction", ], @@ -3708,6 +3709,9 @@ elif "issuing-purchase" in event.subscription: elif "credit-note" in event.subscription: print(event.log.note) + +elif "business-identity" in event.subscription: + print(event.log.identity) ``` ### Query webhook events diff --git a/starkinfra/event/__event.py b/starkinfra/event/__event.py index d9cb466..f888ef1 100644 --- a/starkinfra/event/__event.py +++ b/starkinfra/event/__event.py @@ -14,6 +14,7 @@ from ..issuingcard.log.__log import _resource as _issuingcard_log_resource from ..issuinginvoice.log.__log import _resource as _issuinginvoice_log_resource from ..issuingpurchase.log.__log import _resource as _issuingpurchase_log_resource +from ..businessidentity.log.__log import _resource as _businessidentity_log_resource _resource_by_subscription = { @@ -30,6 +31,7 @@ "issuing-invoice": _issuinginvoice_log_resource, "issuing-purchase": _issuingpurchase_log_resource, "credit-note": _creditnote_log_resource, + "business-identity": _businessidentity_log_resource, } @@ -43,7 +45,7 @@ class Event(Resource): - log [Log]: a Log object from one of the subscribed services (PixRequestLog, PixReversalLog) - created [datetime.datetime]: creation datetime for the notification Event. ex: datetime.datetime(2020, 3, 10, 10, 30, 0, 0) - is_delivered [bool]: true if the Event has been successfully delivered to the user url. ex: False - - subscription [string]: service that triggered this Event. Options: "pix-request.in", "pix-request.out", "pix-reversal.in", "pix-reversal.out", "pix-key", "pix-claim", "pix-infraction", "pix-chargeback", "issuing-card", "issuing-invoice", "issuing-purchase", "credit-note" + - subscription [string]: service that triggered this Event. Options: "pix-request.in", "pix-request.out", "pix-reversal.in", "pix-reversal.out", "pix-key", "pix-claim", "pix-infraction", "pix-chargeback", "issuing-card", "issuing-invoice", "issuing-purchase", "credit-note", "business-identity" - workspace_id [string]: ID of the Workspace that generated this Event. Mostly used when multiple Workspaces have Webhooks registered to the same endpoint. ex: "4545454545454545" """ From 84b4485b72496054c4632e66186845320c72c37a Mon Sep 17 00:00:00 2001 From: Rafael Cabral Date: Fri, 12 Jun 2026 17:49:35 -0300 Subject: [PATCH 4/4] Refactor BusinessAttachment to use business_identity_id instead of identity_id; update related documentation and tests accordingly. --- README.md | 2 +- starkinfra/businessattachment/__businessattachment.py | 9 ++++----- starkinfra/businessidentity/__businessidentity.py | 8 +------- tests/sdk/testBusinessAttachment.py | 2 +- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 5147020..881f378 100644 --- a/README.md +++ b/README.md @@ -3533,7 +3533,7 @@ attachments = starkinfra.businessattachment.create([ starkinfra.BusinessAttachment( name="articles-of-incorporation.pdf", content="data:application/pdf;base64,JVBERi0xLjQ...", - identity_id="5155165527080960", + business_identity_id="5155165527080960", tags=["doc-principal"] ) ]) diff --git a/starkinfra/businessattachment/__businessattachment.py b/starkinfra/businessattachment/__businessattachment.py index 6b1f670..7d3723f 100644 --- a/starkinfra/businessattachment/__businessattachment.py +++ b/starkinfra/businessattachment/__businessattachment.py @@ -15,7 +15,7 @@ class BusinessAttachment(Resource): ## Parameters (required): - name [string]: name of the document. Must be unique among the identity's "created" attachments. ex: "articles-of-incorporation.pdf" - content [string]: Base64 data url of the document. ex: data:application/pdf;base64,JVBERi0xLjQ... - - identity_id [string]: unique id of the BusinessIdentity this attachment belongs to. Sent as "identityId" on creation and returned as "businessIdentityId". ex: "5656565656565656" + - business_identity_id [string]: unique id of the BusinessIdentity this attachment belongs to. ex: "5656565656565656" ## Parameters (optional): - content_type [string, default None]: content MIME type. This parameter is required as input only. ex: "application/pdf", "image/png" or "image/jpeg" - tags [list of strings, default []]: list of strings for reference when searching for BusinessAttachments. ex: ["doc-principal"] @@ -27,14 +27,13 @@ class BusinessAttachment(Resource): - updated [datetime.datetime]: latest update datetime for the BusinessAttachment. ex: datetime.datetime(2020, 3, 10, 10, 30, 0, 0) """ - def __init__(self, name, content, identity_id=None, content_type=None, tags=None, id=None, - business_identity_id=None, attachment_id=None, status=None, created=None, updated=None): + def __init__(self, name, content, business_identity_id, content_type=None, tags=None, id=None, attachment_id=None, + status=None, created=None, updated=None): Resource.__init__(self, id=id) self.name = name self.content = content - # the API expects "identityId" on creation but returns "businessIdentityId"; expose a single attribute - self.identity_id = identity_id if identity_id is not None else business_identity_id + self.business_identity_id = business_identity_id self.tags = tags self.attachment_id = attachment_id self.status = status diff --git a/starkinfra/businessidentity/__businessidentity.py b/starkinfra/businessidentity/__businessidentity.py index 7ba8ec5..7d65d25 100644 --- a/starkinfra/businessidentity/__businessidentity.py +++ b/starkinfra/businessidentity/__businessidentity.py @@ -1,7 +1,6 @@ from ..utils import rest from starkcore.utils.resource import Resource from starkcore.utils.checks import check_datetime, check_date -from starkcore.utils.api import api_json, from_api_json class BusinessIdentity(Resource): @@ -64,12 +63,7 @@ def create(identities, user=None): ## Return: - list of BusinessIdentity objects with updated attributes """ - # the create route uses a non-standard request wrapper ("businessIdentities") while the - # response keeps the conventional one ("identities"), so we build the request manually. - payload = {"businessIdentities": [api_json(identity) for identity in identities]} - json = rest.post_raw(path="business-identity", payload=payload, user=user).json() - entities = json.get("identities", json.get("businessIdentities", [])) - return [from_api_json(_resource, identity) for identity in entities] + return rest.post_multi(resource=_resource, entities=identities, user=user) def get(id, user=None): diff --git a/tests/sdk/testBusinessAttachment.py b/tests/sdk/testBusinessAttachment.py index 6247ab5..ad3dfc5 100644 --- a/tests/sdk/testBusinessAttachment.py +++ b/tests/sdk/testBusinessAttachment.py @@ -13,7 +13,7 @@ def test_success(self): self.assertTrue(len(identities) > 0) attachments = starkinfra.businessattachment.create([ starkinfra.BusinessAttachment( - identity_id=identities[0].id, + business_identity_id=identities[0].id, name="articles-of-incorporation.png", content="iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==", content_type="image/png",