~openbias/bias-trunk/bias-public-trunk

« back to all changes in this revision

Viewing changes to bias_electronic_invoice/wizard/wizard_electronic_invoice_report.py

  • Committer: Jose Patricio
  • Date: 2011-10-19 03:16:40 UTC
  • Revision ID: josepato@bias.com.mx-20111019031640-05zd7r5lxwx084qu
el push inicial

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
##############################################################################
 
2
#
 
3
# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
 
4
#
 
5
# WARNING: This program as such is intended to be used by professional
 
6
# programmers who take the whole responsability of assessing all potential
 
7
# consequences resulting from its eventual inadequacies and bugs
 
8
# End users who are looking for a ready-to-use solution with commercial
 
9
# garantees and support are strongly adviced to contract a Free Software
 
10
# Service Company
 
11
#
 
12
# This program is Free Software; you can redistribute it and/or
 
13
# modify it under the terms of the GNU General Public License
 
14
# as published by the Free Software Foundation; either version 2
 
15
# of the License, or (at your option) any later version.
 
16
#
 
17
# This program is distributed in the hope that it will be useful,
 
18
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
19
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
20
# GNU General Public License for more details.
 
21
#
 
22
# You should have received a copy of the GNU General Public License
 
23
# along with this program; if not, write to the Free Software
 
24
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
25
#
 
26
##############################################################################
 
27
 
 
28
import pooler
 
29
import wizard
 
30
import base64
 
31
from osv import osv
 
32
import time
 
33
import mx.DateTime
 
34
from mx.DateTime import RelativeDateTime, now, DateTime, localtime
 
35
import datetime
 
36
import re
 
37
import StringIO
 
38
import csv
 
39
from lxml import etree
 
40
from tools.misc import UpdateableStr
 
41
 
 
42
def querytuplestr(mytuple):
 
43
        if len(mytuple) == 1:
 
44
                return str(mytuple).replace(",", "")
 
45
        else:
 
46
                return str(mytuple)
 
47
 
 
48
dates_form = '''<?xml version="1.0"?>
 
49
<form string="Select period">
 
50
        <field name="company_id"/>
 
51
        <field name="fiscalyear" colspan="4"/>
 
52
        <field name="period" colspan="4" domain="[('fiscalyear_id','=',fiscalyear)]"/>
 
53
</form>'''
 
54
 
 
55
dates_fields = {
 
56
        'company_id': {'string': 'Company', 'type': 'many2one',
 
57
                'relation': 'res.company', 'required': True},
 
58
        'fiscalyear': {'string': 'Fiscal year', 'type': 'many2one', 'relation': 'account.fiscalyear',
 
59
                'help': 'Keep empty for all open fiscal year'},
 
60
        'period': {'string': 'Period', 'type': 'many2one', 'relation': 'account.period',
 
61
                'help': ''},
 
62
}
 
63
 
 
64
 
 
65
export_form = UpdateableStr()
 
66
export_fields = {}
 
67
 
 
68
 
 
69
def _get_report(self, cr, uid, data, context):
 
70
        pool = pooler.get_pool(cr.dbname)
 
71
        fy_id = data['form']['fiscalyear']
 
72
        pe_id = data['form']['period']
 
73
        company_id = data['form']['company_id']
 
74
        agnio = int(pool.get('account.fiscalyear').browse(cr, uid, fy_id, context=context).date_start[:4])
 
75
        mes = int(pool.get('account.period').browse(cr, uid, pe_id, context=context).date_start[5:7])
 
76
        rfc = pool.get('res.company').browse(cr, uid, company_id, context).partner_id.vat
 
77
        rfc = re.sub('-','',rfc)
 
78
        res = file = self._reporte(cr, uid, rfc, mes, agnio)
 
79
        report_name = str('1%s%s%s.txt'%(rfc, mes, agnio))
 
80
        buf=StringIO.StringIO()
 
81
        writer=buf.write(res)
 
82
        out=base64.encodestring(buf.getvalue())
 
