# -*- encoding: utf8 -*-
import sys
import os
import datetime
import numpy as np
import pandas as pd
from sqlalchemy import create_engine
from dateutil.relativedelta import relativedelta
reload(sys)
sys.setdefaultencoding("utf-8")
pd.options.mode.chained_assignment = None
# 去哪儿源文件
path = u'E:/量化派/去哪儿/去哪儿账单文件/201708'

'''
@author linfang
惠金所模式：
所有放款期数=1期，没有转分期，如果发生提前还款，则全额结算给惠金所；如果发生退款，则全额结算给惠金所
其他则都是到期日 结算，故中间有保理买惠金所的剩余债权（提前部分退款或者提前部分还款）
1、针对 资金方还款表中提取提前结算的数据
2、更新 退款表中的资金方，更新还款表中的资金方
3、打包时间 > 退款时间的规则进行筛选
4、生成债转表中的放款表
5、生成债转表中的还款计划
'''
engine_qunaer = create_engine('mysql+mysqldb://yulong:ohVU1nPITynSZwR2@172.16.3.201:3306/qunaer_new?charset=utf8', echo=False).connect()


# 提取提前结算数据
def step_1(year,month):
    start_time=datetime.date(year,month,1)
    end_time = start_time + relativedelta(months=+1)
    sql_1 = '''
    select fund_code,product_no,repay_amount,package_time,repay_time fund_repay_time from qunaer_new.fund_repay_detail 
    where repay_time >= '%s' and repay_time < '%s' and fund_code = 2 and type in (5,7)
    ''' % (start_time,end_time)
    df=pd.read_sql(sql_1,engine_qunaer)
    df['package_time']=pd.to_datetime(df['package_time']).dt.date
    #惠金所的每日下午15点开始到次日下午15点作为一天
    df['package_time']=df['package_time'].apply(lambda x:x+relativedelta(hours=+15,seconds=+0,minutes=+0))
    return df

# 提取用户退款数据
def step_2(product_nos):
    if len(product_nos) == 0:
        return
    sql_1='''
    select id refund_id,fund_code src_fund_code,product_no,refund_principle,refund_time
    from qunaer_new.refund_detail where product_no in %s
    ''' % str(tuple(product_nos))
    return pd.read_sql(sql_1,engine_qunaer)

# 提取用户还款数据
def step_3(product_nos):
    if len(product_nos) == 0:
        return
    sql_1='''
    select id repay_id,fund_code src_fund_code,product_no,repay_principle,repay_time
    from qunaer_new.repay_detail where product_no in %s 
    ''' % str(tuple(product_nos))
    return pd.read_sql(sql_1,engine_qunaer)

# 更新还款表+退款表的资金方的ID，
def step_4(year,month):
    df_fund_repay=step_1(year,month)
    df_refund=step_2(df_fund_repay['product_no'].astype(str).tolist())
    df_refund['refund_time']=pd.to_datetime(df_refund['refund_time'])
    df_repay = step_3(df_fund_repay['product_no'].astype(str).tolist())
    df_repay['repay_time']=pd.to_datetime(df_repay['repay_time'])
    df_refund=pd.merge(df_refund,df_fund_repay[['product_no','package_time','fund_code']],on=['product_no'],how='left')
    df_repay=pd.merge(df_repay,df_fund_repay[['product_no','package_time','fund_code']],on=['product_no'],how='left')
    #提取债转后的退款数据
    df_refund_after=df_refund.ix[df_refund.refund_time >= df_refund.package_time]
    update_sql_1='''
    update refund_detail set fund_code = 1 where id = %s
    '''
    engine_qunaer.execute(update_sql_1,df_refund_after[['refund_id']].values.tolist())
    #提取债转后的还款数据
    df_repay_after=df_repay.ix[df_repay.repay_time >= df_repay.package_time]
    update_sql_2 = '''
    update repay_detail set fund_code = 1 where id = %s
    '''
    engine_qunaer.execute(update_sql_2, df_repay_after[['repay_id']].values.tolist())
    # #债转前的退款数据
    # df_refund_before=df_refund.ix[df_refund.refund_time < df_refund.package_time]
    # df_repay_before=df_repay.ix[df_repay.repay_time < df_repay.package_time]
    # update_sql_3='''
    # update refund_detail set fund_code= %s where id= %s
    # '''
    # engine_qunaer.execute(update_sql_3, df_refund_before[['fund_code','refund_id']].values.tolist())
    # update_sql_4='''
    # update repay_detail set fund_code = %s where id = %s
    # '''
    # engine_qunaer.execute(update_sql_4, df_repay_before[['fund_code', 'repay_id']].values.tolist())

