diff options
22 files changed, 369 insertions, 32 deletions
diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index 4afeb21b..6815bf6c 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -395,7 +395,8 @@ class SaleOrder(controller.Controller): # Fetch partner details sales_partner = request.env['res.partner'].browse(params['value']['partner_id']) - + partner_invoice = request.env['res.partner'].browse(params['value']['partner_invoice_id']) + main_partner = partner_invoice.get_main_parent() parameters = { 'warehouse_id': 8, 'carrier_id': 1, @@ -411,7 +412,7 @@ class SaleOrder(controller.Controller): 'partner_id': params['value']['partner_id'], 'partner_shipping_id': params['value']['partner_shipping_id'], 'real_shipping_id': params['value']['partner_shipping_id'], - 'partner_invoice_id': params['value']['partner_invoice_id'], + 'partner_invoice_id': main_partner.id, 'real_invoice_id': params['value']['partner_invoice_id'], 'partner_purchase_order_name': params['value']['po_number'], 'partner_purchase_order_file': params['value']['po_file'], @@ -428,7 +429,7 @@ class SaleOrder(controller.Controller): 'npwp': sales_partner.npwp or '0', # Get NPWP from partner 'sppkp': sales_partner.sppkp, # Get SPPKP from partner 'email': sales_partner.email, # Get Email from partner - 'user_id': 3222 # User ID: Nadia Rauhadatul Firdaus + 'user_id': 11314 # User ID: Boy Revandi } sales_partner = request.env['res.partner'].browse(parameters['partner_id']) diff --git a/indoteknik_api/controllers/api_v1/user.py b/indoteknik_api/controllers/api_v1/user.py index 1d26d356..c0974367 100644 --- a/indoteknik_api/controllers/api_v1/user.py +++ b/indoteknik_api/controllers/api_v1/user.py @@ -98,7 +98,7 @@ class User(controller.Controller): user.partner_id.npwp = '00.000.000.0-000.000' user.partner_id.sppkp = '-' user.partner_id.nama_wajib_pajak = user.name - user.partner_id.user_id = 3222 + user.partner_id.user_id = 11314 user.partner_id.property_account_receivable_id = 395 user.partner_id.property_account_payable_id = 438 data = { @@ -208,7 +208,7 @@ class User(controller.Controller): 'email': email_partner, 'street': alamat_bisnis, 'company_type': 'company', - 'user_id': 3222, + 'user_id': 11314, 'property_account_receivable_id': 395, 'property_account_payable_id': 438, 'active': False, @@ -253,7 +253,7 @@ class User(controller.Controller): user.partner_id.npwp = '00.000.000.0-000.000' user.partner_id.sppkp = '-' user.partner_id.nama_wajib_pajak = name - user.partner_id.user_id = 3222 + user.partner_id.user_id = 11314 user.partner_id.property_account_receivable_id= 395 user.partner_id.property_account_payable_id = 438 @@ -605,7 +605,7 @@ class User(controller.Controller): 'email': email_partner, 'street': alamat_bisnis, 'company_type': 'company', - 'user_id': 3222, + 'user_id': 11314, 'property_account_receivable_id': 395, 'property_account_payable_id': 438, 'active': False, diff --git a/indoteknik_api/controllers/api_v1/voucher.py b/indoteknik_api/controllers/api_v1/voucher.py index 910488d1..9ffeeace 100644 --- a/indoteknik_api/controllers/api_v1/voucher.py +++ b/indoteknik_api/controllers/api_v1/voucher.py @@ -22,9 +22,14 @@ class Voucher(controller.Controller): code = kw.get('code') type = kw.get('type') user_id = int(kw.get('user_id', 0)) + partner_id = int(kw.get('partner_id', 0)) source = kw.get('source') visibility = ['public'] + user = request.env['res.users'].search([('id', '=', user_id)], limit=1) + if not user: + return self.response([]) + domain = [] if code: visibility.append('private') @@ -37,14 +42,19 @@ class Voucher(controller.Controller): type = type.split(',') domain += [('apply_type', 'in', type)] + if partner_id: + partner = request.env['res.partner'].search([('id', '=', partner_id)], limit=1) + main_parent = partner.get_main_parent() + if main_parent and main_parent.company_type: + domain += [('account_type', 'in', ['all',main_parent.company_type])] + # domain += [('account_type', 'in', main_parent.company_type)] + + domain += [('visibility', 'in', visibility)] vouchers = request.env['voucher'].get_active_voucher(domain) checkout = cart.get_user_checkout(user_id, source=source) products = checkout['products'] - user = request.env['res.users'].search([('id', '=', user_id)], limit=1) - if not user: - return self.response([]) order_line = [] for product in products: @@ -89,3 +99,9 @@ class Voucher(controller.Controller): sorted_results = sorted(results, key=lambda x: x['can_apply'], reverse=True) return self.response(sorted_results) + + def get_user_by_email(self, email): + return request.env['res.users'].search([ + ('login', '=', email), + ('active', 'in', [True, False]) + ])
\ No newline at end of file diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py index 38c60f50..e031cdcb 100755 --- a/indoteknik_custom/__manifest__.py +++ b/indoteknik_custom/__manifest__.py @@ -163,6 +163,7 @@ 'views/vendor_sla.xml', 'views/coretax_faktur.xml', 'views/public_holiday.xml', + 'views/stock_inventory.xml', ], 'demo': [], 'css': [], diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py index ed9d69be..12f2246a 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -145,3 +145,4 @@ from . import public_holiday from . import ir_actions_report from . import barcoding_product from . import account_payment_register +from . import stock_inventory diff --git a/indoteknik_custom/models/commision.py b/indoteknik_custom/models/commision.py index 48f1c7f6..6920154a 100644 --- a/indoteknik_custom/models/commision.py +++ b/indoteknik_custom/models/commision.py @@ -153,6 +153,10 @@ class CustomerCommision(models.Model): bank_account = fields.Char(string='Account No', tracking=3) note_transfer = fields.Char(string='Keterangan') brand_ids = fields.Many2many('x_manufactures', string='Brands') + payment_status = fields.Selection([ + ('pending', 'Pending'), + ('payment', 'Payment'), + ], string='Payment Status', copy=False, readonly=True, tracking=3, default='pending') # add status for type of commision, fee, rebate / cashback # include child or not? @@ -228,6 +232,20 @@ class CustomerCommision(models.Model): raise UserError('Harus di approved oleh yang bersangkutan') return + def action_confirm_customer_payment(self): + if self.status != 'approved': + raise UserError('Commision harus di approve terlebih dahulu sebelum di konfirmasi pembayarannya') + + if self.payment_status == 'payment': + raise UserError('Customer Commision sudah berstatus Payment') + group_id = self.env.ref('indoteknik_custom.group_role_fat').id + users_in_group = self.env['res.users'].search([('groups_id', 'in', [group_id])]) + if self.env.user.id not in users_in_group.mapped('id'): + raise UserError('Hanya bisa dikonfirmasi oleh FAT') + else: + self.payment_status = 'payment' + return + def generate_customer_commision(self): if self.commision_lines: raise UserError('Line sudah ada, tidak bisa di generate ulang') diff --git a/indoteknik_custom/models/coretax_fatur.py b/indoteknik_custom/models/coretax_fatur.py index 706a4f44..b4bffbd2 100644 --- a/indoteknik_custom/models/coretax_fatur.py +++ b/indoteknik_custom/models/coretax_fatur.py @@ -59,6 +59,7 @@ class CoretaxFaktur(models.Model): ET.SubElement(tax_invoice, 'TrxCode').text = '04' ET.SubElement(tax_invoice, 'AddInfo') ET.SubElement(tax_invoice, 'CustomDoc') + ET.SubElement(tax_invoice, 'CustomDocMonthYear') ET.SubElement(tax_invoice, 'RefDesc').text = invoice.name ET.SubElement(tax_invoice, 'FacilityStamp') ET.SubElement(tax_invoice, 'SellerIDTKU').text = '0742260227086000000000' diff --git a/indoteknik_custom/models/purchase_order_line.py b/indoteknik_custom/models/purchase_order_line.py index 587a09a1..033469b8 100755 --- a/indoteknik_custom/models/purchase_order_line.py +++ b/indoteknik_custom/models/purchase_order_line.py @@ -321,32 +321,60 @@ class PurchaseOrderLine(models.Model): def compute_item_margin(self): sum_so_margin = sum_sales_price = sum_margin = 0 + for line in self: - if not line.product_id or line.product_id.type == 'service' or not self.order_id.sale_order_id: + product = line.product_id + order = line.order_id + + # Skip jika tidak ada product_id, produk adalah service, atau tidak ada purchase order terkait + if not product or product.type == 'service' or not order: line.so_item_margin = 0 line.so_item_percent_margin = 0 line.item_margin = 0 line.item_percent_margin = 0 continue - sale_order_line = self.env['sale.order.line'].search( - [('product_id', '=', line.product_id.id), - ('order_id', '=', line.order_id.sale_order_id.id)], limit=1, order='price_reduce_taxexcl') - line.so_item_margin = sale_order_line.item_margin - line.so_item_percent_margin = sale_order_line.item_percent_margin - sum_so_margin += sale_order_line.item_margin - sales_price = sale_order_line.price_reduce_taxexcl * sale_order_line.product_uom_qty - if sale_order_line.order_id.shipping_cost_covered == 'indoteknik': - sales_price -= sale_order_line.delivery_amt_line - if sale_order_line.order_id.fee_third_party > 0: - sales_price -= sale_order_line.fee_third_party_line - sum_sales_price += sales_price + + # Cari semua sale.order.line terkait dengan purchase.order melalui tabel purchase.order.sales.match + sales_matches = self.env['purchase.order.sales.match'].search([ + ('purchase_order_id', '=', order.id), + ('product_id', '=', product.id) + ]) + + total_sales_price = total_margin = total_qty_so = 0 + for match in sales_matches: + sale_order_line = match.sale_line_id + + # Hitung harga jual setelah mempertimbangkan biaya tambahan + sales_price = sale_order_line.price_reduce_taxexcl * match.qty_so + if sale_order_line.order_id.shipping_cost_covered == 'indoteknik': + sales_price -= sale_order_line.delivery_amt_line + if sale_order_line.order_id.fee_third_party > 0: + sales_price -= sale_order_line.fee_third_party_line + + total_sales_price += sales_price + total_margin += sale_order_line.item_margin + total_qty_so += match.qty_so + + # Set margin berdasarkan total dari semua sales order yang terkait + line.so_item_margin = total_margin + line.so_item_percent_margin = (total_margin / total_sales_price) * 100 if total_sales_price else 0 + + sum_so_margin += total_margin + sum_sales_price += total_sales_price + + # Hitung harga pembelian dengan mempertimbangkan biaya pengiriman purchase_price = line.price_subtotal - if line.order_id.delivery_amount > 0: + if order.delivery_amount > 0: purchase_price += line.delivery_amt_line - real_item_margin = sales_price - purchase_price - real_item_percent_margin = round((real_item_margin/sales_price), 2) * 100 + + # Hitung margin dan persentase margin + real_item_margin = total_sales_price - purchase_price + real_item_percent_margin = (real_item_margin / total_sales_price) * 100 if total_sales_price else 0 + + # Set nilai margin ke dalam line line.item_margin = real_item_margin line.item_percent_margin = real_item_percent_margin + sum_margin += real_item_margin def compute_delivery_amt_line(self): diff --git a/indoteknik_custom/models/purchase_order_sales_match.py b/indoteknik_custom/models/purchase_order_sales_match.py index d1d929d3..ed013dd5 100644 --- a/indoteknik_custom/models/purchase_order_sales_match.py +++ b/indoteknik_custom/models/purchase_order_sales_match.py @@ -24,6 +24,18 @@ class PurchaseOrderSalesMatch(models.Model): margin_item = fields.Float(string='Margin') delivery_amt = fields.Float(string='Delivery Amount', compute='_compute_delivery_amt') margin_deduct = fields.Float(string='After Deduct', compute='_compute_delivery_amt') + purchase_price_so = fields.Float(string='Purchase Price Sale Order', related='sale_line_id.purchase_price') + purchase_price_po = fields.Float('Purchase Price PO', compute='_compute_purchase_price_po') + purchase_line_id = fields.Many2one('purchase.order.line', string='Purchase Line', compute='_compute_purchase_line_id') + + def _compute_purchase_line_id(self): + for line in self: + line.purchase_line_id = self.env['purchase.order.line'].search([('order_id', '=', line.purchase_order_id.id), ('product_id', '=', line.product_id.id)]) + + def _compute_purchase_price_po(self): + for line in self: + purchase_price = self.env['purchase.order.line'].search([('order_id', '=', line.purchase_order_id.id), ('product_id', '=', line.product_id.id)]) + line.purchase_price_po = purchase_price.price_unit def _compute_delivery_amt(self): for line in self: diff --git a/indoteknik_custom/models/requisition.py b/indoteknik_custom/models/requisition.py index c972b485..1d350929 100644 --- a/indoteknik_custom/models/requisition.py +++ b/indoteknik_custom/models/requisition.py @@ -276,10 +276,11 @@ class RequisitionLine(models.Model): _name = 'requisition.line' _description = 'Requisition Line' _order = 'requisition_id, id' + _inherit = ['mail.thread'] requisition_id = fields.Many2one('requisition', string='Ref', required=True, ondelete='cascade', index=True, copy=False) brand_id = fields.Many2one('x_manufactures', string='Brand') - product_id = fields.Many2one('product.product', string='Product') + product_id = fields.Many2one('product.product', string='Product', tracking=3,) partner_id = fields.Many2one('res.partner', string='Vendor') qty_purchase = fields.Float(string='Qty Purchase') price_unit = fields.Float(string='Price') @@ -331,6 +332,45 @@ class RequisitionLine(models.Model): line.taxes_id = taxes line.partner_id = purchase_pricelist.vendor_id.id + @api.model + def create(self, vals): + record = super(RequisitionLine, self).create(vals) + record._track_changes('Tambah') + return record + + def write(self, vals): + for record in self: + old_values = {field: record[field] for field in vals if field in record} + + result = super(RequisitionLine, self).write(vals) + + for record in self: + record._track_changes('Updated', old_values) + + return result + + def unlink(self): + for record in self: + record._track_changes('Hapus') + return super(RequisitionLine, self).unlink() + + def _track_changes(self, action, old_values=None): + message = f"Produk telah di-{action} : <br/>" + if action == 'Tambah': + # message += f"<br/> Product: {self.product_id.name}" + message += f"Product: {self.product_id.name} <br/> Vendor: {self.partner_id.name} <br/> Qty: {self.qty_purchase} <br/> Price: {self.price_unit} <br/> Tax: {self.tax_id.name} <br/> Subtotal: {self.subtotal} <br/> Brand: {self.brand_id.x_name}" + elif action == 'Hapus': + # message += f"<br/> Deleted Product: {self.product_id.name}" + message += f"<br/> Deleted Product: {self.product_id.name} <br/> Vendor: {self.partner_id.name} Qty: {self.qty_purchase} <br/> Price: {self.price_unit} <br/> Tax: {self.tax_id.name} <br/> Subtotal: {self.subtotal} <br/> Brand: {self.brand_id.x_name}" + else: # Updated + for field, old_value in old_values.items(): + new_value = self[field] + if old_value != new_value: + field_label = self._fields[field].string # Ambil nama label field + message += f"{field_label}: {old_value} -> {new_value}<br/>" + + if self.requisition_id: + self.requisition_id.message_post(body=message) class RequisitionPurchaseMatch(models.Model): _name = 'requisition.purchase.match' diff --git a/indoteknik_custom/models/res_users.py b/indoteknik_custom/models/res_users.py index 31b84ae3..b0864f2c 100755 --- a/indoteknik_custom/models/res_users.py +++ b/indoteknik_custom/models/res_users.py @@ -70,6 +70,10 @@ class ResUsers(models.Model): vouchers = self.env['voucher'].get_active_voucher([('show_on_email', '=', 'user_activation')]) if not vouchers: return None return ', '.join(x.code for x in vouchers) + if type == 'switch_account': + vouchers = self.env['voucher'].get_active_voucher([('excl_pricelist_ids', 'not in', [1]), ('apply_type', 'in', ['all', 'brand']), ('account_type', 'in', ['all', 'company']), ('visibility', 'in', ['public'])]) + if not vouchers: return None + return ', '.join(x.code for x in vouchers) return None def check_access(self, model, mode): diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 634ea918..93c2276a 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -7,6 +7,49 @@ from collections import defaultdict _logger = logging.getLogger(__name__) +class CancelReasonOrder(models.TransientModel): + _name = 'cancel.reason.order' + _description = 'Wizard for Cancel Reason order' + + request_id = fields.Many2one('sale.order', string='Request') + reason_cancel = fields.Selection([ + ('harga_terlalu_mahal', 'Harga barang terlalu mahal'), + ('harga_web_tidak_valid', 'Harga web tidak valid'), + ('stok_kosong', 'Stock kosong'), + ('tidak_mau_indent', 'Customer tidak mau indent'), + ('batal_rencana_pembelian', 'Customer membatalkan rencana pembelian'), + ('vendor_tidak_support_demo', 'Vendor tidak support demo/trial product'), + ('product_knowledge_kurang', 'Product knowledge kurang baik'), + ('barang_tidak_sesuai', 'Barang tidak sesuai/tepat'), + ('tidak_sepakat_pembayaran', 'Tidak menemukan kesepakatan untuk pembayaran'), + ('dokumen_tidak_support', 'Indoteknik tidak bisa support document yang dibutuhkan (Ex: TKDN, COO, SNI)'), + ('ganti_quotation', 'Ganti Quotation'), + ('testing_internal', 'Testing Internal'), + ], string='Reason for Cancel', required=True, copy=False, index=True, tracking=3) + attachment_bukti = fields.Many2many( + 'ir.attachment', + string="Attachment Bukti", readonly=False, + tracking=3, required=True + ) + nomor_so_pengganti = fields.Char(string='Nomor SO Pengganti', copy=False, tracking=3) + + def confirm_reject(self): + order = self.request_id + if order: + order.write({'reason_cancel': self.reason_cancel}) + if not self.attachment_bukti: + raise UserError('Attachment bukti wajib disertakan') + order.write({'attachment_bukti': self.attachment_bukti}) + order.message_post(body='Attachment Bukti Cancel', + attachment_ids=[self.attachment_bukti.id]) + if self.reason_cancel == 'ganti_quotation': + if self.nomor_so_pengganti: + order.write({'nomor_so_pengganti': self.nomor_so_pengganti}) + else: + raise UserError('Nomor SO pengganti wajib disertakan') + order.confirm_cancel_order() + + return {'type': 'ir.actions.act_window_close'} class SaleOrder(models.Model): _inherit = "sale.order" @@ -157,6 +200,26 @@ class SaleOrder(models.Model): ) shipping_method_picking = fields.Char(string='Shipping Method Picking', compute='_compute_shipping_method_picking') + reason_cancel = fields.Selection([ + ('harga_terlalu_mahal', 'Harga barang terlalu mahal'), + ('harga_web_tidak_valid', 'Harga web tidak valid'), + ('stok_kosong', 'Stock kosong'), + ('tidak_mau_indent', 'Customer tidak mau indent'), + ('batal_rencana_pembelian', 'Customer membatalkan rencana pembelian'), + ('vendor_tidak_support_demo', 'Vendor tidak support demo/trial product'), + ('product_knowledge_kurang', 'Product knowledge kurang baik'), + ('barang_tidak_sesuai', 'Barang tidak sesuai/tepat'), + ('tidak_sepakat_pembayaran', 'Tidak menemukan kesepakatan untuk pembayaran'), + ('dokumen_tidak_support', 'Indoteknik tidak bisa support document yang dibutuhkan (Ex: TKDN, COO, SNI)'), + ('ganti_quotation', 'Ganti Quotation'), + ('testing_internal', 'Testing Internal'), + ], string='Reason for Cancel', copy=False, index=True, tracking=3) + attachment_bukti = fields.Many2one( + 'ir.attachment', + string="Attachment Bukti Cancel", readonly=False, + ) + nomor_so_pengganti = fields.Char(string='Nomor SO Pengganti', copy=False, tracking=3) + def _compute_shipping_method_picking(self): for order in self: if order.picking_ids: @@ -1155,8 +1218,24 @@ class SaleOrder(models.Model): self.due_id = False if main_parent.use_so_approval: self.send_notif_to_salesperson(cancel=True) + for order in self: + if order.amount_total > 30000000: + return { + 'type': 'ir.actions.act_window', + 'name': _('Cancel Reason'), + 'res_model': 'cancel.reason.order', + 'view_mode': 'form', + 'target': 'new', + 'context': {'default_request_id': self.id}, + } return super(SaleOrder, self).action_cancel() - + + def confirm_cancel_order(self): + """Fungsi ini akan dipanggil oleh wizard setelah alasan pembatalan dipilih""" + if self.state != 'cancel': + self.state = 'cancel' + return super(SaleOrder, self).action_cancel() + def validate_partner_invoice_due(self): parent_id = self.partner_id.parent_id.id parent_id = parent_id if parent_id else self.partner_id.id @@ -1191,7 +1270,7 @@ class SaleOrder(models.Model): return self.total_percent_margin < 15 and not self.env.user.is_leader def _requires_approval_margin_manager(self): - return self.total_percent_margin <= 20 and not self.env.user.is_leader and not self.env.user.is_sales_manager + return self.total_percent_margin >= 15 and not self.env.user.is_leader and not self.env.user.is_sales_manager def _create_approval_notification(self, approval_role): title = 'Warning' diff --git a/indoteknik_custom/models/stock_inventory.py b/indoteknik_custom/models/stock_inventory.py new file mode 100644 index 00000000..12a891de --- /dev/null +++ b/indoteknik_custom/models/stock_inventory.py @@ -0,0 +1,59 @@ +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) + + 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' or "ADJUST OUT" in name_upper or "ADJUST-OUT" in name_upper or "OUT" in name_upper: + last_number = self._get_last_sequence("ADJUST/OUT/") + record.number = f"ADJUST/OUT/{last_number}" + elif self.adjusment_type == 'in' or "ADJUST IN" in name_upper or "ADJUST-IN" in name_upper or "IN" in name_upper: + 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 + + @api.model + def create(self, vals): + order = super(StockInventory, self).create(vals) + self._assign_number(order) + return order diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py index 696d25db..85cdc7eb 100644 --- a/indoteknik_custom/models/stock_picking.py +++ b/indoteknik_custom/models/stock_picking.py @@ -103,7 +103,7 @@ class StockPicking(models.Model): purchase_representative_id = fields.Many2one('res.users', related='move_lines.purchase_line_id.order_id.user_id', string="Purchase Representative") carrier_id = fields.Many2one('delivery.carrier', string='Shipping Method') shipping_status = fields.Char(string='Shipping Status', compute="_compute_shipping_status") - date_reserved = fields.Datetime(string="Date Reserved", help='Tanggal ter-reserved semua barang nya') + date_reserved = fields.Datetime(string="Date Reserved", help='Tanggal ter-reserved semua barang nya', copy=False) status_printed = fields.Selection([ ('not_printed', 'Belum Print'), ('printed', 'Printed') @@ -129,7 +129,7 @@ class StockPicking(models.Model): ('ready', 'Ready to Ship'), ('done', 'Done'), ('cancel', 'Cancelled'), - ], string='Status Reserve', readonly=True, tracking=True, help="The current state of the stock picking.") + ], string='Status Reserve', tracking=True, copy=False, help="The current state of the stock picking.") notee = fields.Text(string="Note") @api.model diff --git a/indoteknik_custom/models/voucher.py b/indoteknik_custom/models/voucher.py index 37c97338..101d4bcf 100644 --- a/indoteknik_custom/models/voucher.py +++ b/indoteknik_custom/models/voucher.py @@ -59,7 +59,11 @@ class Voucher(models.Model): show_on_email = fields.Selection([ ('user_activation', 'User Activation') ], 'Show on Email') - + account_type = fields.Selection(string='Account Type', default="all", selection=[ + ('all', "All Account"), + ('person', "Account Individu"), + ('company', "Account Company"), + ]) @api.constrains('description') def _check_description_length(self): for record in self: diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index 37f5aeab..48c3dfb6 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -164,3 +164,5 @@ access_barcode_product,access.barcode.product,model_barcode_product,,1,1,1,1 access_barcoding_product,access.barcoding.product,model_barcoding_product,,1,1,1,1 access_barcoding_product_line,access.barcoding.product.line,model_barcoding_product_line,,1,1,1,1 access_account_payment_register,access.account.payment.register,model_account_payment_register,,1,1,1,1 +access_stock_inventory,access.stock.inventory,model_stock_inventory,,1,1,1,1 +access_cancel_reason_order,cancel.reason.order,model_cancel_reason_order,,1,1,1,0 diff --git a/indoteknik_custom/views/customer_commision.xml b/indoteknik_custom/views/customer_commision.xml index 0b72587e..51172b1c 100644 --- a/indoteknik_custom/views/customer_commision.xml +++ b/indoteknik_custom/views/customer_commision.xml @@ -12,6 +12,10 @@ <field name="commision_percent"/> <field name="commision_amt" readonly="1"/> <field name="status" readonly="1"/> + <field name="payment_status" readonly="1" + decoration-success="payment_status == 'payment'" + decoration-danger="payment_status == 'pending'" + widget="badge"/> <field name="brand_ids" widget="many2many_tags"/> </tree> </field> @@ -43,6 +47,10 @@ <button name="action_confirm_customer_commision" string="Confirm" type="object" options="{}"/> + <button name="action_confirm_customer_payment" + string="Konfirmasi Pembayaran" type="object" + options="{}" + attrs="{'invisible': [('payment_status', '==', 'payment')], 'readonly': [('payment_status', '=', 'payment')]}"/> </header> <sheet string="Customer Commision"> <div class="oe_button_box" name="button_box"/> @@ -68,6 +76,7 @@ <field name="brand_ids" widget="many2many_tags"/> <field name="notification" readonly="1"/> <field name="status" readonly="1"/> + <field name="payment_status" readonly="1" /> <field name="total_dpp"/> </group> </group> diff --git a/indoteknik_custom/views/purchase_order.xml b/indoteknik_custom/views/purchase_order.xml index 3e4dd89c..a57bd467 100755 --- a/indoteknik_custom/views/purchase_order.xml +++ b/indoteknik_custom/views/purchase_order.xml @@ -109,6 +109,10 @@ <field name="price_vendor" attrs="{'readonly': 1}" optional="hide"/> </field> <field name="price_subtotal" position="after"> + <field name="so_item_margin" attrs="{'readonly': 1}" optional="hide"/> + <field name="so_item_percent_margin" attrs="{'readonly': 1}" optional="hide"/> + <field name="item_margin" attrs="{'readonly': 1}" optional="hide"/> + <field name="item_percent_margin" attrs="{'readonly': 1}" optional="hide"/> <field name="so_line_id" attrs="{'readonly': 1}" optional="hide"/> <field name="so_id" attrs="{'readonly': 1}" optional="hide"/> <field name="indent" optional="hide"/> @@ -296,6 +300,8 @@ <field name="partner_invoice_id"/> <field name="salesperson_id"/> <field name="product_id"/> + <field name="purchase_price_so"/> + <field name="purchase_price_po"/> <field name="qty_so"/> <field name="qty_po"/> <field name="margin_item" optional="hide"/> diff --git a/indoteknik_custom/views/res_users.xml b/indoteknik_custom/views/res_users.xml index 9553bb91..5b35f9c4 100644 --- a/indoteknik_custom/views/res_users.xml +++ b/indoteknik_custom/views/res_users.xml @@ -236,6 +236,7 @@ <tr><td style="padding-bottom: 16px;"><b>Pembayaran Lengkap:</b> Pilih metode pembayaran yang sesuai dengan kebutuhan Anda, baik transfer bank, VA, kartu kredit, atau pembayaran tempo.</td></tr> <tr><td style="padding-bottom: 16px;"><b>Pelacakan Pengiriman:</b> Lacak status pengiriman pesanan Anda secara real-time.</td></tr> <tr><td style="padding-bottom: 16px;">Untuk memulai transaksi, silakan login Kembali menggunakan akun Anda di <a href="https://indoteknik.com/login">Indoteknik.com</a></td></tr> + <tr><td style="padding-bottom: 16px;">Gunakan kode voucher berikut untuk mendapatkan diskon belanja hingga 10 juta: <strong>${object.get_voucher_code('switch_account')}</strong></td></tr> <tr><td style="padding-bottom: 16px;">Kami sangat senang dapat melayani Anda. Jika ada pertanyaan atau membutuhkan bantuan, jangan ragu untuk menghubungi tim layanan Customer kami di Whatsapp <a href="https://wa.me/6281717181922">0817-1718-1922</a> atau <a href="mailto:sales@indoteknik.com">sales@indoteknik.com</a></td></tr> <tr><td style="padding-bottom: 2px;"><b>Hormat kami,</b></td></tr> @@ -299,6 +300,7 @@ <tr><td style="padding-bottom: 16px;">Selamat! Akun bisnis Anda di indoteknik.com sekarang sudah resmi menjadi PKP dari yang sebelumnya Non-PKP.</td></tr> <tr><td style="padding-bottom: 16px;">Jangan lupa untuk mengecek kembali semua data perusahaan kamu, ya. Pastikan NPWP dan informasi Perusahaan lainnya sudah kamu isi dengan benar.</td></tr> + <tr><td style="padding-bottom: 16px;">Gunakan kode voucher berikut untuk mendapatkan diskon belanja hingga 10 juta: <strong>${object.get_voucher_code('switch_account')}</strong></td></tr> <tr><td style="padding-bottom: 16px;">Kamu juga dapat mengubah informasi perusahaan dengan mengunjungi profil atau <a href="https://indoteknik.com/my/profile">klik disini</a></td></tr> <tr><td style="padding-bottom: 2px;">Industrial Supply & Solutions</td></tr> diff --git a/indoteknik_custom/views/sale_order.xml b/indoteknik_custom/views/sale_order.xml index 4cc96cd2..ebee64b1 100755 --- a/indoteknik_custom/views/sale_order.xml +++ b/indoteknik_custom/views/sale_order.xml @@ -286,6 +286,31 @@ </page> </field> </record> + <!-- Wizard for Reject Reason --> + <record id="view_cancel_reason_order_form" model="ir.ui.view"> + <field name="name">cancel.reason.order.form</field> + <field name="model">cancel.reason.order</field> + <field name="arch" type="xml"> + <form string="Cancel Reason"> + <group> + <field name="reason_cancel" widget="selection"/> + <field name="attachment_bukti" widget="many2many_binary" required="1"/> + <field name="nomor_so_pengganti" attrs="{'invisible': [('reason_cancel', '!=', 'ganti_quotation')]}"/> + </group> + <footer> + <button string="Confirm" type="object" name="confirm_reject" class="btn-primary"/> + <button string="Cancel" class="btn-secondary" special="cancel"/> + </footer> + </form> + </field> + </record> + + <record id="action_cancel_reason_order" model="ir.actions.act_window"> + <field name="name">Cancel Reason</field> + <field name="res_model">cancel.reason.order</field> + <field name="view_mode">form</field> + <field name="target">new</field> + </record> </data> <data> <record id="sale_order_tree_view_inherit" model="ir.ui.view"> diff --git a/indoteknik_custom/views/stock_inventory.xml b/indoteknik_custom/views/stock_inventory.xml new file mode 100644 index 00000000..db85f05c --- /dev/null +++ b/indoteknik_custom/views/stock_inventory.xml @@ -0,0 +1,28 @@ +<?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"> + <xpath expr="//field[@name='location_ids']" position="after"> + <field name="number" readonly="1"/> + <field name="adjusment_type" /> + </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> diff --git a/indoteknik_custom/views/voucher.xml b/indoteknik_custom/views/voucher.xml index 29d0ad4b..ae958f05 100755 --- a/indoteknik_custom/views/voucher.xml +++ b/indoteknik_custom/views/voucher.xml @@ -35,6 +35,7 @@ <field name="limit" required="1"/> <field name="limit_user" required="1"/> <field name="apply_type" required="1" /> + <field name="account_type" required="1" /> <field name="show_on_email" /> <field name="excl_pricelist_ids" widget="many2many_tags" domain="[('id', 'in', [4, 15037, 15038, 15039, 17023, 17024, 17025, 17026,17027])]"/> </group> |