83
        buf.close()
 
84
        
 
85
        return {'note': res, report_name: out}
 
86
 
 
87
def last_day_of_month(date):
 
88
        if date.month == 12:
 
89
                return date.replace(day=31)
 
90
        return date.replace(month=date.month+1, day=1) - datetime.timedelta(days=1)     
 
91
        
 
92
        
 
93
class wizard_electronic_report_invoice(wizard.interface):
 
94
 
 
95
 
 
96
        def _reporte(self, cr, uid, rfc, mes, agnio):
 
97
                report_name = str('1%s%s%s.txt'%(rfc, mes, agnio))
 
98
                export_form.string = '''<?xml version="1.0"?><form string="Payment Export"> <field name="%s"/><field name="note" colspan="4" height="300" width="800" nolabel="1"/></form>'''%(report_name)
 
99
                export_fields[report_name] = {
 
100
                        'string':'Export File',
 
101
                        'type':'binary',
 
102
                        'required': False,
 
103
                        'readonly':True,
 
104
                        }
 
105
                export_fields['note'] = {'string':'Log','type':'text'}
 
106
 
 
107
                pool = pooler.get_pool(cr.dbname)
 
108
                attachment_obj = pool.get('ir.attachment')
 
109
                date_from = "%s-%s-01 00:00:00"%(agnio, mes)
 
110
                date_to = last_day_of_month(datetime.date(agnio, mes, 1)).strftime('%Y-%m-%d 24:00:00')
 
111
                cr.execute("SELECT id FROM account_journal WHERE e_invoice = 'True'")
 
112
                journal_id = cr.fetchall()
 
113
                journal_id = tuple([id[0] for id in  journal_id])
 
114
                if len(journal_id) <= 1:
 
115
                        journal_query = 'journal_id = %s'%journal_id[0]
 
116
                else:
 
117
                        journal_query = 'journal_id in %s'%str(journal_id)
 
118
                query = "SELECT id, number, move_id, account_id, type FROM account_invoice WHERE sign_date between '%s' and '%s' and state not in ('proforma','proforma2', 'draft') and %s order by number"%(date_from, date_to, journal_query)
 
119
                cr.execute(query)
 
120
                invoiced_ids = cr.fetchall()
 
121
                query = "SELECT id, number, move_id, account_id, type FROM account_invoice WHERE cancel_date between '%s' and '%s'  and %s   order by number"%(date_from, date_to, journal_query)
 
122
                cr.execute(query)
 
123
                canceld_ids = cr.fetchall()
 
124
                for ix in range(len(invoiced_ids)):
 
125
                        item = invoiced_ids[ix]
 
126
                        query = "SELECT distinct(account_id) FROM account_invoice_line WHERE invoice_id=%i" %(item[0], )
 
127
                        cr.execute(query)
 
128
                        acctlist = querytuplestr(tuple([x[0] for x in cr.fetchall()]))
 
129
                        if item[4] == "out_invoice":
 
130
                                credit_debit = "credit"
 
131
                                collected_paid = "account_collected_id"
 
132
                        elif item[4] == "out_refund":
 
133
                                credit_debit = "debit"
 
134
                                collected_paid = "account_paid_id"
 
135
                        else:
 
136
                                ####Esta mal el tipo de factura...
 
137
                                item[2] = None
 
138
                        query = "SELECT SUM(aml.%s) FROM account_move_line aml," %(credit_debit, )
 
139
                        query += " account_tax at, account_tax_code atc, account_invoice ai, account_invoice_tax ait"
 
140
                        query += " WHERE ai.id=%i AND ai.move_id=aml.move_id" %(item[0], )
 
141
                        query += " AND aml.account_id=at.%s" %(collected_paid, )
 
142
                        query += " AND  (ait.tax_code_id = at.tax_code_id OR ait.tax_code_id = at.ref_tax_code_id)"
 
143
                        query += " AND ait.invoice_id=ai.id"
 
