# -*- coding: utf-8 -*-

"""
新马上扣款流水  和  用户还款计划  流水拆分关联期数;  其中费用(6项)拆分还原;

new_ms_transaction      新马上扣款流水
new_ms_transaction_with_term   新马上用户 还款计划 明细

A 还款计划
  按照loadid, 期数
  计算该还 = (funding_principle, funding_interest, funding_service_fee, qg_service_fee, qg_overdue_fee, qg_late_fee)

B 划款记录
  按照 loadid, repay_date 

处理同一个loadid
   取得 aa bb
     aleft.need_pay,   bleft.repay_amt
     term_no = 0
  # 按照时间线的   bb流水 去 消耗 aa的还款计划. 生成拆分的记录
  loop 不能a b 都到头了
     如果一个到头了
        但还往前走, 处理这种意外 
     谁left 0 谁自增 相加  
       如果a增, 当前期数更新
     尝试消耗 min(bleft, aleft) 生成新纪录
       left各自相减
       新纪录的各项费用  哪个left用完了, 就用那个费用明细, 并维护另外一个费用明细
       增加记录  扣款流水号, load_id, 当前期数, 消耗金额
"""

import pandas as pd
from sqlalchemy import create_engine

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

engine_local = create_engine('mysql+mysqldb://root@localhost:3306/heloword?charset=utf8',
                             echo=True)

sqla = """
    SELECT
      nntr_plan.*,
      (funding_principle + funding_interest + funding_service_fee +
       qg_service_fee +
       qg_overdue_fee +
       qg_late_fee) need_pay
    FROM new_transaction.new_ms_transaction_with_term nntr_plan
    ORDER BY loan_id, term_no;
"""

sqlb = """
    SELECT *
    FROM new_transaction.new_ms_transaction nntr
    ORDER BY  ABS(loan_id) , repay_date;
"""

Adf = pd.read_sql(sql=sqla, con=engine_audit)
Bdf = pd.read_sql(sql=sqlb, con=engine_audit)

Bdf['loan_id'] = Bdf['loan_id'].astype(int)


# Adf = Adf.set_index(['loan_id', 'repay_date'])
# Bdf = Bdf.set_index(['loan_id', 'term_no'])


def series_section_size(data_frame, start_i, value, max_len):
    end_i = start_i

    while True:
        if end_i >= max_len or data_frame.iloc[end_i].loan_id != value:
            break
        end_i += 1

    range_size = end_i - start_i

    return range_size


Ai = 0
Bi = 0
ALEN = len(Adf)
BLEN = len(Bdf)

res_records = []
goon = True

while Ai != ALEN and Bi != BLEN and goon:
    loan_id = Adf.iloc[Ai].loan_id

    # aa = Adf.ix[Adf.loan_id == loan_id]  # 最好有索引
    # bb = Bdf.ix[Bdf.loan_id == loan_id]
    alen = series_section_size(Adf, Ai, loan_id, ALEN)
    blen = series_section_size(Bdf, Bi, loan_id, BLEN)
    aa = Adf.iloc[Ai: Ai + alen]
    bb = Bdf.iloc[Bi: Bi + blen]

    term_no = 0
    ai = 0
    aleft = 0

    bi = 0
    bleft = 0

    Ai += alen
    Bi += blen

    if alen == 0 or blen == 0:
        if alen == 0:
            print "%s 划款没有对应的 计划 " % loan_id, alen, blen
            break
        continue

    # bb = bb.ix[bb.repay_amt != 0]
    # blen = len(bb)
    while not (ai == alen and bi == blen):
        if aleft == 0:
            if ai == alen:  # 有笔扣款没有相应的还款计划
                # 如果 最后一笔扣款是0
                if bb.iloc[bi:blen].repay_amt.sum() == 0.0:
                    # print '扣款 %s 结尾是0     ' % loan_id, blen-bi
                    break
                else:  # 否则 输出
                    # print '扣款 %s not map full  ' % loan_id, ai, alen, bi, blen, blen-bi
                    goon = False
                    break
            a = aa.iloc[ai]
            aleft = a.need_pay
            afee = {  # 当前期剩余未还 各项费用
                'repay_principle': a.funding_principle,
                'repay_intrest': a.funding_interest,
                'fund_service_fee': a.funding_service_fee,
                'service_fee': a.qg_service_fee,
                'late_fee': a.qg_overdue_fee,
                'penalty_fee': a.qg_late_fee
            }
            term_no = a.term_no
            ai += 1

        if bleft == 0:
            if bi == blen:
                # print '计划 not map full  ', loan_id, ai, alen, bi, blen
                # goon = False
                break
            b = bb.iloc[bi]
            bleft = b.repay_amt
            bfee = {
                'repay_principle': b.repay_principle,
                'repay_intrest': b.repay_intrest,
                'fund_service_fee': b.fund_service_fee,
                'service_fee': b.service_fee,
                'late_fee': b.late_fee,
                'penalty_fee': b.penalty_fee
            }
            bi += 1

        cost = min(bleft, aleft)
        aleft -= cost
        bleft -= cost

        if aleft == 0.0:
            fees = afee
            bfee = {key: bfee[key] - afee[key] for key in afee.keys()}
        else:
            fees = bfee
            afee = {key: afee[key] - bfee[key] for key in bfee.keys()}

        new_record = {
            'transfer_id': b.id,
            'loan_id': loan_id,
            'term_no': term_no,
            'amt_for_term': cost,

            'contract_no': b.contract_no,
            'repay_amt': b.repay_amt,
            'loan_paid_at': b.loan_paid_at,
            'repay_date': b.repay_date
        }
        new_record.update(fees)

        # 2,10进制的不可逾越的代沟 或者运算精度  造成   浮点数运算的时候, 结果常有微小的差距
        new_record_fee_unacceptable = any( fee < -1E-10 for fee in fees.itervalues() )
        if new_record_fee_unacceptable:
            print fees
            goon = False
            break

        res_records.append(new_record)
    #该load_id 处理结束   aa bb




res_df = pd.DataFrame(res_records)
res_df.to_sql('new_ms_transaction_map_term', con=engine_local, if_exists='append', index=None, chunksize=10000)

path_out = u'/Users/xujiazhe/Desktop/'
res_df.to_excel(path_out + u'新马上扣款记录加上期数.xlsx', index=None)
