解决重复业务单据

背景:

单个设备在没有业务唯一标识的情况创建业务单据时因网络原因出现异常,服务器接口其实已经正常接收,间隔一定时间后重新保存会出现重复单据

待调整的内容:

涉及到创建的单据有:调拨出库,配货退货,补货申请,库存损溢
在创建单据前根据统一接口(/api/v6/shop/order/order_no/get)获取单号,拿到单号后作为请求参数传入对应创建/更新接口中,服务器端根据单号判断是否存在进入创建或更新逻辑。

涉及到的接口有:
创建,修改调拨单(/api/v6/shop/pick/update/post)
创建,更新损溢单(/api/v6/shop/scrap/update/post)
创建,更新补货单(/api/v6/shop/reload/update/post)

1.新建业务单据表-(业务单号、业务类型、修改人、最后修改时间等字段)doc_no.py
# -*- coding: utf-8 -*-
import datetime
import logging

from openerp.osv import fields, osv

_logger = logging.getLogger(__name__) 

business_type_item = {'sale':1, 'sale_return':2, 'sale_exchange':3, 'shop_pick_out':4, 'stock_move':5, 'refund':6, 'inventory':7, 'scrap':8, 'reload':9}
business_type_list = [(1, u'销售订单'), (2, u'销售退货'), (3, u'销售换货'), (4, u'调拨出库'),(5, u'本店移库'), (6, u'配货退货'), (7, u'盘点'), (8, u'损溢'), (9, u'补货申请')]

class nt_doc_no(osv.osv):
    _name = "nt.doc.no"
    _description = u"业务单号"
    _columns = {
        "business_type": fields.selection(business_type_list, u"业务类型", select=True),
        "doc_no": fields.char(u"业务单号", size=32, required=True, select=True),
        'write_uid': fields.many2one('res.users', u'最后修改者', readonly=True, ),
        'write_date': fields.datetime(u'最后修改时间', readonly=True),
    }

    _sql_constraints = [
        ('nt_doc_type_no_uniq', 'unique(business_type,doc_no)', u'业务单号唯一')
    ]

    def _auto_init(self, cr, context=None):
        #初始化,查找索引,若无就创建
        super(nt_doc_no, self)._auto_init(cr, context)
        cr.execute('SELECT indexname FROM pg_indexes WHERE indexname in %s', (('inx_nt_doc_type_no',),))
        index_names =[rs[0] for rs in cr.fetchall()]
        if 'inx_nt_doc_type_no' not in index_names:
            cr.execute("create index inx_nt_doc_type_no on nt_doc_no(business_type,doc_no)")
            cr.execute('ANALYZE nt_doc_no')

    def _set_doc_no(self, cr, uid, doc_no, business_type=1,  context=None):
        #创建业务单号(openerp自带创建时间和创建人等字段)
        if context is None:context = {}
        cr.execute("""
                INSERT INTO nt_doc_no 
                    (create_uid,create_date,write_date,write_uid, business_type,doc_no) 
                VALUES
                 (%s,now(),now(),%s, %s, '%s') returning id
        """ %(uid, uid, business_type,doc_no))
        doc_no_id = cr.fetchone()[0]
        return doc_no_id

    def _get_doc_no(self, cr, uid, doc_no, business_type,  context=None):
        #获取业务单据方法
        if context is None:context={}
        cr.execute("""
            select id from nt_doc_no where business_type=%s and doc_no = %s limit 1
        """,(business_type, doc_no))
        result = cr.fetchone()
        return result and result[0] or False
