# -*- coding: utf-8 -*-
import sys
import copy
import pandas as pd
from multiprocessing import Manager
from sqlalchemy import create_engine
import multiprocessing as mtp
import numpy as np

reload(sys)
sys.setdefaultencoding('utf8')

engine_test = create_engine(
    'mysql+mysqldb://internal_r:ArbNgtvlJzZHXsEu@172.16.3.201:3306/temp?charset=utf8', echo=True)

"""
需求: 彭千

现金贷 借款 按照月份, 借款评级类型  求 
    总应收服务费
    计提风险金比例
    计提风险金总额
    贷前贷后比例
    应收贷前服务费
    应收贷后服务费
    实收贷前服务费
    实收贷后服务费
    贷前服务费减免
    贷后服务费减免

每个订单   贷后服务费还钱多少     应收贷后服务费-实收贷后服务费-贷后服务费减免>=0

EF 列 按月

"""

"""
数据源  temp
    放款表  loan_menifest lm,    放款时间, 总服务费
    放款评级 loan_class lc,      评级
    用户还款计划 user_repayment_plan urp,  deadline 贷后应收日期
    拆分记录    xjd_repay_plan_repay_record_ref   rp_rrr,  实服, 减服.

校验
    都能关联 ref_id


数据处理 ==>

summary_dict =  
    {
        月份_类型: {
            贷前实收: 0.0, 
            贷后实收: 0.0, 
            贷前减免: 0.0, 
            贷后减免: 0.0
        },
        ...
    }

lm, lc  =>  LC_df, 其字段有    
ref_id, loan_id, class, 放款月份;;   总应收服务费(0), 计提风险金, 贷前应收, 贷后应收;;   
        贷前实收(0), 贷后实收, 贷前减免, 贷后减免,   总实收, 总实减免;;
排序ref_id

LCR_df = LC_df left_join  (月, 类型, 坏账率, 拆分比例)
  计算相关字段   总应收服务费, 计提风险金, 贷前应收, 贷后应收

//
LCR_df   group 月份类型 sum 总应收服务费, 计提风险, 贷前应收,  order by 月份,类型(ABC)  =>  
        总应收服务费_summary, 计提风险金总额_summary, 应收贷前服务费_summary.
df = LCR_df 左连 urp   字段 应收deadline月. 贷后应收/term_no "/ %"   根据dead月, 类型(ABC), 分散汇总  => 
        应收贷后服务费_summary.


实还拆分的流水  rp_rrr
  rp_rrr  ref_id, 实还月(流水日期), 服务费, 减免服务费 
  order by ref_id, 流水日期

//
遍历 LCR_df (loan借款)
    针对一个ref_id
    loan_manifest
    rp_rrr_loan = 该借款 根据term_no拆分流水
    
    rp_rrr_loan 汇总 总实收, 总减免  
    贷前服务费容量 = min(总实收, 贷前应收)
    贷前减免容量 = 贷前服务费容量 - 贷前应收
    
    while
        如果rp_rrr_loan 用完了, 结束
        如果 rp_rrr 的实还, 减免 都用完了 
            rp_rrr_loan.next()
        
        月份_类型, 并拿出 data_dict = summary_dict[月份_类型]
        
        用 实还服务费(!0) (贷前服务费容量 剩余)
            填 贷前实收   减容 分流到 data_dict 贷前实收 汇总
            填 贷后实收        分流
        用 减免服务费(!0) (贷前减免容量 剩余)
            填 贷前减免   减容 分流
            填 贷后减免        分流

# -------
报表1
    总应收服务费_
    计提风险金总额
    应收贷前服务费
    应收贷后服务费

    # 同月份 一个字段,   按照类型(ABC)三列
    实收贷前服务费
    实收贷后服务费
    
    贷前服务费减免
    贷后服务费减免

报表2
    遍历 LCR_df (loan借款)
        订单, 贷后应收 - 贷后实收 - 贷后减免 >= 0
报表3
    月份, 贷后应收, 贷后实收
    
    应收贷后服务费_summary
    实收贷后服务费
    不分类型, 按照月份汇总.    拆key, 选列
"""

# 改数据库
# 检查代码
# 挨个检查 试验

LC_sql = """
  SELECT
    lm.ref_id,
    lm.loan_id,
    lc.class,
    date_format(lm.loan_paid_at, '%%Y年%%m月') loan_month,
    lm.real_loan_amount,
    lm.all_service_fee, 
    lm.contract_term,
    lm.per_term_service_fee * lm.contract_term service_fee, #//TODO 这里?
    0.0 '总应收服务费',
    0.0 '计提风险金',
    0.0 '贷前应收',
    0.0 '贷后应收',
    0.0 '贷前实收',
    0.0 '贷后实收',
    0.0 '贷前减免',
    0.0 '贷后减免',
    0.0 '总实收',
    0.0 '总实减免'
  FROM temp.loan_manifest lm
    JOIN temp.loan_class lc ON lm.ref_id = lc.ref_id
  WHERE lm.is_active IN (1, -2) AND 
    lm.loan_paid_at BETWEEN '{loan_start}' AND '{loan_end}'
  ORDER BY lm.ref_id
  -- LIMIT 100; #//TODO 限制
"""

LC_df = pd.read_sql(LC_sql.format(**{
    "loan_start": '2015-06-01',
    "loan_end": '2017-01-01'
}), con=engine_test)

summary_dict = {}

mlist = [
    u'2015年06月',
    u'2015年07月',
    u'2015年08月',
    u'2015年09月',
    u'2015年10月',
    u'2015年11月',
    u'2015年12月',
    u'2016年01月',
    u'2016年02月',
    u'2016年03月',
    u'2016年04月',
    u'2016年05月',
    u'2016年06月',
    u'2016年07月',
    u'2016年08月',
    u'2016年09月',
    u'2016年10月',
    u'2016年11月',
    u'2016年12月'
]

for month_name in mlist:
    for c in 'ABC':
        summary_dict[u'%s_%s' % (month_name, c)] = {
            '贷前实收': 0.0,
            '贷后实收': 0.0,
            '贷前减免': 0.0,
            '贷后减免': 0.0
        }

cnames = ['loan_month', 'class', 'pre_loan_rate', 'aft_loan_rate', 'bad_rate']
rate_data = [
    [u'2015年06月', u'A', 0.62, 0.38, 0.0331],
    [u'2015年07月', u'A', 0.62, 0.38, 0.0331],
    [u'2015年08月', u'A', 0.62, 0.38, 0.0331],
    [u'2015年09月', u'A', 0.62, 0.38, 0.0331],
    [u'2015年10月', u'A', 0.62, 0.38, 0.0331],
    [u'2015年11月', u'A', 0.62, 0.38, 0.0331],
    [u'2015年12月', u'A', 0.62, 0.38, 0.0331],
    [u'2016年01月', u'A', 0.64, 0.36, 0.0331],
    [u'2016年02月', u'A', 0.64, 0.36, 0.0331],
    [u'2016年03月', u'A', 0.64, 0.36, 0.0331],
    [u'2016年04月', u'A', 0.64, 0.36, 0.0372],
    [u'2016年05月', u'A', 0.64, 0.36, 0.0372],
    [u'2016年06月', u'A', 0.64, 0.36, 0.0372],
    [u'2016年07月', u'A', 0.64, 0.36, 0.0144],
    [u'2016年08月', u'A', 0.64, 0.36, 0.0144],
    [u'2016年09月', u'A', 0.64, 0.36, 0.0144],
    [u'2016年10月', u'A', 0.64, 0.36, 0.0138],
    [u'2016年11月', u'A', 0.64, 0.36, 0.0138],
    [u'2016年12月', u'A', 0.64, 0.36, 0.0138],
    [u'2015年06月', u'B', 0.70, 0.30, 0.0510],
    [u'2015年07月', u'B', 0.70, 0.30, 0.0510],
    [u'2015年08月', u'B', 0.70, 0.30, 0.0510],
    [u'2015年09月', u'B', 0.70, 0.30, 0.0510],
    [u'2015年10月', u'B', 0.70, 0.30, 0.0510],
    [u'2015年11月', u'B', 0.70, 0.30, 0.0510],
    [u'2015年12月', u'B', 0.70, 0.30, 0.0510],
    [u'2016年01月', u'B', 0.76, 0.24, 0.0510],
    [u'2016年02月', u'B', 0.76, 0.24, 0.0510],
    [u'2016年03月', u'B', 0.76, 0.24, 0.0510],
    [u'2016年04月', u'B', 0.76, 0.24, 0.0548],
    [u'2016年05月', u'B', 0.76, 0.24, 0.0548],
    [u'2016年06月', u'B', 0.76, 0.24, 0.0548],
    [u'2016年07月', u'B', 0.76, 0.24, 0.0347],
    [u'2016年08月', u'B', 0.76, 0.24, 0.0347],
    [u'2016年09月', u'B', 0.76, 0.24, 0.0347],
    [u'2016年10月', u'B', 0.76, 0.24, 0.0360],
    [u'2016年11月', u'B', 0.76, 0.24, 0.0360],
    [u'2016年12月', u'B', 0.76, 0.24, 0.0360],
    [u'2015年06月', u'C', 0.88, 0.12, 0.0849],
    [u'2015年07月', u'C', 0.88, 0.12, 0.0849],
    [u'2015年08月', u'C', 0.88, 0.12, 0.0849],
    [u'2015年09月', u'C', 0.88, 0.12, 0.0849],
    [u'2015年10月', u'C', 0.88, 0.12, 0.0849],
    [u'2015年11月', u'C', 0.88, 0.12, 0.0849],
    [u'2015年12月', u'C', 0.88, 0.12, 0.0849],
    [u'2016年01月', u'C', 0.85, 0.15, 0.0849],
    [u'2016年02月', u'C', 0.85, 0.15, 0.0849],
    [u'2016年03月', u'C', 0.85, 0.15, 0.0849],
    [u'2016年04月', u'C', 0.85, 0.15, 0.0932],
    [u'2016年05月', u'C', 0.85, 0.15, 0.0932],
    [u'2016年06月', u'C', 0.85, 0.15, 0.0932],
    [u'2016年07月', u'C', 0.85, 0.15, 0.0672],
    [u'2016年08月', u'C', 0.85, 0.15, 0.0672],
    [u'2016年09月', u'C', 0.85, 0.15, 0.0672],
    [u'2016年10月', u'C', 0.85, 0.15, 0.0678],
    [u'2016年11月', u'C', 0.85, 0.15, 0.0678],
    [u'2016年12月', u'C', 0.85, 0.15, 0.0678]
]
rate_df = pd.DataFrame(rate_data, columns=cnames)

