1.在xml中的domain表达式解析:|,&,!以及表示此意义的符号,都是遵从栈的规则(后进先出),右为栈底,所以从最左端的符号开始判断。
2.xml中也可以进行时间计算,比如在一周内的为即将开始等等等。
可参照https://www.cnblogs.com/hellojesson/p/8144474.html
<filter string="执行阶段" name="execute_stage" domain="[('state','in',['preparing','doing','done'])]"/> <filter string="即将开始" domain="['&', ('state','=','preparing'), ('plan_date', '<=', (context_today()+datetime.timedelta(days=7)).strftime('%Y-%m-%d'))]"/> <filter string="开始延期" domain="['&', ('state','=','preparing'), ('plan_date', '<=', (context_today()+datetime.timedelta(days=0)).strftime('%Y-%m-%d'))]"/> <filter string="即将完成" domain="['&', ('state','=','doing'), ('plan_done_date', '<=', (context_today()+datetime.timedelta(days=7)).strftime('%Y-%m-%d'))]"/> <filter string="执行延期" domain="['&', ('state','=','doing'), ('plan_done_date', '<=', (context_today()+datetime.timedelta(days=0)).strftime('%Y-%m-%d'))]"/> <filter string="我的任务" domain="['&',('operator_id','=',uid),'|',('state','=','inquiring'),('state','=','doing')]"/>
</filter>
<filter string="今日订单" name="today" invisible="0" domain="[('date','=', current_date)]"/> <filter string="本月订单" name="month" invisible="0" domain="[('date','>=', time.strftime('%Y-%m-01')),('date','<', (context_today() + relativedelta(months=1)).strftime('%Y-%m-01') ) ]"/> <filter string="上月订单" name="month2" invisible="0" domain="[('date','<', time.strftime('%Y-%m-01')),('date','>=', (context_today() - relativedelta(months=1)).strftime('%Y-%m-01') ) ]"/> <filter string="本年订单" name="year" invisible="0" domain="[('date','<=', time.strftime('%Y-12-31')),('date','>=', time.strftime('%Y-01-01'))]"/>
Odoo过滤器中可以使用的时间变量
<filter name="not_filled_in_last_week" string="Not Filled in Last Week" domain="[('state','=','draft'),('date_to', '>=', ((context_today()+relativedelta(weeks=-2, days=1, weekday=0)).strftime('%Y-%m-%d'))),('date_to', '<=', ((context_today()+relativedelta(weeks=-1, weekday=6)).strftime('%Y-%m-%d')))]"/> <filter name="not_filled_in_last_month" string="Not Filled in Last Month" domain="[('state','=','draft'),('date_to', '<', time.strftime('%Y-%m-01')),('date_to','>=', (context_today() - relativedelta(months=1)).strftime('%Y-%m-01'))]"/> <filter name="not_filled_in_this_month" string="Not Filled in This Month" domain="[('state','=','draft'),('date_to', 'like', time.strftime('%Y-%m'))]"/> datetime: datetime, context_today: context_today, time: time, relativedelta: relativedelta, current_date
3.在定义字段时,related为强关联,若只为引用(可以用m2m,o2m,m2o关系)时,为了不造成反写(修改)被引用的原有字段(且若无权限修改,则会报错提醒),一定要加上readonly=True加以限制;store=True视情况而定,若报错信息为以下,则多半是不能加store=True。
ProgrammingError: relation "none" does not exist
_______________or_________________
Exception during JSON request handling.
4.流水号
<!--xml文件:此为4位年号,2位月和日号,三位随机数字类型,2位年为%(Y)s,name="code"是model找到这个规则的标志,noupdate="0"代表每次加载都更新,一般加上,如果刚开始是1,之后改为0,得手动到浏览器删除这个序列号,否则不生效--> <data noupdate="0"> <record id="sequence_xx_product_certification_test_order" model="ir.sequence"> <field name="name">xx Product Certification Test Order Sequence</field> <field name="code">xx.product.certification.test.order.code</field> <field name="prefix">CRT%(year)s%(month)s%(day)s</field> <field name="padding">3</field> </record> </data>
# Python文件:
@api.model def create(self, vals): vals['name'] = self.env['ir.sequence'].next_by_code('xx.product.certification.apply.order.code') or '' res = super(xxProductCertificationApply, self).create(vals) return res
5.弹出向导
# Python文件: def create_test(self): """"创建可靠性测试需求,若已创建认证需求,则为完成申请状态""" if self.state == 'create_certification': current_state = 'done' else: current_state = 'create_test' ctx = { #此为一些默认值,需要加载到前端默认显示,相应的要在xml中进行接收,同时这个ctx字典内容会直接放到wizard的self.env.context里面,可以对内容加以保存(可保存到任意表),default_为固定格式 'default_ca_name': self.name, 'default_create_uid': self.env.user.id, 'default_department_id': self.env.user.department_id.id, 'default_cert_apply_id': self.id, 'default_project_id': self.project_id.id, # 'default_ct_type': 'test', 'default_product_center_product_id': self.product_center_product_id.id, 'default_product_model': self.product_model, 'default_categ_id': self.categ_id.id, 'default_submit_date': self.commit_date_time, 'default_product_detail_text': self.product_detail_text, 'default_sales_regions': [(6, 0, self.sales_regions.ids)], 'default_wireless_protocol': [(6, 0, self.wireless_protocol.ids)], 'default_project_user': self.project_user.id, 'default_product_manager_ids': [(6, 0, self.product_manager_ids.ids)], 'current_state': current_state } view = self.env.ref('xx_product_center.xx_pct_order_view') #找到要渲染的view视图 res = { 'res_model': 'xx.pct.oder.wizard', #指明要加载的model模型,有什么字段就可以选择加载什么字段,可以做成form视图和tree视图 'view_type': 'form', 'view_mode': 'form', 'view_id': view.id, #获取视图id 'name': _('Create Test'), #_(")要翻译的内容 'type': 'ir.actions.act_window', #类型 'target': 'new', # 新打开一个页面 'context': ctx, 'views': [(view.id, 'form')] } return res # return给前端
<?xml version="1.0" encoding="utf-8"?> <odoo> <data> <!--认证&测试--> <record id="xx_pct_order_view" model="ir.ui.view"> <field name="name">xx.pct.order.wizard.form</field> <field name="model">xx.pct.oder.wizard</field> <field name="arch" type="xml"> <form> <group> <group> <field name="ca_name" invisible="1"/> <field name="create_uid" invisible="1"/> <field name="department_id" invisible="1"/> <field name="cert_apply_id" invisible="1"/> <field name="project_id" invisible="1"/> <!--<field name="ct_type" invisible="1"/>--> <field name="product_center_product_id" invisible="1"/> <field name="product_center_product_id"/> <field name="product_model"/> <field name="categ_id"/> <field name="submit_date"/> <field name="product_detail_text"/> </group> <group> <field name="sales_regions"/> <field name="wireless_protocol"/> <field name="project_user"/> <field name="product_manager_ids"/> </group> </group> <notebook> <page string="Certification or Reliability Testing"> <field name="certification_test_order_lines"> <tree editable="0"> <field name="cert_test_conf_id" required="1"/> <field name="ct_type" required="1"/> <field name="required_text" required="0"/> </tree> </field> </page> </notebook> <footer> <button string="Cancel" class="btn-default" special="cancel"/> <button string="Save" type="object" name="execute" class="oe_highlight"/> </footer> </form> </field> </record> </data> </odoo>
6.服务器动作(不明白为什么这样叫,就是选择几个记录时,动作中可以有一个按钮,按完可以弹向导),效果如下:
思路:tree视图中多选完,弹出选择时间的wizard,所以必须自己新建一个TransientModel,里面有plan_start_date字段,当选择完时间以后点击提交按钮,触发这个model中的函数,需要处理选择的多行记录,所以我们又在此model中创建一个字段,多对多关联到原tree视图主model,然后在原主model 的context中传入 {'default_certification_test_order_ids': [(6, 0, ids)]},并建立多对多关系(ids为包含多行被选记录的id列表),接收到前端但不显示(<field name="certification_test_order_ids" invisible="1"/>
),这样点击提交按钮,回到在这个TransientModel函数中,就可以直接self点出来了,然后for循环,一一处理。等处理完,收集完问题数据,然后再return一个wizard,所以又需要再创建一个TransientModel,有error_thing,error_info两个字段,只让确定不让取消,确定的函数只需要pass即可,取消会可能把所有的wizard都取消,产生冲突。
<!--主model的tree视图,可以触发多选后的动作按钮--> <record model="ir.actions.server" id="action_start_preparing"> <field name="name">Start Preparing</field> <field name="model_id" ref="model_xx_product_certification_test_order"/> <field name="code"> if records: 直接调用Python方法 action = records.action_start_preparing() </field> </record> <record model="ir.values" id="action_start_preparing_new"> 上下id不一致 <field name="model_id" ref="model_xx_product_certification_test_order" /> <field name="name">Start Preparing</field> <field name="key2">client_action_multi</field> <field name="value" eval="'ir.actions.server,' +str(ref('action_start_preparing'))" />关联上id <field name="key">action</field> <field name="model">xx.product.certification.test.order</field>适用model,tree主model <field name="groups" eval="[(4, ref('group_xx_product_center_certified_engineer')),(4, ref('group_xx_product_center_reliability_engineer'))]"/> 权限 </record>
@api.multi def action_start_preparing(self): ids = self.env.context.get('active_ids', []) #找到所有选择的记录id view = self.env.ref('xx_product_center.xx_pcto_plan_time_view') # 找到要渲染出的视图 res = { 'res_model': 'xx.pcto.quote.plan.time', # 用哪个model去渲染 'view_type': 'form', 'view_mode': 'form', 'view_id': view.id, # 关联视图 'name': _('Plan Start Time'), 'type': 'ir.actions.act_window', 'target': 'new', 'context': {'default_certification_test_order_ids': [(6, 0, ids)]}, # 创建多对多关系 'views': [(view.id, 'form')] } return res
# 两个wizard,一上一下 class xxPCTOQuotePlanTime(models.TransientModel): _name = 'xx.pcto.quote.plan.time' _description = "Product Certification Test Oder Wizard" plan_start_date = fields.Datetime(string='Plan Start Date Time', track_visibility='onchange') certification_test_order_ids = fields.Many2many(string='Certification Test Order', relation='xx_pct_order_plan_time_table', comodel_name='xx.product.certification.test.order') @api.multi def execute(self): #处理过程不用看 error_list = [] val = { 'plan_start_date': self.plan_start_date, 'state': 'preparing' } for record in self.certification_test_order_ids: if record.state == 'approved': record.write(val) else: error_thing = str(record.product_center_product_id.name or record.other_product_text) + ' ' + str(record.cert_test_conf_id.name or '') error_list.append(error_thing) continue error_things = ' '.join(list(set(error_list))) view = self.env.ref('xx_product_center.xx_pcto_plan_time_error_view') err_msg = {'default_error_thing': error_things, 'default_error_info': _('Is not in the completed quote stage. Cannot start planning, please adjust the stage before planning!')} return { 'res_model': 'xx.pcto.quote.plan.time.error', 'view_type': 'form', 'view_mode': 'form', 'view_id': view.id, 'name': _('Plan Start Time Error'), 'type': 'ir.actions.act_window', 'target': 'new', 'context': err_msg, 'views': [(view.id, 'form')] } class xxPCTOQuotePlanTimeError(models.TransientModel): _name = 'xx.pcto.quote.plan.time.error' _description = "Product Certification Test Oder Wizard Error" error_thing = fields.Text(string='Error Thing', readonly=True) error_info = fields.Text(string='Error Info', readonly=True) @api.multi def execute(self): pass
选择时间的wizard: <field name="name">xx.pcto.quote.plan.time.form</field> <field name="model">xx.pcto.quote.plan.time</field> <field name="arch" type="xml"> <form> <group> <field name="certification_test_order_ids" invisible="1"/> <field name="plan_start_date"/> </group> <footer> <button string="Submit" type="object" name="execute" class="oe_highlight"/> </footer> </form> </field>
错误提醒的wizard: <field name="name">xx.pcto.quote.plan.time.error.form</field> <field name="model">xx.pcto.quote.plan.time.error</field> <field name="arch" type="xml"> <form> <group> <field name="error_thing" readonly="1"/> <field name="error_info" readonly="1"/> </group> <footer> <button string="Submit" type="object" name="execute" class="oe_highlight"/> </footer> </form> </field>