144
                        query += " AND atc.tax_type in ('tax_iva', 'tax_ietu')"
 
145
                        cr.execute(query)
 
146
                        tax = cr.fetchall()
 
147
                        if not item[2]:
 
148
                                invoiced_ids[ix] = tuple(item + (0.0,) + (0.0,) + ('ERROR',))
 
149
                        else:
 
150
                                query = "SELECT SUM(%s) FROM account_move_line WHERE move_id=%i and account_id in %s" %(credit_debit, item[2], acctlist)
 
151
                                cr.execute(query)
 
152
                                sums = cr.fetchall()
 
153
                                invoiced_ids[ix] = tuple(item + sums[0] + tax[0])
 
154
                for ix in range(len(canceld_ids)):
 
155
                        item = canceld_ids[ix]
 
156
                        query = "SELECT distinct(account_id) FROM account_invoice_line WHERE invoice_id=%i" %(item[0], )
 
157
                        cr.execute(query)
 
158
                        acctlist = querytuplestr(tuple([x[0] for x in cr.fetchall()]))
 
159
                        if item[4] == "out_invoice":
 
160
                                credit_debit = "credit"
 
161
                                collected_paid = "account_collected_id"
 
162
                        elif item[4] == "out_refund":
 
163
                                credit_debit = "debit"
 
164
                                collected_paid = "account_paid_id"
 
165
                        else:
 
166
                                ####Esta mal el tipo de factura...
 
167
                                item[2] = None
 
168
                        query = "SELECT SUM(aml.%s) FROM account_move_line aml," %(credit_debit, )
 
169
                        query += " account_tax at, account_tax_code atc, account_invoice ai, account_invoice_tax ait"
 
170
                        query += " WHERE ai.id=%i AND ai.move_id=aml.move_id" %(item[0], )
 
171
                        query += " AND aml.account_id=at.%s" %(collected_paid, )
 
172
                        query += " AND  (ait.tax_code_id = at.tax_code_id OR ait.tax_code_id = at.ref_tax_code_id)"
 
173
                        query += " AND ait.invoice_id=ai.id"
 
174
                        query += " AND atc.tax_type in ('tax_iva', 'tax_ietu')"
 
175
                        cr.execute(query)
 
176
                        tax = cr.fetchall()
 
177
                        if not item[2]:
 
178
                                canceld_ids[ix] = tuple(item + (0.0,) + (0.0,) + ('ERROR',))
 
179
                        else:
 
180
                                query = "SELECT SUM(%s) from account_move_line WHERE move_id=%i and account_id in %s" %(credit_debit, item[2], acctlist)
 
181
                                cr.execute(query)
 
182
                                sums = cr.fetchall()
 
183
                                canceld_ids[ix] = tuple(item + sums[0] + tax[0])
 
184
                res_open = {}
 
185
                res_cancel = {}
 
186
                for id in invoiced_ids:
 
187
                        if (len(id) == 8) and (id[7] == 'ERROR'):
 
188
                                res_open[id[1]]={'id':id[0],'state':False, 'subtotal_valuestr': '%.2f' %(id[5] or 0.0, ), 'tax_valuestr': '%.2f' %(id[6] or 0.0, ), 'ERROR':True}
 
189
                        else:
 
190
                                res_open[id[1]]={'id':id[0],'state':False, 'subtotal_valuestr': '%.2f' %(id[5] or 0.0, ), 'tax_valuestr': '%.2f' %(id[6] or 0.0, ), 'ERROR':False}
 
191
                for c_ids in canceld_ids:
 
192
                        if (len(c_ids) == 8) and (c_ids[7] == 'ERROR'):
 
193
                                res_cancel[c_ids[1]]={'id':c_ids[0],'state':True, 'subtotal_valuestr': '%.2f' %(c_ids[5] or 0.0, ), 'tax_valuestr': '%.2f' %(c_ids[6] or 0.0, ),'ERROR':True}
 
194
                        else:
 
