Move Payment logic into Collector process.
* Adds storage layer to Collector * All code from Central related to payments, credit cards etc moved Change-Id: Ibd2d7d54ded239d7a3b8423c25b3291ca54792b2
This commit is contained in:
parent
b0f909200f
commit
f9ab0b1633
@ -19,7 +19,7 @@ import wsmeext.pecan as wsme_pecan
|
||||
|
||||
from billingstack.api.base import Query, _query_to_criterion, RestController
|
||||
from billingstack.api.v2 import models
|
||||
from billingstack.central.rpcapi import central_api
|
||||
from billingstack.collector.rpcapi import collector_api
|
||||
|
||||
|
||||
class PGProviders(RestController):
|
||||
@ -27,7 +27,7 @@ class PGProviders(RestController):
|
||||
def get_all(self, q=[]):
|
||||
criterion = _query_to_criterion(q)
|
||||
|
||||
rows = central_api.list_pg_providers(
|
||||
rows = collector_api.list_pg_providers(
|
||||
request.ctxt, criterion=criterion)
|
||||
|
||||
return map(models.PGProvider.from_db, rows)
|
||||
@ -39,14 +39,14 @@ class PGConfigController(RestController):
|
||||
|
||||
@wsme_pecan.wsexpose(models.PGConfig)
|
||||
def get_all(self):
|
||||
row = central_api.get_pg_config(request.ctxt, self.id_)
|
||||
row = collector_api.get_pg_config(request.ctxt, self.id_)
|
||||
|
||||
return models.PGConfig.from_db(row)
|
||||
|
||||
@wsme.validate(models.PGConfig)
|
||||
@wsme_pecan.wsexpose(models.PGConfig, body=models.PGConfig)
|
||||
def patch(self, body):
|
||||
row = central_api.update_pg_config(
|
||||
row = collector_api.update_pg_config(
|
||||
request.ctxt,
|
||||
self.id_,
|
||||
body.to_db())
|
||||
@ -55,7 +55,7 @@ class PGConfigController(RestController):
|
||||
|
||||
@wsme_pecan.wsexpose(None, status_code=204)
|
||||
def delete(self):
|
||||
central_api.delete_pg_config(request.ctxt, self.id_)
|
||||
collector_api.delete_pg_config(request.ctxt, self.id_)
|
||||
|
||||
|
||||
class PGConfigsController(RestController):
|
||||
@ -67,10 +67,12 @@ class PGConfigsController(RestController):
|
||||
@wsme_pecan.wsexpose(models.PGConfig, body=models.PGConfig,
|
||||
status_code=202)
|
||||
def post(self, body):
|
||||
row = central_api.create_pg_config(
|
||||
values = body.to_db()
|
||||
values['merchant_id'] = request.context['merchant_id']
|
||||
|
||||
row = collector_api.create_pg_config(
|
||||
request.ctxt,
|
||||
request.context['merchant_id'],
|
||||
body.to_db())
|
||||
values)
|
||||
|
||||
return models.PGConfig.from_db(row)
|
||||
|
||||
@ -79,7 +81,7 @@ class PGConfigsController(RestController):
|
||||
criterion = _query_to_criterion(
|
||||
q, merchant_id=request.context['merchant_id'])
|
||||
|
||||
rows = central_api.list_pg_configs(
|
||||
rows = collector_api.list_pg_configs(
|
||||
request.ctxt, criterion=criterion)
|
||||
|
||||
return map(models.PGConfig.from_db, rows)
|
||||
@ -92,14 +94,14 @@ class PaymentMethodController(RestController):
|
||||
|
||||
@wsme_pecan.wsexpose(models.PaymentMethod)
|
||||
def get_all(self):
|
||||
row = central_api.get_payment_method(request.ctxt, self.id_)
|
||||
row = collector_api.get_payment_method(request.ctxt, self.id_)
|
||||
|
||||
return models.PaymentMethod.from_db(row)
|
||||
|
||||
@wsme.validate(models.PaymentMethod)
|
||||
@wsme_pecan.wsexpose(models.PaymentMethod, body=models.PaymentMethod)
|
||||
def patch(self, body):
|
||||
row = central_api.update_payment_method(
|
||||
row = collector_api.update_payment_method(
|
||||
request.ctxt,
|
||||
self.id_,
|
||||
body.to_db())
|
||||
@ -108,7 +110,7 @@ class PaymentMethodController(RestController):
|
||||
|
||||
@wsme_pecan.wsexpose(None, status_code=204)
|
||||
def delete(self):
|
||||
central_api.delete_payment_method(request.ctxt, self.id_)
|
||||
collector_api.delete_payment_method(request.ctxt, self.id_)
|
||||
|
||||
|
||||
class PaymentMethodsController(RestController):
|
||||
@ -120,10 +122,10 @@ class PaymentMethodsController(RestController):
|
||||
@wsme_pecan.wsexpose(models.PaymentMethod, body=models.PaymentMethod,
|
||||
status_code=202)
|
||||
def post(self, body):
|
||||
row = central_api.create_payment_method(
|
||||
request.ctxt,
|
||||
request.context['customer_id'],
|
||||
body.to_db())
|
||||
values = body.to_db()
|
||||
values['customer_id'] = request.context['customer_id']
|
||||
|
||||
row = collector_api.create_payment_method(request.ctxt, values)
|
||||
|
||||
return models.PaymentMethod.from_db(row)
|
||||
|
||||
@ -133,7 +135,7 @@ class PaymentMethodsController(RestController):
|
||||
q, merchant_id=request.context['merchant_id'],
|
||||
customer_id=request.context['customer_id'])
|
||||
|
||||
rows = central_api.list_payment_methods(
|
||||
rows = collector_api.list_payment_methods(
|
||||
request.ctxt, criterion=criterion)
|
||||
|
||||
return map(models.PaymentMethod.from_db, rows)
|
||||
|
@ -155,8 +155,11 @@ class Usage(Base):
|
||||
class PGConfig(Base):
|
||||
name = text
|
||||
title = text
|
||||
|
||||
merchant_id = text
|
||||
provider_id = text
|
||||
|
||||
is_default = bool
|
||||
properties = DictType(key_type=text, value_type=property_type)
|
||||
|
||||
|
||||
@ -165,6 +168,7 @@ class PaymentMethod(Base):
|
||||
identifier = text
|
||||
expires = text
|
||||
|
||||
merchant_id = text
|
||||
customer_id = text
|
||||
provider_config_id = text
|
||||
|
||||
@ -186,15 +190,11 @@ class Merchant(Account):
|
||||
def to_db(self):
|
||||
values = self.as_dict()
|
||||
change_suffixes(values, self._keys, shorten=False)
|
||||
if 'default_gateway' in values:
|
||||
values['default_gateway_id'] = values.pop('default_gateway')
|
||||
return values
|
||||
|
||||
@classmethod
|
||||
def from_db(cls, values):
|
||||
change_suffixes(values, cls._keys)
|
||||
if 'default_gateway_id' in values:
|
||||
values['default_gateway'] = values.pop('default_gateway_id')
|
||||
return cls(**values)
|
||||
|
||||
|
||||
|
@ -86,63 +86,6 @@ class CentralAPI(proxy.RpcProxy):
|
||||
def delete_contact_info(self, ctxt, id_):
|
||||
return self.call(ctxt, self.make_msg('delete_contact_info', id_=id_))
|
||||
|
||||
# PGP
|
||||
def list_pg_providers(self, ctxt, criterion=None):
|
||||
return self.call(ctxt, self.make_msg('list_pg_providers',
|
||||
criterion=criterion))
|
||||
|
||||
def get_pg_provider(self, ctxt, id_):
|
||||
return self.call(ctxt, self.make_msg('get_pg_provider', id_=id_))
|
||||
|
||||
# PGM
|
||||
def list_pg_methods(self, ctxt, criterion=None):
|
||||
return self.call(ctxt, self.make_msg('list_pg_methods',
|
||||
criterion=criterion))
|
||||
|
||||
def get_pg_method(self, ctxt, id_):
|
||||
return self.call(ctxt, self.make_msg('get_pg_method', id_=id_))
|
||||
|
||||
def delete_pg_method(self, ctxt, id_):
|
||||
return self.call(ctxt, self.make_msg('delete_pg_method', id_=id_))
|
||||
|
||||
# PGC
|
||||
def create_pg_config(self, ctxt, merchant_id, values):
|
||||
return self.call(ctxt, self.make_msg('create_pg_config',
|
||||
merchant_id=merchant_id, values=values))
|
||||
|
||||
def list_pg_configs(self, ctxt, criterion=None):
|
||||
return self.call(ctxt, self.make_msg('list_pg_configs',
|
||||
criterion=criterion))
|
||||
|
||||
def get_pg_config(self, ctxt, id_):
|
||||
return self.call(ctxt, self.make_msg('get_pg_config', id_=id_))
|
||||
|
||||
def update_pg_config(self, ctxt, id_, values):
|
||||
return self.call(ctxt, self.make_msg('update_pg_config', id_=id_,
|
||||
values=values))
|
||||
|
||||
def delete_pg_config(self, ctxt, id_):
|
||||
return self.call(ctxt, self.make_msg('delete_pg_config', id_=id_))
|
||||
|
||||
# PaymentMethod
|
||||
def create_payment_method(self, ctxt, customer_id, values):
|
||||
return self.call(ctxt, self.make_msg('create_payment_method',
|
||||
customer_id=customer_id, values=values))
|
||||
|
||||
def list_payment_methods(self, ctxt, criterion=None):
|
||||
return self.call(ctxt, self.make_msg('list_payment_methods',
|
||||
criterion=criterion))
|
||||
|
||||
def get_payment_method(self, ctxt, id_):
|
||||
return self.call(ctxt, self.make_msg('get_payment_method', id_=id_))
|
||||
|
||||
def update_payment_method(self, ctxt, id_, values):
|
||||
return self.call(ctxt, self.make_msg('update_payment_method', id_=id_,
|
||||
values=values))
|
||||
|
||||
def delete_payment_method(self, ctxt, id_):
|
||||
return self.call(ctxt, self.make_msg('delete_payment_method', id_=id_))
|
||||
|
||||
# Merchant
|
||||
def create_merchant(self, ctxt, values):
|
||||
return self.call(ctxt, self.make_msg('create_merchant', values=values))
|
||||
|
@ -100,39 +100,6 @@ class Service(rpc_service.Service):
|
||||
def get_pg_provider(self, ctxt, pgp_id):
|
||||
return self.storage_conn.get_pg_provider(ctxt, pgp_id)
|
||||
|
||||
# PGC
|
||||
def create_pg_config(self, ctxt, merchant_id, values):
|
||||
return self.storage_conn.create_pg_config(ctxt, merchant_id, values)
|
||||
|
||||
def list_pg_configs(self, ctxt, **kw):
|
||||
return self.storage_conn.list_pg_configs(ctxt, **kw)
|
||||
|
||||
def get_pg_config(self, ctxt, id_):
|
||||
return self.storage_conn.get_pg_config(ctxt, id_)
|
||||
|
||||
def update_pg_config(self, ctxt, id_, values):
|
||||
return self.storage_conn.update_pg_config(ctxt, id_, values)
|
||||
|
||||
def delete_pg_config(self, ctxt, id_):
|
||||
return self.storage_conn.delete_pg_config(ctxt, id_)
|
||||
|
||||
# PM
|
||||
def create_payment_method(self, ctxt, customer_id, values):
|
||||
return self.storage_conn.create_payment_method(
|
||||
ctxt, customer_id, values)
|
||||
|
||||
def list_payment_methods(self, ctxt, **kw):
|
||||
return self.storage_conn.list_payment_methods(ctxt, **kw)
|
||||
|
||||
def get_payment_method(self, ctxt, id_, **kw):
|
||||
return self.storage_conn.get_payment_method(ctxt, id_)
|
||||
|
||||
def update_payment_method(self, ctxt, id_, values):
|
||||
return self.storage_conn.update_payment_method(ctxt, id_, values)
|
||||
|
||||
def delete_payment_method(self, ctxt, id_):
|
||||
return self.storage_conn.delete_payment_method(ctxt, id_)
|
||||
|
||||
# Merchant
|
||||
def create_merchant(self, ctxt, values):
|
||||
return self.storage_conn.create_merchant(ctxt, values)
|
||||
|
@ -33,16 +33,6 @@ cfg.CONF.register_group(cfg.OptGroup(
|
||||
cfg.CONF.register_opts(SQLOPTS, group='central:sqlalchemy')
|
||||
|
||||
|
||||
def filter_merchant_by_join(query, cls, criterion):
|
||||
if criterion and 'merchant_id' in criterion:
|
||||
merchant_id = criterion.pop('merchant_id')
|
||||
if not hasattr(cls, 'merchant_id'):
|
||||
raise RuntimeError('No merchant_id attribute on %s' % cls)
|
||||
|
||||
query = query.join(cls).filter(cls.merchant_id == merchant_id)
|
||||
return query
|
||||
|
||||
|
||||
class SQLAlchemyEngine(StorageEngine):
|
||||
__plugin_name__ = 'sqlalchemy'
|
||||
|
||||
@ -176,132 +166,6 @@ class Connection(Connection, api.HelpersMixin):
|
||||
def delete_contact_info(self, ctxt, id_):
|
||||
self._delete(models.ContactInfo, id_)
|
||||
|
||||
# Payment Gateway Providers
|
||||
def pg_provider_register(self, ctxt, values):
|
||||
"""
|
||||
Register a Provider and it's Methods
|
||||
"""
|
||||
values = values.copy()
|
||||
methods = values.pop('methods', [])
|
||||
|
||||
query = self.session.query(models.PGProvider)\
|
||||
.filter_by(name=values['name'])
|
||||
|
||||
try:
|
||||
provider = query.one()
|
||||
except exc.NoResultFound:
|
||||
provider = models.PGProvider()
|
||||
|
||||
provider.update(values)
|
||||
|
||||
self._set_provider_methods(ctxt, provider, methods)
|
||||
|
||||
self._save(provider)
|
||||
return self._dict(provider, extra=['methods'])
|
||||
|
||||
def list_pg_providers(self, ctxt, **kw):
|
||||
"""
|
||||
List available PG Providers
|
||||
"""
|
||||
rows = self._list(models.PGProvider, **kw)
|
||||
return [self._dict(r, extra=['methods']) for r in rows]
|
||||
|
||||
def get_pg_provider(self, ctxt, pgp_id):
|
||||
row = self._get(models.PGProvider, pgp_id)
|
||||
return self._dict(row, extra=['methods'])
|
||||
|
||||
def pg_provider_deregister(self, ctxt, id_):
|
||||
self._delete(models.PGProvider, id_)
|
||||
|
||||
def _get_provider_methods(self, provider):
|
||||
"""
|
||||
Used internally to form a "Map" of the Providers methods
|
||||
"""
|
||||
methods = {}
|
||||
for m in provider.methods:
|
||||
methods[m.key()] = m
|
||||
return methods
|
||||
|
||||
def _set_provider_methods(self, ctxt, provider, config_methods):
|
||||
"""Helper method for setting the Methods for a Provider"""
|
||||
existing = self._get_provider_methods(provider)
|
||||
for method in config_methods:
|
||||
self._set_method(provider, method, existing)
|
||||
|
||||
def _set_method(self, provider, method, existing):
|
||||
key = models.PGMethod.make_key(method)
|
||||
|
||||
if key in existing:
|
||||
existing[key].update(method)
|
||||
else:
|
||||
row = models.PGMethod(**method)
|
||||
provider.methods.append(row)
|
||||
|
||||
# Payment Gateway Configuration
|
||||
def create_pg_config(self, ctxt, merchant_id, values):
|
||||
merchant = self._get(models.Merchant, merchant_id)
|
||||
|
||||
row = models.PGConfig(**values)
|
||||
row.merchant = merchant
|
||||
|
||||
self._save(row)
|
||||
return dict(row)
|
||||
|
||||
def list_pg_configs(self, ctxt, **kw):
|
||||
rows = self._list(models.PGConfig, **kw)
|
||||
return map(dict, rows)
|
||||
|
||||
def get_pg_config(self, ctxt, id_):
|
||||
row = self._get(models.PGConfig, id_)
|
||||
return dict(row)
|
||||
|
||||
def update_pg_config(self, ctxt, id_, values):
|
||||
row = self._update(models.PGConfig, id_, values)
|
||||
return dict(row)
|
||||
|
||||
def delete_pg_config(self, ctxt, id_):
|
||||
self._delete(models.PGConfig, id_)
|
||||
|
||||
# PaymentMethod
|
||||
def create_payment_method(self, ctxt, customer_id, values):
|
||||
"""
|
||||
Configure a PaymentMethod like a CreditCard
|
||||
"""
|
||||
customer = self._get_id_or_name(models.Customer, customer_id)
|
||||
|
||||
# NOTE: Attempt to see if there's a default gateway if none is
|
||||
# specified
|
||||
if not values.get('provider_config_id') and \
|
||||
customer.merchant.default_gateway:
|
||||
values['provider_config_id'] = customer.merchant.default_gateway_id
|
||||
|
||||
row = models.PaymentMethod(**values)
|
||||
row.customer = customer
|
||||
|
||||
self._save(row)
|
||||
return self._dict(row)
|
||||
|
||||
def list_payment_methods(self, ctxt, criterion=None, **kw):
|
||||
query = self.session.query(models.PaymentMethod)
|
||||
|
||||
query = filter_merchant_by_join(query, models.Customer, criterion)
|
||||
|
||||
rows = self._list(query=query, cls=models.PaymentMethod,
|
||||
criterion=criterion, **kw)
|
||||
|
||||
return [self._dict(row) for row in rows]
|
||||
|
||||
def get_payment_method(self, ctxt, id_, **kw):
|
||||
row = self._get_id_or_name(models.PaymentMethod, id_)
|
||||
return self._dict(row)
|
||||
|
||||
def update_payment_method(self, ctxt, id_, values):
|
||||
row = self._update(models.PaymentMethod, id_, values)
|
||||
return self._dict(row)
|
||||
|
||||
def delete_payment_method(self, ctxt, id_):
|
||||
self._delete(models.PaymentMethod, id_)
|
||||
|
||||
# Merchant
|
||||
def create_merchant(self, ctxt, values):
|
||||
row = models.Merchant(**values)
|
||||
@ -595,10 +459,15 @@ class Connection(Connection, api.HelpersMixin):
|
||||
"""
|
||||
query = self.session.query(models.Subscription)
|
||||
|
||||
query = filter_merchant_by_join(query, models.Customer, criterion)
|
||||
# NOTE: Filter needs to be joined for merchant_id
|
||||
query = db_utils.filter_merchant_by_join(
|
||||
query, models.Customer, criterion)
|
||||
|
||||
rows = self._list(query=query, cls=models.Subscription,
|
||||
criterion=criterion, **kw)
|
||||
rows = self._list(
|
||||
query=query,
|
||||
cls=models.Subscription,
|
||||
criterion=criterion,
|
||||
**kw)
|
||||
|
||||
return map(self._subscription, rows)
|
||||
|
||||
|
@ -46,62 +46,6 @@ class Language(BASE):
|
||||
title = Column(Unicode(100), nullable=False)
|
||||
|
||||
|
||||
class PGProvider(BASE, BaseMixin):
|
||||
"""
|
||||
A Payment Gateway - The thing that processes a Payment Method
|
||||
|
||||
This is registered either by the Admin or by the PaymentGateway plugin
|
||||
"""
|
||||
__tablename__ = 'pg_provider'
|
||||
|
||||
name = Column(Unicode(60), nullable=False)
|
||||
title = Column(Unicode(100))
|
||||
description = Column(Unicode(255))
|
||||
|
||||
properties = Column(JSON)
|
||||
|
||||
methods = relationship(
|
||||
'PGMethod',
|
||||
backref='provider',
|
||||
lazy='joined')
|
||||
|
||||
def method_map(self):
|
||||
return self.attrs_map(['provider_methods'])
|
||||
|
||||
|
||||
class PGMethod(BASE, BaseMixin):
|
||||
"""
|
||||
This represents a PaymentGatewayProviders method with some information
|
||||
like name, type etc to describe what is in other settings known as a
|
||||
"CreditCard"
|
||||
|
||||
Example:
|
||||
A Visa card: {"type": "creditcard", "visa"}
|
||||
"""
|
||||
__tablename__ = 'pg_method'
|
||||
|
||||
name = Column(Unicode(100), nullable=False)
|
||||
title = Column(Unicode(100))
|
||||
description = Column(Unicode(255))
|
||||
|
||||
type = Column(Unicode(100), nullable=False)
|
||||
properties = Column(JSON)
|
||||
|
||||
# NOTE: This is so a PGMethod can be "owned" by a Provider, meaning that
|
||||
# other Providers should not be able to use it.
|
||||
provider_id = Column(UUID, ForeignKey(
|
||||
'pg_provider.id',
|
||||
ondelete='CASCADE',
|
||||
onupdate='CASCADE'))
|
||||
|
||||
@staticmethod
|
||||
def make_key(data):
|
||||
return '%(type)s:%(name)s' % data
|
||||
|
||||
def key(self):
|
||||
return self.make_key(self)
|
||||
|
||||
|
||||
class ContactInfo(BASE, BaseMixin):
|
||||
"""
|
||||
Contact Information about an entity like a User, Customer etc...
|
||||
@ -146,20 +90,10 @@ class Merchant(BASE, BaseMixin):
|
||||
title = Column(Unicode(60))
|
||||
|
||||
customers = relationship('Customer', backref='merchant')
|
||||
payment_gateways = relationship(
|
||||
'PGConfig', backref='merchant',
|
||||
primaryjoin='merchant.c.id==pg_config.c.merchant_id')
|
||||
|
||||
plans = relationship('Plan', backref='merchant')
|
||||
products = relationship('Product', backref='merchant')
|
||||
|
||||
default_gateway = relationship(
|
||||
'PGConfig', uselist=False,
|
||||
primaryjoin='merchant.c.id==pg_config.c.merchant_id')
|
||||
default_gateway_id = Column(UUID, ForeignKey('pg_config.id',
|
||||
use_alter=True, name='default_gateway'),
|
||||
nullable=True)
|
||||
|
||||
currency = relationship('Currency', uselist=False, backref='merchants')
|
||||
currency_name = Column(Unicode(10), ForeignKey('currency.name'),
|
||||
nullable=False)
|
||||
@ -169,27 +103,6 @@ class Merchant(BASE, BaseMixin):
|
||||
nullable=False)
|
||||
|
||||
|
||||
class PGConfig(BASE, BaseMixin):
|
||||
"""
|
||||
A Merchant's configuration of a PaymentGateway like api keys, url and more
|
||||
"""
|
||||
__tablename__ = 'pg_config'
|
||||
|
||||
name = Column(Unicode(100), nullable=False)
|
||||
title = Column(Unicode(100))
|
||||
|
||||
properties = Column(JSON)
|
||||
|
||||
# Link to the Merchant
|
||||
merchant_id = Column(UUID, ForeignKey('merchant.id'), nullable=False)
|
||||
|
||||
provider = relationship('PGProvider',
|
||||
backref='merchant_configurations')
|
||||
provider_id = Column(UUID, ForeignKey('pg_provider.id',
|
||||
onupdate='CASCADE'),
|
||||
nullable=False)
|
||||
|
||||
|
||||
class Customer(BASE, BaseMixin):
|
||||
"""
|
||||
A Customer is linked to a Merchant and can have Users related to it
|
||||
@ -200,8 +113,6 @@ class Customer(BASE, BaseMixin):
|
||||
merchant_id = Column(UUID, ForeignKey('merchant.id', ondelete='CASCADE'),
|
||||
nullable=False)
|
||||
|
||||
payment_methods = relationship('PaymentMethod', backref='customer')
|
||||
|
||||
contact_info = relationship(
|
||||
'CustomerInfo',
|
||||
backref='customer',
|
||||
@ -225,22 +136,6 @@ class Customer(BASE, BaseMixin):
|
||||
language_name = Column(Unicode(10), ForeignKey('language.name'))
|
||||
|
||||
|
||||
class PaymentMethod(BASE, BaseMixin):
|
||||
name = Column(Unicode(255), nullable=False)
|
||||
|
||||
identifier = Column(Unicode(255), nullable=False)
|
||||
expires = Column(Unicode(255))
|
||||
|
||||
properties = Column(JSON)
|
||||
|
||||
customer_id = Column(UUID, ForeignKey('customer.id', onupdate='CASCADE'),
|
||||
nullable=False)
|
||||
|
||||
provider_config = relationship('PGConfig', backref='payment_methods')
|
||||
provider_config_id = Column(UUID, ForeignKey('pg_config.id',
|
||||
onupdate='CASCADE'), nullable=False)
|
||||
|
||||
|
||||
class Plan(BASE, BaseMixin):
|
||||
"""
|
||||
A Product collection like a "Virtual Web Cluster" with 10 servers
|
||||
@ -330,6 +225,4 @@ class Subscription(BASE, BaseMixin):
|
||||
customer_id = Column(UUID, ForeignKey('customer.id', ondelete='CASCADE'),
|
||||
nullable=False)
|
||||
|
||||
payment_method = relationship('PaymentMethod', backref='subscriptions')
|
||||
payment_method_id = Column(UUID, ForeignKey('payment_method.id',
|
||||
ondelete='CASCADE', onupdate='CASCADE'))
|
||||
payment_method_id = Column(UUID)
|
||||
|
@ -33,5 +33,62 @@ class CollectorAPI(proxy.RpcProxy):
|
||||
topic=cfg.CONF.collector_topic,
|
||||
default_version=self.BASE_RPC_VERSION)
|
||||
|
||||
# PGP
|
||||
def list_pg_providers(self, ctxt, criterion=None):
|
||||
return self.call(ctxt, self.make_msg('list_pg_providers',
|
||||
criterion=criterion))
|
||||
|
||||
def get_pg_provider(self, ctxt, id_):
|
||||
return self.call(ctxt, self.make_msg('get_pg_provider', id_=id_))
|
||||
|
||||
# PGM
|
||||
def list_pg_methods(self, ctxt, criterion=None):
|
||||
return self.call(ctxt, self.make_msg('list_pg_methods',
|
||||
criterion=criterion))
|
||||
|
||||
def get_pg_method(self, ctxt, id_):
|
||||
return self.call(ctxt, self.make_msg('get_pg_method', id_=id_))
|
||||
|
||||
def delete_pg_method(self, ctxt, id_):
|
||||
return self.call(ctxt, self.make_msg('delete_pg_method', id_=id_))
|
||||
|
||||
# PGC
|
||||
def create_pg_config(self, ctxt, values):
|
||||
return self.call(ctxt, self.make_msg('create_pg_config',
|
||||
values=values))
|
||||
|
||||
def list_pg_configs(self, ctxt, criterion=None):
|
||||
return self.call(ctxt, self.make_msg('list_pg_configs',
|
||||
criterion=criterion))
|
||||
|
||||
def get_pg_config(self, ctxt, id_):
|
||||
return self.call(ctxt, self.make_msg('get_pg_config', id_=id_))
|
||||
|
||||
def update_pg_config(self, ctxt, id_, values):
|
||||
return self.call(ctxt, self.make_msg('update_pg_config', id_=id_,
|
||||
values=values))
|
||||
|
||||
def delete_pg_config(self, ctxt, id_):
|
||||
return self.call(ctxt, self.make_msg('delete_pg_config', id_=id_))
|
||||
|
||||
# PaymentMethod
|
||||
def create_payment_method(self, ctxt, values):
|
||||
return self.call(ctxt, self.make_msg('create_payment_method',
|
||||
values=values))
|
||||
|
||||
def list_payment_methods(self, ctxt, criterion=None):
|
||||
return self.call(ctxt, self.make_msg('list_payment_methods',
|
||||
criterion=criterion))
|
||||
|
||||
def get_payment_method(self, ctxt, id_):
|
||||
return self.call(ctxt, self.make_msg('get_payment_method', id_=id_))
|
||||
|
||||
def update_payment_method(self, ctxt, id_, values):
|
||||
return self.call(ctxt, self.make_msg('update_payment_method', id_=id_,
|
||||
values=values))
|
||||
|
||||
def delete_payment_method(self, ctxt, id_):
|
||||
return self.call(ctxt, self.make_msg('delete_payment_method', id_=id_))
|
||||
|
||||
|
||||
collector_api = CollectorAPI()
|
||||
|
@ -23,6 +23,7 @@ from oslo.config import cfg
|
||||
from billingstack.openstack.common import log as logging
|
||||
from billingstack.openstack.common.rpc import service as rpc_service
|
||||
from billingstack.openstack.common import service as os_service
|
||||
from billingstack.storage.utils import get_connection
|
||||
from billingstack.central.rpcapi import CentralAPI
|
||||
from billingstack import service as bs_service
|
||||
|
||||
@ -47,26 +48,49 @@ class Service(rpc_service.Service):
|
||||
# Get a storage connection
|
||||
self.central_api = CentralAPI()
|
||||
|
||||
def start(self):
|
||||
self.storage_conn = get_connection('collector')
|
||||
super(Service, self).start()
|
||||
|
||||
def wait(self):
|
||||
super(Service, self).wait()
|
||||
self.conn.consumer_thread.wait()
|
||||
|
||||
def get_pg_provider(self, ctxt, pg_info):
|
||||
"""
|
||||
Work out a PGC config either from pg_info or via ctxt fetching it
|
||||
from central.
|
||||
Return the appropriate PGP for this info.
|
||||
# PGP
|
||||
def list_pg_providers(self, ctxt, **kw):
|
||||
return self.storage_conn.list_pg_providers(ctxt, **kw)
|
||||
|
||||
:param ctxt: Request context
|
||||
:param pg_info: Payment Gateway Config...
|
||||
"""
|
||||
# PGC
|
||||
def create_pg_config(self, ctxt, values):
|
||||
return self.storage_conn.create_pg_config(ctxt, values)
|
||||
|
||||
def create_account(self, ctxt, values, pg_config=None):
|
||||
"""
|
||||
Create an Account on the underlying provider
|
||||
def list_pg_configs(self, ctxt, **kw):
|
||||
return self.storage_conn.list_pg_configs(ctxt, **kw)
|
||||
|
||||
:param values: The account values
|
||||
"""
|
||||
def get_pg_config(self, ctxt, id_):
|
||||
return self.storage_conn.get_pg_config(ctxt, id_)
|
||||
|
||||
def update_pg_config(self, ctxt, id_, values):
|
||||
return self.storage_conn.update_pg_config(ctxt, id_, values)
|
||||
|
||||
def delete_pg_config(self, ctxt, id_):
|
||||
return self.storage_conn.delete_pg_config(ctxt, id_)
|
||||
|
||||
# PM
|
||||
def create_payment_method(self, ctxt, values):
|
||||
return self.storage_conn.create_payment_method(ctxt, values)
|
||||
|
||||
def list_payment_methods(self, ctxt, **kw):
|
||||
return self.storage_conn.list_payment_methods(ctxt, **kw)
|
||||
|
||||
def get_payment_method(self, ctxt, id_, **kw):
|
||||
return self.storage_conn.get_payment_method(ctxt, id_)
|
||||
|
||||
def update_payment_method(self, ctxt, id_, values):
|
||||
return self.storage_conn.update_payment_method(ctxt, id_, values)
|
||||
|
||||
def delete_payment_method(self, ctxt, id_):
|
||||
return self.storage_conn.delete_payment_method(ctxt, id_)
|
||||
|
||||
|
||||
def launch():
|
||||
|
108
billingstack/collector/storage/__init__.py
Normal file
108
billingstack/collector/storage/__init__.py
Normal file
@ -0,0 +1,108 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
#
|
||||
# Author: Endre Karlson <endre.karlson@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from billingstack.storage import base
|
||||
|
||||
|
||||
class StorageEngine(base.StorageEngine):
|
||||
"""Base class for the collector storage"""
|
||||
__plugin_ns__ = 'billingstack.collector.storage'
|
||||
|
||||
|
||||
class Connection(base.Connection):
|
||||
"""Define the base API for collector storage"""
|
||||
def pg_provider_register(self):
|
||||
"""
|
||||
Register a Provider and it's Methods
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def list_pg_providers(self, ctxt, **kw):
|
||||
"""
|
||||
List available PG Providers
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_pg_provider(self, ctxt, id_):
|
||||
"""
|
||||
Get a PaymentGateway Provider
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def pg_provider_deregister(self, ctxt, id_):
|
||||
"""
|
||||
De-register a PaymentGateway Provider (Plugin) and all it's methods
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def create_pg_config(self, ctxt, values):
|
||||
"""
|
||||
Create a PaymentGateway Configuration
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def list_pg_configs(self, ctxt, **kw):
|
||||
"""
|
||||
List PaymentGateway Configurations
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_pg_config(self, ctxt, id_):
|
||||
"""
|
||||
Get a PaymentGateway Configuration
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def update_pg_config(self, ctxt, id_, values):
|
||||
"""
|
||||
Update a PaymentGateway Configuration
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def delete_pg_config(self, ctxt, id_):
|
||||
"""
|
||||
Delete a PaymentGateway Configuration
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def create_payment_method(self, ctxt, values):
|
||||
"""
|
||||
Configure a PaymentMethod like a CreditCard
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def list_payment_methods(self, ctxt, criterion=None, **kw):
|
||||
"""
|
||||
List a Customer's PaymentMethods
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_payment_method(self, ctxt, id_, **kw):
|
||||
"""
|
||||
Get a Customer's PaymentMethod
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def update_payment_method(self, ctxt, id_, values):
|
||||
"""
|
||||
Update a Customer's PaymentMethod
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def delete_payment_method(self, ctxt, id_):
|
||||
"""
|
||||
Delete a Customer's PaymentMethod
|
||||
"""
|
||||
raise NotImplementedError
|
258
billingstack/collector/storage/impl_sqlalchemy.py
Normal file
258
billingstack/collector/storage/impl_sqlalchemy.py
Normal file
@ -0,0 +1,258 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
#
|
||||
# Author: Endre Karlson <endre.karlson@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from oslo.config import cfg
|
||||
|
||||
|
||||
from sqlalchemy import Column, ForeignKey
|
||||
from sqlalchemy import Unicode
|
||||
from sqlalchemy.orm import exc, relationship
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
|
||||
from billingstack.collector.storage import Connection, StorageEngine
|
||||
from billingstack.openstack.common import log as logging
|
||||
from billingstack.sqlalchemy.types import JSON, UUID
|
||||
from billingstack.sqlalchemy import api, model_base, session, utils
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
BASE = declarative_base(cls=model_base.ModelBase)
|
||||
|
||||
|
||||
cfg.CONF.register_group(cfg.OptGroup(
|
||||
name='collector:sqlalchemy',
|
||||
title='Config for collector sqlalchemy plugin'))
|
||||
|
||||
cfg.CONF.register_opts(session.SQLOPTS, group='collector:sqlalchemy')
|
||||
|
||||
|
||||
class PGProvider(BASE, model_base.BaseMixin):
|
||||
"""
|
||||
A Payment Gateway - The thing that processes a Payment Method
|
||||
|
||||
This is registered either by the Admin or by the PaymentGateway plugin
|
||||
"""
|
||||
__tablename__ = 'pg_provider'
|
||||
|
||||
name = Column(Unicode(60), nullable=False)
|
||||
title = Column(Unicode(100))
|
||||
description = Column(Unicode(255))
|
||||
|
||||
properties = Column(JSON)
|
||||
|
||||
methods = relationship(
|
||||
'PGMethod',
|
||||
backref='provider',
|
||||
lazy='joined')
|
||||
|
||||
def method_map(self):
|
||||
return self.attrs_map(['provider_methods'])
|
||||
|
||||
|
||||
class PGMethod(BASE, model_base.BaseMixin):
|
||||
"""
|
||||
This represents a PaymentGatewayProviders method with some information
|
||||
like name, type etc to describe what is in other settings known as a
|
||||
"CreditCard"
|
||||
|
||||
Example:
|
||||
A Visa card: {"type": "creditcard", "visa"}
|
||||
"""
|
||||
__tablename__ = 'pg_method'
|
||||
|
||||
name = Column(Unicode(100), nullable=False)
|
||||
title = Column(Unicode(100))
|
||||
description = Column(Unicode(255))
|
||||
|
||||
type = Column(Unicode(100), nullable=False)
|
||||
properties = Column(JSON)
|
||||
|
||||
# NOTE: This is so a PGMethod can be "owned" by a Provider, meaning that
|
||||
# other Providers should not be able to use it.
|
||||
provider_id = Column(UUID, ForeignKey(
|
||||
'pg_provider.id',
|
||||
ondelete='CASCADE',
|
||||
onupdate='CASCADE'))
|
||||
|
||||
@staticmethod
|
||||
def make_key(data):
|
||||
return '%(type)s:%(name)s' % data
|
||||
|
||||
def key(self):
|
||||
return self.make_key(self)
|
||||
|
||||
|
||||
class PGConfig(BASE, model_base.BaseMixin):
|
||||
"""
|
||||
A Merchant's configuration of a PaymentGateway like api keys, url and more
|
||||
"""
|
||||
__tablename__ = 'pg_config'
|
||||
|
||||
name = Column(Unicode(100), nullable=False)
|
||||
title = Column(Unicode(100))
|
||||
|
||||
properties = Column(JSON)
|
||||
|
||||
# Link to the Merchant
|
||||
merchant_id = Column(UUID, nullable=False)
|
||||
|
||||
provider = relationship('PGProvider',
|
||||
backref='merchant_configurations')
|
||||
provider_id = Column(UUID, ForeignKey('pg_provider.id',
|
||||
onupdate='CASCADE'),
|
||||
nullable=False)
|
||||
|
||||
|
||||
class PaymentMethod(BASE, model_base.BaseMixin):
|
||||
name = Column(Unicode(255), nullable=False)
|
||||
|
||||
identifier = Column(Unicode(255), nullable=False)
|
||||
expires = Column(Unicode(255))
|
||||
|
||||
properties = Column(JSON)
|
||||
|
||||
customer_id = Column(UUID, nullable=False)
|
||||
|
||||
provider_config = relationship('PGConfig', backref='payment_methods',
|
||||
lazy='joined')
|
||||
provider_config_id = Column(UUID, ForeignKey('pg_config.id',
|
||||
onupdate='CASCADE'), nullable=False)
|
||||
|
||||
|
||||
class SQLAlchemyEngine(StorageEngine):
|
||||
__plugin_name__ = 'sqlalchemy'
|
||||
|
||||
def get_connection(self):
|
||||
return Connection()
|
||||
|
||||
|
||||
class Connection(Connection, api.HelpersMixin):
|
||||
def __init__(self):
|
||||
self.setup('collector:sqlalchemy')
|
||||
|
||||
def base(self):
|
||||
return BASE
|
||||
|
||||
# Payment Gateway Providers
|
||||
def pg_provider_register(self, ctxt, values):
|
||||
values = values.copy()
|
||||
methods = values.pop('methods', [])
|
||||
|
||||
query = self.session.query(PGProvider)\
|
||||
.filter_by(name=values['name'])
|
||||
|
||||
try:
|
||||
provider = query.one()
|
||||
except exc.NoResultFound:
|
||||
provider = PGProvider()
|
||||
|
||||
provider.update(values)
|
||||
|
||||
self._set_provider_methods(ctxt, provider, methods)
|
||||
|
||||
self._save(provider)
|
||||
return self._dict(provider, extra=['methods'])
|
||||
|
||||
def list_pg_providers(self, ctxt, **kw):
|
||||
rows = self._list(PGProvider, **kw)
|
||||
return [self._dict(r, extra=['methods']) for r in rows]
|
||||
|
||||
def get_pg_provider(self, ctxt, id_, **kw):
|
||||
row = self._get(PGProvider, id_)
|
||||
return self._dict(row, extra=['methods'])
|
||||
|
||||
def pg_provider_deregister(self, ctxt, id_):
|
||||
self._delete(PGProvider, id_)
|
||||
|
||||
def _get_provider_methods(self, provider):
|
||||
"""
|
||||
Used internally to form a "Map" of the Providers methods
|
||||
"""
|
||||
methods = {}
|
||||
for m in provider.methods:
|
||||
methods[m.key()] = m
|
||||
return methods
|
||||
|
||||
def _set_provider_methods(self, ctxt, provider, config_methods):
|
||||
"""Helper method for setting the Methods for a Provider"""
|
||||
existing = self._get_provider_methods(provider)
|
||||
for method in config_methods:
|
||||
self._set_method(provider, method, existing)
|
||||
|
||||
def _set_method(self, provider, method, existing):
|
||||
key = PGMethod.make_key(method)
|
||||
|
||||
if key in existing:
|
||||
existing[key].update(method)
|
||||
else:
|
||||
row = PGMethod(**method)
|
||||
provider.methods.append(row)
|
||||
|
||||
# Payment Gateway Configuration
|
||||
def create_pg_config(self, ctxt, values):
|
||||
row = PGConfig(**values)
|
||||
|
||||
self._save(row)
|
||||
return dict(row)
|
||||
|
||||
def list_pg_configs(self, ctxt, **kw):
|
||||
rows = self._list(PGConfig, **kw)
|
||||
return map(dict, rows)
|
||||
|
||||
def get_pg_config(self, ctxt, id_, **kw):
|
||||
row = self._get(PGConfig, id_, **kw)
|
||||
return dict(row)
|
||||
|
||||
def update_pg_config(self, ctxt, id_, values):
|
||||
row = self._update(PGConfig, id_, values)
|
||||
return dict(row)
|
||||
|
||||
def delete_pg_config(self, ctxt, id_):
|
||||
self._delete(PGConfig, id_)
|
||||
|
||||
# PaymentMethod
|
||||
def create_payment_method(self, ctxt, values):
|
||||
row = PaymentMethod(**values)
|
||||
|
||||
self._save(row)
|
||||
return self._dict(row)
|
||||
|
||||
def list_payment_methods(self, ctxt, criterion=None, **kw):
|
||||
query = self.session.query(PaymentMethod)
|
||||
|
||||
# NOTE: Filter needs to be joined for merchant_id
|
||||
query = utils.filter_merchant_by_join(
|
||||
query, PGConfig, criterion)
|
||||
|
||||
rows = self._list(
|
||||
cls=PaymentMethod,
|
||||
query=query,
|
||||
criterion=criterion,
|
||||
**kw)
|
||||
|
||||
return [self._dict(row) for row in rows]
|
||||
|
||||
def get_payment_method(self, ctxt, id_, **kw):
|
||||
row = self._get_id_or_name(PaymentMethod, id_)
|
||||
return self._dict(row)
|
||||
|
||||
def update_payment_method(self, ctxt, id_, values):
|
||||
row = self._update(PaymentMethod, id_, values)
|
||||
return self._dict(row)
|
||||
|
||||
def delete_payment_method(self, ctxt, id_):
|
||||
self._delete(PaymentMethod, id_)
|
@ -31,7 +31,7 @@ class ProvidersRegister(DatabaseCommand):
|
||||
class ProvidersList(DatabaseCommand, ListCommand):
|
||||
def execute(self, parsed_args):
|
||||
context = get_admin_context()
|
||||
conn = self.get_connection('central')
|
||||
conn = self.get_connection('collector')
|
||||
|
||||
data = conn.list_pg_providers(context)
|
||||
|
||||
|
@ -47,7 +47,7 @@ def _register(ep, context, conn):
|
||||
|
||||
|
||||
def register_providers(context):
|
||||
conn = get_connection('central')
|
||||
conn = get_connection('collector')
|
||||
em = ExtensionManager(Provider.__plugin_ns__)
|
||||
em.map(_register, context, conn)
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from oslo.config import cfg
|
||||
from billingstack.storage import base
|
||||
|
||||
|
||||
@ -38,9 +37,3 @@ class Connection(base.Connection):
|
||||
|
||||
def delete_usage(self, ctxt, id_):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def get_connection():
|
||||
name = cfg.CONF['service:rater'].storage_driver
|
||||
plugin = StorageEngine.get_plugin(name, invoke_on_load=True)
|
||||
return plugin.get_connection()
|
||||
|
@ -42,3 +42,17 @@ def is_valid_id(id_):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def filter_merchant_by_join(query, cls, criterion, pop=True):
|
||||
if criterion and 'merchant_id' in criterion:
|
||||
if not hasattr(cls, 'merchant_id'):
|
||||
raise RuntimeError('No merchant_id attribute on %s' % cls)
|
||||
|
||||
query = query.join(cls).filter(
|
||||
cls.merchant_id == criterion['merchant_id'])
|
||||
|
||||
if pop:
|
||||
criterion.pop('merchant_id')
|
||||
|
||||
return query
|
||||
|
@ -162,6 +162,9 @@ class FunctionalTest(ServiceTestCase, APITestMixin):
|
||||
# NOTE: Needs to be started after the db schema is created
|
||||
self.start_storage('central')
|
||||
self.start_service('central')
|
||||
|
||||
self.start_storage('collector')
|
||||
self.start_service('collector')
|
||||
self.setSamples()
|
||||
|
||||
self.app = self.make_app()
|
||||
|
@ -30,11 +30,16 @@ class TestPaymentMethod(V2Test):
|
||||
|
||||
def setUp(self):
|
||||
super(TestPaymentMethod, self).setUp()
|
||||
self.start_storage('collector')
|
||||
self.start_service('collector')
|
||||
_, self.provider = self.pg_provider_register()
|
||||
|
||||
_, self.customer = self.create_customer(self.merchant['id'])
|
||||
_, self.pg_config = self.create_pg_config(
|
||||
self.merchant['id'], values={'provider_id': self.provider['id']})
|
||||
|
||||
values = {
|
||||
'provider_id': self.provider['id'],
|
||||
'merchant_id': self.merchant['id']}
|
||||
_, self.pg_config = self.create_pg_config(values=values)
|
||||
|
||||
def test_create_payment_method(self):
|
||||
fixture = self.get_fixture('payment_method')
|
||||
@ -48,9 +53,10 @@ class TestPaymentMethod(V2Test):
|
||||
|
||||
def test_list_payment_methods(self):
|
||||
values = {
|
||||
'provider_config_id': self.pg_config['id']
|
||||
'provider_config_id': self.pg_config['id'],
|
||||
'customer_id': self.customer['id']
|
||||
}
|
||||
self.create_payment_method(self.customer['id'], values=values)
|
||||
self.create_payment_method(values=values)
|
||||
|
||||
url = self.path % (self.merchant['id'], self.customer['id'])
|
||||
resp = self.get(url)
|
||||
@ -59,10 +65,10 @@ class TestPaymentMethod(V2Test):
|
||||
|
||||
def test_get_payment_method(self):
|
||||
values = {
|
||||
'provider_config_id': self.pg_config['id']
|
||||
'provider_config_id': self.pg_config['id'],
|
||||
'customer_id': self.customer['id']
|
||||
}
|
||||
_, method = self.create_payment_method(
|
||||
self.customer['id'], values=values)
|
||||
_, method = self.create_payment_method(values=values)
|
||||
|
||||
url = self.item_path(self.merchant['id'],
|
||||
self.customer['id'], method['id'])
|
||||
@ -73,10 +79,10 @@ class TestPaymentMethod(V2Test):
|
||||
|
||||
def test_update_payment_method(self):
|
||||
values = {
|
||||
'provider_config_id': self.pg_config['id']
|
||||
'provider_config_id': self.pg_config['id'],
|
||||
'customer_id': self.customer['id']
|
||||
}
|
||||
fixture, method = self.create_payment_method(
|
||||
self.customer['id'], values=values)
|
||||
fixture, method = self.create_payment_method(values=values)
|
||||
|
||||
url = self.item_path(self.merchant['id'],
|
||||
self.customer['id'], method['id'])
|
||||
@ -87,10 +93,10 @@ class TestPaymentMethod(V2Test):
|
||||
|
||||
def test_delete_payment_method(self):
|
||||
values = {
|
||||
'provider_config_id': self.pg_config['id']
|
||||
'provider_config_id': self.pg_config['id'],
|
||||
'customer_id': self.customer['id']
|
||||
}
|
||||
_, method = self.create_payment_method(
|
||||
self.customer['id'], values=values)
|
||||
_, method = self.create_payment_method(values=values)
|
||||
|
||||
url = self.item_path(self.merchant['id'],
|
||||
self.customer['id'], method['id'])
|
||||
|
@ -117,8 +117,12 @@ class SQLAlchemyHelper(FixtureHelper):
|
||||
def post_init(self):
|
||||
if self.fixture.database_connection == "sqlite://":
|
||||
conn = self.fixture.connection.engine.connect()
|
||||
self._as_string = "".join(
|
||||
l for l in conn.connection.iterdump())
|
||||
try:
|
||||
self._as_string = "".join(
|
||||
l for l in conn.connection.iterdump())
|
||||
except Exception:
|
||||
print "".join(l for l in conn.connection.iterdump())
|
||||
raise
|
||||
self.fixture.connection.engine.dispose()
|
||||
else:
|
||||
cleandb = paths.state_path_rel(self.sqlite_clean_db)
|
||||
@ -338,8 +342,8 @@ class TestCase(BaseTestCase):
|
||||
# NOTE: No services up by default
|
||||
self.services = Services()
|
||||
|
||||
def get_admin_context(self):
|
||||
return get_admin_context()
|
||||
def get_admin_context(self, **kw):
|
||||
return get_admin_context(**kw)
|
||||
|
||||
def get_context(self, **kw):
|
||||
return RequestContext(**kw)
|
||||
@ -431,7 +435,7 @@ class ServiceTestCase(TestCase):
|
||||
fixture['methods'] = [self.get_fixture('pg_method')]
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
|
||||
data = self.services.central.storage_conn.pg_provider_register(
|
||||
data = self.services.collector.storage_conn.pg_provider_register(
|
||||
ctxt, fixture, **kw)
|
||||
|
||||
return fixture, data
|
||||
@ -445,12 +449,12 @@ class ServiceTestCase(TestCase):
|
||||
return fixture, self.services.central.create_merchant(
|
||||
ctxt, fixture, **kw)
|
||||
|
||||
def create_pg_config(self, merchant_id, fixture=0, values={},
|
||||
def create_pg_config(self, fixture=0, values={},
|
||||
**kw):
|
||||
fixture = self.get_fixture('pg_config', fixture, values)
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
return fixture, self.services.central.create_pg_config(
|
||||
ctxt, merchant_id, fixture, **kw)
|
||||
return fixture, self.services.collector.create_pg_config(
|
||||
ctxt, fixture, **kw)
|
||||
|
||||
def create_customer(self, merchant_id, fixture=0, values={}, **kw):
|
||||
fixture = self.get_fixture('customer', fixture, values)
|
||||
@ -459,11 +463,11 @@ class ServiceTestCase(TestCase):
|
||||
return fixture, self.services.central.create_customer(
|
||||
ctxt, merchant_id, fixture, **kw)
|
||||
|
||||
def create_payment_method(self, customer_id, fixture=0, values={}, **kw):
|
||||
def create_payment_method(self, fixture=0, values={}, **kw):
|
||||
fixture = self.get_fixture('payment_method', fixture, values)
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
return fixture, self.services.central.create_payment_method(
|
||||
ctxt, customer_id, fixture, **kw)
|
||||
return fixture, self.services.collector.create_payment_method(
|
||||
ctxt, fixture, **kw)
|
||||
|
||||
def user_add(self, merchant_id, fixture=0, values={}, **kw):
|
||||
fixture = self.get_fixture('user', fixture, values)
|
||||
|
@ -0,0 +1,249 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
#
|
||||
# Author: Endre Karlson <endre.karlson@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from billingstack.openstack.common import log as logging
|
||||
from billingstack.central.storage.impl_sqlalchemy import models
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
UUID = 'caf771fc-6b05-4891-bee1-c2a48621f57b'
|
||||
|
||||
|
||||
class DriverMixin(object):
|
||||
def create_language(self, fixture=0, values={}, **kw):
|
||||
fixture = self.get_fixture('language', fixture, values)
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
return fixture, self.storage_conn.create_language(ctxt, fixture, **kw)
|
||||
|
||||
def create_currency(self, fixture=0, values={}, **kw):
|
||||
fixture = self.get_fixture('currency', fixture, values)
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
return fixture, self.storage_conn.create_currency(ctxt, fixture, **kw)
|
||||
|
||||
def create_merchant(self, fixture=0, values={}, **kw):
|
||||
fixture = self.get_fixture('merchant', fixture, values)
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
|
||||
self._account_defaults(fixture)
|
||||
|
||||
return fixture, self.storage_conn.create_merchant(ctxt, fixture, **kw)
|
||||
|
||||
def create_customer(self, merchant_id, fixture=0, values={}, **kw):
|
||||
fixture = self.get_fixture('customer', fixture, values)
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
self._account_defaults(fixture)
|
||||
return fixture, self.storage_conn.create_customer(
|
||||
ctxt, merchant_id, fixture, **kw)
|
||||
|
||||
def create_product(self, merchant_id, fixture=0, values={}, **kw):
|
||||
fixture = self.get_fixture('product', fixture, values)
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
return fixture, self.storage_conn.create_product(
|
||||
ctxt, merchant_id, fixture, **kw)
|
||||
|
||||
def create_plan(self, merchant_id, fixture=0, values={}, **kw):
|
||||
fixture = self.get_fixture('plan', fixture, values)
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
return fixture, self.storage_conn.create_plan(
|
||||
ctxt, merchant_id, fixture, **kw)
|
||||
|
||||
# Currencies
|
||||
def test_create_currency(self):
|
||||
self.assertDuplicate(self.create_currency)
|
||||
|
||||
# Languages
|
||||
def test_create_language(self):
|
||||
self.assertDuplicate(self.create_language)
|
||||
|
||||
def test_set_properties(self):
|
||||
fixture, data = self.create_product(self.merchant['id'])
|
||||
|
||||
metadata = {"random": True}
|
||||
self.storage_conn.set_properties(data['id'], metadata,
|
||||
cls=models.Product)
|
||||
|
||||
metadata.update({'foo': 1, 'bar': 2})
|
||||
self.storage_conn.set_properties(data['id'], metadata,
|
||||
cls=models.Product)
|
||||
|
||||
actual = self.storage_conn.get_product(self.admin_ctxt, data['id'])
|
||||
self.assertLen(6, actual['properties'])
|
||||
|
||||
# Merchant
|
||||
def test_create_merchant(self):
|
||||
fixture, data = self.create_merchant()
|
||||
self.assertData(fixture, data)
|
||||
|
||||
def test_get_merchant(self):
|
||||
_, expected = self.create_merchant()
|
||||
actual = self.storage_conn.get_merchant(
|
||||
self.admin_ctxt, expected['id'])
|
||||
self.assertData(expected, actual)
|
||||
|
||||
def test_get_merchant_missing(self):
|
||||
self.assertMissing(self.storage_conn.get_merchant,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
def test_update_merchant(self):
|
||||
fixture, data = self.create_merchant()
|
||||
|
||||
fixture['name'] = 'test'
|
||||
updated = self.storage_conn.update_merchant(
|
||||
self.admin_ctxt, data['id'], fixture)
|
||||
|
||||
self.assertData(fixture, updated)
|
||||
|
||||
def test_update_merchant_missing(self):
|
||||
self.assertMissing(self.storage_conn.update_merchant,
|
||||
self.admin_ctxt, UUID, {})
|
||||
|
||||
def test_delete_merchant(self):
|
||||
self.storage_conn.delete_merchant(self.admin_ctxt, self.merchant['id'])
|
||||
self.assertMissing(self.storage_conn.get_merchant,
|
||||
self.admin_ctxt, self.merchant['id'])
|
||||
|
||||
def test_delete_merchant_missing(self):
|
||||
self.assertMissing(self.storage_conn.delete_merchant,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
# Customer
|
||||
def test_create_customer(self):
|
||||
fixture, data = self.create_customer(self.merchant['id'])
|
||||
assert data['default_info'] == {}
|
||||
assert data['contact_info'] == []
|
||||
self.assertData(fixture, data)
|
||||
|
||||
def test_create_customer_with_contact_info(self):
|
||||
contact_fixture = self.get_fixture('contact_info')
|
||||
customer_fixture, data = self.create_customer(
|
||||
self.merchant['id'],
|
||||
values={'contact_info': contact_fixture})
|
||||
self.assertData(customer_fixture, data)
|
||||
self.assertData(contact_fixture, data['default_info'])
|
||||
self.assertData(contact_fixture, data['contact_info'][0])
|
||||
|
||||
def test_get_customer(self):
|
||||
_, expected = self.create_customer(self.merchant['id'])
|
||||
actual = self.storage_conn.get_customer(
|
||||
self.admin_ctxt, expected['id'])
|
||||
self.assertData(expected, actual)
|
||||
|
||||
def test_get_customer_missing(self):
|
||||
self.assertMissing(self.storage_conn.get_customer,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
def test_update_customer(self):
|
||||
fixture, data = self.create_customer(self.merchant['id'])
|
||||
|
||||
fixture['name'] = 'test'
|
||||
updated = self.storage_conn.update_customer(
|
||||
self.admin_ctxt, data['id'], fixture)
|
||||
|
||||
self.assertData(fixture, updated)
|
||||
|
||||
def test_update_customer_missing(self):
|
||||
self.assertMissing(self.storage_conn.update_customer,
|
||||
self.admin_ctxt, UUID, {})
|
||||
|
||||
def test_delete_customer(self):
|
||||
_, data = self.create_customer(self.merchant['id'])
|
||||
self.storage_conn.delete_customer(self.admin_ctxt, data['id'])
|
||||
self.assertMissing(self.storage_conn.get_customer,
|
||||
self.admin_ctxt, data['id'])
|
||||
|
||||
def test_delete_customer_missing(self):
|
||||
self.assertMissing(self.storage_conn.delete_customer,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
# Products
|
||||
def test_create_product(self):
|
||||
f, data = self.create_product(self.merchant['id'])
|
||||
self.assertData(f, data)
|
||||
|
||||
def test_get_product(self):
|
||||
f, expected = self.create_product(self.merchant['id'])
|
||||
actual = self.storage_conn.get_product(self.admin_ctxt, expected['id'])
|
||||
self.assertData(expected, actual)
|
||||
|
||||
def test_get_product_missing(self):
|
||||
self.assertMissing(self.storage_conn.get_product,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
def test_update_product(self):
|
||||
fixture, data = self.create_product(self.merchant['id'])
|
||||
|
||||
fixture['name'] = 'test'
|
||||
updated = self.storage_conn.update_product(
|
||||
self.admin_ctxt, data['id'], fixture)
|
||||
|
||||
self.assertData(fixture, updated)
|
||||
|
||||
def test_update_product_missing(self):
|
||||
self.assertMissing(self.storage_conn.update_product,
|
||||
self.admin_ctxt, UUID, {})
|
||||
|
||||
def test_delete_product(self):
|
||||
fixture, data = self.create_product(self.merchant['id'])
|
||||
self.storage_conn.delete_product(self.admin_ctxt, data['id'])
|
||||
self.assertMissing(self.storage_conn.get_product,
|
||||
self.admin_ctxt, data['id'])
|
||||
|
||||
def test_delete_product_missing(self):
|
||||
self.assertMissing(self.storage_conn.delete_product,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
# Plan
|
||||
def test_create_plan(self):
|
||||
fixture, data = self.create_plan(self.merchant['id'])
|
||||
self.assertData(fixture, data)
|
||||
|
||||
def test_get_plan(self):
|
||||
fixture, data = self.create_plan(self.merchant['id'])
|
||||
actual = self.storage_conn.get_plan(self.admin_ctxt, data['id'])
|
||||
|
||||
# FIXME(ekarlso): This should test the actual items also? But atm
|
||||
# there's am error that if the value is int when getting added it's
|
||||
# string when returned...
|
||||
self.assertEqual(data['name'], actual['name'])
|
||||
self.assertEqual(data['title'], actual['title'])
|
||||
self.assertEqual(data['description'], actual['description'])
|
||||
|
||||
def test_get_plan_missing(self):
|
||||
self.assertMissing(self.storage_conn.get_plan, self.admin_ctxt, UUID)
|
||||
|
||||
def test_update_plan(self):
|
||||
fixture, data = self.create_plan(self.merchant['id'])
|
||||
|
||||
fixture['name'] = 'test'
|
||||
updated = self.storage_conn.update_plan(
|
||||
self.admin_ctxt, data['id'], fixture)
|
||||
|
||||
self.assertData(fixture, updated)
|
||||
|
||||
def test_update_plan_missing(self):
|
||||
self.assertMissing(self.storage_conn.update_plan,
|
||||
self.admin_ctxt, UUID, {})
|
||||
|
||||
def test_delete_plan(self):
|
||||
fixture, data = self.create_plan(self.merchant['id'])
|
||||
self.storage_conn.delete_plan(self.admin_ctxt, data['id'])
|
||||
self.assertMissing(self.storage_conn.get_plan,
|
||||
self.admin_ctxt, data['id'])
|
||||
|
||||
def test_delete_plan_missing(self):
|
||||
self.assertMissing(self.storage_conn.delete_plan,
|
||||
self.admin_ctxt, UUID)
|
@ -1,493 +0,0 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
#
|
||||
# Author: Endre Karlson <endre.karlson@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from billingstack.openstack.common import log as logging
|
||||
from billingstack.central.storage.impl_sqlalchemy import models
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
UUID = 'caf771fc-6b05-4891-bee1-c2a48621f57b'
|
||||
|
||||
|
||||
class DriverMixin(object):
|
||||
def create_language(self, fixture=0, values={}, **kw):
|
||||
fixture = self.get_fixture('language', fixture, values)
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
return fixture, self.storage_conn.create_language(ctxt, fixture, **kw)
|
||||
|
||||
def create_currency(self, fixture=0, values={}, **kw):
|
||||
fixture = self.get_fixture('currency', fixture, values)
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
return fixture, self.storage_conn.create_currency(ctxt, fixture, **kw)
|
||||
|
||||
def pg_provider_register(self, fixture=0, values={}, methods=[], **kw):
|
||||
methods = [self.get_fixture('pg_method')] or methods
|
||||
if not 'methods' in values:
|
||||
values['methods'] = methods
|
||||
|
||||
fixture = self.get_fixture('pg_provider', fixture, values)
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
|
||||
data = self.storage_conn.pg_provider_register(
|
||||
ctxt, fixture.copy(), **kw)
|
||||
|
||||
return fixture, data
|
||||
|
||||
def create_merchant(self, fixture=0, values={}, **kw):
|
||||
fixture = self.get_fixture('merchant', fixture, values)
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
|
||||
self._account_defaults(fixture)
|
||||
|
||||
return fixture, self.storage_conn.create_merchant(ctxt, fixture, **kw)
|
||||
|
||||
def create_pg_config(self, merchant_id, fixture=0, values={},
|
||||
**kw):
|
||||
fixture = self.get_fixture('pg_config', fixture, values)
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
return fixture, self.storage_conn.create_pg_config(
|
||||
ctxt, merchant_id, fixture, **kw)
|
||||
|
||||
def create_customer(self, merchant_id, fixture=0, values={}, **kw):
|
||||
fixture = self.get_fixture('customer', fixture, values)
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
self._account_defaults(fixture)
|
||||
return fixture, self.storage_conn.create_customer(
|
||||
ctxt, merchant_id, fixture, **kw)
|
||||
|
||||
def create_payment_method(self, customer_id, fixture=0,
|
||||
values={}, **kw):
|
||||
fixture = self.get_fixture('payment_method', fixture, values)
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
return fixture, self.storage_conn.create_payment_method(
|
||||
ctxt, customer_id, fixture, **kw)
|
||||
|
||||
def create_product(self, merchant_id, fixture=0, values={}, **kw):
|
||||
fixture = self.get_fixture('product', fixture, values)
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
return fixture, self.storage_conn.create_product(
|
||||
ctxt, merchant_id, fixture, **kw)
|
||||
|
||||
def create_plan(self, merchant_id, fixture=0, values={}, **kw):
|
||||
fixture = self.get_fixture('plan', fixture, values)
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
return fixture, self.storage_conn.create_plan(
|
||||
ctxt, merchant_id, fixture, **kw)
|
||||
|
||||
# Currencies
|
||||
def test_create_currency(self):
|
||||
self.assertDuplicate(self.create_currency)
|
||||
|
||||
# Languages
|
||||
def test_create_language(self):
|
||||
self.assertDuplicate(self.create_language)
|
||||
|
||||
def test_set_properties(self):
|
||||
fixture, data = self.create_product(self.merchant['id'])
|
||||
|
||||
metadata = {"random": True}
|
||||
self.storage_conn.set_properties(data['id'], metadata,
|
||||
cls=models.Product)
|
||||
|
||||
metadata.update({'foo': 1, 'bar': 2})
|
||||
self.storage_conn.set_properties(data['id'], metadata,
|
||||
cls=models.Product)
|
||||
|
||||
actual = self.storage_conn.get_product(self.admin_ctxt, data['id'])
|
||||
self.assertLen(6, actual['properties'])
|
||||
|
||||
# Payment Gateways
|
||||
def test_pg_provider_register(self):
|
||||
fixture, actual = self.pg_provider_register()
|
||||
self.assertEqual(fixture['name'], actual['name'])
|
||||
self.assertEqual(fixture['title'], actual['title'])
|
||||
self.assertEqual(fixture['description'], actual['description'])
|
||||
self.assertData(fixture['methods'][0], actual['methods'][0])
|
||||
|
||||
def test_pg_provider_register_different_methods(self):
|
||||
# Add a Global method
|
||||
method1 = {'type': 'creditcard', 'name': 'mastercard'}
|
||||
method2 = {'type': 'creditcard', 'name': 'amex'}
|
||||
method3 = {'type': 'creditcard', 'name': 'visa'}
|
||||
|
||||
provider = {'name': 'noop', 'methods': [method1, method2, method3]}
|
||||
|
||||
provider = self.storage_conn.pg_provider_register(
|
||||
self.admin_ctxt, provider)
|
||||
|
||||
# TODO(ekarls): Make this more extensive?
|
||||
self.assertLen(3, provider['methods'])
|
||||
|
||||
def test_get_pg_provider(self):
|
||||
_, expected = self.pg_provider_register()
|
||||
actual = self.storage_conn.get_pg_provider(self.admin_ctxt,
|
||||
expected['id'])
|
||||
self.assertData(expected, actual)
|
||||
|
||||
def test_get_pg_provider_missing(self):
|
||||
self.assertMissing(self.storage_conn.get_pg_provider,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
def test_pg_provider_deregister(self):
|
||||
_, data = self.pg_provider_register()
|
||||
self.storage_conn.pg_provider_deregister(self.admin_ctxt, data['id'])
|
||||
self.assertMissing(self.storage_conn.pg_provider_deregister,
|
||||
self.admin_ctxt, data['id'])
|
||||
|
||||
def test_pg_provider_deregister_missing(self):
|
||||
self.assertMissing(self.storage_conn.pg_provider_deregister,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
# Payment Gateway Configuration
|
||||
def test_create_pg_config(self):
|
||||
_, provider = self.pg_provider_register()
|
||||
|
||||
values = {'provider_id': provider['id']}
|
||||
fixture, data = self.create_pg_config(
|
||||
self.merchant['id'], values=values)
|
||||
|
||||
self.assertData(fixture, data)
|
||||
|
||||
def test_get_pg_config(self):
|
||||
_, provider = self.pg_provider_register()
|
||||
|
||||
values = {'provider_id': provider['id']}
|
||||
|
||||
fixture, data = self.create_pg_config(
|
||||
self.merchant['id'], values=values)
|
||||
|
||||
def test_get_pg_config_missing(self):
|
||||
self.assertMissing(self.storage_conn.get_pg_config,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
def test_update_pg_config(self):
|
||||
_, provider = self.pg_provider_register()
|
||||
|
||||
values = {'provider_id': provider['id']}
|
||||
|
||||
fixture, data = self.create_pg_config(
|
||||
self.merchant['id'], values=values)
|
||||
|
||||
fixture['properties'] = {"api": 1}
|
||||
updated = self.storage_conn.update_pg_config(
|
||||
self.admin_ctxt, data['id'], fixture)
|
||||
|
||||
self.assertData(fixture, updated)
|
||||
|
||||
def test_update_pg_config_missing(self):
|
||||
_, provider = self.pg_provider_register()
|
||||
|
||||
values = {'provider_id': provider['id']}
|
||||
|
||||
fixture, data = self.create_pg_config(
|
||||
self.merchant['id'], values=values)
|
||||
|
||||
self.assertMissing(self.storage_conn.update_pg_config,
|
||||
self.admin_ctxt, UUID, {})
|
||||
|
||||
def test_delete_pg_config(self):
|
||||
_, provider = self.pg_provider_register()
|
||||
|
||||
values = {'provider_id': provider['id']}
|
||||
|
||||
fixture, data = self.create_pg_config(
|
||||
self.merchant['id'], values=values)
|
||||
|
||||
self.storage_conn.delete_pg_config(self.admin_ctxt, data['id'])
|
||||
self.assertMissing(self.storage_conn.get_pg_config,
|
||||
self.admin_ctxt, data['id'])
|
||||
|
||||
def test_delete_pg_config_missing(self):
|
||||
self.assertMissing(self.storage_conn.delete_pg_config,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
# PaymentMethod
|
||||
def test_create_payment_method(self):
|
||||
# Setup pgp / pgm / pgc
|
||||
_, provider = self.pg_provider_register()
|
||||
_, config = self.create_pg_config(
|
||||
self.merchant['id'], values={'provider_id': provider['id']})
|
||||
_, customer = self.create_customer(self.merchant['id'])
|
||||
|
||||
# Setup PaymentMethod
|
||||
values = {
|
||||
'provider_config_id': config['id']}
|
||||
|
||||
fixture, data = self.create_payment_method(
|
||||
customer['id'], values=values)
|
||||
self.assertData(fixture, data)
|
||||
|
||||
def test_get_payment_method(self):
|
||||
# Setup pgp / pgm / pgc
|
||||
_, provider = self.pg_provider_register()
|
||||
_, config = self.create_pg_config(
|
||||
self.merchant['id'], values={'provider_id': provider['id']})
|
||||
_, customer = self.create_customer(self.merchant['id'])
|
||||
|
||||
# Setup PaymentMethod
|
||||
values = {
|
||||
'provider_config_id': config['id']}
|
||||
|
||||
_, expected = self.create_payment_method(
|
||||
customer['id'], values=values)
|
||||
actual = self.storage_conn.get_payment_method(self.admin_ctxt,
|
||||
expected['id'])
|
||||
self.assertData(expected, actual)
|
||||
|
||||
# TODO(ekarlso): Make this test more extensive?
|
||||
def test_list_payment_methods(self):
|
||||
# Setup pgp / pgm / pgc
|
||||
_, provider = self.pg_provider_register()
|
||||
_, config = self.create_pg_config(
|
||||
self.merchant['id'], values={'provider_id': provider['id']})
|
||||
|
||||
values = {
|
||||
'provider_config_id': config['id']}
|
||||
|
||||
# Add two Customers with some methods
|
||||
_, customer1 = self.create_customer(self.merchant['id'])
|
||||
self.create_payment_method(
|
||||
customer1['id'], values=values)
|
||||
rows = self.storage_conn.list_payment_methods(
|
||||
self.admin_ctxt,
|
||||
criterion={'customer_id': customer1['id']})
|
||||
self.assertLen(1, rows)
|
||||
|
||||
_, customer2 = self.create_customer(self.merchant['id'])
|
||||
self.create_payment_method(
|
||||
customer2['id'], values=values)
|
||||
self.create_payment_method(
|
||||
customer2['id'], values=values)
|
||||
rows = self.storage_conn.list_payment_methods(
|
||||
self.admin_ctxt,
|
||||
criterion={'customer_id': customer2['id']})
|
||||
self.assertLen(2, rows)
|
||||
|
||||
def test_get_payment_method_missing(self):
|
||||
self.assertMissing(self.storage_conn.get_payment_method,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
def test_update_payment_method(self):
|
||||
# Setup pgp / pgm / pgc
|
||||
_, provider = self.pg_provider_register()
|
||||
_, config = self.create_pg_config(
|
||||
self.merchant['id'], values={'provider_id': provider['id']})
|
||||
_, customer = self.create_customer(self.merchant['id'])
|
||||
|
||||
# Setup PaymentMethod
|
||||
values = {
|
||||
'provider_config_id': config['id']}
|
||||
|
||||
fixture, data = self.create_payment_method(
|
||||
customer['id'], values=values)
|
||||
|
||||
fixture['identifier'] = 1
|
||||
updated = self.storage_conn.update_payment_method(self.admin_ctxt,
|
||||
data['id'], fixture)
|
||||
|
||||
self.assertData(fixture, updated)
|
||||
|
||||
def test_update_payment_method_missing(self):
|
||||
self.assertMissing(self.storage_conn.update_payment_method,
|
||||
self.admin_ctxt, UUID, {})
|
||||
|
||||
def test_delete_payment_method(self):
|
||||
# Setup pgp / pgm / pgc
|
||||
_, provider = self.pg_provider_register()
|
||||
_, config = self.create_pg_config(
|
||||
self.merchant['id'], values={'provider_id': provider['id']})
|
||||
_, customer = self.create_customer(self.merchant['id'])
|
||||
|
||||
# Setup PaymentMethod
|
||||
values = {
|
||||
'provider_config_id': config['id']}
|
||||
|
||||
fixture, data = self.create_payment_method(
|
||||
customer['id'], values=values)
|
||||
|
||||
self.storage_conn.delete_payment_method(self.admin_ctxt, data['id'])
|
||||
self.assertMissing(self.storage_conn.get_payment_method,
|
||||
self.admin_ctxt, data['id'])
|
||||
|
||||
def test_delete_payment_method_missing(self):
|
||||
self.assertMissing(self.storage_conn.delete_payment_method,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
# Merchant
|
||||
def test_create_merchant(self):
|
||||
fixture, data = self.create_merchant()
|
||||
self.assertData(fixture, data)
|
||||
|
||||
def test_get_merchant(self):
|
||||
_, expected = self.create_merchant()
|
||||
actual = self.storage_conn.get_merchant(
|
||||
self.admin_ctxt, expected['id'])
|
||||
self.assertData(expected, actual)
|
||||
|
||||
def test_get_merchant_missing(self):
|
||||
self.assertMissing(self.storage_conn.get_merchant,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
def test_update_merchant(self):
|
||||
fixture, data = self.create_merchant()
|
||||
|
||||
fixture['name'] = 'test'
|
||||
updated = self.storage_conn.update_merchant(
|
||||
self.admin_ctxt, data['id'], fixture)
|
||||
|
||||
self.assertData(fixture, updated)
|
||||
|
||||
def test_update_merchant_missing(self):
|
||||
self.assertMissing(self.storage_conn.update_merchant,
|
||||
self.admin_ctxt, UUID, {})
|
||||
|
||||
def test_delete_merchant(self):
|
||||
self.storage_conn.delete_merchant(self.admin_ctxt, self.merchant['id'])
|
||||
self.assertMissing(self.storage_conn.get_merchant,
|
||||
self.admin_ctxt, self.merchant['id'])
|
||||
|
||||
def test_delete_merchant_missing(self):
|
||||
self.assertMissing(self.storage_conn.delete_merchant,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
# Customer
|
||||
def test_create_customer(self):
|
||||
fixture, data = self.create_customer(self.merchant['id'])
|
||||
assert data['default_info'] == {}
|
||||
assert data['contact_info'] == []
|
||||
self.assertData(fixture, data)
|
||||
|
||||
def test_create_customer_with_contact_info(self):
|
||||
contact_fixture = self.get_fixture('contact_info')
|
||||
customer_fixture, data = self.create_customer(
|
||||
self.merchant['id'],
|
||||
values={'contact_info': contact_fixture})
|
||||
self.assertData(customer_fixture, data)
|
||||
self.assertData(contact_fixture, data['default_info'])
|
||||
self.assertData(contact_fixture, data['contact_info'][0])
|
||||
|
||||
def test_get_customer(self):
|
||||
_, expected = self.create_customer(self.merchant['id'])
|
||||
actual = self.storage_conn.get_customer(
|
||||
self.admin_ctxt, expected['id'])
|
||||
self.assertData(expected, actual)
|
||||
|
||||
def test_get_customer_missing(self):
|
||||
self.assertMissing(self.storage_conn.get_customer,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
def test_update_customer(self):
|
||||
fixture, data = self.create_customer(self.merchant['id'])
|
||||
|
||||
fixture['name'] = 'test'
|
||||
updated = self.storage_conn.update_customer(
|
||||
self.admin_ctxt, data['id'], fixture)
|
||||
|
||||
self.assertData(fixture, updated)
|
||||
|
||||
def test_update_customer_missing(self):
|
||||
self.assertMissing(self.storage_conn.update_customer,
|
||||
self.admin_ctxt, UUID, {})
|
||||
|
||||
def test_delete_customer(self):
|
||||
_, data = self.create_customer(self.merchant['id'])
|
||||
self.storage_conn.delete_customer(self.admin_ctxt, data['id'])
|
||||
self.assertMissing(self.storage_conn.get_customer,
|
||||
self.admin_ctxt, data['id'])
|
||||
|
||||
def test_delete_customer_missing(self):
|
||||
self.assertMissing(self.storage_conn.delete_customer,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
# Products
|
||||
def test_create_product(self):
|
||||
f, data = self.create_product(self.merchant['id'])
|
||||
self.assertData(f, data)
|
||||
|
||||
def test_get_product(self):
|
||||
f, expected = self.create_product(self.merchant['id'])
|
||||
actual = self.storage_conn.get_product(self.admin_ctxt, expected['id'])
|
||||
self.assertData(expected, actual)
|
||||
|
||||
def test_get_product_missing(self):
|
||||
self.assertMissing(self.storage_conn.get_product,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
def test_update_product(self):
|
||||
fixture, data = self.create_product(self.merchant['id'])
|
||||
|
||||
fixture['name'] = 'test'
|
||||
updated = self.storage_conn.update_product(
|
||||
self.admin_ctxt, data['id'], fixture)
|
||||
|
||||
self.assertData(fixture, updated)
|
||||
|
||||
def test_update_product_missing(self):
|
||||
self.assertMissing(self.storage_conn.update_product,
|
||||
self.admin_ctxt, UUID, {})
|
||||
|
||||
def test_delete_product(self):
|
||||
fixture, data = self.create_product(self.merchant['id'])
|
||||
self.storage_conn.delete_product(self.admin_ctxt, data['id'])
|
||||
self.assertMissing(self.storage_conn.get_product,
|
||||
self.admin_ctxt, data['id'])
|
||||
|
||||
def test_delete_product_missing(self):
|
||||
self.assertMissing(self.storage_conn.delete_product,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
# Plan
|
||||
def test_create_plan(self):
|
||||
fixture, data = self.create_plan(self.merchant['id'])
|
||||
self.assertData(fixture, data)
|
||||
|
||||
def test_get_plan(self):
|
||||
fixture, data = self.create_plan(self.merchant['id'])
|
||||
actual = self.storage_conn.get_plan(self.admin_ctxt, data['id'])
|
||||
|
||||
# FIXME(ekarlso): This should test the actual items also? But atm
|
||||
# there's am error that if the value is int when getting added it's
|
||||
# string when returned...
|
||||
self.assertEqual(data['name'], actual['name'])
|
||||
self.assertEqual(data['title'], actual['title'])
|
||||
self.assertEqual(data['description'], actual['description'])
|
||||
|
||||
def test_get_plan_missing(self):
|
||||
self.assertMissing(self.storage_conn.get_plan, self.admin_ctxt, UUID)
|
||||
|
||||
def test_update_plan(self):
|
||||
fixture, data = self.create_plan(self.merchant['id'])
|
||||
|
||||
fixture['name'] = 'test'
|
||||
updated = self.storage_conn.update_plan(
|
||||
self.admin_ctxt, data['id'], fixture)
|
||||
|
||||
self.assertData(fixture, updated)
|
||||
|
||||
def test_update_plan_missing(self):
|
||||
self.assertMissing(self.storage_conn.update_plan,
|
||||
self.admin_ctxt, UUID, {})
|
||||
|
||||
def test_delete_plan(self):
|
||||
fixture, data = self.create_plan(self.merchant['id'])
|
||||
self.storage_conn.delete_plan(self.admin_ctxt, data['id'])
|
||||
self.assertMissing(self.storage_conn.get_plan,
|
||||
self.admin_ctxt, data['id'])
|
||||
|
||||
def test_delete_plan_missing(self):
|
||||
self.assertMissing(self.storage_conn.delete_plan,
|
||||
self.admin_ctxt, UUID)
|
@ -17,7 +17,7 @@
|
||||
# Copied: billingstack
|
||||
from billingstack.openstack.common import log as logging
|
||||
from billingstack.tests.base import TestCase
|
||||
from billingstack.tests.central.storage.base import DriverMixin
|
||||
from billingstack.tests.central.storage import DriverMixin
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
@ -0,0 +1,293 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
#
|
||||
# Author: Endre Karlson <endre.karlson@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from billingstack.openstack.common import log as logging
|
||||
from billingstack.openstack.common.uuidutils import generate_uuid
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
UUID = generate_uuid()
|
||||
MERCHANT_UUID = generate_uuid()
|
||||
CUSTOMER_UUID = generate_uuid()
|
||||
|
||||
|
||||
class DriverMixin(object):
|
||||
def pg_provider_register(self, fixture=0, values={}, methods=[], **kw):
|
||||
methods = [self.get_fixture('pg_method')] or methods
|
||||
if not 'methods' in values:
|
||||
values['methods'] = methods
|
||||
|
||||
fixture = self.get_fixture('pg_provider', fixture, values)
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
|
||||
data = self.storage_conn.pg_provider_register(
|
||||
ctxt, fixture.copy(), **kw)
|
||||
|
||||
return fixture, data
|
||||
|
||||
def create_pg_config(self, fixture=0, values={},
|
||||
**kw):
|
||||
fixture = self.get_fixture('pg_config', fixture, values)
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
return fixture, self.storage_conn.create_pg_config(
|
||||
ctxt, fixture, **kw)
|
||||
|
||||
def create_payment_method(self, fixture=0,
|
||||
values={}, **kw):
|
||||
fixture = self.get_fixture('payment_method', fixture, values)
|
||||
ctxt = kw.pop('context', self.admin_ctxt)
|
||||
return fixture, self.storage_conn.create_payment_method(
|
||||
ctxt, fixture, **kw)
|
||||
|
||||
# Payment Gateways
|
||||
def test_pg_provider_register(self):
|
||||
fixture, actual = self.pg_provider_register()
|
||||
self.assertEqual(fixture['name'], actual['name'])
|
||||
self.assertEqual(fixture['title'], actual['title'])
|
||||
self.assertEqual(fixture['description'], actual['description'])
|
||||
self.assertData(fixture['methods'][0], actual['methods'][0])
|
||||
|
||||
def test_pg_provider_register_different_methods(self):
|
||||
# Add a Global method
|
||||
method1 = {'type': 'creditcard', 'name': 'mastercard'}
|
||||
method2 = {'type': 'creditcard', 'name': 'amex'}
|
||||
method3 = {'type': 'creditcard', 'name': 'visa'}
|
||||
|
||||
provider = {'name': 'noop', 'methods': [method1, method2, method3]}
|
||||
|
||||
provider = self.storage_conn.pg_provider_register(
|
||||
self.admin_ctxt, provider)
|
||||
|
||||
# TODO(ekarls): Make this more extensive?
|
||||
self.assertLen(3, provider['methods'])
|
||||
|
||||
def test_get_pg_provider(self):
|
||||
_, expected = self.pg_provider_register()
|
||||
actual = self.storage_conn.get_pg_provider(self.admin_ctxt,
|
||||
expected['id'])
|
||||
self.assertData(expected, actual)
|
||||
|
||||
def test_get_pg_provider_missing(self):
|
||||
self.assertMissing(self.storage_conn.get_pg_provider,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
def test_pg_provider_deregister(self):
|
||||
_, data = self.pg_provider_register()
|
||||
self.storage_conn.pg_provider_deregister(self.admin_ctxt, data['id'])
|
||||
self.assertMissing(self.storage_conn.pg_provider_deregister,
|
||||
self.admin_ctxt, data['id'])
|
||||
|
||||
def test_pg_provider_deregister_missing(self):
|
||||
self.assertMissing(self.storage_conn.pg_provider_deregister,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
# Payment Gateway Configuration
|
||||
def test_create_pg_config(self):
|
||||
_, provider = self.pg_provider_register()
|
||||
|
||||
values = {
|
||||
'merchant_id': MERCHANT_UUID,
|
||||
'provider_id': provider['id']}
|
||||
fixture, data = self.create_pg_config(values=values)
|
||||
|
||||
self.assertData(fixture, data)
|
||||
|
||||
def test_get_pg_config(self):
|
||||
_, provider = self.pg_provider_register()
|
||||
|
||||
values = {
|
||||
'merchant_id': MERCHANT_UUID,
|
||||
'provider_id': provider['id']}
|
||||
|
||||
fixture, data = self.create_pg_config(values=values)
|
||||
|
||||
def test_get_pg_config_missing(self):
|
||||
self.assertMissing(self.storage_conn.get_pg_config,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
def test_update_pg_config(self):
|
||||
_, provider = self.pg_provider_register()
|
||||
|
||||
values = {
|
||||
'merchant_id': MERCHANT_UUID,
|
||||
'provider_id': provider['id']}
|
||||
fixture, data = self.create_pg_config(values=values)
|
||||
|
||||
fixture['properties'] = {"api": 1}
|
||||
updated = self.storage_conn.update_pg_config(
|
||||
self.admin_ctxt, data['id'], fixture)
|
||||
|
||||
self.assertData(fixture, updated)
|
||||
|
||||
def test_update_pg_config_missing(self):
|
||||
_, provider = self.pg_provider_register()
|
||||
|
||||
values = {
|
||||
'merchant_id': MERCHANT_UUID,
|
||||
'provider_id': provider['id']}
|
||||
|
||||
fixture, data = self.create_pg_config(values=values)
|
||||
|
||||
self.assertMissing(self.storage_conn.update_pg_config,
|
||||
self.admin_ctxt, UUID, {})
|
||||
|
||||
def test_delete_pg_config(self):
|
||||
_, provider = self.pg_provider_register()
|
||||
|
||||
values = {
|
||||
'merchant_id': MERCHANT_UUID,
|
||||
'provider_id': provider['id']}
|
||||
|
||||
fixture, data = self.create_pg_config(values=values)
|
||||
|
||||
self.storage_conn.delete_pg_config(self.admin_ctxt, data['id'])
|
||||
self.assertMissing(self.storage_conn.get_pg_config,
|
||||
self.admin_ctxt, data['id'])
|
||||
|
||||
def test_delete_pg_config_missing(self):
|
||||
self.assertMissing(self.storage_conn.delete_pg_config,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
# PaymentMethod
|
||||
def test_create_payment_method(self):
|
||||
# Setup pgp / pgm / pgc
|
||||
_, provider = self.pg_provider_register()
|
||||
|
||||
values = {
|
||||
'merchant_id': MERCHANT_UUID,
|
||||
'provider_id': provider['id']
|
||||
}
|
||||
_, config = self.create_pg_config(values=values)
|
||||
|
||||
# Setup PaymentMethod
|
||||
values = {
|
||||
'customer_id': CUSTOMER_UUID,
|
||||
'provider_config_id': config['id']}
|
||||
|
||||
fixture, data = self.create_payment_method(values=values)
|
||||
self.assertData(fixture, data)
|
||||
|
||||
def test_get_payment_method(self):
|
||||
# Setup pgp / pgm / pgc
|
||||
_, provider = self.pg_provider_register()
|
||||
|
||||
values = {
|
||||
'merchant_id': MERCHANT_UUID,
|
||||
'provider_id': provider['id']
|
||||
}
|
||||
_, config = self.create_pg_config(values=values)
|
||||
|
||||
# Setup PaymentMethod
|
||||
values = {
|
||||
'customer_id': CUSTOMER_UUID,
|
||||
'provider_config_id': config['id']}
|
||||
|
||||
_, expected = self.create_payment_method(values=values)
|
||||
actual = self.storage_conn.get_payment_method(self.admin_ctxt,
|
||||
expected['id'])
|
||||
self.assertData(expected, actual)
|
||||
|
||||
# TODO(ekarlso): Make this test more extensive?
|
||||
def test_list_payment_methods(self):
|
||||
# Setup pgp / pgm / pgc
|
||||
_, provider = self.pg_provider_register()
|
||||
|
||||
values = {
|
||||
'merchant_id': MERCHANT_UUID,
|
||||
'provider_id': provider['id']
|
||||
}
|
||||
_, config = self.create_pg_config(values=values)
|
||||
|
||||
# Add two Customers with some methods
|
||||
customer1_id = generate_uuid()
|
||||
values = {
|
||||
'customer_id': customer1_id,
|
||||
'provider_config_id': config['id']}
|
||||
self.create_payment_method(values=values)
|
||||
rows = self.storage_conn.list_payment_methods(
|
||||
self.admin_ctxt,
|
||||
criterion={'customer_id': customer1_id})
|
||||
self.assertLen(1, rows)
|
||||
|
||||
customer2_id = generate_uuid()
|
||||
values = {
|
||||
'customer_id': customer2_id,
|
||||
'provider_config_id': config['id']}
|
||||
self.create_payment_method(values=values)
|
||||
self.create_payment_method(values=values)
|
||||
rows = self.storage_conn.list_payment_methods(
|
||||
self.admin_ctxt,
|
||||
criterion={'customer_id': customer2_id})
|
||||
self.assertLen(2, rows)
|
||||
|
||||
def test_get_payment_method_missing(self):
|
||||
self.assertMissing(self.storage_conn.get_payment_method,
|
||||
self.admin_ctxt, UUID)
|
||||
|
||||
def test_update_payment_method(self):
|
||||
# Setup pgp / pgm / pgc
|
||||
_, provider = self.pg_provider_register()
|
||||
|
||||
values = {
|
||||
'merchant_id': MERCHANT_UUID,
|
||||
'provider_id': provider['id']
|
||||
}
|
||||
_, config = self.create_pg_config(values=values)
|
||||
|
||||
# Setup PaymentMethod
|
||||
values = {
|
||||
'customer_id': CUSTOMER_UUID,
|
||||
'provider_config_id': config['id']}
|
||||
|
||||
fixture, data = self.create_payment_method(values=values)
|
||||
|
||||
fixture['identifier'] = 1
|
||||
updated = self.storage_conn.update_payment_method(
|
||||
self.admin_ctxt,
|
||||
data['id'],
|
||||
fixture)
|
||||
|
||||
self.assertData(fixture, updated)
|
||||
|
||||
def test_update_payment_method_missing(self):
|
||||
self.assertMissing(self.storage_conn.update_payment_method,
|
||||
self.admin_ctxt, UUID, {})
|
||||
|
||||
def test_delete_payment_method(self):
|
||||
# Setup pgp / pgm / pgc
|
||||
_, provider = self.pg_provider_register()
|
||||
|
||||
values = {
|
||||
'merchant_id': MERCHANT_UUID,
|
||||
'provider_id': provider['id']
|
||||
}
|
||||
_, config = self.create_pg_config(values=values)
|
||||
|
||||
# Setup PaymentMethod
|
||||
values = {
|
||||
'customer_id': CUSTOMER_UUID,
|
||||
'provider_config_id': config['id']}
|
||||
|
||||
fixture, data = self.create_payment_method(values=values)
|
||||
|
||||
self.storage_conn.delete_payment_method(self.admin_ctxt, data['id'])
|
||||
self.assertMissing(self.storage_conn.get_payment_method,
|
||||
self.admin_ctxt, data['id'])
|
||||
|
||||
def test_delete_payment_method_missing(self):
|
||||
self.assertMissing(self.storage_conn.delete_payment_method,
|
||||
self.admin_ctxt, UUID)
|
29
billingstack/tests/collector/storage/test_sqlalchemy.py
Normal file
29
billingstack/tests/collector/storage/test_sqlalchemy.py
Normal file
@ -0,0 +1,29 @@
|
||||
# Copyright 2012 Managed I.T.
|
||||
#
|
||||
# Author: Kiall Mac Innes <kiall@managedit.ie>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# Copied: billingstack
|
||||
from billingstack.openstack.common import log as logging
|
||||
from billingstack.tests.base import TestCase
|
||||
from billingstack.tests.collector.storage import DriverMixin
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SqlalchemyStorageTest(DriverMixin, TestCase):
|
||||
def setUp(self):
|
||||
super(SqlalchemyStorageTest, self).setUp()
|
||||
fixture = self.start_storage('collector')
|
||||
self.storage_conn = fixture.connection
|
@ -39,6 +39,10 @@ console_scripts =
|
||||
billingstack.central.storage =
|
||||
sqlalchemy = billingstack.central.storage.impl_sqlalchemy:SQLAlchemyEngine
|
||||
|
||||
billingstack.collector.storage =
|
||||
sqlalchemy = billingstack.collector.storage.impl_sqlalchemy:SQLAlchemyEngine
|
||||
|
||||
|
||||
billingstack.biller.storage =
|
||||
sqlalchemy = billingstack.biller.storage.impl_sqlalchemy:SQLAlchemyEngine
|
||||
|
||||
|
@ -9,7 +9,7 @@ from billingstack import service
|
||||
from billingstack.storage.utils import get_connection
|
||||
|
||||
# NOTE: make this based on entrypoints ?
|
||||
SERVICES = ['biller', 'central', 'rater']
|
||||
SERVICES = ['biller', 'central', 'collector', 'rater']
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user