~therp-nl/banking-addons/ba61-lp1246642

« back to all changes in this revision

Viewing changes to account_banking_aggregate_payment/model/export_aggregate.py

  • Committer: Holger Brunn
  • Author(s): stefan at therp
  • Date: 2013-06-24 10:19:38 UTC
  • mfrom: (171.3.9 banking-addons)
  • Revision ID: hbrunn@therp.nl-20130624101938-ev5ebcw2i41jmr3b
[ADD] account_banking_aggregate_payment

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
##############################################################################
 
3
#
 
4
#    OpenERP, Open Source Management Solution
 
5
#    This module copyright (C) 2013 Therp BV (<http://therp.nl>).
 
6
#
 
7
#    This program is free software: you can redistribute it and/or modify
 
8
#    it under the terms of the GNU Affero General Public License as
 
9
#    published by the Free Software Foundation, either version 3 of the
 
10
#    License, or (at your option) any later version.
 
11
#
 
12
#    This program is distributed in the hope that it will be useful,
 
13
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
#    GNU Affero General Public License for more details.
 
16
#
 
17
#    You should have received a copy of the GNU Affero General Public License
 
18
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
#
 
20
##############################################################################
 
21
 
 
22
from openerp.osv import orm, fields
 
23
from openerp.tools.translate import _
 
24
from openerp import netsvc
 
25
 
 
26
 
 
27
class banking_export_aggregate(orm.TransientModel):
 
28
    _name = 'banking.export.aggregate'
 
29
    _description = 'Execute aggregate payment order'
 
30
    _rec_name = 'payment_order_id'
 
31
 
 
32
    _columns = {
 
33
        'payment_order_id': fields.many2one(
 
34
            'payment.order', 'Payment order',
 
35
            required=True),
 
36
        }
 
37
 
 
38
    def create(self, cr, uid, vals, context=None):
 
39
        if context is None:
 
40
            context = {}
 
41
        if not vals.get('payment_order_id'):
 
42
            if not context.get('active_ids'):
 
43
                raise orm.except_orm(
 
44
                    _('Error'),
 
45
                    _('Please select a payment order'))
 
46
            if len(context['active_ids']) > 1:
 
47
                raise orm.except_orm(
 
48
                    _('Error'),
 
49
                    _('Please only select a single payment order'))
 
50
            vals['payment_order_id'] = context['active_ids'][0]
 
51
        return super(banking_export_aggregate, self).create(
 
52
            cr, uid, vals, context=context)
 
53
 
 
54
    def reconcile_lines(self, cr, uid, move_line_ids, context=None):
 
55
        """
 
56
        Reconcile move lines lines, really. ERP core functionality.
 
57
        """
 
58
        reconcile_obj = self.pool.get('account.move.reconcile')
 
59
        account_move_line_obj = self.pool.get('account.move.line')
 
60
        currency_obj = self.pool.get('res.currency')
 
61
        lines = account_move_line_obj.browse(cr, uid, move_line_ids, context=context)
 
62
 
 
63
        for line in lines[1:]:
 
64
            if line.account_id != lines[0].account_id:
 
65
                raise orm.except_orm(
 
66
                    _('Error'),
 
67
                    _('Cannot reconcile between different accounts'))
 
68
 
 
69
        if any([line.reconcile_id and line.reconcile_id.line_id
 
70
                for line in lines]):
 
71
            raise orm.except_orm(
 
72
                _('Error'),
 
73
                _('Line is already fully reconciled'))
 
74
            
 
75
        currency = lines[0].company_id.currency_id
 
76
 
 
77
        partials = []
 
78
        line_ids = []
 
79
        for line in lines:
 
80
            if line.id not in line_ids:
 
81
                line_ids.append(line.id)
 
82
            if line.reconcile_partial_id:
 
83
                line_ids += line.reconcile_partial_id.line_partial_ids
 
84
                if line.reconcile_partial_id.id not in partials:
 
85
                    partials.append(line.reconcile_partial_id.id)
 
86
 
 
87
        total = account_move_line_obj.get_balance(cr, uid, line_ids)
 
