diff options
| author | Rafi Zadanly <zadanlyr@gmail.com> | 2023-11-10 15:51:23 +0700 |
|---|---|---|
| committer | Rafi Zadanly <zadanlyr@gmail.com> | 2023-11-10 15:51:23 +0700 |
| commit | 25722cc3ab5ac5afef4d77947f8e2f27355e6837 (patch) | |
| tree | 7184fd0af0129433446f8b195d7683e5494cc402 | |
| parent | 99e673d2cc5f702cf0a438126ba26d991a3ce6e4 (diff) | |
| parent | b4e74170aeaf00937f78e5af9047218ddb17516c (diff) | |
Merge branch 'production' into cr/auth
# Conflicts:
# indoteknik_custom/__manifest__.py
23 files changed, 733 insertions, 133 deletions
diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py index ace5c720..bc11b346 100755 --- a/indoteknik_custom/__manifest__.py +++ b/indoteknik_custom/__manifest__.py @@ -100,7 +100,9 @@ 'views/stock_move_line.xml', 'views/product_monitoring.xml', 'views/res_users.xml', + 'views/account_bank_statement.xml', 'views/stock_warehouse_orderpoint.xml', + 'views/customer_commision.xml', 'report/report.xml', 'report/report_banner_banner.xml', 'report/report_banner_banner2.xml', diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py index 6a5eac00..35f06f03 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -90,4 +90,6 @@ from . import promotion from . import sale_orders_multi_update from . import quotation_so_multi_update from . import product_monitoring +from . import account_bank_statement from . import stock_warehouse_orderpoint +from . import commision diff --git a/indoteknik_custom/models/account_bank_statement.py b/indoteknik_custom/models/account_bank_statement.py new file mode 100644 index 00000000..23008f13 --- /dev/null +++ b/indoteknik_custom/models/account_bank_statement.py @@ -0,0 +1,19 @@ +from odoo import fields, models, api, _ +from odoo.exceptions import AccessError, UserError, ValidationError + +class AccountBankStatement(models.Model): + _inherit = "account.bank.statement" + + is_edit = fields.Boolean(string='Unlock', default=False) + + def is_edited(self): + if not self.env.user.is_admin_reconcile: + raise UserError('Yang berhak hanya Mba Tania dan Iqmal Saputra') + + self.is_edit = True + + def not_edited(self): + if not self.env.user.is_admin_reconcile: + raise UserError('Yang berhak hanya Mba Tania dan Iqmal Saputra') + + self.is_edit = False
\ No newline at end of file diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index a85e8caa..fe9db583 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -62,6 +62,11 @@ class AccountMove(models.Model): res = super(AccountMove, self).button_draft() if not self.env.user.is_accounting: raise UserError('Hanya Accounting yang bisa Reset to Draft') + + for rec in self.line_ids: + if rec.write_date != rec.create_date: + if rec.statement_line_id and not rec.statement_line_id.statement_id.is_edit and rec.statement_line_id.statement_id.state == 'confirm': + raise UserError('Bank Statement di Lock, Minta admin reconcile untuk unlock') return res def action_post(self): @@ -145,4 +150,17 @@ class AccountMove(models.Model): 'move_ids': [x.id for x in self] } return action -
\ No newline at end of file + + @api.constrains('efaktur_id', 'ref', 'date', 'journal_id', 'name') + def constrains_edit(self): + for rec in self.line_ids: + if rec.statement_line_id and not rec.statement_line_id.statement_id.is_edit and rec.statement_line_id.statement_id.state == 'confirm': + raise UserError('Bank Statement di Lock, Minta admin reconcile untuk unlock') + + # def write(self, vals): + # res = super(AccountMove, self).write(vals) + # for rec in self.line_ids: + # if rec.write_date != rec.create_date: + # if rec.statement_line_id and not rec.statement_line_id.statement_id.is_edit and rec.statement_line_id.statement_id.state == 'confirm': + # raise UserError('Bank Statement di Lock, Minta admin reconcile untuk unlock') + # return res diff --git a/indoteknik_custom/models/automatic_purchase.py b/indoteknik_custom/models/automatic_purchase.py index f81ecdcc..502761e0 100644 --- a/indoteknik_custom/models/automatic_purchase.py +++ b/indoteknik_custom/models/automatic_purchase.py @@ -105,15 +105,18 @@ class AutomaticPurchase(models.Model): ('product_id', '=', point.product_id.id), # ('product_id.x_manufacture.user_id.id', '=', self.responsible_id.id), ('vendor_id', '=', self.vendor_id.id) - ], order='product_price asc', limit=1) + ], order='count_trx_po desc, count_trx_po_vendor desc', limit=1) else: purchase_price = self.env['purchase.pricelist'].search([ ('product_id', '=', point.product_id.id), # ('product_id.x_manufacture.user_id.id', '=', self.responsible_id.id), - ], order='product_price asc', limit=1) + ], order='count_trx_po desc, count_trx_po_vendor desc', limit=1) vendor_id = purchase_price.vendor_id.id - price = purchase_price.product_price or 0 + price = self._get_valid_purchase_price(purchase_price) + + if self.vendor_id and self.vendor_id.id != vendor_id: + continue self.env['automatic.purchase.line'].create([{ 'automatic_purchase_id': self.id, @@ -135,6 +138,19 @@ class AutomaticPurchase(models.Model): _logger.info('Create Automatic Purchase Line %s' % point.product_id.name) self.notification = "Automatic PO Created %s Lines" % count + def _get_valid_purchase_price(self, purchase_price): + p_price = 0 + if purchase_price.system_price > 0 and purchase_price.product_price > 0: + if purchase_price.human_last_update > purchase_price.system_last_update: + p_price = purchase_price.product_price + else: + p_price = purchase_price.system_price + elif purchase_price.system_price > 0 and purchase_price.product_price == 0: + p_price = purchase_price.system_price + elif purchase_price.system_price == 0 and purchase_price.product_price > 0: + p_price = purchase_price.product_price + return p_price + class AutomaticPurchaseLine(models.Model): _name = 'automatic.purchase.line' diff --git a/indoteknik_custom/models/commision.py b/indoteknik_custom/models/commision.py new file mode 100644 index 00000000..d4942a0d --- /dev/null +++ b/indoteknik_custom/models/commision.py @@ -0,0 +1,275 @@ +from odoo import models, api, fields +from odoo.exceptions import UserError +from datetime import datetime +import logging + +_logger = logging.getLogger(__name__) + + +class CustomerRebate(models.Model): + _name = 'customer.rebate' + _order = 'id desc' + _inherit = ['mail.thread'] + + partner_id = fields.Many2one('res.partner', string='Customer', required=True) + date_from = fields.Date(string='Date From', required=True, help="Pastikan tanggal 1 januari, jika tidak, code akan break") + date_to = fields.Date(string='Date To', required=True, help="Pastikan tanggal 31 desember, jika tidak, code akan break") + description = fields.Char(string='Description') + target_1st = fields.Float(string='Target/Quarter 1st') + target_2nd = fields.Float(string='Target/Quarter 2nd') + achieve_1 = fields.Float(string='Achieve 1 %') + achieve_2 = fields.Float(string='Achieve 2 %') + dpp_q1 = fields.Float(string='DPP Q1', compute='_compute_current_dpp') + dpp_q2 = fields.Float(string='DPP Q2', compute='_compute_current_dpp') + dpp_q3 = fields.Float(string='DPP Q3', compute='_compute_current_dpp') + dpp_q4 = fields.Float(string='DPP Q4', compute='_compute_current_dpp') + status_q1 = fields.Char(string='Status Q1', compute='_compute_achievement') + status_q2 = fields.Char(string='Status Q2', compute='_compute_achievement') + status_q3 = fields.Char(string='Status Q3', compute='_compute_achievement') + status_q4 = fields.Char(string='Status Q4', compute='_compute_achievement') + + # all code class CustomerRebate deprecated, cause lack of performance + def _compute_current_dpp(self): + for line in self: + line.dpp_q1 = line._get_current_dpp_q1(line) + line.dpp_q2 = line._get_current_dpp_q2(line) + line.dpp_q3 = line._get_current_dpp_q3(line) + line.dpp_q4 = line._get_current_dpp_q4(line) + + def _compute_achievement(self): + for line in self: + line.status_q1 = line._check_achievement(line.target_1st, line.target_2nd, line.dpp_q1) + line.status_q2 = line._check_achievement(line.target_1st, line.target_2nd, line.dpp_q2) + line.status_q3 = line._check_achievement(line.target_1st, line.target_2nd, line.dpp_q3) + line.status_q4 = line._check_achievement(line.target_1st, line.target_2nd, line.dpp_q4) + + def _check_achievement(self, target_1st, target_2nd, dpp): + status = 'not achieve' + if dpp >= target_1st: + status = '1st' + elif dpp >= target_2nd: + status = '2nd' + else: + status = 'not achieve' + return status + + def _get_current_dpp_q1(self, line): + sum_dpp = 0 + brand = [10, 89, 122] + where = [ + ('move_id.move_type', '=', 'out_invoice'), + ('move_id.state', '=', 'posted'), + ('move_id.is_customer_commision', '=', False), + ('move_id.partner_id.id', '=', line.partner_id.id), + ('move_id.invoice_date', '>=', line.date_from), + ('move_id.invoice_date', '<=', '2023-03-31'), + ('product_id.x_manufacture', 'in', brand), + ] + invoice_lines = self.env['account.move.line'].search(where, order='id') + for invoice_line in invoice_lines: + sum_dpp += invoice_line.price_subtotal + return sum_dpp + + def _get_current_dpp_q2(self, line): + sum_dpp = 0 + brand = [10, 89, 122] + where = [ + ('move_id.move_type', '=', 'out_invoice'), + ('move_id.state', '=', 'posted'), + ('move_id.is_customer_commision', '=', False), + ('move_id.partner_id.id', '=', line.partner_id.id), + ('move_id.invoice_date', '>=', '2023-04-01'), + ('move_id.invoice_date', '<=', '2023-06-30'), + ('product_id.x_manufacture', 'in', brand), + ] + invoices = self.env['account.move.line'].search(where, order='id') + for invoice in invoices: + sum_dpp += invoice.price_subtotal + return sum_dpp + + def _get_current_dpp_q3(self, line): + sum_dpp = 0 + brand = [10, 89, 122] + where = [ + ('move_id.move_type', '=', 'out_invoice'), + ('move_id.state', '=', 'posted'), + ('move_id.is_customer_commision', '=', False), + ('move_id.partner_id.id', '=', line.partner_id.id), + ('move_id.invoice_date', '>=', '2023-07-01'), + ('move_id.invoice_date', '<=', '2023-09-30'), + ('product_id.x_manufacture', 'in', brand), + ] + invoices = self.env['account.move.line'].search(where, order='id') + for invoice in invoices: + sum_dpp += invoice.price_subtotal + return sum_dpp + + def _get_current_dpp_q4(self, line): + sum_dpp = 0 + brand = [10, 89, 122] + where = [ + ('move_id.move_type', '=', 'out_invoice'), + ('move_id.state', '=', 'posted'), + ('move_id.is_customer_commision', '=', False), + ('move_id.partner_id.id', '=', line.partner_id.id), + ('move_id.invoice_date', '>=', '2023-10-01'), + ('move_id.invoice_date', '<=', line.date_to), + ('product_id.x_manufacture', 'in', brand), + ] + invoices = self.env['account.move.line'].search(where, order='id') + for invoice in invoices: + sum_dpp += invoice.price_subtotal + return sum_dpp + + +class CustomerCommision(models.Model): + _name = 'customer.commision' + _order = 'id desc' + _inherit = ['mail.thread'] + _rec_name = 'number' + + number = fields.Char(string='Document No', index=True, copy=False, readonly=True) + date_from = fields.Date(string='Date From', required=True) + date_to = fields.Date(string='Date To', required=True) + partner_id = fields.Many2one('res.partner', String='Customer', required=True) + description = fields.Char(string='Description') + notification = fields.Char(string='Notification') + commision_lines = fields.One2many('customer.commision.line', 'customer_commision_id', string='Lines', auto_join=True) + status = fields.Selection([ + ('pengajuan1', 'Menunggu Approval Marketing'), + ('pengajuan2', 'Menunggu Approval Pimpinan'), + ('approved', 'Approved') + ], string='Status', copy=False, readonly=True, tracking=3) + commision_percent = fields.Float(string='Commision %', tracking=3) + commision_amt = fields.Float(string='Commision Amount', tracking=3) + total_dpp = fields.Float(string='Total DPP', compute='_compute_total_dpp') + commision_type = fields.Selection([ + ('fee', 'Fee'), + ('cashback', 'Cashback'), + ('rebate', 'Rebate'), + ], string='Commision Type', required=True) + + # add status for type of commision, fee, rebate / cashback + # include child or not? + + @api.constrains('commision_percent') + def _onchange_commision_percent(self): + print('masuk onchange commision percent') + self.commision_amt = self.commision_percent * self.total_dpp // 100 + + # @api.constrains('commision_amt') + # def _onchange_commision_amt(self): + # print('masuk onchange commision amt') + # self.commision_percent = (self.commision_amt / self.grand_total * 100) + + def _compute_total_dpp(self): + for data in self: + total_dpp = 0 + for line in data.commision_lines: + total_dpp = total_dpp + line.dpp + data.total_dpp = total_dpp + + @api.model + def create(self, vals): + vals['number'] = self.env['ir.sequence'].next_by_code('customer.commision') or '0' + result = super(CustomerCommision, self).create(vals) + return result + + def action_confirm_customer_commision(self):#add 2 step approval + if not self.status: + self.status = 'pengajuan1' + elif self.status == 'pengajuan1' and self.env.user.id == 19: + self.status = 'pengajuan2' + elif self.status == 'pengajuan2' and self.env.user.is_leader: + for line in self.commision_lines: + line.invoice_id.is_customer_commision = True + self.status = 'approved' + else: + raise UserError('Harus di approved oleh yang bersangkutan') + return + + def generate_customer_commision(self): + if self.commision_lines: + raise UserError('Line sudah ada, tidak bisa di generate ulang') + + if self.commision_type == 'fee': + self._generate_customer_commision_fee() + else: + self._generate_customer_commision_rebate() + + def _generate_customer_commision_rebate(self): + partners = [] + partners += self.partner_id.child_ids + partners.append(self.partner_id) + + for partner in partners: + brand = [92, 10, 89, 12, 324, 11] + where = [ + ('move_id.move_type', '=', 'out_invoice'), + ('move_id.state', '=', 'posted'), + ('move_id.is_customer_commision', '=', False), + ('move_id.amount_residual_signed', '=', 0), + ('move_id.partner_id.id', '=', partner.id), + ('move_id.invoice_date', '>=', self.date_from), + ('move_id.invoice_date', '<=', self.date_to), + ('product_id.x_manufacture', 'in', brand), + ] + invoice_lines = self.env['account.move.line'].search(where, order='id') + for invoice_line in invoice_lines: + tax = invoice_line.price_total - invoice_line.price_subtotal + self.env['customer.commision.line'].create([{ + 'customer_commision_id': self.id, + 'partner_id': invoice_line.move_id.partner_id.id, + 'invoice_id': invoice_line.move_id.id, + 'state': invoice_line.move_id.state, + 'product_id': invoice_line.product_id.id, + 'dpp': invoice_line.price_subtotal, + 'tax': tax, + 'total': invoice_line.price_total + }]) + return + + def _generate_customer_commision_fee(self): + partners = [] + partners += self.partner_id.child_ids + partners.append(self.partner_id) + + for partner in partners: + where = [ + ('move_type', '=', 'out_invoice'), + ('state', '=', 'posted'), + ('is_customer_commision', '=', False), + ('amount_residual_signed', '=', 0), + ('partner_id.id', '=', partner.id), + ('invoice_date', '>=', self.date_from), + ('invoice_date', '<=', self.date_to), + ] + invoices = self.env['account.move'].search(where, order='id') + for invoice in invoices: + self.env['customer.commision.line'].create([{ + 'customer_commision_id': self.id, + 'partner_id': invoice.partner_id.id, + 'invoice_id': invoice.id, + 'state': invoice.state, + 'dpp': invoice.amount_untaxed_signed, + 'tax': invoice.amount_tax_signed, + 'total': invoice.amount_total_signed + }]) + return + +class CustomerCommisionLine(models.Model): + _name = 'customer.commision.line' + _order = 'id' + + customer_commision_id = fields.Many2one('customer.commision', string='Ref', required=True, ondelete='cascade', copy=False) + invoice_id = fields.Many2one('account.move', string='Invoice') + partner_id = fields.Many2one('res.partner', string='Customer') + state = fields.Char(string='InvStatus') + dpp = fields.Float(string='DPP') + tax = fields.Float(string='TaxAmt') + total = fields.Float(string='Total') + product_id = fields.Many2one('product.product', string='Product') + +class AccountMove(models.Model): + _inherit = 'account.move' + is_customer_commision = fields.Boolean(string='Customer Commision Used') diff --git a/indoteknik_custom/models/product_template.py b/indoteknik_custom/models/product_template.py index 10d109fb..d1de2221 100755 --- a/indoteknik_custom/models/product_template.py +++ b/indoteknik_custom/models/product_template.py @@ -53,6 +53,10 @@ class ProductTemplate(models.Model): seq_new_product = fields.Integer(string='Seq New Product', help='Urutan Sequence New Product') is_edited = fields.Boolean(string='Is Edited') qty_sold = fields.Float(string='Sold Quantity', compute='_get_qty_sold') + kind_of = fields.Selection([ + ('sp', 'Spare Part'), + ('acc', 'Accessories') + ], string='Kind of', copy=False) def _get_qty_sold(self): for rec in self: diff --git a/indoteknik_custom/models/purchase_order.py b/indoteknik_custom/models/purchase_order.py index f9cd7f5b..b0f1a569 100755 --- a/indoteknik_custom/models/purchase_order.py +++ b/indoteknik_custom/models/purchase_order.py @@ -49,6 +49,15 @@ class PurchaseOrder(models.Model): has_active_invoice = fields.Boolean(string='Has Active Invoice', compute='_compute_has_active_invoice') description = fields.Char(string='Description', help='bisa diisi sebagai informasi indent barang tertentu atau apapun') purchase_order_lines = fields.One2many('purchase.order.line', 'order_id', string='Indent', auto_join=True) + responsible_ids = fields.Many2many('res.users', string='Responsibles', compute='_compute_responsibles') + + def _compute_responsibles(self): + for purchase in self: + resposible_ids = [] + for line in purchase.order_line: + resposible_ids.append(line.product_id.x_manufacture.user_id.id) + resposible_ids = list(set(resposible_ids)) + purchase.responsible_ids = resposible_ids def _compute_has_active_invoice(self): for order in self: diff --git a/indoteknik_custom/models/requisition.py b/indoteknik_custom/models/requisition.py index 19f0ba7e..6408c4fd 100644 --- a/indoteknik_custom/models/requisition.py +++ b/indoteknik_custom/models/requisition.py @@ -9,6 +9,8 @@ _logger = logging.getLogger(__name__) class Requisition(models.Model): _name = 'requisition' _order = 'id desc' + _inherit = ['mail.thread'] + _rec_name = 'number' number = fields.Char(string='Document No', index=True, copy=False, readonly=True) date_doc = fields.Date(string='Date', help='isi tanggal hari ini') @@ -26,108 +28,108 @@ class Requisition(models.Model): result = super(Requisition, self).create(vals) return result - def create_requisition_from_sales_with_price(self): - if self.requisition_lines: - raise UserError('Sudah digenerate sebelumnya, hapus line terlebih dahulu') - if not self.sale_order_id: - raise UserError('Sale Order harus diisi') - if self.is_po: - raise UserError('Sudah jadi PO, tidak bisa di create ulang PO nya') - - count = 0 - for order_line in self.sale_order_id.order_line: - # get purchase price altama, if nothing, then get other cheaper, if nothing then last po - purchase_price = order_line.purchase_price - vendor_id = order_line.vendor_id.id - - # get qty available bandengan - qty_available = order_line.product_id.qty_onhand_bandengan + order_line.product_id.qty_incoming_bandengan - order_line.product_id.outgoing_qty - suggest = 'harus beli' - if qty_available > order_line.product_qty: - suggest = 'masih cukup' - - self.env['requisition.line'].create([{ - 'requisition_id': self.id, - 'partner_id': vendor_id, - 'brand_id': order_line.product_id.product_tmpl_id.x_manufacture.id, - 'product_id': order_line.product_id.id, - 'qty_purchase': order_line.product_uom_qty, - 'tax_id': order_line.purchase_tax_id.id, - 'price_unit': purchase_price, - 'subtotal': purchase_price * order_line.product_uom_qty, - 'source': 'sales', - 'qty_available_store': qty_available, - 'suggest': suggest, - }]) - count+=1 - _logger.info('Create Requisition %s' % order_line.product_id.name) - self.notification = "Requisition Created %s lines" % count - - def create_requisition_from_sales(self): - if self.requisition_lines: - raise UserError('Sudah digenerate sebelumnya, hapus line terlebih dahulu') - if not self.sale_order_id: - raise UserError('Sale Order harus diisi') - if self.is_po: - raise UserError('Sudah jadi PO, tidak bisa di create ulang PO nya') + # def create_requisition_from_sales_with_price(self): + # if self.requisition_lines: + # raise UserError('Sudah digenerate sebelumnya, hapus line terlebih dahulu') + # if not self.sale_order_id: + # raise UserError('Sale Order harus diisi') + # if self.is_po: + # raise UserError('Sudah jadi PO, tidak bisa di create ulang PO nya') + + # count = 0 + # for order_line in self.sale_order_id.order_line: + # # get purchase price altama, if nothing, then get other cheaper, if nothing then last po + # purchase_price = order_line.purchase_price + # vendor_id = order_line.vendor_id.id + + # # get qty available bandengan + # qty_available = order_line.product_id.qty_onhand_bandengan + order_line.product_id.qty_incoming_bandengan - order_line.product_id.outgoing_qty + # suggest = 'harus beli' + # if qty_available > order_line.product_qty: + # suggest = 'masih cukup' + + # self.env['requisition.line'].create([{ + # 'requisition_id': self.id, + # 'partner_id': vendor_id, + # 'brand_id': order_line.product_id.product_tmpl_id.x_manufacture.id, + # 'product_id': order_line.product_id.id, + # 'qty_purchase': order_line.product_uom_qty, + # 'tax_id': order_line.purchase_tax_id.id, + # 'price_unit': purchase_price, + # 'subtotal': purchase_price * order_line.product_uom_qty, + # 'source': 'sales', + # 'qty_available_store': qty_available, + # 'suggest': suggest, + # }]) + # count+=1 + # _logger.info('Create Requisition %s' % order_line.product_id.name) + # self.notification = "Requisition Created %s lines" % count + + # def create_requisition_from_sales(self): + # if self.requisition_lines: + # raise UserError('Sudah digenerate sebelumnya, hapus line terlebih dahulu') + # if not self.sale_order_id: + # raise UserError('Sale Order harus diisi') + # if self.is_po: + # raise UserError('Sudah jadi PO, tidak bisa di create ulang PO nya') - # old_requisition = self.env['requisition'].search([('sale_order_id', '=', self.sale_order_id.id)], limit=1) - # if old_requisition: - # raise UserError('Sudah pernah jadi Requisition') - - count = 0 - for order_line in self.sale_order_id.order_line: - # get purchase price altama, if nothing, then get other cheaper, if nothing then last po - purchase_price = 0 - vendor_id = 0 - - # get qty available bandengan - qty_available = order_line.product_id.qty_onhand_bandengan + order_line.product_id.qty_incoming_bandengan - order_line.product_id.outgoing_qty - suggest = 'harus beli' - if qty_available > order_line.product_qty: - suggest = 'masih cukup' - - purchase_pricelist = self.env['purchase.pricelist'].search([ - ('product_id.id', '=', order_line.product_id.id), - ('vendor_id.id', '=', 5571) - ], order='product_price asc', limit=1) - purchase_price = purchase_pricelist.product_price - vendor_id = purchase_pricelist.vendor_id.id - source = 'PriceList' + # # old_requisition = self.env['requisition'].search([('sale_order_id', '=', self.sale_order_id.id)], limit=1) + # # if old_requisition: + # # raise UserError('Sudah pernah jadi Requisition') + + # count = 0 + # for order_line in self.sale_order_id.order_line: + # # get purchase price altama, if nothing, then get other cheaper, if nothing then last po + # purchase_price = 0 + # vendor_id = 0 + + # # get qty available bandengan + # qty_available = order_line.product_id.qty_onhand_bandengan + order_line.product_id.qty_incoming_bandengan - order_line.product_id.outgoing_qty + # suggest = 'harus beli' + # if qty_available > order_line.product_qty: + # suggest = 'masih cukup' + + # purchase_pricelist = self.env['purchase.pricelist'].search([ + # ('product_id.id', '=', order_line.product_id.id), + # ('vendor_id.id', '=', 5571) + # ], order='product_price asc', limit=1) + # purchase_price = purchase_pricelist.product_price + # vendor_id = purchase_pricelist.vendor_id.id + # source = 'PriceList' - if not purchase_price or purchase_price <= 0: - purchase_pricelist = self.env['purchase.pricelist'].search([('product_id', '=', order_line.product_id.id)], order='product_price asc', limit=1) - purchase_price = purchase_pricelist.product_price - vendor_id = purchase_pricelist.vendor_id.id - source = 'PriceList' + # if not purchase_price or purchase_price <= 0: + # purchase_pricelist = self.env['purchase.pricelist'].search([('product_id', '=', order_line.product_id.id)], order='product_price asc', limit=1) + # purchase_price = purchase_pricelist.product_price + # vendor_id = purchase_pricelist.vendor_id.id + # source = 'PriceList' - if not purchase_price or purchase_price <= 0: - last_po_line = self.env['purchase.order.line'].search([('product_id', '=', order_line.product_id.id), ('order_id.state', '=', 'done')], order='id desc', limit=1) - purchase_price = last_po_line.price_unit - vendor_id = last_po_line.order_id.partner_id.id - source = 'LastPO' + # if not purchase_price or purchase_price <= 0: + # last_po_line = self.env['purchase.order.line'].search([('product_id', '=', order_line.product_id.id), ('order_id.state', '=', 'done')], order='id desc', limit=1) + # purchase_price = last_po_line.price_unit + # vendor_id = last_po_line.order_id.partner_id.id + # source = 'LastPO' - if not purchase_price or purchase_price <= 0: - purchase_price = 0 - vendor_id = 5571 - source = 'Nothing' - - self.env['requisition.line'].create([{ - 'requisition_id': self.id, - 'partner_id': vendor_id, - 'brand_id': order_line.product_id.product_tmpl_id.x_manufacture.id, - 'product_id': order_line.product_id.id, - 'qty_purchase': order_line.product_uom_qty, - 'tax_id': order_line.purchase_tax_id.id, - 'price_unit': purchase_price, - 'subtotal': purchase_price * order_line.product_uom_qty, - 'source': source, - 'qty_available_store': qty_available, - 'suggest': suggest, - }]) - count+=1 - _logger.info('Create Requisition %s' % order_line.product_id.name) - self.notification = "Requisition Created %s lines" % count + # if not purchase_price or purchase_price <= 0: + # purchase_price = 0 + # vendor_id = 5571 + # source = 'Nothing' + + # self.env['requisition.line'].create([{ + # 'requisition_id': self.id, + # 'partner_id': vendor_id, + # 'brand_id': order_line.product_id.product_tmpl_id.x_manufacture.id, + # 'product_id': order_line.product_id.id, + # 'qty_purchase': order_line.product_uom_qty, + # 'tax_id': order_line.purchase_tax_id.id, + # 'price_unit': purchase_price, + # 'subtotal': purchase_price * order_line.product_uom_qty, + # 'source': source, + # 'qty_available_store': qty_available, + # 'suggest': suggest, + # }]) + # count+=1 + # _logger.info('Create Requisition %s' % order_line.product_id.name) + # self.notification = "Requisition Created %s lines" % count def create_po_from_requisition(self): if not self.requisition_lines: @@ -141,13 +143,14 @@ class Requisition(models.Model): for vendor in vendor_ids: param_header = { 'partner_id': vendor['partner_id'][0], - 'partner_ref': self.sale_order_id.name, + # 'partner_ref': self.sale_order_id.name, 'currency_id': 12, 'user_id': self.env.user.id, 'company_id': 1, # indoteknik dotcom gemilang 'picking_type_id': 28, # indoteknik bandengan receipts 'date_order': current_time, - 'sale_order_id': self.sale_order_id.id + 'sale_order_id': self.sale_order_id.id, + 'note_description': 'from Purchase Requisition' } # new_po = self.env['purchase.order'].create([param_header]) products_vendors = self.env['requisition.line'].search([ @@ -156,9 +159,9 @@ class Requisition(models.Model): ('qty_purchase', '>', 0) ], order='brand_id') count = brand_id = 0 - new_po = '' + for product in products_vendors: - if not new_po or ((count == 200 or brand_id != product.brand_id.id) and vendor['partner_id'][0] == 5571): + if count == 200 or brand_id != product.brand_id.id: count = 0 counter_po_number += 1 new_po = self.env['purchase.order'].create([param_header]) @@ -178,14 +181,16 @@ class Requisition(models.Model): if qty_available > product.qty_purchase: suggest = 'masih cukup' + tax = [22] + param_line = { 'order_id': new_po.id, 'sequence': count, 'product_id': product.product_id.id, 'product_qty': product.qty_purchase, 'product_uom_qty': product.qty_purchase, - 'price_unit': product.last_price, - 'taxes_id': product.tax_id, + 'price_unit': product.price_unit, + 'taxes_id': tax, 'qty_available_store': qty_available, 'suggest': suggest, } @@ -193,7 +198,7 @@ class Requisition(models.Model): product.current_po_id = new_po.id product.current_po_line_id = new_line.id _logger.info('Create PO Line %s' % product.product_id.name) - self.notification = self.notification + ' %s' % new_po.name + # self.notification = self.notification + ' %s' % new_po.name self.is_po = True class RequisitionLine(models.Model): @@ -221,7 +226,13 @@ class RequisitionLine(models.Model): @api.onchange('price_unit') def _onchange_price_unit(self): - self.subtotal = self.price_unit * self.qty_purchase + for line in self: + line.subtotal = line.price_unit * line.qty_purchase + + @api.onchange('product_id') + def _onchange_product(self): + for line in self: + line.brand_id = line.product_id.product_tmpl_id.x_manufacture.id class RequisitionPurchaseMatch(models.Model): _name = 'requisition.purchase.match' diff --git a/indoteknik_custom/models/res_partner.py b/indoteknik_custom/models/res_partner.py index 2983ca45..a1b57147 100644 --- a/indoteknik_custom/models/res_partner.py +++ b/indoteknik_custom/models/res_partner.py @@ -20,6 +20,7 @@ class ResPartner(models.Model): sppkp = fields.Char(string="SPPKP") counter = fields.Integer(string="Counter", default=0) digital_invoice_tax = fields.Boolean(string="Digital Invoice & Faktur Pajak") + is_potential = fields.Boolean(string='Potential') def get_child_ids(self): partner = self.env['res.partner'].search([('id', '=', self.id)], limit=1) diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index cc6941a9..f9229bca 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -70,14 +70,14 @@ class SaleOrder(models.Model): customer_type = fields.Selection([ ('pkp', 'PKP'), ('nonpkp', 'Non PKP') - ]) - sppkp = fields.Char(string="SPPKP") - npwp = fields.Char(string="NPWP") + ], required=True) + sppkp = fields.Char(string="SPPKP", required=True) + npwp = fields.Char(string="NPWP", required=True) purchase_total = fields.Monetary(string='Purchase Total', compute='_compute_purchase_total') voucher_id = fields.Many2one(comodel_name='voucher', string='Voucher', copy=False) applied_voucher_id = fields.Many2one(comodel_name='voucher', string='Applied Voucher', copy=False) amount_voucher_disc = fields.Float(string='Voucher Discount') - source_id = fields.Many2one('utm.source', 'Source', domain="[('id', 'in', [32, 59, 60, 61])]") + source_id = fields.Many2one('utm.source', 'Source', domain="[('id', 'in', [32, 59, 60, 61])]", required=True) estimated_arrival_days = fields.Integer('Estimated Arrival Days', default=0) email = fields.Char(string='Email') picking_iu_id = fields.Many2one('stock.picking', 'Picking IU') diff --git a/indoteknik_custom/models/solr/apache_solr_queue.py b/indoteknik_custom/models/solr/apache_solr_queue.py index 8dd7c273..07274295 100644 --- a/indoteknik_custom/models/solr/apache_solr_queue.py +++ b/indoteknik_custom/models/solr/apache_solr_queue.py @@ -72,11 +72,12 @@ class ApacheSolrQueue(models.Model): if count == 0: self.create(payload) - def delete_weekly_solr(self, limit=500): + def delete_weekly_solr(self, limit=500, days_after=30): solr = self.search([ ('execute_status', '=', 'success'), - ('execute_date', '>=', (datetime.utcnow() - timedelta(days=7))), + ('execute_date', '>=', (datetime.utcnow() - timedelta(days=days_after))), ], limit=limit) + for rec in solr: rec.unlink() diff --git a/indoteknik_custom/models/users.py b/indoteknik_custom/models/users.py index b90c0097..2ff9933e 100644 --- a/indoteknik_custom/models/users.py +++ b/indoteknik_custom/models/users.py @@ -11,6 +11,7 @@ class Users(models.Model): is_accounting = fields.Boolean(string='Accounting', help='Berhak Approval Internal Use') is_logistic_approver = fields.Boolean(string='Logistic Approver', help='Berhak Approval Penerimaan Barang') is_editor_product = fields.Boolean(string='Editor Product', help='Berhak Mengedit Data Product') + is_admin_reconcile = fields.Boolean(string='Admin Reconcile', help='Berhak Mengedit Journal Reconcile') def notify_internal_users(self, message, title): users = self.search([('share', '=', False)]) diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index 7a074c71..ff467204 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -78,4 +78,7 @@ access_stock_scheduler_compute,access.stock.scheduler.compute,model_stock_schedu access_sale_order_promotion,access.sale.order.promotion,model_sale_order_promotion,,1,1,1,1 access_sale_orders_multi_update,access.sale.orders.multi_update,model_sale_orders_multi_update,,1,1,1,1 access_quotation_so_multi_update,access.quotation.so.multi_update,model_quotation_so_multi_update,,1,1,1,1 -access_product_monitoring,access.product.monitoring,model_product_monitoring,,1,1,1,1
\ No newline at end of file +access_product_monitoring,access.product.monitoring,model_product_monitoring,,1,1,1,1 +access_customer_commision,access.customer.commision,model_customer_commision,,1,1,1,1 +access_customer_commision_line,access.customer.commision.line,model_customer_commision_line,,1,1,1,1 +access_customer_rebate,access.customer.rebate,model_customer_rebate,,1,1,1,1
\ No newline at end of file diff --git a/indoteknik_custom/views/account_bank_statement.xml b/indoteknik_custom/views/account_bank_statement.xml new file mode 100644 index 00000000..db380f37 --- /dev/null +++ b/indoteknik_custom/views/account_bank_statement.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<odoo> + <data> + <record id="account_bank_statement_tree_inherit" model="ir.ui.view"> + <field name="name">account.bank.statement.tree</field> + <field name="model">account.bank.statement</field> + <field name="inherit_id" ref="account.view_bank_statement_tree"/> + <field name="arch" type="xml"> + <field name="state" position="after"> + <field name="is_edit"/> + </field> + </field> + </record> + + <record id="account_bank_statement_form_inherit" model="ir.ui.view"> + <field name="name">account.bank.statement.form</field> + <field name="model">account.bank.statement</field> + <field name="inherit_id" ref="account.view_bank_statement_form"/> + <field name="arch" type="xml"> + <button name="button_reprocess" position="after"> + <button string="Unlock" class="oe_highlight" name="is_edited" type="object" attrs="{'invisible':['|', '|', ('is_edit', '=', True), ('line_ids','=',[]), ('state', '!=', 'confirm')]}"/> + + <button string="Lock" class="oe_highlight" name="not_edited" type="object" attrs="{'invisible':['|', '|', ('is_edit', '=', False), ('line_ids','=',[]), ('state', '!=', 'confirm')]}"/> + </button> + <field name="date" position="after"> + <field name="is_edit" invisible="1"/> + </field> + </field> + </record> + </data> +</odoo>
\ No newline at end of file diff --git a/indoteknik_custom/views/customer_commision.xml b/indoteknik_custom/views/customer_commision.xml new file mode 100644 index 00000000..008c79f8 --- /dev/null +++ b/indoteknik_custom/views/customer_commision.xml @@ -0,0 +1,189 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<odoo> + <record id="customer_commision_tree" model="ir.ui.view"> + <field name="name">customer.commision.tree</field> + <field name="model">customer.commision</field> + <field name="arch" type="xml"> + <tree> + <field name="number"/> + <field name="date_from"/> + <field name="date_to"/> + <field name="partner_id"/> + <field name="description"/> + <field name="notification" readonly="1"/> + <field name="status" readonly="1"/> + </tree> + </field> + </record> + + <record id="customer_commision_line_tree" model="ir.ui.view"> + <field name="name">customer.commision.line.tree</field> + <field name="model">customer.commision.line</field> + <field name="arch" type="xml"> + <tree editable="top" create="false"> + <field name="partner_id" readonly="1"/> + <field name="invoice_id" readonly="1"/> + <field name="state" readonly="1"/> + <field name="product_id" readonly="1" optional="hide"/> + <field name="dpp" readonly="1"/> + <field name="tax" readonly="1" optional="hide"/> + <field name="total" readonly="1" optional="hide"/> + </tree> + </field> + </record> + + <record id="customer_commision_form" model="ir.ui.view"> + <field name="name">customer_commision_form</field> + <field name="model">customer.commision</field> + <field name="arch" type="xml"> + <form> + <header> + <button name="action_confirm_customer_commision" + string="Confirm" type="object" + options="{}"/> + </header> + <sheet string="Customer Commision"> + <div class="oe_button_box" name="button_box"/> + <group> + <group> + <field name="number"/> + <field name="date_from"/> + <field name="partner_id"/> + <field name="description"/> + <field name="commision_percent"/> + <field name="commision_amt"/> + </group> + <group> + <div> + <button name="generate_customer_commision" + string="Generate Line" + type="object" + class="mr-2 oe_highlight" + /> + </div> + <field name="date_to"/> + <field name="commision_type"/> + <field name="notification" readonly="1"/> + <field name="status" readonly="1"/> + <field name="total_dpp"/> + </group> + </group> + <notebook> + <page string="Lines"> + <field name="commision_lines"/> + </page> + </notebook> + </sheet> + <div class="oe_chatter"> + <field name="message_follower_ids" widget="mail_followers"/> + <field name="message_ids" widget="mail_thread"/> + </div> + </form> + </field> + </record> + + <record id="customer_commision_action" model="ir.actions.act_window"> + <field name="name">Customer Commision</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">customer.commision</field> + <field name="view_mode">tree,form</field> + </record> + + <menuitem id="menu_customer_commision_acct" + name="Customer Commision" + action="customer_commision_action" + parent="account.menu_finance_entries" + sequence="113" + /> + + <menuitem id="menu_customer_commision_sales" + name="Customer Commision" + action="customer_commision_action" + parent="sale.product_menu_catalog" + sequence="101" + /> + + <record id="customer_rebate_tree" model="ir.ui.view"> + <field name="name">customer.rebate.tree</field> + <field name="model">customer.rebate</field> + <field name="arch" type="xml"> + <tree> + <field name="partner_id"/> + <field name="date_from"/> + <field name="date_to"/> + <field name="description"/> + <field name="target_1st"/> + <field name="target_2nd"/> + <field name="achieve_1"/> + <field name="achieve_2"/> + <field name="dpp_q1" optional="hide"/> + <field name="dpp_q2" optional="hide"/> + <field name="dpp_q3" optional="hide"/> + <field name="dpp_q4" optional="hide"/> + <field name="status_q1" optional="hide"/> + <field name="status_q2" optional="hide"/> + <field name="status_q3" optional="hide"/> + <field name="status_q4" optional="hide"/> + </tree> + </field> + </record> + + <record id="customer_rebate_form" model="ir.ui.view"> + <field name="name">customer_rebate_form</field> + <field name="model">customer.rebate</field> + <field name="arch" type="xml"> + <form> + <sheet string="Customer Rebate"> + <div class="oe_button_box" name="button_box"/> + <group> + <group> + <field name="date_from"/> + <field name="partner_id"/> + <field name="target_1st"/> + <field name="target_2nd"/> + <field name="dpp_q1"/> + <field name="dpp_q2"/> + <field name="dpp_q3"/> + <field name="dpp_q4"/> + </group> + <group> + <field name="date_to"/> + <field name="description"/> + <field name="achieve_1"/> + <field name="achieve_2"/> + <field name="status_q1"/> + <field name="status_q2"/> + <field name="status_q3"/> + <field name="status_q4"/> + </group> + </group> + </sheet> + <div class="oe_chatter"> + <field name="message_follower_ids" widget="mail_followers"/> + <field name="message_ids" widget="mail_thread"/> + </div> + </form> + </field> + </record> + + <record id="customer_rebate_action" model="ir.actions.act_window"> + <field name="name">Customer Rebate</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">customer.rebate</field> + <field name="view_mode">tree,form</field> + </record> + + <menuitem id="menu_customer_rebate_acct" + name="Customer Rebate" + action="customer_rebate_action" + parent="account.menu_finance_entries" + sequence="114" + /> + + <menuitem id="menu_customer_rebate_sales" + name="Customer Rebate" + action="customer_rebate_action" + parent="sale.product_menu_catalog" + sequence="102" + /> +</odoo>
\ No newline at end of file diff --git a/indoteknik_custom/views/ir_sequence.xml b/indoteknik_custom/views/ir_sequence.xml index 6798e5b4..86259b12 100644 --- a/indoteknik_custom/views/ir_sequence.xml +++ b/indoteknik_custom/views/ir_sequence.xml @@ -60,5 +60,15 @@ <field name="number_next">1</field> <field name="number_increment">1</field> </record> + + <record id="sequence_commision_customer" model="ir.sequence"> + <field name="name">Customer Commision</field> + <field name="code">customer.commision</field> + <field name="active">TRUE</field> + <field name="prefix">CC/%(year)s/</field> + <field name="padding">5</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/product_template.xml b/indoteknik_custom/views/product_template.xml index 6fdb5e8f..92d2191e 100755 --- a/indoteknik_custom/views/product_template.xml +++ b/indoteknik_custom/views/product_template.xml @@ -10,6 +10,7 @@ <field name="web_tax_id"/> <field name="x_manufacture"/> <field name="x_model_product"/> + <field name="kind_of"/> <field name="x_studio_field_tGhJR" widget="many2many_tags"/> </field> <field name="uom_po_id" position="after"> diff --git a/indoteknik_custom/views/purchase_order.xml b/indoteknik_custom/views/purchase_order.xml index 8f7ea6df..bc84bcd1 100755 --- a/indoteknik_custom/views/purchase_order.xml +++ b/indoteknik_custom/views/purchase_order.xml @@ -79,7 +79,7 @@ <field name="description"/> <field name="total_so_percent_margin"/> <field name="has_active_invoice" invisible="1" /> - <field name="purchase_order_lines"/> + <field name="responsible_ids" widget="many2many_tags"/> </field> <field name="order_line" position="attributes"> @@ -115,6 +115,7 @@ <field name="arch" type="xml"> <field name="create_date" position="after"> <field name="approval_status" /> + <field name="responsible_ids" widget="many2many_tags" optional="hide"/> </field> </field> </record> @@ -130,6 +131,7 @@ <field name="po_status"/> <field name="note_description" optional="hide"/> <field name="sale_order_id" optional="hide"/> + <field name="responsible_ids" widget="many2many_tags" optional="hide"/> </field> </field> </record> diff --git a/indoteknik_custom/views/requisition.xml b/indoteknik_custom/views/requisition.xml index e7335a57..e9c3b4e0 100644 --- a/indoteknik_custom/views/requisition.xml +++ b/indoteknik_custom/views/requisition.xml @@ -62,16 +62,6 @@ </group> <group> <div> - <button name="create_requisition_from_sales" - string="Create Line" - type="object" - class="mr-2 oe_highlight" - /> - <button name="create_requisition_from_sales_with_price" - string="Create Line with Price" - type="object" - class="mr-2 oe_highlight" - /> <button name="create_po_from_requisition" string="Create PO" type="object" @@ -82,13 +72,26 @@ </group> <notebook> <page string="Lines"> - <field name="requisition_lines"/> + <field name="requisition_lines"> + <tree editable="line"> + <field name="product_id"/> + <field name="partner_id"/> + <field name="qty_purchase"/> + <field name="price_unit"/> + <field name="subtotal"/> + <field name="brand_id"/> + </tree> + </field> </page> <page string="Matches"> <field name="requisition_match"/> </page> </notebook> </sheet> + <div class="oe_chatter"> + <field name="message_follower_ids" widget="mail_followers"/> + <field name="message_ids" widget="mail_thread"/> + </div> </form> </field> </record> diff --git a/indoteknik_custom/views/res_partner.xml b/indoteknik_custom/views/res_partner.xml index ef4898d0..c1ae3ed3 100644 --- a/indoteknik_custom/views/res_partner.xml +++ b/indoteknik_custom/views/res_partner.xml @@ -14,6 +14,7 @@ <field name="industry_id" position="after"> <field name="company_type_id"/> <field name="group_partner_id"/> + <field name="is_potential"/> <field name="digital_invoice_tax"/> </field> <field name="npwp" position="before"> diff --git a/indoteknik_custom/views/sale_order.xml b/indoteknik_custom/views/sale_order.xml index a260c68a..125296e3 100755 --- a/indoteknik_custom/views/sale_order.xml +++ b/indoteknik_custom/views/sale_order.xml @@ -45,12 +45,12 @@ <field name="helper_by_id" readonly="1"/> </field> <field name="analytic_account_id" position="after"> - <field name="customer_type" attrs="{'required': ['|', ('create_date', '>', '2023-06-28'), ('create_date', '=', False)]}"/> - <field name="npwp" placeholder='99.999.999.9-999.999' attrs="{'required': ['|', ('create_date', '>', '2023-06-28'), ('create_date', '=', False)]}"/> - <field name="sppkp" attrs="{'invisible': [('customer_type','!=','pkp')], 'required': [('customer_type', '=', 'pkp')]}"/> + <field name="customer_type" required="1"/> + <field name="npwp" placeholder='99.999.999.9-999.999' required="1"/> + <field name="sppkp" attrs="{'required': [('customer_type', '=', 'pkp')]}"/> <field name="email" required="1"/> <field name="due_id" readonly="1"/> - <field name="source_id" domain="[('id', 'in', [32, 59, 60, 61])]" attrs="{'required':[('create_date', '>', '2023-09-10')]}"/> + <field name="source_id" domain="[('id', 'in', [32, 59, 60, 61])]" required="1"/> </field> <field name="partner_shipping_id" position="after"> <field name="real_shipping_id"/> diff --git a/indoteknik_custom/views/users.xml b/indoteknik_custom/views/users.xml index d67b4474..020d8ddc 100644 --- a/indoteknik_custom/views/users.xml +++ b/indoteknik_custom/views/users.xml @@ -13,6 +13,7 @@ <field name="is_leader"/> <field name="is_logistic_approver"/> <field name="is_editor_product"/> + <field name="is_admin_reconcile"/> </field> </field> </record> |
