Metadata-Version: 1.0
Name: getpaid.core
Version: 0.9.2
Summary: Core ecommerce functionality for zope and python projects
Home-page: http://code.google.com/p/getpaid
Author: Getpaid Community
Author-email: getpaid-dev@googlegroups.com
License: ZPL2.1
Description: This package contains the core functionality of the getpaid framework.
        
        =======
        CHANGES
        =======
        
        0.9.2 (2011-07-06)
        ------------------
        
        - Use getSite to get the store from the order workflow transition handler,
          rather than trying to acquire it from one of the cart items.
          [davisagli]
        
        - Remove obviously broken product and catalog modules.
          [davisagli]
        
        - Depend on zope.intid instead of zope.app.intid.
          [davisagli]
        
        0.9.1 (2010-06-29)
        ------------------
        
        - made tax translatable, rebuilt and synced translation files,
          updated German translations
          [fRiSi]
        
        0.9.0 (2010-05-18)
        ------------------
        
        - Prevent addition of recurring line items to a cart with non-recurring items,
          and vice versa.
          [jesses, alext]
        
        - Fix spelling of "Verification".
          [cewing]
        
        - Added ``is_recurring`` method to ShoppingCart to check whether the cart
          contains a recurring line item.
          [davisagli]
        
        - Fix exception handling in OrderManager's isValid method.
          [davisagli]
        
        - Add renewal_date index for orders.
          [jpg.rcom]
        
        - Add IRecurringPaymentContent interface.
          [jpg.rcom]
        
        - Update IRecurringLineItem to specify interval and total_occurrences
          attributes, instead of period.
          [jpg.rcom]
        
        0.8.0 (2010-04-07)
        ------------------
        
        - Adjusted imports to add support for Zope 2.12, and remove support for
          Zope 2.9.
          [davisagli]
        
        0.7.5 (2009-07-07)
        ------------------
        - Add ship and bill organization
        
        0.7.4 (2009-05-12)
        ------------------
        
        - Add support for variable amount donations
        - Allow annotations on shopping cart
        
        0.7.3 (2009-03-13)
        ------------------
        
        - updated portuguese translation [rafaelcrocha]
        
        0.7.2 (2008-12-30)
        ------------------
        
        * Added 2 fixes (for when you use the shipping system):
        * gave a default value to the order.shipments, because
          it is never set up to anything otherwise and you can't
          access your order,
        * fixed the way we calculate the total, so that we have
          float numbers
          [lucielejard]
        
        0.7.1 (2008-11-24)
        ------------------
        
        * Persisted and added Name on Card and Card Phone Num to orders listing
          viewlet. [ctxlken]
        * Persisted processor transaction id and last-4 digits of credit card to
          ZODB.  Also, modified order-summary.pt to present these two fields.
          [ctxlken]
        * add: added some missing italian translations [bruno.ripa]
        * update getpaid.po and sync with all .po. add Japanese locales
          [cjj.ifpeople]
        * add: missing italian translations [bruno.ripa]
        
        
        0.7 (2008-08-29)
        ----------------
        
        * Added buildout files and general text documents to project root.
        * removed setup.cfg
        * updated txt files so that restructured text works on pypi
        
        Detailed Documentation
        **********************
        
        Order Management in GetPaid
        ===========================
        
        Getpaid's core functionality is represented as an order management
        system. 
        
        Creating an Order
        =================
        
          >>> from getpaid.core.order import Order
          >>> order = Order()
        
        Carts and Line Items
        ====================
        
        An order consists of line items. line items can come from a variety of
        sources, content space payables, gift certificates, ie. anything we 
        potentially want to purchase:
        
          >>> from getpaid.core.item import LineItem
          >>> item = LineItem()
          
        Let's set some attributes expected on line items. The only system invariant
        here is that item_id should be unique when referring to purchasing the same
        item: 
        
          >>> item.item_id = "event-devtalk-2007-1" 
          >>> item.name = "Event Registration"
          >>> item.cost = 25.00
          >>> item.quantity = 5
          >>> item.description = "Development Talk"
          
        Line Items are stored in a line item container, such as a shopping cart
        of shipment:
          
          >>> from getpaid.core.cart import ShoppingCart
          >>> cart = ShoppingCart()
          >>> cart[ item.item_id ] = item
        
        we can ask the cart how many items it has:
        
          >>> cart.size()
          5
        
        Let's attach our cart to the order:
        
          >>> order.shopping_cart = cart
        
        and now we can ask the order, its total price:
          
          >>> from decimal import Decimal
          >>> order.getSubTotalPrice() == Decimal("125.0")
          True
        
        [ xxx talk about products and payable line items here ??]
        
        Customer Information
        ====================
        
        We need some additional information for an order to successfully process it:
        
          >>> from getpaid.core import payment
          >>> bill_address = payment.BillingAddress()
          >>> bill_address.bill_first_line = '1418 W Street NW'
          >>> bill_address.bill_city = 'Washington'
          >>> bill_address.bill_state = "DC"
          >>> bill_address.bill_country = "US"
          >>> bill_address.bill_postal_code = '20009'
          >>>
          >>> 
          >>> contact_info = payment.ContactInformation()
          >>>
          >>> order.contact_information = contact_info
          >>> order.billing_address = bill_address
        
        If we don't need to ship anything to the user, then we can forgo
        setting a shipping address.
        
        
        Introspection and Classification
        ================================
        
        When we create an order, an order inspection component which
        subscribes to the order created event, gets a chance to look at all
        the contents of an order and modify it. The default inspector, will
        add additional marker interfaces to the order to classify it based on
        its contents as a shippable order, donation order, etc. Based on these
        marker interfaces and corresponding compnent registration, we can
        specialize adapation of orders to workflows, payment processing as
        appropriate for a given order. 
        
          >>> try:
          ...     from zope.lifecycleevent import ObjectCreatedEvent
          ... except ImportError:
          ...     from zope.app.event.objectevent import ObjectCreatedEvent
          >>> from zope.event import notify
          >>> notify( ObjectCreatedEvent( order ))
          >>> 
        
        Finance Workflow
        ================
        
        The finance workflow
        
        
        Payment Processor Integration
        =============================  
        
        We payment processor integration to support multiple different
        services and is workflow driven. We dispatch workflow events to a
        processor integration multi adapter which takes as context the order
        and the workflow. 
        
        
        The one public payment processor integration attribute on the order is
        the payment processor id, which corresponds to the name that the
        payment processor adapter is registered on.
        
        
        Its also important to note that there are several varieties of
        asynchronous payment processors, which alsorequire corresponding
        checkout user interface support, and callback url endpoints, which are
        outside of the scope of this example. These doctest examples require a
        synchronous processor api.
        
        
        Managing Collections of Orders
        ==============================
        
        
        Querying Orders
        ===============
        
        
        Reporting on Orders
        ===================
        
        We use workflows to model the order lifecycle for finance and
        fulfillment. We can introspect orders to classify by them interface
        and adapt to the appropriate workflows. As a consequence we can support
        online and shipping based from the same order management system.
        and support virtual delivery, and a shipping lifecycle. we
        utilize hurry.workflow to implement our workflows, one benefits to
        make this lifecycle observable via event subscribers.
        
        
        
        line items are stored in line item containers, like a shopping cart,
        or shipment. a line item is unique within these containers
        based on some unique attribute (at uid, or product sku).
        
        
        getpaid internaly dispatches workflow changes to the appropriate
        payment processor for an order.
        
        
        because we can process workflows asynchronously, we can get pretty
        good at synchronization / integration with other systems.
        
        an order has both a finance workflow and a fulfillment workflow
        dependent on its contained items. the finance workflow models things
        like cc authorization for an order, and capture/charging an order.
        
        Workflow Tests
        ==============
        
        Let's first create an Order object to work with:
        
           >>> from getpaid.core.order import Order
           >>> testorder = Order()
        
        Now we'll test the order workflow...
        
        Before we fire the 'create' transition we don't have a workflow states
        for finance and fulfillment
        
           >>> state = testorder.fulfillment_state
           >>> print state
           None
        
           >>> state = testorder.finance_state
           >>> print state
           None
        
        Firing the 'create' transition in the finance workflow should put us 
        in the REVIEWING state
         
           >>> testorder.finance_workflow.fireTransition('create')
           >>> state = testorder.finance_state
           >>> print state
           REVIEWING
        
        Firing some more transitions to test the finance workflow.  
        
           >>> testorder.finance_workflow.fireTransition('authorize')
           >>> state = testorder.finance_state
           >>> print state
           CHARGEABLE
        
        
           >>> testorder.finance_workflow.fireTransition('charge-chargeable')
           >>> state = testorder.finance_state
           >>> print state
           CHARGING
        
        Firing the 'create' transition in the fulfillment workflow should put us 
        in the REVIEWING state
        
           >>> testorder.fulfillment_workflow.fireTransition('create')
           >>> state = testorder.fulfillment_state
           >>> print state
           NEW
        
        Testing the fulfillment workflow for a delivered order. We need to re-cast 
        the testorder object as we cannot transition back from 
        
           >>> testorder = Order()
           >>> testorder.fulfillment_workflow.fireTransition('create')
           >>> state = testorder.fulfillment_state
           >>> print state
           NEW
        
           >>> testorder.fulfillment_workflow.fireTransition('process-order')
           >>> state = testorder.fulfillment_state
           >>> print state
           PROCESSING
        
           >>> testorder.fulfillment_workflow.fireTransition('deliver-processing-order')
           >>> state = testorder.fulfillment_state
           >>> print state
           DELIVERED
        
        Testing the fulfillment workflow for a cancelled order. We need to re-cast 
        the testorder object as we cannot transition back from DELIVERED state.
        
           >>> testorder2 = Order()
        
           >>> testorder2.fulfillment_workflow.fireTransition('create')
           >>> state = testorder2.fulfillment_state
           >>> print state
           NEW
        
           >>> testorder2.fulfillment_workflow.fireTransition('process-order')
           >>> state = testorder2.fulfillment_state
           >>> print state
           PROCESSING
        
           >>> testorder2.fulfillment_workflow.fireTransition('cancel-order')
           >>> state = testorder2.fulfillment_state
           >>> print state
           WILL_NOT_DELIVER
        
        
        Order Id Management
        ===================
        
        Each order needs an Id with a strong requirement on it being unique
        and non-guessable. You can get a new, nonguessable id with a
        reasonable guarantee of it being unique by calling newOrderId().
        
           >>> from zope import component
           >>> from getpaid.core import interfaces
           >>> from getpaid.core.order import Order
           >>> order_manager = component.getUtility( interfaces.IOrderManager )
           >>> order = Order()
           >>> order.order_id = order_manager.newOrderId()
           >>> order_manager.store( order )
        
        now that the order is stored, no amount of calling newOrderId should
        return the same id. I can't actually test for uniqueness or
        nonguessability, can I?
        
           >>> for i in xrange(10000):
           ...    assert(order_manager.newOrderId() != order.order_id)
        
        but on the other hand, I *can* test that if I create an order with the
        same id as an existing order, things will fail:
        
           >>> new_order = Order()
           >>> new_order.order_id = order.order_id
           >>> try:
           ...     order_manager.store( new_order )
           ... except Exception, e:
           ...     if e.__class__.__name__ in ('KeyError', 'DuplicationError'):
           ...         print 'duplicate'
           duplicate
        
        Download
        **********************
        
Platform: UNKNOWN
Classifier: Framework :: Plone
Classifier: Framework :: Zope3
Classifier: Programming Language :: Python
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Zope Public License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Software Development :: Libraries
