Example #1
0
    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)
Example #2
0
 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]
Example #3
0
    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()
Example #4
0
    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)
Example #7
0
    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)
Example #8
0
# 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]
Example #9
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)
Example #10
0
#!/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
Example #11
0
 def __init__(self, wb_file_name):
     self.wb = xlsxwriter.Workbook(wb_file_name)
     self.log = logger('ReportWriter')
     self._set_styles()