Ejemplo n.º 1
0
    def renew(self, data):
        """renew the order manually

        1. Caculate price needed to deduct
        2. Change cron_time and deduct account in the same session
        3. Change cron job in master
        """
        self._validate_renew(data.as_dict())
        conn = pecan.request.db_conn
        try:
            order, renew_price = conn.renew_order(request.context, self._id,
                                                  data)
            self.master_api.change_monthly_job_time(request.context,
                                                    self._id,
                                                    timeutils.isotime(
                                                        order.cron_time),
                                                    clear_date_jobs=True)
        except exception.OrderNotFound as e:
            LOG.warn(e)
            raise
        except exception.OrderRenewError as e:
            LOG.warn(e)
            raise
        except exception.NotSufficientFund as e:
            LOG.warn(e)
            raise
        except Exception:
            msg = "Fail to renew the order %s" % self._id
            LOG.exception(msg)
            raise exception.DBError(reason=msg)
        result = models.Order.from_db_model(order)
        result.renew_price = str(renew_price)
        return result
Ejemplo n.º 2
0
    def put(self, data):

        check_policy(request.context, "deduct:account_pay")

        if data.reqId == wsme.Unset or data.money == wsme.Unset or \
                data.accountNum == wsme.Unset or data.extData == wsme.Unset or \
                data.extData.order_id == wsme.Unset:
            raise exception.InvalidDeductParameter()

        data.money = gringutils._quantize_decimal(data.money)
        self.conn = pecan.request.db_conn

        try:
            deduct = self.conn.deduct_account(request.context, data.accountNum,
                                              **data.as_dict())
        except db_exc.DBDuplicateEntry:
            LOG.exception('Duplicated deduct req_id: %s' % data.reqId)
            raise exception.DuplicatedDeduct(req_id=data.reqId)
        except exception.NotAuthorized:
            LOG.exception('Fail to deduct the account: %s' % data.accountNum)
            raise exception.NotAuthorized()
        except Exception:
            msg = "Fail to deduct the account: %s, charge value: %s" % (
                data.accountNum, data.money)
            LOG.exception(msg)
            raise exception.DBError(reason=msg)

        pay = models.Pay(transactionNum=deduct.deduct_id,
                         money=deduct.money,
                         createDate=deduct.created_at)

        return models.PayResponse(code="0",
                                  total="1",
                                  message="OK",
                                  data=[pay])
Ejemplo n.º 3
0
    def get_all(self,
                user_id=None,
                limit=None,
                offset=None,
                sort_key='dispatched,used',
                sort_dir='asc'):
        """Get all precharges."""
        context = pecan.request.context
        conn = pecan.request.db_conn
        check_policy(context, "account:precharge")

        if limit and limit < 0:
            raise exception.InvalidParameterValue(err="Invalid limit")
        if offset and offset < 0:
            raise exception.InvalidParameterValue(err="Invalid offset")

        try:
            precharges = conn.get_precharges(context,
                                             user_id=user_id,
                                             limit=limit,
                                             offset=offset,
                                             sort_key=sort_key,
                                             sort_dir=sort_dir)
            total_count = conn.get_precharges_count(context, user_id=user_id)
            pecan.response.headers['X-Total-Count'] = str(total_count)
        except Exception as e:
            LOG.exception('Failed to get all precharges')
            raise exception.DBError(reason=e)

        precharges = [models.PreCharge.from_db_model(p) for p in precharges]
        return models.PreCharges.transform(precharges=precharges,
                                           total_count=total_count)
Ejemplo n.º 4
0
 def delete(self):
     """Delete this product."""
     # ensure product exists before deleting
     product = self._product()
     try:
         self.conn.delete_product(request.context, product.product_id)
     except Exception:
         error = 'Error while deleting product: %s' % product.product_id
         LOG.exception(error)
         raise exception.DBError(reason=error)
