Solving the hard parts of eCommerce
          Symfony Live Madrid 2014
          
            
              Presented by Bojan Zivanovic / @bojan_zivanovic
            
          
        
              
            Our vision is for Drupal Commerce to be the number oneopen source eCommerce platform in the world.
          We're doing something right...
            Commerce Guys
            Paris | London | Ann Arbor, MI
            Creators of Platform.sh and Drupal Commerce
            
              We're a Drupal powered eCommerce company now headquartered in Paris with offices in London and Ann Arbor.
              We formed the international company through a small merger in 2010 to create Drupal Commerce and Platform.sh.
              We're now up to around 60 people, about 25% distributed, delivering a wide variety of projects across
              North America and Europe.
            
              It extends a branch-merge workflow to infrastructure so that every branch can be tested as if it
              were in production, and it scales for the largest sites.
            Once again, we start from scratch
              Currency formatting
            
 Turning '1999.99 USD' into '$1,999.99'
            - Decimal separator (.)
 
              - Thousands separator (,)
 
              - Position of the currency symbol (before/after? Space?)
 
            
Currency formatting
            12 345,99 €
            12.345,99 €
            €12,345.99
          Currency formatting
            د.إ. ٩٩٩٫٩٩
            Different numbering systems!
          There's an extension for that: intl
            But you might not have it
 And it might not be up to date
          Where does the data come from?
            
            Provides the largest and most extensive standard repository of locale data available.
            
          Coming soon to symfony/intl
            Build me an address form!
            Data model: Address
            - Recipient, Organization
 
              - Address line 1, Address line 2
 
              - Postal code, Sorting code
 
              - Locality, Dependent locality
 
              - Administrative area, Country
 
            
Data model: Address format
            - Which fields are used, and in which order
 
              - Which fields are required
 
              - Which fields need to be uppercased
 
              - Field labels
 
              - Regular expression for validating postal codes
 
            
Data model: Subdivision
            - Hierarchical, up to 3 levels
 
              - Multilingual user-facing name
 
              - Code (used on envelopes, e.g. CA for California)
 
              - Postal code validation pattern
 
            
 Form generation 
            -  AddressType -> Field subscriber
 
              -  Gets the address format for the selected country, generates the fields
 
              -  Experimental 
 
            
Validator
            - Country code is valid.
 
              - All required fields are filled in.
 
              - All fields unused by the country's format are empty.
 
              - All subdivisions are valid (values matched against predefined subdivisions).
 
              - The postal code is valid (country and subdivision-level patterns).
 
            
Formatter
            - Formats an address according to the destination country format.
 
              - Appends the country name in the local language
 
              - Takes care of major-to-minor and minor-to-major field ordering.
 
            
Territorial groupings
            - California and Nevada
 
              - European Union
 
              - Germany and a set of Austrian postal codes (6691, 6991, 6992, 6993)
 
              - Austria without specific postal codes (6691, 6991, 6992, 6993)
 
            
 Data model 
            Each zone consists out of zone members.
            - ZoneMemberZone
 
             - ZoneMemberCountry*
 
            
Special: include/exclude postal codes
           Matching an address 
            - against a single zone: $zone->match($address) 
 
              - against all zones: ZoneMatcher
 
            
Problem #1: What are my rates?
            Problem #1.1: 2015 VOES
            - VAT on Electronically Supplied Services
 
            - When selling a digital product, VAT is due at the place of the customer.
 
            - From 2015 this applies to EVERYONE.
 
            
Problem #2: Percentages change
             Problem #3: Tax zones
            German VAT is used in Germany and 5 Austrian postal codes.
            Austrian VAT is used in Austria without those 5 postal codes.
          Problem #4: Charging the correct rate
            - B2B or B2C?
 
              - Physical or digital product?
 
              - Registered for tax in additional countries?
 
              - Place of supply
 
            
Data model
              Zone 1-1 TaxType 1-n TaxRate 1-n TaxRateAmount
- Tax type: French VAT
 
                - Zone: "France (VAT)" (inc. "France ex. Corsica" and "Monaco")
 
                - Tax rates: Standard, Intermediate, Reduced, Super Reduced
 
                - Tax rate amounts for Standard: 19.6% (until Jan 1st 2014), 20% (from Jan 1st 2014)
 
              
Bundled data for EU and Switzerland
              Resolvers
          Resolve the tax types.
            Resolve the tax rate for each resolved tax type.
            Get the tax rate amount for each resolved tax rate.
          Canada Tax Type Resolver
             
              If selling from a store in Quebec to a customer in Ontario, apply the Ontario HST.
            EU Tax Type Resolver
            
              A French store selling physical products (e.g. t-shirts) will charge French VAT to EU customers.
            
            
              A French store selling digital products (e.g. ebooks) from Jan 1st 2015 will
              apply the EU customer's tax rates (German customer - German VAT, etc)
            
            
              A French store will charge the 0% Intra-Community rate if the EU customer has provided a VAT number.
            
          Default Tax Type Resolver
              The Serbian store is selling to a Serbian customer, use Serbian VAT.
          Default Tax Rate Resolver
              Use the default rate ($rate->isDefault()) for the resolved tax type.
          Or write your own!
            No tax in New York for t-shirts under 200$
            No tax for school supplies on september 1st (US tax holiday)
            Reduced rate for ebooks in France.
            PHP has no support for decimal numbers
             2.99, 3.4, 6.78 -> floats, not decimals! 
          Store and handle prices as integers?
            Next steps
            - ComplexPrice (base w/ taxes, discounts, fees)
 
              - Calculators
 
            
Focusing on the interaction between taxes and discounts
            
          Links
            - https://github.com/commerceguys/intl
 
              - https://github.com/commerceguys/addressing
 
              - https://github.com/commerceguys/zone
 
              - https://github.com/commerceguys/tax
 
            
Each README points to a blog post on drupalcommerce.org.
        Questions?
          @bojan_zivanovic
          bojanz.github.io/commerce-libraries
          https://joind.in/12945