class HrContract(models.Model):
    _inherit = 'hr.contract'
    _description = 'Employee Contract'

    analytic_account_id = fields.Many2one('account.analytic.account',
                                          'Analytic Account')
    journal_id = fields.Many2one('account.journal', 'Salary Journal')
示例#2
0
class AccountInvoiceLine(models.Model):
    """ Override AccountInvoice_line to add the link to the purchase order line it is related to"""
    _inherit = 'account.invoice.line'

    purchase_line_id = fields.Many2one('purchase.order.line', 'Purchase Order Line', ondelete='set null', index=True, readonly=True)
    purchase_id = fields.Many2one('purchase.order', related='purchase_line_id.order_id', string='Purchase Order', store=False, readonly=True, related_sudo=False,
        help='Associated Purchase Order. Filled in automatically when a PO is chosen on the vendor bill.')
示例#3
0
class MrpProductionMessage(models.Model):
    _name = "mrp.message"
    _description = "Production Message"

    @api.model
    def _default_valid_until(self):
        return datetime.today() + relativedelta(days=7)

    name = fields.Text(compute='_get_note_first_line', store=True)
    message = fields.Html(required=True)
    product_tmpl_id = fields.Many2one('product.template', 'Product Template')
    product_id = fields.Many2one('product.product', string="Product")
    bom_id = fields.Many2one(
        'mrp.bom',
        'Bill of Material',
        domain=
        "['|', ('product_id', '=', product_id), ('product_tmpl_id.product_variant_ids','=', product_id)]"
    )
    workcenter_id = fields.Many2one('mrp.workcenter', string='Work Center')
    valid_until = fields.Date('Validity Date',
                              default=_default_valid_until,
                              required=True)
    routing_id = fields.Many2one('mrp.routing', string='Routing')

    @api.depends('message')
    def _get_note_first_line(self):
        for message in self:
            message.name = (message.message and html2plaintext(message.message)
                            or "").strip().replace('*', '').split("\n")[0]

    @api.multi
    def save(self):
        """ Used in a wizard-like form view, manual save button when in edit mode """
        return True
示例#4
0
class StockLocation(models.Model):
    _inherit = "stock.location"

    valuation_in_account_id = fields.Many2one(
        'account.account',
        'Stock Valuation Account (Incoming)',
        domain=[('internal_type', '=', 'other'), ('deprecated', '=', False)],
        help=
        "Used for real-time inventory valuation. When set on a virtual location (non internal type), "
        "this account will be used to hold the value of products being moved from an internal location "
        "into this location, instead of the generic Stock Output Account set on the product. "
        "This has no effect for internal locations.")
    valuation_out_account_id = fields.Many2one(
        'account.account',
        'Stock Valuation Account (Outgoing)',
        domain=[('internal_type', '=', 'other'), ('deprecated', '=', False)],
        help=
        "Used for real-time inventory valuation. When set on a virtual location (non internal type), "
        "this account will be used to hold the value of products being moved out of this location "
        "and into an internal location, instead of the generic Stock Output Account set on the product. "
        "This has no effect for internal locations.")

    def _should_be_valued(self):
        """ This method returns a boolean reflecting whether the products stored in `self` should
        be considered when valuating the stock of a company.
        """
        self.ensure_one()
        if self.usage == 'internal' or (self.usage == 'transit'
                                        and self.company_id):
            return True
        return False
class RegistrationEditorLine(models.TransientModel):
    """Event Registration"""
    _name = "registration.editor.line"

    editor_id = fields.Many2one('registration.editor')
    sale_order_line_id = fields.Many2one('sale.order.line', string='Sales Order Line')
    event_id = fields.Many2one('event.event', string='Event', required=True)
    registration_id = fields.Many2one('event.registration', 'Original Registration')
    event_ticket_id = fields.Many2one('event.event.ticket', string='Event Ticket')
    email = fields.Char(string='Email')
    phone = fields.Char(string='Phone')
    name = fields.Char(string='Name', index=True)

    @api.multi
    def get_registration_data(self):
        self.ensure_one()
        return {
            'event_id': self.event_id.id,
            'event_ticket_id': self.event_ticket_id.id,
            'partner_id': self.editor_id.sale_order_id.partner_id.id,
            'name': self.name or self.editor_id.sale_order_id.partner_id.name,
            'phone': self.phone or self.editor_id.sale_order_id.partner_id.phone,
            'email': self.email or self.editor_id.sale_order_id.partner_id.email,
            'origin': self.editor_id.sale_order_id.name,
            'sale_order_id': self.editor_id.sale_order_id.id,
            'sale_order_line_id': self.sale_order_line_id.id,
        }
示例#6
0
class HrSalaryRuleCategory(models.Model):
    _name = 'hr.salary.rule.category'
    _description = 'Salary Rule Category'

    name = fields.Char(required=True, translate=True)
    code = fields.Char(required=True)
    parent_id = fields.Many2one(
        'hr.salary.rule.category',
        string='Parent',
        help=
        "Linking a salary category to its parent is used only for the reporting purpose."
    )
    children_ids = fields.One2many('hr.salary.rule.category',
                                   'parent_id',
                                   string='Children')
    note = fields.Text(string='Description')
    company_id = fields.Many2one(
        'res.company',
        string='Company',
        default=lambda self: self.env['res.company']._company_default_get())

    @api.constrains('parent_id')
    def _check_parent_id(self):
        if not self._check_recursion():
            raise ValidationError(
                _('Error! You cannot create recursive hierarchy of Salary Rule Category.'
                  ))
