Skip to content

Commit

Permalink
Latest VAT changes
Browse files Browse the repository at this point in the history
  • Loading branch information
steveblamey committed Nov 16, 2020
2 parents d3f844d + ca173f7 commit dac35c4
Show file tree
Hide file tree
Showing 33 changed files with 981 additions and 51 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 8 additions & 6 deletions lib/classes/standard/MTD.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -108,18 +107,21 @@ 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;

// 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -376,14 +376,16 @@ 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
{
$errors[] = 'Error getting Tax Status for the Invoice';
return FALSE;
}

if ($eu_acquisition)
if ($eu_acquisition || $vat_postponed || $reverse_charge)
{
$eu_gl_data = $gl_data;
$eu_gl_data['value'] = 0;
Expand Down Expand Up @@ -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))
{
Expand Down Expand Up @@ -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)
{
Expand Down
14 changes: 14 additions & 0 deletions modules/public_pages/erp/ledger/general_ledger/models/GLParams.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
)
);

Expand All @@ -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');
Expand Down Expand Up @@ -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);
}
Expand Down
16 changes: 16 additions & 0 deletions modules/public_pages/erp/ledger/general_ledger/models/GLPeriod.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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']];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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')
{
Expand All @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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' }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -589,8 +589,8 @@ public function make_inactive()
{
$flash->addWarning($e->getMessage());
if ($e->getCode == 1) {
$db->FailTrans();
}
$db->FailTrans();
}

}

Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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();

Expand Down
Loading

0 comments on commit dac35c4

Please sign in to comment.