diff --git a/connect/models/__init__.py b/connect/models/__init__.py index 8a78ae8..8213d6f 100644 --- a/connect/models/__init__.py +++ b/connect/models/__init__.py @@ -16,9 +16,10 @@ from .marketplace import Activation, Agreement, AgreementStats, Contract, Marketplace from .parameters import Constraints, Param, ValueChoice from .product import CustomerUiSettings, Document, DownloadLink, Item, Product, \ - ProductConfiguration, Renewal + ProductCategory, ProductConfiguration, ProductFamily, ProductStats, ProductStatsInfo, Renewal from .server_error_response import ServerErrorResponse -from .tier_config import Template, TierAccount, TierAccounts, TierConfig, TierConfigRequest +from .tier_config import Configuration, Template, TierAccount, TierAccounts, TierConfig, \ + TierConfigRequest from .usage import UsageFile, UsageListing, UsageRecord, UsageRecords __all__ = [ @@ -30,6 +31,7 @@ 'Asset', 'BaseModel', 'Company', + 'Configuration', 'Connection', 'Constraints', 'Contact', @@ -52,7 +54,11 @@ 'Param', 'PhoneNumber', 'Product', + 'ProductCategory', 'ProductConfiguration', + 'ProductFamily', + 'ProductStats', + 'ProductStatsInfo', 'Renewal', 'ServerErrorResponse', 'Template', diff --git a/connect/models/event.py b/connect/models/event.py index 05c53cc..17ae9ec 100644 --- a/connect/models/event.py +++ b/connect/models/event.py @@ -42,3 +42,21 @@ class Events(BaseModel): updated = None # type: EventInfo """ (:py:class:`.EventInfo`) Update event. """ + + approved = None # type: EventInfo + """ (:py:class:`.EventInfo`) Approve event. """ + + uploaded = None # type: EventInfo + """ (:py:class:`.EventInfo`) Uploaded event. """ + + submitted = None # type: EventInfo + """ (:py:class:`.EventInfo`) Submit event. """ + + accepted = None # type: EventInfo + """ (:py:class:`.EventInfo`) Accept event. """ + + rejected = None # type: EventInfo + """ (:py:class:`.EventInfo`) Reject event. """ + + closed = None # type: EventInfo + """ (:py:class:`.EventInfo`) Close event. """ diff --git a/connect/models/parameters.py b/connect/models/parameters.py index 3e41e2a..9b15324 100644 --- a/connect/models/parameters.py +++ b/connect/models/parameters.py @@ -5,6 +5,7 @@ from typing import List, Optional +import connect.models from .base import BaseModel from connect.models.schemas import ValueChoiceSchema, ConstraintsSchema, ParamSchema @@ -35,6 +36,9 @@ class Constraints(BaseModel): choices = None # type: List[ValueChoice] """ (List[:py:class:`.ValueChoice`]) Parameter value choices. """ + unique = None # type: bool + """ (bool) Is the constraint unique? """ + class Param(BaseModel): """ Parameters are used in product and asset definitions. """ @@ -59,10 +63,8 @@ class Param(BaseModel): value_choice = None # type: Optional[List[str]] """ (List[str]|None) Available choices for parameter. """ - value_choices = None # type: Optional[List[ValueChoice]] - """ (List[str]|None) Available dropdown choices for parameter. """ - # Undocumented fields (they appear in PHP SDK) + title = None # type: Optional[str] """ (str|None) Title for parameter. """ @@ -71,3 +73,15 @@ class Param(BaseModel): constraints = None # type: Optional[Constraints] """ (:py:class:`.Constraints` | None) Parameter constraints. """ + + value_choices = None # type: Optional[List[ValueChoice]] + """ (List[str]|None) Available dropdown choices for parameter. """ + + phase = None # type: Optional[str] + """ (str|None) Param phase. """ + + events = None # type: Optional[connect.models.Events] + """ (:py:class:`.Events` | None) Events. """ + + marketplace = None # type: Optional[connect.models.Marketplace] + """ (:py:class:`.Marketplace` | None) Marketplace. """ diff --git a/connect/models/product.py b/connect/models/product.py index 0705c5a..0341138 100644 --- a/connect/models/product.py +++ b/connect/models/product.py @@ -6,9 +6,11 @@ import datetime from typing import List, Optional, Union +import connect.models from .base import BaseModel -from connect.models.schemas import ProductConfigurationSchema, DownloadLinkSchema, DocumentSchema,\ - CustomerUiSettingsSchema, ProductSchema, RenewalSchema, ItemSchema +from connect.models.schemas import ProductConfigurationSchema, DownloadLinkSchema, DocumentSchema, \ + CustomerUiSettingsSchema, ProductSchema, RenewalSchema, ItemSchema, ProductFamilySchema, \ + ProductCategorySchema, ProductStatsInfoSchema, ProductStatsSchema class ProductConfiguration(BaseModel): @@ -34,6 +36,9 @@ class DownloadLink(BaseModel): url = None # type: str """ (str) Link URL. """ + visible_for = None # title: str + """ (str) Link visibility. One of: admin, user. """ + class Document(BaseModel): """ Document for a product. """ @@ -46,9 +51,6 @@ class Document(BaseModel): url = None # title: str """ (str) Document URL. """ - visible_for = None # title: str - """ (str) Document visibility. One of: admin, user. """ - class CustomerUiSettings(BaseModel): """ Customer Ui Settings for a product. """ @@ -68,6 +70,58 @@ class CustomerUiSettings(BaseModel): """ (List[:py:class:`.Document`]) Documents. """ +class ProductFamily(BaseModel): + """ Represents a family of products """ + + _schema = ProductFamilySchema() + + name = None # type: str + """ (str) Family name. """ + + +class ProductCategory(BaseModel): + """ Represents a product category. """ + + _schema = ProductCategorySchema() + + name = None # type: str + """ (str) Category name. """ + + parent = None # type: Optional[ProductCategory] + """ (:py:class:`.ProductCategory` | None) Reference to parent category. """ + + children = None # type: Optional[List[ProductCategory]] + """ (List[:py:class:`.ProductCategory`] | None) List of children categories. """ + + family = None # type: Optional[ProductFamily] + """ (:py:class:`.ProductFamily` | None) Product family. """ + + +class ProductStatsInfo(BaseModel): + _schema = ProductStatsInfoSchema() + + distribution = None # type: int + """ (int) Number of distributions related to the product. """ + + sourcing = None # type: int + """ (int) Number of sourcings related to the product. """ + + +class ProductStats(BaseModel): + """ Statistics of product use. """ + + _schema = ProductStatsSchema() + + listing = None # type: int + """ (int) Number of listings (direct use of product by provider). """ + + agreements = None # type: ProductStatsInfo + """ (:py:class:`.ProductStatsInfo`) Agreements related to the product. """ + + contracts = None # type: ProductStatsInfo + """ (:py:class:`.ProductStatsInfo`) Contracts related to the product """ + + class Product(BaseModel): """ Represents basic marketing information about salable items, parameters, configurations, latest published version and connections. @@ -94,12 +148,29 @@ class Product(BaseModel): version = None # type: int """ (int) Version of product. """ + published_at = None # type: Optional[datetime.datetime] + """ (datetime.datetime) Date of publishing. """ + configurations = None # type: ProductConfiguration """ (:py:class:`.ProductConfiguration`) Product configuration. """ customer_ui_settings = None # type: CustomerUiSettings """ (:py:class:`.CustomerUiSettings`) Customer Ui Settings. """ + category = None # type: Optional[ProductCategory] + """ (:py:class:`.ProductCategory` | None) Reference to ProductCategory Object. """ + + owner = None # type: Optional[connect.models.Company] + """ (:py:class:`.Company` | None) """ + + latest = None # type: Optional[bool] + """ (bool|None) true if version is latest or for master versions without versions, + false otherwise. + """ + + stats = None # type: Optional[ProductStats] + """ (:py:class:``.ProductStats) Statistics of product use, depends on account of callee. """ + class Renewal(BaseModel): """ Item renewal data. """ @@ -138,10 +209,27 @@ class Item(BaseModel): (empty for all other types). """ + params = None # type: List[connect.models.Param] + """ (List[:py:class:`.Param` | None] List of Item and Item x Marketplace Configuration Phase + Parameter Context-Bound Object + """ + + # Undocumented fields (they appear in PHP SDK) + + display_name = None # type: str + """ (str) Display name. """ + global_id = None # type: str """ (str) Global id. """ - # Undocumented fields (they appear in PHP SDK) + item_type = None # type: str + """ (str) Item type. """ period = None # type: str """ (str) Period. """ + + type = None # type: str + """ (str) Type. """ + + name = None # type: str + """ (str) Name. """ diff --git a/connect/models/schemas.py b/connect/models/schemas.py index e73c6ef..c4782f9 100644 --- a/connect/models/schemas.py +++ b/connect/models/schemas.py @@ -99,6 +99,7 @@ class ConstraintsSchema(BaseSchema): hidden = fields.Bool() required = fields.Bool() choices = fields.Nested(ValueChoiceSchema, many=True) + unique = fields.Bool() @post_load def make_object(self, data): @@ -109,7 +110,6 @@ def make_object(self, data): class DocumentSchema(BaseSchema): title = fields.Str() url = fields.Str() - visible_for = fields.Str() @post_load def make_object(self, data): @@ -120,6 +120,7 @@ def make_object(self, data): class DownloadLinkSchema(BaseSchema): title = fields.Str() url = fields.Str() + visible_for = fields.Str() @post_load def make_object(self, data): @@ -152,6 +153,12 @@ class EventsSchema(BaseSchema): pended = fields.Nested(EventInfoSchema) validated = fields.Nested(EventInfoSchema) updated = fields.Nested(EventInfoSchema) + approved = fields.Nested(EventInfoSchema) + uploaded = fields.Nested(EventInfoSchema) + submitted = fields.Nested(EventInfoSchema) + accepted = fields.Nested(EventInfoSchema) + rejected = fields.Nested(EventInfoSchema) + closed = fields.Nested(EventInfoSchema) @post_load def make_object(self, data): @@ -234,20 +241,6 @@ def _deserialize(self, value, attr, obj, **kwargs): raise ValueError({attr: [u'Not a valid int, float or string.']}) -class ItemSchema(BaseSchema): - mpn = fields.Str() - quantity = QuantityField() - old_quantity = QuantityField(allow_none=True) - renewal = fields.Nested(RenewalSchema, allow_none=True) - global_id = fields.Str() - period = fields.Str() - - @post_load - def make_object(self, data): - from connect.models import Item - return Item(**data) - - class MarketplaceSchema(BaseSchema): name = fields.Str() description = fields.Str() @@ -263,6 +256,48 @@ def make_object(self, data): return Marketplace(**data) +class ParamSchema(BaseSchema): + name = fields.Str() + description = fields.Str() + type = fields.Str() + value = fields.Str(allow_none=True) + value_error = fields.Str(allow_none=True) + value_choice = fields.Str(many=True, allow_none=True) + + # Undocumented fields (they appear in PHP SDK) + title = fields.Str(allow_none=True) + scope = fields.Str(allow_none=True) + constraints = fields.Nested(ConstraintsSchema, allow_none=True) + value_choices = fields.Nested(ValueChoiceSchema, many=True, allow_none=True) + phase = fields.Str(allow_none=True) + events = fields.Nested(EventsSchema, allow_none=True) + marketplace = fields.Nested(MarketplaceSchema, allow_none=True) + + @post_load + def make_object(self, data): + from connect.models import Param + return Param(**data) + + +class ItemSchema(BaseSchema): + mpn = fields.Str() + quantity = QuantityField() + old_quantity = QuantityField(allow_none=True) + renewal = fields.Nested(RenewalSchema, allow_none=True) + params = fields.Nested(ParamSchema, many=True, allow_none=True) + display_name = fields.Str(allow_none=True) + global_id = fields.Str(allow_none=True) + item_type = fields.Str(allow_none=True) + period = fields.Str(allow_none=True) + type = fields.Str(allow_none=True) + name = fields.Str(allow_none=True) + + @post_load + def make_object(self, data): + from connect.models import Item + return Item(**data) + + class AgreementSchema(BaseSchema): type = fields.Str() title = fields.Str() @@ -331,24 +366,46 @@ def make_object(self, data): return CustomerUiSettings(**data) -class ParamSchema(BaseSchema): +class ProductFamilySchema(BaseSchema): name = fields.Str() - description = fields.Str() - type = fields.Str() - value = fields.Str(allow_none=True) - value_error = fields.Str(allow_none=True) - value_choice = fields.Str(many=True, allow_none=True) - value_choices = fields.Nested(ValueChoiceSchema, many=True, allow_none=True) - # Undocumented fields (they appear in PHP SDK) - title = fields.Str(allow_none=True) - scope = fields.Str(allow_none=True) - constraints = fields.Nested(ConstraintsSchema, allow_none=True) + @post_load + def make_object(self, data): + from connect.models import ProductFamily + return ProductFamily(**data) + + +class ProductCategorySchema(BaseSchema): + name = fields.Str() + parent = fields.Nested('ProductCategorySchema', allow_none=True) + children = fields.Nested('ProductCategorySchema', many=True, allow_none=True) + family = fields.Nested(ProductFamilySchema, allow_none=True) @post_load def make_object(self, data): - from connect.models import Param - return Param(**data) + from connect.models import ProductCategory + return ProductCategory(**data) + + +class ProductStatsInfoSchema(BaseSchema): + distribution = fields.Int() + sourcing = fields.Int() + + @post_load + def make_object(self, data): + from connect.models import ProductStatsInfo + return ProductStatsInfo(**data) + + +class ProductStatsSchema(BaseSchema): + listing = fields.Int() + agreements = fields.Nested(ProductStatsInfoSchema) + contracts = fields.Nested(ProductStatsInfoSchema) + + @post_load + def make_object(self, data): + from connect.models import ProductStats + return ProductStats(**data) class ProductSchema(BaseSchema): @@ -357,8 +414,13 @@ class ProductSchema(BaseSchema): short_description = fields.Str() detailed_description = fields.Str() version = fields.Int() + published_at = fields.DateTime(allow_none=True) configurations = fields.Nested(ProductConfigurationSchema) customer_ui_settings = fields.Nested(CustomerUiSettingsSchema) + category = fields.Nested(ProductCategorySchema, allow_none=True) + owner = fields.Nested(CompanySchema, allow_none=True) + latest = fields.Bool(allow_none=True) + stats = fields.Nested(ProductStatsSchema, allow_none=True) @post_load def make_object(self, data): @@ -378,6 +440,7 @@ def make_object(self, data): class TemplateSchema(BaseSchema): + name = fields.Str() representation = fields.Str() @post_load @@ -386,6 +449,15 @@ def make_object(self, data): return Template(**data) +class ConfigurationSchema(BaseSchema): + params = fields.Nested(ParamSchema, many=True) + + @post_load + def make_object(self, data): + from connect.models import Configuration + return Configuration(**data) + + class TierAccountSchema(BaseSchema): name = fields.Str() contact_info = fields.Nested(ContactInfoSchema) @@ -464,11 +536,14 @@ class TierConfigSchema(BaseSchema): account = fields.Nested(TierAccountSchema) product = fields.Nested(ProductSchema) tier_level = fields.Int() - connection = fields.Nested(ConnectionSchema) - events = fields.Nested(EventsSchema, allow_none=True) params = fields.Nested(ParamSchema, many=True) - template = fields.Nested(TemplateSchema) + connection = fields.Nested(ConnectionSchema) open_request = fields.Nested(BaseSchema, allow_none=True) + template = fields.Nested(TemplateSchema) + contract = fields.Nested(ContractSchema) + marketplace = fields.Nested(MarketplaceSchema) + configuration = fields.Nested(ConfigurationSchema, allow_none=True) + events = fields.Nested(EventsSchema, allow_none=True) @post_load def make_object(self, data): @@ -480,13 +555,18 @@ class TierConfigRequestSchema(BaseSchema): type = fields.Str() status = fields.Str() configuration = fields.Nested(TierConfigSchema) - events = fields.Nested(EventsSchema, allow_none=True) + parent_configuration = fields.Nested(TierConfigSchema) + account = fields.Nested(TierAccountSchema) + product = fields.Nested(ProductSchema) + tier_level = fields.Int() params = fields.Nested(ParamSchema, many=True) + environment = fields.Str() assignee = fields.Nested(UserSchema, allow_none=True) template = fields.Nested(TemplateSchema, allow_none=True) reason = fields.Str(allow_none=True) activation = fields.Nested(ActivationSchema, allow_none=True) notes = fields.Str(allow_none=True) + events = fields.Nested(EventsSchema, allow_none=True) @post_load def make_object(self, data): @@ -522,16 +602,7 @@ class UsageFileSchema(BaseSchema): rejection_note = fields.Str() error_details = fields.Str() records = fields.Nested(UsageRecordsSchema) - uploaded_by = fields.Str() - uploaded_at = fields.Str() - submitted_by = fields.Str() - submitted_at = fields.Str() - accepted_by = fields.Str() - accepted_at = fields.Str() - rejected_by = fields.Str() - rejected_at = fields.Str() - closed_by = fields.Str() - closed_at = fields.Str() + events = fields.Nested(EventsSchema) @post_load def make_object(self, data): diff --git a/connect/models/tier_config.py b/connect/models/tier_config.py index 2db506b..a4ddcba 100644 --- a/connect/models/tier_config.py +++ b/connect/models/tier_config.py @@ -5,6 +5,7 @@ from typing import Optional, List +import connect.models from .base import BaseModel from .company import User from .connection import Connection @@ -14,7 +15,7 @@ from .parameters import Param from .product import Product from connect.models.schemas import TemplateSchema, TierAccountSchema, \ - TierAccountsSchema, TierConfigSchema, TierConfigRequestSchema + TierAccountsSchema, TierConfigSchema, TierConfigRequestSchema, ConfigurationSchema class TierAccount(BaseModel): @@ -55,10 +56,30 @@ class Template(BaseModel): _schema = TemplateSchema() + name = None # type: str + """ (str) Template name. """ + representation = None # type: str """ (str) Template representation. """ +class Configuration(BaseModel): + """ Configuration Phase Parameter Context-Bound Data Object. + + To be used in parameter contexts: + + - Asset. + - Fulfillment Request. + - TierConfig. + - TierConfig Requests. + """ + + _schema = ConfigurationSchema() + + params = None # type: List[Param] + """ (List[:py:class:`.Param`]) """ + + class TierConfig(BaseModel): """ Full representation of Tier object. """ @@ -78,23 +99,34 @@ class TierConfig(BaseModel): tier_level = None # type: int """ (int) Tier level for product from customer perspective. """ - connection = None # type: Connection - """ (:py:class:`.Connection`) Reference to Connection Object. """ - - events = None # type: Optional[Events] - """ (:py:class:`.Events` | None) Tier Config events. """ - params = None # type: List[Param] """ (List[:py:class:`.Param`]) List of TC parameter data objects as in Asset Object extended with unfilled parameters from product. """ - template = None # type: Template - """ (:py:class:`.Template`) Template Object. """ + connection = None # type: Connection + """ (:py:class:`.Connection`) Reference to Connection Object. """ open_request = None # type: Optional[BaseModel] """ (:py:class:`.BaseModel` | None) Reference to TCR. """ + template = None # type: Template + """ (:py:class:`.Template`) Template Object. """ + + contract = None # type: connect.models.Contract + """ (:py:class:`.Contract`) Contract Object reference. """ + + marketplace = None # type: connect.models.Marketplace + """ (:py:class:`.Marketplace`) Marketplace Object reference. """ + + configuration = None # type: Configuration + """ (:py:class:`.Configuration`) List of Product and Marketplace Configuration Phase Parameter + Context-Bound Object. + """ + + events = None # type: Optional[Events] + """ (:py:class:`.Events` | None) Tier Config events. """ + @classmethod def get(cls, account_id, product_id, config=None): """ @@ -148,16 +180,28 @@ class TierConfigRequest(BaseModel): """ (str) TCR current status. One of: tiers_setup, pending, inquiring, approved, failed. """ configuration = None # type: TierConfig - """ (:py:class:`.TierConfig`) Full representation of Tier Configuration Object. """ + """ (:py:class:`.TierConfig`) Full representation of TierConfig Object. """ - events = None # type: Optional[Events] - """ (:py:class:`.Events` | None) Tier Config request Events. """ + parent_configuration = None # type: Optional[TierConfig] + """ (:py:class:`.TierConfig` | None) Full representation of parent TierConfig. """ + + account = None # type: TierAccount + """ (:py:class:`.TierAccount`) Reference object to TierAccount. """ + + product = None # type: Product + """ (:py:class:`.Product`) Reference object to product (application). """ + + tier_level = None # type: int + """ (int) Tier level for product from customer perspective (1 or 2). """ params = None # type: List[Param] """ (List[:py:class:`.Param`]) List of parameter data objects as in Asset Object. Params can be modified only in Pending state. """ + environment = None # type: str + """ (str) TCR environment (test, prod or preview) """ + assignee = None # type: Optional[User] """ (:py:class:`.User` | None) TCR environment. One of: test, prod, preview. """ @@ -175,6 +219,9 @@ class TierConfigRequest(BaseModel): notes = None # type: Optional[str] """ (str) TCR pending notes. Notes can be modified only in Pending state. """ + events = None # type: Optional[Events] + """ (:py:class:`.Events` | None) Tier Config request Events. """ + def get_param_by_id(self, id_): """ Get a Tier Config Request parameter. diff --git a/connect/models/usage.py b/connect/models/usage.py index 322aa40..8033828 100644 --- a/connect/models/usage.py +++ b/connect/models/usage.py @@ -2,7 +2,7 @@ # This file is part of the Ingram Micro Cloud Blue Connect SDK. # Copyright (c) 2019 Ingram Micro. All Rights Reserved. - +from connect.models import Events from .base import BaseModel from .company import Company from .marketplace import Contract, Marketplace @@ -88,35 +88,8 @@ class UsageFile(BaseModel): records = None # type: UsageRecords """ (:py:class:`.UsageRecords`) UsageRecords Object. """ - uploaded_by = None # type: str - """ (str) User Id who uploaded the file. """ - - uploaded_at = None # type: str - """ (str) Usage file upload time. """ - - submitted_by = None # type: str - """ (str) User Id, who submitted the usage record to Provider. """ - - submitted_at = None # type: str - """ (str) User Id, who submitted the usage record to Provider. """ - - accepted_by = None # type: str - """ (str) User Id, who accepted the usage file as provider. """ - - accepted_at = None # type: str - """ (str) Usage file acceptance time. """ - - rejected_by = None # type: str - """ (str) User Id, who rejected the usage file as provider. """ - - rejected_at = None # type: str - """ (str) Usage file rejection time. """ - - closed_by = None # type: str - """ (str) User Id, who billed the usage file as provider. """ - - closed_at = None # type: str - """ (str) Usage file billing time. """ + events = None # type: Events + """ (:py:class:`.Events`) Events occured on file. """ class UsageListing(BaseModel): diff --git a/connect/resources/fulfillment_automation.py b/connect/resources/fulfillment_automation.py index 1a40826..d7b93b8 100644 --- a/connect/resources/fulfillment_automation.py +++ b/connect/resources/fulfillment_automation.py @@ -126,6 +126,17 @@ def dispatch(self, request): .format(request.id, ex)) return '' + def create_request(self, request): + """ Creates a new request. Using this method requires a provider token used as api_key + in the Config. + + :param Fulfillment request: + :return: The created request. + :rtype: Fulfillment + """ + response, _ = self._api.post(json=request.json) + return Fulfillment.deserialize(response) + @deprecated(deprecated_in='16.0', details='Use ``TierConfig.get`` instead.') def get_tier_config(self, tier_id, product_id): """ diff --git a/tests/data/response_tier_config_request.json b/tests/data/response_tier_config_request.json index b66d915..d07004e 100644 --- a/tests/data/response_tier_config_request.json +++ b/tests/data/response_tier_config_request.json @@ -95,4 +95,4 @@ "link": "http://example.com" } } -] \ No newline at end of file +] diff --git a/tests/data/response_usage_file.json b/tests/data/response_usage_file.json index 1689979..24d113c 100644 --- a/tests/data/response_usage_file.json +++ b/tests/data/response_usage_file.json @@ -38,15 +38,37 @@ "valid": 56, "invalid": 0 }, - "uploaded_by": "rahul.mondal@ingrammicro.com", - "uploaded_at": "2018-11-21T11:10:29+00:00", - "submitted_by": "rahul.mondal@ingrammicro.com", - "submitted_at": "2018-11-21T11:10:29+00:00", - "accepted_by": "admin@a1provider.com", - "accepted_at": "2018-11-21T11:10:29+00:00", - "rejected_by": "admin@a1provider.com", - "rejected_at": "2018-11-21T11:10:29+00:00", - "closed_by": "admin@a1provider.com", - "closed_at": "2018-11-21T11:10:29+00:00" + "events": { + "uploaded": { + "by": { + "name": "rahul.mondal@ingrammicro.com" + }, + "at": "2018-11-21T11:10:29+00:00" + }, + "submitted": { + "by": { + "name": "rahul.mondal@ingrammicro.com" + }, + "at": "2018-11-21T11:10:29+00:00" + }, + "accepted": { + "by": { + "name": "admin@a1provider.com" + }, + "at": "2018-11-21T11:10:29+00:00" + }, + "rejected": { + "by": { + "name": "admin@a1provider.com" + }, + "at": "2018-11-21T11:10:29+00:00" + }, + "closed": { + "by": { + "name": "admin@a1provider.com" + }, + "at": "2018-11-21T11:10:29+00:00" + } + } } ] diff --git a/tests/test_usage_file.py b/tests/test_usage_file.py index 3cdcec6..07989a3 100644 --- a/tests/test_usage_file.py +++ b/tests/test_usage_file.py @@ -4,6 +4,7 @@ # Copyright (c) 2019 Ingram Micro. All Rights Reserved. import os +from datetime import datetime import pytest from mock import patch, MagicMock @@ -80,16 +81,16 @@ def test_create_resource(): assert records.valid == 56 assert records.invalid == 0 - assert request.uploaded_by == 'rahul.mondal@ingrammicro.com' - assert request.uploaded_at == '2018-11-21T11:10:29+00:00' - assert request.submitted_by == 'rahul.mondal@ingrammicro.com' - assert request.submitted_at == '2018-11-21T11:10:29+00:00' - assert request.accepted_by == 'admin@a1provider.com' - assert request.accepted_at == '2018-11-21T11:10:29+00:00' - assert request.rejected_by == 'admin@a1provider.com' - assert request.rejected_at == '2018-11-21T11:10:29+00:00' - assert request.closed_by == 'admin@a1provider.com' - assert request.closed_at == '2018-11-21T11:10:29+00:00' + assert request.events.uploaded.by.name == 'rahul.mondal@ingrammicro.com' + assert request.events.uploaded.at == datetime(2018, 11, 21, 11, 10, 29) + assert request.events.submitted.by.name == 'rahul.mondal@ingrammicro.com' + assert request.events.submitted.at == datetime(2018, 11, 21, 11, 10, 29) + assert request.events.accepted.by.name == 'admin@a1provider.com' + assert request.events.accepted.at == datetime(2018, 11, 21, 11, 10, 29) + assert request.events.rejected.by.name == 'admin@a1provider.com' + assert request.events.rejected.at == datetime(2018, 11, 21, 11, 10, 29) + assert request.events.closed.by.name == 'admin@a1provider.com' + assert request.events.closed.at == datetime(2018, 11, 21, 11, 10, 29) @patch('requests.get', MagicMock(side_effect=_get_response_ok))