idg_letter.py 13.4 KB
from datetime import datetime, timedelta
from odoo import api, fields, models, _
import logging

_logger = logging.getLogger(__name__)



class IdgLetter(models.Model):
    _name = 'idg.letter'
    _description = 'E Office Master'
    _inherit = ['mail.thread', 'mail.activity.mixin']
    _sequence_field = "code"
    _sequence_date_field = "date"

    def _compute_attached_docs_count(self):
        Attachment = self.env['ir.attachment']
        for rec in self:
            rec.doc_count = Attachment.search_count([
                '&',
                ('res_model', '=', 'idg.letter'), ('res_id', '=', rec.id),
            ])

    def attachment_tree_view(self):
        action = self.env['ir.actions.act_window']._for_xml_id('base.action_attachment')
        action['domain'] = str([
            '&',
            ('res_model', '=', 'idg.letter'),
            ('res_id', 'in', self.ids),
        ])
        action['context'] = "{'default_res_model': '%s','default_res_id': %d}" % (self._name, self.id)
        return action

    category_id = fields.Many2one('idg.letter.category', required=True)
    code = fields.Char(index=True, string='Code', default="/")
    full_code = fields.Char(index=True, string='Full Code')
    name = fields.Char(index=True, string='Name', size=255, required=True)
    state = fields.Selection([('draft', 'Draft'),
                              ('pending', 'Pending'),
                              ('approved', 'Approved'),
                              ('refused', 'Refused'),
                              ('canceled', 'Canceled'),
                              ],
                             default='draft',
                             tracking=True,
                             )
    date = fields.Date(string="Date",
                       required=True,
                       index=True,
                       readonly=True,
                       # states={'draft': [('readonly', False)]},
                       copy=False,
                       default=fields.Date.context_today
                       )

    sender_id = fields.Many2one("res.partner")
    contact_id = fields.Many2one('res.partner',
                                 tracking=True,
                                 required=True, )
    typ = fields.Selection([('in', 'Surat Masuk'),
                            ('out', 'Surat Keluar'),
                            ], default='in')
    secrecy = fields.Selection([('B', 'Biasa'),
                                ('R', 'Rahasia'),
                                ('SR', 'Sangat Rahasia')],
                               default='B',
                               copy=False,
                               tracking=True,
                               string="Sifat") #kerahasiaan
    delivery_speed= fields.Selection([('B', 'Biasa'),
                                ('S', 'Segera'),
                                ('AS', 'Amat Segera')],
                               default='B',
                               copy=False,
                               tracking=True,
                                     string='Waktu Penyampaian') #penyampaian

    # department_id = fields.Many2one('hr.department', string="Department", default=)
    # def _compute_department_short(self):
    #     for rec in self:
    #         rec.department_short = rec.department_id.short_name
    #
    # department_short = fields.Char(compute="_compute_department_short", store=True)
    type_id = fields.Many2one('idg.letter.type', required=True, string="Type")


    description = fields.Text()
    need_feedback = fields.Boolean()
    deadline = fields.Date(string="Deadline",
                           copy=False,
                           )
    attachment_ids = fields.One2many('ir.attachment', compute='_compute_attachment_ids', string="Main Attachments",
                                     help="Attachment that don't come from message.")

    @api.onchange('need_feedback')
    def onchange_need_feedback(self):
        for rec in self:
            if not rec.need_feedback:
                rec.deadline = None
            else:
                if not rec.deadline:
                    rec.deadline = datetime.today().strftime('%Y-%m-%d')

    current_id = fields.Many2one('res.users', default=lambda self: self.env.user, tracking=True,
                                 required=True, )
    approver_ids = fields.One2many('idg.letter.approver', 'letter_id', string='Approver', copy=False)
    # comments = fields.One2many('idg.letter.comments', 'letter_id', string='Comments', copy=False)
    # docs = fields.One2many('idg.letter.docs', 'idg_letter_id', string='Docs', copy=False)
    parent_id = fields.Many2one('idg.letter', string='Parent')
    childs = fields.One2many('idg.letter', 'parent_id', string='Letter Lines')
    doc_count = fields.Integer(compute='_compute_attached_docs_count', string="Number of documents attached")

    def _compute_state(self):
        for rec in self:
            rec.all_state = rec.state
            if not rec.approver_ids:
                rec.all_state = rec.state
                return

            for appr in rec.approver_ids:
                if appr.state == 'draft':
                    rec.all_state = 'draft'
                    return

            for appr in rec.approver_ids:
                if appr.required and appr.state == 'canceled':
                    rec.all_state = 'canceled'
                    rec.state = 'canceled'
                    return

            for appr in rec.approver_ids:
                if appr.required and appr.state == 'refused':
                    rec.all_state = 'refused'
                    rec.state = 'refused'
                    return
            for appr in rec.approver_ids:
                if appr.user_id == self.env.user.id:
                    rec.all_state = appr.state
                    return

    all_state = fields.Char(compute='_compute_state')

    def _compute_user_state(self):
        for rec in self:
            rec.user_state = None
            if rec.state in ["refused", "canceled"]:
                rec.user_state = rec.state
                return

            for appr in rec.approver_ids:
                # Jika ada approval baru yang dibuat oleh user aktif maka wajib di submit
                if appr.create_uid.id == self.env.user.id and appr.state == 'draft':
                    rec.user_state = appr.state
                    return

            for appr in rec.approver_ids:
                if appr.user_id.id == self.env.user.id:
                    rec.user_state = appr.state

    user_state = fields.Selection([('draft', 'Draft'),
                                   ('pending', 'To Approve'),
                                   ('approved', 'Approved'),
                                   ('refused', 'Refused'),
                                   ('canceled', 'Canceled'), ],
                                  compute='_compute_user_state')

    def _get_employee_id(self):
        employee_rec = self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
        return employee_rec.id

    employee_id = fields.Many2one('hr.employee', string="Employee", default=_get_employee_id,
                                  required=True, read=['base.group_user'])

    # by default store = False this means the value of this field
    # is always computed.
    current_user = fields.Many2one('res.users', compute='_get_current_user')

    @api.depends()
    def _get_current_user(self):
        for rec in self:
            rec.current_user = self.env.user
        # i think this work too so you don't have to loop
        self.update({'current_user': self.env.user.id})

    def _set_default_approver(self, result):
        approver_lines = []
        employee = self.env['hr.employee'].search([('user_id', '=', result.create_uid.id)], limit=1)
        while employee and employee.parent_id.id:
            if employee.parent_id.id:
                employee = employee.parent_id
                if employee.user_id.id:
                    approver_lines.append((0, 0, {
                        'user_id': employee.user_id.id,
                        "required": True,
                        "state": "draft"}))
        categories = result.category_id.approver_ids
        for cat in categories:
            approver_lines.append((0, 0, {
                'user_id': cat.user_id.id,
                "required": True,
                "state": "pending"}))

        result.approver_ids = approver_lines

    def _get_last_sequence_domain(self, relaxed=False):
        #todo: update disini
        #category type
        """Get the sql domain to retreive the previous sequence number.

        This function should be overriden by models heriting from this mixin.

        :param relaxed: see _get_last_sequence.

        :returns: tuple(where_string, where_params): with
            where_string: the entire SQL WHERE clause as a string.
            where_params: a dictionary containing the parameters to substitute
                at the execution of the query.
        """
        self.ensure_one()
        return "", {}

    def _get_starting_sequence(self):
        # todo: update disini
        """Get a default sequence number.

        This function should be overriden by models heriting from this mixin
        This number will be incremented so you probably want to start the sequence at 0.

        :return: string to use as the default sequence to increment
        """
        self.ensure_one()
        return "00000000"

    @api.model_create_multi
    def create(self, vals):
        result = super(IdgLetter, self).create(vals)
        if result.typ == 'in':
            employee_rec = self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
            department = employee_rec.department_id
            while department:
                parent = department.parent_id
                if not parent:
                    result.approver_ids = [(0, 0, {
                        'user_id': department.manager_id.user_id.id,
                        "required": True,
                        "state": "pending"})]
                department = parent
        else:
            self._set_default_approver(result)
        return result

    def write(self, vals):
        result = super(IdgLetter, self).write(vals)
        return result

    def action_set_code(self):
        for rec in self:
            if not rec.code or rec.code  == '/':
                sequence = self.env['idg.letter.category']
                rec.code=sequence.next_by_code(rec.category_id.code)

    def action_submit(self):
        self.ensure_one()
        for rec in self:
            if rec.typ == 'out' and not rec.approver_ids:
                self._set_default_approver(rec)
            rec.state = "pending"
            for appr in rec.approver_ids:
                if appr.state == 'draft':
                    appr.state = 'pending'

    def action_draft(self):
        for rec in self:
            rec.state = "draft"
            for appr in rec.approver_ids:
                if appr.state != "approved":
                    appr.state = "draft"

    def action_refuse(self):
        for rec in self:
            for appr in rec.approver_ids:
                if appr.user_id.id == self.env.user.id:
                    rec.state = appr.state = "refused"

    def action_cancel(self):
        for rec in self:
            rec.state = "canceled"
            for appr in rec.approver_ids:
                if appr.user_id.id == self.env.user.id or appr.state != "approved":
                    appr.state = "canceled"

    def action_approve(self):
        for rec in self:
            state = "approved"
            for appr in rec.approver_ids:
                if appr.user_id.id == self.env.user.id:
                    appr.state = "approved"
                if appr.required and appr.state != "approved":
                    state = appr.state

            if state == "approved":
                rec.state = "approved"

    def action_recall(self):
        for rec in self:
            for appr in rec.approver_ids:
                if appr.user_id.id == self.env.user.id:
                    appr.state = "pending"


class IdgLetterApprover(models.Model):
    _name = 'idg.letter.approver'
    _description = 'E Office Letter Approver'
    _inherit = ['mail.thread', 'mail.activity.mixin', ]
    letter_id = fields.Many2one('idg.letter')
    user_id = fields.Many2one('res.users')
    required = fields.Boolean(string="Required", default=False)
    state = fields.Selection([('draft', 'Draft'),
                              ('pending', 'To Approve'),
                              ('approved', 'Approved'),
                              ('refused', 'Refused'),
                              ('canceled', 'Canceled'),
                              ], default='draft',
                             tracking=True, )


class IdgLetterDocs(models.Model):
    _name = 'idg.letter.docs'
    _description = 'E Office Documents'
    _inherit = ['format.address.mixin', 'image.mixin']
    idg_letter_id = fields.Many2one('idg.letter')
    name = fields.Char()


class IdgLetterComments(models.Model):
    _name = 'idg.letter.comments'
    _description = 'E Office Comments'
    _inherit = ['format.address.mixin', 'image.mixin']
    idg_letter_id = fields.Many2one('idg.letter')
    comment = fields.Text()