diff options
| author | Mqdd <ahmadmiqdad27@gmail.com> | 2026-02-10 09:18:51 +0700 |
|---|---|---|
| committer | Mqdd <ahmadmiqdad27@gmail.com> | 2026-02-10 09:18:51 +0700 |
| commit | b48c7baad0d5d0ae88a7277745938afc89b35991 (patch) | |
| tree | 0a8edc3099ce23bb3643f33957b11255291ee276 | |
| parent | 6f47933b5ac837af81008a300a0f109c1973d9d4 (diff) | |
<MIqdad> approval adjust out
| -rwxr-xr-x | fixco_custom/__manifest__.py | 1 | ||||
| -rwxr-xr-x | fixco_custom/models/__init__.py | 1 | ||||
| -rw-r--r-- | fixco_custom/models/stock_inventory.py | 109 | ||||
| -rw-r--r-- | fixco_custom/views/stock_inventory.xml | 33 |
4 files changed, 144 insertions, 0 deletions
diff --git a/fixco_custom/__manifest__.py b/fixco_custom/__manifest__.py index 9d781c0..83caa93 100755 --- a/fixco_custom/__manifest__.py +++ b/fixco_custom/__manifest__.py @@ -55,6 +55,7 @@ 'views/purchase_order_line_wizard.xml', 'views/account_payment.xml', 'views/account_move_line.xml', + 'views/stock_inventory.xml', ], 'demo': [], 'css': [], diff --git a/fixco_custom/models/__init__.py b/fixco_custom/models/__init__.py index 94954eb..31b5794 100755 --- a/fixco_custom/models/__init__.py +++ b/fixco_custom/models/__init__.py @@ -42,3 +42,4 @@ from . import purchase_order_multi_bills from . import account_payment from . import stock_location from . import account_asset +from . import stock_inventory
\ No newline at end of file diff --git a/fixco_custom/models/stock_inventory.py b/fixco_custom/models/stock_inventory.py new file mode 100644 index 0000000..96ac045 --- /dev/null +++ b/fixco_custom/models/stock_inventory.py @@ -0,0 +1,109 @@ +from odoo import models, api, fields +from odoo.exceptions import UserError +from datetime import datetime +import logging + +_logger = logging.getLogger(__name__) + + +class StockInventory(models.Model): + _inherit = ['stock.inventory'] + _order = 'id desc' + _rec_name = 'number' + + number = fields.Char(string='Document No', index=True, copy=False, readonly=True) + adjusment_type = fields.Selection([ + ('in', 'Adjusment In'), + ('out', 'Adjusment Out'), + ], string='Adjusments Type', required=True) + approval_state = fields.Selection([ + ('draft', 'Draft'), + ('logistic', 'Logistic'), + ('accounting', 'Accounting'), + ('approved', 'Approved'), + ], default='draft', tracking=True) + + def _generate_number_stock_inventory(self): + """Men-generate nomor untuk semua stock inventory yang belum memiliki number.""" + stock_records = self.env['stock.inventory'].search([('number', '=', False)], order='id asc') + for record in stock_records: + self._assign_number(record) + + _logger.info('Generate Number Done') + + def _assign_number(self, record): + """Menentukan nomor berdasarkan kategori Adjust-In atau Adjust-Out.""" + name_upper = record.name.upper() if record.name else "" + + if self.adjusment_type == 'out': + last_number = self._get_last_sequence("ADJUST/OUT/") + record.number = f"ADJUST/OUT/{last_number}" + elif self.adjusment_type == 'in': + last_number = self._get_last_sequence("ADJUST/IN/") + record.number = f"ADJUST/IN/{last_number}" + else: + record.number = "UNKNOWN" # Jika tidak termasuk kategori + + def _get_last_sequence(self, prefix): + """Mengambil nomor terakhir berdasarkan prefix (ADJUST/OUT/ atau ADJUST/IN/) dengan format 00001, 00002, dst.""" + last_record = self.env['stock.inventory'].search( + [("number", "like", f"{prefix}%")], order="number desc", limit=1 + ) + + if last_record and last_record.number: + try: + last_number = int(last_record.number.split("/")[-1]) # Ambil angka terakhir + return str(last_number + 1).zfill(5) # Format jadi 00001, 00002, dst. + except ValueError: + return "00001" # Jika format tidak valid, mulai dari 00001 + return "00001" # Jika belum ada data, mulai dari 00001 + + def action_start(self): + if self.approval_state != 'approved' and self.adjusment_type == 'out': + raise UserError('Harus melalui proses approval') + if self.adjusment_type == 'in': + if self.env.user.id not in [10, 14, 20, 21]: + raise UserError("Hanya User tertentu yang dapat melakukan Adjust-In") + return super(StockInventory, self).action_start() + + @api.model + def create(self, vals): + """Pastikan nomor hanya dibuat saat penyimpanan.""" + if 'adjusment_type' in vals and not vals.get('number'): + vals['number'] = False # Jangan buat number otomatis dulu + + order = super(StockInventory, self).create(vals) + + if order.adjusment_type: + self._assign_number(order) # Generate number setelah save + + return order + + def action_approve(self): + if self.adjusment_type == 'out': + for rec in self: + if self.approval_state in [False, '', 'draft']: + self.approval_state = 'logistic' + elif self.approval_state == 'logistic': + if not rec.env.user.id in [10, 14, 20, 21]: + raise UserError("Harus diapprove logistic") + self.approval_state = 'accounting' + elif self.approval_state == 'accounting': + if not rec.env.user.id in [13, 24, 2]: + raise UserError("Harus diapprove accounting") + self.approval_state = 'approved' + else: + raise UserError("Sudah Approved") + + def write(self, vals): + """Jika adjusment_type diubah, generate ulang nomor.""" + res = super(StockInventory, self).write(vals) + if 'adjusment_type' in vals: + for record in self: + self._assign_number(record) + return res + + def copy(self, default=None): + """Saat duplikasi, adjusment_type dikosongkan dan number tidak ikut terduplikasi.""" + default = dict(default or {}, adjusment_type=False, number=False) + return super(StockInventory, self).copy(default=default) diff --git a/fixco_custom/views/stock_inventory.xml b/fixco_custom/views/stock_inventory.xml new file mode 100644 index 0000000..df74783 --- /dev/null +++ b/fixco_custom/views/stock_inventory.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<odoo> + <!-- Form View: Tambahkan field 'number' setelah lokasi --> + <record id="view_stock_inventory_form_inherit" model="ir.ui.view"> + <field name="name">stock.inventory.form.inherit</field> + <field name="model">stock.inventory</field> + <field name="inherit_id" ref="stock.view_inventory_form"/> + <field name="arch" type="xml"> + <header> + <button name="action_approve" string="Approve" type="object" + class="btn-primary" attrs="{'invisible': [('adjusment_type', 'not in', ['out'])]}"/> + </header> + <xpath expr="//field[@name='location_ids']" position="after"> + <field name="number" readonly="1"/> + <field name="adjusment_type" /> + <field name="approval_state" readonly="1" attrs="{'invisible': [('adjusment_type', 'not in', ['out'])]}"/> + </xpath> + </field> + </record> + + <!-- Tree View: Tambahkan field 'number' setelah tanggal --> + <record id="view_stock_inventory_tree_inherit" model="ir.ui.view"> + <field name="name">stock.inventory.tree.inherit</field> + <field name="model">stock.inventory</field> + <field name="inherit_id" ref="stock.view_inventory_tree"/> + <field name="arch" type="xml"> + <xpath expr="//field[@name='date']" position="after"> + <field name="number"/> + </xpath> + </field> + </record> + +</odoo> |
