~account-core-editors/account-invoice-report/github-7.0

« back to all changes in this revision

Viewing changes to partner_aging/customer.py

  • Committer: Alexandre Fayolle
  • Date: 2015-08-03 09:19:17 UTC
  • mfrom: (78.1.15)
  • Revision ID: git-v1:97fee65e57d1d9475f4be92ac2db3448211a237e
Merge pull request #32 from savoirfairelinux/partner_aging

Partner aging

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
#    Copyright (C) 2014 Ursa Informative Systems (<www.ursainfosystems.com>).
 
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
 
 
23
from openerp.osv import fields, orm
 
24
from openerp import tools
 
25
 
 
26
 
 
27
class PartnerAgingCustomer(orm.Model):
 
28
    _name = 'partner.aging.customer'
 
29
    _auto = False
 
30
 
 
31
    def open_document(self, cr, uid, ids, context=None):
 
32
        """
 
33
        @description  Open document (invoice or payment) related to the
 
34
                      unapplied payment or outstanding balance on this line
 
35
        """
 
36
        if not context:
 
37
            context = {}
 
38
        models = self.pool.get('ir.model.data')
 
39
        # Get this line's invoice id
 
40
        inv_id = self.browse(cr, uid, ids[0], context=context).invoice_id.id
 
41
 
 
42
        # if this is an unapplied payment(all unapplied payments hard-coded to
 
43
        # -999), get the referenced voucher
 
44
        if inv_id == -999:
 
45
            ref = self.browse(cr, uid, ids[0], context=context).invoice_ref
 
46
            voucher_pool = self.pool['account.voucher']
 
47
            # Get referenced customer payment (invoice_ref field is actually a
 
48
            # payment for these)
 
49
            voucher_id = voucher_pool.search(
 
50
                cr,
 
51
                uid,
 
52
                [('number', '=', ref)],
 
53
                limit=1,
 
54
                context=context,
 
55
            )[0]
 
56
            view = models.get_object_reference(
 
57
                cr,
 
58
                uid,
 
59
                'account_voucher',
 
60
                'view_voucher_form'
 
61
            )
 
62
            # Set values for form
 
63
            view_id = view and view[1] or False
 
64
            name = 'Customer Payments'
 
65
            res_model = 'account.voucher'
 
66
            ctx = "{}"
 
67
            doc_id = voucher_id
 
68
        # otherwise get the invoice
 
69
        else:
 
70
            view = models.get_object_reference(
 
71
                cr,
 
72
                uid,
 
73
                'account',
 
74
                'invoice_form'
 
75
            )
 
76
            view_id = view and view[1] or False
 
77
            name = 'Customer Invoices'
 
78
            res_model = 'account.invoice'
 
79
            ctx = "{'type':'out_invoice'}"
 
80
            doc_id = inv_id
 
81
 
 
82
        if not doc_id:
 
83
            return {}
 
84
 
 
85
        # Open up the document's form
 
86
        return {
 
87
            'name': (name),
 
88
            'view_type': 'form',
 
89
            'view_mode': 'form',
 
90
            'view_id': [view_id],
 
91
            'res_model': res_model,
 
92
            'context': ctx,
 
93
            'type': 'ir.actions.act_window',
 
94
            'nodestroy': True,
 
95
            'target': 'current',
 
96
            'res_id': doc_id,
 
97
        }
 
