Add retry mechanism for build_sales_order

If error happens when adding quotation, cancel that quotation
automatically, and do some retries.

Change-Id: I142382094d12ff8000500dc7a9f4d3c638bd3984
This commit is contained in:
Lingxian Kong 2016-02-11 16:10:32 +13:00
parent 7dff9372b4
commit 87797d4aa9
2 changed files with 50 additions and 31 deletions

View File

@ -29,11 +29,13 @@ import sys
import time import time
import traceback import traceback
from distilclient.client import Client as DistilClient
from keystoneclient.v2_0 import client as keystone_client from keystoneclient.v2_0 import client as keystone_client
import odoorpc import odoorpc
from oslo_utils import importutils from oslo_utils import importutils
from oslo_utils import strutils from oslo_utils import strutils
from retrying import retry
from distilclient.client import Client as DistilClient
TENANT = collections.namedtuple('Tenant', ['id', 'name']) TENANT = collections.namedtuple('Tenant', ['id', 'name'])
@ -299,7 +301,6 @@ def do_quote(shell, args):
print "Failed to create sales order for tenant: %s" % tenant.name print "Failed to create sales order for tenant: %s" % tenant.name
with open('failed_tenants.txt', 'a') as f: with open('failed_tenants.txt', 'a') as f:
f.write(tenant.id + "\n") f.write(tenant.id + "\n")
print('To cancel use order id: %s' % shell.order_id)
raise e raise e
with open('done_tenants.txt', 'a') as f: with open('done_tenants.txt', 'a') as f:
@ -486,6 +487,7 @@ def get_price(shell, pricelist, product, volume):
return price if volume >= 0 else -price return price if volume >= 0 else -price
@retry(stop_max_attempt_number=3, wait_fixed=1000)
def build_sales_order(shell, args, pricelist, usage, partner, tenant_name, def build_sales_order(shell, args, pricelist, usage, partner, tenant_name,
tenant_id): tenant_id):
end_timestamp = datetime.datetime.strptime(args.END, '%Y-%m-%dT%H:%M:%S') end_timestamp = datetime.datetime.strptime(args.END, '%Y-%m-%dT%H:%M:%S')
@ -502,14 +504,15 @@ def build_sales_order(shell, args, pricelist, usage, partner, tenant_name,
log(shell.debug, 'Building sale.order') log(shell.debug, 'Building sale.order')
try: try:
order_dict = {'partner_id': partner['id'], order_dict = {
'pricelist_id': pricelist, 'partner_id': partner['id'],
'partner_invoice_id': partner['id'], 'pricelist_id': pricelist,
'partner_shipping_id': partner['id'], 'partner_invoice_id': partner['id'],
'order_date': billing_date, 'partner_shipping_id': partner['id'],
'note': 'Tenant: %s (%s)' % (tenant_name, tenant_id), 'order_date': billing_date,
'section_id': 10, 'note': 'Tenant: %s (%s)' % (tenant_name, tenant_id),
} 'section_id': 10,
}
order = 'DRY_RUN_MODE' order = 'DRY_RUN_MODE'
print_dict(order_dict) print_dict(order_dict)
@ -524,14 +527,14 @@ def build_sales_order(shell, args, pricelist, usage, partner, tenant_name,
prod = find_oerp_product(shell, m['region'], m['product']) prod = find_oerp_product(shell, m['region'], m['product'])
# TODO(flwang): 1. select the correct unit; 2. map via position # TODO(flwang): 1. select the correct unit; 2. map via position
usage_dict = {'order_id': order, usage_dict = {
'product_id': prod['id'], 'order_id': order,
'product_uom': prod['uom_id'][0], 'product_id': prod['id'],
'product_uom_qty': math.fabs(m['volume']), 'product_uom': prod['uom_id'][0],
'name': m['name'], 'product_uom_qty': math.fabs(m['volume']),
'price_unit': get_price(shell, pricelist, 'name': m['name'],
prod, m['volume']) 'price_unit': get_price(shell, pricelist, prod, m['volume'])
} }
if usage_dict['product_uom_qty'] < 0.005: if usage_dict['product_uom_qty'] < 0.005:
# Odoo will round the product_uom_qty and if it's under 0.0005 # Odoo will round the product_uom_qty and if it's under 0.0005
# then it would be rounded to 0 and as a result the quoting # then it would be rounded to 0 and as a result the quoting
@ -544,13 +547,24 @@ def build_sales_order(shell, args, pricelist, usage, partner, tenant_name,
if not args.DRY_RUN: if not args.DRY_RUN:
shell.Orderline.create(usage_dict) shell.Orderline.create(usage_dict)
print_list(usage_dict_list, ['product_id', 'product_uom', print_list(
'product_uom_qty', 'name', 'price_unit']) usage_dict_list,
['product_id', 'product_uom', 'product_uom_qty', 'name',
'price_unit']
)
shell.order_id = None
except odoorpc.error.RPCError as e: except odoorpc.error.RPCError as e:
exc_type, exc_value, exc_traceback = sys.exc_info() exc_type, exc_value, exc_traceback = sys.exc_info()
traceback.print_exception(exc_type, exc_value, exc_traceback, traceback.print_exception(exc_type, exc_value, exc_traceback,
limit=2, file=sys.stdout) limit=2, file=sys.stdout)
print(e.info) print(e.info)
# Cancel the quotation.
if shell.order_id:
print('Cancel order: %s' % shell.order_id)
update_order_status(shell, shell.order_id)
raise e raise e
except Exception as e: except Exception as e:
exc_type, exc_value, exc_traceback = sys.exc_info() exc_type, exc_value, exc_traceback = sys.exc_info()
@ -621,6 +635,20 @@ def check_duplicate(order):
return False return False
def update_order_status(shell, order_id, new_status='cancel'):
print('Processing order: %s' % order_id)
order = shell.Order.browse(order_id)
# Just a placeholder for further improvement.
is_dup = check_duplicate(order)
if not is_dup:
print "changing state: %s -> %s" % (order.state, new_status)
# By default when updating values of a record, the change is
# automatically sent to the server.
order.state = new_status
@arg('--new-status', '-s', type=str, metavar='STATUS', @arg('--new-status', '-s', type=str, metavar='STATUS',
dest='STATUS', required=True, dest='STATUS', required=True,
choices=['manual', 'cancel', 'draft'], choices=['manual', 'cancel', 'draft'],
@ -653,17 +681,7 @@ def do_update_quote(shell, args):
ids = shell.Order.search(creterion) ids = shell.Order.search(creterion)
for id in ids: for id in ids:
try: try:
print('Processing order: %s' % id) update_order_status(shell, id, args.STATUS)
order = shell.Order.browse(id)
# Just a placeholder for further improvement.
is_dup = check_duplicate(order)
if not is_dup:
print "changing state: %s -> %s" % (order.state, args.STATUS)
# By default when updating values of a record, the change is
# automatically sent to the server.
order.state = args.STATUS
except odoorpc.error.RPCError as e: except odoorpc.error.RPCError as e:
exc_type, exc_value, exc_traceback = sys.exc_info() exc_type, exc_value, exc_traceback = sys.exc_info()
traceback.print_exception(exc_type, exc_value, exc_traceback, traceback.print_exception(exc_type, exc_value, exc_traceback,

View File

@ -1,3 +1,4 @@
argparse==1.2.1 argparse==1.2.1
odoorpc==0.4.2 odoorpc==0.4.2
retrying>=1.3.3
wsgiref==0.1.2 wsgiref==0.1.2