From f6f6923420ed48ee0b6a8325c52e17a2ecedddbd Mon Sep 17 00:00:00 2001 From: Reinhold Kainhofer <reinhold@kainhofer.com> Date: Thu, 5 Feb 2015 00:00:46 +0100 Subject: [PATCH] V0.1: First working version of the EU sales report plugin, including export functionality for AT and DE --- Makefile | 5 +- controllers/eurecap.php | 12 +- elements/eucountries.php | 49 ++++ elements/vmorderstates.php | 43 ++++ elements/vmshoppergroups.php | 43 ++++ elements/vmuserfields.php | 35 +++ eurecap.php | 27 ++ eurecap.script.php | 13 +- eurecap.xml | 56 +++- fields/eucountries.php | 54 ++++ fields/vmuserfields.php | 4 +- .../en-GB/en-GB.plg_vmextended_eurecap.ini | 50 ++-- .../en-GB.plg_vmextended_eurecap.sys.ini | 50 ++-- models/eurecap.php | 242 +++--------------- models/eurecap_config.php | 66 ++++- releases/plg_vmextended_eurecap_v0.1.zip | Bin 0 -> 34512 bytes views/eurecap/tmpl/default.php | 25 +- views/eurecap/tmpl/export.php | 20 ++ views/eurecap/tmpl/export_at_xml.php | 65 +++++ views/eurecap/tmpl/export_de_csv.php | 33 +++ views/eurecap/tmpl/export_full.php | 33 +++ views/eurecap/tmpl/settings.php | 10 +- views/eurecap/view.html.php | 96 +++++-- views/eurecap/view.raw.php | 73 ++++++ 24 files changed, 806 insertions(+), 298 deletions(-) create mode 100644 elements/eucountries.php create mode 100644 elements/vmorderstates.php create mode 100644 elements/vmshoppergroups.php create mode 100644 elements/vmuserfields.php create mode 100644 fields/eucountries.php create mode 100644 releases/plg_vmextended_eurecap_v0.1.zip create mode 100644 views/eurecap/tmpl/export.php create mode 100644 views/eurecap/tmpl/export_at_xml.php create mode 100644 views/eurecap/tmpl/export_de_csv.php create mode 100644 views/eurecap/tmpl/export_full.php create mode 100644 views/eurecap/view.raw.php diff --git a/Makefile b/Makefile index 3ccc465..6f9c680 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,8 @@ MVCFILES=controllers/ models/ views/ SYSTRANSLATIONS=$(call wildcard,language/*/*.plg_$(PLUGINTYPE)_$(BASE).*sys.ini) NONSYSTRANSLATIONS=${SYSTRANSLATIONS:%.sys.ini=%.ini} TRANSLATIONS=$(SYSTRANSLATIONS) $(NONSYSTRANSLATIONS) $(call wildcard,language/*/index.html) language/index.html -FIELDS=$(call wildcard,fields/*.php) +FIELDS=fields/ +ELEMENTS=elements/ ZIPFILE=plg_$(PLUGINTYPE)_$(BASE)_v$(VERSION).zip @@ -20,7 +21,7 @@ $(NONSYSTRANSLATIONS): %.ini: %.sys.ini zip: $(PLUGINFILES) $(TRANSLATIONS) $(SYSTRANSLATIONS) $(NONSYSTRANSLATIONS) @echo "Packing all files into distribution file $(ZIPFILE):" - @zip -r $(ZIPFILE) $(PLUGINFILES) $(MVCFILES) $(TRANSLATIONS) $(FIELDS) + @zip -r $(ZIPFILE) $(PLUGINFILES) $(MVCFILES) $(TRANSLATIONS) $(FIELDS) $(ELEMENTS) clean: rm -f $(ZIPFILE) diff --git a/controllers/eurecap.php b/controllers/eurecap.php index d70b8d5..617b308 100644 --- a/controllers/eurecap.php +++ b/controllers/eurecap.php @@ -38,6 +38,11 @@ class VirtuemartControllerEuRecap extends VmController { $this->addViewPath(JPATH_PLUGINS.DS . 'vmextended' . DS . 'eurecap' . DS . 'views'); } + public function cancel(){ + $msg = vmText::_('VMEXT_EU_RECAP_CANCELLED'); + $this->setRedirect($this->redirectPath, $msg, 'message'); + } + function settings($layout='settings'){ vRequest::setVar('controller', $this->_cname); @@ -53,18 +58,17 @@ class VirtuemartControllerEuRecap extends VmController { $this->display(); } - function export($layout='csv'){ + function export(){ vRequest::setVar('controller', $this->_cname); vRequest::setVar('view', $this->_cname); - vRequest::setVar('layout', $layout); +// vRequest::setVar('layout', $layout); -// $this->addViewPath(VMPATH_ADMIN . DS . 'views'); $document = JFactory::getDocument(); $viewType = $document->getType(); $view = $this->getView($this->_cname, $viewType); - $view->setLayout($layout); +// $view->setLayout($layout); $this->display(); } diff --git a/elements/eucountries.php b/elements/eucountries.php new file mode 100644 index 0000000..7a274ea --- /dev/null +++ b/elements/eucountries.php @@ -0,0 +1,49 @@ +<?php +defined('_JEXEC') or die(); + +/** + * + * @package VirtueMart + * @subpackage Plugins - Elements + * @author Valérie Isaksen, adapted by Reinhold Kainhofer for EU countries + * @link http://www.virtuemart.net + * @copyright Copyright (c) 2004 - 2011 VirtueMart Team. All rights reserved. + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php + * VirtueMart is free software. This version may have been modified pursuant + * to the GNU General Public License, and as distributed it includes or + * is derivative of works licensed under the GNU General Public License or + * other free or open source software licenses. + * @version $Id: $ + */ +/* + * This class is used by VirtueMart Payment or Shipment Plugins + * which uses JParameter + * So It should be an extension of JElement + * Those plugins cannot be configured througth the Plugin Manager anyway. + */ +class JElementEUCountries extends JElement { + + /** + * Element name + * @access protected + * @var string + */ + var $_name = 'euCountries'; + + function fetchElement($name, $value, &$node, $control_name) { + + $db = JFactory::getDBO(); + + $query = 'SELECT `virtuemart_country_id` AS value, `country_name` AS text FROM `#__virtuemart_countries` + WHERE `published` = 1 AND `country_2_code` IN ("AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR", "DE", "GR", "HU", "IE", "IT", "LV", "LT", "LU", "MT", "NL", "PL", "PT", "RO", "SI", "SK", "ES", "SE", "GB") ORDER BY `country_name` ASC '; + + $db->setQuery($query); + $fields = $db->loadObjectList(); + $class = ($node->attributes('class') ? 'class="' . $node->attributes('class') . '"' : ''); + + + $class = 'multiple="true" size="10" '; + return JHTML::_('select.genericlist', $fields, $control_name . '[' . $name . '][]', $class, 'value', 'text', $value, $control_name . $name); + } + +} \ No newline at end of file diff --git a/elements/vmorderstates.php b/elements/vmorderstates.php new file mode 100644 index 0000000..25798b9 --- /dev/null +++ b/elements/vmorderstates.php @@ -0,0 +1,43 @@ +<?php +defined ('_JEXEC') or die(); +/** + * + * @package VirtueMart + * @subpackage Plugins - Elements + * @author Valérie Isaksen + * @link http://www.virtuemart.net + * @copyright Copyright (c) 2004 - 2011 VirtueMart Team. All rights reserved. + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php + * VirtueMart is free software. This version may have been modified pursuant + * to the GNU General Public License, and as distributed it includes or + * is derivative of works licensed under the GNU General Public License or + * other free or open source software licenses. + * @version $Id:$ + */ +if (!class_exists('VmConfig')) require(JPATH_VM_ADMINISTRATOR.DS.'components'.DS.'com_virtuemart'.DS.'helpers'.DS.'config.php'); +if(!class_exists('VmModel')) require(JPATH_VM_ADMINISTRATOR.DS.'helpers'.DS.'vmmodel.php'); + +/* + * This class is used by VirtueMart Payment or Shipment Plugins + * which uses JParameter + * So It should be an extension of JElement + * Those plugins cannot be configured througth the Plugin Manager anyway. + */ +class JElementVmOrderStates extends JElement { + + /** + * Element name + * + * @access protected + * @var string + */ + var $_name = 'OrderStates'; + + function fetchElement ($name, $value, &$node, $control_name) { + $statusModel = VmModel::getModel('OrderStatus'); + $fields = $statusModel->getOrderStatusNames(); + $class = 'class="inputbox" multiple="multiple" size="6" '; + + return JHTML::_ ('select.genericlist', $fields, $control_name . '[' . $name . '][]', $class, 'order_status_code', 'order_status_name', $value, $control_name . $name, true); + } +} diff --git a/elements/vmshoppergroups.php b/elements/vmshoppergroups.php new file mode 100644 index 0000000..2cda4c2 --- /dev/null +++ b/elements/vmshoppergroups.php @@ -0,0 +1,43 @@ +<?php +defined('_JEXEC') or die(); +/** + * + * @package VirtueMart + * @subpackage Plugins - Elements + * @author Valérie Isaksen + * @link http://www.virtuemart.net + * @copyright ${PHING.VM.COPYRIGHT} + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php + * VirtueMart is free software. This version may have been modified pursuant + * to the GNU General Public License, and as distributed it includes or + * is derivative of works licensed under the GNU General Public License or + * other free or open source software licenses. + * @version $Id$ + */ +if (!class_exists('JElementList')) require_once(JPATH_LIBRARIES.DS.'joomla'.DS.'html'.DS.'parameter'.DS.'element'.DS.'list.php'); + +class JELementVmShopperGroups extends JElementList { + + var $_name = 'vmShopperGroups'; + + protected function _getOptions(&$node) { + VmConfig::loadJLang('com_virtuemart_orders', TRUE); + + $options = array(); + $db = JFactory::getDBO(); + + $query = 'SELECT `virtuemart_shoppergroup_id` AS value, `shopper_group_name` AS text + FROM `#__virtuemart_shoppergroups` + WHERE `virtuemart_vendor_id` = 1 + ORDER BY `ordering` ASC, `virtuemart_shoppergroup_id` ASC '; + + $db->setQuery($query); + $values = $db->loadObjectList(); + foreach ($values as $value) { + $options[] = JHtml::_('select.option', $value->value, vmText::_($value->text)); + } + + return $options; + } + +} \ No newline at end of file diff --git a/elements/vmuserfields.php b/elements/vmuserfields.php new file mode 100644 index 0000000..3df5433 --- /dev/null +++ b/elements/vmuserfields.php @@ -0,0 +1,35 @@ +<?php +defined('_JEXEC') or die(); +/** + * + * @package VirtueMart + * @subpackage Plugins - Userfields Form Field + * @author Reinhold Kainhofer, Open Tools + * @link http://www.open-tools.net + * @copyright Copyright (c) 2015 Reinhold Kainhofer. All rights reserved. + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php + * VirtueMart is free software. This version may have been modified pursuant + * to the GNU General Public License, and as distributed it includes or + * is derivative of works licensed under the GNU General Public License or + * other free or open source software licenses. + */ + +if (!class_exists('JElementList')) require_once(JPATH_LIBRARIES.DS.'joomla'.DS.'html'.DS.'parameter'.DS.'element'.DS.'list.php'); + +class JELementVmUserFields extends JElementList { + + var $_name = 'vmUserFields'; + + protected function _getOptions(&$node) { + $model = VmModel::getModel('userfields'); + $userfields = $model->getUserfieldsList(); + $options = array(); + foreach ($userfields as $field) { + if ($field->published) { + $options[] = JHtml::_ ('select.option', $field->name, JText::_($field->title) . " (" . $field->name . ")"); + } + } + return $options; + } + +} \ No newline at end of file diff --git a/eurecap.php b/eurecap.php index 3442a4c..e7aa1c0 100644 --- a/eurecap.php +++ b/eurecap.php @@ -73,5 +73,32 @@ class plgVmExtendedEuRecap extends vmExtendedPlugin { ), ); } + + /** + * A helper function for the plugin installer: In VM 3.0.? the onVmAdminMenuItems trigger was added, which allows to dynamically + * add admin menu items to the the backend. In earlier versions, we need to hardcode the menu item to the database. This function + * decides whether the database entry is needed and if so, it adds it (otherwise it removes it, just in case). + */ + public function onInstallCheckAdminMenuEntries() { + $vmver = vmVersion::$RELEASE; + $db = JFactory::getDBO(); + $db->setQuery("SELECT `id` FROM `#__virtuemart_adminmenuentries` WHERE `view` = 'eurecap'"); + $exists = $db->loadResult(); + if (version_compare($vmver, '3.0.3', 'lt')) { + if (!$exists) { + // Before VM 3.0.3 => Need database entry (in the "Orders" section): + $q = "INSERT INTO `#__virtuemart_adminmenuentries` (`module_id`, `name`, `link`, `depends`, `icon_class`, `ordering`, `published`, `tooltip`, `view`, `task`) VALUES +(2, '" . vmText::_('COM_VIRTUEMART_EU_RECAP') . "', '', '', 'vmicon vmicon-16-report', 25, 1, '', 'eurecap', '')"; + $db->setQuery($q); + $db->query(); + } + } else { + if ($exists) { + $q = "DELETE FROM `#__virtuemart_adminmenuentries` WHERE `view` = 'eurecap' AND `task` = '' AND `module_id` = 2"; + $db->setQuery($q); + $db->query(); + } + } + } } \ No newline at end of file diff --git a/eurecap.script.php b/eurecap.script.php index c1a1bc1..665af77 100644 --- a/eurecap.script.php +++ b/eurecap.script.php @@ -38,13 +38,12 @@ class plgVmExtendedEuRecapInstallerScript * @return boolean True on success */ public function postflight ($type, $parent = null) { -// if(!class_exists( 'vmPlugin' )) -// require JPATH_VM_ADMINISTRATOR.DS.'plugins'.DS.'vmplugin.php'; -// if(!class_exists( 'plgVmShopperOrdernumber' )) -// require JPATH_ROOT.DS.'plugins'.DS.'vmextended'.DS.'eurecap'.DS.'eurecap.php'; -// $dispatcher = new JDispatcher(); -// $config = array('name' => 'eurecap', 'type' => 'vmextended'); -// $plugin = new plgVmExtendedEuRecap($dispatcher, $config); + if(!class_exists( 'plgVmExtendedEuRecap' )) + require JPATH_ROOT.DS.'plugins'.DS.'vmextended'.DS.'eurecap'.DS.'eurecap.php'; + $dispatcher = new JDispatcher(); + $config = array('name' => 'eurecap', 'type' => 'vmextended'); + $plugin = new plgVmExtendedEuRecap($dispatcher, $config); + $plugin->onInstallCheckAdminMenuEntries(); // $plugin->plgVmOnStoreInstallPluginTable('extended'); // // $dispatcher->trigger("plgVmOnStoreInstallPluginTable", array('vmshopper')); } diff --git a/eurecap.xml b/eurecap.xml index 7db6032..9be4506 100644 --- a/eurecap.xml +++ b/eurecap.xml @@ -22,6 +22,7 @@ <folder>controllers</folder> <folder>models</folder> <folder>views</folder> + <folder>helpers</folder> </files> <scriptfile>eurecap.script.php</scriptfile> <languages folder="language"> @@ -29,13 +30,19 @@ <language tag="en-GB">en-GB/en-GB.plg_vmextended_eurecap.sys.ini</language> </languages> +<!-- VM 3.x: Fields --> <vmconfig> <fields name="settings" addfieldpath="/administrator/components/com_virtuemart/fields"> <fieldset name="order_properties" addfieldpath="/plugins/vmextended/eurecap/fields" label="VMEXT_EU_RECAP_ORDERPROPERTIES"> + <field name="countries" type="eucountries" multiple="true" scope="com_virtuemart" default="" label="VMEXT_EU_RECAP_COUNTRIES" description="VMEXT_EU_RECAP_COUNTRIES_DESC"/> <field name="order_status" type="orderstatus" default="C,S" multiple="multiple" label="VMEXT_EU_RECAP_ORDERSTATUS" description="VMEXT_EU_RECAP_ORDERSTATUS_DESC "/> <field name="shopper_groups" type="vmshoppergroups" multiple="multiple" label="VMEXT_EU_RECAP_SHOPPERGROUP" description="VMEXT_EU_RECAP_SHOPPERGROUP_DESC" /> <field name="vatid_userfield" type="vmuserfields" label="VMEXT_EU_RECAP_VATID_USERFIELD" multiple="multiple" default="opc_vat" description="VMEXT_EU_RECAP_VATID_USERFIELD_DESC" /> - <field name="only_untaxed" type="radio" default="1" class="btn-group btn-group-yesno" label="VMEXT_EU_RECAP_UNTAXED" description="VMEXT_EU_RECAP_UNTAXED_DESC" > + <field name="include_taxed_orders" type="radio" default="0" class="btn-group btn-group-yesno" label="VMEXT_EU_RECAP_INCLUDE_TAXED" description="VMEXT_EU_RECAP_INCLUDE_TAXED_DESC" > + <option value="1">JYES</option> + <option value="0">JNO</option> + </field> + <field name="include_free" type="radio" default="0" class="btn-group btn-group-yesno" label="VMEXT_EU_RECAP_INCLUDE_FREE" description="VMEXT_EU_RECAP_INCLUDE_FREE_DESC" > <option value="1">JYES</option> <option value="0">JNO</option> </field> @@ -46,15 +53,58 @@ <option value="3">VMEXT_EU_RECAP_FREQUENCY_QUARTERLY</option> <option value="12">VMEXT_EU_RECAP_FREQUENCY_YEARLY</option> </field> - <field name="countries" type="vmcountries" multiple="true" scope="com_virtuemart" default="" label="VMEXT_EU_RECAP_COUNTRIES" description="VMEXT_EU_RECAP_COUNTRIES_DESC"/> - <field name="taxation_moment" type="list" default="status" label="VMEXT_EU_RECAP_TAXATION_MOMENT" description="VMEXT_EU_RECAP_TAXATION_MOMENT_DESC" > + <field name="taxation_moment" type="list" default="placement" label="VMEXT_EU_RECAP_TAXATION_MOMENT" description="VMEXT_EU_RECAP_TAXATION_MOMENT_DESC" > <option value="placement">VMEXT_EU_RECAP_TAXATION_MOMENT_PLACEMENT</option> <!-- <option value="status">VMEXT_EU_RECAP_TAXATION_MOMENT_STATUSCHANGE</option> --> <!-- <option value="payment">VMEXT_EU_RECAP_TAXATION_MOMENT_PAYMENT</option> --> <option value="invoice">VMEXT_EU_RECAP_TAXATION_MOMENT_INVOICE</option> </field> + <field name="export_format" type="list" default="full" label="VMEXT_EU_RECAP_EXPORT_FORMAT" description="VMEXT_EU_RECAP_EXPORT_FORMAT_DESC" > + <option value="full">VMEXT_EU_RECAP_EXPORT_FULL</option> + <option value="AT_xml">VMEXT_EU_RECAP_EXPORT_AT_XML</option> + <option value="DE_csv">VMEXT_EU_RECAP_EXPORT_DE_CSV</option> + </field> + <field name="vendor_vatid" type="text" scope="com_virtuemart" default="" label="VMEXT_EU_RECAP_VENDOR_VATID" description="VMEXT_EU_RECAP_VENDOR_VATID_DESC"/> <field name="taxnr" type="text" scope="com_virtuemart" default="" label="VMEXT_EU_RECAP_TAXNR" description="VMEXT_EU_RECAP_TAXNR_DESC"/> </fieldset> </fields> </vmconfig> + + + <!-- VM 2.0 support (params rather than fields): --> + <params addpath="/plugins/vmextended/eurecap/elements" /> + <params addpath="/administrator/components/com_virtuemart/elements" > + <param type="vmjpluginwarning" /> + <param name="order_status" type="vmorderstates" default="C,S" multiple="multiple" label="VMEXT_EU_RECAP_ORDERSTATUS" description="VMEXT_EU_RECAP_ORDERSTATUS_DESC "/> + <param name="shopper_groups" type="vmshoppergroups" multiple="multiple" label="VMEXT_EU_RECAP_SHOPPERGROUP" description="VMEXT_EU_RECAP_SHOPPERGROUP_DESC" /> + <param name="vatid_userfield" type="vmuserfields" label="VMEXT_EU_RECAP_VATID_USERFIELD" multiple="multiple" default="opc_vat" description="VMEXT_EU_RECAP_VATID_USERFIELD_DESC" /> + <param name="include_taxed_orders" type="radio" default="0" class="btn-group btn-group-yesno" label="VMEXT_EU_RECAP_INCLUDE_TAXED" description="VMEXT_EU_RECAP_INCLUDE_TAXED_DESC" > + <option value="1">JYES</option> + <option value="0">JNO</option> + </param> + <param name="include_free" type="radio" default="0" class="btn-group btn-group-yesno" label="VMEXT_EU_RECAP_INCLUDE_FREE" description="VMEXT_EU_RECAP_INCLUDE_FREE_DESC" > + <option value="1">JYES</option> + <option value="0">JNO</option> + </param> + <param name="frequency" type="list" default="1" label="VMEXT_EU_RECAP_FREQUENCY" description="VMEXT_EU_RECAP_FREQUENCY_DESC" > + <option value="1">VMEXT_EU_RECAP_FREQUENCY_MONTHLY</option> + <option value="3">VMEXT_EU_RECAP_FREQUENCY_QUARTERLY</option> + <option value="12">VMEXT_EU_RECAP_FREQUENCY_YEARLY</option> + </param> + <param name="countries" type="eucountries" multiple="true" scope="com_virtuemart" default="" label="VMEXT_EU_RECAP_COUNTRIES" description="VMEXT_EU_RECAP_COUNTRIES_DESC"/> + <param name="taxation_moment" type="list" default="placement" label="VMEXT_EU_RECAP_TAXATION_MOMENT" description="VMEXT_EU_RECAP_TAXATION_MOMENT_DESC" > + <option value="placement">VMEXT_EU_RECAP_TAXATION_MOMENT_PLACEMENT</option> +<!-- <option value="status">VMEXT_EU_RECAP_TAXATION_MOMENT_STATUSCHANGE</option> --> +<!-- <option value="payment">VMEXT_EU_RECAP_TAXATION_MOMENT_PAYMENT</option> --> + <option value="invoice">VMEXT_EU_RECAP_TAXATION_MOMENT_INVOICE</option> + </param> + <param name="export_format" type="list" default="full" label="VMEXT_EU_RECAP_EXPORT_FORMAT" description="VMEXT_EU_RECAP_EXPORT_FORMAT_DESC" > + <option value="full">VMEXT_EU_RECAP_EXPORT_FULL</option> + <option value="AT_xml">VMEXT_EU_RECAP_EXPORT_AT_XML</option> + <option value="DE_csv">VMEXT_EU_RECAP_EXPORT_DE_CSV</option> + </param> + <param name="vendor_vatid" type="text" scope="com_virtuemart" default="" label="VMEXT_EU_RECAP_VENDOR_VATID" description="VMEXT_EU_RECAP_VENDOR_VATID_DESC"/> + <param name="taxnr" type="text" scope="com_virtuemart" default="" label="VMEXT_EU_RECAP_TAXNR" description="VMEXT_EU_RECAP_TAXNR_DESC"/> + </params> + </extension> diff --git a/fields/eucountries.php b/fields/eucountries.php new file mode 100644 index 0000000..f884064 --- /dev/null +++ b/fields/eucountries.php @@ -0,0 +1,54 @@ +<?php +defined('_JEXEC') or die(); + +/** + * + * @package VirtueMart + * @subpackage Plugins - Elements + * @author Valérie Isaksen, Adapted by Reinhold Kainhofer for EU countries + * @link http://www.virtuemart.net + * @copyright Copyright (c) 2004 - 2011 VirtueMart Team. All rights reserved. + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php + * VirtueMart is free software. This version may have been modified pursuant + * to the GNU General Public License, and as distributed it includes or + * is derivative of works licensed under the GNU General Public License or + * other free or open source software licenses. + * @version $Id: $ + */ + +JFormHelper::loadFieldClass('list'); +jimport('joomla.form.formfield'); + +class JFormFieldEUCountries extends JFormFieldList { + + /** + * Element name + * @access protected + * @var string + */ + var $type = 'euCountries'; + + protected function getInput() { + $this->multiple=true; + return parent::getInput(); + } + protected function getOptions() { + $options = array(); + $this->multiple=true; + + $query = 'SELECT `virtuemart_country_id` AS value, `country_name` AS text FROM `#__virtuemart_countries` + WHERE `published` = 1 AND `country_2_code` IN ("AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR", "DE", "GR", "HU", "IE", "IT", "LV", "LT", "LU", "MT", "NL", "PL", "PT", "RO", "SI", "SK", "ES", "SE", "GB") ORDER BY `country_name` ASC '; + $db = JFactory::getDBO(); + $db->setQuery($query); + $values = $db->loadObjectList(); + foreach ($values as $v) { + $options[] = JHtml::_('select.option', $v->value, $v->text); + } + + //BAD $class = 'multiple="true" size="10"'; + // Merge any additional options in the XML definition. + $options = array_merge(parent::getOptions(), $options); + + return $options; + } +} \ No newline at end of file diff --git a/fields/vmuserfields.php b/fields/vmuserfields.php index 88d6e54..f80f5e7 100644 --- a/fields/vmuserfields.php +++ b/fields/vmuserfields.php @@ -24,7 +24,9 @@ class JFormFieldVmUserFields extends JFormFieldList { $userfields = $model->getUserfieldsList(); $options = array(); foreach ($userfields as $field) { - $options[] = JHtml::_ ('select.option', $field->name, JText::_($field->title) . " (" . $field->name . ")"); + if ($field->published) { + $options[] = JHtml::_ ('select.option', $field->name, JText::_($field->title) . " (" . $field->name . ")"); + } } return $options; } diff --git a/language/en-GB/en-GB.plg_vmextended_eurecap.ini b/language/en-GB/en-GB.plg_vmextended_eurecap.ini index 50df327..3f94fa8 100644 --- a/language/en-GB/en-GB.plg_vmextended_eurecap.ini +++ b/language/en-GB/en-GB.plg_vmextended_eurecap.ini @@ -1,38 +1,51 @@ -VMEXT_EU_RECAP="EU Recapitulative Statement" -VMEXT_EU_RECAP_DESC="A plugin to automatically create EU Recapitulative Statements for untaxed cross-border EU sales to businesses with a valid EU VAT ID." +VMEXT_EU_RECAP="EU Sales Report" +VMEXT_EU_RECAP_DESC="A plugin to automatically create EU Sales Reports (a.k.a. EU Recapitulative Statements) for untaxed cross-border EU sales to businesses with a valid EU VAT ID." COM_VIRTUEMART_REPORT_MOD="Reports" -COM_VIRTUEMART_EU_RECAP="EU Recapitulative Statement" +COM_VIRTUEMART_EU_RECAP="EU Sales Report" ; COM_VIRTUEMART_EU_RECAP="EU Recapitulative Statement" -VMEXT_EU_RECAP_SETTINGS_TITLE="Configuration of the EU Recapitulative Statement" -VMEXT_EU_RECAP_VIEW_TITLE_DATE="EU Recapitulative Statement for the period from %s to %s" +VMEXT_EU_RECAP_SETTINGS_TITLE="Configuration of the EU Sales Report" +VMEXT_EU_RECAP_VIEW_TITLE_DATE="EU Sales Report for the period from %s to %s" VMEXT_EU_RECAP_LIST_MONTH="Period" VMEXT_EU_RECAP_LIST_YEAR="Year" -VMEXT_EU_RECAP_RECHECK_EUVATID="(Re-)Check EU VAT IDs" +; VMEXT_EU_RECAP_RECHECK_EUVATID="(Re-)Check EU VAT IDs" VMEXT_EU_RECAP_SETTINGS="Settings" +COM_VIRTUEMART_EU_RECAP_SETTINGS="Settings" +COM_VIRTUEMART_EU_RECAP_LIST="Report" VMEXT_EU_RECAP_EXPORT="Export" +VMEXT_EU_RECAP_EXPORT_FULL="Full dataset (country-independend), CSV format" +VMEXT_EU_RECAP_EXPORT_AT_XML="Austrian XML format" +VMEXT_EU_RECAP_EXPORT_DE_CSV="German CSV format" + +VMEXT_EU_RECAP_EXPORT_TB_FULL="Export (full, csv)" +VMEXT_EU_RECAP_EXPORT_TB_AT_XML="Export (AT, xml)" +VMEXT_EU_RECAP_EXPORT_TB_DE_CSV="Export (DE, csv)" VMEXT_EU_RECAP_FORM_NOTFOUND="Configuration form not available" VMEXT_EU_RECAP_ORDERPROPERTIES="Order Properties for Inclusion in the Report" VMEXT_EU_RECAP_ORDERSTATUS="Order Status" -VMEXT_EU_RECAP_ORDERSTATUS_DESC="Only orders with one of the selected statuses will be included in the recapitulative statement. If none are selected, all orders will possibly be included, depending on the other required properties." +VMEXT_EU_RECAP_ORDERSTATUS_DESC="Only orders with one of the selected statuses will be included in the EU Sales Report. If none are selected, all orders will possibly be included, depending on the other required properties." VMEXT_EU_RECAP_SHOPPERGROUP="Shopper Groups" -VMEXT_EU_RECAP_SHOPPERGROUP_DESC="Only orders by users of the selected shopper groups will be included in the recapitulative statement. If none are selected, all orders will possibly be included, depending on the other required properties." +VMEXT_EU_RECAP_SHOPPERGROUP_DESC="Only orders by users of the selected shopper groups will be included in the EU Sales Report. If none are selected, all orders will possibly be included, depending on the other required properties." VMEXT_EU_RECAP_VATID_USERFIELD="The user field(s) that holds the EU VAT ID of the customer." VMEXT_EU_RECAP_VATID_USERFIELD_DESC="An order can only be included if the customer is a EU-based business with a valid EU VAT ID. This number will usually be stored in a configurable user field. If the plugin to handle EU VAT IDs has changed in the past, select all user fields that were used." -VMEXT_EU_RECAP_UNTAXED="Include only untaxed sales." -VMEXT_EU_RECAP_UNTAXED_DESC="Select whether all orders are included or only orders where no tax (neither at product-level nor at order-level) was charged." -VMEXT_EU_RECAP_REPORTSETTINGS="General Settings for the Recapitulative Report" +VMEXT_EU_RECAP_INCLUDE_TAXED="Include sales that were taxed" +VMEXT_EU_RECAP_INCLUDE_TAXED_DESC="Select whether to also include sales where VAT was charged, even though a (possibly invalid) VATID was given." +VMEXT_EU_RECAP_INCLUDE_FREE="Include free orders" +VMEXT_EU_RECAP_INCLUDE_FREE_DESC="Select whether all orders are included or only orders with an order total larger than 0. In the first case, all free orders will also be included." +VMEXT_EU_RECAP_EXPORT_FORMAT="Export format" +VMEXT_EU_RECAP_EXPORT_FORMAT_DESC="Select the format for the data export. Several countries have their own custom format that needs to be used to import the report into the official tax rporting system." +VMEXT_EU_RECAP_REPORTSETTINGS="General Settings for the EU Sales Report" VMEXT_EU_RECAP_FREQUENCY="Frequency of the Report" -VMEXT_EU_RECAP_FREQUENCY_DESC="Select how often you are required to submit a recapitulative report. Only time periods for the selected frequency will be offered in the report page." +VMEXT_EU_RECAP_FREQUENCY_DESC="Select how often you are required to submit a EU Sales Report. Only time periods for the selected frequency will be offered in the report page." VMEXT_EU_RECAP_FREQUENCY_MONTHLY="Monthly" VMEXT_EU_RECAP_FREQUENCY_QUARTERLY="Quarterly" VMEXT_EU_RECAP_FREQUENCY_YEARLY="Yearly" VMEXT_EU_RECAP_COUNTRIES="Countries" -VMEXT_EU_RECAP_COUNTRIES_DESC="Only orders by customers from of the selected countries will be included in the recapitulative statement. Typically, all EU countries except your home country should be selected." +VMEXT_EU_RECAP_COUNTRIES_DESC="Only orders by customers from of the selected countries will be included in the EU Sales Report. Typically, all EU countries except your home country should be selected." VMEXT_EU_RECAP_TAXATION_MOMENT="Moment of taxation" VMEXT_EU_RECAP_TAXATION_MOMENT_DESC="Select the point in time when a new order actually causes a tax liability." VMEXT_EU_RECAP_TAXATION_MOMENT_PLACEMENT="When the order is initially created in VirtueMart." @@ -40,8 +53,11 @@ VMEXT_EU_RECAP_TAXATION_MOMENT_STATUSCHANGE="When the order is first changed to VMEXT_EU_RECAP_TAXATION_MOMENT_PAYMENT="When payment is made." VMEXT_EU_RECAP_TAXATION_MOMENT_INVOICE="When the invoice is created." -VMEXT_EU_RECAP_TAXNR="Your tax number" -VMEXT_EU_RECAP_TAXNR_DESC="When exporting to xml or csv, some countries require the tax number of the vendor to be included in the file. If this is the case for your tax authority, please enter your tax number here so the generated files can be automatically processed by your tax authority." +VMEXT_EU_RECAP_VENDOR_VATID="Your EU VAT ID number" +VMEXT_EU_RECAP_VENDOR_VATID_DESC="When exporting to xml or csv, some countries require the EU VAT ID number of the vendor to be included in the file. If this is the case for your tax authority, please enter your tax number here so the generated files can be automatically processed by your tax authority." +VMEXT_EU_RECAP_TAXNR="Your local tax number" +VMEXT_EU_RECAP_TAXNR_DESC="When exporting to xml or csv, some countries require the local tax number of the vendor to be included in the file. If this is the case for your tax authority, please enter your tax number here so the generated files can be automatically processed by your tax authority." + VMEXT_EU_RECAP_VATID="EU VAT ID" VMEXT_EU_RECAP_COUNTRYCODE="Billing Country" @@ -49,4 +65,6 @@ VMEXT_EU_RECAP_COMPANY="Company Name" VMEXT_EU_RECAP_NAME="Person" VMEXT_EU_RECAP_ORDERS="Orders" VMEXT_EU_RECAP_ORDERTOTALS="Total revenue" -VMEXT_EU_RECAP_ORDERTAXES="Taxes" \ No newline at end of file +VMEXT_EU_RECAP_ORDERTAXES="Taxes" + +VMEXT_EU_RECAP_CANCELLED="EU Sales Report settings cancelled." \ No newline at end of file diff --git a/language/en-GB/en-GB.plg_vmextended_eurecap.sys.ini b/language/en-GB/en-GB.plg_vmextended_eurecap.sys.ini index 50df327..3f94fa8 100644 --- a/language/en-GB/en-GB.plg_vmextended_eurecap.sys.ini +++ b/language/en-GB/en-GB.plg_vmextended_eurecap.sys.ini @@ -1,38 +1,51 @@ -VMEXT_EU_RECAP="EU Recapitulative Statement" -VMEXT_EU_RECAP_DESC="A plugin to automatically create EU Recapitulative Statements for untaxed cross-border EU sales to businesses with a valid EU VAT ID." +VMEXT_EU_RECAP="EU Sales Report" +VMEXT_EU_RECAP_DESC="A plugin to automatically create EU Sales Reports (a.k.a. EU Recapitulative Statements) for untaxed cross-border EU sales to businesses with a valid EU VAT ID." COM_VIRTUEMART_REPORT_MOD="Reports" -COM_VIRTUEMART_EU_RECAP="EU Recapitulative Statement" +COM_VIRTUEMART_EU_RECAP="EU Sales Report" ; COM_VIRTUEMART_EU_RECAP="EU Recapitulative Statement" -VMEXT_EU_RECAP_SETTINGS_TITLE="Configuration of the EU Recapitulative Statement" -VMEXT_EU_RECAP_VIEW_TITLE_DATE="EU Recapitulative Statement for the period from %s to %s" +VMEXT_EU_RECAP_SETTINGS_TITLE="Configuration of the EU Sales Report" +VMEXT_EU_RECAP_VIEW_TITLE_DATE="EU Sales Report for the period from %s to %s" VMEXT_EU_RECAP_LIST_MONTH="Period" VMEXT_EU_RECAP_LIST_YEAR="Year" -VMEXT_EU_RECAP_RECHECK_EUVATID="(Re-)Check EU VAT IDs" +; VMEXT_EU_RECAP_RECHECK_EUVATID="(Re-)Check EU VAT IDs" VMEXT_EU_RECAP_SETTINGS="Settings" +COM_VIRTUEMART_EU_RECAP_SETTINGS="Settings" +COM_VIRTUEMART_EU_RECAP_LIST="Report" VMEXT_EU_RECAP_EXPORT="Export" +VMEXT_EU_RECAP_EXPORT_FULL="Full dataset (country-independend), CSV format" +VMEXT_EU_RECAP_EXPORT_AT_XML="Austrian XML format" +VMEXT_EU_RECAP_EXPORT_DE_CSV="German CSV format" + +VMEXT_EU_RECAP_EXPORT_TB_FULL="Export (full, csv)" +VMEXT_EU_RECAP_EXPORT_TB_AT_XML="Export (AT, xml)" +VMEXT_EU_RECAP_EXPORT_TB_DE_CSV="Export (DE, csv)" VMEXT_EU_RECAP_FORM_NOTFOUND="Configuration form not available" VMEXT_EU_RECAP_ORDERPROPERTIES="Order Properties for Inclusion in the Report" VMEXT_EU_RECAP_ORDERSTATUS="Order Status" -VMEXT_EU_RECAP_ORDERSTATUS_DESC="Only orders with one of the selected statuses will be included in the recapitulative statement. If none are selected, all orders will possibly be included, depending on the other required properties." +VMEXT_EU_RECAP_ORDERSTATUS_DESC="Only orders with one of the selected statuses will be included in the EU Sales Report. If none are selected, all orders will possibly be included, depending on the other required properties." VMEXT_EU_RECAP_SHOPPERGROUP="Shopper Groups" -VMEXT_EU_RECAP_SHOPPERGROUP_DESC="Only orders by users of the selected shopper groups will be included in the recapitulative statement. If none are selected, all orders will possibly be included, depending on the other required properties." +VMEXT_EU_RECAP_SHOPPERGROUP_DESC="Only orders by users of the selected shopper groups will be included in the EU Sales Report. If none are selected, all orders will possibly be included, depending on the other required properties." VMEXT_EU_RECAP_VATID_USERFIELD="The user field(s) that holds the EU VAT ID of the customer." VMEXT_EU_RECAP_VATID_USERFIELD_DESC="An order can only be included if the customer is a EU-based business with a valid EU VAT ID. This number will usually be stored in a configurable user field. If the plugin to handle EU VAT IDs has changed in the past, select all user fields that were used." -VMEXT_EU_RECAP_UNTAXED="Include only untaxed sales." -VMEXT_EU_RECAP_UNTAXED_DESC="Select whether all orders are included or only orders where no tax (neither at product-level nor at order-level) was charged." -VMEXT_EU_RECAP_REPORTSETTINGS="General Settings for the Recapitulative Report" +VMEXT_EU_RECAP_INCLUDE_TAXED="Include sales that were taxed" +VMEXT_EU_RECAP_INCLUDE_TAXED_DESC="Select whether to also include sales where VAT was charged, even though a (possibly invalid) VATID was given." +VMEXT_EU_RECAP_INCLUDE_FREE="Include free orders" +VMEXT_EU_RECAP_INCLUDE_FREE_DESC="Select whether all orders are included or only orders with an order total larger than 0. In the first case, all free orders will also be included." +VMEXT_EU_RECAP_EXPORT_FORMAT="Export format" +VMEXT_EU_RECAP_EXPORT_FORMAT_DESC="Select the format for the data export. Several countries have their own custom format that needs to be used to import the report into the official tax rporting system." +VMEXT_EU_RECAP_REPORTSETTINGS="General Settings for the EU Sales Report" VMEXT_EU_RECAP_FREQUENCY="Frequency of the Report" -VMEXT_EU_RECAP_FREQUENCY_DESC="Select how often you are required to submit a recapitulative report. Only time periods for the selected frequency will be offered in the report page." +VMEXT_EU_RECAP_FREQUENCY_DESC="Select how often you are required to submit a EU Sales Report. Only time periods for the selected frequency will be offered in the report page." VMEXT_EU_RECAP_FREQUENCY_MONTHLY="Monthly" VMEXT_EU_RECAP_FREQUENCY_QUARTERLY="Quarterly" VMEXT_EU_RECAP_FREQUENCY_YEARLY="Yearly" VMEXT_EU_RECAP_COUNTRIES="Countries" -VMEXT_EU_RECAP_COUNTRIES_DESC="Only orders by customers from of the selected countries will be included in the recapitulative statement. Typically, all EU countries except your home country should be selected." +VMEXT_EU_RECAP_COUNTRIES_DESC="Only orders by customers from of the selected countries will be included in the EU Sales Report. Typically, all EU countries except your home country should be selected." VMEXT_EU_RECAP_TAXATION_MOMENT="Moment of taxation" VMEXT_EU_RECAP_TAXATION_MOMENT_DESC="Select the point in time when a new order actually causes a tax liability." VMEXT_EU_RECAP_TAXATION_MOMENT_PLACEMENT="When the order is initially created in VirtueMart." @@ -40,8 +53,11 @@ VMEXT_EU_RECAP_TAXATION_MOMENT_STATUSCHANGE="When the order is first changed to VMEXT_EU_RECAP_TAXATION_MOMENT_PAYMENT="When payment is made." VMEXT_EU_RECAP_TAXATION_MOMENT_INVOICE="When the invoice is created." -VMEXT_EU_RECAP_TAXNR="Your tax number" -VMEXT_EU_RECAP_TAXNR_DESC="When exporting to xml or csv, some countries require the tax number of the vendor to be included in the file. If this is the case for your tax authority, please enter your tax number here so the generated files can be automatically processed by your tax authority." +VMEXT_EU_RECAP_VENDOR_VATID="Your EU VAT ID number" +VMEXT_EU_RECAP_VENDOR_VATID_DESC="When exporting to xml or csv, some countries require the EU VAT ID number of the vendor to be included in the file. If this is the case for your tax authority, please enter your tax number here so the generated files can be automatically processed by your tax authority." +VMEXT_EU_RECAP_TAXNR="Your local tax number" +VMEXT_EU_RECAP_TAXNR_DESC="When exporting to xml or csv, some countries require the local tax number of the vendor to be included in the file. If this is the case for your tax authority, please enter your tax number here so the generated files can be automatically processed by your tax authority." + VMEXT_EU_RECAP_VATID="EU VAT ID" VMEXT_EU_RECAP_COUNTRYCODE="Billing Country" @@ -49,4 +65,6 @@ VMEXT_EU_RECAP_COMPANY="Company Name" VMEXT_EU_RECAP_NAME="Person" VMEXT_EU_RECAP_ORDERS="Orders" VMEXT_EU_RECAP_ORDERTOTALS="Total revenue" -VMEXT_EU_RECAP_ORDERTAXES="Taxes" \ No newline at end of file +VMEXT_EU_RECAP_ORDERTAXES="Taxes" + +VMEXT_EU_RECAP_CANCELLED="EU Sales Report settings cancelled." \ No newline at end of file diff --git a/models/eurecap.php b/models/eurecap.php index 0d6343b..81db64d 100644 --- a/models/eurecap.php +++ b/models/eurecap.php @@ -30,6 +30,8 @@ class VirtuemartModelEuRecap extends VmModel { public $from_date = ''; public $until_date = ''; + public $from = ''; + public $until = ''; protected $frequency = 3; function __construct () { @@ -70,12 +72,12 @@ class VirtuemartModelEuRecap extends VmModel { */ function setPeriod ($year, $month, $frequency) { $this->setFrequency($frequency); - - $fromtime = mktime(0,0,0, $month, 1, $year); -// JFactory::getApplication()->enqueueMessage("<pre>year: $year, month: $month, frequency: $frequency, fromtime: ".print_r($fromtime,1)."</pre>", 'message'); - $this->from_date = date ('Y-m-d', $fromtime); - $this->until_date = date ('Y-m-d', strtotime('+'.$this->frequency.' months -1 day', $fromtime)); + $this->from = mktime(0,0,0, $month, 1, $year); + $this->until = strtotime('+'.$this->frequency.' months -1 day', $this->from); + + $this->from_date = date ('Y-m-d', $this->from); + $this->until_date = date ('Y-m-d', $this->until); $config = JFactory::getConfig(); $siteOffset = $config->get('offset'); @@ -95,13 +97,13 @@ class VirtuemartModelEuRecap extends VmModel { } $settingsModel = VmModel::getModel("eurecap_config"); $settings = $settingsModel->getConfig(); - + $freq = $settings['frequency']; $month = floor( (date("m")-1)/$freq)*$freq+1; $year = vRequest::getVar ('year', date("Y")); $month = vRequest::getVar ('month', $month); $this->setPeriod($year, $month, $freq); - + $mainTable = "`#__virtuemart_orders` AS `o`"; $joins = array(); $joins[] = "LEFT JOIN `#__virtuemart_order_userinfos` AS `ui` ON (`o`.`virtuemart_order_id` = `ui`.`virtuemart_order_id` )"; @@ -109,7 +111,7 @@ class VirtuemartModelEuRecap extends VmModel { $vatfields = array(); foreach ($settings['vatid_userfield'] as $vatfield) { - $vatfields[] = "`$vatfield`"; + $vatfields[] = "`ui`.`$vatfield`"; } $vatfields[] = "''"; // <= To make sure we have at least one entry! $select = array(); @@ -122,68 +124,71 @@ class VirtuemartModelEuRecap extends VmModel { $select[] = "`first_name`"; $select[] = "`last_name`"; $select[] = "`ctr`.`country_2_code` AS `countrycode`"; - + $select[] = 'SUM( `order_total` ) AS `sum_order_total`'; - - $select[] = 'SUM( `order_billTax` ) AS `sum_order_tax`'; - - + + $select[] = 'SUM( `order_tax` ) AS `sum_order_tax`'; + + $where = array(); $where[] = $vatidexpr . " <> ''"; - if ($settings['only_untaxed']>0) { + if ($settings['include_free']==0) { + $where[] = "`o`.`order_total` > 0"; + } + if ($settings['include_taxed_orders']==0) { $where[] = "`o`.`order_tax` = 0"; } $where[] = '`ui`.`address_type` = "BT"'; - + // Order status: $ostatus = array(); foreach ($settings['order_status'] as $s) { - $ostatus[] = '`order_status` = "' . $s . '"'; + $ostatus[] = '`o`.`order_status` = "' . $s . '"'; } if ($ostatus) { $where[] = "(" . join(" OR ", $ostatus) . ")"; } - + // Countries: - if ($settings['countries']) { + if (!empty($settings['countries'])) { $where[] = '`ui`.`virtuemart_country_id` IN (' . join(",", $settings['countries']) . ')'; } - + // Shopper group: if ($settings['shopper_groups']) { -// $where[] = +// $where[] = } - + // TODO: Handle vendorId if (VmConfig::get ('multix', 'none') != 'none') { if ($vendorId != 0) { $where[] = '`o`.`virtuemart_vendor_id` = "' . $vendorId . '" '; } } - + // TODO: Handle creation date! switch($settings['taxation_moment']) { case 'status': // TODO: Handle first status change: $tax_moment = "`o`.`created_on`"; -JFactory::getApplication()->enqueueMessage("Taxation moment 'First status change to any of the selected statuses' not yet implemented", 'message'); + JFactory::getApplication()->enqueueMessage("Taxation moment 'First status change to any of the selected statuses' not yet implemented", 'warning'); break; case 'payment': // TODO: Handle payment: $tax_moment = "`o`.`created_on`"; -// 'o.virtuemart_paymentmethod_id' -JFactory::getApplication()->enqueueMessage("Taxation moment 'When payment is made' not yet implemented", 'message'); + // 'o.virtuemart_paymentmethod_id' + JFactory::getApplication()->enqueueMessage("Taxation moment 'When payment is made' not yet implemented", 'warning'); break; case 'invoice': $tax_moment = "`inv`.`created_on`"; - $joins[] = "LEFT JOIN `#__virtuemart_invoices` AS `inv` ON ( `o`.`virtuemart_order_id` = `inv.virtuemart_order_id` )"; + $joins[] = "LEFT JOIN `#__virtuemart_invoices` AS `inv` ON ( `o`.`virtuemart_order_id` = `inv`.`virtuemart_order_id` )"; break; case 'placement': default: $tax_moment = "`o`.`created_on`"; break; } - + $where[] = ' DATE( ' . $tax_moment . ' ) BETWEEN "' . $this->from_date . '" AND "' . $this->until_date . '" '; $selectString = join(', ', $select) . ' FROM ' . $mainTable; @@ -191,188 +196,11 @@ JFactory::getApplication()->enqueueMessage("Taxation moment 'When payment is mad $whereString = 'WHERE ' . join(' AND ', $where); $groupBy = "GROUP BY `vatid`"; $orderBy = $this->_getOrdering (); - - return $this->exeSortSearchListQuery (1, $selectString, $joinedTables, $whereString, $groupBy, $orderBy); - } - - function getRevenue ($cache = 0) { -return null; - $user = JFactory::getUser(); - if($user->authorise('core.admin', 'com_virtuemart') or $user->authorise('core.manager', 'com_virtuemart')){ - $vendorId = vRequest::getInt('virtuemart_vendor_id'); - } else { - $vendorId = VmConfig::isSuperVendor(); - } - - $orderstates = vRequest::getVar ('order_status_code', array('C','S')); - $intervals = vRequest::getCmd ('intervals', 'day'); - $filterorders = vRequest::getvar ('filter_order', 'intervals'); - $orderdir = (vRequest::getCmd ('filter_order_Dir', NULL) == 'desc') ? 'desc' : ''; - $virtuemart_product_id = vRequest::getInt ('virtuemart_product_id', FALSE); - - if($cache){ - $c = JFactory::getCache ('com_virtuemart_revenue'); - $c->setCaching (1); - $c->setLifeTime($cache); - return $c->call (array('VirtuemartModelReport', 'getRevenueDiag'),$vendorId,$orderstates,$intervals,$filterorders,$orderdir,$virtuemart_product_id,$this->from_date,$this->until_date); - } else { - return $this->getRevenueSortListOrderQuery ($vendorId,$orderstates,$intervals,$filterorders,$orderdir,$virtuemart_product_id); - } - - } - - function getRevenueSortListOrderQuery ($vendorId,$orderstates,$intervals,$filterorders,$orderdir,$virtuemart_product_id) { -return null; - $selectFields = array(); - $mainTable = ''; - $joinTables = array(); - $joinedTables = ''; - $where = array(); - - // group always by intervals (day,week, ... or ID) and set grouping and defaut ordering - switch ($intervals) { - - case 'day': - $this->intervals = 'DATE( o.created_on )'; - break; - case 'week': - $this->intervals = 'WEEK( o.created_on )'; - break; - case 'month': - $this->intervals = 'MONTH( o.created_on )'; - break; - case 'year': - $this->intervals = 'YEAR( o.created_on )'; - break; - default: - // invidual grouping - $this->intervals = 'o.created_on'; - break; - } -// if(!empty($this->intervals)){ -// $orderBy = $this->_getOrdering('o.`created_on`'); -// } - $selectFields['intervals'] = $this->intervals . ' AS intervals, CAST( o.`created_on` AS DATE ) AS created_on'; - - if($intervals=='product_s'){ - - $selectFields[] = '`order_item_name`'; - $selectFields[] = '`virtuemart_product_id`'; - $groupBy = 'GROUP BY `virtuemart_product_id` '; - } else { - $groupBy = 'GROUP BY intervals '; - } - - //$selectFields[] = 'COUNT(virtuemart_order_id) as number_of_orders'; - //with tax => brutto - //$selectFields[] = 'SUM(product_subtotal_with_tax) as order_total'; - - //without tax => netto - //$selectFields[] = 'SUM(product_item_price) as order_subtotal'; - $selectFields[] = 'SUM(product_discountedPriceWithoutTax * product_quantity) as order_subtotal_netto'; - $selectFields[] = 'SUM(product_subtotal_with_tax) as order_subtotal_brutto'; - - $this->dates = ' DATE( o.created_on ) BETWEEN "' . $this->from_date . '" AND "' . $this->until_date . '" '; - - $statusList = array(); - // Filter by status - if ($orderstates) { - $query = 'SELECT `order_status_code` - FROM `#__virtuemart_orderstates` - WHERE published=1 '; - $db = JFactory::getDBO(); - $db->setQuery ($query); - $list = $db->loadColumn (); - foreach ($orderstates as $val) { - if (in_array ($val, $list)) { - $statusList[] = '`i`.`order_status` = "' . $val . '"'; - } - } - if ($statusList) { - $where[] = '(' . implode (' OR ', $statusList) . ')'; - } - } - //getRevenue - // select wich table to order sum ordered - - switch ($filterorders) { - - case 'o.virtuemart_order_id': - $orderBy = ' ORDER BY count_order_id ' . $orderdir; - $groupBy = 'GROUP BY intervals '; - break; - case 'product_quantity' : - // GROUP BY product_quantity, intervals - // ORDER BY `product_quantity` ASC - // TODO grouping and ordering - $orderBy = ' ORDER BY product_quantity ' . $orderdir; - $groupBy = 'GROUP BY intervals '; - - //$selectFields['intervals'] = $this->intervals.' AS intervals, i.`created_on` '; - break; - case 'o.order_subtotal' : - $orderBy = ' ORDER BY order_subtotal'; - break; - //getOrderItemsSumGrouped($this->intervals , $filterorders); - break; - default: - // invidual grouping - $orderBy = $this->_getOrdering (); - vmdebug ('default case', $orderBy); - //$this->intervals= '`o`.`created_on`'; -// $orderBy = ' ORDER BY '.$filterorders.' '.$orderdir; - break; - } - - $selectFields[] = 'COUNT(DISTINCT o.virtuemart_order_id) as count_order_id'; - $selectFields[] = 'SUM(product_quantity) as product_quantity'; - - $mainTable = '`#__virtuemart_order_items` as i'; - - $joinTables['orders'] = ' LEFT JOIN `#__virtuemart_orders` as o ON o.virtuemart_order_id=i.virtuemart_order_id '; - - if (count ($selectFields) > 0) { - - $select = implode (', ', $selectFields) . ' FROM ' . $mainTable; - //$selectFindRows = 'SELECT COUNT(*) FROM '.$mainTable; - if (count ($joinTables) > 0) { - foreach ($joinTables as $table) { - $joinedTables .= $table; - } - } - } - else { - vmError ('No select fields given in getRevenueSortListOrderQuery', 'No select fields given'); - return FALSE; - } - - - if ($virtuemart_product_id) { - $where[] = 'i.virtuemart_product_id = "' . $virtuemart_product_id . '" '; - } - - if (VmConfig::get ('multix', 'none') != 'none') { - if ($vendorId != 0) { - $where[] = 'i.virtuemart_vendor_id = "' . $vendorId . '" '; - } - } - if (count ($where) > 0) { - $this->whereItem = ' WHERE ' . implode (' AND ', $where) . ' AND '; - } - else { - $this->whereItem = ' WHERE '; - } - -// $this->whereItem; - /* WHERE differences with orders and items from orders are only date periods and ordering */ - $whereString = $this->whereItem . $this->dates; - vmdebug('getRevenueSortListOrderQuery '.$select,$whereString); - return $this->exeSortSearchListQuery (1, $select, $joinedTables, $whereString, $groupBy, $orderBy); + return $this->exeSortSearchListQuery (1, $selectString, $joinedTables, $whereString, $groupBy, $orderBy); } - public function renderMonthSelectList ($frequency, $selected='') { $vals = array(); switch ($frequency) { @@ -390,14 +218,14 @@ return null; $vals[11] = vmText::_('November'); $vals[12] = vmText::_('December'); break; - + case 3: // quartely $vals[1] = vmText::_('First Quarter'); $vals[3] = vmText::_('Second Quarter'); $vals[6] = vmText::_('Third Quarter'); $vals[9] = vmText::_('Forth Quarter'); break; - + case 12: // yearly $vals[1] = vmText::_('Year'); break; diff --git a/models/eurecap_config.php b/models/eurecap_config.php index 62a392c..427c044 100644 --- a/models/eurecap_config.php +++ b/models/eurecap_config.php @@ -36,8 +36,58 @@ class VirtuemartModelEuRecap_config extends VmModel { parent::__construct (); } + /** + * Process the passed settings array and load all missing values from the xml file + */ + function loadDefaults($settings_str) { + $path = VMPATH_ROOT .DS. 'plugins' .DS. 'vmextended' . DS . 'eurecap' . DS . 'eurecap' . '.xml'; + if(!defined('VM_VERSION') or VM_VERSION < 3){ + if (!class_exists('vmParameters')) + require(JPATH_VM_ADMINISTRATOR . DS . 'helpers' . DS . 'parameterparser.php'); + $parameters = new vmParameters($settings_str, 'eurecap', 'plugin', 'vmextended'); +// $parameters->loadString($settings_str); + + $settings = array(); + // The getParams returns the rendered representation, but also the value, including the default given in the XML. + // AFAICS, this is the only way to correctly handle the default, apart from manually parsing the xml file. + foreach ($parameters->getParams() as $param) { + if (!empty($param[5])) + $settings[$param[5]] = $param[4]; + } + + } else { + // VM 3.x uses JForm + $defaults = array(); + + $registry = new JRegistry; + $registry->loadString($settings_str); + // Take the settings and load all missing values from the defaults in the xml file: + $settings = $registry->toArray(); + + $form = vmPlugin::loadConfigForm($path, 'eurecap'); + $form->bind(array('settings'=>$settings)); + $fieldSets = $form->getFieldsets(); + foreach ($fieldSets as $name => $fieldSet) { + foreach ($form->getFieldset($name) as $field) { + $fieldname = (string)$field->fieldname; + $settings[$fieldname] = $field->value; + } + } + } + // Manually convert all default values for list params to lists (not handled automatically) + if (!is_array($settings['order_status'])) + $settings['order_status'] = array_filter(explode(',', $settings['order_status'])); + if (!is_array($settings['vatid_userfield'])) + $settings['vatid_userfield'] = array_filter(explode(',', $settings['vatid_userfield'])); + if (!is_array($settings['countries'])) + $settings['countries'] = array_filter(explode(',', $settings['countries'])); + + return $settings; + } + function getConfig() { if (!$this->_settings) { + $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('custom_data')) @@ -48,19 +98,23 @@ class VirtuemartModelEuRecap_config extends VmModel { $db->setQuery($query); $config_str = $db->loadResult(); - $registry = new JRegistry; - $registry->loadString($config_str); - $this->_settings = $registry->toArray(); + // Take the settings and load all missing values from the defaults in the xml file: + $this->_settings = $this->loadDefaults($config_str); } return $this->_settings; } function saveConfig($data) { - $params = array_merge ($this->getConfig(), $data['settings']); - $this->_settings = $params; + $settings = array(); + if (isset($data['params'])) + $settings = $data['params']; + if (isset($data['settings'])) + $settings = $data['settings']; + $settings = array_merge ($this->getConfig(), $settings); + $this->_settings = $settings; $registry = new JRegistry(); - $registry->loadArray($params); + $registry->loadArray($settings); $db = JFactory::getDbo(); $query = $db->getQuery(true) diff --git a/releases/plg_vmextended_eurecap_v0.1.zip b/releases/plg_vmextended_eurecap_v0.1.zip new file mode 100644 index 0000000000000000000000000000000000000000..7e4d929a142a575b91713fd855419915ec6142f3 GIT binary patch literal 34512 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 JVBo0&@c@Zcd%gew literal 0 HcmV?d00001 diff --git a/views/eurecap/tmpl/default.php b/views/eurecap/tmpl/default.php index 8ef017b..b9e5845 100644 --- a/views/eurecap/tmpl/default.php +++ b/views/eurecap/tmpl/default.php @@ -20,6 +20,11 @@ if( !defined( '_JEXEC' ) ) die( 'Direct Access to '.basename(__FILE__).' is not AdminUIHelper::startAdminArea($this); JHtml::_('behavior.framework', true); +if (!class_exists('CurrencyDisplay')) + require(VMPATH_ADMIN . DS . 'helpers' . DS . 'currencydisplay.php'); +$myCurrencyDisplay = CurrencyDisplay::getInstance(); + + ?> <form action="index.php" method="post" name="adminForm" id="adminForm"> <div id="header"> @@ -29,9 +34,9 @@ JHtml::_('behavior.framework', true); <tr> <td align="left" width="100%"> <?php if ($this->frequency<12) { - echo vmText::_('VMEXT_EU_RECAP_LIST_MONTH') . $this->lists['month_list']; + echo vmText::_('VMEXT_EU_RECAP_LIST_MONTH') . $this->period_lists['month_list']; } ?> - <?php echo vmText::_('VMEXT_EU_RECAP_LIST_YEAR') . $this->lists['year_list']; + <?php echo vmText::_('VMEXT_EU_RECAP_LIST_YEAR') . $this->period_lists['year_list']; if(VmConfig::get('multix','none')!='none'){ $vendorId = vRequest::getInt('virtuemart_vendor_id',1); @@ -44,7 +49,7 @@ JHtml::_('behavior.framework', true); </table> </div> <div id="resultscounter"> - <?php echo $this->pagination->getResultsCounter();?> + <?php if ($this->pagination) echo $this->pagination->getResultsCounter();?> </div> </div> @@ -85,7 +90,13 @@ JHtml::_('behavior.framework', true); <td align="center"> <?php echo $r['vatid']; ?> </td> - <td align="center"> + <?php + $vatidcc = substr(trim($r['vatid']), 0, 2); + if ($vatidcc=="EL") $vatidcc="GR"; + if ($vatidcc=="UK") $vatidcc="GB"; + $countrymatch = ($vatidcc == $r['countrycode']); + ?> + <td align="center" <?php if (!$countrymatch) { echo "style=\"background: #FFBFBF;\""; }; ?>> <?php echo $r['countrycode'];?> </td> <td align="left"> @@ -117,10 +128,10 @@ JHtml::_('behavior.framework', true); ?> </td> <td align="right"> - <?php echo $r['sum_order_total'];?> + <?php echo $myCurrencyDisplay->priceDisplay($r['sum_order_total']); ?> </td> <td align="right"> - <?php echo $r['sum_order_tax'];?> + <?php echo $myCurrencyDisplay->priceDisplay($r['sum_order_tax']); ?> </td> </tr> <?php @@ -131,7 +142,7 @@ JHtml::_('behavior.framework', true); <tfoot> <tr> <td colspan="10"> - <?php echo $this->pagination->getListFooter(); ?> + <?php if ($this->pagination) echo $this->pagination->getListFooter(); ?> </td> </tr> </tfoot> diff --git a/views/eurecap/tmpl/export.php b/views/eurecap/tmpl/export.php new file mode 100644 index 0000000..3ccd555 --- /dev/null +++ b/views/eurecap/tmpl/export.php @@ -0,0 +1,20 @@ +<?php +if( !defined( '_JEXEC' ) ) die( 'Direct Access to '.basename(__FILE__).' is not allowed.' ); + +/** +* +* @version $Id$ +* @package VirtueMart +* @subpackage Report +* @copyright Copyright (C) Open Tools, Reinhold Kainhofer +* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php +* VirtueMart is free software. This version may have been modified pursuant +* to the GNU General Public License, and as distributed it includes or +* is derivative of works licensed under the GNU General Public License or +* other free or open source software licenses. +* +* http://www.open-tools.net/ +*/ + +// Load the sub-template as selected in the export format setting: +echo $this->loadTemplate($this->export_format); diff --git a/views/eurecap/tmpl/export_at_xml.php b/views/eurecap/tmpl/export_at_xml.php new file mode 100644 index 0000000..2d51b62 --- /dev/null +++ b/views/eurecap/tmpl/export_at_xml.php @@ -0,0 +1,65 @@ +<?php +if( !defined( '_JEXEC' ) ) die( 'Direct Access to '.basename(__FILE__).' is not allowed.' ); + +/** +* +* @version $Id$ +* @package VirtueMart +* @subpackage Report +* @copyright Copyright (C) Open Tools, Reinhold Kainhofer +* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php +* VirtueMart is free software. This version may have been modified pursuant +* to the GNU General Public License, and as distributed it includes or +* is derivative of works licensed under the GNU General Public License or +* other free or open source software licenses. +* +* http://www.open-tools.net/ +*/ + +$from_month=date("Y-m", $this->from); +$until_month=date("Y-m", $this->until); +$fastnr = preg_replace('/[^0-9]/', '', $this->settings['taxnr']); + +header("Content-Type: text/xml"); +header("Content-Disposition: attachment; filename=\"EU_Zusammenfassende_Meldung_${from_month}_${until_month}.AT.xml\""); + +?><?xml version="1.0" encoding="iso-8859-1"?> +<!-- Zusammenfassende Meldung - Stand: 10.01.2013 --> +<ERKLAERUNGS_UEBERMITTLUNG> + <INFO_DATEN> + <ART_IDENTIFIKATIONSBEGRIFF>FASTNR</ART_IDENTIFIKATIONSBEGRIFF> + <IDENTIFIKATIONSBEGRIFF><?php echo $fastnr; ?></IDENTIFIKATIONSBEGRIFF> + <PAKET_NR><?php echo rand(1, 999999999);?></PAKET_NR> + <DATUM_ERSTELLUNG type="datum"><?php echo date("Y-m-d"); ?></DATUM_ERSTELLUNG> + <UHRZEIT_ERSTELLUNG type="uhrzeit"><?php echo date("H:i:s"); ?></UHRZEIT_ERSTELLUNG> + <ANZAHL_ERKLAERUNGEN>1</ANZAHL_ERKLAERUNGEN> + </INFO_DATEN> + <ERKLAERUNG art="U13"> + <SATZNR><?php echo rand(1, 999999999);?></SATZNR> + <ALLGEMEINE_DATEN> + <ANBRINGEN>U13</ANBRINGEN> + <ZRVON type="jahrmonat"><?php echo $from_month; ?></ZRVON> + <ZRBIS type="jahrmonat"><?php echo $until_month; ?></ZRBIS> + <FASTNR><?php echo $fastnr; ?></FASTNR> + <KUNDENINFO></KUNDENINFO> + </ALLGEMEINE_DATEN> +<?php +foreach ($this->report as $r) { + $vatid = preg_replace('/[^A-Z0-9]/', '', strtoupper(trim($r['vatid']))); +?> + <ZM> + <UID_MS><?php echo $vatid; ?></UID_MS> + <SUM_BGL type="kz"><?php echo $r['sum_order_total']; ?></SUM_BGL> +<?php // <DREIECK>0</DREIECK> ?> + <SOLEI>1</SOLEI> + </ZM> +<?php +} +?> +<?php /* + <GESAMTRUECKZIEHUNG> + <GESAMTRUECK>J</GESAMTRUECK> + </GESAMTRUECKZIEHUNG> +*/ ?> + </ERKLAERUNG> +</ERKLAERUNGS_UEBERMITTLUNG> diff --git a/views/eurecap/tmpl/export_de_csv.php b/views/eurecap/tmpl/export_de_csv.php new file mode 100644 index 0000000..5c35ee7 --- /dev/null +++ b/views/eurecap/tmpl/export_de_csv.php @@ -0,0 +1,33 @@ +<?php +if( !defined( '_JEXEC' ) ) die( 'Direct Access to '.basename(__FILE__).' is not allowed.' ); + +/** +* +* @version $Id$ +* @package VirtueMart +* @subpackage Report +* @copyright Copyright (C) Open Tools, Reinhold Kainhofer +* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php +* VirtueMart is free software. This version may have been modified pursuant +* to the GNU General Public License, and as distributed it includes or +* is derivative of works licensed under the GNU General Public License or +* other free or open source software licenses. +* +* http://www.open-tools.net/ +*/ + +$from_month=date("Y-m", $this->from); +$until_month=date("Y-m", $this->until); + + +header("Content-Type: text/csv"); +header("Content-Disposition: attachment; filename=\"EU_Zusammenfassende_Meldung_${from_month}_${until_month}.DE.csv\""); +?>Laenderkennzeichen,USt-IdNr.,Betrag(EUR),Art der Leistung +<?php +foreach ($this->report as $r) { + $vatid = preg_replace('/[^A-Z0-9]/', '', strtoupper(trim($r['vatid']))); + $vatidcc = substr($vatid, 0, 2); + // TODO: Check whether $vatidcc is a valid country code. If not, use $r['countrycode'] and interpret $vatid as the rest + echo $vatidcc . ',' . substr($vatid, 2) . ',' . $r['sum_order_total'] . ',S +'; +} diff --git a/views/eurecap/tmpl/export_full.php b/views/eurecap/tmpl/export_full.php new file mode 100644 index 0000000..dc7e209 --- /dev/null +++ b/views/eurecap/tmpl/export_full.php @@ -0,0 +1,33 @@ +<?php +if( !defined( '_JEXEC' ) ) die( 'Direct Access to '.basename(__FILE__).' is not allowed.' ); + +/** +* +* @version $Id$ +* @package VirtueMart +* @subpackage Report +* @copyright Copyright (C) Open Tools, Reinhold Kainhofer +* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php +* VirtueMart is free software. This version may have been modified pursuant +* to the GNU General Public License, and as distributed it includes or +* is derivative of works licensed under the GNU General Public License or +* other free or open source software licenses. +* +* http://www.open-tools.net/ +*/ + +$from_month=date("Y-m", $this->from); +$until_month=date("Y-m", $this->until); + +header("Content-Type: text/csv"); +header("Content-Disposition: attachment; filename=\"EU_Recap_Statement_${from_month}_${until_month}.csv\""); + +$keys = array_keys($this->report[0]); +if ($this->report) { + echo '"' . join('","', $keys) . '" +'; +} +foreach ($this->report as $r) { + echo '"' . join('","', array_values($r)) . '" +'; +} diff --git a/views/eurecap/tmpl/settings.php b/views/eurecap/tmpl/settings.php index 6018053..66974cc 100644 --- a/views/eurecap/tmpl/settings.php +++ b/views/eurecap/tmpl/settings.php @@ -23,11 +23,16 @@ JHtml::_('behavior.framework', true); ?> <form name="adminForm" id="adminForm" method="post" action=""> + <?php AdminUIHelper::imitateTabs('start'); ?> <fieldset> <legend><?php echo vmText::_('VMEXT_EU_RECAP_SETTINGS_TITLE'); ?></legend> -<?php if ($this->config_form) { +<?php if (isset($this->config_form)) { + // VM 3 uses JForm and the formrenderer.php $form = $this->config_form; - include(VMPATH_ADMIN.DS.'fields'.DS.'formrenderer.php'); + include (VMPATH_ADMIN.DS.'fields'.DS.'formrenderer.php'); +} elseif ($this->config_params) { + // VM 2 uses vmParameters + echo $this->config_params->render(); } else { ?> <p><?php echo vmText::_('VMEXT_EU_RECAP_FORM_NOTFOUND'); ?></p> <?php @@ -35,6 +40,7 @@ JHtml::_('behavior.framework', true); ?> </fieldset> <?php echo $this->addStandardHiddenToForm(); ?> + <?php AdminUIHelper::imitateTabs('end'); ?> </form> diff --git a/views/eurecap/view.html.php b/views/eurecap/view.html.php index bb5373e..09d6ac1 100644 --- a/views/eurecap/view.html.php +++ b/views/eurecap/view.html.php @@ -48,8 +48,6 @@ class VirtuemartViewEuRecap extends VmViewAdmin { if (!class_exists('VmHTML')) require(VMPATH_ADMIN . DS . 'helpers' . DS . 'html.php'); - if (!class_exists('CurrencyDisplay')) - require(VMPATH_ADMIN . DS . 'helpers' . DS . 'currencydisplay.php'); $model = VmModel::getModel(); $this->addStandardDefaultViewLists($model); @@ -57,16 +55,21 @@ class VirtuemartViewEuRecap extends VmViewAdmin { vRequest::setvar('task',''); $this->SetViewTitle('EU_RECAP'); - $myCurrencyDisplay = CurrencyDisplay::getInstance(); - $layoutName = vRequest::getCmd('layout', 'default'); if ($layoutName == 'settings') { JToolBarHelper::divider(); JToolBarHelper::save(); JToolBarHelper::apply(); JToolBarHelper::cancel(); - $form = $this->renderPluginSettings(); - $this->assignRef('config_form', $form); + if(!defined('VM_VERSION') or VM_VERSION < 3){ + // VM 2.x uses vmParameters + $form = $this->renderPluginSettingsVM2(); + $this->assignRef('config_params', $form); + } else { + // VM 3.x uses JForm + $form = $this->renderPluginSettingsVM3(); + $this->assignRef('config_form', $form); + } // TODO } else { $this->setupListView($model); @@ -75,50 +78,81 @@ class VirtuemartViewEuRecap extends VmViewAdmin { parent::display($tpl); } - function setupListView ($model) { - JToolBarHelper::custom('settings', 'options', 'options','VMEXT_EU_RECAP_SETTINGS', false); - JToolBarHelper::custom('check_eu_vatid', 'recheck', 'recheck', 'VMEXT_EU_RECAP_RECHECK_EUVATID', true); - JToolBarHelper::custom('export', 'export', 'export', 'VMEXT_EU_RECAP_EXPORT', false); + /** + * Copied from VmView(Admin). Only change is the inserted $name in JText::_('COM_VIRTUEMART_'. $name . '_' . $task) + */ + function SetViewTitle($name ='', $msg ='',$icon ='') { + + $view = JRequest::getWord('view', JRequest::getWord('controller')); + if ($name == '') + $name = strtoupper($view); + if ($icon == '') + $icon = strtolower($view); + if (!$task = JRequest::getWord('task')) + $task = 'list'; + + if (!empty($msg)) { + $msg = ' <span style="color: #666666; font-size: large;">' . $msg . '</span>'; + } + $viewText = JText::_('COM_VIRTUEMART_' . strtoupper($name)); + + $taskName = ' <small><small>[ ' . JText::_('COM_VIRTUEMART_'. $name . '_' . $task) . ' ]</small></small>'; + + JToolBarHelper::title($viewText . ' ' . $taskName . $msg, 'head vm_' . $icon . '_48'); + $this->assignRef('viewName',$viewText); //was $viewName? + $app = JFactory::getApplication(); + $doc = JFactory::getDocument(); + $doc->setTitle($app->getCfg('sitename'). ' - ' .JText::_('JADMINISTRATION').' - '.strip_tags($msg)); + } + + function setupListView ($model) { $month = vRequest::getVar('month', '1'); $year = vRequest::getVar('year', date("Y")); - + $settingsModel = VmModel::getModel("eurecap_config"); $settings = $settingsModel->getConfig(); + + $bar = JToolbar::getInstance('toolbar'); + JToolBarHelper::custom('settings', 'options', 'options','VMEXT_EU_RECAP_SETTINGS', false); +// JToolBarHelper::custom('check_eu_vatid', 'recheck', 'recheck', 'VMEXT_EU_RECAP_RECHECK_EUVATID', true); +// $bar->appendButton('Link', 'export', 'VMEXT_EU_RECAP_FULLEXPORT', 'index.php?option=com_virtuemart&view=eurecap&task=export&format=raw&layout=export_full&month='.$month.'&year='.$year); + $bar->appendButton('Link', 'export', 'VMEXT_EU_RECAP_EXPORT_TB_' . $settings['export_format'], 'index.php?option=com_virtuemart&view=eurecap&task=export&format=raw&layout=export&month='.$month.'&year='.$year); + + $this->frequency = $settings['frequency']; - $this->lists['month_list'] = $model->renderMonthSelectList($this->frequency, $month); - $this->lists['year_list'] = $model->renderYearSelectList($year); + $period_list = array(); + $period_list['month_list'] = $model->renderMonthSelectList($this->frequency, $month); + $period_list['year_list'] = $model->renderYearSelectList($year); + $this->assignRef('period_lists', $period_list); $this->assignRef('from_period', $model->from_date); $this->assignRef('until_period', $model->until_date); - $myCurrencyDisplay = CurrencyDisplay::getInstance(); - + $this->assignRef('from', $model->from); + $this->assignRef('until', $model->until); + $this->addStandardDefaultViewLists($model); $euIntracommunityRevenue = $model->getEuRecap(); - foreach ($euIntracommunityRevenue as &$r) { - $r['sum_order_total'] = $myCurrencyDisplay->priceDisplay($r['sum_order_total']); - $r['sum_order_tax'] = $myCurrencyDisplay->priceDisplay($r['sum_order_tax']); - } $this->assignRef('report', $euIntracommunityRevenue); + + $this->assignRef('export_format', $settings['export_format']); $pagination = $model->getPagination(); $this->assignRef('pagination', $pagination); - + } - function renderPluginSettings(){ + function renderPluginSettingsVM3(){ if (!class_exists('vmExtendedPlugin')) require(VMPATH_PLUGINLIBS . DS . 'vmextendedplugin.php'); JForm::addFieldPath(VMPATH_ADMIN . DS . 'fields'); $path = VMPATH_ROOT .DS. 'plugins' .DS. 'vmextended' . DS . $this->getName() . DS . $this->getName() . '.xml'; - // Get the payment XML. - $formFile = vRequest::filterPath( $path ); - if (file_exists($formFile)){ + if (file_exists($path)){ - $form = vmPlugin::loadConfigForm($formFile, $this->getName()); + $form = vmPlugin::loadConfigForm($path, $this->getName()); // load config $eurecapSettingsModel = VmModel::getModel("eurecap_config"); @@ -126,14 +160,22 @@ class VirtuemartViewEuRecap extends VmViewAdmin { $form->bind(array('settings'=>$settings)); } else { $form = false; - vmdebug('renderUserfieldPlugin could not find xml for ' . $this->getName() . ' at ' . $path); + vmdebug('renderPluginSettingsVM3: Unable to find xml for ' . $this->getName() . ' at ' . $path); } - //vmdebug('renderUserfieldPlugin ',$this->userField->form); return $form; } + function renderPluginSettingsVM2(){ + if (!class_exists('vmParameters')) + require(JPATH_VM_ADMINISTRATOR . DS . 'helpers' . DS . 'parameterparser.php'); + // load config + $eurecapSettingsModel = VmModel::getModel("eurecap_config"); + $settings = $eurecapSettingsModel->getConfig(); + $parameters = new vmParameters($settings, 'eurecap', 'plugin', 'vmextended'); + return $parameters; + } } diff --git a/views/eurecap/view.raw.php b/views/eurecap/view.raw.php new file mode 100644 index 0000000..e6d9de8 --- /dev/null +++ b/views/eurecap/view.raw.php @@ -0,0 +1,73 @@ +<?php +if( !defined( '_JEXEC' ) ) die('Restricted access'); + +/** +* +* @version $Id$ +* @package VirtueMart +* @subpackage EU Recapitulative Statement +* @copyright Copyright (C) Open Tools, Reinhold Kainhofer +* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php +* VirtueMart is free software. This version may have been modified pursuant +* to the GNU General Public License, and as distributed it includes or +* is derivative of works licensed under the GNU General Public License or +* other free or open source software licenses. +*/ + +if(!defined('VM_VERSION') or VM_VERSION < 3){ + // VM2 has class VmView instead of VmViewAdmin: + if(!class_exists('VmView')) require(VMPATH_ADMIN.DS.'helpers'.DS.'vmview.php'); + class VmViewAdmin extends VmView {} +} else { + if(!class_exists('VmViewAdmin')) require(VMPATH_ADMIN.DS.'helpers'.DS.'vmviewadmin.php'); +} + +/** + * EU Recapitulative Statement View class + * + * @package VirtueMart + * @subpackage Report + * @author Open Tools + */ +class VirtuemartViewEuRecap extends VmViewAdmin { + function __construct(){ + parent::__construct(); + // Add the proper view pathes... + $this->_addPath('template', JPATH_PLUGINS.DS . 'vmextended' . DS . 'eurecap' . DS . 'views' . DS . $this->getName() . DS . 'tmpl'); + } + + /** + * Render the view + */ + function display($tpl = null){ + $model = VmModel::getModel(); + +// $layoutName = vRequest::getCmd('layout', 'export'); + + $month = vRequest::getVar('month', '1'); + $year = vRequest::getVar('year', date("Y")); + + $settingsModel = VmModel::getModel("eurecap_config"); + $settings = $settingsModel->getConfig(); + + $this->frequency = $settings['frequency']; + + $this->assignRef('from_period', $model->from_date); + $this->assignRef('until_period', $model->until_date); + + $this->assignRef('from', $model->from); + $this->assignRef('until', $model->until); + + $euIntracommunityRevenue = $model->getEuRecap(); + $this->assignRef('report', $euIntracommunityRevenue); + + $this->assignRef('settings', $settings); + + $this->assignRef('export_format', $settings['export_format']); + parent::display($tpl); + } + + + + +} -- GitLab