← Back to team overview

oerppy-hackers team mailing list archive

[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)