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.

159 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. bank_num = fields.Char('银行账号')
  47. credit_limit = fields.Float(
  48. string='信用额度',
  49. tracking=True,
  50. help='客户购买商品时,一般本次发货金额+客户应收余额要小于客户信用额度')
  51. recon_day = fields.Integer("对账日")
  52. active = fields.Boolean('启用', default=True)
  53. company_id = fields.Many2one(
  54. 'res.company',
  55. string='公司',
  56. change_default=True,
  57. default=lambda self: self.env.company)
  58. tag_ids = fields.Many2many(
  59. 'core.value',
  60. ondelete='restrict',
  61. string='标签',
  62. domain=[('type', '=', 'partner_tag')])
  63. channel_id = fields.Many2one(
  64. 'core.value',
  65. string='渠道',
  66. ondelete='restrict',
  67. domain=[('type', '=', 'channel')],
  68. context={'type': 'channel'})
  69. source = fields.Char('来源')
  70. note = fields.Text('备注')
  71. main_contact = fields.Char('主联系人')
  72. responsible_id = fields.Many2one(
  73. 'res.users',
  74. tracking=True,
  75. ondelete='cascade',
  76. string='负责人员')
  77. share_id = fields.Many2one('res.users',
  78. '共享人员')
  79. pay_method = fields.Many2one('pay.method',
  80. string='付款方式',
  81. tracking=True,
  82. ondelete='restrict')
  83. date_qualify = fields.Date('资质到期日期')
  84. days_qualify = fields.Float('资质到期天数',
  85. compute='compute_days_qualify',
  86. store=True,
  87. help='当天到资质到期日期的天数差',
  88. )
  89. _sql_constraints = [
  90. ('name_uniq', 'unique(name)', '业务伙伴不能重名')
  91. ]
  92. @api.constrains('name', 'c_category_id', 's_category_id')
  93. def _check_category_exists(self):
  94. # 客户 或 供应商 类别有一个必输
  95. if self.name and not self.s_category_id and not self.c_category_id:
  96. raise UserError('请选择类别')
  97. @api.model
  98. def name_search(self, name='', args=None, operator='ilike', limit=100):
  99. """
  100. 在many2one字段中支持按编号搜索
  101. """
  102. args = args or []
  103. if name:
  104. res_id = self.search([('code', '=', name)])
  105. if res_id:
  106. return [(record.id, record.display_name)
  107. for record in res_id]
  108. args.append(('code', 'ilike', name))
  109. partners = self.search(args)
  110. if partners:
  111. return [(record.id, record.display_name)
  112. for record in partners]
  113. else:
  114. args.remove(('code', 'ilike', name))
  115. return super(Partner, self).name_search(name=name,
  116. args=args,
  117. operator=operator,
  118. limit=limit)
  119. def write(self, vals):
  120. # 业务伙伴应收/应付余额不为0时,不允许取消对应的客户/供应商身份
  121. if 'c_category_id' in list(vals.keys()) and \
  122. self.c_category_id and not vals.get('c_category_id') \
  123. and self.receivable != 0:
  124. raise UserError('该客户应收余额不为0,不能取消客户类型')
  125. if 's_category_id' in list(vals.keys()) and \
  126. self.s_category_id and not vals.get('s_category_id') \
  127. and self.payable != 0:
  128. raise UserError('该供应商应付余额不为0,不能取消供应商类型')
  129. return super(Partner, self).write(vals)
  130. def copy(self, default=None):
  131. ''' 避免复制时名称重复 '''
  132. if default is None:
  133. default = {}
  134. if 'name' not in default:
  135. default.update(name=_('%s (copy)') % (self.name))
  136. return super().copy(default=default)
  137. @api.depends('date_qualify')
  138. def compute_days_qualify(self):
  139. for partner in self:
  140. """计算当天距离资质到期日期的天数"""
  141. day = 0
  142. if partner.date_qualify:
  143. day = (
  144. partner.date_qualify - fields.Date.context_today(self)
  145. ).days
  146. partner.days_qualify = day
上海开阖软件有限公司 沪ICP备12045867号-1