~openerp-spain-team/openerp-spain/6.0-git

« back to all changes in this revision

Viewing changes to l10n_es_extras/l10n_ES_aeat_mod347/wizard/wizard_export_boe.py

  • Committer: Borja L.S.
  • Date: 2010-10-18 10:04:25 UTC
  • Revision ID: git-v1:271c47a993616dbba60585d48b8b98d603199d93
[REF] *: Refactorización para portar a 6.0 - Paso 1.

- Se han renombrado los módulos para usar la nomenclatura propuesta
  por OpenERP: l10n_es para el módulo base de localización (plan de 
  cuentas), l10n_es_* para el resto de módulos.

- Se eliminan los módulos extra_addons/* que deberían moverse a 
  los extra-addons genéricos (no son específicos de España).

- Se renombran los __terp__.py por __openerp__.py

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: utf-8 -*-
2
 
# -*- encoding: utf-8 -*-
3
 
##############################################################################
4
 
#
5
 
#    OpenERP - Export format BOE model 347 engine
6
 
#    Copyright (C) 2009 Asr Oss. All Rights Reserved
7
 
#    $Id$
8
 
#
9
 
#    This program is free software: you can redistribute it and/or modify
10
 
#    it under the terms of the GNU 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 General Public License for more details.
18
 
#
19
 
#    You should have received a copy of the GNU General Public License
20
 
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 
#
22
 
##############################################################################
23
 
 
24
 
"""
25
 
Export format BOE model 347 engine wizards
26
 
"""
27
 
__author__ = """Alejandro Sanchez Ramirez Asr Oss - alejandro@asr-oss.com
28
 
                Borja López Soilán (Pexego) - borjals@pexego.es"""
29
 
 
30
 
 
31
 
from tools.translate import _
32
 
import wizard
33
 
import pooler
34
 
import base64
35
 
import time
36
 
 
37
 
 
38
 
############################################################################
39
 
# Helper functions
40
 
############################################################################
41
 
 
42
 
def _formatString(text, length, fill=' ', align='<'):
43
 
    """
44
 
    Formats the string into a fixed length ASCII (iso-8859-1) record.
45
 
 
46
 
    Note:
47
 
        'Todos los campos alfanuméricos y alfabéticos se presentarán alineados a la izquierda y
48
 
        rellenos de blancos por la derecha, en mayúsculas sin caracteres especiales, y sin vocales acentuadas.
49
 
        Para los caracteres específicos del idioma se utilizará la codificación ISO-8859-1. De esta
50
 
        forma la letra “Ñ” tendrá el valor ASCII 209 (Hex. D1) y la “Ç”(cedilla mayúscula) el valor ASCII
51
 
        199 (Hex. C7).'
52
 
        (http://www.boe.es/boe/dias/2008/10/23/pdfs/A42154-42190.pdf)
53
 
    """
54
 
    #
55
 
    # Turn text (probably unicode) into an ASCII (iso-8859-1) string
56
 
    #
57
 
    if isinstance(text, (unicode)):
58
 
        ascii_string = text.encode('iso-8859-1', 'ignore')
59
 
    else:
60
 
        ascii_string = str(text or '')
61
 
    # Cut the string if it is too long
62
 
    if len(ascii_string) > length:
63
 
        ascii_string = ascii_string[:length]
64
 
    # Format the string
65
 
    #ascii_string = '{0:{1}{2}{3}s}'.format(ascii_string, fill, align, length) #for python >= 2.6
66
 
    if align == '<':
67
 
        ascii_string = str(ascii_string) + (length-len(str(ascii_string)))*fill
68
 
    elif align == '>':
69
 
        ascii_string = (length-len(str(ascii_string)))*fill + str(ascii_string)
70
 
    else:
71
 
        assert False, _('Wrong aling option. It should be < or >')
72
 
    # Turn into uppercase
73
 
    ascii_string = ascii_string.upper()
74
 
    #
75
 
    # Replace accents
76
 
    #
77
 
    replacements = [('Á', 'A'), ('É', 'E'), ('Í', 'I'), ('Ó', 'O'), ('Ú', 'U')]
78
 
    for orig, repl in replacements:
79
 
        ascii_string.replace(orig, repl)
80
 
    # Sanity-check
81
 
    assert len(ascii_string) == length, \
82
 
                        _("The formated string must match the given length")
83
 
    # Return string
84
 
    return ascii_string
85
 
 
86
 
def _formatNumber(number, int_length, dec_length=0, include_sign=False):
87
 
    """
88
 
    Formats the number into a fixed length ASCII (iso-8859-1) record.
89
 
    Note:
90
 
        'Todos los campos numéricos se presentarán alineados a la derecha
91
 
        y rellenos a ceros por la izquierda sin signos y sin empaquetar.'
92
 
        (http://www.boe.es/boe/dias/2008/10/23/pdfs/A42154-42190.pdf)
93
 
    """
94
 
    #
95
 
    # Separate the number parts (-55.23 => int_part=55, dec_part=0.23, sign='N')
96
 
    #
97
 
    if number == '':
98
 
        number = 0
99
 
    _number = float(number)
100
 
    int_part = int(_number)
101
 
    dec_part = int((_number % 1)*100)
102
 
    sign = _number > 0 and ' ' or 'N'
103
 
    #
104
 
    # Format the string
105
 
    #
106
 
    ascii_string = ''
107
 
    if include_sign:
108
 
        ascii_string += sign
109
 
    if int_length > 0:
110
 
        #ascii_string += '{0:0>{1}}'.format(int_part, int_length) #for python >= 2.6
111
 
        ascii_string += '%.*d' % (int_length, int_part)
112
 
    if dec_length > 0:
113
 
        #ascii_string += '{0:0<{1}}'.format(dec_part, dec_length) #for python >= 2.6
114
 
        ascii_string += str(dec_part)+(dec_length-len(str(dec_part)))*'0'
115
 
    # Sanity-check
116
 
    assert len(ascii_string) == (include_sign and 1 or 0) + int_length + dec_length, \
117
 
                        _("The formated string must match the given length")
118
 
    # Return the string
119
 
    return ascii_string
120
 
 
121
 
def _formatBoolean(value, yes='X', no=' '):
122
 
    """
123
 
    Formats a boolean value into a fixed length ASCII (iso-8859-1) record.
124
 
    """
125
 
    return value and yes or no
126
 
 
127
 
 
128
 
############################################################################
129
 
# Wizard
130
 
############################################################################
131
 
 
132
 
class wizard_export_boe(wizard.interface):
133
 
    """
134
 
    Wizard to export the 347 model report in BOE format.
135
 
    """
136
 
 
137
 
    ############################################################################
138
 
    # Forms
139
 
    ############################################################################
140
 
 
141
 
    _init_form = """<?xml version="1.0" encoding="utf-8"?>
142
 
    <form string="Export 347 in BOE format" colspan="4" width="400">
143
 
        <label string="This wizard will export the 347 report data to a BOE format file." colspan="4"/>
144
 
        <label string="" colspan="4"/>
145
 
        <label string="You may afterwards import this file into the AEAT help program." colspan="4"/>
146
 
    </form>"""
147
 
 
148
 
    _done_form = """<?xml version="1.0" encoding="utf-8"?>
149
 
    <form string="347 report exported in BOE format" colspan="4" width="400">
150
 
        <label string="The report file has been sucessfully generated." colspan="4"/>
151
 
        <label string="" colspan="4"/>
152
 
        <field name="file_name" nolabel="1"/>
153
 
        <field name="file" filename="file_name" nolabel="1"/>
154
 
        <label string="" colspan="4"/>
155
 
        <label string="You may now verify, print or upload the exported file using the AEAT help program available at:" colspan="4"/>
156
 
        <field name="aeat_program_download_url" widget="url" nolabel="1" colspan="4"/>
157
 
    </form>"""
158
 
 
159
 
    _done_fields = {
160
 
        'file' : { 'string': 'Exported file', 'type':'binary', 'readonly':True },
161
 
        'file_name': {'string': 'Exported file', 'type': 'char', 'size': 64, 'readonly':True},
162
 
        'aeat_program_download_url' : {'string': 'AEAT URL', 'type': 'char', 'size': 255 },
163
 
    }
164
 
 
165
 
    ############################################################################
166
 
    # Actions
167
 
    ############################################################################
168
 
 
169
 
    def _get_formated_declaration_record(self, report):
170
 
        """
171
 
        Returns a type 1, declaration/company, formated record.
172
 
 
173
 
        Format of the record:
174
 
            Tipo registro 1 – Registro de declarante:
175
 
            Posiciones  Descripción
176
 
            1           Tipo de Registro
177
 
            2-4         Modelo Declaración
178
 
            5-8         Ejercicio
179
 
            9-17        NIF del declarante
180
 
            18-57       Apellidos y nombre o razón social del declarante
181
 
            58          Tipo de soporte
182
 
            59-67       Teléfono contacto
183
 
            68-107      Apellidos y nombre contacto
184
 
            108-120     Número identificativo de la declaración
185
 
            121-122     Declaración complementaria o substitutiva
186
 
            123-135     Número identificativo de la declaración anterior
187
 
            136-144     Número total de personas y entidades
188
 
            145-159     Importe total de las operaciones
189
 
            160-168     Número total de inmuebles
190
 
            169-183     Importe total de las operaciones de arrendamiento
191
 
            184-390     Blancos
192
 
            391-399     NIF del representante legal
193
 
            400-487     Blancos
194
 
            488-500     Sello electrónico 
195
 
        """
196
 
        text = ''
197
 
 
198
 
        text += '1'                                           # Tipo de Registro
199
 
        text += '347'                                         # Modelo Declaración
200
 
        text += _formatString(report.fiscalyear_id.code, 4)   # Ejercicio
201
 
        text += _formatString(report.company_vat, 9)          # NIF del declarante
202
 
        text += _formatString(report.company_id.name, 40)     # Apellidos y nombre o razón social del declarante
203
 
        text += _formatString(report.support_type, 1)         # Tipo de soporte
204
 
        text += _formatString(report.contact_phone, 9)       # Persona de contacto (Teléfono)
205
 
        text += _formatString(report.contact_name, 40)        # Persona de contacto (Apellidos y nombre)
206
 
        text += _formatNumber(report.number, 13)              # Número identificativo de la declaración
207
 
        text += _formatString(report.type, 2)                 # Declaración complementaria o substitutiva
208
 
        text += _formatNumber(report.previous_number, 13)     # Número identificativo de la declaración anterior
209
 
        text += _formatNumber(report.total_partner_records, 9)          # Número total de personas y entidades
210
 
        text += _formatNumber(report.total_amount, 13, 2)               # Importe total de las operaciones
211
 
        text += _formatNumber(report.total_real_state_records, 9)       # Número total de inmuebles
212
 
        text += _formatNumber(report.total_real_state_amount, 13, 2)    # Importe total de las operaciones de arrendamiento
213
 
        text += 207*' '                                       # Blancos
214
 
        text += _formatString(report.representative_vat, 9)   # NIF del representante legal
215
 
        text += 88*' '                                        # Blancos
216
 
        text += 13*' '                                        # Sello electrónico 
217
 
        text += '\r\n'
218
 
        assert len(text) == 502, _("The type 1 record must be 502 characters long")
219
 
        return text
220
 
 
221
 
    def _get_formated_partner_record(self, report, partner_record):
222
 
        """
223
 
        Returns a type 2, partner, formated record
224
 
 
225
 
        Format of the record:
226
 
            Tipo de Registro 2 – Registro de declarado
227
 
            Posiciones  Descripción
228
 
            1           Tipo de Registro
229
 
            2-4         Modelo Declaración
230
 
            5-8         Ejercicio
231
 
            9-17        NIF del declarante
232
 
            18-26       NIF del declarado
233
 
            27-35       NIF del representante legal
234
 
            36-75       Apellidos y nombre, razón social o denominación del declarado
235
 
            76          Tipo de hoja
236
 
            77-80       Código provincia/país
237
 
            81          Blancos
238
 
            82          Clave de operación
239
 
            83-97       Importe de las operaciones
240
 
            98          Operación de seguro
241
 
            99          Arrendamiento local negocio
242
 
            100-114     Importe percibido en metálico
243
 
            115-129     Importe percibido por transmisiones de inmuebles sujetas a IVA
244
 
            130-500     Blancos
245
 
            488-500     Sello electrónico 
246
 
        """
247
 
        text = ''
248
 
 
249
 
        text += '2'                                                     # Tipo de Registro
250
 
        text += '347'                                                   # Modelo Declaración
251
 
        text += _formatString(report.fiscalyear_id.code, 4)             # Ejercicio
252
 
        text += _formatString(report.company_vat, 9)                    # NIF del declarante
253
 
        text += _formatString(partner_record.partner_vat, 9)            # NIF del declarado
254
 
        text += _formatString(partner_record.representative_vat, 9)     # NIF del representante legal
255
 
        text += _formatString(partner_record.partner_id.name, 40)       # Apellidos y nombre, razón social o denominación del declarado
256
 
        text += 'D'                                                     # Tipo de hoja: Constante ‘D’.
257
 
        text += _formatNumber(partner_record.partner_state_code, 2)     # Código provincia
258
 
        text += _formatString(partner_record.partner_country_code, 2)   # Código país
259
 
        text += ' '                                                     # Blancos
260
 
        text += _formatString(partner_record.operation_key, 1)          # Clave de operación
261
 
        text += _formatNumber(partner_record.amount, 13, 2)             # Importe de las operaciones
262
 
        text += _formatBoolean(partner_record.insurance_operation)                      # Operación de seguro
263
 
        text += _formatBoolean(partner_record.bussiness_real_state_rent)                # Arrendamiento local negocio
264
 
        text += _formatNumber(partner_record.cash_amount, 13, 2)                        # Importe percibido en metálico
265
 
        text += _formatNumber(partner_record.real_state_transmissions_amount, 13, 2)    # Importe percibido por transmisiones de inmuebles sujetas a IVA
266
 
        text += 371*' '                                                 # Blancos
267
 
        text += '\r\n'                                                  # Sello electrónico
268
 
 
269
 
        assert len(text) == 502, _("The type 2-D record (partner) must be 502 characters long")
270
 
        return text
271
 
 
272
 
    def _get_formated_real_state_record(self, report, partner_record):
273
 
        """
274
 
        Returns a type 2, real state, formated record
275
 
 
276
 
        Format of the record:
277
 
            Tipo de Registro 2 – Registro de inmueble
278
 
            Posiciones  Descripción
279
 
            1           Tipo de Registro
280
 
            2-4         Modelo Declaración
281
 
            5-8         Ejercicio
282
 
            9-17        NIF del declarante
283
 
            18-26       NIF del arrendatario
284
 
            27-35       NIF del representante legal
285
 
            36-75       Apellidos y nombre, razón social o denominación del declarado
286
 
            76          Tipo de hoja
287
 
            77-99       Blancos
288
 
            100-114     Importe de la operación
289
 
            115         Situación del inmueble
290
 
            116-140     Referencia catastral
291
 
            141-333     Dirección y datos del inmueble
292
 
                141–145 TIPO DE VÍA
293
 
                146–195 NOMBRE VÍA PUBLICA
294
 
                196–198 TIPO DE NUMERACIÓN
295
 
                199–203 NUMERO DE CASA
296
 
                204-206 CALIFICADOR DEL NUMERO
297
 
                207–209 BLOQUE
298
 
                210–212 PORTAL
299
 
                213–215 ESCALERA
300
 
                216–218 PLANTA O PISO
301
 
                219–221 PUERTA
302
 
                222–261 COMPLEMENTO.
303
 
                262–291 LOCALIDAD O POBLACIÓN.
304
 
                292–321 MUNICIPIO
305
 
                322–326 CODIGO DE MUNICIPIO
306
 
                327-328 CODIGO PROVINCIA
307
 
                329-333 CODIGO POSTAL
308
 
            334-500     Blancos 
309
 
        """
310
 
        text = ''
311
 
 
312
 
        text += '2'                                                     # Tipo de Registro
313
 
        text += '347'                                                   # Modelo Declaración
314
 
        text += _formatNumber(report.fiscalyear_id.code, 4)             # Ejercicio
315
 
        text += _formatString(report.company_vat, 9)                    # NIF del declarante
316
 
        text += _formatString(partner_record.partner_vat, 9)            # NIF del declarado
317
 
        text += _formatString(partner_record.representative_vat, 9)     # NIF del representante legal
318
 
        text += _formatString(partner_record.partner_id.name, 40)       # Apellidos y nombre, razón social o denominación del declarado
319
 
        text += 'I'                                                     # Tipo de hoja: Constante ‘I’.
320
 
        text += 23*''                                                   # Blancos
321
 
        text += _formatNumber(partner_record.real_state_amount, 13, 2)  # Importe de las operaciones
322
 
        text += _formatNumber(partner_record.real_state_situation, 1)   # Situación del inmueble
323
 
        text += _formatString(partner_record.real_state_reference, 25)  # Referencia catastral
324
 
        text += _formatString(partner_record.real_state_address_type, 5)        # TIPO DE VÍA
325
 
        text += _formatString(partner_record.real_state_address, 50)            # NOMBRE VÍA PUBLICA
326
 
        text += _formatString(partner_record.real_state_number_type, 3)         # TIPO DE NUMERACIÓN
327
 
        text += _formatString(partner_record.real_state_number, 5)              # NUMERO DE CASA
328
 
        text += _formatString(partner_record.real_state_number_calification, 3) # CALIFICADOR DEL NUMERO
329
 
        text += _formatString(partner_record.real_state_block, 3)               # BLOQUE
330
 
        text += _formatString(partner_record.real_state_portal, 3)              # PORTAL
331
 
        text += _formatString(partner_record.real_state_stairway, 3)            # ESCALERA
332
 
        text += _formatString(partner_record.real_state_floor, 3)               # PLANTA O PISO
333
 
        text += _formatString(partner_record.real_state_door, 3)                # PUERTA
334
 
        text += _formatString(partner_record.real_state_complement, 40)         # COMPLEMENTO
335
 
        text += _formatString(partner_record.real_state_city, 30)               # LOCALIDAD O POBLACIÓN
336
 
        text += _formatString(partner_record.real_state_township, 30)           # MUNICIPIO
337
 
        text += _formatString(partner_record.real_state_township_code, 5)       # CODIGO DE MUNICIPIO
338
 
        text += _formatString(partner_record.real_state_state_code, 2)          # CODIGO PROVINCIA
339
 
        text += _formatString(partner_record.real_state_postal_code, 5)         # CODIGO POSTAL
340
 
        text += 167*' '                                                 # Blancos
341
 
        text += '\r\n'                                                  # Sello electrónico
342
 
 
343
 
        assert len(text) == 502, _("The type 2-I record (real state) must be 502 characters long")
344
 
        return text
345
 
    
346
 
 
347
 
    def _export_boe_file(self, cr, uid, data, context):
348
 
        """
349
 
        Action that exports the data into a BOE formated text file.
350
 
        """
351
 
 
352
 
        pool = pooler.get_pool(cr.dbname)
353
 
        report = pool.get('l10n.es.aeat.mod347.report').browse(cr, uid, data['id'], context=context)
354
 
 
355
 
        file_contents = ''
356
 
 
357
 
        # Add the header record
358
 
        file_contents += self._get_formated_declaration_record(report)
359
 
 
360
 
        #
361
 
        # Add the partner records
362
 
        #
363
 
        for partner_record in report.partner_record_ids:
364
 
            file_contents += self._get_formated_partner_record(report, partner_record)
365
 
 
366
 
        #
367
 
        # Add the real state records
368
 
        #
369
 
        for real_state_record in report.real_state_record_ids:
370
 
            file_contents += self._get_formated_real_state_record(report, real_state_record)
371
 
 
372
 
        #
373
 
        # Generate the file and save as attachment
374
 
        #
375
 
        file = base64.encodestring(file_contents)
376
 
        file_name = _('347_report_%s.txt') %  time.strftime(_('%Y-%m-%d'))
377
 
        pool.get('ir.attachment').create(cr, uid, {
378
 
            'name': _('347 report %s') %  time.strftime(_('%Y-%m-%d')),
379
 
            'datas': file,
380
 
            'datas_fname': file_name,
381
 
            'res_model': 'l10n.es.aeat.mod347.report',
382
 
            'res_id': data['id'],
383
 
            }, context=context)
384
 
 
385
 
        #
386
 
        # Return the data
387
 
        #
388
 
        return {
389
 
            'file': file,
390
 
            'file_name': file_name,
391
 
            'aeat_program_download_url': "http://www.aeat.es/wps/portal/ProgramaAyuda?channel=e5b22fc8ebd4f010VgnVCM1000004ef01e0a____&ver=L&site=56d8237c0bc1ff00VgnVCM100000d7005a80____"
392
 
        }
393
 
 
394
 
    ############################################################################
395
 
    # States
396
 
    ############################################################################
397
 
 
398
 
    states = {
399
 
        'init': {
400
 
            'actions': [],
401
 
            'result': {'type':'form', 'arch': _init_form, 'fields': {}, 'state':[('end', 'Cancel', 'gtk-cancel', True), ('export', 'Export', 'gtk-apply', True)]}
402
 
        },
403
 
        'export': {
404
 
            'actions': [_export_boe_file],
405
 
            'result': {'type': 'form', 'arch': _done_form, 'fields': _done_fields, 'state':[('end','Done', 'gtk-ok', True)]}
406
 
        }
407
 
    }
408
 
 
409
 
wizard_export_boe('l10n_es_aeat_mod347.wizard_export_boe')
410