解决重复业务单据
背景:
单个设备在没有业务唯一标识的情况创建业务单据时因网络原因出现异常,服务器接口其实已经正常接收,间隔一定时间后重新保存会出现重复单据
待调整的内容:
涉及到创建的单据有:调拨出库,配货退货,补货申请,库存损溢
在创建单据前根据统一接口(/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 loggingfrom 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_iddef _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
<openerp><data><record model="ir.ui.view" id="nt_doc_no_tree_view"><field name="name">nt.doc.no.tree.viewfield><field name="model">nt.doc.nofield><field name="type">treefield><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_windowfield><field name="res_model">nt.doc.nofield><field name="view_type">formfield><field name="view_mode">treefield><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_noelse:#无效的请求业务类型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.jsonpick_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无效单据。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
