def get(self): """Return salesperson of an account """ context = pecan.request.context user_id = self.user_id conn = pecan.request.db_conn account = conn.get_account(context, user_id) sales_id = account.sales_id if not sales_id: # Only allow sales admin to know that an account # belongs to no salesperson. check_policy(context, 'uos_sales_admin') return models.SalesPerson() # Only allow salesperson to get account that # belongs to himself/herself. if not acl.limit_to_sales(context, sales_id): raise exception.NotAuthorized() try: sales_user = kunkka.get_uos_user(sales_id) return models.SalesPerson( user_id=sales_id, user_name=sales_user['name'], user_email=sales_user.get('email', ''), real_name=sales_user.get('real_name', ''), mobile_number=sales_user.get('phone', ''), company=sales_user.get('company', '') ) except (exception.NotFound): msg = _('Could not find salesperson %s of account %s' ' from keystone' % (sales_id, user_id)) LOG.error(msg) raise exception.NotFound(msg)
def get(self, offset=None, limit=None): """Get the accounts of this sales person.""" context = pecan.request.context if not acl.limit_to_sales(context, self.sales_id): raise exception.NotAuthorized() if limit and limit < 0: raise exception.InvalidParameterValue(err="Invalid limit") if offset and offset < 0: raise exception.InvalidParameterValue(err="Invalid offset") conn = pecan.request.db_conn accounts_number, sales_amount = conn.get_salesperson_amount( context, self.sales_id) accounts = conn.get_salesperson_customer_accounts( context, self.sales_id, offset, limit) account_list = [] for account in accounts: user = kunkka.get_uos_user(account.user_id) account_list.append( models.SalesPersonAccount(user_id=account.user_id, user_name=user['name'], user_email=user.get('email', ''), real_name=user.get('real_name', ''), mobile_number=user.get('phone', ''), company=user.get('company', ''), balance=account.balance, consumption=account.consumption, owed=account.owed)) return models.SalesPersonAccounts(total_count=accounts_number, accounts=account_list)
def get(self, offset=None, limit=None): """Get the accounts of this sales person.""" context = pecan.request.context if not acl.limit_to_sales(context, self.sales_id): raise exception.NotAuthorized() if limit and limit < 0: raise exception.InvalidParameterValue(err="Invalid limit") if offset and offset < 0: raise exception.InvalidParameterValue(err="Invalid offset") conn = pecan.request.db_conn accounts_number, sales_amount = conn.get_salesperson_amount( context, self.sales_id) accounts = conn.get_salesperson_customer_accounts( context, self.sales_id, offset, limit) account_list = [] for account in accounts: user = kunkka.get_uos_user(account.user_id) account_list.append( models.SalesPersonAccount( user_id=account.user_id, user_name=user['name'], user_email=user.get('email', ''), real_name=user.get('real_name', ''), mobile_number=user.get('phone', ''), company=user.get('company', ''), balance=account.balance, consumption=account.consumption, owed=account.owed ) ) return models.SalesPersonAccounts( total_count=accounts_number, accounts=account_list)
def _get_user(user_id): user = users.get(user_id) if user: return user contact = kunkka.get_uos_user(user_id) user_name = contact['name'] if contact else None users[user_id] = models.User(user_id=user_id, user_name=user_name) return users[user_id]
def _get_user(user_id): user = users.get(user_id) if user: return user contact = kunkka.get_uos_user(user_id) or {} user_name = contact.get('name') email = contact.get('email') real_name = contact.get('real_name') or 'unknown' mobile = contact.get('phone') or 'unknown' company = contact.get('company') or 'unknown' users[user_id] = models.User(user_id=user_id, user_name=user_name, email=email, real_name=real_name, mobile=mobile, company=company) return users[user_id]
def invitees(self, limit=None, offset=None): """Get invitees of the inviter.""" if limit and limit < 0: raise exception.InvalidParameterValue(err="Invalid limit") if offset and offset < 0: raise exception.InvalidParameterValue(err="Invalid offset") inviter = acl.get_limited_to_user( request.headers, 'referees_get') or self._id self.conn = pecan.request.db_conn try: _invitees, total_count = self.conn.get_invitees(request.context, inviter, limit=limit, offset=offset) except Exception as e: LOG.exception('Fail to get invitees') raise exception.DBError(reason=e) invitees = [] for invitee in _invitees: user = kunkka.get_uos_user(invitee.user_id) if user: user_name = user.get( 'real_name') or user['email'].split('@')[0] user_email = user['email'] else: user_name = "" user_email = "" invitees.append(models.Invitee(user_id=invitee.user_id, user_name=user_name, user_email=user_email, created_at=invitee.created_at, charged=invitee.charged, reward_value=invitee.reward_value)) return models.Invitees(total_count=total_count, invitees=invitees)
def used(self): conn = pecan.request.db_conn context = pecan.request.context user_id = context.user_id project_id = context.project_id user_name = context.user_name key = str("gring-precharge-limit-%s" % user_id) cache = _get_cache() count = cache.get(key) max_count, lock_time = \ self._parse_limit_rule(cfg.CONF.precharge_limit_rule) if count is None: cache.set(key, str(max_count), lock_time) count = max_count price = utils._quantize_decimal('0') ret_code = 0 if int(count) > 0: try: precharge = conn.use_precharge(context, self.code, user_id=user_id, project_id=project_id) price = precharge.price except exception.PreChargeNotFound: LOG.error('The precharge %s not found' % self.code) ret_code = 1 try: cache.decr(key) except AttributeError: cache.incr(key, delta=-1) except exception.PreChargeHasUsed: LOG.error('The precharge %s has been used' % self.code) ret_code = 2 try: cache.decr(key) except AttributeError: cache.incr(key, delta=-1) except exception.PreChargeHasExpired: LOG.error('The precharge %s has been expired' % self.code) ret_code = 3 try: cache.decr(key) except AttributeError: cache.incr(key, delta=-1) except Exception as e: LOG.error('Fail to use precharge(%s), for reason: %s' % (self.code, e)) try: cache.decr(key) except AttributeError: cache.incr(key, delta=-1) raise exception.PreChargeException() else: cache.set(key, str(max_count), lock_time) # Notifier account if cfg.CONF.notify_account_charged: account = conn.get_account(context, user_id).as_dict() contact = kunkka.get_uos_user(user_id) self.notifier = notifier.NotifierService( cfg.CONF.checker.notifier_level) self.notifier.notify_account_charged( context, account, contact, 'coupon', price, bonus=0, operator=user_id, operator_name=user_name, remarks='coupon') left_count = int(cache.get(key)) if left_count == 0: ret_code = 4 return models.PreChargeSimple.transform(price=price, ret_code=ret_code, left_count=left_count, lock_time=lock_time / 60)
def used(self): conn = pecan.request.db_conn context = pecan.request.context user_id = context.user_id project_id = context.project_id user_name = context.user_name key = str("gring-precharge-limit-%s" % user_id) cache = _get_cache() count = cache.get(key) max_count, lock_time = \ self._parse_limit_rule(cfg.CONF.precharge_limit_rule) if count is None: cache.set(key, str(max_count), lock_time) count = max_count price = utils._quantize_decimal('0') ret_code = 0 if int(count) > 0: try: precharge = conn.use_precharge(context, self.code, user_id=user_id, project_id=project_id) price = precharge.price except exception.PreChargeNotFound: LOG.error('The precharge %s not found' % self.code) ret_code = 1 try: cache.decr(key) except AttributeError: cache.incr(key, delta=-1) except exception.PreChargeHasUsed: LOG.error('The precharge %s has been used' % self.code) ret_code = 2 try: cache.decr(key) except AttributeError: cache.incr(key, delta=-1) except exception.PreChargeHasExpired: LOG.error('The precharge %s has been expired' % self.code) ret_code = 3 try: cache.decr(key) except AttributeError: cache.incr(key, delta=-1) except Exception as e: LOG.error('Fail to use precharge(%s), for reason: %s' % (self.code, e)) try: cache.decr(key) except AttributeError: cache.incr(key, delta=-1) raise exception.PreChargeException() else: cache.set(key, str(max_count), lock_time) # Notifier account if cfg.CONF.notify_account_charged: account = conn.get_account(context, user_id).as_dict() contact = kunkka.get_uos_user(user_id) self.notifier = notifier.NotifierService( cfg.CONF.checker.notifier_level) self.notifier.notify_account_charged( context, account, contact, 'coupon', price, bonus=0, operator=user_id, operator_name=user_name, remarks='coupon' ) left_count = int(cache.get(key)) if left_count == 0: ret_code = 4 return models.PreChargeSimple.transform(price=price, ret_code=ret_code, left_count=left_count, lock_time=lock_time / 60)
def check_owed_order_resources_and_notify(self): #noqa """Check order-billing resources and notify related accounts Send sms/email notifications for each has-owed or will-owed order. """ try: accounts = self._assigned_accounts() except Exception: LOG.exception("Fail to get assigned accounts") accounts = [] LOG.warn("[%s] Notifying owed accounts, assigned accounts number: %s", self.member_id, len(accounts)) bill_methods = ['month', 'year'] for account in accounts: try: if not isinstance(account, dict): account = account.as_dict() if account['level'] == 9: continue contact = kunkka.get_uos_user(account['user_id']) language = cfg.CONF.notification_language account['reserved_days'] = utils.cal_reserved_days(account['level']) orders = list( self.gclient.get_active_orders( user_id=account['user_id'], bill_methods=bill_methods) ) for order in orders: # check if the resource exists resource = self.RESOURCE_GET_MAP[order['type']]( order['resource_id'], region_name=order['region_id']) if not resource: # warning that the resource not exists LOG.warn("[%s] The resource(%s|%s) has been " "deleted", self.member_id, order['type'], order['resource_id']) continue order_d = {} order_d['order_id'] = order['order_id'] order_d['region_id'] = order['region_id'] order_d['resource_id'] = order['resource_id'] order_d['resource_name'] = order['resource_name'] order_d['type'] = order['type'] order_d['owed'] = order['owed'] if isinstance(order['date_time'], basestring): order['date_time'] = timeutils.parse_strtime( order['date_time'], fmt=ISO8601_UTC_TIME_FORMAT) if isinstance(order['cron_time'], basestring): order['cron_time'] = timeutils.parse_strtime( order['cron_time'], fmt=ISO8601_UTC_TIME_FORMAT) # if order is owed, reserved_days represent how long resource will be reserved; # if not, reserved_days repesent how long resource will be expired now = datetime.datetime.utcnow() if order['owed']: reserved_days = (order['date_time'] - now).days else: reserved_days = (order['cron_time'] - now).days if reserved_days < 0: LOG.warn("[%s] The order %s reserved_days is " "less than 0", self.member_id, order['order_id']) reserved_days = 0 order_d['reserved_days'] = reserved_days order_d['date_time'] = timeutils.strtime( order['date_time'], fmt=ISO8601_UTC_TIME_FORMAT) order_d['cron_time'] = timeutils.strtime( order['cron_time'], fmt=ISO8601_UTC_TIME_FORMAT) is_notify_will_owed = (order_d['reserved_days'] <= cfg.CONF.checker.days_to_owe) if order_d['owed'] or (not order_d['owed'] and is_notify_will_owed): self.notifier.notify_order_billing_owed(self.ctxt, account, contact, order_d, language=language) except Exception: LOG.exception("Some exceptions occurred when checking owed " "account: %s", account['user_id'])
def check_owed_hour_resources_and_notify(self): # noqa """Check owed hour-billing resources and notify them Get owed accounts, send them sms/email notifications. """ try: accounts = self._assigned_accounts() except Exception: LOG.exception("Fail to get assigned accounts") accounts = [] LOG.warn("[%s] Notifying owed accounts, assigned accounts number: %s", self.member_id, len(accounts)) bill_methods=['hour',] for account in accounts: try: if not isinstance(account, dict): account = account.as_dict() if account['level'] == 9: continue if account['owed']: orders = list( self.gclient.get_active_orders( user_id=account['user_id'], owed=True, bill_methods=bill_methods) ) if not orders: continue contact = keystone.get_user(account['user_id']).to_dict() _projects = self.gclient.get_projects( user_id=account['user_id'], type='simple') orders_dict = {} for project in _projects: orders_dict[project['project_id']] = [] for order in orders: # check if the resource exists resource = self.RESOURCE_GET_MAP[order['type']]( order['resource_id'], region_name=order['region_id']) if not resource: # NOTE(chengkun): just warning if the resource not exists LOG.warn("[%s] The resource(%s|%s) has been " "deleted", self.member_id, order['type'], order['resource_id']) continue order_d = {} order_d['order_id'] = order['order_id'] order_d['region_id'] = order['region_id'] order_d['resource_id'] = order['resource_id'] order_d['resource_name'] = order['resource_name'] order_d['type'] = order['type'] if isinstance(order['date_time'], basestring): order['date_time'] = timeutils.parse_strtime( order['date_time'], fmt=ISO8601_UTC_TIME_FORMAT) now = datetime.datetime.utcnow() reserved_days = (order['date_time'] - now).days if reserved_days < 0: LOG.warn("[%s] The order %s reserved_days is " "less than 0", self.member_id, order['order_id']) reserved_days = 0 order_d['reserved_days'] = reserved_days order_d['date_time'] = timeutils.strtime( order['date_time'], fmt=ISO8601_UTC_TIME_FORMAT) orders_dict[order['project_id']].append(order_d) projects = [] for project in _projects: if orders_dict[project['project_id']]: adict = {} adict['project_id'] = project['project_id'] adict['project_name'] = project['project_name'] adict['orders'] = (orders_dict[ project['project_id']]) projects.append(adict) if not projects: continue reserved_days = utils.cal_reserved_days(account['level']) account['reserved_days'] = reserved_days language = cfg.CONF.notification_language self.notifier.notify_has_owed(self.ctxt, account, contact, projects, language=language) else: orders = self.gclient.get_active_orders( user_id=account['user_id'], bill_methods=bill_methods) if not orders: continue _projects = self.gclient.get_projects( user_id=account['user_id'], type='simple') estimation = {} for project in _projects: estimation[project['project_id']] = 0 price_per_hour = 0 for order in orders: # check if the resource exists resource = self.RESOURCE_GET_MAP[order['type']]( order['resource_id'], region_name=order['region_id']) if not resource: # just warning the resource not exists LOG.warn("[%s] The resource(%s|%s) may has been " "deleted", self.member_id, order['type'], order['resource_id']) continue price_per_hour += utils._quantize_decimal( order['unit_price']) estimation[order['project_id']] += \ utils._quantize_decimal(order['unit_price']) price_per_day = price_per_hour * 24 account_balance = utils._quantize_decimal( account['balance']) if price_per_day == 0: continue days_to_owe_d = float(account_balance / price_per_day) days_to_owe = round(days_to_owe_d) if days_to_owe > cfg.CONF.checker.days_to_owe: continue # caculate projects projects = [] for project in _projects: adict = {} adict['project_id'] = project['project_id'] adict['project_name'] = project['project_name'] adict['estimation'] = str( estimation[project['project_id']] * 24) projects.append(adict) if not projects: continue contact = kunkka.get_uos_user(account['user_id']) language = cfg.CONF.notification_language self.notifier.notify_before_owed(self.ctxt, account, contact, projects, str(price_per_day), days_to_owe, language=language) except Exception: LOG.exception("Some exceptions occurred when checking owed " "account: %s", account['user_id'])
def put(self, data): """Charge the account.""" check_policy(request.context, "account:charge") # check uos_bill_account_charge_limited charge value if "uos_bill_account_charge_limited" in request.context.roles: lscv = int(cfg.CONF.limited_support_charge_value) if data.value < -lscv or data.value > lscv: raise exception.InvalidChargeValue(value=data.value) else: # check accountant charge value lacv = int(cfg.CONF.limited_accountant_charge_value) if data.value < -lacv or data.value > lacv: raise exception.InvalidChargeValue(value=data.value) remarks = data.remarks if data.remarks != wsme.Unset else None operator = request.context.user_id self.conn = pecan.request.db_conn try: charge, is_first_charge = self.conn.update_account( request.context, self._id, operator=operator, **data.as_dict()) has_bonus = False if cfg.CONF.enable_bonus and data['type'] != 'bonus': value = gringutils.calculate_bonus(data['value']) if value > 0: bonus, _ = self.conn.update_account(request.context, self._id, type='bonus', value=value, come_from='system', operator=operator, remarks=remarks) has_bonus = True if cfg.CONF.enable_invitation and is_first_charge: _account = self._account() min_charge_value = gringutils._quantize_decimal( cfg.CONF.min_charge_value) reward_value = gringutils._quantize_decimal( cfg.CONF.reward_value) if _account.inviter \ and data.value >= min_charge_value \ and reward_value > 0: self.conn.update_account( request.context, _account.inviter, type='bonus', value=reward_value, come_from='system', operator=operator, remarks="reward because of invitation", invitee=self._id) if cfg.CONF.notify_account_charged: inviter = self.conn.get_account( request.context, _account.inviter).as_dict() contact = kunkka.get_uos_user(inviter['user_id']) self.notifier = notifier.NotifierService( cfg.CONF.checker.notifier_level) self.notifier.notify_account_charged( request.context, inviter, contact, 'bonus', reward_value, bonus=0, operator=operator, operator_name=request.context.user_name, remarks="reward because of invitation") self.conn.set_charged_orders(request.context, self._id) except exception.NotAuthorized as e: LOG.exception('Fail to charge the account:%s ' 'due to not authorization' % self._id) raise exception.NotAuthorized() except Exception as e: LOG.exception('Fail to charge the account:%s, ' 'charge value: %s' % (self._id, data.value)) raise exception.DBError(reason=e) else: # Notifier account if cfg.CONF.notify_account_charged: account = self.conn.get_account( request.context, self._id).as_dict() contact = kunkka.get_uos_user(account['user_id']) language = cfg.CONF.notification_language self.notifier = notifier.NotifierService( cfg.CONF.checker.notifier_level) self.notifier.notify_account_charged( request.context, account, contact, data['type'], charge.value, bonus=bonus.value if has_bonus else 0, operator=operator, operator_name=request.context.user_name, remarks=remarks, language=language) return models.Charge.from_db_model(charge)