odoo与透视图结合

最近老板提出一个需求,对数据进行汇总,最好能展示出来,后来看到蚂蚁数据可视化中的s2比较合适就做了一下,效果如图:

简单说一下思路:通过JS将S2引入,然后使用RPC通过调用模型中的方法获取数据,按照S2文档出入数据,然后“ir.actions.client”展示Qweb模板,将表格展示出来。

  1. 创建一个菜单(创建一个按钮也可以)

<menuitem id="menu_example_data_s2"
      name="表格分析(S2)"
      action="action_example_s2"
      parent="menu_report_odoo"
      sequence="10"
 />
  1. 创建action:使用的action是“ir.actions.client”,用来打开模板

<record id="action_example_s2" model="ir.actions.client">
    <field name="name">表格分析(S2)</field>
    <field name="tag">example.data.s2</field>
    <field name="target">new</field>
</record>
  1. 要展示的模型:模型中返回数据格式在S2文档中会有要求,所以在JS调用方法时,将数据按照格式返回即可。

class ExampleData(models.Model):
    _name = 'example.data'
    _description = '示例数据'

    def _get_country(self):
        """
        默认为中国
        :return:
        """
        country_id = self.env['res.country'].search([('name', '=', '中国')], limit=1)
        if country_id:
            return country_id.id

    order_name = fields.Char(
        string='订单号'
    )
    country_id = fields.Many2one(
        comodel_name='res.country',
        string='国家',
        default=_get_country
    )
    state_id = fields.Many2one(
        comodel_name='res.country.state',
        string='省份',
        domain="[('country_id', '=', country_id)]"
    )
    city_id = fields.Many2one(
        comodel_name='res.city',
        string='市/县/区',
        # domain="[('state_id', '=', state_id)]"
    )
    product_id = fields.Many2one(
        comodel_name='example.product',
        string='选购产品',
    )
    product_amount = fields.Float(
        string='购买数量'
    )
    product_price = fields.Float(
        string='产品单价',
        related='product_id.price',
        store=True,
        readonly=False
    )
    purchase_date = fields.Date(
        string='采购时间'
    )
    product_total = fields.Float(
        string='购买总价',
        compute='_compute_get_total_price',
        store=True
    )

    @api.model
    def create(self, vals_list):
        name = vals_list.get('order_name')
        if not name:
            vals_list['order_name'] = self._pro_name()
        return super(ExampleData, self).create(vals_list)

    @api.depends('product_price', 'product_amount')
    def _compute_get_total_price(self):
        for rec in self:
            rec.product_total = rec.product_amount * rec.product_price

    def _pro_name(self):
        """
        生成序列号
        :return:
        """
        new_code = self.env['ir.sequence'].get('example.data')
        if new_code:
            return new_code
        else:
            self.env['ir.sequence'].sudo().create({
                'name': '订单记录',
                'code': 'example.data',
                'prefix': 'ED-%(year)s-%(month)s-%(day)s-',
                'padding': 3,
                'number_increment': 1,
                'number_next_actual': 1,
                'implementation': 'standard',
                'active': True,
                'company_id': False
            })
            new_code = self.env['ir.sequence'].get('example.data')
            if new_code:
                return new_code
    
    def get_data_list(self):
        """
        返回S2表格需要的数据
        :return:
        """
        data = []
        data_ids = self.search([])

        data_dict = {
            'fields': {
                'rows': ['country', 'province', 'order_code', 'product'],
                'columns': [],
                'values': ['product_amount', 'product_price']
            },

            'meta': [
                {
                    'field': 'country',
                    'name': '国家',
                },
                {
                    'field': 'province',
                    'name': '省份',
                },
                {
                    'field': 'product',
                    'name': '产品',
                },
                {
                    'field': 'product_price',
                    'name': '单价',
                },
                {
                    'field': 'product_amount',
                    'name': '数量',
                },
                {
                    'field': 'order_code',
                    'name': '订单号',
                },
            ],
            'data': []
        }
        for rec in data_ids:
            info = {
                'country': rec.country_id.name,
                'province': rec.state_id.name,
                'product': rec.product_id.name,
                'product_amount': rec.product_amount,
                'product_price': rec.product_price,
                'order_code': rec.order_name,
                # 'action': 'action_view_detail_form',
                # 'rec_id': rec.id
            }
            data.append(info)
        data_dict['data'] = data
        return data_dict
    def action_view_detail_form(self, order_name):
        """
        查看每条记录的form
        :return:
        """
        order_id = self.search([('order_name', '=', order_name)], limit=1)
        view_id = self.env.ref('odoo_report.example_date_form_wizard_view').id
        action = {
            'name': '查看订单',
            'type': 'ir.actions.act_window',
            'view_mode': 'form',
            'res_model': 'example.data',
            'views': [(view_id, 'form')],
            'view_id': view_id,
            'target': 'new',
            'res_id': order_id.id,
            'context': {
                'create': 0,
                'edit': 0,
            },
        }
        print(action)
        return action
  1. 编写JS,主要就是引入S2,对数据进行处理

