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


    在前面测试通过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"}])
                    }
                })
        }
    }
    View Code

    页面布局部分odooLogin.html

    <ion-content class="background">
      <ion-card>
        <ion-card-content>
    
          <div class="spacer" style="height: 10px;"></div>
          <ion-item>
            <ion-label style="color: #fff">Select Protocol</ion-label>
            <ion-select [(ngModel)]="selectedProtocol" style="color: #fff" name="dbNames">
              <ion-option *ngFor="let item of listForProtocol" value="{{item.protocol}}">{{item.protocol}}</ion-option>
            </ion-select>
          </ion-item>
          <div class="spacer" style="height: 10px;"></div>
          <ion-item>
            <ion-input [(ngModel)]="odooUrl" type="url" name="odooUrl" placeholder="Odoo Url"></ion-input>
          </ion-item>
          <div class="spacer" style="height: 10px;"></div>
          <button ion-button block round outline color="light" (click)="checkUrl()" text-center>
            Check Url
            <ion-icon name="md-arrow-round-forward"></ion-icon>
          </button>
          <div [hidden]="!perfectUrl">
            <form (ngSubmit)="login()" #registerForm="ngForm">
              <div class="spacer" style="height: 10px;"></div>
              <ion-item>
                <ion-input type="email" [(ngModel)]="email" name="email" placeholder="Email" required></ion-input>
              </ion-item>
              <div class="spacer" style="height: 5px;"></div>
              <ion-item>
                <ion-input type="password" [(ngModel)]="password" name="pass" placeholder="Password" required></ion-input>
              </ion-item>
              <div class="spacer" style="height: 10px;"></div>
              <div class="spacer" style="height: 10px;"></div>
              <ion-item>
                <ion-label style="color: #fff">Select Database</ion-label>
                <ion-select [(ngModel)]="selectedDatabase" name="selectDatabase" style="color: #fff" required>
                  <ion-option *ngFor="let item of dbList" value="{{item.dbName}}">{{item.dbName}}</ion-option>
                </ion-select>
              </ion-item>
              <button ion-button block round outline color="light" [disabled]="!registerForm.form.valid" (click)="signin()">Login</button>
            </form>
          </div>
        </ion-card-content>
      </ion-card>
    </ion-content
    View Code

    CSS效果部分odooLogin.scss

    page-odooLogin {
        .background {
            height: 100%;
             100%;
            background-size: cover !important;
            background-position: center center !important;
            background-image: url('../assets/imgs/mountain.jpg')
        }
    
        ion-card.card {
            margin-top: 30%;
            box-shadow: none;
            background: rgba(0, 0, 0, 0.5);
            border-radius: 5px;
        }
        a, p,
        ion-card-header.card-header {
            color: #fff!important;
        }
    
        .list > .item-block:first-child {
            border: medium none;
        }
    
        .item {
            margin-bottom: 10px;
            background: rgba(255, 255, 255, 0.5);
            border: medium none;
    
            .text-input, {
                color: #fff;
            }
    
    
            input::-moz-placeholder{
                color: #fff!important;
            }
            input:-moz-placeholder {
                color: #fff!important;
            }
            *:-moz-placeholder{
                color: #fff!important;
            }
            *:-ms-input-placeholder{
                color: #fff!important;
            }
            *::-webkit-input-placeholder{
                color: #fff!important;
            }
        }
    }
    View Code

    OdooJsonRpc部分Odoojsonrpc.ts

    import { Injectable } from '@angular/core';
    import 'rxjs/add/operator/toPromise';
    import 'rxjs/Rx';
    
    import { Headers, Http } from '@angular/http';
    import { Utils } from './Utils';
    
    @Injectable()
    export class OdooJsonRpc
    {
        private jsonRpcID: number = 0;
        private headers: Headers;
        private odoo_server: string;
        private http_auth: string;
        private list = "/web/database/list";
        private get_list = "/web/database/get_list";
        private jsonrpc = "/jsonrpc";
    
        constructor(private http: Http, private utils: Utils)
        {
            this.http = http;
        }
    
        /**
         * Builds a request for odoo server
         * @param url Odoo Server URL
         * @param params Object
         */
        private buildRequest(url: String, params: any)
        {
            this.jsonRpcID += 1;
            return JSON.stringify
            ({
                jsonrpc: "2.0",
                method: "call",
                id: this.jsonRpcID,
                params: params,
            });
        }
    
        /**
         * Returns the error message
         * @param response Error response from server
         */
        public handleOdooErrors(response: any)
        {
            let err: string = response.error.data.message
            let msg = err.split("
    ")
            let errMsg = msg[0]
    
            this.utils.presentAlert("Error", errMsg, [{
                text: "Ok",
                role: "cancel"
            }])
        }
    
        /**
         * Handles HTTP errors
         */
        public handleHttpErrors(error: any)
        {
            return Promise.reject(error.message || error);
        }
    
        /**
         * Sends a JSON request to the odoo server
         * @param url Url of odoo
         * @param params Object
         */
        public sendRequest(url: string, params: Object): Promise<any>
        {
            let options = this.buildRequest(url, params);
            this.headers = new Headers({
                'Content-Type': 'application/json; charset=utf-8',
            });
    
            let result = this.http.post(this.odoo_server + url, options, { headers: this.headers })
                .toPromise()
            return result;
        }
    
        public init(configs: any)
        {
            this.odoo_server = configs.odoo_server;
            this.http_auth = configs.http_auth || null;
        }
    
        public setOdooServer(odoo_server: string)
        {
            this.odoo_server = odoo_server;
        }
    
    
        public setHttpAuth(http_auth: string)
        {
            this.http_auth = http_auth;
        }
    
        /**
         * Gets the server info
         */
        public getServerInfo()
        {
            return this.sendRequest("/web/webclient/version_info", {});
        }
    
    
        /**
         * Gets the session info
         */
        public getSessionInfo()
        {
            return this.sendRequest("/web/session/get_session_info", {});
        }
    
    
        /**
         * Gets the Odoo Server Version Number
         */
        public getServerVersionNumber(): Promise<number>
        {
            return this.getServerInfo().then((res: any): Promise<number> =>
            {
                return new Promise<number>((resolve) =>
                {
                    resolve(JSON.parse(res._body)["result"]["server_version_info"][0]);
                });
            });
        }
    
        /**
         * Get the database list
         */
        public getDbList(): Promise<string>
        {
            let dbParams =
            {
                context: {}
            }
            return this.getServerVersionNumber().then((data: number) =>
            {
                if (data <= 8)
                {
                    return this.sendRequest(this.get_list, dbParams);
                }
                else if (data == 9)
                {
                    return this.sendRequest(this.jsonrpc, dbParams);
                }
                else
                {
                    return this.sendRequest(this.list, dbParams);
                }
            })
        }
    
        /**
         * Returns all modules that are installed in your database
         */
        public modules(): Promise<string>
        {
            let params =
            {
                context: {}
            }
            return this.sendRequest("/web/session/modules", params)
        }
    
    
        /**
         * Login to the database
         * @param db Database name of odoo
         * @param login Username
         * @param password password
         */
        public login(db: string, login: string, password: string)
        {
            let params =
            {
                db: db,
                login: login,
                password: password,
                base_location: this.odoo_server,
                context: {}
            };
            return this.sendRequest("/web/session/authenticate", params)
        }
    
        /**
         * Check whether the session is live or not
         */
        public check(): Promise<string>
        {
            let params =
            {
                context: this.getContext()
            }
            return this.sendRequest("/web/session/check", params)
        }
    
    
        /**
         * Destroy the session
         */
        public destroy()
        {
            let params =
            {
                context: {}
            }
            return this.sendRequest("/web/session/destroy", params)
        }
    
    
        /**
         * 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);
        }
    
    
        /**
         * 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);
        }
    
    
        /**
         * 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)
        }
    
    
        /**
         * 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)
        }
    
    
        /**
         * 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)
        }
    
        /**
         * Get the User Context from the response of odoo server
         */
        private getContext()
        {
            let response = localStorage.getItem("token");
            let jsonData = JSON.parse(response);
            let context = jsonData["user_context"];
            return context;
        }
    }
    View Code

    通用类Utils.ts

    import { Injectable } from "@angular/core";
    import
    {
        AlertController, Loading,
        LoadingController, Toast, ToastController,
        ActionSheetController
    } from "ionic-angular";
    
    @Injectable()
    export class Utils
    {
        private loading: Loading
    
        constructor(private alrtCtrl: AlertController,
            private loadingCtrl: LoadingController,
            private toastCtrl: ToastController,
            private actionSheetCtrl: ActionSheetController)
        {
    
        }
    
        public presentAlert(title: string,
            message: string,
            buttons: [{}],
            subtitle?: string,
            enableBackdropDismiss?: boolean,
            inputs?: [{}]): void
        {
    
            let alrt = this.alrtCtrl.create
            ({
                title: title,
                subTitle: subtitle,
                message: message,
                buttons: buttons,
                enableBackdropDismiss: enableBackdropDismiss,
                inputs: inputs
            })
    
            alrt.present()
        }
    
        public presentToast(message: string, duration?: number,
            dissmissOnPageChange?: boolean,
            position?: string,
            showCloseButton?: boolean,
            closeButtonText?: string): void
        {
            let toast = this.toastCtrl.create
            ({
                message: message,
                position: position,
                dismissOnPageChange: dissmissOnPageChange,
                duration: duration,
                showCloseButton: showCloseButton,
                closeButtonText: closeButtonText
            })
            toast.present()
        }
    
        public presentLoading(content: string, duration?: number,
            dissmissOnPageChange?: boolean,
            enableBackDropDismiss?: boolean,
            showBackDrop?: boolean,
            spinner?: string): void
        {
            this.loading = this.loadingCtrl.create
            ({
                content: content,
                dismissOnPageChange: dissmissOnPageChange,
                duration: duration,
                enableBackdropDismiss: enableBackDropDismiss,
                showBackdrop: showBackDrop,
                spinner: spinner
            })
            this.loading.present()
        }
    
        public dismissLoading(): void
        {
            this.loading.dismiss()
        }
    
        public presentActionSheet(buttons: [{}], title: string, subtitle?: string,
            enableBackdropDismiss?: boolean): void
        {
            let actionCtrl = this.actionSheetCtrl.create
            ({
                buttons: buttons,
                subTitle: subtitle,
                title: title,
                enableBackdropDismiss: enableBackdropDismiss
            })
            actionCtrl.present()
        }
    }
    View Code
  • 相关阅读:
    计算字符个数
    字符串最后一个单词的长度
    C++面试宝典
    给定三角形ABC和一点P(x,y,z),判断点P是否在ABC内,给出思路并手写代码
    N-皇后问题(N Queens)
    图着色算法详解(Graph Coloring)
    c++学习路线连接
    数据结构--经典排序算法
    5. 最长回文子串
    4. 寻找两个有序数组的中位数
  • 原文地址:https://www.cnblogs.com/crazyguo/p/8558054.html
Copyright © 2020-2023  润新知