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.

351 lines
12 KiB

  1. # -*- coding: utf-8 -*-
  2. from odoo import models, fields, api
  3. from odoo.osv.expression import OR
  4. from .ffck_structure_type import SCALES
  5. class ResPartner(models.Model):
  6. _inherit = "res.partner"
  7. _rec_names_search = ["display_name", "ref", "partner_code", "email"]
  8. # Partner fields
  9. ffck_network = fields.Boolean(string="FFCK network")
  10. first_membership_date = fields.Date("Structure 1st membership")
  11. # Structure typing
  12. partner_scale = fields.Selection(
  13. selection=SCALES,
  14. string="Scale",
  15. compute="_get_partner_scale",
  16. store=True,
  17. )
  18. ffck_structure_type_id = fields.Many2one(
  19. comodel_name="ffck.structure.type",
  20. string="Structure type",
  21. )
  22. partner_code = fields.Char(string="FFCK code", size=6, index=True)
  23. partner_code_editable = fields.Boolean(
  24. string="FFCK code editable", default=True, readonly=True
  25. )
  26. # FFCK
  27. ffck_partner_id = fields.Many2one(
  28. comodel_name="res.partner",
  29. string="FFCK partner",
  30. ondelete="restrict",
  31. compute="_get_ffck_partner",
  32. store=True,
  33. )
  34. ffck_partner_code = fields.Char(string="FFCK", default="0", readonly=True)
  35. # CRCK
  36. crck_partner_id = fields.Many2one(
  37. comodel_name="res.partner",
  38. string="CRCK partner",
  39. index=True,
  40. ondelete="restrict",
  41. compute="_get_crck_partner",
  42. store=True,
  43. )
  44. crck_partner_code = fields.Char(related="crck_partner_id.partner_code", store=True)
  45. # CDCK
  46. cdck_partner_id = fields.Many2one(
  47. comodel_name="res.partner",
  48. string="CDCK partner",
  49. index=True,
  50. ondelete="restrict",
  51. compute="_get_cdck_partner",
  52. store=True,
  53. )
  54. cdck_partner_code = fields.Char(related="cdck_partner_id.partner_code", store=True)
  55. local_partner_id = fields.Many2one(
  56. comodel_name="res.partner",
  57. string="Local partner",
  58. index=True,
  59. ondelete="restrict",
  60. domain=[("ffck_network", "=", True), ("partner_scale", "=", 4)],
  61. )
  62. local_partner_code = fields.Char(
  63. related="local_partner_id.partner_code", store=True
  64. )
  65. crck_partner_ids = fields.One2many(
  66. comodel_name="res.partner",
  67. inverse_name="ffck_partner_id",
  68. domain=[("partner_scale", "=", "2")],
  69. string="Regional Comittees",
  70. )
  71. cdck_partner_ids = fields.One2many(
  72. comodel_name="res.partner",
  73. inverse_name="crck_partner_id",
  74. domain=[("partner_scale", "=", "3")],
  75. string="Departmental Comittees",
  76. )
  77. local_partner_ids = fields.One2many(
  78. comodel_name="res.partner",
  79. inverse_name="cdck_partner_id",
  80. domain=[("partner_scale", "=", "4")],
  81. string="Local structures",
  82. )
  83. # Compute hierarchy for searchpanel TODO : move to standalone module
  84. hierarchy_id = fields.Many2one(
  85. comodel_name="res.partner.hierarchy",
  86. string="Hierarchy element",
  87. compute="_compute_partner_hierarchy",
  88. store=True,
  89. )
  90. @api.depends(
  91. "ffck_network",
  92. "partner_scale",
  93. "partner_code",
  94. "local_partner_id",
  95. "cdck_partner_id",
  96. "crck_partner_id",
  97. "ffck_partner_id",
  98. )
  99. def _compute_partner_hierarchy(self):
  100. for partner in self:
  101. partner.hierarchy_id = (
  102. partner.id
  103. if partner.ffck_network
  104. and int(partner.partner_scale) in range(1, 4)
  105. and partner.partner_code
  106. else partner.local_partner_id.id
  107. or partner.cdck_partner_id.id
  108. or partner.crck_partner_id.id
  109. or partner.ffck_partner_id.id
  110. )
  111. # COMPUTES
  112. @api.depends(
  113. "is_company",
  114. "ffck_network",
  115. "ffck_structure_type_id",
  116. "ffck_structure_type_id.scale",
  117. )
  118. def _get_partner_scale(self):
  119. ffck_partners = self.filtered("ffck_network")
  120. for partner in ffck_partners:
  121. if not partner.is_company:
  122. partner.partner_scale = "5"
  123. else:
  124. partner.partner_scale = (
  125. partner.ffck_structure_type_id.scale
  126. if partner.ffck_structure_type_id
  127. else False
  128. )
  129. for partner in self - ffck_partners:
  130. partner.partner_scale = False
  131. def lock_partner_code(self):
  132. self.write({"partner_code_editable": False})
  133. @api.depends("ffck_network")
  134. def _get_ffck_partner(self):
  135. ffck = self.env.ref("ffck_commons.res_partner_ffck", raise_if_not_found=False)
  136. main = self.env.ref("base.main_partner")
  137. for partner in self:
  138. if main.ref == "FFCK":
  139. if ffck and ffck.active:
  140. ffck.write({"active": False})
  141. partner.ffck_partner_id = main
  142. else:
  143. partner.ffck_partner_id = ffck
  144. @api.depends(
  145. "state_id",
  146. "ffck_network",
  147. "partner_scale",
  148. "cdck_partner_id",
  149. )
  150. def _get_crck_partner(self):
  151. cdck_ok = self.filtered("cdck_partner_id")
  152. for partner in cdck_ok:
  153. partner.crck_partner_id = partner.cdck_partner_id.crck_partner_id
  154. todo = self - cdck_ok
  155. if todo:
  156. states = todo.mapped("state_id")
  157. crck_ok = self.with_context(active_test=False).search(
  158. [
  159. ("ffck_network", "=", True),
  160. ("partner_scale", "=", "2"),
  161. ("state_id", "in", states.ids),
  162. ]
  163. )
  164. states_ok = states & crck_ok.mapped("state_id")
  165. crck_by_state = {crck.state_id: crck for crck in crck_ok}
  166. concerned = todo.filtered(
  167. lambda rp: rp.ffck_network
  168. and int(rp.partner_scale) >= 2
  169. and rp.state_id in states_ok
  170. )
  171. for partner in concerned:
  172. state = partner.state_id
  173. partner.crck_partner_id = crck_by_state[state]
  174. # treat unconcerned
  175. for partner in todo - concerned:
  176. partner.crck_partner_id = False
  177. @api.depends(
  178. "is_company",
  179. "ffck_network",
  180. "partner_code",
  181. "partner_scale",
  182. "local_partner_id",
  183. "local_partner_id",
  184. "local_partner_id.partner_code",
  185. "country_department_id",
  186. "country_department_id.code",
  187. )
  188. def _get_cdck_partner(self):
  189. local_ok = self.filtered("local_partner_id")
  190. for partner in local_ok:
  191. partner.cdck_partner_id = partner.local_partner_id.cdck_partner_id
  192. todo = self - local_ok
  193. if todo:
  194. structures = todo.filtered(
  195. lambda rp: rp.is_company
  196. and rp.ffck_network
  197. and rp.partner_code
  198. and len(rp.partner_code) >= 2
  199. and int(rp.partner_scale) in (3, 4)
  200. )
  201. licensees = todo.filtered(
  202. lambda rp: not rp.is_company
  203. and rp.ffck_network
  204. and int(rp.partner_scale) == 5
  205. and rp.country_department_id
  206. )
  207. dept_codes = todo.mapped(
  208. lambda rp: rp.ffck_network
  209. and (
  210. rp.is_company
  211. and rp.partner_code
  212. and len(rp.partner_code) >= 2
  213. and int(rp.partner_scale) in (3, 4)
  214. and rp.partner_code[:2]
  215. or not rp.is_company
  216. and rp.country_department_id
  217. and rp.country_department_id.code
  218. )
  219. )
  220. cdck_ok = self.with_context(active_test=False).search(
  221. [
  222. ("is_company", "=", True),
  223. ("ffck_network", "=", True),
  224. ("partner_scale", "=", "3"),
  225. (
  226. "partner_code",
  227. "in",
  228. ["{}00".format(code) for code in dept_codes],
  229. ),
  230. ]
  231. )
  232. cdck_by_code = {cdck.partner_code[:2]: cdck for cdck in cdck_ok}
  233. # Treat structures
  234. for partner in structures:
  235. partner.cdck_partner_id = cdck_by_code[partner.partner_code[:2]]
  236. # Treat licensees
  237. for partner in licensees:
  238. dept = partner.country_department_id
  239. local = partner.local_partner_id
  240. local_cd = local.cdck_partner_id
  241. partner.cdck_partner_id = (
  242. local_cd if local and local_cd else cdck_by_code[dept.code]
  243. )
  244. # treat others
  245. for partner in todo - (structures | licensees):
  246. partner.cdck_partner_id = False
  247. @api.depends(
  248. "ffck_network",
  249. "partner_scale",
  250. "ffck_partner_id",
  251. "crck_partner_id",
  252. "cdck_partner_id",
  253. "local_partner_id",
  254. )
  255. def _get_ffck_parent(self):
  256. field_by_scale = {
  257. "2": "ffck_partner_id",
  258. "3": "crck_partner_id",
  259. "4": "cdck_partner_id",
  260. "5": "local_partner_id",
  261. }
  262. for partner in self:
  263. if partner.ffck_network and int(partner.partner_scale) in range(2, 6):
  264. partner.ffck_parent_id = getattr(
  265. partner, field_by_scale[partner.partner_scale]
  266. )
  267. else:
  268. partner.ffck_parent_id = False
  269. # INHERITANCE
  270. # @api.model
  271. # def name_search(self, name="", args=None, operator="ilike", limit=100):
  272. # """Allow searching by sequence code by default."""
  273. # # Do not add any domain when user just clicked on search widget
  274. # if not (name == "" and operator == "ilike"):
  275. # # The dangling | is needed to combine with the domain added by super()
  276. # args = OR(
  277. # [
  278. # [
  279. # "&",
  280. # ("ffck_network", "=", True),
  281. # ("partner_code", "=like", name + "%"),
  282. # ],
  283. # args or [],
  284. # ]
  285. # )
  286. # return super().name_search(name, args, operator, limit)
  287. @api.depends(
  288. "is_company",
  289. "name",
  290. "parent_id.display_name",
  291. "type",
  292. "company_name",
  293. "commercial_company_name",
  294. "ref",
  295. "partner_code",
  296. )
  297. def _compute_display_name(self):
  298. return super()._compute_display_name()
  299. def name_get(self):
  300. res = []
  301. ffck_partners = self.filtered("ffck_network")
  302. others = self - ffck_partners
  303. for record in ffck_partners:
  304. code = record.partner_code
  305. ref = record.ref
  306. res.append(
  307. (
  308. record.id,
  309. "{}{}{}".format(
  310. code and code + " - " or "",
  311. ref and record.is_company and ref + " - " or "",
  312. super(ResPartner, record).name_get()[0][1],
  313. ),
  314. )
  315. )
  316. res += super(ResPartner, others).name_get()
  317. return res
  318. # ONCHANGES
  319. @api.onchange("partner_code", "company_type", "ffck_network")
  320. def onchange_partner_code(self):
  321. if self.ffck_network and self.is_company == False:
  322. code = self.partner_code or "000000"
  323. if len(code) < 6:
  324. self.update({"partner_code": code.zfill(6)})
  325. elif len(code) > 6:
  326. self.update({"partner_code": code[:-6]})
  327. # CRUD
  328. # @api.model_create_multi
  329. # def create(self, vals_list):
  330. # for vals in vals_list:
  331. # vals.update({"partner_code_editable": False})
  332. # return super().create(vals_list)