Ejemplo n.º 5
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)
Ejemplo n.º 6
0
    def post(self, data):
        """Create a new product."""
        data.product_id = uuidutils.generate_uuid()
        conn = pecan.request.db_conn

        # API model to DB model
        try:
            product_in = db_models.Product(deleted=False, **data.as_dict())
        except Exception:
            error = 'Error while turning product: %s' % data.as_dict()
            LOG.exception(error)
            raise exception.MissingRequiredParams(reason=error)

        # Check and process unit_price data
        if product_in.unit_price is not None:
            price_data = ProductExtraData(product_in.unit_price.as_dict())
            price_data.validate()

        # Check if there are duplicated name in the same region
        filters = {
            'name': data.name,
            'service': data.service,
            'region_id': data.region_id
        }

        products = list(conn.get_products(request.context, filters=filters))

        if len(products) > 0:
            error = "Product with name(%s) within service(%s) already "\
                    "exists in region_id(%s)" % \
                    (data.name, data.service, data.region_id)
            LOG.warning(error)
            raise exception.DuplicatedProduct(reason=error)

        # Write product model to DB
        try:
            product = conn.create_product(request.context, product_in)
        except Exception:
            error = 'Error while creating product: %s' % data.as_dict()
            LOG.exception(error)
            raise exception.DBError(reason=error)

        # DB model to API model
        return models.Product(product_id=product.product_id,
                              name=product.name,
                              service=product.service,
                              region_id=product.region_id,
                              description=product.description,
                              unit_price=product_in.unit_price,
                              created_at=product.created_at,
                              updated_at=product.updated_at)
Ejemplo n.º 7
0
    def delete(self):
        """Delete the account including the projects that belong to it."""
        # only admin can delete account
        check_policy(request.context, "account:delete")

        try:
            self.conn = pecan.request.db_conn
            self.conn.delete_account(request.context, self._id)
        except (exception.NotFound):
            msg = _('Could not find account whose user_id is %s' % self._id)
            raise exception.NotFound(msg)
        except Exception as e:
            msg = _("failed to delete account whose user_id is %s." % self._id)
            LOG.warn(msg)
            raise exception.DBError(reason=e)
Ejemplo n.º 8
0
    def close(self):
        """Close this order

        Close means set order's status to deleted in database, then stop
        the cron job in apscheduler.
        """
        conn = pecan.request.db_conn
        try:
            order = conn.close_order(request.context, self._id)
        except Exception:
            msg = "Fail to close the order %s" % self._id
            LOG.exception(msg)
            raise exception.DBError(reason=msg)
        self.master_api.delete_sched_jobs(request.context, self._id)
        return models.Order.from_db_model(order)
Ejemplo n.º 9
0
    def level(self, level):
        if not isinstance(level, int) or level < 0 or level > 9:
            raise exception.InvalidParameterValue(err="Invalid Level")

        self.conn = pecan.request.db_conn
        try:
            account = self.conn.change_account_level(request.context,
                                                     None,
                                                     level,
                                                     project_id=self._id)
        except Exception as e:
            LOG.exception('Fail to change the account level of: %s' % self._id)
            raise exception.DBError(reason=e)

        return models.UserAccount.from_db_model(account)
Ejemplo n.º 10
0
    def level(self, level):
        """Update the account's level."""
        check_policy(request.context, "account:level")

        if not isinstance(level, int) or level < 0 or level > 9:
            raise exception.InvalidParameterValue(err="Invalid Level")

        self.conn = pecan.request.db_conn
        try:
            account = self.conn.change_account_level(request.context, self._id,
                                                     level)
        except Exception as e:
            LOG.exception('Fail to change the account level of: %s' % self._id)
            raise exception.DBError(reason=e)

        return models.UserAccount.from_db_model(account)
