Let's say I set up Server Action A on the stock.inventory model. This action simply logs a value and then calls Sever Action B (which has a database ID of 366). The python code in the action is just:
log('running server action a')
value = {
"type": "ir.actions.server",
"id": 366,
}
Then, in Server Action B, which is on the product.product model, the python code is just:
log('running server aciton b')
Now, when I add Server Action A to the "More" menu, and manually trigger it from the browser on a stock.inventory object, both actions successfully run. In other words, I see both 'running server action a' and 'running server action b' in the logs.
Now, I create an Automated Action to trigger Server Action A on Update or Create of a stock.inventory object. After doing this, and updating or creating a stock.inventory object via the UI, I only see 'running server action a' in the logs. In other words, Server Action B never gets triggered like it did when I ran the same experiment manually from the "More" menu.
So, my question is whether or not it is possible to trigger a second server action from the first server action if the first server action is triggered by an automated action.
I was able to get this working and the solution is very simple. This seems like a pretty cool way for Odoo Online users to treat server actions as functions that can return values to the calling server action.
Here's an example.
Server Action A
a = env['ir.actions.server'].browse(409)
ctx = dict(env.context or {})
ctx.update({'active_id': 169, 'active_model': 'purchase.order'})
a.with_context(ctx).run()
Server Action B (ID = 409)
raise Warning(record)
When you trigger the first action, you'll get the string purchase.order(169,) as output.
Even cooler, if the second server assigns a value to action, it is returned to the first action. For example:
Server Action A
a = env['ir.actions.server'].browse(409)
ctx = dict(env.context or {})
ctx.update({'active_id': 169, 'active_model': 'purchase.order'})
resp = a.with_context(ctx).run()
raise Warning(resp)
Server Action B (ID = 409)
action = record.id
When you trigger the first server action, you'll see 169 as the response.
If you have access to the admin section. You should be able to call the function directly. In odoo8 it looks like this.
Pick your server action
Notice the python code section. You should be able to locate the model you need and execute the function directly.
action = self.env['addon.model'].the_fun()
To execute another action, try the following.
action = self.env['ir.actions.server'].ref('xml_id_of_action')
action.run_action_code_multi()
Here is the description
run_action_code_multi(self, *args, **kwargs)
Override to allow returning response the same way action is already
returned by the basic server action behavior. Note that response has
priority over action, avoid using both.
Related
I created a script which updates work items in a polarion document. However, right now each workitem update is a single save. But my script updates all work items in the document, which results in a large number of save actions in the api and thus a large set of clutter in the history.
If you edit a polarion document yourself, it will update all workitems.
Is it possible to do this same thing with the polarion API?
I tried
Using the tracker service to update work items. This only allows a single work item to be updated.
Using the web development tools to try and get information from the API. This seems to use a UniversalService for which no documentation is available at the API site https://almdemo.polarion.com/polarion/sdk/index.html
Update 1:
I am using the python polarion package to update the workitems.Python polarion Based on the answer by #boaz I tried the following code:
project = client.getProject(project_name)
doc = project.getDocument(document_location)
workitems = doc.getWorkitems()
session_service = client.getService("Session")
tracker_service = client.getService("Tracker")
session_service.beginTransaction()
for workitem in workitems:
workitem.description = workitem._polarion.TextType(
content=str(datetime.datetime.now()), type='text/html', contentLossy=False)
update_list = {
"uri": workitem.uri,
"description": workitem.description
}
tracker_service.updateWorkItem(update_list)
session_service.endTransaction(False)
The login step that #boaz indicated is done in the backend (See: https://github.com/jesper-raemaekers/python-polarion/blob/3e61527cf0f1f3c8614a30289a0a3409d2d8712d/polarion/polarion.py#L103)
However, this gives the following Java exception:
java.lang.RuntimeException: java.lang.NullPointerException
Update 2
There seems to be an issue with the session. If I call the following code:
session_service.logIn(user, password)
print(session_service.hasSubject())
it prints False.
The same thing happens when using the transaction:
session_service.beginTransaction()
print(session_service.transactionExists())
also prints False
Try wrapping your changes in a SessionWebService transaction, see JavaDoc:
sessionService = factory.getSessionService();
sessionService.logIn(prop.getProperty("user"),
prop.getProperty("passwd"));
sessionService.beginTransaction();
// ...
// your changes
// ...
sessionService.endTransaction(false);
sessionService.endSession();
As shown in the example in Polarion/polarion/SDK/examples/com.polarion.example.importer.
This will commit all your changes in one single SVN commit.
I am trying to automatically print a report when a field is triggered with an automated action. In the documentation is says to return an action assign: action = {...} but nothing is happening. Here is my code. I'm just trying to download the basic package report pdf so I can then print the pdf.
action = {
'type': 'ir.actions.report',
'name': 'Package Barcode (PDF)',
'model': 'stock.quant.package',
'report_type': 'qweb-pdf',
'report_name': 'stock.action_report_quant_package_barcode_small',
}
I have also tried to use the report_action() method to download and then print the pdf report but I have had no luck with that either.
env.ref('stock.action_report_quant_package_barcode_small').report_action(record)
Any help would be appreciated. I don't want to rely on a third party module. I'm just looking for the same functionality if you where to click on the print button and then select the report you wanted to print from the UI. It downloads the pdf then you can open it and print it from there.
The automated action will run the corresponding server action and ignore the returned value. It will not execute the returned action.
You see that in the documentation because the delegate parameter is set to True on the server action field which make fields of the target model (Server Action) accessible from the current model (corresponds to _inherits).
The automated action inherited the server action fields
What is the use / purpose of logging menu in the
Settings -> Technical -> Database structure -> Logging
It seems that you can store all the log messages in that view (model ir.logging) as long as you use the parameter --log-db your_database_name when executing odoo-bin in the command line (or add log_db = your_database_name in your Odoo config file).
Check out Odoo 11 info about command line parameters: https://www.odoo.com/documentation/11.0/reference/cmdline.html
--log-db
logs to the ir.logging model (ir_logging table) of the specified database. The database can be the name of a database in the “current” PostgreSQL, or a PostgreSQL URI for e.g. log aggregation
This is the theory, but honestly, I was not able to make it work, and I did not waste much time in trying to know why.
EDIT
As #CZoellner says, it seems that log messages stored in ir_logging table (log messages you see clicking on the menuitem Settings -> Technical -> Database structure -> Logging) come only from scheduled actions. If you create an scheduled action which executes some Python code, you have the following available variables to use in your method code:
env: Odoo Environment on which the action is triggered.
model: Odoo Model of the record on which the action is triggered; is a void recordset.
record: record on which the action is triggered; may be void.
records: recordset of all records on which the action is triggered in multi-mode; may be void.
time, datetime, dateutil, timezone: useful Python libraries.
log: log(message, level='info'): logging function to record debug information in ir.logging table.
Warning: Warning Exception to use with raise To return an action, assign: action = {...}.
If you use the log one, for example:
log('This message will be stored in ir_logging table', level='critical')
That log message and its details will be stored in ir_logging table each time the scheduled action is executed (automatically or manually). This answers your question, but now I am wondering what is the parameter --log-db, as I have tested it and these log messages are stored in ir_logging no matter this parameter is set or not.
I have implemented outputcaching on Action method of controller with
[OutputCache(Duration = 60, VaryByParam = "ID", VaryByHeader="User-Agent", Location = System.Web.UI.OutputCacheLocation.Server)]
public ActionResult MyAction(int ID)
{
_logger.Error("call-" + ID);
}
and I have made log entry within this action. So, My problem is Output caching with location=Server calls this action method every time. It should not call every-time.
So, what's the problem with this?
When I changed Caching location i.e location=Client then only first time it calls the method. Then afterwards action method not called.
Are you trying output caching on the ChildAction? I know you have not written ChildAction attribute in your question but just asking for confirmation ? If it is then you can't use output caching on which are not Child Actions. You need to use this caching plugin if you want to use output caching without child action.
The idea is:
Perform some time consuming action in background.
Have the results from that action be propagated back to the controller using a callback.
Store the result in an in memory session store.
Have the result in session be used and available from that point onward.
Controller receives the results in the callback:
# controller callback, saves result to session
# this method is executed as expected
# session id matches the one from other controller actions
def on_counter_value_calculated(context, new_value)
#counter = new_value
session[:counter] = #counter
end
However, stored session is lost in subsequent calls:
# although the same session is targeted (same id)
# the saved value is not the same
def index
#counter = session[:counter] || 0
end
I've created a small Rails project that demonstrates the issue:
https://github.com/elvanja/controller_callbak_store_in_session
Any input appreciated.
Checked Rails code, and if I understand correctly, session in fact comes from request:
# actionpack-3.2.11/lib/action_controller/metal.rb:132
delegate :session, :to => "#_request"
It seems session is valid only within request cycle context and although it can be accessed, the changes are not saved, as demonstrated by the project.
Hence, this will not work. As suggested # Ruby on Rails Google Group and Ruby Rogues, the best way to deal with this is to use Sidekiq, DelayedJob, Resque or similar frameworks.
EDIT: Access `session` within rails controller thread is actually the reason (background processing in the example is done in a separate thread).