class FleetVehicleLogFuel(models.Model):
    _name = 'fleet.vehicle.log.fuel'
    _inherit = ['fleet.vehicle.log.fuel', 'mail.thread', 'ir.needaction_mixin']
    _order = "date desc,vehicle_id desc"

    name = fields.Char()
    travel_id = fields.Many2one(
        'tms.travel',
        string='Travel',)
    expense_id = fields.Many2one(
        'tms.expense',
        string='Expense',)
    employee_id = fields.Many2one(
        'hr.employee',
        string='Driver',
        domain=[('driver', '=', True)],
        compute='_compute_employee_id',
        store=True,)
    odometer = fields.Float(related='vehicle_id.odometer',)
    product_uom_id = fields.Many2one(
        'product.uom',
        string='UoM ')
    product_qty = fields.Float(
        string='Liters',
        required=True,
        default=1.0,)
    tax_amount = fields.Float(
        string='Taxes',
        required=True,)
    price_total = fields.Float(
        string='Total',
        required=True,)
    special_tax_amount = fields.Float(
        compute="_compute_special_tax_amount",
        string='IEPS',)
    price_unit = fields.Float(
        compute='_compute_price_unit',
        string='Unit Price',)
    price_subtotal = fields.Float(
        string="Subtotal",
        compute='_compute_price_subtotal',)
    invoice_id = fields.Many2one(
        'account.invoice',
        'Invoice',
        readonly=True,
        domain=[('state', '!=', 'cancel')],)
    invoice_paid = fields.Boolean(
        compute='_compute_invoiced_paid')
    operating_unit_id = fields.Many2one(
        'operating.unit',
        string='Operating Unit',)
    currency_id = fields.Many2one(
        'res.currency', string='Currency',
        required=True,
        default=lambda self: self.env.user.company_id.currency_id,)
    notes = fields.Char()
    state = fields.Selection(
        [('draft', 'Draft'),
         ('approved', 'Approved'),
         ('confirmed', 'Confirmed'),
         ('closed', 'Closed'),
         ('cancel', 'Cancelled')],
        readonly=True,
        default='draft',)
    no_travel = fields.Boolean(
        help="Check this if you want to create Fuel Voucher "
        "with no Travel.",)
    vendor_id = fields.Many2one(
        'res.partner',
        required=True)
    product_id = fields.Many2one(
        'product.product',
        string='Product',
        required=True,
        domain=[('tms_product_category', '=', 'fuel')])
    currency_id = fields.Many2one(
        'res.currency', 'Currency', required=True,
        default=lambda self: self.env.user.company_id.currency_id)
    expense_control = fields.Boolean(
        readonly=True,
    )
    ticket_number = fields.Char()

    @api.multi
    @api.depends('vehicle_id')
    def _compute_employee_id(self):
        for rec in self:
            rec.employee_id = rec.vehicle_id.employee_id.id

    @api.multi
    @api.depends('tax_amount')
    def _compute_price_subtotal(self):
        for rec in self:
            rec.price_subtotal = 0
            if rec.tax_amount > 0:
                rec.price_subtotal = rec.tax_amount / 0.16

    @api.multi
    @api.depends('product_qty', 'price_subtotal')
    def _compute_price_unit(self):
        for rec in self:
            rec.price_unit = 0
            if rec.product_qty and rec.price_subtotal > 0:
                rec.price_unit = rec.price_subtotal / rec.product_qty

    @api.multi
    @api.depends('price_subtotal', 'tax_amount', 'price_total')
    def _compute_special_tax_amount(self):
        for rec in self:
            rec.special_tax_amount = 0
            if rec.price_subtotal and rec.price_total and rec.tax_amount > 0:
                rec.special_tax_amount = (
                    rec.price_total - rec.price_subtotal - rec.tax_amount)

    @api.multi
    def action_approved(self):
        for rec in self:
            message = _('<b>Fuel Voucher Approved.</b></br><ul>'
                        '<li><b>Approved by: </b>%s</li>'
                        '<li><b>Approved at: </b>%s</li>'
                        '</ul>') % (self.env.user.name, fields.Date.today())
            rec.message_post(body=message)
            rec.state = 'approved'

    @api.multi
    def action_cancel(self):
        for rec in self:
            if rec.invoice_id:
                raise ValidationError(
                    _('Could not cancel Fuel Voucher !'),
                    _('This Fuel Voucher is already Invoiced'))
            elif (rec.travel_id and
                  rec.travel_id.state == 'closed'):
                raise ValidationError(
                    _('Could not cancel Fuel Voucher !'
                        'This Fuel Voucher is already linked to Travel '
                        'Expenses record'))

    @api.model
    def create(self, values):
        res = super(FleetVehicleLogFuel, self).create(values)
        if not res.operating_unit_id.fuel_log_sequence_id:
            raise ValidationError(_(
                'You need to define the sequence for fuel logs in base %s' %
                res.operating_unit_id.name
            ))
        sequence = res.operating_unit_id.fuel_log_sequence_id
        res.name = sequence.next_by_id()
        return res

    @api.multi
    def set_2_draft(self):
        for rec in self:
            message = _(
                '<b>Fuel Voucher Draft.</b></br><ul>'
                '<li><b>Drafted by: </b>%s</li>'
                '<li><b>Drafted at: </b>%s</li>'
                '</ul>') % (self.env.user.name, fields.Date.today())
            rec.message_post(body=message)
            rec.state = 'draft'

    @api.multi
    def action_confirm(self):
        for rec in self:
            if (rec.product_qty <= 0 or
                    rec.tax_amount <= 0 or
                    rec.price_total <= 0):
                raise ValidationError(
                    _('Liters, Taxes and Total'
                      ' must be greater than zero.'))
            message = _(
                '<b>Fuel Voucher Confirmed.</b></br><ul>'
                '<li><b>Confirmed by: </b>%s</li>'
                '<li><b>Confirmed at: </b>%s</li>'
                '</ul>') % (self.env.user.name, fields.Date.today())
            rec.message_post(body=message)
            rec.state = 'confirmed'

    @api.onchange('travel_id')
    def _onchange_travel(self):
        self.vehicle_id = self.travel_id.unit_id
        self.employee_id = self.travel_id.employee_id

    @api.depends('invoice_id')
    def _compute_invoiced_paid(self):
        for rec in self:
            rec.invoice_paid = (
                rec.invoice_id.id and
                rec.invoice_id.state == 'paid')

    @api.onchange('no_travel')
    def _onchange_no_tracel(self):
        if self.no_travel:
            self.travel_id = False
            self.vehicle_id = False

    @api.multi
    def _amount_to_text(self, product_qty):
        total = str(float(product_qty)).split('.')[0]
        total = num2words(float(total), lang='es').upper()
        return '%s' % (total)
Exemplo n.º 2
0
class mrp_workcenter_product_cost(models.Model):

    _name = 'mrp.workcenter.product.cost'
    _description = 'Per-product workcenter cost'

    @api.model
    def _default_cost_concepts(self):
        mrp_wc_cost_concept_obj = self.env['mrp.workcenter.cost.concept']
        all_concept_names = mrp_wc_cost_concept_obj.search_read([], ['name'])
        lines = []
        for x in all_concept_names:
            lines.append((0, 0, {'name': x['name']}))
        return lines

    @api.multi
    def _get_cost_all(self):
        res = {}
        precision = self.env['decimal.precision'].precision_get(
            'Product costing')
        for record in self:
            res[record.id] = {
                'cost_hour': 0.0,
                'cost_cycle': 0.0,
                'cost_uom': 0.0,
                }
            for line in record.line_ids:
                record.cost_hour += line.cost
            record.cost_cycle = round(
                record.cost_hour * \
                record.time_cycle, precision)
            record.cost_uom = round(
                record.cost_cycle / \
                (record.capacity_per_cycle * \
                 record.product_efficiency), precision)

    workcenter_id = fields.Many2one(comodel_name="mrp.workcenter",
                                    string="Workcenter", required=True)
    # TODO: Filtro para que sólo se muestren productos que usen esta máquina.
    product_id = fields.Many2one(comodel_name="product.product",
            string="Product", required=True)
    product_tmpl_id = fields.Many2one(comodel_name="product.template", string="Product template",
        related="product_id.product_tmpl_id")
    sequence = fields.Integer(string="Sequence", required=True, default=10)
    capacity_per_cycle = fields.Float(string="Capacity/cycle", required=True,
            help="Quantity of production product (in product's UoM) "
                 "that the workcenter contributes to produce in a cycle.",
            digits=(4, 5), default=1.0)
    time_cycle = fields.Float(string="Cycle time",
            help="Time needed for this machine to complete"
                 " one cycle.", digits=(4, 9))
    product_efficiency = fields.Float(string="Efficiency factor",
            help="A factor of 0.9 means a loss of 10% during the production "
                 "process.",
            required=True, default=1.0)
    cost_hour = fields.Float(string="Cost per hour",
                             digits=dp.get_precision('Product costing'),
                             help="Calculated cost per hour.",
                             compute=_get_cost_all)
    cost_cycle = fields.Float(string="Cost per cycle",
                              digits=dp.get_precision('Product costing'),
                              help="Calculated cost per cycle.",
                              compute=_get_cost_all)
    cost_uom = fields.Float(string="Cost per UoM",
                            digits=dp.get_precision('Product costing'),
                            help="Calculated cost per product's UoM.",
                            compute=_get_cost_all)
    line_ids = fields.One2many(comodel_name="mrp.workcenter.product.cost.item",
                               inverse_name="workcenter_product_cost_id",
                               string="Cost details",
                               default=_default_cost_concepts
                               )

    @api.one
    @api.constrains('capacity_per_cycle')
    def _check_qty(self):
        if self.capacity_per_cycle <= 0:
            raise ValidationError("Capacity per cycle cannot "
                                  "be negative or zero!")
        return True

    # Do not allow to declare several cost lines for the same product on a
    # given workcenter
    _sql_constraints = [
        ('product_uniq', 'unique(workcenter_id, product_id)',
         _("A product's cost definition must be unique per work center!")),
        ]
Exemplo n.º 3
0
class ProductUomTotal(models.Model):
    _inherit = 'product.uom.total'

    dim_quantity = fields.Float(string='Nombre',
                                digits_compute=dp.get_precision('Product UoS'))
Exemplo n.º 4
0
class stock_count(models.Model):
    _name = 'stock.count'

    _description = 'statistics stock inventory,On Hand ,Draft,Commit, \
        Backorder,Available,On Order'

    product_id = fields.Many2one('product.product', 'Product')
    location_id = fields.Many2one('stock.location', 'Inventory Location')
    report_date = fields.Datetime('Report Date')
    on_hand_qty = fields.Float('ON hand')
    draft_qty = fields.Float('Draft')
    commit_qty = fields.Float('commit')
    backorder_qty = fields.Float('Backorder')
    available_qty = fields.Float('Available')
    on_order_qty = fields.Float('On Order')
    on_sale_qty = fields.Float('On Sale')

    _order = "product_id,location_id"

    @api.multi
    def compute_stock_report(self, product_ids=[], location_ids=[]):
        if not product_ids:
            product_ids = [
                x.id for x in self.env['product.product'].search([('active',
                                                                   '=', True)])
            ]
        if not location_ids:
            location_ids = [
                x.id for x in self.env['stock.location'].search([('is_compute',
                                                                  '=', True)])
            ]

        self.delete_stock_count_old_data(product_ids, location_ids)

        vals = self.prepare_stock_report_data(product_ids, location_ids)
        for val in vals:
            self.create(val)

    def delete_stock_count_old_data(self, product_ids=[], location_ids=[]):
        count_ids = self.search([('product_id', 'in', product_ids),
                                 ('location_id', 'in', location_ids)])
        if count_ids:
            count_ids.unlink()

    def prepare_stock_report_data(self, product_ids=[], location_ids=[]):
        products = self.env['product.product'].browse(product_ids)
        draft_vals = self.prepare_draft_qty()
        vals = []

        for location in self.env['stock.location'].browse(location_ids):
            qtys = {}
            qtys = self.pool.get('product.product')._product_available(
                self.env.cr,
                self.env.uid,
                product_ids,
                context={'location': location.id})

            for product in products:
                product_qtys = qtys.get(product.id, {})
                outgoing_qty = product_qtys.get('outgoing_qty', 0)
                on_hand_qty = product_qtys.get('qty_available', 0)

                val_line = {
                    'product_id':
                    product.id,
                    'location_id':
                    location.id,
                    'report_date':
                    datetime.datetime.today(),
                    'draft_qty':
                    0,
                    'on_hand_qty':
                    on_hand_qty,
                    'commit_qty':
                    self.prepare_commit(outgoing_qty, on_hand_qty),
                    'backorder_qty':
                    self.prepare_backorder(outgoing_qty, on_hand_qty),
                    'available_qty':
                    self.prepare_available(outgoing_qty, on_hand_qty),
                    'on_order_qty':
                    product_qtys.get('incoming_qty', 0),
                    'on_sale_qty':
                    outgoing_qty
                }

                if location.is_draft_location:
                    val_line.update(
                        {'draft_qty': draft_vals.get(product.id, 0)})
                vals.append(val_line)
        return vals

    def get_value_from_params(self):
        return

    def prepare_commit(self, sale_qty, on_hand_qty):
        return min(sale_qty, on_hand_qty)

    def prepare_backorder(self, sale_qty, on_hand_qty):
        if sale_qty >= on_hand_qty:
            return (sale_qty - on_hand_qty)
        return 0

    def prepare_available(self, sale_qty, on_hand_qty):
        if on_hand_qty > sale_qty:
            return on_hand_qty - sale_qty
        return 0

    def prepare_draft_qty(self):
        sale_orde_obj = self.env['sale.order']
        sale_order_draft_ids = [
            x.id
            for x in sale_orde_obj.search([('is_draft', '=',
                                            'True'), ('state', '=', 'draft')])
        ]

        order_line_obj = self.env['sale.order.line']
        count_res = order_line_obj.read_group(
            [['order_id', 'in', sale_order_draft_ids]],
            ['product_uom_qty', 'product_id'], ['product_id'])

        vals = {}
        for count in count_res:
            if count['product_id']:
                product_id = count['product_id'][0]
                draft_qty = count['product_uom_qty']
                vals[product_id] = draft_qty
        return vals
Exemplo n.º 5
0
class CashFlowReport(models.TransientModel):
    _name = 'cash.flow'
    _description = u'Relatório de Fluxo de Caixa'

    @api.one
    def calc_final_amount(self):
        balance = 0
        for line in self.line_ids:
            balance += line.amount
        balance += self.start_amount
        self.final_amount = balance

    name = fields.Char(string="Descrição", required=True)
    start_date = fields.Date(string="Data Inicio",
                             required=True,
                             default=fields.date.today())
    end_date = fields.Date(string="Data Fim",
                           required=True,
                           default=fields.date.today() +
                           datetime.timedelta(6 * 365 / 12))
    start_amount = fields.Float(string="Valor Inicial",
                                digits_compute=dp.get_precision('Account'))
    final_amount = fields.Float(string="Valor Final",
                                compute="calc_final_amount",
                                digits_compute=dp.get_precision('Account'))
    line_ids = fields.One2many("cash.flow.line",
                               "cashflow_id",
                               string="Linhas Fluxo de Caixa")

    @api.multi
    def calculate_liquidity(self):
        accs = self.env['account.account'].search([('type', '=', 'liquidity')])
        liquidity_lines = []
        for acc in accs:
            if acc.balance != 0:
                liquidity_lines.append({
                    'name': acc.name,
                    'cashflow_id': self.id,
                    'account_id': acc.id,
                    'debit': acc.credit,
                    'credit': acc.debit,
                    'amount': acc.balance,
                })
        return liquidity_lines

    @api.multi
    def calculate_moves(self):
        moveline_obj = self.env['account.move.line']
        moveline_ids = moveline_obj.search([
            '|',
            ('account_id.type', '=', 'receivable'),
            ('account_id.type', '=', 'payable'),
            ('reconcile_id', '=', False),
            ('state', '!=', 'draft'),
            ('company_id', '=', self.env.user.company_id.id),
            ('date_maturity', '<=', self.end_date),
        ])
        moves = []
        for move in moveline_ids:
            debit, credit = move.credit, move.debit
            amount = move.debit - move.credit
            if move.reconcile_partial_id:
                move_ids = moveline_obj.search([
                    ('reconcile_partial_id', '=', move.reconcile_partial_id.id)
                ])
                debit = sum(line.credit for line in move_ids)
                credit = sum(line.debit for line in move_ids)
                amount = credit - debit

            moves.append({
                'name': move.ref,
                'cashflow_id': self.id,
                'partner_id': move.partner_id.id,
                'journal_id': move.journal_id.id,
                'account_id': move.account_id.id,
                'date': move.date_maturity,
                'debit': debit,
                'credit': credit,
                'amount': amount,
            })
        return moves

    @api.multi
    def button_calculate(self):
        self.write({'line_ids': [(5, 0, 0)]})
        balance = self.start_amount
        liquidity_lines = self.calculate_liquidity()
        move_lines = self.calculate_moves()

        move_lines.sort(
            key=lambda x: datetime.datetime.strptime(x['date'], '%Y-%m-%d'))

        for lines in liquidity_lines + move_lines:
            balance += lines['credit'] - lines['debit']
            lines['balance'] = balance
            self.env['cash.flow.line'].create(lines)
Exemplo n.º 6
0
class jmdventa(models.Model):
    _name = "ae.venta"
    _inherit = "mail.thread"

    def create_move(self, cr, uid, ids, args, context=None):
        ret = {}
        for i in self.browse(cr, uid, ids, context):
            if i.poliza_generada:
                return ret
            #creando la poliza
            #print("Por crear la poliza")
            #poliza_obj = self.pool.get("account.move")
            #idpoliza = poliza_obj.create(cr, uid, {
            #        'name': i.concepto_poliza,
            #        'journal_id': i.diario.id,
            #    }, context)
            #print("Poliza Creada")
            #linea_obj = self.pool.get("account.move.line")
            #linea_obj.create(cr, uid, {
            #        'name': i.concepto_poliza,
            #        'account_id': i.cuenta_cargo.id,
            #        'debit': i.monto,
            #        'move_id': idpoliza,
            #    }, context)
            #print("Poliza de Cargo Creada")
            #linea_obj.create(cr, uid, {
            #        'name': i.concepto_poliza,
            #        'account_id': i.cuenta_abono.id,
            #        'credit': i.monto,
            #        'move_id': idpoliza,
            #    }, context)
            #self.write(cr, uid, [i.id], {
            #    'poliza_generada': "Si"
            #    })
        return ret

    def create_invoice(self, cr, uid, ids, args, context=None):
        ret = {}
        for i in self.browse(cr, uid, ids, context):
            if i.factura:
                return ret
            invoice_obj = self.pool.get("account.invoice")
            idfactura = invoice_obj.create(cr, uid, {
                    'name': i.concepto_factura,
                    'partner_id': i.coproductor.id,
                    'account_id': i.cuenta_factura.id,
                })
            self.write(cr, uid, [i.id], {
                    'factura': idfactura
                })
        return ret

    name = fields.Char("Nombre")
    ventana = fields.Many2one("ae.ventana", "Ventana")
    territorio = fields.Many2one("ae.territorio", "Territorio")
    inicio = fields.Date("Inicio")
    fin = fields.Date("Fin")
    monto = fields.Float("Monto")
    tipo = fields.Selection([('capital', 'Capital'), ('especie', 'Especie')],
        "Tipo de contribución")
    proyecto = fields.Many2one("ae.proyecto", "Proyecto")
    coproductor = fields.Many2one("res.partner", string="Cliente")
    cuenta_cargo = fields.Many2one("account.account", string="Cuenta de Cargo")
    cuenta_abono = fields.Many2one("account.account", string="Cuenta Abono")
    concepto_poliza = fields.Char("Concepto de la Póliza")
    poliza_generada = fields.Char("Poliza Generada")
    diario = fields.Many2one("account.journal", string="Diario")
    factura = fields.One2many("account.invoice", "venta_id", string="Factura")
    concepto_factura = fields.Char("Concepto de la Factura")
    cuenta_factura = fields.Many2one("account.account", string="Cuenta de la\
        Factura")
