GoodERP
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

225 行
8.0KB

  1. # Copyright 2016 上海开阖软件有限公司 (http://www.osbzr.com)
  2. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  3. from odoo import models, fields, api
  4. from odoo.exceptions import UserError
  5. class Goods(models.Model):
  6. """
  7. 继承了core里面定义的goods 模块,并定义了视图和添加字段。
  8. """
  9. _inherit = 'goods'
  10. def get_parent_tax_rate(self, parent_id):
  11. # 逐级取商品分类上的税率
  12. tax_rate = parent_id.tax_rate
  13. if not tax_rate and parent_id.parent_id:
  14. tax_rate = self.get_parent_tax_rate(parent_id.parent_id)
  15. return tax_rate
  16. def get_tax_rate(self, goods, partner, type):
  17. """
  18. 获得税率
  19. 如果商品上没有税率,则逐级取商品分类上的税率;
  20. 商品税率和业务伙伴税率做比较:如果都存在,取小的;其中一个存在取该值;都不存在取公司上的进/销项税
  21. """
  22. if not goods:
  23. return
  24. goods_tax_rate, partner_tax_rate = False, False
  25. # 如果商品上没有税率,则取商品分类上的税率
  26. if goods.tax_rate:
  27. goods_tax_rate = goods.tax_rate
  28. elif goods.goods_class_id.tax_rate:
  29. goods_tax_rate = goods.goods_class_id.tax_rate
  30. elif goods.goods_class_id.parent_id: # 逐级取商品分类上的税率
  31. goods_tax_rate = self.get_parent_tax_rate(
  32. goods.goods_class_id.parent_id)
  33. # 取业务伙伴税率
  34. if partner:
  35. partner_tax_rate = partner.tax_rate
  36. # 商品税率和业务伙伴税率做比较,并根据情况返回
  37. if goods_tax_rate and partner_tax_rate:
  38. if goods_tax_rate >= partner_tax_rate:
  39. return partner_tax_rate
  40. else:
  41. return goods_tax_rate
  42. elif goods_tax_rate and not partner_tax_rate:
  43. return goods_tax_rate
  44. elif not goods_tax_rate and partner_tax_rate:
  45. return partner_tax_rate
  46. else:
  47. if type == 'buy':
  48. return self.env.user.company_id.import_tax_rate
  49. elif type == 'sell':
  50. return self.env.user.company_id.output_tax_rate
  51. no_stock = fields.Boolean('虚拟商品')
  52. using_batch = fields.Boolean('管理批号')
  53. force_batch_one = fields.Boolean('管理序列号')
  54. attribute_ids = fields.One2many('attribute', 'goods_id', string='属性')
  55. image = fields.Binary('图片', attachment=True)
  56. supplier_id = fields.Many2one('partner',
  57. '默认供应商',
  58. ondelete='restrict',
  59. domain=[('s_category_id', '!=', False)])
  60. get_way = fields.Selection([
  61. ('self', '自制'),
  62. ('ous', '委外'),
  63. ('po', '采购'),
  64. ], default='po', string='获取方式')
  65. price = fields.Float('售价(不含税)')
  66. gpm = fields.Float('毛利率')
  67. barcode = fields.Char('条形码')
  68. note = fields.Text('备注')
  69. goods_class_id = fields.Many2one(
  70. 'goods.class', string='商品分类',
  71. domain=[('type', '=', 'normal')])
  72. _sql_constraints = [
  73. ('barcode_uniq', 'unique(barcode)', '条形码不能重复'),
  74. ]
  75. @api.onchange('uom_id')
  76. def onchange_uom(self):
  77. """
  78. :return: 当选取单位时辅助单位默认和 单位相等。
  79. """
  80. self.uos_id = self.uom_id
  81. @api.onchange('gpm', 'cost')
  82. def onchange_gpm(self):
  83. """
  84. 根据毛利率计算零售价
  85. """
  86. if self.gpm >= 1 or self.gpm < 0:
  87. raise UserError('毛利率请输入0%-100%之间的数值.')
  88. self.price = self.cost / (1 - self.gpm)
  89. @api.onchange('price', 'cost')
  90. def onchange_price(self):
  91. """
  92. 根据零售价计算毛利率
  93. """
  94. if self.price > 0 and self.cost > 0:
  95. self.gpm = 1 - self.cost / self.price
  96. @api.onchange('using_batch')
  97. def onchange_using_batch(self):
  98. """
  99. :return: 当将管理批号的勾去掉后,自动将管理序列号的勾去掉
  100. """
  101. if not self.using_batch:
  102. self.force_batch_one = False
  103. def conversion_unit(self, qty):
  104. """ 数量 × 转化率 = 辅助数量
  105. :param qty: 传进来数量计算出辅助数量
  106. :return: 返回辅助数量
  107. """
  108. self.ensure_one()
  109. return self.conversion * qty
  110. def anti_conversion_unit(self, qty):
  111. """ 数量 = 辅助数量 / 转化率
  112. :param qty: 传入值为辅助数量
  113. :return: 数量
  114. """
  115. self.ensure_one()
  116. return self.conversion and qty / self.conversion or 0
  117. class Attribute(models.Model):
  118. _name = 'attribute'
  119. _description = '属性'
  120. @api.depends('value_ids')
  121. def _compute_name(self):
  122. for a in self:
  123. a.name = ' '.join(
  124. [value.category_id.name + ':' + value.value_id.name for value in a.value_ids])
  125. @api.model
  126. def name_search(self, name='', args=None, operator='ilike', limit=100):
  127. '''在many2one字段中支持按条形码搜索'''
  128. args = args or []
  129. if name:
  130. attribute_ids = self.search([('ean', '=', name)])
  131. if attribute_ids:
  132. return attribute_ids.name_get()
  133. return super(Attribute, self).name_search(
  134. name=name, args=args, operator=operator, limit=limit)
  135. ean = fields.Char('条码')
  136. name = fields.Char('属性', compute='_compute_name',
  137. store=True, readonly=True)
  138. goods_id = fields.Many2one('goods', '商品', ondelete='cascade')
  139. value_ids = fields.One2many(
  140. 'attribute.value', 'attribute_id', string='属性值')
  141. company_id = fields.Many2one(
  142. 'res.company',
  143. string='公司',
  144. change_default=True,
  145. default=lambda self: self.env.company)
  146. _sql_constraints = [
  147. ('ean_uniq', 'unique (ean)', '该条码已存在'),
  148. ('goods_attribute_uniq', 'unique (goods_id, name)', '该SKU已存在'),
  149. ]
  150. @api.constrains('value_ids')
  151. def check_value_ids(self):
  152. for a in self:
  153. att_dict = {}
  154. for line in a.value_ids:
  155. if line.category_id not in att_dict:
  156. att_dict[line.category_id] = line.category_id
  157. else:
  158. raise UserError('属性值的类别不能相同')
  159. class AttributeValue(models.Model):
  160. _name = 'attribute.value'
  161. _rec_name = 'value_id'
  162. _description = '属性明细'
  163. attribute_id = fields.Many2one('attribute', '商品属性', ondelete='cascade')
  164. category_id = fields.Many2one('core.category', '属性',
  165. ondelete='cascade',
  166. domain=[('type', '=', 'attribute')],
  167. required='1')
  168. value_id = fields.Many2one('attribute.value.value', '值',
  169. ondelete='restrict',
  170. domain="[('category_id','=',category_id)]",
  171. default=lambda self: self.env.context.get(
  172. 'default_category_id'),
  173. required='1')
  174. company_id = fields.Many2one(
  175. 'res.company',
  176. string='公司',
  177. change_default=True,
  178. default=lambda self: self.env.company)
  179. class AttributeValueValue(models.Model):
  180. _name = 'attribute.value.value'
  181. _description = '属性值'
  182. category_id = fields.Many2one('core.category', '属性',
  183. ondelete='cascade',
  184. domain=[('type', '=', 'attribute')],
  185. required='1')
  186. name = fields.Char('值', required=True)
  187. company_id = fields.Many2one(
  188. 'res.company',
  189. string='公司',
  190. change_default=True,
  191. default=lambda self: self.env.company)
  192. _sql_constraints = [
  193. ('name_category_uniq', 'unique(category_id,name)', '同一属性的值不能重复')
  194. ]
上海开阖软件有限公司 沪ICP备12045867号-1