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


import traceback
import random
import re
import os
import json
import datetime
import time
import logging
import copy
import contextlib

import pandas as pd
import numpy as np
import requests
import pymysql
from pymongo import MongoClient
from dateutil.relativedelta import relativedelta as Datedelta
from DBUtils.PooledDB import PooledDB

from config import configs
import utils


def logger_config(date):
    info_file = os.path.join(configs['log']['info'], 'check-%s.log' % date)
    logger = logging.getLogger('')
    logger.setLevel(logging.INFO)
    info_handler = logging.FileHandler(info_file, 'w', encoding='utf8')
    info_handler.setFormatter(logging.Formatter('%(asctime)s-%(levelname)s-%(message)s'))
    logger.addHandler(info_handler)
    return logger


def round_up(value):
    try:
        v = float(value)
        return round(v * 100) / 100.0
    except Exception:
        log.error(traceback.print_exc())
        return 0


today = datetime.date.today()
delta = datetime.timedelta(days=1)
yestoday = (today - delta).strftime('%Y-%m-%d')
print(yestoday)
TODAY = today.strftime('%Y-%m-%d')

log = logger_config(yestoday)

pool = PooledDB(pymysql, mincached=1, maxconnections=3,
                host=configs['mysql']['host'],
                user=configs['mysql']['user'],
                password=configs['mysql']['pwd'],
                charset='utf8'
                )


