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.

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