yaltik_odoo_custom/grant_followup/models/grant_file.py

239 lines
12 KiB
Python

# -*- coding: utf-8 -*-
# Copyright 2018 Youssef El Ouahby <youssef@yaltik.com>
# Copyright 2018 Fabien Bourgeois <fabien@yaltik.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
""" Grant File Management"""
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
class GrantFile(models.Model):
""" Grant File Management """
_name = 'grant.file'
_inherit = 'mail.thread'
_order = 'significance desc, reply_deadline asc, state asc'
_rec_name = 'title'
title = fields.Char(required=True, index=True, readonly=True,
states={'1_draft': [('readonly', False)],
'3_edited': [('readonly', False)]})
description = fields.Text()
note = fields.Text()
partner_id = fields.Many2one('res.partner', index=True, readonly=True,
auto_join=True, string='Main partner',
states={'1_draft': [('readonly', False)],
'3_edited': [('readonly', False)]})
partner_ids = fields.Many2many(
'res.partner', index=True, auto_join=True,
readonly=True, string='Other partners',
states={'1_draft': [('readonly', False)],
'3_edited': [('readonly', False)],
'4_grant_notification': [('readonly', False)]})
display_partner_ids = fields.Char(compute='_compute_display_partner_ids')
responsible_id = fields.Many2one('res.users', string='Responsible',
auto_join=True, index=True,
default=lambda self: self.env.user)
reply_deadline = fields.Date(index=True, readonly=True,
states={'1_draft': [('readonly', False)],
'3_edited': [('readonly', False)]})
assessment_deadline = fields.Date(index=True, readonly=True,
states={'1_draft': [('readonly', False)],
'3_edited': [('readonly', False)],
'4_grant_notification': [('readonly', False)]})
significance = fields.Selection([('0', 'Not evaluated'),
('1', 'Common'),
('2', 'Medium'),
('3', 'High'),
('4', 'Critical')],
default='0', copy=False)
state = fields.Selection([('0_refused', 'Refused'),
('1_draft', 'Draft'),
('2_sent', 'Sent'),
('3_edited', 'Edited'),
('4_grant_notification', 'Grant Notification'),
('6_first_paiement_received', 'First Paiement Received'),
('7_finished', 'Finished')],
default='1_draft', copy=False, track_visibility='onchange')
requested_amount = fields.Monetary(readonly=True, required=True,
states={'1_draft': [('readonly', False)],
'3_edited': [('readonly', False)]})
notified_amount = fields.Monetary(readonly=True, copy=False,
states={'4_grant_notification': [('readonly', False),
('required', True)]})
received_amount = fields.Monetary(readonly=False, copy=False,
track_visibility='onchange',
states={'0_refused': [('readonly', True)],
'1_draft': [('readonly', True)],
'7_finished': [('readonly', True)]})
currency_id = fields.Many2one('res.currency', string='Currency',
required=True, auto_join=True,
default=lambda self: self.env.user.company_id.currency_id)
amount_line_ids = fields.One2many('grant.file.amount.line', 'file_id',
string='Amount lines')
assessment_sent = fields.Boolean('Has assessment been sent ?', readonly=True,
copy=False, track_visibility='onchange')
color = fields.Integer('Color Index')
attachment_ids = fields.One2many(
'ir.attachment', 'res_id', string='Attachments', auto_join=True,
domain=[('res_model', '=', 'grant.file')])
doc_count = fields.Integer(compute='_compute_doc_count')
@api.depends('partner_ids')
def _compute_display_partner_ids(self):
""" Computes display partners """
for gfile in self:
if gfile.partner_ids:
gfile.display_partner_ids = u', '.join(gfile.partner_ids.mapped('name'))
else:
gfile.display_partner_ids = u''
@api.depends('attachment_ids')
def _compute_doc_count(self):
""" Computes doc count """
for gfile in self:
gfile.doc_count = len(gfile.attachment_ids)
@api.multi
def state_refused(self):
""" Updates state to refused """
self.write({'state': '0_refused'})
@api.multi
def state_draft(self):
""" Updates state to draft """
self.write({'state': '1_draft'})
@api.multi
def state_sent(self):
""" Updates state to sent """
self.write({'state': '2_sent'})
@api.multi
def state_grant_notification(self):
""" Updates state to notidication granted """
self.write({'state': '4_grant_notification'})
@api.multi
def sent_assessment(self):
""" Updates state to Assessment sent to True """
for gfile in self:
if gfile.state not in ('4_grant_notification',
'6_first_paiement_received', '7_finished'):
verr = _('You can only mark assessment as sent when grant had '
'been notified.')
raise ValidationError(verr)
self.write({'assessment_sent': True})
@api.multi
def unsent_assessment(self):
""" Updates state to Assessment sent to False """
self.write({'assessment_sent': False})
@api.multi
def state_edit(self):
""" Wizard to enter update reason """
self.ensure_one()
grant_file_id = self[0]
return {'name': _('Please enter the update reason'),
'type': 'ir.actions.act_window',
'res_model': 'grant.file.edit.wizard',
'context': {'default_grant_file_id': grant_file_id.id},
'view_mode': 'form',
'target': 'new'}
@api.constrains('requested_amount', 'notified_amount')
def check_notified_amount(self):
""" Checks notified amount is filled, according to file state """
for gfile in self:
if not gfile.requested_amount or gfile.requested_amount <= 0.0:
verr = _('You must enter a signed requested amount.')
raise ValidationError(verr)
if gfile.state == '4_grant_notification' and gfile.notified_amount <= 0.0:
verr = _('You must enter a signed notified amount.')
raise ValidationError(verr)
@api.constrains('received_amount')
def check_received_amount(self):
""" Check received amount to finish application """
for grant in self:
if grant.received_amount:
if 0 < grant.received_amount < grant.notified_amount:
grant.write({'state': '6_first_paiement_received'}, bypass=True)
elif grant.received_amount and \
(grant.received_amount == grant.notified_amount):
grant.write({'state': '7_finished'}, bypass=True)
else:
verr = _('Operation not allowed, received amount should be a '
'value between 0 and notified amount')
raise ValidationError(verr)
@api.constrains('amount_line_ids')
def check_amount_details(self):
""" Checks coherence between declared amounts and details """
for gfile in self:
if gfile.amount_line_ids:
if gfile.notified_amount != sum(gfile.amount_line_ids.mapped('notified_amount')):
verr = _('Sum of notified amounts on amount details is not '
'the same as global notified amount. Please check '
'your fills.')
raise ValidationError(verr)
if gfile.received_amount != sum(gfile.amount_line_ids.mapped('received_amount')):
verr = _('Sum of received amounts on amount details is not '
'the same as global received amount. Please check '
'your fills.')
raise ValidationError(verr)
@api.multi
def write(self, vals, bypass=False):
""" Check state update coherence """
notified_val = vals.get('notified_amount', 0.0)
if notified_val <= 0.0:
self.check_notified_amount()
if 'state' in vals:
vstate = vals.get('state')
for gfile in self:
if vstate == '0_refused' and gfile.state not in ('2_sent', '3_edited'):
verr = _('You are only allowed to update to refused from '
'sent or edited states.')
raise ValidationError(verr)
elif vstate == '1_draft' and gfile.state not in ('2_sent', '0_refused'):
verr = _('You are only allowed to update to draft from sent '
'or refused states.')
raise ValidationError(verr)
elif vstate == '2_sent' and gfile.state != '1_draft':
verr = _('You are only allowed to update to sent state from draft.')
raise ValidationError(verr)
elif vstate == '3_edited' and gfile.state not in ('2_sent', '3_edited'):
verr = _('You are only allowed to update to edit from sent '
'or edit states.')
raise ValidationError(verr)
elif vstate == '4_grant_notification' and \
gfile.state not in ('2_sent', '3_edited'):
verr = _('You are only allowed to update to notidied from '
'sent or edit states.')
raise ValidationError(verr)
elif vstate in ('6_first_paiement_received', '7_finished') and not bypass:
verr = _('You can not change manually to paid or finished '
'state : fill received amount to achieve this.')
raise ValidationError(verr)
return super(GrantFile, self).write(vals)