Ignore:
Timestamp:
11 Mar 2015, 10:07:50 (10 years ago)
Author:
uli
Message:

Implement an IPayable adapter for contracts.

Location:
main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/customers
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/customers/contracts.py

    r12718 r12727  
    3333    IContractSelectProduct, ICustomersUtils, ISampleContract,
    3434    ISampleContractProcess, ISampleContractEdit, ISampleContractOfficialUse)
    35 from waeup.ikoba.payments.interfaces import IPayer, IPayableFinder
     35from waeup.ikoba.payments.interfaces import IPayer, IPayableFinder, IPayable
    3636from waeup.ikoba.payments.payment import PaymentItem
    3737from waeup.ikoba.utils.helpers import attrs_to_fields
     
    276276        # there should not be more than one result really.
    277277        return result[0]
     278
     279
     280class PayableContract(grok.Adapter):
     281    """Adapter to adapt IContracts to IPayable.
     282    """
     283
     284    grok.context(IContract)
     285    grok.implements(IPayable)
     286
     287    def __init__(self, context):
     288        self.context = context
     289        currencies = set([x.currency for x in context.product_options])
     290        if len(currencies) > 1:
     291            raise ValueError(
     292                "Only contracts with same currency for all options allowed.")
     293        return
     294
     295    @property
     296    def payable_id(self):
     297        return self.context.contract_id
     298
     299    @property
     300    def title(self):
     301        return self.context.title
     302
     303    @property
     304    def currency(self):
     305        if not len(self.context.product_options):
     306            return None
     307        return self.context.product_options[0].currency
     308
     309    @property
     310    def payment_items(self):
     311        result = []
     312        for num, option in enumerate(self.context.product_options):
     313            item = PaymentItem()
     314            item.item_id = u'%s' % num
     315            item.title = option.title
     316            item.amount = option.fee
     317            result.append(item)
     318        return tuple(result)
  • main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/customers/tests/test_contract.py

    r12718 r12727  
    2929from waeup.ikoba.customers.contracts import (
    3030    ContractsContainer, SampleContract, payment_items_from_contract,
    31     ContractPayer, ContractFinder
     31    ContractPayer, ContractFinder, PayableContract,
    3232    )
    3333from waeup.ikoba.app import Company
    3434from waeup.ikoba.customers.customer import Customer
    3535from waeup.ikoba.payments.interfaces import (
    36     IPaymentItem, IPayer, IPayableFinder,
     36    IPaymentItem, IPayer, IPayableFinder, IPayable,
    3737    )
    3838from waeup.ikoba.products.productoptions import ProductOption
     
    187187        result = finder.get_payable_by_id('CON1234')
    188188        self.assertTrue(result is None)
     189
     190
     191class TestContractAsPayable(FunctionalTestCase):
     192
     193    layer = FunctionalLayer
     194
     195    def test_adaptable(self):
     196        # we can turn contracts into payables.
     197        contract = SampleContract()
     198        payable = IPayable(contract)
     199        self.assertTrue(payable is not None)
     200        self.assertTrue(isinstance(payable, PayableContract))
     201
     202    def test_payable_iface(self):
     203        # PayableContracts really provide IPayable
     204        contract = SampleContract()
     205        option1 = ProductOption(u"Fee 1", decimal.Decimal("31.10"), "USD")
     206        option2 = ProductOption(u"Fee 2", decimal.Decimal("12.12"), "USD")
     207        contract.product_options = [option1, option2]
     208        payable = PayableContract(contract)
     209        verifyObject(IPayable, payable)
     210        verifyClass(IPayable, PayableContract)
     211
     212    def test_payable_simple_attributes(self):
     213        # the simple attribs are set correctly, according to context contract
     214        contract = SampleContract()
     215        contract.title = u'the title'
     216        option1 = ProductOption(u"Fee 1", decimal.Decimal("31.10"), "EUR")
     217        option2 = ProductOption(u"Fee 2", decimal.Decimal("12.12"), "EUR")
     218        contract.product_options = [option1, option2]
     219        payable = PayableContract(contract)
     220        self.assertTrue(contract.contract_id, payable.payable_id)
     221        self.assertEqual(payable.title, contract.title)
     222        self.assertEqual(payable.currency, 'EUR')
     223
     224    def test_payable_items(self):
     225        # we can get payment items from payable
     226        contract = SampleContract()
     227        option1 = ProductOption(u"Fee 1", decimal.Decimal("31.10"), "EUR")
     228        option2 = ProductOption(u"Fee 2", decimal.Decimal("12.12"), "EUR")
     229        contract.product_options = [option1, option2]
     230        payable = PayableContract(contract)
     231        items = payable.payment_items
     232        self.assertTrue(isinstance(items, tuple))
     233        self.assertEqual(len(items), 2)
     234        verifyObject(IPaymentItem, items[0])
     235        verifyObject(IPaymentItem, items[1])
     236        self.assertEqual(items[0].item_id, '0')
     237        self.assertEqual(items[0].title, u'Fee 1')
     238        self.assertEqual(items[0].amount, decimal.Decimal("31.10"))
     239
     240    def test_payable_no_items(self):
     241        # payables work also with no options set on contract
     242        contract = SampleContract()
     243        payable = PayableContract(contract)
     244        items = payable.payment_items
     245        self.assertTrue(isinstance(items, tuple))
     246        self.assertEqual(len(items), 0)
     247        self.assertEqual(payable.currency, None)
     248
     249    def test_different_currencies_forbiddedn(self):
     250        # we do not accept different currencies in payment items
     251        contract = SampleContract()
     252        option1 = ProductOption(u"Fee 1", decimal.Decimal("31.10"), "EUR")
     253        option2 = ProductOption(u"Fee 2", decimal.Decimal("12.12"), "USD")
     254        contract.product_options = [option1, option2]
     255        self.assertRaises(ValueError, PayableContract, contract)
Note: See TracChangeset for help on using the changeset viewer.