LCR_df = pd.merge(LC_df, rate_df, on=['loan_month', 'class'])

LCR_df[u'计提风险金'] = LCR_df['bad_rate'] * LCR_df.all_service_fee  # TODO all_service_fee ?
LCR_df[u'贷前应收'] = (LCR_df.all_service_fee - LCR_df[u'计提风险金']) * LCR_df['pre_loan_rate']
LCR_df[u'贷后应收'] = (LCR_df.all_service_fee - LCR_df[u'计提风险金']) * LCR_df['aft_loan_rate']
LCR_df[u'总应收服务费'] = LCR_df[u'计提风险金'] + LCR_df[u'贷前应收'] + LCR_df[u'贷后应收']

res1 = LCR_df.groupby(['loan_month', 'class'], as_index=True).agg(
    {
        u'总应收服务费': "sum",
        u'计提风险金': "sum",
        u'贷前应收': "sum",
        u'贷后应收': "sum"
    }
)

# res1 = res1.sort_values(by=['loan_month', 'class'], inplace=True)
ref_ids = LC_df.ref_id.unique()  # TODO continue
ref_ids_str = ""  # ""('" + "','".join(str(_id) for _id in ref_ids) + "')"
ref_ids_int = ""  # ""(" + ",".join(str(_id) for _id in ref_ids) + ")"

urp_sql = """
  SELECT
    ref_id,
    term_no,
    date_format(deadline, '%s')     pay_month,
    0.0                             aft_service_fee
  FROM temp.user_repayment_plan urp
  -- where ref_id in %s #//TODO 
  ORDER BY ref_id, term_no
""" % ("%%Y年%%m月", ref_ids_str)

urp_df = pd.read_sql(urp_sql, con=engine_test)
urp_df = pd.merge(LCR_df, urp_df, on=['ref_id'], how='left')#, left_index=True, right_index=True)

urp_df['aft_service_fee'] = np.round(urp_df[u'贷后应收'] / urp_df['contract_term'], 2)
urp_df.ix[urp_df.term_no == urp_df.contract_term, 'aft_service_fee'] = urp_df.ix[
    urp_df.term_no == urp_df.contract_term].apply(
        lambda x: np.round(x[u'贷后应收'] - (x['contract_term'] * x['aft_service_fee']) + x['aft_service_fee'], 2),
        axis=1
    )

