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.

438 lines
14 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. # Copyright (C) 2018 - TODAY, Pavlov Media
  2. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  3. from odoo import _, api, fields, models
  4. class Agreement(models.Model):
  5. _name = "agreement"
  6. _inherit = ["agreement", "mail.thread"]
  7. def _default_stage_id(self):
  8. return self.env.ref("agreement_legal.agreement_stage_new")
  9. # General
  10. name = fields.Char(string="Title", required=True)
  11. is_template = fields.Boolean(
  12. string="Is a Template?",
  13. default=False,
  14. copy=False,
  15. help="Make this agreement a template.",
  16. )
  17. version = fields.Integer(
  18. string="Version",
  19. default=1,
  20. copy=False,
  21. help="The versions are used to keep track of document history and "
  22. "previous versions can be referenced.",
  23. )
  24. revision = fields.Integer(
  25. string="Revision",
  26. default=0,
  27. copy=False,
  28. help="The revision will increase with every save event.",
  29. )
  30. description = fields.Text(
  31. string="Description",
  32. track_visibility="onchange",
  33. help="Description of the agreement",
  34. )
  35. dynamic_description = fields.Text(
  36. compute="_compute_dynamic_description",
  37. string="Dynamic Description",
  38. help="Compute dynamic description",
  39. )
  40. start_date = fields.Date(
  41. string="Start Date",
  42. track_visibility="onchange",
  43. help="When the agreement starts.",
  44. )
  45. end_date = fields.Date(
  46. string="End Date",
  47. track_visibility="onchange",
  48. help="When the agreement ends."
  49. )
  50. color = fields.Integer()
  51. active = fields.Boolean(
  52. string="Active",
  53. default=True,
  54. help="If unchecked, it will allow you to hide the agreement without "
  55. "removing it.",
  56. )
  57. company_signed_date = fields.Date(
  58. string="Signed on",
  59. track_visibility="onchange",
  60. help="Date the contract was signed by Company.",
  61. )
  62. partner_signed_date = fields.Date(
  63. string="Signed on",
  64. track_visibility="onchange",
  65. help="Date the contract was signed by the Partner.",
  66. )
  67. term = fields.Integer(
  68. string="Term (Months)",
  69. track_visibility="onchange",
  70. help="Number of months this agreement/contract is in effect with the "
  71. "partner.",
  72. )
  73. expiration_notice = fields.Integer(
  74. string="Exp. Notice (Days)",
  75. track_visibility="onchange",
  76. help="Number of Days before expiration to be notified.",
  77. )
  78. change_notice = fields.Integer(
  79. string="Change Notice (Days)",
  80. track_visibility="onchange",
  81. help="Number of Days to be notified before changes.",
  82. )
  83. special_terms = fields.Text(
  84. string="Special Terms",
  85. track_visibility="onchange",
  86. help="Any terms that you have agreed to and want to track on the "
  87. "agreement/contract.",
  88. )
  89. dynamic_special_terms = fields.Text(
  90. compute="_compute_dynamic_special_terms",
  91. string="Dynamic Special Terms",
  92. help="Compute dynamic special terms",
  93. )
  94. reference = fields.Char(
  95. string="Reference",
  96. copy=False,
  97. required=True,
  98. default=lambda self: _("New"),
  99. track_visibility="onchange",
  100. help="ID used for internal contract tracking.",
  101. )
  102. increase_type_id = fields.Many2one(
  103. "agreement.increasetype",
  104. string="Increase Type",
  105. track_visibility="onchange",
  106. help="The amount that certain rates may increase.",
  107. )
  108. termination_requested = fields.Date(
  109. string="Termination Requested Date",
  110. track_visibility="onchange",
  111. help="Date that a request for termination was received.",
  112. )
  113. termination_date = fields.Date(
  114. string="Termination Date",
  115. track_visibility="onchange",
  116. help="Date that the contract was terminated.",
  117. )
  118. reviewed_date = fields.Date(
  119. string="Reviewed Date",
  120. track_visibility="onchange")
  121. reviewed_user_id = fields.Many2one(
  122. "res.users",
  123. string="Reviewed By",
  124. track_visibility="onchange"
  125. )
  126. approved_date = fields.Date(
  127. string="Approved Date",
  128. track_visibility="onchange")
  129. approved_user_id = fields.Many2one(
  130. "res.users",
  131. string="Approved By",
  132. track_visibility="onchange"
  133. )
  134. currency_id = fields.Many2one(
  135. "res.currency",
  136. string="Currency")
  137. partner_id = fields.Many2one(
  138. "res.partner",
  139. string="Partner",
  140. copy=True,
  141. help="The customer or vendor this agreement is related to.",
  142. )
  143. company_partner_id = fields.Many2one(
  144. "res.partner",
  145. string="Company",
  146. copy=True,
  147. default=lambda self: self.env.user.company_id.partner_id,
  148. )
  149. partner_contact_id = fields.Many2one(
  150. "res.partner",
  151. string="Partner Contact",
  152. copy=True,
  153. help="The primary partner contact (If Applicable).",
  154. )
  155. partner_contact_phone = fields.Char(
  156. related="partner_contact_id.phone",
  157. string="Phone"
  158. )
  159. partner_contact_email = fields.Char(
  160. related="partner_contact_id.email",
  161. string="Email"
  162. )
  163. company_contact_id = fields.Many2one(
  164. "res.partner",
  165. string="Company Contact",
  166. copy=True,
  167. help="The primary contact in the company.",
  168. )
  169. company_contact_phone = fields.Char(
  170. related="company_contact_id.phone",
  171. string="Phone"
  172. )
  173. company_contact_email = fields.Char(
  174. related="company_contact_id.email",
  175. string="Email"
  176. )
  177. agreement_type_id = fields.Many2one(
  178. "agreement.type",
  179. string="Agreement Type",
  180. track_visibility="onchange",
  181. help="Select the type of agreement.",
  182. )
  183. agreement_subtype_id = fields.Many2one(
  184. "agreement.subtype",
  185. string="Agreement Sub-type",
  186. track_visibility="onchange",
  187. help="Select the sub-type of this agreement. Sub-Types are related to "
  188. "agreement types.",
  189. )
  190. product_ids = fields.Many2many(
  191. "product.template",
  192. string="Products & Services")
  193. payment_term_id = fields.Many2one(
  194. "account.payment.term",
  195. string="Payment Term",
  196. track_visibility="onchange",
  197. help="Terms of payments.",
  198. )
  199. assigned_user_id = fields.Many2one(
  200. "res.users",
  201. string="Assigned To",
  202. track_visibility="onchange",
  203. help="Select the user who manages this agreement.",
  204. )
  205. company_signed_user_id = fields.Many2one(
  206. "res.users",
  207. string="Signed By",
  208. track_visibility="onchange",
  209. help="The user at our company who authorized/signed the agreement or "
  210. "contract.",
  211. )
  212. partner_signed_user_id = fields.Many2one(
  213. "res.partner",
  214. string="Signed By",
  215. track_visibility="onchange",
  216. help="Contact on the account that signed the agreement/contract.",
  217. )
  218. parent_agreement_id = fields.Many2one(
  219. "agreement",
  220. string="Parent Agreement",
  221. help="Link this agreement to a parent agreement. For example if this "
  222. "agreement is an amendment to another agreement. This list will "
  223. "only show other agreements related to the same account.",
  224. )
  225. renewal_type_id = fields.Many2one(
  226. "agreement.renewaltype",
  227. string="Renewal Type",
  228. track_visibility="onchange",
  229. help="Describes what happens after the contract expires.",
  230. )
  231. recital_ids = fields.One2many(
  232. "agreement.recital",
  233. "agreement_id",
  234. string="Recitals",
  235. copy=True
  236. )
  237. sections_ids = fields.One2many(
  238. "agreement.section",
  239. "agreement_id",
  240. string="Sections",
  241. copy=True
  242. )
  243. clauses_ids = fields.One2many(
  244. "agreement.clause",
  245. "agreement_id",
  246. string="Clauses",
  247. copy=True
  248. )
  249. appendix_ids = fields.One2many(
  250. "agreement.appendix",
  251. "agreement_id",
  252. string="Appendices",
  253. copy=True
  254. )
  255. previous_version_agreements_ids = fields.One2many(
  256. "agreement",
  257. "parent_agreement_id",
  258. string="Child Agreements",
  259. copy=False,
  260. domain=[("active", "=", False)],
  261. )
  262. child_agreements_ids = fields.One2many(
  263. "agreement",
  264. "parent_agreement_id",
  265. string="Child Agreements",
  266. copy=False,
  267. domain=[("active", "=", True)],
  268. )
  269. line_ids = fields.One2many(
  270. "agreement.line",
  271. "agreement_id",
  272. string="Products/Services",
  273. copy=False
  274. )
  275. state = fields.Selection(
  276. [("draft", "Draft"),
  277. ("active", "Active"),
  278. ("inactive", "Inactive")],
  279. default="draft",
  280. track_visibility="always",
  281. )
  282. notification_address_id = fields.Many2one(
  283. "res.partner",
  284. string="Notification Address",
  285. help="The address to send notificaitons to, if different from "
  286. "customer address.(Address Type = Other)",
  287. )
  288. signed_contract_filename = fields.Char(string="Filename")
  289. signed_contract = fields.Binary(
  290. string="Signed Document",
  291. track_visibility="always")
  292. field_id = fields.Many2one(
  293. "ir.model.fields",
  294. string="Field",
  295. help="""Select target field from the related document model. If it is a
  296. relationship field you will be able to select a target field at the
  297. destination of the relationship.""",
  298. )
  299. sub_object_id = fields.Many2one(
  300. "ir.model",
  301. string="Sub-model",
  302. help="""When a relationship field is selected as first field, this
  303. field shows the document model the relationship goes to.""",
  304. )
  305. sub_model_object_field_id = fields.Many2one(
  306. "ir.model.fields",
  307. string="Sub-field",
  308. help="""When a relationship field is selected as first field, this
  309. field lets you select the target field within the destination document
  310. model (sub-model).""",
  311. )
  312. default_value = fields.Char(
  313. string="Default Value",
  314. help="Optional value to use if the target field is empty.",
  315. )
  316. copyvalue = fields.Char(
  317. string="Placeholder Expression",
  318. help="""Final placeholder expression, to be copy-pasted in the desired
  319. template field.""",
  320. )
  321. # compute the dynamic content for mako expression
  322. @api.multi
  323. def _compute_dynamic_description(self):
  324. MailTemplates = self.env["mail.template"]
  325. for agreement in self:
  326. lang = agreement.partner_id.lang or "en_US"
  327. description = MailTemplates.with_context(
  328. lang=lang)._render_template(
  329. agreement.description, "agreement", agreement.id
  330. )
  331. agreement.dynamic_description = description
  332. @api.multi
  333. def _compute_dynamic_special_terms(self):
  334. MailTemplates = self.env["mail.template"]
  335. for agreement in self:
  336. lang = agreement.partner_id.lang or "en_US"
  337. special_terms = MailTemplates.with_context(
  338. lang=lang)._render_template(
  339. agreement.special_terms, "agreement", agreement.id
  340. )
  341. agreement.dynamic_special_terms = special_terms
  342. @api.onchange("field_id", "sub_model_object_field_id", "default_value")
  343. def onchange_copyvalue(self):
  344. self.sub_object_id = False
  345. self.copyvalue = False
  346. self.sub_object_id = False
  347. if self.field_id and not self.field_id.relation:
  348. self.copyvalue = "${{object.{} or {}}}".format(
  349. self.field_id.name,
  350. self.default_value or "''",
  351. )
  352. self.sub_model_object_field_id = False
  353. if self.field_id and self.field_id.relation:
  354. self.sub_object_id = self.env["ir.model"].search(
  355. [("model", "=", self.field_id.relation)]
  356. )[0]
  357. if self.sub_model_object_field_id:
  358. self.copyvalue = "${{object.{}.{} or {}}}".format(
  359. self.field_id.name,
  360. self.sub_model_object_field_id.name,
  361. self.default_value or "''",
  362. )
  363. # Used for Kanban grouped_by view
  364. @api.model
  365. def _read_group_stage_ids(self, stages, domain, order):
  366. stage_ids = self.env["agreement.stage"].search([])
  367. return stage_ids
  368. stage_id = fields.Many2one(
  369. "agreement.stage",
  370. string="Stage",
  371. group_expand="_read_group_stage_ids",
  372. help="Select the current stage of the agreement.",
  373. track_visibility="onchange",
  374. index=True,
  375. # default=lambda self: self._default_stage_id(),
  376. )
  377. # Create New Version Button
  378. @api.multi
  379. def create_new_version(self, vals):
  380. for rec in self:
  381. if not rec.state == "draft":
  382. # Make sure status is draft
  383. rec.state = "draft"
  384. default_vals = {
  385. "name": "{} - OLD VERSION".format(rec.name),
  386. "active": False,
  387. "parent_agreement_id": rec.id,
  388. }
  389. # Make a current copy and mark it as old
  390. rec.copy(default=default_vals)
  391. # Increment the Version
  392. rec.version = rec.version + 1
  393. # Reset revision to 0 since it's a new version
  394. vals["revision"] = 0
  395. return super(Agreement, self).write(vals)
  396. def create_new_agreement(self):
  397. default_vals = {
  398. "name": "NEW",
  399. "active": True,
  400. "version": 1,
  401. "revision": 0,
  402. "state": "draft",
  403. }
  404. res = self.copy(default=default_vals)
  405. return {
  406. "res_model": "agreement",
  407. "type": "ir.actions.act_window",
  408. "view_mode": "form",
  409. "view_type": "form",
  410. "res_id": res.id,
  411. }
  412. @api.model
  413. def create(self, vals):
  414. if vals.get("reference", _("New")) == _("New"):
  415. vals["reference"] = self.env[
  416. "ir.sequence"].next_by_code("agreement") or _(
  417. "New"
  418. )
  419. return super(Agreement, self).create(vals)
  420. # Increments the revision on each save action
  421. @api.multi
  422. def write(self, vals):
  423. vals["revision"] = self.revision + 1
  424. return super(Agreement, self).write(vals)