class SaleOrderLine(models.Model): _inherit = "sale.order.line" margin = fields.Float(compute='_product_margin', digits=dp.get_precision('Product Price'), store=True) purchase_price = fields.Float(string='Cost', digits=dp.get_precision('Product Price')) def _compute_margin(self, order_id, product_id, product_uom_id): frm_cur = self.env.user.company_id.currency_id to_cur = order_id.pricelist_id.currency_id purchase_price = product_id.standard_price if product_uom_id != product_id.uom_id: purchase_price = product_id.uom_id._compute_price(purchase_price, product_uom_id) ctx = self.env.context.copy() ctx['date'] = order_id.date_order price = frm_cur.with_context(ctx).compute(purchase_price, to_cur, round=False) return price @api.model def _get_purchase_price(self, pricelist, product, product_uom, date): frm_cur = self.env.user.company_id.currency_id to_cur = pricelist.currency_id purchase_price = product.standard_price if product_uom != product.uom_id: purchase_price = product.uom_id._compute_price(purchase_price, product_uom) ctx = self.env.context.copy() ctx['date'] = date price = frm_cur.with_context(ctx).compute(purchase_price, to_cur, round=False) return {'purchase_price': price} @api.onchange('product_id', 'product_uom') def product_id_change_margin(self): if not self.order_id.pricelist_id or not self.product_id or not self.product_uom: return self.purchase_price = self._compute_margin(self.order_id, self.product_id, self.product_uom) @api.model def create(self, vals): vals.update(self._prepare_add_missing_fields(vals)) # Calculation of the margin for programmatic creation of a SO line. It is therefore not # necessary to call product_id_change_margin manually if 'purchase_price' not in vals: order_id = self.env['sale.order'].browse(vals['order_id']) product_id = self.env['product.product'].browse(vals['product_id']) product_uom_id = self.env['product.uom'].browse(vals['product_uom']) vals['purchase_price'] = self._compute_margin(order_id, product_id, product_uom_id) return super(SaleOrderLine, self).create(vals) @api.depends('product_id', 'purchase_price', 'product_uom_qty', 'price_unit', 'price_subtotal') def _product_margin(self): for line in self: currency = line.order_id.pricelist_id.currency_id price = line.purchase_price if not price: from_cur = line.env.user.company_id.currency_id.with_context(date=line.order_id.date_order) price = from_cur.compute(line.product_id.standard_price, currency, round=False) line.margin = currency.round(line.price_subtotal - (price * line.product_uom_qty))
class ConverterTest(models.Model): _name = 'web_editor.converter.test' # disable translation export for those brilliant field labels and values _translate = False char = fields.Char() integer = fields.Integer() float = fields.Float() numeric = fields.Float(digits=(16, 2)) many2one = fields.Many2one('web_editor.converter.test.sub') binary = fields.Binary() date = fields.Date() datetime = fields.Datetime() selection = fields.Selection([ (1, "réponse A"), (2, "réponse B"), (3, "réponse C"), (4, "réponse <D>"), ]) selection_str = fields.Selection( [ ('A', "Qu'il n'est pas arrivé à Toronto"), ('B', "Qu'il était supposé arriver à Toronto"), ('C', "Qu'est-ce qu'il fout ce maudit pancake, tabernacle ?"), ('D', "La réponse D"), ], string=u"Lorsqu'un pancake prend l'avion à destination de Toronto et " u"qu'il fait une escale technique à St Claude, on dit:") html = fields.Html() text = fields.Text()
class Product(models.Model): _inherit = "product.product" website_price = fields.Float('Website price', compute='_website_price', digits=dp.get_precision('Product Price')) website_public_price = fields.Float('Website public price', compute='_website_price', digits=dp.get_precision('Product Price')) website_price_difference = fields.Boolean('Website price difference', compute='_website_price') def _website_price(self): qty = self._context.get('quantity', 1.0) partner = self.env.user.partner_id current_website = self.env['website'].get_current_website() pricelist = current_website.get_current_pricelist() company_id = current_website.company_id context = dict(self._context, pricelist=pricelist.id, partner=partner) self2 = self.with_context(context) if self._context != context else self ret = self.env.user.has_group('sale.group_show_price_subtotal') and 'total_excluded' or 'total_included' for p, p2 in pycompat.izip(self, self2): taxes = partner.property_account_position_id.map_tax(p.sudo().taxes_id.filtered(lambda x: x.company_id == company_id)) p.website_price = taxes.compute_all(p2.price, pricelist.currency_id, quantity=qty, product=p2, partner=partner)[ret] price_without_pricelist = taxes.compute_all(p.list_price, pricelist.currency_id)[ret] p.website_price_difference = False if float_is_zero(price_without_pricelist - p.website_price, precision_rounding=pricelist.currency_id.rounding) else True p.website_public_price = taxes.compute_all(p2.lst_price, quantity=qty, product=p2, partner=partner)[ret] @api.multi def website_publish_button(self): self.ensure_one() return self.product_tmpl_id.website_publish_button()
class HrContract(models.Model): """ Employee contract allows to add different values in fields. Fields are used in salary rule computation. """ _inherit = 'hr.contract' tds = fields.Float(string='TDS', digits=dp.get_precision('Payroll'), help='Amount for Tax Deduction at Source') driver_salay = fields.Boolean( string='Driver Salary', help='Check this box if you provide allowance for driver') medical_insurance = fields.Float( string='Medical Insurance', digits=dp.get_precision('Payroll'), help='Deduction towards company provided medical insurance') voluntary_provident_fund = fields.Float( string='Voluntary Provident Fund (%)', digits=dp.get_precision('Payroll'), help= 'VPF is a safe option wherein you can contribute more than the PF ceiling of 12% that has been mandated by the government and VPF computed as percentage(%)' ) house_rent_allowance_metro_nonmetro = fields.Float( string='House Rent Allowance (%)', digits=dp.get_precision('Payroll'), help= 'HRA is an allowance given by the employer to the employee for taking care of his rental or accommodation expenses for metro city it is 50% and for non metro 40%. \nHRA computed as percentage(%)' ) supplementary_allowance = fields.Float(string='Supplementary Allowance', digits=dp.get_precision('Payroll'))
class ResPartner(models.Model): _inherit = "res.partner" partner_latitude = fields.Float(string='Geo Latitude', digits=(16, 5)) partner_longitude = fields.Float(string='Geo Longitude', digits=(16, 5)) date_localization = fields.Date(string='Geolocation Date') @api.multi def geo_localize(self): # We need country names in English below for partner in self.with_context(lang='en_US'): result = geo_find( geo_query_address(street=partner.street, zip=partner.zip, city=partner.city, state=partner.state_id.name, country=partner.country_id.name)) if result is None: result = geo_find( geo_query_address(city=partner.city, state=partner.state_id.name, country=partner.country_id.name)) if result: partner.write({ 'partner_latitude': result[0], 'partner_longitude': result[1], 'date_localization': fields.Date.context_today(partner) }) return True
class RestaurantTable(models.Model): _name = 'restaurant.table' name = fields.Char('Table Name', required=True, help='An internal identification of a table') floor_id = fields.Many2one('restaurant.floor', string='Floor') shape = fields.Selection([('square', 'Square'), ('round', 'Round')], string='Shape', required=True, default='square') position_h = fields.Float('Horizontal Position', default=10, help="The table's horizontal position from the left side to the table's center, in pixels") position_v = fields.Float('Vertical Position', default=10, help="The table's vertical position from the top to the table's center, in pixels") width = fields.Float('Width', default=50, help="The table's width in pixels") height = fields.Float('Height', default=50, help="The table's height in pixels") seats = fields.Integer('Seats', default=1, help="The default number of customer served at this table.") color = fields.Char('Color', help="The table's color, expressed as a valid 'background' CSS property value") active = fields.Boolean('Active', default=True, help='If false, the table is deactivated and will not be available in the point of sale') @api.model def create_from_ui(self, table): """ create or modify a table from the point of sale UI. table contains the table's fields. If it contains an id, it will modify the existing table. It then returns the id of the table. """ if table.get('floor_id'): table['floor_id'] = table['floor_id'][0] table_id = table.pop('id', False) if table_id: self.browse(table_id).write(table) else: table_id = self.create(table).id return table_id
class ResConfigSettings(models.TransientModel): _inherit = 'res.config.settings' plafond_secu = fields.Float(related='company_id.plafond_secu', string="Plafond de la Securite Sociale") nombre_employes = fields.Integer(related='company_id.nombre_employes', string="Nombre d'employes") cotisation_prevoyance = fields.Float(related='company_id.cotisation_prevoyance', string='Cotisation Patronale Prevoyance') org_ss = fields.Char(related='company_id.org_ss', string="Organisme de securite sociale") conv_coll = fields.Char(related='company_id.conv_coll', string="Convention collective")
class HrContractAdvandageTemplate(models.Model): _name = 'hr.contract.advantage.template' _description = "Employee's Advantage on Contract" name = fields.Char('Name', required=True) code = fields.Char('Code', required=True) lower_bound = fields.Float('Lower Bound', help="Lower bound authorized by the employer for this advantage") upper_bound = fields.Float('Upper Bound', help="Upper bound authorized by the employer for this advantage") default_value = fields.Float('Default value for this advantage')
class PriceRule(models.Model): _name = "delivery.price.rule" _description = "Delivery Price Rules" _order = 'sequence, list_price, id' @api.depends('variable', 'operator', 'max_value', 'list_base_price', 'list_price', 'variable_factor') def _compute_name(self): for rule in self: name = 'if %s %s %s then' % (rule.variable, rule.operator, rule.max_value) if rule.list_base_price and not rule.list_price: name = '%s fixed price %s' % (name, rule.list_base_price) elif rule.list_price and not rule.list_base_price: name = '%s %s times %s' % (name, rule.list_price, rule.variable_factor) else: name = '%s fixed price %s plus %s times %s' % ( name, rule.list_base_price, rule.list_price, rule.variable_factor) rule.name = name name = fields.Char(compute='_compute_name') sequence = fields.Integer(required=True, default=10) carrier_id = fields.Many2one('delivery.carrier', 'Carrier', required=True, ondelete='cascade') variable = fields.Selection([('weight', 'Weight'), ('volume', 'Volume'), ('wv', 'Weight * Volume'), ('price', 'Price'), ('quantity', 'Quantity')], required=True, default='weight') operator = fields.Selection([('==', '='), ('<=', '<='), ('<', '<'), ('>=', '>='), ('>', '>')], required=True, default='<=') max_value = fields.Float('Maximum Value', required=True) list_base_price = fields.Float(string='Sale Base Price', digits=dp.get_precision('Product Price'), required=True, default=0.0) list_price = fields.Float('Sale Price', digits=dp.get_precision('Product Price'), required=True, default=0.0) variable_factor = fields.Selection([('weight', 'Weight'), ('volume', 'Volume'), ('wv', 'Weight * Volume'), ('price', 'Price'), ('quantity', 'Quantity')], 'Variable Factor', required=True, default='weight')
class SaleQuoteOption(models.Model): _name = "sale.quote.option" _description = "Quotation Option" template_id = fields.Many2one('sale.quote.template', 'Quotation Template Reference', ondelete='cascade', index=True, required=True) name = fields.Text('Description', required=True, translate=True) product_id = fields.Many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], required=True) layout_category_id = fields.Many2one('sale.layout_category', string='Section') website_description = fields.Html('Option Description', translate=html_translate, sanitize_attributes=False) price_unit = fields.Float('Unit Price', required=True, digits=dp.get_precision('Product Price')) discount = fields.Float('Discount (%)', digits=dp.get_precision('Discount')) uom_id = fields.Many2one('product.uom', 'Unit of Measure ', required=True) quantity = fields.Float('Quantity', required=True, digits=dp.get_precision('Product UoS'), default=1) @api.onchange('product_id') def _onchange_product_id(self): if not self.product_id: return product = self.product_id self.price_unit = product.list_price self.website_description = product.product_tmpl_id.quote_description self.name = product.name self.uom_id = product.uom_id domain = { 'uom_id': [('category_id', '=', self.product_id.uom_id.category_id.id)] } return {'domain': domain} @api.onchange('uom_id') def _onchange_product_uom(self): if not self.product_id: return if not self.uom_id: self.price_unit = 0.0 return if self.uom_id.id != self.product_id.uom_id.id: self.price_unit = self.product_id.uom_id._compute_price( self.price_unit, self.uom_id)
class ResCompany(models.Model): _inherit = 'res.company' plafond_secu = fields.Float(string='Plafond de la Securite Sociale', digits=dp.get_precision('Payroll')) nombre_employes = fields.Integer(string='Nombre d\'employes') cotisation_prevoyance = fields.Float( string='Cotisation Patronale Prevoyance', digits=dp.get_precision('Payroll')) org_ss = fields.Char(string='Organisme de securite sociale') conv_coll = fields.Char(string='Convention collective')
class Company(models.Model): _inherit = "res.company" l10n_ch_isr_preprinted_account = fields.Boolean( string='Preprinted account', compute='_compute_l10n_ch_isr', inverse='_set_l10n_ch_isr') l10n_ch_isr_preprinted_bank = fields.Boolean( string='Preprinted bank', compute='_compute_l10n_ch_isr', inverse='_set_l10n_ch_isr') l10n_ch_isr_print_bank_location = fields.Boolean( string='Print bank location', default=False, help= 'Boolean option field indicating whether or not the alternate layout (the one printing bank name and address) must be used when generating an ISR.' ) l10n_ch_isr_scan_line_left = fields.Float( string='Scan line horizontal offset (mm)', compute='_compute_l10n_ch_isr', inverse='_set_l10n_ch_isr') l10n_ch_isr_scan_line_top = fields.Float( string='Scan line vertical offset (mm)', compute='_compute_l10n_ch_isr', inverse='_set_l10n_ch_isr') def _compute_l10n_ch_isr(self): get_param = self.env['ir.config_parameter'].sudo().get_param for company in self: company.l10n_ch_isr_preprinted_account = bool( get_param('l10n_ch.isr_preprinted_account', default=False)) company.l10n_ch_isr_preprinted_bank = bool( get_param('l10n_ch.isr_preprinted_bank', default=False)) company.l10n_ch_isr_scan_line_top = float( get_param('l10n_ch.isr_scan_line_top', default=0)) company.l10n_ch_isr_scan_line_left = float( get_param('l10n_ch.isr_scan_line_left', default=0)) def _set_l10n_ch_isr(self): set_param = self.env['ir.config_parameter'].sudo().set_param for company in self: set_param("l10n_ch.isr_preprinted_account", company.l10n_ch_isr_preprinted_account) set_param("l10n_ch.isr_preprinted_bank", company.l10n_ch_isr_preprinted_bank) set_param("l10n_ch.isr_scan_line_top", company.l10n_ch_isr_scan_line_top) set_param("l10n_ch.isr_scan_line_left", company.l10n_ch_isr_scan_line_left)
class HrPayslipLine(models.Model): _name = 'hr.payslip.line' _inherit = 'hr.salary.rule' _description = 'Payslip Line' _order = 'contract_id, sequence' slip_id = fields.Many2one('hr.payslip', string='Pay Slip', required=True, ondelete='cascade') salary_rule_id = fields.Many2one('hr.salary.rule', string='Rule', required=True) employee_id = fields.Many2one('hr.employee', string='Employee', required=True) contract_id = fields.Many2one('hr.contract', string='Contract', required=True, index=True) rate = fields.Float(string='Rate (%)', digits=dp.get_precision('Payroll Rate'), default=100.0) amount = fields.Float(digits=dp.get_precision('Payroll')) quantity = fields.Float(digits=dp.get_precision('Payroll'), default=1.0) total = fields.Float(compute='_compute_total', string='Total', digits=dp.get_precision('Payroll'), store=True) @api.depends('quantity', 'amount', 'rate') def _compute_total(self): for line in self: line.total = float(line.quantity) * line.amount * line.rate / 100 @api.model def create(self, values): if 'employee_id' not in values or 'contract_id' not in values: payslip = self.env['hr.payslip'].browse(values.get('slip_id')) values['employee_id'] = values.get( 'employee_id') or payslip.employee_id.id values['contract_id'] = values.get( 'contract_id' ) or payslip.contract_id and payslip.contract_id.id if not values['contract_id']: raise UserError( _('You must set a contract to create a payslip line.')) return super(HrPayslipLine, self).create(values)
class PosConfig(models.Model): _inherit = 'pos.config' iface_discount = fields.Boolean( string='Order Discounts', help='Allow the cashier to give discounts on the whole order.') discount_pc = fields.Float(string='Discount Percentage', help='The default discount percentage') discount_product_id = fields.Many2one( 'product.product', string='Discount Product', domain="[('available_in_pos', '=', True), ('sale_ok', '=', True)]", help='The product used to model the discount.') @api.onchange('module_pos_discount') def _onchange_module_pos_discount(self): if self.module_pos_discount: self.discount_product_id = self.env.ref( 'point_of_sale.product_product_consumable', raise_if_not_found=False) if not self.discount_product_id or not self.discount_product_id.available_in_pos or not self.discount_product_id.sale_ok: domain = [('available_in_pos', '=', True), ('sale_ok', '=', True)] self.discount_product_id = self.env['product.product'].search( domain, limit=1) self.discount_pc = 10.0 else: self.discount_product_id = False self.discount_pc = 0.0
class HrPayrollAdviceLine(models.Model): ''' Bank Advice Lines ''' _name = 'hr.payroll.advice.line' _description = 'Bank Advice Lines' advice_id = fields.Many2one('hr.payroll.advice', string='Bank Advice') name = fields.Char('Bank Account No.', required=True) ifsc_code = fields.Char(string='IFSC Code') employee_id = fields.Many2one('hr.employee', string='Employee', required=True) bysal = fields.Float(string='By Salary', digits=dp.get_precision('Payroll')) debit_credit = fields.Char(string='C/D', default='C') company_id = fields.Many2one('res.company', related='advice_id.company_id', string='Company', store=True) ifsc = fields.Boolean(related='advice_id.neft', string='IFSC') @api.onchange('employee_id') def onchange_employee_id(self): self.name = self.employee_id.bank_account_id.acc_number self.ifsc_code = self.employee_id.bank_account_id.bank_bic or ''
class Company(models.Model): _inherit = 'res.company' po_lead = fields.Float( string='Purchase Lead Time', required=True, help="Margin of error for vendor lead times. When the system " "generates Purchase Orders for procuring products, " "they will be scheduled that many days earlier " "to cope with unexpected vendor delays.", default=0.0) po_lock = fields.Selection( [('edit', 'Allow to edit purchase orders'), ('lock', 'Confirmed purchase orders are not editable')], string="Purchase Order Modification", default="edit", help= 'Purchase Order Modification used when you want to purchase order editable after confirm' ) po_double_validation = fields.Selection( [('one_step', 'Confirm purchase orders in one step'), ('two_step', 'Get 2 levels of approvals to confirm a purchase order') ], string="Levels of Approvals", default='one_step', help="Provide a double validation mechanism for purchases") po_double_validation_amount = fields.Monetary( string='Double validation amount', default=5000, help="Minimum amount for which a double validation is required")
class MixedModel(models.Model): _name = 'test_new_api.mixed' number = fields.Float(digits=(10, 2), default=3.14) date = fields.Date() now = fields.Datetime(compute='_compute_now') lang = fields.Selection(string='Language', selection='_get_lang') reference = fields.Reference(string='Related Document', selection='_reference_models') comment1 = fields.Html(sanitize=False) comment2 = fields.Html(sanitize_attributes=True, strip_classes=False) comment3 = fields.Html(sanitize_attributes=True, strip_classes=True) comment4 = fields.Html(sanitize_attributes=True, strip_style=True) currency_id = fields.Many2one( 'res.currency', default=lambda self: self.env.ref('base.EUR')) amount = fields.Monetary() @api.one def _compute_now(self): # this is a non-stored computed field without dependencies self.now = fields.Datetime.now() @api.model def _get_lang(self): return self.env['res.lang'].get_installed() @api.model def _reference_models(self): models = self.env['ir.model'].sudo().search([('state', '!=', 'manual') ]) return [(model.model, model.name) for model in models if not model.model.startswith('ir.')]
class ResConfigSettings(models.TransientModel): _inherit = 'res.config.settings' inventory_availability = fields.Selection([ ('never', 'Sell regardless of inventory'), ('always', 'Show inventory on website and prevent sales if not enough stock'), ('threshold', 'Show inventory below a threshold and prevent sales if not enough stock' ), ('custom', 'Show product-specific notifications'), ], string='Inventory', default='never') available_threshold = fields.Float(string='Availability Threshold') @api.multi def set_values(self): super(ResConfigSettings, self).set_values() IrDefault = self.env['ir.default'].sudo() IrDefault.set('product.template', 'inventory_availability', self.inventory_availability) IrDefault.set( 'product.template', 'available_threshold', self.available_threshold if self.inventory_availability == 'threshold' else None) @api.model def get_values(self): res = super(ResConfigSettings, self).get_values() IrDefault = self.env['ir.default'].sudo() res.update(inventory_availability=IrDefault.get( 'product.template', 'inventory_availability') or 'never', available_threshold=IrDefault.get( 'product.template', 'available_threshold') or 5.0) return res
class StockMove(models.Model): _inherit = 'stock.move' def _default_uom(self): uom_categ_id = self.env.ref('product.product_uom_categ_kgm').id return self.env['product.uom'].search( [('category_id', '=', uom_categ_id), ('factor', '=', 1)], limit=1) weight = fields.Float(compute='_cal_move_weight', digits=dp.get_precision('Stock Weight'), store=True) weight_uom_id = fields.Many2one( 'product.uom', string='Weight Unit of Measure', required=True, readonly=True, help= "Unit of Measure (Unit of Measure) is the unit of measurement for Weight", default=_default_uom) @api.depends('product_id', 'product_uom_qty', 'product_uom') def _cal_move_weight(self): for move in self.filtered( lambda moves: moves.product_id.weight > 0.00): move.weight = (move.product_qty * move.product_id.weight) def _get_new_picking_values(self): vals = super(StockMove, self)._get_new_picking_values() vals['carrier_id'] = self.sale_line_id.order_id.carrier_id.id return vals
class AccountTaxTemplate(models.Model): """ Add fields used to define some brazilian taxes """ _inherit = 'account.tax.template' tax_discount = fields.Boolean(string='Discount this Tax in Prince', help="Mark it for (ICMS, PIS e etc.).") base_reduction = fields.Float(string='Redution', digits=0, required=True, help="Um percentual decimal em % entre 0-1.", default=0) amount_mva = fields.Float(string='MVA Percent', digits=0, required=True, help="Um percentual decimal em % entre 0-1.", default=0)
class LandedCostLine(models.Model): _name = 'stock.landed.cost.lines' _description = 'Stock Landed Cost Lines' name = fields.Char('Description') cost_id = fields.Many2one('stock.landed.cost', 'Landed Cost', required=True, ondelete='cascade') product_id = fields.Many2one('product.product', 'Product', required=True) price_unit = fields.Float('Cost', digits=dp.get_precision('Product Price'), required=True) split_method = fields.Selection(product.SPLIT_METHOD, string='Split Method', required=True) account_id = fields.Many2one('account.account', 'Account', domain=[('deprecated', '=', False)]) @api.onchange('product_id') def onchange_product_id(self): if not self.product_id: self.quantity = 0.0 self.name = self.product_id.name or '' self.split_method = self.product_id.split_method or 'equal' self.price_unit = self.product_id.standard_price or 0.0 self.account_id = self.product_id.property_account_expense_id.id or self.product_id.categ_id.property_account_expense_categ_id.id
class ResConfigSettings(models.TransientModel): _inherit = 'res.config.settings' po_lead = fields.Float(related='company_id.po_lead') use_po_lead = fields.Boolean( string="Security Lead Time for Purchase", oldname='default_new_po_lead', help= "Margin of error for vendor lead times. When the system generates Purchase Orders for reordering products,they will be scheduled that many days earlier to cope with unexpected vendor delays." ) @api.onchange('use_po_lead') def _onchange_use_po_lead(self): if not self.use_po_lead: self.po_lead = 0.0 def get_values(self): res = super(ResConfigSettings, self).get_values() res.update(use_po_lead=self.env['ir.config_parameter'].sudo(). get_param('purchase.use_po_lead')) return res def set_values(self): super(ResConfigSettings, self).set_values() self.env['ir.config_parameter'].sudo().set_param( 'purchase.use_po_lead', self.use_po_lead)
class PurchaseOrderLine(models.Model): _inherit = 'purchase.order.line' qty_received = fields.Float(compute='_compute_qty_received', string="Received Qty", store=True) def _compute_qty_received(self): super(PurchaseOrderLine, self)._compute_qty_received() for line in self.filtered(lambda x: x.move_ids and x.product_id.id not in x.move_ids.mapped('product_id').ids): bom = self.env['mrp.bom']._bom_find(product=line.product_id, company_id=line.company_id.id) if bom and bom.type == 'phantom': line.qty_received = line._get_bom_delivered(bom=bom) def _get_bom_delivered(self, bom=False): self.ensure_one() # In the case of a kit, we need to check if all components are shipped. Since the BOM might # have changed, we don't compute the quantities but verify the move state. if bom: bom_delivered = all( [move.state == 'done' for move in self.move_ids]) if bom_delivered: return self.product_qty else: return 0.0
class ResConfigSettings(models.TransientModel): _inherit = 'res.config.settings' security_lead = fields.Float(related='company_id.security_lead', string="Security Lead Time") group_route_so_lines = fields.Boolean("Order-Specific Routes", implied_group='sale_stock.group_route_so_lines') module_sale_order_dates = fields.Boolean("Delivery Date") group_display_incoterm = fields.Boolean("Incoterms", implied_group='sale_stock.group_display_incoterm') use_security_lead = fields.Boolean( string="Security Lead Time for Sales", oldname='default_new_security_lead', help="Margin of error for dates promised to customers. Products will be scheduled for delivery that many days earlier than the actual promised date, to cope with unexpected delays in the supply chain.") default_picking_policy = fields.Selection([ ('direct', 'Ship products as soon as available, with back orders'), ('one', 'Ship all products at once') ], "Shipping Management", default='direct', default_model="sale.order", required=True) @api.onchange('use_security_lead') def _onchange_use_security_lead(self): if not self.use_security_lead: self.security_lead = 0.0 def get_values(self): res = super(ResConfigSettings, self).get_values() res.update( use_security_lead=self.env['ir.config_parameter'].sudo().get_param('sale_stock.use_security_lead') ) return res def set_values(self): super(ResConfigSettings, self).set_values() self.env['ir.config_parameter'].sudo().set_param('sale_stock.use_security_lead', self.use_security_lead)
class FleetVehicleOdometer(models.Model): _name = 'fleet.vehicle.odometer' _description = 'Odometer log for a vehicle' _order = 'date desc' name = fields.Char(compute='_compute_vehicle_log_name', store=True) date = fields.Date(default=fields.Date.context_today) value = fields.Float('Odometer Value', group_operator="max") vehicle_id = fields.Many2one('fleet.vehicle', 'Vehicle', required=True) unit = fields.Selection(related='vehicle_id.odometer_unit', string="Unit", readonly=True) driver_id = fields.Many2one(related="vehicle_id.driver_id", string="Driver") @api.depends('vehicle_id', 'date') def _compute_vehicle_log_name(self): for record in self: name = record.vehicle_id.name if not name: name = record.date elif record.date: name += ' / ' + record.date record.name = name @api.onchange('vehicle_id') def _onchange_vehicle(self): if self.vehicle_id: self.unit = self.vehicle_id.odometer_unit
class ProductAttributevalue(models.Model): _name = "product.attribute.value" _order = 'sequence, attribute_id, id' name = fields.Char('Value', required=True, translate=True) sequence = fields.Integer('Sequence', help="Determine the display order") attribute_id = fields.Many2one('product.attribute', 'Attribute', ondelete='cascade', required=True) product_ids = fields.Many2many('product.product', string='Variants', readonly=True) price_extra = fields.Float( 'Attribute Price Extra', compute='_compute_price_extra', inverse='_set_price_extra', default=0.0, digits=dp.get_precision('Product Price'), help="Price Extra: Extra price for the variant with this attribute value on sale price. eg. 200 price extra, 1000 + 200 = 1200.") price_ids = fields.One2many('product.attribute.price', 'value_id', 'Attribute Prices', readonly=True) _sql_constraints = [ ('value_company_uniq', 'unique (name,attribute_id)', 'This attribute value already exists !') ] @api.one def _compute_price_extra(self): if self._context.get('active_id'): price = self.price_ids.filtered(lambda price: price.product_tmpl_id.id == self._context['active_id']) self.price_extra = price.price_extra else: self.price_extra = 0.0 def _set_price_extra(self): if not self._context.get('active_id'): return AttributePrice = self.env['product.attribute.price'] prices = AttributePrice.search([('value_id', 'in', self.ids), ('product_tmpl_id', '=', self._context['active_id'])]) updated = prices.mapped('value_id') if prices: prices.write({'price_extra': self.price_extra}) else: for value in self - updated: AttributePrice.create({ 'product_tmpl_id': self._context['active_id'], 'value_id': value.id, 'price_extra': self.price_extra, }) @api.multi def name_get(self): if not self._context.get('show_attribute', True): # TDE FIXME: not used return super(ProductAttributevalue, self).name_get() return [(value.id, "%s: %s" % (value.attribute_id.name, value.name)) for value in self] @api.multi def unlink(self): linked_products = self.env['product.product'].with_context(active_test=False).search([('attribute_value_ids', 'in', self.ids)]) if linked_products: raise UserError(_('The operation cannot be completed:\nYou are trying to delete an attribute value with a reference on a product variant.')) return super(ProductAttributevalue, self).unlink() @api.multi def _variant_name(self, variable_attributes): return ", ".join([v.name for v in self if v.attribute_id in variable_attributes])
class SaleReport(models.Model): _inherit = 'sale.report' margin = fields.Float('Margin') def _select(self): return super(SaleReport, self)._select( ) + ", SUM(l.margin / COALESCE(cr.rate, 1.0)) AS margin"
class ChooseDeliveryPackage(models.TransientModel): _name = 'choose.delivery.package' _description = 'Delivery Package Selection Wizard' stock_quant_package_id = fields.Many2one( 'stock.quant.package', string="Physical Package", default=lambda self: self._default_stock_quant_package_id()) delivery_packaging_id = fields.Many2one( 'product.packaging', default=lambda self: self._default_delivery_packaging_id()) shipping_weight = fields.Float( string='Shipping Weight', default=lambda self: self._default_shipping_weight()) def _default_stock_quant_package_id(self): if self.env.context.get('default_stock_quant_package_id'): return self.env['stock.quant.package'].browse( self.env.context['stock_quant_package_id']) def _default_delivery_packaging_id(self): res = None if self.env.context.get('default_delivery_packaging_id'): res = self.env['product.packaging'].browse( self.env.context['default_delivery_packaging_id']) if self.env.context.get('default_stock_quant_package_id'): stock_quant_package = self.env['stock.quant.package'].browse( self.env.context['default_stock_quant_package_id']) res = stock_quant_package.packaging_id return res def _default_shipping_weight(self): if self.env.context.get('default_stock_quant_package_id'): stock_quant_package = self.env['stock.quant.package'].browse( self.env.context['default_stock_quant_package_id']) return stock_quant_package.shipping_weight else: picking_id = self.env['stock.picking'].browse( self.env.context['active_id']) move_line_ids = [ po for po in picking_id.move_line_ids if po.qty_done > 0 and not po.result_package_id ] total_weight = sum( [po.qty_done * po.product_id.weight for po in move_line_ids]) return total_weight def put_in_pack(self): picking_id = self.env['stock.picking'].browse( self.env.context['active_id']) if not self.stock_quant_package_id: stock_quant_package = picking_id._put_in_pack() self.stock_quant_package_id = stock_quant_package # write shipping weight and product_packaging on 'stock_quant_package' if needed if self.delivery_packaging_id: self.stock_quant_package_id.packaging_id = self.delivery_packaging_id if self.shipping_weight: self.stock_quant_package_id.shipping_weight = self.shipping_weight
class ReturnPickingLine(models.TransientModel): _name = "stock.return.picking.line" _rec_name = 'product_id' product_id = fields.Many2one('product.product', string="Product", required=True, domain="[('id', '=', product_id)]") quantity = fields.Float("Quantity", digits=dp.get_precision('Product Unit of Measure'), required=True) uom_id = fields.Many2one('product.uom', string='Unit of Measure', related='move_id.product_uom') wizard_id = fields.Many2one('stock.return.picking', string="Wizard") move_id = fields.Many2one('stock.move', "Move")
class ProductTemplate(models.Model): _inherit = "product.template" bom_ids = fields.One2many('mrp.bom', 'product_tmpl_id', 'Bill of Materials') bom_count = fields.Integer('# Bill of Material', compute='_compute_bom_count') used_in_bom_count = fields.Integer('# of BoM Where is Used', compute='_compute_used_in_bom_count') mo_count = fields.Integer('# Manufacturing Orders', compute='_compute_mo_count') produce_delay = fields.Float( 'Manufacturing Lead Time', default=0.0, help= "Average delay in days to produce this product. In the case of multi-level BOM, the manufacturing lead times of the components will be added." ) def _compute_bom_count(self): read_group_res = self.env['mrp.bom'].read_group( [('product_tmpl_id', 'in', self.ids)], ['product_tmpl_id'], ['product_tmpl_id']) mapped_data = dict([(data['product_tmpl_id'][0], data['product_tmpl_id_count']) for data in read_group_res]) for product in self: product.bom_count = mapped_data.get(product.id, 0) @api.multi def _compute_used_in_bom_count(self): for template in self: template.used_in_bom_count = self.env['mrp.bom'].search_count([ ('bom_line_ids.product_id', 'in', template.product_variant_ids.ids) ]) @api.multi def action_used_in_bom(self): self.ensure_one() action = self.env.ref('mrp.mrp_bom_form_action').read()[0] action['domain'] = [('bom_line_ids.product_id', 'in', self.product_variant_ids.ids)] return action @api.one def _compute_mo_count(self): # TDE FIXME: directly use a read_group self.mo_count = sum( self.mapped('product_variant_ids').mapped('mo_count')) @api.multi def action_view_mos(self): product_ids = self.mapped('product_variant_ids').ids action = self.env.ref('mrp.act_product_mrp_production').read()[0] action['domain'] = [('product_id', 'in', product_ids)] action['context'] = {} return action