zoukankan      html  css  js  c++  java
  • odoo订餐系统之订单设计

    订餐系统的主要功能便是用户下单部分,这里我们分为表头mylunch_order和表体mylunch_order_line两张主要的数据表,表头主要记录订单的一些通用信息,比如下单的操作人员 下单日期 订单状态 以及订单的总价;表体主要记录订餐人,订餐的供应商,餐名,单价等具体的信息。

    class MyLunchOrder(osv.Model):
    
        _name = "mylunch.order"
        _description = "MyLunch Order"
    
        def name_get(self, cr, uid, ids, context=None):
            if not ids:
                return []
            res = []
            for elmt in self.browse(cr, uid, ids, context=context):
                name = _("MyLunch Order")
                name = name + ' ' + str(elmt.id)
                res.append((elmt.id, name))
    
            return res
    
        def _alerts_get(self, cr, uid, ids, name, arg, context=None):
            result = {}
            alert_msg = self._default_alerts_get(cr, uid, context=context)
            for order in self.browse(cr, uid, ids, context=context):
                if order.state == 'new':
                    result[order.id] = alert_msg
            return result
    
        def _default_alerts_get(self, cr, uid, context=None):
            alert_ref = self.pool.get('mylunch.alert')
            alert_ids = alert_ref.search(cr, uid, [], context=context)
            alert_msg = []
    
            for alert in alert_ref.browse(cr, uid, alert_ids, context=context):
                alert_msg.append(alert.message)
    
            return '
    '.join(alert_msg)
    
        def _fetch_orders_from_lines(self, cr, uid, ids, name, context=None):
            result = set()
            for order_line in self.browse(cr, uid, ids, context=context):
                if order_line.order_id:
                    result.add(order_line.order_id.id)
            return list(result)
    
        def _price_get(self, cr, uid, ids, name, arg, context=None):
            result = dict.fromkeys(ids, 0)
            for order in self.browse(cr, uid, ids, context=context):
                result[order.id] = sum(order_line.product_id.price
                                       for order_line in order.order_line_ids)
            return result
    
        _columns = {
            'user_id': fields.many2one('res.users', 'Use Name', required=True, readonly=True, states={'new':[('readonly',False)]}),
            'date': fields.date('Date', required=True, readonly=True, states={'new':[('readonly',False)]}),
            'state': fields.selection([('new', 'New'),
                                       ('confirmed', 'Confirmed'),
                                       ('cancelled', 'Cancelled'),
                                       ('partially', 'Partially Confirmed')],
                                      'Status', readonly=True, select=True, copy=False),
            'alerts': fields.function(_alerts_get, string='Alerts', type='text'),
            'order_line_ids': fields.one2many('mylunch.order.line', 'order_id', 'Products',
                                              ondelete='cascade', readonly=True, states={'new': [('readonly', False)]}, copy=True),
            'total': fields.function(_price_get, string='Total', store={
                'mylunch.order.line': (_fetch_orders_from_lines, ['product_id', 'order_id'], 20)
            }),
        }
    
        _defaults = {
            'user_id': lambda self, cr, uid, context: uid,
            'date': fields.date.context_today,
            'state': 'new',
            'alerts': _default_alerts_get,
        }

    mylunch.order类这里主要有2个字段对应的功能相对复杂,alerts和total字段,alerts字段使用了function方法来获取我们之前设置的警告信息,

    _alerts_get方法为每一个订单设置对应的警告信息,而这个警告信息是通过_default_alert_get方法获取数据库中所有的alert数据,并把这些数据合并成一条以“ ”分隔的字符串。

    total字段用来计算所有表体价格的总和,也是一个函数计算得来,只不过这个数据会存储在数据库中。_price_get函数在数据存储的时候会调用,根据当前订单的id获取所有的表体明细,将所有明细的单价相加,得到订单总和。当UI界面订餐菜单和订单变化的时候,这里要及时修改这里的总价,就需要调用_fetch_orders_from_lines方法,注意这里的参数由于是mylunch.order.line,所以_fetch_orders_from_lines方法的参数self就是mylunch.order.line这个类,这样这个方法的功能是根据表体的id查询出其所属的订单表头id,确定目标对象。大概相当于

    update mylunch_order set total = @totalPrice where id = @TargetId,这里确定了TargetId,那么@totalPrice价格是怎么计算出来的呢?貌似我们的类中没有体现出来这个计算过程,估计应该是框架帮我们完成了具体的计算工作,猜测的话应该会获取变化之后所有的product_id,然后计算出总和。具体过程不是很清楚,这里要深入研究框架的源代码了。

    class MyLunchOrderLine(osv.Model):
        _name = 'mylunch.order.line'
        _description = 'My Lunch Order Line'
    
        def _get_line_order_ids(self, cr, uid, ids, context=None):
            result = set()
            for lunch_order in self.browse(cr, uid, ids, context):
                for line in lunch_order.order_line_ids:
                    result.add(line.id)
            return list(result)
    
        _columns = {
            'name': fields.related('product_id', 'name', readonly=True),
            'order_id': fields.many2one('mylunch.order', 'Order', ondelete='cascade'),
            'product_id': fields.many2one('mylunch.production', 'Product', required=True),
            'date': fields.related('order_id', 'date', type='date', string='Date', readonly=True,
                                   store={
                                       'mylunch.order': (_get_line_order_ids, ['date'], 10),
                                       'mylunch.order.line': (lambda self, cr, uid, ids, context: ids, [], 10)
                                   }),
            'supplier_id': fields.related('product_id', 'supplier_id', type='many2one', relation='res.partner',
                                          string='Supplier', readonly=True, store=True),
            'user_id': fields.related('order_id', 'user_id', type='many2one', relation='res.users',
                                      string='User', readonly=True, store=True),
            'note': fields.text('Note'),
            'price': fields.float('Price'),
            'state': fields.selection([('new', 'New'),
                                       ('confirmed', 'Confirmed'),
                                       ('ordered', 'Ordered'),
                                       ('cancelled', 'Cancelled')], 'Status', readonly=True, select=True),
            'cashmove': fields.one2many('mylunch.cashmove', 'order_line_id', 'Cash Move', ondelete='cascade')
        }

    表体明细的话主要在date日期上,其值主要引用表头的日期date字段,有两种情况会造成该字段的变化更新,1.如果表头的日期date字段变化了,

    就调用_get_line_order_ids方法,根据表头的id获取其下表体的所有id,确定更新目标条件,然后框架帮我们完成date日期的条件设置,达到字段的更新目的。2.如果表体的任何一条数据的任何字段在UI变化了,也会修改date字段,只不过这里使用了lambda匿名表达式。

    class MyLunchCashmove(osv.Model):
        _name = 'mylunch.cashmove'
        _description = 'My Lunch CashMove'
        _columns = {
            'user_id': fields.many2one('res.users', 'User Name', required=True),
            'date': fields.date('Date', required=True),
            'amount': fields.float('Amount', required=True),
            'description': fields.text('Description'),
            'order_line_id': fields.many2one('mylunch.order.line', 'Order', ondelete='cascade'),
            'state': fields.selection([('order', 'Order'), ('payment', 'Payment')], 'Is an order or a payment'),
        }
    
        _defaults = {
            'user_id': lambda self, cr, uid, context: uid,
            'date': fields.date.context_today,
            'state': 'payment'
        }

    菜单事件代码:

    <act_window id="action_mylunch_order_form" name="MyOrder" res_model="mylunch.order" view_mode="tree,form"/>
    <menuitem name="New Order" parent="menu_mylunch_title" id="menu_lunch_order_form" action="action_mylunch_order_form" sequence="1"/>

    列表视图布局:

            <record model="ir.ui.view" id="orders_tree_view">
                <field name="name">Orders Tree View</field>
                <field name="model">mylunch.order</field>
                <field name="arch" type="xml">
                    <tree string="Orders Tree">
                        <field name="date"></field>
                        <field name="user_id"></field>
                        <field name="order_line_ids"></field>
                        <field name="state"></field>
                        <field name="total" sum="Total"></field>
                    </tree>
                </field>
            </record>

    其中total字段的sum属性,会在列表的抵补显示总和是多少,大概效果如下图:

    Form表单视图:

            <record model="ir.ui.view" id="orders_form_view">
                <field name="name">myLunch Order Form</field>
                <field name="model">mylunch.order</field>
                <field name="arch" type="xml">
                    <form string="MyOrders Form" class="oe_mylunch">
                        <header>
                            <field name="state" widget="statusbar" statusbar_visible="new,confirmed"/>
                        </header>
                        <sheet>
                            <group>
                                <group>
                                    <field name="user_id" context="{'default_groups_ref': ['base.group_user','base.group_partner_manager','mylunch.group_my_lunch_user']}"/>
                                </group>
                                <group>
                                    <field name="date"/>
                                </group>
                            </group>
                            <field name="alerts" attrs="{'invisible':['|',('state','!=','new'),('alerts','=',False)]}" class="oe_inline oe_mylunch_alert">
    
                            </field>
                            <div name="preferences">
    
                            </div>
                            <separator string="Select your order"></separator>
                            <field name="order_line_ids" nolabel="1">
                                <tree string="List" editable="bottom">
                                    <field name="product_id"></field>
                                    <field name="note"></field>
                                    <field name="price"></field>
                                    <field name="supplier_id" invisible="1"></field>
                                    <field name="state" invisible="1"></field>
                                </tree>
                            </field>
                            <group class="oe_subtotal_footer oe_right">
                                <field name="total"></field>
                            </group>
                            <br/><br/>
                        </sheet>
                    </form>
                </field>
            </record>

    这里嵌套了表体明细列表,这个视图很有代表性,充分体现了表头与表体明细的布局设计方式,我们还可以在此基础上进行相关的界面扩展,效果图如下:

    权限设计:

    id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
    mylunch_order_manager,'MyLunch Order Manager group',model_mylunch_order,group_my_lunch_manager,1,1,1,1
    mylunch_order_user,'MyLunch Order user group',model_mylunch_order,group_my_lunch_user,1,1,1,1
    mylunch_order_line_manager,'MyLunch Order Line Manager',model_mylunch_order_line,group_my_lunch_manager,1,1,1,1
    mylunch_order_line_user,'MyLunch Order Line user group',model_mylunch_order_line,group_my_lunch_user,1,1,1,1
    mylunch_cashmove_manager,'MyLunch Cashmove Manager group',model_mylunch_cashmove,group_my_lunch_manager,1,1,1,1
    mylunch_cashmove_user,'MyLunch Cashmove user group',model_mylunch_cashmove,group_my_lunch_user,1,0,0,0
  • 相关阅读:
    linux日常。
    tp5中的config类和config助手函数
    TP5隐藏index.php
    TP5读取数据概述
    TP5的安装部署概要
    eclipse4.7中文包安装方法。
    利用mysqldump备份magento数据库
    MySQL 基础知识
    PHP 基础知识
    妖怪与和尚过河问题
  • 原文地址:https://www.cnblogs.com/crazyguo/p/7088727.html
Copyright © 2011-2022 走看看