Exemplo n.º 7
0
class ComputedPurchaseOrder(models.Model):
    _description = 'Computed Purchase Order'
    _name = 'computed.purchase.order'
    _order = 'id desc'

    # Constant Values
    _DEFAULT_NAME = _('New')

    _STATE = [
        ('draft', 'Draft'),
        ('done', 'Done'),
        ('canceled', 'Canceled'),
    ]

    _TARGET_TYPE = [
        ('product_price_inv_eq', '€'),
        ('time', 'days'),
        ('weight', 'kg'),
    ]

    _VALID_PSI = [
        ('first', 'Consider only the first supplier on the product'),
        ('all', 'Consider all the suppliers registered on the product'),
    ]

    # Columns section
    name = fields.Char(
        'Computed Purchase Order Reference',
        size=64,
        required=True,
        readonly=True,
        default=_DEFAULT_NAME,
        help="""Unique number of the automated purchase order, computed"""
        """ automatically when the computed purchase order is created.""")
    company_id = fields.Many2one(
        'res.company',
        'Company',
        readonly=True,
        required=True,
        help="""When you will validate this item, this will create a"""
        """ purchase order for this company.""",
        default=lambda self: self.env.user.company_id,
    )
    active = fields.Boolean(
        'Active',
        default=True,
        help="""By unchecking the active field, you may hide this item"""
        """ without deleting it.""")
    state = fields.Selection(_STATE, 'State', required=True, default='draft')
    incoming_date = fields.Date('Wished Incoming Date',
                                help="Wished date for products delivery.")
    partner_id = fields.Many2one('res.partner',
                                 'Supplier',
                                 required=True,
                                 domain=[('supplier', '=', True)],
                                 help="Supplier of the purchase order.")
    line_ids = fields.One2many(comodel_name='computed.purchase.order.line',
                               inverse_name='computed_purchase_order_id',
                               string='Order Lines',
                               help="Products to order.")
    # this is to be able to display the line_ids on 2 tabs of the view
    stock_line_ids = fields.One2many(
        compute='_get_stock_line_ids',
        comodel_name='computed.purchase.order.line',
        inverse_name='computed_purchase_order_id',
        help="Products to order.")
    compute_pending_quantity = fields.Boolean(
        'Pending quantity taken in account', default=True)
    purchase_order_id = fields.Many2one('purchase.order',
                                        'Purchase Order',
                                        readonly=True)
    purchase_target = fields.Integer('Purchase Target', default=0)
    target_type = fields.Selection(
        _TARGET_TYPE,
        'Target Type',
        required=True,
        default='product_price_inv_eq',
        help="""This defines the amount of products you want to"""
        """ purchase. \n"""
        """The system will compute a purchase order based on the stock"""
        """ you have and the average consumption of each product."""
        """ * Target type '€': computed purchase order will cost at"""
        """ least the amount specified\n"""
        """ * Target type 'days': computed purchase order will last"""
        """ at least the number of days specified (according to current"""
        """ average consumption)\n"""
        """ * Target type 'kg': computed purchase order will weight at"""
        """ least the weight specified""")
    valid_psi = fields.Selection(_VALID_PSI,
                                 'Supplier choice',
                                 required=True,
                                 default='first',
                                 help="""Method of selection of suppliers""")
    computed_amount = fields.Float(
        compute='_get_computed_amount_duration',
        digits_compute=dp.get_precision('Product Price'),
        string='Amount of the computed order',
        multi='computed_amount_duration')
    computed_duration = fields.Integer(compute='_get_computed_amount_duration',
                                       string='Minimum duration after order',
                                       multi='computed_amount_duration')
    products_updated = fields.Boolean(
        compute='_get_products_updated',
        string='Indicate if there were any products updated in the list')

    # Fields Function section
    @api.onchange('line_ids')
    @api.multi
    def _get_stock_line_ids(self):
        for spo in self:
            self.stock_line_ids = self.line_ids

    @api.multi
    def _get_computed_amount_duration(self):
        for cpo in self:
            min_duration = 999
            amount = 0
            for line in cpo.line_ids:
                if line.average_consumption != 0:
                    duration = (line.computed_qty + line.purchase_qty)\
                        / line.average_consumption
                    min_duration = min(duration, min_duration)
                amount += line.subtotal
            cpo.computed_amount = amount
            cpo.computed_duration = min_duration

    @api.multi
    def _get_products_updated(self):
        for cpo in self:
            updated = False
            for line in cpo.line_ids:
                if line.state == 'updated':
                    updated = True
                    break
            cpo.products_updated = updated

    # View Section
    @api.onchange('partner_id')
    def onchange_partner_id(self):
        # TODO: create a wizard to validate the change
        self.purchase_target = 0
        self.target_type = 'product_price_inv_eq'
        if self.partner_id:
            self.purchase_target = self.partner_id.purchase_target
            self.target_type = self.partner_id.target_type
        self.line_ids = map(lambda x: (2, x.id, False), self.line_ids)

    # Overload Section
    @api.model
    def create(self, vals):
        if vals.get('name', self._DEFAULT_NAME) == self._DEFAULT_NAME:
            vals['name'] = self.env['ir.sequence'].get(
                'computed.purchase.order') or '/'
        order = super(ComputedPurchaseOrder, self).create(vals)
        return order

    @api.multi
    def write(self, vals):
        cpo_id = super(ComputedPurchaseOrder, self).write(vals)
        if self.update_sorting(vals):
            self._sort_lines()
        return cpo_id

    @api.multi
    def update_sorting(self, vals):
        for cpo in self:
            try:
                line_ids = vals.get('line_ids', False)
                if not line_ids:
                    return False
                # this context check will allow you to change the field list
                # without overriding the whole function
                need_sorting_fields = self.env.context.get(
                    'need_sorting_fields', False)
                if not need_sorting_fields:
                    need_sorting_fields = [
                        'average_consumption',
                        'computed_qty',
                        'stock_duration',
                        'manual_input_output_qty',
                    ]
                for value in line_ids:
                    if len(value) > 2 and value[2] and isinstance(
                            value[2], dict) and (set(need_sorting_fields)
                                                 & set(value[2].keys())):
                        return True
                return False
            except:
                return False

    # Private Section
    @api.multi
    def _sort_lines(self):
        cpol_obj = self.env['computed.purchase.order.line']
        for cpo in self:
            lines = cpol_obj.browse([x.id for x in cpo.line_ids]).read(
                ['stock_duration', 'average_consumption'])
            lines = sorted(lines,
                           key=lambda line: line['average_consumption'],
                           reverse=True)
            lines = sorted(lines, key=lambda line: line['stock_duration'])

            id_index_list = {}
            for i in lines:
                id_index_list[i['id']] = lines.index(i)
            for line_id in id_index_list.keys():
                cpol_obj.browse(line_id).write(
                    {'sequence': id_index_list[line_id]})

    @api.model
    def _make_po_lines(self):
        all_lines = []
        for line in self.line_ids:
            if line.purchase_qty != 0:
                line_values = {
                    'name':
                    "%s%s" %
                    (line.product_code_inv
                     and '[' + line.product_code_inv + '] ' or '',
                     line.product_name_inv or line.product_id.name_template),
                    'product_qty':
                    line.purchase_qty,
                    'package_qty':
                    line.package_qty,
                    'product_qty_package':
                    (line.purchase_qty / line.package_qty),
                    'price_policy':
                    line.price_policy,
                    'date_planned': (self.incoming_date
                                     or fields.Date.context_today(self)),
                    'product_uom':
                    line.product_id.uom_po_id.id,
                    'product_id':
                    line.product_id.id,
                    'price_unit':
                    line.product_price_inv,
                    'discount':
                    line.discount_inv,
                    'taxes_id':
                    [(6, 0, [x.id
                             for x in line.product_id.supplier_taxes_id])],
                }
                all_lines.append((0, 0, line_values), )
        return all_lines

    @api.multi
    def _compute_purchase_quantities_days(self):
        for cpo in self:
            days = cpo.purchase_target
            for line in cpo.line_ids:
                if line.average_consumption:
                    quantity = max(
                        days * line.average_consumption *
                        line.uom_po_id.factor / line.uom_id.factor -
                        line.computed_qty, 0)
                    if line.package_qty \
                            and quantity % line.package_qty:
                        quantity = ceil(quantity / line.package_qty) *\
                            line.package_qty
                elif line.computed_qty == 0:
                    quantity = line.package_qty or 0
                else:
                    quantity = 0
                line.purchase_qty = quantity
                line.purchase_qty_package = quantity / line.package_qty

    @api.multi
    def _compute_purchase_quantities_other(self, field):
        for cpo in self:
            cpol_obj = self.env['computed.purchase.order.line']
            if not cpo.line_ids:
                return False
            target = cpo.purchase_target
            ok = False
            days = -1
            field_list = cpol_obj.browse([x.id
                                          for x in cpo.line_ids]).read([field])
            field_list_dict = {}
            for i in field_list:
                field_list_dict[i['id']] = i[field]

            while not ok:
                days += 1
                qty_tmp = {}
                for line in cpo.line_ids:
                    if line.average_consumption:
                        quantity = max(
                            days * line.average_consumption *
                            line.uom_po_id.factor / line.uom_id.factor -
                            line.computed_qty, 0)
                        if line.package_qty and\
                                quantity % line.package_qty:
                            quantity = ceil(quantity / line.package_qty)\
                                * line.package_qty
                    elif line.computed_qty == 0:
                        quantity = line.package_qty or 0
                    else:
                        quantity = 0
                    qty_tmp[line.id] = quantity

                ok = cpo._check_purchase_qty(target, field_list_dict, qty_tmp)

            for line in cpo.line_ids:
                line.purchase_qty = qty_tmp[line.id]
                line.purchase_qty_package = qty_tmp[line.id] / line.package_qty

    @api.model
    def _check_purchase_qty(self, target=0, field_list=None, qty_tmp=None):
        if not target or field_list is None or qty_tmp is None:
            return True
        total = 0
        for key in field_list.keys():
            total += field_list[key] * qty_tmp[key]
        return total >= target

    # Action section
    @api.multi
    def compute_active_product_stock(self):
        psi_obj = self.env['product.supplierinfo']
        for cpo in self:
            cpol_list = []
            # TMP delete all rows,
            # TODO : depends on further request to avoid user data to be lost
            cpo.line_ids.unlink()

            # Get product_product and compute stock
            for psi in psi_obj.search([('name', '=', cpo.partner_id.id)]):
                for pp in psi.product_tmpl_id.filtered(
                        lambda pt: pt.state not in
                    ('end', 'obsolete')).product_variant_ids:
                    valid_psi = pp._valid_psi(cpo.valid_psi)
                    if valid_psi and psi in valid_psi[0]:
                        cpol_list.append((0, 0, {
                            'product_id':
                            pp.id,
                            'state':
                            'up_to_date',
                            'product_code':
                            psi.product_code,
                            'product_name':
                            psi.product_name,
                            'product_price':
                            psi.base_price,
                            'price_policy':
                            psi.price_policy,
                            'package_qty':
                            psi.package_qty or psi.min_qty,
                            'displayed_average_consumption':
                            pp.displayed_average_consumption,
                            'consumption_range':
                            pp.display_range,
                            'uom_po_id':
                            psi.product_uom.id,
                        }))
            # update line_ids
            self.line_ids = cpol_list

    @api.multi
    def compute_purchase_quantities(self):
        for cpo in self:
            if any([line.average_consumption for line in cpo.line_ids]):
                if cpo.target_type == 'time':
                    return cpo._compute_purchase_quantities_days()
                else:
                    return cpo._compute_purchase_quantities_other(
                        field=cpo.target_type)

    @api.multi
    def make_order(self):
        for cpo in self:
            po_lines = cpo._make_po_lines()
            if not po_lines:
                raise ValidationError(
                    _('All purchase quantities are set to 0!'))

            po_obj = self.env['purchase.order']
            po_values = {
                'origin':
                cpo.name,
                'partner_id':
                cpo.partner_id.id,
                'location_id':
                self.env['res.users'].browse(self.env.uid).company_id.
                partner_id.property_stock_customer.id,
                'order_line':
                po_lines,
                'date_planned': (cpo.incoming_date
                                 or fields.Date.context_today(self)),
            }
            po_id = po_obj.create(po_values)
            cpo.state = 'done'
            cpo.purchase_order_id = po_id

            mod_obj = self.env['ir.model.data']
            res = mod_obj.get_object_reference('purchase',
                                               'purchase_order_form')
            res_id = res and res[1] or False
            return {
                'name': _('Purchase Order'),
                'view_type': 'form',
                'view_mode': 'form',
                'views': [(res_id, 'form')],
                'view_id': [res_id],
                'res_model': 'purchase.order',
                'type': 'ir.actions.act_window',
                'nodestroy': True,
                'target': 'current',
                'res_id': po_id.id or False,
            }
Exemplo n.º 8
0
class IndividualProgram(models.Model):
    '''Individual Program'''
    _inherit = 'school.individual_program'

    state = fields.Selection(
        [
            ('draft', 'Draft'),
            ('progress', 'In Progress'),
            ('awarded', 'Awarded'),
            ('abandonned', 'Abandonned'),
        ],
        string='Status',
        index=True,
        default='draft',
        copy=False,
        help=
        " * The 'Draft' status is used when results are not confirmed yet.\n"
        " * The 'In Progress' status is used during the cycle.\n"
        " * The 'Awarded' status is used when the cycle is awarded.\n"
        " * The 'Abandonned' status is used if a student leave the program.\n",
        track_visibility='onchange')

    abandonned_date = fields.Date('Abandonned Date')

    @api.multi
    def set_to_draft(self, context):
        # TODO use a workflow to make sure only valid changes are used.
        return self.write({'state': 'draft'})

    @api.multi
    def set_to_progress(self, context):
        # TODO use a workflow to make sure only valid changes are used.
        return self.write({'state': 'progress'})

    @api.multi
    def set_to_awarded(self,
                       context,
                       grade_year_id=None,
                       grade=None,
                       grade_comments=None):
        # TODO use a workflow to make sure only valid changes are used.
        if (grade):
            self.write({
                'state': 'awarded',
                'grade': grade,
                'grade_year_id': grade_year_id,
                'grade_comments': grade_comments,
                'graduation_date': fields.Date.today(),
            })
        else:
            self.write({
                'state': 'awarded',
                'grade_year_id': grade_year_id,
                'graduation_date': fields.Date.today(),
            })

    @api.multi
    def set_to_abandonned(self, context):
        # TODO use a workflow to make sure only valid changes are used.
        return self.write({
            'state': 'abandonned',
            'abandonned_date': fields.Date.today()
        })

    historical_bloc_1_eval = fields.Float(
        string="Hist Bloc 1 Eval",
        track_visibility='onchange',
        digits=dp.get_precision('Evaluation'))
    historical_bloc_1_credits = fields.Integer(string="Hist Bloc 1 ECTS",
                                               track_visibility='onchange')

    historical_bloc_2_eval = fields.Float(
        string="Hist Bloc 2 Eval",
        track_visibility='onchange',
        digits=dp.get_precision('Evaluation'))
    historical_bloc_2_credits = fields.Integer(string="Hist Bloc 2 ECTS",
                                               track_visibility='onchange')

    grade = fields.Selection([
        ('without', 'Without Grade'),
        ('satisfaction', 'Satisfaction'),
        ('distinction', 'Distinction'),
        ('second_class', 'Second Class Honor'),
        ('first_class', 'First Class Honor'),
    ],
                             string="Grade",
                             track_visibility='onchange')

    grade_year_id = fields.Many2one('school.year',
                                    string="Graduation year",
                                    track_visibility='onchange')

    graduation_date = fields.Date(string="Graduation Date",
                                  track_visibility='onchange')

    grade_comments = fields.Text(string="Grade Comments",
                                 track_visibility='onchange')

    evaluation = fields.Float(string="Evaluation",
                              compute="compute_evaluation",
                              digits=dp.get_precision('Evaluation'))

    total_registered_credits = fields.Integer(
        compute='_get_total_acquiered_credits',
        string='Registered Credits',
        track_visibility='onchange')
    total_acquiered_credits = fields.Integer(
        compute='_get_total_acquiered_credits',
        string='Acquiered Credits',
        store=True,
        track_visibility='onchange')

    program_completed = fields.Boolean(compute='_get_total_acquiered_credits',
                                       string="Program Completed",
                                       store=True,
                                       track_visibility='onchange')

    @api.depends('required_credits', 'bloc_ids.state',
                 'bloc_ids.total_acquiered_credits',
                 'historical_bloc_1_credits', 'historical_bloc_2_credits')
    @api.one
    def _get_total_acquiered_credits(self):
        _logger.debug('Trigger "_get_total_acquiered_credits" on Program %s' %
                      self.name)
        total = sum(
            bloc_id.total_acquiered_credits if bloc_id.state in
            ['awarded_first_session', 'awarded_second_session', 'failed'
             ] else 0 for bloc_id in self.bloc_ids)
        total_current = sum(bloc_id.total_credits if bloc_id.state in
                            ['progress', 'postponed'] else 0
                            for bloc_id in self.bloc_ids)
        self.total_acquiered_credits = total + self.historical_bloc_1_credits + self.historical_bloc_2_credits
        self.program_completed = self.total_acquiered_credits >= self.required_credits

    # TODO : Fix this it does not seem right
    @api.depends('grade')
    def _onchange_grade(self):
        if self.grade:
            graduation_date = fields.Date.today()
        self.total_registered_credits = self.total_acquiered_credits + total_current
        self.program_completed = self.required_credits > 0 and self.total_acquiered_credits >= self.required_credits

    @api.depends('bloc_ids.evaluation', 'historical_bloc_1_eval',
                 'historical_bloc_2_eval')
    @api.one
    def compute_evaluation(self):
        total = 0
        count = 0
        for bloc in self.bloc_ids:
            if bloc.evaluation > 0:  # if all is granted do not count
                total += bloc.evaluation
                count += 1
        if self.historical_bloc_1_eval > 0:
            total += self.historical_bloc_1_eval
            count += 1
        if self.historical_bloc_2_eval > 0:
            total += self.historical_bloc_2_eval
            count += 1
        if count > 0:
            self.evaluation = total / count
        # TODO : Implement computation based on UE as per the decret

    @api.depends('bloc_ids.evaluation', 'historical_bloc_1_eval',
                 'historical_bloc_2_eval')
    @api.multi
    def compute_evaluation_details(self):
        self.ensure_one()
        ret = [0, 0, 0, 0, 0, 0]
        if self.historical_bloc_1_eval > 0:
            ret[0] = self.historical_bloc_1_eval
        if self.historical_bloc_2_eval > 0:
            ret[1] = self.historical_bloc_2_eval
        for bloc in self.bloc_ids:
            ret[int(bloc.source_bloc_level) - 1] = bloc.evaluation
        return {'bloc_evaluations': ret}
