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..881f378 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,209 @@ 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 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...", + business_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 @@ -3426,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", ], @@ -3503,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/__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..7d3723f --- /dev/null +++ b/starkinfra/businessattachment/__businessattachment.py @@ -0,0 +1,148 @@ +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... + - 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"] + ## 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, 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 + self.business_identity_id = 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..7d65d25 --- /dev/null +++ b/starkinfra/businessidentity/__businessidentity.py @@ -0,0 +1,172 @@ +from ..utils import rest +from starkcore.utils.resource import Resource +from starkcore.utils.checks import check_datetime, check_date + + +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 + """ + return rest.post_multi(resource=_resource, entities=identities, user=user) + + +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..d438e0c --- /dev/null +++ b/starkinfra/businessidentity/__init__.py @@ -0,0 +1,3 @@ +from .__businessidentity import create, get, query, page, update, cancel +from .log.__log import Log +from . import log 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/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" """ diff --git a/tests/sdk/testBusinessAttachment.py b/tests/sdk/testBusinessAttachment.py new file mode 100644 index 0000000..ad3dfc5 --- /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( + business_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/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