odoo定义view表自定义sql来创建表及反写操作

今天遇到了非常规表的创建及使用,来分享一下

使用场景:展示表用到了其他两个表的字段,并且想要对这俩表的字段进行一个操作

以下为展示表的代码

# -*- coding: utf-8 -*-
from odoo import api, models, fields, tools


class ReceiptFollowUp(models.Model):
    _name = 'receipt.follow.up'
    _description = '收款跟进'
    _auto = False

    salesman = fields.Char('业务员')
    department = fields.Char('部门')
    contract_no = fields.Char('合同编号')
    contract_name = fields.Char('合同名称')
    subordinate_company = fields.Char('所属公司')
    partner_name = fields.Char('客户名称')
    contract_amount = fields.Float('合同金额')
    receipt_stage = fields.Char(string='收款阶段')
    plan_receipt_date = fields.Date(string='计划收款日期')
    stage_payback_amount = fields.Float(string='阶段回款金额')
    received_amount = fields.Float('已收款金额')
    unreceived_amount = fields.Float(string='未收款金额')
    forecast_receipt_date = fields.Date('预测收款日期')
    forecast_receipt_amount = fields.Float('预测收款金额')
    submit_state = fields.Selection([('unsubmitted', '未提交'), ('submitted', '已提交')], string='提交状态')
    receive_plan_id = fields.Integer('收款计划id')



    def action_model_view(self):
        return {
            'type': 'ir.actions.act_window',
            'view_type': 'form',
            'view_mode': 'form',
            'res_model': 'sales.contract',
            'res_id': self.env['sales.contract'].search([('c_cust_contract_no', '=', self.contract_no)])[0].id,
        }
    @api.model
    def btn_confirm_submission(self,select_ids):
        for record in select_ids:
            self_id = self.env['receipt.follow.up'].search([('id', '=', record)],limit=1)
            plan_id = self.env['sales.contract.receive.plan'].search([('id', '=', self_id.receive_plan_id)],limit=1)
            if plan_id:
                plan_id.write({'submit_state': 'submitted'})

    def init(self):
        tools.drop_view_if_exists(self._cr, self._table)
        self._cr.execute(f"""
        CREATE OR REPLACE VIEW {self._table} AS (
            SELECT 
                T2.id,
                t1.emp_id		            as salesman,
                t1.emp_dept_id		        as department,
                t1.c_cust_contract_no		as contract_no,
                t1.proj_name		        as contract_name,
                t1.emp_org_id		        as subordinate_company,
                t1.c_cust_id		        as partner_name,
                t1.pb_amount		        as contract_amount,
                t2.receive_stage_id		    as receipt_stage,
                t2.plan_receive_date		as plan_receipt_date,
                t2.stage_receive_amount		as stage_payback_amount,
                t2.receive_amount		    as received_amount,
                t2.no_receive_amount		as unreceived_amount,
                t2.plan_receive_date		as forecast_receipt_date,
                t2.no_receive_amount		as forecast_receipt_amount,
                t2.submit_state,
                t2.id                       as receive_plan_id
        FROM sales_contract T1 
        INNER JOIN sales_contract_receive_plan T2 on t1."id" = t2.sales_contract_id
        ORDER BY T1.id,T2.id)""")

先定义模型,注意需要设定_auto = False,这样odoo就不会自动创建表及其字段,然后字段就正常定义就好,不需要写逻辑,因为后边会用sql语句对其赋值

btn_confirm_submission为按钮调用的反写方法,直接对主表write对应内容就好了

第二步定义xml

<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
    <data>
        <record id="receipt_follow_up_tree" model="ir.ui.view">
            <field name="name">receipt.follow.up.tree</field>
            <field name="model">receipt.follow.up</field>
            <field name="arch" type="xml">
                <tree create="0" limit="500" delete="false">
                    <field name="salesman" optional="show"/>
                    <field name="department" optional="show"/>
                    <field name="contract_no" optional="show"/>
                    <field name="contract_name" optional="show"/>
                    <field name="subordinate_company" optional="show"/>
                    <field name="partner_name" optional="show"/>
                    <field name="contract_amount" optional="show"/>
                    <field name="receipt_stage" optional="show"/>
                    <field name="plan_receipt_date" optional="show"/>
                    <field name="stage_payback_amount" optional="show"/>
                    <field name="received_amount" optional="show"/>
                    <field name="unreceived_amount" optional="show"/>
                    <field name="forecast_receipt_date" optional="show"/>
                    <field name="forecast_receipt_amount" optional="show"/>
                    <field name="submit_state" optional="show"/>
                </tree>
            </field>
        </record>
        <record id="receipt_follow_up_search" model="ir.ui.view">
            <field name="model">receipt.follow.up</field>
            <field name="arch" type="xml">
                <search string="收款跟进">
                    <field name="salesman"/>
                    <field name="department"/>
                    <field name="contract_no"/>
                    <field name="contract_name"/>
                </search>
            </field>
        </record>

        <!--窗口动作-->
        <record id="receipt_follow_up_action" model="ir.actions.act_window">
            <field name="name">收款跟进</field>
            <field name="res_model">receipt.follow.up</field>
            <field name="view_mode">tree</field>
            <field name="help" type="html">
                <p class="oe_view_nocontent_create">创建您的收款跟进</p>
            </field>
        </record>


        <menuitem id="receipt_follow_up_menu" name="收款跟进" parent="payback_forecast_menu" sequence="1"
                  action="receipt_follow_up_action"/>

    </data>
</odoo>

定义tree,search视图,action及menuitem,与正常表无差别

还有一种情况就是反写的内容不是固定的可怎么办呢:

 可以在tree视图最后增加button来调用后端方法

效果如下

    def btn_operation_update(self):
        """
        收款变更按钮
        :return:
        """
        return {
            'name': '收款变更',
            'type': 'ir.actions.act_window',
            'res_model': 'receipt.change.transient',
            'view_mode': 'form',
            'target': 'new',
            'context': {'forecast_receipt_date': self.forecast_receipt_date, 'forecast_receipt_amount': self.forecast_receipt_amount,
                        'receive_plan_id': self.receive_plan_id}
        }

后端方法来返回一个transient模型的form视图,transient模型是用来计算值的中间表,context中可以传入现在状态的一些数据,注意他不储存数据,只能用这些数据来计算并返回,下面是我定义的transient模型

from odoo import models, fields
from odoo.exceptions import ValidationError


class ReceiptChangeTransient(models.TransientModel):
    _name = 'receipt.change.transient'
    _description = '收款变更 transient'

    forecast_receipt_date = fields.Date('预测收款日期')
    forecast_receipt_amount = fields.Float('预测收款金额')

    def confirm_change(self):
        receive_plan_id = self._context.get('receive_plan_id')
        plan_id = self.env['sales.contract.receive.plan'].search([('id', '=', receive_plan_id)], limit=1)
        if plan_id:
            plan_id.write({'plan_receive_date': self.forecast_receipt_date,
                                   'no_receive_amount': self.forecast_receipt_amount})
        else:
            raise ValidationError('没有找到对应的收款计划!')

我只需要计算两个字段,所以只定义了这两个字段,confirm_change是确认按钮的方法,来实现回写,下面是transient模型的form视图

<?xml version='1.0' encoding='utf-8'?>
<odoo>
  <data noupdate="0">
    <record id="receipt_change_transient_form_view" model="ir.ui.view">
        <field name="name">收款变更wizard</field>
        <field name="model">receipt.change.transient</field>
        <field name="arch" type="xml">
            <form style="text-align: center">
                <sheet>
                    <group>
                        <group>
                            <field name='forecast_receipt_date' string='预测收款日期'/>
                        </group>
                        <group>
                            <field name='forecast_receipt_amount' string='预测收款金额'/>
                        </group>
                    </group>

                    <footer>
                        <button string="确认变更" name="confirm_change" type="object" class="btn btn-primary"/>
                        <button string="取消" class="btn btn-default" special="cancel"/>
                    </footer>
                </sheet>
            </form>
        </field>
    </record>
  </data>
</odoo>

确认变更按钮来调用后端的confirm_change来实现回写逻辑,效果如下:

点击确认变更按钮效果如下,可以发现这俩字段的值已经变了,说明主表的这俩字段已经回写成功(这里其实就是主表的字段,只是用来展示) 

 至此结束

views表解释:

在Odoo中,模型(Model)在数据库中通常被映射为表(Table),而不是视图(View)。模型对应的表用于存储与模型相关的数据,包括模型定义的字段和相关记录。

然而,有时候会有一些特殊情况,某些模型在数据库中会被映射为views表,而不是实际的数据表。这通常发生在具有动态或计算字段的模型上。

当一个模型定义了动态或计算字段时,这些字段的值是根据其他字段的计算结果动态生成的,而不是直接存储在数据库中。因此,对于这些模型,不需要在数据库中创建对应的数据表来存储字段的值。

相反,这些模型的数据是通过视图(View)来呈现和计算的。这些视图定义了模型字段的计算逻辑和展示方式,以及如何将数据显示给用户。这些视图在运行时根据模型的定义动态生成,并在访问模型数据时执行相应的计算。

所以,当一个模型在数据库中被映射为views表时,它表示该模型的数据是通过视图计算和呈现的,而不是存储在实际的数据表中。这种做法使得可以在不存储实际字段值的情况下,动态地计算和展示数据,并在需要时提供准确的计算结果。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Odoo中新建自定义视图,需要进行以下操作: 1. 在odoo的python代码中增加新视图类型与视图模式。这可以通过在ir_actions_act_window.py和ir_ui_view.py文件中添加相关代码来实现。例如,在ir_actions_act_window.py文件中,我们可以增加以下代码来定义新的视图模式: ``` # -*- coding: utf-8 -*- from odoo import fields, models class ActWindowView(models.Model): _inherit = 'ir.actions.act_window.view' view_mode = fields.Selection(selection_add=[('eview', 'echart views')]) ``` 在ir_ui_view.py文件中,我们可以添加以下代码来定义新的视图类型: ``` # -*- coding: utf-8 -*- from odoo import fields, models class View(models.Model): _inherit = 'ir.ui.view' type = fields.Selection(selection_add=[('eview', 'echart views')]) ``` 这样,Odoo就可以识别我们新定义的视图类型。 2. 定义js相关文件和模板代码。通过编写相应的javascript文件和模板代码,我们可以实现对自定义视图的布局和行为的控制。这些文件需要与新定义的视图类型相关联,并与视图模板文件进行交互。具体的实现方法可以根据项目需求和技术要求来确定。 这样,在执行以上操作之后,就可以在Odoo中创建自定义视图了。自定义视图可以根据具体需求来设计和实现,包括自定义的布局、交互和样式等方面 。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Odoo自定义视图教程](https://blog.csdn.net/u012739578/article/details/121670077)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值