예제 #1
0
    def update(self, request, reference):

        purchase = Purchase.objects.get(ref=reference)

        data = json.loads(request.raw_post_data)

        try:
            if data['method'] == 'paypal':
                charging_engine = ChargingEngine(purchase, payment_method='paypal')
            elif data['method'] == 'credit_card':

                # Get the payment info
                if 'credit_card' in data:
                    credit_card = data['credit_card']
                else:
                    if purchase.organization_owned:
                        credit_card = purchase.owner_organization.payment_info
                    else:
                        credit_card = purchase.customer.userprofile.payment_info
                charging_engine = ChargingEngine(purchase, payment_method='credit_card', credit_card=credit_card)

            charging_engine.resolve_charging()
        except:
            # Refresh the purchase info
            purchase = Purchase.objects.get(ref=reference)
            rollback(purchase)
            return build_response(request, 400, 'Invalid JSON content')

        return build_response(request, 200, 'OK')
예제 #2
0
파일: views.py 프로젝트: jartieda/wstore
    def update(self, request, reference):

        purchase = Purchase.objects.get(ref=reference)

        data = json.loads(request.raw_post_data)

        try:
            if data['method'] == 'paypal':
                charging_engine = ChargingEngine(purchase, payment_method='paypal')
            elif data['method'] == 'credit_card':

                # Get the payment info
                if 'credit_card' in data:
                    credit_card = data['credit_card']
                else:
                    if purchase.organization_owned:
                        credit_card = purchase.owner_organization.payment_info
                    else:
                        credit_card = purchase.customer.userprofile.payment_info
                charging_engine = ChargingEngine(purchase, payment_method='credit_card', credit_card=credit_card)

            charging_engine.resolve_charging()
        except:
            # Refresh the purchase info
            purchase = Purchase.objects.get(ref=reference)
            rollback(purchase)
            return build_response(request, 400, 'Invalid JSON content')

        return build_response(request, 200, 'OK')
예제 #3
0
    def handle(self, *args, **options):
        """
            This method is used to perform the charging process
            of the offerings that have pending SDR for more than
            a month
        """
        now = time.mktime(datetime.now().timetuple())

        if len(args) == 0:
            # Get contracts
            for contract in Contract.objects.all():

                pending_sdrs = contract.pending_sdrs

                # If there are subscriptions the renovations are used as triggers
                if len(pending_sdrs) > 0 and (not 'subscription' in contract.pricing_model):
                    time_stamp = time.mktime(pending_sdrs[0]['time_stamp'].timetuple())

                    if (time_stamp + 2592000) <= now:  # A month
                        # Get the related payment info
                        purchase = contract.purchase

                        if purchase.organization_owned:
                            org = purchase.owner_organization
                            payment_info = org.payment_info
                        else:
                            payment_info = purchase.customer.userprofile.payment_info

                        charging = ChargingEngine(purchase, payment_method='credit_card', credit_card=payment_info)
                        charging.resolve_charging(sdr=True)

        elif len(args) == 1:
            # Get the purchase
            try:
                purchase = Purchase.objects.get(ref=args[0])
            except:
                raise Exception('The provided purchase does not exists')

            # Get the contract
            contract = purchase.contract

            # Check if there are pending SDRs
            if (len(contract.pending_sdrs) > 0):

                # Get payment info
                if purchase.organization_owned:
                    org = purchase.owner_organization
                    payment_info = org.payment_info
                else:
                    payment_info = purchase.customer.userprofile.payment_info

                charging = ChargingEngine(purchase, payment_method='credit_card', credit_card=payment_info)
                charging.resolve_charging(sdr=True)

            else:
                raise Exception('No accounting info in the provided purchase')
        else:
            raise Exception('Invalid number of arguments')