88
        is_zero = currency_obj.is_zero(cr, uid, currency, total)
 
89
 
 
90
        vals = {
 
91
            'type': 'auto',
 
92
            'line_id': is_zero and [(6, 0, line_ids)] or [(6, 0, [])],
 
93
            'line_partial_ids': is_zero and [(6, 0, [])] or [(6, 0, line_ids)],
 
94
            }
 
95
 
 
96
        if partials:
 
97
            if len(partials) > 1:
 
98
                reconcile_obj.unlink(
 
99
                    cr, uid, partials[1:], context=context)
 
100
            reconcile_obj.write(
 
101
                cr, uid, partials[0],
 
102
                vals, context=context)
 
103
        else:
 
104
            reconcile_obj.create(
 
105
                cr, uid, vals, context=context)
 
106
 
 
107
        for line_id in line_ids:
 
108
            netsvc.LocalService("workflow").trg_trigger(
 
109
                uid, 'account.move.line', line_id, cr)
 
110
        return True
 
111
 
 
112
    def create_aggregate_order(self, cr, uid, ids, context=None):
 
113
        wiz = self.browse(cr, uid, ids[0], context=context)
 
114
        account_move_line_obj = self.pool.get('account.move.line')
 
115
        account_move_obj = self.pool.get('account.move')
 
116
        payment_order_obj = self.pool.get('payment.order')
 
117
        payment_order_line_obj = self.pool.get('payment.line')
 
118
        payment_order_ids = context.get('active_ids', [])
 
119
        if not payment_order_ids:
 
120
            raise orm.except_orm(
 
121
                _('Error'),
 
122
                _('Please select a payment order'))
 
123
        if len(payment_order_ids) > 1:
 
124
            raise orm.except_orm(
 
125
                _('Error'),
 
126
                _('This operation can only be performed on a single '
 
127
                  'payment order'))
 
128
 
 
129
        today = fields.date.context_today(self, cr, uid, context=context)
 
130
        order = payment_order_obj.browse(
 
131
            cr, uid, payment_order_ids[0], context=context)
 
132
 
 
133
        move_id = account_move_obj.create(cr, uid, {
 
134
                'journal_id': order.mode.transfer_journal_id.id,
 
135
                'ref': _('Aggregate Payment Order %s') % order.reference,
 
136
                }, context=context)
 
137
 
 
138
        counter_move_line_ids = []
 
139
        for line in order.line_ids:
 
140
            # basic checks
 
141
            if not line.move_line_id:
 
142
                raise orm.except_orm(
 
143
                    _('Error'),
 
144
                    _('No move line provided for line %s') % line.name)
 
145
            if line.move_line_id.reconcile_id:
 
146
                raise orm.except_orm(
 
147
                    _('Error'),
 
148
                    _('Move line %s has already been paid/reconciled') % 
 
149
                    line.move_line_id.name
 
150
                    )
 
151
 
 
152
            # TODO: take multicurrency into account?
 
153
            
 
154
            # create the move line on the transfer account
 
155
            vals = {
 
156
                'name': _('Transit %s') % (
 
157
                    line.move_line_id.invoice and 
 
158
                    line.move_line_id.invoice.number or 
 
159
                    line.move_line_id.ref),
 
160
                'move_id': move_id,
 
161
                'partner_id': line.partner_id and line.partner_id.id or False,
 
162
                'account_id': order.mode.transfer_account_id.id,
 
163
                'credit': line.amount,
 
164
                'debit': 0.0,
 
165
                'date': today,
 
166
                }
 
167
            counter_move_line_id = account_move_line_obj.create(
 
168
                cr, uid, vals, context=context)
 
169
            counter_move_line_ids.append(counter_move_line_id)
 
170
 
 
171
            # create the debit move line on the receivable account
 
172
            vals.update({
 
173
                    'name': _('Reconciliation %s') % (
 
174
                        line.move_line_id.invoice and 
 
175
                        line.move_line_id.invoice.number or 
 
176
                        line.move_line_id.name),
 
177
                    'account_id': line.move_line_id.account_id.id,
 
178
                    'credit': 0.0,
 
179
                    'debit': line.amount,
 
180
                    })               
 