Exemplo n.º 9
0
class IndividualCourseGroup(models.Model):
    '''Individual Course Group'''
    _inherit = 'school.individual_course_group'

    ## Compute dispensed hours and ECTS

    total_dispensed_credits = fields.Integer(compute="compute_credits",
                                             string="Dispensed Credits",
                                             store=True)
    total_dispensed_hours = fields.Integer(compute="compute_credits",
                                           string="Dispensed Hours",
                                           store=True)
    total_not_dispensed_credits = fields.Integer(
        compute="compute_credits", string="Not Dispensed Credits", store=True)
    total_not_dispensed_hours = fields.Integer(compute='compute_credits',
                                               string='Not Dispensed Hours',
                                               store=True)

    @api.depends('course_ids.dispense')
    @api.one
    def compute_credits(self):
        self.total_dispensed_credits = sum(
            [ic.credits for ic in self.course_ids if ic.dispense])
        self.total_dispensed_hours = sum(
            [ic.hours for ic in self.course_ids if ic.dispense])
        self.total_not_dispensed_credits = self.total_credits - self.total_dispensed_credits
        self.total_not_dispensed_hours = self.total_hours - self.total_dispensed_hours

    # Actions
    @api.one
    def set_deliberated_to_ten(self, session=1, message=''):
        if session == 1:
            self.write({
                'first_session_deliberated_result':
                max(self.first_session_computed_result, 10),
                'first_session_deliberated_result_bool':
                True,
                'first_session_note':
                message,
            })
        else:
            self.write({
                'second_session_deliberated_result':
                max(self.second_session_computed_result, 10)
                if self.second_session_computed_result_bool else max(
                    self.first_session_computed_result, 10),
                'second_session_deliberated_result_bool':
                True,
                'second_session_note':
                message,
            })

    state = fields.Selection(
        [
            ('draft', 'Draft'),
            ('progress', 'In Progress'),
            ('finish', 'Awarded'),
        ],
        string='Status',
        index=True,
        readonly=True,
        default='draft',
        #track_visibility='onchange', TODO : is this useful for this case ?
        copy=False,
        help=
        " * The 'Draft' status is used when results are not confirmed yet.\n"
        " * The 'Confirmed' status is when restults are confirmed.")

    ## If set a course with an evaluation < 10 will make this course group not acquiered.

    enable_exclusion_bool = fields.Boolean(
        string='Enable exclusion evaluation',
        related="source_course_group_id.enable_exclusion_bool",
        readonly=True)

    ## First Session ##

    first_session_computed_result = fields.Float(
        compute='compute_average_results',
        string='First Session Computed Result',
        store=True,
        digits=dp.get_precision('Evaluation'))
    first_session_computed_result_bool = fields.Boolean(
        compute='compute_average_results',
        string='First Session Computed Active',
        store=True)
    first_session_computed_exclusion_result_bool = fields.Boolean(
        compute='compute_average_results',
        string='First Session Exclusion Result',
        store=True)

    first_session_deliberated_result = fields.Char(
        string='First Session Deliberated Result', track_visibility='onchange')
    first_session_deliberated_result_bool = fields.Boolean(
        string='First Session Deliberated Active', track_visibility='onchange')

    first_session_result = fields.Float(
        compute='compute_first_session_results',
        string='First Session Result',
        store=True,
        digits=dp.get_precision('Evaluation'))
    first_session_result_bool = fields.Boolean(
        compute='compute_first_session_results',
        string='First Session Active',
        store=True)
    first_session_acquiered = fields.Selection(
        ([('A', 'Acquired'), ('NA', 'Not Acquired')]),
        compute='compute_first_session_acquiered',
        string='First Session Acquired Credits',
        default='NA',
        store=True,
        required=True,
        track_visibility='onchange')
    first_session_note = fields.Text(string='First Session Notes')

    ## Second Session ##

    second_session_computed_result = fields.Float(
        compute='compute_average_results',
        string='Second Session Computed Result',
        store=True,
        digits=dp.get_precision('Evaluation'))
    second_session_computed_result_bool = fields.Boolean(
        compute='compute_average_results',
        string='Second Session Computed Active',
        store=True)
    second_session_computed_exclusion_result_bool = fields.Boolean(
        compute='compute_average_results',
        string='Second Session Exclusion Result',
        store=True)

    second_session_deliberated_result = fields.Char(
        string='Second Session Deliberated Result',
        digits=(5, 2),
        track_visibility='onchange')
    second_session_deliberated_result_bool = fields.Boolean(
        string='Second Session Deliberated Active',
        track_visibility='onchange')

    second_session_result = fields.Float(
        compute='compute_second_session_results',
        string='Second Session Result',
        store=True,
        digits=dp.get_precision('Evaluation'))
    second_session_result_bool = fields.Boolean(
        compute='compute_second_session_results',
        string='Second Session Active',
        store=True)
    second_session_acquiered = fields.Selection(
        ([('A', 'Acquired'), ('NA', 'Not Acquired')]),
        compute='compute_second_session_acquiered',
        string='Second Session Acquired Credits',
        default='NA',
        store=True,
        required=True,
        track_visibility='onchange')
    second_session_note = fields.Text(string='Second Session Notes')

    ## Final ##

    dispense = fields.Boolean(compute='compute_dispense',
                              string='Dispense',
                              default=False,
                              track_visibility='onchange',
                              store=True)

    final_result = fields.Float(compute='compute_final_results',
                                string='Final Result',
                                store=True,
                                digits=dp.get_precision('Evaluation'),
                                track_visibility='onchange')
    final_result_disp = fields.Char(string='Final Result Display',
                                    compute='compute_results_disp')
    final_result_bool = fields.Boolean(compute='compute_final_results',
                                       string='Final Active')

    acquiered = fields.Selection(([('A', 'Acquiered'),
                                   ('NA', 'Not Acquiered')]),
                                 compute='compute_acquiered',
                                 string='Acquired Credits',
                                 store=True,
                                 track_visibility='onchange',
                                 default='NA')

    final_note = fields.Text(string='Final Notes')

    @api.one
    def compute_results_disp(self):
        if not self.final_result_bool:
            self.final_result_disp = ""
        if self.dispense:
            self.final_result_disp = "Val"
        else:
            self.final_result_disp = "%.2f" % self.final_result

    def _parse_result(self, input):
        f = float(input)
        if (f < 0 or f > 20):
            raise ValidationError("Evaluation shall be between 0 and 20")
        else:
            return f

    ## override so that courses with dispense and no deferred results are excluded from computation
    @api.depends('course_ids.hours', 'course_ids.credits',
                 'course_ids.c_weight')
    @api.one
    def _get_courses_total(self):
        _logger.debug('Trigger "_get_courses_total" on Course Group %s' %
                      self.name)
        self.total_hours = sum(course.hours for course in self.course_ids)
        self.total_credits = sum(course.credits for course in self.course_ids)
        self.total_weight = sum(course.c_weight for course in self.course_ids)

    @api.depends('course_ids.first_session_result_bool',
                 'course_ids.first_session_result',
                 'course_ids.second_session_result_bool',
                 'course_ids.second_session_result', 'course_ids.c_weight',
                 'course_ids.weight')
    @api.one
    def compute_average_results(self):
        _logger.debug('Trigger "compute_average_results" on Course Group %s' %
                      self.name)
        ## Compute Weighted Average
        running_first_session_result = 0
        running_second_session_result = 0
        self.first_session_computed_result_bool = False
        self.first_session_computed_exclusion_result_bool = False
        self.second_session_computed_result_bool = False
        self.second_session_computed_exclusion_result_bool = False

        for ic in self.course_ids:
            # Compute First Session
            if ic.first_session_result_bool:
                running_first_session_result += ic.first_session_result * ic.c_weight
                self.first_session_computed_result_bool = True
                if ic.first_session_result < 10:
                    self.first_session_computed_exclusion_result_bool = True
            # Compute Second Session
            if ic.second_session_result_bool:
                running_second_session_result += ic.second_session_result * ic.c_weight
                self.second_session_computed_result_bool = True
                if ic.second_session_result < 10:
                    self.second_session_computed_exclusion_result_bool = True
            elif ic.first_session_result_bool:
                # Use First session in computation of the second one if no second one
                running_second_session_result += ic.first_session_result * ic.c_weight
                if ic.first_session_result < 10:
                    self.second_session_computed_exclusion_result_bool = True

        if self.first_session_computed_result_bool:
            if self.total_weight > 0:
                self.first_session_computed_result = running_first_session_result / self.total_weight
        if self.second_session_computed_result_bool:
            if self.total_weight > 0:
                self.second_session_computed_result = running_second_session_result / self.total_weight

    @api.depends('first_session_deliberated_result_bool',
                 'first_session_deliberated_result',
                 'first_session_computed_result_bool',
                 'first_session_computed_result')
    @api.one
    def compute_first_session_results(self):
        _logger.debug(
            'Trigger "compute_first_session_results" on Course Group %s' %
            self.name)
        ## Compute Session Results
        if self.first_session_deliberated_result_bool:
            try:
                f = self._parse_result(self.first_session_deliberated_result)
            except ValueError:
                self.write('first_session_deliberated_result', None)
                raise UserError(
                    _('Cannot decode %s, please encode a Float eg "12.00".' %
                      self.first_session_deliberated_result))
            #if (f < self.first_session_computed_result):
            #    # TODO : take care of this - removed due to Cours artistiques B - Art dramatique - 2 - 2015-2016 - VALERIO Maddy
            #    # raise ValidationError("Deliberated result must be above computed result, i.e. %s > %s." % (self.first_session_deliberated_result, self.first_session_computed_result))
            self.first_session_result = f
            #else:
            #    self.first_session_result = f
            self.first_session_result_bool = True
        elif self.first_session_computed_result_bool:
            self.first_session_result = self.first_session_computed_result
            self.first_session_result_bool = True
        else:
            self.first_session_result = 0
            self.first_session_result_bool = False

    @api.depends('first_session_result_bool', 'first_session_result',
                 'first_session_computed_exclusion_result_bool')
    @api.one
    def compute_first_session_acquiered(self):
        _logger.debug(
            'Trigger "compute_first_session_acquiered" on Course Group %s' %
            self.name)
        self.first_session_acquiered = 'NA'
        #if self.first_session_deliberated_result_bool:
        #    self.first_session_acquiered = 'A'
        #el
        if self.enable_exclusion_bool:
            if self.first_session_result >= 10 and (
                    not self.first_session_computed_exclusion_result_bool
                    or self.first_session_deliberated_result_bool):
                self.first_session_acquiered = 'A'
        else:
            if self.first_session_result >= 10:  # cfr appel Ingisi 27-06 and (not self.first_session_computed_exclusion_result_bool or self.first_session_deliberated_result_bool):
                self.first_session_acquiered = 'A'

    @api.depends('second_session_deliberated_result_bool',
                 'second_session_deliberated_result',
                 'second_session_computed_result_bool',
                 'second_session_computed_result')
    @api.one
    def compute_second_session_results(self):
        _logger.debug(
            'Trigger "compute_second_session_results" on Course Group %s' %
            self.name)
        if self.second_session_deliberated_result_bool:
            try:
                f = self._parse_result(self.second_session_deliberated_result)
            except ValueError:
                self.write('second_session_deliberated_result', None)
                raise UserError(
                    _('Cannot decode %s, please encode a Float eg "12.00".' %
                      self.second_session_deliberated_result))
            if (f < self.second_session_computed_result):
                raise ValidationError(
                    "Deliberated result must be above computed result, i.e. %s > %s."
                    % (self.second_session_deliberated_result,
                       self.second_session_computed_result))
            else:
                self.second_session_result = f
            self.second_session_result_bool = True
        elif self.second_session_computed_result_bool:
            self.second_session_result = self.second_session_computed_result
            self.second_session_result_bool = True
        else:
            self.second_session_result = 0
            self.second_session_result_bool = False

    @api.depends('second_session_result_bool', 'second_session_result',
                 'first_session_acquiered')
    @api.one
    def compute_second_session_acquiered(self):
        _logger.debug(
            'Trigger "compute_second_session_acquiered" on Course Group %s' %
            self.name)
        self.second_session_acquiered = self.first_session_acquiered
        if self.first_session_deliberated_result_bool:
            self.first_session_acquiered = 'A'
        elif self.enable_exclusion_bool:
            if self.second_session_result >= 10 and (
                    not self.second_session_computed_exclusion_result_bool
                    or self.second_session_deliberated_result_bool):
                self.second_session_acquiered = 'A'
        else:
            if self.second_session_result >= 10:  # and (not self.second_session_computed_exclusion_result_bool or self.second_session_deliberated_result_bool):
                self.second_session_acquiered = 'A'

    @api.depends('first_session_result', 'first_session_result_bool',
                 'first_session_acquiered', 'second_session_result',
                 'second_session_result_bool', 'second_session_acquiered')
    @api.one
    def compute_final_results(self):
        _logger.debug('Trigger "compute_final_results" on Course Group %s' %
                      self.name)
        ## Compute Final Results
        if self.second_session_result_bool:
            self.final_result = self.second_session_result
            self.final_result_bool = True
        elif self.first_session_result_bool:
            self.final_result = self.first_session_result
            self.final_result_bool = True
        else:
            self.final_result_bool = False

    @api.depends('course_ids.dispense')
    @api.one
    def compute_dispense(self):
        # Check if Course Group is dispensed
        all_dispensed = True
        for ic in self.course_ids:
            all_dispensed = all_dispensed and ic.dispense
        if all_dispensed:
            self.dispense = True
            self.acquiered = 'A'

    @api.depends('dispense', 'second_session_acquiered')
    @api.one
    def compute_acquiered(self):
        if self.dispense:
            self.acquiered = 'A'
        else:
            self.acquiered = self.second_session_acquiered
Exemplo n.º 10
0
class TaskTimeAccountLine(models.Model):
    _name = 'task.time.account.line'

    @api.multi
    def _get_default_start_time(self):
        active_model = self.env.context.get('active_model')
        
        if active_model =='project.task':
            active_id =  self.env.context.get('active_id')        
            if active_id:
                task_search = self.env['project.task'].search([('id','=',active_id)],limit=1)
                 
                return task_search.start_time
    
    @api.multi
    def _get_default_end_time(self):
        active_model = self.env.context.get('active_model')
        
        if active_model =='project.task':
            active_id =  self.env.context.get('active_id')        
            if active_id:
                task_search = self.env['project.task'].search([('id','=',active_id)],limit=1)
                 
                return task_search.end_time

    @api.multi
    def _get_default_duration(self):
        active_model = self.env.context.get('active_model')
        
        if active_model =='project.task':
            active_id =  self.env.context.get('active_id')        
            if active_id:
                task_search = self.env['project.task'].search([('id','=',active_id)],limit=1)
                return  float(task_search.total_time)

    name = fields.Char("Description",required = True)
    start_date = fields.Datetime("Start Date", default = _get_default_start_time , readonly=True)
    end_date = fields.Datetime("End Date",default = _get_default_end_time , readonly=True)    
    duration = fields.Float("Duration (HH:MM)",default = _get_default_duration , readonly=True)

    @api.multi
    def end_task(self):         

        context = dict(self.env.context or {})       
        
        active_model = context.get('active_model',False)                     
        active_id = context.get('active_id',False)
                             
        vals = {'name':self.name,'unit_amount':self.duration,'amount':self.duration,'date': datetime.now()}
        
        if active_model=='project.task':
            if active_id:
                 
                task_search =self.env['project.task'].search([('id','=',active_id)],limit=1)               
                if task_search:

                    vals.update({'start_date':task_search.start_time })
                    vals.update({'end_date':task_search.end_time })
                    vals.update({'is_timesheet':True })
                    
                    if task_search.project_id:
                        project_id = task_search.project_id.id
                     
                        if project_id:                       
                            act_id = self.env['project.project'].sudo().browse(task_search.project_id.id).analytic_account_id
                            if act_id :
                                vals.update({'account_id':act_id.id})
                    
                    else :
                        analytic_account_search = self.env.user.company_id.analytic_account_id
                        if analytic_account_search:
                            if analytic_account_search.id:
                                vals.update({'account_id':analytic_account_search.id })
                        else :
                            raise UserError('Please set Default Analytic Account for Timesheet, from Project -> Settings')
                     
                    task_search.sudo().write({'start_time':None})
                          
        usr_id = context.get('uid',False)
        if usr_id:
            vals.update({'user_id': usr_id })
            
        line_obj = self.env['account.analytic.line'].sudo().create(vals)
        self.sudo()._cr.commit()
        return
Exemplo n.º 11
0
class IndividualBloc(models.Model):
    '''Individual Bloc'''
    _inherit = 'school.individual_bloc'

    state = fields.Selection(
        [
            ('draft', 'Draft'),
            ('progress', 'In Progress'),
            ('postponed', 'Postponed'),
            ('awarded_first_session', 'Awarded in First Session'),
            ('awarded_second_session', 'Awarded in Second Session'),
            ('failed', 'Failed'),
            ('abandoned', 'Abandoned'),
        ],
        string='Status',
        index=True,
        default='draft',
        copy=False,
        help=
        " * The 'Draft' status is used when results are not confirmed yet.\n"
        " * The 'In Progress' status is used during the courses.\n"
        " * The 'Postponed' status is used when a second session is required.\n"
        " * The 'Awarded' status is used when the bloc is awarded in either first or second session.\n"
        " * The 'Failed' status is used when the bloc is definitively considered as failed.\n"
        " * The 'Abandoned' status is when the student abandoned his bloc.\n",
        track_visibility='onchange')

    total_acquiered_credits = fields.Integer(compute="compute_credits",
                                             string="Acquiered Credits",
                                             store=True)
    total_acquiered_hours = fields.Integer(compute="compute_credits",
                                           string="Acquiered Hours",
                                           store=True)
    total_not_acquiered_credits = fields.Integer(
        compute='compute_credits', string='Not Acquiered Credits', store=True)
    total_not_acquiered_hours = fields.Integer(compute='compute_credits',
                                               string='Not Acquiered Hours',
                                               store=True)
    total_dispensed_credits = fields.Integer(compute="compute_credits",
                                             string="Dispensed Credits",
                                             store=True)
    total_dispensed_hours = fields.Integer(compute="compute_credits",
                                           string="Dispensed Hours",
                                           store=True)
    total_not_dispensed_credits = fields.Integer(
        compute="compute_credits", string="Not Dispensed Credits", store=True)
    total_not_dispensed_hours = fields.Integer(compute='compute_credits',
                                               string='Not Dispensed Hours',
                                               store=True)

    evaluation = fields.Float(string="Evaluation",
                              compute="compute_evaluation",
                              digits=dp.get_precision('Evaluation'))
    decision = fields.Text(string="Decision", track_visibility='onchange')
    exclude_from_deliberation = fields.Boolean(
        string='Exclude from Deliberation', default=False)

    first_session_result = fields.Float(string="Evaluation",
                                        compute="compute_evaluation",
                                        digits=dp.get_precision('Evaluation'))
    second_session_result = fields.Float(string="Evaluation",
                                         compute="compute_evaluation",
                                         digits=dp.get_precision('Evaluation'))

    @api.multi
    def set_to_draft(self, context):
        # TODO use a workflow to make sure only valid changes are used.
        return self.write({'state': 'draft'})

    @api.multi
    def set_to_progress(self, context):
        # TODO use a workflow to make sure only valid changes are used.
        return self.write({'state': 'progress'})

    @api.multi
    def set_to_postponed(self, decision=None, context=None):
        # TODO use a workflow to make sure only valid changes are used.
        if isinstance(decision, dict):
            context = decision
            decision = None
        return self.write({'state': 'postponed', 'decision': decision})

    @api.multi
    def set_to_awarded_first_session(self, decision=None, context=None):
        # TODO use a workflow to make sure only valid changes are used.
        if isinstance(decision, dict):
            context = decision
            decision = None
        return self.write({
            'state': 'awarded_first_session',
            'decision': decision
        })

    @api.multi
    def set_to_awarded_second_session(self, decision=None, context=None):
        # TODO use a workflow to make sure only valid changes are used.
        if isinstance(decision, dict):
            context = decision
            decision = None
        return self.write({
            'state': 'awarded_second_session',
            'decision': decision
        })

    @api.multi
    def set_to_failed(self, decision=None, context=None):
        # TODO use a workflow to make sure only valid changes are used.
        if isinstance(decision, dict):
            context = decision
            decision = None
        return self.write({'state': 'failed', 'decision': decision})

    @api.multi
    def set_to_abandoned(self, decision=None, context=None):
        return self.write({'state': 'abandoned', 'decision': None})

    @api.multi
    def report_send(self):
        """ Open a window to compose an email, with the default template
            message loaded by default
        """
        self.ensure_one()
        template = self.env.ref(
            'school_evaluations.email_template_success_certificate', False)
        compose_form = self.env.ref('mail.email_compose_message_wizard_form',
                                    False)
        ctx = dict(
            default_model='school.individual_bloc',
            default_res_id=self.id,
            default_use_template=bool(template),
            default_template_id=template.id,
            default_composition_mode='comment',
            mark_invoice_as_sent=True,
        )
        return {
            'name': _('Compose Email'),
            'type': 'ir.actions.act_window',
            'view_type': 'form',
            'view_mode': 'form',
            'res_model': 'mail.compose.message',
            'views': [(compose_form.id, 'form')],
            'view_id': compose_form.id,
            'target': 'new',
            'context': ctx,
        }

    @api.depends('course_group_ids.total_credits',
                 'course_group_ids.total_hours', 'course_group_ids.acquiered',
                 'course_group_ids.dispense',
                 'course_group_ids.first_session_computed_result_bool',
                 'course_group_ids.is_ghost_cg')
    @api.one
    def compute_credits(self):
        self.total_acquiered_credits = sum([
            icg.total_credits for icg in self.course_group_ids
            if icg.acquiered == 'A' and not icg.is_ghost_cg
        ])
        self.total_acquiered_hours = sum([
            icg.total_hours for icg in self.course_group_ids
            if icg.acquiered == 'A' and not icg.is_ghost_cg
        ])
        self.total_not_acquiered_credits = self.total_credits - self.total_acquiered_credits
        self.total_not_acquiered_hours = self.total_hours - self.total_acquiered_hours

        # WAS BEFORE May 2018
        #self.total_dispensed_credits = sum([icg.total_dispensed_credits for icg in self.course_group_ids])
        #self.total_dispensed_hours = sum([icg.total_dispensed_hours for icg in self.course_group_ids])

        self.total_dispensed_credits = sum([
            icg.total_credits for icg in self.course_group_ids
            if icg.dispense and not icg.is_ghost_cg
        ])
        self.total_dispensed_hours = sum([
            icg.total_hours for icg in self.course_group_ids
            if icg.dispense and not icg.is_ghost_cg
        ])
        self.total_not_dispensed_credits = self.total_credits - self.total_dispensed_credits
        self.total_not_dispensed_hours = self.total_hours - self.total_dispensed_hours

    @api.depends('course_group_ids.final_result',
                 'course_group_ids.total_weight', 'course_group_ids.acquiered',
                 'course_group_ids.is_ghost_cg')
    @api.one
    def compute_evaluation(self):
        total = 0
        total_first = 0
        total_second = 0
        total_weight = 0
        for icg in self.course_group_ids:
            if icg.acquiered == 'A' and icg.total_weight > 0 and not icg.is_ghost_cg:  # if total_weight == 0 means full dispense
                total += icg.final_result * icg.total_weight
                total_first += icg.first_session_result * icg.total_weight
                total_second += icg.second_session_result * icg.total_weight
                total_weight += icg.total_weight
        if total_weight > 0:
            self.evaluation = total / total_weight
            self.first_session_result = total_first / total_weight
            self.total_second = total_first / total_weight
        else:
            _logger.debug('total_weight is 0 on Bloc %s' % self.name)
            self.evaluation = None
