add default org
This commit is contained in:
@@ -16,6 +16,7 @@ from exceptions import (
|
|||||||
CPFConflictError,
|
CPFConflictError,
|
||||||
EmailConflictError,
|
EmailConflictError,
|
||||||
OrgNotFoundError,
|
OrgNotFoundError,
|
||||||
|
SubscriptionFrozenError,
|
||||||
UserConflictError,
|
UserConflictError,
|
||||||
UserNotFoundError,
|
UserNotFoundError,
|
||||||
)
|
)
|
||||||
@@ -107,6 +108,14 @@ def _create_user(
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
with dyn.transact_writer() as transact:
|
with dyn.transact_writer() as transact:
|
||||||
|
transact.condition(
|
||||||
|
key=KeyPair(
|
||||||
|
pk='SUBSCRIPTION#FROZEN',
|
||||||
|
sk=f'ORG#{org.id}',
|
||||||
|
),
|
||||||
|
cond_expr='attribute_not_exists(sk)',
|
||||||
|
exc_cls=SubscriptionFrozenError,
|
||||||
|
)
|
||||||
transact.put(
|
transact.put(
|
||||||
item=user.model_dump()
|
item=user.model_dump()
|
||||||
| {
|
| {
|
||||||
@@ -223,6 +232,14 @@ def _add_member(user_id: str, org: Org) -> None:
|
|||||||
now_ = now()
|
now_ = now()
|
||||||
|
|
||||||
with dyn.transact_writer() as transact:
|
with dyn.transact_writer() as transact:
|
||||||
|
transact.condition(
|
||||||
|
key=KeyPair(
|
||||||
|
pk='SUBSCRIPTION#FROZEN',
|
||||||
|
sk=f'ORG#{org.id}',
|
||||||
|
),
|
||||||
|
cond_expr='attribute_not_exists(sk)',
|
||||||
|
exc_cls=SubscriptionFrozenError,
|
||||||
|
)
|
||||||
transact.update(
|
transact.update(
|
||||||
key=KeyPair(user_id, '0'),
|
key=KeyPair(user_id, '0'),
|
||||||
# Post-migration (users): uncomment the following line
|
# Post-migration (users): uncomment the following line
|
||||||
|
|||||||
@@ -17,9 +17,20 @@ def get_orgs(
|
|||||||
start_key: Annotated[str | None, Query] = None,
|
start_key: Annotated[str | None, Query] = None,
|
||||||
limit: Annotated[int, Query(ge=25)] = 25,
|
limit: Annotated[int, Query(ge=25)] = 25,
|
||||||
):
|
):
|
||||||
return dyn.collection.query(
|
r = dyn.collection.query(
|
||||||
# Post-migration (users): rename `orgs#` to `ORG#`
|
# Post-migration (users): uncomment the following line
|
||||||
|
# key=KeyPair(user_id, 'ORG#'),
|
||||||
key=KeyPair(user_id, 'orgs#'),
|
key=KeyPair(user_id, 'orgs#'),
|
||||||
start_key=start_key,
|
start_key=start_key,
|
||||||
limit=limit,
|
limit=limit,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
preferred, items = None, []
|
||||||
|
|
||||||
|
for x in r['items']:
|
||||||
|
if 'DEFAULT' in x['sk']:
|
||||||
|
preferred = x.get('org_id')
|
||||||
|
else:
|
||||||
|
items.append(x)
|
||||||
|
|
||||||
|
return r | {'items': items} | ({'preferred_org_id': preferred} if preferred else {})
|
||||||
|
|||||||
@@ -18,3 +18,5 @@ def test_get_orgs(
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert r['statusCode'] == HTTPStatus.OK
|
assert r['statusCode'] == HTTPStatus.OK
|
||||||
|
|
||||||
|
print(r['body'])
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
{"id": "213a6682-2c59-4404-9189-12eec0a846d4", "sk": "orgs#DEFAULT", "org_id": "f6000f79-6e5c-49a0-952f-3bda330ef278"}
|
||||||
{"id": "213a6682-2c59-4404-9189-12eec0a846d4", "sk": "orgs#f6000f79-6e5c-49a0-952f-3bda330ef278", "name": "Banco do Brasil", "cnpj": "00000000000191"}
|
{"id": "213a6682-2c59-4404-9189-12eec0a846d4", "sk": "orgs#f6000f79-6e5c-49a0-952f-3bda330ef278", "name": "Banco do Brasil", "cnpj": "00000000000191"}
|
||||||
// Users
|
// Users
|
||||||
{"id": "15bacf02-1535-4bee-9022-19d106fd7518", "sk": "0", "name": "Sérgio R Siqueira", "email": "sergio@somosbeta.com.br", "emails": ["osergiosiqueira@gmail.com", "sergio@somosbeta.combr"], "cpf": "07879819908"}
|
{"id": "15bacf02-1535-4bee-9022-19d106fd7518", "sk": "0", "name": "Sérgio R Siqueira", "email": "sergio@somosbeta.com.br", "emails": ["osergiosiqueira@gmail.com", "sergio@somosbeta.combr"], "cpf": "07879819908"}
|
||||||
|
|||||||
@@ -548,7 +548,7 @@ function PaymentAttemptsMenu({
|
|||||||
<EllipsisIcon />
|
<EllipsisIcon />
|
||||||
</Button>
|
</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent align="end" className="w-76">
|
<PopoverContent align="end" className="w-82">
|
||||||
<div className="p-2 space-y-1.5">
|
<div className="p-2 space-y-1.5">
|
||||||
{payment_attempts.map(({ sk, brand, last4, status }, index) => {
|
{payment_attempts.map(({ sk, brand, last4, status }, index) => {
|
||||||
const [, , created_at] = sk.split('#')
|
const [, , created_at] = sk.split('#')
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ import { request as req } from '@repo/util/request'
|
|||||||
|
|
||||||
export const middleware: Route.MiddlewareFunction[] = [authMiddleware]
|
export const middleware: Route.MiddlewareFunction[] = [authMiddleware]
|
||||||
|
|
||||||
|
type Response = {
|
||||||
|
items: { sk: string }[]
|
||||||
|
preferred_org_id?: string
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader({ context, request }: Route.ActionArgs) {
|
export async function loader({ context, request }: Route.ActionArgs) {
|
||||||
const user = context.get(userContext)!
|
const user = context.get(userContext)!
|
||||||
|
|
||||||
@@ -21,8 +26,10 @@ export async function loader({ context, request }: Route.ActionArgs) {
|
|||||||
throw new Response(await r.text(), { status: r.status })
|
throw new Response(await r.text(), { status: r.status })
|
||||||
}
|
}
|
||||||
|
|
||||||
const { items = [] } = (await r.json()) as { items: { sk: string }[] }
|
const { items = [], preferred_org_id } = (await r.json()) as Response
|
||||||
const [{ sk } = {}] = items
|
const { sk } = preferred_org_id
|
||||||
|
? (items.find((item) => item.sk.includes(preferred_org_id)) ?? items[0])
|
||||||
|
: items[0]
|
||||||
|
|
||||||
if (sk) {
|
if (sk) {
|
||||||
const [_, id] = sk.split('#')
|
const [_, id] = sk.split('#')
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ class StatusAttr(Enum):
|
|||||||
# EXTERNALLY_PAID = 'paid_at'
|
# EXTERNALLY_PAID = 'paid_at'
|
||||||
EXTERNALLY_PAID = 'payment_date'
|
EXTERNALLY_PAID = 'payment_date'
|
||||||
PAID = 'payment_date'
|
PAID = 'payment_date'
|
||||||
|
|
||||||
CANCELED = 'canceled_at'
|
CANCELED = 'canceled_at'
|
||||||
REFUNDED = 'refunded_at'
|
REFUNDED = 'refunded_at'
|
||||||
EXPIRED = 'expired_at'
|
EXPIRED = 'expired_at'
|
||||||
@@ -47,10 +48,10 @@ def _status_attr(status: str) -> StatusAttr | None:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _friendly_status(s: str) -> str:
|
def _friendly_status(status: str) -> str:
|
||||||
if 'status' == 'EXTERNALLY_PAID':
|
if 'status' == 'EXTERNALLY_PAID':
|
||||||
return 'PAID'
|
return 'PAID'
|
||||||
return s
|
return status
|
||||||
|
|
||||||
|
|
||||||
@app.post('/<order_id>/postback')
|
@app.post('/<order_id>/postback')
|
||||||
|
|||||||
@@ -87,7 +87,8 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
|||||||
pk=keys['id'],
|
pk=keys['id'],
|
||||||
sk=f'START#{start_period}#END#{end_period}',
|
sk=f'START#{start_period}#END#{end_period}',
|
||||||
),
|
),
|
||||||
update_expr='SET #status = :status, s3_uri = :s3_uri, \
|
update_expr='SET #status = :status, \
|
||||||
|
s3_uri = :s3_uri, \
|
||||||
updated_at = :updated_at',
|
updated_at = :updated_at',
|
||||||
expr_attr_names={'#status': 'status'},
|
expr_attr_names={'#status': 'status'},
|
||||||
expr_attr_values={
|
expr_attr_values={
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
|||||||
key=KeyPair(order_id, 'TRANSACTION#STATS'),
|
key=KeyPair(order_id, 'TRANSACTION#STATS'),
|
||||||
update_expr='SET #count = if_not_exists(#count, :zero) + :one, \
|
update_expr='SET #count = if_not_exists(#count, :zero) + :one, \
|
||||||
last_attempt_succeeded = :succeeded, \
|
last_attempt_succeeded = :succeeded, \
|
||||||
|
created_at = if_not_exists(created_at, :now), \
|
||||||
updated_at = :now',
|
updated_at = :now',
|
||||||
expr_attr_names={
|
expr_attr_names={
|
||||||
'#count': 'payment_attempts',
|
'#count': 'payment_attempts',
|
||||||
@@ -109,7 +110,7 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
|||||||
':succeeded': charge['success'],
|
':succeeded': charge['success'],
|
||||||
':zero': 0,
|
':zero': 0,
|
||||||
':one': 1,
|
':one': 1,
|
||||||
':now': now(),
|
':now': now_,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -87,9 +87,6 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
|||||||
)
|
)
|
||||||
|
|
||||||
if 'credit_card' in r:
|
if 'credit_card' in r:
|
||||||
transact.delete(
|
|
||||||
key=KeyPair(order_id, 'CREDIT_CARD#PAYMENT_INTENT'),
|
|
||||||
)
|
|
||||||
transact.put(
|
transact.put(
|
||||||
item={
|
item={
|
||||||
'id': order_id,
|
'id': order_id,
|
||||||
@@ -102,6 +99,9 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
|||||||
},
|
},
|
||||||
cond_expr='attribute_not_exists(sk)',
|
cond_expr='attribute_not_exists(sk)',
|
||||||
)
|
)
|
||||||
|
transact.delete(
|
||||||
|
key=KeyPair(order_id, 'CREDIT_CARD#PAYMENT_INTENT'),
|
||||||
|
)
|
||||||
|
|
||||||
if test_mode:
|
if test_mode:
|
||||||
transact.put(
|
transact.put(
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ class PaymentMethod(str, Enum):
|
|||||||
CREDIT_CARD = 'CREDIT_CARD'
|
CREDIT_CARD = 'CREDIT_CARD'
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Address(BaseModel):
|
class Address(BaseModel):
|
||||||
postcode: str
|
postcode: str
|
||||||
neighborhood: str
|
neighborhood: str
|
||||||
@@ -76,7 +75,7 @@ class Order(BaseModel):
|
|||||||
cnpj: str | None = None
|
cnpj: str | None = None
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass(frozen=True)
|
||||||
class Credentials:
|
class Credentials:
|
||||||
account_id: str
|
account_id: str
|
||||||
api_token: str
|
api_token: str
|
||||||
@@ -161,6 +160,7 @@ class Iugu:
|
|||||||
)
|
)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
except requests.HTTPError as err:
|
except requests.HTTPError as err:
|
||||||
|
logger.info('IUGU Response', response=err.response)
|
||||||
logger.exception(err)
|
logger.exception(err)
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
@@ -197,6 +197,7 @@ class Iugu:
|
|||||||
)
|
)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
except requests.HTTPError as err:
|
except requests.HTTPError as err:
|
||||||
|
logger.info('IUGU Response', response=err.response)
|
||||||
logger.exception(err)
|
logger.exception(err)
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
@@ -233,11 +234,13 @@ class Iugu:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
r = requests.post(
|
r = requests.post(
|
||||||
url, json=payload, timeout=(HTTP_CONNECT_TIMEOUT, HTTP_READ_TIMEOUT)
|
url,
|
||||||
|
json=payload,
|
||||||
|
timeout=(HTTP_CONNECT_TIMEOUT, HTTP_READ_TIMEOUT),
|
||||||
)
|
)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
except requests.HTTPError as err:
|
except requests.HTTPError as err:
|
||||||
logger.info('Response', err.response)
|
logger.info('IUGU Response', response=err.response)
|
||||||
logger.exception(err)
|
logger.exception(err)
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
@@ -247,9 +250,13 @@ class Iugu:
|
|||||||
url = self.url(path=f'/v1/invoices/{format_id(invoice_id)}')
|
url = self.url(path=f'/v1/invoices/{format_id(invoice_id)}')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
r = requests.get(url, timeout=(HTTP_CONNECT_TIMEOUT, HTTP_READ_TIMEOUT))
|
r = requests.get(
|
||||||
|
url,
|
||||||
|
timeout=(HTTP_CONNECT_TIMEOUT, HTTP_READ_TIMEOUT),
|
||||||
|
)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
except requests.HTTPError as err:
|
except requests.HTTPError as err:
|
||||||
|
logger.info('IUGU Response', response=err.response)
|
||||||
logger.exception(err)
|
logger.exception(err)
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user