예제 #1
0
class Transaction:
    def __init__(self,
                 acc_user,
                 acc_asset='',
                 db=None,
                 table='transactions',
                 columns=[
                     'id', 'acc_user', 'acc_asset', 'nam_asset', 'rmk_asset',
                     'amt_trans', 'tye_asset', 'ico_asset', 'tye_flow',
                     'dte_trans', 'tme_trans', 'acc_asset_related',
                     'nam_asset_related', 'rmk_asset_related',
                     'ico_asset_related', 'tye_asset_related',
                     'cod_trans_type', 'txt_trans_type', 'txt_trans_type_sub',
                     'txt_remark', 'ico_trans'
                 ]):
        self.db = db
        self.table = table
        self.columns = columns
        self.dtype_columns = {}
        self.vdefault_columns = {}
        self.acc_user = acc_user
        self.acc_asset = acc_asset
        self.nam_asset = ''
        self.amt_trans = 0.0
        self.tye_flow = ''
        self.dte_trans = ''
        self.tme_trans = ''
        self.acc_asset_related = ''
        self.nam_asset_related = ''
        self.cod_trans_type = ''
        self.txt_trans_type = ''
        self.txt_trans_type_sub = ''
        self.txt_remark = ''

        if not db:
            self.db = DataBase()

    def show_trans(self, acc_asset=None, id=None):
        sql_asset, sql_id = " ", " "
        if acc_asset:
            sql_asset = " and (acc_asset='%s' or acc_asset_related='%s') " % (
                acc_asset, acc_asset)
        if id:
            sql_id = " and id=%s " % id
        sql_show = "select * from transactions where acc_user='******' %s %s order by dte_trans desc, id desc" % \
                   (self.acc_user, sql_asset, sql_id)
        flag, result = self.db.read(sql_show)
        if flag:
            result['index'] = range(len(result))
            return result
        return pd.DataFrame()

    def add_trans(self, dict_tran, is_transaction=False):
        data, columns = [], []
        for key, value in dict_tran.items():
            columns.append(key)
            data.append(value)
        data_trans = pd.DataFrame(data=[data], columns=columns)
        if not is_transaction:
            flag, result = self.db.write(data_trans, self.table)
            if not flag:
                print(result)
            return flag
        else:
            return data_trans, self.table, False, 'append'

    def show_flow(self, month_now):
        sql_show = """
            select 
                tye_flow,
                right(dte_trans,2) as day,
                sum(case when tye_flow='expend' then -1*amt_trans else amt_trans end) as amount
            from %s
            where acc_user='******'
            and left(dte_trans,6)='%s'
            and tye_flow in ('income', 'expend')
            group by tye_flow, day
            order by tye_flow, day
            """ % (self.table, self.acc_user, month_now)
        flag, result = self.db.read(sql_show)
        if flag:
            return result
        return pd.DataFrame()

    def show_report(self, date, date_length):
        sql_show = """
            select 
                tye_flow,
                cod_trans_type,
                txt_trans_type,
                ico_trans,
                sum(case when tye_flow='expend' then -1*amt_trans else amt_trans end) as amount,
                count(*) as cnt
            from %s
            where acc_user='******'
            and left(dte_trans,%s)='%s'
            and tye_flow in ('income', 'expend', 'transfer')
            group by tye_flow, cod_trans_type, txt_trans_type, ico_trans
            order by tye_flow, amount desc
            """ % (self.table, self.acc_user, date_length, date)
        flag, result = self.db.read(sql_show)
        if flag:
            return result
        return pd.DataFrame()

    def export_trans(self):
        sql_export = """
            select 
                dte_trans as `日期`,
                case when amt_trans<0 then -1*amt_trans else amt_trans end as `金额`,
                case 
                    when tye_flow='income' then '流入' 
                    when tye_flow='expend' then '流出' 
                    else '转账' end as `资金流向`,
                txt_trans_type as `交易类型`,
                rmk_asset as `账户名称`,
                rmk_asset_related as `相关账户名称`,
                txt_remark as `备注`
            from %s
            where acc_user='******'
        """ % (self.table, self.acc_user)
        flag, result = self.db.read(sql_export)
        if flag:
            return result
        return pd.DataFrame()

    # 由于删除交易记录会有资金回流,因此一般情况下禁止直接删除记录,而不做后续处理
    def delete_trans(self, id, is_transaction=True):
        sql_delete = "delete from %s where acc_user='******' and id=%s " % (
            self.table, self.acc_user, id)
        if not is_transaction:
            flag, result = self.db.execute(sql_delete)
            if not flag:
                print(result)
            return flag
        else:
            return sql_delete

    @staticmethod
    def revert_dict(dic):
        res = {}
        for key, value in dic.items():
            res[value] = key
        return res

    @staticmethod
    def date_format(date, target_format='yyyymmdd'):
        def date_fill(date_part):
            if len(date_part) == 1:
                date_part = '0%s' % date_part
            return date_part[:2]

        for seg in ['-', '/']:
            if seg in date:
                y, m, d = date.split(' ')[0].split(seg)[:3]
                m = date_fill(m)
                d = date_fill(d)
                date = '%s%s%s' % (y, m, d)
                break
        return date[:8]

    @staticmethod
    def extract_date_column(dic_db2file_columns):
        date_columns = []
        for key, value in dic_db2file_columns.items():
            if key.startswith('dte'):
                date_columns.append(value)
        return date_columns

    def process_column_dtype(self, table_structure, dic_db2file_columns):
        if not self.dtype_columns:
            for Field, Type in table_structure.values[:, :2]:
                column = Field.lower()
                if Type.startswith('decimal'):
                    self.dtype_columns[column] = float
                    self.vdefault_columns[column] = 0.0
                elif Type.startswith('integer'):
                    self.dtype_columns[column] = int
                    self.vdefault_columns[column] = 0
                else:
                    self.dtype_columns[column] = str
                    self.vdefault_columns[column] = ''

        dtype_file_columns = {}
        vdefault_file_columns = {}
        for column, file_column in dic_db2file_columns.items():
            dtype_file_columns[file_column] = self.dtype_columns[column]
            vdefault_file_columns[file_column] = self.vdefault_columns[column]

        return dtype_file_columns, vdefault_file_columns

    def create_from_transactions(self, file_transactions, dic_db2file_columns):
        flag, result = self.db.read('desc %s' % self.table)
        if flag:
            df_table_structure = result
            date_columns = self.extract_date_column(dic_db2file_columns)
            dtype_file_columns, vdefault_file_columns = self.process_column_dtype(
                df_table_structure, dic_db2file_columns)
            df_data = pd.read_excel(file_transactions, dtype=dtype_file_columns)[dtype_file_columns.keys()].\
                fillna(value=vdefault_file_columns)
            for date_column in date_columns:
                df_data[date_column] = df_data[date_column].apply(
                    self.date_format)
            df_data = df_data.rename(
                columns=self.revert_dict(dic_db2file_columns))
            # auto fill
            len_df_data = len(df_data)
            next_id = load_next_id(self.table, self.db)
            df_data['id'] = [next_id + i for i in range(len_df_data)]
            df_data['acc_user'] = [self.acc_user] * len_df_data
            for column in self.columns:
                if column not in df_data.columns:
                    df_data[column] = [self.vdefault_columns[column]
                                       ] * len_df_data
            flag, result = self.db.write(df_data, self.table)
            if not flag:
                print(result)
            return flag
        return flag