Exemplo n.º 12
0
class dtdream_contract(models.Model):
    _name = 'dtdream.contract'
    _inherit = ['mail.thread']
    _description = u'合同评审'

    his_approve = fields.Many2many('hr.employee', string="历史审批人")
    name = fields.Char(string="合同名称")

    @api.constrains('constract_type')
    @api.onchange('constract_type')
    def _compute_constract_id(self):
        if self.constract_type:
            max_constract_id = ''
            baseid = 'DTD-' + self.constract_type.name_id + time.strftime(
                "%Y%m%d", time.localtime())
            sql_baseid = baseid + "%"
            self._cr.execute(
                "select constract_id from dtdream_contract where constract_id like '"
                + sql_baseid + "' order by id desc limit 1")
            for rec in self._cr.fetchall():

                max_constract_id = rec[0]

            if max_constract_id:

                max_id = max_constract_id[15:]

                if int(max_id) < 9:
                    self.constract_id_copy = baseid + '0' + str(
                        int(max_id) + 1)
                    self.constract_id = baseid + '0' + str(int(max_id) + 1)
                else:
                    self.constract_id_copy = baseid + str(int(max_id) + 1)
                    self.constract_id = baseid + str(int(max_id) + 1)
            else:
                self.constract_id_copy = baseid + '01'
                self.constract_id = baseid + '01'

    constract_id = fields.Char(string="合同编号", store=True)
    constract_id_copy = fields.Char(string="合同编号_copy")
    constract_type = fields.Many2one("dtdream.contract.config", string="合同类型")
    constract_type_char = fields.Char(string="合同类型_copy")

    @api.onchange("constract_type")
    def _compute_people(self):

        self.constract_type_char = self.constract_type.name
        config = self.env['dtdream.contract.config'].search([
            ('name', '=', self.constract_type.name)
        ])
        self.legal_interface = config.legal_interface
        self.review_ids = config.review_ids
        self.huiqian_ids = config.huiqian_ids
        self.quanqian_id = config.quanqian_id
        self.stamp_id = config.stamp_id
        self.file_id = config.file_id

    applicant = fields.Many2one('hr.employee',
                                string='申请人',
                                default=lambda self: self.env['hr.employee'].
                                search([('user_id', '=', self.env.user.id)]))

    @api.one
    @api.onchange("applicant")
    def _compute_employee(self):
        self.job_number = self.applicant.job_number
        self.deparment = self.applicant.department_id.complete_name
        self.tel_number = self.applicant.mobile_phone
        self.deparment_manage = self.applicant.department_id.manager_id.id

    # job_number=fields.Char(string="工号",compute=_compute_employee)
    def _compute_is_applicant(self):
        # 判断是否是申请人或者创建人
        if self.state:
            if self.env.user.id != self.applicant.user_id.id and self.env.user.id != self.create_uid.id:
                self.is_applicant = False
            else:
                self.is_applicant = True
        else:
            self.is_applicant = True
        #     判断是否是主管
        if self.env.user.id != self.deparment_manage.user_id.id:
            self.is_manager = False
        else:
            self.is_manager = True
        #判断是否是归档人
        if self.env.user.id != self.file_id.user_id.id:
            self.is_file_id = False
        else:
            self.is_file_id = True

    is_applicant = fields.Boolean(string="是否申请人或创建人",
                                  compute=_compute_is_applicant,
                                  default=True)
    is_manager = fields.Boolean(string="是否是主管", compute=_compute_is_applicant)
    job_number = fields.Char(string="工号", compute=_compute_employee)
    deparment = fields.Char(string="部门", compute=_compute_employee)
    tel_number = fields.Char(string="电话", compute=_compute_employee)
    deparment_manage = fields.Many2one('hr.employee', string="部门主管")
    state = fields.Selection([("0", "草稿"), ("1", "主管审批"), ("2", "待组织评审"),
                              ("3", "评审中"), ("4", "待组织会签"), ("5", "会签中"),
                              ("6", "权签中"), ("7", "待盖章"), ("8", "待归档"),
                              ("9", "闭环"), ("10", "作废")],
                             string="合同状态")
    create_time = fields.Datetime(string='创建时间',
                                  default=lambda self: datetime.now(),
                                  readonly=1)
    money = fields.Float(string="合同金额(元)")

    @api.onchange('money')
    def _compute_money_final(self):
        self.money_final = self.money

    money_final = fields.Float(string="合同最终金额(元)", help='合同最终金额由合同归档人录入')
    background = fields.Text(string="合同背景介绍")
    attachment = fields.Binary(string="合同附件(初稿)", store=True)
    attachment_name = fields.Char(string="附件名")
    att_final = fields.Binary(string="合同附件(最新稿)")
    att_final_name = fields.Char(string="合同终稿附件名")
    remark = fields.Char(string="备注")
    pro_name = fields.Many2one("crm.lead", string="项目名称")
    tip = fields.Char(default=lambda self: self.env['dtdream.contract.url'].
                      search([], limit=1).name)

    @api.onchange('pro_name')
    @api.depends('pro_name')
    def _compute_parter(self):
        try:
            self.partner = self.env['crm.lead'].search([
                ('name', '=', self.pro_name.name)
            ]).partner_id.name
        except:
            return

    partner = fields.Char(string="合作方", compute=_compute_parter, store=True)
    provider = fields.Many2one('res.partner',
                               string='合作方',
                               domain=[('supplier', '=', True)])
    is_standard = fields.Boolean(string="是标准合同",
                                 help='标准合同无需评审,直接进入会签环节,可快速完成合同评审流程')
    current_handler_ids = fields.Many2many('hr.employee',
                                           'c_i_h_e',
                                           string="当前处理人",
                                           store=True)

    @api.one
    def _compute_is_handler(self):
        for handler in self.current_handler_ids:
            if handler.user_id.id == self.env.user.id:
                self.is_handler = True

    @api.one
    def _compute_is_legal_interface(self):
        self.is_legal_interface = False
        for people in self.legal_interface:
            if people.user_id.id == self.env.user.id:
                self.is_legal_interface = True

    is_handler = fields.Boolean("是否当前处理人", compute=_compute_is_handler)
    is_legal_interface = fields.Boolean("是否法务部接口人",
                                        compute=_compute_is_legal_interface)
    legal_interface = fields.Many2many('hr.employee',
                                       'dt_contract_legal_interface',
                                       string="法务接口人")
    review_ids = fields.Many2many('hr.employee',
                                  'r_i_h_e',
                                  string="评审人",
                                  store=True)
    huiqian_ids = fields.Many2many('hr.employee', 'h_i_h_e', string="会签人")
    quanqian_id = fields.Many2one('hr.employee', string="权签人")
    stamp_id = fields.Many2one('hr.employee', string="盖章处理人")

    def _compute_stamp(self):
        self.is_stamped = True
        self.stamp_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())

    def _compute_file(self):
        self.is_filed = True
        self.file_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())

    is_stamped = fields.Boolean(string="是否已盖章")
    stamp_time = fields.Char(string="盖章时间")
    file_id = fields.Many2one('hr.employee', string="归档处理人")
    is_filed = fields.Boolean(string="是否已归档")
    is_file_id = fields.Boolean(string='是否归档人', compute=_compute_is_applicant)
    file_time = fields.Char(string="归档时间")
    review2wait_countersign = fields.Boolean(default=False)

    def send_email(self, cr, uid, id):
        base_url = self.pool.get('ir.config_parameter').get_param(
            cr, uid, 'web.base.url')

        link = '/web?#id=%s&view_type=form&model=dtdream.contract' % id
        url = base_url + link
        damn_self = self.pool.get('dtdream.contract').browse(cr, uid, id)
        for people in damn_self.current_handler_ids:
            damn_self.env['mail.mail'].create({
                'subject':
                u'%s于%s提交合同:%s 评审申请,请您审批!' %
                (damn_self.applicant.name, damn_self.create_time[:10],
                 damn_self.name),
                'body_html':
                u'''
                    <p>%s,您好:</p>
                    <p>%s提交的合同评审正等待您的审批!</p>
                    <p> 请点击链接进入审批:
                    <a href="%s">%s</a></p>
                    <p>dodo</p>
                    <p>万千业务,简单有do</p>
                    <p>%s</p>''' % (people.name, damn_self.applicant.name, url,
                                    url, damn_self.write_date[:10]),
                'email_from':
                damn_self.env['ir.mail_server'].search([], limit=1).smtp_user,
                'email_to':
                people.work_email,
            }).send()
        return url

    @api.one
    def copy(self, default=None):
        default = dict(default or {}, constract_id="")
        print default
        return super(dtdream_contract, self).copy(default=default)

    @api.model
    def create(self, vals):
        config = self.env['dtdream.contract.config'].search([
            ('name', '=', vals['constract_type_char'])
        ])
        result = super(dtdream_contract, self).create(vals)
        # 对只读字段重新写入
        result.legal_interface = config.legal_interface
        result.huiqian_ids = config.huiqian_ids
        result.quanqian_id = config.quanqian_id
        result.stamp_id = config.stamp_id
        result.file_id = config.file_id
        result.money_final = result.money
        result.constract_id = result.constract_id_copy
        # result.message_post(body=u"--------------:%s"%time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
        # 创建人不是申请人添加到关注者
        if self._context['uid'] != result.applicant.user_id.id:
            result.message_subscribe_users(
                user_ids=[result.applicant.user_id.id])

        return result

    @api.multi
    def write(self, vals):

        if self.state == '0':

            if vals.has_key('money'):

                self.money_final = vals['money']
            if vals.has_key('constract_type_char'):
                config = self.env['dtdream.contract.config'].search([
                    ('name', '=', vals['constract_type_char'])
                ])
                self.legal_interface = config.legal_interface
                self.huiqian_ids = config.huiqian_ids
                self.quanqian_id = config.quanqian_id
                self.stamp_id = config.stamp_id
                self.file_id = config.file_id

                self.constract_id = vals['constract_id_copy']
        result = super(dtdream_contract, self).write(vals)

        return result

    _sql_constraints = [('constract_id_unique', 'unique(constract_id)',
                         '合同编号重复,请刷新页面重新填写!')]

    @api.multi
    def wkf_draft(self):
        # 草稿状态

        self.current_handler_ids = ""
        self.state = '0'
        # self.write({'state':'0'})

    @api.multi
    def wkf_manager_review(self):
        # 主管审批
        self.message_post(
            body=u"合同编号:%s,提交,提交时间:%s" %
            (self.constract_id,
             (datetime.now() +
              relativedelta(hours=8)).strftime("%Y-%m-%d %H:%M:%S")))
        self.current_handler_ids = self.deparment_manage
        self.state = '1'
        self.send_email()

    @api.multi
    def wkf_wait_review(self):
        # 待组织评审
        self.current_handler_ids = self.legal_interface
        self.state = '2'
        self.send_email()

    @api.multi
    def wkf_review(self):
        # 评审中
        self.current_handler_ids = self.review_ids
        self.state = '3'
        self.send_email()

    @api.multi
    def wkf_wait_countersign(self):
        # 待组织会签
        self.current_handler_ids = self.legal_interface
        self.state = '4'
        self.send_email()

    @api.multi
    def wkf_countersign(self):
        # 会签中
        self.current_handler_ids = self.huiqian_ids
        self.state = '5'
        self.send_email()

    @api.multi
    def wkf_sign(self):
        # 权签中
        self.current_handler_ids = self.quanqian_id
        self.state = '6'
        self.send_email()

    @api.multi
    def wkf_stamp(self):
        # 待盖章
        self.current_handler_ids = self.stamp_id
        self.state = '7'
        self.send_email()

    @api.multi
    def wkf_file(self):
        # 待归档
        self._compute_stamp()
        self.current_handler_ids = self.file_id
        self.state = '8'
        self.send_email()

    @api.multi
    def wkf_done(self):
        self._compute_file()
        self.current_handler_ids = ''
        self.state = '9'

    @api.multi
    def wkf_void(self):
        self.current_handler_ids = ''
        self.state = '10'

    @api.multi
    def _message_track(self, tracked_fields, initial):
        self.ensure_one()
        changes = set()
        tracking_value_ids = []

        # generate tracked_values data structure: {'col_name': {col_info, new_value, old_value}}
        for col_name, col_info in tracked_fields.items():
            initial_value = initial[col_name]
            new_value = getattr(self, col_name)

            if new_value != initial_value and (
                    new_value
                    or initial_value):  # because browse null != False
                tracking = self.env[
                    'mail.tracking.value'].create_tracking_values(
                        initial_value, new_value, col_name, col_info)
                if tracking:
                    tracking_value_ids.append([0, 0, tracking])

                if col_name in tracked_fields:
                    changes.add(col_name)
        return changes, tracking_value_ids

    @api.multi
    def message_track(self, tracked_fields, initial_values):

        return

    @api.cr_uid_ids_context
    def message_post(self, cr, uid, thread_id, context=None, **kwargs):

        current_contract = self.pool.get('dtdream.contract').browse(
            cr, uid, thread_id, context=context)
        if kwargs.has_key('attachment_ids'):
            for id in kwargs['attachment_ids']:

                current_contract.att_final = self.pool.get(
                    'ir.attachment').browse(cr, uid, id, context=context).datas
                current_contract.att_final_name = self.pool.get(
                    'ir.attachment').browse(cr, uid, id, context=context).name
                base1 = current_contract.pool.get(
                    'ir.config_parameter').get_param(
                        current_contract.env.cr, current_contract.env.user.id,
                        'web.base.url')
                link1 = link = '/web?#id=%s&view_type=form&model=dtdream.contract' % thread_id
                url1 = base1 + link1
                for people in current_contract.current_handler_ids:

                    mess = current_contract.env['mail.mail'].create({
                        'subject':
                        u'%s于%s提交合同:%s 评审申请已经重新上传了附件,请您审批!' %
                        (current_contract.applicant.name,
                         current_contract.create_time[:10],
                         current_contract.name),
                        'body_html':
                        u'''
                            <p>%s,您好:</p>
                            <p>%s提交的合同评审已经重新上传了附件正等待您的审批!</p>
                            <p> 请点击链接进入审批:
                            <a href="%s">%s</a></p>
                            <p>dodo</p>
                            <p>万千业务,简单有do</p>
                            <p>%s</p>''' %
                        (people.name, current_contract.applicant.name, url1,
                         url1, current_contract.write_date[:10]),
                        'email_from':
                        current_contract.env['ir.mail_server'].search(
                            [], limit=1).smtp_user,
                        'email_to':
                        people.work_email,
                        # 'model': "",
                    })
                    mess.write({'model': ""})
                    mess.send()

        return super(dtdream_contract, self).message_post(cr,
                                                          uid,
                                                          thread_id,
                                                          context=context,
                                                          **kwargs)

    @api.model
    def fields_view_get(self,
                        view_id=None,
                        view_type='form',
                        toolbar=False,
                        submenu=False):

        params = self._context.get('params', None)
        action = params.get("action", 0) if params else 0
        my_action = self.env["ir.actions.act_window"].search([('id', '=',
                                                               action)])
        res = super(dtdream_contract,
                    self).fields_view_get(view_id=view_id,
                                          view_type=view_type,
                                          toolbar=toolbar,
                                          submenu=False)
        doc = etree.XML(res['arch'])
        if my_action.name != u"我的申请":
            if res['type'] == "form":
                doc.xpath("//form")[0].set("create", "false")
            if res['type'] == "tree":
                doc.xpath("//tree")[0].set("create", "false")
        res['arch'] = etree.tostring(doc)
        return res
class XLSXReportPabiHiringSummaryResults(models.Model):
    _name = 'xlsx.report.pabi.hiring.summary.results'
    _auto = False
    _description = 'Temp table as ORM holder'

    partner_id = fields.Many2one(
        'res.partner',
        string='Partner',
    )
    category_id = fields.Many2one(
        'res.partner.category',
        string='Partner Category',
    )
    operating_unit_id = fields.Many2one(
        'operating.unit',
        string='OU',
    )
    org_id = fields.Many2one(
        'res.org',
        string='Org',
    )
    po_name = fields.Char(
        string='PO Name',
        readonly=True,
    )
    pol_name = fields.Char(
        string='POL Name',
        readonly=True,
    )
    costcenter_name = fields.Char(
        string='Center Name',
        readonly=True,
    )
    method_name = fields.Char(
        string='Method Name',
        readonly=True,
    )
    amount_total = fields.Float(
        string='Amount Total',
        readonly=True,
    )
    currency = fields.Char(
        string='Currency',
        readonly=True,
    )
    po_date = fields.Date(
        string='PO Date',
        readonly=True,
    )
    pd_date = fields.Date(
        string='PD Date',
        readonly=True,
    )
    date_contract_start = fields.Date(
        string='Contract Start Date',
        readonly=True,
    )
    date_contract_end = fields.Date(
        string='Contract End Date',
        readonly=True,
    )

    def init(self, cr):
        tools.drop_view_if_exists(cr, self._table)
        cr.execute("""CREATE or REPLACE VIEW %s as (
        SELECT 
        row_number() over (order by po.id) as id,
        po.name as po_name,
        po.amount_total,
        cur.name as currency,
        po.date_order as po_date,
        ou.id as operating_unit_id,
        (Case when ou.name = 'สำนักงานกลาง'
        then
        'สำนักงานพัฒนาวิทยาศาสตร์และเทคโนโลยีแห่งชาติ'
        else
        ou.name
	    end) as ou_name,
        rp.id as partner_id,
        (
        SELECT prl.name
        FROM purchase_request_line prl
        WHERE id = prpol.purchase_request_line_id
        LIMIT 1
        ) as prl_name,
        wa.date_contract_start as date_contract_start,
        wa.date_contract_end as date_contract_end,
        org.id as org_id,
        rpc.id as category_id
        FROM purchase_order_line pol
        LEFT JOIN purchase_order po on po.id = pol.order_id
        LEFT JOIN purchase_request_purchase_order_line_rel prpol on prpol.purchase_order_line_id = pol.id
        LEFT JOIN res_partner rp on rp.id = po.partner_id
        LEFT JOIN res_partner_category rpc on rpc.id = rp.category_id
        LEFT JOIN product_template pt on pt.id = pol.product_id
        LEFT JOIN product_category categ ON categ.id = pt.categ_id
        LEFT JOIN purchase_work_acceptance wa ON wa.order_id = po.id
        LEFT JOIN operating_unit ou on ou.id = po.operating_unit_id
        LEFT JOIN res_org org on org.operating_unit_id = ou.id
        LEFT JOIN res_currency cur on cur.id = po.currency_id
        WHERE rp.supplier = True
        AND rp.employee = False
        AND wa.state = 'done'
        AND po.state not in ('cancel' ,'draft')
	    AND categ.name like '%%จ้าง%%'
        )""" % (self._table, ))