示例#7
0
class HrPayrollAdviceLine(models.Model):
    '''
    Bank Advice Lines
    '''
    _name = 'hr.payroll.advice.line'
    _description = 'Bank Advice Lines'

    advice_id = fields.Many2one('hr.payroll.advice', string='Bank Advice')
    name = fields.Char('Bank Account No.', required=True)
    ifsc_code = fields.Char(string='IFSC Code')
    employee_id = fields.Many2one('hr.employee',
                                  string='Employee',
                                  required=True)
    bysal = fields.Float(string='By Salary',
                         digits=dp.get_precision('Payroll'))
    debit_credit = fields.Char(string='C/D', default='C')
    company_id = fields.Many2one('res.company',
                                 related='advice_id.company_id',
                                 string='Company',
                                 store=True)
    ifsc = fields.Boolean(related='advice_id.neft', string='IFSC')

    @api.onchange('employee_id')
    def onchange_employee_id(self):
        self.name = self.employee_id.bank_account_id.acc_number
        self.ifsc_code = self.employee_id.bank_account_id.bank_bic or ''
示例#8
0
class RecruitmentStage(models.Model):
    _name = "hr.recruitment.stage"
    _description = "Stage of Recruitment"
    _order = 'sequence'

    name = fields.Char("Stage name", required=True, translate=True)
    sequence = fields.Integer(
        "Sequence", default=10,
        help="Gives the sequence order when displaying a list of stages.")
    job_id = fields.Many2one('hr.job', string='Job Specific',
                             ondelete='cascade',
                             help='Specific job that uses this stage. Other jobs will not use this stage.')
    requirements = fields.Text("Requirements")
    template_id = fields.Many2one(
        'mail.template', "Automated Email",
        help="If set, a message is posted on the applicant using the template when the applicant is set to the stage.")
    fold = fields.Boolean(
        "Folded in Recruitment Pipe",
        help="This stage is folded in the kanban view when there are no records in that stage to display.")

    @api.model
    def default_get(self, fields):
        if self._context and self._context.get('default_job_id') and not self._context.get('hr_recruitment_stage_mono', False):
            context = dict(self._context)
            context.pop('default_job_id')
            self = self.with_context(context)
        return super(RecruitmentStage, self).default_get(fields)
class FleetVehicleLogServices(models.Model):
    _name = 'fleet.vehicle.log.services'
    _inherits = {'fleet.vehicle.cost': 'cost_id'}
    _description = 'Services for vehicles'

    @api.model
    def default_get(self, default_fields):
        res = super(FleetVehicleLogServices, self).default_get(default_fields)
        service = self.env.ref('fleet.type_service_service_8', raise_if_not_found=False)
        res.update({
            'date': fields.Date.context_today(self),
            'cost_subtype_id': service and service.id or False,
            'cost_type': 'services'
        })
        return res

    purchaser_id = fields.Many2one('res.partner', 'Purchaser', domain="['|',('customer','=',True),('employee','=',True)]")
    inv_ref = fields.Char('Invoice Reference')
    vendor_id = fields.Many2one('res.partner', 'Vendor', domain="[('supplier','=',True)]")
    # we need to keep this field as a related with store=True because the graph view doesn't support
    # (1) to address fields from inherited table and (2) fields that aren't stored in database
    cost_amount = fields.Float(related='cost_id.amount', string='Amount', store=True)
    notes = fields.Text()
    cost_id = fields.Many2one('fleet.vehicle.cost', 'Cost', required=True, ondelete='cascade')

    @api.onchange('vehicle_id')
    def _onchange_vehicle(self):
        if self.vehicle_id:
            self.odometer_unit = self.vehicle_id.odometer_unit
            self.purchaser_id = self.vehicle_id.driver_id.id
class ReportEventRegistrationQuestions(models.Model):
    _name = "event.question.report"
    _auto = False

    attendee_id = fields.Many2one(comodel_name='event.registration',
                                  string='Registration')
    question_id = fields.Many2one(comodel_name='event.question',
                                  string='Question')
    answer_id = fields.Many2one(comodel_name='event.answer', string='Answer')
    event_id = fields.Many2one(comodel_name='event.event', string='Event')

    @api.model_cr
    def init(self):
        """ Event Question main report """
        tools.drop_view_if_exists(self._cr, 'event_question_report')
        self._cr.execute(""" CREATE VIEW event_question_report AS (
            SELECT
                att_answer.id as id,
                att_answer.event_registration_id as attendee_id,
                answer.question_id as question_id,
                answer.id as answer_id,
                question.event_id as event_id
            FROM
                event_registration_answer as att_answer
            LEFT JOIN
                event_answer as answer ON answer.id = att_answer.event_answer_id
            LEFT JOIN
                event_question as question ON question.id = answer.question_id
            GROUP BY
                attendee_id,
                event_id,
                question_id,
                answer_id,
                att_answer.id
        )""")