예제 #2
0
class Statistic:
    def __init__(self, acc_user, dte_month=None, db=None, table='statistics',
                 columns=['id', 'acc_user', 'dte_month', 'amt_income_month', 'amt_expend_month', 'amt_budget',
                          'amt_budget_surplus', 'amt_debt_total', 'amt_asset_total', 'amt_asset_net']):
        self.db = db
        self.table = table
        self.columns = columns
        self.acc_user = acc_user
        self.dte_month = dte_month

        if not self.db:
            self.db = DataBase()

    def init_statistics(self):
        if not self.dte_month:
            self.dte_month = time.strftime("%Y%m", time.localtime())
        df_statistics = pd.DataFrame(
            columns=['acc_user', 'dte_month'],
            data=[[self.acc_user, self.dte_month]])
        flag, result = self.db.write(df_statistics, self.table)
        return flag, result

    # 为避免使用contab等定时工具,需要在执行statistics相关的操作之前,检查是否是新月,来决定是否清空月统计数据
    def reset_statistics(self):
        dte_month_now = time.strftime("%Y%m", time.localtime())
        sql_update = """
            update %s 
            set  	
                amt_income_month = case when dte_month='%s' then amt_income_month else 0 end,
                amt_expend_month = case when dte_month='%s' then amt_expend_month else 0 end,
		dte_month = case when dte_month='%s' then dte_month else '%s' end
            where acc_user='******' 
            """ % (self.table, dte_month_now, dte_month_now, dte_month_now, dte_month_now, self.acc_user)
        flag, result = self.db.execute(sql_update)
        # print(sql_update, flag, result)
	if not flag:
            print(result)
        return flag

    def show_statistics(self):
        self.reset_statistics()

        sql_show = " select * from %s where acc_user='******' " % (self.table, self.acc_user)
        flag, result = self.db.read(sql_show)
        if not flag:
            print(result)
            return pd.DataFrame()
        else:
            return result

    def update_statistics(self, tye_amount, amount, cod_trans_type='', tye_asset='', tye_asset_related='', tye_update='add', is_transaction=False):
        """
        :param tye_update: ['add', 'delete_trans', 'delete_asset']
        :param tye_amount: ['income', 'expend', 'transfer', 'budget', 'asset', 'debt']
        :param amount: 根据type_amount,取对应的值或者相反数
        :param cod_trans_type: 交易类型代码
        :param tye_asset: 资产账户类型
        :param tye_asset_related: 相关联的资产账户类型
        :param is_transaction: 为False则直接执行;为True则返回sql语句,待后续按照数据库事务规范执行
        :return: 返回执行结果或返回适用于数据库事务的sql
        """
        self.reset_statistics()

        sql_set = " amt_asset_total = amt_asset_total "
        if tye_update == 'add':
            if tye_amount == 'income':     # 流入
                if tye_asset == 'asset':
                    if cod_trans_type in ('yqkDZNq7', 'xSTyQpeH'):  # 退款、报销,不计入收入,但支出、预算剩余应减少
                        sql_set = " amt_asset_total = amt_asset_total + %s, amt_asset_net = amt_asset_net + %s, amt_expend_month = amt_expend_month + %s, amt_budget_surplus = amt_budget + amt_expend_month " % tuple([amount]*3)
                    else:
                        sql_set = " amt_income_month = amt_income_month + %s, amt_asset_total = amt_asset_total + %s, amt_asset_net = amt_asset_net + %s " % tuple([amount]*3)
                elif tye_asset == 'debt':
                    if cod_trans_type in ('yqkDZNq7', 'xSTyQpeH'):  # 退款、报销,不计入收入,但支出、预算剩余应减少
                        sql_set = " amt_debt_total = amt_debt_total + %s, amt_asset_net = amt_asset_net + %s, amt_expend_month = amt_expend_month + %s, amt_budget_surplus = amt_budget + amt_expend_month " % tuple([amount]*3)
                    else:
                        sql_set = " amt_income_month = amt_income_month + %s, amt_debt_total = amt_debt_total + %s, amt_asset_net = amt_asset_net + %s " % tuple([amount]*3)
            elif tye_amount == 'expend':   # 流出
                if tye_asset == 'asset':
                    sql_set = " amt_expend_month = amt_expend_month + %s, amt_budget_surplus = amt_budget + amt_expend_month, amt_asset_total = amt_asset_total + %s, amt_asset_net = amt_asset_net + %s " % tuple([amount]*3)
                elif tye_asset == 'debt':
                    sql_set = " amt_expend_month = amt_expend_month + %s, amt_budget_surplus = amt_budget + amt_expend_month, amt_debt_total = amt_debt_total + %s, amt_asset_net = amt_asset_net + %s " % tuple([amount]*3)
            elif tye_amount == 'transfer': # 转账
                if tye_asset == 'asset' and tye_asset_related == 'debt':    # 资产负债都减少,但数值一减一增
                    sql_set = " amt_asset_total = amt_asset_total - %s, amt_debt_total = amt_debt_total + %s " % tuple([amount]*2)
                elif tye_asset == 'debt' and tye_asset_related == 'asset':  # 资产负债都增加,但数值一增一减
                    sql_set = " amt_asset_total = amt_asset_total + %s, amt_debt_total = amt_debt_total - %s " % tuple([amount]*2)
            elif tye_amount == 'budget':
                sql_set = " amt_budget = %s, amt_budget_surplus = %s + amt_expend_month " % tuple([amount]*2)
            elif tye_amount == 'asset':
                sql_set = " amt_asset_total = amt_asset_total + %s, amt_asset_net = amt_asset_net + %s " % tuple([amount] * 2)
            elif tye_amount == 'debt':
                sql_set = " amt_debt_total = amt_debt_total + %s, amt_asset_net = amt_asset_net + %s " % tuple([amount] * 2)
        elif tye_update == 'delete_trans':  # 删除交易记录会引起资产账户变动
            if tye_amount == 'income':     # 原交易记录为流入
                if cod_trans_type in ('yqkDZNq7', 'xSTyQpeH'):  # 退款、报销
                    sql_set = " amt_asset_total = amt_asset_total - %s, amt_asset_net = amt_asset_net - %s, amt_expend_month = amt_expend_month - %s, amt_budget_surplus = amt_budget + amt_expend_month " % tuple([amount]*3)
                else:
                    sql_set = " amt_income_month = amt_income_month - %s, amt_asset_total = amt_asset_total - %s, amt_asset_net = amt_asset_net - %s " % tuple([amount]*3)
            elif tye_amount == 'expend':   # 原交易记录为流出
                if tye_asset == 'asset':
                    sql_set = " amt_expend_month = amt_expend_month - %s, amt_budget_surplus = amt_budget + amt_expend_month, amt_asset_total = amt_asset_total - %s, amt_asset_net = amt_asset_net - %s " % tuple([amount]*3)
                elif tye_asset == 'debt':
                    sql_set = " amt_expend_month = amt_expend_month - %s, amt_budget_surplus = amt_budget + amt_expend_month, amt_debt_total = amt_debt_total - %s, amt_asset_net = amt_asset_net - %s " % tuple([amount]*3)
            elif tye_amount == 'transfer': # 原交易记录为转账
                if tye_asset == 'asset' and tye_asset_related == 'debt':    
                    sql_set = " amt_asset_total = amt_asset_total + %s, amt_debt_total = amt_debt_total - %s " % tuple([amount]*2)
                elif tye_asset == 'debt' and tye_asset_related == 'asset': 
                    sql_set = " amt_asset_total = amt_asset_total - %s, amt_debt_total = amt_debt_total + %s " % tuple([amount]*2)
            elif tye_amount == 'adjust':    # 原交易记录为资金调整
                if tye_asset == 'asset':    
                    sql_set = " amt_asset_total = amt_asset_total - %s, amt_asset_net = amt_asset_net - %s " % tuple([amount]*2)
                elif tye_asset == 'debt': 
                    sql_set = " amt_debt_total = amt_debt_total - %s, amt_asset_net = amt_asset_net - %s " % tuple([amount]*2)
        elif tye_update == 'delete_asset':
            if tye_asset == 'asset':    
                sql_set = " amt_asset_total = amt_asset_total - %s, amt_asset_net = amt_asset_net - %s " % tuple([amount]*2)
            elif tye_asset == 'debt':
                sql_set = " amt_debt_total = amt_debt_total - %s, amt_asset_net = amt_asset_net - %s " % tuple([amount] * 2)

        sql_update = "update %s set %s where acc_user ='******'" % (self.table, sql_set, self.acc_user)
        print('sql_update_statistics', sql_update)

        if not is_transaction:
            flag, result = self.db.execute(sql_update)
            if not flag:
                print(result)
            return flag
        else:
            return sql_update
