darkor

/overview/grouped - final

Mar 12th, 2023
1,054
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.24 KB | None | 0 0
  1. @subscriptions_api.route("/overview/grouped")
  2. class SubscriptionsOverviewGrouped(Resource):
  3.  
  4.     @subscriptions_api.doc("Overview groups of subscriptions")
  5.     @subscriptions_api.marshal_with(SubscriptionModel.subscriptions_overview_grouped_model)
  6.     @authorize_employee
  7.     def get(self):
  8.         """Overview groups of subscriptions"""
  9.         kwargs = {"company_id": request.employee.company_id}
  10.         if request.employee.role != UserRolesEnum.ADMIN.value:
  11.             kwargs["employee_email"] = request.employee.email
  12.  
  13.         current_date, services = datetime.now(), []
  14.         max_day = monthrange(current_date.year, current_date.month)[1]
  15.  
  16.         response = {"variations": [], "upcoming": [], "failed": []}
  17.         variations = {}
  18.  
  19.         subscriptions = list(get_subscriptions_for_overview(**kwargs))
  20.  
  21.         subscriptions_v2 = []
  22.         for subs in subscriptions:
  23.             skip = True  # skip adding the original item as is to result
  24.  
  25.             if subs.get("billed") == SubscriptionBilledEnum.MONTHLY.value:
  26.                 ytg = copy.deepcopy(subs.get("ytg"))
  27.  
  28.                 if current_month_ytg := (ytg or {}).get(str(current_date.year), {}).get(str(current_date.month), {}):
  29.                     del ytg[str(current_date.year)][str(current_date.month)]
  30.                     skip = False
  31.                     if not ytg[str(current_date.year)]:
  32.                         del ytg[str(current_date.year)]
  33.  
  34.                 if ytg:
  35.                     year_data = ytg.get(max(ytg, key=int))
  36.                     month_data = year_data.get(max(year_data, key=int))
  37.  
  38.                     flag_add_to_result = False
  39.                     for day, money in month_data.items():
  40.                         if int(day) > current_date.day:
  41.                             # case: payment incoming
  42.                             flag_add_to_result = True
  43.  
  44.                         elif int(day) < current_date.day and current_month_ytg.get(str(min(int(day), max_day))) is None:
  45.                             # case: payment failed (second check is just to be sure the payment was not happened)
  46.                             flag_add_to_result = True
  47.  
  48.                         elif (
  49.                             int(day) == current_date.day
  50.                             and datetime.fromtimestamp(subs.get("last_payment_date")).date() != current_date.date()
  51.                         ):
  52.                             # case: payment incoming
  53.                             flag_add_to_result = True
  54.  
  55.                         if flag_add_to_result:
  56.                             subscriptions_v2.append({
  57.                                 **subs,
  58.                                 "next_payment": datetime(
  59.                                     current_date.year, current_date.month, min(int(day), max_day)
  60.                                 ).timestamp(),
  61.                                 "last_payment": money,
  62.                                 "last_payment_date": 0,  # to avoid getting into "variation" list
  63.                             })
  64.  
  65.                 elif not subs.get("next_payment") and subs.get("expected_first_payment"):
  66.                     subs_day = datetime.fromtimestamp(subs.get("expected_first_payment")).day
  67.                     if int(subs_day) > current_date.day:
  68.                         subscriptions_v2.append({
  69.                             **subs,
  70.                             "next_payment": datetime(
  71.                                 current_date.year, current_date.month, min(subs_day, max_day)
  72.                             ).timestamp(),
  73.                             "last_payment": subs.get("budget_limit"),
  74.                             "last_payment_date": 0,  # to avoid getting into "variation" list
  75.                         })
  76.                     else:
  77.                         skip = False  # we should add this item without changing, to let goes to "failed"
  78.  
  79.                 # in case there is spending this month we should add it to list and then to "variation" list
  80.                 if skip:
  81.                     continue
  82.  
  83.             subscriptions_v2.append(subs)
  84.  
  85.         for subscription in subscriptions_v2:
  86.             last_payment = subscription.get("last_payment", 0)
  87.             last_payment_date, ytg = subscription.get("last_payment_date", 0), subscription.get("ytg", {})
  88.  
  89.             next_payment = subscription.get("next_payment", subscription.get("expected_first_payment", None))
  90.  
  91.             services.append(subscription.get("service"))
  92.  
  93.             if last_payment is None or next_payment is None:
  94.                 continue
  95.  
  96.             # add upcoming
  97.             if last_payment_date < int(current_date.timestamp()) < next_payment:
  98.                 billed, payment_date = subscription.get("billed"), datetime.fromtimestamp(last_payment_date)
  99.  
  100.                 variation, current_period, previous_period = False, 0, 0
  101.                 if billed == SubscriptionBilledEnum.WEEKLY.value:
  102.                     if (
  103.                         payment_date.year == current_date.year
  104.                         and payment_date.isocalendar()[1] == current_date.isocalendar()[1]
  105.                     ):
  106.                         variation = True
  107.  
  108.                         try:
  109.                             last_week_date = current_date - relativedelta(days=7)
  110.                             last_week_dates = [
  111.                                 last_week_date + timedelta(days=i)
  112.                                 for i in range(0 - last_week_date.weekday(), 7 - last_week_date.weekday())
  113.                             ]
  114.  
  115.                             for date in last_week_dates:
  116.                                 previous_period += (
  117.                                     ytg.get(str(date.year), {}).get(str(date.month), {}).get(str(date.day), 0)
  118.                                 )
  119.  
  120.                             current_week_dates = [
  121.                                 current_date + timedelta(days=i)
  122.                                 for i in range(0 - current_date.weekday(), 7 - current_date.weekday())
  123.                             ]
  124.  
  125.                             for date in current_week_dates:
  126.                                 current_period += (
  127.                                     ytg.get(str(date.year), {}).get(str(date.month), {}).get(str(date.day), 0)
  128.                                 )
  129.  
  130.                         except Exception as e:
  131.                             print(e)
  132.  
  133.                 elif billed == SubscriptionBilledEnum.MONTHLY.value:
  134.                     if payment_date.year == current_date.year and payment_date.month == current_date.month:
  135.                         variation = True
  136.  
  137.                         try:
  138.                             last_month_date = current_date - relativedelta(months=1)
  139.                             previous_period = sum(ytg.get(last_month_date.year, {}).get(last_month_date.month).values())
  140.                             current_period = sum(ytg.get(current_date.year, {}).get(current_date.month).values())
  141.  
  142.                         except Exception as e:
  143.                             print(e)
  144.  
  145.                 elif billed == SubscriptionBilledEnum.YEARLY.value:
  146.                     if payment_date.year == current_date.year:
  147.                         variation = True
  148.  
  149.                         try:
  150.                             last_year_date = current_date - relativedelta(years=1)
  151.                             for month in ytg.get(str(last_year_date.year)):
  152.                                 previous_period += sum(month.values())
  153.  
  154.                             for month in ytg.get(str(current_date.year)):
  155.                                 current_period += sum(month.values())
  156.  
  157.                         except Exception as e:
  158.                             print(e)
  159.  
  160.                 if variation:
  161.                     subscription = {
  162.                         "trend": calculate_trend(current_month=current_period, previous_month=previous_period),
  163.                         "variation": current_period - previous_period,
  164.                         **subscription,
  165.                     }
  166.  
  167.                     variations[subscription.get("subscription_id")] = subscription
  168.  
  169.                 else:
  170.                     response["upcoming"].append({
  171.                         **subscription,
  172.                         "next_payment": next_payment,
  173.                         "expected_payment": subscription.get("last_payment") or subscription.get("budget_limit")
  174.                     })
  175.  
  176.             # add failed
  177.             else:
  178.                 response["failed"].append(subscription)
  179.  
  180.         response["variations"] = list(variations.values())
  181.  
  182.         services_dict = get_services(services=services)
  183.         for collection in response.keys():
  184.             for item in response[collection]:
  185.                 if isinstance(item["service"], str):
  186.                     item["service"] = services_dict.get(item.get("service"))
  187.  
  188.         new_items = extend_subscriptions_list(subscriptions=subscriptions[0:5], company_id=request.employee.company_id)
  189.         for item in new_items:
  190.             budget_limit = item.get("budget_limit", None)
  191.  
  192.             if item.get("last_payment", None) == Decimal(0) and budget_limit is not None:
  193.                 item["last_payment"] = budget_limit
  194.  
  195.         response["upcoming"].sort(key=lambda x: x["next_payment"])
  196.  
  197.         return {"new": new_items, **response}
Advertisement
Add Comment
Please, Sign In to add comment