res2 = urp_df.groupby(
    by=['pay_month', 'class'], as_index=True
        )['aft_service_fee'].agg(
            {'sum'}
        ).reset_index(
        ).rename(
            columns={'sum': u'应收贷后服务费'}
        ).sort_index(
            ascending=False
        )              # TODO 排序

rp_rrr_sql = """
  SELECT
    lm.ref_id,
    lc.class,
    rp_rrr.service_fee,
    rp_rrr.mitigate_service_fee,
    CASE
    WHEN (rp_rrr.repay_channel < 13)
      THEN date_format(urp.xyqb_repaid_at, '%%Y年%%m月')
    ELSE date_format(trp_rrrrd.repaid_at, '%%Y年%%m月') END
      paid_month
  FROM
    xjd_repay_plan_repay_record_ref rp_rrr
    JOIN temp.xjd_repay_plan_repay_record_ref_repay_date trp_rrrrd ON trp_rrrrd.xjd_ref_id = rp_rrr.id
    JOIN user_repayment_plan urp ON rp_rrr.plan_id = urp.id
    JOIN loan_manifest lm ON lm.ref_id = urp.ref_id
    JOIN temp.loan_class lc ON lc.ref_id = urp.ref_id
  WHERE (
    (rp_rrr.repay_channel IN (13, 14, 15, 16) AND
     trp_rrrrd.repaid_at BETWEEN '{real_paid_start}' AND '{real_paid_end}')
    OR
    (rp_rrr.repay_channel < 13 AND urp.xyqb_repaid_at BETWEEN '{real_paid_start}' AND '{real_paid_end}')
  ) -- and lm.ref_id in {_str} #//TODO
  
  ORDER BY ref_id,
    CASE
    WHEN (rp_rrr.repay_channel < 13)
      THEN urp.xyqb_repaid_at
    ELSE trp_rrrrd.repaid_at
    END
  ASC
""".format(**{
    "_str": ref_ids_int,
    "real_paid_start": '2015-06-01',
    "real_paid_end": '2017-01-01'
})

rp_rrr_df = pd.read_sql(rp_rrr_sql, con=engine_test)

rp_rrr_df_i = rp_rrr_df_j = 0
for i, loan_manifest_r in LCR_df.iterrows():
    ref_id = loan_manifest_r['ref_id']

    while rp_rrr_df_i < len(rp_rrr_df) and rp_rrr_df.iloc[rp_rrr_df_i].ref_id < ref_id: rp_rrr_df_i += 1
    rp_rrr_df_j = rp_rrr_df_i
    while rp_rrr_df_j < len(rp_rrr_df) and rp_rrr_df.iloc[rp_rrr_df_j].ref_id == ref_id: rp_rrr_df_j += 1

    rp_rrr_loan = rp_rrr_df[rp_rrr_df_i:rp_rrr_df_j]  # 该借款 根据term_no拆分流水
    rp_rrr_df_i = rp_rrr_df_j

    LCR_df.ix[i, u'总实收'] = rp_rrr_loan['service_fee'].sum()  # LCR_df.set_value
    LCR_df.ix[i, u'总实减免'] = rp_rrr_loan['mitigate_service_fee'].sum()

    pre_loan_capacity = min(LCR_df.ix[i, u'总实收'], LCR_df.ix[i, u'贷前应收'])
    pre_loan_migrate_capacity = pre_loan_capacity - LCR_df.ix[i, u'贷前应收']

    rp_rrr_loan_i = 0
    rp_rrr_loan_len = len(rp_rrr_loan)
    if rp_rrr_loan_len == 0:
        continue

    rp_rrr = rp_rrr_loan.iloc[rp_rrr_loan_i]
    while True:
        rp_rrr_used_over = rp_rrr.service_fee <= 1.0E-06 and \
                           rp_rrr.mitigate_service_fee <= 1.0E-06
        if rp_rrr_used_over:
            rp_rrr_loan_i += 1
            if rp_rrr_loan_i == rp_rrr_loan_len: break
            rp_rrr = rp_rrr_loan.iloc[rp_rrr_loan_i]

        key = '%s_%s' % (rp_rrr.paid_month, rp_rrr['class'])
        data_dict = summary_dict[key]
        if rp_rrr.service_fee > 1.0E-06:
            if pre_loan_capacity > 1.0E-06:
                cost = min(pre_loan_capacity, rp_rrr.service_fee)
                LCR_df.ix[i, u'贷前实收'] += cost
                data_dict['贷前实收'] += cost
                rp_rrr.service_fee -= cost
                pre_loan_capacity -= cost
            else:
                cost = rp_rrr.service_fee
                LCR_df.ix[i, u'贷后实收'] += cost
                data_dict['贷后实收'] += cost
                rp_rrr.service_fee = 0

        if rp_rrr.mitigate_service_fee > 1.0E-06:
            if pre_loan_migrate_capacity > 1.0E-06:
                cost = min(pre_loan_migrate_capacity, rp_rrr.mitigate_service_fee)
                LCR_df.ix[i, u'贷前减免'] += cost
                data_dict['贷前减免'] += cost
                rp_rrr.mitigate_service_fee -= cost
                pre_loan_migrate_capacity -= cost
            else:
                cost = rp_rrr.mitigate_service_fee
                LCR_df.ix[i, u'贷后减免'] += cost
                data_dict['贷后减免'] += cost
                rp_rrr.mitigate_service_fee = 0
    # break
    if rp_rrr_df_j == len(rp_rrr_df):
        break

