Example #1
0
    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)
Example #2
0
    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)
Example #3
0
    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)
Example #4
0
 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]
Example #5
0
 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]
Example #6
0
 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]
Example #7
0
 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]
Example #8
0
    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)
Example #9
0
    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)
Example #10
0
    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)
Example #11
0
    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'])
Example #12
0
    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'])
Example #13
0
    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)