~anna-g/micronaet/anna

« back to all changes in this revision

Viewing changes to mexal_order_statistic/etl/import_order.py

  • Committer: Anna Micronaet
  • Date: 2013-07-18 09:08:36 UTC
  • Revision ID: anna@micronaet.it-20130718090836-ssmst48rrnvcd69w
Tolti tutti i moduli

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python
2
 
# -*- encoding: utf-8 -*-
3
 
 
4
 
# ETL. import csv file with preformatted data comes from Mexal orders
5
 
# use: import.csv mexal_file_csv.csv
6
 
 
7
 
# Modules required:
8
 
import xmlrpclib, csv, sys, ConfigParser
9
 
from posta import *
10
 
import sys, time, os # for get date of file
11
 
 
12
 
# Start main code *************************************************************
13
 
if len(sys.argv)!=2 :
14
 
   print """
15
 
         *** Syntax Error! ***
16
 
         *  Use the command with this syntax: python ./import.py ocdetoerp.FIA
17
 
         *********************
18
 
         """ 
19
 
   sys.exit()
20
 
 
21
 
# Funzioni:
22
 
def prepare(valore):  
23
 
    # For problems: input win output ubuntu; trim extra spaces
24
 
    #valore=valore.decode('ISO-8859-1')
25
 
    valore=valore.decode('cp1252')
26
 
    valore=valore.encode('utf-8')
27
 
    return valore.strip()
28
 
 
29
 
def prepare_date(valore):
30
 
    valore=valore.strip()
31
 
    if len(valore)==8:
32
 
       if valore: # TODO test correct date format
33
 
          return valore[:4] + "/" + valore[4:6] + "/" + valore[6:8]
34
 
    return '' #time.strftime("%d/%m/%Y") (per gli altri casi)
35
 
 
36
 
def prepare_float(valore):
37
 
    valore=valore.strip() 
38
 
    if valore: # TODO test correct date format       
39
 
       return float(valore.replace(",","."))
40
 
    else:
41
 
       return 0.0   # for empty values
42
 
       
43
 
def get_partner_id(sock, uid, pwd, mexal_id):
44
 
    ''' Ricavo l'ID del partner dall'id di mexal
45
 
    '''
46
 
    item_id = sock.execute(dbname, uid, pwd, 'res.partner', 'search', [('ref', '=', mexal_id)])
47
 
    if item_id:
48
 
       return item_id[0]
49
 
    return 0   
50
 
 
51
 
FileInput=sys.argv[1]
52
 
if FileInput:
53
 
   sigla_azienda=FileInput[-3:].lower()
54
 
else:
55
 
   print "[ERR] File input non presente!"
56
 
   sys.exit()   
57
 
if sigla_azienda in ('gpb','fia'):
58
 
   cfg_file=sigla_azienda + ".openerp.cfg"
59
 
else:
60
 
   print "[ERR] Sigla azienda non trovata!"
61
 
   sys.exit()        
62
 
    
63
 
# Ricavo la data del file per comunicarla
64
 
create_date=time.ctime(os.path.getctime(FileInput))    
65
 
 
66
 
# Set up parameters (for connection to Open ERP Database) ********************************************
67
 
config = ConfigParser.ConfigParser()
68
 
config.read([cfg_file]) # if file is in home dir add also: , os.path.expanduser('~/.openerp.cfg')])
69
 
dbname = config.get('dbaccess','dbname')
70
 
user = config.get('dbaccess','user')
71
 
pwd = config.get('dbaccess','pwd')
72
 
server = config.get('dbaccess','server')
73
 
port = config.get('dbaccess','port')   # verify if it's necessary: getint
74
 
separator = config.get('dbaccess','separator') # test
75
 
verbose = eval(config.get('import_mode','verbose')) #;verbose=True
76
 
 
77
 
verbose= False # TODO togliere
78
 
 
79
 
smtp_sender = config.get('smtp', 'sender')
80
 
smtp_receiver = config.get('smtp', 'receiver')
81
 
smtp_subject = config.get('smtp', 'subject') + " (Importazione Ordini e verifica date files)"
82
 
smtp_text = config.get('smtp', 'text')
83
 
smtp_log = config.get('smtp', 'log_file') + ".ordini.csv"
84
 
smtp_server = config.get('smtp', 'server')
85
 
#verbose_mail: True
86
 
 
87
 
debug_mode=True # TODO reset false when OK
88
 
 
89
 
# Open file log error (if verbose mail the file are sent to admin email)
90
 
try: 
91
 
   out_file = open(smtp_log,"w")