## =============== 出结果 ===============

indexer = []
for month in mlist:
    for c in 'ABC':
        indexer.append([month, c])
indexer = pd.DataFrame(indexer, columns=['loan_month', 'class'])

res1 = pd.merge(res1.reset_index(), indexer, on=['loan_month', 'class'], how='outer').fillna(0)
res1 = pd.pivot_table(res1, values=[u'总应收服务费', u'计提风险金', u'贷前应收', u'贷后应收'],
                      index=['loan_month'], columns=['class']
                      ).sort_index(axis=1)

res2 = pd.merge(res2,
                indexer,
                left_on=['pay_month', 'class'],
                right_on=['loan_month', 'class'], how='outer'
                ).fillna(0).drop('pay_month', 1)

res2 = pd.pivot_table(res2, values=[u'应收贷后服务费'],
                      index=['loan_month'], columns=['class']
                      ).sort_index(axis=1)

Data_df = pd.DataFrame(summary_dict).T.reset_index()
Data_df['loan_month'], Data_df['class'] = Data_df['index'].str.split('_', 1).str
Data_df = Data_df.drop('index', 1)
Data_df = Data_df.sort_index(axis=1, ascending=True).sort_values(by=['loan_month', 'class'])
Data_df = pd.pivot_table(Data_df, index=['loan_month'], columns=['class'])
Data_df1 = pd.merge(Data_df, res1, how='outer', left_index=True, right_index=True)
Data_df2 = pd.merge(Data_df1.reset_index(), res2.reset_index(), on='loan_month', how='outer')

Data_df2.to_excel('/Users/xujiazhe/Downloads/total.xlsx', index=None)

# 每月
#   贷后应收
#   贷后实收  Data_df['贷后实收']
EF_df = res1[u'贷后应收']
EF_df[u'贷后应收'] = EF_df['A'] + EF_df['B'] + EF_df['C']
ef_df2 = Data_df['贷后实收']
EF_df['贷后实收'] = ef_df2['A'] + ef_df2['B'] + ef_df2['C']
EF_df = EF_df.drop(['A', 'B', 'C'], axis=1)


def map_func(x):
    map_func.last_one += x
    return map_func.last_one


map_func.last_one = 0
EF_df[u'贷后应收'] = EF_df[u'贷后应收'].map(map_func)
map_func.last_one = 0
EF_df['贷后实收'] = EF_df['贷后实收'].map(map_func)

EF_df['E'] = EF_df[u'贷后应收'] - EF_df['贷后实收']
EF_df['F'] = EF_df[u'贷后应收'] - EF_df['贷后实收']

EF_df.ix[EF_df['F'] < 0, 'F'] = ''
EF_df.ix[EF_df['E'] > 0, 'E'] = ''
# EF_df = EF_df.drop([u'贷后应收', '贷后实收'], axis=1)
EF_df.to_excel('/Users/xujiazhe/Downloads/EF.xlsx')
