summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIndoteknik . <it@fixcomart.co.id>2025-09-02 17:35:47 +0700
committerIndoteknik . <it@fixcomart.co.id>2025-09-02 17:35:47 +0700
commitd43eb7ff8ffd4b11120a7354295e86736135344a (patch)
tree0e6bce3428149b694f12e22e29ba0ca561271fb9
parenta35dcc5907500e5189516459160c972bb72e1686 (diff)
(andri) add menu surat piutang
-rwxr-xr-xindoteknik_custom/__manifest__.py1
-rwxr-xr-xindoteknik_custom/models/__init__.py3
-rw-r--r--indoteknik_custom/models/letter_receivable.py90
-rwxr-xr-xindoteknik_custom/security/ir.model.access.csv4
-rw-r--r--indoteknik_custom/views/ir_sequence.xml9
-rw-r--r--indoteknik_custom/views/letter_receivable.xml79
6 files changed, 184 insertions, 2 deletions
diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py
index 9ebab15e..e300670a 100755
--- a/indoteknik_custom/__manifest__.py
+++ b/indoteknik_custom/__manifest__.py
@@ -178,6 +178,7 @@
# 'views/refund_sale_order.xml',
'views/update_date_planned_po_wizard_view.xml',
'views/unpaid_invoice_view.xml',
+ 'views/letter_receivable.xml',
],
'demo': [],
'css': [],
diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py
index ba3dbad9..c8910669 100755
--- a/indoteknik_custom/models/__init__.py
+++ b/indoteknik_custom/models/__init__.py
@@ -157,4 +157,5 @@ from . import refund_sale_order
from . import tukar_guling
from . import tukar_guling_po
from . import update_date_planned_po_wizard
-from . import unpaid_invoice_view \ No newline at end of file
+from . import unpaid_invoice_view
+from . import letter_receivable \ No newline at end of file
diff --git a/indoteknik_custom/models/letter_receivable.py b/indoteknik_custom/models/letter_receivable.py
new file mode 100644
index 00000000..541f64ff
--- /dev/null
+++ b/indoteknik_custom/models/letter_receivable.py
@@ -0,0 +1,90 @@
+from odoo import models, fields, api
+
+class SuratPiutang(models.Model):
+ _name = "surat.piutang"
+ _description = "Surat Piutang"
+ _inherit = ['mail.thread', 'mail.activity.mixin']
+
+ name = fields.Char(string="Nomor Surat", readonly=True, copy=False)
+ partner_id = fields.Many2one("res.partner", string="Customer", required=True)
+ tujuan_nama = fields.Char(string="Nama Tujuan")
+ tujuan_email = fields.Char(string="Email Tujuan")
+ perihal = fields.Selection([
+ ('sp1', 'Surat Peringatan Piutang'),
+ ('sp2', 'Surat Peringatan Piutang ke-2'),
+ ('sp3', 'Surat Peringatan Piutang ke-3')
+ ], string="Perihal", required=True, tracking=True)
+ line_ids = fields.One2many("surat.piutang.line", "surat_id", string="Invoice Lines")
+ state = fields.Selection([
+ ("draft", "Draft"),
+ ("sent", "Sent")
+ ], default="draft", tracking=True)
+ send_date = fields.Datetime(string="Tanggal Kirim", tracking=True)
+
+ currency_id = fields.Many2one('res.currency')
+
+ # Grand total (total sisa semua line yang dicentang)
+ grand_total = fields.Monetary(
+ string='Total Sisa',
+ currency_field='currency_id',
+ compute='_compute_grand_total',
+ )
+
+ @api.depends('line_ids.amount_residual', 'line_ids.selected')
+ def _compute_grand_total(self):
+ for rec in self:
+ rec.grand_total = sum(
+ line.amount_residual or 0.0 for line in rec.line_ids if line.selected
+ )
+
+ @api.onchange('partner_id')
+ def _onchange_partner_id(self):
+ if self.partner_id:
+ invoice_lines = self.env['unpaid.invoice.view'].search(
+ [('partner_id', '=', self.partner_id.id)],
+ order='new_invoice_day_to_due asc'
+ )
+ lines = [(0, 0, {
+ 'invoice_view_id': inv.id,
+ 'invoice_id': inv.invoice_id.id,
+ 'invoice_number': inv.invoice_number,
+ 'invoice_date': inv.invoice_date,
+ 'invoice_date_due': inv.invoice_date_due,
+ 'invoice_day_to_due': inv.invoice_day_to_due,
+ 'ref': inv.ref,
+ 'amount_residual': inv.amount_residual,
+ 'currency_id': inv.currency_id.id,
+ 'payment_term_id': inv.payment_term_id.id,
+ 'selected': False
+ }) for inv in invoice_lines]
+ self.line_ids = lines
+
+ @api.model
+ def create(self, vals):
+ # Generate nomor surat otomatis
+ if not vals.get("name"):
+ seq = self.env["ir.sequence"].next_by_code("surat.piutang") or "000"
+ today = fields.Date.today()
+ bulan_romawi = ["I","II","III","IV","V","VI","VII","VIII","IX","X","XI","XII"][today.month-1]
+ tahun = today.strftime("%y")
+ vals["name"] = f"{seq}/LO/FAT/IDG/{bulan_romawi}/{tahun}"
+
+ return super().create(vals)
+
+class SuratPiutangLine(models.Model):
+ _name = 'surat.piutang.line'
+ _description = 'Surat Piutang Line'
+
+ surat_id = fields.Many2one('surat.piutang', string='Surat Piutang', ondelete='cascade')
+ invoice_view_id = fields.Many2one('unpaid.invoice.view', string='Unpaid Invoice')
+ invoice_id = fields.Many2one('account.move', string='Invoice')
+ selected = fields.Boolean(string="Pilih", default=False)
+
+ invoice_number = fields.Char(string='Invoice Number')
+ invoice_date = fields.Date(string='Invoice Date')
+ invoice_date_due = fields.Date(string='Due Date')
+ invoice_day_to_due = fields.Integer(string='Day to Due')
+ ref = fields.Char(string='Reference')
+ amount_residual = fields.Monetary(string='Amount Due Signed')
+ currency_id = fields.Many2one('res.currency')
+ payment_term_id = fields.Many2one('account.payment.term', string='Payment Terms')
diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv
index 4649c743..25273893 100755
--- a/indoteknik_custom/security/ir.model.access.csv
+++ b/indoteknik_custom/security/ir.model.access.csv
@@ -196,4 +196,6 @@ access_purchase_order_update_date_wizard,access.purchase.order.update.date.wizar
access_sync_promise_date_wizard,access.sync.promise.date.wizard,model_sync_promise_date_wizard,base.group_user,1,1,1,1
access_sync_promise_date_wizard_line,access.sync.promise.date.wizard.line,model_sync_promise_date_wizard_line,base.group_user,1,1,1,1
access_change_date_planned_wizard,access.change.date.planned.wizard,model_change_date_planned_wizard,,1,1,1,1
-access_unpaid_invoice_view,access.unpaid.invoice.view,model_unpaid_invoice_view,base.group_user,1,1,1,1 \ No newline at end of file
+access_unpaid_invoice_view,access.unpaid.invoice.view,model_unpaid_invoice_view,base.group_user,1,1,1,1
+access_surat_piutang_user,surat.piutang user,model_surat_piutang,base.group_user,1,1,1,1
+access_surat_piutang_line_user,surat.piutang.line user,model_surat_piutang_line,base.group_user,1,1,1,1 \ No newline at end of file
diff --git a/indoteknik_custom/views/ir_sequence.xml b/indoteknik_custom/views/ir_sequence.xml
index 94c2cd07..4b8fec53 100644
--- a/indoteknik_custom/views/ir_sequence.xml
+++ b/indoteknik_custom/views/ir_sequence.xml
@@ -228,5 +228,14 @@
<field name="number_increment">1</field>
<field name="active">True</field>
</record>
+
+ <record id="seq_surat_piutang" model="ir.sequence">
+ <field name="name">Surat Piutang</field>
+ <field name="code">surat.piutang</field>
+ <field name="prefix"></field> <!-- format manual di model -->
+ <field name="padding">3</field>
+ <field name="number_next">1</field>
+ <field name="number_increment">1</field>
+ </record>
</data>
</odoo> \ No newline at end of file
diff --git a/indoteknik_custom/views/letter_receivable.xml b/indoteknik_custom/views/letter_receivable.xml
new file mode 100644
index 00000000..72eae640
--- /dev/null
+++ b/indoteknik_custom/views/letter_receivable.xml
@@ -0,0 +1,79 @@
+<odoo>
+ <!-- Tree View -->
+ <record id="view_surat_piutang_tree" model="ir.ui.view">
+ <field name="name">surat.piutang.tree</field>
+ <field name="model">surat.piutang</field>
+ <field name="arch" type="xml">
+ <tree string="Surat Piutang">
+ <field name="name"/>
+ <field name="partner_id"/>
+ <field name="perihal"/>
+ <field name="state"/>
+ <field name="send_date"/>
+ <field name="line_ids" widget="one2many_list"/>
+ </tree>
+ </field>
+ </record>
+
+ <!-- Form View -->
+ <record id="view_surat_piutang_form" model="ir.ui.view">
+ <field name="name">surat.piutang.form</field>
+ <field name="model">surat.piutang</field>
+ <field name="arch" type="xml">
+ <form string="Surat Piutang">
+ <header>
+ <field name="state" widget="statusbar" statusbar_visible="draft,sent"/>
+ <!-- <button name="action_send_surat" type="object" string="Kirim Surat"
+ states="draft" class="btn-primary"/> -->
+ </header>
+ <sheet>
+ <group>
+ <field name="name" readonly="1"/>
+ <field name="partner_id" options="{'no_create': True}"/>
+ <field name="perihal"/>
+ <field name="tujuan_nama"/>
+ <field name="tujuan_email"/>
+ <field name="send_date" readonly="1"/>
+ </group>
+ <notebook>
+ <page string="Invoice Lines">
+ <field name="line_ids">
+ <tree editable="bottom">
+ <field name="selected"/>
+ <field name="invoice_number" readonly="1" force_save="1"/>
+ <field name="ref" readonly="1" force_save="1"/>
+ <field name="invoice_date" readonly="1" force_save="1"/>
+ <field name="invoice_date_due" readonly="1" force_save="1"/>
+ <field name="invoice_day_to_due" readonly="1" force_save="1"/>
+ <field name="amount_residual" readonly="1" force_save="1" sum="Grand Total"/>
+ <!-- <field name="currency_id" readonly="1" force_save="1"/> -->
+ <field name="payment_term_id" readonly="1" force_save="1"/>
+ </tree>
+ </field>
+ </page>
+ </notebook>
+ </sheet>
+ </form>
+ </field>
+ </record>
+
+ <!-- Menu -->
+ <record id="menu_surat_piutang_root" model="ir.ui.menu">
+ <field name="name">Surat Piutang</field>
+ <field name="parent_id" ref="account.menu_finance"/>
+ <field name="sequence" eval="10"/>
+ </record>
+
+ <record id="action_surat_piutang" model="ir.actions.act_window">
+ <field name="name">Surat Piutang</field>
+ <field name="res_model">surat.piutang</field>
+ <field name="view_mode">tree,form</field>
+ <field name="view_id" ref="view_surat_piutang_tree"/>
+ </record>
+
+ <menuitem id="menu_surat_piutang"
+ name="Surat Piutang"
+ parent="account.menu_finance_receivables"
+ action="action_surat_piutang"
+ sequence="1"/>
+</odoo>