跳转至内容
  • 版块
  • 标签
  • 热门
  • 用户
  • 群组
皮肤
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • 默认(Flatly)
  • 不使用皮肤
折叠

Odoo 中文社区

  1. 主页
  2. 版块
  3. Odoo 系统测试
  4. 今天开始OpenERP进销存源码分析活动

今天开始OpenERP进销存源码分析活动

已定时 已固定 已锁定 已移动 Odoo 系统测试
10 帖子 5 发布者 17.0k 浏览
  • 从旧到新
  • 从新到旧
  • 最多赞同
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • wjfonhandW 离线
    wjfonhandW 离线
    wjfonhand
    写于 最后由 编辑
    #1

    HornERP3.0的目标是针对OpenERP的核心进销存模块做增强和简化。那么前提就是对系统原有的功能和逻辑有深入了解,为了满足这个前提,HornERP项目组决定从今天(2010-9-1)开始,对OpenERP5.0.12版本的stock、purchase、sale、mrp等进销存涉及的基础模块做源码级的研究和分析。为保持开源项目的开放性,此活动以下面方式运作:

    1、每天此帖公布当天分析的对象和次日分析的计划
    2、分析和讨论在qq群中进行,聊天记录整理后记录到此帖
    3、根据分析结果完善中文帮助的wiki
    4、根据分析结果完善各模块对应的翻译
    5、根据分析结果总结出HornERP3.0对应的需求

    愿意参与的,有更好的运作建议的,已经有心得的,马上加入我们!!

    GoodERP -- Odoo China fork

    1 条回复 最后回复
    0
    • JoshuaJ 离线
      JoshuaJ 离线
      Joshua 管理员
      写于 最后由 编辑
      #2

      欢迎喜欢源码分析的筒子踊跃参与 😛

      【上海先安科技】(joshua AT openerp.cn),欢迎关注公众号:openerp_cn

      1 条回复 最后回复
      0
      • L 离线
        L 离线
        liu198619
        写于 最后由 编辑
        #3

        报个名先!

        1 条回复 最后回复
        0
        • wjfonhandW 离线
          wjfonhandW 离线
          wjfonhand
          写于 最后由 编辑
          #4

          研究ERP流程的惯例是先主数据后业务数据,那就从partner开始吧
          http://code.google.com/p/hornerp/source/browse/branches/codereview/server/5.0.12/bin/addons/base/res/partner/partner.py

          GoodERP -- Odoo China fork

          1 条回复 最后回复
          0
          • T 离线
            T 离线
            tomp
            写于 最后由 编辑
            #5

            上海-Jeff(85822082)  15:03:51
            partner是base模块里就带着的一个业务对象,基本上每个后续模块都会继承base里的这个partner对象,往上加字段,所以今天我们针对业务功能的源码分析就从这个开始

            打开这个
            [attachimg=1]
            只有base模块的database,partner就是这些字段对应网页上的源文件 130 行其他class都是为它服务的,逐个字段分析res_partner对象就能都涉及到class res_partner(osv.osv): 所有oe的业务对象类都是osv的子类_description='Partner' 这就是在对象列表里显示的名称,每个类都必须有 _name = "res.partner"
            上海-Jeff(85822082)  15:11:12
            _order = "name" ,这里要注意了,partnr列表是按名称排序的,不是我们习惯的按编号
            好像列表的排序只能在列里定义,view里无法确定顺序?

            广东-Joshua(470534800)  15:13:06
            view没试过

            上海-Jeff(85822082)  15:14:23
            _columns = {
            这个也是必需的

            'name': fields.char('Name', size=128, required=True, select=True),

            广东-Joshua(470534800)  15:20:22
            'name': fields.char('Name', size=128, required=True, select=True),
            select=False, 如为True,在数据库表的这个字段上创建一个索引

            上海-Jeff(85822082)  15:21:10
            我也想问一下这个select,真的是用来创建索引的?

            深圳-Seraphim(409166304)  3:17:10 PM
            mrp\mrp_view.xml  474行,加个groups试试

            广东-Joshua(470534800)  15:22:32
            'date': fields.date('Date', select=1),第二条 =1..
            上海-Jeff(85822082)  15:23:21
            是啊,怪就怪在他一会儿是True False,一会儿是1,2

            广东-Joshua(470534800)  15:23:55
            [attachimg=2]
            上海-Jeff(85822082)  15:25:26
            确实建了三个索引
            广东-Joshua(470534800)  15:28:20
            分别是 true 1 2
            重庆-mrshelly(49812643)  15:55:13
            关于 selected 的. 不是 为2就是高级检索吗?  0 不放到检索里. 1 放到 base 检索里. 2 放到advance 检索里.

            上海-Jeff(85822082)  15:55:46
            true呢?

            重庆-mrshelly(49812643)  15:55:49
            true=1
            False = 0

            上海-Jeff(85822082)  15:57:06
            你说的这个好象是view.xml里的select属性
            重庆-mrshelly(49812643)  15:57:09
            字段的这个也是一样的.

            上海-Jeff(85822082)  15:57:26
            我们刚才说的是class里field的select属性
            重庆-mrshelly(49812643)  15:57:28
            是啊. 你view 里没有指定的话. 就是 field 的 select 值啊. 就如同  digits  在字段里指定了.
            上海-Jeff(85822082)  15:57:59

            [attachimg=3]
            广东-Joshua(470534800)  15:58:32
            没有date
            上海-Jeff(85822082)  15:59:16
            没有parent_id哦,parent_id在高级里,=2

            广东-Joshua(470534800)  16:00:36
            'date': fields.date('Date', select=1),
            上海-Jeff(85822082)  16:01:23
            接下来去看看view里是不是去掉了date,加了ref customer contact
                                    <field name="name" select="1"/>
                                    <field name="ref" select="1"/>
                                    <field name="customer" select="1"/>

            上海-Jeff(85822082)  16:02:58
              <field name="date" select="2"/>
            广东-Joshua(470534800)  16:03:41
            [attachimg=4]
            广东-Joshua(470534800)  16:04:03
            [attachimg=5]
            上海-Jeff(85822082)  15:34:59
            'title': fields.selection(_partner_title_get, 'Title', size=32),
            这里用到了动态下拉列表
            为了过滤 partner_title的类型。因为那个title可能是给个人用的也可能是给公司用的,这里下拉列表只显示可供公司用的title

            上海-Jeff(85822082)  15:41:24

                    'child_ids': fields.one2many('res.partner', 'parent_id', 'Partner Ref.'),
            既然有父公司,就有子公司,这个字段是给那个公司结构的tree用的

            上海-Jeff(85822082)  15:49:20
                    'lang': fields.selection(_lang_get, 'Language', size=5, help="If the selected language is loaded in the system, all documents related to this partner will be printed in this language. If not, it will be english."),
            又一个动态下拉列表,只显示已安装的语言
            发现这种用法那个_lang_get 都是class之外的function啊,不知道另一个class的method行不行?
                 
            'user_id': fields.many2one('res.users', 'Dedicated Salesman', help='The internal user that is in charge of communicating with this partner if any.'),

            上海-Jeff(85822082)  15:53:15
            这个是负责这个业务伙伴的用户,叫客户经理?专员?
            上海-Jeff(85822082)  15:53:45
            业务伙伴专员?
            粤-Black Jack(104144648)  15:54:05
            业务员
            四川--Tomp(139776)  15:53:46
            都差不多的
            上海-Jeff(85822082)  15:54:24
            现在的翻译是业务专员,感觉业务员更好些,呵呵

            上海-Jeff(85822082)  16:08:29
            'bank_ids': fields.one2many('res.partner.bank', 'partner_id', 'Banks'),
            这个界面上也没有啊,估计都是给account服务的

            四川--Tomp(139776)  16:08:46
            还不如增加银行账户更加实用

            上海-Jeff(85822082)  16:10:00
            要不要跳到res.partner.bank去看看?
            上海-Jeff(85822082)  16:13:43
            '''Bank Accounts'''
            _description = doc ,玩这个花样干嘛
            _name = "res.partner.bank"
            _rec_name = "acc_number"
            _rec_name
            名称字段的字段名,默认是"name"。这个字段的字段值是类的name_get的返回值。many2one的字段在界面上的文本框里显示的就是这个值。
            这个挺有用的

            重庆-mrshelly(49812643)  16:16:45
            最多的应用 就象 科目 名.

            上海-Jeff(85822082)  16:16:48
            _order = 'sequence'
            不按银行帐号排序却按sequence排序,有趣
            joshua发的那个截屏,哪有sequence

            重庆-mrshelly(49812643)  16:18:16
            然后 把经常要操作的银行记录调到最前面.
            上海-Jeff(85822082)  16:18:38
            按一个不在界面上显示的字段排序,这个有点妖异吧
            重庆-mrshelly(49812643)  16:18:50
            排序应该只针对 tree view
            重庆-mrshelly(49812643)  16:22:07
            change_default 是玩啥的?
            上海-Jeff(85822082)  16:22:21
            让我疑惑的是为什么不弄个address,还搞那些国省市街的干啥
            重庆-mrshelly(49812643)  16:22:57
            我估计这样精确定位后, 可以确定汇率, 以及计算手续费. 
            重庆-mrshelly(49812643)  16:23:29
            然后 匹配 离银行最近的公司.
            重庆-mrshelly(49812643)  16:23:37
            或者离某公司最近的银行.

            上海-Jeff(85822082)  16:23:40
            change_default=False, 该字段可以作为取其他字段的当前用户默认值的条件
            重庆-mrshelly(49812643)  16:24:08
            True  就每次修改都把最后修改当默认值?
            上海-Jeff(85822082)  16:25:05
            你存默认值的时候不止可以存 B field的value,还可以存这个A field作为条件,你要是常用用户默认值就知道了

            重庆-mrshelly(49812643)  16:26:03
            按我的想法. 好象是说,  change_default 就是改变默认值.
            上海-Jeff(85822082)  16:26:13
            你save过默认值么?没事儿试试,有change_default=True和没有change_default=True会是不同的精彩

            重庆-mrshelly(49812643)  16:26:51
            [attachimg=10]
            两个有什么区别?
            上海-Jeff(85822082)  16:27:18
            上面是get,下面是set

            上海-Jeff(85822082)  16:30:21
            我找到了一个例子
            上海-Jeff(85822082)  16:30:14
            [attachimg=6]

            重庆-mrshelly(49812643)  16:30:36
            我打开保存, 还是没有能理解.
            上海-Jeff(85822082)  16:30:59
            这里这个邮编就是 change_default=True

            广东-Joshua(470534800)  16:31:09
            联动

            重庆-mrshelly(49812643)  16:31:31
            那联动条件呢?
            上海-Jeff(85822082)  16:31:51
            change_default=True的字段就是联动条件
            重庆-mrshelly(49812643)  16:32:20
            哦?? 意思是 change_default 可以是 True  False 也可以是一个 domain?
            上海-Jeff(85822082)  16:33:47
            应该只是是boolean吧
            重庆-mrshelly(49812643)  16:34:09
             
            上海-Jeff(85822082)  16:34:14
            就是那个 值有效如果...
            重庆-mrshelly(49812643)  16:34:20
            这个 zip = 313200 在哪里设置的? 
            广东-Joshua(470534800)  16:34:49
            [attachimg=7]
            重庆-mrshelly(49812643)  16:34:57
            难道是 公司定义的 zip?
            广东-Joshua(470534800)  16:35:00
            你填神马就是神马
            上海-Jeff(85822082)  16:35:04
            213200是你在存默认值的时候zip字段的值啊
            重庆-mrshelly(49812643)  16:35:28
              那 change_default 倒底是定义到 zip 上?
            重庆-mrshelly(49812643)  16:35:35
            还是定义在 Function 字段上?

            上海-Jeff(85822082)  16:35:40
            是在zip上的
            重庆-mrshelly(49812643)  16:35:49
            那就是说. 如果一个字段定义了. 
            上海-Jeff(85822082)  16:35:58
            change_default=True就可以给人服务
            重庆-mrshelly(49812643)  16:36:20
            如果 country也定义了 change_default=True
            那么, 在 Function 里设置默认值就会有两个条件/

            上海-Jeff(85822082)  16:36:50
            会有两个check box
            重庆-mrshelly(49812643)  16:36:41
            那么, 在 Function 里设置默认值就会有两个条件/

            上海-Jeff(85822082)  16:36:50
            会有两个check box
            上海-Jeff(85822082)  16:39:18
            我这里出不来两个checkbox
            重庆-mrshelly(49812643)  16:39:35
            那出来哪一个? 还是  zip? 你把 zip 的定义调后一点... 
            上海-Jeff(85822082)  16:39:53
            一个都不出来,估计是bug

            重庆-mrshelly(49812643)  16:39:56
            看看 会不会出来 country. 好多字段都是 change_default
            ==========================================
            重庆-mrshelly(49812643)  16:40:41
              看这个:
            [attachimg=8]
            广东-Joshua(470534800)  16:42:26
            那个联动的我先在好像测试不到他有动,明明记得之前测试时可以的
            重庆-mrshelly(49812643)  16:42:55
            [attachimg=9]
            上海-Jeff(85822082)  16:43:09
            这个用来写文章,当然,大多数时候都是空着的
            重庆-mrshelly(49812643)  16:43:08
            bank 多个 change_default 的确没用.

            ============================================================

            上海-Jeff(85822082)  16:40:05
            下一话题,回到partner:
            'website': fields.char('Website',size=64),
            这个牛B的地方在于它的view做成了一个link

            上海-Jeff(85822082)  16:42:53
            'comment': fields.text('Notes')
            'address': fields.one2many('res.partner.address', 'partner_id', 'Contacts'),
            配角上场,这个复杂了,必须跳到res.partner.address上去了
                _description ='Partner Addresses'
                _name = 'res.partner.address'
                _order = 'id'
                _columns = {

            重庆-mrshelly(49812643)  16:44:52
            就是联系人嘛..
            广东-Joshua(470534800)  16:45:10
            我不明白为什么
                    'street': fields.char('Street', size=128),
                    'street2': fields.char('Street2', size=128),
            2个地址!

            上海-Jeff(85822082)  16:46:07
            怕128位写不下,再搞个延长的
            重庆-mrshelly(49812643)  16:46:24
            那还不如用 256
            四川--Tomp(139776)  16:46:19
            太长了影响试图


            上海-Jeff(85822082)  16:45:45
                    'partner_id': fields.many2one('res.partner', 'Partner', ondelete='set null', select=True, help="Keep empty for a private address, not related to partner."),

            广东-Joshua(470534800)  16:46:27
            ondelete="setnull", 用于many2one类型的字段 如setnull,one的对象删除后many这边字段值设为空
            上海-Jeff(85822082)  16:46:49
            就是说删了业务伙伴不删地址
            重庆-mrshelly(49812643)  16:46:48
            阔以写  "SetNULL" 不?

            上海-Jeff(85822082)  16:47:30
            前面注意了没有,删除业务伙伴bank也会被删
            广东-Joshua(470534800)  16:47:39
            @shelly ondelete='set null'
            上海-Jeff(85822082)  16:48:02
            同样是many2one,差距可大了,写程序的时候可注意了

            广东-Joshua(470534800)  16:48:39
            'type': fields.selection( [ ('default','Default'),('invoice','Invoice'), ('delivery','Delivery'), ('contact','Contact'), ('other','Other') ],'Address Type', help="Used to select automatically the right address according to the context in sales and purchases documents."),
            上海-Jeff(85822082)  16:49:48
            这里就有意思了,每个公司必须有个default
            上海-Jeff(85822082)  16:50:17
            inv del两个有也行,没有就用default填充
            上海-Jeff(85822082)  16:50:29
            contact只是其中一个类型
            重庆-mrshelly(49812643)  16:50:39
            没有看到必须有 default 呀.
            上海-Jeff(85822082)  16:51:08
            没有的话采购订单和销售订单都取不到地址
            上海-Jeff(85822082)  16:51:52
            我曾经建议一个网商设置一个没有default的partner作为零售客户
            上海-Jeff(85822082)  16:52:06
            因为每次送货地址都变化
            重庆-mrshelly(49812643)  16:52:36
            难道, 只建一个 partner ? 然后 每个客户一个地址?

            广东-Joshua(470534800)  16:52:42
            sales order report 里面用到这个
            上海-Jeff(85822082)  16:52:45
            有个小子昨天说每个公司都至少有个联系人,请看昨天下午的聊天记录
            地址是根据partner复制到order的
            上海-Jeff(85822082)  16:53:51
            不需要——然后 每个客户一个地址?

            上海-Jeff(85822082)  16:54:16
            这个我们看order的代码的时候会看到
            上海-Jeff(85822082)  16:54:34
            'function': fields.many2one('res.partner.function', 'Function'),
            广东-Joshua(470534800)  16:55:21
            业务伙伴联系人的职务,职能
            上海-Jeff(85822082)  16:55:29
            职位,没啥说的
            广东-Joshua(470534800)  16:55:41
            职位的code不能重复

            上海-Jeff(85822082)  16:55:40
                    'title': fields.selection(_contact_title_get, 'Title', size=32),
            动态下拉菜单,只能选针对个人的称谓,雷德森或者健特们

            上海-Jeff(85822082)  16:57:08
                    'name': fields.char('Contact Name', size=64),
                    'street': fields.char('Street', size=128),
                    'street2': fields.char('Street2', size=128),
                    'zip': fields.char('Zip', change_default=True, size=24),
                    'city': fields.char('City', size=128),
                    'state_id': fields.many2one("res.country.state", 'Fed. State', domain="[('country_id','=',country_id)]"),

            广东-Joshua(470534800)  16:57:08
            def _contact_title_get(self, cr, uid, context={}):
                obj = self.pool.get('res.partner.title')
                ids = obj.search(cr, uid, [('domain', '=', 'contact')])
                res = obj.read(cr, uid, ids, ['shortcut','name'], context)
            return [(r['shortcut'], r['name']) for r in res] + [('','')]

            重庆-mrshelly(49812643)  16:57:07
            好多定义里都有类似的代码.
            上海-Jeff(85822082)  16:57:17
            这才是联动
            上海-Jeff(85822082)  16:57:38
            domain="[('country_id','=',country_id)]"),

            重庆-mrshelly(49812643)  16:57:48
            这个是过滤呀...
            上海-Jeff(85822082)  16:58:14
              'birthdate': fields.char('Birthdate', size=64),

            重庆-mrshelly(49812643)  16:58:14
            联动, 我觉得 是 onchange
            上海-Jeff(85822082)  16:58:21
            为啥不用date?

            上海-Jeff(85822082)  16:58:52
            'active': fields.boolean('Active', help="Uncheck the active field to hide the contact."),
            四川--Tomp(139776)  17:00:30
              _defaults = {
                    'active': lambda *a: 1,
                } 
            有缺省值

            1 条回复 最后回复
            0
            • J 离线
              J 离线
              jack
              写于 最后由 编辑
              #6

              俺喜欢的mm

              1 条回复 最后回复
              0
              • wjfonhandW 离线
                wjfonhandW 离线
                wjfonhand
                写于 最后由 编辑
                #7

                      上次说到298行,birthdate
                    *
                      上海-Jeff (85822082)
                      2010-09-06 15:16:50

                      'active': fields.boolean('Active', help="Uncheck the active field to hide the contact."),
                    *
                      上海-Jeff (85822082)
                      2010-09-06 15:17:21

                      这个active是个很特殊的字段,是orm里默认的五个字段之一
                    *
                      上海-Jeff (85822082)
                      2010-09-06 15:18:37

                      一个对象至少包含这5个字段,即使你不在_columns里指定,pgsql表里也会创建
                    *
                      上海-Jeff (85822082)
                      2010-09-06 15:19:26

                      但是一旦你需要把它显示在view里,那就必须在对象的_columns属性里显式地声明他
                    *
                      四川--Tomp (139776)
                      2010-09-06 15:19:29

                      你们先进行,我做完事情就来。我等会去查记录
                    *
                      广东-Joshua (470534800)
                      2010-09-06 15:19:31

                      active 如果是false就会隐藏了

                #
                上海-Jeff (85822082)
                2010-09-06 15:21:49

                active如果是false,就会掩藏这个记录,但是对他的子记录有什么影响呢?
                #
                广东-Joshua (470534800)
                2010-09-06 15:22:37

                子记录?
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:23:18

                应该没有影响. 看OE的东西. 一般子记录就没有入口了. 所以看不到.
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:23:26

                也可以从一定意义上讲是隐藏了.
                #
                上海-Jeff (85822082)
                2010-09-06 15:23:40

                比如partner被deactive了
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:23:45

                这一块OE应该没有做太严谨...
                #
                上海-Jeff (85822082)
                2010-09-06 15:24:07

                它的address应该有个partner字段,会显示啥?

                #
                重庆-mrshelly (49812643)
                2010-09-06 15:24:43

                看不懂.
                #
                上海-Jeff (85822082)
                2010-09-06 15:25:04

                address是有单独的菜单入口的,shelly
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:25:36

                active 你指谁的 acitve ?
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:25:40

                partner?
                #
                上海-Jeff (85822082)
                2010-09-06 15:25:45

                恩
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:25:51

                应该可以看得到.
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:26:04

                我估计 address 的 partner 应该也看得到.
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:26:10

                谁测试一下?
                #
                上海-Jeff (85822082)
                2010-09-06 15:26:23

                主数据active=false了的话,对业务数据有啥影响,这个比较关键
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:26:38

                OE应该也没有处理.
                #
                上海-Jeff (85822082)
                2010-09-06 15:29:43

                测试结果、没有处理
                #
                四川--Tomp (139776)
                2010-09-06 15:30:05

                谁在记录?
                #
                上海-Jeff (85822082)
                2010-09-06 15:30:13

                qq在记录
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:30:14

                看OE的代码风格, 应该就可以看得出来.
                #
                上海-Jeff (85822082)
                2010-09-06 15:30:35

                机制是这样
                #
                上海-Jeff (85822082)
                2010-09-06 15:31:26

                如果一个产品有销售订单,那么你设置产品的active=false以后
                #
                上海-Jeff (85822082)
                2010-09-06 15:31:52

                无论是输入新订单还是查看产品列表,你都看不到这个产品了
                #
                上海-Jeff (85822082)
                2010-09-06 15:32:10

                但是旧的订单上,这个产品还在
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:33:02

                所以说啊.
                #
                上海-Jeff (85822082)
                2010-09-06 15:33:09

                所以这个逻辑删除和物理删除是有区别的,不需要做检查
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:33:11

                OE的大部分都是在 view 端控制的.
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:33:38

                也就是说, 只是把入口切断了.
                #
                上海-Jeff (85822082)
                2010-09-06 15:33:50

                如果你把这个product删除了,相信会有一个方法检查是否有历史记录,然后报错
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:33:51

                这种方式是很不科学的.
                #
                上海-Jeff (85822082)
                2010-09-06 15:34:09

                我觉得这个逻辑是合理的
                #
                上海-Jeff (85822082)
                2010-09-06 15:41:11

                'active': lambda *a: 1,
                #
                上海-Jeff (85822082)
                2010-09-06 15:50:15

                partner address的字段看完了,接下来看方法
                #
                上海-Jeff (85822082)
                2010-09-06 15:50:32

                305行 def name_get
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:51:38

                显示地址的方式... 没有必要看.
                #
                广东-Joshua (470534800)
                2010-09-06 15:51:53

                来了..
                #
                上海-Jeff (85822082)
                2010-09-06 15:52:08

                比较有意思,需要显示联系人就显示人名,需要显示地址就用逗号把地址串起来
                #
                上海-Jeff (85822082)
                2010-09-06 15:53:24

                感觉这里应该重写,中国的地址顺序和国际友人不同
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:53:37

                嗯...
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:53:44

                这个不是重点. 个人觉得.
                #
                上海-Jeff (85822082)
                2010-09-06 15:53:50

                咱从大处着眼,从中国写起,他们先写门牌号
                #
                广东-Joshua (470534800)
                2010-09-06 15:53:56

                OE里面很多name_get都喜欢这样连起来
                #
                广东-Joshua (470534800)
                2010-09-06 15:54:03

                嗯,可以跳下一个
                #
                上海-Jeff (85822082)
                2010-09-06 15:54:27

                def name_search
                #
                上海-Jeff (85822082)
                2010-09-06 15:54:38

                这是干啥用的?
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:55:10

                自定义查找方法.
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:55:18

                一般的检索, 就是在字段内检索.
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:55:32

                自定义后, 就可以乱七八糟检索.
                #
                广东-Joshua (470534800)
                2010-09-06 15:55:44

                嗯
                #
                广东-Joshua (470534800)
                2010-09-06 15:56:10

                先搜name 再搜 zip 再乱七八糟
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:56:17

                看,代码里, 可以按 zip 按 city 按 name
                #
                上海-Jeff (85822082)
                2010-09-06 15:56:40

                我试着来解释一下
                #
                广东-Joshua (470534800)
                2010-09-06 15:56:44

                这个很多地方都有
                #
                上海-Jeff (85822082)
                2010-09-06 15:56:52

                既然显示是分人名和地址
                #
                上海-Jeff (85822082)
                2010-09-06 15:57:29

                那输入的时候 用输入的文字去找adress对象 也是走两条路
                #
                上海-Jeff (85822082)
                2010-09-06 15:58:11

                比如你找联系人,那就输入 张,会搜出来姓张的人
                #
                上海-Jeff (85822082)
                2010-09-06 15:58:49

                但找地址就不能输入 张 了,而应该是如 解放碑 之类的
                #
                上海-Jeff (85822082)
                2010-09-06 15:58:56

                agree ?
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:59:02

                嗯...
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:59:17

                就如同 解放碑这个地址里有一个"张灰牛肉"
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:59:29

                然后 你检索的时候, 会出来"解放碑"
                #
                上海-Jeff (85822082)
                2010-09-06 15:59:53

                所以说 name_get 是用来显示many2one的
                #
                重庆-mrshelly (49812643)
                2010-09-06 15:59:55

                这一块儿 在整个框架中, 做得不错... 企业里很多这样的应用.
                #
                上海-Jeff (85822082)
                2010-09-06 16:00:15

                name_search是用来帮助输入many2one的
                #
                广东-Joshua (470534800)
                2010-09-06 16:00:24

                对的!
                #
                上海-Jeff (85822082)
                2010-09-06 16:01:04

                def get_city
                #
                上海-Jeff (85822082)
                2010-09-06 16:01:17

                这是干嘛用的,哪里调用了?
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:01:59

                我估计查邮编的时候可能要用到.
                #
                上海-Jeff (85822082)
                2010-09-06 16:05:13

                好的,partner address整完了,咱还回到partner
                #
                上海-Jeff (85822082)
                2010-09-06 16:05:24

                现在我们在148行
                #
                上海-Jeff (85822082)
                2010-09-06 16:06:04

                'category_id': fields.many2many('res.partner.category', 'res_partner_category_rel', 'partner_id', 'category_id', 'Categories'),
                #
                上海-Jeff (85822082)
                2010-09-06 16:07:58

                原来我不明白数据库咋存储多对多,现在理解应该是用 res_partner_category_rel 把关系拆成了两个一对多,是么?
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:08:28

                就是把两个对象用一个中间表 来关联 对象之间的关系.
                #
                广东-Joshua (470534800)
                2010-09-06 16:08:38

                是的
                #
                上海-Jeff (85822082)
                2010-09-06 16:09:25

                class res_partner_category
                #
                上海-Jeff (85822082)
                2010-09-06 16:09:51

                按惯例,我们又跳到 54行 了
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:10:08

                为什么要这样惯?
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:10:15

                跳来跳切好麻烦.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:10:20

                顺着看就行了.
                #
                广东-Joshua (470534800)
                2010-09-06 16:11:37

                #
                广东-Joshua (470534800)
                2010-09-06 16:11:49

                看错了
                #
                上海-Jeff (85822082)
                2010-09-06 16:12:04

                我倒觉得这个需求和我们做的那个 显示会计科目全名很像
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:12:16

                是的.
                #
                广东-Joshua (470534800)
                2010-09-06 16:12:21

                name_get?
                #
                上海-Jeff (85822082)
                2010-09-06 16:12:50

                恩
                #
                上海-Jeff (85822082)
                2010-09-06 16:13:14

                def name_get
                #
                广东-Joshua (470534800)
                2010-09-06 16:13:22

                是啊,我覆盖了旧的方法
                #
                上海-Jeff (85822082)
                2010-09-06 16:13:34

                reads = self.read(cr, uid, ids, ['name','parent_id'], context=context)
                #
                上海-Jeff (85822082)
                2010-09-06 16:14:26

                请问两位老师,这样会把 father拿出来,还是连father 的 father的father都能一起俘虏?
                #
                上海-Jeff (85822082)
                2010-09-06 16:16:50

                果然是把整个 一大家子都拿出来了
                #
                广东-Joshua (470534800)
                2010-09-06 16:16:57


                reads = self.read(cr, uid, ids, ['name','parent_id'], context=context)


                #
                上海-Jeff (85822082)
                2010-09-06 16:17:20

                高手给讲讲,怎么做到的? 不用循环就能取到?
                #
                广东-Joshua (470534800)
                2010-09-06 16:17:26

                for record in reads:
                name = record['name']
                if record['parent_id']:
                name = record['parent_id'][1]+' / '+name
                res.append((record['id'], name))
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:17:38

                关键我估计要看 context 里的东西吧?
                #
                广东-Joshua (470534800)
                2010-09-06 16:18:08

                for循环吧
                #
                上海-Jeff (85822082)
                2010-09-06 16:18:22

                不是,我懂了
                #
                上海-Jeff (85822082)
                2010-09-06 16:18:36

                这样只会把 father拿出来
                #
                上海-Jeff (85822082)
                2010-09-06 16:18:58

                grandfather抓不到
                #
                广东-Joshua (470534800)
                2010-09-06 16:19:03

                看来只是只是找出直系
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:19:03

                然后 father 取 name 的时候, 应该又会调用 name_get
                #
                上海-Jeff (85822082)
                2010-09-06 16:19:09

                是的
                #
                广东-Joshua (470534800)
                2010-09-06 16:19:12

                哈对!
                #
                上海-Jeff (85822082)
                2010-09-06 16:19:32

                所以这里的for循环只会执行一次,根本就是fetchone
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:19:35

                这就是 osv 中的牛X地方.
                #
                广东-Joshua (470534800)
                2010-09-06 16:19:50

                这段可以改善我之前写的那个
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:20:02

                嗯...
                #
                上海-Jeff (85822082)
                2010-09-06 16:22:54

                def _check_recursion
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:23:06

                _check_recursion
                讨论过了.
                #
                上海-Jeff (85822082)
                2010-09-06 16:24:43

                level = 100
                while len(ids):
                cr.execute('select distinct parent_id from res_partner_category where id in %s', (tuple(ids),))
                #
                上海-Jeff (85822082)
                2010-09-06 16:24:55

                这几句看懂了
                #
                上海-Jeff (85822082)
                2010-09-06 16:25:12

                ids = filter(None, map(lambda x:x[0], cr.fetchall()))
                这是啥啊?

                #
                重庆-mrshelly (49812643)
                2010-09-06 16:25:37

                这句, 就是取出 给定的 ids 里所有 父 ids
                #
                广东-Joshua (470534800)
                2010-09-06 16:25:40

                这句靠水哥

                #
                广东-Joshua (470534800)
                2010-09-06 16:27:03

                filter()这个是python的方法??
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:28:15

                这一句, 那个 filter 应该是多余的.
                #
                上海-Jeff (85822082)
                2010-09-06 16:28:58

                是不是把空值干掉啊
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:29:20

                不是...
                #
                上海-Jeff (85822082)
                2010-09-06 16:29:30

                cr.fetchall() 返回的可能会有一些空的element
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:29:35

                这句的作用是, 用 None 去过滤 map 的结果.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:29:49

                因为方法是 None 也就是不过滤.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:30:07

                所以, 理论上, 这句与 map(lambda x:x[0], cr.fetchall())
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:30:11

                是一样的效果.
                #
                上海-Jeff (85822082)
                2010-09-06 16:31:12

                超出会计的理解能力了
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:31:44

                所以, 就理解为 取出 给定类别的所有父类ID
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:31:46

                就行了.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:31:53

                读代码, 应该 先块级读.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:31:57

                再去行读.
                #
                上海-Jeff (85822082)
                2010-09-06 16:32:44

                if not level:
                return False
                level -= 1
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:33:00

                这个是递归只允许 100级.
                #
                上海-Jeff (85822082)
                2010-09-06 16:33:08

                这个是避免死循环的吧,读到100级就放弃了
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:33:27

                也就是说, 如果你的 partner 分类 级达到100级以上,,, 呵呵... OE就不会管这个限制了.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:33:31

                估计米人这么变态.
                #
                上海-Jeff (85822082)
                2010-09-06 16:33:47

                _description='Partner Categories'
                _name = 'res.partner.category'
                _columns = {
                'name': fields.char('Category Name', required=True, size=64, translate=True),
                'parent_id': fields.many2one('res.partner.category', 'Parent Category', select=True),
                'complete_name': fields.function(_name_get_fnc, method=True, type="char", string='Full Name'),
                'child_ids': fields.one2many('res.partner.category', 'parent_id', 'Child Categories'),
                'active' : fields.boolean('Active', help="The active field allows you to hide the category without removing it."),
                }

                #
                上海-Jeff (85822082)
                2010-09-06 16:34:31

                这些应该没什么需要解释的吧,如果大家对function字段类型没意见的话
                #
                广东-Joshua (470534800)
                2010-09-06 16:35:12

                嗯
                #
                上海-Jeff (85822082)
                2010-09-06 16:35:14

                _constraints = [
                (_check_recursion, 'Error ! You can not create recursive categories.', ['parent_id'])
                ]
                _defaults = {
                'active' : lambda *a: 1,
                }
                _order = 'parent_id,name'
                #
                上海-Jeff (85822082)
                2010-09-06 16:35:59

                第一次碰到_constraints,这个是server级别的,还有个数据库级别的
                #
                上海-Jeff (85822082)
                2010-09-06 16:36:14

                那我们回去partner ?
                #
                广东-Joshua (470534800)
                2010-09-06 16:36:28

                嗯
                #
                上海-Jeff (85822082)
                2010-09-06 16:36:58

                'events': fields.one2many('res.partner.event', 'partner_id', 'Events'),

                #
                上海-Jeff (85822082)
                2010-09-06 16:37:26

                为了避免跳出去找不到回来的路,我们这次就不跳了吧
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:37:46

                server 级的.

                #
                重庆-mrshelly (49812643)
                2010-09-06 16:37:53

                这一块就是不太清楚.
                #
                上海-Jeff (85822082)
                2010-09-06 16:37:55

                这里可以算个crm的雏形,用不起crm的穷公司可以先用这个记录一下
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:38:19

                这个 _check_recursion 为 True 时候, 是允许, 还是 False 的时候 允许呢?

                #
                上海-Jeff (85822082)
                2010-09-06 16:40:40

                shelly好问题!
                #
                广东-Joshua (470534800)
                2010-09-06 16:43:22

                False--> Error ! You can not create recursive categories.
                #
                上海-Jeff (85822082)
                2010-09-06 16:44:58

                应该是false的时候报错,true的时候直接通过
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:45:07

                嗯.. 想想 _check_recursion 在什么情况下, 会 return False?
                #
                广东-Joshua (470534800)
                2010-09-06 16:45:25

                真的搞100层
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:45:25

                not level
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:45:33

                不对劲啊.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:45:40

                哦.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:45:41

                对的.
                #
                上海-Jeff (85822082)
                2010-09-06 16:45:44

                shelly我觉得你你对那句话的解释不对啊
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:45:58

                如果是死 循环的话, 就很容易超过 100
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:46:05

                然后 就 return False 了.
                #
                广东-Joshua (470534800)
                2010-09-06 16:46:15

                哦~

                上海-Jeff (85822082)
                2010-09-06 16:47:24

                然后42再找35,35再找42

                #
                重庆-mrshelly (49812643)
                2010-09-06 16:47:39

                level 一直减
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:47:45

                减到 0 就返回.
                #
                广东-Joshua (470534800)
                2010-09-06 16:47:48

                经测试是这样的!

                #
                重庆-mrshelly (49812643)
                2010-09-06 16:47:59

                呵呵... OE的这个算法有些意思.
                #
                上海-Jeff (85822082)
                2010-09-06 16:48:24

                值得一读
                #
                上海-Jeff (85822082)
                2010-09-06 16:48:50

                有些for循环只跑一次,有些while循环总跑100次

                #
                重庆-mrshelly (49812643)
                2010-09-06 16:49:15

                但是 如果我写.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:49:24

                我肯定把查到的 id push 到一个地方.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:49:28

                然后 继续查...
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:49:42

                只要新查到的 parent 已经push 过了.
                #
                上海-Jeff (85822082)
                2010-09-06 16:49:43

                有重复的就结束了
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:49:47

                就直接 return False 了.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:49:58

                他这个算法有问题.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:50:00

                有些耗.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:50:14

                即使是100级.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:50:21

                也才保存 100 个id 而已.

                #
                重庆-mrshelly (49812643)
                2010-09-06 16:50:26

                内存耗用也不会太大.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:51:13

                35 -->[35]
                35 查到 42
                42 -->[35, 42]
                42 查到 48
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:51:21

                48 --> [35,42,48]
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:51:25

                48查到 38
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:51:36

                48查到35
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:51:39

                然后 就判断出来了.
                #
                广东-Joshua (470534800)
                2010-09-06 16:51:40

                有改进的点了
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:51:51

                只有几次循环, 不用他那样循环100次.
                #
                上海-Jeff (85822082)
                2010-09-06 16:51:57

                他现在8行代码,你那么写16行不止
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:52:07

                不公.

                #
                重庆-mrshelly (49812643)
                2010-09-06 16:52:09

                不会.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:52:13

                即使16行.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:52:18

                我也会选择16行的代码.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:52:39

                16 行的好处就是 少了很多次循环.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:52:51

                而且它这里, 还要查询数据库.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:52:56

                100次查询.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:53:01

                这个优化还是很值得的.
                #
                上海-Jeff (85822082)
                2010-09-06 16:53:02

                这个在深入就是人生观了,到此为止
                #
                广东-Joshua (470534800)
                2010-09-06 16:53:10

                #
                上海-Jeff (85822082)
                2010-09-06 16:53:35

                'credit_limit': fields.float(string='Credit Limit'),
                #
                上海-Jeff (85822082)
                2010-09-06 16:54:04

                这个应该在account或者sale才用到的字段,这么早就放进去啦
                #
                上海-Jeff (85822082)
                2010-09-06 16:54:18

                'ean13': fields.char('EAN13', size=13),
                #
                上海-Jeff (85822082)
                2010-09-06 16:54:31

                partner也支持条码输入
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:54:35

                嗯...
                #
                上海-Jeff (85822082)
                2010-09-06 16:54:42

                'active': fields.boolean('Active'),
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:54:48

                我很最以前, 就玩过条码管理供应端.
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:54:57

                不过是做的是供应商的车辆管理.
                #
                上海-Jeff (85822082)
                2010-09-06 16:55:10

                'customer': fields.boolean('Customer', help="Check this box if the partner is a customer."),
                'supplier': fields.boolean('Supplier', help="Check this box if the partner is a supplier. If it's not checked, purchase people will not see it when encoding a purchase order."),
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:55:22

                每个供应商需要有个条码... 才能门禁确认.
                #
                上海-Jeff (85822082)
                2010-09-06 16:55:33

                'city':fields.related('address','city',type='char', string='City'),
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:55:52

                related ?
                #
                上海-Jeff (85822082)
                2010-09-06 16:56:01

                related是啥意思来着,偶查查
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:56:07

                相关...
                #
                粤-Black Jack (104144648)
                2010-09-06 16:56:47

                引用的号码就是引用的记录
                #
                重庆-mrshelly (49812643)
                2010-09-06 16:57:49

                号码?
                #
                上海-Jeff (85822082)
                2010-09-06 16:58:22

                这个牛啊
                #
                粤-Black Jack (104144648)
                2010-09-06 16:58:48

                。。。sorry就理解为对象引用的一个标记
                #
                四川--Tomp (139776)
                2010-09-06 16:58:56

                我忙完了。
                #
                粤-Black Jack (104144648)
                2010-09-06 16:59:06

                那例子就是引用city
                #
                粤-Black Jack (104144648)
                2010-09-06 16:59:32

                不过type是什么意思
                #
                上海-Jeff (85822082)
                2010-09-06 17:02:25

                related:

                Sometimes you need to refer to the relation of a relation. For example, supposing you have objects: City -> State -> Country, and you need to refer to the Country from a City, you can define a field as below in the City object:

                'country_id': fields.related(
                'state_id',
                'country_id',
                type="many2one",
                relation="module.country",
                string="Country",
                store=False)

                #
                上海-Jeff (85822082)
                2010-09-06 17:03:38

                我英文不好,哪位能翻译
                #
                粤-Black Jack (104144648)
                2010-09-06 17:04:32

                。。。
                #
                广东-Joshua (470534800)
                2010-09-06 17:04:51

                有时你需要参考的一个关系的关系。举例来说,假如你有对象:城市 - >状态 - >国家,你需要把一个城市到乡村,你可以定义为城市中的对象以下字段:
                #
                上海-Outlook (8492321)
                2010-09-06 17:05:31

                这里refer表示引用比较恰当
                #
                粤-Black Jack (104144648)
                2010-09-06 17:05:50

                就是说在确定city时那个count就可以用relation
                #
                上海-Jeff (85822082)
                2010-09-06 17:06:07

                把一个城市到乡村,哥,你笑死我了
                #
                粤-Black Jack (104144648)
                2010-09-06 17:06:19

                系统给出一个选择图标出来
                #
                重庆-mrshelly (49812643)
                2010-09-06 17:06:36

                好象可以理解为 如果partner 有设置 address City 的话, 就直接沿用 这个 City
                #
                粤-Black Jack (104144648)
                2010-09-06 17:07:03

                这怎么理解?
                #
                重庆-mrshelly (49812643)
                2010-09-06 17:07:31

                不过, 好象 partner 先建 address 后建吧. 通常情况.
                #
                浙江-疯子 (15369940)
                2010-09-06 17:07:49

                没称市就用弟子
                #
                粤-Black Jack (104144648)
                2010-09-06 17:07:52

                有设置的
                #
                重庆-mrshelly (49812643)
                2010-09-06 17:08:28

                哦. 取 address 这个字段对象的 city 值做为本记录的值.
                #
                上海-Jeff (85822082)
                2010-09-06 17:10:08

                重庆-mrshelly(49812643) 5:08:28 PM
                哦. 取 address 这个字段对象的 city 值做为本记录的值.niubility !
                #
                上海-Jeff (85822082)
                2010-09-06 17:30:20

                下一个问题是多个adress的city不一样看它用哪一个
                #
                上海-Jeff (85822082)
                2010-09-06 17:31:17

                放学了,谢谢各位!
                #
                重庆-mrshelly (49812643)
                2010-09-06 17:31:20

                嗯.. 正要问到这里, 多个 address 它如何选择.

                GoodERP -- Odoo China fork

                1 条回复 最后回复
                0
                • JoshuaJ 离线
                  JoshuaJ 离线
                  Joshua 管理员
                  写于 最后由 编辑
                  #8

                  关于partner的源码分析整理到WIKI里面 :)<br / [检测到链接无效,已移除] br />

                  【上海先安科技】(joshua AT openerp.cn),欢迎关注公众号:openerp_cn

                  1 条回复 最后回复
                  0
                  • wjfonhandW 离线
                    wjfonhandW 离线
                    wjfonhand
                    写于 最后由 编辑
                    #9

                    well done, I modified it to give you some color see see

                    GoodERP -- Odoo China fork

                    1 条回复 最后回复
                    0

                    • 登录

                    • 没有帐号? 注册

                    • 登录或注册以进行搜索。
                    • 第一个帖子
                      最后一个帖子
                    0
                    • 版块
                    • 标签
                    • 热门
                    • 用户
                    • 群组