1
##############################################################################
3
# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
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
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.
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.
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.
26
##############################################################################
34
from mx.DateTime import RelativeDateTime, now, DateTime, localtime
39
from lxml import etree
40
from tools.misc import UpdateableStr
42
def querytuplestr(mytuple):
44
return str(mytuple).replace(",", "")
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)]"/>
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',
65
export_form = UpdateableStr()
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()
82
out=base64.encodestring(buf.getvalue())
85
return {'note': res, report_name: out}
87
def last_day_of_month(date):
89
return date.replace(day=31)
90
return date.replace(month=date.month+1, day=1) - datetime.timedelta(days=1)
93
class wizard_electronic_report_invoice(wizard.interface):
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',
105
export_fields['note'] = {'string':'Log','type':'text'}
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]
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)
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)
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], )
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"
136
####Esta mal el tipo de factura...
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')"
148
invoiced_ids[ix] = tuple(item + (0.0,) + (0.0,) + ('ERROR',))
150
query = "SELECT SUM(%s) FROM account_move_line WHERE move_id=%i and account_id in %s" %(credit_debit, item[2], acctlist)
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], )
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"
166
####Esta mal el tipo de factura...
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')"
178
canceld_ids[ix] = tuple(item + (0.0,) + (0.0,) + ('ERROR',))
180
query = "SELECT SUM(%s) from account_move_line WHERE move_id=%i and account_id in %s" %(credit_debit, item[2], acctlist)
183
canceld_ids[ix] = tuple(item + sums[0] + tax[0])
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}
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}
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 ]
199
inv_numbers = res.keys()
201
for inv_numb in inv_numbers:
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'
215
report_line += line +'\n'
216
#report_line += line +'\n'
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'
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)
230
company_id = user.company_id.id
232
company_id = pool.get('res.company').search(cr, uid,
233
[('parent_id', '=', False)])[0]
234
data['form']['company_id'] = company_id
239
'actions': [_get_defaults],
240
'result': {'type':'form',
242
'fields':dates_fields,
243
'state':[('end','Cancel'),('export','Export')]}
246
'actions' : [_get_report],
247
'result' : {'type' : 'form',
248
'arch' : export_form,
249
'fields' : export_fields,
250
'state' : [('close', 'Ok','gtk-ok') ]}
254
'result': {'type': 'state', 'state':'end'}
258
wizard_electronic_report_invoice('account.invoice.electronic.report')