示例#11
0
class EventTypeMail(models.Model):
    """ Template of event.mail to attach to event.type. Those will be copied
    upon all events created in that type to ease event creation. """
    _name = 'event.type.mail'
    _description = 'Mail Scheduling on Event Type'

    event_type_id = fields.Many2one('event.type',
                                    string='Event Type',
                                    ondelete='cascade',
                                    required=True)
    interval_nbr = fields.Integer('Interval', default=1)
    interval_unit = fields.Selection([('now', 'Immediately'),
                                      ('hours', 'Hour(s)'), ('days', 'Day(s)'),
                                      ('weeks', 'Week(s)'),
                                      ('months', 'Month(s)')],
                                     string='Unit',
                                     default='hours',
                                     required=True)
    interval_type = fields.Selection([('after_sub', 'After each registration'),
                                      ('before_event', 'Before the event'),
                                      ('after_event', 'After the event')],
                                     string='Trigger',
                                     default="before_event",
                                     required=True)
    template_id = fields.Many2one(
        'mail.template',
        string='Email Template',
        domain=[('model', '=', 'event.registration')],
        required=True,
        ondelete='restrict',
        help=
        'This field contains the template of the mail that will be automatically sent'
    )
示例#12
0
class grant_badge_wizard(models.TransientModel):
    """ Wizard allowing to grant a badge to a user"""
    _name = 'gamification.badge.user.wizard'

    user_id = fields.Many2one("res.users", string='User', required=True)
    badge_id = fields.Many2one("gamification.badge", string='Badge', required=True)
    comment = fields.Text('Comment')

    @api.multi
    def action_grant_badge(self):
        """Wizard action for sending a badge to a chosen user"""

        BadgeUser = self.env['gamification.badge.user']

        uid = self.env.uid
        for wiz in self:
            if uid == wiz.user_id.id:
                raise exceptions.UserError(_('You can not grant a badge to yourself'))

            #create the badge
            BadgeUser.create({
                'user_id': wiz.user_id.id,
                'sender_id': uid,
                'badge_id': wiz.badge_id.id,
                'comment': wiz.comment,
            })._send_badge()

        return True
示例#13
0
class Notification(models.Model):
    _name = 'mail.notification'
    _table = 'mail_message_res_partner_needaction_rel'
    _rec_name = 'res_partner_id'
    _log_access = False
    _description = 'Message Notifications'

    mail_message_id = fields.Many2one(
        'mail.message', 'Message', index=True, ondelete='cascade', required=True)
    res_partner_id = fields.Many2one(
        'res.partner', 'Needaction Recipient', index=True, ondelete='cascade', required=True)
    is_read = fields.Boolean('Is Read', index=True)
    is_email = fields.Boolean('Sent by Email', index=True)
    email_status = fields.Selection([
        ('ready', 'Ready to Send'),
        ('sent', 'Sent'),
        ('bounce', 'Bounced'),
        ('exception', 'Exception')], 'Email Status',
        default='ready', index=True)

    @api.model_cr
    def init(self):
        self._cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('mail_notification_res_partner_id_is_read_email_status_mail_message_id',))
        if not self._cr.fetchone():
            self._cr.execute('CREATE INDEX mail_notification_res_partner_id_is_read_email_status_mail_message_id ON mail_message_res_partner_needaction_rel (res_partner_id, is_read, email_status, mail_message_id)')
示例#14
0
class LinkTrackerClick(models.Model):
    _inherit = "link.tracker.click"

    mail_stat_id = fields.Many2one('mail.mail.statistics', string='Mail Statistics')
    mass_mailing_id = fields.Many2one('mail.mass_mailing', string='Mass Mailing')
    mass_mailing_campaign_id = fields.Many2one('mail.mass_mailing.campaign', string='Mass Mailing Campaign')

    @api.model
    def add_click(self, code, ip, country_code, stat_id=False):
        res = super(LinkTrackerClick, self).add_click(code, ip, country_code, stat_id=stat_id)
        if stat_id:
            stat_sudo = self.env['mail.mail.statistics'].sudo().browse(stat_id)
            stat_sudo.set_opened()
            stat_sudo.set_clicked()
        return res

    def _get_click_values_from_route(self, route_values):
        click_values = super(LinkTrackerClick, self)._get_click_values_from_route(route_values)
        if route_values['stat_id']:
            mail_stat = self.env['mail.mail.statistics'].browse(route_values['stat_id'])
            click_values['mail_stat_id'] = mail_stat.id
            if mail_stat.mass_mailing_campaign_id:
                click_values['mass_mailing_campaign_id'] = mail_stat.mass_mailing_campaign_id.id
            if mail_stat.mass_mailing_id:
                click_values['mass_mailing_id'] = mail_stat.mass_mailing_id.id
        return click_values
示例#15
0
class RecruitmentSource(models.Model):
    _name = "hr.recruitment.source"
    _description = "Source of Applicants"
    _inherits = {"utm.source": "source_id"}

    source_id = fields.Many2one('utm.source', "Source", ondelete='cascade', required=True)
    email = fields.Char(related='alias_id.display_name', string="Email", readonly=True)
    job_id = fields.Many2one('hr.job', "Job ID")
    alias_id = fields.Many2one('mail.alias', "Alias ID")

    @api.multi
    def create_alias(self):
        campaign = self.env.ref('hr_recruitment.utm_campaign_job')
        medium = self.env.ref('utm.utm_medium_email')
        for source in self:
            vals = {
                'alias_parent_thread_id': source.job_id.id,
                'alias_name': "%s+%s" % (source.job_id.alias_name or source.job_id.name, source.name),
                'alias_defaults': {
                    'job_id': source.job_id.id,
                    'campaign_id': campaign.id,
                    'medium_id': medium.id,
                    'source_id': source.source_id.id,
                },
            }
            source.alias_id = self.with_context(alias_model_name='hr.applicant', alias_parent_model_name='hr.job').env['mail.alias'].create(vals)
            source.name = source.source_id.name