195
                                res_cancel[c_ids[1]]={'id':c_ids[0],'state':True, 'subtotal_valuestr': '%.2f' %(c_ids[5] or 0.0, ), 'tax_valuestr': '%.2f' %(c_ids[6] or 0.0, ),'ERROR':False}
 
196
                invoices = [res_open, res_cancel ]
 
197
                report_line = ''
 
198
                for res in invoices:
 
199
                        inv_numbers = res.keys()
 
200
                        inv_numbers.sort()
 
201
                        for inv_numb in inv_numbers:
 
202
                                try:
 
203
                                        attachment_id = attachment_obj.search(cr, uid, [('res_id','=', res[inv_numb]['id']),('res_model','=', 'account.invoice'),('datas_fname','ilike', '%.xml'),('name','not ilike', '%.old')])[0]
 
204
                                        xml_str = attachment_obj.browse(cr, uid, attachment_id).datas
 
205
                                        xml_str = base64.decodestring(xml_str)
 
206
                                        xml_str = unicode(xml_str, 'utf-8')
 
207
                                        xml_obj = StringIO.StringIO(xml_str.encode('utf-8'))
 
208
                                        xml_str_obj = etree.parse(xml_obj)
 
209
                                        line = pool.get('account.invoice').cfdutil_getLineaReporte(xml_str_obj, res[inv_numb]['state'],
 
210
                                                                                                   res[inv_numb]['subtotal_valuestr'],
 
211
                                                                                                   res[inv_numb]['tax_valuestr'])
 
212
                                        if res[inv_numb]['ERROR']:
 
213
                                                report_line += line + '********** REVISAR MANUALMENTE FOLIO %s, ID %s *********'%(inv_numb, res[inv_numb]['id']) + '\n'
 
214
                                        else:
 
215
                                                report_line += line +'\n'
 
216
                                        #report_line += line +'\n'
 
217
                                except IndexError:
 
218
                                        report_line += '-------- NO HAY ARCHIVO XML DEL FOLIO %s, ID %s -----------'%(inv_numb , res[inv_numb]['id']) + '\n'
 
219
                                except etree.XMLSyntaxError:
 
220
                                        report_line += '-------- ERROR EN ARCHIVO XML DEL FOLIO %s, ID %s-----------'%(inv_numb, res[inv_numb]['id']) + '\n'
 
221
                                        
 
222
                return report_line
 
223
 
 
224
        def _get_defaults(self, cr, uid, data, context):
 
225
                pool = pooler.get_pool(cr.dbname)
 
226
                fiscalyear_obj = pool.get('account.fiscalyear')
 
227
                data['form']['fiscalyear'] = fiscalyear_obj.find(cr, uid)
 
228
                user = pool.get('res.users').browse(cr, uid, uid, context=context)
 
229
                if user.company_id:
 
230
                        company_id = user.company_id.id
 
231
                else:
 
232
                        company_id = pool.get('res.company').search(cr, uid,
 
233
                                        [('parent_id', '=', False)])[0]
 
234
                data['form']['company_id'] = company_id
 
235
                return data['form']
 
236
 
 
237
        states = {
 
238
        'init': {
 
239
                'actions': [_get_defaults],
 
240
                'result': {'type':'form', 
 
241
                        'arch':dates_form, 
 
242
                        'fields':dates_fields, 
 
243
                        'state':[('end','Cancel'),('export','Export')]}
 
244
                },
 
245
        'export' : {
 
246
                'actions' : [_get_report],
 
247
                'result' : {'type' : 'form',
 
248
                        'arch' : export_form,
 
249
                        'fields' : export_fields,
 
250
                        'state' : [('close', 'Ok','gtk-ok') ]}
 
251
        },
 
252
        'close': {
 
253
                'actions': [],
 
254
                'result': {'type': 'state', 'state':'end'}
 
255
        }
 
256
 
 
257
    }
 
258
wizard_electronic_report_invoice('account.invoice.electronic.report')
 
259