summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xindoteknik_custom/__manifest__.py2
-rw-r--r--indoteknik_custom/models/account_move.py28
-rw-r--r--indoteknik_custom/models/approval_payment_term.py3
-rw-r--r--indoteknik_custom/models/res_partner.py11
-rwxr-xr-xindoteknik_custom/models/sale_order.py24
-rw-r--r--indoteknik_custom/report/purchase_report.xml162
-rw-r--r--indoteknik_custom/views/res_partner.xml3
-rwxr-xr-xindoteknik_custom/views/sale_order.xml9
8 files changed, 232 insertions, 10 deletions
diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py
index 31685005..09a3aa6f 100755
--- a/indoteknik_custom/__manifest__.py
+++ b/indoteknik_custom/__manifest__.py
@@ -166,6 +166,7 @@
'report/report_invoice.xml',
'report/report_picking.xml',
'report/report_sale_order.xml',
+ 'report/purchase_report.xml',
'views/vendor_sla.xml',
'views/coretax_faktur.xml',
'views/public_holiday.xml',
@@ -177,6 +178,7 @@
'views/tukar_guling_po.xml',
# 'views/refund_sale_order.xml',
'views/update_date_planned_po_wizard_view.xml',
+ # 'views/reimburse.xml',
],
'demo': [],
'css': [],
diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py
index c93cfb76..70cd07e4 100644
--- a/indoteknik_custom/models/account_move.py
+++ b/indoteknik_custom/models/account_move.py
@@ -105,6 +105,34 @@ class AccountMove(models.Model):
tracking=True
)
+ # def _check_and_lock_cbd(self):
+ # cbd_term = self.env['account.payment.term'].browse(26)
+ # today = date.today()
+
+ # # Cari semua invoice overdue
+ # overdue_invoices = self.search([
+ # ('move_type', '=', 'out_invoice'),
+ # ('state', '=', 'posted'),
+ # ('payment_state', 'not in', ['paid', 'in_payment', 'reversed']),
+ # ('invoice_date_due', '!=', False),
+ # ('invoice_date_due', '<=', today - timedelta(days=30)),
+ # ], limit=3)
+
+ # _logger.info(f"Found {len(overdue_invoices)} overdue invoices for CBD lock check.")
+ # _logger.info(f"Overdue Invoices: {overdue_invoices.mapped('name')}")
+
+ # # Ambil partner unik dari invoice
+ # partners_to_lock = overdue_invoices.mapped('partner_id').filtered(lambda p: not p.is_cbd_locked)
+ # _logger.info(f"Partners to lock: {partners_to_lock.mapped('name')}")
+
+ # # Lock hanya partner yang belum locked
+ # if partners_to_lock:
+ # partners_to_lock.write({
+ # 'is_cbd_locked': True,
+ # 'property_payment_term_id': cbd_term.id,
+ # })
+
+
def compute_partial_payment(self):
for move in self:
if move.amount_total_signed > 0 and move.amount_residual_signed > 0 and move.payment_state == 'partial':
diff --git a/indoteknik_custom/models/approval_payment_term.py b/indoteknik_custom/models/approval_payment_term.py
index 61339b99..7cab91f1 100644
--- a/indoteknik_custom/models/approval_payment_term.py
+++ b/indoteknik_custom/models/approval_payment_term.py
@@ -172,7 +172,8 @@ class ApprovalPaymentTerm(models.Model):
'blocking_stage': self.blocking_stage,
'warning_stage': self.warning_stage,
'active_limit': self.active_limit,
- 'property_payment_term_id': self.property_payment_term_id.id
+ 'property_payment_term_id': self.property_payment_term_id.id,
+ 'is_locked_cbd': False,
})
self.approve_date = datetime.utcnow()
self.state = 'approved'
diff --git a/indoteknik_custom/models/res_partner.py b/indoteknik_custom/models/res_partner.py
index 148a3fd0..36570e8f 100644
--- a/indoteknik_custom/models/res_partner.py
+++ b/indoteknik_custom/models/res_partner.py
@@ -1,6 +1,6 @@
from odoo import models, fields, api
from odoo.exceptions import UserError, ValidationError
-from datetime import datetime
+from datetime import datetime, timedelta
from odoo.http import request
import re
import requests
@@ -181,10 +181,8 @@ class ResPartner(models.Model):
payment_difficulty = fields.Selection([('bermasalah', 'Bermasalah'),('sulit', 'Sulit'),('agak_sulit', 'Agak Sulit'),('normal', 'Normal')], string='Payment Difficulty', tracking=3)
payment_history_url = fields.Text(string='Payment History URL')
- # no compute
- # payment_diff = fields.Selection([('bermasalah', 'Bermasalah'),('sulit', 'Sulit'),('agak_sulit', 'Agak Sulit'),('normal', 'Normal')], string='Payment Difficulty', tracking=3)
-
- # tidak terpakai
+ is_cbd_locked = fields.Boolean("Locked to CBD?", default=False, tracking=True, help="Jika dicentang, maka partner ini terkunci pada payment term CBD karena memiliki invoice yang sudah jatuh tempo lebih dari 30 hari.")
+
@api.model
def _default_payment_term(self):
@@ -193,9 +191,10 @@ class ResPartner(models.Model):
property_payment_term_id = fields.Many2one(
'account.payment.term',
string='Payment Terms',
- default=_default_payment_term
+ default=_default_payment_term, tracking=3
)
+
@api.depends("street", "street2", "city", "state_id", "country_id", "blok", "nomor", "rt", "rw", "kelurahan_id",
"kecamatan_id")
def _alamat_lengkap_text(self):
diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py
index 9952af9a..76d4d7e7 100755
--- a/indoteknik_custom/models/sale_order.py
+++ b/indoteknik_custom/models/sale_order.py
@@ -393,6 +393,26 @@ class SaleOrder(models.Model):
('paid', 'Full Paid'),
('no_invoice', 'No Invoice'),
], string="Payment Status Invoice", compute="_compute_payment_state_custom", store=False)
+ partner_is_cbd_locked = fields.Boolean(
+ string="Partner Locked CBD",
+ compute="_compute_partner_is_cbd_locked"
+ )
+
+ @api.depends('partner_id.is_cbd_locked')
+ def _compute_partner_is_cbd_locked(self):
+ for order in self:
+ order.partner_is_cbd_locked = order.partner_id.is_cbd_locked
+
+
+ @api.constrains('payment_term_id', 'partner_id', 'state')
+ def _check_cbd_lock_sale_order(self):
+ # cbd_term = self.env['account.payment.term'].browse(26)
+ for rec in self:
+ if rec.state == 'draft' and rec.partner_id.is_cbd_locked:
+ # if rec.payment_term_id and rec.payment_term_id != cbd_term:
+ raise ValidationError(
+ "Customer ini terkunci ke CBD, hanya boleh pakai Payment Term CBD."
+ )
@api.depends('invoice_ids.payment_state', 'invoice_ids.amount_total', 'invoice_ids.amount_residual')
def _compute_payment_state_custom(self):
@@ -2115,8 +2135,8 @@ class SaleOrder(models.Model):
if self.payment_term_id.id == 31 and self.total_percent_margin < 25:
raise UserError("Jika ingin menggunakan Tempo 90 Hari maka margin harus di atas 25%")
- if self.warehouse_id.id != 8 and self.warehouse_id.id != 10: # GD Bandengan
- raise UserError('Gudang harus Bandengan')
+ if self.warehouse_id.id != 8 and self.warehouse_id.id != 10 and self.warehouse_id.id != 12: # GD Bandengan / Pameran
+ raise UserError('Gudang harus Bandengan atau Pameran')
if self.state not in ['draft', 'sent']:
raise UserError("Status harus draft atau sent")
diff --git a/indoteknik_custom/report/purchase_report.xml b/indoteknik_custom/report/purchase_report.xml
new file mode 100644
index 00000000..9d7f4028
--- /dev/null
+++ b/indoteknik_custom/report/purchase_report.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+ <data>
+ <!-- Report Action -->
+ <record id="action_report_purchaseorder_website" model="ir.actions.report">
+ <field name="name">Purchase Order (Website)</field>
+ <field name="model">purchase.order</field>
+ <field name="report_type">qweb-pdf</field>
+ <field name="report_name">indoteknik_custom.report_purchaseorder_website</field>
+ <field name="report_file">indoteknik_custom.report_purchaseorder_website</field>
+ <field name="print_report_name">
+ ('PO - %s - %s' % (object.partner_id.name, object.name))
+ </field>
+ <field name="binding_model_id" ref="purchase.model_purchase_order"/>
+ <field name="binding_type">report</field>
+ </record>
+ </data>
+
+ <!-- Wrapper Template -->
+ <template id="report_purchaseorder_website">
+ <t t-call="web.html_container">
+ <t t-foreach="docs" t-as="doc">
+ <t t-call="indoteknik_custom.report_purchaseorder_website_document" t-lang="doc.partner_id.lang"/>
+ </t>
+ </t>
+ </template>
+
+ <!-- Document Template -->
+<template id="report_purchaseorder_website_document">
+ <t t-call="web.external_layout">
+ <t t-set="doc" t-value="doc.with_context(lang=doc.partner_id.lang)" />
+
+ <div class="page">
+ <!-- Header Image -->
+ <div class="mb16">
+ <img src="https://erp.indoteknik.com/api/image/ir.attachment/datas/2498521"
+ style="width:100%; max-height:100px; object-fit:contain;"/>
+ </div>
+
+ <!-- Title -->
+ <h2 class="text-center mb4" style="color:#d32f2f; font-weight:bold;">
+ PURCHASE ORDER
+ </h2>
+ <h4 class="text-center mb32">
+ No. <span t-field="doc.name"/>
+ </h4>
+
+ <!-- Top Info sejajar -->
+ <div class="row mb16" style="font-size:12px;">
+ <div class="col-4">
+ <strong>Term Of Payment:</strong>
+ <span t-field="doc.payment_term_id.name"/>
+ </div>
+ <div class="col-4">
+ <strong>Order Date:</strong>
+ <span t-field="doc.date_order" t-options='{"widget": "date"}'/>
+ </div>
+ <div class="col-4">
+ <strong>Responsible:</strong>
+ <span t-field="doc.user_id"/>
+ </div>
+ </div>
+
+ <!-- Vendor & Shipping Info sejajar -->
+ <div class="row mb32" style="font-size:12px;">
+ <div class="col-6" style="border:1px solid #ccc; padding:8px;">
+ <strong>Alamat Pengiriman:</strong><br/>
+ PT Indoteknik (Bandengan 1 Depan)<br/>
+ Jl. Bandengan Utara Komp A 8 B<br/>
+ RT. Penjaringan, Kec. Penjaringan, Jakarta (BELAKANG INDOMARET)<br/>
+ JK 14440<br/>
+ Indonesia
+ </div>
+ <div class="col-6" style="border:1px solid #ccc; padding:8px;">
+ <strong>Nama Vendor:</strong><br/>
+ <div t-field="doc.partner_id"
+ t-options='{"widget": "contact", "fields": ["address", "name", "phone"],
+ "no_marker": True, "phone_icons": True}'/>
+ </div>
+ </div>
+
+ <!-- Order Lines -->
+ <table class="table table-sm o_main_table" style="font-size:11px; border:1px solid #000; border-collapse: collapse; width:100%;">
+ <thead style="display: table-row-group; background:#f5f5f5;">
+ <tr>
+ <th style="border:1px solid #000; padding:4px;">Description</th>
+ <th class="text-right" style="border:1px solid #000; padding:4px;">Quantity</th>
+ <th class="text-right" style="border:1px solid #000; padding:4px;">Unit Price</th>
+ <th class="text-right" style="border:1px solid #000; padding:4px;">Taxes</th>
+ <th class="text-right" style="border:1px solid #000; padding:4px;">Subtotal</th>
+ </tr>
+ </thead>
+ <tbody>
+ <t t-foreach="doc.order_line" t-as="line">
+ <!-- Main row -->
+ <tr>
+ <td style="border:1px solid #000; padding:4px;">
+ <span t-field="line.name"/>
+ </td>
+ <td class="text-right" style="border:1px solid #000; padding:4px;">
+ <span t-field="line.product_qty"/>
+ <span t-field="line.product_uom"/>
+ </td>
+ <td class="text-right" style="border:1px solid #000; padding:4px;">
+ <span t-field="line.price_unit"/>
+ </td>
+ <td class="text-right" style="border:1px solid #000; padding:4px;">
+ <span t-esc="', '.join(map(lambda x: (x.description or x.name), line.taxes_id))"/>
+ </td>
+ <td class="text-right" style="border:1px solid #000; padding:4px;">
+ <span t-field="line.price_subtotal"/>
+ </td>
+ </tr>
+ <!-- Website Description row -->
+ <t t-if="line.product_id.website_description">
+ <tr>
+ <td colspan="5" style="border:1px solid #000; padding:6px; font-size:10px; color:#555;">
+ <div t-raw="line.product_id.website_description"/>
+ </td>
+ </tr>
+ </t>
+ </t>
+ </tbody>
+ </table>
+
+ <!-- Totals -->
+ <div class="clearfix">
+ <div class="row">
+ <div class="col-4 ml-auto">
+ <table class="table table-sm" style="border:1px solid #000; border-collapse: collapse; width:100%;">
+ <tr>
+ <td style="border:1px solid #000; padding:4px;"><strong>Subtotal</strong></td>
+ <td class="text-right" style="border:1px solid #000; padding:4px;">
+ <span t-field="doc.amount_untaxed"/>
+ </td>
+ </tr>
+ <tr>
+ <td style="border:1px solid #000; padding:4px;">Taxes</td>
+ <td class="text-right" style="border:1px solid #000; padding:4px;">
+ <span t-field="doc.amount_tax"/>
+ </td>
+ </tr>
+ <tr class="o_total">
+ <td style="border:1px solid #000; padding:4px;"><strong>Total</strong></td>
+ <td class="text-right" style="border:1px solid #000; padding:4px;">
+ <span t-field="doc.amount_total"/>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </div>
+ </div>
+
+ <!-- Notes -->
+ <div class="mt32" style="font-size:11px;">
+ <p t-field="doc.notes"/>
+ </div>
+ </div>
+ </t>
+ </template>
+
+</odoo>
diff --git a/indoteknik_custom/views/res_partner.xml b/indoteknik_custom/views/res_partner.xml
index ca1a36de..7d5be3b7 100644
--- a/indoteknik_custom/views/res_partner.xml
+++ b/indoteknik_custom/views/res_partner.xml
@@ -21,6 +21,7 @@
<field name="reference_number"/>
</field>
<field name="property_payment_term_id" position="after">
+ <field name="is_cbd_locked" readonly="1"/>
<field name="user_payment_terms_sales" readonly="1"/>
<field name="date_payment_terms_sales" readonly="1"/>
</field>
@@ -107,7 +108,7 @@
<field name="reminder_invoices"/>
</xpath>
<xpath expr="//field[@name='property_payment_term_id']" position="attributes">
- <attribute name="readonly">0</attribute>
+ <attribute name="readonly">1</attribute>
</xpath>
<xpath expr="//field[@name='property_supplier_payment_term_id']" position="attributes">
<attribute name="readonly">1</attribute>
diff --git a/indoteknik_custom/views/sale_order.xml b/indoteknik_custom/views/sale_order.xml
index 156c48d7..326fd560 100755
--- a/indoteknik_custom/views/sale_order.xml
+++ b/indoteknik_custom/views/sale_order.xml
@@ -41,6 +41,15 @@
string="Refund"
class="btn-primary" />
</xpath>
+ <xpath expr="//sheet" position="before">
+ <field name="partner_is_cbd_locked" invisible="1"/>
+ <div class="alert alert-danger"
+ role="alert"
+ style="height: 40px; margin-bottom:0px;"
+ attrs="{'invisible':['|', ('partner_is_cbd_locked','=',False), ('state', 'not in', ['draft', 'cancel'])]}">
+ <strong>Warning!</strong> Payment Terms Customer terkunci menjadi <b>Cash Before Delivery (C.B.D.)</b> karena ada invoice telah jatuh tempo <b>30 hari</b>. Silakan ajukan <b>Approval Payment Term</b> untuk membuka kunci.
+ </div>
+ </xpath>
<div class="oe_button_box" name="button_box">
<field name="advance_payment_move_ids" invisible="1"/>
<button name="action_open_advance_payment_moves"