98
 
 
99
    _columns = {
 
100
        'partner_id': fields.many2one(
 
101
            'res.partner',
 
102
            u'Partner',
 
103
            readonly=True
 
104
        ),
 
105
        'partner_name': fields.text('Name', readonly=True),
 
106
        'avg_days_overdue': fields.integer(u'Avg Days Overdue', readonly=True),
 
107
        'date': fields.date(u'Due Date', readonly=True),
 
108
        'total': fields.float(u'Total', readonly=True),
 
109
        'days_due_01to30': fields.float(u'01/30', readonly=True),
 
110
        'days_due_31to60': fields.float(u'31/60', readonly=True),
 
111
        'days_due_61to90': fields.float(u'61/90', readonly=True),
 
112
        'days_due_91to120': fields.float(u'91/120', readonly=True),
 
113
        'days_due_121togr': fields.float(u'+121', readonly=True),
 
114
        'max_days_overdue': fields.integer(
 
115
            u'Days Overdue',
 
116
            group_operator="max",
 
117
            readonly=True
 
118
        ),
 
119
        'current': fields.float(u'Total', readonly=True),
 
120
        'invoice_ref': fields.char('Reference', size=25, readonly=True),
 
121
        'invoice_id': fields.many2one(
 
122
            'account.invoice',
 
123
            'Invoice',
 
124
            readonly=True
 
125
        ),
 
126
        'currency_name': fields.text('Currency', readonly=True),
 
127
        'comment': fields.text('Notes', readonly=True),
 
128
        'salesman': fields.many2one('res.users', u'Sales Rep', readonly=True),
 
129
    }
 
130
 
 
131
    _order = 'partner_name'
 
132
 
 
133
    def init(self, cr):
 
134
        """
 
135
        @author       Ursa Information Systems
 
136
        @description  Update table on load with latest aging information
 
137
        """
 