示例#16
0
class LunchCashMove(models.Model):
    """ Two types of cashmoves: payment (credit) or order (debit) """
    _name = 'lunch.cashmove'
    _description = 'lunch cashmove'

    user_id = fields.Many2one('res.users',
                              'User',
                              default=lambda self: self.env.uid)
    date = fields.Date('Date',
                       required=True,
                       default=fields.Date.context_today)
    amount = fields.Float(
        'Amount',
        required=True,
        help=
        'Can be positive (payment) or negative (order or payment if user wants to get his money back)'
    )
    description = fields.Text('Description',
                              help='Can be an order or a payment')
    order_id = fields.Many2one('lunch.order.line', 'Order', ondelete='cascade')
    state = fields.Selection([('order', 'Order'), ('payment', 'Payment')],
                             'Is an order or a payment',
                             default='payment')

    @api.multi
    def name_get(self):
        return [(cashmove.id,
                 '%s %s' % (_('Lunch Cashmove'), '#%d' % cashmove.id))
                for cashmove in self]
class ResConfigSettings(models.TransientModel):
    _inherit = 'res.config.settings'

    def _get_crm_default_team_domain(self):
        if self.env.user.has_group('crm.group_use_lead'):
            return [('use_leads', '=', True)]
        else:
            return [('use_opportunities', '=', True)]

    crm_default_team_id = fields.Many2one(
        'crm.team',
        string='Default Sales Channel',
        related='website_id.crm_default_team_id',
        domain=lambda self: self._get_crm_default_team_domain(),
        help=
        'Default sales channel for new leads created through the Contact Us form.'
    )
    crm_default_user_id = fields.Many2one(
        'res.users',
        string='Default Salesperson',
        related='website_id.crm_default_user_id',
        domain=[('share', '=', False)],
        help=
        'Default salesperson for new leads created through the Contact Us form.'
    )
示例#18
0
class ResourceCalendarLeaves(models.Model):
    _name = "resource.calendar.leaves"
    _description = "Leave Detail"

    name = fields.Char('Reason')
    company_id = fields.Many2one(
        'res.company', related='calendar_id.company_id', string="Company",
        readonly=True, store=True)
    calendar_id = fields.Many2one('resource.calendar', 'Working Hours')
    date_from = fields.Datetime('Start Date', required=True)
    date_to = fields.Datetime('End Date', required=True)
    tz = fields.Selection(
        _tz_get, string='Timezone', default=lambda self: self._context.get('tz') or self.env.user.tz or 'UTC',
        help="Timezone used when encoding the leave. It is used to correctly "
             "localize leave hours when computing time intervals.")
    resource_id = fields.Many2one(
        "resource.resource", 'Resource',
        help="If empty, this is a generic holiday for the company. If a resource is set, the holiday/leave is only for this resource")

    @api.constrains('date_from', 'date_to')
    def check_dates(self):
        if self.filtered(lambda leave: leave.date_from > leave.date_to):
            raise ValidationError(_('Error! leave start-date must be lower then leave end-date.'))

    @api.onchange('resource_id')
    def onchange_resource(self):
        if self.resource_id:
            self.calendar_id = self.resource_id.calendar_id
示例#19
0
class ProductTemplate(models.Model):
    _inherit = "product.template"

    taxes_id = fields.Many2many('account.tax',
                                'product_taxes_rel',
                                'prod_id',
                                'tax_id',
                                string='Customer Taxes',
                                domain=[('type_tax_use', '=', 'sale')])
    supplier_taxes_id = fields.Many2many('account.tax',
                                         'product_supplier_taxes_rel',
                                         'prod_id',
                                         'tax_id',
                                         string='Vendor Taxes',
                                         domain=[('type_tax_use', '=',
                                                  'purchase')])
    property_account_income_id = fields.Many2one(
        'account.account',
        company_dependent=True,
        string="Income Account",
        oldname="property_account_income",
        domain=[('deprecated', '=', False)],
        help=
        "Keep this field empty to use the default value from the product category."
    )
    property_account_expense_id = fields.Many2one(
        'account.account',
        company_dependent=True,
        string="Expense Account",
        oldname="property_account_expense",
        domain=[('deprecated', '=', False)],
        help=
        "The expense is accounted for when a vendor bill is validated, except in anglo-saxon accounting with perpetual inventory valuation in which case the expense (Cost of Goods Sold account) is recognized at the customer invoice validation. If the field is empty, it uses the one defined in the product category."
    )

    @api.multi
    def _get_product_accounts(self):
        return {
            'income':
            self.property_account_income_id
            or self.categ_id.property_account_income_categ_id,
            'expense':
            self.property_account_expense_id
            or self.categ_id.property_account_expense_categ_id
        }

    @api.multi
    def _get_asset_accounts(self):
        res = {}
        res['stock_input'] = False
        res['stock_output'] = False
        return res

    @api.multi
    def get_product_accounts(self, fiscal_pos=None):
        accounts = self._get_product_accounts()
        if not fiscal_pos:
            fiscal_pos = self.env['account.fiscal.position']
        return fiscal_pos.map_accounts(accounts)
