在前面测试通过odoo登录的功能,这次的问题重点是如何访问后台具体的业务类的接口呢?这次就以我们在odoo中安装的lunch模块为例,目标是获取lunch.alert的数据,如下图
具体过程接上次文章,继续完善OdooJsonRpc类的代码,首先是基础代码,这个是需要提供具体的model名称和具体方法,也是是一个很基础的方法,后台的odoo网站会利用类似C#反射的机制调用目标类的方法。
/** * Calls the method of that particular model * @param model Model name * @param method Method name of particular model * @param args Array of fields * @param kwargs Object */ public call(model: string, method: string, args: any, kwargs?: any) { kwargs = kwargs || {}; let params = { model: model, method: method, args: args, kwargs: kwargs == false ? {} : kwargs, context: this.getContext() }; return this.sendRequest("/web/dataset/call_kw", params); }
调用以上基础call方法的几个基本封装函数有如下几个,基本实现了对数据的CRUD功能,当然基本上是针对一条数据的操作
/** * Reads that perticular fields of that particular ID * @param model Model Name * @param id Id of that record which you want to read * @param mArgs Array of fields which you want to read of the particular id */ public read(model: string, id: number, mArgs: any): Promise<any> { let args = [ id, [mArgs] ] return this.call(model, 'read', args) } /** * Provide the name that you want to search * @param model Model name * @param name Name that you want to search */ public nameSearch(model: string, name: string): Promise<any> { let kwargs = { name: name, args: [], operator: "ilike", limit: 0 } return this.call(model, 'name_search', [], kwargs) } /** * Provide the IDs and you will get the names of that paticular IDs * @param model Model name * @param mArgs Array of IDs that you want to pass */ public nameGet(model: string, mArgs: any): Promise<any> { let args = [mArgs] return this.call(model, 'name_get', args) } /** * Create a new record * @param model Model name * @param mArgs Object of fields and value */ public createRecord(model: string, mArgs: any) { let args = [mArgs]; return this.call(model, "create", args, null) } /** * Delete the record of particular ID * @param model Model Name * @param id Id of record that you want to delete */ public deleteRecord(model: string, id: number) { let mArgs = [id] return this.call(model, "unlink", mArgs, null) } /** * Updates the record of particular ID * @param model Model Name * @param id Id of record that you want to update the. * @param mArgs The Object of fields and value that you want to update * (e.g) * let args = { * "name": "Mtfa" * } */ public updateRecord(model: string, id: number, mArgs: any) { let args = [ [id], mArgs ] return this.call(model, "write", args, null) }
针对单条数据的读取,这里还有另外一种方法,类似上面的read函数
/** * Loads all data of the paricular ID * @param model Model name * @param id Id of that particular data which you want to load */ public load(model: string, id: number): Promise<any> { let params = { model: model, id: id, fields: [], context: this.getContext() } return this.sendRequest("/web/dataset/load", params) }
还有对odoo多条件查询的情况,尤其还有分页的问题,这里也有这样一个很实用的分页查询的方法,这个在日后app的开发中会经常用到
/** * Fires query in particular model with fields and conditions * @param model Model name * @param domain Conditions that you want to fire on your query * (e.g) let domain = [ * ["id","=",11] * ] * @param fields Fields names which you want to bring from server * (e.g) let fields = [ * ["id","name","email"] * ] * @param limit limit of the record * @param offset * @param sort sorting order of data (e.g) let sort = "ascending" */ public searchRead(model: string, domain: any, fields: any, limit: number, offset: any, sort: string) { let params = { model: model, fields: fields, domain: domain, offset: offset, limit: limit, sort: sort, context: this.getContext() }; return this.sendRequest("/web/dataset/search_read", params); }
到此,访问odoo具体业务类的OdooJsonRpc类封装完毕,完整的代码在这里。接下来怎么获取我们的lunch.alert数据呢??
首先定义我们访问odoo业务类的成员变量,这里我们的model类是lunch.alert,需要获取的字段是message和id,其他参数我们暂使用默认的值
private lunchAlert = "lunch.alert"; private fields = ["message", "id"]; private domain = [] private sort = "" private limit = 0 private offset = 0 private items: Array<{ id: number, message: string }> = []
第二步是,与odoo后台网站交互获取数据的过程
private TestMyOdooModel() { this.odooRpc.searchRead(this.lunchAlert,this.domain, this.fields, this.limit, this.offset,this.sort) .then((lunchAlerts: any) => { let json = JSON.parse(lunchAlerts._body); if (!json.error) { let query = json["result"].records for (let i in query) { this.items.push ({ id: query[i].id, message: query[i].message }) } this.utils.presentAlert("Lunch Message", this.items[0].message,[{text: "Ok"}]) } else { this.utils.presentAlert("LunchAlert", "Parse lunch alert error",[{text: "Ok"}]) } }) }
如果正确获取数据,我们会弹出第一条数据对应的message.
编译打包成*.apk,在手机上测试,确实成功了,如下图所示。
由于这些都是测试阶段的代码,将来可能会改变,现阶段把这些代码全部放在这里。
测试部分的Page页面odooLogin.ts
import { Component } from '@angular/core';
import {
AlertController,
IonicPage,
Loading,
LoadingController,
NavController,
NavParams
} from 'ionic-angular';
import { OdooJsonRpc } from '../../../../providers/baseService/Odoojsonrpc';
import { Utils } from "../../../../providers/baseService/Utils";
@IonicPage()
@Component
({
selector: 'page-odooLogin',
templateUrl: 'odooLogin.html',
})
export class OdooLoginPage
{
private listForProtocol: Array<{ protocol: string}> = []
public perfectUrl: boolean = false
public odooUrl
public selectedProtocol
private dbList: Array<{ dbName: string}> = []
private selectedDatabase
private email
private password
constructor(public navCtrl: NavController,
private alert: AlertController, public navParams: NavParams,
private odooRpc: OdooJsonRpc, private loadingCtrl: LoadingController,
private utils: Utils)
{
this.listForProtocol.push({ protocol: "http" })
this.listForProtocol.push({protocol: "https"})
}
public checkUrl()
{
this.utils.presentLoading("Please Wait")
this.odooRpc.init
({
odoo_server: this.selectedProtocol + "://" + this.odooUrl
//http_auth: 'username:password' // optional
})
this.odooRpc.getDbList().then((dbList: any) =>
{
console.log(dbList)
this.perfectUrl = true
this.utils.dismissLoading()
this.fillData(dbList)
}).
catch((err: any) =>
{
console.log(err)
this.utils.presentAlert("Error", "You Entered a wrong Odoo URL",
[{
text: "Ok"
}])
this.utils.dismissLoading()
});
}
public fillData(res: any)
{
let body = JSON.parse(res._body)
let json = body['result'];
this.dbList.length = 0;
for (var key in json)
{
this.dbList.push({ dbName: json[key] });
}
}
private login()
{
this.utils.presentLoading("Please wait", 0, true)
this.odooRpc.login(this.selectedDatabase, this.email, this.password)
.then((res: any) =>
{
let logiData: any = JSON.parse(res._body)["result"];
logiData.password = this.password
localStorage.setItem("token", JSON.stringify(logiData));
//this.utils.dismissLoading()
this.utils.presentAlert("Congratulation", "You login success",[{text: "Ok"}])
this.TestMyOdooModel()
}).
catch((err) =>
{
this.utils.presentAlert("Error", "Username or password must be incorrect",
[{
text: "Ok"
}])
});
}
private lunchAlert = "lunch.alert";
private fields = ["message", "id"];
private domain = []
private sort = ""
private limit = 0
private offset = 0
private items: Array<{ id: number, message: string }> = []
private TestMyOdooModel()
{
this.odooRpc.searchRead(this.lunchAlert,this.domain, this.fields, this.limit, this.offset,this.sort)
.then((lunchAlerts: any) =>
{
let json = JSON.parse(lunchAlerts._body);
if (!json.error)
{
let query = json["result"].records
for (let i in query)
{
this.items.push
({
id: query[i].id,
message: query[i].message
})
}
this.utils.presentAlert("Lunch Message", this.items[0].message,[{text: "Ok"}])
}
else
{
this.utils.presentAlert("LunchAlert", "Parse lunch alert error",[{text: "Ok"}])
}
})
}
}