use crate as odoo_api;
use crate::jsonrpc::{OdooApiMethod, OdooId};
use odoo_api_macros::odoo_api;
use serde::ser::SerializeTuple;
use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
use serde_tuple::Serialize_tuple;
#[odoo_api(service = "object", method = "execute", auth = true)]
#[derive(Debug)]
pub struct Execute {
pub database: String,
pub uid: OdooId,
pub password: String,
pub model: String,
pub method: String,
pub args: Vec<Value>,
}
impl Serialize for Execute {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut state = serializer.serialize_tuple(5 + self.args.len())?;
state.serialize_element(&self.database)?;
state.serialize_element(&self.uid)?;
state.serialize_element(&self.password)?;
state.serialize_element(&self.model)?;
state.serialize_element(&self.method)?;
for arg in &self.args {
state.serialize_element(&arg)?;
}
state.end()
}
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(transparent)]
pub struct ExecuteResponse {
pub data: Value,
}
#[odoo_api(service = "object", method = "execute_kw", auth = true)]
#[derive(Debug, Serialize_tuple)]
pub struct ExecuteKw {
pub database: String,
pub uid: OdooId,
pub password: String,
pub model: String,
pub method: String,
pub args: Vec<Value>,
pub kwargs: Map<String, Value>,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(transparent)]
pub struct ExecuteKwResponse {
pub data: Value,
}
#[cfg(test)]
mod test {
use super::*;
use crate::client::error::Result;
use crate::jsonrpc::{JsonRpcParams, JsonRpcResponse};
use crate::{jmap, jvec};
use serde_json::{from_value, json, to_value};
#[test]
fn execute() -> Result<()> {
let expected = json!({
"jsonrpc": "2.0",
"method": "call",
"id": 1000,
"params": {
"service": "object",
"method": "execute",
"args": [
"some-database",
2,
"password",
"res.users",
"read",
[1, 2],
["id", "login"]
]
}
});
let actual = to_value(
Execute {
database: "some-database".into(),
uid: 2,
password: "password".into(),
model: "res.users".into(),
method: "read".into(),
args: jvec![[1, 2], ["id", "login"]],
}
.build(1000),
)?;
assert_eq!(actual, expected);
Ok(())
}
#[test]
fn execute_response() -> Result<()> {
let payload = json!({
"jsonrpc": "2.0",
"id": 1000,
"result": [
{
"id": 1,
"login": "__system__"
},
{
"id": 2,
"login": "admin"
}
]
});
let response: JsonRpcResponse<ExecuteResponse> = from_value(payload)?;
match response {
JsonRpcResponse::Error(e) => Err(e.error.into()),
JsonRpcResponse::Success(_) => Ok(()),
}
}
#[test]
fn execute_kw() -> Result<()> {
let expected = json!({
"jsonrpc": "2.0",
"method": "call",
"id": 1000,
"params": {
"service": "object",
"method": "execute_kw",
"args": [
"some-database",
2,
"password",
"res.users",
"read",
[
[1, 2]
],
{
"fields": ["id", "login"]
}
]
}
});
let actual = to_value(
ExecuteKw {
database: "some-database".into(),
uid: 2,
password: "password".into(),
model: "res.users".into(),
method: "read".into(),
args: jvec![[1, 2]],
kwargs: jmap! {
"fields": ["id", "login"]
},
}
.build(1000),
)?;
assert_eq!(actual, expected);
Ok(())
}
#[test]
fn execute_kw_response() -> Result<()> {
let payload = json!({
"jsonrpc": "2.0",
"id": 1000,
"result": [
{
"id": 1,
"login": "__system__"
},
{
"id": 2,
"login": "admin"
}
]
});
let response: JsonRpcResponse<ExecuteKwResponse> = from_value(payload)?;
match response {
JsonRpcResponse::Error(e) => Err(e.error.into()),
JsonRpcResponse::Success(_) => Ok(()),
}
}
}