odoo.define('example_data.s2', function (require) {
    "use strict";

    var AbstractAction = require('web.AbstractAction');
    var core = require('web.core');

    var ExampleDataS2 = AbstractAction.extend({
        # 引入Qweb模板
        template: 'ExampleDataS2',
        event: {},

        init: function (parent, action) {
            var self = this;
            this._super.apply(this, arguments);
            // 挡在单据跳转时可以获取到当前action的值
            this.params = action.params;
        },

        start: function () {
            var self = this;
            var params = this.params
            # 使用RPC获取模型中的数据
            this._rpc({
                model: 'example.data',
                method: 'get_data_list',
                args: [[]],
            }).then(function (data) {
                console.log('获取的数据', data)
                self._show_data_list(data);
            })
        },
        # 对数据进行处理
        _show_data_list: function (data) {
            var self = this;
            var container = document.getElementById('example_data_s2');
            const s2options = {
                width: 900,
                height: 450,
                interaction: {
                    // 仅支持rows里面的
                    linkFields: ['order_code'],
                },
                conditions: {
                    text: [
                        {
                            field: 'product_amount',
                            mapping(fieldValue, data) {
                                return {
                                    fill: "#ffc107",
                                };
                            }
                        },
                        {
                            field: 'product_price',
                            mapping(fieldValue, data) {
                                return {
                                    fill: "#28a745",
                                };
                            }
                        }
                    ],
                    // background: [
                    //     {
                    //         field: 'product_price',
                    //         mapping(fieldValue, data) {
                    //             if (fieldValue) {
                    //                 return {
                    //                     fill: "#28a745",
                    //                 };
                    //             }
                    //         }
                    //     }
                    // ]
                }
            };
            const s2 = new S2.PivotSheet(container, data, s2options);

            // 链接跳转
            console.log(S2.S2Event.GLOBAL_LINK_FIELD_JUMP)
            s2.on(S2.S2Event.GLOBAL_LINK_FIELD_JUMP, (a) => {
                console.log('data的值', a)
                const {key, record} = a
                const value = record['order_code']
                if (value) {
                    return this._rpc({
                        model: 'example.data',
                        method: 'action_view_detail_form',
                        args: [[], value],
                    }).then(function (result) {
                        self.do_action(result);
                    });
                } else {
                    return this.do_warn('警告', '禁止此操作')
                }
            });
            s2.render();
        }

    });

    core.action_registry.add('example.data.s2', ExampleDataS2);
})
  1. 展示模板,模板写的比较简单。

<template>
    <t t-name="ExampleDataS2">
        <div style="padding: 20px; background-color: #FFF">
            <t t-call="example_data"/>
        </div>
    </t>

    <t t-name="example_data">
        <div>
            <div id="example_data_s2" style="height: 100%; width: 100%"/>
        </div>
    </t>
</template>
  1. 引入Qweb以及S2

<template id="odoo_report.assets_end" inherit_id="web.assets_backend">
        <xpath expr="." position="inside">
            <script type="text/javascript" src="/odoo_report/static/js/s2/s2.js"/>

        </xpath>
    </template>

注意:odoo的版本为14,s2文档链接https://s2.antv.vision/manual/introduction

S2中其实还有许多功能都比较实用的,自己可以摸索一下,若有不当之处,还望指出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一年级的小菜鸡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值