#!/usr/bin/env python
# encoding: utf-8
"""
logistics.py
Created by 徐 光硕 on 2011-11-18.
Copyright (c) 2011 __MyCompanyName__. All rights reserved.
"""
from api import TOP, TOPRequest, TOPDate
from user import Location
from trade import Task, Subtask
[docs]class TransitStepInfo(TOP):
'''物流跟踪信息的一条'''
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(TransitStepInfo, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.models = {'status_time':TOPDate}
self.fields = ['status_time','status_desc']
[docs]class Area(TOP):
'''地址区域结构'''
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(Area, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.fields = ['id','type', 'name', 'parent_id', 'zip']
class Areas(TOP):
'''地址区域结构'''
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(Areas, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.models = {'areas':Area}
self.fields = ['areas',]
def get(self, fields=[]):
'''taobao.areas.get 查询地址区域
查询标准地址区域代码信息 参考:http://www.stats.gov.cn/tjbz/xzqhdm/t20100623_402652267.htm'''
request = TOPRequest('taobao.areas.get')
if not fields:
area = Area()
fields = area.fields
request['fields'] = fields
self.create(self.execute(request))
return self.areas
[docs]class DeliveryTemplate(TOP):
'''运费模板对象'''
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(DeliveryTemplate, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.models = {'fee_list':TopFee}
self.fields = ['template_id','name', 'assumer', 'valuation', 'fee_list', 'supports', 'created', 'modified']
[docs] def add(self, name, assumer, valuation, template_types, template_dests, template_start_standards, template_start_fees, template_add_standards, template_add_fees, session):
'''taobao.delivery.template.add 新增运费模板
新增运费模板'''
request = TOPRequest('taobao.delivery.template.add')
request['name'] = name
request['assumer'] = assumer
request['valuation'] = valuation
request['template_types'] = template_types
request['template_dests'] = template_dests
request['template_start_standards'] = template_start_standards
request['template_start_fees'] = template_start_fees
request['template_add_standards'] = template_add_standards
request['template_add_fees'] = template_add_fees
self.create(self.execute(request, session)['delivery_template'])
return self
[docs] def delete(self, template_id, session):
'''taobao.delivery.template.delete 删除运费模板
根据用户指定的模板ID删除指定的模板'''
request = TOPRequest('taobao.delivery.template.delete')
request['template_id'] = template_id
self.create(self.execute(request, session), fields=['complete', ])
return self.complete
[docs] def get(self, template_ids, session, fields=[]):
'''taobao.delivery.template.get 获取用户指定运费模板信息
获取用户指定运费模板信息'''
request = TOPRequest('taobao.delivery.template.get')
request['template_ids'] = template_ids
if not fields:
fields = self.fields
request['fields'] = fields
self.create(self.execute(request, session), fields=['delivery_templates', 'total_results'], models={'delivery_templates':DeliveryTemplate})
return self.delivery_templates
[docs] def update(self, template_id, assumer, template_types, template_dests, template_start_standards, template_start_fees, template_add_standards, template_add_fees, session, name=None):
'''taobao.delivery.template.update 修改运费模板
修改运费模板'''
request = TOPRequest('taobao.delivery.template.update')
if name!=None: request['name'] = name
request['assumer'] = assumer
request['template_id'] = template_id
request['template_types'] = template_types
request['template_dests'] = template_dests
request['template_start_standards'] = template_start_standards
request['template_start_fees'] = template_start_fees
request['template_add_standards'] = template_add_standards
request['template_add_fees'] = template_add_fees
self.create(self.execute(request, session), fields=['complete', ])
return self.complete
[docs]class DeliveryTemplates(TOP):
'''运费模板对象'''
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(DeliveryTemplates, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.models = {'delivery_templates':DeliveryTemplate}
self.fields = ['delivery_templates','total_results']
[docs] def get(self, session):
'''taobao.delivery.templates.get 获取用户下所有模板
根据用户ID获取用户下所有模板'''
request = TOPRequest('taobao.delivery.templates.get')
self.create(self.execute(request, session))
return self.delivery_templates
[docs]class PartnerDetail(TOP):
'''物流公司详细信息'''
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(PartnerDetail, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.fields = ['account_no','company_code', 'company_id', 'full_name', 'company_name', 'wangwang_id', 'reg_mail_no']
[docs]class LogisticsCompany(TOP):
'''物流公司基础数据结构'''
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(LogisticsCompany, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.fields = ['id','code', 'name', 'reg_mail_no']
[docs]class LogisticsCompanies(TOP):
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(LogisticsCompanies, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.models = {'logistics_companies':LogisticsCompany}
self.fields = ['logistics_companies',]
[docs] def get(self, session, is_recommended=None, order_mode=None, fields=[]):
'''taobao.logistics.companies.get 查询物流公司信息
查询淘宝网合作的物流公司信息,用于发货接口。'''
request = TOPRequest('taobao.logistics.companies.get')
if not fields:
lc = LogisticsCompany()
fields = lc.fields
request['fields'] = fields
if is_recommended!=None: request['is_recommended'] = is_recommended
if order_mode!=None: request['order_mode'] = order_mode
self.create(self.execute(request, session))
return self.logistics_companies
[docs]class PostageMode(TOP):
'''运费方式模板收费方式'''
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(PostageMode, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.fields = ['postage_id','id', 'type', 'dests', 'price', 'increase']
[docs]class Shipping(TOP):
'''物流数据结构'''
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(Shipping, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.models ={'delivery_start':TOPDate, 'delivery_end':TOPDate, 'location':Location, 'created':TOPDate, 'modified':TOPDate}
self.fields = ['tid','order_code', 'seller_nick', 'buyer_nick', 'delivery_start', 'delivery_end', 'out_sid', 'item_title', 'receiver_name', 'receiver_phone', 'receiver_mobile', 'location', 'status', 'type', 'freight_payer', 'seller_confirm', 'company_name', 'is_success', 'created', 'modified']
[docs]class TopFee(TOP):
'''运费模板中运费信息对象'''
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(TopFee, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.fields = ['service_type','destination', 'start_standard', 'start_fee', 'add_standard', 'add_fee']
[docs]class Postage(TOP):
'''运费模板结构'''
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(Postage, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.models ={'postage_modes':PostageMode, 'created':TOPDate, 'modified':TOPDate}
self.fields = ['postage_id','name', 'memo', 'created', 'modified', 'post_price', 'post_increase', 'express_price', 'express_increase', 'ems_price', 'ems_increase', 'postage_modes']
[docs] def add(self, name, session, **kwargs):
'''taobao.postage.add 添加邮费模板
添加邮费模板
新增的邮费模板属于当前会话用户
postage_mode_types、postage_mode_dests、postage_mode_prices、 postage_mode_increases四个字段组合起来表示邮费的子模板列表。每个邮费子模板都包含了type(邮费类型,有post、 express、ems可以选择)、dest(邮费模板应用地区,每个模板可以使用于多个地区,每个地区填入他的代码,地区与地区之间用半角逗号分隔)、 price(邮费基价)、increment(邮费增价)四个部分。如果有多个子模板,则将他们的4个部分分别组合,之间用半角分号隔开(注意每个模板的每个部分的位置要一样。即,子模板1号的type、dest、price、increment都要排在这四个参数的第一位;子模板2号要排在第二位……以此类推)'''
request = TOPRequest('taobao.postage.add')
request['name'] = name
for k, v in kwargs.iteritems():
if k not in ('post_price', 'post_increase', 'express_price', 'express_increase', 'ems_price', 'ems_increase', 'memo', 'postage_mode_types', 'postage_mode_dests', 'postage_mode_prices', 'postage_mode_increases') and v==None: continue
request[k] = v
self.create(self.execute(request, session)['postage'])
return self
[docs] def delete(self, postage_id, session):
'''taobao.postage.delete 删除单个运费模板
删除单个邮费模板 postage_id对应的邮费模板要属于当前会话用户'''
request = TOPRequest('taobao.postage.delete')
request['postage_id'] = postage_id
self.create(self.execute(request, session)['postage'])
return self
[docs] def get(self, postage_id, nick, fields=[]):
'''taobao.postage.get 获取单个运费模板
获取单个邮费模板
postage_id对应的邮费模板要属于nick所对应的用户
- Q:是否必须是模板所有者才能够使用这个接口?
- A: 不是的,只要给出了邮费模板id和创建者的昵称就可以使用'''
request = TOPRequest('taobao.postage.get')
request['postage_id'] = postage_id
request['nick'] = nick
if not fields:
fields = self.fields
request['fields'] = fields
self.create(self.execute(request)['postage'])
return self
[docs] def update(self, postage_id, session, **kwargs):
'''taobao.postage.update 修改邮费模板
- 修改邮费模板
- 修改的邮费模板属于当前会话用户
- 修改的邮费子模板要传入子模板id,否则作为添加子模板处理。postage_mode_types、 postage_mode_dests、postage_mode_prices、postage_mode_increases四个字段的处理逻辑见 taobao.postage.add中的描述'''
request = TOPRequest('taobao.postage.update')
request['postage_id'] = postage_id
for k, v in kwargs.iteritems():
if k not in ('post_price', 'post_increase', 'express_price', 'express_increase', 'ems_price', 'ems_increase', 'name', 'memo', 'postage_mode_ids', 'postage_mode_types', 'postage_mode_dests', 'postage_mode_prices', 'postage_mode_increases', 'postage_mode_optTypes', 'remove_post', 'remove_express', 'remove_ems') and v==None: continue
request[k] = v
self.create(self.execute(request, session)['postage'])
return self
[docs]class Postages(TOP):
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(Postages, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.models ={'postages':Postage}
self.fields = ['postages','total_results']
[docs] def get(self, session, fields=[]):
'''taobao.postages.get 获取卖家的运费模板
获得当前会话用户的所有邮费模板'''
request = TOPRequest('taobao.postages.get')
if not fields:
postage = Postage()
fields = postage.fields
request['fields'] = fields
self.create(self.execute(request, session))
return self.postages
[docs]class AddressResult(TOP):
'''地址库返回数据信息'''
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(AddressResult, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.models ={'modify_date':TOPDate}
self.fields = ['postage_id','contact_name', 'province', 'city', 'country', 'addr', 'zip_code', 'phone', 'mobile_phone', 'seller_company', 'memo', 'area_id', 'send_def', 'get_def', 'cancel_def', 'modify_date']
[docs]class LogisticsPartner(TOP):
'''查询揽送范围之内的物流公司信息'''
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(LogisticsPartner, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.models ={'partner':ParnterDetail}
self.fields = ['cover_remark','uncover_remark', 'partner']
[docs]class LogisticsPartners(TOP):
'''查询揽送范围之内的物流公司信息'''
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(LogisticsPartners, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.models ={'logistics_partners':LogisticsPartner}
self.fields = ['logistics_partners',]
[docs] def get(self, service_type, source_id=None, target_id=None, goods_value=None):
'''taobao.logistics.partners.get 查询支持起始地到目的地范围的物流公司
查询物流公司信息(可以查询目的地可不可达情况)'''
request = TOPRequest('taobao.logistics.partners.get')
request['service_type'] = service_type
if source_id!=None: request['source_id'] = source_id
if target_id!=None: request['target_id'] = target_id
if goods_value!=None: request['goods_value'] = goods_value
self.create(self.execute(request))
return self.logistics_partners
[docs]class LogisticsAddress(TOP):
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(LogisticsAddress, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.models = {'address_result':AddressResult}
self.fields = ['address_result',]
[docs] def add(self, contact_name, province, city, addr, session, **kwargs):
'''taobao.logistics.address.add 卖家地址库新增接口
通过此接口新增卖家地址库,卖家最多可添加5条地址库,新增第一条卖家地址,将会自动设为默认地址库'''
request = TOPRequest('taobao.logistics.address.add')
request['contact_name'] = contact_name
request['province'] = province
request['city'] = city
request['addr'] = addr
for k, v in kwargs.iteritems():
if k not in ('country', 'zip_code', 'phone', 'mobile_phone', 'seller_company', 'memo', 'get_def', 'cancel_def') and v==None: continue
request[k] = v
self.create(self.execute(request, session))
return self.address_result
[docs] def modify(self, contact_id, contact_name, province, city, addr, session, **kwargs):
'''taobao.logistics.address.modify 卖家地址库修改
卖家地址库修改'''
request = TOPRequest('taobao.logistics.address.modify')
request['contact_id'] = contact_id
request['contact_name'] = contact_name
request['province'] = province
request['city'] = city
request['addr'] = addr
for k, v in kwargs.iteritems():
if k not in ('country', 'zip_code', 'phone', 'mobile_phone', 'seller_company', 'memo', 'get_def', 'cancel_def') and v==None: continue
request[k] = v
self.create(self.execute(request, session))
return self.address_result
[docs] def remove(self, contact_id, session):
'''taobao.logistics.address.remove 删除卖家地址库
用此接口删除卖家地址库'''
request = TOPRequest('taobao.logistics.address.remove')
request['contact_id'] = contact_id
self.create(self.execute(request, session))
return self.address_result
[docs] def search(self, session, rdef=None):
'''taobao.logistics.address.search 查询卖家地址库
通过此接口查询卖家地址库,'''
request = TOPRequest('taobao.logistics.address.search')
if rdef!=None: request['rdef'] = rdef
self.create(self.execute(request, session), fields=['addresses', ], models={'addresses':AddressResult})
return self.addresses
[docs]class LogisticsDummy(TOP):
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(LogisticsDummy, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.models = {'shipping':Shipping}
self.fields = ['shipping',]
[docs] def send(self, tid, session, feature=None):
'''taobao.logistics.dummy.send 无需物流(虚拟)发货处理
用户调用该接口可实现无需物流(虚拟)发货,使用该接口发货,交易订单状态会直接变成卖家已发货'''
request = TOPRequest('taobao.logistics.dummy.send')
request['tid'] = tid
if feature!=None: request['feature'] = feature
self.create(self.execute(request, session))
return self.shipping
[docs]class LogisticsOffline(TOP):
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(LogisticsOffline, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.models = {'shipping':Shipping}
self.fields = ['shipping',]
[docs] def send(self, tid, out_sid, company_code, session, sender_id=None, cancel_id=None, feature=None):
'''taobao.logistics.offline.send 自己联系物流(线下物流)发货
用户调用该接口可实现自己联系发货(线下物流),使用该接口发货,交易订单状态会直接变成卖家已发货。不支持货到付款、在线下单类型的订单。'''
request = TOPRequest('taobao.logistics.offline.send')
request['tid'] = tid
request['out_sid'] = out_sid
request['company_code'] = company_code
if feature!=None: request['feature'] = feature
if sender_id!=None: request['sender_id'] = sender_id
if cancel_id!=None: request['cancel_id'] = cancel_id
self.create(self.execute(request, session))
return self.shipping
[docs]class LogisticsOnline(TOP):
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(LogisticsOnline, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
[docs] def cancel(self, tid, session):
'''taobao.logistics.online.cancel 取消物流订单接口
调此接口取消发货的订单,重新选择物流公司发货。前提是物流公司未揽收货物。对未发货和已经被物流公司揽收的物流订单,是不能取消的。'''
request = TOPRequest('taobao.logistics.online.cancel')
request['tid'] = tid
self.create(self.execute(request, session), fields = ['is_success','modify_time','recreated_order_id'], models = {'modify_time':TOPDate})
return self
[docs] def confirm(self, tid, out_sid, session):
'''taobao.logistics.online.confirm 确认发货通知接口
确认发货的目的是让交易流程继承走下去,确认发货后交易状态会由【买家已付款】变为【卖家已发货】,然后买家才可以确认收货,货款打入卖家账号。货到付款的订单除外'''
request = TOPRequest('taobao.logistics.online.confirm')
request['tid'] = tid
request['out_sid'] = out_sid
self.create(self.execute(request, session), fields = ['shipping',], models = {'shipping':Shipping})
return self.shipping
[docs] def send(self, tid, company_code, session, **kwargs):
'''taobao.logistics.online.send 在线订单发货处理(支持货到付款)
- 用户调用该接口可实现在线订单发货(支持货到付款)
- 调用该接口实现在线下单发货,有两种情况:
- 如果不输入运单号的情况:交易状态不会改变,需要调用taobao.logistics.online.confirm确认发货后交易状态才会变成卖家已发货。
- 如果输入运单号的情况发货:交易订单状态会直接变成卖家已发货 。'''
request = TOPRequest('taobao.logistics.online.send')
request['tid'] = tid
request['company_code'] = company_code
for k, v in kwargs.iteritems():
if k not in ('out_sid', 'sender_id', 'cancel_id', 'feature') and v==None: continue
request[k] = v
self.create(self.execute(request, session), fields=['shipping', ], models={'shipping':Shipping})
return self.shipping
[docs]class Orders(TOP):
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(Orders, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.models = {'shippings':Shipping}
self.fields = ['shippings', 'total_results']
[docs] def detail_get(self, session, fields=[], **kwargs):
'''taobao.logistics.orders.detail.get 批量查询物流订单,返回详细信息
查询物流订单的详细信息,涉及用户隐私字段。(注:该API主要是提供给卖家查询物流订单使用,买家查询物流订单,建议使用taobao.logistics.trace.search)'''
request = TOPRequest('taobao.logistics.orders.detail.get')
if not fields:
shipping = Shipping()
fields = shipping.fields
request['fields'] = fields
for k, v in kwargs.iteritems():
if k not in ('tid', 'buyer_nick', 'status', 'seller_confirm', 'receiver_name', 'start_created', 'end_created', 'freight_payer', 'type', 'page_no', 'page_size') and v==None: continue
request[k] = v
self.create(self.execute(request, session))
return self.shippings
[docs] def get(self, session, fields=[], **kwargs):
'''taobao.logistics.orders.get 批量查询物流订单
批量查询物流订单。(注:该API主要是提供给卖家查询物流订单使用,买家查询物流订单,建议使用taobao.logistics.trace.search)'''
request = TOPRequest('taobao.logistics.orders.get')
if not fields:
shipping = Shipping()
fields = shipping.fields
request['fields'] = fields
for k, v in kwargs.iteritems():
if k not in ('tid', 'buyer_nick', 'status', 'seller_confirm', 'receiver_name', 'start_created', 'end_created', 'freight_payer', 'type', 'page_no', 'page_size') and v==None: continue
request[k] = v
self.create(self.execute(request, session))
return self.shippings
[docs]class LogisticsTrace(TOP):
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(LogisticsTrace, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.models = {'trace_list':TransitStepInfo}
self.fields = ['out_sid','company_name','tid','status','trace_list']
[docs] def search(self, tid, seller_nick):
'''taobao.logistics.trace.search 物流流转信息查询
用户根据淘宝交易号查询物流流转信息,如2010-8-10 15:23:00到达杭州集散地'''
request = TOPRequest('taobao.logistics.address.add')
request['tid'] = tid
request['seller_nick'] = seller_nick
self.create(self.execute(request))
return self
[docs]class TopatsDelivery(TOP):
'''运费模板结构'''
def __init__(self, API_KEY=None, APP_SECRET=None, ENVIRONMENT='sandbox'):
super(TopatsDelivery, self).__init__( API_KEY, APP_SECRET, ENVIRONMENT )
self.models ={'task':Task}
self.fields = ['task',]
[docs] def send(self, tids, session, **kwargs):
'''taobao.topats.delivery.send 异步批量物流发货api
使用指南:http://open.taobao.com/dev/index.php/ATS%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97
- 1.提供异步批量物流发货功能
- 2.一次最多发货40个订单
- 3.提交任务会进行初步任务校验,如果成功会返回任务号和创建时间,如果失败就报错
- 4.可以接收淘宝发出的任务完成消息,也可以过一段时间来取结果。获取结果接口为taobao.topats.result.get
- 5.此api执行完成发送的通知消息格式为{"task":{"task_id":123456,"created":"2010-8-19"}}'''
request = TOPRequest('taobao.postage.add')
request['tids'] = tids
for k, v in kwargs.iteritems():
if k not in ('company_codes', 'out_sids', 'seller_name', 'seller_area_id', 'seller_address', 'seller_zip', 'seller_phone', 'seller_mobile', 'order_types', 'memos') and v==None: continue
request[k] = v
self.create(self.execute(request, session))
return self.task