forked from OCA/account-financial-tools
-
Notifications
You must be signed in to change notification settings - Fork 1
/
run.py
175 lines (154 loc) · 6.6 KB
/
run.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Nicolas Bessi, Guewen Baconnier
# Copyright 2012-2014 Camptocamp SA
#
# 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/>.
#
##############################################################################
import logging
from openerp import models, fields, api, _
logger = logging.getLogger('credit.control.run')
class CreditControlRun(models.Model):
""" Credit Control run generate all credit control lines and reject """
_name = "credit.control.run"
_rec_name = 'date'
_description = "Credit control line generator"
date = fields.Date(string='Controlling Date', required=True,
readonly=True,
states={'draft': [('readonly', False)]})
@api.model
def _get_policies(self):
return self.env['credit.control.policy'].search([])
policy_ids = fields.Many2many(
'credit.control.policy',
rel="credit_run_policy_rel",
id1='run_id', id2='policy_id',
string='Policies',
readonly=True,
states={'draft': [('readonly', False)]},
default=_get_policies,
)
report = fields.Html(string='Report', readonly=True, copy=False)
state = fields.Selection([('draft', 'Draft'),
('done', 'Done')],
string='State',
required=True,
readonly=True,
default='draft')
line_ids = fields.One2many(
comodel_name='credit.control.line',
inverse_name='run_id',
string='Generated lines')
manual_ids = fields.Many2many(
'account.move.line',
rel="credit_runreject_rel",
string='Lines to handle manually',
help='If a credit control line has been generated'
'on a policy and the policy has been changed '
'in the meantime, it has to be handled '
'manually',
readonly=True,
copy=False,
)
@api.multi
def _check_run_date(self, controlling_date):
""" Ensure that there is no credit line in the future
using controlling_date
"""
runs = self.search([('date', '>', controlling_date)],
order='date DESC', limit=1)
if runs:
raise api.Warning(_('A run has already been executed more '
'recently than %s') % (runs.date))
line_obj = self.env['credit.control.line']
lines = line_obj.search([('date', '>', controlling_date)],
order='date DESC', limit=1)
if lines:
raise api.Warning(_('A credit control line more '
'recent than %s exists at %s') %
(controlling_date, lines.date))
@api.multi
@api.returns('credit.control.line')
def _generate_credit_lines(self):
""" Generate credit control lines. """
self.ensure_one()
cr_line_obj = self.env['credit.control.line']
move_line_obj = self.env['account.move.line']
manually_managed_lines = move_line_obj.browse()
self._check_run_date(self.date)
policies = self.policy_ids
if not policies:
raise api.Warning(_('Please select a policy'))
report = ''
generated = cr_line_obj.browse()
for policy in policies:
if policy.do_nothing:
continue
lines = policy._get_move_lines_to_process(self.date)
manual_lines = policy._lines_different_policy(lines)
lines -= manual_lines
manually_managed_lines |= manual_lines
policy_lines_generated = cr_line_obj.browse()
if lines:
# policy levels are sorted by level
# so iteration is in the correct order
create = cr_line_obj.create_or_update_from_mv_lines
for level in reversed(policy.level_ids):
level_lines = level.get_level_lines(self.date, lines)
policy_lines_generated += create(level_lines,
level,
self.date)
generated |= policy_lines_generated
if policy_lines_generated:
report += (_("Policy \"<b>%s</b>\" has generated <b>%d Credit "
"Control Lines.</b><br/>") %
(policy.name, len(policy_lines_generated)))
else:
report += _(
"Policy \"<b>%s</b>\" has not generated any "
"Credit Control Lines.<br/>" % policy.name
)
vals = {'state': 'done',
'report': report,
'manual_ids': [(6, 0, manually_managed_lines.ids)],
'line_ids': [(6, 0, generated.ids)]}
self.write(vals)
return generated
@api.multi
def generate_credit_lines(self):
""" Generate credit control lines
Lock the ``credit_control_run`` Postgres table to avoid concurrent
calls of this method.
"""
try:
self.env.cr.execute('SELECT id FROM credit_control_run'
' LIMIT 1 FOR UPDATE NOWAIT')
except Exception:
# In case of exception openerp will do a rollback
# for us and free the lock
raise api.Warning(_('A credit control run is already running'
' in background, please try later.'))
self._generate_credit_lines()
return True
@api.multi
def open_credit_lines(self):
""" Open the generated lines """
self.ensure_one()
action_name = 'account_credit_control.credit_control_line_action'
action = self.env.ref(action_name)
action = action.read()[0]
action['domain'] = [('id', 'in', self.line_ids.ids)]
return action