1
# -*- encoding: utf-8 -*-
2
##############################################################################
4
# OpenERP, Open Source Management Solution
5
# Copyright (c) 2011 Zikzakmedia S.L. (http://zikzakmedia.com) All Rights Reserved.
6
# Jes�s Mart�n <jmartin@zikzakmedia.com>
7
# Raimon Esteve <resteve@zikzakmedia.com>
10
# This program is free software: you can redistribute it and/or modify
11
# it under the terms of the GNU General Public License as published by
12
# the Free Software Foundation, either version 3 of the License, or
13
# (at your option) any later version.
15
# This program is distributed in the hope that it will be useful,
16
# but WITHOUT ANY WARRANTY; without even the implied warranty of
17
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
# GNU General Public License for more details.
20
# You should have received a copy of the GNU General Public License
21
# along with this program. If not, see <http://www.gnu.org/licenses/>.
23
##############################################################################
25
from osv import osv, fields
26
from tools.translate import _
33
class csv_file_field(osv.osv):
34
_name = 'csv.file.field'
39
class csv_file(osv.osv):
43
'name': fields.char('Code', size=64, required=True, help="Code Name of this file. Use lowcase and az09 characters."),
44
'path': fields.char('Path', size=300, required=True, help="The path to the file name. The last slash is not necessary"),
45
'state' : fields.selection([('draft', 'Draft'),('done', 'Done')],'State',required=True,readonly=True),
46
'file':fields.char('CSV File', required=True, size=64, help='CSV Filename'),
47
'file_csv_separator': fields.selection([
51
], 'CSV Separator', required=True, help="Product File CSV Separator"),
52
'header': fields.boolean('Header', help="Header (fields name) on files"),
53
'quote': fields.char('Quote', size=1, required=True, help="Character to use as quote"),
54
'field_ids': fields.one2many('csv.file.field','file_id','Fields'),
55
'model_id': fields.many2one('ir.model', 'OpenERP Model', required=True, select=True, ondelete='cascade'),
56
'model':fields.related('model_id', 'model', type='char', string='Model Name', readonly=True),
60
'quote': lambda *a: '',
61
'file_csv_separator':lambda *a: ",",
62
'state' : lambda *a: 'draft',
65
def create(self, cr, uid, vals, context=None):
66
vals['name'] = re.sub(r'\W+', '',vals['name']).lower() #replace name to az09 characters and lowercase
67
csv_file_ids = self.pool.get('csv.file').search(cr, uid, [('name','ilike',vals['name'])])
68
if len(csv_file_ids) > 0:
69
raise osv.except_osv(_('Error!'), _("Another External Mapping have the same code!"))
70
vals['state'] = 'done'
71
return super(csv_file, self).create(cr, uid, vals, context)
76
def lines_csv(self, cr, uid, id, context=None):
80
csv_file = self.browse(cr, uid, id)
82
csvpath = csv_file.path
83
if not csvpath[-1] == '/':
86
csvfile = open(csvpath+csv_file.file, "r")
88
num_lines = sum(1 for line in open(csvpath+csv_file.file))
91
num_lines = num_lines-1
96
Import CSV list from line file
97
If you have a big CSV file, we recomended use mincalls in this function and use number line
99
def import_line_csv(self, cr, uid, ids, line, context=None):
100
self.logger = netsvc.Logger()
101
csv_file_field_obj = self.pool.get('csv.file.field')
103
for csv_file in self.browse(cr, uid, ids):
104
csvpath = csv_file.path
105
if not csvpath[-1] == '/':
108
csvfile = open(csvpath+csv_file.file, "r")
110
separator = csv_file.file_csv_separator
111
if separator == "tab":
116
#if you have a big CSV file, we recomended use mincalls in this function and use number line
118
csvfile_lines = csvfile.readlines()
121
csvfile_values = csvfile_lines[line].split(separator)
127
for cell, value in enumerate(csvfile_values):
128
field_ids = csv_file_field_obj.search(cr, uid, [('file_id','=',csv_file.id), ('sequence','=',cell)])
130
csv_file_value = csv_file_field_obj.browse(cr, uid, field_ids[0])
132
if csv_file_value.import_expression:
133
localspace = {"self":self, "cr":cr, "uid":uid, "ids":ids, "re":re, "context":context, "incsv":value, "row":row}
134
code = csv_file_value.import_expression.replace('\r\n', '\n')
135
exec code in localspace
136
if 'value' in localspace:
137
value = localspace['value']
141
values.append({'field':csv_file_value.field_id.name, 'value':value})
143
self.logger.notifyChannel(_("CSV File"), netsvc.LOG_INFO, _("Add dicc row line %s") % line)
144
csv_values.append(values)
146
self.logger.notifyChannel(_("CSV File"), netsvc.LOG_ERROR, _("Not line specified"))
154
return all rows in list
156
def import_csv(self, cr, uid, ids, context=None):
157
self.logger = netsvc.Logger()
158
csv_file_field_obj = self.pool.get('csv.file.field')
162
for csv_file in self.browse(cr, uid, ids):
163
csvpath = csv_file.path
164
if not csvpath[-1] == '/':
167
csvfile = open(csvpath+csv_file.file, "r")
169
separator = csv_file.file_csv_separator
170
if separator == "tab":
173
rows = csv.reader(csvfile, delimiter="%s" % str(separator))
177
if csv_file.header: # Header file. Skip
178
if rows.line_num == 1:
180
for cell, value in enumerate(row):
181
field_ids = csv_file_field_obj.search(cr, uid, [('file_id','=',csv_file.id), ('sequence','=',cell)])
183
csv_file_value = csv_file_field_obj.browse(cr, uid, field_ids[0])
185
if csv_file_value.import_expression:
186
localspace = {"self":self, "cr":cr, "uid":uid, "ids":ids, "re":re, "context":context, "incsv":value, "row":row}
187
code = csv_file_value.import_expression.replace('\r\n', '\n')
188
exec code in localspace
189
if 'value' in localspace:
190
value = localspace['value']
194
values.append({csv_file_value.field_id.name:value})
196
self.logger.notifyChannel(_("CSV File"), netsvc.LOG_INFO, _("Add dicc row line %s") % rows.line_num)
197
csv_values.append(values)
206
def export_csv(self, cr, uid, ids, context=None):
207
#TODO. Design this function. You can inspire code in nan_file_format module
214
class csv_file_field(osv.osv):
215
_name = 'csv.file.field'
218
'name': fields.char('Name',size=64, required=True, help="The name of the field. It's used if you have selected the Header checkbox"),
219
'sequence': fields.integer('Sequence', help="Is the order that you want for the columns field in the file"),
220
'field_id': fields.many2one('ir.model.fields', 'OpenERP Field', select=True, ondelete='cascade', required=True, domain="[('model_id', '=', parent.model_id),('ttype','!=','binary')]"),
221
'file_id': fields.many2one('csv.file','External Mapping'),
222
# 'header': fields.related('file_id','header', type='boolean', string='Header'), #TODO: name or sequence visible if header true or false
223
'import_expression': fields.text('Import Expression', help="Where we put the python code. The fields are called like '$name_of_field' (without the simple quotes)"),
224
'export_expression': fields.text('Export Expression', help="Where we put the python code. The fields are called like '$name_of_field' (without the simple quotes)"),
225
'type': fields.selection([('str', 'String'), ('bool', 'Boolean'), ('int', 'Integer'), ('float', 'Float')], 'Type'),
231
'type': lambda *a: 'str',