diff options
| author | it-fixcomart <it@fixcomart.co.id> | 2025-08-06 09:25:09 +0700 |
|---|---|---|
| committer | it-fixcomart <it@fixcomart.co.id> | 2025-08-06 09:25:09 +0700 |
| commit | 10d0e2bf639b31e58fd0d80a61062aa3ddc8f041 (patch) | |
| tree | fd92b9538c820e1419154a43f19bea1090d62465 | |
| parent | fcd98b0f038cfa1653b8b12df77750253ebd7a68 (diff) | |
| parent | c42bdba2996d85d328897e42e7a1d86001b3a14d (diff) | |
<hafid> change delivered api
19 files changed, 159 insertions, 36 deletions
diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index 33b2a4e3..d63f569b 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -607,9 +607,6 @@ class SaleOrder(controller.Controller): if is_flash_sale_item: is_has_disc = True _logger.info("Item is flash sale product - marked as discounted") - elif discount_percent > 0 and not global_flash_sale: - is_has_disc = True - _logger.info(f"Item has discount {discount_percent}% - marked as discounted") elif global_flash_sale: _logger.info("Global flash sale active but item not eligible - not marked as discounted") diff --git a/indoteknik_api/controllers/api_v1/stock_picking.py b/indoteknik_api/controllers/api_v1/stock_picking.py index 85b0fbba..762e17c5 100644 --- a/indoteknik_api/controllers/api_v1/stock_picking.py +++ b/indoteknik_api/controllers/api_v1/stock_picking.py @@ -125,28 +125,33 @@ class StockPicking(controller.Controller): @http.route(prefix + 'stock-picking/<scanid>/documentation', auth='public', methods=['PUT', 'OPTIONS'], csrf=False) @controller.Controller.must_authorized() def write_partner_stock_picking_documentation(self, **kw): - scanid = int(kw.get('scanid', 0)) + scanid = kw.get('scanid', '').strip() sj_document = kw.get('sj_document', False) paket_document = kw.get('paket_document', False) - params = {'sj_documentation': sj_document, - 'paket_documentation': paket_document, - 'driver_arrival_date': datetime.utcnow(), - } + params = { + 'sj_documentation': sj_document, + 'paket_documentation': paket_document, + 'driver_arrival_date': datetime.utcnow(), + } - picking_data = request.env['stock.picking'].search([('id', '=', scanid)], limit=1) + picking_data = False + if scanid.isdigit() and int(scanid) < 2147483647: + picking_data = request.env['stock.picking'].search([('id', '=', int(scanid))], limit=1) if not picking_data: picking_data = request.env['stock.picking'].search([('picking_code', '=', scanid)], limit=1) if not picking_data: return self.response(code=404, description='picking not found') + picking_data.write(params) return self.response({ 'name': picking_data.name }) + @http.route(prefix + 'webhook/biteship', type='json', auth='public', methods=['POST'], csrf=False) def update_status_from_biteship(self, **kw): _logger.info("Biteship Webhook: Request received at controller start (type='json').") diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py index 2a4db273..d1ae681a 100755 --- a/indoteknik_custom/__manifest__.py +++ b/indoteknik_custom/__manifest__.py @@ -174,6 +174,7 @@ # 'views/tukar_guling_return_views.xml' 'views/tukar_guling_po.xml', # 'views/refund_sale_order.xml', + 'views/update_date_planned_po_wizard_view.xml', ], 'demo': [], 'css': [], diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py index 51d25c1f..3a9f9312 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -156,3 +156,4 @@ from . import refund_sale_order # from . import patch from . import tukar_guling from . import tukar_guling_po +from . import update_date_planned_po_wizard
\ No newline at end of file diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index 1a6fad1c..4be6c984 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -94,6 +94,21 @@ class AccountMove(models.Model): compute='_compute_has_refund_so', ) + payment_date = fields.Date(string="Payment Date", compute='_compute_payment_date') + + def _compute_payment_date(self): + for move in self: + accountPayment = self.env['account.payment'] + + payment = accountPayment.search([]).filtered( + lambda p: move.id in p.reconciled_invoice_ids.ids + ) + + if payment: + move.payment_date = payment[0].date + else: + move.payment_date = False + # def name_get(self): # result = [] # for move in self: diff --git a/indoteknik_custom/models/commision.py b/indoteknik_custom/models/commision.py index 9f7df464..6d538b83 100644 --- a/indoteknik_custom/models/commision.py +++ b/indoteknik_custom/models/commision.py @@ -208,7 +208,7 @@ class CustomerCommision(models.Model): ('pending', 'Pending'), ('payment', 'Payment'), ], string='Payment Status', copy=False, readonly=True, tracking=3, default='pending') - note_finnance = fields.Text('Notes Finnance') + note_finnance = fields.Text('Notes Finance') reason_reject = fields.Char(string='Reason Reaject', tracking=True, track_visibility='onchange') approved_by = fields.Char(string='Approved By', tracking=True, track_visibility='always') @@ -399,6 +399,27 @@ class CustomerCommision(models.Model): # result = super(CustomerCommision, self).create(vals) # return result + def _fill_note_finance(self): + for rec in self: + fee_percent = rec.commision_percent or 0.0 + dpp = rec.total_dpp or 0.0 + + fee = dpp * fee_percent / 100 + pph21 = 0.5 * fee * 0.05 + fee_net = fee - pph21 + rec.note_finnance = ( + "Kelengkapan data penerima fee sudah lengkap (NPWP dan KTP)\n" + f"Perhitungan Fee ({fee_percent:.0f}%) dari nilai DPP pada Invoice terlampir sudah\n" + f"sesuai yaitu Rp {fee:,.0f}\n" + "Sesuai PMK No. 168 tahun 2023, komisi fee dikenakan PPH 21\n" + "sebesar :\n" + f"= 50% x Penghasilan Bruto x 5%\n" + f"= 50% x Rp {fee:,.0f} x 5%\n" + f"= Rp {pph21:,.0f}\n" + "Sehingga fee bersih sebesar\n" + f"= Rp {fee:,.0f} - Rp {pph21:,.0f}\n" + f"= Rp {fee_net:,.0f}" + ) def action_confirm_customer_commision(self): jakarta_tz = pytz.timezone('Asia/Jakarta') now = datetime.now(jakarta_tz) @@ -425,6 +446,8 @@ class CustomerCommision(models.Model): elif self.status == 'pengajuan4' and self.env.user.id == 1272: for line in self.commision_lines: line.invoice_id.is_customer_commision = True + if self.commision_type == 'fee': + self._fill_note_finance() self.status = 'approved' self.approved_by = (self.approved_by + ', ' if self.approved_by else '') + self.env.user.name self.date_approved_accounting = now_naive diff --git a/indoteknik_custom/models/cust_commision.py b/indoteknik_custom/models/cust_commision.py index c3105cfd..05c68935 100644 --- a/indoteknik_custom/models/cust_commision.py +++ b/indoteknik_custom/models/cust_commision.py @@ -34,4 +34,3 @@ class CustCommision(models.Model): for rec in duplicate_partner: if self.commision_type == rec.commision_type: raise UserError('Partner already exists') -
\ No newline at end of file diff --git a/indoteknik_custom/models/purchase_order.py b/indoteknik_custom/models/purchase_order.py index 27aca0d1..103a9131 100755 --- a/indoteknik_custom/models/purchase_order.py +++ b/indoteknik_custom/models/purchase_order.py @@ -1083,9 +1083,9 @@ class PurchaseOrder(models.Model): # Tambahan: redirect ke BU hanya untuk single PO yang berhasil dikonfirmasi _logger.info("Jumlah PO: %s | State: %s", len(self), self.state) - if len(self) == 1: - _logger.info("Redirecting ke BU") - return self.action_view_related_bu() + # if len(self) == 1: + # _logger.info("Redirecting ke BU") + # return self.action_view_related_bu() return res diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 4e36a9fb..94cfdc39 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -163,7 +163,7 @@ class SaleOrder(models.Model): carrier_id = fields.Many2one('delivery.carrier', string='Shipping Method', tracking=3) have_visit_service = fields.Boolean(string='Have Visit Service', compute='_have_visit_service', help='To compute is customer get visit service') - delivery_amt = fields.Float(string='Delivery Amt', copy=False) + delivery_amt = fields.Float(string='Delivery Amt', copy=False, tracking=True) shipping_cost_covered = fields.Selection([ ('indoteknik', 'Indoteknik'), ('customer', 'Customer') @@ -3088,6 +3088,24 @@ class SaleOrder(models.Model): except: pass + #payment term vals + if 'payment_term_id' in vals and any( + order.approval_status in ['pengajuan1', 'pengajuan2', 'approved'] for order in self): + raise UserError( + "Payment Term tidak dapat diubah karena Sales Order sedang dalam proses approval atau sudah diapprove.") + + if 'payment_term_id' in vals: + for order in self: + partner = order.partner_id.parent_id or order.partner_id + customer_payment_term = partner.property_payment_term_id + if vals['payment_term_id'] != customer_payment_term.id: + raise UserError( + f"Payment Term berbeda pada Master Data Customer. " + f"Harap ganti ke '{customer_payment_term.name}' " + f"sesuai dengan payment term yang terdaftar pada customer." + ) + + res = super(SaleOrder, self).write(vals) # Update before margin setelah write diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py index 92ca6e39..f2f5f52a 100644 --- a/indoteknik_custom/models/stock_picking.py +++ b/indoteknik_custom/models/stock_picking.py @@ -810,6 +810,7 @@ class StockPicking(models.Model): self.biteship_tracking_id = data.get("courier", {}).get("tracking_id", "") self.biteship_waybill_id = data.get("courier", {}).get("waybill_id", "") self.delivery_tracking_no = self.biteship_waybill_id + self.biteship_shipping_price = data.get("price", 0.0) waybill_id = self.biteship_waybill_id diff --git a/indoteknik_custom/models/tukar_guling_po.py b/indoteknik_custom/models/tukar_guling_po.py index 92d8c9a6..467fff44 100644 --- a/indoteknik_custom/models/tukar_guling_po.py +++ b/indoteknik_custom/models/tukar_guling_po.py @@ -74,19 +74,19 @@ class TukarGulingPO(models.Model): return res - @api.constrains('return_type', 'operations') - def _check_bill_on_revisi_po(self): - for record in self: - if record.return_type == 'revisi_po' and record.origin: - bills = self.env['account.move'].search([ - ('invoice_origin', 'ilike', record.origin), - ('move_type', '=', 'in_invoice'), # hanya vendor bill - ('state', 'not in', ['draft', 'cancel']) - ]) - if bills: - raise ValidationError( - _("Tidak bisa memilih Return Type 'Revisi PO' karena PO %s sudah dibuat vendor bill.") % record.origin - ) + # @api.constrains('return_type', 'operations') + # def _check_bill_on_revisi_po(self): + # for record in self: + # if record.return_type == 'revisi_po' and record.origin: + # bills = self.env['account.move'].search([ + # ('invoice_origin', 'ilike', record.origin), + # ('move_type', '=', 'in_invoice'), # hanya vendor bill + # ('state', 'not in', ['draft', 'cancel']) + # ]) + # if bills: + # raise ValidationError( + # _("Tidak bisa memilih Return Type 'Revisi PO' karena PO %s sudah dibuat vendor bill.") % record.origin + # ) @api.onchange('operations') def _onchange_operations(self): @@ -281,7 +281,7 @@ class TukarGulingPO(models.Model): def write(self, vals): if self.operations.picking_type_id.id not in [75, 28]: raise UserError("❌ Tidak bisa retur bukan BU/INPUT atau BU/PUT!") - self._check_bill_on_revisi_po() + # self._check_bill_on_revisi_po() tipe = vals.get('return_type', self.return_type) if self.operations and self.operations.picking_type_id.id == 28 and tipe == 'tukar_guling': @@ -349,7 +349,7 @@ class TukarGulingPO(models.Model): def action_submit(self): self.ensure_one() - self._check_bill_on_revisi_po() + # self._check_bill_on_revisi_po() self._validate_product_lines() self._check_not_allow_tukar_guling_on_bu_input() @@ -385,7 +385,7 @@ class TukarGulingPO(models.Model): def action_approve(self): self.ensure_one() self._validate_product_lines() - self._check_bill_on_revisi_po() + # self._check_bill_on_revisi_po() self._check_not_allow_tukar_guling_on_bu_input() if not self.operations: diff --git a/indoteknik_custom/models/update_date_planned_po_wizard.py b/indoteknik_custom/models/update_date_planned_po_wizard.py new file mode 100644 index 00000000..a0d241c8 --- /dev/null +++ b/indoteknik_custom/models/update_date_planned_po_wizard.py @@ -0,0 +1,14 @@ +from odoo import models, fields, api + +class PurchaseOrderUpdateDateWizard(models.TransientModel): + _name = 'purchase.order.update.date.wizard' + _description = 'Wizard to Update Receipt Date on Purchase Order Lines' + + date_planned = fields.Datetime(string="New Receipt Date", required=True) + + def action_update_date(self): + active_ids = self.env.context.get('active_ids', []) + orders = self.env['purchase.order'].browse(active_ids) + for order in orders: + order.write({'date_planned': self.date_planned}) + return {'type': 'ir.actions.act_window_close'} diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index 9b43bf2a..d6e44f9d 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -191,4 +191,5 @@ access_tukar_guling_all_users,tukar.guling.all.users,model_tukar_guling,base.gro access_tukar_guling_line_all_users,tukar.guling.line.all.users,model_tukar_guling_line,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_po_all_users,tukar.guling.line.po.all.users,model_tukar_guling_line_po,base.group_user,1,1,1,1 -access_tukar_guling_mapping_koli_all_users,tukar.guling.mapping.koli.all.users,model_tukar_guling_mapping_koli,base.group_user,1,1,1,1
\ No newline at end of file +access_tukar_guling_mapping_koli_all_users,tukar.guling.mapping.koli.all.users,model_tukar_guling_mapping_koli,base.group_user,1,1,1,1 +access_purchase_order_update_date_wizard,access.purchase.order.update.date.wizard,model_purchase_order_update_date_wizard,base.group_user,1,1,1,1
\ No newline at end of file diff --git a/indoteknik_custom/views/account_move.xml b/indoteknik_custom/views/account_move.xml index 9b1c791b..23f2d931 100644 --- a/indoteknik_custom/views/account_move.xml +++ b/indoteknik_custom/views/account_move.xml @@ -29,6 +29,7 @@ </field> <field name="payment_reference" position="after"> <field name="date_completed" readonly="1" attrs="{'invisible': [('move_type', '!=', 'out_invoice')]}"/> + <field name="payment_date" readonly="1" attrs="{'invisible': [('move_type', '!=', 'out_invoice')]}"/> <field name="reklas_id" attrs="{'invisible': [('move_type', '!=', 'out_invoice')]}"/> </field> <field name="invoice_date" position="after"> diff --git a/indoteknik_custom/views/purchase_order.xml b/indoteknik_custom/views/purchase_order.xml index fedcb4f9..15cdc788 100755 --- a/indoteknik_custom/views/purchase_order.xml +++ b/indoteknik_custom/views/purchase_order.xml @@ -428,4 +428,24 @@ <field name="code">action = records.open_form_multi_cancel()</field> </record> </data> + <data> + <record id="action_update_receipt_date_po" model="ir.actions.server"> + <field name="name">Update Receipt Date</field> + <field name="model_id" ref="purchase.model_purchase_order"/> + <field name="binding_model_id" ref="purchase.model_purchase_order"/> + <field name="state">code</field> + <field name="binding_view_types">list</field> + <field name="code"> + action = { + 'type': 'ir.actions.act_window', + 'res_model': 'purchase.order.update.date.wizard', + 'view_mode': 'form', + 'target': 'new', + 'context': { + 'active_ids': env.context.get('active_ids', []), + }, + } + </field> + </record> + </data> </odoo>
\ No newline at end of file diff --git a/indoteknik_custom/views/res_partner.xml b/indoteknik_custom/views/res_partner.xml index a030a75c..38cd2756 100644 --- a/indoteknik_custom/views/res_partner.xml +++ b/indoteknik_custom/views/res_partner.xml @@ -217,7 +217,7 @@ <group string="Aging Info"> <field name="avg_aging" readonly="1"/> <field name="payment_difficulty" attrs="{'readonly': [('parent_id', '!=', False)]}" /> - <field name="payment_history_url" readonly="1" /> + <field name="payment_history_url" readonly="1" widget="url"/> </group> </page> </notebook> diff --git a/indoteknik_custom/views/sale_order.xml b/indoteknik_custom/views/sale_order.xml index e8f41ca3..868bce7b 100755 --- a/indoteknik_custom/views/sale_order.xml +++ b/indoteknik_custom/views/sale_order.xml @@ -355,8 +355,9 @@ </field> <field name="payment_term_id" position="attributes"> <attribute name="attrs"> - {'readonly': [('approval_status', '=', 'approved'), ('state', 'not in', - ['cancel', 'draft'])]} + {'readonly': ['|', ('approval_status', 'in', ['pengajuan1', 'pengajuan2', 'approved']), + ('state', 'not in', + ['cancel', 'draft'])]} </attribute> </field> diff --git a/indoteknik_custom/views/update_date_planned_po_wizard_view.xml b/indoteknik_custom/views/update_date_planned_po_wizard_view.xml new file mode 100644 index 00000000..6b3ab991 --- /dev/null +++ b/indoteknik_custom/views/update_date_planned_po_wizard_view.xml @@ -0,0 +1,25 @@ +<odoo> + <record id="view_update_date_planned_po_wizard_form" model="ir.ui.view"> + <field name="name">purchase.order.update.date.wizard.form</field> + <field name="model">purchase.order.update.date.wizard</field> + <field name="arch" type="xml"> + <form string="Update Receipt Date"> + <group> + <field name="date_planned"/> + </group> + <footer> + <button string="Apply" type="object" name="action_update_date" class="btn-primary"/> + <button string="Cancel" special="cancel"/> + </footer> + </form> + </field> + </record> + + <record id="action_update_date_planned_po_wizard" model="ir.actions.act_window"> + <field name="name">Update Receipt Date</field> + <field name="res_model">purchase.order.update.date.wizard</field> + <field name="view_mode">form</field> + <field name="target">new</field> + </record> + </odoo> +
\ No newline at end of file diff --git a/indoteknik_custom/views/user_company_request.xml b/indoteknik_custom/views/user_company_request.xml index 88d04c64..5f296cb0 100644 --- a/indoteknik_custom/views/user_company_request.xml +++ b/indoteknik_custom/views/user_company_request.xml @@ -31,7 +31,8 @@ <group> <field name="user_id" readonly="1"/> <field name="similar_company_ids" invisible="1"/> - <field name="user_company_id" domain="[('id', 'in', similar_company_ids)]"/> +<!-- <field name="user_company_id" domain="[('id', 'in', similar_company_ids)]"/>--> + <field name="user_company_id" /> <field name="user_input" readonly="1"/> <field name="is_approve" |
