Skip to content

Commit

Permalink
feat: Add Masa Portal (#126)
Browse files Browse the repository at this point in the history
  • Loading branch information
GuyKh authored Aug 14, 2024
1 parent 3c4d300 commit b7934a9
Show file tree
Hide file tree
Showing 12 changed files with 1,192 additions and 5 deletions.
14 changes: 13 additions & 1 deletion iec_api/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@
HEADERS_WITH_AUTH["Cookie"] = "ARRAffinity=?; " "ARRAffinitySameSite=?;" " GCLB=?"

TIMEZONE = pytz.timezone("Asia/Jerusalem")
IEC_API_BASE_URL = "https://iecapi.iec.co.il//api/"
IEC_API_BASE_URL = "https://iecapi.iec.co.il/api/"
IEC_FAULT_PORTAL_API_URL = "https://masa-faultsportalapi.iec.co.il/api/"
IEC_MASA_BASE_URL = "https://masaapi-wa.azurewebsites.net/"
IEC_MASA_API_BASE_URL = IEC_MASA_BASE_URL + "api/"
IEC_MASA_LOOKUP_BASE_URL = IEC_MASA_BASE_URL + "lookup/"
IEC_MASA_MAINPORTAL_API_BASE_URL = "https://masa-mainportalapi.iec.co.il/api/"

GET_ACCOUNTS_URL = IEC_API_BASE_URL + "outages/accounts"
GET_CONSUMER_URL = IEC_API_BASE_URL + "customer"
Expand All @@ -48,6 +52,14 @@
GET_CALCULATOR_GADGET_URL = IEC_API_BASE_URL + "content/en-US/calculators/gadget"
GET_OUTAGES_URL = IEC_API_BASE_URL + "outages/transactions/{account_id}/2"

GET_MASA_CITIES_LOOKUP_URL = IEC_MASA_MAINPORTAL_API_BASE_URL + "cities"
GET_MASA_USER_PROFILE_LOOKUP_URL = IEC_MASA_MAINPORTAL_API_BASE_URL + "contacts/userprofile"
GET_MASA_ORDER_TITLES_URL = IEC_MASA_API_BASE_URL + "accounts/{account_id}/orders/titles"
GET_MASA_ORDER_LOOKUP_URL = IEC_MASA_API_BASE_URL + "orderLookup"
GET_MASA_VOLT_LEVELS_URL = IEC_MASA_API_BASE_URL + "voltLevels/active"
GET_MASA_EQUIPMENTS_URL = IEC_MASA_BASE_URL + "equipments/get?accountId={account_id}&pageNumber=1&pageSize=10"
GET_MASA_LOOKUP_URL = IEC_MASA_BASE_URL + "lookup/all"

GET_USER_PROFILE_FROM_FAULT_PORTAL_URL = IEC_FAULT_PORTAL_API_URL + "contacts/userprofile"
GET_OUTAGES_FROM_FAULT_PORTAL_URL = IEC_FAULT_PORTAL_API_URL + "accounts/{account_id}/tranzactions/2"
ERROR_FIELD_NAME = "Error"
Expand Down
113 changes: 111 additions & 2 deletions iec_api/iec_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,16 @@
import jwt
from aiohttp import ClientSession

from iec_api import commons, data, fault_portal_data, login, static_data
from iec_api import commons, data, fault_portal_data, login, masa_data, static_data
from iec_api.fault_portal_models.outages import FaultPortalOutage
from iec_api.fault_portal_models.user_profile import UserProfile
from iec_api.masa_api_models.cities import City
from iec_api.masa_api_models.equipment import GetEquipmentResponse
from iec_api.masa_api_models.lookup import GetLookupResponse
from iec_api.masa_api_models.order_lookup import OrderCategory
from iec_api.masa_api_models.titles import GetTitleResponse
from iec_api.masa_api_models.user_profile import MasaUserProfile
from iec_api.masa_api_models.volt_levels import VoltLevel
from iec_api.models.account import Account
from iec_api.models.contract import Contract
from iec_api.models.contract_check import ContractCheck
Expand Down Expand Up @@ -75,6 +82,7 @@ def __init__(self, user_id: str | int, session: Optional[ClientSession] = None):
self._bp_number: Optional[str] = None # BP Number associated with the instance
self._contract_id: Optional[str] = None # Contract ID associated with the instance
self._account_id: Optional[str] = None # Account ID associated with the instance
self._masa_connection_size_map: Optional[dict[int, str]] = None

def _shutdown(self):
if not self._session.closed:
Expand Down Expand Up @@ -105,7 +113,7 @@ async def get_accounts(self) -> Optional[List[Account]]:

if accounts and len(accounts) > 0:
self._bp_number = accounts[0].account_number
self._account_id = accounts[0].id
self._account_id = str(accounts[0].id)

return accounts

Expand Down Expand Up @@ -519,6 +527,107 @@ async def get_outages_by_account(self, account_id: Optional[str] = None) -> Opti

return await data.get_outages_by_account(self._session, self._token, account_id)

# ----------------
# Masa API Flow
# ----------------

async def get_masa_equipment_by_account(self, account_id: Optional[str] = None) -> GetEquipmentResponse:
"""Get Equipment for the Account
Args:
self: The instance of the class.
account_id (str): The Account ID of the meter.
Returns:
GetEquipmentResponse: Get Equipment Response
"""
await self.check_token()

if not account_id:
account_id = self._account_id

assert account_id, "Account Id must be provided"

return await masa_data.get_masa_equipments(self._session, self._token, account_id)

async def get_masa_user_profile(self) -> MasaUserProfile:
"""Get Masa User Profile
Args:
self: The instance of the class.
Returns:
MasaUserProfile: Masa User Profile
"""
await self.check_token()

return await masa_data.get_masa_user_profile(self._session, self._token)

async def get_masa_cities(self) -> List[City]:
"""Get Masa Cities
Args:
self: The instance of the class.
Returns:
list[City]: List of Cities
"""
await self.check_token()

return await masa_data.get_masa_cities(self._session, self._token)

async def get_masa_order_categories(self) -> List[OrderCategory]:
"""Get Masa Cities for the Account
Args:
self: The instance of the class.
Returns:
list[OrderCategory]: List of Order Categories
"""
await self.check_token()

return await masa_data.get_masa_order_categories(self._session, self._token)

async def get_masa_volt_levels(self) -> List[VoltLevel]:
"""Get Masa Volt Level
Args:
self: The instance of the class.
Returns:
list[VoltLevel]: List of Volt Levelts
"""
await self.check_token()
return await masa_data.get_masa_volt_levels(self._session, self._token)

async def get_masa_order_titles(self, account_id: Optional[str] = None) -> GetTitleResponse:
"""Get Masa Cities
Args:
self: The instance of the class.
account_id (str): The Account ID of the meter.
Returns:
GetTitleResponse: Get Title Response
"""
await self.check_token()

if not account_id:
account_id = self._account_id

assert account_id, "Account Id must be provided"

return await masa_data.get_masa_order_titles(self._session, self._token, account_id)

async def get_masa_lookup(self) -> GetLookupResponse:
"""Get Masa Lookup
Args:
self: The instance of the class.
Returns:
GetLookupResponse: Get Title Response
"""
await self.check_token()
return await masa_data.get_masa_lookup(self._session, self._token)

async def get_masa_connection_size_from_masa(self, account_id: Optional[str] = None) -> Optional[str]:
if not self._masa_connection_size_map:
lookup = await self.get_masa_lookup()
self._masa_connection_size_map = {obj.size_type: obj.name for obj in lookup.connection_size_types}

equipment = await self.get_masa_equipment_by_account(account_id)
connection_size = equipment.items[0].connections[0].power_connection_size

return self._masa_connection_size_map.get(connection_size)

# ----------------
# Fault Portal Endpoints
# ----------------
Expand Down
213 changes: 213 additions & 0 deletions iec_api/masa_api_models/building_options.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
from dataclasses import dataclass, field
from typing import List
from uuid import UUID

from mashumaro import DataClassDictMixin, field_options

# GET https://masaapi-wa.azurewebsites.net/lookup/newConnection/buildingOptions
#
# {
# "residenceOptions": [
# {
# "orderPurpose": {
# "desc": "בית בודד",
# "buildingType": 1,
# "id": "a31b52d8-68da-e911-a973-000d3a29f080",
# "name": "מגורים צמודי קרקע"
# },
# "connectionSizes": [
# {
# "id": "84dab873-671f-e911-a961-000d3a29f1fd",
# "name": "חד פאזי 40 אמפר (1X40)"
# } //..
# ]
# },
# {
# "orderPurpose": {
# "desc": "דו משפחתי",
# "buildingType": 1,
# "id": "ae1b52d8-68da-e911-a973-000d3a29f080",
# "name": "צ.קרקע אחד מדו-משפחתי"
# },
# "connectionSizes": [
# {
# "id": "84dab873-671f-e911-a961-000d3a29f1fd",
# "name": "חד פאזי 40 אמפר (1X40)"
# } //..
# ]
# }
# ],
# "commercialOptions": [
# {
# "orderPurpose": {
# "desc": "חיבור אחד בפילר/ מערכת מנייה",
# "buildingType": 3,
# "id": "ab1b52d8-68da-e911-a973-000d3a29f080",
# "name": "לא מגורים בפילר מונים"
# },
# "connectionSizes": [
# {
# "id": "7ddab873-671f-e911-a961-000d3a29f1fd",
# "name": "חד פאזי 6 אמפר (1X6)"
# } //..
# ]
# },
# {
# "orderPurpose": {
# "desc": "חיבור אחד בפילר לשני מונים",
# "buildingType": 1,
# "id": "b91b52d8-68da-e911-a973-000d3a29f080",
# "name": "לא מגורים בפילר-אחד מתוך דו-משפחתי"
# },
# "connectionSizes": [
# {
# "id": "84dab873-671f-e911-a961-000d3a29f1fd",
# "name": "חד פאזי 40 אמפר (1X40)"
# } //...
# ]
# }
# ],
# "tempOptions": [
# {
# "orderPurpose": {
# "desc": "חיבור זמני לאתר בניה",
# "buildingType": 6,
# "id": "8f1b52d8-68da-e911-a973-000d3a29f080",
# "name": "חיבור ארעי"
# },
# "connectionSizes": [
# {
# "id": "84dab873-671f-e911-a961-000d3a29f1fd",
# "name": "חד פאזי 40 אמפר (1X40)"
# } //...
# ]
# }
# ],
# "residenceSizeTypes": [
# {
# "id": "84dab873-671f-e911-a961-000d3a29f1fd",
# "name": "חד פאזי 40 אמפר (1X40)"
# } // ...
# ],
# "commercialSizeTypes": [
# {
# "id": "84dab873-671f-e911-a961-000d3a29f1fd",
# "name": "חד פאזי 40 אמפר (1X40)"
# },
# {
# "id": "85dab873-671f-e911-a961-000d3a29f1fd",
# "name": "תלת פאזי 25 אמפר (3X25)"
# } // ..
# ],
# "publicSizeTypes": [
# {
# "id": "84dab873-671f-e911-a961-000d3a29f1fd",
# "name": "חד פאזי 40 אמפר (1X40)"
# } //...
# ],
# "parkingSizeTypes": [
# {
# "id": "84dab873-671f-e911-a961-000d3a29f1fd",
# "name": "חד פאזי 40 אמפר (1X40)"
# } //...
# ]
# }

@dataclass
class OrderPurpose(DataClassDictMixin):
"""
Represents the purpose of an order related to building types.
Attributes:
desc (str): A description of the order purpose.
building_type (int): The type of building associated with the order.
id (UUID): The unique identifier for the order purpose.
name (str): The name of the order purpose.
"""
desc: str = field(metadata=field_options(alias="desc"))
building_type: int = field(metadata=field_options(alias="buildingType"))
id: UUID = field(metadata=field_options(alias="id"))
name: str = field(metadata=field_options(alias="name"))

@dataclass
class ConnectionSize(DataClassDictMixin):
"""
Represents a connection size option.
Attributes:
id (UUID): The unique identifier for the connection size.
name (str): The name of the connection size, typically including phase and amperage details.
"""
id: UUID = field(metadata=field_options(alias="id"))
name: str = field(metadata=field_options(alias="name"))

@dataclass
class ResidenceOption(DataClassDictMixin):
"""
Represents a residential option, including order purpose and available connection sizes.
Attributes:
order_purpose (OrderPurpose): The purpose of the order for a residential option.
connection_sizes (List[ConnectionSize]): A list of connection sizes available for this residential option.
"""
order_purpose: OrderPurpose = field(metadata=field_options(alias="orderPurpose"))
connection_sizes: List[ConnectionSize] = field(metadata=field_options(alias="connectionSizes"))

@dataclass
class CommercialOption(DataClassDictMixin):
"""
Represents a commercial option, including order purpose and available connection sizes.
Attributes:
order_purpose (OrderPurpose): The purpose of the order for a commercial option.
connection_sizes (List[ConnectionSize]): A list of connection sizes available for this commercial option.
"""
order_purpose: OrderPurpose = field(metadata=field_options(alias="orderPurpose"))
connection_sizes: List[ConnectionSize] = field(metadata=field_options(alias="connectionSizes"))

@dataclass
class TempOption(DataClassDictMixin):
"""
Represents a temporary option, including order purpose and available connection sizes.
Attributes:
order_purpose (OrderPurpose): The purpose of the order for a temporary option.
connection_sizes (List[ConnectionSize]): A list of connection sizes available for this temporary option.
"""
order_purpose: OrderPurpose = field(metadata=field_options(alias="orderPurpose"))
connection_sizes: List[ConnectionSize] = field(metadata=field_options(alias="connectionSizes"))

@dataclass
class OptionSizeType(DataClassDictMixin):
"""
Represents a size type option for various building categories.
Attributes:
id (UUID): The unique identifier for the size type.
name (str): The name of the size type, typically including phase and amperage details.
"""
id: UUID = field(metadata=field_options(alias="id"))
name: str = field(metadata=field_options(alias="name"))

@dataclass
class GetBuildingOptionsResponse(DataClassDictMixin):
"""
Represents the overall response structure containing various options for residential, commercial,
and temporary connections.
Attributes:
residence_options (List[ResidenceOption]): A list of residential options available.
commercial_options (List[CommercialOption]): A list of commercial options available.
temp_options (List[TempOption]): A list of temporary options available.
residence_size_types (List[OptionSizeType]): A list of size types available for residential buildings.
commercial_size_types (List[OptionSizeType]): A list of size types available for commercial buildings.
public_size_types (List[OptionSizeType]): A list of size types available for public buildings.
parking_size_types (List[OptionSizeType]): A list of size types available for parking facilities.
"""
residence_options: List[ResidenceOption] = field(metadata=field_options(alias="residenceOptions"))
commercial_options: List[CommercialOption] = field(metadata=field_options(alias="commercialOptions"))
temp_options: List[TempOption] = field(metadata=field_options(alias="tempOptions"))
residence_size_types: List[OptionSizeType] = field(metadata=field_options(alias="residenceSizeTypes"))
commercial_size_types: List[OptionSizeType] = field(metadata=field_options(alias="commercialSizeTypes"))
public_size_types: List[OptionSizeType] = field(metadata=field_options(alias="publicSizeTypes"))
parking_size_types: List[OptionSizeType] = field(metadata=field_options(alias="parkingSizeTypes"))
Loading

0 comments on commit b7934a9

Please sign in to comment.