示例#20
0
class FixedPutAwayStrategy(models.Model):
    _name = 'stock.fixed.putaway.strat'
    _order = 'sequence'

    putaway_id = fields.Many2one('product.putaway', 'Put Away Method', required=True)
    category_id = fields.Many2one('product.category', 'Product Category', required=True)
    fixed_location_id = fields.Many2one('stock.location', 'Location', required=True)
    sequence = fields.Integer('Priority', help="Give to the more specialized category, a higher priority to have them in top of the list.")
示例#21
0
class CrossoveredBudget(models.Model):
    _name = "crossovered.budget"
    _description = "Budget"
    _inherit = ['mail.thread']

    name = fields.Char('Budget Name',
                       required=True,
                       states={'done': [('readonly', True)]})
    creating_user_id = fields.Many2one('res.users',
                                       'Responsible',
                                       default=lambda self: self.env.user)
    date_from = fields.Date('Start Date',
                            required=True,
                            states={'done': [('readonly', True)]})
    date_to = fields.Date('End Date',
                          required=True,
                          states={'done': [('readonly', True)]})
    state = fields.Selection([('draft', 'Draft'), ('cancel', 'Cancelled'),
                              ('confirm', 'Confirmed'),
                              ('validate', 'Validated'), ('done', 'Done')],
                             'Status',
                             default='draft',
                             index=True,
                             required=True,
                             readonly=True,
                             copy=False,
                             track_visibility='always')
    crossovered_budget_line = fields.One2many(
        'crossovered.budget.lines',
        'crossovered_budget_id',
        'Budget Lines',
        states={'done': [('readonly', True)]},
        copy=True)
    company_id = fields.Many2one('res.company',
                                 'Company',
                                 required=True,
                                 default=lambda self: self.env['res.company'].
                                 _company_default_get('account.budget.post'))

    @api.multi
    def action_budget_confirm(self):
        self.write({'state': 'confirm'})

    @api.multi
    def action_budget_draft(self):
        self.write({'state': 'draft'})

    @api.multi
    def action_budget_validate(self):
        self.write({'state': 'validate'})

    @api.multi
    def action_budget_cancel(self):
        self.write({'state': 'cancel'})

    @api.multi
    def action_budget_done(self):
        self.write({'state': 'done'})
示例#22
0
class CrmLeadConvert2Task(models.TransientModel):
    """ wizard to convert a Lead into a Project task and move the Mail Thread """

    _name = "crm.lead.convert2task"
    _inherit = 'crm.partner.binding'

    @api.model
    def default_get(self, fields):
        result = super(CrmLeadConvert2Task, self).default_get(fields)
        lead_id = self.env.context.get('active_id')
        if lead_id:
            result['lead_id'] = lead_id
        return result

    lead_id = fields.Many2one('crm.lead',
                              string='Lead',
                              domain=[('type', '=', 'lead')])
    project_id = fields.Many2one('project.project', string='Project')

    @api.multi
    def action_lead_to_project_task(self):
        self.ensure_one()
        # get the lead to transform
        lead = self.lead_id
        partner_id = self._find_matching_partner()
        if not partner_id and (lead.partner_name or lead.contact_name):
            partner_id = lead.handle_partner_assignation()[lead.id]
        # create new project.task
        vals = {
            "name": lead.name,
            "description": lead.description,
            "email_from": lead.email_from,
            "project_id": self.project_id.id,
            "partner_id": partner_id,
            "user_id": None
        }
        task = self.env['project.task'].create(vals)
        # move the mail thread
        lead.message_change_thread(task)
        # move attachments
        attachments = self.env['ir.attachment'].search([
            ('res_model', '=', 'crm.lead'), ('res_id', '=', lead.id)
        ])
        attachments.write({'res_model': 'project.task', 'res_id': task.id})
        # archive the lead
        lead.write({'active': False})
        # return the action to go to the form view of the new Task
        view = self.env.ref('project.view_task_form2')
        return {
            'name': 'Task created',
            'view_type': 'form',
            'view_mode': 'form',
            'view_id': view.id,
            'res_model': 'project.task',
            'type': 'ir.actions.act_window',
            'res_id': task.id,
            'context': self.env.context
        }