181
            reconcile_move_line_id = account_move_line_obj.create(
 
182
                cr, uid, vals, context=context)
 
183
                
 
184
            self.reconcile_lines(
 
185
                cr, uid, [reconcile_move_line_id, line.move_line_id.id],
 
186
                context=context)
 
187
 
 
188
        total = account_move_line_obj.get_balance(
 
189
            cr, uid, counter_move_line_ids)
 
190
 
 
191
        vals = {
 
192
            'name': _('Transit reconciliation'),
 
193
            'move_id': move_id,
 
194
            'partner_id': order.mode.aggregate_partner_id.id,
 
195
            'account_id': order.mode.transfer_account_id.id,
 
196
            'debit': total < 0 and -total or 0.0,
 
197
            'credit': total >= 0 and total or 0.0,
 
198
            'date': today,
 
199
            }
 
200
        aggregate_move_line_id = account_move_line_obj.create(
 
201
            cr, uid, vals, context=context)
 
202
 
 
203
        self.reconcile_lines(
 
204
            cr, uid, counter_move_line_ids + [aggregate_move_line_id],
 
205
            context=context)
 
206
 
 
207
        # create the credit move line on the aggregate partner
 
208
        vals.update({
 
209
                'name': _('Amount payable'),
 
210
                'account_id': order.mode.aggregate_partner_id.property_account_payable.id,
 
211
                'partner_id': order.mode.aggregate_partner_id.id,
 
212
                'debit': total >= 0 and total or 0.0,
 
213
                'credit': total < 0 and -total or 0.0,
 
214
                })               
 
215
 
 
216
        payable_move_line = account_move_line_obj.browse(
 
217
            cr, uid,
 
218
            account_move_line_obj.create(
 
219
                cr, uid, vals, context=context),
 
220
            context=context)
 
221
 
 
222
        account_move_obj.post(cr, uid, [move_id], context=context)
 
223
 
 
224
        wf_service = netsvc.LocalService('workflow')
 
225
        wf_service.trg_validate(uid, 'payment.order', order.id, 'sent', cr)
 
226
        wf_service.trg_validate(uid, 'payment.order', order.id, 'done', cr)
 
227
        order.refresh()
 
228
        if order.state != 'done':
 
229
            raise orm.except_orm(
 
230
                _('Error'),
 
231
                _('Payment order workflow does not go into state "done"'))
 
232
 
 
233
        payment_order_id = payment_order_obj.create(
 
234
            cr, uid, {
 
235
                'company_id': order.company_id.id,
 
236
                'mode': order.mode.chained_mode_id.id,
 
237
                }, context=context)
 
238
 
 
239
        lines2bank = account_move_line_obj.line2bank(
 
240
            cr, uid, [payable_move_line.id], order.mode.id, context)
 
241
 
 
242
        payment_order_line_obj.create(cr, uid,{
 
243
                'move_line_id': payable_move_line.id,
 
244
                'amount_currency': payable_move_line.amount_to_pay,
 
245
                'bank_id': lines2bank.get(payable_move_line.id),
 
246
                'order_id': payment_order_id,
 
247
                'partner_id': order.mode.aggregate_partner_id.id,
 
248
                'communication': order.reference.replace('/', ''),
 
249
                'communication2': False,
 
250
                'state': 'structured',
 
251
                'date': today,
 
252
                'currency': (
 
253
                    line.move_line_id.journal_id.currency.id or
 
254
                    line.move_line_id.journal_id.company_id.currency_id.id),
 
255
                }, context=context)
 
256
 
 
257
        return {
 
258
            'name': payment_order_obj._description,
 
259
            'view_type': 'form',
 
260
            'view_mode': 'form',
 
261
            'res_model': payment_order_obj._name,
 
262
            'domain': [],
 
263
            'context': context,
 
264
            'type': 'ir.actions.act_window',
 
265
            'target': 'current',
 
266
            'res_id': payment_order_id,
 
267
            'nodestroy': True,
 
268
            }