I'm working with Odoo 16 and have encountered a problem with linking two models and handling _unknown
values. Specifically, I have two models: nkap_custom_paiement
and account.payment.register
. The former is a custom model inheriting from account.payment
, and the latter is a TransientModel
used for payment registration.
Models Overview:
nkap_custom_paiement
(Inheriting account.payment
)
Has a field related_payment_id
that links to account.register.payment
. Handles payment approvals and has methods like action_cashier_approval
to perform actions on linked payments.
CustomPaymentRegister
(Inheriting account.payment.register
)
Handles the creation of account.payment
records and sets the related_payment_id
to link back to the wizard.
I am trying to add an approval process to the payments that are registered through the wizard. After the approval, it should call back the initial method on the wizard (that's why I need to store id)
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError, UserError
import re
class nkap_custom_paiement(models.Model):
# _inherit = 'account.payment'
_inherit = ['account.payment']
related_payment_id = fields.Many2one('account.register.payment', string='Related Wizard')
state = fields.Selection([
('draft', 'Drafted'),
('waiting_approval', 'Waiting Approval'),
('approved', 'Approved'),
('rejected', 'Rejected'),
('posted', 'Posted'),
], string="Approval Status",default='draft')
DFC_approver_sign = fields.Binary('DFC Signature')
DG_approver_sign = fields.Binary('DG Signature')
current_approval = fields.Selection([('1', '1'), ('2', '2'), ('3', '3')], string="Is Current Approver")
def action_submit_for_approval(self):
company_id=self.env.company
self.write({'state': 'waiting_approval'})
message = "Vous avez un paiement pour la 1ere approbation"
self.current_approval = '1'
self.activity_schedule('purchase_order_approval.mail_activity_data_approval', user_id=company_id.po_third_approver_ids.id, note=message)
self.env['bus.bus']._sendone(company_id.po_third_approver_ids.partner_id, 'simple_notification', {'title': _("Information"), 'message': message})
def action_DFC_approval(self):
company_id=self.env.company
if self.env.user.id in company_id.po_third_approver_ids.ids:
self.current_approval = '2'
self.write({'state': 'waiting_approval'})
self.DFC_approver_sign = self.env.user.user_signature
message = "Vous avez un paiement pour la 2ere approbation "
self.activity_schedule('purchase_order_approval.mail_activity_data_approval', user_id=company_id.po_DG_approver_ids.id, note=message)
else:
raise ValidationError(_("Seul %s peut approver !"% company_id.po_third_approver_ids.id ))
def action_DG_approval(self):
company_id=self.env.company
if self.env.user.id in company_id.po_DG_approver_ids.ids:
self.write({'state': 'approved'})
self.current_approval = '3'
self.DG_approver_sign = self.env.user.user_signature
message = "Vous avez un paiement pour la validation"
self.activity_schedule('purchase_order_approval.mail_activity_data_approval', user_id=company_id.po_fourth_approver_ids.id, note=message)
else:
raise ValidationError(_("Seul %s peut approver !"% company_id.po_DG_approver_ids.id ))
def action_cashier_approval(self):
company_id=self.env.company
if self.env.user.id in company_id.po_fourth_approver_ids.ids:
self.write({'state': 'posted'})
if self.related_payment_id:
related_payment = self.env['account.payment.register'].browse(self.related_payment_id)
if related_payment.exists():
# Call a method on the related payment record
related_payment.action_create_payments()
else:
_logger.error("Related payment record with ID %s does not exist", self.related_payment_id.id)
else:
raise ValidationError(_("Seul %s peut approver !"% company_id.po_fourth_approver_ids.id ))
def action_reject(self):
company_id=self.env.company
current_approver = None
if self.current_approval =='1':
current_approver=company_id.po_third_approver_ids
elif self.current_approval =='2':
current_approver=company_id.po_DG_approver_ids
else:
raise UserError(_(f"{self.current_approval},{type(self.current_approval)}"))
if self.env.user.id in current_approver.ids:
self.write({'state': 'rejected'})
else:
raise ValidationError(_("Seul %s peut refuser cette DA !" % current_approver.name))
def rollback(self):
'''to cancel all the signature already done to false'''
self.write({
'DFC_approver_sign': False,
'DG_approver_sign': False,
'current_approval': False,
})
class CustomPaymentRegister(models.TransientModel):
_inherit = 'account.payment.register'
payment_id = fields.Many2one('account.payment', string='Created Payment')
def _collect_payment_vals(self):
payment_vals = {
'amount': self.amount,
'partner_id': self.partner_id.id,
'journal_id': self.journal_id.id,
'payment_method_line_id': self.payment_method_line_id.id,
'date': self.payment_date,
'currency_id': self.currency_id.id,
'ref': self.communication,
'partner_bank_id': self.partner_bank_id.id,
'bank_reference': self.bank_reference,
'cheque_reference': self.cheque_reference,
}
return payment_vals
def action_submit_for_approval(self):
payment_vals = self._collect_payment_vals()
payment = self.env['account.payment'].create(payment_vals)
self.payment_id = payment.id
payment.related_payment_id = self.id
# raise ValidationError(_(f"{self.id}// {payment.related_payment_id}//{number}"))
# Call the approval flow for each payment created
payment.action_submit_for_approval()
I have tried several ways to link the both model through the field payment_id
in account.register.payment
model and related_payment_id
in account.payment
, but it is still giving the self_id
in this _unknown(actual_id,)
That's just a typo on your class nkap_custom_paiement
. The comodel for the field related_payment_id
is account.payment.register
and not account.register.payment
. If Odoo can't find the related model on e.g. a Many2one field in its model pool, it will fill it with model name _unknown
(click)
def setup_nonrelated(self, model):
super().setup_nonrelated(model)
if self.comodel_name not in model.pool:
_logger.warning("Field %s with unknown comodel_name %r", self, self.comodel_name)
self.comodel_name = '_unknown'