예제 #3
0
class User:
    def __init__(self,
                 acc_user=None,
                 pwd_user_md5=None,
                 db=None,
                 table='users',
                 columns=[
                     'id', 'acc_user', 'pwd_user_md5', 'nam_user', 'vlu_email',
                     'vlu_phone', 'vlu_openid', 'nam_nick', 'cod_gender',
                     'vlu_lang', 'vlu_city', 'vlu_prov', 'vlu_country',
                     'url_avatar'
                 ]):
        self.db = db
        self.table = table
        self.columns = columns
        self.acc_user = acc_user
        self.pwd_user_md5 = pwd_user_md5
        self.nam_user = ''
        self.vlu_email = ''
        self.vlu_phone = ''
        self.vlu_openid = ''

        if not self.db:
            self.db = DataBase()

    def show_userinfo(self):
        sql_show = "select * from %s where acc_user='******' " % (self.table,
                                                              self.acc_user)
        flag, result = self.db.read(sql_show)
        if not flag:
            print(result)
            return pd.DataFrame()
        else:
            return result

    def save_userinfo(self, userinfo, is_transaction=False):
        if not self.acc_user:
            self.acc_user = gen_short_uuid()
        self.pwd_user_md5 = get_md5(self.acc_user)

        sql_delete = "delete from %s where acc_user='******' " % (self.table,
                                                              self.acc_user)

        columns = ['acc_user', 'pwd_user_md5', 'vlu_openid']
        data = [self.acc_user, self.pwd_user_md5, userinfo['vlu_openid']]
        for key, column in dict_mapping.items():
            columns.append(column)
            data.append(userinfo.get(key, ''))
        df_userinfo = pd.DataFrame(data=[data], columns=columns)

        if not is_transaction:
            flag, result = self.db.execute(sql_delete)
            if not flag:
                print(result)
                return False
            else:
                flag, result = self.db.write(df_userinfo, self.table)
                if not flag:
                    print(result)
                return False
            return True
        else:
            return sql_delete, df_userinfo, self.table, False, 'append'

    def create(self):
        if not self.acc_user:
            self.acc_user = gen_short_uuid()
        self.pwd_user_md5 = get_md5(self.acc_user)

        columns = ['acc_user', 'pwd_user_md5', 'vlu_openid']
        data = [self.acc_user, self.pwd_user_md5, self.vlu_openid]
        df_user = pd.DataFrame(data=[data], columns=columns)
        flag, result = self.db.write(df_user, self.table)

        if flag:
            return self.acc_user
        else:
            print(result)
            return False

    def user_check(self, openid):
        self.vlu_openid = openid

        sql_check = "select acc_user from %s where vlu_openid='%s' " % (
            self.table, self.vlu_openid)
        flag, result = self.db.read(sql_check)

        if flag and not result.empty:
            self.acc_user = result['acc_user'][0]
            flag_new = False
        else:
            self.acc_user = self.create()
            flag_new = True
        return self.acc_user, flag_new