92
 
except:
93
 
   print "[WARNING]","Error creating log files:", smtp_log
94
 
   # No raise as it'a a warning
95
 
 
96
 
header_lines = 0 # mai da mexal
97
 
# XMLRPC connection for autentication (UID) and proxy 
98
 
sock = xmlrpclib.ServerProxy('http://' + server + ':' + port + '/xmlrpc/common', allow_none=True)
99
 
uid = sock.login(dbname ,user ,pwd)
100
 
sock = xmlrpclib.ServerProxy('http://' + server + ':' + port + '/xmlrpc/object', allow_none=True)
101
 
 
102
 
# Open CSV passed file (see arguments) mode: read / binary, delimiation char 
103
 
lines = csv.reader(open(FileInput,'rU'),delimiter=separator)   # prima era: rb
104
 
counter={'tot':-header_lines,'new':0,'upd':0,'order':0} # tot negative (jump N lines)
105
 
 
106
 
# Elimino tutti gli elementi della tabella prima di procedere all'importazione:
107
 
header_ids = sock.execute(dbname, uid, pwd, 'statistic.header', 'search', []) 
108
 
response =  sock.execute(dbname, uid, pwd, 'statistic.header', 'unlink', header_ids) 
109
 
 
110
 
order_ids = sock.execute(dbname, uid, pwd, 'statistic.order', 'search', []) 
111
 
response =  sock.execute(dbname, uid, pwd, 'statistic.order', 'unlink', order_ids) 
112
 
 
113
 
# Carico gli elementi da file CSV:
114
 
tot_col = 0
115
 
header_id = 0
116
 
old_order_number = ''
117
 
sequence = 0
118
 
try:
119
 
    for line in lines:
120
 
        if tot_col==0: # memorizzo il numero colonne la prima volta
121
 
           tot_col=len(line)
122
 
           print "[INFO] Colonne rilevate", tot_col
123
 
           raise_error("[INFO] Procedura: %s \n\tFile importato: %s [creazione: %s]"%(sys.argv, FileInput, create_date), out_file)
124
 
        if counter['tot']<0:  # salto le N righe di intestazione
125
 
           counter['tot']+=1
126
 
        else:   
127
 
           if len(line) and (tot_col==len(line)): # salto le righe vuote e le righe con colonne diverse
128
 
               counter['tot']+=1 
129
 
               try:
130
 
                   csv_id=0       # Codice cliente di mexal forma (NNN.NNNNN)
131
 
                   mexal_id = prepare(line[csv_id])
132
 
                   csv_id+=1      # Cliente descrizione
133
 
                   cliente = prepare(line[csv_id]) 
134
 
                   csv_id+=1      # Order number
135
 
                   number = prepare(line[csv_id])
136
 
                   csv_id+=1      # Data OC formato: YYYYMMDD
137
 
                   order_date = prepare_date(line[csv_id]) or False
138
 
                   csv_id+=1      # Scadenza OC formato: YYYYMMDD
139
 
                   order_deadline = prepare_date(line[csv_id]) or False
140
 
                   csv_id+=1      # Articolo
141
 
                   articolo_id = prepare(line[csv_id]) 
142
 
                   csv_id+=1      # Articolo descrizione   (oppure campo campo note nelle righe (D)escrittive )
143
 
                   articolo = prepare(line[csv_id]) 
144
 
                   csv_id+=1      # Quantity
145
 
                   quantity = prepare_float(line[csv_id]) or 0.0
146
 
                   csv_id+=1      # Tipo di riga (b si intende prodotto)
147
 
                   type_of_line = prepare(line[csv_id]) 
148
 
                   csv_id+=1      # Note
149
 
                   note = prepare(line[csv_id]) 
150
 
 
151
 
                   csv_id+=1      # Descrizione italiano
152
 
                   product_description = prepare(line[csv_id]) 
153
 
                   csv_id+=1      # Descrizione inglese
154
 
                   product_description_eng = prepare(line[csv_id]) 
155
 
                   csv_id+=1      # Numero colli
156
 
                   colli = prepare(line[csv_id]) 
157
 
                   csv_id+=1      # Tipo di riga (A o D)
158
 
                   line_type = prepare(line[csv_id]).lower() # a=articolo, d=descrizione
159
 
 
160
 
                   csv_id+=1      # Codice porto
161
 
                   port_code = prepare(line[csv_id]).lower()
162
 
                   csv_id+=1      # Descrizione italiano
163
 
                   port_description = prepare(line[csv_id]) 