# 录入债转后的放款表
def step_5(year,month):
    df_fund_repay=step_1(year,month)
    sql_repay='''
    select fund_code,product_no,sum(repay_principle) repay_principle,max(repay_time) repay_time from 
    qunaer_new.repay_detail where product_no in %s 
    group by 1,2
    ''' % str(tuple(df_fund_repay['product_no'].astype(str).tolist()))
    df_repay=pd.read_sql(sql_repay,engine_qunaer)
    sql_refund='''
    select fund_code,product_no,-sum(refund_principle) repay_principle,max(refund_time) repay_time from qunaer_new.refund_detail
    WHERE product_no in %s 
    GROUP by 1,2
    ''' % str(tuple(df_fund_repay['product_no'].astype(str).tolist()))
    df_refund=pd.read_sql(sql_refund,engine_qunaer)
    df_repay_all=pd.concat([df_repay,df_refund],ignore_index=True)
    df_repay_all=df_repay_all.groupby(['fund_code','product_no']).agg({'repay_principle':'sum','repay_time':'max'}).reset_index()
    df_fund_repay=pd.merge(df_fund_repay,df_repay_all,on=['fund_code','product_no'],how='left')
    # diff---债转后的金额
    df_fund_repay['diff']=np.round(df_fund_repay['repay_amount']-df_fund_repay['repay_principle'],2)
    df_fund_repay=df_fund_repay.ix[df_fund_repay['diff'] != 0]
    sql_pay='''
    select product_no,user_no,loan_time,loan_amount,stages,is_ptf,status,rate
    from qunaer_new.pay_detail where product_no in %s 
    ''' % str(tuple(df_fund_repay['product_no'].astype(str).tolist()))
    df_pay=pd.read_sql(sql_pay,engine_qunaer)
    df_fund_repay=pd.merge(df_fund_repay,df_pay,on='product_no',how='left')
    df_fund_repay['fund_code'] = 1
    df_fund_repay['trans_time']=pd.to_datetime(df_fund_repay['fund_repay_time'])
    #针对已有的保理数据
    sql_baoli='''
    select product_no,loan_amount baoli_loan_amount from qunaer_new.baoli_pay_detail
    '''
    df_baoli=pd.read_sql(sql_baoli,engine_qunaer)
    df_fund_repay=pd.merge(df_fund_repay,df_baoli,on='product_no',how='left')
    df_fund_repay_no=df_fund_repay.ix[~df_fund_repay.product_no.isin(df_baoli.product_no)]
    df_fund_repay_yes = df_fund_repay.ix[df_fund_repay.product_no.isin(df_baoli.product_no)]
    print '=====有问题数据====',len(df_fund_repay_yes)
    df_fund_repay_no=df_fund_repay_no[['fund_code','product_no','stages','status','is_ptf','loan_time','diff','trans_time','user_no','rate']]
    df_fund_repay_no.rename(columns={'diff':'loan_amount'},inplace=True)
    # df_fund_repay_no.to_csv('E:/cc.csv')
    df_fund_repay_no.to_sql('baoli_pay_detail',engine_qunaer,if_exists='append',index=None,chunksize=10000)


