Files
Fulfillment-Backend/services/statistics/expenses_statistics.py
2024-12-12 20:23:19 +04:00

64 lines
2.2 KiB
Python

from datetime import date
from sqlalchemy import select, func, Subquery, cast, CTE
from sqlalchemy.dialects.postgresql import TIMESTAMP
from models import PaymentRecord
from schemas.statistics import CommonProfitFilters
from services.base import BaseService
from services.statistics.common import generate_date_range
class PaymentStatisticsService(BaseService):
date_from: date
date_to: date
@staticmethod
def _fill_date_gaps(payments: Subquery, all_dates: CTE) -> Subquery:
return (
select(
all_dates.c.date,
(all_dates.c.expenses + func.coalesce(payments.c.expenses, 0)).label("expenses"),
)
.join(payments, all_dates.c.date == payments.c.date, isouter=True)
.order_by(all_dates.c.date)
.subquery()
)
def _get_payment_records_sub(self) -> Subquery:
all_dates = generate_date_range(self.date_from, self.date_to, ["expenses"])
expenses = (
select(
func.sum(PaymentRecord.amount).label("expenses"),
cast(PaymentRecord.start_date, TIMESTAMP(timezone=False)).label("date"),
)
.group_by("date")
.subquery()
)
expenses_with_filled_gaps = self._fill_date_gaps(expenses, all_dates)
return expenses_with_filled_gaps
@staticmethod
def _apply_payments(deals_by_dates: Subquery, expenses_subquery: Subquery):
return (
select(
deals_by_dates.c.date,
deals_by_dates.c.deals_count,
deals_by_dates.c.revenue,
(func.coalesce(deals_by_dates.c.profit, 0) - func.coalesce(expenses_subquery.c.expenses, 0))
.label("profit"),
(deals_by_dates.c.expenses + expenses_subquery.c.expenses).label("expenses"),
)
.join(expenses_subquery, expenses_subquery.c.date == deals_by_dates.c.date)
)
def apply_payments(self, filters: CommonProfitFilters, deals_by_dates: Subquery):
self.date_from, self.date_to = filters.date_range
salary_expenses = self._get_payment_records_sub()
deals_by_dates = self._apply_payments(deals_by_dates, salary_expenses)
return deals_by_dates