Merge lp:~vauxoo/openerp-mexico-localization/7.0-l10n_mx_facturae-Jinja2-template-CFD-CFDI-dev_jc into lp:openerp-mexico-localization/7.0
- 7.0-l10n_mx_facturae-Jinja2-template-CFD-CFDI-dev_jc
- Merge into 7.0
Proposed by
Juan Carlos Hernandez
Status: | Merged |
---|---|
Merge reported by: | Moisés López - http://www.vauxoo.com |
Merged at revision: | not available |
Proposed branch: | lp:~vauxoo/openerp-mexico-localization/7.0-l10n_mx_facturae-Jinja2-template-CFD-CFDI-dev_jc |
Merge into: | lp:openerp-mexico-localization/7.0 |
Diff against target: |
815 lines (+290/-247) 6 files modified
l10n_mx_facturae/__openerp__.py (+1/-0) l10n_mx_facturae/invoice.py (+254/-204) l10n_mx_facturae/template/cfd.xml (+1/-0) l10n_mx_facturae_pac/invoice.py (+30/-39) l10n_mx_facturae_pac_sf/ir_attachment_facturae.py (+3/-4) l10n_mx_facturae_pac_sf/template/cfdi.xml (+1/-0) |
To merge this branch: | bzr merge lp:~vauxoo/openerp-mexico-localization/7.0-l10n_mx_facturae-Jinja2-template-CFD-CFDI-dev_jc |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jorge Angel Naranjo Rogel - http://www.vauxoo.com | Pending | ||
Juan Carlos Hernandez | Pending | ||
Julio Serna-http://www.vauxoo.com | Pending | ||
Moisés López - http://www.vauxoo.com | Pending | ||
Review via email: mp+203193@code.launchpad.net |
Commit message
Description of the change
se agregó Jinja para crear los XML CFD y CFDI version 3.2.Es decir una plantilla para CFD y CFDI
se agregó una función para quitar los acentos.
To post a comment you must log in.
Revision history for this message
Moisés López - http://www.vauxoo.com (moylop260) wrote : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'l10n_mx_facturae/__openerp__.py' |
2 | --- l10n_mx_facturae/__openerp__.py 2013-10-04 23:02:23 +0000 |
3 | +++ l10n_mx_facturae/__openerp__.py 2014-01-25 00:46:46 +0000 |
4 | @@ -68,6 +68,7 @@ |
5 | "l10n_mx_facturae_report", |
6 | "l10n_mx_facturae_group_show_wizards", |
7 | "l10n_mx_settings_facturae", |
8 | + "l10n_mx_params_pac", |
9 | ], |
10 | "demo" : [ |
11 | "demo/l10n_mx_facturae_seq_demo.xml", |
12 | |
13 | === modified file 'l10n_mx_facturae/invoice.py' |
14 | --- l10n_mx_facturae/invoice.py 2013-12-10 01:11:31 +0000 |
15 | +++ l10n_mx_facturae/invoice.py 2014-01-25 00:46:46 +0000 |
16 | @@ -45,6 +45,9 @@ |
17 | import os |
18 | import codecs |
19 | from datetime import datetime, timedelta |
20 | +import jinja2 |
21 | +import xml |
22 | +import unicodedata |
23 | |
24 | |
25 | def exec_command_pipe(name, *args): |
26 | @@ -80,37 +83,6 @@ |
27 | return val |
28 | return None |
29 | |
30 | -# TODO: Agregar una libreria para esto |
31 | - |
32 | - |
33 | -def conv_ascii(text): |
34 | - """ |
35 | - @param text : text that need convert vowels accented & characters to ASCII |
36 | - Converts accented vowels, ñ and ç to their ASCII equivalent characters |
37 | - """ |
38 | - old_chars = [ |
39 | - 'á', 'é', 'í', 'ó', 'ú', 'à', 'è', 'ì', 'ò', 'ù', 'ä', 'ë', 'ï', 'ö', |
40 | - 'ü', 'â', 'ê', 'î', 'ô', 'û', 'Á', 'É', 'Í', 'Ó', 'Ú', 'À', 'È', 'Ì', |
41 | - 'Ò', 'Ù', 'Ä', 'Ë', 'Ï', 'Ö', 'Ü', 'Â', 'Ê', 'Î', 'Ô', 'Û', 'ñ', 'Ñ', |
42 | - 'ç', 'Ç', 'ª', 'º', '°', ' ', 'Ã', 'Ø' |
43 | - ] |
44 | - new_chars = [ |
45 | - 'a', 'e', 'i', 'o', 'u', 'a', 'e', 'i', 'o', 'u', 'a', 'e', 'i', 'o', |
46 | - 'u', 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U', 'A', 'E', 'I', |
47 | - 'O', 'U', 'A', 'E', 'I', 'O', 'U', 'A', 'E', 'I', 'O', 'U', 'n', 'N', |
48 | - 'c', 'C', 'a', 'o', 'o', ' ', 'A', '0' |
49 | - ] |
50 | - for old, new in zip(old_chars, new_chars): |
51 | - try: |
52 | - text = text.replace(unicode(old, 'UTF-8'), new) |
53 | - except: |
54 | - try: |
55 | - text = text.replace(old, new) |
56 | - except: |
57 | - raise osv.except_osv(_('Warning !'), _( |
58 | - "Can't recode the string [%s] in the letter [%s]") % (text, old)) |
59 | - return text |
60 | - |
61 | # Cambiar el error |
62 | msg2 = "Contact you administrator &/or to info@vauxoo.com" |
63 | |
64 | @@ -118,6 +90,39 @@ |
65 | class account_invoice(osv.Model): |
66 | _inherit = 'account.invoice' |
67 | |
68 | + def remove_accents(self, cr, uid, ids, input_str): |
69 | + nkfd_form = unicodedata.normalize('NFKD', unicode(input_str)) |
70 | + only_ascii = nkfd_form.encode('ASCII', 'ignore') |
71 | + return self.conv_ascii(cr, uid, ids, only_ascii) |
72 | + |
73 | + def conv_ascii(self, cr, uid, ids, text): |
74 | + """ |
75 | + @param text : text that need convert vowels accented & characters to ASCII |
76 | + Converts accented vowels, ñ and ç to their ASCII equivalent characters |
77 | + """ |
78 | + old_chars = [ |
79 | + 'á', 'é', 'í', 'ó', 'ú', 'à', 'è', 'ì', 'ò', 'ù', 'ä', 'ë', 'ï', 'ö', |
80 | + 'ü', 'â', 'ê', 'î', 'ô', 'û', 'Á', 'É', 'Í', 'Ó', 'Ú', 'À', 'È', 'Ì', |
81 | + 'Ò', 'Ù', 'Ä', 'Ë', 'Ï', 'Ö', 'Ü', 'Â', 'Ê', 'Î', 'Ô', 'Û', 'ñ', 'Ñ', |
82 | + 'ç', 'Ç', 'ª', 'º', '°', ' ', 'Ã', 'Ø', '&', '´' |
83 | + ] |
84 | + new_chars = [ |
85 | + 'a', 'e', 'i', 'o', 'u', 'a', 'e', 'i', 'o', 'u', 'a', 'e', 'i', 'o', |
86 | + 'u', 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U', 'A', 'E', 'I', |
87 | + 'O', 'U', 'A', 'E', 'I', 'O', 'U', 'A', 'E', 'I', 'O', 'U', 'n', 'N', |
88 | + 'c', 'C', 'a', 'o', 'o', ' ', 'A', '0' ,'y', '' |
89 | + ] |
90 | + for old, new in zip(old_chars, new_chars): |
91 | + try: |
92 | + text = text.replace(unicode(old, 'UTF-8'), new) |
93 | + except: |
94 | + try: |
95 | + text = text.replace(old, new) |
96 | + except: |
97 | + raise osv.except_osv(_('Warning !'), _( |
98 | + "Can't recode the string [%s] in the letter [%s]") % (text, old)) |
99 | + return text |
100 | + |
101 | def create_report(self, cr, uid, res_ids, report_name=False, file_name=False, context=None): |
102 | """ |
103 | @param report_name : Name of report with the name of object more type |
104 | @@ -700,7 +705,7 @@ |
105 | key_item_sort.append([key_too, data_dict[key_too]]) |
106 | return key_item_sort |
107 | |
108 | - def dict2xml(self, data_dict, node=False, doc=False): |
109 | + def dict2xml(self, cr, uid, ids, data_dict, node=False, doc=False): |
110 | """ |
111 | @param data_dict : Dictionary of attributes for add in the XML |
112 | that will be generated |
113 | @@ -717,20 +722,20 @@ |
114 | if isinstance(attribute, dict): |
115 | if not parent: |
116 | node = doc.createElement(element) |
117 | - self.dict2xml(attribute, node, doc) |
118 | + self.dict2xml(cr, uid, ids, attribute, node, doc) |
119 | else: |
120 | child = doc.createElement(element) |
121 | - self.dict2xml(attribute, child, doc) |
122 | + self.dict2xml(cr, uid, ids, attribute, child, doc) |
123 | node.appendChild(child) |
124 | elif isinstance(attribute, list): |
125 | child = doc.createElement(element) |
126 | for attr in attribute: |
127 | if isinstance(attr, dict): |
128 | - self.dict2xml(attr, child, doc) |
129 | + self.dict2xml(cr, uid, ids, attr, child, doc) |
130 | node.appendChild(child) |
131 | else: |
132 | if isinstance(attribute, str) or isinstance(attribute, unicode): |
133 | - attribute = conv_ascii(attribute) |
134 | + attribute = self.remove_accents(cr, uid, ids, attribute) |
135 | else: |
136 | attribute = str(attribute) |
137 | node.setAttribute(element, attribute) |
138 | @@ -742,88 +747,104 @@ |
139 | def _get_facturae_invoice_xml_data(self, cr, uid, ids, context=None): |
140 | if context is None: |
141 | context = {} |
142 | - data_dict = self._get_facturae_invoice_dict_data( |
143 | - cr, uid, ids, context=context)[0] |
144 | - doc_xml = self.dict2xml({ |
145 | - 'Comprobante': data_dict.get('Comprobante')}) |
146 | - invoice_number = "sn" |
147 | - (fileno_xml, fname_xml) = tempfile.mkstemp( |
148 | + data_dict = self._get_facturae_invoice_dict_data(cr, uid, ids, context=context)[0] |
149 | + data_xml=False |
150 | + fname_xml=False |
151 | + ir_seq_app_obj = self.pool.get('ir.sequence.approval') |
152 | + invoice = self.browse(cr, uid, ids[0], context=context) |
153 | + sequence_app_id = ir_seq_app_obj.search(cr, uid, [( |
154 | + 'sequence_id', '=', invoice.invoice_sequence_id.id)], context=context) |
155 | + if sequence_app_id: |
156 | + type_inv = ir_seq_app_obj.browse(cr, uid, sequence_app_id[0], context=context).type |
157 | + if not 'cfdi' in type_inv: |
158 | + #doc_xml = self.dict2xml(cr, uid, ids, {'Comprobante': data_dict.get('Comprobante')}) |
159 | + all_paths = tools.config["addons_path"].split(",") |
160 | + for my_path in all_paths: |
161 | + if os.path.isdir(os.path.join(my_path, 'l10n_mx_facturae', 'template')): |
162 | + fname_jinja_tmpl = my_path and os.path.join(my_path, 'l10n_mx_facturae', 'template', 'cfd' + '.xml') or '' |
163 | + dictargs = { |
164 | + 'o': data_dict |
165 | + } |
166 | + invoice_number = "sn" |
167 | + (fileno_xml, fname_xml) = tempfile.mkstemp('.xml', 'openerp_' + (invoice_number or '') + '__facturae__') |
168 | + with open(fname_jinja_tmpl, 'r') as f_jinja_tmpl: |
169 | + jinja_tmpl_str = f_jinja_tmpl.read().encode('utf-8') |
170 | + tmpl = jinja2.Template( jinja_tmpl_str ) |
171 | + with open(fname_xml, 'w') as new_xml: |
172 | + new_xml.write( tmpl.render(**dictargs) ) |
173 | + with open(fname_xml,'rb') as b: |
174 | + jinja2_xml = b.read().encode('utf-8') |
175 | + doc_xml = xml.dom.minidom.parseString(jinja2_xml) |
176 | + (fileno_xml, fname_xml) = tempfile.mkstemp( |
177 | '.xml', 'openerp_' + (invoice_number or '') + '__facturae__') |
178 | - fname_txt = fname_xml + '.txt' |
179 | - f = open(fname_xml, 'w') |
180 | - doc_xml.writexml( |
181 | - f, indent=' ', addindent=' ', newl='\r\n', encoding='UTF-8') |
182 | - f.close() |
183 | - os.close(fileno_xml) |
184 | - |
185 | - (fileno_sign, fname_sign) = tempfile.mkstemp('.txt', 'openerp_' + ( |
186 | - invoice_number or '') + '__facturae_txt_md5__') |
187 | - os.close(fileno_sign) |
188 | - |
189 | - context.update({ |
190 | - 'fname_xml': fname_xml, |
191 | - 'fname_txt': fname_txt, |
192 | - 'fname_sign': fname_sign, |
193 | - }) |
194 | - context.update(self._get_file_globals(cr, uid, ids, context=context)) |
195 | - fname_txt, txt_str = self._xml2cad_orig( |
196 | - cr=False, uid=False, ids=False, context=context) |
197 | - data_dict['cadena_original'] = txt_str |
198 | - |
199 | - if not txt_str: |
200 | - raise osv.except_osv(_('Error en Cadena original!'), _( |
201 | - "Can't get the string original of the voucher.\nCkeck your configuration.\n%s" % (msg2))) |
202 | - |
203 | - if not data_dict['Comprobante'].get('folio', ''): |
204 | - raise osv.except_osv(_('Error in Folio!'), _( |
205 | - "Can't get the folio of the voucher.\nBefore generating the XML, click on the button, generate invoice.\nCkeck your configuration.\n%s" % (msg2))) |
206 | - |
207 | - # time.strftime('%Y-%m-%dT%H:%M:%S', |
208 | - # time.strptime(invoice.date_invoice, '%Y-%m-%d %H:%M:%S')) |
209 | - context.update({'fecha': data_dict['Comprobante']['fecha']}) |
210 | - sign_str = self._get_sello( |
211 | - cr=False, uid=False, ids=False, context=context) |
212 | - if not sign_str: |
213 | - raise osv.except_osv(_('Error in Stamp !'), _( |
214 | - "Can't generate the stamp of the voucher.\nCkeck your configuration.\ns%s") % (msg2)) |
215 | - |
216 | - nodeComprobante = doc_xml.getElementsByTagName("Comprobante")[0] |
217 | - nodeComprobante.setAttribute("sello", sign_str) |
218 | - data_dict['Comprobante']['sello'] = sign_str |
219 | - |
220 | - noCertificado = self._get_noCertificado(cr, uid, ids, context['fname_cer']) |
221 | - if not noCertificado: |
222 | - raise osv.except_osv(_('Error in No. Certificate !'), _( |
223 | - "Can't get the Certificate Number of the voucher.\nCkeck your configuration.\n%s") % (msg2)) |
224 | - nodeComprobante.setAttribute("noCertificado", noCertificado) |
225 | - data_dict['Comprobante']['noCertificado'] = noCertificado |
226 | - |
227 | - cert_str = self._get_certificate_str(context['fname_cer']) |
228 | - if not cert_str: |
229 | - raise osv.except_osv(_('Error in Certificate!'), _( |
230 | - "Can't generate the Certificate of the voucher.\nCkeck your configuration.\n%s") % (msg2)) |
231 | - cert_str = cert_str.replace(' ', '').replace('\n', '') |
232 | - nodeComprobante.setAttribute("certificado", cert_str) |
233 | - data_dict['Comprobante']['certificado'] = cert_str |
234 | - |
235 | - self.write_cfd_data(cr, uid, ids, data_dict, context=context) |
236 | - |
237 | - if context.get('type_data') == 'dict': |
238 | - return data_dict |
239 | - if context.get('type_data') == 'xml_obj': |
240 | - return doc_xml |
241 | - data_xml = doc_xml.toxml('UTF-8') |
242 | - data_xml = codecs.BOM_UTF8 + data_xml |
243 | - fname_xml = (data_dict['Comprobante']['Emisor']['rfc'] or '') + '_' + ( |
244 | - data_dict['Comprobante'].get('serie', '') or '') + '_' + ( |
245 | - data_dict['Comprobante'].get('folio', '') or '') + '.xml' |
246 | - data_xml = data_xml.replace('<?xml version="1.0" encoding="UTF-8"?>', '<?xml version="1.0" encoding="UTF-8"?>\n') |
247 | - date_invoice = data_dict.get('Comprobante',{}) and datetime.strptime( data_dict.get('Comprobante',{}).get('fecha',{}), '%Y-%m-%dT%H:%M:%S').strftime('%Y-%m-%d') or False |
248 | - facturae_version = '2.2' |
249 | - if date_invoice and date_invoice < '2012-07-01': |
250 | - facturae_version = '2.0' |
251 | - self.validate_scheme_facturae_xml(cr, uid, ids, [data_xml], facturae_version) |
252 | - data_dict.get('Comprobante',{}) |
253 | + fname_txt = fname_xml + '.txt' |
254 | + f = open(fname_xml, 'w') |
255 | + doc_xml.writexml(f, indent=' ', addindent=' ', newl='\r\n', encoding='UTF-8') |
256 | + f.close() |
257 | + os.close(fileno_xml) |
258 | + (fileno_sign, fname_sign) = tempfile.mkstemp('.txt', 'openerp_' + ( |
259 | + invoice_number or '') + '__facturae_txt_md5__') |
260 | + os.close(fileno_sign) |
261 | + context.update({ |
262 | + 'fname_xml': fname_xml, |
263 | + 'fname_txt': fname_txt, |
264 | + 'fname_sign': fname_sign, |
265 | + }) |
266 | + context.update(self._get_file_globals(cr, uid, ids, context=context)) |
267 | + fname_txt, txt_str = self._xml2cad_orig(cr=False, uid=False, ids=False, context=context) |
268 | + data_dict['cadena_original'] = txt_str |
269 | + |
270 | + if not txt_str: |
271 | + raise osv.except_osv(_('Error en Cadena original!'), _( |
272 | + "Can't get the string original of the voucher.\nCkeck your configuration.\n%s" % (msg2))) |
273 | + |
274 | + if not data_dict['Comprobante'].get('folio', ''): |
275 | + raise osv.except_osv(_('Error in Folio!'), _( |
276 | + "Can't get the folio of the voucher.\nBefore generating the XML, click on the button, generate invoice.\nCkeck your configuration.\n%s" % (msg2))) |
277 | + |
278 | + # time.strftime('%Y-%m-%dT%H:%M:%S', |
279 | + # time.strptime(invoice.date_invoice, '%Y-%m-%d %H:%M:%S')) |
280 | + context.update({'fecha': data_dict['Comprobante']['fecha']}) |
281 | + sign_str = self._get_sello(cr=False, uid=False, ids=False, context=context) |
282 | + if not sign_str: |
283 | + raise osv.except_osv(_('Error in Stamp !'), _( |
284 | + "Can't generate the stamp of the voucher.\nCkeck your configuration.\ns%s") % (msg2)) |
285 | + |
286 | + nodeComprobante = doc_xml.getElementsByTagName("Comprobante")[0] |
287 | + nodeComprobante.setAttribute("sello", sign_str) |
288 | + data_dict['Comprobante']['sello'] = sign_str |
289 | + |
290 | + noCertificado = self._get_noCertificado(cr, uid, ids, context['fname_cer']) |
291 | + if not noCertificado: |
292 | + raise osv.except_osv(_('Error in No. Certificate !'), _( |
293 | + "Can't get the Certificate Number of the voucher.\nCkeck your configuration.\n%s") % (msg2)) |
294 | + nodeComprobante.setAttribute("noCertificado", noCertificado) |
295 | + data_dict['Comprobante']['noCertificado'] = noCertificado |
296 | + |
297 | + cert_str = self._get_certificate_str(context['fname_cer']) |
298 | + if not cert_str: |
299 | + raise osv.except_osv(_('Error in Certificate!'), _( |
300 | + "Can't generate the Certificate of the voucher.\nCkeck your configuration.\n%s") % (msg2)) |
301 | + cert_str = cert_str.replace(' ', '').replace('\n', '') |
302 | + nodeComprobante.setAttribute("certificado", cert_str) |
303 | + data_dict['Comprobante']['certificado'] = cert_str |
304 | + |
305 | + self.write_cfd_data(cr, uid, ids, data_dict, context=context) |
306 | + if context.get('type_data') == 'dict': |
307 | + return data_dict |
308 | + if context.get('type_data') == 'xml_obj': |
309 | + return doc_xml |
310 | + data_xml = doc_xml.toxml('UTF-8') |
311 | + data_xml = codecs.BOM_UTF8 + data_xml |
312 | + fname_xml = (data_dict['Comprobante']['Emisor']['rfc'] or '') + '_' + ( |
313 | + data_dict['Comprobante'].get('serie', '') or '') + '_' + ( |
314 | + data_dict['Comprobante'].get('folio', '') or '') + '.xml' |
315 | + data_xml = data_xml.replace('<?xml version="1.0" encoding="UTF-8"?>', '<?xml version="1.0" encoding="UTF-8"?>\n') |
316 | + date_invoice = data_dict.get('Comprobante',{}) and datetime.strptime( data_dict.get('Comprobante',{}).get('fecha',{}), '%Y-%m-%dT%H:%M:%S').strftime('%Y-%m-%d') or False |
317 | + facturae_version = '2.2' |
318 | + if date_invoice and date_invoice < '2012-07-01': |
319 | + facturae_version = '2.0' |
320 | + self.validate_scheme_facturae_xml(cr, uid, ids, [data_xml], facturae_version) |
321 | return fname_xml, data_xml |
322 | |
323 | def validate_scheme_facturae_xml(self, cr, uid, ids, datas_xmls=[], facturae_version = None, facturae_type="cfdv", scheme_type='xsd'): |
324 | @@ -842,7 +863,6 @@ |
325 | if os.path.isdir(os.path.join(my_path, 'l10n_mx_facturae', 'SAT')): |
326 | # If dir is in path, save it on real_path |
327 | fname_scheme = my_path and os.path.join(my_path, 'l10n_mx_facturae', 'SAT', facturae_type + facturae_version + '.' + scheme_type) or '' |
328 | - #fname_scheme = os.path.join(tools.config["addons_path"], u'l10n_mx_facturae', u'SAT', facturae_type + facturae_version + '.' + scheme_type ) |
329 | fname_out = certificate_lib.b64str_to_tempfile(cr, uid, ids, base64.encodestring(''), file_suffix='.txt', file_prefix='openerp__' + (False or '') + '__schema_validation_result__' ) |
330 | result = certificate_lib.check_xml_scheme(cr, uid, ids, fname_data_xml, fname_scheme, fname_out) |
331 | if result: #Valida el xml mediante el archivo xsd |
332 | @@ -865,8 +885,7 @@ |
333 | cfd_data = cfd_datas |
334 | noCertificado = cfd_data.get( |
335 | 'Comprobante', {}).get('noCertificado', '') |
336 | - certificado = cfd_data.get( |
337 | - 'Comprobante', {}).get('certificado', '') |
338 | + certificado = cfd_data.get('Comprobante', {}).get('certificado', '') |
339 | sello = cfd_data.get('Comprobante', {}).get('sello', '') |
340 | cadena_original = cfd_data.get('cadena_original', '') |
341 | data = { |
342 | @@ -996,7 +1015,7 @@ |
343 | invoice.date_invoice_tz, '%Y-%m-%d %H:%M:%S')) |
344 | or '', |
345 | 'tipoDeComprobante': tipoComprobante, |
346 | - 'formaDePago': u'Pago en una sola exhibición', |
347 | + 'formaDePago': "Pago en una sola exhibicion", |
348 | 'noCertificado': '@', |
349 | 'sello': '@', |
350 | 'certificado': '@', |
351 | @@ -1036,22 +1055,70 @@ |
352 | |
353 | invoice_data = invoice_data_parent['Comprobante'] |
354 | invoice_data['Emisor'] = {} |
355 | + name = self.remove_accents(cr, uid, ids, address_invoice_parent.name) |
356 | + calle = address_invoice_parent.street and \ |
357 | + address_invoice_parent.street.replace('\n\r', ' ').\ |
358 | + replace('\r\n', ' ').replace('\n', ' ').replace( |
359 | + '\r', ' ') or '' |
360 | + calle = self.remove_accents(cr, uid, ids, calle) |
361 | + colonia = address_invoice_parent.street2 and \ |
362 | + address_invoice_parent.street2.replace('\n\r', ' ').\ |
363 | + replace('\r\n', ' ').replace('\n', ' ').replace( |
364 | + '\r', ' ') or False |
365 | + colonia = self.remove_accents(cr, uid, ids, colonia) |
366 | + localidad = address_invoice_parent.l10n_mx_city2 and \ |
367 | + address_invoice_parent.l10n_mx_city2.replace( |
368 | + '\n\r', ' ').replace('\r\n', ' ').replace('\n', ' ').\ |
369 | + replace('\r', ' ') or False |
370 | + localidad = self.remove_accents(cr, uid, ids, localidad) |
371 | + municipio = address_invoice_parent.city and \ |
372 | + address_invoice_parent.city.replace('\n\r', ' ').\ |
373 | + replace('\r\n', ' ').replace('\n', ' ').replace( |
374 | + '\r', ' ') or '' |
375 | + municipio = self.remove_accents(cr, uid, ids, municipio) |
376 | + estado = address_invoice_parent.state_id and \ |
377 | + address_invoice_parent.state_id.name and \ |
378 | + address_invoice_parent.state_id.name.replace( |
379 | + '\n\r', ' ').replace('\r\n', ' ').replace( |
380 | + '\n', ' ').replace('\r', ' ') or '' |
381 | + estado = self.remove_accents(cr, uid, ids, estado) |
382 | + pais = address_invoice_parent.country_id and address_invoice_parent.\ |
383 | + country_id.name and address_invoice_parent.country_id.name.\ |
384 | + replace('\n\r', ' ').replace('\r\n', ' ').replace( |
385 | + '\n', ' ').replace('\r', ' ') or '' |
386 | + pais = self.remove_accents(cr, uid, ids, pais) |
387 | + |
388 | + ExpedidoEncalle = address_invoice.street and address_invoice.\ |
389 | + street.replace('\n\r', ' ').replace('\r\n', ' ').\ |
390 | + replace('\n', ' ').replace('\r', ' ') or '' |
391 | + ExpedidoEncalle = self.remove_accents(cr, uid, ids, ExpedidoEncalle) |
392 | + ExpedidoEncolonia = address_invoice.street2 and address_invoice.\ |
393 | + street2.replace('\n\r', ' ').replace('\r\n', ' ').\ |
394 | + replace('\n', ' ').replace('\r', ' ') or False |
395 | + ExpedidoEncolonia = self.remove_accents(cr, uid, ids, ExpedidoEncolonia) |
396 | + ExpedidoEnlocalidad = address_invoice.l10n_mx_city2 and \ |
397 | + address_invoice.l10n_mx_city2.replace('\n\r', ' ').\ |
398 | + replace('\r\n', ' ').replace('\n', ' ').replace( |
399 | + '\r', ' ') or False |
400 | + ExpedidoEnlocalidad = self.remove_accents(cr, uid, ids, ExpedidoEnlocalidad) |
401 | + ExpedidoEnmunicipio = address_invoice.city and address_invoice.\ |
402 | + city.replace('\n\r', ' ').replace('\r\n', ' ').replace( |
403 | + '\n', ' ').replace('\r', ' ') or '' |
404 | + ExpedidoEnmunicipio = self.remove_accents(cr, uid, ids, ExpedidoEnmunicipio) |
405 | + ExpedidoEnestado = address_invoice.state_id and address_invoice.\ |
406 | + state_id.name and address_invoice.state_id.name.replace( |
407 | + '\n\r', ' ').replace('\r\n', ' ').replace('\n', ' ').\ |
408 | + replace('\r', ' ') or '' |
409 | + ExpedidoEnestado = self.remove_accents(cr, uid, ids, ExpedidoEnestado) |
410 | + |
411 | + |
412 | invoice_data['Emisor'].update({ |
413 | - |
414 | 'rfc': (('vat_split' in address_invoice_parent._columns and \ |
415 | address_invoice_parent.vat_split or address_invoice_parent.vat) \ |
416 | or '').replace('-', ' ').replace(' ', ''), |
417 | - 'nombre': address_invoice_parent.name or '', |
418 | - # Obtener domicilio dinamicamente |
419 | - # virtual_invoice.append( (invoice.company_id and |
420 | - # invoice.company_id.partner_id and |
421 | - # invoice.company_id.partner_id.vat or '').replac |
422 | - |
423 | + 'nombre': name or '', |
424 | 'DomicilioFiscal': { |
425 | - 'calle': address_invoice_parent.street and \ |
426 | - address_invoice_parent.street.replace('\n\r', ' ').\ |
427 | - replace('\r\n', ' ').replace('\n', ' ').replace( |
428 | - '\r', ' ') or '', |
429 | + 'calle': calle or '', |
430 | 'noExterior': address_invoice_parent.l10n_mx_street3 and \ |
431 | address_invoice_parent.l10n_mx_street3.replace( |
432 | '\n\r', ' ').replace('\r\n', ' ').replace('\n', ' ').\ |
433 | @@ -1060,37 +1127,18 @@ |
434 | address_invoice_parent.l10n_mx_street4.replace( |
435 | '\n\r', ' ').replace('\r\n', ' ').replace('\n', ' ').\ |
436 | replace('\r', ' ') or 'N/A', # "Numero Interior" |
437 | - 'colonia': address_invoice_parent.street2 and \ |
438 | - address_invoice_parent.street2.replace('\n\r', ' ').\ |
439 | - replace('\r\n', ' ').replace('\n', ' ').replace( |
440 | - '\r', ' ') or False, |
441 | - 'localidad': address_invoice_parent.l10n_mx_city2 and \ |
442 | - address_invoice_parent.l10n_mx_city2.replace( |
443 | - '\n\r', ' ').replace('\r\n', ' ').replace('\n', ' ').\ |
444 | - replace('\r', ' ') or False, |
445 | - 'municipio': address_invoice_parent.city and \ |
446 | - address_invoice_parent.city.replace('\n\r', ' ').\ |
447 | - replace('\r\n', ' ').replace('\n', ' ').replace( |
448 | - '\r', ' ') or '', |
449 | - 'estado': address_invoice_parent.state_id and \ |
450 | - address_invoice_parent.state_id.name and \ |
451 | - address_invoice_parent.state_id.name.replace( |
452 | - '\n\r', ' ').replace('\r\n', ' ').replace( |
453 | - '\n', ' ').replace('\r', ' ') or '', |
454 | - 'pais': address_invoice_parent.country_id and \ |
455 | - address_invoice_parent.country_id.name and \ |
456 | - address_invoice_parent.country_id.name.replace( |
457 | - '\n\r', ' ').replace('\r\n', ' ').replace( |
458 | - '\n', ' ').replace('\r', ' ')or '', |
459 | + 'colonia': colonia or False, |
460 | + 'localidad': localidad or False, |
461 | + 'municipio': municipio or '', |
462 | + 'estado': estado or '', |
463 | + 'pais': pais or '', |
464 | 'codigoPostal': address_invoice_parent.zip and \ |
465 | address_invoice_parent.zip.replace('\n\r', ' ').\ |
466 | replace('\r\n', ' ').replace('\n', ' ').replace( |
467 | '\r', ' ').replace(' ', '') or '', |
468 | }, |
469 | 'ExpedidoEn': { |
470 | - 'calle': address_invoice.street and address_invoice.\ |
471 | - street.replace('\n\r', ' ').replace('\r\n', ' ').\ |
472 | - replace('\n', ' ').replace('\r', ' ') or '', |
473 | + 'calle': ExpedidoEncalle or '', |
474 | 'noExterior': address_invoice.l10n_mx_street3 and \ |
475 | address_invoice.l10n_mx_street3.replace( |
476 | '\n\r', ' ').replace('\r\n', ' ').replace('\n', ' ').\ |
477 | @@ -1099,24 +1147,11 @@ |
478 | address_invoice.l10n_mx_street4.replace('\n\r', ' ').\ |
479 | replace('\r\n', ' ').replace('\n', ' ').replace( |
480 | '\r', ' ') or 'N/A', # "Numero Interior" |
481 | - 'colonia': address_invoice.street2 and address_invoice.\ |
482 | - street2.replace('\n\r', ' ').replace('\r\n', ' ').\ |
483 | - replace('\n', ' ').replace('\r', ' ') or False, |
484 | - 'localidad': address_invoice.l10n_mx_city2 and \ |
485 | - address_invoice.l10n_mx_city2.replace('\n\r', ' ').\ |
486 | - replace('\r\n', ' ').replace('\n', ' ').replace( |
487 | - '\r', ' ') or False, |
488 | - 'municipio': address_invoice.city and address_invoice.\ |
489 | - city.replace('\n\r', ' ').replace('\r\n', ' ').replace( |
490 | - '\n', ' ').replace('\r', ' ') or '', |
491 | - 'estado': address_invoice.state_id and address_invoice.\ |
492 | - state_id.name and address_invoice.state_id.name.replace( |
493 | - '\n\r', ' ').replace('\r\n', ' ').replace('\n', ' ').\ |
494 | - replace('\r', ' ') or '', |
495 | - 'pais': address_invoice.country_id and address_invoice.\ |
496 | - country_id.name and address_invoice.country_id.name.\ |
497 | - replace('\n\r', ' ').replace('\r\n', ' ').replace( |
498 | - '\n', ' ').replace('\r', ' ')or '', |
499 | + 'colonia': ExpedidoEncolonia or False, |
500 | + 'localidad': ExpedidoEnlocalidad or False, |
501 | + 'municipio': ExpedidoEnmunicipio or '', |
502 | + 'estado': ExpedidoEnestado or '', |
503 | + 'pais': pais or '', |
504 | 'codigoPostal': address_invoice.zip and address_invoice.\ |
505 | zip.replace('\n\r', ' ').replace('\r\n', ' ').replace( |
506 | '\n', ' ').replace('\r', ' ').replace(' ', '') or '', |
507 | @@ -1148,13 +1183,40 @@ |
508 | address_invoice = partner_obj.browse(cr, uid, \ |
509 | invoice.partner_id.id, context=context) |
510 | invoice_data['Receptor'] = {} |
511 | + parent_name = self.remove_accents(cr, uid, ids, parent_obj.name) |
512 | + Receptorcalle = address_invoice.street and address_invoice.\ |
513 | + street.replace('\n\r', ' ').replace('\r\n', ' ').replace( |
514 | + '\n', ' ').replace('\r', ' ') or '' |
515 | + Receptorcalle = self.remove_accents(cr, uid, ids, Receptorcalle) |
516 | + Receptorpais = address_invoice.country_id and address_invoice.\ |
517 | + country_id.name and address_invoice.country_id.name.\ |
518 | + replace('\n\r', ' ').replace('\r\n', ' ').replace( |
519 | + '\n', ' ').replace('\r', ' ')or '' |
520 | + Receptorpais = self.remove_accents(cr, uid, ids, Receptorpais) |
521 | + Receptorcolonia = address_invoice.street2 and address_invoice.\ |
522 | + street2.replace('\n\r', ' ').replace('\r\n', ' ').\ |
523 | + replace('\n', ' ').replace('\r', ' ') or False |
524 | + Receptorcolonia = self.remove_accents(cr, uid, ids, Receptorcolonia) |
525 | + Receptorlocalidad = address_invoice.l10n_mx_city2 and \ |
526 | + address_invoice.l10n_mx_city2.replace('\n\r', ' ').\ |
527 | + replace('\r\n', ' ').replace('\n', ' ').replace( |
528 | + '\r', ' ') or False |
529 | + Receptorlocalidad = self.remove_accents(cr, uid, ids, Receptorlocalidad) |
530 | + Receptormunicipio = address_invoice.city and address_invoice.\ |
531 | + city.replace('\n\r', ' ').replace('\r\n', ' ').replace( |
532 | + '\n', ' ').replace('\r', ' ') or '' |
533 | + Receptormunicipio = self.remove_accents(cr, uid, ids, Receptormunicipio) |
534 | + Receptorestado = address_invoice.state_id and address_invoice.\ |
535 | + state_id.name and address_invoice.state_id.name.replace( |
536 | + '\n\r', ' ').replace('\r\n', ' ').replace('\n', ' ').\ |
537 | + replace('\r', ' ') or '' |
538 | + Receptorestado = self.remove_accents(cr, uid, ids, Receptorestado) |
539 | + |
540 | invoice_data['Receptor'].update({ |
541 | 'rfc': rfc, |
542 | - 'nombre': (parent_obj.name or ''), |
543 | + 'nombre': parent_name or '', |
544 | 'Domicilio': { |
545 | - 'calle': address_invoice.street and address_invoice.\ |
546 | - street.replace('\n\r', ' ').replace('\r\n', ' ').replace( |
547 | - '\n', ' ').replace('\r', ' ') or '', |
548 | + 'calle': Receptorcalle or '', |
549 | 'noExterior': address_invoice.l10n_mx_street3 and \ |
550 | address_invoice.l10n_mx_street3.replace('\n\r', ' ').\ |
551 | replace('\r\n', ' ').replace('\n', ' ').replace( |
552 | @@ -1163,24 +1225,11 @@ |
553 | address_invoice.l10n_mx_street4.replace('\n\r', ' ').\ |
554 | replace('\r\n', ' ').replace('\n', ' ').replace( |
555 | '\r', ' ') or 'N/A', # "Numero Interior" |
556 | - 'colonia': address_invoice.street2 and address_invoice.\ |
557 | - street2.replace('\n\r', ' ').replace('\r\n', ' ').\ |
558 | - replace('\n', ' ').replace('\r', ' ') or False, |
559 | - 'localidad': address_invoice.l10n_mx_city2 and \ |
560 | - address_invoice.l10n_mx_city2.replace('\n\r', ' ').\ |
561 | - replace('\r\n', ' ').replace('\n', ' ').replace( |
562 | - '\r', ' ') or False, |
563 | - 'municipio': address_invoice.city and address_invoice.\ |
564 | - city.replace('\n\r', ' ').replace('\r\n', ' ').replace( |
565 | - '\n', ' ').replace('\r', ' ') or '', |
566 | - 'estado': address_invoice.state_id and address_invoice.\ |
567 | - state_id.name and address_invoice.state_id.name.replace( |
568 | - '\n\r', ' ').replace('\r\n', ' ').replace('\n', ' ').\ |
569 | - replace('\r', ' ') or '', |
570 | - 'pais': address_invoice.country_id and address_invoice.\ |
571 | - country_id.name and address_invoice.country_id.name.\ |
572 | - replace('\n\r', ' ').replace('\r\n', ' ').replace( |
573 | - '\n', ' ').replace('\r', ' ')or '', |
574 | + 'colonia': Receptorcolonia or False, |
575 | + 'localidad': Receptorlocalidad or False, |
576 | + 'municipio': Receptormunicipio or '', |
577 | + 'estado': Receptorestado or '', |
578 | + 'pais': Receptorpais or '', |
579 | 'codigoPostal': address_invoice.zip and address_invoice.\ |
580 | zip.replace('\n\r', ' ').replace('\r\n', ' ').replace( |
581 | '\n', ' ').replace('\r', ' ') or '', |
582 | @@ -1202,7 +1251,7 @@ |
583 | line.quantity or 0.0 |
584 | concepto = { |
585 | 'cantidad': "%.2f" % (line.quantity or 0.0), |
586 | - 'descripcion': line.name or '', |
587 | + 'descripcion': self.remove_accents(cr, uid, ids, line.name) or '', |
588 | 'valorUnitario': "%.2f" % (price_unit or 0.0), |
589 | 'importe': "%.2f" % (line.price_subtotal or 0.0), # round(line.price_unit *(1-(line.discount/100)),2) or 0.00),#Calc: iva, disc, qty |
590 | # Falta agregar discount |
591 | @@ -1259,7 +1308,7 @@ |
592 | totalImpuestosRetenidos += line_tax_id_amount |
593 | impuesto_dict = {impuesto_str: |
594 | { |
595 | - 'impuesto': tax_name, |
596 | + 'impuesto': self.remove_accents(cr, uid, ids, tax_name), |
597 | 'importe': "%.2f" % (line_tax_id_amount), |
598 | } |
599 | } |
600 | @@ -1281,7 +1330,7 @@ |
601 | if tax_required in tax_names: |
602 | continue |
603 | invoice_data_impuestos['Traslados'].append({'Traslado': { |
604 | - 'impuesto': tax_required, |
605 | + 'impuesto': self.remove_accents(cr, uid, ids, tax_required), |
606 | 'tasa': "%.2f" % (0.0), |
607 | 'importe': "%.2f" % (0.0), |
608 | }}) |
609 | @@ -1349,11 +1398,12 @@ |
610 | invoice_data_parents[0]['Comprobante'][ |
611 | 'NumCtaPago'] = invoice.acc_payment.last_acc_number\ |
612 | or 'No identificado' |
613 | + metodoDePago = invoice.pay_method_id.name or 'No identificado' |
614 | invoice_data_parents[0]['Comprobante'][ |
615 | - 'metodoDePago'] = invoice.pay_method_id.name or 'No identificado' |
616 | - invoice_data_parents[0]['Comprobante']['Emisor']['RegimenFiscal'] = { |
617 | - 'Regimen': invoice.company_emitter_id.partner_id.\ |
618 | - regimen_fiscal_id.name or ''} |
619 | + 'metodoDePago'] = self.remove_accents(cr, uid, ids, metodoDePago) |
620 | + regimen = invoice.company_emitter_id.partner_id.regimen_fiscal_id.name or '' |
621 | + regimen = self.remove_accents(cr, uid, ids, regimen) |
622 | + invoice_data_parents[0]['Comprobante']['Emisor']['RegimenFiscal'] ={'Regimen': regimen} |
623 | invoice_data_parents[0]['Comprobante']['LugarExpedicion'] = address |
624 | return invoice_data_parents |
625 | |
626 | |
627 | === added directory 'l10n_mx_facturae/template' |
628 | === added file 'l10n_mx_facturae/template/cfd.xml' |
629 | --- l10n_mx_facturae/template/cfd.xml 1970-01-01 00:00:00 +0000 |
630 | +++ l10n_mx_facturae/template/cfd.xml 2014-01-25 00:46:46 +0000 |
631 | @@ -0,0 +1,1 @@ |
632 | +<?xml version="1.0" encoding="UTF-8"?><Comprobante LugarExpedicion="{{ o['Comprobante']['LugarExpedicion'] }}" Moneda="{{ o['Comprobante']['Moneda'] }}" NumCtaPago="{{ o['Comprobante']['NumCtaPago'] }}" TipoCambio="{{ o['Comprobante']['TipoCambio'] }}" anoAprobacion="{{ o['Comprobante']['anoAprobacion'] }}" certificado="{{ o['Comprobante']['certificado'] }}" descuento="{{ o['Comprobante']['descuento'] }}" fecha="{{ o['Comprobante']['fecha'] }}" folio="{{ o['Comprobante']['folio'] }}" formaDePago="{{ o['Comprobante']['formaDePago'] }}" metodoDePago="{{ o['Comprobante']['metodoDePago'] }}" noAprobacion="{{ o['Comprobante']['noAprobacion'] }}" noCertificado="{{ o['Comprobante']['noCertificado'] }}" sello="{{ o['Comprobante']['sello'] }}" serie="{{ o['Comprobante']['serie'] }}" subTotal="{{ o['Comprobante']['subTotal'] }}" tipoDeComprobante="{{ o['Comprobante']['tipoDeComprobante'] }}" total="{{ o['Comprobante']['total'] }}" version="{{ o['Comprobante']['version'] }}" xmlns="{{ o['Comprobante']['xmlns'] }}" xmlns:xsi="{{ o['Comprobante']['xmlns:xsi'] }}" xsi:schemaLocation="{{ o['Comprobante']['xsi:schemaLocation'] }}"><Emisor nombre="{{ o['Comprobante']['Emisor']['nombre'] }}" rfc="{{ o['Comprobante']['Emisor']['rfc'] }}"><DomicilioFiscal calle="{{ o['Comprobante']['Emisor']['DomicilioFiscal']['calle'] }}" codigoPostal="{{ o['Comprobante']['Emisor']['DomicilioFiscal']['codigoPostal'] }}" colonia="{{ o['Comprobante']['Emisor']['DomicilioFiscal']['colonia'] }}" estado="{{ o['Comprobante']['Emisor']['DomicilioFiscal']['estado'] }}" localidad="{{ o['Comprobante']['Emisor']['DomicilioFiscal']['localidad'] }}" municipio="{{ o['Comprobante']['Emisor']['DomicilioFiscal']['municipio'] }}" noExterior="{{ o['Comprobante']['Emisor']['DomicilioFiscal']['noExterior'] }}" noInterior="{{ o['Comprobante']['Emisor']['DomicilioFiscal']['noInterior'] }}" pais="{{ o['Comprobante']['Emisor']['DomicilioFiscal']['pais'] }}"/><ExpedidoEn calle="{{ o['Comprobante']['Emisor']['ExpedidoEn']['calle'] }}" codigoPostal="{{ o['Comprobante']['Emisor']['ExpedidoEn']['codigoPostal'] }}" colonia="{{ o['Comprobante']['Emisor']['ExpedidoEn']['colonia'] }}" estado="{{ o['Comprobante']['Emisor']['ExpedidoEn']['estado'] }}" localidad="{{ o['Comprobante']['Emisor']['ExpedidoEn']['localidad'] }}" municipio="{{ o['Comprobante']['Emisor']['ExpedidoEn']['municipio'] }}" noExterior="{{ o['Comprobante']['Emisor']['ExpedidoEn']['noExterior'] }}" noInterior="{{ o['Comprobante']['Emisor']['ExpedidoEn']['noInterior'] }}" pais="{{ o['Comprobante']['Emisor']['ExpedidoEn']['pais'] }}"/><RegimenFiscal Regimen="{{ o['Comprobante']['Emisor']['RegimenFiscal']['Regimen'] }}"/></Emisor><Receptor nombre="{{ o['Comprobante']['Receptor']['nombre'] }}" rfc="{{ o['Comprobante']['Receptor']['rfc'] }}"><Domicilio calle="{{ o['Comprobante']['Receptor']['Domicilio']['calle'] }}" codigoPostal="{{ o['Comprobante']['Receptor']['Domicilio']['codigoPostal'] }}" colonia="{{ o['Comprobante']['Receptor']['Domicilio']['colonia'] }}" estado="{{ o['Comprobante']['Receptor']['Domicilio']['estado'] }}" localidad="{{ o['Comprobante']['Receptor']['Domicilio']['localidad'] }}" municipio="{{ o['Comprobante']['Receptor']['Domicilio']['municipio'] }}" noExterior="{{ o['Comprobante']['Receptor']['Domicilio']['noExterior'] }}" noInterior="{{ o['Comprobante']['Receptor']['Domicilio']['noInterior'] }}" pais="{{ o['Comprobante']['Receptor']['Domicilio']['pais'] }}"/></Receptor>{% if o['Comprobante']['Conceptos']%}<Conceptos>{% for i in o['Comprobante']['Conceptos'] %}<Concepto cantidad="{{ i['Concepto']['cantidad'] }}" descripcion="{{ i['Concepto']['descripcion'] }}" importe="{{ i['Concepto']['importe'] }}" noIdentificacion="{{ i['Concepto']['noIdentificacion'] }}" unidad="{{ i['Concepto']['unidad'] }}" valorUnitario="{{ i['Concepto']['valorUnitario'] }}"/>{% endfor %}{% endif %}</Conceptos>{% if o['Comprobante']['Impuestos']['totalImpuestosTrasladados'] %}<Impuestos totalImpuestosTrasladados="{{ o['Comprobante']['Impuestos']['totalImpuestosTrasladados'] }}"><Traslados>{% for i in o['Comprobante']['Impuestos']['Traslados'] %}<Traslado importe="{{ i['Traslado']['importe'] }}" impuesto="{{ i['Traslado']['impuesto'] }}" tasa="{{ i['Traslado']['tasa'] }}"/>{% endfor %}</Traslados></Impuestos>{% endif %}</Comprobante> |
633 | \ No newline at end of file |
634 | |
635 | === modified file 'l10n_mx_facturae_pac/invoice.py' |
636 | --- l10n_mx_facturae_pac/invoice.py 2013-11-20 23:20:47 +0000 |
637 | +++ l10n_mx_facturae_pac/invoice.py 2014-01-25 00:46:46 +0000 |
638 | @@ -29,7 +29,6 @@ |
639 | import os |
640 | import codecs |
641 | import base64 |
642 | -import xml.dom.minidom |
643 | from datetime import datetime, timedelta |
644 | from openerp.tools.translate import _ |
645 | try: |
646 | @@ -39,6 +38,8 @@ |
647 | pass |
648 | import time |
649 | from openerp import tools |
650 | +import jinja2 |
651 | +import xml |
652 | |
653 | |
654 | class account_invoice(osv.Model): |
655 | @@ -54,7 +55,6 @@ |
656 | invoice = self.browse(cr, uid, ids[0], context=context) |
657 | sequence_app_id = ir_seq_app_obj.search(cr, uid, [( |
658 | 'sequence_id', '=', invoice.invoice_sequence_id.id)], context=context) |
659 | - type_inv = 'cfd22' |
660 | if sequence_app_id: |
661 | type_inv = ir_seq_app_obj.browse( |
662 | cr, uid, sequence_app_id[0], context=context).type |
663 | @@ -114,6 +114,7 @@ |
664 | invoice = self.browse(cr, uid, ids[0], context=context) |
665 | sequence_app_id = ir_seq_app_obj.search(cr, uid, [( |
666 | 'sequence_id', '=', invoice.invoice_sequence_id.id)], context=context) |
667 | + all_paths = tools.config["addons_path"].split(",") |
668 | type_inv = 'cfd22' |
669 | if sequence_app_id: |
670 | type_inv = ir_seq_app_obj.browse( |
671 | @@ -124,6 +125,10 @@ |
672 | receptor = 'cfdi:Receptor' |
673 | concepto = 'cfdi:Conceptos' |
674 | facturae_version = '3.2' |
675 | + for my_path in all_paths: |
676 | + if os.path.isdir(os.path.join(my_path, 'l10n_mx_facturae_pac_sf', 'template')): |
677 | + fname_jinja_tmpl = my_path and os.path.join(my_path, 'l10n_mx_facturae_pac_sf', |
678 | + 'template', 'cfdi' + '.xml') or '' |
679 | else: |
680 | comprobante = 'Comprobante' |
681 | emisor = 'Emisor' |
682 | @@ -131,16 +136,30 @@ |
683 | receptor = 'Receptor' |
684 | concepto = 'Conceptos' |
685 | facturae_version = '2.2' |
686 | - data_dict = self._get_facturae_invoice_dict_data( |
687 | - cr, uid, ids, context=context)[0] |
688 | - doc_xml = self.dict2xml({comprobante: data_dict.get(comprobante)}) |
689 | + for my_path in all_paths: |
690 | + if os.path.isdir(os.path.join(my_path, 'l10n_mx_facturae', 'template')): |
691 | + fname_jinja_tmpl = my_path and os.path.join(my_path, 'l10n_mx_facturae', |
692 | + 'template', 'cfd' + '.xml') or '' |
693 | + |
694 | + data_dict = self._get_facturae_invoice_dict_data(cr, uid, ids, context=context)[0] |
695 | + dictargs = { |
696 | + 'o': data_dict |
697 | + } |
698 | invoice_number = "sn" |
699 | + (fileno_xml, fname_xml) = tempfile.mkstemp('.xml', 'openerp_' + (invoice_number or '') + '__facturae__') |
700 | + with open(fname_jinja_tmpl, 'r') as f_jinja_tmpl: |
701 | + jinja_tmpl_str = f_jinja_tmpl.read().encode('utf-8') |
702 | + tmpl = jinja2.Template( jinja_tmpl_str ) |
703 | + with open(fname_xml, 'w') as new_xml: |
704 | + new_xml.write( tmpl.render(**dictargs) ) |
705 | + with open(fname_xml,'rb') as b: |
706 | + jinja2_xml = b.read().encode('utf-8') |
707 | + doc_xml = xml.dom.minidom.parseString(jinja2_xml) |
708 | (fileno_xml, fname_xml) = tempfile.mkstemp( |
709 | '.xml', 'openerp_' + (invoice_number or '') + '__facturae__') |
710 | fname_txt = fname_xml + '.txt' |
711 | f = open(fname_xml, 'w') |
712 | - doc_xml.writexml( |
713 | - f, indent=' ', addindent=' ', newl='\r\n', encoding='UTF-8') |
714 | + doc_xml.writexml(f, indent=' ', addindent=' ', newl='\r\n', encoding='UTF-8') |
715 | f.close() |
716 | os.close(fileno_xml) |
717 | (fileno_sign, fname_sign) = tempfile.mkstemp('.txt', 'openerp_' + ( |
718 | @@ -152,8 +171,7 @@ |
719 | 'fname_sign': fname_sign, |
720 | }) |
721 | context.update(self._get_file_globals(cr, uid, ids, context=context)) |
722 | - fname_txt, txt_str = self._xml2cad_orig( |
723 | - cr=False, uid=False, ids=False, context=context) |
724 | + fname_txt, txt_str = self._xml2cad_orig(cr=False, uid=False, ids=False, context=context) |
725 | data_dict['cadena_original'] = txt_str |
726 | msg2='' |
727 | |
728 | @@ -166,8 +184,7 @@ |
729 | "Can't get the folio of the voucher.\nBefore generating the XML, click on the button, generate invoice.\nCkeck your configuration.\n%s" % (msg2))) |
730 | |
731 | context.update({'fecha': data_dict[comprobante]['fecha']}) |
732 | - sign_str = self._get_sello( |
733 | - cr=False, uid=False, ids=False, context=context) |
734 | + sign_str = self._get_sello(cr=False, uid=False, ids=False, context=context) |
735 | if not sign_str: |
736 | raise osv.except_osv(_('Error in Stamp !'), _( |
737 | "Can't generate the stamp of the voucher.\nCkeck your configuration.\ns%s") % (msg2)) |
738 | @@ -190,13 +207,11 @@ |
739 | cert_str = cert_str.replace(' ', '').replace('\n', '') |
740 | nodeComprobante.setAttribute("certificado", cert_str) |
741 | data_dict[comprobante]['certificado'] = cert_str |
742 | + |
743 | + |
744 | if 'cfdi' in type_inv: |
745 | nodeComprobante.removeAttribute('anoAprobacion') |
746 | nodeComprobante.removeAttribute('noAprobacion') |
747 | - x = doc_xml.documentElement |
748 | - nodeReceptor = doc_xml.getElementsByTagName(receptor)[0] |
749 | - nodeConcepto = doc_xml.getElementsByTagName(concepto)[0] |
750 | - x.insertBefore(nodeReceptor, nodeConcepto) |
751 | |
752 | self.write_cfd_data(cr, uid, ids, data_dict, context=context) |
753 | |
754 | @@ -215,28 +230,4 @@ |
755 | if date_invoice and date_invoice < '2012-07-01': |
756 | facturae_version = '2.0' |
757 | self.validate_scheme_facturae_xml(cr, uid, ids, [data_xml], facturae_version) |
758 | - data_dict.get('Comprobante',{}) |
759 | return fname_xml, data_xml |
760 | - |
761 | - def validate_scheme_facturae_xml(self, cr, uid, ids, datas_xmls=[], facturae_version = None, facturae_type="cfdv", scheme_type='xsd'): |
762 | - #TODO: bzr add to file fname_schema |
763 | - if not datas_xmls: |
764 | - datas_xmls = [] |
765 | - certificate_lib = self.pool.get('facturae.certificate.library') |
766 | - for data_xml in datas_xmls: |
767 | - (fileno_data_xml, fname_data_xml) = tempfile.mkstemp('.xml', 'openerp_' + (False or '') + '__facturae__' ) |
768 | - f = open(fname_data_xml, 'wb') |
769 | - f.write( data_xml ) |
770 | - f.close() |
771 | - os.close(fileno_data_xml) |
772 | - all_paths = tools.config["addons_path"].split(",") |
773 | - for my_path in all_paths: |
774 | - if os.path.isdir(os.path.join(my_path, 'l10n_mx_facturae', 'SAT')): |
775 | - # If dir is in path, save it on real_path |
776 | - fname_scheme = my_path and os.path.join(my_path, 'l10n_mx_facturae', 'SAT', facturae_type + facturae_version + '.' + scheme_type) or '' |
777 | - #fname_scheme = os.path.join(tools.config["addons_path"], u'l10n_mx_facturae', u'SAT', facturae_type + facturae_version + '.' + scheme_type ) |
778 | - fname_out = certificate_lib.b64str_to_tempfile(cr, uid, ids, base64.encodestring(''), file_suffix='.txt', file_prefix='openerp__' + (False or '') + '__schema_validation_result__' ) |
779 | - result = certificate_lib.check_xml_scheme(cr, uid, ids, fname_data_xml, fname_scheme, fname_out) |
780 | - if result: #Valida el xml mediante el archivo xsd |
781 | - raise osv.except_osv('Error al validar la estructura del xml!', 'Validación de XML versión %s:\n%s'%(facturae_version, result)) |
782 | - return True |
783 | |
784 | === modified file 'l10n_mx_facturae_pac_sf/ir_attachment_facturae.py' |
785 | --- l10n_mx_facturae_pac_sf/ir_attachment_facturae.py 2013-12-10 01:11:31 +0000 |
786 | +++ l10n_mx_facturae_pac_sf/ir_attachment_facturae.py 2014-01-25 00:46:46 +0000 |
787 | @@ -148,8 +148,8 @@ |
788 | has completed correctly.\n- The uuid cancelled is:\ |
789 | ') + folio_cancel |
790 | invoice_obj.write(cr, uid, [invoice.id], { |
791 | - 'cfdi_fecha_cancelacion': time.strftime( |
792 | - '%Y-%m-%d %H:%M:%S') |
793 | + 'cfdi_fecha_cancelacion': time.strftime('%Y-%m-%d %H:%M:%S'), |
794 | + 'pac_id' : pac_params_id or False |
795 | }) |
796 | status = True |
797 | else: |
798 | @@ -169,8 +169,7 @@ |
799 | pac_params_obj = invoice_obj.pool.get('params.pac') |
800 | for ir_attachment_facturae_mx_id in self.browse(cr, uid, ids, context=context): |
801 | invoice = ir_attachment_facturae_mx_id.invoice_id |
802 | - comprobante = invoice_obj._get_type_sequence( |
803 | - cr, uid, [invoice.id], context=context) |
804 | + comprobante = invoice_obj._get_type_sequence(cr, uid, [invoice.id], context=context) |
805 | cfd_data = base64.decodestring(fdata or invoice_obj.fdata) |
806 | xml_res_str = xml.dom.minidom.parseString(cfd_data) |
807 | xml_res_addenda = invoice_obj.add_addenta_xml( |
808 | |
809 | === added directory 'l10n_mx_facturae_pac_sf/template' |
810 | === added file 'l10n_mx_facturae_pac_sf/template/cfdi.xml' |
811 | --- l10n_mx_facturae_pac_sf/template/cfdi.xml 1970-01-01 00:00:00 +0000 |
812 | +++ l10n_mx_facturae_pac_sf/template/cfdi.xml 2014-01-25 00:46:46 +0000 |
813 | @@ -0,0 +1,1 @@ |
814 | +<?xml version="1.0" encoding="UTF-8"?><cfdi:Comprobante xmlns:cfdi="http://www.sat.gob.mx/cfd/3" LugarExpedicion="{{ o['cfdi:Comprobante']['LugarExpedicion'] }}" Moneda="{{ o['cfdi:Comprobante']['Moneda'] }}" NumCtaPago="{{ o['cfdi:Comprobante']['NumCtaPago'] }}" TipoCambio="{{ o['cfdi:Comprobante']['TipoCambio'] }}" anoAprobacion="{{ o['cfdi:Comprobante']['anoAprobacion'] }}" certificado="{{ o['cfdi:Comprobante']['certificado'] }}" descuento="{{ o['cfdi:Comprobante']['descuento'] }}" fecha="{{ o['cfdi:Comprobante']['fecha'] }}" folio="{{ o['cfdi:Comprobante']['folio'] }}" formaDePago="{{ o['cfdi:Comprobante']['formaDePago'] }}" metodoDePago="{{ o['cfdi:Comprobante']['metodoDePago'] }}" noAprobacion="{{ o['cfdi:Comprobante']['noAprobacion'] }}" noCertificado="{{ o['cfdi:Comprobante']['noCertificado'] }}" sello="{{ o['cfdi:Comprobante']['sello'] }}" serie="{{ o['cfdi:Comprobante']['serie'] }}" subTotal="{{ o['cfdi:Comprobante']['subTotal'] }}" tipoDeComprobante="{{ o['cfdi:Comprobante']['tipoDeComprobante'] }}" total="{{ o['cfdi:Comprobante']['total'] }}" version="{{ o['cfdi:Comprobante']['version'] }}" xmlns="{{ o['cfdi:Comprobante']['xmlns'] }}" xmlns:xsi="{{ o['cfdi:Comprobante']['xmlns:xsi'] }}" xsi:schemaLocation="{{ o['cfdi:Comprobante']['xsi:schemaLocation'] }}"><cfdi:Emisor nombre="{{ o['cfdi:Comprobante']['cfdi:Emisor']['nombre'] }}" rfc="{{ o['cfdi:Comprobante']['cfdi:Emisor']['rfc'] }}"><cfdi:DomicilioFiscal calle="{{ o['cfdi:Comprobante']['cfdi:Emisor']['cfdi:DomicilioFiscal']['calle'] }}" codigoPostal="{{ o['cfdi:Comprobante']['cfdi:Emisor']['cfdi:DomicilioFiscal']['codigoPostal'] }}" colonia="{{ o['cfdi:Comprobante']['cfdi:Emisor']['cfdi:DomicilioFiscal']['colonia'] }}" estado="{{ o['cfdi:Comprobante']['cfdi:Emisor']['cfdi:DomicilioFiscal']['estado'] }}" localidad="{{ o['cfdi:Comprobante']['cfdi:Emisor']['cfdi:DomicilioFiscal']['localidad'] }}" municipio="{{ o['cfdi:Comprobante']['cfdi:Emisor']['cfdi:DomicilioFiscal']['municipio'] }}" noExterior="{{ o['cfdi:Comprobante']['cfdi:Emisor']['cfdi:DomicilioFiscal']['noExterior'] }}" noInterior="{{ o['cfdi:Comprobante']['cfdi:Emisor']['cfdi:DomicilioFiscal']['noInterior'] }}" pais="{{ o['cfdi:Comprobante']['cfdi:Emisor']['cfdi:DomicilioFiscal']['pais'] }}"/><cfdi:ExpedidoEn calle="{{ o['cfdi:Comprobante']['cfdi:Emisor']['cfdi:ExpedidoEn']['calle'] }}" codigoPostal="{{ o['cfdi:Comprobante']['cfdi:Emisor']['cfdi:ExpedidoEn']['codigoPostal'] }}" colonia="{{ o['cfdi:Comprobante']['cfdi:Emisor']['cfdi:ExpedidoEn']['colonia'] }}" estado="{{ o['cfdi:Comprobante']['cfdi:Emisor']['cfdi:ExpedidoEn']['estado'] }}" localidad="{{ o['cfdi:Comprobante']['cfdi:Emisor']['cfdi:ExpedidoEn']['localidad'] }}" municipio="{{ o['cfdi:Comprobante']['cfdi:Emisor']['cfdi:ExpedidoEn']['municipio'] }}" noExterior="{{ o['cfdi:Comprobante']['cfdi:Emisor']['cfdi:ExpedidoEn']['noExterior'] }}" noInterior="{{ o['cfdi:Comprobante']['cfdi:Emisor']['cfdi:ExpedidoEn']['noInterior'] }}" pais="{{ o['cfdi:Comprobante']['cfdi:Emisor']['cfdi:ExpedidoEn']['pais'] }}"/><cfdi:RegimenFiscal Regimen="{{ o['cfdi:Comprobante']['cfdi:Emisor']['cfdi:RegimenFiscal']['Regimen'] }}"/></cfdi:Emisor><cfdi:Receptor nombre="{{ o['cfdi:Comprobante']['cfdi:Receptor']['nombre'] }}" rfc="{{ o['cfdi:Comprobante']['cfdi:Receptor']['rfc'] }}"><cfdi:Domicilio calle="{{ o['cfdi:Comprobante']['cfdi:Receptor']['cfdi:Domicilio']['calle'] }}" codigoPostal="{{ o['cfdi:Comprobante']['cfdi:Receptor']['cfdi:Domicilio']['codigoPostal'] }}" colonia="{{ o['cfdi:Comprobante']['cfdi:Receptor']['cfdi:Domicilio']['colonia'] }}" estado="{{ o['cfdi:Comprobante']['cfdi:Receptor']['cfdi:Domicilio']['estado'] }}" localidad="{{ o['cfdi:Comprobante']['cfdi:Receptor']['cfdi:Domicilio']['localidad'] }}" municipio="{{ o['cfdi:Comprobante']['cfdi:Receptor']['cfdi:Domicilio']['municipio'] }}" noExterior="{{ o['cfdi:Comprobante']['cfdi:Receptor']['cfdi:Domicilio']['noExterior'] }}" noInterior="{{ o['cfdi:Comprobante']['cfdi:Receptor']['cfdi:Domicilio']['noInterior'] }}" pais="{{ o['cfdi:Comprobante']['cfdi:Receptor']['cfdi:Domicilio']['pais'] }}"/></cfdi:Receptor>{% if o['cfdi:Comprobante']['cfdi:Conceptos']%}<cfdi:Conceptos>{% for i in o['cfdi:Comprobante']['cfdi:Conceptos'] %}<cfdi:Concepto cantidad="{{ i['cfdi:Concepto']['cantidad'] }}" descripcion="{{ i['cfdi:Concepto']['descripcion'] }}" importe="{{ i['cfdi:Concepto']['importe'] }}" noIdentificacion="{{ i['cfdi:Concepto']['noIdentificacion'] }}" unidad="{{ i['cfdi:Concepto']['unidad'] }}" valorUnitario="{{ i['cfdi:Concepto']['valorUnitario'] }}"/>{% endfor %}{% endif %}</cfdi:Conceptos>{% if o['cfdi:Comprobante']['cfdi:Impuestos']['totalImpuestosTrasladados'] %}<cfdi:Impuestos totalImpuestosTrasladados="{{ o['cfdi:Comprobante']['cfdi:Impuestos']['totalImpuestosTrasladados'] }}"><cfdi:Traslados>{% for i in o['cfdi:Comprobante']['cfdi:Impuestos']['cfdi:Traslados'] %}<cfdi:Traslado importe="{{ i['cfdi:Traslado']['importe'] }}" impuesto="{{ i['cfdi:Traslado']['impuesto'] }}" tasa="{{ i['cfdi:Traslado']['tasa'] }}"/>{% endfor %}</cfdi:Traslados></cfdi:Impuestos>{% endif %}</cfdi:Comprobante> |
815 | \ No newline at end of file |
Merged to Trunk