164
 
                   csv_id+=1      # Destinazione descrizione
165
 
                   destination_description = prepare(line[csv_id]) 
166
 
                   csv_id+=1      # Destinazione indirizzo
167
 
                   destination_address = prepare(line[csv_id]) 
168
 
                   csv_id+=1      # Destinazione CAP
169
 
                   destination_cap = prepare(line[csv_id]) 
170
 
                   csv_id+=1      # Destinazione localita'
171
 
                   destination_loc = prepare(line[csv_id]) 
172
 
                   csv_id+=1      # Destinazione provincia
173
 
                   destination_prov = prepare(line[csv_id]) 
174
 
 
175
 
                   # Videata extra:
176
 
                   csv_id+=1      # Data di registrazione
177
 
                   registration_date = prepare_date(line[csv_id]) or False
178
 
                   csv_id+=1      # Note aggiuntive (nella stampa)
179
 
                   extra_note = prepare(line[csv_id]) 
180
 
                   csv_id+=1      # Note aggiuntive (nella stampa)
181
 
                   agent_description = prepare(line[csv_id]) 
182
 
 
183
 
                   # Calculated field:
184
 
                   # Dati dimensionali letti dal prodotto:
185
 
                   product_ids = sock.execute(dbname, uid, pwd, 'product.product', 'search', [('mexal_id','=', articolo_id )])  
186
 
 
187
 
                   if product_ids and line_type == 'a':
188
 
                       product_item = sock.execute(dbname, uid, pwd, 'product.product', 'read', product_ids)[0]
189
 
                       total_linear_meter = (quantity or 0.0) * product_item['linear_length']
190
 
                       total_volume = (quantity or 0.0) * (product_item['volume'] or 0.0)
191
 
                       total_weight = (quantity or 0.0) * (product_item['weight'] or 0.0)
192
 
                   else: # description line
193
 
                       total_linear_meter = False 
194
 
                       total_volume = False 
195
 
                       total_weight = False 
196
 
 
197
 
                       if line_type == "a": 
198
 
                          raise_error("[ERR] Riga:%s - Prodotto non trovato: %s"%(counter['tot'], articolo_id), out_file)
199
 
                   
200
 
                   total=0 #TODO
201
 
                   partner_id = get_partner_id(sock, uid, pwd, mexal_id)
202
 
 
203
 
                   if line_type=="a":
204
 
                      if not colli:
205
 
                         colli = quantity # se non ci sono i colli metto uguale a quantity (per avere il 20 x 1)
206
 
                   if port_code not in ('', 'f', 'a', 'd'):
207
 
                      raise_error("[ERR] Riga:%s - Codice Porto non trovato: %s"%(counter['tot'], port_code), out_file)
208
 
 
209
 
                   if line_type not in ('a', 'd'):
210
 
                      raise_error("[ERR] Riga:%s - Tipo di linea non trovato: %s"%(counter['tot'], line_type), out_file)
211
 
                      
212
 
                   if not partner_id:
213
 
                      raise_error("[ERR] Riga:%s - Partner non trovato: %s"%(counter['tot'], mexal_id), out_file)
214
 
 
215
 
                   if type_of_line.lower() == 'b':
216
 
                      quantity_ok = quantity or 0.0
217
 
                   else:
218
 
                      quantity_ok = 0.0
219
 
                       
220
 
                   if not number:   
221
 
                      raise_error("[ERR] Riga:%s - Numero d'ordine non trovato: %s"%(counter['tot'], number), out_file)
222
 
                      
223
 
                   # Inserimento ordine testata statistic.header
224
 
                   if old_order_number != number: # se cambia faccio le verifiche o lo creo altrimenti rimane l'ID prec.
225
 
                       old_order_number = number # memorizzo il vecchio numero
226
 
                       counter['order']+=1
227
 
                       sequence = 1
228
 
                       header = {'name': number, #"Ordine n.:%s"%(number,),
229
 
                                 'partner_id': partner_id,
230
 
                                 'date': order_date,
231
 
                                 'deadline': order_deadline,
232
 
                                 #'total': fields.float('Total', digits=(16, 2)),
233
 
                                 'note': note,
234
 
                                 'port_code': port_code,
235
 
                                 'port_description':port_description,
236
 
                                 'destination':destination_description,
237
 
                                 'destination_address': destination_address,
238
 
                                 'destination_cap': destination_cap,
239
 
                                 'destination_country': destination_loc,
240
 
                                 'destination_prov': destination_prov,
241
 
                                 'agent_description': agent_description,
242
 
                                 # extra window:
243
 
                                 
244
 
                                 'registration_date': registration_date,
245
 
                                 'extra_note': extra_note,                                 
246
 
                                }