class Reviewer:
    def __init__(self, date):
        self.rule = Rule()
        self.rule.centers_info()
        self.date = date
        self.errors = []
        self.fields = list(configs['use'].keys())
        self.columns = self.build_cols()
        self.csv = os.path.join(configs['log']['info'], 'check-%s.csv' % date)

    def build_cols(self):
        cols = ['cid', 'city', 'order_id', 'login', ]
        for item in self.fields:
            cols.append(item)
            cols.append('t_%s' % item)
        return cols

    @staticmethod
    def from_mongo(order_id):
        time.sleep(0.02)
        try:
            url = 'http://tv.51gjj.com:11250/gjj/%s' % order_id
            response = requests.get(url)
            #  print(response.status_code)
            return response.json()
        except Exception:
            traceback.print_exc()
            log.error(traceback.print_exc())
            return {'code': -1, 'msg': '获取数据失败'}

    def find_order_ids(self, tables):
        order_ids = set()
        for table in tables:
            query = "SELECT orderId FROM node_gjj.%s WHERE `status`='success' AND DATE(updateDate) = '%s'" \
                    % (table, self.date)
            t1 = time.clock()
            conn = pool.connection()
            with contextlib.closing(conn) as conn:
                cursor = conn.cursor()
                with contextlib.closing(cursor) as cursor:
                    rows = cursor.execute(query)
                    if configs['limit']:
                        datas = cursor.fetchall()[:configs['limit']]
                    else:
                        datas = cursor.fetchall()
            t2 = time.clock()
            log.info('Execute sql costs %.3fs, gets the number of rows is %s' % (t2 - t1, rows))
            for row in datas:
                order_ids.add(row[0])
        return order_ids

    def process(self, order_ids):
        for order_id in order_ids:
            log.info(str(order_id))
            #  print(row)
            doc = self.from_mongo(order_id)
            if doc['code'] == 0:
                data = doc['data']['gjjData']
                #  warn_msg is list
                try:
                    warn_msg = self.rule.run(data)
                    if warn_msg[1]:
                        #  print(warn_msg[1])
                        self.warn(warn_msg[0], order_id, warn_msg[1])
                except Exception:
                    print(order_id)
                    log.error(traceback.print_exc())
            else:
                log.info('%s: %s' % (order_id, doc['msg']))
                #  print('%s: %s' % (row[0], doc['msg']))

    def warn(self, city, order_id, warn_msg):
        params = self.login_params(order_id)
        record = {'order_id': order_id, 'city': city}
        try:
            record['login'] = str(params)
        except Exception:
            record['login'] = ''
        for k, v in warn_msg.items():
            record[k] = v
        self.errors.append(record)
        log.warn('[ %s ]-[ %s ]: %s ' % (order_id, city, warn_msg))

    def check_order(self, order_id):
        doc = self.from_mongo(order_id)
        if doc['code'] == 0:
            result = doc['data']['gjjData']
            warn_msg = self.rule.run(result)
            log.warn(warn_msg)
        else:
            log.warn('[ %s ]: %s ' % (order_id, doc['msg']))
            #  print('%s is error: %s' % (order_id, doc['msg']))

    def refresh(self):
        url = 'https://tt.51gjj.com/postloan/update'
        headers = {
            'Content-Type': 'application/json'
        }
        for order_id in self.rule.need_refresh:
            form = {
                "param": {
                    "orderSn": order_id
                },
                "callbackUrl": "https://tt.51gjj.com:5000/redirect"
            }
            requests.post(url, data=form, headers=headers)
            time.sleep(1)
        time.sleep(120)

    def login_params(self, order_id):
        try:
            url = 'http://tv.51gjj.com:11250/gjjlogininfo/%s' % order_id
            res = requests.get(url)
            r = res.json()
            if not r.get('msg'):
                del r['cityname']
            return r
        except Exception:
            return {'msg': '获取登录参数错误'}

    def out_result(self):
        sub = Submit()
        sub.login()
        #  for record in self.errors:
        #      sub.submit_bug(record['city'], record)
        #      time.sleep(1)
        df = pd.DataFrame(self.errors, columns=self.columns)
        for item in self.fields:
            t_item = 't_%s' % item
            if not configs['debug']:
                try:
                    grouped = df.groupby(['city', t_item])
                    for (city, field), group in grouped:
                        d = group[:5]
                        title = '%s: %s' % (city, self.trans_rule_desc(field))
                        content = []
                        for error in list(d.T.to_dict().values()):
                            content.append(
                                {'order_id': error['order_id'],
                                 'login': error['login'],
                                 item: error[item]
                                 })
                        if 'analyzed' in title:
                            continue
                        sub.submit_bug(title, content)
                        time.sleep(20)
                except Exception as e:
                    log.error('[%s]: %s' % ('out_result', traceback.print_exc()))
                    #  print('out_result', e)
            df[t_item] = df[t_item].map(self.trans_rule_desc)
        df.to_csv(self.csv, encoding='gbk')

    @staticmethod
    def trans_rule_desc(keys):
        if isinstance(keys, str):
            rule = keys.split('|')
            desc = '; '.join([configs['rules'][i]['desc'] for i in rule[2:]])
            return '%s配置为%s: %s' % (rule[0], trans_config(rule[1]), desc)


def trans_config(t):
    if t == '1':
        return '完整'
    if t == '-1':
        return '不存在'
    if t == '0':
        return '不完整'


def build_index():
    a = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    b = '0123456789'
    index = '%s%s%s' % (random.choice(a), random.choice(b), random.choice(a),)
    while index in configs['rules'].keys():
        index = '%s%s%s%s' % (random.choice(a), random.choice(b), random.choice(a), random.choice(a))
    return index