예제 #4
0
class Asset:
    def __init__(self,
                 acc_user,
                 db=None,
                 table='assets',
                 columns=[
                     'id', 'acc_user', 'acc_asset', 'nam_asset', 'rmk_asset',
                     'tye_asset', 'amt_asset', 'ico_asset', 'boo_active'
                 ]):
        self.db = db
        self.table = table
        self.columns = columns
        self.acc_user = acc_user
        self.df_asset = pd.DataFrame()

        if not self.db:
            self.db = DataBase()

    def show_assets(self, acc_asset=None, flag_active=1, need_index=True):
        """
        :param db:
        :param flag_active: 1, 0, 'all'
        :return:
        """
        sql_active, sql_asset = " ", " "
        if flag_active in (0, 1):
            sql_active = " and boo_active='%s' " % flag_active
        if acc_asset:
            sql_asset = " and acc_asset='%s' " % acc_asset
        sql_show = "select * from assets where acc_user='******' %s %s order by id" % (
            self.acc_user, sql_active, sql_asset)

        flag, result = self.db.read(sql_show)
        if flag:
            if need_index:
                result['index'] = range(len(result))
            return result
        return pd.DataFrame()

    def add_assets(self, dict_asset, is_transaction=False):
        if not dict_asset.has_key('acc_asset'):
            dict_asset['acc_asset'] = gen_short_uuid()
        data, columns = [], []
        for key, value in dict_asset.items():
            columns.append(key)
            data.append(value)
        data_asset = pd.DataFrame(data=[data], columns=columns)
        if not is_transaction:
            flag, result = self.db.write(data_asset, self.table)
            return flag
        else:
            return data_asset, self.table, False, 'append'

    # 用于资产账户信息的更改
    def modify_assets(self, acc_asset, df_asset, is_transaction=False):
        # 由于中文编码有问题,所以update改为delete+insert
        sql_delete = "delete from %s where acc_user='******' and acc_asset='%s'" % (
            self.table, self.acc_user, acc_asset)
        if not is_transaction:
            flag, result = self.db.execute(sql_delete)
            if not flag:
                print(result)
                return False
            else:
                flag, result = self.db.write(df_asset, self.table)
                if not flag:
                    print(result)
                    return False
            return True
        else:
            return sql_delete, self.table, False, 'append'

    # 用于交易等相关数据库事务的更新
    def update_assets(self,
                      tye_flow,
                      amount,
                      acc_asset,
                      tye_asset,
                      acc_asset_related,
                      tye_asset_related,
                      tye_update='add',
                      is_transaction=False):
        """
        :param tye_flow: ['income', 'expend', 'transfer', 'adjust']
        :param tye_update: ['add', 'delete_trans', 'delete_asset']
        """
        sql_update_assets, sql_update_assets_related = "", ""
        sql_template = "update %s set amt_asset=amt_asset %s %s where acc_user='******' and acc_asset='%s' "
        if tye_update == 'add':
            if tye_flow == 'transfer':  # 账面金额一减一增
                sql_update_assets = sql_template % (self.table, '-', amount,
                                                    self.acc_user, acc_asset)
                sql_update_assets_related = sql_template % (
                    self.table, '+', amount, self.acc_user, acc_asset_related)
            elif tye_flow in ('income', 'expend'):
                sql_update_assets = sql_template % (self.table, '+', amount,
                                                    self.acc_user, acc_asset)
            else:
                pass
        elif tye_update == 'delete_trans':  # 删除交易记录会引起资产账户变动
            if tye_flow == 'transfer':
                sql_update_assets = sql_template % (self.table, '+', amount,
                                                    self.acc_user, acc_asset)
                sql_update_assets_related = sql_template % (
                    self.table, '-', amount, self.acc_user, acc_asset_related)
            elif tye_flow in ('income', 'expend', 'adjust'):
                sql_update_assets = sql_template % (self.table, '-', amount,
                                                    self.acc_user, acc_asset)
            else:
                pass
        elif tye_update == 'delete_asset':
            pass
        else:
            pass

        print('sql_update_assets', sql_update_assets)
        print('sql_update_assets_related', sql_update_assets_related)

        if not is_transaction:
            if sql_update_assets:
                flag, result = self.db.execute(sql_update_assets)
                if not flag:
                    print(result)
                    return False
                else:
                    if sql_update_assets_related:
                        flag, result = self.db.execute(
                            sql_update_assets_related)
                        if not flag:
                            print(result)
                            return False
            return True
        else:
            return sql_update_assets, sql_update_assets_related

    # 由于删除账户会有资产变动,因此一般情况下禁止直接删除账户,而不做后续处理
    def delete_assets(self, acc_asset, is_transaction=True):
        sql_delete = "delete from %s where acc_user='******' and acc_asset='%s' " % (
            self.table, self.acc_user, acc_asset)
        if not is_transaction:
            flag, result = self.db.execute(sql_delete)
            if not flag:
                print(result)
            return flag
        else:
            return sql_delete

    # 适用于导入交易记录时自动创建交易类型
    def create_from_transactions(self, df_transactions):
        next_id = load_next_id()

        data_asset = []
        nam_asset_list = df_transactions['nam_asset'].unique()
        for i in range(len(nam_asset_list)):
            id = next_id + i
            nam_asset = nam_asset_list[i]
            acc_asset = gen_short_uuid()
            tye_asset = ''
            amt_asset = 0.0
            data_asset.append([
                id, self.acc_user, acc_asset, nam_asset, tye_asset, amt_asset
            ])
        self.df_asset = pd.DataFrame(data=data_asset, columns=self.columns)
        flag, result = DataBase().write(self.df_asset, self.table)
        print(flag, result)

        return self.acc_user