Includes customer information, store information, and the calculation date.
Exemplo n.º 1
0
 /**
  * {@inheritdoc}
  */
 public function resolveAmounts(TaxableInterface $taxable, Context $context)
 {
     $date = $context->getDate();
     $rates = $this->resolveRates($taxable, $context);
     $amounts = [];
     foreach ($rates as $rate) {
         $amounts[] = $rate->getAmount($date);
     }
     return $amounts;
 }
Exemplo n.º 2
0
 /**
  * Checks whether the store is registered to collect taxes in the given zone.
  *
  * @param ZoneInterface $zone    The zone.
  * @param Context       $context The context containing store information.
  *
  * @return bool True if the store is registered to collect taxes in the
  *              given zone, false otherwise.
  */
 protected function checkStoreRegistration(ZoneInterface $zone, Context $context)
 {
     $storeRegistrations = $context->getStoreRegistrations();
     foreach ($storeRegistrations as $country) {
         if (!isset($this->emptyAddresses[$country])) {
             $this->emptyAddresses[$country] = new Address($country);
         }
         if ($zone->match($this->emptyAddresses[$country])) {
             return true;
         }
     }
     return false;
 }
Exemplo n.º 3
0
 /**
  * {@inheritdoc}
  */
 public function resolve(TaxableInterface $taxable, Context $context)
 {
     $taxTypes = $this->getTaxTypes();
     $customerAddress = $context->getCustomerAddress();
     $customerCountry = $customerAddress->getCountryCode();
     $customerTaxTypes = $this->filterByAddress($taxTypes, $customerAddress);
     if (empty($customerTaxTypes)) {
         // The customer is not in the EU.
         return [];
     }
     $storeAddress = $context->getStoreAddress();
     $storeCountry = $storeAddress->getCountryCode();
     $storeTaxTypes = $this->filterByAddress($taxTypes, $storeAddress);
     $storeRegistrationTaxTypes = $this->filterByStoreRegistration($taxTypes, $context);
     if (empty($storeTaxTypes) && empty($storeRegistrationTaxTypes)) {
         // The store is not in the EU nor registered to collect EU VAT.
         return [];
     }
     $customerTaxNumber = $context->getCustomerTaxNumber();
     // Since january 1st 2015 all digital services sold to EU customers
     // must apply the destination tax type(s). For example, an ebook sold
     // to Germany needs to have German VAT applied.
     $isDigital = $context->getDate()->format('Y') >= '2015' && !$taxable->isPhysical();
     $resolvedTaxTypes = [];
     if (empty($storeTaxTypes) && !empty($storeRegistrationTaxTypes)) {
         // The store is not in the EU but is registered to collect VAT.
         // This VAT is only charged on B2C digital services.
         $resolvedTaxTypes = self::NO_APPLICABLE_TAX_TYPE;
         if ($isDigital && !$customerTaxNumber) {
             $resolvedTaxTypes = $customerTaxTypes;
         }
     } elseif ($customerTaxNumber && $customerCountry != $storeCountry) {
         // Intra-community supply (B2B).
         $icTaxType = $this->taxTypeRepository->get('eu_ic_vat');
         $resolvedTaxTypes = [$icTaxType];
     } elseif ($isDigital) {
         $resolvedTaxTypes = $customerTaxTypes;
     } else {
         // Physical products use the origin tax types, unless the store is
         // registered to pay taxes in the destination zone. This is required
         // when the total yearly transactions breach the defined threshold.
         // See http://www.vatlive.com/eu-vat-rules/vat-registration-threshold/
         $resolvedTaxTypes = $storeTaxTypes;
         $customerTaxType = reset($customerTaxTypes);
         if ($this->checkStoreRegistration($customerTaxType->getZone(), $context)) {
             $resolvedTaxTypes = $customerTaxTypes;
         }
     }
     return $resolvedTaxTypes;
 }
Exemplo n.º 4
0
 /**
  * {@inheritdoc}
  */
 public function resolve(TaxableInterface $taxable, Context $context)
 {
     $taxTypes = $this->getTaxTypes();
     $results = [];
     foreach ($taxTypes as $taxType) {
         $zone = $taxType->getZone();
         $customerZoneMatch = $zone->match($context->getCustomerAddress());
         $storeZoneMatch = $zone->match($context->getStoreAddress());
         if ($customerZoneMatch && $storeZoneMatch) {
             // The customer and store belong to the same zone.
             $results[] = $taxType;
         } elseif ($customerZoneMatch && $this->checkStoreRegistration($zone, $context)) {
             // The customer belongs to the zone, and the store is
             // registered to collect taxes there.
             $results[] = $taxType;
         }
     }
     return $results;
 }
Exemplo n.º 5
0
 /**
  * {@inheritdoc}
  */
 public function resolve(TaxableInterface $taxable, Context $context)
 {
     $customerAddress = $context->getCustomerAddress();
     $storeAddress = $context->getStoreAddress();
     if ($customerAddress->getCountryCode() != 'CA' || $storeAddress->getCountryCode() != 'CA') {
         // The customer or the store is not in Canada.
         return [];
     }
     // Canadian tax types are matched by the customer address.
     // If the customer is from Ontario, the tax types are for Ontario.
     $taxTypes = $this->getTaxTypes();
     $results = [];
     foreach ($taxTypes as $taxType) {
         $zone = $taxType->getZone();
         if ($zone->match($customerAddress)) {
             $results[] = $taxType;
         }
     }
     return $results;
 }
Exemplo n.º 6
0
 /**
  * @covers ::__construct
  *
  * @uses \CommerceGuys\Tax\Resolver\Context::getCustomerAddress
  * @uses \CommerceGuys\Tax\Resolver\Context::getStoreAddress
  * @uses \CommerceGuys\Tax\Resolver\Context::getCustomerTaxNumber
  * @uses \CommerceGuys\Tax\Resolver\Context::getStoreRegistrations
  * @uses \CommerceGuys\Tax\Resolver\Context::getDate
  */
 public function testConstructor()
 {
     $customerAddress = $this->getMockBuilder('CommerceGuys\\Addressing\\Model\\Address')->getMock();
     $storeAddress = $this->getMockBuilder('CommerceGuys\\Addressing\\Model\\Address')->getMock();
     $date = new \DateTime('2014-10-10');
     $context = new Context($customerAddress, $storeAddress, '0123', ['DE'], $date);
     $this->assertSame($customerAddress, $context->getCustomerAddress());
     $this->assertSame($storeAddress, $context->getStoreAddress());
     $this->assertEquals('0123', $context->getCustomerTaxNumber());
     $this->assertEquals(['DE'], $context->getStoreRegistrations());
     $this->assertSame($date, $context->getDate());
 }