from odoo import fields, api, _, models from odoo.exceptions import UserError, ValidationError from datetime import datetime class FtpFeed(models.Model): _name = 'ftp.feed' _description = 'Social Feed Posts' _order = 'create_date desc' description = fields.Text(string='Post Content') images = fields.Many2many('ir.attachment', string='Post Images') user_id = fields.Many2one('res.users', default=lambda self: self.env.user, string='Author') employee_id = fields.Many2one('hr.employee', string='Employee', compute='_compute_employee', store=True) feed_data = fields.One2many('ftp.feed.data', 'feed_id', string='Reactions') feed_comments = fields.One2many('ftp.feed.comments', 'feed_id', string='Comments') like_count = fields.Integer(compute='_compute_like_count', string='Likes') comment_count = fields.Integer(compute='_compute_comment_count', string='Comments') post_time = fields.Char(compute='_compute_post_time', string='Posted') @api.depends('user_id') def _compute_employee(self): for record in self: employee = self.env['hr.employee'].search([('user_id', '=', record.user_id.id)], limit=1) record.employee_id = employee.id if employee else False @api.depends('feed_data.feed_type') def _compute_like_count(self): for record in self: record.like_count = len(record.feed_data.filtered(lambda x: x.feed_type == 'like')) @api.depends('feed_comments') def _compute_comment_count(self): for record in self: record.comment_count = len(record.feed_comments) @api.depends('create_date') def _compute_post_time(self): for record in self: if record.create_date: delta = datetime.now() - record.create_date if delta.days > 0: record.post_time = f"{delta.days}d ago" elif delta.seconds > 3600: record.post_time = f"{delta.seconds // 3600}h ago" elif delta.seconds > 60: record.post_time = f"{delta.seconds // 60}m ago" else: record.post_time = "Just now" else: record.post_time = "" @api.model def create(self, vals): vals['user_id'] = self.env.uid if not vals.get('images') and not vals.get('description'): raise ValidationError(_("Can't create an empty post")) # Handle images to ensure they are public if vals.get('images'): # images is a list of commands like [(6, 0, [id1, id2])] image_ids = [] for command in vals['images']: if command[0] == 6: # REPLACE command image_ids = command[2] elif command[0] in (4, 1): # LINK or CREATE command image_ids.append(command[1] if command[0] == 4 else command[0]) # Update all attachments to be public if image_ids: self.env['ir.attachment'].browse(image_ids).write({'public': True}) return super().create(vals) def write(self, vals): for record in self: if self.env.user != record.user_id: if 'description' in vals or 'images' in vals: raise UserError(_("Only the author can modify post content")) if vals.get('images'): # Get all new image IDs being added new_image_ids = [] for command in vals['images']: if command[0] == 6: # REPLACE command new_image_ids = command[2] elif command[0] in (4, 1): # LINK or CREATE command new_image_ids.append(command[1] if command[0] == 4 else command[0]) # Update all new attachments to be public if new_image_ids: self.env['ir.attachment'].browse(new_image_ids).write({'public': True}) return super().write(vals) def unlink(self): for record in self: if self.env.user != record.user_id: raise UserError(_("Only the author can delete this post")) return super().unlink() class FtpFeedData(models.Model): _name = 'ftp.feed.data' _description = 'Feed Reactions' feed_type = fields.Selection([ ('like', 'Like'), ('dislike', 'Dislike') ], default='like', required=True) user_id = fields.Many2one('res.users', default=lambda self: self.env.user, required=True) feed_id = fields.Many2one('ftp.feed', required=True, ondelete='cascade') _sql_constraints = [ ('unique_user_feed', 'unique(user_id, feed_id)', 'You can only react once per post!'), ] class FtpFeedComments(models.Model): _name = 'ftp.feed.comments' _description = 'Feed Comments' _order = 'create_date desc' feed_comment = fields.Text(string='Comment', required=True) user_id = fields.Many2one('res.users', default=lambda self: self.env.user, string='Author') employee_id = fields.Many2one('hr.employee', string='Employee', compute='_compute_employee', store=True) feed_id = fields.Many2one('ftp.feed', required=True, ondelete='cascade') comment_time = fields.Char(compute='_compute_comment_time', string='Commented') @api.depends('user_id') def _compute_employee(self): for record in self: employee = self.env['hr.employee'].search([('user_id', '=', record.user_id.id)], limit=1) record.employee_id = employee.id if employee else False @api.depends('create_date') def _compute_comment_time(self): for record in self: if record.create_date: delta = datetime.now() - record.create_date if delta.days > 0: record.comment_time = f"{delta.days}d ago" elif delta.seconds > 3600: record.comment_time = f"{delta.seconds // 3600}h ago" elif delta.seconds > 60: record.comment_time = f"{delta.seconds // 60}m ago" else: record.comment_time = "Just now" else: record.comment_time = ""