class Rule:
    _deposit_amount_error = 50
    _status_set = {'交存', '缴存', '正常交存', '正常缴存', '正常', '正常汇缴', '进行中', '正常缴交', }
    #  官网有问题的 ,不检查的城市:  绥化, 宁德, 驻马店, 内江
    #  多个账号明细合一起的: 巴中, 重庆
    _ignore_date_cid = {'356', '135', '430', '22', '443', '32', '288', '136', '247', }
    _ignore_deposit_base = {'110', '19', '95', '447', '37', '351', '124', '417', '269', '62', '430', '87', '34',
                            '338', '57', '381', '352', '105', '27', '47', '38', '101', '312', '92', '358',
                            '121', '438', '94', '309', '380', '375', '367', '366', '292', '309', '368', '320', '311',
                            '349', '63',
                            }
    _ignore_rate = {'22', '352', '87', '345', '380', '375', '367', '366', '292', '309', '368', '320', '311', '52', '82',
                    '62', '445', }
    _keys = {'data', 'cid', 'orderId', 'location', 'cityName', 'create_date'}
    _rate_weight = 2
    _base_weight = 3
    brief_keys = {"ID", "name", "card", "customer_id", "deposit_amount", "fb_deposit_amount", "person_rate",
                  "fb_balance", "once_balance", "status", "record_date", "company", "deposit_base", "balance",
                  "company_rate", "init_date", "start_date", "sex", "email", "phone", "marriage", "address",
                  "birthday", "company_id", "person_deposit_amount", "company_deposit_amount", "deposit_rate",
                  }
    record_key = {"id", "gjj_type", "company", "order_id", "record_date", "op_type", "record_month",
                  "amount", "balance", "remark", "comments", "deposit_type", "cont_flag", "back_cont_flag"
                  }
    detail_filter = '上年结转|前日余额|本年合计|^期初'
    op_set = set()
    farest_date = '1990-01-01'
    infos = None
    need_refresh = set()

    def __init__(self):
        self.cid = None
        self.orderId = None
        self.error = {}
        self.newest_date = None
        self.last_record = None
        self.first_record = None
        self.last_deposit = None
        self.has_record = False
        self.const_ret = []
        self.all_ret = []
        self.history_record = []

    @classmethod
    def centers_info(cls):
        res = requests.get('http://tm.51gjj.com:1010/CenterConfig/GetCentersJson')
        infos = res.json()
        centers = []
        for province in infos:
            for city in province['城市']:
                for center in city['公积金中心']:
                    centers.append(center)
        df = pd.DataFrame(centers)
        df_new = df.set_index('中心id')
        logging.error(df_new)
        for column in df_new.columns:
            # print(column)
            df_new[column] = df_new[column].map(Rule.trans)
        df_new['个人缴纳比例上限'] = df_new['个人缴纳比例上限'].replace('', 0).map(float)
        df_new['公司缴纳比例上限'] = df_new['公司缴纳比例上限'].replace('', 0).map(float)
        df_new['个人缴纳比例下限'] = df_new['个人缴纳比例下限'].replace('', 0).map(float)
        df_new['公司缴纳比例下限'] = df_new['公司缴纳比例下限'].replace('', 0).map(float)
        df_new['缴纳比例上限'] = df_new['个人缴纳比例上限'] + df_new['公司缴纳比例上限']
        df_new['缴纳比例下限'] = df_new['个人缴纳比例下限'] + df_new['公司缴纳比例下限']
        cls.infos = df_new

    @staticmethod
    def trans(text):
        # print(text)
        if re.findall('不完整', text):
            return '0'
        if re.findall('完整', text):
            return '1'
        if re.findall('不存在', text):
            return '-1'
        return text

    def check_id(self, id_num):
        mode = self.get_mode('身份证')
        if mode != '-1':
            self.test_value(id_num, 'ID', mode)

    def check_name(self, name):
        mode = self.get_mode('姓名')
        if mode != '-1':
            self.test_value(name, 'name', mode)
            #  if not (re.findall(r'[·.﹒]', name) or cid in ['279', '31', '213', '35', '154']):
            #      rule_index = self.test_len(name, 2, 5)
            #      if rule_index:
            #          self.build_error(name, 'name', mode, rule_index)

    def check_deposit_amount(self, brief):
        mode = self.get_mode('月缴')
        #  从明细里取的月缴/比例或者基数有问题
        if self.cid in {'14'}:
            return
        if self.cid in ['100', '333', '180', '390', '21', '202', '36', '270', '108', '110', '7', '81', '48'
                        '110', '51', '46', '39'] and not self.last_deposit:
            return
        self.test_value(brief['deposit_amount'], 'deposit_amount', mode)
        #  基本信息里有月缴, 没有缴存基数, 个人缴存额, 没有明细
        #  100-有半缴个人
        if self.cid in {'141', '29', '14', '374', '28', '339', '56', '326', '321', '138', '332', '345', '100'}:
            return
        passed = False
        if mode != '-1':
            try:
                amount = float(brief['deposit_amount'])
            except ValueError:
                return
            # 缴存基数 * 缴存比例
            if brief['deposit_rate'] and brief['deposit_base']:
                rate = float(brief['deposit_rate'])
                base = float(brief['deposit_base'])
                if rate * base - amount < abs(self._deposit_amount_error):
                    passed = True
            # 个人缴存额 + 公司缴存额
            if brief['person_deposit_amount'] and brief['company_deposit_amount']:
                amount = float(brief['deposit_amount'])
                p_da = float(brief['person_deposit_amount'])
                c_da = float(brief['company_deposit_amount'])
                if c_da + p_da - amount < abs(self._deposit_amount_error):
                    passed = True
            # 要有明细 与最新一条汇缴明细比较
            if self.last_deposit:
                last_deposit = float(self.last_deposit)
                if last_deposit - amount < abs(self._deposit_amount_error):
                    passed = True
            if not passed:
                self.build_error(amount, 'deposit_amount', mode, 'a2')

    def check_deposit_base(self, deposit_base):
        if self.cid in ['352', '14']:
            return
        mode = self.get_mode('缴存基数')
        self.test_value(deposit_base, 'deposit_base', mode)

    def check_company(self, company):
        mode = self.get_mode('公司')
        if mode != '-1':
            self.test_value(company, 'company', mode)

    def check_status(self, status):
        mode = self.get_mode('公积金状态')
        self.test_value(status, 'status', mode)

    def check_customer_id(self, customer_id):
        if self.cid in ['14']:
            return
        if self.cid in ['61'] and not self.has_record:
            return
        mode = self.get_mode('公积金账号')
        self.test_value(customer_id, 'customer_id', mode)

    def check_card(self, card):
        if self.cid in ['307']:
            return
        mode = self.get_mode('联名卡号')
        self.test_value(card, 'card', mode)

    def check_company_id(self, company_id):
        mode = self.get_mode('单位账号')

        self.test_value(company_id, 'company_id', mode)

    def check_phone(self, phone):
        mode = self.get_mode('手机号')
        self.test_value(phone, 'phone', mode)

    def check_date(self, i_date, s_date, r_date, ):
        i_mode = self.get_mode('开户时间')
        s_mode = self.get_mode('开始缴存时间')
        mode = self.get_mode('公积金record_date')
        if r_date:
            self.test_value(r_date, 'record_date', mode)
            if not self.farest_date <= r_date <= TODAY:
                self.build_error(r_date, 'record_date', mode, 'k')
                # 从基本信息里取的record_date
                #  明细配置为完整,
                #  if not self.detail_ret.get('end_date'):
                #      #  没有明细, 可能是真的没取到, 可能是销户
                #      if account_state == '1':
                #          self.build_error(date, 'record_date', mode, 'm')
        if self.cid in self._ignore_date_cid:
            return
        if i_date and r_date and i_date > r_date:
            #  init_date
            self.test_value(i_date, 'init_date', i_mode)
            self.build_error([i_date, s_date, r_date], 'init_date', i_mode, 'v')
            return
        if i_date and s_date and i_date > s_date:
            #  start_date
            self.test_value(s_date, 'start_date', s_mode)
            self.build_error([i_date, s_date, r_date], 'init_date', i_mode, 'v')
            return
        if r_date and s_date and s_date > r_date:
            self.build_error([s_date, r_date], 'start_date', s_mode, 'w')
            return

    def check_rate(self, p_rate, c_rate, rate):
        if p_rate and float(p_rate) > 0:
            p_mode = self.get_mode('个人缴存比例')
            self.test_value(p_rate, 'person_rate', p_mode)
        if c_rate and float(c_rate) > 0:
            c_mode = self.get_mode('公司缴存比例')
            self.test_value(c_rate, 'company_rate', c_mode)
        try:
            if rate and float(rate) > 0:
                self.test_value(rate, 'deposit_rate', '1')
        except Exception:
            traceback.print_exc()
            log.error(self.error)

    def check_birthday(self, birthday):
        if birthday:
            self.test_value(birthday, 'birthday', '1')

    def check_balance(self, balance):
        if self.cid in ['207', '14'] and not self.has_record:
            return
        mode = self.get_mode('余额')
        self.test_value(balance, 'balance', mode)

    def check_analyzed(self, doc):
        s = self.user_state(doc)
        if s == doc['gjj_account_analyzed_data']['newest_account']:
            return True
        else:
            self.build_error(doc['gjj_account_analyzed_data']['newest_account'], 'newest_account', '', 'z')

    def check_details(self, details, init_date, bal):
        self.skip_detail(details)
        report = True
        report_id = 0
        item_id = ''
        amount = ''
        for item in details:
            if item['record_month'] and not item['record_date']:
                self.build_error('%s|%s' % (item['id'], item['record_date']), 'detail_record_date', '', 'a8')
            if item['gjj_type'] not in ['0', '1']:
                self.build_error('%s|%s' % (item['id'], item['gjj_type']), 'detail_gjj_type', '', 'a5')
                return
            if item['record_date'] and not re.findall(r'^\d{4}-\d{2}-\d{2}$', item['record_date']):
                self.build_error('%s|%s' % (item['id'], item['record_date']), 'detail_record_date', '', 'a7')
                return
            if item['record_month'] and not re.findall(r'^\d{6}$', item['record_month']):
                self.build_error('%s|%s' % (item['id'], item['record_month']), 'detail_record_month', '', 'a7')
                return
            if item['amount'] and not re.findall(r'^[\d\.\-]+$', item['amount']):
                self.build_error('%s|%s' % (item['id'], item['amount']), 'detail_amount', '', 'a6')
                return
            if item['balance'] and not re.findall(r'^[\d\.\-]+$', item['balance']):
                self.build_error('%s|%s' % (item['id'], item['balance']), 'detail_balance', '', 'a6')
                return
            if re.search('提取|偿还|支取|还贷', item['state']) and '-' in item['amount'] and self.zero(item['amount']):
                report = False
            if re.search('提取|偿还|支取|还贷', item['state']) and not re.search('退回|还贷缴存|失败|公积金偿还利息|冲账|支取红冲|支取退款', item['state']) and '-' not in item['amount'] and self.zero(item['amount']) and report:
                report_id = 2
                item_id = item['id']
                amount = item['amount']
        if report_id == 2 and report:
            self.build_error('%s|%s' % (item_id, amount), 'detail_amount', '', 'a4')
        d = utils.away_today(init_date)
        mode = self.get_mode('公积金明细')
        if mode == '1' and len(details) == 0 and d and d[0] == 0 and d[1] > 2 and self.zero(bal):
            print('%s is added to set' % self.orderId)
            self.need_refresh.add(self.orderId)

    # self.build_error(len(details), 'gjj_details', mode, 'a1')
    #  修复->check_details --> 如果还是出错就报bug

    def check_analyzed_data(self, analyzed):
        if self.cid in ['122']:
            return
        if len(self.const_ret) > 0:
            if int(analyzed['cont_last_times']) != self.const_ret[-1]:
                self.build_error(str(analyzed), 'analyzed', '', 'a3')
                return
            if int(analyzed['cont_max_times']) != max(self.const_ret):
                self.build_error(str(analyzed), 'analyzed', '', 'a3')
                return
            if int(analyzed['sum_times']) != sum(self.const_ret):
                self.build_error(str(analyzed), 'analyzed', '', 'a3')
                return
        if len(self.all_ret) > 0:
            if int(analyzed['back_cont_max_times']) != max(self.all_ret):
                self.build_error(str(analyzed), 'analyzed', '', 'a3')
                return
            if int(analyzed['back_sum_times']) != sum(self.all_ret):
                self.build_error(str(analyzed), 'analyzed', '', 'a3')
                return
            if int(analyzed['back_cont_last_times']) != self.all_ret[-1]:
                self.build_error(str(analyzed), 'analyzed', '', 'a3')
                return

    def test_value(self, raw, col, mode):
        used_rules = configs['use'][col][mode]
        for index in used_rules:
            rule = configs['rules'][index]
            if bool(re.findall(rule['_re'], raw, re.I)) == rule['m']:
                self.build_error(raw, col, mode, index)

    def test_range(self, raw, col):
        """  检查是否在上下限之内   """
        if not raw:
            return
        col = col.replace('缴存', '缴纳')
        col = col.replace('缴纳基数', '基数')
        try:
            if '比例' in col:
                _min = self.get_mode('%s下限' % col) / 100 / self._rate_weight
            else:
                _min = float(self.get_mode('%s下限' % col)) / self._base_weight
        except ValueError:
            _min = 0
        try:
            if '比例' in col:
                _max = self.get_mode('%s上限' % col) / 100 * self._rate_weight
            else:
                _max = float(self.get_mode('%s上限' % col)) * self._base_weight
        except ValueError:
            _max = None
        if _min > round_up(raw):
            return 's'
        if _max and _max < round_up(raw):
            return 't'

    def get_mode(self, col):
        cell = self.infos.ix[int(self.cid), [col]]
        mode = '-1'
        if len(cell) > 0:
            mode = cell[0]
        return mode

    def user_state(self, doc):
        status = doc['gjj_brief']['status']
        record_date = doc['gjj_brief']['record_date']
        if not isinstance(status, str):
            raise TypeError('Status')
        if status:
            if status in self._status_set:
                return '1'
            else:
                return '0'

        datedelta = utils.away_today(record_date)
        if datedelta:
            if datedelta[1] < 3 and datedelta[0] == 0:
                return '1'
            else:
                return '0'
        else:
            return '0'

    def build_error(self, raw, col, mode, rule_index):
        """

        :param raw: 检测的元数据
        :param col: 元数据所在的字段名
        :param mode: 元数据的配置
        :param rule_index: 规则的索引
        :return:
        """
        key = 't_%s' % col
        if self.error.get(key):
            self.error[key] += '|%s' % rule_index
        else:
            self.error[col] = str(raw)
            self.error[key] = '%s|%s|%s' % (col, mode, rule_index)

    @staticmethod
    def test_len(raw, min_len=0, max_len=0):
        try:
            if not min_len <= len(str(raw)) <= max_len:
                rule_index = '4'
                configs['rules'][rule_index] = {'_re': '', 'desc': '长度不在[%d, %d]之内' % (min_len, max_len)}
                return rule_index
                #  return '(%s)-长度不在[%d, %d]之内' % (raw, min_len, max_len)
            return ''
        except Exception:
            log.error(traceback.print_exc())

    def field_integrity(self, doc):
        if doc['gjj_brief']:
            lack = self.brief_keys.difference(doc['gjj_brief'].keys())
            if lack:
                self.build_error(lack, '缺少字段', '', 'y')
        if doc['gjj_detail']:
            for record in doc['gjj_detail']:
                lack = self.record_key.difference(record.keys())
                if lack:
                    self.build_error(lack, '缺少字段', '', 'y')
                    return

    def skip_detail(self, details):
        """
        :param details:
        :return: newest balance, amount, company
        """
        #  提取/偿还/支取/还贷
        raw = []
        history_df = []
        if self.history_record:
            history_df = pd.DataFrame(self.history_record)
            history_df = history_df['record_date'].tolist()
        details.extend(self.history_record)
        for item in details:
            item['state'] = '|'.join([item['remark'], item['deposit_type'], item['comments']])
            op = re.sub('[\d公积金]+', '', item['state'])
            self.op_set.add(op)
            if not (re.search(self.detail_filter, item['state']) or item['record_month'] == ''):
                raw.append(item)
        if len(raw) == 0:
            return
        self.has_record = True
        data = pd.DataFrame(raw)

        df = data.set_index('record_date')
        df = df.sort_values(by='record_month')
        m = n = 0
        for index, row in df[0:].iterrows():
            #  print(row['record_month'], row['state'])
            state = row['state']
            minuend = utils.format_date(row['record_month'])
            if re.search('汇缴|补|缴交|汇交|缴存|交缴|未分摊转入到住房公积金|月缴公积金|半缴|漏缴|^汇\d', state) and not re.search('自定义缴存单位', state):
                if m == 0:
                    all_mark = minuend
                    self.all_ret.append(1)
                    m += 1
                mon_delta = Datedelta(minuend, all_mark)
                if mon_delta.years == 0 and mon_delta.months == 1:
                    self.all_ret[-1] += 1
                elif mon_delta.months > 1 or mon_delta.years > 0:
                    self.all_ret.append(1)
                all_mark = minuend
            if re.search('汇缴|缴交|汇交|缴存|交缴|未分摊转入到住房公积金|月缴公积金|半缴|^汇\d', state) and not re.search('[^汇及含]补|自定义缴存单位|缴存红冲|漏缴', state):
                if n == 0:
                    const_mark = minuend
                    self.const_ret.append(1)
                    n += 1
                mon_delta = Datedelta(minuend, const_mark)
                #  print(mon_delta.years, '_', mon_delta.months)
                far_today = Datedelta(today, minuend)
                if far_today.years == 0 and far_today.months < 4 and index not in history_df:
                    self.last_deposit = row['amount']
                if mon_delta.years == 0 and mon_delta.months == 1:
                    # self.build_error()
                    self.const_ret[-1] += 1
                elif mon_delta.months > 1 or mon_delta.years > 0:
                    self.const_ret.append(1)
                const_mark = minuend
        #  print(self.all_ret, self.const_ret)

    @staticmethod
    def zero(amount):
        try:
            if float(amount) != 0:
                return True
            else:
                return False
        except:
            return False

    def run(self, data):
        """
        check
        :param data:  gjjData['data']
        :return:
        """
        try:
            self.orderId = data['orderId']
            diff = self._keys.issubset(set(data.keys()))
            if not diff:
                self.build_error(diff, '字段缺失或冗余', '', 'y')
            else:
                for gjj_data in data['data']['gjj_data']:
                    if gjj_data['gjj_account_analyzed_data']['newest_account'] != '1':
                        self.history_record.extend(gjj_data['gjj_detail'])
                for gjj_data in data['data']['gjj_data']:
                    self.cid = data['cid']
                    self.field_integrity(gjj_data)
                    if gjj_data['gjj_account_analyzed_data']['newest_account'] != '1':
                        continue
                    self.check_id(gjj_data['gjj_brief']['ID'])
                    self.check_name(gjj_data['gjj_brief']['name'])
                    self.check_company(gjj_data['gjj_brief']['company'])
                    self.check_status(gjj_data['gjj_brief']['status'])
                    self.check_customer_id(gjj_data['gjj_brief']['customer_id'])
                    self.check_card(gjj_data['gjj_brief']['card'])
                    self.check_company_id(gjj_data['gjj_brief']['company_id'])
                    self.check_phone(gjj_data['gjj_brief']['phone'])
                    self.check_balance(gjj_data['gjj_brief']['balance'])
                    #  比较复杂的检查
                    self.check_deposit_base(gjj_data['gjj_brief']['deposit_base'])
                    self.check_date(gjj_data['gjj_brief']['init_date'], gjj_data['gjj_brief']['start_date'],
                                    gjj_data['gjj_brief']['record_date'])
                    self.check_rate(gjj_data['gjj_brief']['person_rate'], gjj_data['gjj_brief']['company_rate'],
                                    gjj_data['gjj_brief']['deposit_rate'])
                    self.check_birthday(gjj_data['gjj_brief']['birthday'])
                    self.check_details(gjj_data['gjj_detail'], gjj_data['gjj_brief']['init_date'],
                                       gjj_data['gjj_brief']['balance'])
                    self.check_deposit_amount(gjj_data['gjj_brief'])
                    self.check_analyzed_data(gjj_data['gjj_account_analyzed_data'])
                    self.all_ret = []
                    self.const_ret = []
            warn_msg = copy.deepcopy(self.error)
            ret = '%s%s' % (data['cityName'], self.cid), warn_msg
            self.__init__()
            return ret
        except Exception as e:
            print('%s is error' % self.orderId)
            traceback.print_exc()
            self.__init__()


