~zaber/openobject-addons/zaber-custom

« back to all changes in this revision

Viewing changes to account_payment_extension/account_move_line.py

  • Committer: Aki Mimoto
  • Date: 2013-08-27 12:25:06 UTC
  • Revision ID: aki+launchpad@zaber.com-20130827122506-e4hildop20zysli2
[IMP] Add modules from extras repo: account_payment_extension/ purchase_payment/

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- encoding: utf-8 -*-
 
2
##############################################################################
 
3
#
 
4
#    OpenERP, Open Source Management Solution
 
5
#    Copyright (c) 2008 Zikzakmedia S.L. (http://zikzakmedia.com) All Rights Reserved.
 
6
#                       Jordi Esteve <jesteve@zikzakmedia.com>
 
7
#    $Id$
 
8
#
 
9
#    This program is free software: you can redistribute it and/or modify
 
10
#    it under the terms of the GNU Affero General Public License as published by
 
11
#    the Free Software Foundation, either version 3 of the License, or
 
12
#    (at your option) any later version.
 
13
#
 
14
#    This program is distributed in the hope that it will be useful,
 
15
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
#    GNU Affero General Public License for more details.
 
18
#
 
19
#    You should have received a copy of the GNU Affero General Public License
 
20
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
21
#
 
22
##############################################################################
 
23
 
 
24
import netsvc
 
25
from osv import fields, osv
 
26
 
 
27
class account_move_line(osv.osv):
 
28
    _name = 'account.move.line'
 
29
    _inherit = 'account.move.line'
 
30
 
 
31
    def _invoice(self, cr, uid, ids, name, arg, context=None):
 
32
        return super(account_move_line, self)._invoice(cr, uid, ids, name, arg, context)
 
33
 
 
34
    def _invoice_search(self, cr, uid, obj, name, args, context={}):
 
35
        """ Redefinition for searching account move lines without any invoice related ('invoice.id','=',False)"""
 
36
        for x in args:
 
37
            if (x[2] is False) and (x[1] == '=') and (x[0] == 'invoice'):
 
38
                cr.execute('SELECT l.id FROM account_move_line l ' \
 
39
                    'LEFT JOIN account_invoice i ON l.move_id = i.move_id ' \
 
40
                    'WHERE i.id IS NULL', [])
 
41
                res = cr.fetchall()
 
42
                if not len(res):
 
43
                    return [('id', '=', '0')]
 
44
                return [('id', 'in', [x[0] for x in res])]
 
45
        return super(account_move_line, self)._invoice_search(cr, uid, obj, name, args, context=context)
 
46
 
 
47
    def amount_to_pay(self, cr, uid, ids, name, arg={}, context={}):
 
48
        """
 
49
        Return amount pending to be paid taking into account payment lines and the reconciliation.
 
50
        Note that the amount to pay can be due to negative supplier refund invoices or customer invoices.
 
51
        """
 
52
 
 
53
        if not ids:
 
54
            return {}
 
55
        cr.execute("""SELECT ml.id,
 
56
                    CASE WHEN ml.amount_currency < 0
 
57
                        THEN - ml.amount_currency
 
58
                        WHEN ml.amount_currency > 0
 
59
                        THEN ml.amount_currency
 
60
                        ELSE ml.credit - ml.debit
 
61
                    END AS debt,
 
62
                    (SELECT coalesce(sum(CASE WHEN pl.type='receivable' THEN -amount_currency ELSE amount_currency END),0)
 
63
                        FROM payment_line pl
 
64
                            INNER JOIN payment_order po
 
65
                                ON (pl.order_id = po.id)
 
66
                        WHERE 
 
67
                            pl.move_line_id = ml.id AND
 
68
                            pl.payment_move_id IS NULL AND 
 
69
                            po.state != 'cancel'
 
70
                    ) AS paid,
 
71
                    (
 
72
                        SELECT
 
73
                            COALESCE( SUM(COALESCE(amrl.credit,0) - COALESCE(amrl.debit,0)), 0 )
 
74
                        FROM
 
75
                            account_move_reconcile amr,
 
76
                            account_move_line amrl
 
77
                        WHERE
 
78
                            amr.id = amrl.reconcile_partial_id AND
 
79
                            amr.id = ml.reconcile_partial_id
 
80
                    ) AS unreconciled,
 
81
                    reconcile_id
 
82
                    FROM account_move_line ml
 
83
                    WHERE id in (%s)""" % (",".join([str(int(x)) for x in ids])))
 
84
        result = {}
 
85
        for record in cr.fetchall():
 
86
            id = record[0]
 
87
            debt = record[1] or 0.0
 
88
            paid = record[2]
 
89
            unreconciled = record[3]
 
90
            reconcile_id = record[4]
 
91
            if reconcile_id:
 
92
                debt = 0.0
 
93
            else:
 
94
                if not unreconciled:
 
95
                    unreconciled = debt
 
96
                if debt > 0:
 
97
                    debt = min(debt - paid, max(0.0, unreconciled))
 
98
                else:
 
99
                    debt = max(debt - paid, min(0.0, unreconciled))
 
