# © 2021 Le Filament (<http://www.le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo import models, fields, api from datetime import date class ScopCotisation(models.AbstractModel): _name = "scop.cotisation" _description = "Base des cotisations" @api.model def default_get(self, fields): """ Attribue la valeur des conditions de paiments par défault à la base de cotisation :param fields: :return: """ res = super(ScopCotisation, self).default_get(fields) res['payment_term_id'] = self.env.user.company_id.\ contribution_default_payment_term_id.id return res year = fields.Selection( [(year, str(year)) for year in range( fields.Datetime.now().year - 1, fields.Datetime.now().year + 2)], string='Année de cotisation', required=True) company_id = fields.Many2one( comodel_name='res.company', string='Company', change_default=True, required=True, readonly=True, default=lambda self: self.env.user.company_id) company_currency_id = fields.Many2one( comodel_name='res.currency', related='company_id.currency_id', string="Company Currency", readonly=True) payment_term_id = fields.Many2one( comodel_name='account.payment.term', string="Conditions de paiement", domain=[('is_contribution', '=', True)], required=True, ) date_cotisation = fields.Date("Date de cotisation", required=True) member_count = fields.Integer( "Adhérents renouvelés", compute='_compute_member_count') new_member_count = fields.Integer( "Nouveaux adhérents", compute='_compute_new_member_count') trimester_1 = fields.Date('1er Trimestre') trimester_2 = fields.Date('2ème Trimestre') trimester_3 = fields.Date('3ème Trimestre') trimester_4 = fields.Date('4ème Trimestre') # ------------------------------------------------------ # Compute fields # ------------------------------------------------------ @api.multi def _compute_member_count(self): for cotiz in self: cotiz.member_count = len(cotiz.get_members()) @api.multi def _compute_new_member_count(self): for cotiz in self: cotiz.new_member_count = len(cotiz.get_new_members()) # ------------------------------------------------------ # Global functions # ------------------------------------------------------ def create_contribution( self, product, partner, type_contribution, liasse=None, amount=0, date=False, journal_id=False, account_id=False, type_invoice='out_invoice', is_regul=False, bordereau=False): """ Create invoice from Contribution Base :param product: product_id :param partner: partner_id :param type_contribution: type_contribution (CG, UR, Fédé) :param liasse: liasse_fiscale_id (reference) :param amount: contribution amount (float) :param date: date invoice :param journal_id: journal :param account_id: customer_account_id :param type_invoice: invoice or refund :param is_regul: used for CG Scop regul :return: invoice """ Invoice = self.env['account.invoice'] InvoiceLine = self.env['account.invoice.line'] domain = [ ('partner_id', '=', partner.id), ('year', '=', self.year), ('type_contribution_id', '=', type_contribution), ] if bordereau: domain.append(('bordereau_id', '=', bordereau.id)) exisiting_invoice = Invoice.search(domain) if not exisiting_invoice or is_regul: date_invoice = date if date else self.date_cotisation journal_id = self.company_id.contribution_journal_id \ if not journal_id else journal_id account_id = partner.property_account_receivable_id \ if not account_id else account_id member_invoice = Invoice.create({ 'partner_id': partner.id, 'liasse_fiscale_id': liasse.id, 'type': type_invoice, 'year': self.year, 'is_contribution': True, 'type_contribution_id': type_contribution, 'journal_id': journal_id.id, 'state': 'draft', 'account_id': account_id.id, 'payment_term_id': self.payment_term_id.id, 'payment_mode_id': partner.customer_payment_mode_id.id, 'date_invoice': date_invoice, }) else: member_invoice = exisiting_invoice # Création de la ligne CG Scop exisiting_invoice_line_ids = InvoiceLine.search([ ('invoice_id', '=', member_invoice.id), ('product_id', '=', product.id) ]) if not exisiting_invoice_line_ids or is_regul: InvoiceLine.create({ 'invoice_id': member_invoice.id, 'product_id': product.id, 'account_id': product.property_account_income_id.id, 'invoice_line_tax_ids': [(6, 0, product.taxes_id.ids)], 'name': product.name, 'price_unit': amount }) else: exisiting_invoice_line_ids[0].write({ 'price_unit': amount }) return member_invoice @api.multi def get_members(self): self.ensure_one() members = self.env['scop.membership.period'].search([ ('type_id', '=', self.env.ref( 'cgscop_partner.membership_type_1').id), ('start', '<', date(self.year, 1, 1)), ('end', '=', None), ]).mapped('partner_id') return members @api.multi def get_new_members(self, limit_start_date=None): if not limit_start_date: limit_start_date = date(self.year, 12, 31) self.ensure_one() members = self.env['scop.membership.period'].search([ ('type_id', '=', self.env.ref( 'cgscop_partner.membership_type_1').id), ('start', '>=', date(self.year, 1, 1)), ('start', '<=', limit_start_date), '|', ('end', '=', None), ('end', '>', date(self.year, 1, 1)) ]).mapped('partner_id') return members def round_to_closest_multiple(self, float_to_round, multiple): """ :param float_to_round: :param multiple: :return: closest_multiple """ small_multiple = (float_to_round // multiple) * multiple large_multiple = small_multiple + multiple # Return the closest of two if abs(float_to_round - small_multiple) < \ abs(float_to_round - large_multiple): return small_multiple else: return large_multiple