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 from app.log import log, logging
# Import the routers here first: # 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 from app.db_sql import db, sql_select # , sql_connect
@@ -226,7 +226,6 @@ app.include_router(
) )
app.include_router( app.include_router(
event_person_tracking.router, event_person_tracking.router,
# prefix='/event/person/tracking',
tags=['Event Person Tracking'], tags=['Event Person Tracking'],
) )
app.include_router( app.include_router(
@@ -249,6 +248,10 @@ app.include_router(
# prefix='/event/session', # prefix='/event/session',
tags=['Event Session'], tags=['Event Session'],
) )
app.include_router(
fundraising.router,
tags=['Fundraising'],
)
app.include_router( app.include_router(
hosted_file.router, hosted_file.router,
prefix='/hosted_file', prefix='/hosted_file',

View File

@@ -41,7 +41,7 @@ def load_account_cfg_obj(
log.error(e.json()) log.error(e.json())
if inc_fundraising_cfg: 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, account_id = account_id,
model_as_dict = model_as_dict, model_as_dict = model_as_dict,
): ):

View File

@@ -1,17 +1,49 @@
from __future__ import annotations
import datetime import datetime
from typing import Dict, List, Optional, Set, Union from typing import Dict, List, Optional, Set, Union
from pydantic import BaseModel, EmailStr, Field, PrivateAttr, ValidationError, validator from pydantic import BaseModel, EmailStr, Field, PrivateAttr, ValidationError, validator
from app.db_sql import redis_lookup_id_random, sql_select 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 from app.lib_general import log, logging, logger_reset
from app.models.fundraising_cfg_models import Fundraising_Cfg_Base from app.models.fundraising_cfg_models import Fundraising_Cfg_Base
# ### BEGIN ### API Fundraising Cfg Methods ### load_fundraising_cfg_obj() ### # ### BEGIN ### API Fundraising Cfg Methods ### load_fundraising_cfg_obj() ###
# Updated 2022-11-18
def load_fundraising_cfg_obj( 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, account_id: int|str,
model_as_dict: bool = False, model_as_dict: bool = False,
) -> Fundraising_Cfg_Base|dict|bool: ) -> 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 return fundraising_cfg_obj.dict(by_alias=True, exclude_unset=True) # pylint: disable=no-member
else: else:
return fundraising_cfg_obj 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() ### # ### BEGIN ### API Product Methods ### load_product_obj() ###
def load_product_obj( def load_product_obj(
product_id: int|str, product_id: int|str,
# limit: int = 1000,
by_alias: bool = True, by_alias: bool = True,
exclude_unset: bool = True, exclude_unset: bool = True,
model_as_dict: bool = False, 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 pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator
from app.db_sql import redis_lookup_id_random 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 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): 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()) log.debug(locals())
id_random: Optional[str] = Field( id_random: Optional[str] = Field(
**base_fields['fundraising_cfg_id_random'], **base_fields['fundraising_id_random'],
alias = 'fundraising_cfg_id_random', alias = 'fundraising_id_random',
) )
id: Optional[int] = Field( id: Optional[int] = Field(
#alias = 'fundraising_cfg_id' #alias = 'fundraising_id'
) )
account_id_random: Optional[str] account_id_random: Optional[str]
account_id: Optional[int] account_id: Optional[int]
order_thanks: Optional[str] header_html: Optional[str]
order_message: Optional[str] start_html: Optional[str]
message: 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) _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) @validator('id', always=True)
def fundraising_cfg_id_lookup(cls, v, values, **kwargs): def fundraising_cfg_id_lookup(cls, v, values, **kwargs):
log.setLevel(logging.WARNING) if isinstance(v, int) and v > 0: return v
log.debug(locals()) 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
if values['id_random']:
log.debug(values['id_random'])
return redis_lookup_id_random(record_id_random=values['id_random'], table_name='fundraising_cfg')
return None return None
@validator('account_id', always=True) @validator('account_id', always=True)
def account_id_lookup(cls, v, values, **kwargs): def account_id_lookup(cls, v, values, **kwargs):
log.setLevel(logging.WARNING) if isinstance(v, int) and v > 0: return v
log.debug(locals()) elif id_random := values.get('account_id_random'):
return redis_lookup_id_random(record_id_random=id_random, table_name='account')
if values['account_id_random']:
return redis_lookup_id_random(record_id_random=values['account_id_random'], table_name='account')
return None return None
class Config: class Config:
underscore_attrs_are_private = True underscore_attrs_are_private = True
allow_population_by_field_name = True
fields = base_fields fields = base_fields
# ### END ### API Fundraising Config Models ### Fundraising_Cfg_Base() ###
#Fundraising_Cfg_Base.update_forward_refs()

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.db_sql import redis_lookup_id_random
from app.lib_general import log, logging from app.lib_general import log, logging
from .common_field_schema import base_fields, default_num_bytes from app.models.common_field_schema import base_fields, default_num_bytes
#from .user_models import User_Base
# ### BEGIN ### API User Role Models ### User_Role_Base() ### # ### 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() ###