/
account_move.py
148 lines (127 loc) · 5.69 KB
/
account_move.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
# © 2019 Eficent Business and IT Consulting Services S.L.
# © 2019 Serpent Consulting Services Pvt. Ltd.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from odoo import api, fields, models, _
from odoo.exceptions import UserError
class AccountMoveLine(models.Model):
_inherit = "account.move.line"
operating_unit_id = fields.Many2one(
comodel_name='operating.unit',
string='Operating Unit',
domain="[('user_ids', '=', uid)]",)
@api.model
def create(self, vals):
if vals.get('move_id', False):
move = self.env['account.move'].browse(vals['move_id'])
if move.operating_unit_id:
vals['operating_unit_id'] = move.operating_unit_id.id
return super(AccountMoveLine, self).create(vals)
@api.model
def _query_get(self, domain=None):
if domain is None:
domain = []
if self._context.get('operating_unit_ids', False):
domain.append(('operating_unit_id', 'in',
self._context.get('operating_unit_ids')))
return super(AccountMoveLine, self)._query_get(domain)
@api.multi
@api.constrains('operating_unit_id', 'company_id')
def _check_company_operating_unit(self):
for rec in self:
if (rec.company_id and rec.operating_unit_id and rec.company_id !=
rec.operating_unit_id.company_id):
raise UserError(_('Configuration error. The Company in the'
' Move Line and in the Operating Unit must '
'be the same.'))
@api.multi
@api.constrains('operating_unit_id', 'move_id')
def _check_move_operating_unit(self):
for rec in self:
if (rec.move_id and rec.move_id.operating_unit_id and
rec.operating_unit_id and rec.move_id.operating_unit_id !=
rec.operating_unit_id):
raise UserError(_('Configuration error. The Operating Unit in'
' the Move Line and in the Move must be the'
' same.'))
class AccountMove(models.Model):
_inherit = "account.move"
operating_unit_id = fields.Many2one(
comodel_name='operating.unit',
string='Default operating unit',
domain="[('user_ids', '=', uid)]",
help="This operating unit will be "
"defaulted in the move lines.")
@api.multi
def _prepare_inter_ou_balancing_move_line(self, move, ou_id,
ou_balances):
if not move.company_id.inter_ou_clearing_account_id:
raise UserError(_('Configuration error. You need to define an \
inter-operating unit clearing account in the company settings'))
res = {
'name': 'OU-Balancing',
'move_id': move.id,
'journal_id': move.journal_id.id,
'date': move.date,
'operating_unit_id': ou_id,
'account_id': move.company_id.inter_ou_clearing_account_id.id
}
if ou_balances[ou_id] < 0.0:
res['debit'] = abs(ou_balances[ou_id])
else:
res['credit'] = ou_balances[ou_id]
return res
@api.multi
def _check_ou_balance(self, move):
# Look for the balance of each OU
ou_balance = {}
for line in move.line_ids:
if line.operating_unit_id.id not in ou_balance:
ou_balance[line.operating_unit_id.id] = 0.0
ou_balance[line.operating_unit_id.id] += (line.debit - line.credit)
return ou_balance
@api.multi
def post(self, invoice=False):
ml_obj = self.env['account.move.line']
for move in self:
if not move.company_id.ou_is_self_balanced:
continue
# If all move lines point to the same operating unit, there's no
# need to create a balancing move line
ou_list_ids = [line.operating_unit_id and
line.operating_unit_id.id for line in
move.line_ids if line.operating_unit_id]
if len(ou_list_ids) <= 1:
continue
# Create balancing entries for un-balanced OU's.
ou_balances = self._check_ou_balance(move)
amls = []
for ou_id in list(ou_balances.keys()):
# If the OU is already balanced, then do not continue
if move.company_id.currency_id.is_zero(ou_balances[ou_id]):
continue
# Create a balancing move line in the operating unit
# clearing account
line_data = self._prepare_inter_ou_balancing_move_line(
move, ou_id, ou_balances)
if line_data:
amls.append(ml_obj.with_context(wip=True).
create(line_data))
if amls:
move.with_context(wip=False).\
write({'line_ids': [(4, aml.id) for aml in amls]})
return super(AccountMove, self).post(invoice)
def assert_balanced(self):
if self.env.context.get('wip'):
return True
return super(AccountMove, self).assert_balanced()
@api.multi
@api.constrains('line_ids')
def _check_ou(self):
for move in self:
if not move.company_id.ou_is_self_balanced:
continue
for line in move.line_ids:
if not line.operating_unit_id:
raise UserError(_('Configuration error. The operating\
unit is mandatory for each line as the operating\
unit has been defined as self-balanced at company level.'))