예제 #4
0
    def resolve_purchase_usage(self, purchase):
        # Get payment info
        if purchase.organization_owned:
            org = purchase.owner_organization
            payment_info = org.payment_info
        else:
            payment_info = purchase.customer.userprofile.payment_info

        charging = ChargingEngine(purchase, payment_method='credit_card', credit_card=payment_info)
        charging.resolve_charging(type_='use')
    def _process_modify_items(self, items):
        if len(items) > 1:
            raise OrderingError(
                'Only a modify item is supported per order item')

        item = items[0]
        if 'product' not in item:
            raise OrderingError(
                'It is required to specify product information in modify order items'
            )

        product = item['product']

        if 'id' not in product:
            raise OrderingError(
                'It is required to provide product id in modify order items')

        client = InventoryClient()
        order, contract = self._get_existing_contract(client, product['id'])

        # Build the new contract
        new_contract = self._build_contract(item)
        if new_contract.pricing_model != {}:
            contract.pricing_model = new_contract.pricing_model
            contract.revenue_class = new_contract.revenue_class

        order.save()

        # The modified item is treated as an initial payment
        charging_engine = ChargingEngine(order)
        return charging_engine.resolve_charging(type_='initial',
                                                related_contracts=[contract])
    def _process_modify_items(self, items):
        if len(items) > 1:
            raise OrderingError('Only a modify item is supported per order item')

        item = items[0]
        if 'product' not in item:
            raise OrderingError('It is required to specify product information in modify order items')

        product = item['product']

        if 'id' not in product:
            raise OrderingError('It is required to provide product id in modify order items')

        client = InventoryClient()
        order, contract = self._get_existing_contract(client, product['id'])

        # Build the new contract
        new_contract = self._build_contract(item)
        if new_contract.pricing_model != {}:
            contract.pricing_model = new_contract.pricing_model
            contract.revenue_class = new_contract.revenue_class

        order.save()

        # The modified item is treated as an initial payment
        charging_engine = ChargingEngine(order)
        return charging_engine.resolve_charging(type_='initial', related_contracts=[contract])
예제 #7
0
    def _process_add_items(self, items, order_id, description, terms_accepted):

        new_contracts = [self._build_contract(item) for item in items]

        terms_found = False
        for c in new_contracts:
            off = Offering.objects.get(pk=ObjectId(c.offering))
            if off.asset is not None and off.asset.has_terms:
                terms_found = True

        if terms_found and not terms_accepted:
            raise OrderingError('You must accept the terms and conditions of the offering to acquire it')

        current_org = self._customer.userprofile.current_organization
        order = Order.objects.create(
            order_id=order_id,
            customer=self._customer,
            owner_organization=current_org,
            date=datetime.utcnow(),
            state='pending',
            tax_address=self._get_billing_address(items),
            contracts=new_contracts,
            description=description
        )

        self.rollback_logger['models'].append(order)

        charging_engine = ChargingEngine(order)
        return charging_engine.resolve_charging()
    def create(self, request):

        try:
            task = json.loads(request.body)
        except:
            return build_response(request, 400, 'The provided data is not a valid JSON object')

        # Check the products to be renovated
        if 'name' not in task or 'id' not in task or 'priceType' not in task:
            return build_response(request, 400, 'Missing required field, must contain name, id  and priceType fields')

        # Parse oid from product name
        parsed_name = task['name'].split('=')

        try:
            order = Order.objects.get(order_id=parsed_name[1])
        except:
            return build_response(request, 404, 'The oid specified in the product name is not valid')

        # Get contract to renovate
        if isinstance(task['id'], int):
            task['id'] = unicode(task['id'])

        try:
            contract = order.get_product_contract(task['id'])
        except:
            return build_response(request, 404, 'The specified product id is not valid')

        # Refresh accounting information
        on_usage_refreshed(order, contract)

        # Build charging engine
        charging_engine = ChargingEngine(order)

        if task['priceType'].lower() not in ['recurring', 'usage']:
            return build_response(request, 400, 'Invalid priceType only recurring and usage types can be renovated')

        try:
            redirect_url = charging_engine.resolve_charging(type_=task['priceType'].lower(), related_contracts=[contract])
        except ValueError as e:
            return build_response(request, 400, unicode(e))
        except OrderingError as e:
            return build_response(request, 422, unicode(e))
        except:
            return build_response(request, 500, 'An unexpected event prevented your payment to be created')

        response = build_response(request, 200, 'OK')

        # Include redirection header if needed
        if redirect_url is not None:
            response['X-Redirect-URL'] = redirect_url

        return response
    def _process_add_items(self, items, order_id, description):

        new_contracts = [self._build_contract(item) for item in items]

        current_org = self._customer.userprofile.current_organization
        order = Order.objects.create(
            order_id=order_id,
            customer=self._customer,
            owner_organization=current_org,
            date=datetime.utcnow(),
            state='pending',
            tax_address=self._get_billing_address(items),
            contracts=new_contracts,
            description=description)

        self.rollback_logger['models'].append(order)

        charging_engine = ChargingEngine(order)
        return charging_engine.resolve_charging()
    def _process_add_items(self, items, order_id, description):

        new_contracts = [self._build_contract(item) for item in items]

        current_org = self._customer.userprofile.current_organization
        order = Order.objects.create(
            order_id=order_id,
            customer=self._customer,
            owner_organization=current_org,
            date=datetime.utcnow(),
            state='pending',
            tax_address=self._get_billing_address(items),
            contracts=new_contracts,
            description=description
        )

        self.rollback_logger['models'].append(order)

        charging_engine = ChargingEngine(order)
        return charging_engine.resolve_charging()
