|  | # Copyright 2016 上海开阖软件有限公司 (http://www.osbzr.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api
from odoo.exceptions import UserError
class Goods(models.Model):
    """
    继承了core里面定义的goods 模块,并定义了视图和添加字段。
    """
    _inherit = 'goods'
    def get_parent_tax_rate(self, parent_id):
        # 逐级取商品分类上的税率
        tax_rate = parent_id.tax_rate
        if not tax_rate and parent_id.parent_id:
            tax_rate = self.get_parent_tax_rate(parent_id.parent_id)
        return tax_rate
    def get_tax_rate(self, goods, partner, type):
        """
        获得税率
        如果商品上没有税率,则逐级取商品分类上的税率;
        商品税率和业务伙伴税率做比较:如果都存在,取小的;其中一个存在取该值;都不存在取公司上的进/销项税
        """
        if not goods:
            return
        goods_tax_rate, partner_tax_rate = False, False
        # 如果商品上没有税率,则取商品分类上的税率
        if goods.tax_rate:
            goods_tax_rate = goods.tax_rate
        elif goods.goods_class_id.tax_rate:
            goods_tax_rate = goods.goods_class_id.tax_rate
        elif goods.goods_class_id.parent_id:  # 逐级取商品分类上的税率
            goods_tax_rate = self.get_parent_tax_rate(
                goods.goods_class_id.parent_id)
        # 取业务伙伴税率
        if partner:
            partner_tax_rate = partner.tax_rate
        # 商品税率和业务伙伴税率做比较,并根据情况返回
        if goods_tax_rate and partner_tax_rate:
            if goods_tax_rate >= partner_tax_rate:
                return partner_tax_rate
            else:
                return goods_tax_rate
        elif goods_tax_rate and not partner_tax_rate:
            return goods_tax_rate
        elif not goods_tax_rate and partner_tax_rate:
            return partner_tax_rate
        else:
            if type == 'buy':
                return self.env.user.company_id.import_tax_rate
            elif type == 'sell':
                return self.env.user.company_id.output_tax_rate
    no_stock = fields.Boolean('虚拟商品')
    using_batch = fields.Boolean('管理批号')
    force_batch_one = fields.Boolean('管理序列号')
    attribute_ids = fields.One2many('attribute', 'goods_id', string='属性')
    image = fields.Binary('图片', attachment=True)
    supplier_id = fields.Many2one('partner',
                                  '默认供应商',
                                  ondelete='restrict',
                                  domain=[('s_category_id', '!=', False)])
    get_way = fields.Selection([
        ('self', '自制'),
        ('ous', '委外'),
        ('po', '采购'),
    ], default='po', string='获取方式')
    price = fields.Float('售价(不含税)')
    gpm = fields.Float('毛利率')
    barcode = fields.Char('条形码')
    note = fields.Text('备注')
    goods_class_id = fields.Many2one(
        'goods.class', string='商品分类',
        domain=[('type', '=', 'normal')])
    _sql_constraints = [
        ('barcode_uniq', 'unique(barcode)', '条形码不能重复'),
    ]
    @api.onchange('uom_id')
    def onchange_uom(self):
        """
        :return: 当选取单位时辅助单位默认和 单位相等。
        """
        self.uos_id = self.uom_id
    @api.onchange('gpm', 'cost')
    def onchange_gpm(self):
        """
        根据毛利率计算零售价
        """
        if self.gpm >= 1 or self.gpm < 0:
            raise UserError('毛利率请输入0%-100%之间的数值.')
        self.price = self.cost / (1 - self.gpm)
    @api.onchange('price', 'cost')
    def onchange_price(self):
        """
        根据零售价计算毛利率
        """
        if self.price > 0 and self.cost > 0:
            self.gpm = 1 - self.cost / self.price
    @api.onchange('using_batch')
    def onchange_using_batch(self):
        """
        :return: 当将管理批号的勾去掉后,自动将管理序列号的勾去掉
        """
        if not self.using_batch:
            self.force_batch_one = False
    def conversion_unit(self, qty):
        """ 数量 × 转化率 = 辅助数量
        :param qty: 传进来数量计算出辅助数量
        :return: 返回辅助数量
        """
        self.ensure_one()
        return self.conversion * qty
    def anti_conversion_unit(self, qty):
        """ 数量 = 辅助数量 / 转化率
        :param qty: 传入值为辅助数量
        :return: 数量
        """
        self.ensure_one()
        return self.conversion and qty / self.conversion or 0
class Attribute(models.Model):
    _name = 'attribute'
    _description = '属性'
    @api.depends('value_ids')
    def _compute_name(self):
        for a in self:
            a.name = ' '.join(
                [value.category_id.name + ':' + value.value_id.name for value in a.value_ids])
    @api.model
    def name_search(self, name='', args=None, operator='ilike', limit=100):
        '''在many2one字段中支持按条形码搜索'''
        args = args or []
        if name:
            attribute_ids = self.search([('ean', '=', name)])
            if attribute_ids:
                return attribute_ids.name_get()
        return super(Attribute, self).name_search(
            name=name, args=args, operator=operator, limit=limit)
    ean = fields.Char('条码')
    name = fields.Char('属性', compute='_compute_name',
                       store=True, readonly=True)
    goods_id = fields.Many2one('goods', '商品', ondelete='cascade')
    value_ids = fields.One2many(
        'attribute.value', 'attribute_id', string='属性值')
    company_id = fields.Many2one(
        'res.company',
        string='公司',
        change_default=True,
        default=lambda self: self.env.company)
    _sql_constraints = [
        ('ean_uniq', 'unique (ean)', '该条码已存在'),
        ('goods_attribute_uniq', 'unique (goods_id, name)', '该SKU已存在'),
    ]
    @api.constrains('value_ids')
    def check_value_ids(self):
        for a in self:
            att_dict = {}
            for line in a.value_ids:
                if line.category_id not in att_dict:
                    att_dict[line.category_id] = line.category_id
                else:
                    raise UserError('属性值的类别不能相同')
class AttributeValue(models.Model):
    _name = 'attribute.value'
    _rec_name = 'value_id'
    _description = '属性明细'
    attribute_id = fields.Many2one('attribute', '商品属性', ondelete='cascade')
    category_id = fields.Many2one('core.category', '属性',
                                  ondelete='cascade',
                                  domain=[('type', '=', 'attribute')],
                                  required=True)
    value_id = fields.Many2one('attribute.value.value', '值',
                               ondelete='restrict',
                               domain="[('category_id','=',category_id)]",
                               default=lambda self: self.env.context.get(
                                   'default_category_id'),
                               required=True)
    company_id = fields.Many2one(
        'res.company',
        string='公司',
        change_default=True,
        default=lambda self: self.env.company)
class AttributeValueValue(models.Model):
    _name = 'attribute.value.value'
    _description = '属性值'
    category_id = fields.Many2one('core.category', '属性',
                                  ondelete='cascade',
                                  domain=[('type', '=', 'attribute')],
                                  required=True)
    name = fields.Char('值', required=True)
    company_id = fields.Many2one(
        'res.company',
        string='公司',
        change_default=True,
        default=lambda self: self.env.company)
    _sql_constraints = [
        ('name_category_uniq', 'unique(category_id,name)', '同一属性的值不能重复')
    ]
 |