Exemplo n.º 14
0
class wiz_mo_repair(models.TransientModel):
    """ 
        Wiz manufacturing order for repair
    """
    _name = 'wiz.mo.repair'
    _description = 'Wiz manufacturing order for repair'
    _rec_name = 'origin_num_serie_id'

    @api.one
    @api.depends('origin_num_serie_id')
    def _compute_origin_num_serie_id(self):
        """
            All origin_num_serie_id
        """
        self.product_id = self.origin_num_serie_id.product_id.id
        self.uom_id = self.origin_num_serie_id.uom_id.id
        self.qty_label = self.origin_num_serie_id.uom_qty

    @api.model
    def _repair_type_get(self):
        return [
            ('repair_overhead', _('Repair overhead')),
            ('repair_subset', _('Repair subset')),
        ]

    @api.one
    @api.depends('routing_id')
    def _compute_all_operation_ids(self):
        """
            All routing_id
        """
        all_operation_ids = []
        for ope in self.routing_id.routing_line_ids:
            all_operation_ids.append((4, ope.id))

        self.all_operation_ids = all_operation_ids

    @api.one
    @api.depends('disassembly_rl_id', 'assembly_rl_id', 'mo_repair_ope_ids')
    def _compute_use_operation_ids(self):
        """
            All routing_id
        """
        use_operation_ids = []
        if self.disassembly_rl_id:
            use_operation_ids.append((4, self.disassembly_rl_id.id))

        if self.assembly_rl_id:
            use_operation_ids.append((4, self.assembly_rl_id.id))

        for mo_repair_ope in self.mo_repair_ope_ids:
            use_operation_ids.append((4, mo_repair_ope.rl_id.id))

        self.use_operation_ids = use_operation_ids

    #===========================================================================
    # COLUMNS
    #===========================================================================
    repair_date = fields.Date(string='Repair date',
                              default=lambda self: fields.Date.today())
    return_date = fields.Date(string='Return date')
    cause = fields.Text(string='Cause')
    repair_type = fields.Selection('_repair_type_get',
                                   string='Repair type',
                                   required=True)
    origin_num_serie_id = fields.Many2one('stock.label',
                                          string='Origin serial num',
                                          required=True,
                                          ondelete='cascade')
    is_new_num_serie = fields.Boolean(string='Create a new serial num',
                                      default=False)
    wmrl_ids = fields.One2many('wiz.mo.repair.label',
                               'wiz_mo_repair_id',
                               string='Labels')
    disassembly_rl_id = fields.Many2one('mrp.routing.line',
                                        string='Disassembly operation',
                                        required=False,
                                        ondelete='cascade')
    mo_repair_ope_ids = fields.One2many('wiz.mo.repair.operations',
                                        'wiz_mo_repair_id',
                                        string='Routing lines')
    assembly_rl_id = fields.Many2one('mrp.routing.line',
                                     string='Assembly operation',
                                     required=False,
                                     ondelete='cascade')
    routing_id = fields.Many2one('mrp.routing',
                                 string='Routing',
                                 required=True,
                                 ondelete='cascade')
    quantity = fields.Float(string='Quantity', default=1.0, required=True)
    product_id = fields.Many2one('product.product',
                                 string='Product',
                                 compute='_compute_origin_num_serie_id',
                                 store=True)
    origin_product_id = fields.Many2one('product.product',
                                        string='Origin product product',
                                        ondelete='cascade')
    uom_id = fields.Many2one('product.uom',
                             string='UoM',
                             compute='_compute_origin_num_serie_id',
                             store=True)
    qty_label = fields.Float(string='Label qty',
                             compute='_compute_origin_num_serie_id',
                             store=True)
    intervention_id = fields.Many2one('intervention',
                                      string='Intervention',
                                      required=False,
                                      ondelete='cascade')
    all_operation_ids = fields.Many2many('mrp.routing.line',
                                         'wiz_mo_repair_all_rl_rel',
                                         'wiz_id',
                                         'rl_id',
                                         string='All operations',
                                         compute='_compute_all_operation_ids')
    use_operation_ids = fields.Many2many('mrp.routing.line',
                                         'wiz_mo_repair_use_rl_rel',
                                         'wiz_id',
                                         'rl_id',
                                         string='Use operations',
                                         compute='_compute_use_operation_ids')

    #===========================================================================
    # Button
    #===========================================================================
    @api.multi
    def action_validation(self):
        wo_obj = self.env['mrp.workorder']
        product_obj = self.env['product.product']
        location_obj = self.env['stock.location']
        move_obj = self.env['stock.move']
        wo_resource_obj = self.env['mrp.wo.resource']
        wmro_obj = self.env['wiz.mo.repair.operations']
        mlc_obj = self.env['mrp.label.consumption']
        product_int_rcs = product_obj.search([('is_int', '=', True)], limit=1)
        location_out = location_obj.search([('usage', '=', 'production')],
                                           limit=1)
        location_in = location_obj.search([('usage', '=', 'internal')],
                                          limit=1)
        list_sequence = []
        for wiz in self:
            mo_rcs = False
            intervention_id = wiz.intervention_id and wiz.intervention_id.id or False
            min_start_date = wiz.intervention_id and wiz.intervention_id.start_date_requested and '%s 06:00:00' % (
                wiz.intervention_id.start_date_requested) or False
            max_end_date = wiz.intervention_id and wiz.intervention_id.ended_date_requested and '%s 16:00:00' % (
                wiz.intervention_id.ended_date_requested) or False
            other_data_arg_mo = {
                'intervention_id': intervention_id,
                'requested_date': wiz.repair_date,
                'max_end_date': wiz.return_date,
                'note_manufacturing': wiz.cause,
                'min_start_date': min_start_date,
                'max_end_date': max_end_date,
            }
            other_data_arg_wo = {'intervention_id': intervention_id}
            if wiz.mo_repair_ope_ids:
                arg_rl_sequences = []
                routing_line_ids = []
                for x in self.mo_repair_ope_ids:
                    arg_rl_sequences.append((x.sequence, x.rl_id.id))
                    routing_line_ids.append(x.rl_id.id)
                    if Decimal(str(x.sequence)) % Decimal(str(10)):
                        raise except_orm(
                            _('Error'),
                            _('The sequence field must be a multiple of 10.'))

                    list_sequence.append(x.sequence)

                no_wo = {
                    'quantity': wiz.quantity,
                    'uom': wiz.uom_id,
                    'product': wiz.product_id,
                    'routing_id': wiz.routing_id.id
                }
                mo_rcs = wo_obj.add_operation_wo(
                    routing_line_ids,
                    True,
                    False,
                    False,
                    False,
                    arg_rl_sequences=arg_rl_sequences,
                    no_wo=no_wo,
                    other_data_arg=other_data_arg_mo)

            if wiz.repair_type == 'repair_subset':
                if not mo_rcs:
                    mo_rcs = wo_obj.create_mo_light(
                        wiz.product_id,
                        wiz.quantity,
                        wiz.uom_id,
                        wiz.routing_id.id,
                        bom_id=False,
                        other_data=other_data_arg_mo)

                first_wo_rcs = wo_obj.create_wo_without_bom(
                    wiz.disassembly_rl_id,
                    mo_rcs,
                    1,
                    other_data_arg=other_data_arg_wo)
                if wiz.mo_repair_ope_ids:
                    last_sequence = wmro_obj.search(
                        [('wiz_mo_repair_id', '=', wiz.id)],
                        order='sequence desc',
                        limit=1).sequence + 10
                else:
                    last_sequence = 10

                last_wo_rcs = wo_obj.create_wo_without_bom(
                    wiz.assembly_rl_id,
                    mo_rcs,
                    last_sequence,
                    other_data_arg=other_data_arg_wo)
            elif mo_rcs:
                first_wo_rcs = wo_obj.search([('mo_id', '=', mo_rcs.id)],
                                             order='sequence asc',
                                             limit=1)
                last_wo_rcs = wo_obj.search([('mo_id', '=', mo_rcs.id)],
                                            order='sequence desc',
                                            limit=1)
            else:
                raise except_orm(_('Error'),
                                 _('Please choose at least one operation.'))

            if list_sequence:
                if wiz.repair_type != 'repair_subset':
                    min_sequence = min(list_sequence)
                    max_sequence = max(list_sequence)
                    if list_sequence.count(min_sequence) > 1:
                        raise except_orm(
                            _('Error'),
                            _('It can not be two times the same minimal sequence.'
                              ))

                    if list_sequence.count(max_sequence) > 1:
                        raise except_orm(
                            _('Error'),
                            _('It can not be two times the same maximum sequence.'
                              ))

            # Création matières à consommer et produits finaux
            # Pour le premier OT
            wo_resource_rcs = wo_resource_obj.search(
                [('wo_id', '=', first_wo_rcs.id)],
                order='sequence asc',
                limit=1)
            if wo_resource_rcs:
                location_in_int = wo_resource_rcs.resource_id.location_id
            else:
                location_in_int = location_in

            move_product_rm = self.add_rm(first_wo_rcs, first_wo_rcs.quantity,
                                          wiz.uom_id, wiz.product_id,
                                          location_in_int.id, location_out.id,
                                          move_obj)
            move_product_rm.assign_label(wiz.origin_num_serie_id,
                                         with_scrap=False)
            mlc_obj.create({
                'wo_id': first_wo_rcs.id,
                'label_id': wiz.origin_num_serie_id.id,
                'use_consumption': True,
                'quantity': wiz.quantity,
            })

            # Pour le dernier OT
            wo_resource_rcs = wo_resource_obj.search(
                [('wo_id', '=', last_wo_rcs.id)],
                order='sequence asc',
                limit=1)
            if wo_resource_rcs:
                location_in_int = wo_resource_rcs.resource_id.location_id
            else:
                location_in_int = location_in

            self.add_fp(last_wo_rcs, last_wo_rcs.quantity, wiz.uom_id,
                        wiz.product_id, location_in_int.id, location_out.id,
                        move_obj)
            if not wiz.is_new_num_serie:
                last_wo_rcs.write(
                    {'label_mo_repair_id': wiz.origin_num_serie_id.id})

            # Product int
            wo_int_rcs = wo_obj.search([('mo_id', '=', mo_rcs.id),
                                        ('id', 'not in', (first_wo_rcs.id,
                                                          last_wo_rcs.id))])
            for wo_int in wo_int_rcs:
                self.add_fp(wo_int, wo_int.quantity, product_int_rcs.uom_id,
                            product_int_rcs, location_in_int.id,
                            location_out.id, move_obj)

            if wiz.repair_type == 'repair_subset':
                self.add_fp(first_wo_rcs, first_wo_rcs.quantity,
                            product_int_rcs.uom_id, product_int_rcs,
                            location_in_int.id, location_out.id, move_obj)
                # Liste des sous ensembles à démonter
                dico_label_ids = {}
                for wmrl in wiz.wmrl_ids:
                    label = wmrl.label_id
                    if label.product_id in dico_label_ids:
                        dico_label_ids[label.product_id]['uom_qty'] += Decimal(
                            str(wmrl.uom_qty))
                        dico_label_ids[label.product_id]['label_rcs'] += label
                        dico_label_ids[
                            label.product_id]['dict_label_qty'][label] = (
                                wmrl.uom_qty, 0)
                    else:
                        dico_label_ids[label.product_id] = {
                            'label_rcs': label,
                            'uom_rcs': label.uom_id,
                            'uom_qty': Decimal(str(wmrl.uom_qty)),
                            'dict_label_qty': {
                                label: (wmrl.uom_qty, 0)
                            }
                        }

                    mlc_obj.create({
                        'wo_id': last_wo_rcs.id,
                        'label_id': label.id,
                        'use_consumption': True,
                        'quantity': wmrl.uom_qty
                    })

                for dico_label in dico_label_ids:
                    move_fp = self.add_fp(
                        first_wo_rcs, dico_label_ids[dico_label]['uom_qty'],
                        dico_label_ids[dico_label]['uom_rcs'], dico_label,
                        location_in_int.id, location_out.id, move_obj)
                    move_fp.assign_label(
                        dico_label_ids[dico_label]['label_rcs'],
                        dict_label_qty=dico_label_ids[dico_label]
                        ['dict_label_qty'],
                        with_scrap=False)
                    self.add_rm(last_wo_rcs,
                                dico_label_ids[dico_label]['uom_qty'],
                                dico_label_ids[dico_label]['uom_rcs'],
                                dico_label, location_in_int.id,
                                location_out.id, move_obj)

            else:
                if first_wo_rcs != last_wo_rcs:
                    self.add_fp(first_wo_rcs, first_wo_rcs.quantity,
                                product_int_rcs.uom_id, product_int_rcs,
                                location_in_int.id, location_out.id, move_obj)

            # Construction des suivants/précédents
            if first_wo_rcs != last_wo_rcs:
                new_sequence_next_rcs = wo_obj.search(
                    [('mo_id', '=', mo_rcs.id),
                     ('sequence', '>', first_wo_rcs.sequence)],
                    order='sequence asc',
                    limit=1)
                if new_sequence_next_rcs:
                    new_sequence_next = new_sequence_next_rcs.read(
                        ['sequence'])[0]['sequence']
                    self.recursive_prev_next_wo(mo_rcs, first_wo_rcs,
                                                new_sequence_next, wo_obj)

            return {
                'name': _('Manufacturing order for repair'),
                'view_type': 'form',
                'view_mode': 'form',
                'res_model': 'mrp.manufacturingorder',
                'type': 'ir.actions.act_window',
                'target': 'current',
                'res_id': mo_rcs.id,
                'nodestroy': True
            }

        return {'type': 'ir.actions.act_window_close'}

    def add_rm(self, wo, quantity, uom, product, location_id, location_dest_id,
               move_obj):
        efficient_unit_qty = wo.quantity and float(
            quantity) / wo.quantity or float(quantity)
        move = move_obj.create_move(product,
                                    location_id,
                                    location_dest_id,
                                    qty=float(quantity),
                                    uom=uom,
                                    other_data={
                                        'wo_incoming_id': wo.id,
                                        'efficient_unit_qty':
                                        efficient_unit_qty,
                                        'is_forecast': wo.is_forecast,
                                    },
                                    in_product_uom=True)

        return move

    def add_fp(self, wo, quantity, uom, product, location_id, location_dest_id,
               move_obj):
        efficient_unit_qty = wo.quantity and float(
            quantity) / wo.quantity or float(quantity)
        move = move_obj.create_move(product,
                                    location_dest_id,
                                    location_id,
                                    qty=float(quantity),
                                    uom=uom,
                                    other_data={
                                        'wo_outgoing_id': wo.id,
                                        'efficient_unit_qty':
                                        efficient_unit_qty,
                                        'is_forecast': wo.is_forecast,
                                    },
                                    in_product_uom=True)

        return move

    def recursive_prev_next_wo(self, mo_rcs, wo_prec_rcs, sequence_next,
                               wo_obj):
        wo_next_rcs = wo_obj.search([('mo_id', '=', mo_rcs.id),
                                     ('sequence', '=', sequence_next)])
        wo_prec_rcs.write({'next_wo_ids': [(6, 0, wo_next_rcs.ids)]})
        new_sequence_next_rcs = wo_obj.search(
            [('mo_id', '=', mo_rcs.id),
             ('sequence', '>', wo_next_rcs[0].sequence)],
            order='sequence asc',
            limit=1)
        if new_sequence_next_rcs:
            new_sequence_next = new_sequence_next_rcs.read(['sequence'
                                                            ])[0]['sequence']
            self.recursive_prev_next_wo(mo_rcs, wo_next_rcs, new_sequence_next,
                                        wo_obj)

        return True

    @api.multi
    def action_select_label(self):
        for wiz in self:
            wmrsl = self.env['wiz.mo.repair.select.label'].create(
                {'wiz_mo_repair_id': wiz.id})
            return {
                'name': _('Select labels'),
                'view_type': 'form',
                'view_mode': 'form',
                'res_model': 'wiz.mo.repair.select.label',
                'type': 'ir.actions.act_window',
                'target': 'stack',
                'res_id': wmrsl.id,
                'nodestroy': True,
            }
Exemplo n.º 15
0
class SectionBudgetTransfer(models.Model):
    _name = 'section.budget.transfer'
    _inherit = ['mail.thread']
    # _inherit = ['mail.thread', 'ir.needaction_mixin']
    _description = "Section Budget Transfer"
    _order = 'id desc'
    #
    # _track = {
    #     'state': {
    #         'pabi_budget_transfer.mt_transferd_draft_to_confirmed':
    #             lambda self, cr, uid, obj, ctx=None: obj.state == 'confirm',
    #     },
    # }

    # @api.model
    # def _needaction_domain_get(self):
    #     """ Show as unread to everyone as it is transfered """
    #     return [('state', '=', 'draft')]

    name = fields.Char(
        string='Name',
        required=True,
        readonly=True,
        default='/',
        size=100,
    )
    fiscalyear_id = fields.Many2one(
        'account.fiscalyear',
        string='Fiscal Year',
        required=True,
        readonly=True,
        # states={'draft': [('readonly', False)]},
        default=lambda self: self.env['account.fiscalyear'].find(),
        help="Fiscalyear will be as of current date only, no backdate allowed"
    )
    division_id = fields.Many2one(
        'res.division',
        string='Division',
        required=True,
        readonly=True,
        default=lambda self:
        self.env.user.partner_id.employee_id.section_id.division_id,
    )
    org_ids = fields.Many2many(
        'res.org',
        string='Org',
        required=True,
        readonly=True,
        default=lambda self: self._default_org_ids(),
    )
    currency_id = fields.Many2one(
        'res.currency',
        string="Currency",
        default=lambda self: self.env.user.company_id.currency_id,
        readonly=True,
    )
    date_prepare = fields.Date(
        string="Prepare Date",
        default=lambda self: fields.Date.context_today(self),
        readonly=True,
        states={'draft': [('readonly', False)]},
    )
    date_approve = fields.Date(
        string="Approved Date",
        readonly=True,
    )
    date_transfer = fields.Date(
        string="Transfer Date",
        readonly=True,
    )
    preparer_user_id = fields.Many2one(
        'res.users',
        string='Preparer',
        default=lambda self: self.env.user,
        readonly=True,
        states={'draft': [('readonly', False)]},
    )
    approver_user_id = fields.Many2one(
        'res.users',
        string='Approver',
        readonly=True,
    )
    transfer_user_id = fields.Many2one(
        'res.users',
        string='Transferer',
        readonly=True,
    )
    state = fields.Selection(
        _TRANSFER_STATE,
        string='Status',
        default='draft',
        index=True,
        readonly=True,
        copy=False,
        track_visibility='onchange',
    )
    transfer_line_ids = fields.One2many(
        'section.budget.transfer.line',
        'transfer_id',
        string='Budget Transfer Lines',
        readonly=True,
        states={'draft': [('readonly', False)]},
    )
    notes = fields.Text(
        string='Additional Information',
        size=1000,
    )
    total_transfer_amt = fields.Float(
        string='Transferred Amount',
        compute='_compute_total_transfer_amt',
    )

    @api.model
    def _default_org_ids(self):
        org_origin = self.env.user.partner_id.employee_id.section_id.org_id
        org_addition = self.env.user.partner_id.employee_id.org_ids
        return org_origin + org_addition

    @api.multi
    @api.constrains('fiscalyear_id', 'transfer_line_ids')
    def _check_transfer_line(self):
        """ Check that, all budget selected must be
        * chart_view = 'unit_base'
        * Same fiscal as the header
        * Belong to the same Org
        * Must be in state draft
        """
        for trans in self:
            for l in trans.transfer_line_ids:
                # State
                if l.from_budget_id.state != 'draft' or \
                        l.to_budget_id.state != 'draft':
                    raise ValidationError(_('Please verify that all budgets '
                                            'are in draft state!'))
                # Unit based
                if l.from_budget_id.chart_view != 'unit_base' or \
                        l.to_budget_id.chart_view != 'unit_base':
                    raise ValidationError(
                        _('Please verify that all budgets are unit based'))
                # Fiscal year
                this_fy_id = self.env['account.fiscalyear'].find()
                this_fy = self.env['account.fiscalyear'].browse(this_fy_id)
                if this_fy.id != trans.fiscalyear_id.id:
                    raise ValidationError(
                        _('Current FY is %s, you are not allow to transfer '
                          'budget out of this fiscalyear.') % (this_fy.name))
                if l.from_budget_id.fiscalyear_id != trans.fiscalyear_id or \
                        l.to_budget_id.fiscalyear_id != trans.fiscalyear_id:
                    raise ValidationError(
                        _('Please verify that all budgets are on fiscal '
                          'year %s') % (trans.fiscalyear_id.name))
                # Org
                # kittiu: this result in error during save
                # if l.from_budget_id.org_id != trans.org_id or \
                #         l.to_budget_id.org_id != trans.org_id:
                #     raise ValidationError(
                #        _('Please verify that all budgets belong to Org %s') %
                #         (trans.org_id.name_short))
                # Not same budget
                if l.from_budget_id == l.to_budget_id:
                    raise ValidationError(_('Please verify that source and '
                                            'target budget are not same!'))

    @api.depends('transfer_line_ids',
                 'transfer_line_ids.amount_transfer',
                 'state')
    def _compute_total_transfer_amt(self):
        for record in self:
            if record.state == 'transfer':
                lines = record.transfer_line_ids
                total_amt = sum([i.amount_transfer
                                 for i in lines])
                record.total_transfer_amt = total_amt

    @api.multi
    def button_draft(self):
        self.write({'state': 'draft'})
        return True

    @api.multi
    def button_cancel(self):
        self.write({'state': 'cancel'})
        return True

    @api.multi
    def button_confirm(self):
        fiscalyear_id = self.env['account.fiscalyear'].find()
        for record in self:
            # 1) Lines
            if sum(record.transfer_line_ids.mapped('amount_transfer')) == 0.0:
                raise ValidationError(
                    _('You can not confirm without transfer line amount!'))
            # 2) Can't transfer > room
            for line in record.transfer_line_ids:
                balance = line._get_balance()
                if float_compare(line.amount_transfer, balance, 2) == 1:
                    raise ValidationError(
                        _('Your amount is bigger than '
                          'available amount to transfer!'))
            name = self.env['ir.sequence'].\
                with_context(fiscalyear_id=fiscalyear_id).\
                next_by_code('section.budget.transfer')
            record.write({'state': 'confirm',
                          'name': name})
        return True

    @api.multi
    def button_approve(self):
        self.write({'state': 'approve',
                    'date_approve': fields.Date.context_today(self),
                    'approver_user_id': self._uid})
        return True

    @api.multi
    def button_transfer(self):
        for transfer in self:
            transfer.transfer_line_ids.action_transfer()
        self.write({'state': 'transfer',
                    'date_transfer': fields.Date.today(),
                    'transfer_user_id': self._uid})
        return True

    @api.multi
    def unlink(self):
        for rec in self:
            if rec.state != 'draft':
                raise ValidationError(
                    _('You can not delete non-draft records!'))
        return super(SectionBudgetTransfer, self).unlink()
Exemplo n.º 16
0
class IndividualCourse(models.Model):
    '''Individual Course'''
    _inherit = 'school.individual_course'

    ## Type and weight for average computation (ie 0 for dispenses) ##

    type = fields.Selection(([('S', 'Simple'), ('C', 'Complex'),
                              ('D', 'Deferred')]),
                            compute='compute_type',
                            string='Type',
                            store=True,
                            default="S")
    c_weight = fields.Float(compute='compute_weight',
                            readonly=True,
                            store=True)

    ## Evaluation ##

    ann_result = fields.Char(string='Annual Result',
                             track_visibility='onchange')
    jan_result = fields.Char(string='January Result',
                             track_visibility='onchange')
    jun_result = fields.Char(string='June Result', track_visibility='onchange')
    sept_result = fields.Char(string='September Result',
                              track_visibility='onchange')

    ## First Session ##

    first_session_result = fields.Float(compute='compute_results',
                                        string='First Session Result',
                                        store=True,
                                        group_operator='avg',
                                        digits=dp.get_precision('Evaluation'))
    first_session_result_bool = fields.Boolean(compute='compute_results',
                                               string='First Session Active',
                                               store=True)
    first_session_note = fields.Text(string='First Session Notes')

    first_session_result_disp = fields.Char(
        string='Final Result Display',
        compute='compute_first_session_result_disp')

    @api.one
    def compute_first_session_result_disp(self):
        if not self.first_session_result_bool:
            self.first_session_result_disp = ""
        if self.dispense:
            self.first_session_result_disp = "Val"
        else:
            self.first_session_result_disp = "%.2f" % self.first_session_result

    ## Second Session ##

    second_session_result = fields.Float(compute='compute_results',
                                         string='Second Session Result',
                                         store=True,
                                         group_operator='avg',
                                         digits=dp.get_precision('Evaluation'))
    second_session_result_bool = fields.Boolean(compute='compute_results',
                                                string='Second Session Active',
                                                store=True)
    second_session_note = fields.Text(string='Second Session Notes')

    second_session_result_disp = fields.Char(
        string='Final Result Display',
        compute='compute_second_session_result_disp')

    @api.one
    def compute_second_session_result_disp(self):
        if not self.second_session_result_bool:
            self.second_session_result_disp = ""
        if self.dispense:
            self.second_session_result_disp = "D"
        else:
            self.second_session_result_disp = "%.2f" % self.second_session_result

    @api.model
    def create(self, values):
        if not (values.get('type', False)) and values.get(
                'source_course_id', False):
            course = self.env['school.course'].browse(
                values['source_course_id'])
            values['type'] = course.type or 'S'
        result = super(IndividualCourse, self).create(values)
        return result

    @api.one
    @api.depends('dispense', 'weight', 'jun_result')
    def compute_weight(self):
        _logger.debug('Trigger "compute_weight" on Course %s' % self.name)
        if self.dispense and not self.jun_result:
            self.c_weight = 0
        else:
            self.c_weight = self.weight

    @api.one
    @api.depends('dispense', 'source_course_id.type')
    def compute_type(self):
        _logger.debug('Trigger "compute_type" on Course %s' % self.name)
        if self.dispense:
            self.type = 'D'
        else:
            self.type = self.source_course_id.type

    def _parse_result(self, input):
        f = float(input)
        if (f < 0 or f > 20):
            raise ValidationError("Evaluation shall be between 0 and 20")
        else:
            return f

    @api.depends('type', 'ann_result', 'jan_result', 'jun_result',
                 'sept_result')
    @api.one
    def compute_results(self):
        _logger.debug('Trigger "compute_results" on Course %s' % self.name)
        if self.type == 'D':
            if self.jun_result:
                try:
                    f = self._parse_result(self.jun_result)
                    self.first_session_result = f
                    self.first_session_result_bool = True
                except ValueError:
                    self.first_session_result = 0
                    self.first_session_result_bool = False
                    raise UserError(
                        _('Cannot decode %s in June Result, please encode a Float eg "12.00".'
                          % self.jun_result))

        if self.type in ['S', 'D']:
            f = -1
            if self.jan_result:
                try:
                    f = self._parse_result(self.jan_result)
                except ValueError:
                    self.first_session_result = 0
                    self.first_session_result_bool = False
                    raise UserError(
                        _('Cannot decode %s in January Result, please encode a Float eg "12.00".'
                          % self.jan_result))
            if self.jun_result:
                try:
                    f = self._parse_result(self.jun_result)
                except ValueError:
                    self.first_session_result = 0
                    self.first_session_result_bool = False
                    raise UserError(
                        _('Cannot decode %s in June Result, please encode a Float eg "12.00".'
                          % self.jun_result))
            if f >= 0:
                self.first_session_result = f
                self.first_session_result_bool = True
            if self.sept_result:
                try:
                    f = self._parse_result(self.sept_result)
                    self.second_session_result = f
                    self.second_session_result_bool = True
                except ValueError:
                    self.second_session_result = 0
                    self.second_session_result_bool = False
                    raise UserError(
                        _('Cannot decode %s in September Result, please encode a Float eg "12.00".'
                          % self.sept_result))
        if self.type in ['C']:
            ann = None
            jan = None
            if self.ann_result:
                try:
                    ann = self._parse_result(self.ann_result)
                except ValueError:
                    raise UserError(
                        _('Cannot decode %s in January Result, please encode a Float eg "12.00".'
                          % self.ann_result))
            if self.jan_result:
                try:
                    jan = self._parse_result(self.jan_result)
                except ValueError:
                    raise UserError(
                        _('Cannot decode %s in January Result, please encode a Float eg "12.00".'
                          % self.jan_result))
            if self.jun_result:
                try:
                    jun = self._parse_result(self.jun_result)
                    if self.ann_result and self.jan_result:
                        self.first_session_result = ann * 0.5 + (
                            jan * 0.5 + jun * 0.5) * 0.5
                        self.first_session_result_bool = True
                    elif self.ann_result:
                        self.first_session_result = ann * 0.5 + jun * 0.5
                        self.first_session_result_bool = True
                    else:
                        self.first_session_result = 0
                        self.first_session_result_bool = False
                except ValueError:
                    self.first_session_result = 0
                    self.first_session_result_bool = False
                    raise UserError(
                        _('Cannot decode %s in June Result, please encode a Float eg "12.00".'
                          % self.jun_result))
            if self.sept_result:
                try:
                    sept = self._parse_result(self.sept_result)
                    if self.ann_result:
                        self.second_session_result = ann * 0.5 + sept * 0.5
                        self.second_session_result_bool = True
                    else:
                        self.first_session_result = 0
                        self.first_session_result_bool = False
                except ValueError:
                    self.second_session_result = 0
                    self.second_session_result_bool = False
                    raise UserError(
                        _('Cannot decode %s in September Result, please encode a Float eg "12.00".'
                          % self.sept_result))
