← Back to team overview

openerp-community team mailing list archive

Re: time tracking system

 

Le 02/09/2013 02:58, Maxime Chambreuil a écrit :
> Hello Quentin,
>
> I would be interested by this script. Would you share it ?
>
> Thank you very much.
Hello Maxime and others,

Please find in attachment the two scripts that we are using to
synchronize OpenERP tasks with Hamster indicator.

I've made some changes on these scripts to remove TeMPO Consulting
default parameters, so feel free to contact me if anything doesn't work.

Kind regards.

-- 
Quentin THEURET

TeMPO Consulting
9, rue du Parc
67205 Oberhausbergen
France

http://www.tempo-consulting.fr
Tel : +33 3 88 56 82 18
Fax : +33 3 88 56 46 64 

#!/usr/bin/python
# -*- encoding: utf-8 -*-
##############################################################################
#
#    OpenERP to Hamster
#    Copyright (C) 2011 TeMPO consulting
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

import sqlite3
from mx import DateTime
import re
import xmlrpclib
import optparse
import os.path 
import getpass
import socket 
import sys

default_hamsterdb = os.path.join(os.path.expanduser('~'),'.gnome2/hamster-applet/hamster.db')
if not os.path.exists(default_hamsterdb) or os.path.getsize(default_hamsterdb) == 0:
	default_hamsterdb = os.path.join(os.path.expanduser('~'),'.local/share/hamster-applet/hamster.db')

usage = "usage: %prog [options] terp_user terp_password"
parser = optparse.OptionParser(usage=usage)
parser.add_option("-d", "--database", dest="terpdb", help=u"Name of the database [default: %default]",default="openerp")
parser.add_option("-H", "--host", dest="terphost", help=u"OpenERP server address [default: %default]",default="127.0.0.1")
parser.add_option("-p", "--port", dest="terpport", help=u"OpenERP server port [default: %default]",default="8069")
parser.add_option("-u", "--user", dest="terpuser", help="Username")
parser.add_option("-w", "--password", dest="terppwd", help="Password")
parser.add_option("-b", "--hamsterdb", dest="hamsterdb", help=u"Path to hamster DB [default: %default]",default=default_hamsterdb)
group = optparse.OptionGroup(parser, "Dangerous options",
                    "The following options can create doublons in OpenERP.")
group.add_option("--date", dest="date", help=u"Push tasks which start since this date in format : YYYY-MM-JJ HH:MM")
group.add_option("--activity", dest="activity", help=u"n'Push only tasks of this activity.")
parser.add_option_group(group)

(opt, args) = parser.parse_args()

if not opt.terpuser:
    parser.error("Please provide an username for the DB OpenERP")
else:
    username = opt.terpuser

if not opt.terppwd:
    passwd = getpass.getpass('OpenERP password: ')
else:
    passwd = opt.terppwd

try:
	sock = xmlrpclib.ServerProxy('http://%s:%s/xmlrpc/common'%(opt.terphost,opt.terpport))
	uid = sock.login(opt.terpdb, username, passwd)
	sock = xmlrpclib.ServerProxy('http://%s:%s/xmlrpc/object'%(opt.terphost,opt.terpport))
except socket.error, err:
	sys.exit(str(err))
except xmlrpclib.Fault:
	sys.exit('Error in database name')

if not uid:
	sys.exit('Incorrect password or username')
	

model = "project.task.work"

if opt.date:
	try:
		mindate = DateTime.strptime(opt.date,'%Y-%m-%d %H:%M')
	except DateTime.Error:
		sys.exit('Invalid date format − Please use "%Y-%m-%d %H:%M"')	
else:
	mindate = DateTime.now()+DateTime.RelativeDateTime(days=-1,hour=8,minute=0,second=0)  #yesterday 08:00:00
	ids = sock.execute(opt.terpdb, uid, passwd, model, 'search', [('user_id','in',[uid])], 0,1,'date desc')
	if ids:
		extask = sock.execute(opt.terpdb, uid, passwd, model, 'read', ids[-1],['date','hours'])
		mindate = DateTime.strptime(extask['date'],'%Y-%m-%d %H:%M:%S')+DateTime.RelativeDateTime(hours=extask['hours']) 

print "Add tasks since %s"%(mindate.strftime('%d/%m/%Y %H:%M'),)

con = sqlite3.connect(opt.hamsterdb)
cr = con.cursor()

description=""
cr.execute(" PRAGMA table_info(facts) ")
for col in cr.fetchall():
	if col[1] == 'description':
		description = ',f.description'
		break

if not opt.activity:
	cr.execute("SELECT a.name,f.start_time,f.end_time " + description + " FROM facts f, activities a WHERE a.id = f.activity_id AND f.start_time >= ? and f.end_time IS NOT NULL", (mindate.strftime('%Y-%m-%d %H:%M:%S'),))
