Ignore:
Timestamp:
6 Mar 2015, 23:12:36 (10 years ago)
Author:
uli
Message:

Merge changes from uli-fake-gw-provider back into trunk.

Location:
main/waeup.ikoba/trunk/src/waeup/ikoba/payments
Files:
4 edited
2 copied

Legend:

Unmodified
Added
Removed
  • main/waeup.ikoba/trunk/src/waeup/ikoba/payments/catalog.py

    r12311 r12671  
    3232    payment_id = grok.index.Field(attribute='payment_id')
    3333    payer_id = grok.index.Field(attribute='payer_id')
    34     payed_item_id = grok.index.Field(attribute='payed_item_id')
    3534    state = grok.index.Field(attribute='state')
    3635    amount = grok.index.Field(attribute='amount')
  • main/waeup.ikoba/trunk/src/waeup/ikoba/payments/interfaces.py

    r12319 r12671  
    2020from zope import schema
    2121from zope.component import getUtilitiesFor
    22 from zope.interface import Interface
     22from zope.container.interfaces import IContainer
     23from zope.container.constraints import contains
     24from zope.interface import Interface, Attribute
    2325from waeup.ikoba.interfaces import (
    2426    IIkobaObject, SimpleIkobaVocabulary, ContextualDictSourceFactoryBase)
     
    8688        )
    8789
    88     def create_payment(payer, payment_item,  payee):
     90    def create_payment(payer, payment_item_list,  payee):
    8991        """Create a payment.
    9092
     
    101103
    102104
     105class IPaymentGatewayServicesLister(Interface):
     106    """A utility that lists all valid payment gateways.
     107
     108    This is a subset of the available payment methods, as some might
     109    be disabled in some site.
     110
     111    Register your own lister in customized sites!
     112    """
     113
     114
    103115class PaymentCategorySource(ContextualDictSourceFactoryBase):
    104116    """A payment category source delivers all categories of payments.
     
    115127
    116128
    117 class IPayment(IIkobaObject):
     129class ICreditCard(Interface):
     130    """A credit card.
     131
     132    A credit card is connected to a Payer.
     133    """
     134    credit_card_id = schema.TextLine(
     135        title=u'Internal Credit Card ID',
     136        required=True,
     137        )
     138
     139
     140class IPaymentItem(Interface):
     141    """Something to sell.
     142    """
     143    item_id = schema.TextLine(
     144        title=u'Payment Item ID',
     145        required=True,
     146        )
     147
     148    title = schema.TextLine(
     149        title=u'Title',
     150        description=u'A short title of the good sold.',
     151        required=True,
     152        default=u'Unnamed'
     153        )
     154
     155    amount = schema.Decimal(
     156        title=u'Amount',
     157        description=u'Total amount, includung any taxes, fees, etc.',
     158        required=True,
     159        default=decimal.Decimal('0.00'),
     160        )
     161
     162
     163class IPayment(IContainer):
    118164    """A base representation of payments.
    119165
     
    139185    we mark the payment 'failed'.
    140186    """
     187    contains(IPaymentItem)
     188
    141189    payment_id = schema.TextLine(
    142190        title=u'Payment Identifier',
     
    151199        )
    152200
    153     payed_item_id = schema.TextLine(
    154         title=u'Payed Item ID',
    155         default=None,
    156         required=True,
    157         )
     201    payee_id = schema.TextLine(
     202        title=u'Payee',
     203        default=None,
     204        required=False,
     205    )
    158206
    159207    gateway_service = schema.Choice(
     
    184232        )
    185233
    186     amount = schema.Decimal(
    187         title=_(u'Amount'),
    188         description=_(
    189             'The overall sum payed, including all taxes fees, etc.'),
    190         default=decimal.Decimal("0.00"),
    191         required=True,
    192         readonly=False,
    193         )
     234    currency = schema.Choice(
     235        title=u'Currency',
     236        source=ISO_4217_CURRENCIES_VOCAB,
     237        required=True,
     238        default='USD',
     239        )
     240
     241    amount = Attribute("Sum of amounts of items contained")
    194242
    195243    def approve():
     
    208256        """
    209257
    210 
    211 class IOnlinePayment(IPayment):
    212     """A payment via payment gateways.
    213 
    214     """
    215 
    216     ac = schema.TextLine(
    217         title=_(u'Activation Code'),
    218         default=None,
    219         required=False,
    220         readonly=False,
    221         )
    222 
    223     r_amount_approved = schema.Float(
    224         title=_(u'Response Amount Approved'),
    225         default=0.0,
    226         required=False,
    227         readonly=False,
    228         )
    229 
    230     r_code = schema.TextLine(
    231         title=_(u'Response Code'),
    232         default=None,
    233         required=False,
    234         readonly=False,
    235         )
    236 
    237     r_desc = schema.TextLine(
    238         title=_(u'Response Description'),
    239         default=None,
    240         required=False,
    241         readonly=False,
    242         )
    243 
    244     def approve():
    245         "Approve an online payment and set to paid."
    246 
    247 
    248 class ICreditCard(Interface):
    249     """A credit card.
    250 
    251     A credit card is connected to a Payer.
    252     """
    253     credit_card_id = schema.TextLine(
    254         title=u'Internal Credit Card ID',
    255         required=True,
    256         )
     258    def add_payment_item(item):
     259        """Payments contain payment items.
     260
     261        Add one
     262        """
    257263
    258264
     
    283289        required=True
    284290        )
    285 
    286 
    287 class IPaymentItem(Interface):
    288     """Something to sell.
    289     """
    290     item_id = schema.TextLine(
    291         title=u'Payment Item ID',
    292         required=True,
    293         )
    294 
    295     title = schema.TextLine(
    296         title=u'Title',
    297         description=u'A short title of the good sold.',
    298         required=True,
    299         default=u'Unnamed'
    300         )
    301 
    302     amount = schema.Decimal(
    303         title=u'Amount',
    304         description=u'Total amount, includung any taxes, fees, etc.',
    305         required=True,
    306         default=decimal.Decimal('0.00'),
    307         )
    308 
    309     currency = schema.Choice(
    310         title=u'Currency',
    311         source=ISO_4217_CURRENCIES_VOCAB,
    312         required=True,
    313         default='USD',
    314         )
  • main/waeup.ikoba/trunk/src/waeup/ikoba/payments/payment.py

    r12461 r12671  
    2828from waeup.ikoba.payments.interfaces import (
    2929    IPayment, STATE_UNPAID, STATE_FAILED, STATE_PAID,
    30     IPaymentGatewayService, IPayer, IPaymentItem,
     30    IPaymentGatewayService, IPayer, IPaymentItem, IPayee,
     31    IPaymentGatewayServicesLister,
    3132    )
    3233from waeup.ikoba.utils.logger import Logger
     
    3435
    3536def get_payment_providers():
    36     """Get all services of payment gateways registered.
     37    """Get all payment providers registered.
    3738    """
    3839    return dict(
    3940        getUtilitiesFor(IPaymentGatewayService)
    40         )
     41    )
     42
     43
     44class PaymentGatewayServicesLister(grok.GlobalUtility):
     45    grok.implements(IPaymentGatewayServicesLister)
     46
     47    def __call__(self):
     48        """Get all services of payment gateways registered.
     49        """
     50        return get_payment_providers()
    4151
    4252
     
    4959
    5060
    51 class Payment(grok.Model, Logger):
     61@attrs_to_fields
     62class Payment(grok.Container, Logger):
    5263    """This is a payment.
    5364    """
     
    5970    logger_format_str = '"%(asctime)s","%(user)s",%(message)s'
    6071
     72    @property
     73    def amount(self):
     74        """The amount of a payment.
     75
     76        Equals the sum of items contained.
     77        """
     78        return sum(
     79            [item.amount for item in self.values()],
     80            decimal.Decimal("0.00")  # default value
     81        )
     82
    6183    def __init__(self):
    6284        super(Payment, self).__init__()
     
    6486        self.payment_date = None
    6587        self.payment_id = u'PAY_' + unicode(uuid.uuid4().hex)
    66         self.gateway_service = None
    67         self.amount = decimal.Decimal("0.00")
    68         self.payed_item_id = None
    69         self.payer_id = None
    7088        self.state = STATE_UNPAID
    7189        return
     
    95113        notify(grok.ObjectModifiedEvent(self))
    96114
     115    def add_payment_item(self, item):
     116        """Add `item`
     117
     118        Returns the key under which the `item` was stored. Please do
     119        not make anby assumptions about the key. It will be a
     120        string. That is all we can tell.
     121
     122        """
     123        cnt = 0
     124        while str(cnt) in self:
     125            cnt += 1
     126        self[str(cnt)] = item
     127        return str(cnt)
     128
     129
     130@attrs_to_fields
     131class Payer(object):
     132    """A Payment is for testing.
     133
     134    It cannot be stored in ZODB.
     135    """
     136    grok.implements(IPayer)
     137
    97138
    98139@attrs_to_fields
     
    100141
    101142    grok.implements(IPaymentItem)
     143
     144    def __init__(self):
     145        super(PaymentItem, self).__init__()
     146
     147
     148@attrs_to_fields
     149class Payee(object):
     150    """Someone being paid.
     151
     152    This is for testing only and cannot be stored in ZODB.
     153    """
     154    grok.implements(IPayee)
  • main/waeup.ikoba/trunk/src/waeup/ikoba/payments/tests/test_payment.py

    r12461 r12671  
    1717##
    1818import datetime
     19import decimal
    1920import re
    2021import unittest
    21 from zope.component import getUtilitiesFor, getSiteManager
     22from zope.component import getUtilitiesFor, getSiteManager, queryUtility
    2223from zope.interface import implements
    2324from zope.interface.verify import verifyClass, verifyObject
    2425from waeup.ikoba.payments.interfaces import (
    2526    IPayment, STATE_UNPAID, STATE_PAID, STATE_FAILED,
    26     IPaymentGatewayService, IPaymentItem
     27    IPaymentGatewayService, IPaymentItem, IPaymentGatewayServicesLister,
    2728    )
    2829from waeup.ikoba.payments.payment import (
    2930    Payment, get_payment_providers, PaymentItem,
    3031    )
     32from waeup.ikoba.testing import (FunctionalLayer, FunctionalTestCase)
    3133
    3234
     
    5860        assert result.keys() == ['some_name', ]
    5961        assert result['some_name'] is fake_util
     62
     63
     64class FunctionalHelperTests(FunctionalTestCase):
     65
     66    layer = FunctionalLayer
     67
     68    def test_services_lister_is_registered(self):
     69        # a lister of gateway services is registered on startup
     70        util = queryUtility(IPaymentGatewayServicesLister)
     71        assert util is not None
     72
     73    def test_services_are_really_listed(self):
     74        # we can really get locally registered gateways when calling
     75        util = queryUtility(IPaymentGatewayServicesLister)
     76        assert len(util()) > 0
    6077
    6178
     
    113130        assert p1.state == STATE_FAILED
    114131
     132    def test_add_payment_item(self):
     133        # we can add payment items
     134        p1 = Payment()
     135        item1 = PaymentItem()
     136        result = p1.add_payment_item(item1)
     137        assert len(p1) == 1  # do not make assumptions about result content
     138        assert isinstance(result, basestring)
     139
     140    def test_add_payment_item_multiple(self):
     141        # we can add several items
     142        p1 = Payment()
     143        item1 = PaymentItem()
     144        item2 = PaymentItem()
     145        result1 = p1.add_payment_item(item1)
     146        result2 = p1.add_payment_item(item2)
     147        assert len(p1) == 2  # do not make assumptions about result content
     148        assert isinstance(result1, basestring)
     149        assert isinstance(result2, basestring)
     150
     151    def test_amount(self):
     152        # the amount of a payment is the sum of amounts of its items
     153        p1 = Payment()
     154        item1 = PaymentItem()
     155        item2 = PaymentItem()
     156        p1.add_payment_item(item1)
     157        p1.add_payment_item(item2)
     158        item1.amount = decimal.Decimal("12.25")
     159        item2.amount = decimal.Decimal("0.5")
     160        assert p1.amount == decimal.Decimal("12.75")
     161
     162    def test_amount_negative(self):
     163        # we can sum up negative numbers
     164        p1 = Payment()
     165        item1 = PaymentItem()
     166        item2 = PaymentItem()
     167        p1.add_payment_item(item1)
     168        p1.add_payment_item(item2)
     169        item1.amount = decimal.Decimal("2.21")
     170        item2.amount = decimal.Decimal("-3.23")
     171        assert p1.amount == decimal.Decimal("-1.02")
     172
     173    def test_amount_empty(self):
     174        # the amount of zero items is 0.00.
     175        p1 = Payment()
     176        assert p1.amount == decimal.Decimal("0.00")
     177        assert isinstance(p1.amount, decimal.Decimal)
     178
    115179
    116180class PaymentItemTests(unittest.TestCase):
Note: See TracChangeset for help on using the changeset viewer.