# © 2019 Le Filament (<http://www.le-filament.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).


import logging
import time
from datetime import datetime, timedelta

from odoo import _, api, fields, models
from odoo.exceptions import UserError, ValidationError
from lxml import etree

_logger = logging.getLogger(__name__)


class ScopPartner(models.Model):
    _inherit = "res.partner"

    def _default_ur(self):
        return self.env["res.company"]._ur_default_get()

    def _default_country(self):
        return self.env.ref("base.fr", False)

    @api.model
    def _get_domain_incubator_id(self):
        try:
            incubator_id = self.env.ref("cgscop_partner.incubator").id
            return [
                ("is_company", "=", True),
                ("organization_subtype_id", "=", incubator_id),
            ]
        except Exception:
            return [("is_company", "=", True)]

    @api.model
    def _get_domain_revision_company_id(self):
        try:
            rev_id = self.env.ref("cgscop_partner.riga_14953").id
            com_id = self.env.ref("cgscop_partner.riga_16433").id
            return [
                ("is_company", "=", True),
                ("organization_subtype_id", "in", [com_id, rev_id]),
            ]
        except Exception:
            return [("is_company", "=", True)]

    # Inherit parent
    active = fields.Boolean(
        tracking=True,
    )

    # Infos générales - champs non affichés
    is_cooperative = fields.Boolean("Est une coopérative")
    parent_is_cooperative = fields.Boolean(
        string="Parent est une coopérative",
        related="parent_id.is_cooperative",
    )
    current_user_ur_id = fields.Many2one(
        "union.regionale",
        string="Union Régionale de l'utilisateur",
        compute="_compute_current_user_ur_id",
        search="_search_current_user_ur_id",
    )

    # Informations organisme - champs non affichés
    id_ur = fields.Char("Identifiant UR")

    # Informations Bandeau
    project_status = fields.Selection(
        [
            ("1_information", "Phase d'information"),
            ("2_pre-diagnostic", "Phase de pré-diagnostic"),
            ("3_accompagnement", "Phase d'accompagnement projet"),
            ("4_suivi", "Phase de suivi"),
            ("5_abandonne", "Projet abandonné"),
            ("6_decede", "Coop Décédée"),
        ],
        tracking=True,
        string="Statut projet",
        index=True,
    )
    name = fields.Char(index=True, tracking=True, string="Dénomination Sociale")
    nickname = fields.Char(string="Dénomination interne")
    cooperative_form_id = fields.Many2one(
        "res.partner.cooperative.form",
        string="Cooperative form",
        ondelete="restrict",
        tracking=True,
    )
    partner_company_type_id = fields.Many2one(
        comodel_name="res.partner.company.type",
        string="Statut Juridique",
        ondelete="restrict",
        tracking=True,
    )

    membership_status = fields.Selection(
        [
            ("not_member", "Non Adhérent"),
            ("adhesion", "Phase d'Adhésion"),
            ("soumis_cg", "Soumis CG"),
            ("member", "Adhérent"),
            ("out", "Radié"),
        ],
        string="Statut d'adhésion",
        default="not_member",
        tracking=True,
    )
    member_number = fields.Char(
        "No adhérent (texte)", compute="_compute_membership_number", store=True
    )
    member_number_int = fields.Integer(
        "No adhérent",
        group_operator="",
    )
    member_start = fields.Date(
        "Date d'adhésion", compute="_compute_membership", store=True
    )
    cae = fields.Boolean("CAE", tracking=True)

    dissolution_date = fields.Date("Date de Décès", tracking=True)
    dissolution_reason_id = fields.Many2one(
        "res.partner.dissolution.reason",
        string="Motif Décès",
        ondelete="restrict",
        tracking=True,
    )

    # Infos générales / Contact
    sigle = fields.Char("Sigle")
    street = fields.Char("Rue", tracking=1)
    street2 = fields.Char("Rue 2", tracking=1)
    street3 = fields.Char("Rue 3", tracking=1)
    zip = fields.Char("CP", change_default=True, tracking=1)
    zip_departement = fields.Char(
        "Num Département", compute="_compute_num_departement", store=True
    )
    region = fields.Many2one(
        comodel_name="res.country.state",
        string="Région",
        compute="_compute_region",
        store=True,
    )
    city = fields.Char("Ville", tracking=1)
    cedex = fields.Char("Cedex", tracking=1)
    country_id = fields.Many2one(
        "res.country",
        string="Pays",
        ondelete="restrict",
        default=_default_country,
        tracking=True,
    )
    # Adresse postale
    postal_street = fields.Char("Adresse postale - Rue", tracking=1)
    postal_street2 = fields.Char("Adresse postale - Rue 2", tracking=1)
    postal_street3 = fields.Char("Adresse postale - Rue 3", tracking=1)
    postal_zip = fields.Char("Adresse postale - CP", tracking=1)
    postal_city = fields.Char("Adresse postale - Ville", tracking=1)
    postal_cedex = fields.Char("Adresse postale - Cedex", tracking=1)
    phone = fields.Char("Téléphone 1", tracking=True)
    mobile = fields.Char("Téléphone 2", tracking=True)
    email = fields.Char("eMail administratif", tracking=True)
    facebook = fields.Char("Facebook")
    linkedin = fields.Char("LinkedIn")
    twitter = fields.Char("Twitter")
    instagram = fields.Char("Instagram")

    # Infos générales / Suivi UR
    ur_id = fields.Many2one(
        "union.regionale",
        string="Union Régionale",
        index=True,
        ondelete="restrict",
        default=_default_ur,
        tracking=True,
    )
    creation_delegate_id = fields.Many2one(
        "res.users",
        string="Délégué de création",
        ondelete="restrict",
        tracking=True,
    )
    followup_delegate_id = fields.Many2one(
        "res.users",
        string="Délégué de suivi",
        domain=[("active", "=", True)],
        ondelete="restrict",
        tracking=True,
    )
    support_delegate_id = fields.Many2one(
        "res.users",
        string="Délégué en support",
        domain=[("active", "=", True)],
        ondelete="restrict",
        tracking=True,
    )
    segment_1_id = fields.Many2many(
        "res.partner.segment1",
        column1="partner_id",
        column2="segment_id",
        string="Segmentation 1",
    )
    segment_2_id = fields.Many2many(
        "res.partner.segment2",
        column1="partner_id",
        column2="segment_id",
        string="Segmentation 2",
    )
    segment_3_id = fields.Many2many(
        "res.partner.segment3",
        column1="partner_id",
        column2="segment_id",
        string="Segmentation 3",
    )
    segment_4_id = fields.Many2many(
        "res.partner.segment4",
        column1="partner_id",
        column2="segment_id",
        string="Segmentation 4",
    )

    segment_1_nb = fields.Integer(
        string="Nb de segments 1", compute="_compute_segment_nb"
    )
    segment_2_nb = fields.Integer(
        string="Nb de segments 2", compute="_compute_segment_nb"
    )
    segment_3_nb = fields.Integer(
        string="Nb de segments 3", compute="_compute_segment_nb"
    )
    segment_4_nb = fields.Integer(
        string="Nb de segments 4", compute="_compute_segment_nb"
    )
    filiere_ids = fields.Many2many(
        "res.partner.filiere",
        column1="partner_id",
        column2="filiere_id",
        string="Filière",
    )
    is_mucs = fields.Boolean(string="Est adhérent Mucs", tracking=True)
    is_mucs_update_date = fields.Date(string="Date MAJ Mucs", tracking=True)
    is_union_sociale = fields.Boolean(
        string="Est adhérent Union Sociale", tracking=True
    )
    is_union_sociale_update_date = fields.Date(
        string="Date MAJ Union Sociale", tracking=True
    )

    # Infos générales / Infos activité
    creation_origin_id = fields.Many2one(
        "res.partner.creation.origin",
        string="Origine création en coop",
        domain=[("parent_id", "=", False)],
        ondelete="restrict",
        tracking=True,
    )
    creation_suborigin_id = fields.Many2one(
        "res.partner.creation.origin",
        string="Sous-Origine création en coop",
        domain=[("child_ids", "=", False)],
        ondelete="restrict",
        tracking=True,
    )
    date_1st_sign = fields.Date("Date 1ère signature coop", tracking=True)
    registration_date = fields.Date(string="Date d'immatriculation RCS", tracking=True)
    social_object = fields.Text("Objet Social", tracking=True)
    naf_id = fields.Many2one(
        "res.partner.naf",
        string="Code NAF",
        ondelete="restrict",
        tracking=True,
    )
    secteur_id = fields.Many2one(
        "res.partner.secteur.activite",
        string="Secteur d'activité",
        related="naf_id.secteur_id",
        store=True,
    )
    activity_desc = fields.Text("Description de l'activité", tracking=True)
    activity_customers = fields.Selection(
        [
            ("ND", "Non définie"),
            ("PR", "Clients professionnels"),
            ("PA", "Clients particuliers"),
            ("PP", "Clients professionnels et particuliers"),
        ],
        string="Relation commerciale",
        default="ND",
        tracking=True,
    )
    certification_ids = fields.Many2many(
        comodel_name="res.partner.certification",
        string="Agréments",
        ondelete="restrict",
    )
    other_certification = fields.Char(string="Autre agrément", required=False)
    siret = fields.Char(string="SIRET du siège", size=14, index=True, tracking=True, copy=False)
    formatted_siret = fields.Char(
        string="SIRET formaté", compute="_compute_formatted_siret"
    )
    siren = fields.Char(string="SIREN", size=11, compute="_compute_siren")
    pappers_url = fields.Char(string="URL Pappers", compute="_compute_siren")
    capital = fields.Integer("Capital (en €)")
    first_closeout = fields.Date("1er bilan en coop")
    closeout_month = fields.Selection(
        [
            ("1", "Janvier"),
            ("2", "Février"),
            ("3", "Mars"),
            ("4", "Avril"),
            ("5", "Mai"),
            ("6", "Juin"),
            ("7", "Juillet"),
            ("8", "Août"),
            ("9", "Septembre"),
            ("10", "Octobre"),
            ("11", "Novembre"),
            ("12", "Décembre"),
        ],
        string="Mois clôture exercices",
    )
    is_seed_scop = fields.Boolean("Est une SCOP d'amorçage")
    seed_end = fields.Date("Date de fin du dispositif d'amorçage")
    is_incubated = fields.Boolean("Est incubé")
    incubator_id = fields.Many2one(
        "res.partner",
        string="Incubateur",
        domain=_get_domain_incubator_id,
        ondelete="restrict",
    )
    is_ag_constitution = fields.Boolean("AG constitutive réalisée")
    is_registration_in_progress = fields.Boolean(
        string="En cours d'immatriculation", default=False
    )
    is_federation_com = fields.Boolean(
        string="Fédération de la Communication",
        compute="_compute_federation",
        store=True,
        default=False,
    )
    is_federation_btp = fields.Boolean(
        string="Fédération du BTP",
        compute="_compute_federation",
        store=True,
        default=False,
    )
    is_federation_indus = fields.Boolean(
        string="Fédération de l'Industrie",
        compute="_compute_federation",
        store=True,
        default=False,
    )
    is_federation_cae = fields.Boolean(
        string="Fédération des CAE",
        compute="_compute_federation",
        store=True,
        default=False,
    )
    activity_federation_com_ids = fields.Many2many(
        comodel_name="scop.federation.com.activity",
        relation="res_partner_federation_com_activity_rel",
        column1="partner_id",
        column2="com_activity_id",
        string="Domaine d'activité Com",
        help="Fédération de la Com - Domaine d'activité",
    )
    activity_federation_indus_ids = fields.Many2many(
        comodel_name="scop.federation.indus.activity",
        relation="res_partner_federation_indus_activity_rel",
        column1="partner_id",
        column2="indus_activity_id",
        string="Domaine d'activité Industrie",
        help="Fédération de l'Industrie - Domaine d'activité",
    )
    copadev_member = fields.Boolean(string="Adhérent copadev", tracking=True)

    # Contacts
    director_ids = fields.One2many(
        "res.partner",
        "parent_id",
        string="Contacts Dirigeants",
        domain=[("mandate_id", "!=", False)],
    )
    other_child_ids = fields.One2many(
        "res.partner",
        "parent_id",
        string="Autres Contacts",
        domain=[("mandate_id", "=", False)],
    )

    # Révisions
    revision_contract = fields.Date(
        string="Début du contrat de révision",
        tracking=True,
    )
    revision_contract_end = fields.Date(
        string="Fin du contrat de révision",
        tracking=True,
    )
    revision_contract_tacite = fields.Boolean(
        string="Tacite reconduction",
        tracking=True,
        default=False
    )
    revision_mandat_cac = fields.Boolean(
        string="Mandat CAC actif",
        tracking=True,
        default=False
    )
    revision_company_id = fields.Many2one(
        "res.partner",
        string="Organisme de révision",
        domain=_get_domain_revision_company_id,
        ondelete="restrict",
        tracking=True,
    )
    revision_backup_company_id = fields.Many2one(
        "res.partner",
        string="Organisme de révision suppléant",
        domain=_get_domain_revision_company_id,
        ondelete="restrict",
        tracking=True,
    )
    revision_person_id = fields.Many2one(
        comodel_name="res.users",
        string="Réviseur",
        ondelete="restrict",
        tracking=True,
    )
    revision_certified_person_id = fields.Many2one(
        comodel_name="res.users",
        string="Réviseur agréé",
        ondelete="restrict",
        tracking=True,
    )
    revision_person_assign_date = fields.Date(
        string="Date de nomination du réviseur", tracking=True
    )
    revision_person_assign_end = fields.Date(
        string="Date de fin nomination réviseur", tracking=True
    )
    revision_type = fields.Selection(
        [
            ("1y", "Annuelle"),
            ("5y", "Quinquennale"),
            ("5ys", "Quinquennale séquencée (annuel)"),
            ("5ys23", "Quinquennale séquencée (2 ans et 3 ans)"),
        ],
        string="Périodicité de la révision",
        tracking=True,
    )
    revision_type_ok = fields.Boolean(
        string="Périodicité de révision ok",
        tracking=True,
        compute="_compute_revision_type_ok",
    )
    revision_quinq_exercice = fields.Integer(
        "Quinquénnale exercice à réviser",
        compute="_compute_revision_quinq_exercice",
    )
    revision_next_date = fields.Date("Prochain exercice révisable (old)")
    revision_format_id = fields.Many2one(
        "scop.revision.format",
        string="Format de révision",
        ondelete="restrict",
        tracking=True,
    )
    revision_tarif = fields.Integer(
        "Tarif de vente", related="revision_format_id.tarif", store=False
    )
    revision_next_exercice = fields.Integer(
        "Prochain exercice révisable",
        compute="_compute_revision_next_exercice",
        store=True,
        readonly=False,
    )
    revision_same_exercice = fields.Boolean(
        string="Révision sur l'année de cloture",
        tracking=True,
    )
    revision_next_year = fields.Integer(
        "Année prochaine révision",
        compute="_compute_revision_next_year",
        store=True,
        readonly=False,
    )
    revision_ids = fields.One2many(
        comodel_name="scop.revision",
        inverse_name="partner_id",
        string="Liste des Révisions",
    )
    revision_quinq_A1 = fields.Integer(
        "Quinquénnale année 1",
        compute="_compute_revision_quinq_annee",
    )
    revision_quinq_A2 = fields.Integer(
        "Quinquénnale année 2",
        compute="_compute_revision_quinq_annee",
    )
    revision_quinq_A3 = fields.Integer(
        "Quinquénnale année 3",
        compute="_compute_revision_quinq_annee",
    )
    revision_quinq_A4 = fields.Integer(
        "Quinquénnale année 4",
        compute="_compute_revision_quinq_annee",
    )
    revision_quinq_A5 = fields.Integer(
        "Quinquénnale année 5",
        compute="_compute_revision_quinq_annee",
    )

    revision_activite_A1 = fields.Integer(
        "Activité révision année 1",
        tracking=True,
    )
    revision_activite_A2 = fields.Integer(
        "Activité révision année 2",
        tracking=True,
    )
    revision_activite_A3 = fields.Integer(
        "Activité révision année 3",
        tracking=True,
    )
    revision_activite_A4 = fields.Integer(
        "Activité révision année 4",
        tracking=True,
    )
    revision_activite_A5 = fields.Integer(
        "Activité révision année 5",
        tracking=True,
    )

    # Action RSE et TE
    action_rse_ids = fields.One2many(
        comodel_name="scop.action.rse",
        inverse_name="partner_id",
        string="Liste des Actions RSE",
    )
    action_te_ids = fields.Many2many(
        "scop.action.te",
        column1="partner_id",
        column2="action_id",
        string="Expertises transition éco.",
    )
    is_rse = fields.Boolean(
        string="Engagement TE", compute="_compute_is_rse", store=True, default=False
    )

    # Historique
    scop_period_ids = fields.One2many(
        comodel_name="scop.period",
        inverse_name="partner_id",
        string="Historique",
    )

    # Période d'adhésion
    membership_period_ids = fields.One2many(
        comodel_name="scop.membership.period",
        inverse_name="partner_id",
        string="Périodes d'adhésion",
    )

    # Effectifs
    staff_ids = fields.One2many(
        comodel_name="scop.partner.staff",
        inverse_name="partner_id",
        string="Effectifs",
    )

    # Liste Ministère
    staff_last = fields.Integer(
        string="Dernier effectif connu",
        compute="_compute_last_effective",
        store=True,
    )
    staff_shareholder_last = fields.Integer(
        string="Dernier effectif associés connu",
        compute="_compute_last_effective",
        store=True,
    )

    staff_last_date = fields.Date(
        string="Date dernier effectif connu",
        compute="_compute_last_effective",
        store=True,
    )

    # Champs pour personnes
    birthyear = fields.Integer("Année de naissance")
    subscription_ids = fields.One2many(
        comodel_name="res.partner.newsletter.subscription",
        inverse_name="partner_id",
        string="Abonnements",
    )
    contact_origin_id = fields.Many2one(
        "res.partner.rgpd.origin",
        string="Origine du contact",
        ondelete="restrict",
    )
    mandate_id = fields.Many2one(
        "res.partner.mandate", string="Mandat", ondelete="restrict"
    )
    function_lst_id = fields.Many2one(
        "res.partner.function_lst", string="Fonction", ondelete="restrict"
    )
    contact_legality = fields.Selection(
        [
            ("employee", "Salarié"),
            ("customer", "Client en contrat"),
            ("supplier", "Fournisseur en contrat"),
            ("consent", "Consentement"),
            ("legitimate", "Intérêt légitime"),
            ("none", "Aucune"),
        ],
        string="Licéité du contact",
        compute="_compute_contact_legality",
        store=True,
    )
    associate = fields.Selection(
        selection=[
            ("asso", "Associé extérieur"),
            ("coop", "Associé coopérateur"),
            ("none", "Non associé"),
        ],
        string="Associé",
    )
    employee = fields.Boolean(string="Salarié", default=True)

    has_mvt_mandate = fields.Boolean(string="Elu du mouvement", default=False)

    mvt_mandate_ids = fields.Many2many(
        comodel_name="res.partner.mvt.mandate",
        relation="res_partner_mvt_mandate_rel",
        column1="partner_id",
        column2="mvt_mandate_id",
        string="Mandats mouvement",
    )

    mvt_vip_ids = fields.Many2many(
        comodel_name="res.partner.mvt.vip",
        relation="res_partner_mvt_vip_rel",
        column1="partner_id",
        column2="mvt_vip_id",
        string="Etiquettes VIP",
    )

    # Champs pour partenaires
    organization_type_id = fields.Many2one(
        "res.partner.organization.type",
        string="Famille",
        ondelete="restrict",
        compute="_compute_org_type_id",
        tracking=True,
    )
    organization_subtype_id = fields.Many2one(
        "res.partner.organization.type",
        string="Type",
        domain=[("child_ids", "=", False)],
        ondelete="restrict",
        tracking=True,
    )

    # Droits utilisateurs
    is_administrative = fields.Boolean(compute="_compute_is_administrative")

    # Hack pour la création de contacts depuis la fiche organisme
    parent_id_onchange = fields.Many2one("res.partner")

    # ------------------------------------------------------
    # Constrains
    # ------------------------------------------------------
    @api.constrains("zip_id", "country_id", "city_id", "state_id")
    def _check_zip(self):
        return

    @api.constrains("revision_contract", "revision_contract_end")
    def _check_revision_contract(self):
        for rec in self:
            if rec.revision_contract and \
               rec.revision_contract_end and \
               rec.revision_contract > rec.revision_contract_end:
                raise ValidationError(
                    _(
                        "La date de fin du contrat de révision doit être supérieure"
                        " à la date de début du contrat de révision"
                    )
                )
        return

    @api.constrains("revision_person_assign_date", "revision_person_assign_end")
    def _check_revision_person_assign(self):
        for rec in self:
            if rec.revision_person_assign_date and \
               rec.revision_person_assign_end and \
               rec.revision_person_assign_date > rec.revision_person_assign_end:
                raise ValidationError(
                    _(
                        "La date de fin de nomination du réviseur doit être supérieure"
                        " à la date de début de nomination du réviseur"
                    )
                )
        return

    @api.constrains("siret")
    def _check_siret(self):
        if self.siret and not self.env.context.get("import_file"):
            siren = self.siret[:3] + " " + self.siret[3:6] + " " + self.siret[6:9]
            if (
                not self.siret.isdigit()
                and self.siret != "En attente d'immatriculation"
            ):
                raise ValidationError(_("Ce SIRET n'est pas valide"))
            if len(self.siret) != 14:
                raise ValidationError(_("La longueur du SIRET doit être égale à 14"))
            if (
                self.search_count(
                    [
                        ("siret", "=like", siren + "%"),
                        ("is_cooperative", "=", True),
                    ]
                )
                > 1
            ):
                raise ValidationError(_("Ce SIREN existe déjà parmi les coopératives"))
            elif self.search_count([("siret", "=", self.siret)]) > 1:
                raise ValidationError(_("Ce SIRET existe déjà"))

    @api.constrains("is_company", "type", "email", "phone", "mobile", "user_ids")
    def _check_contact_info(self):
        # Contrainte de tel ou mail lors de la modification d'un contact
        if not self.is_company and self.type == "contact" and not self.user_ids:
            if not self.email and not self.phone and not self.mobile:
                raise UserError(
                    _("Vous devez saisir au moins un e-mail ou un téléphone pour %s")
                    % self.name
                )

    # ------------------------------------------------------
    # Onchange
    # ------------------------------------------------------
    # TODO: à vérifier
    # Hack pour la création de contacts depuis la fiche organisme
    @api.onchange("parent_id_onchange")
    def _onchange_parent_id_onchange(self):
        self.parent_id = self.parent_id_onchange

    @api.onchange("nickname")
    def onchange_nickname(self):
        if (
            self.is_cooperative
            and self.project_status in ["1_information", "2_pre-diagnostic", "3_accompagnement"]
        ):
            self.lastname = self.nickname

    # TODO: à vérifier
    @api.onchange("parent_id")
    def _onchange_parent_id(self):
        if self.parent_id.ur_id:
            self.ur_id = self.parent_id.ur_id

    @api.onchange("ur_id")
    def _onchange_ur_id(self):
        if self.child_ids:
            for child in self.child_ids:
                child.ur_id = self.ur_id

    @api.onchange("creation_origin_id")
    def onchange_creation_origin_id(self):
        for coop in self:
            coop.creation_suborigin_id = False

    # TODO: à vérifier
    @api.onchange("is_seed_scop")
    def onchange_is_seed_scop(self):
        for coop in self:
            if coop.is_seed_scop:
                if coop.date_1st_sign:
                    coop.seed_end = coop.date_1st_sign + timedelta(2556)
                else:
                    coop.seed_end = datetime.today().date() + timedelta(2556)
            else:
                coop.seed_end = False

    @api.onchange("name")
    def onchange_name(self):
        if self.search_count([("name", "=ilike", self.name)]) > 0:
            return {
                "warning": {
                    "title": "Attention",
                    "message": "Ce nom / cette raison sociale existe déjà, "
                    + "merci de vérifier que vous n'êtes pas en "
                    + "train de créer un doublon",
                }
            }

    @api.onchange("mobile")
    def onchange_mobile(self):
        if self.mobile and len(self.mobile) > 0 and len(self.mobile) < 10:
            raise ValidationError(
                _("Le numéro de téléphone doit contenir au moins 10 caractères")
            )

    @api.onchange("phone")
    def onchange_phone(self):
        if self.phone and len(self.phone) > 0 and len(self.phone) < 10:
            raise ValidationError(
                _("Le numéro de téléphone doit contenir au moins 10 caractères")
            )

    @api.onchange("siret")
    def onchange_siret(self):
        if self.siret:
            siren = self.siret[:3] + " " + self.siret[3:6] + " " + self.siret[6:9]
            if self.search_count([("siret", "=like", self.siret)]) > 0:
                return {
                    "warning": {
                        "title": "Attention",
                        "message": "Ce SIRET existe déjà, merci de vérifier "
                        + "que vous n'êtes pas en train de créer un"
                        + " doublon",
                    }
                }
            elif self.search_count([("siret", "=like", siren + "%")]) > 0:
                return {
                    "warning": {
                        "title": "Attention",
                        "message": "Ce SIREN existe déjà, merci de vérifier "
                        + "que vous n'êtes pas en train de créer un"
                        + " doublon",
                    }
                }

    @api.onchange("cooperative_form_id")
    def onchange_cooperative_form_id(self):
        if self.cooperative_form_id == self.env.ref(
            "cgscop_partner.form_noncooperative"
        ):
            self.creation_origin_id = None
            self.creation_suborigin_id = None
            self.is_ag_constitution = None
            self.date_1st_sign = None
            self.first_closeout = None

    # ------------------------------------------------------
    # Common functions
    # ------------------------------------------------------
    def _create_period(self, partner):
        new_period = self._add_period(partner)
        partner.scop_period_ids = new_period

    def _add_period(self, partner):
        new_period = self.env["scop.period"].with_context().create(
            {
                "partner_id": partner.id,
                "start": partner.registration_date or fields.Date.today(),
                "name": partner.name,
                "cooperative_form_id": partner.cooperative_form_id.id,
                "partner_company_type_id": partner.partner_company_type_id.id,
                "siret": (
                    partner.siret
                    if partner.siret or not partner.is_registration_in_progress
                    else "En attente d'immatriculation"
                ),
                "street": partner.street,
                "street2": partner.street2,
                "street3": partner.street3,
                "zip": partner.zip,
                "zip_id": partner.zip_id.id,
                "city": partner.city,
                "cedex": partner.cedex,
                "state_id": partner.state_id.id,
                "country_id": partner.country_id.id,
                "naf_id": partner.naf_id.id,
                "ur_id": partner.ur_id.id,
                "cae": partner.cae,
            }
        )
        return new_period

    # ------------------------------------------------------
    # Override ORM
    # ------------------------------------------------------
    @api.model
    def _name_search(
        self, name, args=None, operator="ilike", limit=100, name_get_uid=None
    ):
        args = args or []
        domain = [
            "|",
            "|",
            "|",
            ("name", operator, name),
            ("member_number", "ilike", name),
            ("nickname", operator, name),
            ("sigle", operator, name),
        ]
        return self._search(domain + args, limit=limit, access_rights_uid=name_get_uid)

    # Creation d'une periode lorsque le statut passe en Phase de Suivi
    def write(self, vals):
        # Gestion casse des informations
        if vals.get("name"):
            vals["name"] = vals.get("name").title()
        if vals.get("lastname"):
            vals["lastname"] = vals.get("lastname").title()
        if vals.get("firstname"):
            vals["firstname"] = vals.get("firstname").title()
        if vals.get("city"):
            vals["city"] = vals.get("city").upper()
        if len(self) == 1 and self.parent_id:
            if self.type in ("contact", "invoice", "private"):
                parent_ur_id = self.parent_id.ur_id.id
                vals["ur_id"] = parent_ur_id

        result = super(ScopPartner, self).write(vals)

        # Hack pour notification lors de la modification du logo
        if "image_128" in vals:
            self.message_post(
                body=_("Modification Logo"),
                subtype="cgscop_base.cg_values_change",
            )

        for partner in self:
            # Création d'une période lors du changement de statut en Suivi
            if vals.get("project_status") == "4_suivi" and not self.env.context.get(
                "import_file"
            ):
                if not partner.scop_period_ids:
                    partner.sudo()._create_period(partner)

            # Ajout des followers de la fiche
            partners_to_subscribe = []
            if partner.followup_delegate_id != partner.create_uid:
                partners_to_subscribe.append(partner.followup_delegate_id.partner_id.id)
            if partner.creation_delegate_id != partner.create_uid:
                partners_to_subscribe.append(partner.creation_delegate_id.partner_id.id)

            if partners_to_subscribe:
                partner.message_subscribe(partner_ids=partners_to_subscribe)

        return result

    @api.model_create_multi
    def create(self, vals_list):
        """
        Création d'une période lors de la création d'une coopérative
        """
        # Gestion casse des informations
        for vals in vals_list:
            if vals.get("name"):
                vals["name"] = vals.get("name").title()
            if vals.get("lastname"):
                vals["lastname"] = vals.get("lastname").title()
            if vals.get("firstname"):
                vals["firstname"] = vals.get("firstname").title()
            if vals.get("city"):
                vals["city"] = vals.get("city").upper()

        partners = super(ScopPartner, self).create(vals_list)

        for vals in vals_list:
            # Création d'une période si la coop est en statut en Suivi
            if vals.get("is_cooperative") and vals.get("project_status") == "4_suivi":
                for partner in partners:
                    if not partner.scop_period_ids:
                        partner.sudo()._create_period(partner)

        return partners

    @api.model
    def _address_fields(self):
        address_fields = super(ScopPartner, self)._address_fields()
        address_fields.append("cedex")
        return address_fields

    # ------------------------------------------------------
    # Override parent
    # ------------------------------------------------------
    def _get_contact_name(self, partner, name):
        super(ScopPartner, self)._get_contact_name(partner, name)
        return "%s, %s" % (
            name,
            partner.commercial_company_name or partner.sudo().parent_id.name,
        )

    def action_archive(self):
        """
        Lève une erreur si une coopérative qui n'est pas à l'état abandonné fait partie des
        items à archiver
        """
        coop_ids = self.filtered(
            lambda p: p.is_cooperative and p.project_status != "5_abandonne"
        )
        if coop_ids:
            raise UserError(
                _(
                    "Il n'est pas possible d'archiver une coopérative qui n'est pas en "
                    "statut abandonné."
                )
            )
        else:
            return super().action_archive()

    # ------------------------------------------------------
    # Computed Fields
    # ------------------------------------------------------
    @api.depends("siret")
    def _compute_siren(self):
        for partner in self:
            if partner.siret:
                partner.siren = (
                    partner.siret[:3]
                    + " "
                    + partner.siret[3:6]
                    + " "
                    + partner.siret[6:9]
                )
                partner.pappers_url = (
                    "https://www.pappers.fr/entreprise/" + partner.siret[:9]
                )
            else:
                partner.siren = None
                partner.pappers_url = None

    def _compute_formatted_siret(self):
        for partner in self:
            if partner.siret:
                partner.formatted_siret = (
                    partner.siret[:3]
                    + " "
                    + partner.siret[3:6]
                    + " "
                    + partner.siret[6:9]
                    + " "
                    + partner.siret[9:]
                )
            else:
                partner.formatted_siret = None

    @api.depends("zip")
    def _compute_num_departement(self):
        for company in self:
            if company.zip:
                zip_starts = company.zip[:3]
                if zip_starts in ["200", "201"]:
                    zip_departement = "2A"
                elif zip_starts == "202":
                    zip_departement = "2B"
                elif zip_starts[:2] == "97":
                    zip_departement = zip_starts
                else:
                    zip_departement = zip_starts[:2]

                if zip_departement in ["2A", "2B"] or zip_departement.isdigit():
                    company.zip_departement = zip_departement
                else:
                    company.zip_departement = False

    @api.depends("zip")
    def _compute_region(self):
        for partner in self:
            if partner.zip:
                zip_id = self.env["res.city.zip"].search([("name", "=", partner.zip)])
                if zip_id:
                    partner.region = zip_id[0].city_id[0].state_id

    @api.model
    def _compute_current_user_ur_id(self):
        for partner in self:
            partner.current_user_ur_id = self.env.company.ur_id

    def _search_current_user_ur_id(self, operator, value):
        return [("ur_id", "=", self.env.company.ur_id.id)]

    @api.depends(
        "contact_origin_id",
        "parent_id.cooperative_form_id",
        "parent_id.membership_status",
    )
    def _compute_contact_legality(self):
        for partner in self:
            partner.contact_legality = "none"
            if partner.contact_origin_id.name == "Fiche contact, site internet":
                partner.contact_legality = "consent"
            if partner.contact_origin_id.name in (
                "Prospect journée d'info coll",
                "Prospect (salon, rdv, internet…)",
                "Elus",
            ):
                partner.contact_legality = "legitimate"
            if partner.contact_origin_id.name in (
                "Salariés CG",
                "Salariés UR",
                "Salariés Fédération",
            ):
                partner.contact_legality = "employee"
            if partner.contact_origin_id.name in (
                "Elus",
                "VIP, Officiels",
                "Fournisseurs",
            ):
                partner.contact_legality = "legitimate"
            if not partner.is_company and partner.parent_id:
                parent = partner.parent_id
                if (
                    partner.contact_origin_id.name
                    in (
                        "Dossiers d'adhésion",
                        "Dossiers annuels non LM (scic, scop47)",
                    )
                    and parent.cooperative_form_id
                    and parent.membership_status == "member"
                ):
                    partner.contact_legality = "customer"
                if (
                    partner.contact_origin_id.name
                    == ("Dossiers annuels non LM (scic, scop47)")
                    and parent.membership_status != "member"
                ):
                    partner.contact_legality = "legitimate"
                if (
                    partner.contact_origin_id.name == ("Dossiers Liste ministère")
                    and parent.cooperative_form_id.name == "SCIC"
                ):
                    partner.contact_legality = "customer"

    @api.depends("action_rse_ids","action_te_ids")
    def _compute_is_rse(self):
        """
        Est on une coop RSE/TE
        """
        for partner in self:
            partner.is_rse = False

            if len(partner.action_rse_ids) != 0:
                partner.is_rse = True
            if len(partner.action_te_ids) != 0:
                partner.is_rse = True

    @api.depends(
        "membership_period_ids",
        "membership_period_ids.end_reason_id",
        "membership_period_ids.end",
        "membership_period_ids.start",
    )
    # Todo: A revoir comment on assigne le statut member
    def _compute_membership(self):
        for partner in self:
            if partner.membership_period_ids:
                type_cg = self.env.ref("cgscop_partner.membership_type_1").id
                last_membership_period = self.env["scop.membership.period"].search(
                    [("partner_id", "=", partner.id), ("type_id", "=", type_cg)],
                    limit=1,
                    order="start desc,id desc",
                )
                if last_membership_period and not last_membership_period.end:
                    partner.membership_status = "member"
                    partner.member_start = last_membership_period.start
                elif last_membership_period and last_membership_period.end_reason_id:
                    partner.membership_status = "out"
            else:
                partner.membership_status = "not_member"

    @api.depends("member_number_int")
    def _compute_membership_number(self):
        for partner in self:
            if partner.member_number_int:
                partner.member_number = str(partner.member_number_int)
            else:
                partner.member_number = False

    @api.depends("membership_period_ids", "membership_period_ids.end")
    def _compute_federation(self):
        for partner in self:
            if partner.is_cooperative:
                partner.is_federation_com = partner._get_federation(
                    "cgscop_partner.membership_type_2"
                )
                partner.is_federation_btp = partner._get_federation(
                    "cgscop_partner.membership_type_4"
                )
                partner.is_federation_indus = partner._get_federation(
                    "cgscop_partner.membership_type_3"
                )
                partner.is_federation_cae = partner._get_federation(
                    "cgscop_partner.membership_type_5"
                )

    def _get_federation(self, external_id):
        member_type_id = self.env.ref(external_id).id
        partner_id = self.id
        membership_period = self.env["scop.membership.period"].search(
            [
                ("partner_id", "=", partner_id),
                ("type_id", "=", member_type_id),
                ("end", "=", False),
            ]
        )
        if membership_period:
            return True
        else:
            return False

    @api.depends(
        "staff_ids",
        "staff_ids.staff_count",
        "staff_ids.staff_shareholder_count",
        "staff_ids.effective_date",
    )
    def _compute_last_effective(self):
        for partner in self:
            lines = partner._get_staff_lines()
            if lines:
                partner.staff_last = lines[0].staff_count
                partner.staff_shareholder_last = lines[0].staff_shareholder_count
                partner.staff_last_date = lines[0].effective_date

    def _compute_segment_nb(self):
        for partner in self:
            # Calcul nombre de segment 1
            seg1 = partner.env["res.partner.segment1"].search(
                [("ur_id", "=", self.env.user.ur_id.id)]
            )
            partner.segment_1_nb = len(seg1)
            # Calcul nombre de segment 2
            seg2 = partner.env["res.partner.segment2"].search(
                [("ur_id", "=", self.env.user.ur_id.id)]
            )
            partner.segment_2_nb = len(seg2)
            # Calcul nombre de segment 3
            seg3 = partner.env["res.partner.segment3"].search(
                [("ur_id", "=", self.env.user.ur_id.id)]
            )
            partner.segment_3_nb = len(seg3)
            # Calcul nombre de segment 4
            seg4 = partner.env["res.partner.segment4"].search(
                [("ur_id", "=", self.env.user.ur_id.id)]
            )
            partner.segment_4_nb = len(seg4)

    @api.depends("organization_subtype_id")
    def _compute_org_type_id(self):
        for partner in self:
            if partner.organization_subtype_id:
                partner.organization_type_id = partner.organization_subtype_id.parent_id
            else:
                partner.organization_type_id = False

    def _compute_is_administrative(self):
        for partner in self:
            if self.env.user.has_group("cgscop_partner.group_cg_administrative"):
                partner.is_administrative = True
            else:
                partner.is_administrative = False

    @api.depends(
        "revision_next_exercice", "revision_same_exercice",
    )
    def _compute_revision_next_year(self):
        for partner in self:
            if partner.revision_same_exercice:
                partner.revision_next_year = partner.revision_next_exercice
            else:
                partner.revision_next_year = partner.revision_next_exercice + 1

    @api.depends(
        "revision_type",
        "revision_ids",
        "revision_ids.revision_result_year",
        "first_closeout",
    )
    def _compute_revision_next_exercice(self):
        for partner in self:
            # Si aucune périodicité de défini, on n'insiste pas
            if not partner.revision_type or not partner.first_closeout:
                partner.revision_next_exercice = False
            else:
                # On commence par regarder si l'on a des révisions
                last_rev = partner.revision_ids.sorted(
                    key=lambda r: r.revision_result_year, reverse=True
                )

                # On calcule l'année de référence du calcul
                if len(last_rev) > 0:
                    # si On a déjà révisé un exercice il devient la base du calcul
                    base_rev = last_rev[0].revision_result_year
                else:
                    base_rev = partner.first_closeout.year - 1

                # On calcule le prochain exercice révisable
                # Cas d'une révision annuelle
                if partner.revision_type == "1y":
                    partner.revision_next_exercice = base_rev + 1
                # Cas d'une révision quinquénnale
                elif partner.revision_type == "5y":
                    self._compute_revision_quinq_exercice()
                    partner.revision_next_exercice = partner.revision_quinq_exercice
                # Cas d'une révision quinquénnale séquencée (annuelle)
                elif partner.revision_type == "5ys":
                    partner.revision_next_exercice = base_rev + 1
                # Cas d'une révision quinquénnale séquencée (2 et 3)
                elif partner.revision_type == "5ys23":
                    # On doit regarder l'écart avec la révision précédente
                    if len(last_rev) > 1:
                        # On a une réunion précédente ...
                        # ... il faut regarder l'écart entre les deux
                        ex1 = last_rev[0].revision_result_year
                        ex2 = last_rev[1].revision_result_year
                        # ... prochain exercice = 5 - durée de la précédente révision
                        partner.revision_next_exercice = base_rev + (5 - (ex1 - ex2))
                    else:
                        # Pas de révision précédente
                        partner.revision_next_exercice = base_rev + 2

    @api.depends(
        "revision_type",
        "revision_ids",
        "revision_ids.revision_result_year",
        "revision_ids.revision_type",
        "first_closeout",
    )
    def _compute_revision_quinq_exercice(self):
        for partner in self:
            # Si aucune périodicité de défini, on n'insiste pas
            if not partner.revision_type or not partner.first_closeout:
                partner.revision_quinq_exercice = False
            else:
                # On commence par regarder si l'on a des révisions classique ou speciale
                last_rev = partner.revision_ids.filtered(
                    lambda p: p.revision_type != "int"
                    ).sorted(
                    key=lambda r: r.revision_result_year, reverse=True
                    )

                # On calcule l'année de référence du calcul
                if len(last_rev) > 0:
                    # si On a déjà révisé un exercice il devient la base du calcul
                    base_rev = last_rev[0].revision_result_year
                else:
                    base_rev = partner.first_closeout.year - 1

                # On calcule l'année de révision de la quinquénale
                partner.revision_quinq_exercice = base_rev + 5

    @api.depends(
        "revision_quinq_exercice",
        "revision_same_exercice",
    )
    def _compute_revision_quinq_annee(self):
        for partner in self:
            if partner.revision_same_exercice:
                partner.revision_quinq_A5 = partner.revision_quinq_exercice
                partner.revision_quinq_A4 = partner.revision_quinq_exercice - 1
                partner.revision_quinq_A3 = partner.revision_quinq_exercice - 2
                partner.revision_quinq_A2 = partner.revision_quinq_exercice - 3
                partner.revision_quinq_A1 = partner.revision_quinq_exercice - 4
            else:
                partner.revision_quinq_A5 = partner.revision_quinq_exercice + 1
                partner.revision_quinq_A4 = partner.revision_quinq_exercice
                partner.revision_quinq_A3 = partner.revision_quinq_exercice - 1
                partner.revision_quinq_A2 = partner.revision_quinq_exercice - 2
                partner.revision_quinq_A1 = partner.revision_quinq_exercice - 3

    @api.depends(
        "revision_type",
        "revision_mandat_cac",
    )
    def _compute_revision_type_ok(self):
        for partner in self:
            partner.revision_type_ok = True
            if (partner.revision_type == "1y") and (partner.revision_mandat_cac) :
                partner.revision_type_ok = False
            if (partner.revision_type == "1y") and (partner.cooperative_form_id.name == "SCIC") :
                partner.revision_type_ok = False

    # ------------------------------------------------------
    # Button & Action
    # ------------------------------------------------------
    def open_facebook(self):
        self.ensure_one()
        return {
            "type": "ir.actions.act_url",
            "url": self.facebook,
        }

    def open_linkedin(self):
        self.ensure_one()
        return {
            "type": "ir.actions.act_url",
            "url": self.linkedin,
        }

    def open_twitter(self):
        self.ensure_one()
        return {
            "type": "ir.actions.act_url",
            "url": self.twitter,
        }

    def open_instagram(self):
        self.ensure_one()
        return {
            "type": "ir.actions.act_url",
            "url": self.instagram,
        }

    def open_pappers(self):
        self.ensure_one()
        return {
            "type": "ir.actions.act_url",
            "url": self.pappers_url,
        }

    def remove_director(self):
        self.write({"mandate_id": False})
        return {"type": "ir.actions.act_window_close"}

    def partner_archive(self):
        self.active = False

    def scop_prj_adhesion(self):
        self.write({"membership_status": "adhesion"})
        return True

    def scop_abandonne(self):
        self.write(
            {
                "project_status": "5_abandonne",
            }
        )
        return True

    def add_director(self):
        return {
            "type": "ir.actions.act_window",
            "views": [
                [
                    self.env.ref("cgscop_partner.scop_partner_director_form_view").id,
                    "form",
                ]
            ],
            "view_mode": "form",
            "res_model": "res.partner",
            "target": "new",
            "context": {
                "default_parent_id_onchange": self.id,
                "default_street": self.street,
                "default_street2": self.street2,
                "default_street3": self.street3,
                "default_city": self.city,
                "default_city_id": self.city_id.id,
                "default_cedex": self.cedex,
                "default_state_id": self.state_id.id,
                "default_zip": self.zip,
                "default_country_id": self.country_id.id,
                "default_lang": self.lang,
                "default_user_id": self.user_id.id,
                "ur_id": self.ur_id.id,
                "default_type": "contact",
            },
        }

    def edit_director(self):
        return {
            "type": "ir.actions.act_window",
            "views": [
                [
                    self.env.ref("cgscop_partner.scop_partner_director_form_view").id,
                    "form",
                ]
            ],
            "view_mode": "form",
            "res_model": "res.partner",
            "res_id": self.id,
            "target": "new",
        }

    def add_contact(self):
        return {
            "type": "ir.actions.act_window",
            "views": [
                [
                    self.env.ref("cgscop_partner.scop_partner_contact_form_view").id,
                    "form",
                ]
            ],
            "view_mode": "form",
            "res_model": "res.partner",
            "target": "new",
            "context": {
                "default_parent_id_onchange": self.id,
                "default_street": self.street,
                "default_street2": self.street2,
                "default_street3": self.street3,
                "default_city": self.city,
                "default_city_id": self.city_id.id,
                "default_cedex": self.cedex,
                "default_state_id": self.state_id.id,
                "default_zip": self.zip,
                "default_country_id": self.country_id.id,
                "default_lang": self.lang,
                "default_user_id": self.user_id.id,
            },
        }

    def edit_contact(self):
        return {
            "type": "ir.actions.act_window",
            "views": [
                [
                    self.env.ref("cgscop_partner.scop_partner_contact_form_view").id,
                    "form",
                ]
            ],
            "view_mode": "form",
            "res_model": "res.partner",
            "res_id": self.id,
            "target": "new",
        }

    def write_contact(self):
        return self

    def show_coop(self):
        """
        Affichage des coop avec filtre par défaut
        """
        ctx = {
            "default_is_company": True,
            "default_is_cooperative": True,
            "default_company_type": "company",
            "default_project_status": "4_suivi",
        }

        # Détermine le filtre par défaut pour l'affichage
        filtre = self.env.company.ur_id.partner_filter
        if filtre == "1":
            ctx.update({"search_default_is_adherent": True})
        elif filtre == "2":
            ctx.update({"search_default_my_ur_adherent": True})
        elif filtre == "3":
            ctx.update({"search_default_is_federation_com": True})
        elif filtre == "4":
            ctx.update({"search_default_is_federation_indus": True})
        elif filtre == "5":
            ctx.update({"search_default_my_is_federation_btp": True})
        elif filtre == "6":
            ctx.update({"search_default_my_is_federation_cae": True})

        return {
            "name": "Coopératives",
            "type": "ir.actions.act_window",
            "res_model": "res.partner",
            "search_view_id": (
                self.env.ref("cgscop_partner.scop_partner_view_search").id,
            ),
            "view_mode": "tree,form,activity",
            "views": [
                (
                    self.env.ref("cgscop_partner.view_partner_cooperative_tree").id,
                    "tree",
                ),
                (
                    self.env.ref("cgscop_partner.scop_contact_view_form").id,
                    "form",
                ),
            ],
            "target": "current",
            "domain": [
                ("is_cooperative", "=", True),
                ("project_status", "=", "4_suivi"),
            ],
            "context": ctx,
        }

    def show_creation_project(self):
        """
        Affichage des projets en création avec filtre par défaut
        """
        ctx = {
            "default_is_company": True,
            "default_is_cooperative": True,
            "default_company_type": "company",
            "default_project_status": "1_information",
        }

        # Détermine le filtre par défaut pour l'affichage
        filtre = self.env.company.ur_id.partner_filter
        if filtre == "2":
            ctx.update({"search_default_my_ur": True})

        return {
            "name": "Projets de création",
            "type": "ir.actions.act_window",
            "res_model": "res.partner",
            "search_view_id": (
                self.env.ref("cgscop_partner.scop_partner_view_search").id,
            ),
            "view_mode": "kanban,tree,form,activity",
            "views": [
                (
                    self.env.ref("cgscop_partner.view_partner_cooperative_kanban").id,
                    "kanban",
                ),
                (
                    self.env.ref("cgscop_partner.view_partner_prospect_tree").id,
                    "tree",
                ),
                (
                    self.env.ref("cgscop_partner.scop_contact_view_form").id,
                    "form",
                ),
            ],
            "target": "current",
            "domain": [
                ("is_cooperative", "=", True),
                (
                    "project_status",
                    "in",
                    (
                        "1_information",
                        "2_pre-diagnostic",
                        "3_accompagnement",
                        "5_abandonne",
                    ),
                ),
            ],
            "context": ctx,
        }

    def show_organisme(self):
        """
        Affichage des organismes avec filtre par défaut
        """
        ctx = {
            "default_is_company": True,
            "default_is_cooperative": True,
            "default_company_type": "company",
            "default_project_status": "1_information",
        }

        # Détermine le filtre par défaut pour l'affichage
        filtre = self.env.company.ur_id.partner_filter
        if filtre == "2":
            ctx.update({"search_default_my_ur_adherent": True})

        return {
            "name": "Tous les organismes",
            "type": "ir.actions.act_window",
            "res_model": "res.partner",
            "search_view_id": (
                self.env.ref("cgscop_partner.scop_partner_view_search").id,
            ),
            "view_mode": "tree,form,activity",
            "views": [
                (
                    self.env.ref("cgscop_partner.view_partner_cooperative_tree").id,
                    "tree",
                ),
                (
                    self.env.ref("cgscop_partner.scop_contact_view_form").id,
                    "form",
                ),
            ],
            "target": "current",
            "domain": [
                ("is_cooperative", "=", True),
            ],
            "context": ctx,
        }

    def show_processus_adhesion(self):
        """
        Affichage des coopératives dans leur processus d'adhésion par défaut
        """
        ctx = {
            "default_is_company": True,
            "default_is_cooperative": True,
            "default_company_type": "company",
            "default_project_status": "4_suivi",
        }

        # Détermine le filtre par défaut pour l'affichage
        filtre = self.env.company.ur_id.partner_filter
        if filtre == "2":
            ctx.update({"search_default_my_ur": True})

        return {
            "name": "Processus d'adhésion",
            "type": "ir.actions.act_window",
            "res_model": "res.partner",
            "search_view_id": (
                self.env.ref("cgscop_partner.scop_partner_view_search").id,
            ),
            "view_mode": "kanban,tree,form,activity",
            "views": [
                (
                    self.env.ref("cgscop_partner.view_partner_adhesion_kanban").id,
                    "kanban",
                ),
                (
                    self.env.ref("cgscop_partner.view_partner_prospect_tree").id,
                    "tree",
                ),
                (
                    self.env.ref("cgscop_partner.scop_contact_view_form").id,
                    "form",
                ),
            ],
            "target": "current",
            "domain": [
                ("is_cooperative", "=", True),
                (
                    "membership_status",
                    "in",
                    ("adhesion", "soumis_cg"),
                ),
            ],
            "context": ctx,
        }

    # ------------------------------------------------------
    # Business Methods
    # ------------------------------------------------------
    def get_formatted_address(self):
        self.ensure_one()
        address_fields = [self.street, self.street2, self.street3]
        address = [f for f in address_fields if f]
        return "\n".join(address) if address else ""

    def get_postal_address(self):
        self.ensure_one()
        street_address_fields = [self.postal_street, self.postal_street2, self.postal_street3]
        street_address_list = list(filter(bool, street_address_fields))
        city_address_list = list(filter(bool, self.postal_zip, self.postal_city))
        street_address = "\n".join(street_address_list) if street_address_list else ""
        city_address = " ".join(city_address_list) if city_address_list else ""
        cedex = f" CEDEX {self.postal_cedex}" if self.postal_cedex else ""
        return f"{street_address}\n{city_address}{cedex}"

    def _get_staff_lines(self):
        self.ensure_one()
        return self.staff_ids.sorted(key="effective_date", reverse=True)

    # ------------------------------------------------------
    # CRON function
    # ------------------------------------------------------
    def _cron_geoloc_data_gouv(self, days=1):
        # Récupération des valeurs de suivi sur zip/city/street de la veille
        yesterday = fields.Date.today() - timedelta(days=days)
        partner_model = self.env["ir.model"].search([("model", "=", "res.partner")])
        address_values = self.env["ir.model.fields"].search(
            [
                ("model_id", "=", partner_model.id),
                ("name", "in", ["street", "street2", "zip", "city"]),
            ]
        )
        mail_tracking_value_ids = self.env["mail.tracking.value"].search(
            [
                ("field", "in", address_values.ids),
                ("create_date", ">=", yesterday),
            ]
        )

        # Récupération des messages de notif sur
        # res.partner en lien avec les valeurs de suivi
        mail_mess_ids = self.env["mail.message"].search(
            [
                ("model", "=", "res.partner"),
                ("message_type", "=", "notification"),
                ("tracking_value_ids", "in", mail_tracking_value_ids.ids),
            ]
        )

        partner_list = mail_mess_ids.mapped("res_id")

        # Récupération des partners pour calcul des données GPS
        partners = self.env["res.partner"].search(
            [
                "|",
                "|",
                ("id", "in", partner_list),
                ("partner_latitude", "=", 0.0),
                ("partner_latitude", "=", False),
                "|",
                ("membership_status", "=", "member"),
                ("is_incubated", "=", True),
            ]
        )

        i = 0
        for partner in partners:
            partner.geo_localize()
            i += 1
            time.sleep(1)
        _logger.info("Mise à jour de %d coordonnées", i)