Exemplo n.º 17
0
class SectionBudgetTransferLine(models.Model):
    _name = 'section.budget.transfer.line'
    _description = "Section Budget Transfer Lines"

    transfer_id = fields.Many2one(
        'section.budget.transfer',
        string='Section Budget Transfer',
        ondelete='cascade',
        index=True,
    )
    state = fields.Selection(
        _TRANSFER_STATE,
        string='Status',
        related='transfer_id.state',
        readonly=True,
        store=True,
    )
    from_budget_id = fields.Many2one(
        'account.budget',
        string='From Section',
        required=True,
        domain=lambda self: self._domain_budget_id()
    )
    from_budget = fields.Char(
        string='From Budget',
        related='from_budget_id.name',
        readonly=True,
    )
    from_section_id = fields.Many2one(
        'res.section',
        string='From Secton',
        related='from_budget_id.section_id',
        readonly=True,
    )
    amount_transfer = fields.Float(
        string='Transfer Amount',
        required=True,
    )
    to_budget_id = fields.Many2one(
        'account.budget',
        string='To Section',
        required=True,
        domain=lambda self: self._domain_budget_id()
    )
    to_budget = fields.Char(
        string='To Budget',
        related='to_budget_id.name',
        readonly=True,
    )
    to_section_id = fields.Many2one(
        'res.section',
        string='To Secton',
        related='to_budget_id.section_id',
        readonly=True,
    )
    notes = fields.Text(
        string='Notes/Reason',
        size=1000,
    )
    _sql_constraints = [
        ('no_negative_transfer_amount', 'CHECK(amount_transfer >= 0)',
         'Transfer amount must be positive'),
    ]

    def _domain_budget_id(self):
        org_origin = self.env.user.partner_id.employee_id.section_id.org_id
        org_addition = self.env.user.partner_id.employee_id.org_ids
        org_ids = org_origin + org_addition
        fiscalyear_id = self.env['account.fiscalyear'].find()
        dom = [('state', '=', 'draft'), ('chart_view', '=', 'unit_base'),
               ('section_id', '!=', False), ('org_id', 'in', org_ids.ids),
               ('fiscalyear_id', '=', fiscalyear_id)]
        return dom

    @api.multi
    def action_transfer(self):
        # Only available setup to use section budget transfer it,
        for line in self:
            from_budget = line.from_budget_id
            to_budget = line.to_budget_id
            # Check budget level
            from_budget_release = from_budget.budget_level_id.budget_release
            to_budget_release = to_budget.budget_level_id.budget_release
            if from_budget_release != 'manual_header' or \
                    to_budget_release != 'manual_header':
                raise ValidationError(
                    _('Budget level for unit base is not valid for transfer.\n'
                      'Please make sure Release Type = "Budget Header".'))
            from_budget.write({
                'to_release_amount': (from_budget.released_amount -
                                      line.amount_transfer)})
            from_budget._validate_plan_vs_release()
            to_budget.write({
                'to_release_amount': (to_budget.released_amount +
                                      line.amount_transfer)})
            to_budget._validate_plan_vs_release()
        return True

    @api.onchange('from_budget_id', 'to_budget_id')
    def _onchange_from_to_budget_id(self):
        self.ensure_one()
        if self.from_budget_id and self.to_budget_id:
            if self.from_budget_id.org_id != self.to_budget_id.org_id:
                raise ValidationError(_(
                    "Can not transfer budget different org."))

    @api.onchange('from_budget_id')
    def _onchange_from_budget_id(self):
        balance = self._get_balance()
        if self.from_budget_id and balance <= 0.0:
            raise ValidationError(
                _("%s don't have enough budget to transfer.\n"
                  "Make sure its rolling amount is less than its released") %
                self.from_budget_id.name)
        self.amount_transfer = balance

    @api.onchange('amount_transfer')
    def _onchange_amount_transfer(self):
        balance = self._get_balance()
        if float_compare(self.amount_transfer, balance, 2) == 1:
            raise ValidationError(
                _('Your amount is bigger than available amount to transfer!'))

    @api.multi
    def _get_balance(self):
        budget = self.from_budget_id
        fiscalyear = budget.fiscalyear_id
        control_external = fiscalyear.control_ext_charge_only
        if control_external:
            expense_lines = budget.section_id.monitor_expense_ids.filtered(
                lambda l: l.fiscalyear_id in fiscalyear
                and l.charge_type == 'external'
            )
        else:
            expense_lines = budget.section_id.monitor_expense_ids.filtered(
                lambda l: l.fiscalyear_id in fiscalyear
            )
        consumed = sum([i.amount_consumed for i in expense_lines])
        release = self.from_budget_id.to_release_amount
        balance = release - consumed
        return balance
class ComputedPurchaseOrderLine(models.Model):
    _description = 'Computed Purchase Order Line'
    _name = 'computed.purchase.order.line'
    _order = 'sequence'

    _STATE = [
        ('new', 'New'),
        ('up_to_date', 'Up to date'),
        ('updated', 'Updated'),
    ]

    # Columns section
    computed_purchase_order_id = fields.Many2one(
        'computed.purchase.order', 'Order Reference', required=True,
        ondelete='cascade')
    state = fields.Selection(
        _STATE, 'State', required=True, readonly=True, default='new',
        help="Shows if the product's information has been updated")
    sequence = fields.Integer(
        'Sequence',
        help="""Gives the sequence order when displaying a list of"""
        """ purchase order lines.""")
    product_id = fields.Many2one(
        'product.product', 'Product', required=True,
        domain=[('purchase_ok', '=', True)])
    uom_id = fields.Many2one(
        related='product_id.uom_id', string="UoM", readonly='True')
    product_code = fields.Char('Supplier Product Code',)
    product_code_inv = fields.Char(
        compute='_get_product_information', inverse='_set_product_code',
        string='Supplier Product Code', multi='product_code_name_price',
        help="""This supplier's product code will be used when printing"""
        """ a request for quotation. Keep empty to use the internal"""
        """ one.""")
    product_name = fields.Char('Supplier Product Name',)
    product_name_inv = fields.Char(
        compute='_get_product_information', inverse='_set_product_name',
        string='Supplier Product Name', multi='product_code_name_price',
        help="""This supplier's product name will be used when printing"""
        """ a request for quotation. Keep empty to use the internal"""
        """ one.""")
    product_price = fields.Float(
        'Supplier Product Price',
        digits_compute=dp.get_precision('Product Price'))
    discount = fields.Float(
        string='Discount (%)', digits_compute=dp.get_precision('Discount'))
    discount_inv = fields.Float(
        string='Discount (%)', digits_compute=dp.get_precision('Discount'),
        compute='_get_product_information', inverse='_set_discount',
        multi='product_code_name_price',)
    product_price_inv = fields.Float(
        compute='_get_product_information', inverse='_set_product_price',
        string='Supplier Product Price', multi='product_code_name_price',)
    price_policy = fields.Selection(
        [('uom', 'per UOM'), ('package', 'per Package')], "Price Policy",
        default='uom', required=True)
    product_price_inv_eq = fields.Float(
        compute='_compute_product_price_inv_eq',
        string='Supplier Product Price per Uom',)
    subtotal = fields.Float(
        'Subtotal', compute='_compute_subtotal_price',
        digits_compute=dp.get_precision('Product Price'))
    package_qty = fields.Float('Package quantity')
    package_qty_inv = fields.Float(
        compute='_get_product_information', inverse='_set_package_qty',
        string='Package quantity', multi='product_code_name_price',)
    weight = fields.Float(
        related='product_id.weight', string='Net Weight', readonly='True')
    uom_po_id = fields.Many2one('product.uom', 'UoM', required=True)

    average_consumption = fields.Float(
        compute="_compute_average_consumption", digits=(12, 3))
    displayed_average_consumption = fields.Float(
        'Average Consumption', digits=(12, 3))
    consumption_range = fields.Integer(
        'Range (days)', help="""Range (in days) used to display the average
        consumption""")
    stock_duration = fields.Float(
        compute='_compute_stock_duration', string='Stock Duration (Days)',
        readonly='True', help="Number of days the stock should last.")
    virtual_duration = fields.Float(
        compute='_compute_stock_duration', string='Virtual Duration (Days)',
        readonly='True', help="""Number of days the stock should last after"""
        """ the purchase.""")
    purchase_qty_package = fields.Float(
        'Number of packages',
        help="""The number of packages you'll buy.""")
    purchase_qty = fields.Float(
        'Quantity to purchase',
        compute='_compute_purchase_qty',
        store=True,
        help="The quantity you should purchase.")
    manual_input_output_qty = fields.Float(
        string='Manual variation', default=0,
        help="""Write here some extra quantity depending of some"""
        """ input or output of products not entered in the software\n"""
        """- negative quantity : extra output ; \n"""
        """- positive quantity : extra input.""")
    qty_available = fields.Float(
        compute='_get_qty', string='Quantity On Hand', multi='get_qty',
        help="The available quantity on hand for this product")
    incoming_qty = fields.Float(
        compute='_get_qty', string='Incoming Quantity',
        help="Virtual incoming entries", multi='get_qty',)
    outgoing_qty = fields.Float(
        compute='_get_qty', string='Outgoing Quantity',
        help="Virtual outgoing entries", multi='get_qty',)
    virtual_qty = fields.Float(
        compute='_get_qty', string='Virtual Quantity',
        help="Quantity on hand + Virtual incoming and outgoing entries",
        multi='get_qty',)
    computed_qty = fields.Float(
        compute='_get_computed_qty', string='Stock',
        help="The sum of all quantities selected.",
        digits_compute=dp.get_precision('Product UoM'),)
    cpo_state = fields.Selection([
        ('draft', 'Draft'),
        ('done', 'Done'),
        ('canceled', 'Canceled'),
    ],
        related='computed_purchase_order_id.state',
        string='State')

    # Constraints section
    _sql_constraints = [(
        'product_id_uniq', 'unique(computed_purchase_order_id,product_id)',
        'Product must be unique by computed purchase order!'),
    ]

    # Columns section
    @api.multi
    @api.onchange('purchase_qty')
    def onchange_purchase_qty(self):
        for cpol in self:
            if cpol.package_qty_inv:
                cpol.purchase_qty_package = cpol.purchase_qty /\
                    cpol.package_qty_inv

    @api.multi
    @api.depends('purchase_qty_package', 'package_qty_inv')
    def _compute_purchase_qty(self):
        for cpol in self:
            if cpol.purchase_qty_package == int(cpol.purchase_qty_package):
                cpol.purchase_qty = cpol.package_qty_inv *\
                    cpol.purchase_qty_package

    @api.multi
    @api.onchange('package_qty_inv', 'product_price_inv', 'price_policy')
    def _compute_product_price_inv_eq(self):
        for line in self:
            if line.price_policy == 'package':
                if line.package_qty_inv:
                    line.product_price_inv_eq = line.product_price_inv /\
                        line.package_qty_inv
                else:
                    line.product_price_inv_eq = 0
            else:
                line.product_price_inv_eq = line.product_price_inv

    @api.depends(
        'purchase_qty', 'product_price', 'product_price_inv', 'price_policy',
        'package_qty_inv', 'discount_inv')
    @api.multi
    def _compute_subtotal_price(self):
        for line in self:
            net_unit_price =\
                line.product_price_inv * (1 - line.discount_inv / 100.0)
            if line.price_policy == 'package':
                line.subtotal = line.package_qty_inv and line.purchase_qty *\
                    net_unit_price / line.package_qty_inv or 0
            else:
                line.subtotal = line.purchase_qty * net_unit_price

    @api.onchange('displayed_average_consumption', 'consumption_range')
    @api.multi
    def _compute_average_consumption(self):
        for line in self:
            line.average_consumption = line.consumption_range and\
                line.displayed_average_consumption / line.consumption_range\
                or 0

    # Fields Function section
    @api.depends('product_id')
    @api.multi
    def _get_qty(self):
        for cpol in self:
            cpol.qty_available = cpol.product_id.qty_available
            cpol.incoming_qty = cpol.product_id.incoming_qty
            cpol.outgoing_qty = cpol.product_id.outgoing_qty
            cpol.virtual_qty = cpol.qty_available + cpol.incoming_qty - \
                cpol.outgoing_qty

    @api.multi
    def _get_computed_qty(self):
        use_pending_qties = False
        for cpol in self:
            if cpol.computed_purchase_order_id.compute_pending_quantity:
                use_pending_qties = True
            if use_pending_qties:
                break

        for cpol in self:
            q = cpol.qty_available
            if use_pending_qties:
                q += cpol.incoming_qty - cpol.outgoing_qty
            cpol.computed_qty = q

    @api.multi
    def _get_product_information(self):
        psi_obj = self.env['product.supplierinfo']
        for cpol in self:
            if not cpol.product_id:
                cpol.product_code_inv = None
                cpol.product_name_inv = None
                cpol.product_price_inv = 0.0
                cpol.discount = 0.0
                cpol.price_policy = 'uom'
                cpol.package_qty_inv = 0.0
            elif cpol.state in ('updated', 'new'):
                cpol.product_code_inv = cpol.product_code
                cpol.product_name_inv = cpol.product_name
                cpol.product_price_inv = cpol.product_price
                cpol.discount_inv = cpol.discount
                cpol.package_qty_inv = cpol.package_qty
            else:
                psi = psi_obj.search([
                    ('name', '=',
                        cpol.computed_purchase_order_id.partner_id.id),
                    ('product_tmpl_id', '=',
                        cpol.product_id.product_tmpl_id.id)])
                if len(psi):
                    psi = psi[0]
                    if psi:
                        cpol.product_code_inv = psi.product_code
                        cpol.product_name_inv = psi.product_name
                        cpol.product_price_inv = psi.base_price
                        cpol.discount_inv = psi.discount
                        cpol.package_qty_inv = psi.package_qty
                        cpol.price_policy = psi.price_policy

    @api.depends('product_code_inv')
    def _set_product_code(self):
        self.product_code = self.product_code_inv
        if self.state == 'up_to_date':
            self.state = 'updated'

    @api.depends('product_name_inv')
    def _set_product_name(self):
        self.product_name = self.product_name_inv
        if self.state == 'up_to_date':
            self.state = 'updated'

    @api.depends('product_price_inv')
    def _set_product_price(self):
        self.product_price = self.product_price_inv
        if self.state == 'up_to_date':
            self.state = 'updated'

    @api.depends('discount_inv')
    def _set_discount(self):
        self.discount = self.discount_inv
        if self.state == 'up_to_date':
            self.state = 'updated'

    @api.onchange('package_qty_inv')
    def _set_package_qty(self):
        self.package_qty = self.package_qty_inv
        if self.state == 'up_to_date':
            self.state = 'updated'

    @api.multi
    @api.depends('purchase_qty')
    def _compute_stock_duration(self):
        for cpol in self:
            if cpol.product_id:
                if cpol.average_consumption != 0:
                    cpol.stock_duration = (
                        cpol.computed_qty + cpol.manual_input_output_qty)\
                        / cpol.average_consumption
                    cpol.virtual_duration = (
                        cpol.computed_qty + cpol.manual_input_output_qty +
                        cpol.purchase_qty) / cpol.average_consumption

    # View Section
    @api.onchange(
        'product_code_inv', 'product_name_inv', 'product_price_inv',
        'package_qty_inv', 'price_policy', 'discount_inv')
    def onchange_product_info(self):
        self.state = 'updated'

    @api.onchange(
        'computed_purchase_order_id', 'product_id',
    )
    def onchange_product_id(self):
        vals = {
            'state': 'new',
            'purchase_qty': 0,
            'manual_input_output_qty': 0,
        }
        if self.product_id:
            psi_obj = self.env['product.supplierinfo']
            pp = self.product_id
            computed_qty = pp.qty_available

            if self.computed_purchase_order_id:
                cpo = self.computed_purchase_order_id
                # Check if the product is already in the list.
                products = [x.product_id.id for x in cpo.line_ids]
                if self.product_id.id in products:
                    raise ValidationError(
                        _('This product is already in the list!'))
                if cpo.compute_pending_quantity:
                    computed_qty += pp.incoming_qty - pp.outgoing_qty
            vals.update({
                'qty_available': pp.qty_available,
                'incoming_qty': pp.incoming_qty,
                'outgoing_qty': pp.outgoing_qty,
                'computed_qty': computed_qty,
                'weight': pp.weight,
                'uom_po_id': pp.uom_id.id,
                'product_price_inv': 0,
                'discount_inv': 0,
                'price_policy': 'uom',
                'package_qty_inv': 0,
                'average_consumption': pp.displayed_average_consumption,
                'consumption_range': pp.display_range,
            })

            # If product is in the supplierinfo,
            # retrieve values and set state up_to_date
            psi_id = psi_obj.search([
                ('name', '=', self.computed_purchase_order_id.partner_id.id),
                ('product_tmpl_id', '=', pp.product_tmpl_id.id)])
            if psi_id:
                psi = psi_id[0]
                vals.update({
                    'product_code_inv': psi.product_code,
                    'product_name_inv': psi.product_name,
                    'product_price_inv': psi.price,
                    'discount_inv': psi.discount,
                    'price_policy': psi.price_policy,
                    'package_qty_inv': psi.package_qty,
                    'uom_po_id': psi.product_uom.id,
                    'state': 'up_to_date',
                })
            self.qty_available = vals['qty_available']
            self.incoming_qty = vals['incoming_qty']
            self.outgoing_qty = vals['outgoing_qty']
            self.computed_qty = vals['computed_qty']
            self.weight = vals['weight']
            self.uom_po_id = vals['uom_po_id']
            self.product_price_inv = vals['product_price_inv']
            self.discount_inv = vals['discount_inv']
            self.price_policy = vals['price_policy']
            self.package_qty_inv = vals['package_qty_inv']
            self.average_consumption = vals['average_consumption']
            self.consumption_range = vals['consumption_range']

    @api.multi
    def unlink_psi(self):
        psi_obj = self.env["product.supplierinfo"]
        for cpol in self:
            cpo = cpol.computed_purchase_order_id
            partner_id = cpo.partner_id.id
            product_tmpl_id = cpol.product_id.product_tmpl_id.id
            psi_ids = psi_obj.search([
                ('name', '=', partner_id),
                ('product_tmpl_id', '=', product_tmpl_id)])
            psi_ids.unlink()
            cpol.unlink()

    @api.multi
    def create_psi(self):
        psi_obj = self.env['product.supplierinfo']
        for cpol in self:
            cpo = cpol.computed_purchase_order_id
            partner_id = cpo.partner_id.id
            product_tmpl_id = cpol.product_id.product_tmpl_id.id
            vals = {
                'name': partner_id,
                'product_name': cpol.product_name,
                'product_code': cpol.product_code,
                'product_uom': cpol.uom_po_id.id,
                'package_qty': cpol.package_qty_inv,
                'min_qty': cpol.package_qty,
                'product_id': product_tmpl_id,
                'pricelist_ids': [(0, 0, {
                    'min_quantity': 0,
                    'price': cpol.product_price_inv,
                    'discount': cpol.discount_inv,
                })],
                'price_policy': cpol.price_policy,
            }
            psi_id = psi_obj.create(vals)
            cpol.state = 'up_to_date'
        return psi_id
Exemplo n.º 19
0
class AccountInvoiceLine(models.Model):
    _inherit = 'account.invoice.line'

    @api.one
    @api.depends('price_unit', 'discount', 'invoice_line_tax_id', 'quantity',
                 'product_id', 'invoice_id.partner_id',
                 'invoice_id.currency_id')
    def _compute_price(self):
        price = self.price_unit * (1 - (self.discount or 0.0) / 100.0)
        taxes = self.invoice_line_tax_id.compute_all(
            price,
            self.quantity,
            product=self.product_id,
            partner=self.invoice_id.partner_id,
            fiscal_position=self.fiscal_position)
        self.price_subtotal = taxes['total'] - taxes['total_tax_discount']
        self.price_total = taxes['total']
        if self.invoice_id:
            self.price_subtotal = self.invoice_id.currency_id.round(
                self.price_subtotal)
            self.price_total = self.invoice_id.currency_id.round(
                self.price_total)

    invoice_line_tax_id = fields.Many2many('account.tax',
                                           'account_invoice_line_tax',
                                           'invoice_line_id',
                                           'tax_id',
                                           string='Taxes',
                                           domain=[('parent_id', '=', False)])
    fiscal_category_id = fields.Many2one('l10n_br_account.fiscal.category',
                                         'Categoria Fiscal')
    fiscal_position = fields.Many2one(
        'account.fiscal.position',
        u'Posição Fiscal',
        domain="[('fiscal_category_id', '=', fiscal_category_id)]")
    price_total = fields.Float(string='Amount',
                               store=True,
                               digits=dp.get_precision('Account'),
                               readonly=True,
                               compute='_compute_price')

    def fields_view_get(self,
                        cr,
                        uid,
                        view_id=None,
                        view_type=False,
                        context=None,
                        toolbar=False,
                        submenu=False):

        result = super(AccountInvoiceLine,
                       self).fields_view_get(cr,
                                             uid,
                                             view_id=view_id,
                                             view_type=view_type,
                                             context=context,
                                             toolbar=toolbar,
                                             submenu=submenu)

        if context is None:
            context = {}

        if view_type == 'form':
            eview = etree.fromstring(result['arch'])

            if 'type' in context.keys():
                expr = "//field[@name='fiscal_category_id']"
                fiscal_categories = eview.xpath(expr)
                for fiscal_category_id in fiscal_categories:
                    fiscal_category_id.set(
                        'domain', """[('type', '=', '%s'),
                        ('journal_type', '=', '%s')]""" %
                        (OPERATION_TYPE[context['type']],
                         JOURNAL_TYPE[context['type']]))
                    fiscal_category_id.set('required', '1')

            product_ids = eview.xpath("//field[@name='product_id']")
            for product_id in product_ids:
                product_id.set(
                    'domain', "[('fiscal_type', '=', '%s')]" %
                    (context.get('fiscal_type', 'service')))

            result['arch'] = etree.tostring(eview)

        return result
