from .MerchantCalc import MerchantCalc, mch_detail_paths, mch_paths from .algorithm import calc_mch_profit from .DataStream import EMchPosmap as pos_map from .DataStream import day_stamp import logging import time as time import logging import json logger = logging.getLogger('MProfitRatioCalc') def mixed_ratio(rclient): result = list() data = rclient.get('nc_refill-stat-merchant-mixed') if data is not None: mch_cfgs = json.loads(data) for mchid, val in mch_cfgs.items(): mchid = int(mchid) period = int(val['period']) formula = val['profit_formula'].strip() result.append((mchid, period, formula)) return result class MProfitRatioCalc(MerchantCalc): def _calc_handler(self, rclient): logger.debug('_calc_handler') mixed_ratios = mixed_ratio(rclient) reader = self._reader() gross = dict() detail = dict() types = dict() _fix = False for mchid, period, formula in mixed_ratios: logger.debug(f'mchid={mchid} period={period}') end_time = int(time.time()) if period == 86401: cur_day = day_stamp(end_time) period = end_time - cur_day _fix = True logger.debug(f'mchid={mchid} period={period}') days, start_time, end_time = self.calc_time(reader, end_time - period, end_time) if len(days) == 0: continue stamp = days[0] tuple_pathes = reader.many_tuple_path(days, mchids={mchid}) gen = mch_detail_paths(reader, tuple_pathes, days) start = start_time - stamp end = end_time - stamp types_detail = {} spec_amount = 0.0 for _mchid, _card_type, _spec, _data in gen: submit_count, succ_count, fail_count, succ_ratio, profit = calc_mch_profit(_data, pos_map, start, end) if _card_type is None and _spec is None: if _fix == True and succ_count == 0: profit += 5 spec_amount += 5 profit_ratio = round(profit / (spec_amount + 0.0000001), 6) gross[_mchid] = [submit_count, succ_count, fail_count, succ_ratio, profit, profit_ratio] spec_amount = 0.0 else: key = f"{_mchid}-{_card_type}-{_spec}" amount = succ_count * _spec spec_amount += amount profit_ratio = round(profit / (amount + 0.0000001), 6) detail[key] = [submit_count, succ_count, fail_count, succ_ratio, profit, profit_ratio] if _card_type not in types_detail: types_detail[_card_type] = [] types_detail[_card_type].append((submit_count, succ_count, fail_count, succ_ratio, profit, profit_ratio, _spec)) _mch_type_detail = self._calc_types_detail(mchid, types_detail) types.update(_mch_type_detail) result = {'gross': gross, 'detail': detail, 'types': types} logger.debug(f'profit_ratio={result}') if len(gross) != 0 or len(detail) != 0: rclient.set(f"nc_refill_merchant_profit_ratio", json.dumps(result)) rclient.publish('refill', json.dumps({'type': 'mch_profit_ratio', 'value': 0})) return 5 def _calc_types_detail(self, _mchid, types_detail): result = {} for _card_type, vals in types_detail.items(): key = f'{_mchid}-{_card_type}' submit_count, succ_count, fail_count, succ_ratio, profit, profit_ratio = 0, 0, 0, 0.0, 0.0, 0.0 spec_amount = 0 for item in vals: _submit_count, _succ_count, _fail_count, _succ_ratio, _profit, _profit_ratio, _spec = item submit_count += _submit_count succ_count += _succ_count fail_count += _fail_count profit += _profit spec_amount += _spec * _succ_count succ_ratio = round(succ_count / (succ_count + fail_count + 0.0000001), 6) profit_ratio = round(profit / (spec_amount + 0.000001), 6) result[key] = [submit_count, succ_count, fail_count, succ_ratio, profit, profit_ratio] return result