class Submit:
    """
    提交异常数据到bugclose
    """

    def __init__(self):
        self.session = requests.Session()
        self.session.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '
                          '(KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36',
            'X-Requested-With': 'XMLHttpRequest',
            'Origin': 'https://www.bugclose.com',
            'Accept': 'application/json, text/javascript, */*; q=0.01',
            'Accept-Encoding': 'gzip, deflate, br',
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        }
        self.token = None
        self.user = 'huangwei@jianbing.com'
        self.pwd = 'Hw123211'

    def login(self):
        url = 'https://www.bugclose.com/cgi/user/login'
        form = {
            'email': self.user,
            'password': self.pwd,
            'inviteCode': '',
        }
        res = self.session.post(url, data=form)
        root = res.json()
        self.token = root['root']
        url = 'https://www.bugclose.com/cgi/project/hasJoined'
        form = {
            'token': root['root'],
            'id': '14124'
        }
        res = self.session.post(url, data=form)
        ret = res.json()

    def submit_bug(self, title, content):
        content = self.format_json(content)
        url = 'https://www.bugclose.com/cgi/bug/add'
        form = {
            'title': title,
            'imageIds': '',
            'bugType': '',
            'attachmentIds': '',
            'priority': 'Urgent',
            'version': '',
            'environment': '',
            'description': content,
            #  产品id
            'productId': '9534',
            #  指向谁 朱: 54396  ,宋:  24452
            'assignToId': '24452',
            'sprintId': '0',
            'planDate': '',
            'dueDate': '',
            'planVersion': '',
            'parentId': '',
            'module': '',
            'workload': '',
            'value': '',
            'tagIds': '',
            'testCaseId': '',
            'testTaskId': '',
            'customValues': '',
            'token': self.token,
            'projectId': '14124',
        }
        res = self.session.post(url, data=form)
        ret = res.json()
        if ret['success']:
            log.info('提交bug成功')
        else:
            time.sleep(30)
            log.warn('%s\n%s' % (title, content))
            log.warn('提交bug失败: %s' % ret)

    def format_json(self, list_data):
        s = ''
        for row in list_data:
            s += str(row) + '\n'
        return s[:1990]


if __name__ == '__main__':
    log.info(configs)
    viewer = Reviewer(yestoday)
    ts = {'gjj_status', 'gjjh5_status'}
    orderids = viewer.find_order_ids(ts)
    viewer.process(orderids)
    # viewer.check_order('ef95904b-75ab-4f00-b82a-d9c2f3709835')
    if viewer.rule.need_refresh:
        viewer.refresh()
        # viewer.process(viewer.rule.need_refresh)
    viewer.out_result()
