def __init__(self, client, server, database, username, password, date_from, date_to): self.log = logger('ReportData') self.date_from = date_from self.date_to = date_to self.dt_from = datetime.strptime(date_from, '%Y-%m-%d') self.dt_to = datetime.strptime(date_to, '%Y-%m-%d') self.duration = (self.dt_to - self.dt_from).days if client != None: self.client = erppeek.Client.from_config(client) else: self.client = erppeek.Client( server, database, username, password) all = ['|', ('active', '=', True), ('active', '=', False)] self.log.info("Load teams") self.teams = self.client.model('hr.team').browse([]) self.team_dict = {t.id: t for t in self.teams} self.log.info("Load employees") self.employees = self.client.model('hr.employee').browse(all) self.employee_dict = {e.id: e for e in self.employees} self.team_filter = None self.log.info("Load contracts") self.contracts = self.client.model('hr.contract').browse([]) self.contract_dict = self._init_contract_dict() self.log.debug(self.contract_dict) self.log.info("Load users") self.users = self.client.model('res.users').browse(all) self.user_dict = {u.id: u for u in self.users} self.log.info("Load projects") project_fields = ["id", "name", "owner_id", 'team_id'] projects = self.client.model('tms.project').read(all, fields=project_fields) self.projects = { Project(p, self.team_dict, self.get_user(p['owner_id'][0])) for p in projects if p['owner_id']} # self.projects = self.fix_projects(projects) self.project_dict = {p.id: p for p in self.projects} self.log.info("Load activities") self.activities = self.client.model('tms.activity').browse(all) self.activity_dict = {a.id: a for a in self.activities} self.log.info("Load Dedicated Resources") DedicatedResource = self.client.model('hr.dedicated.resource.contract') self.dedicated_resources = DedicatedResource.browse([]) self.log.info("Prepare Working Hours Data") self.wh_data = working_hours_data.WorkingHoursData(self) self.log.info("Prepare Profitability Data") self.profitability_data = profitability_data.ProfitabilityData(self)
def __init__(self, vals, team_dict, owner_id): self.log = logger('Project') self.id = vals['id'] self.name = vals['name'] self.owner_id = owner_id if not vals['team_id']: self.log.warning('Team not defined for project %s.', self.name) TEAM_JC_ODOO = 10 self.team_id = team_dict[ vals['team_id'] and vals['team_id'][0] or TEAM_JC_ODOO]
def __init__(self, report_data): self.log = logger('ProfitabilityData') self.report_data = report_data self.profitability_dict = self._init_profitability_dict() self.tickets = self._init_ticket() self._set_ticket_workload_produced_time_spent() self._set_support_budget() self._set_time_spent() self._set_dedicated_resource()
def __init__(self, vals): self.log = logger('Profitability') project = vals.get('project', None) if project: self.team_id = project.team_id self.project_name = project.name else: self.team_id = vals.get('team_id', None) self.project_name = vals.get('project_name', None) self.ticket_workload = vals.get('ticket_workload', 0) self.ticket_time_spent = vals.get('ticket_time_spent', 0) self.support_budget = vals.get('support_budget', 0) self.dedicated_resource = vals.get('dedicated_resource', 0) self.project_time_spent = vals.get('project_time_spent', 0) self.team_time_spent = vals.get('team_time_spent', 0) self.trobz_time_spent = vals.get('trobz_time_spent', 0) self.project_weight = vals.get('project_weight', 0)
def run(client, date_from, date_to): ''' Rerports for appraisal results for quarterly bonus based on create_date ''' log = logger('Appraisal') APPRAISAL_TEMPLATE = 'Trobz - HR - Quarterly Bonus Appraisal' client = erppeek.Client.from_config(client) if date_from: date_from = datetime.strptime(date_from, '%Y-%m-%d') else: date_from = datetime.now() + relativedelta(days=-15) if date_to: date_to = datetime.strptime(date_to, '%Y-%m-%d') else: date_to = datetime.now() InputLines = client.model('hr.appraisal.input.line') # Employee = client.model('hr.employee') input_lines = InputLines.browse( [('create_date', '>=', date_from.strftime('%Y-%m-%d')), ('create_date', '<=', date_to.strftime('%Y-%m-%d')), ('input_id.appraisal_id.template_evaluator_id.name', '=', APPRAISAL_TEMPLATE)], # order='input_id.appraisal_id.employee_id.name,question_id.sequence') order='input_id,question_id') log.info("Found %s input lines.", len(input_lines)) questions = client.model('hr.appraisal.question').browse( [('template_id.name', '=', APPRAISAL_TEMPLATE)], order='sequence') log.info("Questions:") for q in questions: log.info("- %s", q.name) write_result(log, prepare_rows(log, input_lines, questions), questions)
def run(client, server, database, username, password, date_from, date_to): ''' Geneates the performance reports, date must use the format yyyy-mm-dd. ''' log = logger('run') log.info('client: %s', client) log.info('server: %s', server) log.info('database: %s', database) log.info('username: %s', username) log.info('password: %s', password) log.info('date_from: %s', date_from) log.info('date_to: %s', date_to) my_data = report_data.ReportData(client, server, database, username, password, date_from, date_to) report_filename = ('performance_report (%s to %s).xlsx' % (date_from, date_to)) report = report_writer.ReportWriter(report_filename) cols = [20, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15] def add_sheet(ws='Trobz'): worksheet = report_writer.WorkSheetWriter(report, ws, column_widths=cols) my_data.profitability_data.write_project_profitability(worksheet) my_data.profitability_data.write_team_profitability(worksheet) my_data.profitability_data.write_trobz_profitability(worksheet) my_data.wh_data.write_missing_working_hours(worksheet) add_sheet() for team_id, team in my_data.team_dict.iteritems(): my_data.team_filter = team_id add_sheet(team.name) report.close() log.success('Report "%s" generated!', report_filename)
def __init__(self, report_data): self.log = logger('WorkingHoursData') self.report_data = report_data WH = self.report_data.client.model('tms.working.hour') wh_fields = [ "id", "employee_id", "project_id", "tms_activity_id", "duration_hour", "date" ] whs = WH.read([('date', '>=', self.report_data.date_from), ('date', '<=', self.report_data.date_to)], fields=wh_fields) self.whs = [WorkingHour(w) for w in whs] self.wh_e_dict, self.wh_p_dict = self._get_wh_dicts() self.missing_whs = self._get_missing_working_hours( self.report_data.employees, self.report_data.dt_from, self.report_data.dt_to)
# Description: Analyze the reopening type of a user since the beginning of his # work to now. # Usage: # $ python analyze_reopening_reason.py tms-production {user login} import erppeek from operator import itemgetter from collections import OrderedDict import os import re import sys from trobz.log import init_logger, logger init_logger() log = logger('analyze.reopening.reason') if len(sys.argv) < 3: log.error('Missing argument. Usage ' '`python analyze_reopening_reason.py {env} {user login}`') exit(os.EX_USAGE) client = erppeek.Client.from_config(sys.argv[1]) User = client.model('res.users') user_login = sys.argv[2] target_user = User.browse([('login', '=', user_login)]) if not target_user: log.error('Cannot find user with login %s' % user_login) exit(os.EX_NOTFOUND) user_id = target_user.id[0]
def run(client, date_to, date_from, order_by): ''' Analyze capacity vs productivity, dates in format yyyy-mm-dd. ''' log = logger('Employee Info') client = erppeek.Client.from_config(client) if date_to: date_to = datetime.strptime(date_to, '%Y-%m-%d') else: date_to = (datetime.now() + relativedelta(weekday=calendar.SATURDAY) + relativedelta(days=-7)) if date_from: date_from = datetime.strptime(date_from, '%Y-%m-%d') else: date_from = date_to + relativedelta(days=-7) duration = (date_to - date_from).days work_hours = 8 * duration * 20 / 30 duration_str = "From %s to %s" % (date_from.strftime('%Y-%m-%d'), date_to.strftime('%Y-%m-%d')) log.info("Analysis: " + duration_str) Project = client.model('tms.project') Users = client.model('res.users') Employee = client.model('hr.employee') Capacity = client.model('hr.employee.capacity') Ticket = client.model('tms.forge.ticket') Partner = client.model('res.partner') projects = Project.browse([('active', 'in', (True, False))]) employees = Employee.browse([]) capacities = Capacity.browse([('employee_id.active', '=', True)]) capacity_dict = {} for c in capacities: employee_id = c.employee_id.name if employee_id in capacity_dict: if c.starting_date < capacity_dict[employee_id].starting_date: continue capacity_dict[employee_id] = c log.info("%s active Employee Capacities.", len(capacity_dict)) tickets = Ticket.browse([ ('completion_date', '>=', date_from.strftime('%Y-%m-%d')), ('completion_date', '<=', date_to.strftime('%Y-%m-%d')) ]) productivity_dict = {} for t in tickets: employee_id = t.developer_id.employee_id.name if employee_id in productivity_dict: productivity_dict[employee_id] += t.development_time else: productivity_dict[employee_id] = t.development_time # Check missing capacities for employee in employees: if 'Technical' in employee.job_id.name: if employee.name not in capacity_dict: log.warning("%s does not have a capacity set.", employee.name) # Measure total, team capacities, job capacities total_capacity = 0 total_productivity = 0 team_capacity = {} job_capacity = {} capacity_employee_lines = [] for k, c in capacity_dict.iteritems(): job = c.employee_id.job_id.name team = c.employee_id.team_id.name capa = c.production_rate / 100 * work_hours productivity = productivity_dict.get(k, 0) capacity_employee_lines.append([ team, k, job, str(round(c.production_rate * 8 / 100, 1)), str(capa), str(productivity), str_ratio(productivity, capa) ]) total_capacity += c.production_rate / 100 total_productivity += productivity _add_capacity_info(job, job_capacity, c, productivity) _add_capacity_info(team, team_capacity, c, productivity) log.separator("Analysis per employee %s" % duration_str) capacity_employee_header = [ "Team", "Employee", "Job", "Daily Capacity", 'Capacity', 'Productivity', "Ratio" ] def getKey(item): if order_by == 'team': return (item[0], item[1]) elif order_by == 'name': return (item[1], item[2], item[0]) elif order_by == 'job': return (item[2], item[0], item[1]) else: raise "Order by not recognized" log.table( sorted(capacity_employee_lines, key=getKey), capacity_employee_header, ) def getOrderGroup(item): return item[0] def _log_result(name, results): header = [ name, 'Daily Capacity', 'Technical Members', 'Average Capacity', 'Capacity', 'Productivity', "Ratio" ] result_list = [] for k, v in results.iteritems(): capa = v['capacity'] * work_hours result_list.append([ k, str(v['capacity']), str(v['count']), str(round(capa / v['count'], 1)), str(capa), str(v['productivity']), str_ratio(v['productivity'], capa) ]) log.separator("Analysis per %s %s " % (name, duration_str)) log.table(sorted(result_list, key=getOrderGroup), header) _log_result("Job", job_capacity) _log_result("Team", team_capacity) log.separator("Overall " + duration_str) header = [ "Daily Capacity", "Technical Members", "Average Capacity in Technical positions", "Capacity", "Productivity", "Ratio" ] results = [[ str(total_capacity * 8), str(len(capacity_dict)), str(round(total_capacity * 8 / len(capacity_dict), 2)), str(total_capacity * work_hours), str(total_productivity), str_ratio(total_productivity, total_capacity * work_hours) ]] log.table(results, header) log.info("Daily Capacity reflects a ratio to working days. " "For instance a capacity of 12 represents 12 days of workload " "can be produced within 1 working day.") log.info("The columns 'Capaciy', 'Productivity' and 'Ratio' are calculated" " for the period of analysis: %s" % duration_str)
#!/usr/bin/env python # -*- coding: utf-8 -*- import click import csv import erppeek from trobz.log import init_logger, logger import sys log = logger('run') init_logger(colored=True, formatter='simple') class Ticket: def __init__(self, client, line): self.client = client self.line = line self.functional_block_id = None self.summary = None self.workload_char = None self.milestone_id = None self.description = None self.owner_id = None self.reporter_id = None self.project_id = None self.activity_id = None self.customer_id = None # Only case when we should use this script self.ticket_type = 'initial_project' self.quotation_approved = False
def __init__(self, wb_file_name): self.wb = xlsxwriter.Workbook(wb_file_name) self.log = logger('ReportWriter') self._set_styles()