示例#23
0
class HrContract(models.Model):
    _inherit = 'hr.contract'

    car_id = fields.Many2one('fleet.vehicle', string='Company Car',
        domain=lambda self: self._get_available_cars_domain(),
        default=lambda self: self.env['fleet.vehicle'].search([('driver_id', '=', self.employee_id.address_home_id.id)], limit=1),
        track_visibility="onchange",
        help="Employee's company car.")
    car_atn = fields.Float(compute='_compute_car_atn_and_costs', string='ATN Company Car', store=True)
    company_car_total_depreciated_cost = fields.Float(compute='_compute_car_atn_and_costs', store=True)
    available_cars_amount = fields.Integer(compute='_compute_available_cars_amount', string='Number of available cars')
    new_car = fields.Boolean('Request a new car')
    new_car_model_id = fields.Many2one('fleet.vehicle.model', string="Model", domain=lambda self: self._get_possible_model_domain())
    max_unused_cars = fields.Integer(compute='_compute_max_unused_cars')

    @api.depends('car_id', 'new_car', 'new_car_model_id', 'car_id.total_depreciated_cost',
        'car_id.atn', 'new_car_model_id.default_atn', 'new_car_model_id.default_total_depreciated_cost',
        'car_id.co2_fee', 'car_id.log_contracts', 'car_id.log_contracts.state', # YTI TODO: Store total_depreciated_costs on
        'car_id.log_contracts.recurring_cost_amount_depreciated') # the fleet vehicle to avoid these dependencies
    def _compute_car_atn_and_costs(self):
        for contract in self:
            if not contract.new_car and contract.car_id:
                contract.car_atn = contract.car_id.atn
                contract.company_car_total_depreciated_cost = contract.car_id.total_depreciated_cost
            elif contract.new_car and contract.new_car_model_id:
                contract.car_atn = contract.new_car_model_id.default_atn
                contract.company_car_total_depreciated_cost = contract.new_car_model_id.default_total_depreciated_cost

    @api.depends('name')
    def _compute_available_cars_amount(self):
        for contract in self:
            contract.available_cars_amount = self.env['fleet.vehicle'].search_count([('driver_id', '=', False)])

    @api.depends('name')
    def _compute_max_unused_cars(self):
        params = self.env['ir.config_parameter'].sudo()
        max_unused_cars = params.get_param('l10n_be_hr_payroll_fleet.max_unused_cars', default=1000)
        for contract in self:
            contract.max_unused_cars = int(max_unused_cars)

    @api.onchange('employee_id')
    def _onchange_employee_id(self):
        super(HrContract, self)._onchange_employee_id()
        self.car_id = self.env['fleet.vehicle'].search([('driver_id', '=', self.employee_id.address_home_id.id)], limit=1)
        return {'domain': {'car_id': self._get_available_cars_domain()}}

    @api.onchange('transport_mode')
    def _onchange_transport_mode(self):
        super(HrContract, self)._onchange_transport_mode()
        if self.transport_mode != 'company_car':
            self.car_id = False
            self.new_car_model_id = False

    def _get_available_cars_domain(self):
        return ['|', ('driver_id', '=', False), ('driver_id', '=', self.employee_id.address_home_id.id)]

    def _get_possible_model_domain(self):
        return [('can_be_requested', '=', True)]
示例#24
0
class RepairFee(models.Model):
    _name = 'mrp.repair.fee'
    _description = 'Repair Fees Line'

    repair_id = fields.Many2one(
        'mrp.repair', 'Repair Order Reference',
        index=True, ondelete='cascade', required=True)
    name = fields.Char('Description', index=True, required=True)
    product_id = fields.Many2one('product.product', 'Product')
    product_uom_qty = fields.Float('Quantity', digits=dp.get_precision('Product Unit of Measure'), required=True, default=1.0)
    price_unit = fields.Float('Unit Price', required=True)
    product_uom = fields.Many2one('product.uom', 'Product Unit of Measure', required=True)
    price_subtotal = fields.Float('Subtotal', compute='_compute_price_subtotal', digits=0)
    tax_id = fields.Many2many('account.tax', 'repair_fee_line_tax', 'repair_fee_line_id', 'tax_id', 'Taxes')
    invoice_line_id = fields.Many2one('account.invoice.line', 'Invoice Line', copy=False, readonly=True)
    invoiced = fields.Boolean('Invoiced', copy=False, readonly=True)

    @api.one
    @api.depends('price_unit', 'repair_id', 'product_uom_qty', 'product_id')
    def _compute_price_subtotal(self):
        taxes = self.tax_id.compute_all(self.price_unit, self.repair_id.pricelist_id.currency_id, self.product_uom_qty, self.product_id, self.repair_id.partner_id)
        self.price_subtotal = taxes['total_excluded']

    @api.onchange('repair_id', 'product_id', 'product_uom_qty')
    def onchange_product_id(self):
        """ On change of product it sets product quantity, tax account, name,
        uom of product, unit price and price subtotal. """
        if not self.product_id:
            return

        partner = self.repair_id.partner_id
        pricelist = self.repair_id.pricelist_id

        if partner and self.product_id:
            self.tax_id = partner.property_account_position_id.map_tax(self.product_id.taxes_id, self.product_id, partner).ids
        if self.product_id:
            self.name = self.product_id.display_name
            self.product_uom = self.product_id.uom_id.id

        warning = False
        if not pricelist:
            warning = {
                'title': _('No Pricelist!'),
                'message':
                    _('You have to select a pricelist in the Repair form !\n Please set one before choosing a product.')}
        else:
            price = pricelist.get_product_price(self.product_id, self.product_uom_qty, partner)
            if price is False:
                warning = {
                    'title': _('No valid pricelist line found !'),
                    'message':
                        _("Couldn't find a pricelist line matching this product and quantity.\nYou have to change either the product, the quantity or the pricelist.")}
            else:
                self.price_unit = price
        if warning:
            return {'warning': warning}
