diff options
| author | pinky <> | 2006-12-07 13:41:40 +0000 |
|---|---|---|
| committer | pinky <> | 2006-12-07 13:41:40 +0000 |
| commit | a83dce15e0f33145b2eea7e878ae7eacf3aba90a (patch) | |
| tree | a3d1399cbfebf7d90a8894d97c9b7e0a9d881960 /addons/hr_timesheet | |
| parent | 004a0b996ff8f269451e07346f71a129a1f3fbaf (diff) | |
New trunk
bzr revid: pinky-dedd7f8a42bd4557112a0513082691b8590ad6cc
Diffstat (limited to 'addons/hr_timesheet')
| -rw-r--r-- | addons/hr_timesheet/__init__.py | 3 | ||||
| -rw-r--r-- | addons/hr_timesheet/__terp__.py | 14 | ||||
| -rw-r--r-- | addons/hr_timesheet/hr.analytic.timesheet.csv | 0 | ||||
| -rw-r--r-- | addons/hr_timesheet/hr_timesheet.py | 114 | ||||
| -rw-r--r-- | addons/hr_timesheet/hr_timesheet_data.xml | 10 | ||||
| -rw-r--r-- | addons/hr_timesheet/hr_timesheet_demo.xml | 35 | ||||
| -rw-r--r-- | addons/hr_timesheet/hr_timesheet_report.xml | 37 | ||||
| -rw-r--r-- | addons/hr_timesheet/hr_timesheet_view.xml | 103 | ||||
| -rw-r--r-- | addons/hr_timesheet/hr_timesheet_wizard.xml | 8 | ||||
| -rw-r--r-- | addons/hr_timesheet/report/__init__.py | 2 | ||||
| -rw-r--r-- | addons/hr_timesheet/report/user_timesheet.py | 95 | ||||
| -rw-r--r-- | addons/hr_timesheet/report/user_timesheet.xsl | 133 | ||||
| -rw-r--r-- | addons/hr_timesheet/report/users_timesheet.py | 100 | ||||
| -rw-r--r-- | addons/hr_timesheet/report/users_timesheet.xsl | 124 | ||||
| -rw-r--r-- | addons/hr_timesheet/wizard/__init__.py | 30 | ||||
| -rw-r--r-- | addons/hr_timesheet/wizard/sign_in_out.py | 176 | ||||
| -rw-r--r-- | addons/hr_timesheet/wizard/wizard_print_timesheet.py | 63 | ||||
| -rw-r--r-- | addons/hr_timesheet/wizard/wizard_print_timesheet_users.py | 61 |
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]) < 7.5"> + <xsl:attribute name="style">glande</xsl:attribute> + </xsl:when> + <xsl:when test="sum(//time-element[@date=$today]) < 8.5 and sum(//time-element[@date=$today]) >= 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]) < 7.5"> + <xsl:attribute name="style">glande</xsl:attribute> + </xsl:when> + <xsl:when test="sum(//employee[@id=$id]/time-element[@date=$today]) < 8.5 and sum(//time-element[@date=$today]) >= 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') |
