diff --git a/CHANGELOG.md b/CHANGELOG.md index 0568272b..b4f62303 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,16 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Added + +- Support for Postponed VAT Accounting for goods +- Suppport for VAT Reverse Charge on services +- Allow a VAT status to be inactive (not available when adding new customer or supplier ledger accounts) + ### Fixed - Cashbook payments not saved when entering invalid combination of values with tax rate 'None' -- Cashbook payments no longer allow payments to inactive companies or people +- Cashbook no longer allows payments to inactive companies or people - Output VAT transactions for the selected period ## [1.25.1] 2020-08-12 diff --git a/lib/classes/standard/MTD.php b/lib/classes/standard/MTD.php index ba5c9ed1..00e5c2a0 100644 --- a/lib/classes/standard/MTD.php +++ b/lib/classes/standard/MTD.php @@ -59,7 +59,6 @@ function __construct($client_fp_info='', $config_key='mtd-vat') { ]); $config = Config::Instance(); - $device_uuid = $oauth_config['clientuuid']; $current = timezone_open('Europe/London'); $utcTime = new \DateTime('now', new \DateTimeZone('UTC')); $offsetInSecs = $current->getOffset($utcTime); @@ -108,7 +107,14 @@ function __construct($client_fp_info='', $config_key='mtd-vat') { // Gov-Client-Browser-Plugins // Modern browsers return an empty list - //$browser_plugins = get_object_vars($this->client_fp_info->plugins); + $browser_plugins = get_object_vars($this->client_fp_info->plugins); + if (count($browser_plugins) > 0) { + $plugin_names = []; + foreach ($browser_plugins as $plugin) { + $plugin_names[] = rawurlencode($plugin->name); + } + $this->fraud_protection_headers['Gov-Client-Browser-Plugins'] = implode(',', $plugin_names); + } // Gov-Client-Browser-JS-User-Agent $this->fraud_protection_headers['Gov-Client-Browser-JS-User-Agent'] = $this->client_fp_info->userAgent; @@ -116,10 +122,6 @@ function __construct($client_fp_info='', $config_key='mtd-vat') { // Gov-Client-Browser-Do-Not-Track $this->fraud_protection_headers['Gov-Client-Browser-Do-Not-Track'] = $this->client_fp_info->dnt; - - // Gov-Client-Multi-Factor - //N/a - // Gov-Vendor-Public-IP // The public IP address of the servers the originating device sent their requests to. // Public networks only diff --git a/modules/public_pages/erp/invoicing/purchase_invoicing/models/PInvoice.php b/modules/public_pages/erp/invoicing/purchase_invoicing/models/PInvoice.php index 3e671045..acf59c0b 100644 --- a/modules/public_pages/erp/invoicing/purchase_invoicing/models/PInvoice.php +++ b/modules/public_pages/erp/invoicing/purchase_invoicing/models/PInvoice.php @@ -376,6 +376,8 @@ protected function makeGLTransactionLines($gl_data, &$gl_transactions, &$errors if ($tax_status->load($this->tax_status_id)) { $eu_acquisition = ($tax_status->eu_tax == 't'); + $vat_postponed = ($tax_status->postponed_vat_accounting == 't'); + $reverse_charge = ($tax_status->reverse_charge == 't'); } else { @@ -383,7 +385,7 @@ protected function makeGLTransactionLines($gl_data, &$gl_transactions, &$errors return FALSE; } - if ($eu_acquisition) + if ($eu_acquisition || $vat_postponed || $reverse_charge) { $eu_gl_data = $gl_data; $eu_gl_data['value'] = 0; @@ -469,7 +471,7 @@ protected function makeGLTransactionLines($gl_data, &$gl_transactions, &$errors } // Calculate tax value if EU acquisition - if (($eu_acquisition) && ($line->tax_rate_id)) + if (($eu_acquisition || $vat_postponed || $reverse_charge) && ($line->tax_rate_id)) { if (isset($tax_rates[$line->tax_rate_id]) && ($tax_rates[$line->tax_rate_id] > 0)) { @@ -508,6 +510,38 @@ protected function makeGLTransactionLines($gl_data, &$gl_transactions, &$errors $gl_transactions[] = $eu_tax_element; } } + + if ($vat_postponed) + { + + $eu_tax_elements = GLTransaction::makeTax($eu_gl_data, 'PVA', $newerrors); + + foreach ($eu_tax_elements as $eu_tax_element) + { + if ($eu_tax_element === false) + { + $errors+=$newerrors; + return false; + } + $gl_transactions[] = $eu_tax_element; + } + } + + if ($reverse_charge) + { + + $eu_tax_elements = GLTransaction::makeTax($eu_gl_data, 'RC', $newerrors); + + foreach ($eu_tax_elements as $eu_tax_element) + { + if ($eu_tax_element === false) + { + $errors+=$newerrors; + return false; + } + $gl_transactions[] = $eu_tax_element; + } + } if (count($errors)>0) { diff --git a/modules/public_pages/erp/ledger/general_ledger/models/GLParams.php b/modules/public_pages/erp/ledger/general_ledger/models/GLParams.php index dbb22304..261c64a5 100755 --- a/modules/public_pages/erp/ledger/general_ledger/models/GLParams.php +++ b/modules/public_pages/erp/ledger/general_ledger/models/GLParams.php @@ -41,6 +41,8 @@ class GLParams extends DataObject { public $vat_control_account = "VAT Control Account"; public $vat_payee_company = "VAT Payee"; public $vat_eu_acquisitions = "VAT EU Acquisitions"; + public $vat_postponed = "VAT Postponed Account"; + public $vat_reverse_charge = "VAT Reverse Charge Account"; public $intrastat_net_mass = "UoM for Intrastat Net Mass"; // Array containing 'soft' fk references @@ -80,6 +82,8 @@ function __construct($tablename = 'gl_params') ,$this->vat_eu_acquisitions=>$this->vat_eu_acquisitions ,$this->vat_payee_company=>$this->vat_payee_company ,$this->intrastat_net_mass=>$this->intrastat_net_mass + ,$this->vat_postponed => $this->vat_postponed + ,$this->vat_reverse_charge => $this->vat_reverse_charge ) ); @@ -101,6 +105,8 @@ function __construct($tablename = 'gl_params') $this->hasMany('GLAccount', $this->vat_output, 'account', $control_account); $this->hasMany('GLAccount', $this->vat_control_account, 'account', $control_account); $this->hasMany('GLAccount', $this->vat_eu_acquisitions, 'account', $control_account); + $this->hasMany('GLAccount', $this->vat_postponed, 'account', $control_account); + $this->hasMany('GLAccount', $this->vat_reverse_charge, 'account', $control_account); $this->hasMany('Company', $this->vat_payee_company, 'name'); $this->hasMany('GLAccount', $this->product_account, 'account'); $this->hasMany('GLCentre', $this->product_centre, 'cost_centre'); @@ -343,6 +349,14 @@ public function eu_acquisitions () { return $this->getParam($this->vat_eu_acquisitions); } + public function vat_postponed_account () { + return $this->getParam($this->vat_postponed); + } + + public function vat_reverse_charge_account () { + return $this->getParam($this->vat_reverse_charge); + } + public function vat_payee_company () { return $this->getParam($this->vat_payee_company); } diff --git a/modules/public_pages/erp/ledger/general_ledger/models/GLPeriod.php b/modules/public_pages/erp/ledger/general_ledger/models/GLPeriod.php index 05386c18..4eab1e68 100755 --- a/modules/public_pages/erp/ledger/general_ledger/models/GLPeriod.php +++ b/modules/public_pages/erp/ledger/general_ledger/models/GLPeriod.php @@ -268,6 +268,22 @@ public static function getFuturePeriods($period, $year) return $glperiod->getAll($cc); } + + /** + * Return a list of open GL Periods + * + * @param boolean $ledger true = all open periods, false = periods open for VAT + * @return array options array + */ + public function getOpenPeriods($ledger=true) { + $cc = new ConstraintChain(); + if ($ledger === true) { + $cc->add(new Constraint('closed', 'IS', false)); + } else { + $cc->add(new Constraint('tax_period_closed', 'IS', false)); + } + return $this->getAll($cc); + } public static function getIdsForTaxPeriod($tax_period, $year) { diff --git a/modules/public_pages/erp/ledger/general_ledger/models/GLTransaction.php b/modules/public_pages/erp/ledger/general_ledger/models/GLTransaction.php index b64f9267..682f1ada 100755 --- a/modules/public_pages/erp/ledger/general_ledger/models/GLTransaction.php +++ b/modules/public_pages/erp/ledger/general_ledger/models/GLTransaction.php @@ -1012,6 +1012,55 @@ public static function makeEuTax($transaction, &$errors = array()) return $eu_tax_elements; } + /** + * Handle tax for PVA and Reverse Charge + * + * @param $transaction + * @param $type 'RC' = Reverse Charge, 'PVA' = Postponed VAT Accounting + * @param array $errors + * @return void + */ + public static function makeTax($transaction, $tax_type='none', &$errors = array()) + { + $mult = self::$multipliers[$transaction['source']][$transaction['type']]; + $eu_tax_element = $transaction; + + $glparams = DataObjectFactory::Factory('GLParams'); + + switch ($tax_type) { + case 'PVA': + $eu_tax_element['glaccount_id'] = $glparams->vat_postponed_account(); + break; + case 'RC': + $eu_tax_element['glaccount_id'] = $glparams->vat_reverse_charge_account(); + break; + default: + $errors[] = "Tax type not specified"; + } + + if ($eu_tax_element['glaccount_id'] === false) { + $errors[] = "Account Code for tax '{$tax_type}' not found"; + } + + $eu_tax_element['glcentre_id'] = $glparams->balance_sheet_cost_centre(); + + if ($eu_tax_element['glcentre_id'] === false) { + $errors[] = 'Balance Sheet Cost Centre Code not found'; + } + + $eu_tax_element['value'] = bcmul($mult, $eu_tax_element['value']); + $eu_tax_element['twinvalue'] = bcmul($mult, $eu_tax_element['twinvalue']); + + $eu_tax_elements = array(); + $eu_tax_elements[] = GLTransaction::Factory($eu_tax_element, $errors); + + $eu_tax_element['value'] *= - 1; + $eu_tax_element['twinvalue'] *= - 1; + $eu_tax_elements[] = GLTransaction::Factory($eu_tax_element, $errors); + + return $eu_tax_elements; + } + public static function makeCBLine($transaction, &$errors = array()) { $mult = self::$multipliers[$transaction['source']][$transaction['type']]; diff --git a/modules/public_pages/erp/ledger/ledger_setup/models/TaxStatus.php b/modules/public_pages/erp/ledger/ledger_setup/models/TaxStatus.php index c476582a..918b1fee 100755 --- a/modules/public_pages/erp/ledger/ledger_setup/models/TaxStatus.php +++ b/modules/public_pages/erp/ledger/ledger_setup/models/TaxStatus.php @@ -9,7 +9,12 @@ class TaxStatus extends DataObject { - protected $version='$Revision: 1.6 $'; + protected $defaultDisplayFields = ['description', + 'active', + 'apply_tax', + 'eu_tax', + 'postponed_vat_accounting' => 'PVA', + 'reverse_charge']; function __construct($tablename='tax_statuses') { @@ -21,6 +26,34 @@ function __construct($tablename='tax_statuses') } + /** + * Return an array of tax status options valid for an SLCustomer + * + * @return array Status options + */ + public function get_customer_tax_statuses() + { + $cc = new ConstraintChain(); + $cc->add(new Constraint('postponed_vat_accounting', 'IS', false)); + $cc->add(new Constraint('reverse_charge', 'IS', false)); + $cc->add(new Constraint('active', 'IS', true)); + $statuses = $this->getAll($cc); + return $statuses; + } + + /** + * Return an array of tax status options + * + * @return array Status options + */ + public function get_active_tax_statuses() + { + $cc = new ConstraintChain(); + $cc->add(new Constraint('active', 'IS', true)); + $statuses = $this->getAll($cc); + return $statuses; + } + } // End of TaxStatus diff --git a/modules/public_pages/erp/ledger/ledger_setup/templates/taxstatuss/new.tpl b/modules/public_pages/erp/ledger/ledger_setup/templates/taxstatuss/new.tpl index d1e5961b..3c6f6de0 100755 --- a/modules/public_pages/erp/ledger/ledger_setup/templates/taxstatuss/new.tpl +++ b/modules/public_pages/erp/ledger/ledger_setup/templates/taxstatuss/new.tpl @@ -10,8 +10,11 @@ {input type='hidden' attribute='id' } {include file='elements/auditfields.tpl' } {input type='text' attribute='description' class="compulsory" } + {input type='checkbox' attribute='active' class="compulsory" } {input type='checkbox' attribute='apply_tax' class="compulsory" } {input type='checkbox' label='EU Tax' attribute='eu_tax' class="compulsory" } + {input type='checkbox' label='PVA' attribute='postponed_vat_accounting' class="compulsory" } + {input type='checkbox' attribute='reverse_charge' class="compulsory" } {/with} {submit} {/form} diff --git a/modules/public_pages/erp/ledger/purchase_ledger/controllers/PlsuppliersController.php b/modules/public_pages/erp/ledger/purchase_ledger/controllers/PlsuppliersController.php index 1c226ddf..be45b073 100644 --- a/modules/public_pages/erp/ledger/purchase_ledger/controllers/PlsuppliersController.php +++ b/modules/public_pages/erp/ledger/purchase_ledger/controllers/PlsuppliersController.php @@ -112,6 +112,11 @@ public function _new() $supplier->cb_account_id = $cbaccount->{$cbaccount->idField}; } + $taxstatus = new TaxStatus(); + $taxstatuses = $taxstatus->get_active_tax_statuses(); + + $this->view->set('f_taxstatuses', $taxstatuses); + $this->view->set('bank_account', $supplier->cb_account_id); $this->view->set('bank_accounts', $this->getbankAccounts($supplier->id)); diff --git a/modules/public_pages/erp/ledger/purchase_ledger/templates/plsuppliers/new.tpl b/modules/public_pages/erp/ledger/purchase_ledger/templates/plsuppliers/new.tpl index 9f9b6f5b..e1950d1a 100755 --- a/modules/public_pages/erp/ledger/purchase_ledger/templates/plsuppliers/new.tpl +++ b/modules/public_pages/erp/ledger/purchase_ledger/templates/plsuppliers/new.tpl @@ -36,10 +36,12 @@ {select attribute='payment_term_id' } {select attribute='payment_type_id' } {if $action=='new' } - {select attribute='tax_status_id' } + {select attribute='tax_status_id' options=$f_taxstatuses} {else} {if $transaction_count == 0} - {select attribute='tax_status_id' } + {select attribute='tax_status_id' options=$f_taxstatuses} + {else} + {view_data attribute='tax_status_id'} {/if} {/if} {select attribute='delivery_term_id' } diff --git a/modules/public_pages/erp/ledger/sales_ledger/controllers/SlcustomersController.php b/modules/public_pages/erp/ledger/sales_ledger/controllers/SlcustomersController.php index 58db0377..d8e2ac9d 100755 --- a/modules/public_pages/erp/ledger/sales_ledger/controllers/SlcustomersController.php +++ b/modules/public_pages/erp/ledger/sales_ledger/controllers/SlcustomersController.php @@ -60,7 +60,7 @@ public function __construct($module = null, $action = null) $system_prefs = SystemPreferences::instance(); $module_prefs = $system_prefs->getModulePreferences('ledger_setup'); if (! isset($module_prefs['sales-invoice-report-type'])) { - $module_prefs['sales-invoice-report-type'] = ''; + $module_prefs['sales-invoice-report-type'] = ''; } $this->module_prefs = $module_prefs; $this->view->set('module_prefs', $module_prefs); @@ -589,8 +589,8 @@ public function make_inactive() { $flash->addWarning($e->getMessage()); if ($e->getCode == 1) { - $db->FailTrans(); - } + $db->FailTrans(); + } } @@ -1227,12 +1227,17 @@ public function _new() } if (is_null($customer->cb_account_id)) - { - $cbaccount = CBAccount::getPrimaryAccount(); - $customer->cb_account_id = $cbaccount->{$cbaccount->idField}; - } + { + $cbaccount = CBAccount::getPrimaryAccount(); + $customer->cb_account_id = $cbaccount->{$cbaccount->idField}; + } + + $taxstatus = new TaxStatus(); + $taxstatuses = $taxstatus->get_customer_tax_statuses(); + + $this->view->set('f_taxstatuses', $taxstatuses); - $this->view->set('bank_account', $customer->cb_account_id); + $this->view->set('bank_account', $customer->cb_account_id); $this->view->set('bank_accounts', $this->getbankAccounts($customer->id)); $this->view->set('billing_addresses', $customer->getInvoiceAddresses()); @@ -1544,11 +1549,11 @@ public function getbankAccounts($_customer_id = '') $currency_id = $customer->currency_id; // If the user has selected a new currency - // the id will be in the request, - // so set the selected currency id. - if(isset($this->_data['ajax'])) { - $currency_id = $this->_data['id']; - } + // the id will be in the request, + // so set the selected currency id. + if(isset($this->_data['ajax'])) { + $currency_id = $this->_data['id']; + } $cc = new ConstraintChain(); diff --git a/modules/public_pages/erp/ledger/sales_ledger/templates/slcustomers/new.tpl b/modules/public_pages/erp/ledger/sales_ledger/templates/slcustomers/new.tpl index 274a73ee..11e6ddab 100755 --- a/modules/public_pages/erp/ledger/sales_ledger/templates/slcustomers/new.tpl +++ b/modules/public_pages/erp/ledger/sales_ledger/templates/slcustomers/new.tpl @@ -36,10 +36,12 @@ {select attribute='payment_type_id' } {select attribute='so_price_type_id' } {if $action=='new' } - {select attribute='tax_status_id' } + {select attribute='tax_status_id' options=$f_taxstatuses} {else} {if $transaction_count == 0} - {select attribute='tax_status_id' } + {select attribute='tax_status_id' options=$f_taxstatuses} + {else} + {view_data attribute='tax_status_id'} {/if} {/if} {select attribute='delivery_term_id' } diff --git a/modules/public_pages/erp/ledger/vat/controllers/VatController.php b/modules/public_pages/erp/ledger/vat/controllers/VatController.php index 8fd5d6f5..26c36e7f 100644 --- a/modules/public_pages/erp/ledger/vat/controllers/VatController.php +++ b/modules/public_pages/erp/ledger/vat/controllers/VatController.php @@ -24,7 +24,7 @@ public function __construct($module = null, $action = null) $this->uses($this->_templateobject); - $this->titles=array(4=>'Inputs', 6=>'Outputs', 8=>'EU Sales', 9=>'EU Purchases'); + $this->titles=array(4=>'Inputs', 6=>'Outputs', 8=>'EU Sales', 9=>'EU Purchases', 98=>'Postponed VAT Purchases',99=>'Reverse Charge Purchases'); } @@ -86,9 +86,9 @@ public function index() public function enter_journal() { - $flash=Flash::Instance(); + //$flash=Flash::Instance(); - $errors=array(); + //$errors=array(); if (!$this->checkParams('vat_type')) { @@ -111,6 +111,11 @@ public function enter_journal() $gl_account->load($account_id); $this->view->set('gl_centres',$gl_account->getCentres()); + + $period = DataObjectFactory::Factory('GLPeriod'); + $current = $period->getPeriod(un_fix_date(fix_date(date(DATE_FORMAT)))); + $this->view->set('periods', $period->getOpenPeriods(false)); + $this->view->set('current_period', $current['id']); $this->view->set('vat_type', $this->_data['vat_type']); $this->view->set('vat', DataObjectFactory::Factory('Vat')); @@ -131,9 +136,12 @@ public function savejournal () $data = $this->_data['Vat']; - if ($data['value']['net']<=0 || $data['value']['vat']<=0) + if ($data['value']['vat']<=0) { - $errors[]='Net and Vat values must be greater than zero'; + $errors[]='Vat Value must be greater than zero'; + } + elseif ($data['value']['net']<=0) { + $flash->addWarning('Transaction saved with Net Value of zero'); } else { @@ -299,6 +307,14 @@ public function viewEuSalesList () return $this->viewEUTransactions($collection, $sh); } + + /** + * View the list of transactions of each type for this VAT return + * + * Calls private function printTransactions() for printing + * + * Exporting to csv is handled here not in the print section + */ public function viewTransactions() { $errors = array(); @@ -326,29 +342,48 @@ public function viewTransactions() $year = $this->search->getValue('year'); if (isset($this->_data['box'])) + // switch the model/collection based on the 'box' (sic) { switch ($this->_data['box']) { case '4': // inputs $this->_templateobject = DataObjectFactory::Factory('VatInputs'); $this->uses($this->_templateobject); - parent::index(new VatInputsCollection($this->_templateobject)); + $vatTransactions = new VatInputsCollection($this->_templateobject); + $company_type='supplier'; break; case '6': // outputs $this->_templateobject = DataObjectFactory::Factory('VatOutputs'); $this->uses($this->_templateobject); - parent::index(new VatOutputsCollection($this->_templateobject)); + $vatTransactions = new VatOutputsCollection($this->_templateobject); + $company_type='customer'; break; case '8': // eu sales $this->_templateobject = DataObjectFactory::Factory('VatEuSales'); $this->uses($this->_templateobject); - parent::index(new VatEuSalesCollection($this->_templateobject)); + $vatTransactions = new VatEuSalesCollection($this->_templateobject); + $company_type='customer'; break; case '9': // eu purchases $this->_templateobject = DataObjectFactory::Factory('VatEuPurchases'); $this->uses($this->_templateobject); - parent::index(new VatEuPurchasesCollection($this->_templateobject)); + $vatTransactions = new VatEuPurchasesCollection($this->_templateobject); + $company_type='supplier'; + break; + case '98': // postponed VAT + $this->_templateobject = DataObjectFactory::Factory('VatPVPurchases'); + $this->uses($this->_templateobject); + $vatTransactions = new VatPVPurchasesCollection($this->_templateobject); + $company_type='supplier'; + break; + case '99': // reverse charge VAT + $this->_templateobject = DataObjectFactory::Factory('VatRCPurchases'); + $this->uses($this->_templateobject); + $vatTransactions = new VatRCPurchasesCollection($this->_templateobject); + $company_type='supplier'; break; } + // Show the data in the index + parent::index($vatTransactions); $this->view->set('box',$this->_data['box']); $this->view->set('page_title',"VAT Transactions {$year}/{$tax_period} - ".$this->titles[$this->_data['box']]); } @@ -356,6 +391,49 @@ public function viewTransactions() $return = new VatReturn(); $return->loadVatReturn($year, $tax_period); + if ($this->_data['format'] == 'csv') { + + $sh = new SearchHandler($vatTransactions, FALSE); + $sh->addConstraintChain(new Constraint('year', '=', $s_data['year'])); + $sh->addConstraintChain(new Constraint('tax_period', '=', $s_data['tax_period'])); + $csvExports = $vatTransactions->load($sh,'',3); + + $column_order = ['transaction_date', + 'docref', + 'ext_reference', + $company_type, + 'comment', + 'vat', + 'net', + 'source', + 'type']; + + // output headers so that the file is downloaded rather than displayed + header('Content-Type: text/csv; charset=utf-8'); + header('Content-Disposition: attachment; filename=vat_transactions.csv'); + + // create a file pointer connected to the output stream + $handle = fopen('php://output', 'w'); + + // output the column headings to match the index view + fputcsv($handle, ['Date', + 'Doc Ref', + 'Ext Ref', + 'Company', + 'Comment', + 'VAT', + 'Net', + 'Source', + 'Type']); + + foreach($csvExports as $csvrow) { + $csvrow = array_slice(array_merge(array_flip($column_order), $csvrow),0,9); + fputcsv($handle, $csvrow); + } + fclose($handle); + exit(); + } + $sidebar = new SidebarController($this->view); $returns_sidebar['all'] = [ @@ -387,7 +465,7 @@ public function viewTransactions() } $sidebar->addList( - 'Actions', + 'Output', array( 'printtransactions'=>array( 'link'=>array_merge(array('modules'=>$this->_modules @@ -397,8 +475,17 @@ public function viewTransactions() ,'filename'=>'Transactions_'.$year.'-'.$tax_period ) ,$print_params), - 'tag'=>'Output Transactions' + 'tag'=>'Print Transactions' ), + 'exporttransactions'=>array( + 'link'=>array_merge(array('modules'=>$this->_modules + ,'controller'=>$this->name + ,'action'=>'viewTransactions' + ,'format'=>'csv' + ) + ,$print_params), + 'tag'=>'Export Transactions to CSV' + ) ) ); @@ -644,6 +731,26 @@ private function reportSidebar($titles, $year, $tax_period) ,'tax_period'=>$tax_period ), 'tag'=>$titles[9] + ), + 'box98'=>array( + 'link'=>array('modules'=>$this->_modules + ,'controller'=>$this->name + ,'action'=>'viewTransactions' + ,'box'=>98 + ,'year'=>$year + ,'tax_period'=>$tax_period + ), + 'tag'=>$titles[98] + ), + 'box99'=>array( + 'link'=>array('modules'=>$this->_modules + ,'controller'=>$this->name + ,'action'=>'viewTransactions' + ,'box'=>99 + ,'year'=>$year + ,'tax_period'=>$tax_period + ), + 'tag'=>$titles[99] ) ); return $list; @@ -863,8 +970,7 @@ public function printTransactions($status = 'generate') $options = array( 'type' => array( 'pdf' => '', - 'xml' => '', - 'csv' => '' + 'xml' => '' ), 'output' => array( 'print' => '', @@ -910,13 +1016,25 @@ public function printTransactions($status = 'generate') $gltransaction = DataObjectFactory::Factory('VatEuPurchases'); $gltransactions = new VatEuPurchasesCollection($gltransaction); break; + case '98': // postponed VAT + $gltransaction = DataObjectFactory::Factory('VatPVPurchases'); + $gltransactions = new VatPVPurchasesCollection($gltransaction); + break; + case '99': // reverse charge VAT + $gltransaction = DataObjectFactory::Factory('VatRCPurchases'); + $gltransactions = new VatRCPurchasesCollection($gltransaction); + break; } } $sh = new SearchHandler($gltransactions, false); $sh->addConstraint($cc); $gltransactions->load($sh); - + // Need the underling view here so we can get the sum + $viewname=$gltransactions->_tablename; + $totalvat = $this->_templateobject->getSum('vat', $cc, $viewname); + $totalnet = $this->_templateobject->getSum('net', $cc, $viewname); + if (count($errors) > 0) { echo $this->build_print_dialog_response( @@ -966,10 +1084,19 @@ public function printTransactions($status = 'generate') case 9: $title = "VAT EU Purchases {$title}"; break; + case 98: + $title = "Postponed VAT Purchases {$title}"; + break; + case 99: + $title = "Reverse Charge Purchases {$title}"; + break; } $extra = array( 'title' => $title + ,'totalvat' => number_format($totalvat,2) + ,'totalnet' => number_format($totalnet,2) + ); // generate the xml and add it to the options array @@ -1151,7 +1278,7 @@ public function view() { ), 'tag'=>'View Transactions' ); - + $returns_sidebar['all'] = [ 'link' => [ 'modules' => $this->_modules, diff --git a/modules/public_pages/erp/ledger/vat/models/Vat.php b/modules/public_pages/erp/ledger/vat/models/Vat.php index d324fab8..388a8eb6 100755 --- a/modules/public_pages/erp/ledger/vat/models/Vat.php +++ b/modules/public_pages/erp/ledger/vat/models/Vat.php @@ -109,6 +109,8 @@ private function getControlAccounts (&$errors=array()) 'retained_profits' => $glparams->retained_profits_account(), 'vat_control' => $glparams->vat_control_account(), 'eu_acquisitions' => $glparams->eu_acquisitions(), + 'vat_postponed' => $glparams->vat_postponed_account(), + 'vat_reverse_charge'=> $glparams->vat_reverse_charge_account(), ); if (in_array(false, $this->control_accounts, true)) { @@ -270,11 +272,10 @@ function getVATvalues($year=null, $tax_period=null) $qparams = [$year, $tax_period]; $query = <<<'QUERY' select tax_period, -coalesce(sum((select sum(vat) from gltransactions_vat_outputs where glperiods_id=glp.id)), 0.00) as "Box1", +coalesce(sum((select sum(vat) from gltransactions_vat_outputs vo where vo.glperiods_id=glp.id)) + coalesce(sum((select sum(vat) from gl_taxpvpurchases vo where vo.glperiods_id=glp.id)),0.00)+ coalesce(sum((select sum(vat) from gl_taxrcpurchases vo where vo.glperiods_id=glp.id)),0.00), 0.00) as "Box1", coalesce(sum((select sum(vat) from gl_taxeupurchases vo where vo.glperiods_id=glp.id)), 0.00) as "Box2", -coalesce(sum((select sum(vat) from gltransactions_vat_inputs vo where vo.glperiods_id=glp.id)) + coalesce(sum((select sum(vat) from gl_taxeupurchases vo where vo.glperiods_id=glp.id)),0.00), 0.00) as "Box4", -coalesce(sum((select sum(vat) from gltransactions_vat_inputs vo where vo.glperiods_id=glp.id)), 0.00) as "inputs", -coalesce(sum((select sum(net) from gltransactions_vat_outputs vo where vo.glperiods_id=glp.id)), 0.00) as "Box6", +coalesce(sum((select sum(vat) from gltransactions_vat_inputs vo where vo.glperiods_id=glp.id)) + coalesce(sum((select sum(vat) from gl_taxeupurchases vo where vo.glperiods_id=glp.id)),0.00)+ coalesce(sum((select sum(vat) from gl_taxpvpurchases vo where vo.glperiods_id=glp.id)),0.00)+ coalesce(sum((select sum(vat) from gl_taxrcpurchases vo where vo.glperiods_id=glp.id)),0.00), 0.00) as "Box4", +coalesce(sum((select sum(net) from gltransactions_vat_outputs vo where vo.glperiods_id=glp.id))+coalesce(sum((select sum(net) from gl_taxrcpurchases vo where vo.glperiods_id=glp.id)), 0.00), 0.00) as "Box6", coalesce(sum((select sum(net) from gltransactions_vat_inputs vo where vo.glperiods_id=glp.id)), 0.00) as "Box7", coalesce(sum((select sum(net) from gltransactions_vat_outputs vo where vo.glperiods_id=glp.id and eutaxstatus='T')), 0.00) as "Box8", coalesce(sum((select sum(net) from gltransactions_vat_inputs vo where vo.glperiods_id=glp.id and eutaxstatus='T')), 0.00) as "Box9" diff --git a/modules/public_pages/erp/ledger/vat/models/VatEuPurchases.php b/modules/public_pages/erp/ledger/vat/models/VatEuPurchases.php index b66b0cd4..92444187 100644 --- a/modules/public_pages/erp/ledger/vat/models/VatEuPurchases.php +++ b/modules/public_pages/erp/ledger/vat/models/VatEuPurchases.php @@ -31,6 +31,10 @@ function __construct($tablename='gl_taxeupurchases') { $glt = new GLTransaction; $this->setEnum('type', $glt->enums['type']); $this->setEnum('source', $glt->enums['source']); + + // Define field formats + $this->getField('vat')->setFormatter(new NumericFormatter()); + $this->getField('net')->setFormatter(new NumericFormatter()); } } ?> \ No newline at end of file diff --git a/modules/public_pages/erp/ledger/vat/models/VatEuSales.php b/modules/public_pages/erp/ledger/vat/models/VatEuSales.php index 0ef4571b..8b77bbac 100644 --- a/modules/public_pages/erp/ledger/vat/models/VatEuSales.php +++ b/modules/public_pages/erp/ledger/vat/models/VatEuSales.php @@ -31,6 +31,10 @@ function __construct($tablename='gl_taxeusales') { $glt = new GLTransaction; $this->setEnum('type', $glt->enums['type']); $this->setEnum('source', $glt->enums['source']); + + // Define field formats + $this->getField('vat')->setFormatter(new NumericFormatter()); + $this->getField('net')->setFormatter(new NumericFormatter()); } } ?> \ No newline at end of file diff --git a/modules/public_pages/erp/ledger/vat/models/VatInputs.php b/modules/public_pages/erp/ledger/vat/models/VatInputs.php index e390c4cb..1e0972c6 100644 --- a/modules/public_pages/erp/ledger/vat/models/VatInputs.php +++ b/modules/public_pages/erp/ledger/vat/models/VatInputs.php @@ -31,6 +31,10 @@ function __construct($tablename='gltransactions_vat_inputs') { $glt = new GLTransaction; $this->setEnum('type', $glt->enums['type']); $this->setEnum('source', $glt->enums['source']); + + // Define field formats + $this->getField('vat')->setFormatter(new NumericFormatter()); + $this->getField('net')->setFormatter(new NumericFormatter()); } } ?> \ No newline at end of file diff --git a/modules/public_pages/erp/ledger/vat/models/VatOutputs.php b/modules/public_pages/erp/ledger/vat/models/VatOutputs.php index 2a71857d..b346639e 100644 --- a/modules/public_pages/erp/ledger/vat/models/VatOutputs.php +++ b/modules/public_pages/erp/ledger/vat/models/VatOutputs.php @@ -31,6 +31,10 @@ function __construct($tablename='gltransactions_vat_outputs') { $glt = new GLTransaction; $this->setEnum('type', $glt->enums['type']); $this->setEnum('source', $glt->enums['source']); + + // Define field formats + $this->getField('vat')->setFormatter(new NumericFormatter()); + $this->getField('net')->setFormatter(new NumericFormatter()); } } ?> \ No newline at end of file diff --git a/modules/public_pages/erp/ledger/vat/models/VatPVPurchases.php b/modules/public_pages/erp/ledger/vat/models/VatPVPurchases.php new file mode 100644 index 00000000..8c8a6d98 --- /dev/null +++ b/modules/public_pages/erp/ledger/vat/models/VatPVPurchases.php @@ -0,0 +1,40 @@ + + * @license GPLv3 or later + * @copyright (c) 2019 uzERP LLP (support#uzerp.com). All rights reserved. + * + * uzERP is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + */ +class VatPVPurchases extends DataObject { + protected $defaultDisplayFields = [ + 'transaction_date', + 'gl_id', + 'docref', + 'ext_reference', + 'supplier', + 'comment', + 'vat', + 'net', + 'source', + 'type' + ]; + + function __construct($tablename='gl_taxpvpurchases') { + parent::__construct($tablename); + $this->orderby = ['transaction_date']; + + // Use enumerators from the GLT model + $glt = new GLTransaction; + $this->setEnum('type', $glt->enums['type']); + $this->setEnum('source', $glt->enums['source']); + + // Define field formats + $this->getField('vat')->setFormatter(new NumericFormatter()); + $this->getField('net')->setFormatter(new NumericFormatter()); + } +} +?> \ No newline at end of file diff --git a/modules/public_pages/erp/ledger/vat/models/VatPVPurchasesCollection.php b/modules/public_pages/erp/ledger/vat/models/VatPVPurchasesCollection.php new file mode 100644 index 00000000..c88bc9e1 --- /dev/null +++ b/modules/public_pages/erp/ledger/vat/models/VatPVPurchasesCollection.php @@ -0,0 +1,20 @@ + + * @license GPLv3 or later + * @copyright (c) 2019 uzERP LLP (support#uzerp.com). All rights reserved. + * + * uzERP is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + */ +class VatPVPurchasesCollection extends DataObjectCollection { + + public $field; + + function __construct($do='VatPVPurchases', $tablename='gl_taxpvpurchases') { + parent::__construct($do, $tablename); + } +} +?> \ No newline at end of file diff --git a/modules/public_pages/erp/ledger/vat/models/VatRCPurchases.php b/modules/public_pages/erp/ledger/vat/models/VatRCPurchases.php new file mode 100644 index 00000000..9b084f9b --- /dev/null +++ b/modules/public_pages/erp/ledger/vat/models/VatRCPurchases.php @@ -0,0 +1,40 @@ + + * @license GPLv3 or later + * @copyright (c) 2019 uzERP LLP (support#uzerp.com). All rights reserved. + * + * uzERP is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + */ +class VatRCPurchases extends DataObject { + protected $defaultDisplayFields = [ + 'transaction_date', + 'gl_id', + 'docref', + 'ext_reference', + 'supplier', + 'comment', + 'vat', + 'net', + 'source', + 'type' + ]; + + function __construct($tablename='gl_taxrcpurchases') { + parent::__construct($tablename); + $this->orderby = ['transaction_date']; + + // Use enumerators from the GLT model + $glt = new GLTransaction; + $this->setEnum('type', $glt->enums['type']); + $this->setEnum('source', $glt->enums['source']); + + // Define field formats + $this->getField('vat')->setFormatter(new NumericFormatter()); + $this->getField('net')->setFormatter(new NumericFormatter()); + } +} +?> \ No newline at end of file diff --git a/modules/public_pages/erp/ledger/vat/models/VatRCPurchasesCollection.php b/modules/public_pages/erp/ledger/vat/models/VatRCPurchasesCollection.php new file mode 100644 index 00000000..894fd505 --- /dev/null +++ b/modules/public_pages/erp/ledger/vat/models/VatRCPurchasesCollection.php @@ -0,0 +1,20 @@ + + * @license GPLv3 or later + * @copyright (c) 2019 uzERP LLP (support#uzerp.com). All rights reserved. + * + * uzERP is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + */ +class VatRCPurchasesCollection extends DataObjectCollection { + + public $field; + + function __construct($do='VatRCPurchases', $tablename='gl_taxrcpurchases') { + parent::__construct($do, $tablename); + } +} +?> \ No newline at end of file diff --git a/modules/public_pages/erp/ledger/vat/models/VatReturn.php b/modules/public_pages/erp/ledger/vat/models/VatReturn.php index 31083cdb..12cc5e5a 100644 --- a/modules/public_pages/erp/ledger/vat/models/VatReturn.php +++ b/modules/public_pages/erp/ledger/vat/models/VatReturn.php @@ -61,6 +61,17 @@ public function __construct($tablename='vat_return') { // Output to smarty from the formatter will be html, // flag as html to prevent escaping $this->getField('tax_period_closed')->type = 'html'; + + // Define field formats + $this->getField('vat_due_sales')->setFormatter(new NumericFormatter()); + $this->getField('vat_due_acquisitions')->setFormatter(new NumericFormatter()); + $this->getField('total_vat_due')->setFormatter(new NumericFormatter()); + $this->getField('vat_reclaimed_curr_period')->setFormatter(new NumericFormatter()); + $this->getField('net_vat_due')->setFormatter(new NumericFormatter()); + $this->getField('total_value_sales_ex_vat')->setFormatter(new NumericFormatter()); + $this->getField('total_value_purchase_ex_vat')->setFormatter(new NumericFormatter()); + $this->getField('total_value_goods_supplied_ex_vat')->setFormatter(new NumericFormatter()); + $this->getField('total_acquisitions_ex_vat')->setFormatter(new NumericFormatter()); } diff --git a/modules/public_pages/erp/ledger/vat/resources/js/vat.js b/modules/public_pages/erp/ledger/vat/resources/js/vat.js index b7a6f634..0cd0f42f 100755 --- a/modules/public_pages/erp/ledger/vat/resources/js/vat.js +++ b/modules/public_pages/erp/ledger/vat/resources/js/vat.js @@ -28,6 +28,53 @@ $(document).ready(function(){ dnt: '' } + var getBrowserPlugins = function(navigator) { + var rdls = function (vals) { + var res = []; + var tmp = vals.sort(); + + for (var i = 0; i < tmp.length; i++) { + res.push(tmp[i]); + while (JSON.stringify(tmp[i]) == JSON.stringify(tmp[i + 1])) { + i++; + } + } + + return res; + }; + + var res = []; + if (!navigator || !navigator.plugins) { + return res; + } + + for (var p in navigator.plugins) { + var plugin = navigator.plugins[p]; + + for (var j = 0; j < plugin.length; j++) { + var mime = plugin[j]; + + if (!mime) { + continue; + } + + var ep = mime.enabledPlugin; + if (ep) { + var item = { + mime: mime.type, + name: ep.name, + description: ep.description, + filename: ep.filename + }; + + res.push(item); + } + } + } + + return rdls(res); + }; + const ip = new Promise((resolve, reject) => { const conn = new RTCPeerConnection() conn.createDataChannel('') @@ -51,7 +98,7 @@ $(document).ready(function(){ fp.windowWidth = window.outerWidth; fp.windowHeight = window.outerHeight; - fp.plugins = navigator.plugins; + fp.plugins = getBrowserPlugins(navigator); fp.userAgent = navigator.userAgent; diff --git a/modules/public_pages/erp/ledger/vat/templates/vat/enter_journal.tpl b/modules/public_pages/erp/ledger/vat/templates/vat/enter_journal.tpl index 12a5e314..4496d18d 100755 --- a/modules/public_pages/erp/ledger/vat/templates/vat/enter_journal.tpl +++ b/modules/public_pages/erp/ledger/vat/templates/vat/enter_journal.tpl @@ -13,7 +13,7 @@ {input type="hidden" attribute="vat_type" value=$vat_type} {input type="text" attribute='net' number='value' value='0.00' label='Net Value '} {input type="text" attribute='vat' number='value' value='0.00' label='Vat Value '} - {select attribute="glperiods_id" label="Post to Period"} + {select attribute="glperiods_id" label="Post to Period" options=$periods value=$current_period} {input type="text" attribute="reference"} {input type="text" attribute="comment"} {select attribute='glaccount_id' label='Account' force=true options=$gl_accounts} diff --git a/modules/public_pages/erp/ledger/vat/templates/vat/viewtransactions.tpl b/modules/public_pages/erp/ledger/vat/templates/vat/viewtransactions.tpl index 8b89b1b0..68fb8dde 100644 --- a/modules/public_pages/erp/ledger/vat/templates/vat/viewtransactions.tpl +++ b/modules/public_pages/erp/ledger/vat/templates/vat/viewtransactions.tpl @@ -11,6 +11,10 @@ {assign var=data value=$vateusaless} {else if $box == '9'} {assign var=data value=$vateupurchasess} +{else if $box == '98'} + {assign var=data value=$vatpvpurchasess} +{else if $box == '99'} + {assign var=data value=$vatrcpurchasess} {/if} {content_wrapper} {paging} @@ -20,7 +24,7 @@ Date {heading_cell field="docref"} - Doc Ref: + Doc Ref. {/heading_cell}