odoo return wizard from onchange method - python

From what i read you cannot return an action from an onchange function. But I want to show a dialog of some sort when a user changes the product within an orderline. The goal is to check if the product contains has_newproduct = True. In this case I want to ask the user if they want to delete the origin product (since it will not be needed).
I am overriding the onchange function of purchase order line like this:
class api_advanced(models.Model):
_inherit = "purchase.order.line"
has_newproduct = fields.Boolean("New Product")
#api.onchange('product_id')
def onchange_product_id(self):
_logger.debug("------------------- OLD PRODUCT ID ----------------")
_logger.debug(self._origin.product_id)
_logger.debug(self._origin.has_newproduct)
_logger.debug("------------------- NEW PRODUCT ID ----------------")
_logger.debug(self.product_id)
_logger.debug(self.has_newproduct)
# Code to fire wizard is here but it does nothing...
How would i have to acomplish something similar? Or do i have to do something totally different? I could just delete the product without asking but that's not really the goal here...

How you open wizard. when you click on button odoo calls a method,
method return a dictionary to the client side. the client side will
examine the returned value. client side know that this is an action to open a view.
What i'm trying to say this behavior is defined in javascript so if you
want some thing like that you should extends the form view to handle
the returned value from onchange event to open a wizard.
Or you can just add a button to the tree view with text delete orignal product
that button will appear only if has_newproduct = True (use related field to add it to tree so you can use it in attrs). The user will know that he can delete the orignal
product if he see that button and you can add confirm message to explain what
are the consequence of that operation.

Related

How to register payment for invoice from python in Odoo v15 CE

I am trying to make a single action on a sales order in Odoo v15 CE that creates an invoice for the sales order and immediately posts it and registers a payment for it. The way I'm doing so is through a wizard method that looks like this:
def create_invoices(self):
sale_orders = self.env['sale.order'].browse(self._context.get('active_ids', []))
for order in sale_orders:
order._create_invoices()
for inv in order.invoice_ids:
# make invoice:
inv.action_post()
# register payment
# ????
Currently, it creates the invoice and posts it. I would like to add something like inv.register_payment() to the final line in order to register the payment.
I've fount the action_register_payment method of the account.move model and also looked into using the account.payment.register wizard but neither worked. I've also found this question, which is trying to do something similar, but through an XML-RPC call (from what I can tell).
Can anyone please explain how to do this? Thanks!
You have to post the invoices using action_post then register payment by creating a payment like in
https://github.com/odoo/odoo/blob/15.0/addons/account/wizard/account_payment_register.py#L496
account.payment.register is a wizard, that's why you need to create values for it, otherwise you can action_register_payment which is a window action that will trigger the wizard and then it's for the user to register the payment (which is the standard behavior of Odoo)
You can create an account.payment.register record and pass the model and invoice ids in context then call action_create_payments to create the payment with the default values.
Example:
payment_register.with_context(
{'active_model': 'account.move',
'active_ids': inv.ids}
).create({}).action_create_payments()

Automated Action Grant Portal Access

Im trying to make an Automated Action, when I create a user also grand access to portal.
My code so far is bind on button Apply to All (see image below):
for rec in records:
for user in rec.user_ids:
user['in_portal'] = True
rec.action_apply()
Apply to All Button Code: <button name="563" type="action" string="Apply to All"/>
How can i modify the code so it run, when I create a user and also grand access to portal?
There are some options, to implement what you need.
Override create() of model res.users and just add users to your desired group(s) after super call.
Create an automated action (Settings/Technical/Automation/Automated Actions)
Model: Users (res.users)
Trigger Condition: On Creation
Action To Do: Update the Record
Data to Write: add one line
Field: Groups (res.users)
Evaluation Type: Python expression
Value: [(4,env.ref('external id of group').id)]
Substitute external id of group with base.group_portal so in your case it should be [(4,env.ref('base.group_portal').id)]

Odoo - Changing user group id just right after signup (ecommerce)