# 债转后的保理放款表的还款计划入库
def step_6(year,month):
    start_time = datetime.date(year, month, 1)
    end_time = start_time + relativedelta(months=+1)
    sql_1='''
    select product_no from qunaer_new.baoli_pay_detail where trans_time >= '%s' and trans_time < '%s'
    and product_no not in (select product_no from qunaer_new.baoli_repayment_plan)
    ''' % (start_time,end_time)
    df_1=pd.read_sql(sql_1,engine_qunaer)
    #还款计划
    sql_2='''
    select product_no,current_stage_no user_current_stage_no,deadline,rate,require_fee,principle,fee_amount,due_amount,status
    from qunaer_new.repayment_plan_2017 where product_no in %s 
    ''' % str(tuple(df_1['product_no'].astype(str).tolist()))
    df_2=pd.read_sql(sql_2,engine_qunaer)
    df_2['fund_code']=1
    df_2['current_stage_no'] = 1
    df_2.to_sql('baoli_repayment_plan',engine_qunaer,if_exists='append',index=None,chunksize=10000)

def step_7(year,month):
    start_time = datetime.date(year, month, 1)
    end_time = start_time + relativedelta(months=+1)
    sql_refund='''
    select t1.product_no from qunaer_new.refund_detail t1 
    JOIN qunaer_new.baoli_pay_detail t2 on t1.fund_code = t2.fund_code AND t1.product_no = t2.product_no
    where t1.refund_time >= '%s' and t1.refund_time < '%s'
    ''' % (start_time,end_time)

    sql_user_plan='''
    select product_no,current_stage_no,require_fee,principle,fee_amount,due_amount ,status from qunaer_new.repayment_plan_2017 
    WHERE product_no in %s
    '''
    sql_baoli_plan='''
    select id,product_no,user_current_stage_no,require_fee baoli_require_fee from qunaer_new.baoli_repayment_plan 
    where product_no in %s
    '''
    update_sql='''
    update baoli_repayment_plan set require_fee=%s,principle=%s,fee_amount=%s,due_amount=%s,status=%s where id=%s
    '''
    df_refund=pd.read_sql(sql_refund,engine_qunaer)
    df_user_plan=pd.read_sql(sql_user_plan % str(tuple(df_refund['product_no'].astype(str).tolist())),engine_qunaer)
    df_baoli_plan = pd.read_sql(sql_baoli_plan % str(tuple(df_refund['product_no'].astype(str).tolist())), engine_qunaer)
    df_plan=pd.merge(df_baoli_plan,df_user_plan,left_on=['product_no','user_current_stage_no'],right_on=['product_no','current_stage_no'],how='left')
    df_plan['diff']=np.round(df_plan['baoli_require_fee']-df_plan['require_fee'],2)
    df_plan=df_plan.ix[df_plan['diff'] != 0]
    engine_qunaer.execute(update_sql,df_plan[['require_fee','principle','fee_amount','due_amount','status','id']].values.tolist())

#更新还款状态
def step_8(year,month):
    start_time = datetime.date(year, month, 1)
    end_time = start_time + relativedelta(months=+1)
    sql_repay = '''
        select t1.product_no,t1.current_stage_no,t1.repay_status from qunaer_new.repay_detail t1 
        JOIN qunaer_new.baoli_pay_detail t2 on t1.fund_code = t2.fund_code AND t1.product_no = t2.product_no
        where t1.repay_time >= '%s' and t1.repay_time < '%s' and t1.repay_status=1
    ''' % (start_time, end_time)

    sql_baoli_plan = '''
        select id,product_no,user_current_stage_no from qunaer_new.baoli_repayment_plan 
        where product_no in %s
        '''
    update_sql = '''
        update baoli_repayment_plan set status=2 where id=%s
    '''
    df_repay = pd.read_sql(sql_repay, engine_qunaer)
    df_baoli_plan = pd.read_sql(sql_baoli_plan % str(tuple(df_repay['product_no'].astype(str).tolist())),engine_qunaer)
    df_plan = pd.merge(df_baoli_plan, df_repay, left_on=['product_no', 'user_current_stage_no'],
                       right_on=['product_no', 'current_stage_no'], how='inner')
    engine_qunaer.execute(update_sql, df_plan[[ 'id']].values.tolist())





if __name__ == '__main__':
    year = 2017
    month = 9
    #====针对提前结算的处理========
    #===只有提前结算有债转处理=====
    #===到期日
    # step_4(year,month)
    # step_5(year,month)
    # step_6(year,month)
    #--根据客户的还款计划更新保理的还款计划
    # step_7(year,month)
    step_8(year,month)