Exemplo n.º 20
0
class jmd_asunto(models.Model):
    _inherit = "mail.thread"
    _name = "utils.minuta.asunto"

    @api.one
    def task(self):
        ret = {}
        self.project_id.write({
            'task_ids': [(0, 0, {
                'name': self.descripcion,
                'planned_hours': 1,
                'user_id': self.responsable.user_id.id,
                'date_deadline': self.fecha_limite
            })]
        })
        self.write({'tarea': True})
        return ret

    @api.one
    def appoint(self):
        ret = {}
        fecha = self.fecha_limite
        print(type(fecha))
        print(fecha)
        fecha_obj = datetime.strptime(self.fecha_limite, "%Y-%m-%d")
        fechastr = datetime.strftime(fecha_obj, "%Y-%m-%d") + " 10:00:00"
        fechastop = datetime.strftime(fecha_obj, "%Y-%m-%d") + " 11:00:00"
        self.env['calendar.event'].create({
            'name': self.descripcion,
            'start_datetime': fechastr,
            'stop_datetime': fechastop,
        })
        self.write({'cita': True})
        return ret

    name = fields.Char("Consecutivo")
    descripcion = fields.Char("Descripción")
    responsable = fields.Many2one("hr.employee", string="Responsable")
    fecha_limite = fields.Date("Fecha Límite")
    vuelta = fields.Integer("Vuelta", default=1)
    horas_dedicadas = fields.Float("Horas Dedicadas")
    realizado = fields.Boolean("Realizado")
    comentarios = fields.Text("Comentarios")
    prioridad = fields.Selection([("Alta", "Alta"), ("Media", "Media"),
                                  ("Baja", "Baja")],
                                 string="Prioridad")
    pasos = fields.Char("Pasos a seguir")
    tarea = fields.Boolean("Tarea")
    cita = fields.Boolean("Cita")
    minuta_id = fields.Many2one("utils.minuta")
    motivo_cambios = fields.Selection(
        [('diseno', 'Problemas de Diseño'),
         ('cliente', 'Problemas de Cliente'),
         ('construccion', 'Problemas de Construcción')],
        string="Motivo de los Cambios")
    project_id = fields.Many2one("project.project", string="Proyecto")
    adjunto = fields.Binary("Archivo Adjunto")
    nadjunto = fields.Char("Nombre del Archivo")
    tipo = fields.Selection([('Proveedor', 'Proveedor'),
                             ('Cliente', 'Cliente')],
                            string="Tipo")
Exemplo n.º 21
0
class location_moves(models.TransientModel):

    _name = 'location.moves'

    product_id = fields.Many2one('product.product', 'Product', required=True)
    qty = fields.Float('Qty', required=True)
    check_qty = fields.Boolean(
        'Check Qty',
        default=lambda self: self.env.context.get('manual', False))

    move_type = fields.Selection([
        ('beach_stock', 'Beach -> Stock'),
        ('beach_kitchen', 'Beach -> Kitchen'),
        ('beach_pantry', 'Beach -> Pantry'),
        ('stock_kitchen', 'Stock -> Kitchen'),
        ('stock_pantry', 'Stock -> Pantry'),
        ('pantry_kitchen', 'Pantry -> Kitchen'),
        ('kitchen_cooked', 'Kitchen -> Cooked'),
        ('kitchen_nursing', 'Kitchen -> Nursing'),
        ('nursing_damaged', 'Nursing -> Damaged'),
        ('nursing_cooked', 'Nursing -> Cooked'),
        ('quality_cooked', 'Quality -> Cooked'),
        ('cooked_quality', 'Cooked -> Quality'),
        ('cooked_damaged', 'Cooked -> Damaged'),
        ('marketing_stock', 'Marketing -> Stock'),
        ('marketing_product', 'Marketing -> Product'),
        ('stock_marketing', 'Stock -> Marketing'),
        ('product_stock', 'Product -> Stock'),
        ('stock_product', 'Stock -> Product'),
        ('development_stock', 'Development -> Stock'),
        ('stock_development', 'Stock -> Development'),
        ('sat_stock', 'SAT -> Stock'),
        ('stock_sat', 'Stock -> SAT'),
        ('external_stock', 'External -> Stock'),
        ('beach_external', 'Beach -> External'),
    ],
                                 'Move type',
                                 required=True)

    @api.one
    def create_moves(self):
        loc_obj = self.env['stock.location']
        types = {
            'beach_stock': loc_obj.move_beach_stock,
            'beach_kitchen': loc_obj.move_beach_kitchen,
            'beach_pantry': loc_obj.move_beach_pantry,
            'stock_kitchen': loc_obj.move_stock_kitchen,
            'stock_pantry': loc_obj.move_stock_pantry,
            'pantry_kitchen': loc_obj.move_pantry_kitchen,
            'kitchen_cooked': loc_obj.move_kitchen_cooked,
            'kitchen_nursing': loc_obj.move_kitchen_nursing,
            'nursing_damaged': loc_obj.move_nursing_damaged,
            'nursing_cooked': loc_obj.move_nursing_cooked,
            'quality_cooked': loc_obj.move_quality_cooked,
            'cooked_damaged': loc_obj.move_cooked_damaged,
            'marketing_stock': loc_obj.move_marketing_stock,
            'stock_marketing': loc_obj.move_stock_marketing,
            'product_stock': loc_obj.move_product_stock,
            'stock_product': loc_obj.move_stock_product,
            'development_stock': loc_obj.move_development_stock,
            'stock_development': loc_obj.move_stock_development,
            'sat_stock': loc_obj.move_sat_stock,
            'stock_sat': loc_obj.move_stock_sat,
            'cooked_quality': loc_obj.move_cooked_quality,
            'marketing_product': loc_obj.move_marketing_product,
            'external_stock': loc_obj.move_external_stock,
            'beach_external': loc_obj.move_beach_external
        }
        types[self.move_type](self.product_id.id, self.qty, self.check_qty)
        return True
Exemplo n.º 22
0
class StockMove(models.Model):
    _inherit = 'stock.move'

    returned_qty = fields.Float()
Exemplo n.º 23
0
class recibos(models.Model):
    _name = 'recibos'
    _description = u'Recibos'
    _inherit = ['mail.thread']
    _rec_name = 'concepto'

    _track = {
        'concepto': {
            'recibos.mt_concepto_change':
            lambda self, cr, uid, obj, ctx=None: True,
        },
        'fecha': {
            'recibos.mt_fecha_change':
            lambda self, cr, uid, obj, ctx=None: True,
        },
        'importe': {
            'recibos.mt_importe_change':
            lambda self, cr, uid, obj, ctx=None: True,
        },
        'cobrado': {
            'recibos.mt_cobrado_change':
            lambda self, cr, uid, obj, ctx=None: True,
        },
        'pagado': {
            'recibos.mt_pagado_change':
            lambda self, cr, uid, obj, ctx=None: True,
        },
    }

    _mail_post_access = 'read'

    #API VIEJA
    #_columns = {
    #    'concepto': fields.char(_(u'Concepto'), size=500, required=True),
    #    'fecha': fields.date(_(u'Fecha'), required=True),
    #    'importe': fields.float(_(u'Importe'), required=True),
    #    'cobrado': fields.float(_(u'Cobrado'), required=True),
    #    'pagado': fields.boolean(_(u'Pagado')),
    #    'product_id': fields.many2one('product.product', _(u'Vivienda')),
    #    'pendiente': fields.function(_get_importe_pendiente, type='float', digits=(12, 2), string=_(u'Pendiente')),
    #}

    #_defaults = {
    #    'cobrado': 0,
    #}

    #API NUEVA - odoo8
    concepto = fields.Char(string='Concepto', required=True)
    fecha = fields.Date(string='Fecha', required=True)
    importe = fields.Float(string='Importe Factura', required=True)
    cobrado = fields.Float(string='Importe Cobrado',
                           required=True,
                           default=0.0)
    pagado = fields.Boolean(string='Pagado Propietario', default=False)

    account_id = fields.Many2one('account.analytic.account', string='Contrato')

    pendiente = fields.Float(string='Importe Pendiente de Cobrar',
                             store=False,
                             compute='_get_importe_pendiente')
    account_product = fields.Char(string='Vivienda',
                                  store=True,
                                  compute='_get_account_product')
    account_product_owner = fields.Char(string='Propietario',
                                        store=False,
                                        compute='_get_account_product_owner')
    account_product_tenant = fields.Char(string='Inquilino',
                                         store=False,
                                         compute='_get_account_product_tenant')

    @api.one
    @api.depends('importe', 'cobrado')
    def _get_importe_pendiente(self):
        self.pendiente = self.importe - self.cobrado

    @api.one
    @api.depends('account_id')
    def _get_account_product(self):
        self.account_product = self.account_id.product.name

    @api.one
    @api.depends('account_id')
    def _get_account_product_owner(self):
        self.account_product_owner = self.account_id.product.owner.name

    @api.one
    @api.depends('account_id')
    def _get_account_product_tenant(self):
        self.account_product_tenant = self.account_id.partner_id.name
Exemplo n.º 24
0
class Ticket(models.Model):
    """Add complexity and risk functionnality to tickets
    Risk is based on complexities. Each complexity has a risk value,
    and the risk is copied on the ticket
    """
    _inherit = 'anytracker.ticket'

    @api.depends('rating_ids', 'parent_id', 'child_ids')
    def _get_my_rating(self):
        """get my latest rating for this ticket
        """
        RATING = self.env['anytracker.rating']
        rating = False
        for ticket in self:
            ratings = RATING.search([('user_id', '=', ticket.env.uid),
                                     ('ticket_id', '=', ticket.id)],
                                    order='time DESC, id DESC')
            if ratings:
                rating = ratings[0].complexity_id.id
            ticket.my_rating = rating

    def _set_my_rating(self):
        """set my rating
        """
        # pre-read ratings of the recordset because I found a cache bug
        # if I replace ratings[ticket.id] with ticket.my_rating.id
        ratings = {t.id: t.my_rating.id for t in self}
        RATING = self.env['anytracker.rating']
        for ticket in self:
            RATING.create({
                'complexity_id': ratings[ticket.id],
                'ticket_id': ticket.id,
                'user_id': ticket.env.uid,
                'time': strftime('%Y-%m-%d %H:%M:%S')
            })

    @api.depends('rating_ids', 'my_rating', 'parent_id', 'child_ids')
    def _get_color(self):
        """get the color of the rating with highest risk
        """
        for ticket in self:
            colors = list((r.complexity_id.risk, r.complexity_id)
                          for r in ticket.sudo().rating_ids)
            if colors:
                ticket.color = list(reversed(sorted(colors)))[0][1].color
            else:
                ticket.color = 0

    def compute_risk_and_rating(self, ids):
        """compute the risk and rating of a leaf ticket,
        given all its individual ratings
        """
        # TODO: split risk and rating
        res_risk, res_rating = {}, {}
        for ticket in self.browse(ids):
            if ticket.type.has_children:  # not a leaf
                res_risk[ticket.id] = ticket.risk
                res_rating[ticket.id] = ticket.rating
                continue
            latest_person_risk, latest_person_rating = {}, {}
            # find latest risk and rating for each person
            for risk in sorted([(r.time, r.id, r.user_id, r.complexity_id.risk)
                                for r in ticket.rating_ids]):
                latest_person_risk[risk[2]] = risk[-1]
            for rating in sorted([(r.time, r.id, r.user_id,
                                   r.complexity_id.value)
                                  for r in ticket.rating_ids]):
                latest_person_rating[rating[2]] = rating[-1]
            # a rating or risk of False or None is skipped
            latest_person_rating = dict([
                r for r in latest_person_rating.items()
                if r[-1] not in (None, False)
            ])
            latest_person_risk = dict([
                r for r in latest_person_risk.items()
                if r[-1] not in (None, False)
            ])
            # compute the mean of all latest ratings
            res_risk[ticket.id] = (risk_mean(latest_person_risk.values())
                                   if latest_person_risk else 0.5)
            res_rating[ticket.id] = (sum(latest_person_rating.values()) /
                                     len(latest_person_rating)
                                     if latest_person_rating else 0)
        return res_risk, res_rating

    def recompute_subtickets(self):
        """recompute the overall risk and rating of the node, based on subtickets.
        And recompute sub-nodes as well
        """
        for ticket in self:
            if not ticket.type.has_children:
                risk, rating = self.compute_risk_and_rating(ticket.id)
                ticket.write({
                    'risk': risk[ticket.id],
                    'rating': rating[ticket.id]
                })
            else:
                leafs = self.search([('id', 'child_of', ticket.id),
                                     ('type.has_children', '=', False),
                                     ('id', '!=', ticket.id)])
                leafs.recompute_subtickets()

                subnodes = self.search([('id', 'child_of', ticket.id),
                                        ('type.has_children', '=', True),
                                        ('id', '!=', ticket.id)])
                for node in ticket + subnodes:
                    leafs = self.search([('id', 'child_of', node.id),
                                         ('type.has_children', '=', False),
                                         ('id', '!=', node.id)])
                    rating = sum(leaf.rating for leaf in leafs)
                    risk = risk_mean(leaf.risk for leaf in leafs)
                    node.write({'risk': risk, 'rating': rating})
        return True

    @api.multi
    def unlink(self):
        parent_ids = self.parent_id.ids
        for ticket in self:
            # check if the old parent had other children
            if len(ticket.parent_id.child_ids) == 1:
                ticket.parent_id.write({'rating': 0.0, 'risk': 0.5})
        super(Ticket, self).unlink()
        # recompute the remaining
        self.search([('id', 'in', parent_ids)]).recompute_parents()

    def write(self, values):
        """Climb the tree from the ticket to the root
        and recompute the risk of parents
        Unrated tickets have a risk of 0.5 and rating of 0.0!!
        """
        if 'my_rating' in values or 'parent_id' in values:
            old_values = [{
                'id': t.id,
                'parent_id': t.parent_id.id,
                'project_id': t.project_id.id
            } for t in self]
        res = super(Ticket, self).write(values)
        if 'my_rating' in values or 'parent_id' in values:
            # update the rating and risk (may be different for each ticket,
            # even if my_rating is the same)
            new_risk, new_rating = self.compute_risk_and_rating(self.ids)
            for ticket in self:
                super(Ticket, ticket).write({
                    'risk': new_risk[ticket.id],
                    'rating': new_rating[ticket.id]
                })
        # Propagate to the parents
        if 'my_rating' in values and 'parent_id' not in values:
            parents = self.browse(v['parent_id'] for v in old_values)
            parents.recompute_parents()
        elif values.get('parent_id'):
            # We reparented, we recompute the subnodes
            old_proj_ids = [v['project_id'] for v in old_values]
            new_proj_ids = self.browse(self.ids).project_id.ids
            all_projects = self.browse(list(set(old_proj_ids + new_proj_ids)))
            all_projects.recompute_subtickets()
        return res

    def create(self, values):
        """climb the tree up to the root and recompute
        """
        # ignore False or None ratings at creation in case the UI gives it
        if 'my_rating' in values and not values['my_rating']:
            values.pop('my_rating')
        ticket = super(Ticket, self).create(values)
        if values.get('my_rating'):
            new_risk, new_rating = self.compute_risk_and_rating([ticket.id])
            super(Ticket, ticket).write({
                'risk': new_risk[ticket.id],
                'rating': new_rating[ticket.id]
            })
        if values.get('parent_id'):
            self.browse(values.get('parent_id')).recompute_parents()
        return ticket

    def recompute_parents(self):
        """climb the tree starting from ids up to the root
        and recompute the risk and rating of each ticket.

        The overall rating is the sum of all the rating below.
        If we have 3 tickets with risks a, b, c,
        we compute the overall risk as: R3 = 1 - ((1-a)(1-b)-(1-c))^1/3
        """
        # ticket is the ticket that has been changed or reparented
        if not self:
            return
        for ticket in self:
            parent = ticket if ticket else None
            if not parent:
                continue
            # loop up to the root
            while parent:
                leafs = self.search([('id', 'child_of', parent.id),
                                     ('type.has_children', '=', False),
                                     ('id', '!=', parent.id)])
                if leafs:
                    rating = sum(leaf.rating for leaf in leafs)
                    risk = risk_mean(leaf.risk for leaf in leafs)
                    parent.write({'risk': risk, 'rating': rating})
                parent = parent.parent_id

    rating_ids = fields.One2many('anytracker.rating', 'ticket_id', 'Ratings')
    my_rating = fields.Many2one('anytracker.complexity',
                                compute=_get_my_rating,
                                inverse=_set_my_rating,
                                string="My Rating")
    risk = fields.Float('Risk', group_operator="avg", default=0.5)
    color = fields.Integer(compute=_get_color, string='Color')
    rating = fields.Float('Rating', group_operator="sum")
Exemplo n.º 25
0
class Milibro2(models.Model):
    _inherit = 'milibro'
    isbn = fields.Char('ISBN', size=15, required=True)
    preu = fields.Float('Preu', (3, 2))
    resum = fields.Text('Resum')
    data = fields.Date('Fecha')
Exemplo n.º 26
0
class ObservationComponent(models.Model):
    _name = "hc.observation.component"
    _description = "Observation Component"
    _inherit = ["hc.backbone.element"]

    observation_id = fields.Many2one(
        comodel_name="hc.res.observation",
        string="Observation",
        required="True",
        help="Observation associated with this Observation Component.")
    code = fields.Float(string="Code",
                        required="True",
                        help="Type of component observation (code / type).")
    value_type = fields.Selection(string="Component Value Type",
                                  selection=[("quantity", "Quantity"),
                                             ("code", "Code"),
                                             ("string", "String"),
                                             ("range", "Range"),
                                             ("ratio", "Ratio"),
                                             ("sampled_data", "Sampled Data"),
                                             ("attachment", "Attachment"),
                                             ("time", "Time"),
                                             ("date_time", "Date Time"),
                                             ("period", "Period")],
                                  help="Type of result.")
    value_name = fields.Char(string="Value",
                             compute="_compute_value_name",
                             help="Actual result.")
    value_quantity = fields.Float(string="Value Quantity",
                                  help="Quantity actual result.")
    value_quantity_uom_id = fields.Many2one(
        comodel_name="product.uom",
        string="Value Quantity UOM",
        help="Value quantity unit of measure.")
    value_code_id = fields.Many2one(
        comodel_name="hc.vs.observation.value.code",
        string="Value Code",
        help="Code of actual result.")
    value_string = fields.Char(string="Value", help="String of actual result.")
    value_range_low = fields.Float(string="Value Range Low",
                                   help="Low limit of actual result.")
    value_range_high = fields.Float(string="Value Range High",
                                    help="High limit of actual result.")
    value_numerator = fields.Float(string="Value Numerator",
                                   help="Numerator value of actual result.")
    value_numerator_uom_id = fields.Many2one(
        comodel_name="product.uom",
        string="Value Numerator UOM",
        help="Value numerator unit of measure.")
    value_denominator = fields.Float(
        string="Value Denominator", help="Denominator value of actual result.")
    value_denominator_uom_id = fields.Many2one(
        comodel_name="product.uom",
        string="Value Denominator UOM",
        help="Value denominator unit of measure.")
    value_ratio = fields.Float(string="Value Ratio",
                               compute="_compute_value_ratio",
                               store="True",
                               help="Ratio of actual result.")
    value_ratio_uom = fields.Char(string="Value Ratio UOM",
                                  compute="_compute_value_ratio_uom",
                                  store="True",
                                  help="Value Ratio unit of measure.")
    value_component = fields.Float(string="Value Component",
                                   compute="_compute_value_component",
                                   store="True",
                                   help="Actual result.")
    value_component_uom_id = fields.Many2one(
        comodel_name="product.uom",
        string="Value Component UOM",
        help="Actual result unit of measure.")
    value_sampled_data_id = fields.Many2one(
        comodel_name="hc.observation.component.value.sampled.data",
        string="Value Sampled Data",
        help="Sampled Data actual result.")
    value_attachment_id = fields.Many2one(
        comodel_name="hc.observation.component.value.attachment",
        string="Value Attachment",
        help="Attachment actual result.")
    value_time = fields.Char(string="Value Time", help="Time actual result.")
    value_date_time = fields.Datetime(string="Value Date Time",
                                      help="Date Time actual result.")
    value_start_date = fields.Datetime(string="Value Start Date",
                                       help="Start of the actual result.")
    value_end_date = fields.Datetime(string="Value End Date",
                                     help="End of the actual result.")
    is_data_absent = fields.Boolean(string="Data Absent",
                                    help="Result is missing?")
    data_absent_reason_id = fields.Many2one(
        comodel_name="hc.vs.observation.value.absent.reason",
        string="Data Absent Reason",
        help="Why the result is missing.")
    interpretation_id = fields.Many2one(
        comodel_name="hc.vs.observation.interpretation",
        string="Interpretation",
        help="High, low, normal, etc.")
    reference_range_ids = fields.One2many(
        comodel_name="hc.observation.reference.range",
        inverse_name="component_id",
        string="Reference Ranges",
        help="Provides guide for interpretation.")

    # Extension attribute
    modifier_extension_ids = fields.One2many(
        comodel_name="hc.observation.component.modifier.extension",
        inverse_name="component_id",
        string="Modifier Extensions",
        help="Extensions that cannot be ignored.")
    value_quantity_id = fields.Many2one(
        comodel_name="hc.observation.component.value.quantity",
        string="Value Quantity",
        required="True",
        help="Value Quantity associated with this Component.")

    @api.multi
    def _compute_value_name(self):
        for hc_observation_component in self:
            if hc_observation_component.value_type == 'quantity':
                hc_observation_component.value_name = str(
                    hc_observation_component.value_quantity)
            elif hc_observation_component.value_type == 'code':
                hc_observation_component.value_name = hc_observation_component.value_codeable_concept_id.name
            elif hc_observation_component.value_type == 'string':
                hc_observation_component.value_name = hc_observation_component.value_string
            elif hc_observation_component.value_type == 'range':
                hc_observation_component.value_name = "Between " + str(
                    hc_observation_component.value_range_low) + " and " + str(
                        hc_observation_component.value_range_high)
            elif hc_observation_component.value_type == 'ratio':
                hc_observation_component.value_name = str(
                    hc_observation_component.value_ratio) + " " + str(
                        hc_observation_component.value_ratio_uom)
            elif hc_observation_component.value_type == 'sampled_data':
                hc_observation_component.value_name = hc_observation_component.value_sampled_data_id.name
            elif hc_observation_component.value_type == 'attachment':
                hc_observation_component.value_name = hc_observation_component.value_attachment_id.name
            elif hc_observation_component.value_type == 'time':
                hc_observation_component.value_name = hc_observation_component.value_time
            elif hc_observation_component.value_type == 'date_time':
                hc_observation_component.value_name = str(
                    hc_observation_component.value_date_time)
            elif hc_observation_component.value_type == 'period':
                hc_observation_component.value_name = "Between " + str(
                    hc_observation_component.value_start_date) + " and " + str(
                        hc_observation_component.value_end_date)