Ejemplo n.º 11
0
 def activate_auto_renew(self, data):
     """Activate auto renew of this order
     """
     self._validate_renew(data.as_dict())
     conn = pecan.request.db_conn
     try:
         order = conn.activate_auto_renew(request.context, self._id, data)
     except exception.OrderNotFound as e:
         LOG.warn(e)
         raise
     except exception.OrderRenewError as e:
         LOG.warn(e)
         raise
     except Exception:
         msg = "Fail to activate auto renew of the order %s" % self._id
         LOG.exception(msg)
         raise exception.DBError(reason=msg)
     return models.Order.from_db_model(order)
Ejemplo n.º 12
0
    def post(self, data):
        """Create a new product
        """
        data.product_id = uuidutils.generate_uuid()
        conn = pecan.request.db_conn

        # API model to DB model
        try:
            product_in = db_models.Product(quantity=0,
                                           deleted=False,
                                           **data.as_dict())
        except Exception as e:
            error = 'Error while turning product: %s' % data.as_dict()
            LOG.exception(error)
            raise exception.MissingRequiredParams(reason=error)

        # Check if there are duplicated name in the same region
        filters = {
            'name': data.name,
            'service': data.service,
            'region_id': data.region_id
        }

        products = list(conn.get_products(request.context, filters=filters))

        if len(products) > 0:
            error = "Product with name(%s) within service(%s) already "\
                    "exists in region_id(%s)" % \
                    (data.name, data.service, data.region_id)
            LOG.warning(error)
            raise exception.DuplicatedProduct(reason=error)

        # Write product model to DB
        try:
            product = conn.create_product(request.context, product_in)
        except Exception as e:
            error = 'Error while creating product: %s' % data.as_dict()
            LOG.exception(error)
            raise exception.DBError(reason=error)

        product.unit_price = gringutils._quantize_decimal(product.unit_price)

        # DB model to API model
        return models.Product.from_db_model(product)
Ejemplo n.º 13
0
    def put(self, data):
        """Modify this product. PUT method will override all the fields.
        """
        # Ensure this product exists
        # NOTE(suo): we can't make product_in and product_old
        # point to the same object
        product_in = self._product()
        product_old = self._product()

        for k, v in data.as_dict().items():
            product_in[k] = v

        product_in.updated_at = datetime.datetime.utcnow()

        # Check if there are other same names in the same region
        # except itself
        filters = {
            'name': product_in.name,
            'service': product_in.service,
            'region_id': product_in.region_id
        }
        products = list(
            self.conn.get_products(request.context, filters=filters))

        if len(products) > 0 and (
                product_old.name != product_in.name
                or product_old.service != product_in.service
                or product_old.region_id != product_in.region_id):
            error = "Product with name(%s) within service(%s) already "\
                    "exists in region_id(%s)" % \
                    (data.name, data.service, data.region_id)
            LOG.warning(error)
            raise exception.DuplicatedProduct(reason=error)

        # Update product model to DB
        try:
            product = self.conn.update_product(request.context, product_in)
        except Exception as e:
            error = 'Error while updating product: %s' % data.as_dict()
            LOG.exception(error)
            raise exception.DBError(reason=error)

        # DB model to API model
        return models.Product.from_db_model(product)
Ejemplo n.º 14
0
    def get_all(self, owed=None, limit=None, offset=None, duration=None):
        """Get all accounts."""

        check_policy(request.context, "account:all")

        if limit and limit < 0:
            raise exception.InvalidParameterValue(err="Invalid limit")
        if offset and offset < 0:
            raise exception.InvalidParameterValue(err="Invalid offset")

        self.conn = pecan.request.db_conn

        duration = gringutils.normalize_timedelta(duration)
        if duration:
            active_from = datetime.datetime.utcnow() - duration
        else:
            active_from = None

        try:
            accounts = self.conn.get_accounts(request.context,
                                              owed=owed,
                                              limit=limit,
                                              offset=offset,
                                              active_from=active_from)
            count = self.conn.get_accounts_count(request.context,
                                                 owed=owed,
                                                 active_from=active_from)
            pecan.response.headers['X-Total-Count'] = str(count)
        except exception.NotAuthorized as e:
            LOG.exception('Failed to get all accounts')
            raise exception.NotAuthorized()
        except Exception as e:
            LOG.exception('Failed to get all accounts')
            raise exception.DBError(reason=e)

        accounts = [
            models.AdminAccount.from_db_model(account) for account in accounts
        ]

        return models.AdminAccounts(total_count=count, accounts=accounts)
Ejemplo n.º 15
0
    def get_all(self, owed=None, limit=None, offset=None):
        """Get all accounts
        """
        self.conn = pecan.request.db_conn

        try:
            accounts = self.conn.get_accounts(request.context,
                                              owed=owed,
                                              limit=limit,
                                              offset=offset)
            count = self.conn.get_accounts_count(request.context, owed=owed)
            pecan.response.headers['X-Total-Count'] = str(count)
        except exception.NotAuthorized as e:
            LOG.exception('Fail to get all accounts')
            raise exception.NotAuthorized()
        except Exception as e:
            LOG.exception('Fail to get all accounts')
            raise exception.DBError(reason=e)

        return [
            models.AdminAccount.from_db_model(account) for account in accounts
        ]
Ejemplo n.º 16
0
    def get(self, reqId):

        check_policy(request.context, "deduct:check_req")
        self.conn = pecan.request.db_conn

        status = "0"
        try:
            self.conn.get_deduct(request.context, reqId)
        except exception.DeductNotFound:
            LOG.warn('Deduct Req: %s not found' % reqId)
            status = "-1"
        except exception.NotAuthorized:
            LOG.exception('Fail to get the deduct req: %s' % reqId)
            raise exception.NotAuthorized()
        except Exception:
            msg = "Fail to get the deduct req: %s" % reqId
            LOG.exception(msg)
            raise exception.DBError(reason=msg)
        return models.CheckReqResponse(code="0",
                                       total="1",
                                       message="OK",
                                       data=[models.CheckReq(status=status)])
Ejemplo n.º 17
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)
Ejemplo n.º 18
0
    def switch_auto_renew(self, data):
        """Start/Stop auto renew of this order
        """
        if data.action not in ['start', 'stop']:
            err = "Wrong switch renew action, should be start or stop"
            LOG.warn(err)
            raise exception.InvalidParameterValue(err=err)

        conn = pecan.request.db_conn
        try:
            order = conn.switch_auto_renew(request.context, self._id,
                                           data.action)
        except exception.OrderNotFound as e:
            LOG.warn(e)
            raise
        except exception.OrderRenewError as e:
            LOG.warn(e)
            raise
        except Exception:
            msg = "Fail to switch auto renew of the order %s" % self._id
            LOG.exception(msg)
            raise exception.DBError(reason=msg)
        return models.Order.from_db_model(order)
Ejemplo n.º 19
0
    def put(self, data):
        """Modify this product. PUT method will override all the fields."""
        # Ensure this product exists
        # NOTE(suo): we can't make product_in and product_old
        # point to the same object
        product_in = self._product()
        product_old = self._product()

        p = data.as_dict()

        # Default to reset subscription and order
        reset = p.pop("reset") if 'reset' in p else True

        for k, v in p.items():
            product_in[k] = v

        product_in.updated_at = datetime.datetime.utcnow()

        # Check and process unit_price data
        if product_in.unit_price is not None:
            price_data = ProductExtraData(product_in.unit_price.as_dict())
            price_data.validate()

        # Check if there are other same names in the same region
        # except itself
        filters = {
            'name': product_in.name,
            'service': product_in.service,
            'region_id': product_in.region_id
        }
        products = list(
            self.conn.get_products(request.context, filters=filters))

        if len(products) > 0 and (
            (product_old.name != product_in.name) or
            (product_old.service != product_in.service) or
            (product_old.region_id != product_in.region_id)):
            error = "Product with name(%s) within service(%s) already "\
                    "exists in region_id(%s)" % \
                    (data.name, data.service, data.region_id)
            LOG.warning(error)
            raise exception.DuplicatedProduct(reason=error)

        # Update product model to DB
        try:
            product = self.conn.update_product(request.context, product_in)
        except Exception:
            error = 'Error while updating product: %s' % data.as_dict()
            LOG.exception(error)
            raise exception.DBError(reason=error)

        # Reset order and subscription's unit price
        if reset:
            try:
                self.conn.reset_product(request.context, product,
                                        cfg.CONF.ignore_tenants)
            except Exception:
                error = "Fail to reset the product: %s" % data.as_dict()
                LOG.exception(error)
                raise exception.DBError(reason=error)

        # DB model to API model
        return models.Product(product_id=product.product_id,
                              name=product.name,
                              service=product.service,
                              region_id=product.region_id,
                              description=product.description,
                              unit_price=product_in.unit_price,
                              created_at=product.created_at,
                              updated_at=product.updated_at)
Ejemplo n.º 20
0
    def get_all(self, user_id=None, type=None, duration=None):
        """Get all projects."""
        user_id = acl.get_limited_to_user(request.headers,
                                          'projects_get') or user_id
        self.conn = pecan.request.db_conn
        result = []

        if not type or type.lower() == 'pay':
            # if admin call this api, limit to admin's user_id
            if not user_id:
                user_id = request.context.user_id

            try:
                user_projects = self.conn.get_user_projects(request.context,
                                                            user_id=user_id)
            except Exception as e:
                LOG.exception('Fail to get all projects')
                raise exception.DBError(reason=e)

            project_ids = [up.project_id for up in user_projects]

            if not project_ids:
                LOG.warn('User %s has no payed projects' % user_id)
                return []

            projects = self._list_keystone_projects()

            for u, p in itertools.product(user_projects, projects):
                if u.project_id == p['id']:
                    billing_owner = p['users']['billing_owner']
                    project_owner = p['users']['project_owner']
                    project_creator = p['users']['project_creator']
                    up = models.UserProject(
                        user_id=user_id,
                        project_id=u.project_id,
                        project_name=p['name'],
                        user_consumption=u.user_consumption,
                        project_consumption=u.project_consumption,
                        billing_owner=dict(user_id=billing_owner.get('id')
                                           if billing_owner else None,
                                           user_name=billing_owner.get('name')
                                           if billing_owner else None),
                        project_owner=dict(user_id=project_owner.get('id')
                                           if project_owner else None,
                                           user_name=project_owner.get('name')
                                           if project_owner else None),
                        project_creator=dict(
                            user_id=project_creator.get('id')
                            if project_creator else None,
                            user_name=project_creator.get('name')
                            if project_creator else None),
                        is_historical=u.is_historical,
                        created_at=timeutils.parse_isotime(p['created_at'])
                        if p['created_at'] else None)
                    result.append(up)
        elif type.lower() == 'all':
            # if admin call this api, limit to admin's user_id
            if not user_id:
                user_id = request.context.user_id

            k_projects = keystone.get_project_list(name=user_id)
            project_ids = [p['id'] for p in k_projects]

            if not project_ids:
                LOG.warn('User %s has no projects' % user_id)
                return []

            try:
                g_projects = self.conn.get_projects_by_project_ids(
                    request.context, project_ids)
            except Exception as e:
                LOG.exception('Fail to get all projects')
                raise exception.DBError(reason=e)
            for k, g in itertools.product(k_projects, g_projects):
                if k['id'] == g.project_id:
                    billing_owner = k['users']['billing_owner']
                    project_owner = k['users']['project_owner']
                    project_creator = k['users']['project_creator']
                    up = models.UserProject(
                        user_id=user_id,
                        project_id=g.project_id,
                        project_name=k['name'],
                        project_consumption=g.consumption,
                        billing_owner=dict(user_id=billing_owner.get('id')
                                           if billing_owner else None,
                                           user_name=billing_owner.get('name')
                                           if billing_owner else None),
                        project_owner=dict(user_id=project_owner.get('id')
                                           if project_owner else None,
                                           user_name=project_owner.get('name')
                                           if project_owner else None),
                        project_creator=dict(
                            user_id=project_creator.get('id')
                            if project_creator else None,
                            user_name=project_creator.get('name')
                            if project_creator else None),
                        is_historical=False,
                        created_at=timeutils.parse_isotime(k['created_at'])
                        if k['created_at'] else None)
                    result.append(up)

        elif type.lower() == 'simple':
            duration = gringutils.normalize_timedelta(duration)
            if duration:
                active_from = datetime.datetime.utcnow() - duration
            else:
                active_from = None
            g_projects = list(
                self.conn.get_projects(request.context,
                                       user_id=user_id,
                                       active_from=active_from))
            project_ids = [p.project_id for p in g_projects]

            if not project_ids:
                LOG.warn('User %s has no payed projects' % user_id)
                return []

            k_projects = self._list_keystone_projects()

            for k, g in itertools.product(k_projects, g_projects):
                if k.id == g.project_id:
                    up = models.UserProject(
                        project_id=g.project_id,
                        project_name=k.name,
                        domain_id=g.domain_id,
                        billing_owner=dict(user_id=g.user_id))
                    result.append(up)

        return result