2.编写tree视图doc_n0_view.xml
<?xml version="1.0" encoding="utf-8"?>
<openerp>
    <data>
         
        <record model="ir.ui.view" id="nt_doc_no_tree_view">
            <field name="name">nt.doc.no.tree.view</field>
            <field name="model">nt.doc.no</field>
            <field name="type">tree</field>
            <field name="arch" type="xml">
                <tree string="业务单号" create="0" delete="0" edit="0">
                    <field name="business_type"/>
                    <field name="doc_no"/>
                    <field name="write_uid"/>
                    <field name="write_date"/>
                </tree>
            </field>
        </record>

        <record id="action_nt_doc_no_tree_list" model="ir.actions.act_window">
            <field name="name">业务单号</field>
            <field name="type">ir.actions.act_window</field>
            <field name="res_model">nt.doc.no</field>
            <field name="view_type">form</field>
            <field name="view_mode">tree</field>
			<field name="context">{}</field>
			<field name="domain">[]</field>
        </record>

    </data>
</openerp>

3.在统一获取订单编号接口,判断获取的business_type是什么,来找到对应的业务单据接口,调整业务逻辑
    def get_pos_order_no(self, cr, uid, session):
        data = request.json
        # 默认取销售单号
        business_type = data.get('business_type','sale')
        if business_type_item.get(business_type,False):
            # 细分方便后续单号规则拓展
            if business_type == 'sale':
                doc_no = self.pool.get('ir.sequence').get(cr, uid, 'sale.order.seq')
            elif business_type == 'sale_return':
                doc_no = self.pool.get('ir.sequence').get(cr, uid, 'nt.rma.seq')
            elif business_type == 'sale_exchange':
                doc_no = self.pool.get('ir.sequence').get(cr, uid, 'nt.rma.seq')
            elif business_type == 'shop_pick_out':
                doc_no  = self.pool.get('ir.sequence').get(cr, uid, 'nt.shop.pick.seq')
            elif business_type == 'stock_move':
                doc_no = self.pool.get('ir.sequence').get(cr, uid, 'nt.shop.pick.seq')
            elif business_type == 'refund':
                doc_no = self.pool.get('ir.sequence').get(cr, uid, 'nt.shop.pick.seq')
            elif business_type == 'inventory':
                doc_no = self.pool.get('ir.sequence').get(cr, uid, 'nt.stock.inventory.plan.seq')
            elif business_type == 'scrap':
                doc_no = self.pool.get('ir.sequence').get(cr, uid, 'nt.shop.scrap.seq')
            elif business_type == 'reload':
                doc_no = self.pool.get('ir.sequence').get(cr, uid, 'nt.shop.reload.seq')
            self.pool.get('nt.doc.no')._set_doc_no(cr, uid, doc_no, business_type_item[business_type])
            return doc_no
        else:
            #无效的请求业务类型
            raise_error(error.ERROR_INVALID_BUSINESS_TYPE)
4.调拨单接口增加业务逻辑/api/v6/shop/pick/update/post,获取调拨单号,查doc_no表中是否存在,如果不存在,直接报错
    def upload_pick(pool, cr, uid, session):
        data = request.json
        pick_id = data.get('pick_id', False)
        pick_no = data.get('pick_no','')
        shop_id = session['shop_id']
        if shop_id:
            key = pick_id and '%s_%s'%(str(shop_id),str(pick_id)) or str(shop_id)
            flag = helper.concurrnt_control(key, 3, 'PICK_UPDATE')
            if flag != 1:
                raise_error(error.ERROR_ORDER_PROCESSING, (u'更新',))
        pick_obj = pool.get('nt.shop.pick')
        self_instance = pool.get('nt.pos.api')
        action_type = data.get('type','')
        #若有调拨单号而没有id的话
        if pick_no and not pick_id:
            #查询doc_no,如果没有,则报错(请确认单号是否有效)
            if not pool.get('nt.doc.no')._get_doc_no(cr, uid, pick_no, business_type_item.get(action_type,1)):
                raise_error(WARNING_INVALID_DOC_NO)
5.另外两个接口调整相同逻辑即可。下次创建和更新单据时,都会去doc_no表中查看订单是否存在,如果存在就走创建和更新的方法,如果不存在就raise无效单据。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值