else:
	cr.execute("SELECT a.name,f.start_time,f.end_time  " + description + " FROM facts f, activities a WHERE a.id = f.activity_id AND f.start_time >= ? and f.end_time IS NOT NULL AND a.name = ?", (mindate.strftime('%Y-%m-%d %H:%M:%S'),opt.activity))
totalhours = 0
totaltask = 0
for task in  cr.fetchall():
	m = re.match(".* (\d+)\s*$",task[0])
	if m:
		taskid = m.group(1)
		beg = DateTime.DateTimeFrom(task[1])
		end = DateTime.DateTimeFrom(task[2])
		duration = (end - beg).hours
		data = {
			'date': beg.strftime('%Y-%m-%d %H:%M:%S'),
			'hours': round(duration,3),
			'task_id': int(taskid),
			'user_id': uid,
			'name': description and task[3] or "",
		}
		totaltask+=1
		totalhours+=duration
        	try:
    			sock.execute(opt.terpdb, uid, passwd, model, 'create', data)
	        except xmlrpclib.Fault, err:
        	    print "Error %s"%(err.faultString,)
	            sys.exit(1)
	else:
		print "Impossible to add %s"%task[0]
print "%s task(s) added, %s hour(s)"%(totaltask,totalhours)
con.close()
#!/usr/bin/python
# -*- encoding: utf-8 -*-
##############################################################################
#
#    Hamster to OpenERP
#    Copyright (C) 2011 TeMPO consulting
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

import sqlite3
from mx import DateTime
import re
import xmlrpclib
import optparse
import os.path
import getpass
import socket
import sys

default_hamsterdb = os.path.join(os.path.expanduser('~'),'.gnome2/hamster-applet/hamster.db')
if not os.path.exists(default_hamsterdb) or os.path.getsize(default_hamsterdb) == 0:
    default_hamsterdb = os.path.join(os.path.expanduser('~'),'.local/share/hamster-applet/hamster.db')

usage = "usage: %prog [options] terp_user terp_password"
parser = optparse.OptionParser(usage=usage)
parser.add_option("-d", "--database", dest="terpdb", help=u"Name of the DB [default: %default]",default="openerp")
parser.add_option("-H", "--host", dest="terphost", help=u"OpenERP server address [default: %default]",default="127.0.0.1")
parser.add_option("-p", "--port", dest="terpport", help=u"OpenERP server port [default: %default]",default="8069")
parser.add_option("-u", "--user", dest="terpuser", help="username")
parser.add_option("-w", "--password", dest="terppwd", help="password")
parser.add_option("-b", "--hamsterdb", dest="hamsterdb", help=u"Path to Hamster database [default: %default]",default=default_hamsterdb)

(opt, args) = parser.parse_args()

if not opt.terpuser:
    parser.error("Please provide an username for the OpenERP database")
else:
    username = opt.terpuser
    

if not opt.terppwd:
    passwd = getpass.getpass('OpenERP password: ')
else:
    passwd = opt.terppwd

try:
    sock = xmlrpclib.ServerProxy('http://%s:%s/xmlrpc/common'%(opt.terphost,opt.terpport))
    uid = sock.login(opt.terpdb, username, passwd)
    sock = xmlrpclib.ServerProxy('http://%s:%s/xmlrpc/object'%(opt.terphost,opt.terpport))
except socket.error, err:
    sys.exit(str(err))
except xmlrpclib.Fault:
    sys.exit('Bad database name')

if not uid:
    sys.exit('Incorrect username or password')

con = sqlite3.connect(opt.hamsterdb)
cr = con.cursor()

cr.execute("SELECT a.name FROM activities a")
allact = []
for act in  cr.fetchall():
    m = re.match(".* (\d+)\s*$",act[0])
    if m:
        allact.append(int(m.group(1)))

cr.execute("SELECT min(c.id) FROM categories c")
categ_id = cr.fetchone()[0]

model = "project.task"
tids = sock.execute(opt.terpdb, uid, passwd, model, 'search',[('projmember','in',[uid]),('state','in',['draft','open','pending'])])
tasksids = [ x for x in tids if x not in allact]
nb = 0
for ts in  sock.execute(opt.terpdb, uid, passwd, model, 'read', tasksids, ['name','project_id','state']):
    name = "%s - %s %s"%(ts['project_id'] and ts['project_id'][1] or "", ts['name'], ts['id'] )
    nb += 1
    cr.execute('INSERT INTO activities (name, search_name, category_id, activity_order) VALUES (?, ?, ?, 100)',(name, name, categ_id))

con.commit()
con.close()
print "%d tasks added"%(nb,)

References