I'm using Odoo 10. After a new user sign up (through localhost:8069/web/signup) i want him to be automatically allocated inside a group i created on my very own custom module (the user will need authentication from an admin later on so he can be converted to a regular portal user; after signup he will receive restricted access).
I have tried many things. My latest effort looks like this:
class RestrictAccessOnSignup(auth_signup_controller.AuthSignupHome):
def do_signup(self, *args):
super(RestrictAccessOnSignup, self).do_signup(*args)
request.env['res.groups'].sudo().write({'groups_id': 'group_unuser'})
Note that I have import odoo.addons.auth_signup.controllers.main as auth_signup_controller so that I can override the auth_signup controller.
I have located that method as the responsible for doing the signup. So I call it in my new method and then try to change the newly created user's group_id.
What i miss is a fundamental understanding of how to overwrite a field's value from another model inside a controller method context. I'm using the 'request' object although i'm not sure of it. I have seen people using 'self.pool['res.users'] (e.g.) for such purposes but i don't understand how to apply it inside my problem's context.
I believe, also, that there is a way to change the default group for a user after it is created (i would like to know), but i also want to understand how to solve the general problem (accessing and overwriting a field's value from another module).
Another weird thing is that the field groups_id does exist in 'res.users' model, but it does not appear as a column in my pgAdmin interface when i click to see the 'res.users' table... Any idea why?
Thanks a lot!
i don't know if after calling :
super(RestrictAccessOnSignup,self).do_signup(*args)
you will have access to user record in request object but if so just add
the group to user like this, if not you have to find where the user record or id is saved after calling do_signup because you need to update that record to ad this group.
# create env variable i hate typing even i'm typing here ^^
env = request.env
env.user.sudo().write({'groups_id': [
# in odoo relation field accept a list of commands
# command 4 means add the id in the second position must be an integer
# ref return an object so we return the id
( 4, env.ref('your_module_name.group_unuser').id),
]
})
and if changes are not committed in database you may need to commit them
request.env.cr.commit()
Note: self.env.ref you must pass the full xmlID.
This is what worked for me:
def do_signup(self, *args):
super(RestrictAccessOnSignup, self).do_signup(*args)
group_id = request.env['ir.model.data'].get_object('academy2', 'group_unuser')
group_id.sudo().write({'users': [(4, request.env.uid)]})
In the get_object i pass as arguments the 'module' and the 'xmlID' of the group i want to fetch.
It is still not clear to me why 'ir.model.data' is the environment used, but this works as a charm. Please note that here we are adding a user to the group, and not a group to the user, and to me that actually makes more sense.
Any further elucidation or parallel solutions are welcome, the methods aren't as clear to me as they should be.
thanks.

"disable" on_change id odoo 9 after creating product

I'd like to ask, if is there any way to "disable" onchange decorator, when product is already created.
I have a field (X), which value depends, what will be in the 3 another fields (Y). I've used "api.onchange". When product is created, i want to make, that one of Y fields, will not change a value of X anymore.
I tryed to check, if "self" is existing in database, like exists(), but even new record is marked as "existing". I tryed to get access to self.id, but it's impossible. I thought about create additional field with Boolean type, but it's the last resort.
NEW API
First picture i added an onchange event to the name of product.template i used debug mode to stop the program and see if i have an acces to self._origin clearly i have access to it
Second picture it shows when I updated a product the ID value is passed
Now Third picture shows when i'm creating a new Product the value of the id in self._origin is False
so can you post the code that use used please i want to understand why you don't have acccess to self._origin
OLD API
when using old api self._origin is not access but you have the list of ids in edit mode the list will not be empty .
def onchange_name(self, cr, uid, ids, name, context=None):
# when updating a record ids will not be empty
# in my case will be ids=[55]
# in create mode the ids is empty
# id = []
if not ids :
# here you are in create mode you put your logic here

Django ModelChoiceField with empty_label as valid input

I'm using the following form to generate a dropdown list with my registered users:
class TaskAssignUserForm(forms.Form):
user = forms.ModelChoiceField(queryset=User.objects.all().order_by('username'))
Inside my template I render the above form together with a submit button. The application user can choose from the registered users to select one and assign him/her to a task. This is working, if a user and not the empty label (--------) was selected.
But, I want the empty label as a valid option too, to cancel the assignment between the task and the user. I'm working with the following views.py and looking for an option to check if the empty label or an empty choice was made.
if form_TaskAssignUserForm.is_valid():
task.user_assigned = form_TaskAssignUserForm.cleaned_data['user']
task.save()
else:
if # check if emtpy label is set
task.user_assigned = None
task.save()
I found out that checking if form_TaskAssignUserForm.cleaned_data['user'] exists could be an option but I feel not comfortable with that. There should be a way that works together with the .is_valid() check.
Is there a djangonian way solving that problem?
Bye, aronadaal
You should just need to set required=False on the field.
user = forms.ModelChoiceField(required=False, queryset=User.objects.all().order_by('username'))
This means that no selection is required for the form to be valid.

Categories