38
38
class txt_iva(osv.osv):
40
40
_inherit = ['mail.thread']
42
def _get_amount_total(self,cr,uid,ids,name,args,context=None):
42
def _get_amount_total(self, cr, uid, ids, name, args, context=None):
43
43
""" Return total amount withheld of each selected bill
45
45
context = context or {}
47
for txt in self.browse(cr,uid,ids,context):
47
for txt in self.browse(cr, uid, ids, context):
49
49
for txt_line in txt.txt_ids:
50
if txt_line.invoice_id.type in ['out_refund','in_refund']:
50
if txt_line.invoice_id.type in ['out_refund', 'in_refund']:
51
51
res[txt.id] -= txt_line.amount_withheld
53
53
res[txt.id] += txt_line.amount_withheld
56
def _get_amount_total_base(self,cr,uid,ids,name,args,context=None):
56
def _get_amount_total_base(self, cr, uid, ids, name, args, context=None):
57
57
""" Return total amount base of each selected bill
59
59
context = context or {}
61
for txt in self.browse(cr,uid,ids,context):
61
for txt in self.browse(cr, uid, ids, context):
63
63
for txt_line in txt.txt_ids:
64
if txt_line.invoice_id.type in ['out_refund','in_refund']:
64
if txt_line.invoice_id.type in ['out_refund', 'in_refund']:
65
65
res[txt.id] -= txt_line.untaxed
67
67
res[txt.id] += txt_line.untaxed
71
'name':fields.char('Description',128, required=True, select=True, help = "Description about statement of withholding income"),
72
'company_id': fields.many2one('res.company', 'Company', required=True, readonly=True,states={'draft':[('readonly',False)]}, help='Company'),
71
'name': fields.char('Description', 128, required=True, select=True, help="Description about statement of withholding income"),
72
'company_id': fields.many2one('res.company', 'Company', required=True, readonly=True, states={'draft': [('readonly', False)]}, help='Company'),
73
73
'state': fields.selection([
75
75
('confirmed', 'Confirmed'),
77
('cancel','Cancelled')
78
],'Estado', select=True, readonly=True, help="proof status"),
79
'period_id':fields.many2one('account.period','Period',required=True,readonly=True,states={'draft':[('readonly',False)]}, help='fiscal period' ),
80
'type':fields.boolean('Retention Suppliers?',required=True,states={'draft':[('readonly',False)]}, help="Select the type of retention to make"),
81
'date_start': fields.date('Begin Date',required=True,states={'draft':[('readonly',False)]}, help="Begin date of period"),
82
'date_end': fields.date('End date', required=True,states={'draft':[('readonly',False)]}, help="End date of period"),
83
'txt_ids':fields.one2many('txt.iva.line','txt_id', readonly=True,states={'draft':[('readonly',False)]}, help='Txt field lines of ar required by SENIAT for VAT withholding'),
84
'amount_total_ret':fields.function(_get_amount_total,method=True, digits=(16, 2), readonly=True, string='Withholding total amount', help="Monto Total Retenido"),
85
'amount_total_base':fields.function(_get_amount_total_base,method=True, digits=(16, 2), readonly=True, string='Taxable total amount', help="Total de la Base Imponible"),
77
('cancel', 'Cancelled')
78
], 'Estado', select=True, readonly=True, help="proof status"),
79
'period_id': fields.many2one('account.period', 'Period', required=True, readonly=True, states={'draft': [('readonly', False)]}, help='fiscal period'),
80
'type': fields.boolean('Retention Suppliers?', required=True, states={'draft': [('readonly', False)]}, help="Select the type of retention to make"),
81
'date_start': fields.date('Begin Date', required=True, states={'draft': [('readonly', False)]}, help="Begin date of period"),
82
'date_end': fields.date('End date', required=True, states={'draft': [('readonly', False)]}, help="End date of period"),
83
'txt_ids': fields.one2many('txt.iva.line', 'txt_id', readonly=True, states={'draft': [('readonly', False)]}, help='Txt field lines of ar required by SENIAT for VAT withholding'),
84
'amount_total_ret': fields.function(_get_amount_total, method=True, digits=(16, 2), readonly=True, string='Withholding total amount', help="Monto Total Retenido"),
85
'amount_total_base': fields.function(_get_amount_total_base, method=True, digits=(16, 2), readonly=True, string='Taxable total amount', help="Total de la Base Imponible"),
88
88
'state': lambda *a: 'draft',
89
'company_id': lambda self, cr, uid, context: \
90
self.pool.get('res.users').browse(cr, uid, uid,
89
'company_id': lambda self, cr, uid, context:
90
self.pool.get('res.users').browse(cr, uid, uid,
91
91
context=context).company_id.id,
92
'type': lambda *a:True,
93
'period_id': lambda self,cr,uid,context: self.period_return(cr,uid,context),
94
'name':lambda self,cr,uid,context : 'Withholding Vat '+time.strftime('%m/%Y')
92
'type': lambda *a: True,
93
'period_id': lambda self, cr, uid, context: self.period_return(cr, uid, context),
94
'name': lambda self, cr, uid, context: 'Withholding Vat ' + time.strftime('%m/%Y')
97
def period_return(self,cr,uid,context=None):
97
def period_return(self, cr, uid, context=None):
98
98
""" Return current period
100
100
context = context or {}
101
101
period_obj = self.pool.get('account.period')
102
102
fecha = time.strftime('%m/%Y')
103
period_id = period_obj.search(cr,uid,[('code','=',fecha)])
103
period_id = period_obj.search(cr, uid, [('code', '=', fecha)])
105
105
return period_id[0]
138
138
context = context or {}
139
139
self.check_txt_ids(cr, uid, ids, context=context)
140
return self.write(cr, uid, ids, {'state':'confirmed'})
140
return self.write(cr, uid, ids, {'state': 'confirmed'})
142
def action_generate_lines_txt(self,cr,uid,ids,context=None):
142
def action_generate_lines_txt(self, cr, uid, ids, context=None):
143
143
""" Current lines are cleaned and rebuilt
145
145
context = context or {}
146
146
rp_obj = self.pool.get('res.partner')
147
147
voucher_obj = self.pool.get('account.wh.iva')
148
148
txt_iva_obj = self.pool.get('txt.iva.line')
150
txt_brw= self.browse(cr,uid,ids[0])
151
txt_ids = txt_iva_obj.search(cr,uid,[('txt_id','=',txt_brw.id)])
150
txt_brw = self.browse(cr, uid, ids[0])
151
txt_ids = txt_iva_obj.search(cr, uid, [('txt_id', '=', txt_brw.id)])
153
txt_iva_obj.unlink(cr,uid,txt_ids)
153
txt_iva_obj.unlink(cr, uid, txt_ids)
156
voucher_ids = voucher_obj.search(cr,uid,[('date_ret','>=',txt_brw.date_start),('date_ret','<=',txt_brw.date_end),('period_id','=',txt_brw.period_id.id),('state','=','done'),('type','in',['in_invoice','in_refund'])])
156
voucher_ids = voucher_obj.search(cr, uid, [('date_ret', '>=', txt_brw.date_start), ('date_ret', '<=', txt_brw.date_end), ('period_id', '=', txt_brw.period_id.id), ('state', '=', 'done'), ('type', 'in', ['in_invoice', 'in_refund'])])
158
voucher_ids = voucher_obj.search(cr,uid,[('date_ret','>=',txt_brw.date_start),('date_ret','<=',txt_brw.date_end),('period_id','=',txt_brw.period_id.id),('state','=','done'),('type','in',['out_invoice','out_refund'])])
158
voucher_ids = voucher_obj.search(cr, uid, [('date_ret', '>=', txt_brw.date_start), ('date_ret', '<=', txt_brw.date_end), ('period_id', '=', txt_brw.period_id.id), ('state', '=', 'done'), ('type', 'in', ['out_invoice', 'out_refund'])])
160
for voucher in voucher_obj.browse(cr,uid,voucher_ids):
160
for voucher in voucher_obj.browse(cr, uid, voucher_ids):
161
161
acc_part_id = rp_obj._find_accounting_partner(voucher.partner_id)
162
162
for voucher_lines in voucher.wh_lines:
163
if voucher_lines.invoice_id.state not in ['open','paid']:
163
if voucher_lines.invoice_id.state not in ['open', 'paid']:
165
165
for voucher_tax_line in voucher_lines.tax_line:
166
166
txt_iva_obj.create(
168
168
{'partner_id': acc_part_id.id,
169
169
'voucher_id': voucher.id,
170
170
'invoice_id': voucher_lines.invoice_id.id,
172
172
'untaxed': voucher_tax_line.base,
173
173
'amount_withheld': voucher_tax_line.amount_ret,
174
174
'tax_wh_iva_id': voucher_tax_line.id,
178
178
def action_done(self, cr, uid, ids, context=None):
179
179
""" Transfer the document status to done
181
181
context = context or {}
182
root = self.generate_txt(cr,uid,ids)
183
self._write_attachment(cr,uid,ids,root,context)
184
self.write(cr, uid, ids, {'state':'done'})
182
root = self.generate_txt(cr, uid, ids)
183
self._write_attachment(cr, uid, ids, root, context)
184
self.write(cr, uid, ids, {'state': 'done'})
188
def get_type_document(self,cr,uid,txt_line):
188
def get_type_document(self, cr, uid, txt_line):
189
189
""" Return the document type
190
190
@param txt_line: line of the current document
193
if txt_line.invoice_id.type in ['out_invoice','in_invoice']:
195
elif txt_line.invoice_id.type in ['out_invoice','in_invoice'] and txt_line.invoice_id.parent_id:
193
if txt_line.invoice_id.type in ['out_invoice', 'in_invoice']:
195
elif txt_line.invoice_id.type in ['out_invoice', 'in_invoice'] and txt_line.invoice_id.parent_id:
199
def get_document_affected(self,cr,uid,txt_line,context=None):
199
def get_document_affected(self, cr, uid, txt_line, context=None):
200
200
""" Return the reference or number depending of the case
201
201
@param txt_line: line of the current document
203
203
context = context or {}
205
if txt_line.invoice_id.type in ['in_invoice','in_refund'] and txt_line.invoice_id.parent_id:
205
if txt_line.invoice_id.type in ['in_invoice', 'in_refund'] and txt_line.invoice_id.parent_id:
206
206
number = txt_line.invoice_id.parent_id.supplier_invoice_number
207
207
elif txt_line.invoice_id.parent_id:
208
208
number = txt_line.invoice_id.parent_id.number
211
def get_number(self,cr,uid,number,inv_type,long):
211
def get_number(self, cr, uid, number, inv_type, long):
212
212
""" Return a list of number for document number
213
213
@param number: list of characters from number or reference of the bill
214
214
@param inv_type: invoice type
221
if inv_type=='vou_number' and i.isdigit():
221
if inv_type == 'vou_number' and i.isdigit():
222
if len(result) < long:
223
223
result = i + result
224
224
elif i.isalnum():
225
if len(result) < long:
226
226
result = i + result
227
227
return result[::-1].strip()
229
def get_document_number(self,cr,uid,ids,txt_line,inv_type,context=None):
229
def get_document_number(self, cr, uid, ids, txt_line, inv_type, context=None):
230
230
""" Return the number o reference of the invoice into txt line
231
231
@param txt_line: One line of the current txt document
232
232
@param inv_type: invoice type into txt line
234
234
context = context or {}
236
if txt_line.invoice_id.type in ['in_invoice','in_refund']:
236
if txt_line.invoice_id.type in ['in_invoice', 'in_refund']:
237
237
if not txt_line.invoice_id.supplier_invoice_number:
238
raise osv.except_osv(_('Invalid action !'),_("Unable to make txt file, because the bill has no reference number free!"))
238
raise osv.except_osv(_('Invalid action !'), _("Unable to make txt file, because the bill has no reference number free!"))
240
number = self.get_number(cr,uid,txt_line.invoice_id.supplier_invoice_number.strip(),inv_type,20)
240
number = self.get_number(cr, uid, txt_line.invoice_id.supplier_invoice_number.strip(), inv_type, 20)
241
241
elif txt_line.invoice_id.number:
242
number = self.get_number(cr,uid,txt_line.invoice_id.number.strip(),inv_type,20)
242
number = self.get_number(cr, uid, txt_line.invoice_id.number.strip(), inv_type, 20)
245
def get_amount_exempt_document(self,cr,uid,txt_line):
245
def get_amount_exempt_document(self, cr, uid, txt_line):
246
246
""" Return total amount not entitled to tax credit and the remaining amounts
247
247
@param txt_line: One line of the current txt document
289
289
total = txt_line.tax_wh_iva_id.base + txt_line.tax_wh_iva_id.amount + exempt
290
290
return total, exempt
292
def get_alicuota(self,cr,uid,txt_line):
292
def get_alicuota(self, cr, uid, txt_line):
293
293
""" Return aliquot of the withholding into line
294
294
@param txt_line: One line of the current txt document
296
296
return int(txt_line.tax_wh_iva_id.tax_id.amount * 100)
298
def generate_txt(self,cr,uid,ids,context=None):
298
def generate_txt(self, cr, uid, ids, context=None):
299
299
""" Return string with data of the current document
301
301
context = context or {}
303
303
rp_obj = self.pool.get('res.partner')
304
for txt in self.browse(cr,uid,ids,context):
304
for txt in self.browse(cr, uid, ids, context):
305
305
vat = rp_obj._find_accounting_partner(txt.company_id.partner_id).vat[2:]
306
306
for txt_line in txt.txt_ids:
308
vendor,buyer=self.get_buyer_vendor(cr,uid,txt,txt_line)
308
vendor, buyer = self.get_buyer_vendor(cr, uid, txt, txt_line)
309
309
period = txt.period_id.name.split('/')
310
period2 = period[0]+period[1]
310
period2 = period[0] + period[1]
311
311
# TODO: use the start date of the period to get the period2 with the 'YYYYmm'
313
operation_type = 'V' if txt_line.invoice_id.type in ['out_invoice','out_refund'] else 'C'
314
document_type = self.get_type_document(cr,uid,txt_line)
315
document_number=self.get_document_number(cr,uid,ids,txt_line,'inv_number')
316
control_number = self.get_number(cr,uid,txt_line.invoice_id.nro_ctrl,'inv_ctrl',20)
317
document_affected= self.get_document_affected(cr,uid,txt_line)
318
voucher_number = self.get_number(cr,uid,txt_line.voucher_id.number,'vou_number',14)
319
amount_exempt,amount_untaxed = self.get_amount_exempt_document(cr,uid,txt_line)
320
alicuota = self.get_alicuota(cr,uid,txt_line)
321
amount_total,amount_exempt = self.get_amount_line(cr, uid, txt_line, amount_exempt)
313
operation_type = 'V' if txt_line.invoice_id.type in ['out_invoice', 'out_refund'] else 'C'
314
document_type = self.get_type_document(cr, uid, txt_line)
315
document_number = self.get_document_number(cr, uid, ids, txt_line, 'inv_number')
316
control_number = self.get_number(cr, uid, txt_line.invoice_id.nro_ctrl, 'inv_ctrl', 20)
317
document_affected = self.get_document_affected(cr, uid, txt_line)
318
voucher_number = self.get_number(cr, uid, txt_line.voucher_id.number, 'vou_number', 14)
319
amount_exempt, amount_untaxed = self.get_amount_exempt_document(cr, uid, txt_line)
320
alicuota = self.get_alicuota(cr, uid, txt_line)
321
amount_total, amount_exempt = self.get_amount_line(cr, uid, txt_line, amount_exempt)
323
txt_string= txt_string + buyer +'\t'+period2.strip()+'\t'\
324
+txt_line.invoice_id.date_invoice+'\t'+operation_type+'\t'+document_type+'\t'+vendor+'\t'\
325
+document_number+'\t'+control_number+'\t'+str(round(amount_total,2))+'\t'\
326
+str(round(txt_line.untaxed,2))+'\t'\
327
+str(round(txt_line.amount_withheld,2))+'\t'+document_affected+'\t'+voucher_number+'\t'\
328
+str(round(amount_exempt,2))+'\t'+str(alicuota)+'\t'+'0'\
323
txt_string = txt_string + buyer + '\t' + period2.strip() + '\t'\
324
+ txt_line.invoice_id.date_invoice + '\t' + operation_type + '\t' + document_type + '\t' + vendor + '\t'\
325
+ document_number + '\t' + control_number + '\t' + str(round(amount_total, 2)) + '\t'\
326
+ str(round(txt_line.untaxed, 2)) + '\t'\
327
+ str(round(txt_line.amount_withheld, 2)) + '\t' + document_affected + '\t' + voucher_number + '\t'\
328
+ str(round(amount_exempt, 2)) + '\t' + str(alicuota) + '\t' + '0'\
330
330
return txt_string
332
def _write_attachment(self, cr,uid,ids,root,context=None):
332
def _write_attachment(self, cr, uid, ids, root, context=None):
333
333
""" Encrypt txt, save it to the db and view it on the client as an attachment
334
334
@param root: location to save document
336
336
context = context or {}
337
337
fecha = time.strftime('%Y_%m_%d_%H%M%S')
338
name = 'IVA_' + fecha +'.'+ 'txt'
338
name = 'IVA_' + fecha + '.' + 'txt'
339
339
self.pool.get('ir.attachment').create(cr, uid, {
341
341
'datas': base64.encodestring(root),
342
342
'datas_fname': name,
343
343
'res_model': 'txt.iva',
344
344
'res_id': ids[0],
348
348
self.message_post(cr, uid, ids[0], _('File Created'),
355
355
_name = "txt.iva.line"
358
'partner_id':fields.many2one('res.partner','Buyer/Seller',help="Natural or juridical person that generates the Invoice, Credit Note, Debit Note or C ertification (seller)"),
359
'invoice_id':fields.many2one('account.invoice','Bill/ND/NC',help="Date of invoice, credit note, debit note or certificate, I mportación Statement"),
360
'voucher_id':fields.many2one('account.wh.iva','Tax Withholding',help="Withholding of Value Added Tax (VAT)"),
361
'amount_withheld':fields.float('Amount Withheld', help='amount to withhold'),
362
'untaxed':fields.float('Untaxed', help='Untaxed amount'),
363
'txt_id':fields.many2one('txt.iva','Generate-Document txt VAT', help='withholding lines'),
364
'tax_wh_iva_id':fields.many2one('account.wh.iva.line.tax','Tax Wh Iva Line'),
358
'partner_id': fields.many2one('res.partner', 'Buyer/Seller', help="Natural or juridical person that generates the Invoice, Credit Note, Debit Note or C ertification (seller)"),
359
'invoice_id': fields.many2one('account.invoice', 'Bill/ND/NC', help="Date of invoice, credit note, debit note or certificate, I mportación Statement"),
360
'voucher_id': fields.many2one('account.wh.iva', 'Tax Withholding', help="Withholding of Value Added Tax (VAT)"),
361
'amount_withheld': fields.float('Amount Withheld', help='amount to withhold'),
362
'untaxed': fields.float('Untaxed', help='Untaxed amount'),
363
'txt_id': fields.many2one('txt.iva', 'Generate-Document txt VAT', help='withholding lines'),
364
'tax_wh_iva_id': fields.many2one('account.wh.iva.line.tax', 'Tax Wh Iva Line'),
366
366
_rec_name = 'partner_id'