在前面测试通过odoo登录的功能,这次的问题重点是如何访问后台具体的业务类的接口呢?这次就以我们在odoo中安装的lunch模块为例,目标是获取lunch.alert的数据,如下图

ionic 访问odoo11之具体业务类api接口

具体过程接上次文章,继续完善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,在手机上测试,确实成功了,如下图所示。

ionic 访问odoo11之具体业务类api接口

由于这些都是测试阶段的代码,将来可能会改变,现阶段把这些代码全部放在这里。

测试部分的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"}])
                }
            })
    }
}
View Code

相关文章: