diff options
| author | Mqdd <ahmadmiqdad27@gmail.com> | 2026-02-14 11:16:39 +0700 |
|---|---|---|
| committer | Mqdd <ahmadmiqdad27@gmail.com> | 2026-02-14 11:16:39 +0700 |
| commit | 17e9e2303ac37e77676326608a71d68a2dc35197 (patch) | |
| tree | 450855b8102aff95866e093b72138b6f20417a9f | |
| parent | 30e7aae41d50528a4e61e6f55f38e3dd647e41c6 (diff) | |
| parent | 55a8c1e5b204bd19733f3197b253293bc00fdf32 (diff) | |
Merge branch 'gudang-service' of https://bitbucket.org/altafixco/indoteknik-addons into gudang-service
| -rwxr-xr-x | indoteknik_custom/models/__init__.py | 2 | ||||
| -rw-r--r-- | indoteknik_custom/models/gudang_service.py | 108 | ||||
| -rw-r--r-- | indoteknik_custom/models/tukar_guling.py | 116 | ||||
| -rwxr-xr-x | indoteknik_custom/security/ir.model.access.csv | 2 | ||||
| -rw-r--r-- | indoteknik_custom/views/gudang_service.xml | 23 |
5 files changed, 103 insertions, 148 deletions
diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py index 3b3dcd9d..4e5c3d3b 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -166,4 +166,4 @@ from . import domain_apo from . import uom_uom from . import commission_internal from . import gudang_service -from . import update_depreciation_move_wizard
\ No newline at end of file +from . import update_depreciation_move_wizard diff --git a/indoteknik_custom/models/gudang_service.py b/indoteknik_custom/models/gudang_service.py index 1056c4c8..4900113f 100644 --- a/indoteknik_custom/models/gudang_service.py +++ b/indoteknik_custom/models/gudang_service.py @@ -13,8 +13,8 @@ class GudangService(models.Model): name = fields.Char('Name', readonly=True) partner_id = fields.Many2one('res.partner', string='Customer', readonly=True) - vendor_id = fields.Many2one('res.partner', string='Vendor', readonly=True, required=True) - origin = fields.Many2one('sale.order', string='Origin SO', required=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, @@ -34,9 +34,15 @@ class GudangService(models.Model): # ) remaining_date = fields.Char( compute='_compute_remaining_date', - string='Remaining Date' + string='Date Status' ) - state = fields.Selection([('draft', 'Backlog'), ('onprogress', 'On Progress'),('done', 'Done'), ('cancel', 'Cancel')], default='draft', tracking=True) + 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 _send_logistic_notification(self): @@ -82,33 +88,12 @@ class GudangService(models.Model): @api.model def cron_notify_onprogress_gudang_service(self): records = self.search([ - ('state', '=', 'draft') + ('state', 'in', ['draft', 'received_from_customer']), ]) if records: records._send_logistic_notification() - # @api.depends('schedule_date', 'start_date', 'state') - # def _compute_unprocessed_date(self): - # today = fields.Date.today() - - # for rec in self: - # if not rec.schedule_date or rec.state == 'cancel': - # rec.unprocessed_date = "-" - # continue - - # schedule = rec.schedule_date - - # # BELUM DIPROSES - # if not rec.start_date: - # days = (today - schedule).days - - # # SUDAH DIPROSES - # else: - # days = (rec.start_date.date() - schedule).days - - # rec.unprocessed_date = _("Unprocessed %s days") % max(days, 0) - @api.depends('schedule_date', 'create_date') def _compute_remaining_date(self): today = fields.Date.today() @@ -133,21 +118,28 @@ class GudangService(models.Model): def action_submit(self): for rec in self: - rec.state = 'onprogress' - rec.start_date = fields.Datetime.now() - # rec.date = fields.Datetime.now() + 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: - activities = self.env['mail.activity'].search([ - ('res_id', '=', rec.id), - ('res_model', '=', 'gudang.service'), - ('state', '=', 'done') - ]) - activities.unlink() - rec.state = 'done' - if not rec.done_date: - rec.done_date = fields.Datetime.now() + if self.state != 'received_from_vendor': + raise UserError("Only 'Received From Vendor' state can be set to Done") + else: + for rec in self: + activities = self.env['mail.activity'].search([ + ('res_id', '=', rec.id), + ('res_model', '=', 'gudang.service'), + ('state', '=', 'delivered_to_cust'), + ]) + activities.unlink() + rec.state = 'delivered_to_cust' + if not rec.done_date: + rec.done_date = fields.Datetime.now() def action_draft(self): """Reset to draft state""" @@ -165,7 +157,7 @@ class GudangService(models.Model): ('res_model', '=', 'gudang.service'), ]) activities.unlink() - if rec.state == 'done': + 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") @@ -183,42 +175,6 @@ class GudangService(models.Model): so = self.env['sale.order'].browse(vals['origin']) vals['partner_id'] = so.partner_id.id - # 1️⃣ Cari BU/OUT dari SO - picking = self.env['stock.picking'].search([ - ('origin', '=', so.name), - ('picking_type_id', '=', 29), # BU/OUT - ('state', '=', 'done'), - ], limit=1) - - if not picking: - raise UserError("BU/OUT (done) tidak ditemukan untuk SO ini.") - - # 2️⃣ Validasi product service ada di picking - picking_products = picking.move_lines.mapped('product_id') - service_lines = vals.get('gudang_service_lines', []) - - tg_lines = [] - for line in service_lines: - product = self.env['product.product'].browse(line[2]['product_id']) - if product not in picking_products: - raise UserError( - f"Produk {product.display_name} tidak ada di BU/OUT {picking.name}" - ) - - tg_lines.append((0, 0, { - 'product_id': product.id, - 'quantity': line[2]['quantity'], - })) - - # 3️⃣ Create Tukar Guling - self.env['tukar.guling'].create({ - 'origin_so': so.id, - 'operation_type': 'service', - 'partner_id': so.partner_id.id, - 'operations': picking.id, - 'line_ids': tg_lines, - }) - res = super(GudangService, self).create(vals) res._send_logistic_notification() diff --git a/indoteknik_custom/models/tukar_guling.py b/indoteknik_custom/models/tukar_guling.py index 03af984f..619e7c99 100644 --- a/indoteknik_custom/models/tukar_guling.py +++ b/indoteknik_custom/models/tukar_guling.py @@ -62,7 +62,7 @@ class TukarGuling(models.Model): notes = fields.Text('Notes') return_type = fields.Selection(String='Return Type', selection=[ ('tukar_guling', 'Tukar Guling'), # -> barang yang sama - ('service', 'Service'), # -> barang yang sama + # ('service', 'Service'), # -> barang yang sama ('retur_so', 'Retur SO')], required=True, tracking=3, help='Retur SO (ORT-SRT),\n Tukar Guling (ORT-SRT-PICK-OUT)') state = fields.Selection(string='Status', selection=[ ('draft', 'Draft'), @@ -933,64 +933,64 @@ class TukarGuling(models.Model): record.message_post( body=f"📦 <b>{new_pick.name}</b> created by <b>{self.env.user.name}</b> (state: <b>{new_pick.state}</b>)") - if record.return_type == 'service': - GUDANG_SERVICE_LOCATION_ID = 98 - # From STOCK to OUTPUT - done_service = self.env['stock.picking'].create({ - 'group_id': bu_out.group_id.id, - 'tukar_guling_id': record.id, - 'sale_order': record.origin, - 'note': record.notes, - 'picking_type_id': 32, - 'location_id': GUDANG_SERVICE_LOCATION_ID, - 'location_dest_id': BU_STOCK_LOCATION_ID, - 'partner_id': bu_out.partner_id.id, - 'move_ids_without_package': [(0, 0, { - 'product_id': line.product_id.id, - 'product_uom_qty': line.product_uom_qty, - 'product_uom': line.product_uom.id, - 'name': line.product_id.display_name, - 'location_id': GUDANG_SERVICE_LOCATION_ID, - 'location_dest_id': BU_STOCK_LOCATION_ID, - }) for line in record.line_ids], - }) - if done_service: - done_service.action_confirm() - done_service.action_assign() - else: - raise UserError("Gagal membuat picking service") + # if record.return_type == 'service': + # GUDANG_SERVICE_LOCATION_ID = 98 + # # From STOCK to OUTPUT + # done_service = self.env['stock.picking'].create({ + # 'group_id': bu_out.group_id.id, + # 'tukar_guling_id': record.id, + # 'sale_order': record.origin, + # 'note': record.notes, + # 'picking_type_id': 32, + # 'location_id': GUDANG_SERVICE_LOCATION_ID, + # 'location_dest_id': BU_STOCK_LOCATION_ID, + # 'partner_id': bu_out.partner_id.id, + # 'move_ids_without_package': [(0, 0, { + # 'product_id': line.product_id.id, + # 'product_uom_qty': line.product_uom_qty, + # 'product_uom': line.product_uom.id, + # 'name': line.product_id.display_name, + # 'location_id': GUDANG_SERVICE_LOCATION_ID, + # 'location_dest_id': BU_STOCK_LOCATION_ID, + # }) for line in record.line_ids], + # }) + # if done_service: + # done_service.action_confirm() + # done_service.action_assign() + # else: + # raise UserError("Gagal membuat picking service") - service_to_output = self.env['stock.picking'].create({ - 'group_id': bu_out.group_id.id, - 'tukar_guling_id': record.id, - 'sale_order': record.origin, - 'note': record.notes, - 'picking_type_id': 32, - 'location_id': BU_STOCK_LOCATION_ID, - 'location_dest_id': BU_OUTPUT_LOCATION_ID, - 'partner_id': bu_out.partner_id.id, - 'move_lines': [(0, 0, { - 'product_id': line.product_id.id, - 'product_uom_qty': line.product_uom_qty, - 'product_uom': line.product_uom.id, - 'name': line.product_id.display_name, - 'location_id':BU_STOCK_LOCATION_ID, - 'location_dest_id': BU_STOCK_LOCATION_ID, - }) for line in record.line_ids], - 'move_ids_without_package': [(0, 0, { - 'product_id': line.product_id.id, - 'product_uom_qty': line.product_uom_qty, - 'product_uom': line.product_uom.id, - 'name': line.product_id.display_name, - 'location_id': BU_STOCK_LOCATION_ID, - 'location_dest_id': BU_OUTPUT_LOCATION_ID, - }) for line in record.line_ids], - }) - if service_to_output: - service_to_output.action_confirm() - service_to_output.action_assign() - else: - raise UserError("Gagal membuat picking service") + # service_to_output = self.env['stock.picking'].create({ + # 'group_id': bu_out.group_id.id, + # 'tukar_guling_id': record.id, + # 'sale_order': record.origin, + # 'note': record.notes, + # 'picking_type_id': 32, + # 'location_id': BU_STOCK_LOCATION_ID, + # 'location_dest_id': BU_OUTPUT_LOCATION_ID, + # 'partner_id': bu_out.partner_id.id, + # 'move_lines': [(0, 0, { + # 'product_id': line.product_id.id, + # 'product_uom_qty': line.product_uom_qty, + # 'product_uom': line.product_uom.id, + # 'name': line.product_id.display_name, + # 'location_id':BU_STOCK_LOCATION_ID, + # 'location_dest_id': BU_STOCK_LOCATION_ID, + # }) for line in record.line_ids], + # 'move_ids_without_package': [(0, 0, { + # 'product_id': line.product_id.id, + # 'product_uom_qty': line.product_uom_qty, + # 'product_uom': line.product_uom.id, + # 'name': line.product_id.display_name, + # 'location_id': BU_STOCK_LOCATION_ID, + # 'location_dest_id': BU_OUTPUT_LOCATION_ID, + # }) for line in record.line_ids], + # }) + # if service_to_output: + # service_to_output.action_confirm() + # service_to_output.action_assign() + # else: + # raise UserError("Gagal membuat picking service") # BU/OUT Baru dari SRT diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index 9859b127..50e2b382 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -217,4 +217,4 @@ access_sj_tele,access.sj.tele,model_sj_tele,base.group_system,1,1,1,1 access_stock_picking_sj_document,stock.picking.sj.document,model_stock_picking_sj_document,base.group_user,1,1,1,1 access_gudang_service,gudang.service,model_gudang_service,base.group_user,1,1,1,1 access_gudang_service_line,gudang.service.line,model_gudang_service_line,base.group_user,1,1,1,1 -access_update_depreciation_move_wizard,access.update.depreciation.move.wizard,model_update_depreciation_move_wizard,,1,1,1,1
\ No newline at end of file +access_update_depreciation_move_wizard,access.update.depreciation.move.wizard,model_update_depreciation_move_wizard,,1,1,1,1 diff --git a/indoteknik_custom/views/gudang_service.xml b/indoteknik_custom/views/gudang_service.xml index 9a8382d3..e5cc94c4 100644 --- a/indoteknik_custom/views/gudang_service.xml +++ b/indoteknik_custom/views/gudang_service.xml @@ -6,10 +6,8 @@ <field name="name">gudang.serivice.tree</field> <field name="model">gudang.service</field> <field name="arch" type="xml"> - <tree string="Monitoring Barang Service" - decoration-danger="state == 'draft'" decoration-warning="state == 'onprogress'" - decoration-success="state == 'done'" decoration-muted="state == 'cancel'" - > + <tree string="Monitoring Barang Service" decoration-danger="state in ('draft', 'received_from_cust')" decoration-warning="state in ('sent_to_vendor', 'received_from_vendor')" + decoration-success="state == 'delivered_to_cust'" decoration-muted="state == 'cancel'" > <field name="name"/> <field name="partner_id"/> <field name="vendor_id"/> @@ -17,8 +15,8 @@ <field name="schedule_date"/> <field name="start_date" optional="hide"/> <field name="remaining_date"/> - <field name="state" widget="badge" decoration-danger="state in ('draft')" decoration-warning="state == 'onprogress'" - decoration-success="state == 'done'" decoration-muted="state == 'cancel'" /> + <field name="state" widget="badge" decoration-danger="state in ('draft', 'received_from_cust')" decoration-warning="state in ('sent_to_vendor', 'received_from_vendor')" + decoration-success="state == 'delivered_to_cust'" decoration-muted="state == 'cancel'" /> <field name="cancel_reason" optional="hide"/> <field name="create_date" optional="hide"/> </tree> @@ -33,16 +31,16 @@ <header> <button name="action_submit" string="Proceed" type="object" class="btn-primary" - attrs="{'invisible': [('state', 'in', ['cancel', 'done', 'onprogress'])]}"/> + attrs="{'invisible': [('state', 'in', ['cancel', 'done', 'received_from_vendor', 'delivered_to_cust'])]}"/> <button name="action_done" string="Set Done" type="object" class="btn-primary" - attrs="{'invisible': [('state', 'not in', ['onprogress'])]}"/> + attrs="{'invisible': [('state', 'not in', ['received_from_vendor'])]}"/> <button name="action_cancel" string="Cancel" type="object" class="btn-secondary" - attrs="{'invisible': [('state', 'in', ['cancel', 'done', 'draft'])]}"/> + attrs="{'invisible': [('state', 'in', ['cancel', 'delivered_to_cust'])]}"/> <button name="action_draft" string="Set to Backlog" type="object" class="btn-secondary" - attrs="{'invisible': [('state', 'in', ['draft', 'done', 'onprogress'])]}"/> + attrs="{'invisible': [('state', 'not in', ['cancel'])]}"/> <field name="state" widget="statusbar" readonly="1"/> </header> <sheet> @@ -58,16 +56,17 @@ <field name="remaining_date"/> <field name="schedule_date" attrs="{'readonly': [('state', 'not in', ['draft'])]}"/> <field name="start_date" readonly="1"/> - <field name="done_date" attrs="{'invisible': [('state', 'not in', ['done'])]}"/> + <field name="done_date" attrs="{'invisible': [('state', 'not in', ['delivered_to_cust'])]}"/> <field name="create_uid"/> <field name="cancel_reason" - attrs="{'invisible': [('state', 'in', ['done', 'draft'])]}"/> + attrs="{'invisible': [('state', 'in', ['delivered_to_cust', 'draft'])]}"/> </group> <notebook> <page string="Product Lines" name="product_lines"> <field name="gudang_service_lines"> <tree string="Product Lines" editable="top" create="0" delete="1"> <field name="product_id"/> + <field name="quantity"/> </tree> </field> </page> |
