Пример #1
0
class calendar_event_category(osv.osv):
    _inherit = 'calendar.event.category'

    is_worklog = Boolean(
        string='Is Worklog',
        help='Default Is Worklog setting for meetings with this category',
        default=False)
    is_attendance = Boolean(
        string='Is Attendance',
        help='Default Is-Attendance setting for meetings with this category',
        default=False)
Пример #2
0
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
class ResPartner(Model):
    _inherit = 'res.partner'

    @api.multi
    def get_object_activity(self,
                            object_name,
                            partner_field_name,
                            nb_month=24):
        """
        Returns a dictionary containing the active status of the partner concerning the object
        :param nb_month: number of month the partner activity must be checked
        :returns: a dictionary containing the active status of the partner concerning the object
        """
        res = {}
        obj = self.env[object_name]
        start_date = datetime.now() - timedelta(nb_month * 365 / 12)
        for partner in self:
            res.update({partner.id: False})
            lead_recs = obj.search([(partner_field_name, '=', partner.id),
                                    ('create_date', '>=',
                                     datetime.strftime(start_date,
                                                       "%Y-%m-%d 00:00:00"))])

            ## If a child is active than the parent partner must be active too
            active_child = False
            child_recs = self.search([('parent_id', '=', partner.id)])
            res_children = child_recs.get_object_activity(
                object_name, partner_field_name)
            for res_child in res_children:
                if res_children.get(res_child, False):
                    active_child = True

            if len(lead_recs) or active_child:
                res.update({partner.id: True})

        return res

    @api.multi
    @api.depends('opportunity_count')
    def _get_activity_status(self):
        """
        Returns a dictionary containing the active status in last 24 month
        """
        lead_res = self.get_object_activity('crm.lead', 'partner_id', 24)

        for partner in self:
            if lead_res.get(partner.id):
                partner.is_active = True
            else:
                partner.is_active = False

    is_active = Boolean('Active during last 2 years',
                        compute=_get_activity_status)
Пример #4
0
class IrActionsReportXML(Model):
    _inherit = "ir.actions.report.xml"

    add_terms_conditions = Boolean(string='add Terms and Conditions',
                                   default=False)
    terms_conditions_language_field = Char('Language field')
Пример #5
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')

    # 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
class CrmLead(Model):
    _inherit = 'crm.lead'

    def compute_lost_visible(self):
        for rec in self:
            if rec.stage_id.name == 'Lost':
                rec.lost_visible = True

    @api.multi
    def action_set_lost(self):
        """ Lost semantic: probability = 0, active = False """
        lost_stage = self.env['crm.stage'].search([('name','=','Lost')])[0]
        return self.write({'probability': 0,'stage_id':lost_stage.id})

    @api.multi
    def open_form_view(self):
        if self[0].type == 'lead':
            name = _('Leads')
            res = self.env.ref('crm.crm_case_form_view_leads')
        else:
            name = _('Opportunities')
            res = self.env.ref('crm.crm_case_form_view_oppor')
        return {
            'name': name or '',
            'view_type': 'form',
            'view_mode': 'form',
            'view_id': [res.id],
            'res_model': 'crm.lead',
            'context': "{}",
            'type': 'ir.actions.act_window',
            'nodestroy': True,
            'res_id': self[0].id or False
        }


    @api.onchange('partner_id')
    def on_change_partner_id(self):
        result = super(CrmLead, self)._onchange_partner_id_values(self.partner_id.id if self.partner_id else False)
        if not self.partner_id:
            return result


        partner = self.env['res.partner'].browse(self.partner_id.id)
        result.update({'website': partner.website})
        return result



    @api.model
    def _lead_create_contact(self, name, is_company, parent_id=False):
        partner_id = super(CrmLead, self)._lead_create_contact(name, is_company, parent_id)
        self.env['res.partner'].browse(partner_id.id).write({'website': self.website})
        return partner_id


    @api.model
    def create(self, values):
        if values.get('stage_id'):
            crm_stage_rec = self.env['crm.case.stage'].browse(values.get('stage_id'))
            values.update({'probability': crm_stage_rec.probability})
        return super(CrmLead, self).create(values)


    website = Char('Website', size=64, help="Website of Partner or Company")
    lost_visible = Boolean(default=False ,compute='compute_lost_visible',store=False)
Пример #7
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
Пример #8
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()