Skip to content

Commit

Permalink
Merge pull request #712 from BoostryJP/feature/#711
Browse files Browse the repository at this point in the history
Add search query and sort item for ChildAccount API
  • Loading branch information
YoshihitoAso authored Oct 29, 2024
2 parents b5fb183 + 04e35da commit 42021b1
Show file tree
Hide file tree
Showing 8 changed files with 1,159 additions and 45 deletions.
1 change: 1 addition & 0 deletions app/model/schema/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
CreateUpdateChildAccountRequest,
ListAllChildAccountQuery,
ListAllChildAccountResponse,
ListAllChildAccountSortItem,
)
from .batch_issue_redeem import (
BatchIssueRedeemUploadIdResponse,
Expand Down
34 changes: 33 additions & 1 deletion app/model/schema/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@
"""

from datetime import datetime
from enum import StrEnum
from typing import Optional

from pydantic import BaseModel, Field, RootModel, field_validator

from app.model import ValidatedDatetimeStr
from app.model.db import AccountRsaStatus
from app.model.schema.base import BasePaginationQuery, ResultSet, SortOrder
from app.model.schema.personal_info import PersonalInfo, PersonalInfoInput
Expand All @@ -48,6 +50,8 @@ class ChildAccount(BaseModel):
child_account_index: int
child_account_address: str
personal_information: PersonalInfo | None
created: datetime | None
modified: datetime | None


############################
Expand Down Expand Up @@ -135,10 +139,38 @@ class CreateUpdateChildAccountRequest(BaseModel):
personal_information: PersonalInfoInput


class ListAllChildAccountSortItem(StrEnum):
child_account_index = "child_account_index"
child_account_address = "child_account_address"
name = "name"
created = "created"
modified = "modified"


class ListAllChildAccountQuery(BasePaginationQuery):
child_account_address: Optional[str] = Field(
None, description="Child account address (partial match)"
)
name: Optional[str] = Field(None, description="Child account name (partial match)")
created_from: Optional[ValidatedDatetimeStr] = Field(
None, description="Personal information created datetime (From)"
)
created_to: Optional[ValidatedDatetimeStr] = Field(
None, description="Personal information created datetime (To)"
)
modified_from: Optional[ValidatedDatetimeStr] = Field(
None, description="Personal information modified datetime (From)"
)
modified_to: Optional[ValidatedDatetimeStr] = Field(
None, description="Personal information modified datetime (To)"
)

sort_item: Optional[ListAllChildAccountSortItem] = Field(
ListAllChildAccountSortItem.child_account_index, description="Sort item"
)
sort_order: Optional[SortOrder] = Field(
SortOrder.ASC,
description="The sort order of the child_account_index. 0:asc, 1:desc",
description=SortOrder.__doc__,
)


Expand Down
2 changes: 1 addition & 1 deletion app/model/schema/token_holders.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class RetrieveTokenHoldersCollectionSortItem(StrEnum):
hold_balance = "hold_balance"
locked_balance = "locked_balance"
key_manager = "key_manager"
holder_name = "tax_category"
tax_category = "tax_category"


class RetrieveTokenHoldersCollectionQuery(BasePaginationQuery):
Expand Down
120 changes: 103 additions & 17 deletions app/routers/issuer/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
CreateUpdateChildAccountRequest,
ListAllChildAccountQuery,
ListAllChildAccountResponse,
ListAllChildAccountSortItem,
)
from app.utils.check_utils import (
address_is_valid_address,
Expand All @@ -94,6 +95,7 @@
router = APIRouter(tags=["account"])

local_tz = pytz.timezone(TZ)
utc_tz = pytz.timezone("UTC")


# POST: /accounts
Expand Down Expand Up @@ -704,13 +706,76 @@ async def list_all_child_account(
)
)
total = await db.scalar(select(func.count()).select_from(stmt.subquery()))
count = total

if get_query.child_account_address is not None:
stmt = stmt.where(
ChildAccount.child_account_address.like(
"%" + get_query.child_account_address + "%"
)
)
if get_query.name is not None:
stmt = stmt.where(
IDXPersonalInfo._personal_info["name"]
.as_string()
.like("%" + get_query.name + "%")
)
if get_query.created_from:
_created_from = datetime.strptime(
get_query.created_from + ".000000", "%Y-%m-%d %H:%M:%S.%f"
)
stmt = stmt.where(
IDXPersonalInfo.created
>= local_tz.localize(_created_from).astimezone(utc_tz)
)
if get_query.created_to:
_created_to = datetime.strptime(
get_query.created_to + ".999999", "%Y-%m-%d %H:%M:%S.%f"
)
stmt = stmt.where(
IDXPersonalInfo.created <= local_tz.localize(_created_to).astimezone(utc_tz)
)
if get_query.modified_from:
_modified_from = datetime.strptime(
get_query.modified_from + ".000000", "%Y-%m-%d %H:%M:%S.%f"
)
stmt = stmt.where(
IDXPersonalInfo.modified
>= local_tz.localize(_modified_from).astimezone(utc_tz)
)
if get_query.modified_to:
_modified_to = datetime.strptime(
get_query.modified_to + ".999999", "%Y-%m-%d %H:%M:%S.%f"
)
stmt = stmt.where(
IDXPersonalInfo.modified
<= local_tz.localize(_modified_to).astimezone(utc_tz)
)

count = await db.scalar(select(func.count()).select_from(stmt.subquery()))

# Sort
if get_query.sort_order == 0: # ASC
stmt = stmt.order_by(asc(ChildAccount.child_account_index))
else: # DESC
stmt = stmt.order_by(desc(ChildAccount.child_account_index))
def _order(_order):
if _order == 0:
return asc
else:
return desc

_sort_order = get_query.sort_order
match get_query.sort_item:
case ListAllChildAccountSortItem.child_account_index:
stmt = stmt.order_by(_order(_sort_order)(ChildAccount.child_account_index))
case ListAllChildAccountSortItem.child_account_address:
stmt = stmt.order_by(
_order(_sort_order)(ChildAccount.child_account_address)
)
case ListAllChildAccountSortItem.name:
stmt = stmt.order_by(
_order(_sort_order)(IDXPersonalInfo._personal_info["name"].as_string())
)
case ListAllChildAccountSortItem.created:
stmt = stmt.order_by(_order(_sort_order)(IDXPersonalInfo.created))
case ListAllChildAccountSortItem.modified:
stmt = stmt.order_by(_order(_sort_order)(IDXPersonalInfo.modified))

# Pagination
if get_query.limit is not None:
Expand All @@ -724,16 +789,26 @@ async def list_all_child_account(

child_accounts = []
for _tmp_child_account in _tmp_child_accounts:
child_accounts.append(
{
if _tmp_child_account[1] is not None:
_personal_info = _tmp_child_account[1].json()
_child_account = {
"issuer_address": _tmp_child_account[0].issuer_address,
"child_account_index": _tmp_child_account[0].child_account_index,
"child_account_address": _tmp_child_account[0].child_account_address,
"personal_information": _tmp_child_account[1].personal_info
if _tmp_child_account[1] is not None
else None,
"personal_information": _personal_info["personal_info"],
"created": _personal_info["created"],
"modified": _personal_info["modified"],
}
)
else:
_child_account = {
"issuer_address": _tmp_child_account[0].issuer_address,
"child_account_index": _tmp_child_account[0].child_account_index,
"child_account_address": _tmp_child_account[0].child_account_address,
"personal_information": None,
"created": None,
"modified": None,
}
child_accounts.append(_child_account)

return json_response(
{
Expand Down Expand Up @@ -800,16 +875,27 @@ async def retrieve_child_account(
if _child_account is None:
raise HTTPException(status_code=404, detail="child account does not exist")

return json_response(
{
if _child_account[1] is not None:
_personal_info = _child_account[1].json()
_resp_account = {
"issuer_address": _child_account[0].issuer_address,
"child_account_index": _child_account[0].child_account_index,
"child_account_address": _child_account[0].child_account_address,
"personal_information": _child_account[1].personal_info
if _child_account[1] is not None
else None,
"personal_information": _personal_info["personal_info"],
"created": _personal_info["created"],
"modified": _personal_info["modified"],
}
)
else:
_resp_account = {
"issuer_address": _child_account[0].issuer_address,
"child_account_index": _child_account[0].child_account_index,
"child_account_address": _child_account[0].child_account_address,
"personal_information": None,
"created": None,
"modified": None,
}

return json_response(_resp_account)


# POST: /accounts/{issuer_address}/child_accounts/{child_account_index}
Expand Down
2 changes: 1 addition & 1 deletion app/routers/issuer/token_holders.py
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ async def retrieve_token_holders_collection(
count = await db.scalar(select(func.count()).select_from(stmt.subquery()))

# Sort
if get_query.sort_item == RetrieveTokenHoldersCollectionSortItem.holder_name:
if get_query.sort_item == RetrieveTokenHoldersCollectionSortItem.tax_category:
sort_attr = IDXPersonalInfo._personal_info["tax_category"].as_integer()
elif get_query.sort_item == RetrieveTokenHoldersCollectionSortItem.key_manager:
sort_attr = IDXPersonalInfo._personal_info["key_manager"].as_string()
Expand Down
98 changes: 96 additions & 2 deletions docs/ibet_prime.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -483,17 +483,88 @@ paths:
description: Limit for pagination
title: Limit
description: Limit for pagination
- name: child_account_address
in: query
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Child account address (partial match)
title: Child Account Address
description: Child account address (partial match)
- name: name
in: query
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Child account name (partial match)
title: Name
description: Child account name (partial match)
- name: created_from
in: query
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Personal information created datetime (From)
title: Created From
description: Personal information created datetime (From)
- name: created_to
in: query
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Personal information created datetime (To)
title: Created To
description: Personal information created datetime (To)
- name: modified_from
in: query
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Personal information modified datetime (From)
title: Modified From
description: Personal information modified datetime (From)
- name: modified_to
in: query
required: false
schema:
anyOf:
- type: string
- type: 'null'
description: Personal information modified datetime (To)
title: Modified To
description: Personal information modified datetime (To)
- name: sort_item
in: query
required: false
schema:
anyOf:
- $ref: '#/components/schemas/ListAllChildAccountSortItem'
- type: 'null'
description: Sort item
default: child_account_index
title: Sort Item
description: Sort item
- name: sort_order
in: query
required: false
schema:
anyOf:
- $ref: '#/components/schemas/SortOrder'
- type: 'null'
description: The sort order of the child_account_index. 0:asc, 1:desc
description: 'Sort order (0: ASC, 1: DESC)'
default: 0
title: Sort Order
description: The sort order of the child_account_index. 0:asc, 1:desc
description: 'Sort order (0: ASC, 1: DESC)'
responses:
'200':
description: Successful Response
Expand Down Expand Up @@ -10378,12 +10449,26 @@ components:
anyOf:
- $ref: '#/components/schemas/PersonalInfo'
- type: 'null'
created:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Created
modified:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Modified
type: object
required:
- issuer_address
- child_account_index
- child_account_address
- personal_information
- created
- modified
title: ChildAccount
description: Child account schema
ChildAccountResponse:
Expand Down Expand Up @@ -12892,6 +12977,15 @@ components:
- child_accounts
title: ListAllChildAccountResponse
description: List all child accounts schema (RESPONSE)
ListAllChildAccountSortItem:
type: string
enum:
- child_account_index
- child_account_address
- name
- created
- modified
title: ListAllChildAccountSortItem
ListAllDVPAgentAccountResponse:
items:
$ref: '#/components/schemas/DVPAgentAccountResponse'
Expand Down
Loading

0 comments on commit 42021b1

Please sign in to comment.