247
 
                       # TODO ottimizzabile cercando la rottura di codice:       
248
 
                       search_header_id = sock.execute(dbname, uid, pwd, 'statistic.header', 'search', [('name','=',number)])
249
 
                       if search_header_id:
250
 
                          header_id=search_header_id[0] # Memorizzo per associarlo poi all'ordine
251
 
                       else: # Creo:
252
 
                           try:
253
 
                              header_id = sock.execute(dbname, uid, pwd, 'statistic.header', 'create', header)
254
 
                           except:
255
 
                              raise_error("[ERR] Riga:%s - Errore creando header: %s"%(counter['tot'], number), out_file)
256
 
                           if verbose: 
257
 
                              raise_error("[INFO] Riga:%s - Header inserito: %s"%(counter['tot'], number), out_file)
258
 
                   else: # stesso ordine
259
 
                       sequence += 1
260
 
 
261
 
                   # Inserimento dettaglio ordine  (associando la riga con l'header_id)
262
 
                   # Importazione dato: statistic.order
263
 
                   data={'name': number,
264
 
                         'partner_id': partner_id,
265
 
                         'date': order_date,
266
 
                         'deadline': order_deadline,
267
 
                         'total': total,
268
 
                         'code': articolo_id, # codice di mexal
269
 
                         'article': "%s %s"%(articolo,product_description), # descrizione articolo + descrizione italiana aggiuntiva
270
 
                         'quantity': quantity,
271
 
                         'quantity_ok': quantity_ok,
272
 
                         'total_linear_meter': total_linear_meter,
273
 
                         'total_volume': total_volume,
274
 
                         'total_weight': total_weight,
275
 
                         'note':note,                         
276
 
                         'header_id': header_id, 
277
 
                         'line_type': line_type,
278
 
                         'colli': colli,
279
 
                         'sequence': sequence,
280
 
                         }
281
 
                   
282
 
                   if not order_deadline and line_type=="a": # Comunico solo nel caso non sia riga descrittiva 
283
 
                      raise_error("[ERR] Riga:%s - Scadenza non trovata: %s"%(counter['tot'], number), out_file)
284
 
                   elif order_deadline:
285
 
                      mod_response = sock.execute(dbname, uid, pwd, 'statistic.header', 'write', header_id, {'deadline': order_deadline,}) # TODO optimize! <<<<<<<<<<<
286
 
                      
287
 
 
288
 
                   if type_of_line:
289
 
                      data['type']= type_of_line.lower()
290
 
 
291
 
                   try:
292
 
                     order_id = sock.execute(dbname, uid, pwd, 'statistic.order', 'create', data)  
293
 
                   except:
294
 
                      raise_error("[ERR] Riga:%s - Errore creando ordine: %s"%(counter['tot'], number), out_file)
295
 
                   
296
 
                   if verbose: 
297
 
                      raise_error("[INFO] Riga:%s - Ordine inserito: %s"%(counter['tot'], number), out_file)
298
 
 
299
 
               except:
300
 
                   raise_error("[ERR] Riga:%s - Errore di importazione: %s"%(counter['tot'],  sys.exc_info()[0]), out_file)
301
 
           else:
302
 
                   raise_error("[ERR] Riga:%s - Riga vuota o con colonne diverse: file %s, riga %s"%(counter['tot'], tot_col, len(line)), out_file)
303
 
except:
304
 
    raise_error("[ERR] Errore importando gli ordini!", out_file)
305
 
    raise 
306
 
raise_error("[INFO] Totale ordini: %s  -  Totale righe: %s"%(counter['order'],counter['tot'],), out_file)
307
 
 
308
 
if debug_mode: # Parte comune a tutte le procedure:
309
 
    file_log=os.path.abspath(os.path.dirname(FileInput))+"/log.FIA"
310
 
    raise_error("\n\n[DEBUG] Date files importati:", out_file)      
311
 
    i=0
312
 
    for line in open(file_log,'r'):
313
 
       i+=1
314
 
       if i>7: # jump first line (description and . / ..)
315
 
          if line and line[0:1]!=" ":
316
 
             raise_error("\tData: %s - File: %s"%(line[0:17], line[35:].strip(),), out_file)
317
 
 
318
 
out_file.close()           
319
 
send_mail(smtp_sender,[smtp_receiver,],smtp_subject,smtp_text,[smtp_log,],smtp_server)
320