def generate_scores_distributions_pipeline(min_score: int, max_score: int, distribution_count: int): if max_score == 0: raise ScoringException(4, 'maxScore cannot be zero!') if min_score >= max_score: raise ScoringException(4, 'minScore cannot be bigger or equal maxScore!') if distribution_count == 0 and distribution_count > max_score: raise ScoringException(4, 'step cannot be zero or bigger than maxScore!') step = (max_score - min_score) // distribution_count start = min_score end = start + step pipeline = [] facet_dict = {} project_dict = {} for i in range(distribution_count): # add facet part items key = str(start) + SCORE_DISTRIBUTION_SEPARATOR + str(end) f_dict_first_item: {} = get_facet_dict_match_item(start, end) f_dict_second_item: {} = {"$count": COUNT_KEY} facet_dict_array_items = [f_dict_first_item, f_dict_second_item] facet_dict.__setitem__(key, facet_dict_array_items) # add project part items p_dict_item = get_project_dict_item(start, end) project_dict.__setitem__(key, p_dict_item) start = end + 1 end = (start + step - 1) if i < (distribution_count - 2) else max_score pipeline.append({"$facet": facet_dict}) pipeline.append({"$project": project_dict}) return pipeline
def generate_score_changes_max_in_month_interval_pipeline(dates: list): if dates is None: raise ScoringException(5, 'dates list can not be None!') if len(dates) < 2: raise ScoringException(5, 'dates list should be have at least 2 items!') dates.sort() pipeline = [] facet_dict = {} start_date = dates[ZERO] key = "month" for i in range(1, len(dates)): facet_dict_array_items = [ get_facet_dict_match_item(start_date, dates[i]), # add facet match item get_facet_dict_bucket_item(min_score, max_score), # add facet bucket item get_bucket_project_item() # add facet' bucket project item ] # facet_dict.__setitem__((key + str(i)), facet_dict_array_items) facet_dict.__setitem__(str(start_date.isoformat()), facet_dict_array_items) start_date = dates[i] pipeline.append({"$facet": facet_dict}) return pipeline
def get_score_reason_by_rule_code(self, rule_code: str) -> ScoreReason: if rule_code is None: raise ScoringException(2, 'rule_code is empty!') dic = self.db.scoreReasons.find_one({RULE_CODES: rule_code}) if dic is None: return ScoreReason() return ScoreReason.parse_obj(dic)
def get_user_cheque(self, user_id: int) -> Cheque: if user_id is None: raise ScoringException(3, 'user_id can not be None!') dic = self.db.cheques.find_one({USER_ID: user_id}) if dic is None: return Cheque() return Cheque.parse_obj(dic)
def get_cheques(self, filter_dict: {}) -> List[Cheque]: if filter_dict is None: raise ScoringException(2, 'filter_dict is empty!') dic = self.db.cheques.find(filter_dict) if dic is None: return [] return parse_obj_as(List[Cheque], dic)
def get_user_loan(self, user_id: int) -> Loan: if user_id is None: raise ScoringException(3, 'user_id can not be None!') dic = self.db.loans.find_one({USER_ID: user_id}) if dic is None: return Loan() return Loan.parse_obj(dic)
def get_loans(self, filter_dict: {}) -> List[Loan]: if filter_dict is None: raise ScoringException(2, 'filter_dict is empty!') dic = self.db.loans.find(filter_dict) if dic is None: return [] return parse_obj_as(List[Loan], dic)
def get_user_undone_trade(self, user_id: int) -> UndoneTrade: if user_id is None: raise ScoringException(3, 'user_id can not be None!') dic = self.db.undoneTrades.find_one({USER_ID: user_id}) if dic is None: return UndoneTrade() return UndoneTrade.parse_obj(dic)
def get_undone_trades(self, filter_dict: {}) -> List[UndoneTrade]: if filter_dict is None: raise ScoringException(2, 'filter_dict is empty!') dic = self.db.undoneTrades.find(filter_dict) if dic is None: return [] return parse_obj_as(List[UndoneTrade], dic)
def get_user_profile(self, user_id: int) -> Profile: if user_id is None: raise ScoringException(3, 'user_id can not be None!') dic = self.db.profiles.find_one({USER_ID: user_id}) if dic is None: return Profile() return Profile.parse_obj(dic)
def get_users_scores(self, user_ids: [int]) -> List[UserScoreDTO]: if user_ids is None or len(user_ids) == ZERO: raise ScoringException(4, 'user_ids can not be Empty!') profiles: [Profile] = self.get_users_profiles(user_ids) usr_scr_dtos: [UserScoreDTO] = [] for p in profiles: usr_scr_dtos.append(UserScoreDTO(user_id=p.user_id, score=p.score)) return usr_scr_dtos
def get_users_profiles(self, user_ids: [int]): if user_ids is None or len(user_ids) == ZERO: raise ScoringException(4, 'user_ids can not be Empty!') p_cursor = self.db.profiles.find({USER_ID: {'$in': user_ids}}) profiles: [Profile] = [] while p_cursor.alive: profiles.append(Profile.parse_obj(p_cursor.next())) return profiles
def get_score_changes(self, user_id: int) -> List[ScoreChangeDTO]: if user_id is None: raise ScoringException(3, 'user_id can not be None!') score_changes: [ScoreChange] = self.get_user_score_changes(user_id) scr_dtos: [ScoreChangeDTO] = [] for sch in score_changes: scr_dtos.append(create_score_changes_dto(sch)) return scr_dtos
def get_vosouq_status(self, user_id: int) -> VosouqStatusDTO: if user_id is None: raise ScoringException(3, 'user_id can not be None!') # load profile pf: Profile = self.get_user_profile(user_id) if pf.membership_date is None: pf.membership_date = date.today() # calc membership duration membership_duration = calculate_dates_diff_by_months_and_days( datetime(year=pf.membership_date.year, month=pf.membership_date.month, day=pf.membership_date.day), datetime.today()) # load & calc doneTrade # load doneTrade dt: DoneTrade = self.get_user_done_trade(user_id) # calc all doneTrades count dt_count = get_zero_if_none(dt.timely_trades_count_of_last_3_months) + get_zero_if_none(dt.timely_trades_count_between_last_3_to_12_months) \ + get_zero_if_none(dt.past_due_trades_count_of_last_3_months) + get_zero_if_none(dt.past_due_trades_count_between_last_3_to_12_months) \ + get_zero_if_none(dt.arrear_trades_count_of_last_3_months) + get_zero_if_none(dt.arrear_trades_count_between_last_3_to_12_months) # calc delayed doneTrades count delay_days_avg = 0 if dt_count > 0: delayed_dt_count = dt_count - (get_zero_if_none( dt.timely_trades_count_of_last_3_months) + get_zero_if_none( dt.timely_trades_count_between_last_3_to_12_months)) # calc delayDays' avg delay_days_avg = 0 if delayed_dt_count == 0 else dt.total_delay_days // delayed_dt_count # calc negativeStatus count # todo: this field should be calculated later based on negative_histories which should be provided negative_status_count = 0 # load & calc undoneTrade udt: UndoneTrade = self.get_user_undone_trade(user_id) # calc all undoneTrades count udt_count = get_zero_if_none( udt.undue_trades_count) + get_zero_if_none( udt.past_due_trades_count) + get_zero_if_none( udt.arrear_trades_count) # make & return VosouqStatusDTO return create_vosouq_status_dto(membership_duration[DAYS], membership_duration[MONTHS], dt_count, udt_count, negative_status_count, delay_days_avg, pf.recommended_to_others_count)
def get_score_time_series(self, user_id: int, number_of_days: int) -> List[ScoreTimeSeriesDTO]: if user_id is None: raise ScoringException(3, 'user_id can not be None!') end_date = date.today() start_date = end_date - timedelta(number_of_days) score_ts: [ScoreTimeSeries ] = self.get_db_score_time_series(user_id, start_date, end_date) score_changes_dtos: [ScoreTimeSeriesDTO] = [] for ts in score_ts: score_changes_dtos.append( ScoreTimeSeriesDTO(score_date=ts.score_date, score=ts.score)) return score_changes_dtos
def get_db_score_time_series(self, user_id: int, start_date: date, end_date: date) -> List[ScoreTimeSeries]: if user_id is None: raise ScoringException(3, 'user_id can not be None!') start_date = dateutil.parser.parse(start_date.isoformat()) end_date = dateutil.parser.parse(end_date.isoformat()) ret_list = list( self.db.scoreTimeSeries.find({ USER_ID: user_id, SCORE_DATE: { "$gte": start_date, "$lte": end_date } })) return parse_obj_as(List[ScoreTimeSeries], ret_list)
def get_user_score_changes(self, user_id: int) -> List[ScoreChange]: if user_id is None: raise ScoringException(3, 'user_id can not be None!') ret_list = list(self.db.scoreChanges.find({USER_ID: user_id})) return parse_obj_as(List[ScoreChange], ret_list)
def get_rule(self, filter_dict: {}) -> Rule: if filter_dict is None: raise ScoringException(1, 'filter_dict is empty!') return self.db.rules.find_one(filter_dict)
def get_score_details(self, user_id: int) -> ScoreDetailsDTO: if user_id is None: raise ScoringException(3, 'user_id can not be None!') pf: Profile = self.get_user_profile(user_id) return create_score_details_dto(pf)
def get_cheques_status(self, user_id: int) -> ChequesStatusDTO: if user_id is None: raise ScoringException(3, 'user_id can not be None!') ch: Cheque = self.get_user_cheque(user_id) return create_cheque_status_dto(ch)
def get_loans_status(self, user_id: int) -> LoansStatusDTO: if user_id is None: raise ScoringException(3, 'user_id can not be None!') ln: Loan = self.get_user_loan(user_id) return create_loan_status_dto(ln)
def get_score_status(self, user_id: int) -> ScoreStatusDTO: if user_id is None: raise ScoringException(3, 'user_id can not be None!') pf: Profile = self.get_user_profile(user_id) gs = self.get_score_gauges() return create_score_status_dto(pf.score, gs, 8, datetime.today())