示例#25
0
class BadgeUser(models.Model):
    """User having received a badge"""

    _name = 'gamification.badge.user'
    _description = 'Gamification user badge'
    _order = "create_date desc"
    _rec_name = "badge_name"

    user_id = fields.Many2one('res.users',
                              string="User",
                              required=True,
                              ondelete="cascade",
                              index=True)
    sender_id = fields.Many2one('res.users',
                                string="Sender",
                                help="The user who has send the badge")
    badge_id = fields.Many2one('gamification.badge',
                               string='Badge',
                               required=True,
                               ondelete="cascade",
                               index=True)
    challenge_id = fields.Many2one(
        'gamification.challenge',
        string='Challenge originating',
        help="If this badge was rewarded through a challenge")
    comment = fields.Text('Comment')
    badge_name = fields.Char(related='badge_id.name', string="Badge Name")
    create_date = fields.Datetime('Created', readonly=True)
    create_uid = fields.Many2one('res.users', string='Creator', readonly=True)

    def _send_badge(self):
        """Send a notification to a user for receiving a badge

        Does not verify constrains on badge granting.
        The users are added to the owner_ids (create badge_user if needed)
        The stats counters are incremented
        :param ids: list(int) of badge users that will receive the badge
        """
        template = self.env.ref('gamification.email_template_badge_received')

        for badge_user in self:
            self.env['mail.thread'].message_post_with_template(
                template.id,
                model=badge_user._name,
                res_id=badge_user.id,
                composition_mode='mass_mail',
                partner_ids=badge_user.user_id.partner_id.ids,
            )

        return True

    @api.model
    def create(self, vals):
        self.env['gamification.badge'].browse(
            vals['badge_id']).check_granting()
        return super(BadgeUser, self).create(vals)
class account_financial_report(models.Model):
    _name = "account.financial.report"
    _description = "Account Report"

    @api.multi
    @api.depends('parent_id', 'parent_id.level')
    def _get_level(self):
        '''Returns a dictionary with key=the ID of a record and value = the level of this  
           record in the tree structure.'''
        for report in self:
            level = 0
            if report.parent_id:
                level = report.parent_id.level + 1
            report.level = level

    def _get_children_by_order(self):
        '''returns a recordset of all the children computed recursively, and sorted by sequence. Ready for the printing'''
        res = self
        children = self.search([('parent_id', 'in', self.ids)], order='sequence ASC')
        if children:
            for child in children:
                res += child._get_children_by_order()
        return res

    name = fields.Char('Report Name', required=True, translate=True)
    parent_id = fields.Many2one('account.financial.report', 'Parent')
    children_ids = fields.One2many('account.financial.report', 'parent_id', 'Account Report')
    sequence = fields.Integer('Sequence')
    level = fields.Integer(compute='_get_level', string='Level', store=True)
    type = fields.Selection([
        ('sum', 'View'),
        ('accounts', 'Accounts'),
        ('account_type', 'Account Type'),
        ('account_report', 'Report Value'),
        ], 'Type', default='sum')
    account_ids = fields.Many2many('account.account', 'account_account_financial_report', 'report_line_id', 'account_id', 'Accounts')
    account_report_id = fields.Many2one('account.financial.report', 'Report Value')
    account_type_ids = fields.Many2many('account.account.type', 'account_account_financial_report_type', 'report_id', 'account_type_id', 'Account Types')
    sign = fields.Selection([(-1, 'Reverse balance sign'), (1, 'Preserve balance sign')], 'Sign on Reports', required=True, default=1,
                            help='For accounts that are typically more debited than credited and that you would like to print as negative amounts in your reports, you should reverse the sign of the balance; e.g.: Expense account. The same applies for accounts that are typically more credited than debited and that you would like to print as positive amounts in your reports; e.g.: Income account.')
    display_detail = fields.Selection([
        ('no_detail', 'No detail'),
        ('detail_flat', 'Display children flat'),
        ('detail_with_hierarchy', 'Display children with hierarchy')
        ], 'Display details', default='detail_flat')
    style_overwrite = fields.Selection([
        (0, 'Automatic formatting'),
        (1, 'Main Title 1 (bold, underlined)'),
        (2, 'Title 2 (bold)'),
        (3, 'Title 3 (bold, smaller)'),
        (4, 'Normal Text'),
        (5, 'Italic Text (smaller)'),
        (6, 'Smallest Text'),
        ], 'Financial Report Style', default=0,
        help="You can set up here the format you want this record to be displayed. If you leave the automatic formatting, it will be computed based on the financial reports hierarchy (auto-computed field 'level').")
示例#27
0
class ImLivechatReportOperator(models.Model):
    """ Livechat Support Report on the Operator """

    _name = "im_livechat.report.operator"
    _description = "Livechat Support Report"
    _order = 'livechat_channel_id, partner_id'
    _auto = False

    partner_id = fields.Many2one('res.partner', 'Operator', readonly=True)
    livechat_channel_id = fields.Many2one('im_livechat.channel',
                                          'Channel',
                                          readonly=True)
    nbr_channel = fields.Integer('# of Sessions',
                                 readonly=True,
                                 group_operator="sum",
                                 help="Number of conversation")
    channel_id = fields.Many2one('mail.channel', 'Conversation', readonly=True)
    start_date = fields.Datetime('Start Date of session',
                                 readonly=True,
                                 help="Start date of the conversation")
    time_to_answer = fields.Float(
        'Time to answer',
        digits=(16, 2),
        readonly=True,
        group_operator="avg",
        help="Average time to give the first answer to the visitor")
    duration = fields.Float('Average duration',
                            digits=(16, 2),
                            readonly=True,
                            group_operator="avg",
                            help="Duration of the conversation (in seconds)")

    @api.model_cr
    def init(self):
        # Note : start_date_hour must be remove when the read_group will allow grouping on the hour of a datetime. Don't forget to change the view !
        tools.drop_view_if_exists(self.env.cr, 'im_livechat_report_operator')
        self.env.cr.execute("""
            CREATE OR REPLACE VIEW im_livechat_report_operator AS (
                SELECT
                    row_number() OVER () AS id,
                    P.id as partner_id,
                    L.id as livechat_channel_id,
                    count(C.id) as nbr_channel,
                    C.id as channel_id,
                    C.create_date as start_date,
                    EXTRACT('epoch' FROM (max((SELECT (max(M.create_date)) FROM mail_message M JOIN mail_message_mail_channel_rel R ON (R.mail_message_id = M.id) WHERE R.mail_channel_id = C.id))-C.create_date)) as duration,
                    EXTRACT('epoch' from ((SELECT min(M.create_date) FROM mail_message M, mail_message_mail_channel_rel R WHERE M.author_id=P.id AND R.mail_channel_id = C.id AND R.mail_message_id = M.id)-(SELECT min(M.create_date) FROM mail_message M, mail_message_mail_channel_rel R WHERE M.author_id IS NULL AND R.mail_channel_id = C.id AND R.mail_message_id = M.id))) as time_to_answer
                FROM im_livechat_channel_im_user O
                    JOIN res_users U ON (O.user_id = U.id)
                    JOIN res_partner P ON (U.partner_id = P.id)
                    LEFT JOIN im_livechat_channel L ON (L.id = O.channel_id)
                    LEFT JOIN mail_channel C ON (C.livechat_channel_id = L.id)
                GROUP BY P.id, L.id, C.id, C.create_date
            )
        """)
