fix block
add check name to subscription
This commit is contained in:
@@ -11,6 +11,20 @@ class ConflictError(ServiceError):
|
|||||||
super().__init__(HTTPStatus.CONFLICT, msg)
|
super().__init__(HTTPStatus.CONFLICT, msg)
|
||||||
|
|
||||||
|
|
||||||
|
class NotAcceptableError(ServiceError):
|
||||||
|
def __init__(self, msg: str | dict):
|
||||||
|
super().__init__(HTTPStatus.NOT_ACCEPTABLE, msg)
|
||||||
|
|
||||||
|
|
||||||
|
class SubscriptionRequiredError(NotAcceptableError): ...
|
||||||
|
|
||||||
|
|
||||||
|
class SubscriptionFrozenError(NotAcceptableError): ...
|
||||||
|
|
||||||
|
|
||||||
|
class SubscriptionConflictError(ConflictError): ...
|
||||||
|
|
||||||
|
|
||||||
class OrgNotFoundError(NotFoundError): ...
|
class OrgNotFoundError(NotFoundError): ...
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
from datetime import date, datetime, time, timedelta
|
from datetime import date, datetime, time, timedelta
|
||||||
from http import HTTPStatus
|
|
||||||
from typing import Annotated, TypedDict
|
from typing import Annotated, TypedDict
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
from aws_lambda_powertools import Logger
|
from aws_lambda_powertools import Logger
|
||||||
from aws_lambda_powertools.event_handler.api_gateway import Router
|
from aws_lambda_powertools.event_handler.api_gateway import Router
|
||||||
from aws_lambda_powertools.event_handler.exceptions import (
|
|
||||||
ServiceError,
|
|
||||||
)
|
|
||||||
from aws_lambda_powertools.event_handler.openapi.params import Body
|
from aws_lambda_powertools.event_handler.openapi.params import Body
|
||||||
from aws_lambda_powertools.shared.functions import extract_event_from_common_models
|
from aws_lambda_powertools.shared.functions import extract_event_from_common_models
|
||||||
from layercake.batch import BatchProcessor
|
from layercake.batch import BatchProcessor
|
||||||
@@ -20,7 +16,7 @@ from pydantic import UUID4, BaseModel, EmailStr, Field, FutureDate
|
|||||||
|
|
||||||
from boto3clients import dynamodb_client
|
from boto3clients import dynamodb_client
|
||||||
from config import DEDUP_WINDOW_OFFSET_DAYS, ENROLLMENT_TABLE, TZ, USER_TABLE
|
from config import DEDUP_WINDOW_OFFSET_DAYS, ENROLLMENT_TABLE, TZ, USER_TABLE
|
||||||
from exceptions import ConflictError
|
from exceptions import ConflictError, SubscriptionFrozenError, SubscriptionRequiredError
|
||||||
from middlewares.authentication_middleware import User as Authenticated
|
from middlewares.authentication_middleware import User as Authenticated
|
||||||
|
|
||||||
logger = Logger(__name__)
|
logger = Logger(__name__)
|
||||||
@@ -29,16 +25,6 @@ dyn = DynamoDBPersistenceLayer(ENROLLMENT_TABLE, dynamodb_client)
|
|||||||
processor = BatchProcessor()
|
processor = BatchProcessor()
|
||||||
|
|
||||||
|
|
||||||
class SubscriptionRequiredError(ServiceError):
|
|
||||||
def __init__(self, msg: str | dict):
|
|
||||||
super().__init__(HTTPStatus.NOT_ACCEPTABLE, msg)
|
|
||||||
|
|
||||||
|
|
||||||
class SubscriptionFrozenError(ServiceError):
|
|
||||||
def __init__(self, msg: str | dict):
|
|
||||||
super().__init__(HTTPStatus.NOT_ACCEPTABLE, msg)
|
|
||||||
|
|
||||||
|
|
||||||
class DeduplicationConflictError(ConflictError): ...
|
class DeduplicationConflictError(ConflictError): ...
|
||||||
|
|
||||||
|
|
||||||
@@ -139,7 +125,7 @@ def enroll(
|
|||||||
dyn.put_item(item=item)
|
dyn.put_item(item=item)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.exception(exc)
|
logger.exception(exc)
|
||||||
finally:
|
else:
|
||||||
return item
|
return item
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,14 +10,17 @@ from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair
|
|||||||
from api_gateway import JSONResponse
|
from api_gateway import JSONResponse
|
||||||
from boto3clients import dynamodb_client
|
from boto3clients import dynamodb_client
|
||||||
from config import USER_TABLE
|
from config import USER_TABLE
|
||||||
from exceptions import OrgNotFoundError
|
from exceptions import (
|
||||||
|
OrgNotFoundError,
|
||||||
|
SubscriptionConflictError,
|
||||||
|
SubscriptionRequiredError,
|
||||||
|
)
|
||||||
|
|
||||||
router = Router()
|
router = Router()
|
||||||
dyn = DynamoDBPersistenceLayer(USER_TABLE, dynamodb_client)
|
dyn = DynamoDBPersistenceLayer(USER_TABLE, dynamodb_client)
|
||||||
|
|
||||||
|
|
||||||
class PaymentMethod(str, Enum):
|
class PaymentMethod(str, Enum):
|
||||||
PIX = 'PIX'
|
|
||||||
BANK_SLIP = 'BANK_SLIP'
|
BANK_SLIP = 'BANK_SLIP'
|
||||||
MANUAL = 'MANUAL'
|
MANUAL = 'MANUAL'
|
||||||
|
|
||||||
@@ -26,7 +29,7 @@ class PaymentMethod(str, Enum):
|
|||||||
def add(
|
def add(
|
||||||
org_id: str,
|
org_id: str,
|
||||||
name: Annotated[str, Body(embed=True)],
|
name: Annotated[str, Body(embed=True)],
|
||||||
billing_day: Annotated[int, Body(embed=True, ge=1)],
|
billing_day: Annotated[int, Body(embed=True, ge=1, le=31)],
|
||||||
payment_method: Annotated[PaymentMethod, Body(embed=True)],
|
payment_method: Annotated[PaymentMethod, Body(embed=True)],
|
||||||
):
|
):
|
||||||
now_ = now()
|
now_ = now()
|
||||||
@@ -35,11 +38,15 @@ def add(
|
|||||||
transact.update(
|
transact.update(
|
||||||
key=KeyPair(org_id, '0'),
|
key=KeyPair(org_id, '0'),
|
||||||
update_expr='SET subscription_covered = :true, updated_at = :now',
|
update_expr='SET subscription_covered = :true, updated_at = :now',
|
||||||
|
cond_expr='attribute_exists(sk) AND #name = :name',
|
||||||
|
expr_attr_names={
|
||||||
|
'#name': 'name',
|
||||||
|
},
|
||||||
expr_attr_values={
|
expr_attr_values={
|
||||||
|
':name': name,
|
||||||
':true': True,
|
':true': True,
|
||||||
':now': now_,
|
':now': now_,
|
||||||
},
|
},
|
||||||
cond_expr='attribute_exists(sk)',
|
|
||||||
exc_cls=OrgNotFoundError,
|
exc_cls=OrgNotFoundError,
|
||||||
)
|
)
|
||||||
transact.put(
|
transact.put(
|
||||||
@@ -49,7 +56,9 @@ def add(
|
|||||||
'billing_day': billing_day,
|
'billing_day': billing_day,
|
||||||
'payment_method': payment_method.value,
|
'payment_method': payment_method.value,
|
||||||
'created_at': now_,
|
'created_at': now_,
|
||||||
}
|
},
|
||||||
|
cond_expr='attribute_not_exists(sk)',
|
||||||
|
exc_cls=SubscriptionConflictError,
|
||||||
)
|
)
|
||||||
transact.put(
|
transact.put(
|
||||||
item={
|
item={
|
||||||
@@ -59,6 +68,71 @@ def add(
|
|||||||
'created_at': now_,
|
'created_at': now_,
|
||||||
},
|
},
|
||||||
cond_expr='attribute_not_exists(sk)',
|
cond_expr='attribute_not_exists(sk)',
|
||||||
|
exc_cls=SubscriptionConflictError,
|
||||||
)
|
)
|
||||||
|
|
||||||
return JSONResponse(status_code=HTTPStatus.CREATED)
|
return JSONResponse(status_code=HTTPStatus.CREATED)
|
||||||
|
|
||||||
|
|
||||||
|
@router.put('/<org_id>/subscription')
|
||||||
|
def edit(
|
||||||
|
org_id: str,
|
||||||
|
billing_day: Annotated[int, Body(embed=True, ge=1, le=31)],
|
||||||
|
payment_method: Annotated[PaymentMethod, Body(embed=True)],
|
||||||
|
subscription_frozen: Annotated[bool, Body(embed=True)] = False,
|
||||||
|
):
|
||||||
|
now_ = now()
|
||||||
|
|
||||||
|
with dyn.transact_writer() as transact:
|
||||||
|
transact.condition(
|
||||||
|
key=KeyPair('SUBSCRIPTION', f'ORG#{org_id}'),
|
||||||
|
cond_expr='attribute_exists(sk)',
|
||||||
|
exc_cls=SubscriptionRequiredError,
|
||||||
|
)
|
||||||
|
transact.update(
|
||||||
|
key=KeyPair(org_id, 'METADATA#SUBSCRIPTION'),
|
||||||
|
update_expr='SET billing_day = :billing_day, \
|
||||||
|
payment_method = :payment_method, \
|
||||||
|
updated_at = :now',
|
||||||
|
expr_attr_values={
|
||||||
|
':billing_day': billing_day,
|
||||||
|
':payment_method': payment_method.value,
|
||||||
|
':now': now_,
|
||||||
|
},
|
||||||
|
cond_expr='attribute_exists(sk)',
|
||||||
|
exc_cls=OrgNotFoundError,
|
||||||
|
)
|
||||||
|
|
||||||
|
if subscription_frozen:
|
||||||
|
transact.put(
|
||||||
|
item={
|
||||||
|
'id': 'SUBSCRIPTION#FREEZE',
|
||||||
|
'sk': f'ORG#{org_id}',
|
||||||
|
'created_at': now_,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
transact.delete(key=KeyPair('SUBSCRIPTION#FREEZE', f'ORG#{org_id}'))
|
||||||
|
|
||||||
|
return JSONResponse(status_code=HTTPStatus.NO_CONTENT)
|
||||||
|
|
||||||
|
|
||||||
|
@router.delete('/<org_id>/subscription')
|
||||||
|
def remove(org_id: str):
|
||||||
|
now_ = now()
|
||||||
|
|
||||||
|
with dyn.transact_writer() as transact:
|
||||||
|
transact.update(
|
||||||
|
key=KeyPair(org_id, '0'),
|
||||||
|
update_expr='SET updated_at = :now REMOVE subscription_covered',
|
||||||
|
expr_attr_values={
|
||||||
|
':now': now_,
|
||||||
|
},
|
||||||
|
cond_expr='attribute_exists(sk)',
|
||||||
|
exc_cls=OrgNotFoundError,
|
||||||
|
)
|
||||||
|
transact.delete(key=KeyPair(org_id, 'METADATA#SUBSCRIPTION'))
|
||||||
|
transact.delete(key=KeyPair('SUBSCRIPTION', f'ORG#{org_id}'))
|
||||||
|
transact.delete(key=KeyPair('SUBSCRIPTION#FREEZE', f'ORG#{org_id}'))
|
||||||
|
|
||||||
|
return JSONResponse(status_code=HTTPStatus.NO_CONTENT)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ def test_subscription(
|
|||||||
):
|
):
|
||||||
r = app.lambda_handler(
|
r = app.lambda_handler(
|
||||||
http_api_proxy(
|
http_api_proxy(
|
||||||
raw_path='/orgs/2a8963fc-4694-4fe2-953a-316d1b10f1f5/subscription',
|
raw_path='/orgs/2a8963fc-4694-4fe2-953a-316d1b10f1f5',
|
||||||
method=HTTPMethod.GET,
|
method=HTTPMethod.GET,
|
||||||
),
|
),
|
||||||
lambda_context,
|
lambda_context,
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
{"id": "cnpj", "sk": "00000000000191", "org_id": "6000f79-6e5c-49a0-952f-3bda330ef278"}
|
{"id": "cnpj", "sk": "00000000000191", "org_id": "6000f79-6e5c-49a0-952f-3bda330ef278"}
|
||||||
{"id": "SUBSCRIPTION", "sk": "ORG#2a8963fc-4694-4fe2-953a-316d1b10f1f5"}
|
{"id": "SUBSCRIPTION", "sk": "ORG#2a8963fc-4694-4fe2-953a-316d1b10f1f5"}
|
||||||
{"id": "SUBSCRIPTION", "sk": "ORG#cJtK9SsnJhKPyxESe7g3DG"}
|
{"id": "SUBSCRIPTION", "sk": "ORG#cJtK9SsnJhKPyxESe7g3DG"}
|
||||||
{"id": "SUBSCRIPTION#FROZEN", "sk": "ORG#2a8963fc-4694-4fe2-953a-316d1b10f1f5", "frozen": true, "created_at": "2025-12-24T00:05:27-03:00"}
|
{"id": "SUBSCRIPTION#FREEZE", "sk": "ORG#2a8963fc-4694-4fe2-953a-316d1b10f1f5", "created_at": "2025-12-24T00:05:27-03:00"}
|
||||||
|
|
||||||
// CPFs
|
// CPFs
|
||||||
{"id": "cpf", "sk": "07879819908", "user_id": "15bacf02-1535-4bee-9022-19d106fd7518"}
|
{"id": "cpf", "sk": "07879819908", "user_id": "15bacf02-1535-4bee-9022-19d106fd7518"}
|
||||||
|
|||||||
797
api.saladeaula.digital/uv.lock
generated
797
api.saladeaula.digital/uv.lock
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user