Jan Fromm Posted June 23, 2022 Share Posted June 23, 2022 Hi @kongondo, I would be interested to know to what degree Padloper handles EU taxes for digital products, and what may need to be added by the developer. As I’m sure you know, this varies greatly depending on whether the seller is based in the EU or not, whether the customer is based in the EU or not, and whether it's private (without VAT number) or business (with VAT number). There is this option »Charge EU Digital Goods VAT Taxes« in the tax settings. As far as I can see, this has no effect yet. Or did I miss something? Is this still WIP? Or what are your plans? Thanks! Link to comment Share on other sites More sharing options...
kongondo Posted June 23, 2022 Share Posted June 23, 2022 Hi @Jan Fromm, 5 hours ago, Jan Fromm said: There is this option »Charge EU Digital Goods VAT Taxes« in the tax settings. As far as I can see, this has no effect yet. It does have an effect, unless I recently broke something ?. I've just tested the below and it works fine. 5 hours ago, Jan Fromm said: to what degree Padloper handles EU taxes for digital products, and what may need to be added by the developer. Currently this is limited to the following: A product has been designated as NOT taxable. The product is specified as a digital product. The Charge EU Digital Goods VAT Taxes is ticked. The customer country is IN the EU (proceed to #6). The customer country is NOT in the EU (proceed to #7). (EU Digital Goods) Tax will be charged on this product. (unless it is a manual order and the order or the customer has been exempted from tax). Taxes will not be charged on this product (unless it was specified as taxable in #1). 5 hours ago, Jan Fromm said: As I’m sure you know, this varies greatly depending on whether the seller is based in the EU or not, whether the customer is based in the EU or not, and whether it's private (without VAT number) or business (with VAT number). These complexities (at least currently) would have to be handled by the developer. I'm not sure that we currently have somewhere to hook into. I'll have a look. Link to comment Share on other sites More sharing options...
Jan Fromm Posted June 23, 2022 Author Share Posted June 23, 2022 2 hours ago, kongondo said: A product has been designated as NOT taxable. That was the trick. Thanks! Assuming that only digital products are to be sold, would it be enough to only care about the tax rates of EU countries? The other countries could be created without tax rates, right? 2 hours ago, kongondo said: These complexities (at least currently) would have to be handled by the developer. I'm not sure that we currently have somewhere to hook into. I'll have a look. Fantastic. Thanks again. Link to comment Share on other sites More sharing options...
kongondo Posted June 23, 2022 Share Posted June 23, 2022 19 minutes ago, Jan Fromm said: Assuming that only digital products are to be sold, would it be enough to only care about the tax rates of EU countries? The other countries could be created without tax rates, right? Theoretically, yes. However, you would need to be aware of any laws similar to the EU Digital Goods regulations. Not closely related, but I forgot to mention (and you are probably aware of this) that we also have tax overrides that can be applied per category of products or shipping. 22 minutes ago, Jan Fromm said: That was the trick. Thanks! Glad you got it sorted. 1 Link to comment Share on other sites More sharing options...
Jan Fromm Posted July 20, 2022 Author Share Posted July 20, 2022 Hi @kongondo, On 6/23/2022 at 6:55 PM, kongondo said: These complexities (at least currently) would have to be handled by the developer. I'm not sure that we currently have somewhere to hook into. I'll have a look. Have you been able to check this? I am currently thinking about how I could add this functionality. My current idea looks like this: 1) Add new textfield »VAT« to custom customer form 2) Hook processCustomOrderCustomerForm and process VAT validation 3) Hook isChargeEUDigitalGoodsTax At the moment, digital goods taxes are collected IF1 It is set in the store settings AND2 The customer is located in the EU AND3 It is a digital product This must be extended by4 The customer does NOT have a valid VAT number, unless he is located in the same country as the shop owner. Is this possible? There are some pitfalls for sure, but that would be my approach. Thanks further hints, ideas or doubts! Link to comment Share on other sites More sharing options...
kongondo Posted July 20, 2022 Share Posted July 20, 2022 9 hours ago, Jan Fromm said: Have you been able to check this? @Jan Fromm, Sorry this slipped through the cracks! 9 hours ago, Jan Fromm said: 1) Add new textfield »VAT« to custom customer form That would work..., yes. 9 hours ago, Jan Fromm said: 2) Hook processCustomOrderCustomerForm and process VAT validation This could work. How do you intend to do the validation? I am asking to see where best to hook. 9 hours ago, Jan Fromm said: 3) Hook isChargeEUDigitalGoodsTax Yes, good idea. Link to comment Share on other sites More sharing options...
kongondo Posted July 20, 2022 Share Posted July 20, 2022 2 hours ago, kongondo said: This could work. How do you intend to do the validation? I am asking to see where best to hook. @Jan Fromm. Just to add to my question, do you want to tell the customer if the validation fails? Link to comment Share on other sites More sharing options...
Jan Fromm Posted July 21, 2022 Author Share Posted July 21, 2022 17 hours ago, kongondo said: This could work. How do you intend to do the validation? I am asking to see where best to hook. Probably with a SOAP call to the EU VAT Information Exchange System (VIES). 14 hours ago, kongondo said: Just to add to my question, do you want to tell the customer if the validation fails? That would already make sense. Thanks a lot! 1 Link to comment Share on other sites More sharing options...
kongondo Posted July 21, 2022 Share Posted July 21, 2022 Thanks @Jan Fromm. Started working on this. Will let you know. 1 Link to comment Share on other sites More sharing options...
Jan Fromm Posted July 21, 2022 Author Share Posted July 21, 2022 No rush @kongondo. Thanks in advance! BTW: I found a promising PHP class for VAT validation. In case you want to take a look at it. 1 Link to comment Share on other sites More sharing options...
kongondo Posted July 24, 2022 Share Posted July 24, 2022 Hi @Jan Fromm, The Hooks are now ready per the latest release today (004). A demo implementation is here (demo 3) in the demo repo. The hooks are (per demo linked to above): PadloperProcessOrder::checkCustomOrderCustomerFormForErrors This will allow you to reject business customer form and return it to them for amendment, .e.g., in case they stated they are a business customer but did not fill in the VAT number or VAT number is invalid. It is better to hook here instead of PadloperProcessOrder::processCustomOrderCustomerForm as it gives you early access to the form. Please have a look at the demo and let me know if you have any questions. and PadloperUtilities::isChargeEUDigitalGoodsTax Please see the demo for an example. This will allow you to apply/exempt EU digital tax per line item in the order based on complex conditions as you state above. Note that this demo is not a robust solution compared to the VAT library you have linked to. For instance, the demo doesn't check for country-specific prefixes in the VAT number. Please let me know if you have any questions. Grab version 004 using your purchase link, per usual. Thanks. 1 Link to comment Share on other sites More sharing options...
Jan Fromm Posted July 24, 2022 Author Share Posted July 24, 2022 You are really amazing @kongondo. Big thanks! I’ll take a look at it. Link to comment Share on other sites More sharing options...
Jan Fromm Posted October 27, 2022 Author Share Posted October 27, 2022 Hi @kongondo, Sorry for the long silence. I finally had a chance to look into the demo and am amazed that your VAT validation code is already 99% functional! I just had to take into account the country prefixes and now it runs like a charm. Anyway, one milestone passed, and the next one is just around the corner. I’d like to store the customers VAT number in OrderCustomer so I can display it on the confirmation page and on the invoice. I guess I need to add a custom field to the OrderCustomer template, right? I’m not sure where to do that, unfortunately. My second issue is to show a note on the invoice if Reverse Charge applies (customer has valid VAT number and gets an invoice without VAT). My idea is to hook in __orderSaved and add this hint to the order using the Notes feature. Unfortunately I have not found any information about this in the demos and the forum. As always, I appreciate any hints and help. Thanks! 1 Link to comment Share on other sites More sharing options...
kongondo Posted November 3, 2022 Share Posted November 3, 2022 (edited) On 10/27/2022 at 12:49 PM, Jan Fromm said: I just had to take into account the country prefixes and now it runs like a charm. Hi @Jan Fromm. Glad it worked! On 10/27/2022 at 12:49 PM, Jan Fromm said: I’d like to store the customers VAT number in OrderCustomer so I can display it on the confirmation page and on the invoice. I guess I need to add a custom field to the OrderCustomer template, right? I’m not sure where to do that, unfortunately. Yes, you will need a custom field. Customers do not have their own template You would need to add the field to the order template itself (padloper-order). Please see Demo 2. It explains how you can do this. On 10/27/2022 at 12:49 PM, Jan Fromm said: My idea is to hook in __orderSaved and add this hint to the order using the Notes feature. Good idea. But there are alternatives with respect to the Notes feature. Also see the caveats below. On 10/27/2022 at 12:49 PM, Jan Fromm said: Unfortunately I have not found any information about this in the demos and the forum. Apologies. Documentation is still lacking. Notes are stored in the field padloper_notes. This field is used in the template padloper-order. Padloper notes are a type of WireArray. You have access to all the methods of WireArray. Back to notes... On 10/27/2022 at 12:49 PM, Jan Fromm said: My second issue is to show a note on the invoice if Reverse Charge applies (customer has valid VAT number and gets an invoice without VAT). Caveats Dedicated Text or Custom Field OR Notes Given that padloper_notes can take multiple notes and given that some of these are generated programmatically, using it to save a very specific note as described in your case might not be the better approach. For instance, you would need to search the WireArray of Notes for your 'reverse charges hint note' before you can display it on their invoice. Searching is not a big deal as you would be searching the WireArray in-memory, however, you will need some key words to match the note you are looking for amongst the order's other notes. An alternative is to add and use a dedicated text field in the order's template similar to the customer's VAT number above. A third alternative is to create your own custom field to store both notes and VAT numbers. Just a few thoughts. If you want to add a note using the API, it is quite simple as shown below. This example assumes you are doing this via a Hook. <?php namespace ProcessWire; # CONTENT OF A HOOK METHOD # /* if hooking $this->addHookAfter('PadloperProcessOrder::orderSaved', null, 'nameOfYourHookFunction'); */ // Retrieve argument by name /** @var Page $orderPage */ $orderPage = $event->arguments('orderPage'); $orderNoteText = "The text of my note. This customer has a VAT..."; # @note: this method will add tje created and modified times for you # you can add your user ID if you want, as the 3rd argument to this method /** @var WireData $note */ $note = $padloper->buildNote($orderNoteText,'admin'); $orderPage->of(false); // add the $note to the order page $orderPage->padloper_notes->add($note); // save the page $orderPage->save('padloper_notes'); # --------- OR ------------- // $notes = $orderPage->padloper_notes; // $notes->add($note); // $orderPage->setAndSave('padloper_notes', $notes); Method to Hook Usually hooking into __orderSaved would be fine. However, this method will be called every time the order is amended during the payment process. For instance, a customer can go to checkout and enter their details. This will cause an order to be created. Whilst in the order confirmation/payment page, the customer could decide to amend their shopping cart and subsequently head to the checkout. Since we already have an order created, it won't be recreated, however, it will be amended if needed, hence orderSaved() will be called again. This might mean your note would be created multiple times. You might not want this. You could always check if such a note exists for the given order and amend it if necessary. To avoid this, it could be better to hook into the PadloperProcessOrder::sendConfirmation() method instead as shown below. This method will be called only once, when the order checkout processing is complete. <?php namespace ProcessWire; # CONTENT OF A HOOK METHOD # /* if hooking $this->addHookAfter('PadloperProcessOrder::sendConfirmation', null, 'nameOfYourHookFunction'); */ $padloper = wire('padloper'); // @NOTE: Retrieve argument by name <- won't work since argument value is Null // instead, we get the orderPage from the session /** @var Page $orderPage */ $orderPage = $padloper->getOrderPage(); // ------------- $orderNoteText = "The text of my note if sendConfirmation() Hook. This customer has a VAT..."; # @note: this method will add the created and modified times for you # you can add your user ID if you want, as the 3rd argument to this method /** @var WireData $note */ $note = $padloper->buildNote($orderNoteText, 'admin'); $orderPage->of(false); // add the $note to the order page $orderPage->padloper_notes->add($note); // save the page $orderPage->save('padloper_notes'); Hope this helps! Edited November 11, 2022 by kongondo typos 2 Link to comment Share on other sites More sharing options...
Jan Fromm Posted November 11, 2022 Author Share Posted November 11, 2022 On 11/3/2022 at 6:32 PM, kongondo said: Hope this helps! It did! I got it to run with two custom fields in the order-template. These are populated with a hook in __orderSaved and then shown at checkout-confirmation and on the invoice. Thanks again for your help, @kongondo! 2 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now