summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xindoteknik_custom/__manifest__.py1
-rw-r--r--indoteknik_custom/models/tukar_guling.py211
-rwxr-xr-xindoteknik_custom/security/ir.model.access.csv1
-rw-r--r--indoteknik_custom/views/tukar_guling.xml196
-rw-r--r--indoteknik_custom/views/tukar_guling_po.xml117
5 files changed, 357 insertions, 169 deletions
diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py
index e973f553..9f8fad01 100755
--- a/indoteknik_custom/__manifest__.py
+++ b/indoteknik_custom/__manifest__.py
@@ -168,6 +168,7 @@
'views/public_holiday.xml',
'views/stock_inventory.xml',
'views/tukar_guling.xml',
+ 'views/tukar_guling_po.xml',
],
'demo': [],
'css': [],
diff --git a/indoteknik_custom/models/tukar_guling.py b/indoteknik_custom/models/tukar_guling.py
index f8cbec0a..95aa7cd6 100644
--- a/indoteknik_custom/models/tukar_guling.py
+++ b/indoteknik_custom/models/tukar_guling.py
@@ -12,66 +12,34 @@ class TukarGuling(models.Model):
date = fields.Datetime('Date', default=fields.Datetime.now, required=True)
out_num = fields.Many2one('stock.picking', 'Nomor BU/Out',
domain=[('picking_type_id.code', '=', 'outgoing')])
- in_num = fields.Many2one('stock.picking', 'Nomor BU/In', domain=[('picking_type_id.code', '=', 'incoming')])
ba_num = fields.Text('Nomor BA')
notes = fields.Text('Notes')
return_type = fields.Selection(String='Return Type', selection=[
('tukar_guling', 'Tukar Guling'), # -> barang yang sama
('revisi_so', 'Revisi SO'), # -> ganti barang ?
- ('revisi_po', 'Revisi PO'),
- ('credit_memo', 'Credit Memo'), # -> dijadiin credit memo
- ('debit_memo', 'Debit Memo')])
+ ('credit_memo', 'Credit Memo')]) # -> dijadiin credit memo
state = fields.Selection(string='Status', selection=[
('draft', 'Draft'),
- ('waiting', 'Waiting for Approval'),
+ ('approval_sales', ' Approval Sales'),
+ ('approval_logistic', 'Approval Logistic'),
+ ('approval_finance', 'Approval Finance'),
('done', 'Done'),
('cancel', 'Canceled')
], default='draft', tracking=True, required=True)
line_ids = fields.One2many('tukar.guling.line', 'tukar_guling_id', string='Product Lines')
- @api.onchange('return_type')
- def _onchange_return_type(self):
- in_domain = []
- out_domain = []
-
- if self.return_type in ['debit_memo', 'revisi_po']:
- # Hanya tampilkan BU In
- in_domain = [('picking_type_id.code', '=', 'incoming')]
- out_domain = [('id', '=', False)] # Kosongkan BU Out
- elif self.return_type in ['revisi_so', 'credit_memo']:
- # Hanya tampilkan BU Out
- in_domain = [('id', '=', False)] # Kosongkan BU In
- out_domain = [('picking_type_id.code', '=', 'outgoing')]
- elif self.return_type == 'tukar_guling':
- # Boleh pilih keduanya
- in_domain = [('picking_type_id.code', '=', 'incoming')]
- out_domain = [('picking_type_id.code', '=', 'outgoing')]
-
- return {
- 'domain': {
- 'in_num': in_domain,
- 'out_num': out_domain,
- }
- }
-
- @api.constrains('return_type', 'in_num', 'out_num')
+ @api.constrains('return_type', 'out_num')
def _check_required_bu_fields(self):
for record in self:
- if record.return_type in ['debit_memo', 'revisi_po'] and not record.in_num:
- raise ValidationError("BU/In harus diisi untuk return type Debit Memo atau Revisi PO.")
-
- if record.return_type in ['revisi_so', 'credit_memo'] and not record.out_num:
- raise ValidationError("BU/Out harus diisi untuk return type Revisi SO atau Credit Memo.")
-
- if record.return_type == 'tukar_guling' and not (record.in_num or record.out_num):
- raise ValidationError("Untuk Tukar Guling, minimal isi salah satu, BU/In atau BU/Out.")
+ if record.return_type in ['revisi_so', 'credit_memo', 'tukar_guling'] and not record.out_num:
+ raise ValidationError("BU/Out harus diisi!")
@api.constrains('line_ids', 'state')
def _check_product_lines(self):
"""Constraint: Product lines harus ada jika state bukan draft"""
for record in self:
- if record.state in ('waiting', 'done') and not record.line_ids:
+ if record.state in ('approval_sales', 'approval_logistic', 'approval_finance', 'done') and not record.line_ids:
raise ValidationError("Product lines harus diisi sebelum submit atau approve!")
def _validate_product_lines(self):
@@ -95,29 +63,29 @@ class TukarGuling(models.Model):
return True
- @api.model_create_multi
- def create(self, vals_list):
- for vals in vals_list:
- if vals.get('name', 'New') == 'New':
- vals['name'] = self.env['ir.sequence'].next_by_code('tukar.guling') or 'PTG/00001'
- return super(TukarGuling, self).create(vals_list)
+ @api.model
+ def create(self, vals):
+ if not vals.get('name') or vals['name'] == 'New':
+ vals['name'] = self.env['ir.sequence'].next_by_code('tukar.guling') or 'New'
+ return super(TukarGuling, self).create(vals)
def copy(self, default=None):
- """Override copy untuk custom behavior saat duplicate"""
if default is None:
default = {}
- # Reset fields penting saat duplicate
+ if 'name' not in default:
+ default.update({
+ 'name': self.env['ir.sequence'].next_by_code(self._name) or 'New',
+ })
+
default.update({
- 'name': 'New',
'state': 'draft',
'date': fields.Datetime.now(),
})
- # Copy record dengan default values
new_record = super(TukarGuling, self).copy(default)
- # Re-sequence line items record baru
+ # Re-sequence lines
if new_record.line_ids:
for i, line in enumerate(new_record.line_ids):
line.sequence = (i + 1) * 10
@@ -134,40 +102,153 @@ class TukarGuling(models.Model):
def action_submit(self):
self.ensure_one()
- # cek bu out sudah diisi atau blm
+
+ if self.state != 'draft':
+ raise UserError("Submit hanya bisa dilakukan dari Draft.")
+ self.state = 'approval_sales'
+
+ def action_approve(self):
+ self.ensure_one()
+
if not self.out_num:
raise UserError("BU/Out harus diisi!")
- # cek return type
- # if not self.return_type:
- # raise UserError("Return Type harus diisi!")
+ if not self.return_type:
+ raise UserError("Return Type harus diisi!")
+
+ # Cek hak akses berdasarkan state
+ if self.state == 'approval_sales':
+ if not self.env.user.has_group('indoteknik_custom.group_sales_manager'):
+ raise UserError("Hanya Sales Manager yang boleh approve tahap ini.")
+ self.state = 'approval_logistic'
+
+ elif self.state == 'approval_logistic':
+ if not self.env.user.has_group('indoteknik_custom.group_logistic'):
+ raise UserError("Hanya Logistic Manager yang boleh approve tahap ini.")
+ self.state = 'approval_finance'
+
+ elif self.state == 'approval_finance':
+ if not self.env.user.has_group('indoteknik_custom.group_finance'):
+ raise UserError("Hanya Finance Manager yang boleh approve tahap ini.")
+ self.state = 'done'
+
+ else:
+ raise UserError("Status ini tidak bisa di-approve.")
+ def action_cancel(self):
+ self.ensure_one()
+ # if self.state == 'done':
+ # raise UserError("Tidak bisa cancel jika sudah done")
+ self.state = 'cancel'
+
+class TukarGulingPO(models.Model):
+ _name = 'tukar.guling.po'
+ _inherit = 'tukar.guling'
+ _description = 'Tukar Guling PO'
+
+ # tukar_guling_id = fields.Many2one(
+ # 'tukar.guling', required=True, ondelete='cascade', string='Tukar Guling Ref'
+ # )
+
+ return_type = fields.Selection([
+ ('tukar_guling', 'Tukar Guling'),
+ ('revisi_po', 'Revisi PO'),
+ ('debit_memo', 'Debit Memo'),
+ ], string='Return Type', required=True)
+
+ @api.constrains('return_type', 'out_num')
+ def _check_required_bu_fields(self):
+ for record in self:
+ if record.return_type in ['tukar_guling', 'revisi_po', 'debit_memo'] and not record.out_num:
+ raise ValidationError("BU/Out harus diisi!")
+
+ @api.constrains('line_ids', 'state')
+ def _check_product_lines(self):
+ """Constraint: Product lines harus ada jika state bukan draft"""
+ for record in self:
+ if record.state in ('approval_sales', 'approval_logistic', 'approval_finance', 'done') and not record.line_ids:
+ raise ValidationError("Product lines harus diisi sebelum submit atau approve!")
+
+ def _validate_product_lines(self):
+ """Helper method untuk validasi product lines"""
+ self.ensure_one()
+
+ # Check ada product lines
+ if not self.line_ids:
+ raise UserError("Belum ada product lines yang ditambahkan!")
+
+ # Check product sudah diisi
+ empty_lines = self.line_ids.filtered(lambda line: not line.product_id)
+ if empty_lines:
+ raise UserError("Ada product lines yang belum diisi productnya!")
+
+ # Check quantity > 0
+ zero_qty_lines = self.line_ids.filtered(lambda line: line.product_uom_qty <= 0)
+ if zero_qty_lines:
+ raise UserError("Quantity product tidak boleh kosong atau 0!")
+ return True
+
+ @api.model
+ def create(self, vals):
+ if not vals.get('name') or vals['name'] in ('New', False):
+ vals['name'] = self.env['ir.sequence'].next_by_code('tukar.guling.po') or 'New'
+ return super(TukarGulingPO, self).create(vals)
+ def copy(self, default=None):
+ if default is None:
+ default = {}
+
+ # Generate sequence satu-satunya di sini
+ default['name'] = self.env['ir.sequence'].next_by_code('tukar.guling.po') or 'New'
+ default['state'] = 'draft'
+ default['date'] = fields.Datetime.now()
+
+ new_record = super(TukarGulingPO, self).copy(default)
+
+ # Re-sequence lines
+ if new_record.line_ids:
+ for i, line in enumerate(new_record.line_ids):
+ line.sequence = (i + 1) * 10
+
+ return new_record
+
+ def action_draft(self):
+ """Reset to draft state"""
+ for record in self:
+ if record.state == 'cancel':
+ record.write({'state': 'draft'})
+ else:
+ raise UserError("Hanya record yang di-cancel yang bisa dikembalikan ke draft")
+
+ def action_submit(self):
+ self.ensure_one()
if self.state != 'draft':
- raise UserError("Hanya status Draft saja yang bisa di submit")
- self.state = 'waiting'
+ raise UserError("Submit hanya bisa dilakukan dari Draft.")
+ self.state = 'approval_sales'
def action_approve(self):
self.ensure_one()
- # cek bu out sudah diisi atau blm
if not self.out_num:
raise UserError("BU/Out harus diisi!")
- # cek return type
if not self.return_type:
raise UserError("Return Type harus diisi!")
- if self.state != 'waiting':
- raise UserError("Hanya status Waiting saja yang bisa di approve")
- self.state = 'done'
+ if self.state == 'approval_sales':
+ self.state = 'approval_logistic'
+ elif self.state == 'approval_logistic':
+ self.state = 'approval_finance'
+ elif self.state == 'approval_finance':
+ self.state = 'done'
+ else:
+ raise UserError("Status ini tidak bisa di-approve.")
def action_cancel(self):
self.ensure_one()
- if self.state == 'done':
- raise UserError("Tidak bisa cancel jika sudah done")
+ # if self.state == 'done':
+ # raise UserError("Tidak bisa cancel jika sudah done")
self.state = 'cancel'
-
class TukarGulingLine(models.Model):
_name = 'tukar.guling.line'
_description = 'Tukar Guling Line'
diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv
index 26198a0f..f8fb6ac6 100755
--- a/indoteknik_custom/security/ir.model.access.csv
+++ b/indoteknik_custom/security/ir.model.access.csv
@@ -182,4 +182,5 @@ access_production_purchase_match,access.production.purchase.match,model_producti
access_image_carousel,access.image.carousel,model_image_carousel,,1,1,1,1
access_v_sale_notin_matchpo,access.v.sale.notin.matchpo,model_v_sale_notin_matchpo,,1,1,1,1
access_tukar_guling_all_users,tukar.guling.all.users,model_tukar_guling,base.group_user,1,1,1,1
+access_tukar_guling_po_all_users,tukar.guling.po.all.users,model_tukar_guling_po,base.group_user,1,1,1,1
access_tukar_guling_line_all_users,tukar.guling.line.all.users,model_tukar_guling_line,base.group_user,1,1,1,1
diff --git a/indoteknik_custom/views/tukar_guling.xml b/indoteknik_custom/views/tukar_guling.xml
index 1556adcb..e008d2a1 100644
--- a/indoteknik_custom/views/tukar_guling.xml
+++ b/indoteknik_custom/views/tukar_guling.xml
@@ -1,127 +1,115 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
- <data>
- <!-- Action -->
- <record id="action_pengajuan_tukar_guling" model="ir.actions.act_window">
- <field name="name">Pengajuan Tukar Guling</field>
- <field name="type">ir.actions.act_window</field>
- <field name="res_model">tukar.guling</field>
- <field name="view_mode">tree,form</field>
- </record>
-
- <!-- Menu -->
- <menuitem
+ <data>
+ <!-- Action -->
+ <record id="action_pengajuan_tukar_guling" model="ir.actions.act_window">
+ <field name="name">Pengajuan Tukar Guling SO</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">tukar.guling</field>
+ <field name="view_mode">tree,form</field>
+ </record>
+ <!-- Menu -->
+ <menuitem
id="menu_pengajuan_tukar_guling"
- name="Pengajuan Tukar Guling"
- parent="stock.menu_warehouse_report"
+ name="Pengajuan Tukar Guling SO"
+ parent="sale.sale_order_menu"
sequence="3"
action="action_pengajuan_tukar_guling"
/>
-
- <!-- Sequence -->
- <record id="seq_tukar_guling" model="ir.sequence">
- <field name="name">Pengajuan Tukar Guling</field>
- <field name="code">tukar.guling</field>
- <field name="prefix">PTG/</field>
- <field name="padding">5</field>
- <field name="number_next">1</field>
- <field name="number_increment">1</field>
- <field name="company_id" eval="False"/>
- </record>
-
- <!-- Tree View -->
- <record id="pengajuan_tukar_guling_tree" model="ir.ui.view">
- <field name="name">pengajuan.tukar.guling.tree</field>
- <field name="model">tukar.guling</field>
- <field name="arch" type="xml">
- <tree create="1" delete="1" default_order="create_date desc">
- <field name="name"/>
- <field name="date"/>
- <field name="out_num" string="BU/Out"/>
- <field name="in_num" string="BU/In"/>
- <field name="ba_num" string="Nomor BA"/>
- <field name="return_type" string="Return Type"/>
- <field name="state" widget="badge"
- decoration-info="state in ('draft', 'waiting')"
+ <!-- Sequence -->
+ <record id="seq_tukar_guling" model="ir.sequence">
+ <field name="name">Pengajuan Tukar Guling SO</field>
+ <field name="code">tukar.guling</field>
+ <field name="prefix">PTG/</field>
+ <field name="padding">5</field>
+ <field name="number_next">1</field>
+ <field name="number_increment">1</field>
+ <field name="company_id" eval="False"/>
+ </record>
+ <!-- Tree View -->
+ <record id="pengajuan_tukar_guling_tree" model="ir.ui.view">
+ <field name="name">pengajuan.tukar.guling.tree</field>
+ <field name="model">tukar.guling</field>
+ <field name="arch" type="xml">
+ <tree create="1" delete="1" default_order="create_date desc">
+ <field name="name"/>
+ <field name="date"/>
+ <field name="out_num" string="BU/Out"/>
+ <field name="ba_num" string="Nomor BA"/>
+ <field name="return_type" string="Return Type"/>
+ <field name="state" widget="badge"
+ decoration-info="state in ('draft', 'approval_sales', 'approval_logistic','approval_finance')"
decoration-success="state == 'done'"
decoration-muted="state == 'cancel'"
/>
- </tree>
- </field>
- </record>
-
- <!-- Form View -->
- <record id="pengajuan_tukar_guling_form" model="ir.ui.view">
- <field name="name">pengajuan.tukar.guling.form</field>
- <field name="model">tukar.guling</field>
- <field name="arch" type="xml">
- <form>
- <header>
- <button name="action_submit" string="Submit" type="object"
+ </tree>
+ </field>
+ </record>
+ <!-- Form View -->
+ <record id="pengajuan_tukar_guling_form" model="ir.ui.view">
+ <field name="name">pengajuan.tukar.guling.form</field>
+ <field name="model">tukar.guling</field>
+ <field name="arch" type="xml">
+ <form>
+ <header>
+ <button name="action_submit" string="Submit" type="object"
class="btn-primary"
attrs="{'invisible': [('state', '!=', 'draft')]}"/>
- <button name="action_approve" string="Approve" type="object"
- class="btn-primary"
- attrs="{'invisible': [('state', '!=', 'waiting')]}"/>
- <button name="action_cancel" string="Cancel" type="object"
+ <button name="action_approve" string="Approve" type="object"
+ class="btn-primary"
+ attrs="{'invisible': [('state', 'not in', ['approval_sales', 'approval_logistic', 'approval_finance'])]}"/>
+ <button name="action_cancel" string="Cancel" type="object"
class="btn-secondary"
- attrs="{'invisible': [('state', 'in', ('done', 'cancel'))]}"
+ attrs="{'invisible': [('state', '=', 'draft')]}"
confirm="Are you sure you want to cancel this record?"/>
- <button name="action_draft" string="Set to Draft" type="object"
+ <button name="action_draft" string="Set to Draft" type="object"
class="btn-secondary"
attrs="{'invisible': [('state', '!=', 'cancel')]}"
confirm="Are you sure you want to reset this record to draft?"/>
- <field name="state" widget="statusbar" readonly="1"/>
- </header>
- <sheet>
- <div class="oe_title">
- <h1>
- <field name="name" readonly="1" class="oe_inline"/>
- </h1>
- <hr/>
- </div>
- <group>
- <group>
- <field name="date" string="Date" readonly="1"/>
- <field name="return_type"/>
- <field name="in_num" string="BU/In"
- attrs="{
- 'invisible': [('return_type', 'not in', ['debit_memo', 'revisi_po', 'tukar_guling'])],
- 'required': [('return_type', 'in', ['debit_memo', 'revisi_po'])]
- }"/>
-
- <field name="out_num" string="BU/Out"
+ <field name="state" widget="statusbar" readonly="1"
+ statusbar_visible="draft,approval_sales,approval_logistic,approval_finance,done"/>
+ </header>
+ <sheet>
+ <div class="oe_title">
+ <h1>
+ <field name="name" readonly="1" class="oe_inline"/>
+ </h1>
+ <hr/>
+ </div>
+ <group>
+ <group>
+ <field name="date" string="Date" readonly="1"/>
+ <field name="return_type"/>
+ <field name="out_num" string="BU/Out"
attrs="{
'invisible': [('return_type', 'not in', ['revisi_so', 'credit_memo', 'tukar_guling'])],
'required': [('return_type', 'in', ['revisi_so', 'credit_memo'])]
}"/>
- </group>
- <group>
- <field name="ba_num" string="Nomor BA"/>
- <field name="notes"/>
-<!-- <field name="state" readonly="1"/>-->
- </group>
- </group>
-
- <!-- Product Lines -->
- <notebook>
- <page string="Product Lines" name="product_lines">
- <field name="line_ids">
- <tree string="Product Lines" editable="bottom">
- <field name="sequence" widget="handle"/>
- <field name="product_id" required="1"
+ </group>
+ <group>
+ <field name="ba_num" string="Nomor BA"/>
+ <field name="notes"/>
+ </group>
+ </group>
+ <!-- Product Lines -->
+ <notebook>
+ <page string="Product Lines" name="product_lines">
+ <field name="line_ids">
+ <tree string="Product Lines" editable="bottom">
+ <field name="sequence" widget="handle"/>
+ <field name="product_id" required="1"
options="{'no_create': True, 'no_create_edit': True}"/>
- <field name="name" force_save="1"/>
- <field name="product_uom_qty" string="Quantity"/>
- <field name="product_uom" string="UoM"
+ <field name="name" force_save="1"/>
+ <field name="product_uom_qty" string="Quantity"/>
+ <field name="product_uom" string="UoM"
options="{'no_create': True, 'no_create_edit': True}"/>
- </tree>
- </field>
- </page>
- </notebook>
- </sheet>
- </form>
- </field>
- </record>
- </data>
+ </tree>
+ </field>
+ </page>
+ </notebook>
+ </sheet>
+ </form>
+ </field>
+ </record>
+ </data>
</odoo> \ No newline at end of file
diff --git a/indoteknik_custom/views/tukar_guling_po.xml b/indoteknik_custom/views/tukar_guling_po.xml
new file mode 100644
index 00000000..840b625b
--- /dev/null
+++ b/indoteknik_custom/views/tukar_guling_po.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<odoo>
+ <data>
+ <!-- Action -->
+ <record id="action_pengajuan_tukar_guling_po" model="ir.actions.act_window">
+ <field name="name">Pengajuan Tukar Guling PO</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">tukar.guling.po</field>
+ <field name="view_mode">tree,form</field>
+ </record>
+
+ <menuitem
+ id="menu_pengajuan_tukar_guling_po"
+ name="Pengajuan Tukar Guling PO"
+ parent="purchase.menu_procurement_management"
+ sequence="4"
+ action="action_pengajuan_tukar_guling_po"
+ />
+
+ <!-- Sequence -->
+ <record id="seq_tukar_guling_po" model="ir.sequence">
+ <field name="name">Pengajuan Tukar Guling PO</field>
+ <field name="code">tukar.guling.po</field>
+ <field name="prefix">PTGPO/</field>
+ <field name="padding">5</field>
+ <field name="number_next">1</field>
+ <field name="number_increment">1</field>
+ <field name="company_id" eval="False"/>
+ </record>
+
+ <!-- Tree View -->
+ <record id="pengajuan_tukar_guling_po_tree" model="ir.ui.view">
+ <field name="name">pengajuan.tukar.guling.po.tree</field>
+ <field name="model">tukar.guling.po</field>
+ <field name="arch" type="xml">
+ <tree create="1" delete="1" default_order="create_date desc">
+ <field name="name"/>
+ <field name="date"/>
+ <field name="out_num" string="BU/Out"/>
+ <field name="ba_num" string="Nomor BA"/>
+ <field name="return_type" string="Return Type"/>
+ <field name="state" widget="badge"
+ decoration-info="state in ('draft', 'approval_sales', 'approval_logistic','approval_finance')"
+ decoration-success="state == 'done'"
+ decoration-muted="state == 'cancel'"
+ />
+ </tree>
+ </field>
+ </record>
+
+ <!-- Form View -->
+ <record id="pengajuan_tukar_guling_po_form" model="ir.ui.view">
+ <field name="name">pengajuan.tukar.guling.po.form</field>
+ <field name="model">tukar.guling.po</field>
+ <field name="arch" type="xml">
+ <form>
+ <header>
+ <button name="action_submit" string="Submit" type="object"
+ class="btn-primary"
+ attrs="{'invisible': [('state', '!=', 'draft')]}"/>
+ <button name="action_approve" string="Approve" type="object"
+ class="btn-primary"
+ attrs="{'invisible': [('state', 'not in', ['approval_sales', 'approval_logistic', 'approval_finance'])]}"/>
+ <button name="action_cancel" string="Cancel" type="object"
+ class="btn-secondary"
+ attrs="{'invisible': [('state', '=', 'draft')]}"
+ confirm="Are you sure you want to cancel this record?"/>
+ <button name="action_draft" string="Set to Draft" type="object"
+ class="btn-secondary"
+ attrs="{'invisible': [('state', '!=', 'cancel')]}"
+ confirm="Are you sure you want to reset this record to draft?"/>
+ <field name="state" widget="statusbar" readonly="1"
+ statusbar_visible="draft,approval_sales,approval_logistic,approval_finance,done"/>
+ </header>
+ <sheet>
+ <div class="oe_title">
+ <h1>
+ <field name="name" readonly="1" class="oe_inline"/>
+ </h1>
+ <hr/>
+ </div>
+ <group>
+ <group>
+ <field name="date" string="Date" readonly="1"/>
+ <field name="return_type"/>
+ <field name="out_num" string="BU/Out"
+ attrs="{
+ 'invisible': [('return_type', 'not in', ['revisi_po', 'debit_memo', 'tukar_guling'])],
+ 'required': [('return_type', 'in', ['revisi_po', 'debit_memo'])]
+ }"/>
+ </group>
+ <group>
+ <field name="ba_num" string="Nomor BA"/>
+ <field name="notes"/>
+ </group>
+ </group>
+ <notebook>
+ <page string="Product Lines" name="product_lines">
+ <field name="line_ids">
+ <tree string="Product Lines" editable="bottom">
+ <field name="sequence" widget="handle"/>
+ <field name="product_id" required="1"
+ options="{'no_create': True, 'no_create_edit': True}"/>
+ <field name="name" force_save="1"/>
+ <field name="product_uom_qty" string="Quantity"/>
+ <field name="product_uom" string="UoM"
+ options="{'no_create': True, 'no_create_edit': True}"/>
+ </tree>
+ </field>
+ </page>
+ </notebook>
+ </sheet>
+ </form>
+ </field>
+ </record>
+ </data>
+</odoo>