summaryrefslogtreecommitdiff
path: root/addons/hr_timesheet
diff options
context:
space:
mode:
authorpinky <>2006-12-07 13:41:40 +0000
committerpinky <>2006-12-07 13:41:40 +0000
commita83dce15e0f33145b2eea7e878ae7eacf3aba90a (patch)
treea3d1399cbfebf7d90a8894d97c9b7e0a9d881960 /addons/hr_timesheet
parent004a0b996ff8f269451e07346f71a129a1f3fbaf (diff)
New trunk
bzr revid: pinky-dedd7f8a42bd4557112a0513082691b8590ad6cc
Diffstat (limited to 'addons/hr_timesheet')
-rw-r--r--addons/hr_timesheet/__init__.py3
-rw-r--r--addons/hr_timesheet/__terp__.py14
-rw-r--r--addons/hr_timesheet/hr.analytic.timesheet.csv0
-rw-r--r--addons/hr_timesheet/hr_timesheet.py114
-rw-r--r--addons/hr_timesheet/hr_timesheet_data.xml10
-rw-r--r--addons/hr_timesheet/hr_timesheet_demo.xml35
-rw-r--r--addons/hr_timesheet/hr_timesheet_report.xml37
-rw-r--r--addons/hr_timesheet/hr_timesheet_view.xml103
-rw-r--r--addons/hr_timesheet/hr_timesheet_wizard.xml8
-rw-r--r--addons/hr_timesheet/report/__init__.py2
-rw-r--r--addons/hr_timesheet/report/user_timesheet.py95
-rw-r--r--addons/hr_timesheet/report/user_timesheet.xsl133
-rw-r--r--addons/hr_timesheet/report/users_timesheet.py100
-rw-r--r--addons/hr_timesheet/report/users_timesheet.xsl124
-rw-r--r--addons/hr_timesheet/wizard/__init__.py30
-rw-r--r--addons/hr_timesheet/wizard/sign_in_out.py176
-rw-r--r--addons/hr_timesheet/wizard/wizard_print_timesheet.py63
-rw-r--r--addons/hr_timesheet/wizard/wizard_print_timesheet_users.py61
18 files changed, 1108 insertions, 0 deletions
diff --git a/addons/hr_timesheet/__init__.py b/addons/hr_timesheet/__init__.py
new file mode 100644
index 00000000000..5dc3071ed5a
--- /dev/null
+++ b/addons/hr_timesheet/__init__.py
@@ -0,0 +1,3 @@
+import hr_timesheet
+import wizard
+import report
diff --git a/addons/hr_timesheet/__terp__.py b/addons/hr_timesheet/__terp__.py
new file mode 100644
index 00000000000..de0a42af991
--- /dev/null
+++ b/addons/hr_timesheet/__terp__.py
@@ -0,0 +1,14 @@
+{
+ "name" : "Human Resources (Timesheet encoding)",
+ "version" : "0.1",
+ "author" : "Tiny",
+ "category" : "Generic Modules/Human Resources",
+ "website" : "http://tinyerp.com/module_hr.html",
+ "description": "Timesheet system, completly integrated with the cost accounting module. It allows you to set up a management by affair.",
+ "depends" : ["account", "hr"],
+ "init_xml" : ["hr_timesheet_data.xml"],
+ "demo_xml" : ["hr_timesheet_demo.xml","hr.analytic.timesheet.csv"],
+ "update_xml" : ["hr_timesheet_view.xml", "hr_timesheet_report.xml","hr_timesheet_wizard.xml"],
+ "active": False,
+ "installable": True
+}
diff --git a/addons/hr_timesheet/hr.analytic.timesheet.csv b/addons/hr_timesheet/hr.analytic.timesheet.csv
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/addons/hr_timesheet/hr.analytic.timesheet.csv
diff --git a/addons/hr_timesheet/hr_timesheet.py b/addons/hr_timesheet/hr_timesheet.py
new file mode 100644
index 00000000000..cd223049608
--- /dev/null
+++ b/addons/hr_timesheet/hr_timesheet.py
@@ -0,0 +1,114 @@
+##############################################################################
+#
+# Copyright (c) 2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+#
+# $Id$
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import time
+from osv import fields
+from osv import osv
+
+
+class hr_employee(osv.osv):
+ _name = "hr.employee"
+ _inherit = "hr.employee"
+ _columns = {
+ 'product_id': fields.many2one('product.product', 'Product'),
+ 'journal_id': fields.many2one('account.analytic.journal', 'Analytic Journal')
+ }
+hr_employee()
+
+
+class hr_analytic_timesheet(osv.osv):
+ _name = "hr.analytic.timesheet"
+ _table = 'hr_analytic_timesheet'
+ _inherits = {'account.analytic.line': 'line_id'}
+ _columns = {
+ 'line_id' : fields.many2one('account.analytic.line', 'Analytic line', ondelete='cascade'),
+ }
+
+ def unlink(self, cr, uid, ids, context={}):
+ toremove = {}
+ for obj in self.browse(cr, uid, ids, context):
+ toremove[obj.line_id.id] = True
+ self.pool.get('account.analytic.line').unlink(cr, uid, toremove.keys(), context)
+ return super(hr_analytic_timesheet, self).unlink(cr, uid, ids, context)
+
+ def on_change_unit_amount(self, cr, uid, id, prod_id, unit_amount, unit, context={}):
+ return self.pool.get('account.analytic.line').on_change_unit_amount(cr, uid, id, prod_id, unit_amount,unit, context)
+
+ def _getEmployeeProduct(self, cr, uid, context):
+ emp_obj = self.pool.get('hr.employee')
+ emp_id = emp_obj.search(cr, uid, [('user_id', '=', uid)])
+ if emp_id:
+ return emp_obj.browse(cr, uid, emp_id[0], context).product_id.id
+ return False
+
+ def _getEmployeeUnit(self, cr, uid, context):
+ emp_obj = self.pool.get('hr.employee')
+ emp_id = emp_obj.search(cr, uid, [('user_id', '=', uid)])
+ if emp_id:
+ return emp_obj.browse(cr, uid, emp_id[0], context).product_id.uom_id.id
+ return False
+
+ def _getGeneralAccount(self, cr, uid, context):
+ emp_obj = self.pool.get('hr.employee')
+ emp_id = emp_obj.search(cr, uid, [('user_id', '=', uid)])
+ if emp_id:
+ emp = self.pool.get('hr.employee').browse(cr, uid, emp_id[0], context=context)
+ if bool(emp.product_id):
+ a = emp.product_id.product_tmpl_id.property_account_income
+ if not a:
+ a = emp.product_id.categ_id.property_account_income_categ
+ return a[0]
+ return False
+
+ def _getAnalyticJournal(self, cr, uid, context):
+ emp_obj = self.pool.get('hr.employee')
+ emp_id = emp_obj.search(cr, uid, [('user_id', '=', uid)])
+ if emp_id:
+ emp = self.pool.get('hr.employee').browse(cr, uid, emp_id[0], context=context)
+ if emp.journal_id:
+ return emp.journal_id.id
+ return False
+
+
+ _defaults = {
+ 'product_uom_id' : _getEmployeeUnit,
+ 'product_id' : _getEmployeeProduct,
+ 'general_account_id' : _getGeneralAccount,
+ 'journal_id' : _getAnalyticJournal,
+ 'user_id' : lambda obj, cr, uid, ctx : uid,
+ }
+
+ def on_change_account_id(self, cr, uid, ids, account_id):
+ return {}
+ if not account_id:
+ return {}
+ account = self.pool.get('account.analytic.account').read(cr, uid, [account_id], ['name'])[0]['name']
+ user = self.pool.get('res.users').read(cr, uid, [uid], ['name'])[0]['name']
+ return {'value' : {'name' : '%s (%s)' % (account, user)}}
+hr_analytic_timesheet()
diff --git a/addons/hr_timesheet/hr_timesheet_data.xml b/addons/hr_timesheet/hr_timesheet_data.xml
new file mode 100644
index 00000000000..6b980d5829a
--- /dev/null
+++ b/addons/hr_timesheet/hr_timesheet_data.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<terp>
+ <data>
+ <record model="account.analytic.journal" id="analytic_journal">
+ <field name="code">TS</field>
+ <field name="name">Timesheet Journal</field>
+ <field name="type">general</field>
+ </record>
+ </data>
+</terp>
diff --git a/addons/hr_timesheet/hr_timesheet_demo.xml b/addons/hr_timesheet/hr_timesheet_demo.xml
new file mode 100644
index 00000000000..78341e80161
--- /dev/null
+++ b/addons/hr_timesheet/hr_timesheet_demo.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<terp>
+ <data noupdate="1">
+
+ <record model="product.uom.categ" id="uom_categ_wtime">
+ <field name="name">Working Time</field>
+ </record>
+ <record model="product.uom" id="uom_hour">
+ <field name="name">Hour</field>
+ <field name="category_id" eval="uom_categ_wtime"/>
+ <field name="factor">1.0</field>
+ </record>
+ <record model="product.uom" id="uom_day">
+ <field name="name">Day</field>
+ <field name="category_id" eval="uom_categ_wtime"/>
+ <field name="factor">8.0</field>
+ </record>
+
+ <record id="product_consultant" model="product.product">
+ <field name="default_code">DEV</field>
+ <field name="list_price">75.0</field>
+ <field name="standard_price">30.0</field>
+ <field name="uom_id" ref="uom_hour"/>
+ <field name="uom_po_id" ref="uom_hour"/>
+ <field name="name">Consultancy - Senior Developper</field>
+ <field name="categ_id" ref="product.product_category_10"/>
+ </record>
+
+ <!-- complete our example employee -->
+ <record model="hr.employee" id="hr.employee1">
+ <field name="product_id" ref="product_consultant"/>
+ <field name="journal_id" ref="analytic_journal"/>
+ </record>
+ </data>
+</terp>
diff --git a/addons/hr_timesheet/hr_timesheet_report.xml b/addons/hr_timesheet/hr_timesheet_report.xml
new file mode 100644
index 00000000000..5501fea2690
--- /dev/null
+++ b/addons/hr_timesheet/hr_timesheet_report.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<terp>
+ <data>
+ <report
+ id="report_user_timesheet"
+ string="Employee timesheet"
+ model="hr.employee"
+ name="hr.analytical.timesheet"
+ xsl="hr_timesheet/report/user_timesheet.xsl"
+ auto="False"
+ menu="False"/>
+
+ <wizard id="wizard_hr_timesheet"
+ string="Employee timesheet"
+ model="hr.employee"
+ name="hr.analytical.timesheet"
+ menu="False" />
+ <menuitem name="Human Resources/Hours encoding/Print timesheet" action="wizard_hr_timesheet" type="wizard" />
+
+ <report id="report_users_timesheet"
+ string="Employees timesheet"
+ model="hr.employee"
+ name="hr.analytical.timesheet_users"
+ xsl="hr_timesheet/report/users_timesheet.xsl"
+ auto="False"
+ menu="False"/>
+
+ <wizard id="wizard_hr_timesheet_users"
+ string="Employees timesheet"
+ model="hr.employee"
+ name="hr.analytical.timesheet_users"
+ menu="False"/>
+ <menuitem name="Human Resources/Hours encoding/Print users timesheet" action="wizard_hr_timesheet_users" type="wizard"/>
+
+ </data>
+</terp>
+
diff --git a/addons/hr_timesheet/hr_timesheet_view.xml b/addons/hr_timesheet/hr_timesheet_view.xml
new file mode 100644
index 00000000000..a8ad4e2eded
--- /dev/null
+++ b/addons/hr_timesheet/hr_timesheet_view.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" ?>
+<terp>
+ <data>
+ <record model="ir.ui.view" id="hr_timesheet_line_tree">
+ <field name="name">hr.analytic.timesheet.tree</field>
+ <field name="model">hr.analytic.timesheet</field>
+ <field name="type">tree</field>
+ <field name="arch" type="xml">
+ <tree string="Timesheet Line" editable="bottom">
+ <field name="user_id" required="1"/>
+ <field name="date" />
+ <field name="account_id" on_change="on_change_account_id(account_id)" domain="[('type','=','normal')]"/>
+ <field name="name" />
+ <field name="unit_amount" on_change="on_change_unit_amount(product_id, unit_amount, product_uom_id)" />
+ <field name="product_id"/>
+ <field name="product_uom_id" on_change="on_change_unit_amount(product_id, unit_amount, product_uom_id)" />
+ <field name="amount" />
+ </tree>
+ </field>
+ </record>
+ <record model="ir.ui.view" id="hr_timesheet_line_form">
+ <field name="name">hr.analytic.timesheet.form</field>
+ <field name="model">hr.analytic.timesheet</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form string="Timesheet Line">
+ <field name="name" colspan="3"/>
+ <field name="user_id" select="1" required="1"/>
+ <field name="date" select="1"/>
+ <field name="unit_amount" on_change="on_change_unit_amount(product_id, unit_amount, product_uom_id)" />
+ <newline/>
+ <field name="product_id" on_change="on_change_unit_amount(product_id, unit_amount, product_uom_id)"/>
+ <field name="product_uom_id" on_change="on_change_unit_amount(product_id, unit_amount, product_uom_id)" />
+
+ <field name="account_id" on_change="on_change_account_id(account_id)" domain="[('type','=','normal')]" select="1"/>
+ <field name="amount" select="1"/>
+ <field name="general_account_id" select="1"/>
+ <field name="journal_id"/>
+ </form>
+ </field>
+ </record>
+
+ <record model="ir.actions.act_window" id="act_hr_timesheet_line_today_form">
+ <field name="name">hr.analytic.timesheet.form</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">hr.analytic.timesheet</field>
+ <field name="view_type">form</field>
+ <field name="view_id" ref="hr_timesheet_line_form" />
+ </record>
+ <menuitem name="Human Resources/Hours encoding" id="menu_act_hr_timesheet_line_today_form" action="act_hr_timesheet_line_today_form" />
+
+ <record model="ir.actions.act_window" id="act_hr_timesheet_line_me_today_form">
+ <field name="name">hr.analytic.timesheet.form</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">hr.analytic.timesheet</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ <field name="domain">[('date', '=', time.strftime('%Y-%m-%d')),('user_id','=',uid)]</field>
+ </record>
+ <menuitem name="Human Resources/Hours encoding/For me/My works of the day" id="menu_act_hr_timesheet_line_me_today_form" action="act_hr_timesheet_line_me_today_form" />
+
+ <record model="ir.actions.act_window" id="act_hr_timesheet_line_me_all_form">
+ <field name="name">hr.analytic.timesheet.form</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">hr.analytic.timesheet</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ <field name="domain">[('user_id','=',uid)]</field>
+ </record>
+ <menuitem name="Human Resources/Hours encoding/For me/All my works" id="menu_act_hr_timesheet_line_me_all_form" action="act_hr_timesheet_line_me_all_form" />
+
+ <record model="ir.actions.act_window" id="act_hr_timesheet_line_evry1_today_form">
+ <field name="name">hr.analytic.timesheet.form</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">hr.analytic.timesheet</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ <field name="domain">[('date', '=', time.strftime('%Y-%m-%d'))]</field>
+ </record>
+ <menuitem name="Human Resources/Hours encoding/For everyone/All works of the day" id="menu_act_hr_timesheet_line_evry1_today_form" action="act_hr_timesheet_line_evry1_today_form" />
+
+ <record model="ir.actions.act_window" id="act_hr_timesheet_line_evry1_all_form">
+ <field name="name">hr.analytic.timesheet.form</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">hr.analytic.timesheet</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ </record>
+ <menuitem name="Human Resources/Hours encoding/For everyone/All works" id="menu_act_hr_timesheet_line_evry1_all_form" action="act_hr_timesheet_line_evry1_all_form" />
+
+ <record model="ir.ui.view" id="hr_timesheet_employee_extd_form">
+ <field name="name">hr.timesheet.employee.extd_form</field>
+ <field name="model">hr.employee</field>
+ <field name="inherit_id" ref="hr.view_employee_form" />
+ <field name="arch" type="xml">
+ <field name="notes" position="after">
+ <field name="product_id" />
+ <field name="journal_id" />
+ </field>
+ </field>
+ </record>
+ </data>
+</terp>
diff --git a/addons/hr_timesheet/hr_timesheet_wizard.xml b/addons/hr_timesheet/hr_timesheet_wizard.xml
new file mode 100644
index 00000000000..2bd982a59de
--- /dev/null
+++ b/addons/hr_timesheet/hr_timesheet_wizard.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" ?>
+<terp>
+ <data>
+ <wizard string="Sign in / Sign out by project" model="hr.employee" name="hr_timesheet.si_so" id="si_so"/>
+ <menuitem name="Human Resources/Attendances/Sign in\/out by project" action="si_so" type="wizard" groups="admin" id="menu_si_so"/>
+
+ </data>
+</terp>
diff --git a/addons/hr_timesheet/report/__init__.py b/addons/hr_timesheet/report/__init__.py
new file mode 100644
index 00000000000..deb273e9447
--- /dev/null
+++ b/addons/hr_timesheet/report/__init__.py
@@ -0,0 +1,2 @@
+import user_timesheet
+import users_timesheet
diff --git a/addons/hr_timesheet/report/user_timesheet.py b/addons/hr_timesheet/report/user_timesheet.py
new file mode 100644
index 00000000000..b485b6a0076
--- /dev/null
+++ b/addons/hr_timesheet/report/user_timesheet.py
@@ -0,0 +1,95 @@
+##############################################################################
+#
+# Copyright (c) 2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+#
+# $Id$
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import datetime
+
+from report.interface import report_rml
+from report.interface import toxml
+
+def lengthmonth(year, month):
+ if month == 2 and ((year % 4 == 0) and ((year % 100 != 0) or (year % 400 == 0))):
+ return 29
+ return [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
+
+class report_custom(report_rml):
+ def create_xml(self, cr, uid, ids, data, context):
+
+ # Computing the dates (start of month: som, and end of month: eom)
+ som = datetime.date(data['form']['year'], data['form']['month'], 1)
+ eom = som + datetime.timedelta(lengthmonth(som.year, som.month))
+ date_xml = ['<date month="%s" year="%d" />' % (som.strftime('%B'), som.year), '<days>']
+ date_xml += ['<day number="%d" name="%s" />' % (x, som.replace(day=x).strftime('%a')) for x in range(1, lengthmonth(som.year, som.month)+1)]
+ date_xml.append('</days>')
+ date_xml.append('<cols>2.5cm%s,2cm</cols>\n' % (',0.7cm' * lengthmonth(som.year, som.month)))
+
+ # Computing the attendence by analytical account
+ cr.execute(
+ "select line.date, (unit_amount * unit.factor) as amount, account_id, account.name "\
+ "from account_analytic_line as line, hr_analytic_timesheet as hr, "\
+ "account_analytic_account as account, product_uom as unit "\
+ "where hr.line_id=line.id and line.account_id=account.id "\
+ "and product_uom_id = unit.id "\
+ "and line.user_id=%d and line.date >= %s and line.date < %s "
+ "order by line.date",
+ (data['form']['user_id'], som.strftime('%Y-%m-%d'), eom.strftime('%Y-%m-%d')))
+
+ # Sum attendence by account, then by day
+ accounts = {}
+ for presence in cr.dictfetchall():
+ day = int(presence['date'][-2:])
+ account = accounts.setdefault((presence['account_id'], presence['name']), {})
+ account[day] = account.get(day, 0.0) + presence['amount']
+
+ xml = '''
+ <time-element date="%s">
+ <amount>%s</amount>
+ </time-element>
+ '''
+ account_xml = []
+ for account, telems in accounts.iteritems():
+ aid, aname = account
+ account_xml.append('<account id="%d" name="%s">' % (aid, toxml(aname)))
+ account_xml.append('\n'.join([xml % (day, amount) for day, amount in telems.iteritems()]))
+ account_xml.append('</account>')
+
+ # Computing the employee
+ cr.execute("select name from res_users where id=%d", (data['form']['user_id'],))
+ emp = cr.fetchone()[0]
+
+ # Computing the xml
+ xml = '''<?xml version="1.0" encoding="UTF-8" ?>
+ <report>
+ <employee>%s</employee>
+ %s
+ </report>
+ ''' % (toxml(emp), '\n'.join(date_xml) + '\n'.join(account_xml))
+ return xml
+
+report_custom('report.hr.analytical.timesheet', 'hr.employee', '', 'addons/hr_timesheet/report/user_timesheet.xsl')
+
diff --git a/addons/hr_timesheet/report/user_timesheet.xsl b/addons/hr_timesheet/report/user_timesheet.xsl
new file mode 100644
index 00000000000..c54152cdb80
--- /dev/null
+++ b/addons/hr_timesheet/report/user_timesheet.xsl
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:fo="http://www.w3.org/1999/XSL/Format">
+
+ <xsl:template match="/">
+ <xsl:call-template name="rml" />
+ </xsl:template>
+
+
+ <xsl:template name="rml">
+ <document filename="example.pdf">
+ <template pageSize="29.7cm,21cm" leftMargin="2.0cm" rightMargin="2.0cm" topMargin="2.0cm" bottomMargin="2.0cm" title="Timesheets" author="Generated by Tiny ERP, Fabien Pinckaers" allowSplitting="20">
+ <pageTemplate id="first">
+ <frame id="col1" x1="2.0cm" y1="2.5cm" width="24.7cm" height="17cm"/>
+ </pageTemplate>
+ </template>
+
+ <stylesheet>
+ <paraStyle name="normal" fontName="Helvetica" fontSize="6" alignment="center" />
+ <paraStyle name="normal-title" fontName="Helvetica" fontSize="6" />
+ <paraStyle name="title" fontName="Helvetica" fontSize="18" alignment="center" />
+ <paraStyle name="employee" fontName="Helvetica-Oblique" fontSize="10" textColor="blue" />
+ <paraStyle name="glande" textColor="purple" />
+ <paraStyle name="normal_people" textColor="green" />
+ <paraStyle name="esclave" textColor="red" />
+ <blockTableStyle id="month">
+ <blockAlignment value="CENTER" start="1,0" stop="-1,-1" />
+ <blockFont name="Helvetica" size="8" start="0,0" stop="-1,1"/>
+ <blockFont name="Helvetica" size="6" start="0,2" stop="-2,-2"/>
+ <blockFont name="Helvetica-BoldOblique" size="8" start="0,-1" stop="-1,-1"/>
+ <blockBackground colorName="#AAAAAA" start="1,0" stop="-2,1"/>
+ <xsl:for-each select="/report/days/day[@name='Sat']">
+ <xsl:variable name="col" select="attribute::number" />
+ <blockBackground>
+ <xsl:attribute name="colorName">lightgrey</xsl:attribute>
+ <xsl:attribute name="start">
+ <xsl:value-of select="$col" />
+ <xsl:text>,0</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="stop">
+ <xsl:value-of select="$col+1" />
+ <xsl:text>,-1</xsl:text>
+ </xsl:attribute>
+ </blockBackground>
+ </xsl:for-each>
+ <lineStyle kind="LINEABOVE" colorName="black" start="0,0" stop="-1,-1" />
+ <lineStyle kind="LINEBEFORE" colorName="black" start="0,0" stop="-1,-1"/>
+ <lineStyle kind="LINEAFTER" colorName="black" start="-1,0" stop="-1,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="black" start="0,-1" stop="-1,-1"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+ </stylesheet>
+
+ <story>
+ <xsl:call-template name="story"/>
+ </story>
+ </document>
+ </xsl:template>
+
+ <xsl:template name="story">
+ <para style="title" t="1">Timesheet</para>
+ <spacer length="1cm" />
+ <para style="employee"><xsl:value-of select="/report/employee" /></para>
+ <spacer length="1cm" />
+ <blockTable>
+ <xsl:attribute name="style">month</xsl:attribute>
+ <xsl:attribute name="colWidths"><xsl:value-of select="report/cols" /></xsl:attribute>
+ <tr>
+ <td><xsl:value-of select="report/date/attribute::year" /></td>
+ <xsl:for-each select="report/days/day">
+ <td>
+ <xsl:value-of select="attribute::name" />
+ </td>
+ </xsl:for-each>
+ <td></td>
+ </tr>
+ <tr>
+ <td><xsl:value-of select="report/date/attribute::month" /></td>
+ <xsl:for-each select="report/days/day">
+ <td>
+ <xsl:value-of select="attribute::number" />
+ </td>
+ </xsl:for-each>
+ <td t="1">Total</td>
+ </tr>
+ <xsl:apply-templates select="report/account"/>
+ <tr>
+ <td t="1">Sum</td>
+ <xsl:for-each select="report/days/day">
+ <xsl:variable name="today" select="attribute::number" />
+ <td>
+ <para>
+ <xsl:choose>
+ <xsl:when test="sum(//time-element[@date=$today]) &lt; 7.5">
+ <xsl:attribute name="style">glande</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="sum(//time-element[@date=$today]) &lt; 8.5 and sum(//time-element[@date=$today]) &gt;= 7.5">
+ <xsl:attribute name="style">normal_people</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style">esclave</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:value-of select="sum(//time-element[@date=$today])" />
+ </para>
+ </td>
+ </xsl:for-each>
+ <td>
+ <xsl:value-of select="sum(//time-element)" />
+ </td>
+ </tr>
+ </blockTable>
+ </xsl:template>
+
+ <xsl:template match="account">
+ <xsl:variable name="aid" select="attribute::id" />
+ <tr>
+ <td>
+ <para style="normal-title"><xsl:value-of select="attribute::name" /></para>
+ </td>
+ <xsl:for-each select="/report/days/day">
+ <xsl:variable name="today" select="attribute::number" />
+ <td>
+ <para style="normal"><xsl:value-of select="//account[@id=$aid]/time-element[@date=$today]" /></para>
+ </td>
+ </xsl:for-each>
+ <td>
+ <para style="normal"><xsl:value-of select="sum(//account[@id=$aid]/time-element)" /></para>
+ </td>
+ </tr>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/addons/hr_timesheet/report/users_timesheet.py b/addons/hr_timesheet/report/users_timesheet.py
new file mode 100644
index 00000000000..9855a988215
--- /dev/null
+++ b/addons/hr_timesheet/report/users_timesheet.py
@@ -0,0 +1,100 @@
+##############################################################################
+#
+# Copyright (c) 2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+#
+# $Id: user_timesheet.py 4229 2006-10-13 15:11:17Z ged $
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import datetime
+from report.interface import report_rml
+from report.interface import toxml
+
+def lengthmonth(year, month):
+ if month == 2 and ((year % 4 == 0) and ((year % 100 != 0) or (year % 400 == 0))):
+ return 29
+ return [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
+
+def emp_create_xml(cr, id, som, eom):
+ # Computing the attendence by analytical account
+ cr.execute(
+ "select line.date, (unit_amount * unit.factor) as amount "\
+ "from account_analytic_line as line, hr_analytic_timesheet as hr, "\
+ "product_uom as unit "\
+ "where hr.line_id=line.id "\
+ "and product_uom_id = unit.id "\
+ "and line.user_id=%d and line.date >= %s and line.date < %s "
+ "order by line.date",
+ (id, som.strftime('%Y-%m-%d'), eom.strftime('%Y-%m-%d')))
+
+ # Sum by day
+ month = {}
+ for presence in cr.dictfetchall():
+ day = int(presence['date'][-2:])
+ month[day] = month.get(day, 0.0) + presence['amount']
+
+ xml = '''
+ <time-element date="%s">
+ <amount>%s</amount>
+ </time-element>
+ '''
+ time_xml = ([xml % (day, amount) for day, amount in month.iteritems()])
+
+ # Computing the employee
+ cr.execute("select name from res_users where id=%d", (id,))
+ emp = cr.fetchone()[0]
+
+ # Computing the xml
+ xml = '''
+ <employee id="%d" name="%s">
+ %s
+ </employee>
+ ''' % (id, toxml(emp), '\n'.join(time_xml))
+ return xml
+
+class report_custom(report_rml):
+ def create_xml(self, cr, uid, ids, data, context):
+
+ # Computing the dates (start of month: som, and end of month: eom)
+ som = datetime.date(data['form']['year'], data['form']['month'], 1)
+ eom = som + datetime.timedelta(lengthmonth(som.year, som.month))
+ date_xml = ['<date month="%s" year="%d" />' % (som.strftime('%B'), som.year), '<days>']
+ date_xml += ['<day number="%d" name="%s" />' % (x, som.replace(day=x).strftime('%a')) for x in range(1, lengthmonth(som.year, som.month)+1)]
+ date_xml.append('</days>')
+ date_xml.append('<cols>2.5cm%s,2cm</cols>\n' % (',0.7cm' * lengthmonth(som.year, som.month)))
+
+ emp_xml=''
+ for id in data['form']['user_ids'][0][2]:
+ emp_xml += emp_create_xml(cr, id, som, eom)
+
+ # Computing the xml
+ xml='''<?xml version="1.0" encoding="UTF-8" ?>
+ <report>
+ %s
+ %s
+ </report>
+ ''' % (date_xml, emp_xml)
+ return xml
+
+report_custom('report.hr.analytical.timesheet_users', 'hr.employee', '', 'addons/hr_timesheet/report/users_timesheet.xsl')
diff --git a/addons/hr_timesheet/report/users_timesheet.xsl b/addons/hr_timesheet/report/users_timesheet.xsl
new file mode 100644
index 00000000000..c6f310211df
--- /dev/null
+++ b/addons/hr_timesheet/report/users_timesheet.xsl
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:fo="http://www.w3.org/1999/XSL/Format">
+
+ <xsl:template match="/">
+ <xsl:call-template name="rml" />
+ </xsl:template>
+
+
+ <xsl:template name="rml">
+ <document filename="example.pdf">
+ <template pageSize="29.7cm,21cm" leftMargin="2.0cm" rightMargin="2.0cm" topMargin="2.0cm" bottomMargin="2.0cm" title="Timesheets" author="Generated by Tiny ERP, Fabien Pinckaers" allowSplitting="20">
+ <pageTemplate id="first">
+ <frame id="col1" x1="2.0cm" y1="2.5cm" width="24.7cm" height="17cm"/>
+ </pageTemplate>
+ </template>
+
+ <stylesheet>
+ <paraStyle name="normal" fontName="Helvetica" fontSize="6" alignment="center" />
+ <paraStyle name="normal-title" fontName="Helvetica" fontSize="6" />
+ <paraStyle name="title" fontName="Helvetica" fontSize="18" alignment="center" />
+ <paraStyle name="employee" fontName="Helvetica-Oblique" fontSize="10" textColor="blue" />
+ <paraStyle name="glande" textColor="purple" />
+ <paraStyle name="normal_people" textColor="green" />
+ <paraStyle name="esclave" textColor="red" />
+ <blockTableStyle id="month">
+ <blockAlignment value="CENTER" start="1,0" stop="-1,-1" />
+ <blockFont name="Helvetica" size="8" start="0,0" stop="-1,1"/>
+ <blockFont name="Helvetica" size="6" start="0,2" stop="-2,-2"/>
+ <blockFont name="Helvetica-BoldOblique" size="8" start="0,-1" stop="-1,-1"/>
+ <blockBackground colorName="#AAAAAA" start="1,0" stop="-2,1"/>
+ <xsl:for-each select="/report/days/day[@name='Sat']">
+ <xsl:variable name="col" select="attribute::number" />
+ <blockBackground>
+ <xsl:attribute name="colorName">lightgrey</xsl:attribute>
+ <xsl:attribute name="start">
+ <xsl:value-of select="$col" />
+ <xsl:text>,0</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="stop">
+ <xsl:value-of select="$col+1" />
+ <xsl:text>,-1</xsl:text>
+ </xsl:attribute>
+ </blockBackground>
+ </xsl:for-each>
+ <lineStyle kind="LINEABOVE" colorName="black" start="0,0" stop="-1,-1" />
+ <lineStyle kind="LINEBEFORE" colorName="black" start="0,0" stop="-1,-1"/>
+ <lineStyle kind="LINEAFTER" colorName="black" start="-1,0" stop="-1,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="black" start="0,-1" stop="-1,-1"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+ </stylesheet>
+
+ <story>
+ <xsl:call-template name="story"/>
+ </story>
+ </document>
+ </xsl:template>
+
+ <xsl:template name="story">
+ <para style="title" t="1">Timesheet</para>
+ <spacer length="1cm" />
+ <blockTable>
+ <xsl:attribute name="style">month</xsl:attribute>
+ <xsl:attribute name="colWidths"><xsl:value-of select="report/cols" /></xsl:attribute>
+ <tr>
+ <td><xsl:value-of select="report/date/attribute::year" /></td>
+ <xsl:for-each select="report/days/day">
+ <td>
+ <xsl:value-of select="attribute::name" />
+ </td>
+ </xsl:for-each>
+ <td></td>
+ </tr>
+ <tr>
+ <td><xsl:value-of select="report/date/attribute::month" /></td>
+ <xsl:for-each select="report/days/day">
+ <td>
+ <xsl:value-of select="attribute::number" />
+ </td>
+ </xsl:for-each>
+ <td t="1">Total</td>
+ </tr>
+ <xsl:apply-templates select="report/employee"/>
+ <xsl:for-each select="report/employee">
+ <xsl:variable name="id" select="attribute::id"/>
+ <tr>
+ <td t="1"><xsl:value-of select="attribute::name"/></td>
+ <xsl:for-each select="//report/days/day">
+ <xsl:variable name="today" select="attribute::number" />
+ <td>
+ <para>
+ <xsl:choose>
+ <xsl:when test="sum(//employee[@id=$id]/time-element[@date=$today]) &lt; 7.5">
+ <xsl:attribute name="style">glande</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="sum(//employee[@id=$id]/time-element[@date=$today]) &lt; 8.5 and sum(//time-element[@date=$today]) &gt;= 7.5">
+ <xsl:attribute name="style">normal_people</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style">esclave</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:value-of select="//employee[@id=$id]/time-element[@date=$today]" />
+ </para>
+ </td>
+ </xsl:for-each>
+ <td>
+ <xsl:value-of select="sum(//employee[@id=$id]/time-element)"/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ <tr>
+ <td>Total</td>
+ <xsl:for-each select="report/days/day">
+ <xsl:variable name="today" select="attribute::number"/>
+ <td t="1"><xsl:value-of select="sum(//time-element[@date=$today])"/></td>
+ </xsl:for-each>
+ <td t="1"><xsl:value-of select="sum(//time-element)"/></td>
+ </tr>
+ </blockTable>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/addons/hr_timesheet/wizard/__init__.py b/addons/hr_timesheet/wizard/__init__.py
new file mode 100644
index 00000000000..1b2720da0f6
--- /dev/null
+++ b/addons/hr_timesheet/wizard/__init__.py
@@ -0,0 +1,30 @@
+##############################################################################
+#
+# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import sign_in_out
+import wizard_print_timesheet
+import wizard_print_timesheet_users
diff --git a/addons/hr_timesheet/wizard/sign_in_out.py b/addons/hr_timesheet/wizard/sign_in_out.py
new file mode 100644
index 00000000000..088155133b4
--- /dev/null
+++ b/addons/hr_timesheet/wizard/sign_in_out.py
@@ -0,0 +1,176 @@
+##############################################################################
+#
+# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+#
+# $Id: sign_in_out.py 2871 2006-04-25 14:08:22Z ged $
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+
+import wizard
+import netsvc
+import time
+
+si_form ='''<?xml version="1.0"?>
+<form string="Sign in / Sign out">
+ <separator string="Sign in" colspan="4"/>
+ <field name="name" readonly="True" />
+ <field name="state" readonly="True" />
+ <field name="server_date"/>
+ <label string="(local time on the server side)" colspan="2"/>
+ <field name="date"/>
+ <label string="(Keep empty for current time)" colspan="2"/>
+</form>'''
+
+si_fields = {
+ 'name': {'string': "Employee's name", 'type':'char', 'required':True, 'readonly':True},
+ 'state': {'string': "Current state", 'type' : 'char', 'required' : True, 'readonly': True},
+ 'date': {'string':"Starting Date", 'type':'datetime'},
+ 'server_date': {'string':"Current Date", 'type':'datetime', 'readonly':True},
+}
+
+so_form = '''<?xml version="1.0" ?>
+<form string="Sign in status">
+ <separator string="General Information" colspan="4" />
+ <field name="name" readonly="True" />
+ <field name="state" readonly="True" />
+ <field name="date_start"/>
+ <field name="server_date"/>
+ <separator string="Work done in the last period" colspan="4" />
+ <field name="account_id" colspan="3"/>
+ <field name="info" colspan="3"/>
+ <field name="date"/>
+ <label string="(Keep empty for current_time)" colspan="2"/>
+ <field name="analytic_amount"/>
+</form>'''
+
+so_fields = {
+ 'name': {'string':"Employee's name", 'type':'char', 'required':True, 'readonly':True},
+ 'state': {'string':"Current state", 'type':'char', 'required':True, 'readonly':True},
+ 'account_id': {'string':"Analytic Account", 'type':'many2one', 'relation':'account.analytic.account', 'required':True, 'domain':"[('type','=','normal')]"},
+ 'info': {'string':"Work Description", 'type':'char', 'size':64, 'required':True},
+ 'date': {'string':"Closing Date", 'type':'datetime'},
+ 'date_start': {'string':"Starting Date", 'type':'datetime', 'readonly':True},
+ 'server_date': {'string':"Current Server Date", 'type':'datetime', 'readonly':True},
+ 'analytic_amount': {'string':"Minimum Analytic Amount", 'type':'float'},
+}
+
+def _get_empid(self, cr, uid, data, context):
+ service = netsvc.LocalService('object_proxy')
+ emp_id = service.execute(cr.dbname, uid, 'hr.employee', 'search', [('user_id', '=', uid)])
+ if emp_id:
+ employee = service.execute(cr.dbname, uid, 'hr.employee', 'read', emp_id)[0]
+ return {'name': employee['name'], 'state': employee['state'], 'emp_id': emp_id[0], 'date':False, 'server_date':time.strftime('%Y-%m-%d %H:%M:%S')}
+ raise wizard.except_wizard('UserError', 'No employee defined for your user !')
+
+def _get_empid2(self, cr, uid, data, context):
+ res = _get_empid(self,cr, uid, data, context)
+ cr.execute('select name,action from hr_attendance where employee_id=%d order by name desc limit 1', (res['emp_id'],))
+ res['server_date'] = time.strftime('%Y-%m-%d %H:%M:%S')
+ res['date_start'] = cr.fetchone()[0]
+ res['info'] = ''
+ res['account_id'] = False
+ return res
+
+def _sign_in_result(self, cr, uid, data, context):
+ service = netsvc.LocalService('object_proxy')
+ emp_id = data['form']['emp_id']
+ try:
+ success = service.execute(cr.dbname, uid, 'hr.employee', 'sign_in', [emp_id], dt=data['form']['date'] or False)
+ except:
+ raise wizard.except_wizard('UserError', 'You tried to sign in with a date anterior to another event !\nTry to contact the administrator to correct attendances.')
+ return {}
+
+def _write(self, cr, uid, data, emp_id, context):
+ service = netsvc.LocalService('object_proxy')
+ hour = (time.mktime(time.strptime(data['form']['date'] or time.strftime('%Y-%m-%d %H:%M:%S'), '%Y-%m-%d %H:%M:%S')) -
+ time.mktime(time.strptime(data['form']['date_start'], '%Y-%m-%d %H:%M:%S'))) / 3600.0
+ minimum = data['form']['analytic_amount']
+ if minimum:
+ hour = round(round((hour + minimum / 2) / minimum) * minimum, 2)
+ res = service.execute(cr.dbname, uid, 'hr.analytic.timesheet', 'default_get', ['product_id','product_uom_id'])
+ if not res['product_uom_id']:
+ raise wizard.except_wizard('UserError', 'No cost unit defined for this employee !')
+ up = service.execute(cr.dbname, uid, 'hr.analytic.timesheet', 'on_change_unit_amount', False, res['product_id'], hour, res['product_uom_id'])['value']
+ res['name'] = data['form']['info']
+ res['account_id'] = data['form']['account_id']
+ res['unit_amount'] = hour
+ res.update(up)
+ return service.execute(cr.dbname, uid, 'hr.analytic.timesheet', 'create', res, context)
+
+def _sign_out_result_end(self, cr, uid, data, context):
+ service = netsvc.LocalService('object_proxy')
+ emp_id = data['form']['emp_id']
+ try:
+ service.execute(cr.dbname, uid, 'hr.employee', 'sign_out', [emp_id], dt=data['form']['date'])
+ except:
+ raise wizard.except_wizard('UserError', 'You tried to sign in with a date anterior to another event !\nTry to contact the administrator to correct attendances.')
+ _write(self, cr, uid, data, emp_id, context)
+ return {}
+
+def _sign_out_result(self, cr, uid, data, context):
+ service = netsvc.LocalService('object_proxy')
+ emp_id = data['form']['emp_id']
+ service.execute(cr.dbname, uid, 'hr.employee', 'sign_change', [emp_id], dt=data['form']['date'])
+ _write(self, cr, uid, data, emp_id, context)
+ return {}
+
+def _state_check(self, cr, uid, data, context):
+ emp_id = _get_empid(self, cr, uid, data, context)['emp_id']
+ # get the latest action (sign_in or out) for this employee
+ cr.execute('select action from hr_attendance where employee_id=%d and action in (\'sign_in\',\'sign_out\') order by name desc limit 1', (emp_id,))
+ res = (cr.fetchone() or ('sign_out',))[0]
+#TODO: invert sign_in et sign_out
+ return res
+
+class wiz_si_so(wizard.interface):
+ states = {
+ 'init' : {
+ 'actions' : [],
+ 'result' : {'type' : 'choice', 'next_state': _state_check}
+ },
+ 'sign_out' : { # this means sign_in...
+ 'actions' : [_get_empid],
+ 'result' : {'type':'form', 'arch':si_form, 'fields' : si_fields, 'state':[('end', 'Cancel'),('si_result', 'Start Working') ] }
+ },
+ 'si_result' : {
+ 'actions' : [_sign_in_result],
+ 'result' : {'type':'state', 'state':'end'}
+ },
+ 'sign_in' : { # this means sign_out...
+ 'actions' : [_get_empid2],
+ 'result' : {'type':'form', 'arch':so_form, 'fields':so_fields, 'state':[('end', 'Cancel'),('so_result', 'Change Work'),('so_result_end', 'Stop Working') ] }
+ },
+ 'so_result' : {
+ 'actions' : [_sign_out_result],
+ 'result' : {'type':'state', 'state':'end'}
+ },
+ 'so_result_end' : {
+ 'actions' : [_sign_out_result_end],
+ 'result' : {'type':'state', 'state':'end'}
+ },
+ }
+wiz_si_so('hr_timesheet.si_so')
+
+# vim:noexpandtab:tw=0
diff --git a/addons/hr_timesheet/wizard/wizard_print_timesheet.py b/addons/hr_timesheet/wizard/wizard_print_timesheet.py
new file mode 100644
index 00000000000..2f1c23c9af9
--- /dev/null
+++ b/addons/hr_timesheet/wizard/wizard_print_timesheet.py
@@ -0,0 +1,63 @@
+##############################################################################
+#
+# Copyright (c) 2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+#
+# $Id$
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import datetime
+
+import wizard
+import netsvc
+
+dates_form = '''<?xml version="1.0"?>
+<form string="Choose your month">
+ <field name="month" />
+ <field name="year" />
+ <field name="user_id" colspan="3" />
+</form>'''
+
+dates_fields = {
+ 'month': dict(string=u'Month', type='selection', required=True, selection=[(x, datetime.date(2000, x, 1).strftime('%B')) for x in range(1, 13)]),
+ 'year': dict(string=u'Year', type=u'integer', required=True),
+ 'user_id' : dict(string=u'User', type='many2one', relation='res.users', required=True),
+}
+
+def _get_value(self, cr, uid, data, context):
+ today = datetime.date.today()
+ return dict(month=today.month, year=today.year, user_id=uid)
+
+class wizard_report(wizard.interface):
+ states = {
+ 'init': {
+ 'actions': [_get_value],
+ 'result': {'type':'form', 'arch':dates_form, 'fields':dates_fields, 'state':[ ('end','Cancel'),('report','Print')]}
+ },
+ 'report': {
+ 'actions': [],
+ 'result': {'type':'print', 'report':'hr.analytical.timesheet', 'state':'end'}
+ }
+ }
+wizard_report('hr.analytical.timesheet')
diff --git a/addons/hr_timesheet/wizard/wizard_print_timesheet_users.py b/addons/hr_timesheet/wizard/wizard_print_timesheet_users.py
new file mode 100644
index 00000000000..cbf238f4987
--- /dev/null
+++ b/addons/hr_timesheet/wizard/wizard_print_timesheet_users.py
@@ -0,0 +1,61 @@
+##############################################################################
+#
+# Copyright (c) 2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+#
+# $Id: wizard_print_timesheet.py 2871 2006-04-25 14:08:22Z ged $
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import wizard
+import datetime
+
+form='''<?xml version="1.0"?>
+<form string="Choose Users">
+ <field name="month"/>
+ <field name="year"/>
+ <field name="user_ids" colspan="3"/>
+</form>'''
+
+fields = {
+ 'month': dict(string=u'Month', type='selection', required=True, selection=[(x, datetime.date(2000, x, 1).strftime('%B')) for x in range(1, 13)]),
+ 'year': dict(string=u'Year', type='integer', required=True),
+ 'user_ids': dict(string=u'Users', type='many2many', relation='res.users', required=True),
+}
+
+def _get_value(self, cr, uid, data, context):
+ today=datetime.date.today()
+ return dict(month=today.month, year=today.year)
+
+class wizard_report(wizard.interface):
+ states={
+ 'init':{
+ 'actions':[_get_value],
+ 'result':{'type':'form', 'arch':form, 'fields':fields, 'state':[('end','Cancel'),('report','Print')]}
+ },
+ 'report':{
+ 'actions':[],
+ 'result':{'type':'print', 'report':'hr.analytical.timesheet_users', 'state':'end'}
+ }
+ }
+wizard_report('hr.analytical.timesheet_users')