138
        query = """
 
139
SELECT id,
 
140
       partner_id,
 
141
       partner_name,
 
142
       salesman,
 
143
       avg_days_overdue,
 
144
       oldest_invoice_date AS date,
 
145
       total,
 
146
       days_due_01to30,
 
147
       days_due_31to60,
 
148
       days_due_61to90,
 
149
       days_due_91to120,
 
150
       days_due_121togr,
 
151
       max_days_overdue,
 
152
       current,
 
153
       invoice_ref,
 
154
       invoice_id,
 
155
       comment,
 
156
       currency_name
 
157
FROM   account_voucher_customer_unapplied
 
158
UNION
 
159
SELECT *
 
160
FROM   (SELECT l.id                AS id,
 
161
               l.partner_id        AS partner_id,
 
162
               res_partner.name    AS "partner_name",
 
163
               res_partner.user_id AS salesman,
 
164
               days_due            AS "avg_days_overdue",
 
165
               CASE
 
166
                 WHEN ai.id IS NOT NULL THEN ai.date_due
 
167
                 ELSE l.date_maturity
 
168
               end                 AS "date",
 
169
               CASE
 
170
                 WHEN ai.id IS NOT NULL THEN
 
171
                   CASE
 
172
                     WHEN ai.type = 'out_refund' THEN -1 * ai.residual
 
173
                     ELSE ai.residual
 
174
                   end
 
175
                 WHEN ai.id IS NULL THEN l.debit - l.credit
 
176
                 ELSE 0
 
177
               end                 AS "total",
 
178
               CASE
 
179
                 WHEN ( days_due BETWEEN 01 AND 30 )
 
180
                      AND ai.id IS NOT NULL THEN
 
181
                   CASE
 
182
                     WHEN ai.type = 'out_refund' THEN -1 * ai.residual
 
183
                     ELSE ai.residual
 
184
                   end
 
185
                 WHEN ( days_due BETWEEN 01 AND 30 )
 
186
                      AND ai.id IS NULL THEN l.debit - l.credit
 
187
                 ELSE 0
 
188
               end                 AS "days_due_01to30",
 
189
               CASE
 
190
                 WHEN ( days_due BETWEEN 31 AND 60 )
 
191
                      AND ai.id IS NOT NULL THEN
 
192
                   CASE
 
193
                     WHEN ai.type = 'out_refund' THEN -1 * ai.residual
 
194
                     ELSE ai.residual
 
195
                   end
 
196
                 WHEN ( days_due BETWEEN 31 AND 60 )
 
197
                      AND ai.id IS NULL THEN l.debit - l.credit
 
198
                 ELSE 0
 
199
               end                 AS "days_due_31to60",
 
200
               CASE
 
201
                 WHEN ( days_due BETWEEN 61 AND 90 )
 
202
                      AND ai.id IS NOT NULL THEN
 
203
                   CASE
 
204
                     WHEN ai.type = 'out_refund' THEN -1 * ai.residual
 
205
                     ELSE ai.residual
 
206
                   end
 
207
                 WHEN ( days_due BETWEEN 61 AND 90 )
 
208
                      AND ai.id IS NULL THEN l.debit - l.credit
 
209
                 ELSE 0
 
210
               end                 AS "days_due_61to90",
 
211
               CASE
 
212
                 WHEN ( days_due BETWEEN 91 AND 120 )
 
213
                      AND ai.id IS NOT NULL THEN
 
214
                   CASE
 
215
                     WHEN ai.type = 'out_refund' THEN -1 * ai.residual
 
216
                     ELSE ai.residual
 
217
                   end
 
218
                 WHEN ( days_due BETWEEN 91 AND 120 )
 
219
                      AND ai.id IS NULL THEN l.debit - l.credit
 
220
                 ELSE 0
 
221
               end                 AS "days_due_91to120",
 
222
               CASE
 
223
                 WHEN days_due >= 121
 
224
                      AND ai.id IS NOT NULL THEN
 
225
                   CASE
 
226
                     WHEN ai.type = 'out_refund' THEN -1 * ai.residual
 
227
                     ELSE ai.residual
 
228
                   end
 
229
                 WHEN days_due >= 121
 
230
                      AND ai.id IS NULL THEN l.debit - l.credit
 
231
                 ELSE 0
 
232
               end                 AS "days_due_121togr",
 
233
               CASE
 
234
                 WHEN days_due < 0 THEN 0
 
235
                 ELSE days_due
 
236
               end                 AS "max_days_overdue",
 
237
               CASE
 
238
                 WHEN days_due <= 0
 
239
                      AND ai.id IS NOT NULL THEN
 
240
                   CASE
 
241
                     WHEN ai.type = 'out_refund' THEN -1 * ai.residual
 
242
                     ELSE ai.residual
 
243
                   end
 
244
                 WHEN days_due <= 0
 
245
                      AND ai.id IS NULL THEN l.debit - l.credit
 
246
                 ELSE 0
 
247
               end                 AS "current",
 
248
               l.ref               AS "invoice_ref",
 
249
               ai.id               AS "invoice_id",
 
250
               ai.comment,
 
251
               res_currency.name   AS "currency_name"
 
252
        FROM   account_move_line AS l
 
253
               INNER JOIN (SELECT lt.id,
 
254
                                  CASE
 
255
                                    WHEN inv.id IS NOT NULL THEN
 
256
                                    Extract(day FROM ( Now() - inv.date_due ))
 
257
                                    ELSE Extract(day FROM (
 
258
                                                 Now() - lt.date_maturity ))
 
259
                                  end AS days_due
 
260
                           FROM   account_move_line lt
 
261
                                  LEFT JOIN account_invoice inv
 
262
                                         ON lt.move_id = inv.move_id) DaysDue
 
263
                       ON DaysDue.id = l.id
 
264
               INNER JOIN account_account
 
265
                       ON account_account.id = l.account_id
 
266
               INNER JOIN res_company
 
267
                       ON account_account.company_id = res_company.id
 
268
               INNER JOIN account_move
 
269
                       ON account_move.id = l.move_id
 
270
               LEFT JOIN account_invoice AS ai
 
271
                      ON ai.move_id = l.move_id
 
272
               INNER JOIN res_partner
 
273
                       ON res_partner.id = l.partner_id
 
274
               INNER JOIN res_currency
 
275
                       ON res_currency.id = ai.currency_id
 
276
        WHERE  account_account.active
 
277
               AND ai.state <> 'paid'
 
278
               AND ( account_account.type IN ( 'receivable' ) )
 
279
               AND ( l.reconcile_id IS NULL )
 
280
               AND account_move.state = 'posted'
 
281
               AND DaysDue.days_due IS NOT NULL) sq
 
282
        """
 
283
 
 
284
        tools.drop_view_if_exists(cr, '%s' % (self._name.replace('.', '_')))
 
285
        cr.execute(
 
286
            "CREATE OR REPLACE VIEW %s AS ( %s)" %
 
287
            (self._name.replace('.', '_'), query)
 
288
        )