Skip to content
Snippets Groups Projects
hall_contract.py 7.12 KiB
Newer Older
# Copyright 2023 Le Filament (https://le-filament.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)

from datetime import date

from dateutil.relativedelta import relativedelta

from odoo import api, fields, models


class HallContract(models.Model):
    _inherit = "hall.contract"

    # ------------------------------------------------------
    # Fields declaration
    # ------------------------------------------------------

    # ------------------------------------------------------
    # SQL Constrains
    # ------------------------------------------------------

    # ------------------------------------------------------
    # Compute functions
    # ------------------------------------------------------

    # ------------------------------------------------------
    # Action buttons
    # ------------------------------------------------------
    def show_overview(self):
        """
        Affiche le tableau de bors pour un contrat
        """
        self.ensure_one()
        action = self.env["ir.actions.actions"]._for_xml_id(
            "festa_dashboard.hall_contract_overview_action"
        )
        action["context"] = {
            "active_id": self.id,
            "active_ids": self.ids,
            "active_test": False,
            "search_default_display_name": self.display_name,
        }
        return action

    @api.model
    def update_cashpad_values(self):
        """
        Fonction de mise à jour de chargement des ventes depuis le Dashboard
        """
        self.search([("cashpad_id", "!=", False)]).get_sales()

    # ------------------------------------------------------
    # Common functions
    # ------------------------------------------------------
    def is_running(self, date_filter):
        """
        Fonction permettant de calculer si un contrat est en cours à une date donnée
        :param date date_filter: date de référence
        """
        self.ensure_one()
        if self.date_start <= date_filter and not self.date_end:
            return True
        elif self.date_start <= date_filter <= self.date_end:
            return True
        else:
            return False

    def get_overview(self):
        """
        Retourne les données pour la vue Qweb du Dashboard
        """
        job_ids = (
            self.env["queue.job"]
            .sudo()
            .search(
                [
                    ("model_name", "=", "hall.contract"),
                    ("method_name", "=", "_import_sales"),
                    ("state", "in", ["pending", "enqueued", "started", "failed"]),
                ]
            )
        )
        return {
            "contract_ids": self,
            "hall_ids": self.mapped("hall_id"),
            "company_id": self.env.company,
            "sales": self.get_overview_sales(),
            "flow": self.get_overview_flow(),
    def get_overview_flow(self):
        """
        Get visitor & Passerby data
        """
        yesterday = date.today() - relativedelta(days=1)
        start_year = date(yesterday.year, 1, 1)
        date(yesterday.year, yesterday.month, 1)
        flow_ids = self.env["hall.flow"].search(
            [
                ("hall_id", "in", self.mapped("hall_id").ids),
                ("date", ">=", start_year),
            ]
        )
        visitor_ids = flow_ids.filtered(lambda f: f.flow_type == "visitor")
        passerby_ids = flow_ids.filtered(lambda f: f.flow_type == "passerby")
        return {
            "visitor_ids": visitor_ids,
            "passerby_ids": passerby_ids,
        }

    def get_overview_sales(self):
        """
        Données de la vue QWEB des indicateurs CA
        today = date.today()
        yesterday = date.today() - relativedelta(days=1)
        start_year = date(yesterday.year, 1, 1)
        start_month = date(yesterday.year, yesterday.month, 1)
        start_last_month = start_month - relativedelta(months=1)
        end_last_month = start_month - relativedelta(days=1)
        return {
            "yesterday": self._get_sale_amount(yesterday, yesterday),
            "last_year": self._get_sale_amount(
                yesterday.replace(year=yesterday.year - 1),
                yesterday.replace(year=yesterday.year - 1),
            ),
            "this_month": self._get_sale_amount(start_month, today),
            "last_month": self._get_sale_amount(start_last_month, end_last_month),
            "this_year": self._get_sale_amount(start_year, today),
            "target_month": self._get_target(today.year, today.month),
            "target_last_month": self._get_target(
                start_last_month.year, start_last_month.month
            ),
            "target_year": self._get_target(today.year),
            "revenue_detail": self._get_revenue_detail(),
            "day": yesterday,
            "month": start_month,
            "year": start_year,
        }

    def _get_sale_amount(self, start, end):
        """
        Retourne le montant HT des ventes en fonction de dates pour des contrats

        :param start date:
        :param end date:
        @returns float amount untaxed
        """
        sale_ids = self.sale_ids.search(
            [
                ("contract_id", "in", self.ids),
                ("day_date", ">=", start),
                ("day_date", "<=", end),
                ("is_test_datas", "=", False),
            ]
        )
        total_sales = sum(sale_ids.mapped("sales_excl_taxes"))
        total_receipts = sum(sale_ids.mapped("nb_receipts"))
        average_sales = total_sales / total_receipts if total_receipts > 0 else 0
        return {
            "total_sales": total_sales,
            "total_receipts": total_receipts,
            "average_sales": average_sales,
        }

    def _get_target(self, year, month=None):
        """
        Retourne le CA cible pour une année ou un mois donné
        :param int year: année
        :param int month: mois
        @returns monetary target: montant cible
        """
        granularity = "month" if month else "year"
        month = month if month else 1
        start = date(year, month, 1)
        end = fields.Date.end_of(start, granularity)
        target_ids = self.target_ids.search(
            [
                ("contract_id", "in", self.ids),
                ("date_target", ">=", start),
                ("date_target", "<=", end),
            ]
        )
        return sum(target_ids.mapped("amount_untaxed_target"))

    def _get_revenue_detail(self):
        """
        Retourne le détail du CA pour un contrat pour permettre l'affichage
        détaillé par mois
        Retourne False si il y a plus d'un contrat dans self
        """
        if len(self) != 1:
            return False

        today = fields.Date.today()
        start = today.replace(day=1) - relativedelta(months=12)
        end = today.replace(day=1)
        target_report_ids = self.env["hall.contract.target.report"].search(
            [
                ("contract_id", "=", self.id),
                ("day_date", ">=", start),
                ("day_date", "<=", end),
            limit=12,
        )
        return target_report_ids