# -*- encoding: utf8 -*-
import sys
import datetime
import pandas as pd
from sqlalchemy import create_engine
from dateutil.relativedelta import relativedelta
import numpy as np
from itertools import product

reload(sys)
sys.setdefaultencoding("utf-8")
pd.options.mode.chained_assignment = None

'''
@author linfang
计算去哪儿的在贷明细
product_no 的明细
包括观察点时的在贷和观察点之后的贷后表现
其中需要剔除 loan_amount > 0 & 剩余 < 0 的情况---这些是因为 还款计划拆分的问题造成的。
16年0930 的版本以这个为准
'''

engine_qunaer = create_engine('mysql+mysqldb://internal_r:ArbNgtvlJzZHXsEu@172.16.3.201:3306/qunaer_new?charset=utf8',echo=False)

file_path =  u'E:/审计出表/去哪儿-在贷/在贷明细表/'
file_name = u'去哪儿-在贷-明细'
max_limit = 800000
#这个只需要执行一次即可

sql_trans='''
select product_no,trans_no from qunaer_new.trans_ref 
'''
df_trans=pd.read_sql(sql_trans,engine_qunaer)

def qunaer_zaidai(listen_time,watch_time,user_plan_2016,user_plan_2017):

	#is_ptf和trans_ref是否一致
	sql_loan='''
	select product_no,date(loan_time) loan_time,  IF(is_ptf=0,loan_amount,0) loan_amount
	from qunaer_new.pay_detail
	where loan_time < '%s' AND fund_code = 1 
	''' % listen_time

	sql_loan_2='''
	select product_no,date(loan_time) loan_time,loan_amount 
	from qunaer_new.baoli_pay_detail 
	WHERE trans_time < '%s'
	''' % listen_time

	sql_pre_refund='''
	select product_no,-sum(refund_principle) pre_refund_principle from 
	qunaer_new.refund_detail
	where refund_time < '%s' AND fund_code=1 AND flow_id is NULL 
	GROUP by 1
	''' % listen_time

	sql_pre_repay='''
	select product_no,sum(repay_principle)  pre_repay_principle from 
	qunaer_new.repay_detail
	where repay_time < '%s' AND fund_code = 1
	GROUP by 1
	''' % listen_time

	sql_pre_repay2='''
	select product_no,-sum(refund_principle)  pre_repay_principle from 
	qunaer_new.refund_detail
	where refund_time < '%s' AND fund_code = 1 and flow_id is not NULL 
	GROUP by 1
	''' % listen_time

	df_loan=pd.read_sql(sql_loan,engine_qunaer)
	df_loan_1=pd.read_sql(sql_loan_2,engine_qunaer)
	df_loan = pd.concat([df_loan,df_loan_1],ignore_index=True)
	# df_not_loan=pd.read_sql(sql_not_loan,engine_qunaer)
	df_pre_refund=pd.read_sql(sql_pre_refund,engine_qunaer)
	df_pre_repay=pd.read_sql(sql_pre_repay,engine_qunaer)
	df_pre_repay2=pd.read_sql(sql_pre_repay2,engine_qunaer)
	df_pre_repay = pd.concat([df_pre_repay,df_pre_repay2],ignore_index=True)
	df_pre_repay =  df_pre_repay.groupby('product_no')['pre_repay_principle'].sum().reset_index()

	#剔除发生转分期的订单
	# df_loan=df_loan.ix[~df_loan.product_no.isin(df_not_loan.product_no)]
	df_zaidai=pd.merge(df_loan,df_pre_refund,on='product_no',how='left')
	df_zaidai=pd.merge(df_zaidai,df_pre_repay,on='product_no',how='left')

	df_zaidai.fillna(0,inplace=True)
	df_zaidai['zaidai']=np.round(df_zaidai['loan_amount']-df_zaidai['pre_refund_principle']-df_zaidai['pre_repay_principle'],2)
	# df=df.ix[df['剩余']>=0]
	df_zaidai['new_loan_amount']=df_zaidai['loan_amount']-df_zaidai['pre_refund_principle']
	print(u'当前月份在贷金额为： '+str(df_zaidai['zaidai'].sum()),u'当前月份累计放款金额为： '+str(df_zaidai['new_loan_amount'].sum()))

	sql_trans='''
	select product_no,trans_no from qunaer_new.trans_ref 
	'''
	df_trans=pd.read_sql(sql_trans,engine_qunaer)

	sql_pay='''
	select product_no,stages,date(trans_time) loan_time from qunaer_new.pay_detail where fund_code =1
	'''
	df_pay=pd.read_sql(sql_pay,engine_qunaer)
	sql_baoli_pay='''
	select product_no,stages ,date(loan_time) loan_time from qunaer_new.baoli_pay_detail where fund_code = 1
	'''
	df_pay_baoli=pd.read_sql(sql_baoli_pay,engine_qunaer)
	df_pay=pd.concat([df_pay,df_pay_baoli],ignore_index=True)

	sql_2016='''
	select product_no,date(deadline) deadline ,status from %s
	''' % user_plan_2016
	df_2016=pd.read_sql(sql_2016,engine_qunaer)
	sql_2017='''
	select t1.product_no,date(deadline) deadline,t1.status from %s  t1
	join pay_detail t2 on t1.product_no = t2.product_no 
	where t2.fund_code = 1
	''' % user_plan_2017
	df_2017=pd.read_sql(sql_2017,engine_qunaer)
	sql_baoli='''
	select product_no ,date(deadline) deadline,status from baoli_repayment_plan 
	'''

	df_baoli=pd.read_sql(sql_baoli,engine_qunaer)
	df_plan=pd.concat([df_2016,df_2017,df_baoli],ignore_index=True)
	#===首先提取 status=3 的这部分订单
	df_trans_select=df_trans.ix[df_trans.product_no.isin(df_plan.ix[df_plan.status==3].product_no)]
	# 将在贷中属于转分期的订单进行合并
	df_zaidai=pd.merge(df_zaidai,df_trans_select,on='product_no',how='left')
	df_zaidai.ix[~(df_zaidai.trans_no.isnull()),'product_no']=df_zaidai.ix[~(df_zaidai.trans_no.isnull())]['trans_no']
	# 最终的在贷值和最新的产品编号
	df_zaidai_gp=df_zaidai.groupby('product_no')['zaidai','new_loan_amount'].sum().reset_index()

	print(u'在贷金额为：'+str(df_zaidai_gp['zaidai'].sum()))

	#区分 还款状态为 1 和 2 的情况
	df_plan_status_1=df_plan.ix[df_plan.status == 1]
	df_plan_status_1=df_plan_status_1.ix[df_plan_status_1.product_no.isin(df_zaidai_gp.product_no)]

	df_que=df_zaidai_gp.ix[~df_zaidai_gp.product_no.isin(df_plan_status_1.product_no)]
	fu_amount=df_que['zaidai'].sum()

	print(u'需要处理负数值： '+str(fu_amount))

	#逾期部分处理代码
	df_plan=df_plan_status_1
	df_plan=df_plan[['product_no','deadline']]
	df_plan_gp=df_plan.groupby('product_no')['deadline'].count().reset_index().rename(columns={'deadline':'p_count'})
	df_plan=pd.merge(df_plan,df_plan_gp,on='product_no',how='left')
	df_plan_tmp=pd.merge(df_plan,df_zaidai_gp[['product_no','zaidai','new_loan_amount']],on='product_no',how='left')
	df_plan_tmp['no_pay']=df_plan_tmp[u'zaidai'] / df_plan_tmp['p_count']
	df_plan_tmp.deadline=pd.to_datetime(df_plan_tmp.deadline).dt.date
	df_plan_tmp['date_diff']=df_plan_tmp.deadline.apply(lambda x:(yuqi_time-x).days)
	df_plan_tmp.ix[df_plan_tmp['date_diff'] < 0 ,'date_name'] =u'未到期'
	df_plan_tmp.ix[(df_plan_tmp['date_diff'] >= 0) & (df_plan_tmp['date_diff']  <= 30 ) ,'date_name'] =  u'逾期30天'
	df_plan_tmp.ix[(df_plan_tmp['date_diff'] > 30) ,'date_name'] = u'逾期30天上'
	# df_plan_tmp=pd.merge(df_plan_tmp,df_pay,on='product_no',how='left')
	# df_zaidai_gp_new=pd.merge(df_zaidai_gp[['product_no']],df_zaidai[['product_no','loan_time']],on='product_no',how='left')
	# df_zaidai_gp_new.drop_duplicates('product_no',inplace=True)
	df_plan_tmp = pd.merge(df_plan_tmp,df_pay[['product_no','loan_time','stages']],on='product_no',how='left')
	df_plan_tmp.deadline=pd.to_datetime(df_plan_tmp.deadline).dt.date
	df_plan_tmp.drop_duplicates(['product_no','deadline'],inplace=True)
	df_plan_tmp.loan_time=pd.to_datetime(df_plan_tmp.loan_time).dt.date

	#调账的负数
	df_plan_tmp_fu=df_plan_tmp.ix[df_plan_tmp['no_pay'] < 0]
	df_plan_tmp=df_plan_tmp.ix[df_plan_tmp['no_pay'] >= 0]
	fu_amount+=df_plan_tmp_fu['no_pay'].sum()

	print(u'给财务的调账金额： '+str(fu_amount))

	df_plan_tmp['loan_year']=df_plan_tmp.loan_time.apply(lambda x:x.year)
	df_plan_tmp['loan_month']=df_plan_tmp.loan_time.apply(lambda x:x.month)
	df_plan_tmp['deadline_year']=df_plan_tmp.deadline.apply(lambda x:x.year)
	df_plan_tmp['deadline_month']=df_plan_tmp.deadline.apply(lambda x:x.month)

	#=====汇总输出========
	df_out=df_plan_tmp.groupby(['loan_year','loan_month','deadline_year','deadline_month','date_name'])['no_pay'].sum().reset_index()
	df_out.to_excel(file_path+u'去哪儿-在贷-汇总-20170630-最终版.xlsx')

	print(u'在贷明细中订单金额为0行数：'+str(len(df_plan_tmp.ix[df_plan_tmp.new_loan_amount < 0])))

	df_plan_tmp.ix[df_plan_tmp[['product_no','deadline']].duplicated(),'new_loan_amount']=0

	df_plan_tmp=df_plan_tmp[['product_no','deadline','new_loan_amount','no_pay','loan_time','stages']]
	# 缺少 调账的订单编号
	df_que['no_pay']=0
	df_plan_tmp_fu['no_pay']=0
	df_tiaozheng=pd.concat([df_que[['product_no','no_pay']],df_plan_tmp_fu[['product_no','no_pay']]],ignore_index=True)
	df_tiaozheng=pd.merge(df_tiaozheng,df_zaidai_gp[['product_no','new_loan_amount']],how='left')
	#=== 如果 new_loan_amount 为负数没有处理
	df_tiaozheng=pd.merge(df_tiaozheng,df_pay[['product_no','loan_time','stages']],how='left')

	df_plan_tmp=pd.concat([df_plan_tmp,df_tiaozheng],ignore_index=True)
	df_plan_tmp.rename(columns = {'product_no':u'产品编号','no_pay':u'未还本金','new_loan_amount':u'订单金额','loan_time':u'贷款时间',\
								  u'stages':u'期数'},inplace=True)
	if len(df_plan_tmp)>max_limit:
		for i in xrange(0,len(df_plan_tmp),max_limit):
			df_plan_tmp[i:i+max_limit].to_csv(file_path+u'%s(%s-%02d)-%d' %(file_name,watch_time.year,watch_time.month,i/max_limit+1),\
											  index=None,encoding='gb18030')

if __name__ == '__main__':

	years= [2017]
	months = [3,6,9]
	# 配置部分代码 --- >注意修改观察点例如出 Q1的截止时间为 3月31日，则 month = 3

	for year,month in product(years,months):
		print(str(year),str(month),'  begins-------')
		#两个用户还款计划的配置，如果跑2016年的，则修改一下，删除 user_plan_2017
		user_plan_2016 = 'repayment_plan_2016_20170' + str(month)
		user_plan_2017 = 'repayment_plan_20170' + str(month)

		#设置是否逾期的观察点，month = 3 对应观察点 是 3月31日
		yuqi_time = datetime.date(year, month+1, 1) + relativedelta(days=-1)
		listen_time = datetime.datetime(year, month + 1, 1, 0, 0, 0)

		qunaer_zaidai(listen_time,yuqi_time,user_plan_2016,user_plan_2017)
		print(str(year),str(month),   'ends--------')