Added better fundraising routes, methods, and models! I thought I already did this...

This commit is contained in:
Scott Idem
2022-11-18 15:52:41 -05:00
parent 1d40f41651
commit 5ebb725532
9 changed files with 407 additions and 40 deletions

View File

@@ -18,7 +18,7 @@ from . import config
from app.log import log, logging
# Import the routers here first:
from app.routers import aether_cfg, api_crud, api, importing, sql, account, activity_log, address, archive, archive_content, contact, cont_edu_cert, cont_edu_cert_person, data_store, event, event_badge, event_badge_template, event_device, event_exhibit, event_exhibit_tracking, event_file, event_importing, event_location, event_person, event_person_detail, event_person_tracking, event_presentation, event_presenter, event_registration, event_session, flask_cfg, hosted_file, journal, journal_entry, log_client_viewing, lookup, membership_cfg, membership_group, membership_person_group, membership_person, membership_person_profile, membership_type, membership_person_type, order, order_v3, order_line, order_cart, organization, page, person, person_user, post, post_comment, product, qr, site, site_domain, user, websockets, e_cvent, c_idaa, e_impexium, e_stripe
from app.routers import aether_cfg, api_crud, api, importing, sql, account, activity_log, address, archive, archive_content, contact, cont_edu_cert, cont_edu_cert_person, data_store, event, event_badge, event_badge_template, event_device, event_exhibit, event_exhibit_tracking, event_file, event_importing, event_location, event_person, event_person_detail, event_person_tracking, event_presentation, event_presenter, event_registration, event_session, flask_cfg, fundraising, hosted_file, journal, journal_entry, log_client_viewing, lookup, membership_cfg, membership_group, membership_person_group, membership_person, membership_person_profile, membership_type, membership_person_type, order, order_v3, order_line, order_cart, organization, page, person, person_user, post, post_comment, product, qr, site, site_domain, user, websockets, e_cvent, c_idaa, e_impexium, e_stripe
from app.db_sql import db, sql_select # , sql_connect
@@ -226,7 +226,6 @@ app.include_router(
)
app.include_router(
event_person_tracking.router,
# prefix='/event/person/tracking',
tags=['Event Person Tracking'],
)
app.include_router(
@@ -249,6 +248,10 @@ app.include_router(
# prefix='/event/session',
tags=['Event Session'],
)
app.include_router(
fundraising.router,
tags=['Fundraising'],
)
app.include_router(
hosted_file.router,
prefix='/hosted_file',

View File

@@ -41,7 +41,7 @@ def load_account_cfg_obj(
log.error(e.json())
if inc_fundraising_cfg:
if fundraising_cfg_dict := load_fundraising_cfg_obj(
if fundraising_cfg_dict := load_fundraising_cfg_obj_old(
account_id = account_id,
model_as_dict = model_as_dict,
):

View File

@@ -1,17 +1,49 @@
from __future__ import annotations
import datetime
from typing import Dict, List, Optional, Set, Union
from pydantic import BaseModel, EmailStr, Field, PrivateAttr, ValidationError, validator
from app.db_sql import redis_lookup_id_random, sql_select
from app.lib_general import log, logging
from app.db_sql import redis_lookup_id_random, sql_enable_part, sql_insert, sql_limit_offset_part, sql_select, sql_update
from app.lib_general import log, logging, logger_reset
from app.models.fundraising_cfg_models import Fundraising_Cfg_Base
# ### BEGIN ### API Fundraising Cfg Methods ### load_fundraising_cfg_obj() ###
# Updated 2022-11-18
def load_fundraising_cfg_obj(
fundraising_id: int|str,
model_as_dict: bool = False,
) -> Fundraising_Cfg_Base|dict|bool:
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
if fundraising_id := redis_lookup_id_random(record_id_random=fundraising_id, table_name='fundraising'): pass
else: return False
if fundraising_cfg_rec := sql_select(
table_name = 'v_fundraising_cfg',
field_name = 'fundraising_id',
field_value = fundraising_id
): pass
else: return False
log.debug(fundraising_cfg_rec)
try:
fundraising_cfg_obj = Fundraising_Cfg_Base(**fundraising_cfg_rec)
log.debug(fundraising_cfg_obj)
except ValidationError as e:
log.error(e.json())
if model_as_dict:
return fundraising_cfg_obj.dict(by_alias=True, exclude_unset=True) # pylint: disable=no-member
else:
return fundraising_cfg_obj
# ### END ### API Fundraising Cfg Methods ### load_fundraising_cfg_obj() ###
# ### BEGIN ### API Fundraising Cfg Methods ### load_fundraising_cfg_obj_old() ###
# Updated 2022-11-18
def load_fundraising_cfg_obj_old(
account_id: int|str,
model_as_dict: bool = False,
) -> Fundraising_Cfg_Base|dict|bool:
@@ -38,4 +70,4 @@ def load_fundraising_cfg_obj(
return fundraising_cfg_obj.dict(by_alias=True, exclude_unset=True) # pylint: disable=no-member
else:
return fundraising_cfg_obj
# ### END ### API Fundraising Cfg Methods ### load_fundraising_cfg_obj() ###
# ### END ### API Fundraising Cfg Methods ### load_fundraising_cfg_obj_old() ###

View File

@@ -0,0 +1,165 @@
import datetime
from typing import Dict, List, Optional, Set, Union
from pydantic import BaseModel, EmailStr, Field, PrivateAttr, ValidationError, validator
from app.db_sql import redis_lookup_id_random, sql_enable_part, sql_insert, sql_limit_offset_part, sql_select, sql_update
from app.lib_general import log, logging, logger_reset
from app.methods.fundraising_cfg_methods import load_fundraising_cfg_obj
from app.methods.product_methods import get_product_rec_list, load_product_obj
from app.models.fundraising_models import Fundraising_Base
from app.models.fundraising_cfg_models import Fundraising_Cfg_Base
# ### BEGIN ### API Fundraising Cfg Methods ### load_fundraising_obj() ###
# Updated 2022-11-18
def load_fundraising_obj(
fundraising_id: int|str,
inc_fundraising_cfg: bool = False,
inc_product_list: bool = False,
enabled: str = 'enabled', # enabled, disabled, all
limit: int = 100,
offset: int = 0,
model_as_dict: bool = False,
) -> Fundraising_Base|dict|bool:
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
if fundraising_id := redis_lookup_id_random(record_id_random=fundraising_id, table_name='fundraising'): pass
else: return False
if fundraising_rec := sql_select(table_name='v_fundraising', record_id=fundraising_id): pass
else: return False
log.debug(fundraising_rec)
try:
fundraising_obj = Fundraising_Base(**fundraising_rec)
except ValidationError as e:
log.error(e.json())
return False
log.debug(fundraising_obj)
# Updated 2022-11-18
if inc_fundraising_cfg:
log.info('Need to include fundraising configuration...')
if fundraising_cfg_result := load_fundraising_cfg_obj(
fundraising_id = fundraising_id,
# by_alias = by_alias,
# exclude_unset = exclude_unset,
# model_as_dict = model_as_dict,
):
fundraising_obj.fundraising_cfg = fundraising_cfg_result
else: fundraising_obj.fundraising_cfg = {} # None
log.debug(fundraising_obj.fundraising_cfg)
# Updated 2022-11-18
if inc_product_list:
# log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.info('Need to include product list...')
if product_rec_list_result := get_product_rec_list(
for_obj_type = 'fundraising',
for_obj_id = fundraising_id,
enabled = enabled,
):
product_result_list = []
for product_rec in product_rec_list_result:
if load_product_result := load_product_obj(
product_id = product_rec.get('product_id', None),
):
product_result_list.append(load_product_result)
else:
product_result_list.append(None)
log.debug(product_result_list)
fundraising_obj.product_list = product_result_list
elif isinstance(product_rec_list_result, list):
fundraising_obj.product_list = []
else:
fundraising_obj.product_list = None
if model_as_dict:
return fundraising_obj.dict(by_alias=True, exclude_unset=True) # pylint: disable=no-member
else:
return fundraising_obj
# ### END ### API Fundraising Cfg Methods ### load_fundraising_obj() ###
# ### BEGIN ### API Fundraising Cfg Methods ### get_fundraising_rec_list() ###
@logger_reset
def get_fundraising_rec_list(
account_id: str = None,
enabled: str = 'enabled', # enabled, disabled, all
hidden: str = 'not_hidden', # hidden, not_hidden, all
priority: str = 'all', # priority, not_priority, all
limit: int = 100,
offset: int = 0,
) -> list|bool:
log.setLevel(logging.INFO) # 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: pass
data = {}
data['account_id'] = account_id
sql_where_account_id = f'`fundraising`.account_id = :account_id'
sql_hidden = ''
if hidden in ['hidden', 'not_hidden', 'all']:
if hidden == 'hidden':
data['hide'] = True
sql_hidden = f'AND `fundraising`.hide = :hide'
elif hidden == 'not_hidden':
data['hide'] = False
sql_hidden = f'AND `fundraising`.hide = :hide'
elif hidden == 'all':
sql_hidden = ''
sql_priority = ''
if priority in ['priority', 'not_priority', 'all']:
if priority == 'priority':
data['priority'] = True
sql_priority = f'AND `fundraising`.priority = :priority'
elif priority == 'not_priority':
data['priority'] = False
sql_priority = f'AND `fundraising`.priority = :priority'
elif priority == 'all':
sql_priority = ''
sql_enabled, data['enable'] = sql_enable_part(table_name='fundraising', enabled=enabled) # Reasonably safe return str and bool
sql_limit = sql_limit_offset_part(limit=limit, offset=offset) # Reasonably safe return str
sql = f"""
SELECT `fundraising`.id AS 'fundraising_id', `fundraising`.id_random AS 'fundraising_id_random'
FROM `fundraising` AS `fundraising`
WHERE
{sql_where_account_id}
{sql_hidden}
{sql_priority}
{sql_enabled}
ORDER BY `fundraising`.priority DESC, -`fundraising`.sort DESC, `fundraising`.title ASC, `fundraising`.created_on DESC, `fundraising`.updated_on DESC
{sql_limit};
"""
if fundraising_rec_li_result := sql_select(data=data, sql=sql, as_list=True):
fundraising_rec_li = fundraising_rec_li_result
else:
fundraising_rec_li = []
# log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(fundraising_rec_li_result)
log.debug(type(fundraising_rec_li))
log.debug(len(fundraising_rec_li))
return fundraising_rec_li
# ### END ### API Fundraising Cfg Methods ### get_fundraising_rec_list() ###

View File

@@ -13,7 +13,7 @@ from app.models.product_models import Product_Base
# ### BEGIN ### API Product Methods ### load_product_obj() ###
def load_product_obj(
product_id: int|str,
# limit: int = 1000,
by_alias: bool = True,
exclude_unset: bool = True,
model_as_dict: bool = False,

View File

@@ -4,61 +4,65 @@ from typing import Dict, List, Optional, Set, Union
from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator
from app.db_sql import redis_lookup_id_random
from app.lib_general import *
from app.lib_general import log, logging
from app.models.common_field_schema import base_fields, default_num_bytes
# ### BEGIN ### API Fundraising Config Models ### Fundraising_Cfg_Base() ###
class Fundraising_Cfg_Base(BaseModel):
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
id_random: Optional[str] = Field(
**base_fields['fundraising_cfg_id_random'],
alias = 'fundraising_cfg_id_random',
**base_fields['fundraising_id_random'],
alias = 'fundraising_id_random',
)
id: Optional[int] = Field(
#alias = 'fundraising_cfg_id'
#alias = 'fundraising_id'
)
account_id_random: Optional[str]
account_id: Optional[int]
order_thanks: Optional[str]
order_message: Optional[str]
message: Optional[str]
header_html: Optional[str]
start_html: Optional[str]
message_html: Optional[str]
end_html: Optional[str]
footer_html: Optional[str]
order_thanks: Optional[str] # Is this needed here or at all?
order_message: Optional[str] # Is this needed here or at all?
message: Optional[str] # Is this needed here or at all?
enable: Optional[bool]
hide: Optional[bool]
priority: Optional[bool]
sort: Optional[int]
group: Optional[str] # Same or similar as file_purpose?
created_on: Optional[datetime.datetime] = None
updated_on: Optional[datetime.datetime] = None
_processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now)
#@validator('fundraising_cfg_id_random', always=True)
def fundraising_cfg_id_random_copy(cls, v, values, **kwargs):
log.setLevel(logging.WARNING)
log.debug(locals())
if values['id_random']:
return values['id_random']
return None
@validator('id', always=True)
def fundraising_cfg_id_lookup(cls, v, values, **kwargs):
log.setLevel(logging.WARNING)
log.debug(locals())
if values['id_random']:
log.debug(values['id_random'])
return redis_lookup_id_random(record_id_random=values['id_random'], table_name='fundraising_cfg')
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='v_fundraising_cfg') # There is only a view 2022-11-18
return None
@validator('account_id', always=True)
def account_id_lookup(cls, v, values, **kwargs):
log.setLevel(logging.WARNING)
log.debug(locals())
if values['account_id_random']:
return redis_lookup_id_random(record_id_random=values['account_id_random'], table_name='account')
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('account_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='account')
return None
class Config:
underscore_attrs_are_private = True
allow_population_by_field_name = True
fields = base_fields
#Fundraising_Cfg_Base.update_forward_refs()
# ### END ### API Fundraising Config Models ### Fundraising_Cfg_Base() ###

View File

@@ -0,0 +1,81 @@
import datetime, pytz
from typing import Dict, List, Optional, Set, Union
from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator
from app.db_sql import redis_lookup_id_random
from app.lib_general import log, logging
from app.models.common_field_schema import base_fields, default_num_bytes
from app.models.fundraising_cfg_models import Fundraising_Cfg_Base
from app.models.product_models import Product_Base
# ### BEGIN ### API Fundraising Models ### Fundraising_Base() ###
class Fundraising_Base(BaseModel):
log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
id_random: Optional[str] = Field(
**base_fields['fundraising_id_random'],
alias = 'fundraising_id_random',
)
id: Optional[int] = Field(
#alias = 'fundraising_id'
)
account_id_random: Optional[str]
account_id: Optional[int]
title: Optional[str]
summary: Optional[str]
description: Optional[str]
header_html: Optional[str]
start_html: Optional[str]
message_html: Optional[str]
end_html: Optional[str]
footer_html: Optional[str]
enable: Optional[bool]
hide: Optional[bool]
priority: Optional[bool]
sort: Optional[int]
group: Optional[str] # Same or similar as file_purpose?
notes: Optional[str]
created_on: Optional[datetime.datetime] = None
updated_on: Optional[datetime.datetime] = None
# Including convenience data
# This is only for convenience. Probably going to keep unless it causes a problem.
# header_html: Optional[str]
# start_html: Optional[str]
# Including other related objects
fundraising_cfg: Optional[Union[Fundraising_Cfg_Base, None]]
product_list: Optional[list[Product_Base]]
_processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now)
@validator('id', always=True)
def fundraising_cfg_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='v_fundraising_cfg') # There is only a view 2022-11-18
return None
@validator('account_id', always=True)
def account_id_lookup(cls, v, values, **kwargs):
if isinstance(v, int) and v > 0: return v
elif id_random := values.get('account_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='account')
return None
class Config:
underscore_attrs_are_private = True
allow_population_by_field_name = True
fields = base_fields
# ### END ### API Fundraising Models ### Fundraising_Base() ###

View File

@@ -6,8 +6,7 @@ from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationEr
from app.db_sql import redis_lookup_id_random
from app.lib_general import log, logging
from .common_field_schema import base_fields, default_num_bytes
#from .user_models import User_Base
from app.models.common_field_schema import base_fields, default_num_bytes
# ### BEGIN ### API User Role Models ### User_Role_Base() ###

View File

@@ -0,0 +1,83 @@
import datetime, time
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 log, logging, secure_hash_string, verify_secure_hash_string, common_route_params, Common_Route_Params
from app.config import settings
from app.db_sql import sql_insert, sql_update, sql_insert_or_update, sql_select, sql_delete, redis_lookup_id_random
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.fundraising_methods import get_fundraising_rec_list, load_fundraising_obj
# from app.methods.fundraising_cfg_methods import load_fundraising_cfg_obj
from app.models.fundraising_models import Fundraising_Base
from app.models.response_models import Resp_Body_Base, mk_resp
router = APIRouter()
# ### BEGIN ### API Event ### get_account_obj_fundraising_list() ###
# Updated 2021-12-13
@router.get('/account/{account_id}/fundraising/list', response_model=Resp_Body_Base)
async def get_account_obj_fundraising_list(
account_id: str = Query(..., min_length=11, max_length=22),
hidden: str = 'not_hidden', # hidden, not_hidden, all
priority: str = 'all', # priority, not_priority, all
inc_account_cfg: bool = False,
inc_fundraising_cfg: bool = False,
inc_product: bool = False,
inc_product_list: bool = False,
commons: Common_Route_Params = Depends(common_route_params),
):
log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
account_id = commons.x_account_id
# Updated 2021-12-13
if fundraising_rec_list_result := get_fundraising_rec_list(
account_id = account_id,
enabled = commons.enabled,
hidden = hidden,
priority = priority,
limit = commons.limit,
offset = commons.offset,
):
fundraising_result_list = []
for fundraising_rec in fundraising_rec_list_result:
if load_fundraising_result := load_fundraising_obj(
fundraising_id = fundraising_rec.get('fundraising_id', None),
inc_fundraising_cfg = inc_fundraising_cfg,
inc_product_list = inc_product_list,
enabled = commons.enabled,
limit = commons.limit,
offset = commons.offset,
# exclude_unset = commons.exclude_unset,
# model_as_dict = model_as_dict,
):
fundraising_result_list.append(load_fundraising_result)
else:
fundraising_result_list.append(None)
response_data = fundraising_result_list
elif isinstance(fundraising_rec_list_result, list) or fundraising_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
log.debug(response_data)
return mk_resp(data=response_data, response=commons.response)
# ### END ### API Event ### get_account_obj_fundraising_list() ###