def setUp(self): from billy.models.company import CompanyModel from billy.models.customer import CustomerModel from billy.models.plan import PlanModel super(TestSubscriptionModel, self).setUp() # build the basic scenario for plan model self.company_model = CompanyModel(self.session) self.customer_model = CustomerModel(self.session) self.plan_model = PlanModel(self.session) with db_transaction.manager: self.company_guid = self.company_model.create('my_secret_key') self.daily_plan_guid = self.plan_model.create( company_guid=self.company_guid, plan_type=self.plan_model.TYPE_CHARGE, amount=10, frequency=self.plan_model.FREQ_DAILY, ) self.weekly_plan_guid = self.plan_model.create( company_guid=self.company_guid, plan_type=self.plan_model.TYPE_CHARGE, amount=10, frequency=self.plan_model.FREQ_WEEKLY, ) self.monthly_plan_guid = self.plan_model.create( company_guid=self.company_guid, plan_type=self.plan_model.TYPE_CHARGE, amount=10, frequency=self.plan_model.FREQ_MONTHLY, ) self.customer_tom_guid = self.customer_model.create( company_guid=self.company_guid, )
def setUp(self): from billy.models.company import CompanyModel from billy.models.customer import CustomerModel from billy.models.plan import PlanModel from billy.models.subscription import SubscriptionModel super(TestTransactionModel, self).setUp() # build the basic scenario for transaction model self.company_model = CompanyModel(self.session) self.customer_model = CustomerModel(self.session) self.plan_model = PlanModel(self.session) self.subscription_model = SubscriptionModel(self.session) with db_transaction.manager: self.company_guid = self.company_model.create('my_secret_key') self.plan_guid = self.plan_model.create( company_guid=self.company_guid, plan_type=self.plan_model.TYPE_CHARGE, amount=10, frequency=self.plan_model.FREQ_MONTHLY, ) self.customer_guid = self.customer_model.create( company_guid=self.company_guid, ) self.subscription_guid = self.subscription_model.create( customer_guid=self.customer_guid, plan_guid=self.plan_guid, payment_uri='/v1/cards/tester', )
def test_create_subscription_to_other_company_plan(self): from billy.models.company import CompanyModel from billy.models.plan import PlanModel company_model = CompanyModel(self.testapp.session) plan_model = PlanModel(self.testapp.session) with db_transaction.manager: other_company_guid = company_model.create( processor_key='MOCK_PROCESSOR_KEY', ) other_plan_guid = plan_model.create( company_guid=other_company_guid, frequency=plan_model.FREQ_WEEKLY, plan_type=plan_model.TYPE_CHARGE, amount=10, ) self.testapp.post( '/v1/subscriptions', dict( customer_guid=self.customer_guid, plan_guid=other_plan_guid, ), extra_environ=dict(REMOTE_USER=self.api_key), status=403, )
def setUp(self): from billy.models.company import CompanyModel super(TestCustomerModel, self).setUp() # build the basic scenario for plan model self.company_model = CompanyModel(self.session) with transaction.manager: self.company_guid = self.company_model.create('my_secret_key')
def auth_api_key(request): """Authenticate API KEY and return corresponding company """ model = CompanyModel(request.session) company = model.get_by_api_key(unicode(request.remote_user)) if company is None: raise HTTPForbidden('Invalid API key {}'.format(request.remote_user)) return company
def setUp(self): from billy.models.company import CompanyModel super(TestCustomerViews, self).setUp() model = CompanyModel(self.testapp.session) with db_transaction.manager: self.company_guid = model.create( processor_key='MOCK_PROCESSOR_KEY') company = model.get(self.company_guid) self.api_key = str(company.api_key)
def company_list_post(request): """Create a new company """ form = validate_form(CompanyCreateForm, request) processor_key = form.data['processor_key'] model = CompanyModel(request.session) # TODO: do validation here with db_transaction.manager: guid = model.create(processor_key=processor_key) company = model.get(guid) return company
def company_get(request): """Get and return a company """ api_company = auth_api_key(request) model = CompanyModel(request.session) guid = request.matchdict['company_guid'] company = model.get(guid) if company is None: return HTTPNotFound('No such company {}'.format(guid)) if guid != api_company.guid: return HTTPForbidden( 'You have no premission to access company {}'.format(guid)) return company
def test_get_customer_of_other_company(self): from billy.models.company import CompanyModel model = CompanyModel(self.testapp.session) with db_transaction.manager: other_company_guid = model.create( processor_key='MOCK_PROCESSOR_KEY') other_company = model.get(other_company_guid) other_api_key = str(other_company.api_key) res = self.testapp.post( '/v1/customers', extra_environ=dict(REMOTE_USER=other_api_key), status=200, ) guid = res.json['guid'] res = self.testapp.get( '/v1/customers/{}'.format(guid), extra_environ=dict(REMOTE_USER=self.api_key), status=403, )
def test_create_subscription_to_other_company_customer(self): from billy.models.company import CompanyModel from billy.models.customer import CustomerModel company_model = CompanyModel(self.testapp.session) customer_model = CustomerModel(self.testapp.session) with db_transaction.manager: other_company_guid = company_model.create( processor_key='MOCK_PROCESSOR_KEY', ) other_customer_guid = customer_model.create( company_guid=other_company_guid) self.testapp.post( '/v1/subscriptions', dict( customer_guid=other_customer_guid, plan_guid=self.plan_guid, ), extra_environ=dict(REMOTE_USER=self.api_key), status=403, )
def test_cancel_subscription_to_other_company(self): from billy.models.subscription import SubscriptionModel from billy.models.company import CompanyModel subscription_model = SubscriptionModel(self.testapp.session) company_model = CompanyModel(self.testapp.session) with db_transaction.manager: subscription_guid = subscription_model.create( customer_guid=self.customer_guid, plan_guid=self.plan_guid, ) other_company_guid = company_model.create( processor_key='MOCK_PROCESSOR_KEY', ) other_company = company_model.get(other_company_guid) other_api_key = str(other_company.api_key) self.testapp.post( '/v1/subscriptions/{}/cancel'.format(subscription_guid), extra_environ=dict(REMOTE_USER=other_api_key), status=403, )
def setUp(self): from billy.models.company import CompanyModel from billy.models.customer import CustomerModel from billy.models.plan import PlanModel self.settings = {'billy.processor_factory': DummyProcessor} super(TestSubscriptionViews, self).setUp() company_model = CompanyModel(self.testapp.session) customer_model = CustomerModel(self.testapp.session) plan_model = PlanModel(self.testapp.session) with db_transaction.manager: self.company_guid = company_model.create( processor_key='MOCK_PROCESSOR_KEY', ) self.customer_guid = customer_model.create( company_guid=self.company_guid) self.plan_guid = plan_model.create( company_guid=self.company_guid, frequency=plan_model.FREQ_WEEKLY, plan_type=plan_model.TYPE_CHARGE, amount=10, ) company = company_model.get(self.company_guid) self.api_key = str(company.api_key)
def test_get_subscription_of_other_company(self): from billy.models.company import CompanyModel from billy.models.customer import CustomerModel from billy.models.plan import PlanModel company_model = CompanyModel(self.testapp.session) customer_model = CustomerModel(self.testapp.session) plan_model = PlanModel(self.testapp.session) with db_transaction.manager: other_company_guid = company_model.create( processor_key='MOCK_PROCESSOR_KEY', ) other_customer_guid = customer_model.create( company_guid=other_company_guid) other_plan_guid = plan_model.create( company_guid=other_company_guid, frequency=plan_model.FREQ_WEEKLY, plan_type=plan_model.TYPE_CHARGE, amount=10, ) other_company = company_model.get(other_company_guid) other_api_key = str(other_company.api_key) res = self.testapp.post( '/v1/subscriptions', dict( customer_guid=other_customer_guid, plan_guid=other_plan_guid, ), extra_environ=dict(REMOTE_USER=other_api_key), status=200, ) other_guid = res.json['guid'] self.testapp.get( '/v1/subscriptions/{}'.format(other_guid), extra_environ=dict(REMOTE_USER=self.api_key), status=403, )
def test_get_plan_of_other_company(self): from billy.models.company import CompanyModel model = CompanyModel(self.testapp.session) with db_transaction.manager: other_company_guid = model.create( processor_key='MOCK_PROCESSOR_KEY') other_company = model.get(other_company_guid) other_api_key = str(other_company.api_key) res = self.testapp.post( '/v1/plans', dict( plan_type='charge', amount='55.66', frequency='weekly', ), extra_environ=dict(REMOTE_USER=other_api_key), status=200, ) guid = res.json['guid'] res = self.testapp.get( '/v1/plans/{}'.format(guid), extra_environ=dict(REMOTE_USER=self.api_key), status=403, )
def make_one(self, *args, **kwargs): from billy.models.company import CompanyModel return CompanyModel(*args, **kwargs)
def create_company_model(self): """Create a company model """ return CompanyModel(self)
def test_main_with_crash(self): from pyramid.paster import get_appsettings from billy.models import setup_database from billy.models.company import CompanyModel from billy.models.customer import CustomerModel from billy.models.plan import PlanModel from billy.models.subscription import SubscriptionModel from billy.scripts import initializedb from billy.scripts import process_transactions class MockProcessor(object): def __init__(self): self.charges = {} self.tx_sn = 0 self.called_times = 0 def create_customer(self, customer): return 'MOCK_PROCESSOR_CUSTOMER_ID' def prepare_customer(self, customer, payment_uri=None): pass def charge(self, transaction): self.called_times += 1 if self.called_times == 2: raise KeyboardInterrupt guid = transaction.guid if guid in self.charges: return self.charges[guid] self.charges[guid] = self.tx_sn self.tx_sn += 1 mock_processor = MockProcessor() cfg_path = os.path.join(self.temp_dir, 'config.ini') with open(cfg_path, 'wt') as f: f.write( textwrap.dedent("""\ [app:main] use = egg:billy sqlalchemy.url = sqlite:///%(here)s/billy.sqlite """)) initializedb.main([initializedb.__file__, cfg_path]) settings = get_appsettings(cfg_path) settings = setup_database({}, **settings) session = settings['session'] company_model = CompanyModel(session) customer_model = CustomerModel(session) plan_model = PlanModel(session) subscription_model = SubscriptionModel(session) with db_transaction.manager: company_guid = company_model.create('my_secret_key') plan_guid = plan_model.create( company_guid=company_guid, plan_type=plan_model.TYPE_CHARGE, amount=10, frequency=plan_model.FREQ_MONTHLY, ) customer_guid = customer_model.create(company_guid=company_guid, ) subscription_model.create( customer_guid=customer_guid, plan_guid=plan_guid, payment_uri='/v1/cards/tester', ) subscription_model.create( customer_guid=customer_guid, plan_guid=plan_guid, payment_uri='/v1/cards/tester', ) with self.assertRaises(KeyboardInterrupt): process_transactions.main( [process_transactions.__file__, cfg_path], processor=mock_processor) process_transactions.main([process_transactions.__file__, cfg_path], processor=mock_processor) # here is the story, we have two subscriptions here # # Subscription1 # Subscription2 # # And the time is not advanced, so we should only have two transactions # to be yielded and processed. However, we assume bad thing happens # durring the process. We let the second call to charge of processor # raises a KeyboardInterrupt error. So, it would look like this # # charge for transaction from Subscription1 # charge for transaction from Subscription2 (Crash) # # Then, we perform the process_transactions again, if it works # correctly, the first transaction is already yield and processed. # # charge for transaction from Subscription2 # # So, there would only be two charges in processor. This is mainly # for making sure we won't duplicate charges/payouts self.assertEqual(len(mock_processor.charges), 2)