示例#28
0
class SaleQuoteOption(models.Model):
    _name = "sale.quote.option"
    _description = "Quotation Option"

    template_id = fields.Many2one('sale.quote.template',
                                  'Quotation Template Reference',
                                  ondelete='cascade',
                                  index=True,
                                  required=True)
    name = fields.Text('Description', required=True, translate=True)
    product_id = fields.Many2one('product.product',
                                 'Product',
                                 domain=[('sale_ok', '=', True)],
                                 required=True)
    layout_category_id = fields.Many2one('sale.layout_category',
                                         string='Section')
    website_description = fields.Html('Option Description',
                                      translate=html_translate,
                                      sanitize_attributes=False)
    price_unit = fields.Float('Unit Price',
                              required=True,
                              digits=dp.get_precision('Product Price'))
    discount = fields.Float('Discount (%)',
                            digits=dp.get_precision('Discount'))
    uom_id = fields.Many2one('product.uom', 'Unit of Measure ', required=True)
    quantity = fields.Float('Quantity',
                            required=True,
                            digits=dp.get_precision('Product UoS'),
                            default=1)

    @api.onchange('product_id')
    def _onchange_product_id(self):
        if not self.product_id:
            return
        product = self.product_id
        self.price_unit = product.list_price
        self.website_description = product.product_tmpl_id.quote_description
        self.name = product.name
        self.uom_id = product.uom_id
        domain = {
            'uom_id':
            [('category_id', '=', self.product_id.uom_id.category_id.id)]
        }
        return {'domain': domain}

    @api.onchange('uom_id')
    def _onchange_product_uom(self):
        if not self.product_id:
            return
        if not self.uom_id:
            self.price_unit = 0.0
            return
        if self.uom_id.id != self.product_id.uom_id.id:
            self.price_unit = self.product_id.uom_id._compute_price(
                self.price_unit, self.uom_id)
示例#29
0
class Sponsor(models.Model):
    _name = "event.sponsor"
    _description = 'Event Sponsor'
    _order = "sequence"

    event_id = fields.Many2one('event.event', 'Event', required=True)
    sponsor_type_id = fields.Many2one('event.sponsor.type', 'Sponsoring Type', required=True)
    partner_id = fields.Many2one('res.partner', 'Sponsor/Customer', required=True)
    url = fields.Char('Sponsor Website')
    sequence = fields.Integer('Sequence', store=True, related='sponsor_type_id.sequence')
    image_medium = fields.Binary(string='Logo', related='partner_id.image_medium', store=True, attachment=True)
示例#30
0
class HrContract(models.Model):
    """
    Employee contract based on the visa, work permits
    allows to configure different Salary structure
    """
    _inherit = 'hr.contract'
    _description = 'Employee Contract'

    struct_id = fields.Many2one('hr.payroll.structure',
                                string='Salary Structure')
    schedule_pay = fields.Selection(
        [
            ('monthly', 'Monthly'),
            ('quarterly', 'Quarterly'),
            ('semi-annually', 'Semi-annually'),
            ('annually', 'Annually'),
            ('weekly', 'Weekly'),
            ('bi-weekly', 'Bi-weekly'),
            ('bi-monthly', 'Bi-monthly'),
        ],
        string='Scheduled Pay',
        index=True,
        default='monthly',
        help="Defines the frequency of the wage payment.")
    resource_calendar_id = fields.Many2one(required=True,
                                           help="Employee's working schedule.")

    @api.multi
    def get_all_structures(self):
        """
        @return: the structures linked to the given contracts, ordered by hierachy (parent=False first,
                 then first level children and so on) and without duplicata
        """
        structures = self.mapped('struct_id')
        if not structures:
            return []
        # YTI TODO return browse records
        return list(set(structures._get_parent_structure().ids))

    @api.multi
    def get_attribute(self, code, attribute):
        return self.env['hr.contract.advantage.template'].search(
            [('code', '=', code)], limit=1)[attribute]

    @api.multi
    def set_attribute_value(self, code, active):
        for contract in self:
            if active:
                value = self.env['hr.contract.advantage.template'].search(
                    [('code', '=', code)], limit=1).default_value
                contract[code] = value
            else:
                contract[code] = 0.0