Files
OSIT-AE-API-FastAPI/app/routers/order_v3.py

631 lines
26 KiB
Python

import datetime
from fastapi import APIRouter, Body, Depends, Header, HTTPException, Query, Response, status
from pydantic import BaseModel, EmailStr, Field
from typing import Dict, List, Optional, Set, Union
from app.lib_general import *
from app.config import settings
from app.db_sql import *
from app.routers.api_crud import delete_obj_template, get_obj_template, get_obj_li_template, patch_obj_template, post_obj_template
from app.methods.order_methods import get_order_rec_list, load_order_obj, save_order_obj
from app.models.response_models import Resp_Body_Base, mk_resp
from app.models.order_models_v3 import Order_Base
from app.models.order_line_models_v3 import Order_Line_Base
router = APIRouter()
# ### BEGIN ### API Order Routers ### post_order_obj() ###
# Updated 2022-01-18
@router.post('/v3/order', response_model=Resp_Body_Base)
@router.post('/v3/person/{person_id}/order', response_model=Resp_Body_Base)
async def post_order_obj(
order_obj: Order_Base,
person_id: str = Query(..., min_length=11, max_length=22),
inc_address: bool = False,
inc_contact: bool = False,
inc_person: bool = False,
inc_order_line_list: bool = True,
return_obj: bool = True,
commons: Common_Route_Params = Depends(common_route_params),
):
log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
# ### SECTION ### Secondary data validation
if person_id := redis_lookup_id_random(record_id_random=person_id, table_name='person'): pass
else: return mk_resp(data=None, status_code=404, response=commons.response, status_message='The person ID was invalid or not found.')
# ### SECTION ### Process data
if order_id := create_order(
account_id = commons.x_account_id,
person_id = person_id,
order_dict_obj = order_obj,
): pass
else:
log.warning('Likely bad request')
return mk_resp(data=False, status_code=400, response=commons.response, status_message='Something failed while processing the data.') # Bad Request
# ### SECTION ### Return successful results
if return_obj:
order_obj = load_order_obj(
order_id = order_id,
inc_address = inc_address,
inc_contact = inc_contact,
inc_person = inc_person,
).dict(by_alias=commons.by_alias, exclude_unset=commons.exclude_unset)
data = order_obj
else:
order_id_random = get_id_random(record_id=order_id, table_name='order')
data = {}
data['order_id'] = order_id
data['order_id_random'] = order_id_random
return mk_resp(data=data, response=commons.response)
# ### END ### API Order Routers ### post_order_obj() ###
# ### BEGIN ### API Order Routers ### patch_order_obj() ###
# Updated 2022-01-18
@router.patch('/v3/order/{order_id}', response_model=Resp_Body_Base)
# @router.patch('/v3/person/{person_id}/order/{order_id}', response_model=Resp_Body_Base)
async def patch_order_obj(
order_obj: Order_Base,
order_id: str = Query(..., min_length=11, max_length=22),
person_id: str = Query(None, min_length=11, max_length=22),
inc_address: bool = False,
inc_contact: bool = False,
inc_person: bool = False,
inc_order_line_list: bool = True,
return_obj: Optional[bool] = True,
commons: Common_Route_Params = Depends(common_route_params),
):
log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
# ### SECTION ### Secondary data validation
order_id_random = order_id # This is used later for the response data
# person_id_random = person_id # This is used later for the response data
if order_id := redis_lookup_id_random(record_id_random=order_id, table_name='order'): pass
elif order_id is None: pass
else: return mk_resp(data=None, status_code=404, response=commons.response, status_message='The order ID was invalid or not found.')
# if person_id := redis_lookup_id_random(record_id_random=person_id, table_name='person'): pass
# else: return mk_resp(data=None, status_code=404, response=commons.response, status_message='The person ID was invalid or not found.')
# ### SECTION ### Process data
if order_update_result := update_order(
order_id = order_id,
order_dict_obj = order_obj,
# person_id = person_id,
): pass
else:
log.warning('Likely bad request')
return mk_resp(data=False, status_code=400, response=commons.response, status_message='Something failed while processing the data.') # Bad Request
# ### SECTION ### Return successful results
if return_obj:
order_obj = load_order_obj(
order_id = order_id,
inc_address = inc_address,
inc_contact = inc_contact,
inc_order_line_list = inc_order_line_list,
inc_person = inc_person,
).dict(by_alias=commons.by_alias, exclude_unset=commons.exclude_unset)
data = order_obj
else:
data = {}
data['order_id'] = order_id
data['order_id_random'] = order_id_random
return mk_resp(data=data, response=commons.response)
# ### END ### API Order Routers ### patch_order_obj() ###
# ### BEGIN ### API Order Routers ### delete_order_obj() ###
# Updated 2022-01-18
@router.delete('/order/{order_id}', response_model=Resp_Body_Base)
async def delete_order_obj(
order_id: str = Query(..., min_length=11, max_length=22),
commons: Common_Route_Params = Depends(common_route_params),
):
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
obj_type = 'order'
result = delete_obj_template(
obj_type = obj_type,
obj_id = obj_id,
)
return result
# ### END ### API Order Routers ### delete_order_obj() ###
# ### BEGIN ### API Order Routers ### patch_order_obj_add_line() ###
# Updated 2022-01-18
@router.patch('/v3/order/{order_id}/line/add', response_model=Resp_Body_Base)
async def patch_order_obj_add_line(
order_obj: Order_Base,
order_id: str = Query(..., min_length=11, max_length=22),
# inc_order: bool = False,
inc_order_line_list: bool = True,
return_obj: Optional[bool] = True,
commons: Common_Route_Params = Depends(common_route_params),
):
log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
# ### SECTION ### Secondary data validation
order_id_random = order_id # This is used later for the response data
if order_id := redis_lookup_id_random(record_id_random=order_id, table_name='order'): pass
else: return mk_resp(data=None, status_code=404, response=commons.response, status_message='The order ID was invalid or not found.')
# ### SECTION ### Process data
if order_line_add_result := add_order_line(
order_id = order_id,
order_line_dict_obj = order_line_obj,
): pass
else:
log.warning('Likely bad request')
return mk_resp(data=False, status_code=400, response=commons.response, status_message='Something failed while processing the data.') # Bad Request
# ### SECTION ### Return successful results
if return_obj:
order_obj = load_order_obj(
order_id = order_id,
inc_order_line_list = inc_order_line_list,
).dict(by_alias=commons.by_alias, exclude_unset=commons.exclude_unset)
data = order_obj
else:
data = {}
data['order_id'] = order_id
data['order_id_random'] = order_id_random
return mk_resp(data=data, response=commons.response)
# ### END ### API Order Routers ### patch_order_obj_add_line() ###
# ### BEGIN ### API Order Routers ### patch_order_obj_update_line() ###
# Updated 2022-01-18
@router.patch('/v3/order/{order_id}/line/{order_line_id}/update', response_model=Resp_Body_Base)
async def patch_order_obj_update_line(
order_obj: Order_Line_Base,
order_id: str = Query(..., min_length=11, max_length=22),
order_line_id: str = Query(..., min_length=11, max_length=22),
# inc_order: bool = False,
inc_order_line_list: bool = True,
return_obj: Optional[bool] = True,
commons: Common_Route_Params = Depends(common_route_params),
):
log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
# ### SECTION ### Secondary data validation
order_id_random = order_id # This is used later for the response data
order_line_id_random = order_line_id # This is used later for the response data
if order_id := redis_lookup_id_random(record_id_random=order_id, table_name='order'): pass
else: return mk_resp(data=None, status_code=404, response=commons.response, status_message='The order ID was invalid or not found.')
if order_line_id := redis_lookup_id_random(record_id_random=order_line_id, table_name='order_line'): pass
else: return mk_resp(data=None, status_code=404, response=commons.response, status_message='The order line ID was invalid or not found.')
# ### SECTION ### Process data
if order_line_update_result := update_order_line(
order_line_id = order_line_id,
order_line_dict_obj = order_line_obj,
): pass
else:
log.warning('Likely bad request')
return mk_resp(data=False, status_code=400, response=commons.response, status_message='Something failed while processing the data.') # Bad Request
# ### SECTION ### Return successful results
if return_obj:
order_obj = load_order_obj(
order_id = order_id,
inc_order_line_list = inc_order_line_list,
).dict(by_alias=commons.by_alias, exclude_unset=commons.exclude_unset)
data = order_obj
else:
data = {}
data['order_id'] = order_id
data['order_id_random'] = order_id_random
return mk_resp(data=data, response=commons.response)
# ### END ### API Order Routers ### patch_order_obj_update_line() ###
# ### BEGIN ### API Order Routers ### patch_order_obj_remove_line() ###
# Updated 2022-01-18
@router.patch('/v3/order/{order_id}/line/{order_line_id}/remove', response_model=Resp_Body_Base)
async def patch_order_obj_remove_line(
order_obj: Order_Line_Base,
order_id: str = Query(..., min_length=11, max_length=22),
order_line_id: str = Query(..., min_length=11, max_length=22),
# inc_order: bool = False,
inc_order_line_list: bool = True,
return_obj: Optional[bool] = True,
commons: Common_Route_Params = Depends(common_route_params),
):
log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
# ### SECTION ### Secondary data validation
order_id_random = order_id # This is used later for the response data
order_line_id_random = order_line_id # This is used later for the response data
if order_id := redis_lookup_id_random(record_id_random=order_id, table_name='order'): pass
else: return mk_resp(data=None, status_code=404, response=commons.response, status_message='The order ID was invalid or not found.')
if order_line_id := redis_lookup_id_random(record_id_random=order_line_id, table_name='order_line'): pass
else: return mk_resp(data=None, status_code=404, response=commons.response, status_message='The order line ID was invalid or not found.')
# ### SECTION ### Process data
if order_line_remove_result := remove_order_line(
order_line_id = order_line_id,
): pass
else:
log.warning('Likely bad request')
return mk_resp(data=False, status_code=400, response=commons.response, status_message='Something failed while processing the data.') # Bad Request
# ### SECTION ### Return successful results
if return_obj:
order_obj = load_order_obj(
order_id = order_id,
inc_order_line_list = inc_order_line_list,
).dict(by_alias=commons.by_alias, exclude_unset=commons.exclude_unset)
data = order_obj
else:
data = {}
data['order_id'] = order_id
data['order_id_random'] = order_id_random
return mk_resp(data=data, response=commons.response)
# ### END ### API Order Routers ### patch_order_obj_remove_line() ###
# ### BEGIN ### API Order Routers ### get_order_obj_li() ###
# Updated 2022-01-18
@router.get('/v3/{for_obj_type}/{for_obj_id}/order/list', response_model=Resp_Body_Base)
async def get_order_obj_li(
for_obj_type: str = Query(..., min_length=2, max_length=50),
for_obj_id: str = Query(..., min_length=11, max_length=22),
order_status: str = 'complete',
from_datetime: datetime.datetime = None,
to_datetime: datetime.datetime = None,
inc_order_line_list: bool = False,
inc_order_cfg: bool = False,
inc_person_obj: bool = False,
commons: Common_Route_Params = Depends(common_route_params),
):
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
if obj_type_id := redis_lookup_id_random(record_id_random=for_obj_id, table_name=for_obj_type): pass
else: return mk_resp(data=False, status_code=404, response=commons.response) # Not Found
if order_rec_list_result := get_order_rec_list(
for_obj_type = for_obj_type,
for_obj_id = for_obj_id,
from_datetime = from_datetime,
to_datetime = to_datetime,
status = status,
enabled = commons.enabled,
limit = commons.limit,
offset = commons.offset,
):
order_result_list = []
for order_rec in order_rec_list_result:
if load_order_result := load_order_obj(
order_id = order_rec.get('order_id', None),
inc_address = inc_address,
inc_contact = inc_contact,
inc_order_line_list = inc_order_line_list,
inc_person = inc_person,
enabled = commons.enabled,
limit = commons.limit,
by_alias = commons.by_alias,
exclude_unset = commons.exclude_unset,
# model_as_dict = model_as_dict,
):
order_result_list.append(load_order_result)
else:
order_result_list.append(None)
response_data = order_result_list
elif isinstance(order_rec_list_result, list) or order_rec_list_result is None: # Empty list or None
log.info('No results')
return mk_resp(data=None, status_code=404, response=commons.response) # Not Found
else:
log.warning('Likely bad request')
return mk_resp(data=False, status_code=400, response=commons.response) # Bad Request
return mk_resp(data=response_data, response=commons.response)
# ### END ### API Order Routers ### get_order_obj_li() ###
# ### BEGIN ### API Order Routes ### get_order_obj() ###
# NOTE 2021-08-09: Use with rework of order_cart
# Updated 2021-08-07
@router.get('/order/{order_id}', response_model=Resp_Body_Base)
async def get_order_obj(
order_id: str = Query(..., min_length=11, max_length=22),
limit: int = 500,
enabled: str = 'enabled',
inc_order_line_list: bool = False,
inc_order_cfg: bool = False,
inc_person: bool = False,
x_account_id: str = Header(...),
by_alias: bool = True,
exclude_unset: bool = True,
response: Response = Response,
):
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
if order_obj := load_order_obj(
order_id = order_id,
limit = limit,
enabled = enabled,
by_alias = by_alias,
exclude_unset = exclude_unset,
# model_as_dict = model_as_dict,
inc_order_line_list = inc_order_line_list,
inc_order_cfg = inc_order_cfg,
inc_person = inc_person,
):
log.debug(order_obj)
data = order_obj.dict(by_alias=by_alias, exclude_unset=False) # NOTE NOTE NOTE NOTE exclude_unset is forced to False for now. Will return more fields than is ideal. Need to create another Order_Line_Base. Probably Order_Line_OUT_Base
return mk_resp(data=data)
else:
return mk_resp(data=False, status_code=404, response=response) # Not Found
# ### END ### API Order Routes ### get_order_obj() ###
# ### BEGIN ### API Order ### get_obj_id_order_list() ###
# Updated 2021-12-13
@router.get('/{obj_type}/{obj_id}/order/list', response_model=Resp_Body_Base)
async def get_obj_id_order_list(
obj_type: str = Query(..., min_length=4, max_length=25), # Expects account or person
obj_id: str = Query(..., min_length=11, max_length=22),
from_datetime: datetime.datetime = None,
to_datetime: datetime.datetime = None,
inc_order_cfg: bool = False,
inc_order_line_list: bool = False,
# w_prod_type: str = 'all', # all, cont_edu_cert, event, fundraising, membership, etc
inc_person: bool = False,
status: str = 'closed', # open, locked, reopened?, closed (complete), canceled, other
enabled: str = 'enabled',
limit: int = 50,
by_alias: Optional[bool] = True,
exclude_unset: Optional[bool] = True,
x_account_id: str = Header(..., min_length=11, max_length=22),
response: Response = Response,
):
log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
if obj_type in ['account', 'person']:
if obj_id := redis_lookup_id_random(record_id_random=obj_id, table_name=obj_type): pass
else: return mk_resp(data=None, status_code=404, response=response)
else:
log.warning('Likely bad request')
return mk_resp(data=False, status_code=400, response=response) # Bad Request
if order_rec_list_result := get_order_rec_list(
for_obj_type = obj_type,
for_obj_id = obj_id,
from_datetime = from_datetime,
to_datetime = to_datetime,
status = status,
enabled = enabled,
limit = limit,
):
order_result_list = []
for order_rec in order_rec_list_result:
if load_order_result := load_order_obj(
order_id = order_rec.get('order_id', None),
inc_order_cfg = inc_order_cfg,
inc_order_line_list = inc_order_line_list,
inc_person = inc_person,
enabled = enabled,
limit = limit,
by_alias = by_alias,
exclude_unset = exclude_unset,
# model_as_dict = model_as_dict,
):
order_result_list.append(load_order_result)
else:
order_result_list.append(None)
response_data = order_result_list
elif isinstance(order_rec_list_result, list) or order_rec_list_result is None: # Empty list or None
log.info('No results')
return mk_resp(data=None, status_code=404, response=response) # Not Found
else:
log.warning('Likely bad request')
return mk_resp(data=False, status_code=400, response=response) # Bad Request
return mk_resp(data=response_data, response=response)
# ### END ### API Order ### get_obj_id_order_list() ###
# # ### BEGIN ### API Order ### get_account_obj_order_list() ###
# # Updated 2021-11-19
# @router.get('/account/{account_id}/order/list', response_model=Resp_Body_Base)
# async def get_account_id_order_list(
# account_id: str = Query(..., min_length=11, max_length=22),
# limit: int = 50,
# enabled: str = 'enabled',
# from_datetime: datetime.datetime = None,
# to_datetime: datetime.datetime = None,
# inc_order_cfg: bool = False,
# inc_order_line_list: bool = False,
# # inc_order_w_prod_type: str = 'all', # all, membership, fundraising, event, etc
# status: str = 'closed', # open, locked, reopened?, closed (complete), canceled, other
# x_account_id: str = Header(...),
# by_alias: Optional[bool] = True,
# exclude_unset: Optional[bool] = True,
# response: Response = Response,
# ):
# log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
# log.debug(locals())
# if account_id := redis_lookup_id_random(record_id_random=account_id, table_name='account'): pass
# else: return mk_resp(data=None, status_code=404, response=response)
# # Updated 2021-06-28
# if order_rec_list_result := get_order_rec_list(
# for_obj_type = 'account',
# for_obj_id = account_id,
# limit = limit,
# enabled = enabled,
# from_datetime = from_datetime,
# to_datetime = to_datetime,
# status = status,
# ):
# order_result_list = []
# for order_rec in order_rec_list_result:
# if load_order_result := load_order_obj(
# order_id = order_rec.get('order_id', None),
# limit = limit,
# enabled = enabled,
# by_alias = by_alias,
# exclude_unset = exclude_unset,
# # model_as_dict = model_as_dict,
# inc_order_cfg = inc_order_cfg,
# inc_order_line_list = inc_order_line_list,
# ):
# order_result_list.append(load_order_result)
# else:
# order_result_list.append(None)
# response_data = order_result_list
# else:
# return mk_resp(data=False, status_code=400, response=response) # Bad Request
# return mk_resp(data=response_data)
# # ### END ### API Order ### get_account_obj_order_list() ###
# # ### BEGIN ### API Order ### get_person_obj_order_list() ###
# # Updated 2021-11-19
# @router.get('/person/{person_id}/order/list', response_model=Resp_Body_Base)
# async def get_person_id_order_list(
# person_id: str = Query(..., min_length=11, max_length=22),
# limit: int = 50,
# enabled: str = 'enabled',
# from_datetime: datetime.datetime = None,
# to_datetime: datetime.datetime = None,
# inc_order_cfg: bool = False,
# inc_order_line_list: bool = False,
# # inc_order_w_prod_type: str = 'all', # all, membership, fundraising, event, etc
# status: str = 'closed', # open, locked, reopened?, closed (complete), canceled, other
# x_account_id: str = Header(...),
# by_alias: Optional[bool] = True,
# exclude_unset: Optional[bool] = True,
# response: Response = Response,
# ):
# log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
# log.debug(locals())
# if person_id := redis_lookup_id_random(record_id_random=person_id, table_name='person'): pass
# else: return mk_resp(data=None, status_code=404, response=response)
# # Updated 2021-06-28
# if order_rec_list_result := get_order_rec_list(
# for_obj_type = 'person',
# for_obj_id = person_id,
# limit = limit,
# enabled = enabled,
# from_datetime = from_datetime,
# to_datetime = to_datetime,
# status = status,
# ):
# order_result_list = []
# for order_rec in order_rec_list_result:
# if load_order_result := load_order_obj(
# order_id = order_rec.get('order_id', None),
# limit = limit,
# enabled = enabled,
# by_alias = by_alias,
# exclude_unset = exclude_unset,
# # model_as_dict = model_as_dict,
# inc_order_cfg = inc_order_cfg,
# inc_order_line_list = inc_order_line_list,
# ):
# order_result_list.append(load_order_result)
# else:
# order_result_list.append(None)
# response_data = order_result_list
# else:
# return mk_resp(data=False, status_code=400, response=response) # Bad Request
# return mk_resp(data=response_data)
# # ### END ### API Order ### get_person_obj_order_list() ###
# ### BEGIN ### API Order ### get_person_id_order_cart() ###
# NOTE 2021-08-09: Use with rework of order_cart. The most recent (hopefully only one) "open" order for a person.
# Updated 2021-11-19
@router.get('/person/{person_id}/order/cart', response_model=Resp_Body_Base)
async def get_person_id_order_cart(
person_id: str = Query(..., min_length=11, max_length=22),
enabled: str = 'enabled',
inc_order_line_list: bool = False,
inc_order_cfg: bool = False,
x_account_id: str = Header(...),
by_alias: bool = True,
exclude_unset: bool = True,
response: Response = Response,
):
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
# Query to get the one "open" order status for a person ID
return False
# ### END ### API Order ### get_person_id_order_cart() ###
@router.delete('/order/{obj_id}', response_model=Resp_Body_Base)
async def delete_order_obj(
obj_id: str = Query(..., min_length=1, max_length=22),
x_account_id: str = Header(...),
response: Response = Response,
):
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
obj_type = 'order'
result = delete_obj_template(
obj_type=obj_type,
obj_id=obj_id,
)
return result
# NOTE 2021-08-09: Use with rework of order_cart
# NOTE: The router needs to have the prefix (/order) removed.
@router.delete('/order/{order_id}/line/<order_line_id>/remove', response_model=Resp_Body_Base)
async def delete_order_line_obj_NOT_SURE(
order_id: str = Query(..., min_length=1, max_length=22),
obj: Order_Base = None,
x_account_id: Optional[str] = Header(..., ),
return_obj: Optional[bool] = True,
by_alias: Optional[bool] = True,
exclude_unset: Optional[bool] = True,
response: Response = Response,
):
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())