[IMP]: Removed pageSize from report rml as it will be taken from company paper format;
[odoo/odoo.git] / addons / hr_attendance / report / attendance_by_month.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 #
20 ##############################################################################
21
22 import time
23 from datetime import datetime, timedelta
24 from dateutil.relativedelta import relativedelta
25 import netsvc
26 import pooler
27
28 from report.interface import report_rml
29 from report.interface import toxml
30
31 from report import report_sxw
32 from tools import ustr
33 from tools.translate import _
34
35 one_day = relativedelta(days=1)
36 month2name = [0, 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
37
38 def hour2str(h):
39     hours = int(h)
40     minutes = int(round((h - hours) * 60, 0))
41     return '%02dh%02d' % (hours, minutes)
42
43 def lengthmonth(year, month):
44     if month == 2 and ((year % 4 == 0) and ((year % 100 != 0) or (year % 400 == 0))):
45         return 29
46     return [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
47
48 class report_custom(report_rml):
49
50     def create_xml(self, cr, uid, ids, datas, context=None):
51         obj_emp = pooler.get_pool(cr.dbname).get('hr.employee')
52         if context is None:
53             context = {}
54         month = datetime(datas['form']['year'], datas['form']['month'], 1)
55         emp_ids = context.get('active_ids', [])
56         user_xml = ['<month>%s</month>' % _(month2name[month.month]), '<year>%s</year>' % month.year]
57         if emp_ids:
58             for emp in obj_emp.read(cr, uid, emp_ids, ['name']):
59                 stop, days_xml = False, []
60                 user_repr = '''
61                 <user>
62                   <name>%s</name>
63                   %%s
64                 </user>
65                 ''' % (ustr(toxml(emp['name'])))
66                 today, tomor = month, month + one_day
67                 while today.month == month.month:
68                     #### Work hour calculation
69                     sql = '''
70                     select action, att.name
71                     from hr_employee as emp inner join hr_attendance as att
72                          on emp.id = att.employee_id
73                     where att.name between %s and %s and emp.id = %s
74                     order by att.name
75                     '''
76                     cr.execute(sql, (today.strftime('%Y-%m-%d %H:%M:%S'), tomor.strftime('%Y-%m-%d %H:%M:%S'), emp['id']))
77                     attendences = cr.dictfetchall()
78                     wh = 0.0
79                     # Fake sign ins/outs at week ends, to take attendances across week ends into account
80                     if attendences and attendences[0]['action'] == 'sign_out':
81                         attendences.insert(0, {'name': today.strftime('%Y-%m-%d %H:%M:%S'), 'action':'sign_in'})
82                     if attendences and attendences[-1]['action'] == 'sign_in':
83                         attendences.append({'name': tomor.strftime('%Y-%m-%d %H:%M:%S'), 'action':'sign_out'})
84                     # sum up the attendances' durations
85                     ldt = None
86                     for att in attendences:
87                         dt = datetime.strptime(att['name'], '%Y-%m-%d %H:%M:%S')
88                         if ldt and att['action'] == 'sign_out':
89                             wh += (float((dt - ldt).seconds)/60/60)
90                         else:
91                             ldt = dt
92                     # Week xml representation
93                     wh = hour2str(wh)
94                     today_xml = '<day num="%s"><wh>%s</wh></day>' % ((today - month).days+1, (wh))
95                     dy=(today - month).days+1
96                     days_xml.append(today_xml)
97                     today, tomor = tomor, tomor + one_day
98                 user_xml.append(user_repr % '\n'.join(days_xml))
99                 
100         rpt_obj = pooler.get_pool(cr.dbname).get('hr.employee')
101         rml_obj=report_sxw.rml_parse(cr, uid, rpt_obj._name,context)
102         header_xml = '''
103         <header>
104         <date>%s</date>
105         <company>%s</company>
106         </header>
107         ''' % (str(rml_obj.formatLang(time.strftime("%Y-%m-%d"),date=True))+' ' + str(time.strftime("%H:%M")),pooler.get_pool(cr.dbname).get('res.users').browse(cr,uid,uid).company_id.name)
108        
109         first_date = str(month)
110         som = datetime.strptime(first_date, '%Y-%m-%d %H:%M:%S')
111         eom = som + timedelta(int(dy)-1)
112         day_diff=eom-som
113         date_xml=[]
114         cell=1
115         date_xml.append('<days>')
116         if day_diff.days>=30:
117             date_xml += ['<dayy number="%d" name="%s" cell="%d"/>' % (x, _(som.replace(day=x).strftime('%a')),x-som.day+1) for x in range(som.day, lengthmonth(som.year, som.month)+1)]
118         else:
119             if day_diff.days>=(lengthmonth(som.year, som.month)-som.day):
120                 date_xml += ['<dayy number="%d" name="%s" cell="%d"/>' % (x, _(som.replace(day=x).strftime('%a')),x-som.day+1) for x in range(som.day, lengthmonth(som.year, som.month)+1)]
121             else:
122                 date_xml += ['<dayy number="%d" name="%s" cell="%d"/>' % (x, _(som.replace(day=x).strftime('%a')),x-som.day+1) for x in range(som.day, eom.day+1)]
123         cell=x-som.day+1
124         day_diff1=day_diff.days-cell+1
125         width_dict={}
126         month_dict={}
127         i=1
128         j=1
129         year=som.year
130         month=som.month
131         month_dict[j]=som.strftime('%B')
132         width_dict[j]=cell
133         
134         while day_diff1>0:
135             if month+i<=12:
136                 if day_diff1 > lengthmonth(year,i+month): # Not on 30 else you have problems when entering 01-01-2009 for example
137                     som1=datetime.date(year,month+i,1)
138                     date_xml += ['<dayy number="%d" name="%s" cell="%d"/>' % (x, _(som1.replace(day=x).strftime('%a')),cell+x) for x in range(1, lengthmonth(year,i+month)+1)]
139                     i=i+1
140                     j=j+1
141                     month_dict[j]=som1.strftime('%B')
142                     cell=cell+x
143                     width_dict[j]=x
144                 else:
145                     som1=datetime.date(year,month+i,1)
146                     date_xml += ['<dayy number="%d" name="%s" cell="%d"/>' % (x, _(som1.replace(day=x).strftime('%a')),cell+x) for x in range(1, eom.day+1)]
147                     i=i+1
148                     j=j+1
149                     month_dict[j]=som1.strftime('%B')
150                     cell=cell+x
151                     width_dict[j]=x
152                 day_diff1=day_diff1-x
153             else:
154                 years=year+1
155                 year=years
156                 month=0
157                 i=1
158                 if day_diff1>=30:
159                     som1=datetime.date(years,i,1)
160                     date_xml += ['<dayy number="%d" name="%s" cell="%d"/>' % (x, _(som1.replace(day=x).strftime('%a')),cell+x) for x in range(1, lengthmonth(years,i)+1)]
161                     i=i+1
162                     j=j+1
163                     month_dict[j]=som1.strftime('%B')
164                     cell=cell+x
165                     width_dict[j]=x
166                 else:
167                     som1=datetime.date(years,i,1)
168                     i=i+1
169                     j=j+1
170                     month_dict[j]=som1.strftime('%B')
171                     date_xml += ['<dayy number="%d" name="%s" cell="%d"/>' % (x, _(som1.replace(day=x).strftime('%a')),cell+x) for x in range(1, eom.day+1)]
172                     cell=cell+x
173                     width_dict[j]=x
174                 day_diff1=day_diff1-x
175         date_xml.append('</days>')
176         date_xml.append('<cols>3.5cm%s</cols>\n' % (',0.74cm' * (int(dy))))
177         xml = '''<?xml version="1.0" encoding="UTF-8" ?>
178         <report>
179         %s
180         <title>%s</title>
181         %s
182         %s
183         </report>
184         ''' % (header_xml,_('Attendances By Month'),'\n'.join(user_xml),date_xml)
185         return xml
186
187 report_custom('report.hr.attendance.bymonth', 'hr.employee', '', 'addons/hr_attendance/report/bymonth.xsl')
188
189 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: