Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- @subscriptions_api.route("/overview/grouped")
- class SubscriptionsOverviewGrouped(Resource):
- @subscriptions_api.doc("Overview groups of subscriptions")
- @subscriptions_api.marshal_with(SubscriptionModel.subscriptions_overview_grouped_model)
- @authorize_employee
- def get(self):
- """Overview groups of subscriptions"""
- kwargs = {"company_id": request.employee.company_id}
- if request.employee.role != UserRolesEnum.ADMIN.value:
- kwargs["employee_email"] = request.employee.email
- current_date, services = datetime.now(), []
- max_day = monthrange(current_date.year, current_date.month)[1]
- response = {"variations": [], "upcoming": [], "failed": []}
- variations = {}
- subscriptions = list(get_subscriptions_for_overview(**kwargs))
- subscriptions_v2 = []
- for subs in subscriptions:
- skip = True # skip adding the original item as is to result
- if subs.get("billed") == SubscriptionBilledEnum.MONTHLY.value:
- ytg = copy.deepcopy(subs.get("ytg"))
- if current_month_ytg := (ytg or {}).get(str(current_date.year), {}).get(str(current_date.month), {}):
- del ytg[str(current_date.year)][str(current_date.month)]
- skip = False
- if not ytg[str(current_date.year)]:
- del ytg[str(current_date.year)]
- if ytg:
- year_data = ytg.get(max(ytg, key=int))
- month_data = year_data.get(max(year_data, key=int))
- flag_add_to_result = False
- for day, money in month_data.items():
- if int(day) > current_date.day:
- # case: payment incoming
- flag_add_to_result = True
- elif int(day) < current_date.day and current_month_ytg.get(str(min(int(day), max_day))) is None:
- # case: payment failed (second check is just to be sure the payment was not happened)
- flag_add_to_result = True
- elif (
- int(day) == current_date.day
- and datetime.fromtimestamp(subs.get("last_payment_date")).date() != current_date.date()
- ):
- # case: payment incoming
- flag_add_to_result = True
- if flag_add_to_result:
- subscriptions_v2.append({
- **subs,
- "next_payment": datetime(
- current_date.year, current_date.month, min(int(day), max_day)
- ).timestamp(),
- "last_payment": money,
- "last_payment_date": 0, # to avoid getting into "variation" list
- })
- elif not subs.get("next_payment") and subs.get("expected_first_payment"):
- subs_day = datetime.fromtimestamp(subs.get("expected_first_payment")).day
- if int(subs_day) > current_date.day:
- subscriptions_v2.append({
- **subs,
- "next_payment": datetime(
- current_date.year, current_date.month, min(subs_day, max_day)
- ).timestamp(),
- "last_payment": subs.get("budget_limit"),
- "last_payment_date": 0, # to avoid getting into "variation" list
- })
- else:
- skip = False # we should add this item without changing, to let goes to "failed"
- # in case there is spending this month we should add it to list and then to "variation" list
- if skip:
- continue
- subscriptions_v2.append(subs)
- for subscription in subscriptions_v2:
- last_payment = subscription.get("last_payment", 0)
- last_payment_date, ytg = subscription.get("last_payment_date", 0), subscription.get("ytg", {})
- next_payment = subscription.get("next_payment", subscription.get("expected_first_payment", None))
- services.append(subscription.get("service"))
- if last_payment is None or next_payment is None:
- continue
- # add upcoming
- if last_payment_date < int(current_date.timestamp()) < next_payment:
- billed, payment_date = subscription.get("billed"), datetime.fromtimestamp(last_payment_date)
- variation, current_period, previous_period = False, 0, 0
- if billed == SubscriptionBilledEnum.WEEKLY.value:
- if (
- payment_date.year == current_date.year
- and payment_date.isocalendar()[1] == current_date.isocalendar()[1]
- ):
- variation = True
- try:
- last_week_date = current_date - relativedelta(days=7)
- last_week_dates = [
- last_week_date + timedelta(days=i)
- for i in range(0 - last_week_date.weekday(), 7 - last_week_date.weekday())
- ]
- for date in last_week_dates:
- previous_period += (
- ytg.get(str(date.year), {}).get(str(date.month), {}).get(str(date.day), 0)
- )
- current_week_dates = [
- current_date + timedelta(days=i)
- for i in range(0 - current_date.weekday(), 7 - current_date.weekday())
- ]
- for date in current_week_dates:
- current_period += (
- ytg.get(str(date.year), {}).get(str(date.month), {}).get(str(date.day), 0)
- )
- except Exception as e:
- print(e)
- elif billed == SubscriptionBilledEnum.MONTHLY.value:
- if payment_date.year == current_date.year and payment_date.month == current_date.month:
- variation = True
- try:
- last_month_date = current_date - relativedelta(months=1)
- previous_period = sum(ytg.get(last_month_date.year, {}).get(last_month_date.month).values())
- current_period = sum(ytg.get(current_date.year, {}).get(current_date.month).values())
- except Exception as e:
- print(e)
- elif billed == SubscriptionBilledEnum.YEARLY.value:
- if payment_date.year == current_date.year:
- variation = True
- try:
- last_year_date = current_date - relativedelta(years=1)
- for month in ytg.get(str(last_year_date.year)):
- previous_period += sum(month.values())
- for month in ytg.get(str(current_date.year)):
- current_period += sum(month.values())
- except Exception as e:
- print(e)
- if variation:
- subscription = {
- "trend": calculate_trend(current_month=current_period, previous_month=previous_period),
- "variation": current_period - previous_period,
- **subscription,
- }
- variations[subscription.get("subscription_id")] = subscription
- else:
- response["upcoming"].append({
- **subscription,
- "next_payment": next_payment,
- "expected_payment": subscription.get("last_payment") or subscription.get("budget_limit")
- })
- # add failed
- else:
- response["failed"].append(subscription)
- response["variations"] = list(variations.values())
- services_dict = get_services(services=services)
- for collection in response.keys():
- for item in response[collection]:
- if isinstance(item["service"], str):
- item["service"] = services_dict.get(item.get("service"))
- new_items = extend_subscriptions_list(subscriptions=subscriptions[0:5], company_id=request.employee.company_id)
- for item in new_items:
- budget_limit = item.get("budget_limit", None)
- if item.get("last_payment", None) == Decimal(0) and budget_limit is not None:
- item["last_payment"] = budget_limit
- response["upcoming"].sort(key=lambda x: x["next_payment"])
- return {"new": new_items, **response}
Advertisement
Add Comment
Please, Sign In to add comment