diff options
Diffstat (limited to 'indoteknik_custom/models/gudang_service.py')
| -rw-r--r-- | indoteknik_custom/models/gudang_service.py | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/indoteknik_custom/models/gudang_service.py b/indoteknik_custom/models/gudang_service.py new file mode 100644 index 00000000..d699ccf4 --- /dev/null +++ b/indoteknik_custom/models/gudang_service.py @@ -0,0 +1,273 @@ +from odoo import models, fields, api, _ +from odoo.exceptions import UserError, ValidationError +import logging +from datetime import datetime +from collections import defaultdict + + +class GudangService(models.Model): + _name = "gudang.service" + _description = "Gudang Service" + _inherit = ["mail.thread", "mail.activity.mixin"] + _order = "id asc" + + name = fields.Char("Name", readonly=True) + partner_id = fields.Many2one("res.partner", string="Customer", readonly=True) + vendor_id = fields.Many2one("res.partner", string="Vendor Service", required=True) + origin = fields.Many2one( + "sale.order", + string="Origin SO", + required=True, + domain=[("state", "in", ["done", "sale"])], + ) + schedule_date = fields.Date(string="Schedule Date", required=True, tracking=True) + start_date = fields.Datetime(string="Date Processed", copy=False, tracking=True) + create_date = fields.Datetime( + string="Create Date", copy=False, tracking=True, default=fields.Datetime.now() + ) + done_date = fields.Datetime(string="Date Done", copy=False, tracking=True) + gudang_service_lines = fields.One2many( + "gudang.service.line", "gudang_service_id", string="Gudang Service Lines" + ) + # unprocessed_date = fields.Char( + # string='Unprocessed Since', + # compute='_compute_unprocessed_date' + # ) + remaining_date = fields.Char( + compute="_compute_remaining_date", string="Date Status" + ) + state = fields.Selection( + [ + ("draft", "Backlog"), + ("received_from_cust", "Received From Customer"), + ("sent_to_vendor", "Sent to Service Vendor"), + ("received_from_vendor", "Received From Service Vendor"), + ("delivered_to_cust", "Delivered to Customer"), + ("cancel", "Cancel"), + ], + default="draft", + tracking=True, + ) + cancel_reason = fields.Text("Cancel Reason", tracking=True) + + def check_duplicate_docs(self): + for rec in self: + found = self.env["gudang.service"].search( + [ + ("id", "!=", self.id), + ("origin.id", "=", self.origin.id), + ("partner_id.id", "=", rec.partner_id.id), + ("vendor_id.id", "=", rec.vendor_id.id), + ("schedule_date", "=", rec.schedule_date), + ( + "gudang_service_lines.product_id.name", + "=", + rec.gudang_service_lines.product_id.name, + ), + ( + "gudang_service_lines.quantity", + "=", + rec.gudang_service_lines.quantity, + ), + ] + ) + if found: + raise UserError("This Document has duplicate with %s" % found.name) + + def _send_logistic_notification(self): + group = self.env.ref( + "indoteknik_custom.group_role_logistic", raise_if_not_found=False + ) + if not group: + return + + users = group.users + # MD + md = self.env["res.users"].browse([3425, 4801, 1036]) + # send to logistic and MD + users = users | md + + if not users: + return + + # Logistic users to be excluded + excluded_users = [7, 17098, 216, 28, 15710] + + for rec in self: + for user in users: + if user.id in excluded_users: + continue + self.env["mail.activity"].create( + { + "res_model_id": self.env["ir.model"]._get_id("gudang.service"), + "res_id": rec.id, + "activity_type_id": self.env.ref( + "mail.mail_activity_data_todo" + ).id, + "user_id": user.id, + "summary": "Gudang Service On Progress", + "note": _( + "Ada Jadwal Service Barang di Document <b>%s</b> Jadwal Service 📅 <b>%s</b>" + ) + % (rec.name, rec.schedule_date), + # 'date_deadline': fields.Date.today(), + } + ) + + # kirim ke private message odoo + channel = ( + self.env["mail.channel"] + .channel_get([self.env.user.partner_id.id, user.partner_id.id]) + .get("id") + ) + if not channel: + continue + res = self.env["mail.channel"].browse(channel) + res.with_user(self.env.user.browse(25)).message_post( + body=_( + "Ada Jadwal Service Barang di Document <b>%s</b> Jadwal Service 📅 <b>%s</b>" + ) + % (rec.name, rec.schedule_date), + message_type="comment", + subtype_xmlid="mail.mt_comment", + ) + + @api.model + def cron_notify_onprogress_gudang_service(self): + records = self.search( + [ + ("state", "in", ["draft", "received_from_customer"]), + ] + ) + + if records: + records._send_logistic_notification() + + @api.depends("schedule_date", "create_date") + def _compute_remaining_date(self): + today = fields.Date.today() + + for rec in self: + if not rec.schedule_date: + rec.remaining_date = "-" + continue + + base_date = rec.create_date.date() if rec.create_date else today + + schedule = rec.schedule_date + days = (schedule - base_date).days + + if days > 0: + rec.remaining_date = _("In %s days") % days + elif days == 0: + rec.remaining_date = _("Today") + else: + rec.remaining_date = _("Overdue %s days") % abs(days) + + def action_submit(self): + self.ensure_one() + self.check_duplicate_docs() + for rec in self: + if rec.state == "draft": + rec.state = "received_from_cust" + elif rec.state == "received_from_cust": + rec.state = "sent_to_vendor" + rec.start_date = fields.Datetime.now() + elif rec.state == "sent_to_vendor": + rec.state = "received_from_vendor" + + def action_done(self): + for rec in self: + if rec.state != "received_from_vendor": + raise UserError("Only 'Received From Vendor' state can be set to Done") + + rec.activity_ids.unlink() + + rec.write( + {"state": "delivered_to_cust", "done_date": fields.Datetime.now()} + ) + + def action_draft(self): + """Reset to draft state""" + for rec in self: + rec.cancel_reason = False + if rec.state == "cancel": + rec.write({"state": "draft"}) + else: + raise UserError("Only Canceled Record Can Be Reset To Draft") + + def action_cancel(self): + for rec in self: + activities = self.env["mail.activity"].search( + [ + ("res_id", "=", rec.id), + ("res_model", "=", "gudang.service"), + ] + ) + activities.unlink() + if rec.state == "delivered_to_cust": + raise UserError("You cannot cancel a done record") + if not rec.cancel_reason: + raise UserError("Cancel Reason must be filled") + rec.start_date = False + rec.done_date = False + rec.state = "cancel" + + @api.model + def create(self, vals): + # sequence + if not vals.get("name") or vals["name"] == "New": + vals["name"] = self.env["ir.sequence"].next_by_code("gudang.service") + + # partner dari SO + so = self.env["sale.order"].browse(vals["origin"]) + vals["partner_id"] = so.partner_id.id + + res = super(GudangService, self).create(vals) + + res.check_duplicate_docs() + res._send_logistic_notification() + return res + + def write(self, vals): + if vals.get("origin"): + so = self.env["sale.order"].browse(vals["origin"]) + vals["partner_id"] = so.partner_id.id + vals.check_duplicate_docs() + + return super(GudangService, self).write(vals) + + @api.onchange("origin") + def _onchange_origin(self): + if not self.origin: + self.gudang_service_lines = [(5, 0, 0)] + return + + self.partner_id = self.origin.partner_id + + lines = [] + for line in self.origin.order_line: + lines.append( + ( + 0, + 0, + { + "product_id": line.product_id.id, + "quantity": line.product_uom_qty, + "origin_so": self.origin.id, + }, + ) + ) + + # hapus line lama lalu isi baru + self.gudang_service_lines = [(5, 0, 0)] + lines + + +class GudangServiceLine(models.Model): + _name = "gudang.service.line" + _inherit = ["mail.thread", "mail.activity.mixin"] + + product_id = fields.Many2one("product.product", string="Product") + quantity = fields.Float(string="Quantity") + origin_so = fields.Many2one("sale.order", string="Origin SO") + gudang_service_id = fields.Many2one("gudang.service", string="Gudang Service ID") |
