def index_loans(request: Request, id: int = 0, after_time: int = 0, before_time: int = 0, borrower_id: int = 0, lender_id: int = 0, includes_user_id: int = 0, borrower_name: str = '', lender_name: str = '', includes_user_name: str = '', principal_cents: int = 0, principal_repayment_cents: int = -1, unpaid: int = -1, repaid: int = -1, format: int = 2, limit: int = 10): id = _zero_to_none(id) after_time = _zero_to_none(after_time) before_time = _zero_to_none(before_time) borrower_id = _zero_to_none(borrower_id) lender_id = _zero_to_none(lender_id) includes_user_id = _zero_to_none(includes_user_id) borrower_name = _blank_to_none(borrower_name) lender_name = _blank_to_none(lender_name) includes_user_name = _blank_to_none(includes_user_name) principal_cents = _zero_to_none(principal_cents) principal_repayment_cents = _neg1_to_none(principal_repayment_cents) unpaid = _neg1_to_none(unpaid) repaid = _neg1_to_none(repaid) limit = _zero_to_none(limit) attempt_request_cost = 5 headers = {'x-request-cost': str(attempt_request_cost)} with LazyItgs() as itgs: auth = find_bearer_token(request) user_id, _, perms = users.helper.get_permissions_from_header( itgs, auth, ratelimit_helper.RATELIMIT_PERMISSIONS) resp = try_handle_deprecated_call(itgs, request, SLUG, user_id=user_id) if resp is not None: return resp if not ratelimit_helper.check_ratelimit(itgs, user_id, perms, attempt_request_cost): return JSONResponse(content=RATELIMIT_RESPONSE.dict(), status_code=429, headers=headers) if limit is not None and (limit < 0 or limit >= 1000): return JSONResponse(content=PHPErrorResponse(errors=[ PHPError( error_type='INVALID_PARAMETER', error_message=( 'Limit must be 0 or a positive integer less than 1000' )) ]).dict(), status_code=400) if limit is None and user_id is None: headers[ 'x-limit-warning'] = 'unauthed requests limit=0 replaced with limit=100' limit = 100 if format not in (0, 1, 2, 3): return JSONResponse(content=PHPErrorResponse(errors=[ PHPError(error_type='INVALID_PARAMETER', error_message=('Format must be 0, 1, 2, or 3')) ]).dict(), status_code=400) loans = Table('loans') if limit is None: real_request_cost = 100 else: real_request_cost = min(100, limit) if format == 0: real_request_cost = math.ceil(math.log(real_request_cost + 1)) elif format < 3: # Cost needs to be greater than loans show real_request_cost = 25 + real_request_cost * 2 else: # We need to ensure the cost is greater than using the /users show # endpoint for getting usernames real_request_cost = 25 + math.ceil(real_request_cost * 4.1) headers['x-request-cost'] = str(attempt_request_cost + real_request_cost) if not ratelimit_helper.check_ratelimit(itgs, user_id, perms, real_request_cost): return JSONResponse(content=RATELIMIT_RESPONSE.dict(), status_code=429, headers=headers) moneys = Table('moneys') principals = moneys.as_('principals') principal_repayments = moneys.as_('principal_repayments') usrs = Table('users') lenders = usrs.as_('lenders') borrowers = usrs.as_('borrowers') query = (Query.from_(loans).where(loans.deleted_at.isnull()).orderby( loans.id, order=Order.desc)) params = [] joins = set() def _add_param(val): params.append(val) return Parameter(f'${len(params)}') def _ensure_principals(): nonlocal query if 'principals' in joins: return joins.add('principals') query = (query.join(principals).on( principals.id == loans.principal_id)) def _ensure_principal_repayments(): nonlocal query if 'principal_repayments' in joins: return joins.add('principal_repayments') query = (query.join(principal_repayments).on( principal_repayments.id == loans.principal_repayment_id)) def _ensure_lenders(): nonlocal query if 'lenders' in joins: return joins.add('lenders') query = (query.join(lenders).on(lenders.id == loans.lender_id)) def _ensure_borrowers(): nonlocal query if 'borrowers' in joins: return joins.add('borrowers') query = (query.join(borrowers).on( borrowers.id == loans.borrower_id)) if id is not None: query = query.where(loans.id == _add_param(id)) if after_time is not None: query = (query.where(loans.created_at > _add_param( datetime.fromtimestamp(after_time / 1000.0)))) if before_time is not None: query = (query.where(loans.created_at < _add_param( datetime.fromtimestamp(before_time / 1000.0)))) if principal_cents is not None: _ensure_principals() query = (query.where( principals.amount_usd_cents == _add_param(principal_cents))) if principal_repayment_cents is not None: _ensure_principal_repayments() query = (query.where(principal_repayments.amount_usd_cents == _add_param(principal_repayment_cents))) if borrower_id is not None: query = (query.where(loans.borrower_id == _add_param(borrower_id))) if lender_id is not None: query = (query.where(loans.lender_id == _add_param(lender_id))) if includes_user_id is not None: prm = _add_param(includes_user_id) query = (query.where((loans.borrower_id == prm) | (loans.lender_id == prm))) if borrower_name is not None: _ensure_borrowers() query = (query.where( borrowers.username == _add_param(borrower_name.lower()))) if lender_name is not None: _ensure_lenders() query = (query.where( lenders.username == _add_param(lender_name.lower()))) if includes_user_name is not None: _ensure_lenders() _ensure_borrowers() prm = _add_param(includes_user_name) query = (query.where((lenders.username == prm) | (borrowers.username == prm))) if unpaid is not None: if unpaid: query = query.where(loans.unpaid_at.notnull()) else: query = query.where(loans.unpaid_at.isnull()) if repaid is not None: if repaid: query = query.where(loans.repaid_at.notnull()) else: query = query.where(loans.repaid_at.isnull()) if limit is not None: query = query.limit(limit) query = query.select(loans.id) if format > 0: _ensure_principals() _ensure_principal_repayments() event_tables = (Table('loan_repayment_events'), Table('loan_unpaid_events'), Table('loan_admin_events')) latest_events = Table('latest_events') query = (query.with_( Query.from_(loans).select( loans.id.as_('loan_id'), Greatest(loans.created_at, *(tbl.created_at for tbl in event_tables )).as_('latest_event_at')).groupby(loans.id), 'latest_events').left_join(latest_events).on( latest_events.loan_id == loans.id).select( loans.lender_id, loans.borrower_id, principals.amount_usd_cents, principal_repayments.amount_usd_cents, (Case().when( loans.unpaid_at.isnull(), 'false').else_('true')), Cast( Extract('epoch', loans.created_at) * 1000, 'bigint'), Cast( Extract('epoch', latest_events.latest_event_at) * 1000, 'bigint'))) if format == 3: creation_infos = Table('loan_creation_infos') _ensure_borrowers() _ensure_lenders() query = (query.join(creation_infos).on( creation_infos.loan_id == loans.id).select( Function('SUBSTRING', creation_infos.parent_fullname, 4), Function('SUBSTRING', creation_infos.comment_fullname, 4), lenders.username, borrowers.username)) sql, args = convert_numbered_args(query.get_sql(), params) headers['Cache-Control'] = 'public, max-age=600' if format == 0: return _UltraCompactResponse((sql, args), headers, 'LOANS_ULTRACOMPACT') elif format == 1: return _CompactResponse((sql, args), headers, 'LOANS_COMPACT') elif format == 2: return _StandardResponse((sql, args), headers, 'LOANS_STANDARD') else: return _ExtendedResponse((sql, args), headers, 'LOANS_EXTENDED')
def extract_microsecond_equal(field: Term, value: int) -> Criterion: return Extract(DatePart.microsecond, field).eq(value)
def extract_minute_equal(field: Term, value: int) -> Criterion: return Extract(DatePart.minute, field).eq(value)
def extract_hour_equal(field: Term, value: int) -> Criterion: return Extract(DatePart.hour, field).eq(value)
def extract_day_equal(field: Term, value: int) -> Criterion: return Extract(DatePart.day, field).eq(value)
def extract_week_equal(field: Term, value: int) -> Criterion: return Extract(DatePart.week, field).eq(value)