Ejemplo n.º 21
0
    def get_all(self,
                user_id=None,
                owed=None,
                limit=None,
                offset=None,
                sort_key='created_at',
                sort_dir='desc'):
        check_policy(request.context, "account:all")

        if limit and limit < 0:
            raise exception.InvalidParameterValue(err="Invalid limit")
        if offset and offset < 0:
            raise exception.InvalidParameterValue(err="Invalid offset")

        self.conn = pecan.request.db_conn

        try:
            accounts = self.conn.get_accounts(request.context,
                                              user_id=user_id,
                                              owed=owed,
                                              limit=limit,
                                              offset=offset,
                                              sort_key=sort_key,
                                              sort_dir=sort_dir)
            count = self.conn.get_accounts_count(request.context,
                                                 owed=owed,
                                                 user_id=user_id)
            pecan.response.headers['X-Total-Count'] = str(count)
        except exception.NotAuthorized as e:
            LOG.exception('Failed to get all accounts')
            raise exception.NotAuthorized()
        except Exception as e:
            LOG.exception('Failed to get all accounts')
            raise exception.DBError(reason=e)

        results = []
        user_ids = []
        for account in accounts:
            user_ids.append(account.user_id)
            if account.sales_id:
                user_ids.append(account.sales_id)

            if cfg.CONF.external_billing.enable:
                try:
                    external_balance = \
                        self.external_client.get_external_balance(
                            account.user_id)['data'][0]['money']
                    external_balance = \
                        gringutils._quantize_decimal(
                            external_balance)
                    account.balance = external_balance
                except exception.GetExternalBalanceFailed:
                    msg = _('Fail to get %s\'s external balance' %
                            (account.user_id))
                    LOG.warn(msg)

            price_per_day, remaining_day = \
                self._estimate_per_day(account.user_id,
                                       account.balance)

            result = models.AdminAccountInDetail(
                user=None,
                user_id=account.user_id,
                salesperson=None,
                sales_id=account.sales_id,
                balance=account.balance,
                consumption=account.consumption,
                level=account.level,
                project_id=account.project_id,
                domain_id=account.domain_id,
                owed=owed,
                inviter=account.inviter,
                created_at=account.created_at,
                price_per_day=price_per_day,
                remaining_day=remaining_day)
            results.append(result)

        users = keystone.get_users_by_user_ids(user_ids)
        for result in results:
            user = users.get(result.user_id)
            salesperson = users.get(result.sales_id)
            if user:
                result.user = models.UserInDetail(**user)
            if salesperson:
                result.salesperson = models.UserInDetail(**salesperson)

        return models.AdminAccountsInDetail(total_count=count,
                                            accounts=results)
Ejemplo n.º 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)