28
28
from osv import osv, fields
29
29
from tools.translate import _
30
30
from report import report_sxw
32
_logger = logging.getLogger(__name__)
32
34
class partner_vat_intra(osv.osv_memory):
36
_name = "partner.vat.intra"
35
""" VAT Intracom declaration
37
_name = 'partner.vat.intra'
37
38
_description = 'Partner VAT Intra'
39
def _get_xml_data(self, cr, uid, context=None):
40
if context.get('file_save', False):
41
return base64.encodestring(context['file_save'].encode('utf8'))
44
def _get_europe_country(self, cursor, user, context=None):
45
return self.pool.get('res.country').search(cursor, user, [('code', 'in', ['AT', 'BG', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'GB'])])
40
def _get_period(self, cr, uid, context=None):
41
domain = [('special', '=', False), ('date_stop', '<', time.strftime('%Y-%m-%d'))]
42
result = self.pool.get('account.period').search(cr, uid, domain)
43
return result and result[-1:] or False
45
def _get_europe_country(self, cr, uid, context=None):
46
return self.pool.get('res.country').search(cr, uid, [('code', 'in', ['AT', 'BG', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'GB'])])
48
def _get_tax_code(self, cr, uid, context=None):
49
obj_tax_code = self.pool.get('account.tax.code')
50
obj_user = self.pool.get('res.users')
51
company_id = obj_user.browse(cr, uid, uid, context=context).company_id.id
52
tax_code_ids = obj_tax_code.search(cr, uid, [('company_id', '=', company_id), ('parent_id', '=', False)], context=context)
53
return tax_code_ids and tax_code_ids[0] or False
48
56
'name': fields.char('File Name', size=32),
49
'period_code': fields.char('Period Code',size = 6,required = True, help = '''This is where you have to set the period code for the intracom declaration using the format: ppyyyy
57
'file_save' : fields.binary('Save File', readonly=True),
58
'period_ids': fields.many2many('account.period', 'vat_intra_period_rel', 'acc_id', 'period_id', 'Period (s)', required=True,
59
help='Select here the period(s) you want to include in your Intracom declaration'),
60
'period_code': fields.char('Period Code',size = 6,
61
help = """This field allows you to override the period code for the Intracom declaration.
50
63
PP can stand for a month: from '01' to '12'.
51
64
PP can stand for a trimester: '31','32','33','34'
52
65
The first figure means that it is a trimester,
53
66
The second figure identify the trimester.
54
67
PP can stand for a complete fiscal year: '00'.
55
68
YYYY stands for the year (4 positions).
58
'period_ids': fields.many2many('account.period', 'account_period_rel', 'acc_id', 'period_id', 'Period (s)', help = 'Select here the period(s) you want to include in your intracom declaration'),
59
72
'tax_code_id': fields.many2one('account.tax.code', 'Company', domain=[('parent_id', '=', False)], help="Keep empty to use the user's company", required=True),
60
'test_xml': fields.boolean('Test XML file', help="Sets the XML output as test file"),
61
'mand_id' : fields.char('Reference', size=14, help="Reference given by the Representative of the sending company."),
62
'msg': fields.text('File created', size=14, readonly=True),
63
'no_vat': fields.text('Partner With No VAT', size=14, readonly=True, help="The Partner whose VAT number is not defined and they are not included in XML File."),
64
'file_save' : fields.binary('Save File', readonly=True),
65
73
'country_ids': fields.many2many('res.country', 'vat_country_rel', 'vat_id', 'country_id', 'European Countries'),
66
74
'comments': fields.text('Comments'),
69
def _get_tax_code(self, cr, uid, context=None):
70
obj_tax_code = self.pool.get('account.tax.code')
71
obj_user = self.pool.get('res.users')
72
company_id = obj_user.browse(cr, uid, uid, context=context).company_id.id
73
tax_code_ids = obj_tax_code.search(cr, uid, [('company_id', '=', company_id), ('parent_id', '=', False)], context=context)
74
return tax_code_ids and tax_code_ids[0] or False
78
'period_ids': _get_period,
77
79
'country_ids': _get_europe_country,
78
'file_save': _get_xml_data,
79
'name': 'vat_intra.xml',
80
80
'tax_code_id': _get_tax_code,
83
83
def _get_datas(self, cr, uid, ids, context=None):
84
"""Collects require data for vat intra xml
84
"""Collects required data for vat intra xml
85
85
:param ids: id of wizard.
86
86
:return: dict of all data to be used to generate xml for Partner VAT Intra.
147
147
raise osv.except_osv(_('Insufficient Data!'),_('No email address associated with the company.'))
149
149
raise osv.except_osv(_('Insufficient Data!'),_('No phone associated with the company.'))
151
account_periods = wiz_data.period_ids
153
period_end_dates = sorted([x.date_stop for x in account_periods])
154
period_start_dates = sorted([x.date_start for x in account_periods])
156
starting_month = period_start_dates[0][5:7]
157
ending_month = period_end_dates[-1][5:7]
158
year = period_end_dates[-1][:4]
159
quarter = str(((int(starting_month) - 1) / 3) + 1)
151
'company_name': data_company.name,
152
'company_vat': company_vat,
153
'vatnum': company_vat[2:],
154
'mand_id': wiz_data.mand_id,
155
'sender_date': str(time.strftime('%Y-%m-%d')),
158
'post_code': post_code,
161
'phone': phone.replace('/','').replace('.','').replace('(','').replace(')','').replace(' ',''),
162
'period': wiz_data.period_code,
164
'comments': comments,
165
'issued_by': issued_by,
162
'company_name': data_company.name,
163
'company_vat': company_vat,
164
'vatnum': company_vat[2:],
165
#'mand_id': wiz_data.mand_id, # dropped since also not supported in periodical VAT declaration
166
'sender_date': str(time.strftime('%Y-%m-%d')),
169
'post_code': post_code,
172
'phone': phone.replace('/','').replace('.','').replace('(','').replace(')','').replace(' ',''),
173
'period_code': wiz_data.period_code,
175
'starting_month': starting_month,
176
'ending_month': ending_month,
179
'comments': comments,
180
'issued_by': issued_by,
168
183
codes = ('44', '46L', '46T', '48s44', '48s46L', '48s46T')
169
cr.execute('''SELECT p.name As partner_name, l.partner_id AS partner_id, p.vat AS vat,
184
cr.execute('''SELECT p.name AS partner_name, l.partner_id AS partner_id, p.vat AS vat,
170
185
(CASE WHEN t.code = '48s44' THEN '44'
171
186
WHEN t.code = '48s46L' THEN '46L'
172
187
WHEN t.code = '48s46T' THEN '46T'
173
188
ELSE t.code END) AS intra_code,
174
SUM(CASE WHEN t.code in ('48s44','48s46L','48s46T') THEN -l.tax_amount ELSE l.tax_amount END) AS amount
189
SUM(CASE WHEN t.code IN ('48s44','48s46L','48s46T') THEN -l.tax_amount ELSE l.tax_amount END) AS amount
175
190
FROM account_move_line l
176
191
LEFT JOIN account_tax_code t ON (l.tax_code_id = t.id)
177
192
LEFT JOIN res_partner p ON (l.partner_id = p.id)
178
193
WHERE t.code IN %s
179
194
AND l.period_id IN %s
180
195
AND t.company_id = %s
181
GROUP BY p.name, l.partner_id, p.vat, intra_code''', (codes, tuple([p.id for p in wiz_data.period_ids]), data_company.id))
196
GROUP BY p.name, l.partner_id, p.vat, intra_code''',
197
(codes, tuple([p.id for p in wiz_data.period_ids]), data_company.id))
199
rows = cr.dictfetchall()
201
raise osv.except_osv(_('No Data Available'), _('No intracom transactions found for the selected period(s) !'))
185
for row in cr.dictfetchall():
186
205
if not row['vat']:
194
213
intra_code = row['intra_code'] == '44' and 'S' or (row['intra_code'] == '46L' and 'L' or (row['intra_code'] == '46T' and 'T' or ''))
196
215
xmldict['clientlist'].append({
197
'partner_name': row['partner_name'],
199
'vatnum': row['vat'][2:].replace(' ','').upper(),
201
'country': row['vat'][:2].upper(),
203
'intra_code': row['intra_code'],
216
'partner_name': row['partner_name'],
218
'vatnum': row['vat'][2:].replace(' ','').upper(),
220
'country': row['vat'][:2].upper(),
222
'amount': '%.2f' %amt, # used in xml
223
'amt': amt, # used in pdf
224
'intra_code': row['intra_code'],
206
xmldict.update({'dnum': dnum, 'clientnbr': str(seq), 'amountsum': amount_sum, 'partner_wo_vat': p_count})
229
'clientnbr': str(seq),
230
'amountsum': '%.2f' %amount_sum, # used in xml
231
'amtsum': amount_sum, # used in pdf
232
'partner_wo_vat': p_count})
209
def create_xml(self, cursor, user, ids, context=None):
235
def create_xml(self, cr, uid, ids, context=None):
210
236
"""Creates xml that is to be exported and sent to estate for partner vat intra.
211
237
:return: Value for next action.
214
240
mod_obj = self.pool.get('ir.model.data')
215
xml_data = self._get_datas(cursor, user, ids, context=context)
216
month_quarter = xml_data['period'][:2]
217
year = xml_data['period'][2:]
241
xml_data = self._get_datas(cr, uid, ids, context=context)
220
244
# Can't we do this by etree?
230
254
<EmailAddress>%(email)s</EmailAddress>
231
255
<Phone>%(phone)s</Phone>
232
256
</ns2:Representative>""" % (xml_data)
233
if xml_data['mand_id']:
234
data_head += '\n\t\t<ns2:RepresentativeReference>%(mand_id)s</ns2:RepresentativeReference>' % (xml_data)
257
#if xml_data['mand_id']:
258
# data_head += '\n\t\t<ns2:RepresentativeReference>%(mand_id)s</ns2:RepresentativeReference>' % (xml_data)
235
259
data_comp_period = '\n\t\t<ns2:Declarant>\n\t\t\t<VATNumber>%(vatnum)s</VATNumber>\n\t\t\t<Name>%(company_name)s</Name>\n\t\t\t<Street>%(street)s</Street>\n\t\t\t<PostCode>%(post_code)s</PostCode>\n\t\t\t<City>%(city)s</City>\n\t\t\t<CountryCode>%(country)s</CountryCode>\n\t\t\t<EmailAddress>%(email)s</EmailAddress>\n\t\t\t<Phone>%(phone)s</Phone>\n\t\t</ns2:Declarant>' % (xml_data)
236
if month_quarter.startswith('3'):
237
data_comp_period += '\n\t\t<ns2:Period>\n\t\t\t<ns2:Quarter>'+month_quarter[1]+'</ns2:Quarter> \n\t\t\t<ns2:Year>'+year+'</ns2:Year>\n\t\t</ns2:Period>'
238
elif month_quarter.startswith('0') and month_quarter.endswith('0'):
239
data_comp_period+= '\n\t\t<ns2:Period>\n\t\t\t<ns2:Year>'+year+'</ns2:Year>\n\t\t</ns2:Period>'
261
if xml_data['period_code']:
262
month_quarter = xml_data['period_code'][:2]
263
year = xml_data['period_code'][2:]
264
if month_quarter.startswith('3'):
265
data_comp_period += '\n\t\t<ns2:Period>\n\t\t\t<ns2:Quarter>'+month_quarter[1]+'</ns2:Quarter> \n\t\t\t<ns2:Year>'+year+'</ns2:Year>\n\t\t</ns2:Period>'
266
elif month_quarter.startswith('0') and month_quarter.endswith('0'):
267
data_comp_period += '\n\t\t<ns2:Period>\n\t\t\t<ns2:Year>'+year+'</ns2:Year>\n\t\t</ns2:Period>'
269
data_comp_period += '\n\t\t<ns2:Period>\n\t\t\t<ns2:Month>'+month_quarter+'</ns2:Month> \n\t\t\t<ns2:Year>'+year+'</ns2:Year>\n\t\t</ns2:Period>'
241
data_comp_period += '\n\t\t<ns2:Period>\n\t\t\t<ns2:Month>'+month_quarter+'</ns2:Month> \n\t\t\t<ns2:Year>'+year+'</ns2:Year>\n\t\t</ns2:Period>'
271
year = xml_data['year']
272
if xml_data['starting_month'] != xml_data['ending_month']:
273
month_quarter = '3' + xml_data['quarter']
274
#starting month and ending month of selected period are not the same
275
#it means that the accounting is not based on periods of 1 month but on quarters
276
data_comp_period += '\n\t\t<ns2:Period>\n\t\t\t<ns2:Quarter>%(quarter)s</ns2:Quarter> \n\t\t\t<ns2:Year>%(year)s</ns2:Year>\n\t\t</ns2:Period>' % (xml_data)
278
month_quarter = xml_data['ending_month']
279
data_comp_period += '\n\t\t<ns2:Period>\n\t\t\t<ns2:Month>'+xml_data['ending_month']+'</ns2:Month> \n\t\t\t<ns2:Year>%(year)s</ns2:Year>\n\t\t</ns2:Period>' % (xml_data)
243
281
data_clientinfo = ''
244
282
for client in xml_data['clientlist']:
249
287
data_decl = '\n\t<ns2:IntraListing SequenceNumber="1" ClientsNbr="%(clientnbr)s" DeclarantReference="%(dnum)s" AmountSum="%(amountsum)s">' % (xml_data)
251
data_file += data_head + data_decl + data_comp_period + data_clientinfo + '\n\t\t<ns2:Comment>%(comments)s</ns2:Comment>\n\t</ns2:IntraListing>\n</ns2:IntraConsignment>' % (xml_data)
252
context['file_save'] = data_file
254
model_data_ids = mod_obj.search(cursor, user,[('model','=','ir.ui.view'),('name','=','view_vat_intra_save')], context=context)
255
resource_id = mod_obj.read(cursor, user, model_data_ids, fields=['res_id'], context=context)[0]['res_id']
289
data_file += data_head + data_decl + data_comp_period + data_clientinfo
290
if xml_data['comments']:
291
data_file += '\n\t\t<ns2:Comment>%(comments)s</ns2:Comment>' % (xml_data)
292
data_file += '\n\t</ns2:IntraListing>\n</ns2:IntraConsignment>'
294
self.write(cr, uid, ids, {
295
'file_save': base64.encodestring(data_file.encode('utf8')),
296
'name': 'vat_intra_%s_%s.xml' %(year, month_quarter[0] == '3' and ('Q' + month_quarter[1]) or month_quarter),
299
model_data_ids = mod_obj.search(cr, uid,[('model','=','ir.ui.view'),('name','=','view_vat_intra_save')], context=context)
300
resource_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id']
258
303
'name': _('Save'),
259
304
'context': context,
260
305
'view_type': 'form',
261
306
'view_mode': 'form',
262
308
'res_model': 'partner.vat.intra',
263
309
'views': [(resource_id,'form')],
264
310
'view_id': 'view_vat_intra_save',