Пример #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 = keystone.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('mobile_number', ''),
                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)
Пример #2
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 = keystone.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('mobile_number', ''),
                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)
Пример #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 = keystone.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(
                                              'mobile_number', ''),
                                          company=user.get('company', ''),
                                          balance=account.balance,
                                          consumption=account.consumption,
                                          owed=account.owed))

        return models.SalesPersonAccounts(total_count=accounts_number,
                                          accounts=account_list)
Пример #4
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 = keystone.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('mobile_number', ''),
                    company=user.get('company', ''),
                    balance=account.balance,
                    consumption=account.consumption,
                    owed=account.owed
                )
            )

        return models.SalesPersonAccounts(
            total_count=accounts_number, accounts=account_list)
Пример #5
0
 def _get_user(user_id):
     user = users.get(user_id)
     if user:
         return user
     contact = keystone.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]
Пример #6
0
 def _get_user(user_id):
     user = users.get(user_id)
     if user:
         return user
     contact = keystone.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]
Пример #7
0
    def put(self, data):
        """Charge the account
        """
        # Check the charge value
        if data.value < -100000 or data.value > 100000:
            raise exception.InvalidChargeValue(value=data.value)

        self.conn = pecan.request.db_conn

        try:
            charge, _ = self.conn.update_account(request.context,
                                                 None,
                                                 project_id=self._id,
                                                 **data.as_dict())
            has_bonus = False
            if cfg.CONF.enable_bonus and data['type'] != 'bonus':
                data['type'] = 'bonus'
                data['come_from'] = 'system'
                value = gringutils.calculate_bonus(data['value'])
                if value > 0:
                    data['value'] = value
                    bonus, _ = self.conn.update_account(request.context,
                                                        None,
                                                        project_id=self._id,
                                                        **data.as_dict())
                    has_bonus = True

            self.conn.set_charged_orders(request.context,
                                         None,
                                         project_id=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 and charge['type'] != 'bonus':
                account = self.conn.get_account(request.context,
                                                None,
                                                project_id=self._id).as_dict()
                contact = keystone.get_uos_user(account['user_id'])
                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)
        return models.Charge.from_db_model(charge)
Пример #8
0
    def _send_email_notification(self, message):

        def convert_to_localtime(timestamp):
            FORMAT = '%Y-%m-%d %H:%M:%S.%f'
            try:
                # convert from UTC to UTC+8(Beijing)
                dt = datetime.strptime(timestamp, FORMAT) + timedelta(hours=8)
                return dt.strftime(FORMAT[:-3])
            except (ValueError):
                return timestamp

        CTX_TEMPLATE = '_context_%s'

        user_id = message.get(CTX_TEMPLATE % 'user_id')
        if not user_id:
            return

        user = ks_client.get_uos_user(user_id)
        username = user.get('name', '')
        if username == 'doctor':
            return

        event_type = message['event_type']
        if 'create' in event_type:
            event_name = u'创建公网IP'
        elif 'delete' in event_type:
            event_name = u'删除公网IP'
        else:
            return

        content = []
        content.append(u'事件: %s' % (event_name))
        content.append(u'时间: %s' % (
            convert_to_localtime(message['timestamp'])))
        content.append('<hr noshade size=1>')
        content.append(u'项目: %s' % (
            message[CTX_TEMPLATE % 'project_name']))
        content.append(u'用户名: %s' % (username))
        content.append(u'姓名: %s' % (user.get('real_name', '')))
        content.append(u'公司: %s' % (user.get('company', '')))
        content.append(u'公司地址: %s' % (user.get('company_addr', '')))
        content.append(u'Email: %s' % (user.get('email', '')))
        content.append(u'手机号: %s' % (user.get('mobile_number', '')))

        fip = generate_ip_str(message)
        content.append(u'公网IP地址: %s' % (fip))

        # format of created_at is %Y-%m-%dT%H:%M:%S.%f
        payload = get_payload(message)
        content.append(u'创建时间: %s' % (
            convert_to_localtime(payload['created_at'].replace('T', ' '))))

        lotus.send_notification_email(
            u'公网IP变动通知', u'<br />'.join(content))
Пример #9
0
    def _send_email_notification(self, message):

        def convert_to_localtime(timestamp):
            FORMAT = '%Y-%m-%d %H:%M:%S.%f'
            try:
                # convert from UTC to UTC+8(Beijing)
                dt = datetime.strptime(timestamp, FORMAT) + timedelta(hours=8)
                return dt.strftime(FORMAT[:-3])
            except (ValueError):
                return timestamp

        CTX_TEMPLATE = '_context_%s'

        user_id = message.get(CTX_TEMPLATE % 'user_id')
        if not user_id:
            return

        user = ks_client.get_uos_user(user_id)
        username = user.get('name', '')
        if username == 'doctor':
            return

        event_type = message['event_type']
        if 'create' in event_type:
            event_name = u'创建公网IP'
        elif 'delete' in event_type:
            event_name = u'删除公网IP'
        else:
            return

        content = []
        content.append(u'事件: %s' % (event_name))
        content.append(u'时间: %s' % (
            convert_to_localtime(message['timestamp'])))
        content.append('<hr noshade size=1>')
        content.append(u'项目: %s' % (
            message[CTX_TEMPLATE % 'project_name']))
        content.append(u'用户名: %s' % (username))
        content.append(u'姓名: %s' % (user.get('real_name', '')))
        content.append(u'公司: %s' % (user.get('company', '')))
        content.append(u'公司地址: %s' % (user.get('company_addr', '')))
        content.append(u'Email: %s' % (user.get('email', '')))
        content.append(u'手机号: %s' % (user.get('mobile_number', '')))

        fip = generate_ip_str(message)
        content.append(u'公网IP地址: %s' % (fip))

        # format of created_at is %Y-%m-%dT%H:%M:%S.%f
        payload = get_payload(message)
        content.append(u'创建时间: %s' % (
            convert_to_localtime(payload['created_at'].replace('T', ' '))))

        lotus.send_notification_email(
            u'公网IP变动通知', u'<br />'.join(content))
Пример #10
0
    def put(self, data):
        """Charge the account
        """
        # Check the charge value
        if data.value < -100000 or data.value > 100000:
            raise exception.InvalidChargeValue(value=data.value)

        self.conn = pecan.request.db_conn

        try:
            charge, _ = self.conn.update_account(request.context,
                                                 None,
                                                 project_id=self._id,
                                                 **data.as_dict())
            has_bonus = False
            if cfg.CONF.enable_bonus and data['type'] != 'bonus':
                data['type'] = 'bonus'
                data['come_from'] = 'system'
                value = gringutils.calculate_bonus(data['value'])
                if value > 0:
                    data['value'] = value
                    bonus, _ = self.conn.update_account(request.context,
                                                        None,
                                                        project_id=self._id,
                                                        **data.as_dict())
                    has_bonus = True

            self.conn.set_charged_orders(request.context, None, project_id=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 and charge['type'] != 'bonus':
                account = self.conn.get_account(request.context, None, project_id=self._id).as_dict()
                contact = keystone.get_uos_user(account['user_id'])
                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)
        return models.Charge.from_db_model(charge)
Пример #11
0
 def _get_user(user_id):
     user = users.get(user_id)
     if user:
         return user
     contact = keystone.get_uos_user(user_id) or {}
     user_name = contact.get('name')
     email = contact.get('email')
     real_name = contact.get('real_name')
     mobile = contact.get('mobile_number')
     company = contact.get('company')
     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]
Пример #12
0
 def _get_user(user_id):
     user = users.get(user_id)
     if user:
         return user
     contact = keystone.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('mobile_number') 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]
Пример #13
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 = keystone.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)
Пример #14
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 = keystone.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)
Пример #15
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 = keystone.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)
Пример #16
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 = keystone.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)
Пример #17
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 = keystone.get_uos_user(account['user_id'])
                country_code = contact.get("country_code") or "86"
                language = "en_US" if country_code != '86' else "zh_CN"
                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'])
Пример #18
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
                    country_code = contact.get("country_code") or "86"
                    language = "en_US" if country_code != '86' else "zh_CN"
                    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 = keystone.get_uos_user(account['user_id'])
                    country_code = contact.get("country_code") or "86"
                    language = "en_US" if country_code != '86' else "zh_CN"
                    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'])
Пример #19
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 = keystone.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 = keystone.get_uos_user(account['user_id'])
                country_code = contact.get("country_code") or "86"
                language = "en_US" if country_code != '86' else "zh_CN"
                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)
Пример #20
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 = keystone.get_uos_user(account['user_id'])
                country_code = contact.get("country_code") or "86"
                language = "en_US" if country_code != '86' else "zh_CN"
                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'])
Пример #21
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
                    country_code = contact.get("country_code") or "86"
                    language = "en_US" if country_code != '86' else "zh_CN"
                    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 = keystone.get_uos_user(account['user_id'])
                    country_code = contact.get("country_code") or "86"
                    language = "en_US" if country_code != '86' else "zh_CN"
                    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'])
Пример #22
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 = keystone.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 = keystone.get_uos_user(account['user_id'])
                country_code = contact.get("country_code") or "86"
                language = "en_US" if country_code != '86' else "zh_CN"
                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)