def process_product_payment(self, request, task, order, contract):
    # Refresh accounting information
    on_usage_refreshed(order, contract)

    # Build charging engine
    charging_engine = ChargingEngine(order)

    redirect_url = None
    try:
        redirect_url = charging_engine.resolve_charging(
            type_=task['priceType'].lower(), related_contracts=[contract])
    except ValueError as e:
        return None, build_response(request, 400, str(e))
    except OrderingError as e:
        # The error might be raised because renewing a suspended product not expired
        if str(
                e
        ) == 'OrderingError: There is not recurring payments to renovate' and contract.suspended:
            try:
                on_product_acquired(order, contract)

                # Change product state to active
                contract.suspended = False
                order.save()

                inventory_client = InventoryClient()
                inventory_client.activate_product(contract.product_id)
            except:
                return None, build_response(
                    request, 400, 'The asset has failed to be activated')

        else:
            return None, build_response(request, 422, str(e))
    except:
        return None, build_response(
            request, 500,
            'An unexpected event prevented your payment to be created')

    return redirect_url, None
예제 #12
0
    def handle(self, *args, **options):
        """
            This method is used to perform the charging process
            of the offerings that have pending SDR for more than
            a month
        """
        now = time.mktime(datetime.now().timetuple())

        if len(args) == 0:
            # Get contracts
            for contract in Contract.objects.all():

                pending_sdrs = contract.pending_sdrs

                # If there are subscriptions the renovations are used as triggers
                if len(pending_sdrs) > 0 and (not 'subscription'
                                              in contract.pricing_model):
                    time_stamp = time.mktime(
                        pending_sdrs[0]['time_stamp'].timetuple())

                    if (time_stamp + 2592000) <= now:  # A month
                        # Get the related payment info
                        purchase = contract.purchase

                        if purchase.organization_owned:
                            org = purchase.owner_organization
                            payment_info = org.payment_info
                        else:
                            payment_info = purchase.customer.userprofile.payment_info

                        charging = ChargingEngine(purchase,
                                                  payment_method='credit_card',
                                                  credit_card=payment_info)
                        charging.resolve_charging(sdr=True)

        elif len(args) == 1:
            # Get the purchase
            try:
                purchase = Purchase.objects.get(ref=args[0])
            except:
                raise Exception('The provided purchase does not exists')

            # Get the contract
            contract = purchase.contract

            # Check if there are pending SDRs
            if (len(contract.pending_sdrs) > 0):

                # Get payment info
                if purchase.organization_owned:
                    org = purchase.owner_organization
                    payment_info = org.payment_info
                else:
                    payment_info = purchase.customer.userprofile.payment_info

                charging = ChargingEngine(purchase,
                                          payment_method='credit_card',
                                          credit_card=payment_info)
                charging.resolve_charging(sdr=True)

            else:
                raise Exception('No accounting info in the provided purchase')
        else:
            raise Exception('Invalid number of arguments')
예제 #13
0
def create_purchase(user, offering, org_owned=False, payment_info=None):

    if offering.state != 'published':
        raise PermissionDenied("This offering can't be purchased")

    if offering.open:
        raise PermissionDenied('Open offerings cannot be purchased')

    if accepted_needed(offering) and not payment_info['accepted']:
        raise PermissionDenied('You must accept the terms and conditions of the offering to acquire it')

    profile = UserProfile.objects.get(user=user)

    # Check if the offering is already purchased
    if (org_owned and offering.pk in profile.current_organization.offerings_purchased) \
            or (not org_owned and offering.pk in profile.offerings_purchased):
        raise PermissionDenied('The offering has been already purchased')

    organization = profile.current_organization

    plan = None
    # Check the selected plan
    if payment_info and 'plan' in payment_info:
        plan = payment_info['plan']

    # Get the effective tax address
    if 'tax_address' not in payment_info:
        if org_owned:
            tax = organization.tax_address
        else:
            tax = profile.tax_address

        # Check that the customer has a tax address
        if 'street' not in tax:
            raise ValueError('The customer does not have a tax address')
    else:
        tax = payment_info['tax_address']

        # Check tax_address fields
        if ('street' not in tax) or ('postal' not in tax)\
                or ('city' not in tax) or ('country' not in tax):
            raise ValueError('The tax address is not valid')

    # Check the payment method before purchase creation in order to avoid
    # an inconsistent state in the database
    credit_card_info = None
    if payment_info['payment_method'] == 'credit_card':
        if 'credit_card' in payment_info:
            # Check credit card info
            if (not ('number' in payment_info['credit_card'])) or (not ('type' in payment_info['credit_card']))\
                    or (not ('expire_year' in payment_info['credit_card'])) or (not ('expire_month' in payment_info['credit_card']))\
                    or (not ('cvv2' in payment_info['credit_card'])):
                raise ValueError('Invalid credit card info')

            credit_card_info = payment_info['credit_card']
        else:
            if org_owned:
                credit_card_info = organization.payment_info
            else:
                credit_card_info = profile.payment_info

            # Check the credit card info
            if 'number' not in credit_card_info:
                raise Exception('The customer does not have payment info')

    elif payment_info['payment_method'] != 'paypal':
        raise ValueError('Invalid payment method')

    # Check if a purchase object exists
    old_purchase = Purchase.objects.filter(owner_organization=organization, offering=offering)
    if len(old_purchase) > 0:
        for p in old_purchase:
            p.delete()

    # Create the purchase
    purchase = Purchase.objects.create(
        customer=user,
        date=datetime.now(),
        offering=offering,
        organization_owned=org_owned,
        state='pending',
        tax_address=tax,
        owner_organization=organization
    )

    # Load ref
    purchase.ref = purchase.pk
    purchase.save()

    if credit_card_info is not None:
        charging_engine = ChargingEngine(purchase, payment_method='credit_card', credit_card=credit_card_info, plan=plan)
    else:
        charging_engine = ChargingEngine(purchase, payment_method='paypal', plan=plan)

    redirect_url = charging_engine.resolve_charging(new_purchase=True)

    if redirect_url is None:
        result = purchase

        # If no redirect URL is provided the purchase has ended so the user profile
        # info is updated
        if org_owned:
            organization.offerings_purchased.append(offering.pk)
            organization.save()
        else:
            profile.offerings_purchased.append(offering.pk)
            profile.save()

        notify_provider(purchase)

    else:
        result = redirect_url

    # Update offering indexes
    index_path = os.path.join(settings.BASEDIR, 'wstore')
    index_path = os.path.join(index_path, 'search')
    index_path = os.path.join(index_path, 'indexes')

    se = SearchEngine(index_path)
    se.update_index(offering)

    return result