100
            result[id] = debt
 
101
        return result
 
102
 
 
103
    def _to_pay_search(self, cr, uid, obj, name, args, context={}):
 
104
        if not len(args):
 
105
            return []
 
106
        currency = self.pool.get('res.users').browse(cr, uid, uid, context).company_id.currency_id
 
107
 
 
108
        # For searching we first discard reconciled moves because the filter is fast and discards most records
 
109
        # quickly.
 
110
        ids = self.pool.get('account.move.line').search(cr, uid, [('reconcile_id','=',False)], context=context)
 
111
        records = self.pool.get('account.move.line').read(cr, uid, ids, ['id', 'amount_to_pay'], context)
 
112
        ids = []
 
113
        for record in records:
 
114
            if not self.pool.get('res.currency').is_zero( cr, uid, currency, record['amount_to_pay'] ):
 
115
                ids.append( record['id'] )
 
116
        if not ids:
 
117
            return [('id','=',False)]
 
118
        return [('id','in',ids)]
 
119
 
 
120
    def _payment_type_get(self, cr, uid, ids, field_name, arg, context={}):
 
121
        result = {}
 
122
        invoice_obj = self.pool.get('account.invoice')
 
123
        for rec in self.browse(cr, uid, ids, context):
 
124
            result[rec.id] = (0,0)
 
125
            invoice_id = invoice_obj.search(cr, uid, [('move_id', '=', rec.move_id.id)], context=context)
 
126
            if invoice_id:
 
127
                inv = invoice_obj.browse(cr, uid, invoice_id[0], context)
 
128
                if inv.payment_type:
 
129
                    result[rec.id] = (inv.payment_type.id, self.pool.get('payment.type').browse(cr, uid, inv.payment_type.id, context).name)
 
130
            else:
 
131
                result[rec.id] = (0,0)
 
132
        return result
 
133
 
 
134
    def _payment_type_search(self, cr, uid, obj, name, args, context={}):
 
135
        if not len(args):
 
136
            return []
 
137
        operator = args[0][1]
 
138
        value = args[0][2]
 
139
        if not value:
 
140
            return []
 
141
        if isinstance(value, int) or isinstance(value, long):
 
142
            ids = [value]
 
143
        elif isinstance(value, list):
 
144
            ids = value 
 
145
        else:
 
146
            ids = self.pool.get('payment.type').search(cr,uid,[('name','ilike',value)], context=context)
 
147
        if ids:
 
148
            cr.execute('SELECT l.id ' \
 
149
                'FROM account_move_line l, account_invoice i ' \
 
150
                'WHERE l.move_id = i.move_id AND i.payment_type in (%s)' % (','.join(map(str, ids))))
 
151
            res = cr.fetchall()
 
152
            if len(res):
 
153
                return [('id', 'in', [x[0] for x in res])]
 
154
        return [('id','=','0')]
 
155
 
 
156
    _columns = {
 
157
        'invoice': fields.function(_invoice, method=True, string='Invoice',
 
158
            type='many2one', relation='account.invoice', fnct_search=_invoice_search),
 
159
        'received_check': fields.boolean('Received check', help="To write down that a check in paper support has been received, for example."),
 
160
        'partner_bank_id': fields.many2one('res.partner.bank','Bank Account'),
 
161
        'amount_to_pay' : fields.function(amount_to_pay, method=True, type='float', string='Amount to pay', fnct_search=_to_pay_search),
 
162
        'payment_type': fields.function(_payment_type_get, fnct_search=_payment_type_search, method=True, type="many2one", relation="payment.type", string="Payment type"),
 
163
    }
 
164
 
 
165
    def write(self, cr, uid, ids, vals, context=None, check=True, update_check=True):
 
166
        for key in vals.keys():
 
167
            if key not in ['received_check', 'partner_bank_id', 'date_maturity']:
 
168
                return super(account_move_line, self).write(cr, uid, ids, vals, context, check, update_check)
 
169
        return super(account_move_line, self).write(cr, uid, ids, vals, context, check, update_check=False)
 
170
 
 
171
    def fields_view_get(self, cr, uid, view_id=None, view_type='form', context={}, toolbar=False, submenu=False):
 
172
        menus = [
 
173
            self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account_payment_extension', 'menu_action_invoice_payments'),
 
174
            self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account_payment_extension', 'menu_action_done_payments'),
 
175
        ]
 
176
        menus = [m[1] for m in menus]
 
177
        if 'active_id' in context and context['active_id'] in menus:
 
178
            # Use standard views for account.move.line object
 
179
            if view_type == 'search':
 
180
                # Get a specific search view (bug in 6.0RC1, it does not give the search view defined in the action window)
 
181
                view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account_payment_extension', 'view_payments_filter')[1]
 
182
            result = super(osv.osv, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar=toolbar, submenu=submenu)
 
183
        else:
 
184
            # Use special views for account.move.line object (for ex. tree view contains user defined fields)
 
185
            result = super(account_move_line, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar=toolbar, submenu=submenu)
 
186
        return result
 
187
 
 
188
account_move_line()
 
189
 
 
190
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: