예제 #1
0
class CRMLeadStageHistory(models.Model):
    _name = 'crm.lead.stage.history'

    @api.one
    @api.depends('date', 'lead_id')
    def _compute_value(self):
        last_history = self.search([
            ('lead_id', '=', self.lead_id.id),
            ('date', '<', self.date)], order='date DESC', limit=1)
        if last_history:
            now = datetime.strptime(self.date,
                                    DEFAULT_SERVER_DATETIME_FORMAT)
            last = datetime.strptime(last_history.date,
                                     DEFAULT_SERVER_DATETIME_FORMAT)
            self.value = (((now - last).days * 24.0 * 60.0) +
                          (now - last).seconds / 60.0) / 60.0
        else:
            self.value = 0.0

    stage_from_id = Many2one('crm.case.stage', 'Stage from',
                             select=True, copy=False)
    stage_to_id = Many2one('crm.case.stage', 'Stage to',
                           select=True, copy=False)
    date = fields.Datetime(
        'Date', default=lambda self: fields.Datetime.now(), required=True)
    lead_id = fields.Many2one('crm.lead', 'Lead', required=True)
    value = fields.Float('Value', store=True, compute='_compute_value')
예제 #2
0
파일: calendar.py 프로젝트: sc4you/online
class calendar_event(osv.osv):
    _inherit = 'calendar.event'
    # If we do not want to set a default value for category_id but still be able to install this addon in an existing
    # Database we could use the  _auto_init or even better the init method to execute an SQL query and prepopulate the
    # table - see addon website_sale_categories for an example
    # https://www.odoo.com/es_ES/forum/help-1/question/is-there-a-way-to-set-a-value-for-a-field-for-all-existing-records-in-the-database-at-addon-installation-only-89400
    # https://gist.github.com/lepistone/3ca65107fc7344440777

    @api.model
    def _get_category(self):
        category = self.env.ref("calendar_category.category_generalactivity", raise_if_not_found=False)
        if not category:
            category = self.env['calendar.event.category'].search([], limit=1, order='id')
        return category

    no_invitations = Boolean(string='No invitation e-mails!', help='Do not send invitation e-mails!', default=True)
    odometer_start = Integer(string='Odometer at start')
    odometer_finish = Integer(string='Odometer at finish')
    category_id = Many2one('calendar.event.category', string='Category', required=True,
                           default=lambda self: self._get_category())
    meeting_minutes = Text('Internal Meeting Minutes')
    mainpartner_id = Many2one('res.partner', string='Main Partner')

    @api.onchange('mainpartner_id')
    def _add_attendee(self):
        if self.mainpartner_id:
            # http://odoo-new-api-guide-line.readthedocs.org/en/latest/environment.html#the-ids-attribute
            # http://www.mindissoftware.com/2014/11/07/Understand-Odoo-Model-Part1
            # https://github.com/odoo/odoo/issues/2693
            # https://www.odoo.com/fr_FR/forum/help-1/question/how-to-add-records-in-many2many-field-82878
            # https://www.odoo.com/fr_FR/forum/help-1/question/how-to-insert-value-to-a-one2many-field-in-table-with-create-method-28714
            # https://www.odoo.com/fr_FR/forum/help-1/question/insert-new-record-into-one2many-field-20931
            self.partner_ids = [(4, self.mainpartner_id.id)]
예제 #3
0
파일: wizard.py 프로젝트: sc4you/online
class ReplaceCategoryWizard(models.TransientModel):
    _name = 'calendar_log.replace_eventcategory_wizard'

    category_old_id = Many2one('calendar.event.category',
                               string='Old Category')
    category_new_id = Many2one('calendar.event.category',
                               string='Replaced by Category')

    @api.multi
    def replace_category(self):

        # Replace the old category in every calendar.event with the new one
        events = self.env['calendar.event'].search([('category_id', '=',
                                                     self.category_old_id.id)])
        for event in events:
            event.category_id = self.category_new_id

        # Do not store any reference to the Categories or they can not be deleted (seems like a odoo bug to mee):
        oldcatid = self.category_old_id.id
        self.category_old_id = False
        self.category_new_id = False

        # Remove the old category
        self.env['calendar.event.category'].browse(oldcatid).unlink()
        return {}
예제 #4
0
class HrAttendance(models.Model):
    _inherit = 'hr.attendance'

    calendar_event_sign_in_ids = One2many(string="Calendar SignIn",
                                          comodel_name="calendar.event",
                                          inverse_name="sign_in_id")
    calendar_event_sign_out_ids = One2many(string="Calendar SignOut",
                                           comodel_name="calendar.event",
                                           inverse_name="sign_out_id")
    calendar_timelog_event = Many2one(string="Calendar Event",
                                      comodel_name='calendar.event',
                                      compute='_calendar_timelog_event',
                                      readonly=True)

    @api.depends('calendar_event_sign_in_ids', 'calendar_event_sign_out_ids')
    def _calendar_timelog_event(self):
        for r in self:
            if r.calendar_event_sign_in_ids:
                r.calendar_timelog_event = r.calendar_event_sign_in_ids[0]
            elif r.calendar_event_sign_out_ids:
                r.calendar_timelog_event = r.calendar_event_sign_out_ids[0]
            else:
                r.calendar_timelog_event = False
예제 #5
0
파일: calendar.py 프로젝트: sc4you/online
class calendar_event(osv.osv):
    _inherit = 'calendar.event'

    is_worklog = Boolean(string='Is Worklog', help='Create a Work-Log Entry', default=False)
    project_id = Many2one('project.project', string='Project')
    task_id = Many2one('project.task', string='Task')
    worklog_text = Char('Work-Log', size=128)
    task_work_id = Many2one('project.task.work', string='Task Worklog ID')
    analytic_time_id = Many2one('hr.analytic.timesheet', string='HR Analytic Timesheet ID')

    # DISABLED FOR NOW Update the field event_category_id at installation or update
    # def init(self, cr, context=None):
    #     print "INIT OF calendar_log_project"
    #     events = self.browse(cr, SUPERUSER_ID, self.search(cr, SUPERUSER_ID, []))
    #     for event in events:
    #         # We trigger the write method at install or update time for all events to update the event_category_id
    #         event.write({"name": event.name or None})

    @api.onchange('category_id')
    def _set_worklog(self):
        if self.category_id:
            self.is_worklog = self.category_id.is_worklog

    @api.onchange('task_id')
    def _set_project(self):
        if self.task_id:
            # Set the Project to the project_id of the Task
            if self.project_id != self.task_id.project_id:
                self.project_id = self.task_id.project_id
            # Set the Main Partner to the task or project partner
            if not self.mainpartner_id:
                if self.task_id.partner_id:
                    self.mainpartner_id = self.task_id.partner_id
                elif self.project_id.partner_id:
                    self.mainpartner_id = self.project_id.partner_id

    @api.onchange('project_id')
    def _set_task(self):
        # https://github.com/odoo/odoo/issues/4574
        if self.project_id:
            # Clear the Task if it has a different project_id
            if self.task_id:
                if self.task_id.project_id != self.project_id:
                    self.task_id = False

            # Try to set the Main Partner
            if not self.mainpartner_id:
                if self.task_id and self.task_id.partner_id:
                    self.mainpartner_id = self.task_id.partner_id
                elif self.project_id.partner_id:
                    self.mainpartner_id = self.project_id.partner_id

            # Set a domain for the task list to only show tasks that belong to this project
            return {'domain': {'task_id': [('project_id', '=', self.project_id.id)]}}
        else:
            # Clear the Domain for Tasks if no Project is selected
            return {'domain': {'task_id': []}}

    @api.multi
    def write(self, values):
        # Unlink any existing task_work_id if task has changed
        # So we force a task_work_id create which will create a new task_work_id.hr_analytic_timesheet_id!
        if 'task_id' in values and self.task_work_id and self.ensure_one():
            self.task_work_id.hr_analytic_timesheet_id.unlink()
            self.task_work_id.unlink()

        res = super(calendar_event, self).write(values)

        if res and self.ensure_one():
            # Create or Update related hr.analytic.timesheet entries
            if self.is_worklog and (self.task_id or self.project_id):
                if self.task_id:
                    # Create or update Task Work Log
                    values_worklog = {
                        'name': self.worklog_text or self.name,
                        'user_id': self.user_id.id,
                        'date': self.start_datetime,
                        'hours': self.duration,
                        'task_id': self.task_id.id,
                    }
                    # UNLINK hr.analytic.timesheet
                    if self.analytic_time_id:
                        self.analytic_time_id.unlink()

                    # CREATE (No Worklog exists)
                    if not self.task_work_id:
                        self.task_work_id = self.task_id.work_ids.create(values_worklog)

                    # UPDATE (Worklog exists - relinks to new task if changed)
                    else:
                        self.task_work_id.write(values_worklog)

                    # Update the related hr.analytic.timesheet of the task_work_id with event_category_id
                    self.task_work_id.hr_analytic_timesheet_id.write({'event_category_id': self.category_id.id, })

                elif self.project_id:
                    # Get the Values for hr.analytic.timesheet
                    time_obj = self.env['hr.analytic.timesheet']
                    values_hr_line = {
                        'name': self.worklog_text or self.name,
                        'user_id': self.user_id.id,
                        'date': self.start_datetime,
                        'unit_amount': self.duration,
                        'account_id': self.project_id.analytic_account_id.id,
                        'journal_id': time_obj._getAnalyticJournal(context={'user_id': self.user_id.id}),
                        'product_id': time_obj._getEmployeeProduct(context={'user_id': self.user_id.id}),
                        'product_uom_id': time_obj._getEmployeeUnit(context={'user_id': self.user_id.id}),
                        'general_account_id': time_obj._getGeneralAccount(context={'user_id': self.user_id.id}),
                        'event_category_id': self.category_id.id,
                    }
                    # Recheck the UOM and recalculate if needed
                    default_uom = self.env['res.users'].browse(self.user_id.id).company_id.project_time_mode_id.id
                    if values_hr_line['product_uom_id'] != default_uom:
                        values_hr_line['unit_amount'] = self.pool['product.uom']._compute_qty(default_uom, values_hr_line['unit_amount'], values_hr_line['product_uom_id'])

                    if self.task_work_id:
                        # Unlink task worklog
                        self.task_work_id.unlink()

                    if not self.analytic_time_id:
                        # Create analytic timeline entry
                        self.analytic_time_id = self.analytic_time_id.create(values_hr_line)
                    else:
                        # Update analytic timeline entry
                        self.analytic_time_id.write(values_hr_line)
            else:
                # UNLINK Work Logs
                if self.task_work_id:
                    self.task_work_id.unlink()
                if self.analytic_time_id:
                    self.analytic_time_id.unlink()

        return res

    @api.multi
    def unlink(self):
        for event in self:
            if event.task_work_id:
                event.task_work_id.unlink()
            if event.analytic_time_id:
                event.analytic_time_id.unlink()
        return super(calendar_event, self).unlink()
예제 #6
0
파일: calendar.py 프로젝트: sc4you/online
class hr_timesheet_sheet_sheet_day_cat_detail(osv.osv):
    _name = "hr_timesheet_sheet.sheet.day_cat_detail"
    _description = "Category by Days in Period"
    _auto = False
    _order = 'name'

    # Fields:
    name = Date(string='Date', readonly='True')
    timesheet_id = Many2one(comodel_name='hr_timesheet_sheet.sheet', string='Timesheet')
    employee_id = Many2one(comodel_name='hr.employee', string='Employee')

    ga = Float(string="GA", readonly='True')
    ga_e = Float(string="GA Expense", readonly='True')
    ga_a = Float(string="GA Abroad", readonly='True')
    ga_ae = Float(string="GA Abroad Expense", readonly='True')

    cm = Float(string="CM", readonly='True')
    cm_e = Float(string="CM Expense", readonly='True')
    cm_a = Float(string="CM Abroad", readonly='True')
    cm_ae = Float(string="CM Abroad Expense", readonly='True')

    t = Float(string="T", readonly='True')
    t_e = Float(string="T Expense", readonly='True')
    t_a = Float(string="T Abroad", readonly='True')
    t_ae = Float(string="T Abroad Expense", readonly='True')

    os = Float(string="OS", readonly='True')
    os_e = Float(string="OS Expense", readonly='True')
    os_a = Float(string="OS Abroad", readonly='True')
    os_ae = Float(string="OS Abroad Expense", readonly='True')

    sum_e = Float(string="Expense", readonly='True')
    sum_a = Float(string="Abroad", readonly='True')
    sum_ae = Float(string="Abroad Expense", readonly='True')

    # Sum of the events categories per day
    def init(self, cr):
        tools.drop_view_if_exists(cr, 'hr_timesheet_sheet_sheet_day_cat_detail')
        cr.execute(""" CREATE OR REPLACE VIEW hr_timesheet_sheet_sheet_day_cat_detail as (
            select
                 ts.id * 100000 + ((period.day::date - ts.date_from::timestamp::date) + 1) AS id
                ,ts.id timesheet_id
                ,ts.employee_id
                ,ts.user_id
                ,period.day as name
                ,count(distinct e.id)
                ,sum(case when cc.name = 'GENERAL ACTIVITY' then e.duration else 0 end) ga
                ,sum(case when cc.name = 'GENERAL ACTIVITY > Expense Entitled' then e.duration else 0 end) ga_e
                ,sum(case when cc.name = 'GENERAL ACTIVITY > Abroad' then e.duration else 0 end) ga_a
                ,sum(case when cc.name = 'GENERAL ACTIVITY > Abroad > Expense Entitled' then e.duration else 0 end) ga_ae
                ,sum(case when cc.name = 'CUSTOMER MEETING' then e.duration else 0 end) cm
                ,sum(case when cc.name = 'CUSTOMER MEETING > Expense Entitled' then e.duration else 0 end) cm_e
                ,sum(case when cc.name = 'CUSTOMER MEETING > Abroad' then e.duration else 0 end) cm_a
                ,sum(case when cc.name = 'CUSTOMER MEETING > Abroad > Expense Entitled' then e.duration else 0 end) cm_ae
                ,sum(case when cc.name = 'TRIP' then e.duration else 0 end) t
                ,sum(case when cc.name = 'TRIP > Expense Entitled' then e.duration else 0 end) t_e
                ,sum(case when cc.name = 'TRIP > Abroad' then e.duration else 0 end) t_a
                ,sum(case when cc.name = 'TRIP > Abroad > Expense Entitled' then e.duration else 0 end) t_ae
                ,sum(case when cc.name = 'OVERNIGHT STAY > Expense Entitled' then e.duration else 0 end) os_e
                ,sum(case when cc.name = 'OVERNIGHT STAY > Abroad' then e.duration else 0 end) os_a
                ,sum(case when cc.name = 'OVERNIGHT STAY > Abroad > Expense Entitled' then e.duration else 0 end) os_ae
                ,sum(case when cc.name = 'OVERNIGHT STAY' then e.duration else 0 end) os
                -- ,sum(case when cc.name like '%Expense%' then e.duration else 0 end) sum_exp
                -- ,sum(case when cc.name like '%Abroad%' then e.duration else 0 end) sum_abr
                ,sum(case when cc.name in ( 'GENERAL ACTIVITY > Expense Entitled'
                                           ,'CUSTOMER MEETING > Expense Entitled'
                                           ,'TRIP > Expense Entitled'
                                            ) then e.duration else 0 end) sum_e
                ,sum(case when cc.name in ( 'GENERAL ACTIVITY > Abroad'
                                           ,'CUSTOMER MEETING > Abroad'
                                           ,'TRIP > Abroad'
                                            ) then e.duration else 0 end) sum_a
                ,sum(case when cc.name in ( 'GENERAL ACTIVITY > Abroad > Expense Entitled'
                                           ,'CUSTOMER MEETING > Abroad > Expense Entitled'
                                           ,'TRIP > Abroad > Expense Entitled'
                                            ) then e.duration else 0 end) sum_ae
                ,p.name partner_name
            from   hr_timesheet_sheet_sheet ts
            inner join res_users u
                on u.id = ts.user_id
            inner join res_partner p
                on p.id = u.partner_id
            cross join generate_series(ts.date_from::timestamp without time zone, ts.date_to::timestamp without time zone, '1 day'::interval) period(day)
            left join calendar_event e
                on e.user_id = ts.user_id
                   and e.start_datetime::timestamp::date = period.day::timestamp::date
                   and e.category_id in (select id from calendar_event_category where name in
                                                        ('GENERAL ACTIVITY'
                                                        ,'GENERAL ACTIVITY > Expense Entitled'
                                                        ,'GENERAL ACTIVITY > Abroad'
                                                        ,'GENERAL ACTIVITY > Abroad > Expense Entitled'
                                                        ,'CUSTOMER MEETING'
                                                        ,'CUSTOMER MEETING > Expense Entitled'
                                                        ,'CUSTOMER MEETING > Abroad'
                                                        ,'CUSTOMER MEETING > Abroad > Expense Entitled'
                                                        ,'TRIP'
                                                        ,'TRIP > Expense Entitled'
                                                        ,'TRIP > Abroad'
                                                        ,'TRIP > Abroad > Expense Entitled'
                                                        ,'OVERNIGHT STAY > Expense Entitled'
                                                        ,'OVERNIGHT STAY > Abroad'
                                                        ,'OVERNIGHT STAY > Abroad > Expense Entitled'
                                                        ,'OVERNIGHT STAY'))

            left join calendar_event_category cc
                on cc.id = e.category_id
            group by
                 ts.id
                ,ts.employee_id
                ,ts.user_id
                ,period.day
                ,p.name
            order by ts.id, period.day
            )""")
예제 #7
0
파일: calendar.py 프로젝트: sc4you/online
class hr_analytic_timesheet(osv.osv):
    _inherit = 'hr.analytic.timesheet'
    event_category_id = Many2one('calendar.event.category', string='Event Category', readonly=False)
예제 #8
0
class calendar_event(osv.osv):
    _inherit = 'calendar.event'

    is_worklog = Boolean(string='Is Worklog',
                         help='Create a Work-Log Entry',
                         default=False)
    project_id = Many2one('project.project', string='Project')
    task_id = Many2one('project.task', string='Task')
    worklog_text = Char('Work-Log', size=128)
    task_work_id = Many2one('project.task.work', string='Task Worklog ID')
    analytic_time_id = Many2one('hr.analytic.timesheet',
                                string='HR Analytic Timesheet ID')

    @api.onchange('task_id')
    def _set_project(self):
        if self.task_id:
            # Set the Project to the project_id of the Task
            if self.project_id != self.task_id.project_id:
                self.project_id = self.task_id.project_id
            # Set the Main Partner to the task or project partner
            if not self.mainpartner_id:
                if self.task_id.partner_id:
                    self.mainpartner_id = self.task_id.partner_id
                elif self.project_id.partner_id:
                    self.mainpartner_id = self.project_id.partner_id

    @api.onchange('project_id')
    def _set_task(self):
        # https://github.com/odoo/odoo/issues/4574
        if self.project_id:
            # Clear the Task if it has a different project_id
            if self.task_id:
                if self.task_id.project_id != self.project_id:
                    self.task_id = False

            # Try to set the Main Partner
            if not self.mainpartner_id:
                if self.task_id and self.task_id.partner_id:
                    self.mainpartner_id = self.task_id.partner_id
                elif self.project_id.partner_id:
                    self.mainpartner_id = self.project_id.partner_id

            # Set a domain for the task list to only show tasks that belong to this project
            return {
                'domain': {
                    'task_id': [('project_id', '=', self.project_id.id)]
                }
            }
        else:
            # Clear the Domain for Tasks if no Project is selected
            return {'domain': {'task_id': []}}

    @api.multi
    def write(self, values):
        print 'Test'

        res = super(calendar_event, self).write(values)

        if res and self.ensure_one():

            # Create or Update related hr.analytic.timesheet entries
            if self.is_worklog and (self.task_id or self.project_id):
                if self.task_id:
                    # Create or update Task Work Log
                    values_worklog = {
                        'name': self.worklog_text or self.name,
                        'user_id': self.user_id.id,
                        'date': self.start_datetime,
                        'hours': self.duration,
                        'task_id': self.task_id.id,
                    }
                    # UNLINK hr.analytic.timesheet
                    if self.analytic_time_id:
                        self.analytic_time_id.unlink()

                    # CREATE (No Worklog exists)
                    if not self.task_work_id:
                        self.task_work_id = self.task_id.work_ids.create(
                            values_worklog)
                    # UPDATE (Worklog exists - relinks to new task if changed)
                    else:
                        self.task_work_id.write(values_worklog)

                elif self.project_id:
                    # Get the Values for hr.analytic.timesheet
                    time_obj = self.env['hr.analytic.timesheet']
                    values_hr_line = {
                        'name':
                        self.worklog_text or self.name,
                        'user_id':
                        self.user_id.id,
                        'date':
                        self.start_datetime,
                        'unit_amount':
                        self.duration,
                        'account_id':
                        self.project_id.analytic_account_id.id,
                        'journal_id':
                        time_obj._getAnalyticJournal(
                            context={'user_id': self.user_id.id}),
                        'product_id':
                        time_obj._getEmployeeProduct(
                            context={'user_id': self.user_id.id}),
                        'product_uom_id':
                        time_obj._getEmployeeUnit(
                            context={'user_id': self.user_id.id}),
                        'general_account_id':
                        time_obj._getGeneralAccount(
                            context={'user_id': self.user_id.id}),
                    }
                    # Recheck the UOM and recalculate if needed
                    default_uom = self.env['res.users'].browse(
                        self.user_id.id).company_id.project_time_mode_id.id
                    if values_hr_line['product_uom_id'] != default_uom:
                        values_hr_line['unit_amount'] = self.pool[
                            'product.uom']._compute_qty(
                                default_uom, values_hr_line['unit_amount'],
                                values_hr_line['product_uom_id'])

                    if self.task_work_id:
                        # Unlink task worklog
                        self.task_work_id.unlink()

                    if not self.analytic_time_id:
                        # Create analytic timeline entry
                        self.analytic_time_id = self.analytic_time_id.create(
                            values_hr_line)
                    else:
                        # Update analytic timeline entry
                        self.analytic_time_id.write(values_hr_line)
            else:
                # UNLINK Work Logs
                if self.task_work_id:
                    self.task_work_id.unlink()
                if self.analytic_time_id:
                    self.analytic_time_id.unlink()

        return res
예제 #9
0
class calendar_event(osv.osv):
    _inherit = 'calendar.event'

    is_worklog = Boolean(string='Is Worklog',
                         help='Create a Work-Log Entry',
                         default=False)
    is_attendance = Boolean(string='Is Attendance',
                            help='Create Attendance Entry (Sing In/Out)',
                            default=False)
    project_id = Many2one('project.project', string='Project')
    task_id = Many2one('project.task', string='Task')
    worklog_text = Char('Work-Log', size=128)
    task_work_id = Many2one('project.task.work', string='Task Worklog ID')
    # These are the worklog lines NOT the timesheet itself
    analytic_time_id = Many2one('hr.analytic.timesheet',
                                string='HR Analytic Timesheet ID')
    sign_in_id = Many2one('hr.attendance', string='Sign In')
    sign_out_id = Many2one('hr.attendance', string='Sign Out')

    to_invoice = Many2one(
        'hr_timesheet_invoice.factor',
        'Invoiceable',
        help="It allows to set the discount while making invoice, "
        "keep empty if the activities should not be invoiced.")

    # DISABLED FOR NOW Update the field event_category_id at installation or update
    # def init(self, cr, context=None):
    #     print "INIT OF calendar_log_project"
    #     events = self.browse(cr, SUPERUSER_ID, self.search(cr, SUPERUSER_ID, []))
    #     for event in events:
    #         # We trigger the write method at install or update time for all events to update the event_category_id
    #         event.write({"name": event.name or None})

    @api.constrains('is_worklog', 'is_attendance')
    def _constraint_user_partner_id_in_event_partner_ids(self):
        for r in self:
            if (r.is_worklog or r.is_attendance) and r.user_id.partner_id:
                assert r.user_id.partner_id in r.partner_ids, _(
                    "You must be a participant if is_worklog or is_attendance is set!"
                )

    @api.onchange('category_id')
    def _oc_category_id(self):
        # Only update if a category was set
        if self.category_id:
            # Set boolean field is_worklog to category setting
            self.is_worklog = self.category_id.is_worklog
            # Set boolean field is attendance to category setting
            self.is_attendance = self.category_id.is_attendance

    @api.onchange('task_id')
    def _set_project(self):
        if self.task_id:
            # Set the Project to the project_id of the Task
            if self.project_id != self.task_id.project_id:
                self.project_id = self.task_id.project_id
            # Set the Main Partner to the task or project partner
            if not self.mainpartner_id:
                if self.task_id.partner_id:
                    self.mainpartner_id = self.task_id.partner_id
                elif self.project_id.partner_id:
                    self.mainpartner_id = self.project_id.partner_id

    @api.onchange('project_id')
    def _set_task(self):
        # https://github.com/odoo/odoo/issues/4574
        if self.project_id:
            # Clear the Task if it has a different project_id
            if self.task_id:
                if self.task_id.project_id != self.project_id:
                    self.task_id = False

            # Try to set the Main Partner
            if not self.mainpartner_id:
                if self.task_id and self.task_id.partner_id:
                    self.mainpartner_id = self.task_id.partner_id
                elif self.project_id.partner_id:
                    self.mainpartner_id = self.project_id.partner_id

            # Make sure we are still a participant
            if self.is_worklog or self.is_attendance:
                if self.user_id and self.user_id.partner_id not in self.partner_ids:
                    self.partner_ids = [(4, self.user_id.partner_id.id, '')]

            # Set a domain for the task list to only show tasks that belong to this project
            return {
                'domain': {
                    'task_id': [('project_id', '=', self.project_id.id)]
                }
            }
        else:
            # Clear the Domain for Tasks if no Project is selected
            return {'domain': {'task_id': []}}

    @api.onchange('is_worklog', 'is_attendance')
    def _onchange_set_user_id_partner_id_as_participant(self):
        if self.is_worklog or self.is_attendance:
            if self.user_id and self.user_id.partner_id not in self.partner_ids:
                self.partner_ids = [(4, self.user_id.partner_id.id, '')]
        # Clear to_invoice of not worklog
        if self.to_invoice and not self.is_worklog:
            self.to_invoice = False

    # @api.multi
    # def create(self, values, context=None):
    #     return super(calendar_event, self).create(values, context=context)

    @api.multi
    def write(self, values):
        # WARNING: Check that NO defaults are set for is_worklog and is_attendance fields cause this will make it
        #          impossible for other code to create events. MUST BE FALSE BY DEFAULT!
        assert not self.env['ir.values'].sudo().search([
            '&', ('name', '=', 'is_worklog'), ('model', '=', 'calendar.event')
        ]), _(
            'Remove any Default for calendar.event.is_worklog field! Settings > Technical > Actions > User Defaults'
        )
        assert not self.env['ir.values'].sudo().search([
            '&', ('name', '=', 'is_attendance'),
            ('model', '=', 'calendar.event')
        ]), _(
            'Remove any Default for calendar.event.is_attendance field! Settings > Technical > Actions > User Defaults'
        )

        # Create or update hr.timesheet worklog and attendance records
        # ------------------------------------------------------------
        if values.get(
                'active', ''
        ) is not False and 'skipp_calendar_log_project' not in values:

            # Loop through the records
            for r in self:
                rec_values = dict()

                # HINT: A event creation will also call the write method because of the "message_last_post" field
                #       Therefore we do not have to extend the create method also.
                # WARNING: Do nothing if record gets unlinked (there is {'active': False} included in vals on unlink)
                # Prepare variables
                # HINT: r.task_id.id will return FALSE if r.task_id is empty (no assertion will be thrown!)
                name = values.get('name') if 'name' in values else r.name
                start = values.get('start') if 'start' in values else \
                    values.get('start_datetime') if 'start_datetime' in values \
                    else r.start
                stop = values.get('stop') if 'stop' in values else \
                    values.get('stop_datetime') if 'stop_datetime' in values \
                    else r.stop
                duration = values.get(
                    'duration') if 'duration' in values else r.duration
                is_worklog = values.get(
                    'is_worklog') if 'is_worklog' in values else r.is_worklog
                worklog_text = values.get(
                    'worklog_text'
                ) if 'worklog_text' in values else r.worklog_text
                is_attendance = values.get(
                    'is_attendance'
                ) if 'is_attendance' in values else r.is_attendance
                user_id = values.get(
                    'user_id') if 'user_id' in values else r.user_id.id
                category_id = values.get(
                    'category_id'
                ) if 'category_id' in values else r.category_id.id
                project_id = values.get(
                    'project_id'
                ) if 'project_id' in values else r.project_id.id
                task_id = values.get(
                    'task_id') if 'task_id' in values else r.task_id.id

                to_invoice = values.get(
                    'to_invoice', r.to_invoice.id if r.to_invoice else False)

                _logger.info(
                    "Create or update worklog and attendance records for calendar.event %s with user %s"
                    % (r.id, user_id))

                # =======
                # WORKLOG
                # =======
                # Unlink task worklog
                if task_id != r.task_id.id or not is_worklog:
                    # Unlink task worklog and related analytic timesheet worklog
                    if r.task_work_id:
                        if r.task_work_id.hr_analytic_timesheet_id:
                            r.task_work_id.hr_analytic_timesheet_id.unlink()
                        r.task_work_id.unlink()

                # Unlink project worklog
                # ATTENTION: Unlink any existing project worklog also if a task is available
                if project_id != r.project_id.id or task_id or not is_worklog:
                    if r.analytic_time_id:
                        r.analytic_time_id.unlink()

                # Create or update worklog
                if is_worklog:
                    assert project_id, _(
                        'You have to choose a project if Is Worklog is checked!'
                    )

                    # TASK WORKLOG
                    # ------------
                    # HINT: You can add bool in but it's not necessary, because bool is a subclass of int.
                    if task_id:
                        task_worklog_values = {
                            'name': worklog_text or name,
                            'user_id': user_id,
                            'date': start,
                            'hours': duration,
                            'task_id': task_id,
                        }
                        # Update an existing task worklog
                        # HINT: If the task changed the task worklog would already be deleted before we reach this point.
                        if r.task_work_id:
                            r.task_work_id.write(task_worklog_values)
                        # Create a new task worklog
                        # HINT: We did not write the event so need to create the worklog without r.task_work_id
                        else:
                            task_obj = r.env['project.task']
                            task = task_obj.browse([task_id])
                            task_work_id = task.work_ids.create(
                                task_worklog_values)
                            # HINT: task.work_ids will create a related hr_analytic_timesheet entry on creation
                            task_work_id.hr_analytic_timesheet_id.event_category_id = category_id
                            rec_values['task_work_id'] = task_work_id.id
                    # PROJECT WORKLOG
                    # ---------------
                    else:
                        # Prepare values
                        ts_obj = r.env['hr.analytic.timesheet']
                        prj_obj = r.env['project.project']
                        project = prj_obj.browse([project_id])
                        account_id = project.analytic_account_id.id
                        unit_amount = duration
                        company_time_unit_id = r.env['res.users'].browse(
                            [user_id]).company_id.project_time_mode_id.id
                        employee_time_unit_id = ts_obj._getEmployeeUnit(
                            context={'user_id': user_id})
                        # If the company has a different time unit than the employee we need to recalculate unit_amount
                        if company_time_unit_id != employee_time_unit_id:
                            unit_amount = r.env['product.uom']._compute_qty(
                                company_time_unit_id, unit_amount,
                                employee_time_unit_id)
                        ts_values = {
                            'name':
                            worklog_text or name,
                            'user_id':
                            user_id,
                            'date':
                            start,
                            'unit_amount':
                            unit_amount,
                            'account_id':
                            account_id,
                            'journal_id':
                            ts_obj._getAnalyticJournal(
                                context={'user_id': user_id}),
                            'product_id':
                            ts_obj._getEmployeeProduct(
                                context={'user_id': user_id}),
                            'product_uom_id':
                            employee_time_unit_id,
                            'general_account_id':
                            ts_obj._getGeneralAccount(
                                context={'user_id': user_id}),
                            'event_category_id':
                            category_id,
                            'to_invoice':
                            to_invoice,
                        }
                        # Update an existing project worklog
                        # HINT: If the project changed the project worklog would already be deleted
                        #       So an update id only possible if the project exists and stayed the same.
                        if r.analytic_time_id:
                            r.analytic_time_id.write(ts_values)
                        # Create a project worklog
                        # HINT: We did not write the event so need to create the worklog without r.analytic_time_id
                        else:
                            project_worklog = ts_obj.create(ts_values)
                            rec_values['analytic_time_id'] = project_worklog.id

                # ==========
                # ATTENDANCE
                # ==========
                # Unlink attendance
                if not is_attendance:
                    if r.sign_in_id:
                        r.sign_in_id.unlink()
                    if r.sign_out_id:
                        r.sign_out_id.unlink()

                # Create or Update Attendance
                if is_attendance:
                    attendance_obj = r.env['hr.attendance']
                    # Get the employee id
                    employee_obj = r.env['hr.employee']
                    employee_id = employee_obj.search(
                        [('user_id', '=', r.user_id.id)], limit=1).id
                    assert employee_id, _(
                        'No employee found for current user!')

                    # SIGN_IN attendance
                    sign_in_values = {
                        'employee_id': employee_id,
                        'name': start,
                        'action': 'sign_in',
                    }
                    # Update existing sign-in attendance
                    if r.sign_in_id:
                        r.sign_in_id.write(sign_in_values)
                    # Create new sign-in attendance
                    else:
                        sign_in = attendance_obj.create(sign_in_values)
                        rec_values['sign_in_id'] = sign_in.id

                    # SIGN_OUT attendance
                    sign_out_values = {
                        'employee_id': employee_id,
                        'name': stop,
                        'action': 'sign_out',
                    }
                    # Update existing sign-out attendance
                    if r.sign_out_id:
                        r.sign_out_id.write(sign_out_values)
                    # Create new sign-out attendance
                    else:
                        sign_out = attendance_obj.create(sign_out_values)
                        rec_values['sign_out_id'] = sign_out.id

                # UPDATE RECORD VALUES
                if rec_values:
                    # Make sure "Create or update hr.timesheet worklog and attendance records" is only run once!
                    rec_values['skipp_calendar_log_project'] = True

                    # Call write again with updated values and 'skipp_calendar_log_project' only for this single record
                    r.write(rec_values)

        # END Create or update hr.timesheet worklog and attendance records
        # ----------------------------------------------------------------

        # Remove 'skipp_calendar_log_project' for the rec_values write
        if 'skipp_calendar_log_project' in values:
            values.pop('skipp_calendar_log_project')

        return super(calendar_event, self).write(values)

    @api.multi
    def unlink(self):
        for event in self:
            if event.task_work_id:
                event.task_work_id.unlink()
            if event.analytic_time_id:
                event.analytic_time_id.unlink()
            if event.sign_in_id:
                event.sign_in_id.unlink()
            if event.sign_out_id:
                event.sign_out_id.unlink()
        return super(calendar_event, self).unlink()