note.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. # -*- coding: utf-8 -*-
  2. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  3. from odoo import api, fields, models, _
  4. from odoo.tools import html2plaintext
  5. from odoo.addons.web_editor.controllers.main import handle_history_divergence
  6. class Stage(models.Model):
  7. _name = "note.stage"
  8. _description = "Note Stage"
  9. _order = 'sequence'
  10. name = fields.Char('Stage Name', translate=True, required=True)
  11. sequence = fields.Integer(default=1)
  12. user_id = fields.Many2one('res.users', string='Owner', required=True, ondelete='cascade', default=lambda self: self.env.uid)
  13. fold = fields.Boolean('Folded by Default')
  14. class Tag(models.Model):
  15. _name = "note.tag"
  16. _description = "Note Tag"
  17. name = fields.Char('Tag Name', required=True, translate=True)
  18. color = fields.Integer('Color Index')
  19. _sql_constraints = [
  20. ('name_uniq', 'unique (name)', "Tag name already exists !"),
  21. ]
  22. class Note(models.Model):
  23. _name = 'note.note'
  24. _inherit = ['mail.thread', 'mail.activity.mixin']
  25. _description = "Note"
  26. _order = 'sequence, id desc'
  27. def _get_default_stage_id(self):
  28. return self.env['note.stage'].search([('user_id', '=', self.env.uid)], limit=1)
  29. name = fields.Text(
  30. compute='_compute_name', string='Note Summary', store=True, readonly=False)
  31. company_id = fields.Many2one('res.company')
  32. user_id = fields.Many2one('res.users', string='Owner', default=lambda self: self.env.uid)
  33. memo = fields.Html('Note Content')
  34. sequence = fields.Integer('Sequence', default=0)
  35. stage_id = fields.Many2one('note.stage', compute='_compute_stage_id',
  36. inverse='_inverse_stage_id', string='Stage', default=_get_default_stage_id)
  37. stage_ids = fields.Many2many('note.stage', 'note_stage_rel', 'note_id', 'stage_id',
  38. string='Stages of Users', default=_get_default_stage_id)
  39. open = fields.Boolean(string='Active', default=True)
  40. date_done = fields.Date('Date done')
  41. color = fields.Integer(string='Color Index')
  42. tag_ids = fields.Many2many('note.tag', 'note_tags_rel', 'note_id', 'tag_id', string='Tags')
  43. # modifying property of ``mail.thread`` field
  44. message_partner_ids = fields.Many2many(compute_sudo=True)
  45. @api.depends('memo')
  46. def _compute_name(self):
  47. """ Read the first line of the memo to determine the note name """
  48. for note in self:
  49. if note.name:
  50. continue
  51. text = html2plaintext(note.memo) if note.memo else ''
  52. note.name = text.strip().replace('*', '').split("\n")[0]
  53. def _compute_stage_id(self):
  54. first_user_stage = self.env['note.stage'].search([('user_id', '=', self.env.uid)], limit=1)
  55. for note in self:
  56. for stage in note.stage_ids.filtered(lambda stage: stage.user_id == self.env.user):
  57. note.stage_id = stage
  58. # note without user's stage
  59. if not note.stage_id:
  60. note.stage_id = first_user_stage
  61. def _inverse_stage_id(self):
  62. for note in self.filtered('stage_id'):
  63. note.stage_ids = note.stage_id + note.stage_ids.filtered(lambda stage: stage.user_id != self.env.user)
  64. @api.model
  65. def name_create(self, name):
  66. return self.create({'memo': name}).name_get()[0]
  67. @api.model
  68. def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):
  69. if groupby and groupby[0] == "stage_id" and (len(groupby) == 1 or lazy):
  70. stages = self.env['note.stage'].search([('user_id', '=', self.env.uid)])
  71. if stages:
  72. # if the user has some stages
  73. result = []
  74. for stage in stages:
  75. # notes by stage for stages user
  76. nb_stage_counts = self.search_count(domain + [('stage_ids', '=', stage.id)])
  77. result.append({
  78. '__context': {'group_by': groupby[1:]},
  79. '__domain': domain + [('stage_ids.id', '=', stage.id)],
  80. 'stage_id': (stage.id, stage.name),
  81. 'stage_id_count': nb_stage_counts,
  82. '__count': nb_stage_counts,
  83. '__fold': stage.fold,
  84. })
  85. # note without user's stage
  86. nb_notes_ws = self.search_count(domain + [('stage_ids', 'not in', stages.ids)])
  87. if nb_notes_ws:
  88. # add note to the first column if it's the first stage
  89. dom_not_in = ('stage_ids', 'not in', stages.ids)
  90. if result and result[0]['stage_id'][0] == stages[0].id:
  91. dom_in = result[0]['__domain'].pop()
  92. result[0]['__domain'] = domain + ['|', dom_in, dom_not_in]
  93. result[0]['stage_id_count'] += nb_notes_ws
  94. result[0]['__count'] += nb_notes_ws
  95. else:
  96. # add the first stage column
  97. result = [{
  98. '__context': {'group_by': groupby[1:]},
  99. '__domain': domain + [dom_not_in],
  100. 'stage_id': (stages[0].id, stages[0].name),
  101. 'stage_id_count': nb_notes_ws,
  102. '__count': nb_notes_ws,
  103. '__fold': stages[0].name,
  104. }] + result
  105. else: # if stage_ids is empty, get note without user's stage
  106. nb_notes_ws = self.search_count(domain)
  107. if nb_notes_ws:
  108. result = [{ # notes for unknown stage
  109. '__context': {'group_by': groupby[1:]},
  110. '__domain': domain,
  111. 'stage_id': False,
  112. 'stage_id_count': nb_notes_ws,
  113. '__count': nb_notes_ws
  114. }]
  115. else:
  116. result = []
  117. return result
  118. return super(Note, self).read_group(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby, lazy=lazy)
  119. def action_close(self):
  120. return self.write({'open': False, 'date_done': fields.date.today()})
  121. def action_open(self):
  122. return self.write({'open': True})
  123. def write(self, vals):
  124. if len(self) == 1:
  125. handle_history_divergence(self, 'memo', vals)
  126. return super(Note, self).write(vals)