oerppy-hackers team mailing list archive
-
oerppy-hackers team
-
Mailing list archive
-
Message #00016
[Branch ~oerppy-hackers/oerppy/trunk] Rev 36: * Renamed CanonicalAddOns to CanonicalAddOn.
------------------------------------------------------------
revno: 36
committer: duncan@xxxxxxxxxx
branch nick: trunk
timestamp: Fri 2011-06-03 12:46:30 -0600
message:
* Renamed CanonicalAddOns to CanonicalAddOn.
* Renamed script and export for cumulative weeks export.
* Moved project code from the canonical addon to its own addon.
* Moved hr code from the canonical addon to its own addon.
* Created a Query base class for all queries (used by addons).
* Created an AddOn base class (subclasses Query).
* Moved field-parsing logic into new field models.
* Added missing field definitions to HR Employee.
added:
oerppy/addons/base.py
oerppy/addons/canonical/model.py
oerppy/addons/hr/
oerppy/addons/hr/__init__.py
oerppy/addons/hr/model.py
oerppy/addons/hr/query.py
oerppy/addons/project/
oerppy/addons/project/__init__.py
oerppy/addons/project/model.py
oerppy/addons/project/query.py
oerppy/query.py
renamed:
bin/export_weekly_timesheets => bin/export_all_weeks_timesheets
modified:
bin/export_month_timesheets
oerppy/addons/canonical/query.py
oerppy/addons/canonical/scripting/export.py
oerppy/model.py
oerppy/service.py
oerppy/tests/test_model.py
bin/export_all_weeks_timesheets
--
lp:oerppy
https://code.launchpad.net/~oerppy-hackers/oerppy/trunk
Your team oerppy Hackers is subscribed to branch lp:oerppy.
To unsubscribe from this branch go to https://code.launchpad.net/~oerppy-hackers/oerppy/trunk/+edit-subscription
=== renamed file 'bin/export_weekly_timesheets' => 'bin/export_all_weeks_timesheets'
--- bin/export_weekly_timesheets 2011-06-02 17:25:28 +0000
+++ bin/export_all_weeks_timesheets 2011-06-03 18:46:30 +0000
@@ -11,7 +11,7 @@
# class(es)
config_data = get_config_data()
# setup any addons that we want
-registry.add(const.CANONICAL, query.CanonicalAddOns)
+registry.add(const.CANONICAL, query.CanonicalAddOn)
# run the exporter
-weekly_export = export.WeeklyExport(config_data)
-weekly_export.run()
+all_weeks_export = export.AllWeeksExport(config_data)
+all_weeks_export.run()
=== modified file 'bin/export_month_timesheets'
--- bin/export_month_timesheets 2011-06-02 17:25:28 +0000
+++ bin/export_month_timesheets 2011-06-03 18:46:30 +0000
@@ -3,7 +3,7 @@
from oerppy.reg import registry
# XXX we probably want to eventually put these addons in their own project
-from oerppy.addons.canonical import query, const
+from oerppy.addons.canonical import const, query
from oerppy.addons.canonical.scripting import export
@@ -11,7 +11,7 @@
# class(es)
config_data = get_config_data()
# setup any addons that we want
-registry.add(const.CANONICAL, query.CanonicalAddOns)
+registry.add(const.CANONICAL, query.CanonicalAddOn)
# run the exporter
monthly_export = export.MonthlyExport(config_data)
monthly_export.run()
=== added file 'oerppy/addons/base.py'
--- oerppy/addons/base.py 1970-01-01 00:00:00 +0000
+++ oerppy/addons/base.py 2011-06-03 18:46:30 +0000
@@ -0,0 +1,10 @@
+from oerppy.query import Query
+
+
+class AddOn(Query):
+ """
+ The addons should only need access to the client object, since through
+ it, one will have access to al the endpoints, the dbname, the
+ credentials, and the basic client query methods.
+ """
+ pass
=== added file 'oerppy/addons/canonical/model.py'
--- oerppy/addons/canonical/model.py 1970-01-01 00:00:00 +0000
+++ oerppy/addons/canonical/model.py 2011-06-03 18:46:30 +0000
@@ -0,0 +1,4 @@
+from oerppy import model
+
+
+
=== modified file 'oerppy/addons/canonical/query.py'
--- oerppy/addons/canonical/query.py 2011-06-03 14:19:21 +0000
+++ oerppy/addons/canonical/query.py 2011-06-03 18:46:30 +0000
@@ -1,20 +1,11 @@
-from datetime import date, timedelta
-
from oerppy import model
+from oerppy.addons import hr, project
from oerppy.addons.canonical import const
-
-
-class CanonicalAddOns(object):
-
- def __init__(self, client):
- """
- The addons should only need access to the client object, since through
- it, one will have access to al the endpoints, the dbname, the
- credentials, and the basic client query methods.
- """
- self.client = client
- self.fields = []
- self.user_dept = None
+from oerppy.addons.hr.query import HRAddOn
+from oerppy.addons.project.query import ProjectAddOn
+
+
+class CanonicalAddOn(HRAddOn, ProjectAddOn):
def views(self):
return const.TIMESHEET_VIEWS
@@ -36,50 +27,6 @@
raise OpenERPPyParameterError("Unknown value for 'report.'")
return records
- def set_departments(self):
- """
- Build a lookup dictionary of department vs user_id.
- """
- raw_results = self.client.searchfields(
- entity="hr.employee",
- query=[],
- fields=['name','department_id','resource_id','user_id'])
- results = model.HREmployeeSet(raw_results)
- # build dictionary of resource_id vs department
- self.user_dept = results.build_department_lookup_table()
-
- def timesheet_hours(self, domains):
- raw_results = self.client.searchfields(
- entity="project.task.work",
- query=domains,
- fields=self.fields)
- return model.ProjectTaskWorkSet(raw_results, self.user_dept)
-
- def get_all_timeentry_weeks(self):
- """
- Get timeentry data since we've been tracking it.
- """
- today = date.today()
- last_week = today - timedelta(days=-7)
- weeks = self.client.searchfields(
- entity='project.timeentry.week',
- query=[
- (['week','>','2010-12-31']),
- ('week','<=', last_week.isoformat())
- ],
- fields=[])
- return weeks
-
- def get_users_timeentry(self, week, user_ids):
- """
- Get the timeentry for a given week.
- """
- timesheets = self.client.searchfields(
- 'project.timeentry',
- [('week_start','=',week['week']),('user_id','in', user_ids)],
- [])
- return timesheets
-
def get_oem_user_ids(self):
"""
Get the IDs for everyone who uses the OEM timesheets.
@@ -90,16 +37,6 @@
['user_ids'])
return user_fields[0]['user_ids']
- def get_user_names(self, user_ids):
- """
- Get the OpenERP user names for the user IDs provided.
- """
- users = self.client.searchfields(
- 'res.users' ,
- [('id','in', user_ids)],
- ['id', 'name'])
- return users
-
def weekly_timesheets(self, domains):
"""
Get the weekly timeentry records, highlighting the missing weeks.
=== modified file 'oerppy/addons/canonical/scripting/export.py'
--- oerppy/addons/canonical/scripting/export.py 2011-06-02 19:03:01 +0000
+++ oerppy/addons/canonical/scripting/export.py 2011-06-03 18:46:30 +0000
@@ -32,14 +32,14 @@
self.export(data)
-class WeeklyExport(ExportScript):
+class AllWeeksExport(ExportScript):
def get_option_parser(self):
"""
Options for monthly exports.
"""
now = datetime.now()
- parser = super(WeeklyExport, self).get_option_parser()
+ parser = super(AllWeeksExport, self).get_option_parser()
parser.add_option(
"-s", "--report-style", dest="report_style", action="store",
default=const.TIMESHEETS_WEEKLY,
=== added directory 'oerppy/addons/hr'
=== added file 'oerppy/addons/hr/__init__.py'
--- oerppy/addons/hr/__init__.py 1970-01-01 00:00:00 +0000
+++ oerppy/addons/hr/__init__.py 2011-06-03 18:46:30 +0000
@@ -0,0 +1,1 @@
+from oerppy.addons.hr import model, query
=== added file 'oerppy/addons/hr/model.py'
--- oerppy/addons/hr/model.py 1970-01-01 00:00:00 +0000
+++ oerppy/addons/hr/model.py 2011-06-03 18:46:30 +0000
@@ -0,0 +1,77 @@
+from oerppy import model
+
+
+class Employee(model.Model):
+ """
+ This is an object model that maps to search results from OpenERP's
+ "hr.employee" entity.
+ """
+ def __init__(self, row):
+ self.id = row.get("id")
+ self.name = row.get("name")
+ self.work_email = row.get("work_email")
+ self.active = row.get("active")
+ self.resource_type = row.get("resource_type")
+ self.child_ids = row.get("child_ids")
+ self.time_efficiency = row.get("time_efficiency")
+ self.state = row.get("state")
+ self.gender = row.get("gender")
+ self.photo = row.get("photo")
+ # The following are key/value pairs, each with .key and .value
+ # attributes
+ self.user = model.KeyValuePairField(row.get("user_id"))
+ self.resource = model.KeyValuePairField(row.get("resource_id"))
+ self.department = model.KeyValuePairField(row.get("department_id"))
+ self.address = model.KeyValuePairField(row.get("address_id"))
+ self.country = model.KeyValuePairField(row.get("country_id"))
+ self.company = model.KeyValuePairField(row.get("company_id"))
+ self.parent = model.KeyValuePairField(row.get("parent_id"))
+ self.product = model.KeyValuePairField(row.get("product_id"))
+ self.journal = model.KeyValuePairField(row.get("journal_id"))
+ # XXX I haven't used these; they need to be checked by someone who has
+ # and then given the appropriate field class.
+ # XXX I'm assuming these would just be simple values:
+ self.code = None
+ self.marital = None
+ self.sinid = None
+ self.work_phone = None
+ self.category_ids = None
+ self.mobile_phone = None
+ self.birthday = None
+ self.work_location = None
+ self.notes = None
+ self.ssnid = None
+ # XXX I'm assuming these would be key-value pairs:
+ self.coach_id = None
+ self.identification_id = None
+ self.partner_id = None
+ self.job_id = None
+ self.bank_account_id = None
+ self.calendar_id = None
+ self.address_home_id = None
+ self.passport_id = None
+
+
+class EmployeeSet(model.ResultSet):
+ """
+ An object for collecting HREmployees together.
+ """
+ model = Employee
+
+ def get_user(self, user_id):
+ for employee in self:
+ if employee.user.key == user_id:
+ return employee
+
+ def build_department_lookup_table(self):
+ table = {}
+ table["unknown"] = 0
+ for employee in self:
+ if employee.department and employee.user.key:
+ table[employee.user.key] = employee.department.value
+ elif employee.user.key:
+ table[employee.user.key] = "?"
+ else:
+ table["unknown"] += 1
+ return table
+
=== added file 'oerppy/addons/hr/query.py'
--- oerppy/addons/hr/query.py 1970-01-01 00:00:00 +0000
+++ oerppy/addons/hr/query.py 2011-06-03 18:46:30 +0000
@@ -0,0 +1,22 @@
+from oerppy.addons import base
+from oerppy.addons.hr import model
+
+
+class HRAddOn(base.AddOn):
+ """
+ """
+ def __init__(self, *args, **kwargs):
+ super(HRAddOn, self).__init__(*args, **kwargs)
+ self.user_dept = None
+
+ def set_departments(self):
+ """
+ Build a lookup dictionary of department vs user_id.
+ """
+ raw_results = self.client.searchfields(
+ entity="hr.employee",
+ query=[],
+ fields=['name','department_id','resource_id','user_id'])
+ results = model.EmployeeSet(raw_results)
+ # build dictionary of resource_id vs department
+ self.user_dept = results.build_department_lookup_table()
=== added directory 'oerppy/addons/project'
=== added file 'oerppy/addons/project/__init__.py'
--- oerppy/addons/project/__init__.py 1970-01-01 00:00:00 +0000
+++ oerppy/addons/project/__init__.py 2011-06-03 18:46:30 +0000
@@ -0,0 +1,1 @@
+from oerppy.addons.project import model, query
=== added file 'oerppy/addons/project/model.py'
--- oerppy/addons/project/model.py 1970-01-01 00:00:00 +0000
+++ oerppy/addons/project/model.py 2011-06-03 18:46:30 +0000
@@ -0,0 +1,30 @@
+from oerppy import model
+
+
+class TaskWork(model.Model):
+ """
+ This is an object model that maps to search results from OpenERP's
+ "project.task.work" entity.
+ """
+ def __init__(self, row, depts):
+ self.project = model.KeyValuePairField(row.get("project_id"))
+ self.task = model.KeyValuePairField(row.get("task_id"))
+ self.user = model.KeyValuePairField(row.get("user_id"))
+ self.hours = row.get("hours")
+ self.date = row.get("date")
+ self.week_start = row.get("week_start")
+ self.year = int(self.date[0:4])
+ self.month = int(self.date[5:7])
+ self.department_name = depts.get(self.user.key)
+
+
+class TaskWorkSet(model.ResultSet):
+ """
+ An object for collecting HREmployees together.
+ """
+ model = TaskWork
+
+ def get_work(self, project_id):
+ for project in self:
+ if project.project.key == project_id:
+ return project
=== added file 'oerppy/addons/project/query.py'
--- oerppy/addons/project/query.py 1970-01-01 00:00:00 +0000
+++ oerppy/addons/project/query.py 2011-06-03 18:46:30 +0000
@@ -0,0 +1,40 @@
+from datetime import date, timedelta
+
+from oerppy.addons import base
+from oerppy.addons.project import model
+
+
+class ProjectAddOn(base.AddOn):
+ """
+ """
+ def timesheet_hours(self, domains):
+ raw_results = self.client.searchfields(
+ entity="project.task.work",
+ query=domains,
+ fields=[])
+ return model.TaskWorkSet(raw_results, self.user_dept)
+
+ def get_all_timeentry_weeks(self):
+ """
+ Get timeentry data since we've been tracking it.
+ """
+ today = date.today()
+ last_week = today - timedelta(days=-7)
+ weeks = self.client.searchfields(
+ entity='project.timeentry.week',
+ query=[
+ (['week','>','2010-12-31']),
+ ('week','<=', last_week.isoformat())
+ ],
+ fields=[])
+ return weeks
+
+ def get_users_timeentry(self, week, user_ids):
+ """
+ Get the timeentry for a given week.
+ """
+ timesheets = self.client.searchfields(
+ 'project.timeentry',
+ [('week_start','=',week['week']),('user_id','in', user_ids)],
+ [])
+ return timesheets
=== modified file 'oerppy/model.py'
--- oerppy/model.py 2011-06-03 14:19:21 +0000
+++ oerppy/model.py 2011-06-03 18:46:30 +0000
@@ -1,3 +1,24 @@
+class Field(object):
+ """
+ An object representing a data point.
+ """
+ def __init__(self, data):
+ self.value = value
+ def __repr__(self):
+ return self.value
+ def __str__(self):
+ return str(self.value)
+
+
+class KeyValuePairField(Field):
+ """
+ An object representing a field that has an ID and a string value.
+ """
+ def __init__(self, data):
+ if not data:
+ data = (None, None)
+ (self.key, self.value) = data
+
class Model(object):
"""
@@ -16,80 +37,5 @@
for row in results:
try:
self.add(self.model(row, *args, **kwds))
- except:
+ except Exception, error:
import pdb;pdb.set_trace()
-
-
-class HREmployee(Model):
- """
- This is an object model that maps to search results from OpenERP's
- "hr.employee" entity.
- """
- def __init__(self, row):
- user_data = row["user_id"]
- if user_data:
- self.user_id = user_data[0]
- else:
- self.user_id = None
- self.name = row["name"][0]
- self.resource_id = row["resource_id"][0]
- department_data = row["department_id"]
- if department_data:
- self.department_id = department_data[0]
- self.department_name = department_data[1]
- else:
- self.department_id = None
- self.department_name = None
-
-
-class HREmployeeSet(ResultSet):
- """
- An object for collecting HREmployees together.
- """
- model = HREmployee
-
- def get_user(self, user_id):
- for user in self:
- if user.user_id == user_id:
- return user
-
- def build_department_lookup_table(self):
- table = {}
- table["unknown"] = 0
- for user in self:
- if user.department_name and user.user_id:
- table[user.user_id] = user.department_name
- elif user.user_id:
- table[user.user_id] = "?"
- else:
- table["unknown"] += 1
- return table
-
-
-class ProjectTaskWork(Model):
- """
- This is an object model that maps to search results from OpenERP's
- "project.task.work" entity.
- """
- def __init__(self, row, depts):
- self.project_id = row['project_id'][1]
- self.task_id = row['task_id'][1]
- self.user_id = row['user_id'][1]
- self.department_name = depts.get(self.user_id, "?")
- self.hours = row['hours']
- self.date = row['date']
- self.year = int(row['date'][0:4])
- self.month = int(row['date'][5:7])
- self.week = row['week_start']
-
-
-class ProjectTaskWorkSet(ResultSet):
- """
- An object for collecting HREmployees together.
- """
- model = ProjectTaskWork
-
- def get_work(self, project_id):
- for project in self:
- if project.project_id == project_id:
- return project
=== added file 'oerppy/query.py'
--- oerppy/query.py 1970-01-01 00:00:00 +0000
+++ oerppy/query.py 2011-06-03 18:46:30 +0000
@@ -0,0 +1,32 @@
+class Query(object):
+ """
+ A wrapper class for RPC requests (queries) that are more
+ involved/complicated than the ones implemented in the client class.
+
+ AddOn classes use this as a baseclass.
+ """
+ def __init__(self, client):
+ self.client = client
+
+ def query(self, report, domains=None):
+ """
+ A dispatch method that each subclass needs to implement.
+ """
+ raise NotImplementedError
+
+ def get_users(self):
+ users = self.client.searchfields(
+ entity='res.users',
+ query=[],
+ fields=[])
+ return users
+
+ def get_user_names(self, user_ids):
+ """
+ Get the OpenERP user names for the user IDs provided.
+ """
+ users = self.client.searchfields(
+ 'res.users' ,
+ [('id','in', user_ids)],
+ ['id', 'name'])
+ return users
=== modified file 'oerppy/service.py'
--- oerppy/service.py 2011-06-03 14:19:21 +0000
+++ oerppy/service.py 2011-06-03 18:46:30 +0000
@@ -1,6 +1,6 @@
import xmlrpclib
-from oerppy import client, reg, util
+from oerppy import client, exceptions, reg, util
class Credentials(object):
@@ -153,7 +153,7 @@
def __init__(self, url, dbname, user, password):
for variable in [url, dbname, user, password]:
if not variable:
- raise exception.OpenERPPyConfigError(
+ raise exceptions.OpenERPPyConfigError(
"url, dbname, user and password must "
"all have values set.")
self.endpoints = ServiceEndpoints(url)
=== modified file 'oerppy/tests/test_model.py'
--- oerppy/tests/test_model.py 2011-06-03 14:19:21 +0000
+++ oerppy/tests/test_model.py 2011-06-03 18:46:30 +0000
@@ -1,79 +1,3 @@
import unittest
from oerppy import model
-
-
-user_results = [
- {"name": ["Bob"],
- "user_id": [314],
- "department_id": [1, "Crypto"],
- "resource_id": [34]},
- {"name": ["Alice"],
- "user_id": [315],
- "department_id": [2, "Maths"],
- "resource_id": [37]},
- {"name": ["Carol"],
- "user_id": [316],
- "department_id": False,
- "resource_id": [42]},
- ]
-
-
-class HRTestCase(unittest.TestCase):
-
- def test_hr_employee(self):
- employee = model.HREmployee(user_results[1])
- self.assertEqual(employee.user_id, 315)
- self.assertEqual(employee.name, "Alice")
- self.assertEqual(employee.department_id, 2)
- self.assertEqual(employee.resource_id, 37)
-
- def test_hr_employee_set(self):
- results = model.HREmployeeSet(user_results)
- self.assertEqual(len(results), 3)
- user = results.get_user(314)
- self.assertEqual(user.name, "Bob")
- table = results.build_department_lookup_table()
- self.assertEqual(table.get(315), "Maths")
- self.assertEqual(table.get(316), "?")
-
-class ProjectTaskWorkTestCase(unittest.TestCase):
-
- def setUp(self):
- self.work_results = [
- {"project_id": ["UKN", 1],
- "task_id": ["UKN", 1001],
- "user_id": ["UKN", 314],
- "hours": 273,
- "department_id": [1, "Crypto"],
- "date": "2011-05-01",
- "week_start": 172},
- {"project_id": ["UKN", 2],
- "task_id": ["UKN", 1002],
- "user_id": ["UKN", 315],
- "hours": 735,
- "department_id": [2, "Maths"],
- "date": "2011-05-01",
- "week_start": 172},
- ]
- self.results = model.HREmployeeSet(user_results)
- self.table = self.results.build_department_lookup_table()
-
- def test_project_task_work(self):
-
- work = model.ProjectTaskWork(self.work_results[1], self.table)
- self.assertEqual(work.project_id, 2)
- self.assertEqual(work.task_id, 1002)
- self.assertEqual(work.user_id, 315)
- self.assertEqual(work.department_name, "Maths")
- self.assertEqual(work.hours, 735)
- self.assertEqual(work.date, "2011-05-01")
- self.assertEqual(work.year, 2011)
- self.assertEqual(work.month, 5)
- self.assertEqual(work.week, 172)
-
- def test_project_task_work_set(self):
- results = model.ProjectTaskWorkSet(self.work_results, self.table)
- self.assertEqual(len(results), 2)
- work = results.get_work(1)
- self.assertEqual(work.hours, 273)