GoodERP
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
6.3KB

  1. # Copyright 2016 上海开阖软件有限公司 (http://www.osbzr.com)
  2. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  3. from odoo import api, fields, models, _
  4. from odoo.exceptions import UserError
  5. AVAILABLE_PRIORITIES = [
  6. ('0', 'E'),
  7. ('1', 'D'),
  8. ('2', 'C'),
  9. ('3', 'B'),
  10. ('4', 'A'),
  11. ]
  12. class Partner(models.Model):
  13. '''
  14. odoo 中 res.partner 被过度使用,导致很多针对客户的控制逻辑很难实现。
  15. GoodERP采用了全新的业务伙伴对象。
  16. c_category_id 非空 业务伙伴是客户。
  17. s_category_id 非空 业务伙伴是供应商。
  18. '''
  19. _name = 'partner'
  20. _description = '业务伙伴'
  21. _inherit = ['mail.thread', 'mail.activity.mixin']
  22. code = fields.Char('编号')
  23. name = fields.Char('名称', required=True,)
  24. main_mobile = fields.Char('主要联系方式', required=False,)
  25. main_address = fields.Char('注册地址 电话')
  26. priority = fields.Selection(AVAILABLE_PRIORITIES,
  27. '客户重要性', default='0')
  28. supp_priority = fields.Selection(AVAILABLE_PRIORITIES,
  29. '供应商重要性', default='0')
  30. c_category_id = fields.Many2one('core.category', '客户类别',
  31. ondelete='restrict',
  32. domain=[('type', '=', 'customer')])
  33. s_category_id = fields.Many2one('core.category', '供应商类别',
  34. ondelete='restrict',
  35. domain=[('type', '=', 'supplier')])
  36. receivable = fields.Float('应收余额', readonly=True,
  37. copy=False,
  38. digits='Amount')
  39. payable = fields.Float('应付余额', readonly=True,
  40. copy=False,
  41. digits='Amount')
  42. tax_num = fields.Char('税务登记号')
  43. tax_rate = fields.Float('税率(%)',
  44. help='业务伙伴税率')
  45. bank_name = fields.Char('开户行')
  46. bic = fields.Char('行号')
  47. bank_num = fields.Char('银行账号')
  48. credit_limit = fields.Float(
  49. string='信用额度',
  50. tracking=True,
  51. help='客户购买商品时,一般本次发货金额+客户应收余额要小于客户信用额度')
  52. recon_day = fields.Integer("对账日")
  53. active = fields.Boolean('启用', default=True)
  54. company_id = fields.Many2one(
  55. 'res.company',
  56. string='公司',
  57. change_default=True,
  58. default=lambda self: self.env.company)
  59. tag_ids = fields.Many2many(
  60. 'core.value',
  61. ondelete='restrict',
  62. string='标签',
  63. domain=[('type', '=', 'partner_tag')])
  64. channel_id = fields.Many2one(
  65. 'core.value',
  66. string='渠道',
  67. ondelete='restrict',
  68. domain=[('type', '=', 'channel')],
  69. context={'type': 'channel'})
  70. source = fields.Char('来源')
  71. note = fields.Text('备注')
  72. main_contact = fields.Char('主联系人')
  73. responsible_id = fields.Many2one(
  74. 'res.users',
  75. tracking=True,
  76. ondelete='cascade',
  77. string='负责人员')
  78. share_id = fields.Many2one('res.users',
  79. '共享人员')
  80. pay_method = fields.Many2one('pay.method',
  81. string='付款方式',
  82. tracking=True,
  83. ondelete='restrict')
  84. date_qualify = fields.Date('资质到期日期')
  85. days_qualify = fields.Float('资质到期天数',
  86. compute='compute_days_qualify',
  87. store=True,
  88. help='当天到资质到期日期的天数差',
  89. )
  90. _sql_constraints = [
  91. ('name_uniq', 'unique(name)', '业务伙伴不能重名')
  92. ]
  93. @api.constrains('name', 'c_category_id', 's_category_id')
  94. def _check_category_exists(self):
  95. # 客户 或 供应商 类别有一个必输
  96. if self.name and not self.s_category_id and not self.c_category_id:
  97. raise UserError('请选择类别')
  98. @api.model
  99. def name_search(self, name='', args=None, operator='ilike', limit=100):
  100. """
  101. 在many2one字段中支持按编号搜索
  102. """
  103. args = args or []
  104. if name:
  105. res_id = self.search([('code', '=', name)])
  106. if res_id:
  107. return [(record.id, record.display_name)
  108. for record in res_id]
  109. args.append(('code', 'ilike', name))
  110. partners = self.search(args)
  111. if partners:
  112. return [(record.id, record.display_name)
  113. for record in partners]
  114. else:
  115. args.remove(('code', 'ilike', name))
  116. return super(Partner, self).name_search(name=name,
  117. args=args,
  118. operator=operator,
  119. limit=limit)
  120. def write(self, vals):
  121. # 业务伙伴应收/应付余额不为0时,不允许取消对应的客户/供应商身份
  122. if 'c_category_id' in list(vals.keys()) and \
  123. self.c_category_id and not vals.get('c_category_id') \
  124. and self.receivable != 0:
  125. raise UserError('该客户应收余额不为0,不能取消客户类型')
  126. if 's_category_id' in list(vals.keys()) and \
  127. self.s_category_id and not vals.get('s_category_id') \
  128. and self.payable != 0:
  129. raise UserError('该供应商应付余额不为0,不能取消供应商类型')
  130. return super(Partner, self).write(vals)
  131. def copy(self, default=None):
  132. ''' 避免复制时名称重复 '''
  133. if default is None:
  134. default = {}
  135. if 'name' not in default:
  136. default.update(name=_('%s (copy)') % (self.name))
  137. return super().copy(default=default)
  138. @api.depends('date_qualify')
  139. def compute_days_qualify(self):
  140. for partner in self:
  141. """计算当天距离资质到期日期的天数"""
  142. day = 0
  143. if partner.date_qualify:
  144. day = (
  145. partner.date_qualify - fields.Date.context_today(self)
  146. ).days
  147. partner.days_qualify = day
上海开阖软件有限公司 沪ICP备12045867号-1