class ImLivechatReportChannel(models.Model):
    """ Livechat Support Report on the Channels """

    _name = "im_livechat.report.channel"
    _description = "Livechat Support Report"
    _order = 'start_date, technical_name'
    _auto = False

    uuid = fields.Char('UUID', readonly=True)
    channel_id = fields.Many2one('mail.channel', 'Conversation', readonly=True)
    channel_name = fields.Char('Channel Name', readonly=True)
    technical_name = fields.Char('Code', readonly=True)
    livechat_channel_id = fields.Many2one('im_livechat.channel',
                                          'Channel',
                                          readonly=True)
    start_date = fields.Datetime('Start Date of session',
                                 readonly=True,
                                 help="Start date of the conversation")
    start_date_hour = fields.Char('Hour of start Date of session',
                                  readonly=True)
    duration = fields.Float('Average duration',
                            digits=(16, 2),
                            readonly=True,
                            group_operator="avg",
                            help="Duration of the conversation (in seconds)")
    nbr_speaker = fields.Integer('# of speakers',
                                 readonly=True,
                                 group_operator="avg",
                                 help="Number of different speakers")
    nbr_message = fields.Integer('Average message',
                                 readonly=True,
                                 group_operator="avg",
                                 help="Number of message in the conversation")
    partner_id = fields.Many2one('res.partner', 'Operator', readonly=True)

    def init(self, cr):
        # 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(cr, 'im_livechat_report_channel')
        cr.execute("""
            CREATE OR REPLACE VIEW im_livechat_report_channel AS (
                SELECT
                    C.id as id,
                    C.uuid as uuid,
                    C.id as channel_id,
                    C.name as channel_name,
                    CONCAT(L.name, ' / ', C.id) as technical_name,
                    C.livechat_channel_id as livechat_channel_id,
                    C.create_date as start_date,
                    to_char(date_trunc('hour', C.create_date), 'YYYY-MM-DD HH24:MI:SS') as start_date_hour,
                    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,
                    count(distinct P.id) as nbr_speaker,
                    count(distinct M.id) as nbr_message,
                    MAX(S.partner_id) as partner_id
                FROM mail_channel C
                    JOIN mail_message_mail_channel_rel R ON (C.id = R.mail_channel_id)
                    JOIN mail_message M ON (M.id = R.mail_message_id)
                    JOIN mail_channel_partner S ON (S.channel_id = C.id)
                    JOIN im_livechat_channel L ON (L.id = C.livechat_channel_id)
                    LEFT JOIN res_partner P ON (M.author_id = P.id)
                GROUP BY C.id, C.name, C.livechat_channel_id, L.name, C.create_date, C.uuid
            )
        """)
Exemplo n.º 28
0
class Observation(models.Model):
    _name = "hc.res.observation"
    _description = "Observation"
    _inherit = ["hc.domain.resource"]
    _rec_name = "name"

    name = fields.Char(
        string="Event Name",
        required="True",
        help=
        "Text representation of the observation event. Subject Name + Code + Effective Date."
    )
    identifier_ids = fields.One2many(
        comodel_name="hc.observation.identifier",
        inverse_name="observation_id",
        string="Identifiers",
        help="Unique Id for this particular observation.")
    based_on_ids = fields.One2many(comodel_name="hc.observation.based.on",
                                   inverse_name="observation_id",
                                   string="Based On",
                                   help="Fulfills plan, proposal or order.")
    status = fields.Selection(string="Status",
                              selection=[("registered", "Registered"),
                                         ("preliminary", "Preliminary"),
                                         ("final", "Final"),
                                         ("amended", "Amended")],
                              help="The status of the result value.")
    category_ids = fields.Many2many(
        comodel_name="hc.vs.observation.category",
        string="Categories",
        help="Classification of type of observation.")
    code_id = fields.Many2one(comodel_name="hc.vs.observation.code",
                              string="Code",
                              required="True",
                              help="Type of observation (code / type).")
    subject_type = fields.Selection(
        string="Observation Subject Type",
        selection=[("patient", "Patient"), ("group", "Group"),
                   ("device", "Device"), ("location", "Location")],
        help="Type of who and/or what this is about.")
    subject_name = fields.Char(string="Subject",
                               compute="_compute_subject_name",
                               help="Who and/or what this is about.")
    subject_patient_id = fields.Many2one(
        comodel_name="hc.res.patient",
        string="Subject Patient",
        help="Patient who and/or what this is about.")
    subject_group_id = fields.Many2one(
        comodel_name="hc.res.group",
        string="Subject Group",
        help="Group who and/or what this is about.")
    subject_device_id = fields.Many2one(
        comodel_name="hc.res.device",
        string="Subject Device",
        help="Device who and/or what this is about.")
    subject_location_id = fields.Many2one(
        comodel_name="hc.res.location",
        string="Subject Location",
        help="Location who and/or what this is about.")
    context_type = fields.Selection(
        tring="Context Type",
        selection=[("encounter", "Encounter"),
                   ("episode_of_care", "Episode Of Care")],
        help="Healthcare event during which this observation is made.")
    context_name = fields.Char(
        string="Context",
        compute="_compute_context_name",
        store="True",
        help="Healthcare event during which this observation is made.")
    context_encounter_id = fields.Many2one(
        comodel_name="hc.res.encounter",
        string="Context Encounter",
        help="Encounter during which this observation is made.")
    context_episode_of_care_id = fields.Many2one(
        comodel_name="hc.res.episode.of.care",
        string="Context Episode Of Care",
        help="Episode Of Care during which this observation is made.")
    effective_type = fields.Selection(
        string="Effective Date Type",
        selection=[("date_time", "Datetime"), ("period", "Period")],
        help="Type of Clinically relevant time/time-period for observation.")
    effective_name = fields.Char(string="Effective Date",
                                 compute="_compute_effective_name",
                                 help="Clinically relevant time/time.")
    effective_date_time = fields.Datetime(
        string="Effective Datetime",
        help="Date time clinically relevant time/time-period for observation.")
    effective_start_date = fields.Datetime(
        string="Effective Start Date",
        help=
        "Start of the clinically relevant time/time-period for observation.")
    effective_end_date = fields.Datetime(
        string="Effective End Date",
        help="End of the clinically relevant time/time-period for observation."
    )
    issued_date = fields.Datetime(string="Issued Date Date",
                                  help="Date/Time this was made available.")
    performer_ids = fields.One2many(
        comodel_name="hc.observation.performer",
        inverse_name="observation_id",
        string="Performers",
        help="Who is responsible for the observation.")
    value_type = fields.Selection(string="Observation Value Type",
                                  selection=[("quantity", "Quantity"),
                                             ("code", "Code"),
                                             ("string", "String"),
                                             ("range", "Range"),
                                             ("ratio", "Ratio"),
                                             ("sampled_data", "Sampled Data"),
                                             ("attachment", "Attachment"),
                                             ("time", "Time"),
                                             ("date_time", "Date Time"),
                                             ("period", "Period")],
                                  help="Type of result.")
    value_name = fields.Char(string="Value",
                             compute="_compute_value_name",
                             help="Actual result.")
    value_quantity = fields.Float(string="Value Quantity",
                                  help="Quantity actual result.")
    value_quantity_uom_id = fields.Many2one(
        comodel_name="product.uom",
        string="Value Quantity UOM",
        help="Value quantity unit of measure.")
    value_code_id = fields.Many2one(
        comodel_name="hc.vs.observation.value.code",
        string="Value Code",
        help="Code of actual result.")
    value_string = fields.Char(string="Value", help="String of actual result.")
    value_range_low = fields.Float(string="Value Range Low",
                                   help="Low limit of actual result.")
    value_range_high = fields.Float(string="Value Range High",
                                    help="High limit of actual result.")
    value_ratio_numerator = fields.Float(
        string="Value Ratio Numerator",
        help="Numerator value of actual result.")
    value_ratio_numerator_uom_id = fields.Many2one(
        comodel_name="product.uom",
        string="Value Ratio Numerator UOM",
        help="Value numerator unit of measure.")
    value_ratio_denominator = fields.Float(
        string="Value Ratio Denominator",
        help="Denominator value of actual result.")
    value_ratio_denominator_uom_id = fields.Many2one(
        comodel_name="product.uom",
        string="Value Ratio Denominator UOM",
        help="Value denominator unit of measure.")
    value_ratio = fields.Float(string="Value Ratio",
                               compute="_compute_value_ratio",
                               store="True",
                               help="Ratio of actual result.")
    value_ratio_uom = fields.Char(string="Value Ratio UOM",
                                  compute="_compute_value_ratio_uom",
                                  store="True",
                                  help="Value Ratio unit of measure.")
    value_ratio_name = fields.Char(
        string="Value Ratio",
        compute="_compute_value_ratio_name",
        store="True",
        help="Numerator + Numerator UOM / Denominator + Denominator UOM.")
    value_sampled_data_id = fields.Many2one(
        comodel_name="hc.observation.value.sampled.data",
        string="Value Sampled Data",
        help="Sampled Data actual result.")
    value_attachment_id = fields.Many2one(
        comodel_name="hc.observation.value.attachment",
        string="Value Attachment",
        help="Attachment actual result.")
    value_time = fields.Char(string="Value Time", help="Time actual result.")
    value_date_time = fields.Datetime(string="Value Date Time",
                                      help="Date Time actual result.")
    value_start_date = fields.Datetime(string="Value Start Date",
                                       help="Start of the actual result.")
    value_end_date = fields.Datetime(string="Value End Date",
                                     help="End of the actual result.")
    is_data_absent = fields.Boolean(string="Data Absent",
                                    help="Result is missing?")
    data_absent_reason_id = fields.Many2one(
        comodel_name="hc.vs.observation.value.absent.reason",
        string="Data Absent Reason",
        help="Why the result is missing.")
    interpretation_id = fields.Many2one(
        comodel_name="hc.vs.observation.interpretation",
        string="Interpretation",
        help="High, low, normal, etc.")
    comment = fields.Text(string="Comment", help="Comments about result.")
    body_site_id = fields.Many2one(comodel_name="hc.vs.body.site",
                                   string="Body Site",
                                   help="Observed body part")
    method_id = fields.Many2one(comodel_name="hc.vs.observation.method",
                                string="Method",
                                help="How it was done.")
    specimen_id = fields.Many2one(comodel_name="hc.res.specimen",
                                  string="Specimen",
                                  help="Specimen used for this observation.")
    device_type = fields.Selection(string="Observation Device Type",
                                   selection=[("device", "Device"),
                                              ("device_metric",
                                               "Device Metric")],
                                   help="Type of device.")
    device_name = fields.Char(string="Device",
                              compute="_compute_device_name",
                              help="(Measurement) Device.")
    device_id = fields.Many2one(comodel_name="hc.res.device",
                                string="Device",
                                help="Device (measurement) device.")
    device_metric_id = fields.Many2one(
        comodel_name="hc.res.device.metric",
        string="Device Metric",
        help="Device Metric (measurement) device.")
    reference_range_ids = fields.One2many(
        comodel_name="hc.observation.reference.range",
        inverse_name="observation_id",
        string="Reference Ranges",
        help="Provides guide for interpretation.")
    related_ids = fields.One2many(
        comodel_name="hc.observation.related",
        inverse_name="observation_id",
        string="Related",
        help="Observations related to this observation.")
    component_ids = fields.One2many(comodel_name="hc.observation.component",
                                    inverse_name="observation_id",
                                    string="Components",
                                    help="Component results.")

    # Extension Attribute
    id = fields.Char(string="Id", help="Logical id of this artifact.")
    meta_id = fields.Many2one(comodel_name="hc.observation.meta",
                              string="Meta",
                              help="Metadata about the resource.")
    implicit_rules = fields.Char(
        string="Implicit Rules URI",
        help="A set of rules under which this content was created.")
    language_id = fields.Many2one(comodel_name="res.lang",
                                  string="Language",
                                  help="of the resource content.")
    text_id = fields.Many2one(
        comodel_name="hc.observation.text",
        string="Text",
        help="Text summary of the resource, for human interpretation.")
    contained_ids = fields.One2many(comodel_name="hc.observation.contained",
                                    inverse_name="observation_id",
                                    string="Contained",
                                    help="Contained, inline Resources.")
    modifier_extension_ids = fields.One2many(
        comodel_name="hc.observation.modifier.extension",
        inverse_name="observation_id",
        string="Modifier Extensions",
        help="Extensions that cannot be ignored.")

    # technical attribute
    has_value_ratio_numerator = fields.Boolean(
        string="Has Value Ratio Numerator",
        invisible=True,
        help=
        "Indicates if value_ratio_numerator exists. Used to enforce constraint value_ratio_numerator and value_ratio_denominator."
    )

    _sql_constraints = [
        ('value_ratio_numerator_gt_zero',
         'CHECK(value_ratio_numerator >= 0.0)',
         'Value Ratio Numerator SHALL be a non-negative value.'),
        ('value_ratio_denominator_gt_zero',
         'CHECK(value_ratio_denominator >= 0.0)',
         'Value Ratio Denominator SHALL be a non-negative value.')
    ]

    @api.multi
    def _compute_subject_name(self):
        for hc_res_observation in self:
            if hc_res_observation.subject_type == 'patient':
                hc_res_observation.subject_name = hc_res_observation.subject_patient_id.name
            elif hc_res_observation.subject_type == 'group':
                hc_res_observation.subject_name = hc_res_observation.subject_group_id.name
            elif hc_res_observation.subject_type == 'device':
                hc_res_observation.subject_name = hc_res_observation.subject_device_id.name
            elif hc_res_observation.subject_type == 'location':
                hc_res_observation.subject_name = hc_res_observation.subject_location_id.name

    @api.multi
    def _compute_effective_name(self):
        for hc_res_observation in self:
            if hc_res_observation.effective_type == 'date_time':
                hc_res_observation.effective_name = str(
                    hc_res_observation.effective_date_time)
            elif hc_res_observation.effective_type == 'period':
                hc_res_observation.effective_name = "Between " + str(
                    hc_res_observation.effective_start_date) + " and " + str(
                        hc_res_observation.effective_end_date)

    @api.multi
    def _compute_value_name(self):
        for hc_res_observation in self:
            if hc_res_observation.value_type == 'quantity':
                hc_res_observation.value_name = str(
                    hc_res_observation.value_quantity)
            elif hc_res_observation.value_type == 'code':
                hc_res_observation.value_name = hc_res_observation.value_codeable_concept_id.name
            elif hc_res_observation.value_type == 'string':
                hc_res_observation.value_name = hc_res_observation.value_string
            elif hc_res_observation.value_type == 'range':
                hc_res_observation.value_name = "Between " + str(
                    hc_res_observation.value_range_low) + " and " + str(
                        hc_res_observation.value_range_high)
            elif hc_res_observation.value_type == 'ratio':
                hc_res_observation.value_name = str(
                    hc_res_observation.value_ratio) + " " + str(
                        hc_res_observation_.value_ratio_uom)
            elif hc_res_observation.value_type == 'sampled_data':
                hc_res_observation.value_name = hc_res_observation.value_sampled_data_id.name
            elif hc_res_observation.value_type == 'attachment':
                hc_res_observation.value_name = hc_res_observation.value_attachment_id.name
            elif hc_res_observation.value_type == 'time':
                hc_res_observation.value_name = hc_res_observation.value_time
            elif hc_res_observation.value_type == 'date_time':
                hc_res_observation.value_name = str(
                    hc_res_observation.value_date_time)
            elif hc_res_observation.value_type == 'period':
                hc_res_observation.value_name = "Between " + str(
                    hc_res_observation.value_start_date) + " and " + str(
                        hc_res_observation.value_end_date)

    @api.multi
    def _compute_device_name(self):
        for hc_res_observation in self:
            if hc_res_observation.device_type == 'device':
                hc_res_observation.device_name = hc_res_observation.device_device_id.name
            elif hc_res_observation.device_type == 'device_metric':
                hc_res_observation.device_name = hc_res_observation.device_device_metric_id.name

    @api.onchange('value_ratio_numerator')
    def _onchange_value_ratio_numerator(self):
        if self.value_ratio_numerator:
            self.has_value_ratio_numerator = True
        else:
            self.has_value_ratio_numerator = False

    @api.depends('value_ratio_numerator', 'value_ratio_denominator')
    def _compute_value_ratio(self):
        if self.value_ratio_numerator and self.value_ratio_denominator:
            self.value_ratio = self.value_ratio_numerator / self.value_ratio_denominator

    @api.depends('value_ratio_numerator_uom_id',
                 'value_ratio_denominator_uom_id')
    def _compute_value_ratio_uom(self):
        value_ratio_uom = '/'
        if self.value_ratio_numerator_uom_id:
            value_ratio_uom = self.value_ratio_numerator_uom_id.code
        if self.value_ratio_denominator_uom_id:
            value_ratio_uom = value_ratio_uom + ' per ' + self.value_ratio_denominator_uom_id.code
        self.value_ratio_uom = value_ratio_uom

    @api.depends('value_ratio_numerator', 'value_ratio_denominator',
                 'value_ratio_numerator_uom_id',
                 'value_ratio_denominator_uom_id')
    def _compute_value_ratio_name(self):
        value_ratio_name = '/'
        if self.value_ratio_numerator and self.value_ratio_denominator:
            self.value_ratio_name = str(
                self.value_ratio_numerator) + ' ' + str(
                    self.value_ratio_numerator_uom_id.code) + '/' + str(
                        self.value_ratio_denominator) + ' ' + str(
                            self.value_ratio_denominator_uom_id.code)
Exemplo n.º 29
0
class AccountInvoice(models.Model):
    _inherit = "account.invoice"

    amount_expense_request = fields.Float(
        string='Expense Request Amount',
        copy=False,
        readonly=True,
    )
    diff_expense_amount_flag = fields.Integer(
        string='Amount different from expense',
        compute='_compute_diff_expense_amount_flag',
        readonly=True,
        default=0,
        help="""
        * Flat = 0 when amount invoice = amount expense\n
        * Flag = 1 when amount invoice > amount expense.\n
        * Flag = -1 when amount invoice < amount expense.
        """)
    diff_expense_amount_reason = fields.Char(
        string='Amount Diff Reason',
        readonly=True,
        states={'draft': [('readonly', False)]},
        help="Reason when amount is different from Expense",
    )

    @api.multi
    @api.depends('amount_total')
    def _compute_diff_expense_amount_flag(self):
        for rec in self:
            if rec.expense_id:
                rec.diff_expense_amount_flag = 0
                clear_amount = sum([
                    x.price_subtotal < 0.0 and x.price_subtotal or 0.0
                    for x in rec.invoice_line
                ])
                amount = rec.amount_total - clear_amount
                rec.diff_expense_amount_flag = \
                    float_compare(amount, rec.amount_expense_request,
                                  precision_digits=1)

    @api.onchange('advance_expense_id')
    def _onchange_advance_expense_id(self):
        super(AccountInvoice, self)._onchange_advance_expense_id()
        if len(self.taxbranch_ids) == 1:
            self.taxbranch_id = self.taxbranch_ids[0].id

    @api.multi
    def confirm_paid(self):
        expenses = self.env['hr.expense.expense'].search([('invoice_id', 'in',
                                                           self._ids)])
        History = self.env['hr.expense.advance.due.history']
        Voucher = self.env['account.voucher']
        for expense in expenses:
            if not expense.is_employee_advance:
                continue
            date_due = False
            # Case 1) buy_product, date_due = date_value + 30 days
            if expense.advance_type == 'buy_product':
                move_ids = \
                    expense.invoice_id.payment_ids.mapped('move_id')._ids
                vouchers = Voucher.search([('move_id', 'in', move_ids)],
                                          order='date desc',
                                          limit=1)
                date_paid = vouchers[0].date_value
                date_due = (datetime.strptime(date_paid, '%Y-%m-%d') +
                            relativedelta(days=30))
            # Case 2) attend_seminar, date_due = arrive date + 30 days
            elif expense.advance_type == 'attend_seminar':
                date_back = expense.date_back
                date_due = (datetime.strptime(date_back, '%Y-%m-%d') +
                            relativedelta(days=30))
            else:
                raise ValidationError(
                    _('Can not calculate due date. '
                      'No Advance Type vs Due Date Rule'))
            if date_due:
                History.create({
                    'expense_id': expense.id,
                    'date_due': date_due.strftime('%Y-%m-%d'),
                })
        return super(AccountInvoice, self).confirm_paid()

    @api.multi
    def action_cancel(self):
        for invoice in self:
            if invoice.expense_id:
                expense = invoice.expense_id
                if expense.state == 'paid':
                    expense.signal_workflow('invoice_except')
                elif expense.state == 'done':
                    expense.signal_workflow('done_to_except')
        return super(AccountInvoice, self).action_cancel()

    @api.multi
    def action_move_create(self):
        result = super(AccountInvoice, self).action_move_create()
        for invoice in self:
            if invoice.diff_expense_amount_flag == 1:
                raise ValidationError(
                    _('New amount over expense is not allowed!'))
            if invoice.diff_expense_amount_flag == -1 and \
                    not invoice.diff_expense_amount_reason:
                raise ValidationError(
                    _('Total amount is changed from Expense Request Amount.\n'
                      'Please provide Amount Diff Reason'))
        return result
Exemplo n.º 30
0
class ContractType(models.Model):

    _name = 'contract.type'

    name = fields.Char()
    hours = fields.Float()