Bug #2400: TVA Non déductible et TVA autoliquidation

This commit is contained in:
sparkyx 2024-12-27 17:23:06 +01:00
parent d25e56c1c4
commit 4ff5243aef
5 changed files with 106 additions and 63 deletions

View file

@ -48,6 +48,7 @@
'nd_vat_rate'=>'nd_vat_rate',
'amount_perso'=>'amount_perso',
'amount_perso_rate'=>'amount_perso_rate' );
* 'autoreverse'=>'autoreverse'
*/
@ -68,7 +69,8 @@ class Acc_Compute
'amount_perso_rate'=>'amount_perso_rate',
'amount_currency'=>'amount_currency',
'amount_vat_currency'=>'amount_vat_currency',
'currency_rate'=>'currency_rate'
'currency_rate'=>'currency_rate',
'autoreverse'=>'autoreverse'
);
private $order; // check that the compute
@ -196,7 +198,7 @@ class Acc_Compute
}
/**!
/*!
* \brief verify that all the amount are positive or null
* otherwise throw a exception and the sum of amount + vat must
* equal to the sum of all the amount of the current object

View file

@ -556,22 +556,18 @@ class Acc_Ledger_Purchase extends Acc_Ledger
bcscale(4);
// variable : $tot_amount float : total amount of the purchase (debit)
$tot_amount=0;
// variable : $tot_tva float : total amount of the VAT
$tot_tva=0;
// variable: $tot_debit float : amount on debit side
$tot_debit=0;
$this->db->start();
// variable : $tot_nd float total not Deductible
$tot_nd=0;
// variable : $tot_perso float total private amount
$tot_perso=0;
// variable : $tot_tva_nd float total vat not deductible
$tot_tva_nd=0;
// variable : $tot_tva_ndded float total vat not deductible - deductible via another tax
$tot_tva_ndded=0;
$tot_tva_reversed=0; //@todo to remove
// variable: $tot_tva_reversed float total VAT autoreverse, to deduce from supplier's amount
$tot_tva_reversed=0;
// variable : $tva array that will contain all the VAT Amount
$tva=array();
@ -579,6 +575,9 @@ class Acc_Ledger_Purchase extends Acc_Ledger
// variable : $tva_reverse array that contain all the VAT autoreverse AND negative
$tva_reverse = array();
// variable : $tva_reverse_credit array that contain all the VAT autoreverse for credit
$tva_reverse_credit = array();
// variable : $tot_amount_cur : total amount in currency
$tot_amount_cur=0;
@ -600,7 +599,6 @@ class Acc_Ledger_Purchase extends Acc_Ledger
if ($g_parameter->MY_TVA_USE=='Y')
{
$idx_tva=trim(${'e_march'.$i.'_tva_id'});
\Noalyss\Dbg::echo_var(1," idx_tva [$idx_tva]",);
$oTva=Acc_Tva::build($this->db,$idx_tva);
$oTva->load();
@ -650,13 +648,16 @@ class Acc_Ledger_Purchase extends Acc_Ledger
/* compute ND */
// variable: $save_amount_vat total float amount of VAT before changing due to NOT DEDUCTIBLE
$save_amount_vat=$acc_amount->amount_vat;
$this->compute_no_deductible($acc_amount, $fiche);
$acc_amount->correct();
// TVA which avoid
$acc_amount->amount_unpaid=($tva_both == 1 ) ? $save_amount_vat :0 ;
$tot_tva_reversed=bcadd($tot_tva_reversed,$acc_amount->amount_unpaid);
// TVA which avoid
if ( $tva_both == 1 ) {
$acc_amount->autoreverse=$save_amount_vat;
$tot_tva_reversed=bcadd($tot_tva_reversed,$save_amount_vat);
}
$tot_amount=round(bcadd($tot_amount,$acc_amount->amount),2);
@ -700,13 +701,16 @@ class Acc_Ledger_Purchase extends Acc_Ledger
if ( $g_parameter->MY_TVA_USE=='Y')
{
$tva_item=$acc_amount->amount_vat;
$tva[$idx_tva]=(isset( $tva[$idx_tva]))? $tva[$idx_tva]:0;
if ($tva_both == 0 || $tva_item >= 0){
if ($tva_both == 0 ){
$tva[$idx_tva]=(isset( $tva[$idx_tva]))? $tva[$idx_tva]:0;
$tva[$idx_tva]=bcadd($tva[$idx_tva], $tva_item);
}else {
// $tva_item < 0 && $tva_both == 1
$tva_reverse[$idx_tva]=(isset($tva_reverse[$idx_tva]))?$tva_reverse[$idx_tva]:0;
$tva_reverse[$idx_tva]=bcadd($tva_item,$tva_reverse[$idx_tva]);
$tva_reverse_credit[$idx_tva]=(isset($tva_reverse_credit[$idx_tva]))?$tva_reverse_credit[$idx_tva]:0;
$tva_reverse_credit[$idx_tva]=bcadd($save_amount_vat,$tva_reverse_credit[$idx_tva]);
}
}
/* Save the stock */
@ -760,7 +764,7 @@ class Acc_Ledger_Purchase extends Acc_Ledger
,$acc_amount->nd_ded_vat /* 10 */
,$acc_amount->amount_perso /* 11 */
,$e_client /* 12 */
, $acc_amount->amount_unpaid /*13*/
, $acc_amount->autoreverse /*13*/
,$price_euro /* 14 */
));
@ -783,7 +787,7 @@ class Acc_Ledger_Purchase extends Acc_Ledger
,$acc_amount->nd_ded_vat /* 10 */
,$acc_amount->amount_perso /* 11 */
,$e_client /* 12 */
, $acc_amount->amount_unpaid /*13*/
, $acc_amount->autoreverse /*13*/
,$price_euro /* 14 */
));
}
@ -890,30 +894,7 @@ class Acc_Ledger_Purchase extends Acc_Ledger
$acc_operation->type='d';
$acc_operation->periode=$tperiode;
if ( $value > 0 ) $tot_debit=bcadd($tot_debit,abs($value));
if ( $oTva->get_parameter("both_side") == 1 && $value ==0 ) continue;
$acc_operation->insert_jrnx();
// if TVA is on both side, we deduce it immediately
if ( $oTva->get_parameter("both_side")==1 )
{
// $x temp variable is the tva_reverse_account and will be used to check $poste_vat
$x=$oTva->get_parameter("tva_reverse_account");
$poste_vat =(trim($x??"")=="")? $oTva->get_side('c'):$x;
if ( $poste_vat == '#')
{
$poste_vat=$oTva->get_side('d');
}
$acc_operation=new Acc_Operation($this->db);
$acc_operation->date=$e_date;
$acc_operation->poste=$poste_vat;
$acc_operation->amount=$value;
$acc_operation->grpt=$seq;
$acc_operation->jrn=$p_jrn;
$acc_operation->type='c';
$acc_operation->periode=$tperiode;
$acc_operation->insert_jrnx();
//if ( $value < 0 ) $tot_debit=bcadd($tot_debit,abs($value));
}
} // LOOP : foreach $tva
foreach ($tva_reverse as $i => $value) {
@ -936,7 +917,10 @@ class Acc_Ledger_Purchase extends Acc_Ledger
$acc_operation->insert_jrnx();
// if TVA is on both side, we deduce it immediately
$poste_vat = $oTva->get_side('c');
// $x temp variable is the tva_reverse_account and will be used to check $poste_vat
$x=$oTva->get_parameter("tva_reverse_account");
$poste_vat =(trim($x??"")=="")? $oTva->get_side('c'):$x;
if ( $poste_vat == '#')
{
$poste_vat=$oTva->get_side('d');
@ -944,7 +928,7 @@ class Acc_Ledger_Purchase extends Acc_Ledger
$acc_operation = new Acc_Operation($this->db);
$acc_operation->date = $e_date;
$acc_operation->poste = $poste_vat;
$acc_operation->amount = $value;
$acc_operation->amount = $tva_reverse_credit[$i];
$acc_operation->grpt = $seq;
$acc_operation->jrn = $p_jrn;
$acc_operation->type = 'c';
@ -952,7 +936,6 @@ class Acc_Ledger_Purchase extends Acc_Ledger
$acc_operation->insert_jrnx();
$tot_debit = bcadd($tot_debit, $value);
$tot_debit = round($tot_debit, 2);
$n_both = $value;
} //LOOP: foreach $tva_reverse
}

View file

@ -189,7 +189,7 @@ class Acc_ComputeTest extends TestCase
$result=ob_get_contents();
ob_end_clean();
$this->assertStringStartsWith("key amount Description amount value is 0<br>key amount_vat Description amount_vat value is 0<br>",$result);
$this->assertStringEndsWith("<br>key amount_vat_currency Description amount_vat_currency value is 0<br>key currency_rate Description currency_rate value is 0<br>",$result);
$this->assertStringEndsWith("<br>key amount_vat_currency Description amount_vat_currency value is 0<br>key currency_rate Description currency_rate value is 0<br>key autoreverse Description autoreverse value is 0<br>",$result);
}
public function testCompute()

View file

@ -448,10 +448,11 @@ class Acc_Ledger_PurchaseTest extends TestCase
/**
* @testdox Purchase not deductible : VAT , TAX , PRIVATE fee
* @dataProvider data_no_deductible
* Parameters : $p_attribut if the no deductible attribute, the $p_value is the % not deductible, $p_amount
* is the corresponding column in quant_purchase and $p_accounting is the counterpart
* for this not deductible fee($p_counterpart)
*/
* @parameter $p_attribut int ATTR_DEF.AD_ID $p_attribut if the no deductible attribute,
* @parameter $p_value int is the % not deductible,
* @parameter $p_amount float the corresponding column in quant_purchase
* @parameter $p_accounting string is the accounting counterpart for this not deductible fee($p_counterpart)
*/
public function testInsertPurchase_No_Ded($p_attribut , $p_value,$p_column,$p_amount,$p_counterpart,$p_accounting)
{
global $g_connection;
@ -497,7 +498,63 @@ class Acc_Ledger_PurchaseTest extends TestCase
}
/**
* @testdox Purchase not deductible + autoreverse: VAT , TAX , PRIVATE fee with VAT autoreverse
* @dataProvider data_no_deductible
* @parameter $p_attribut int ATTR_DEF.AD_ID $p_attribut if the no deductible attribute,
* @parameter $p_value int is the % not deductible,
* @parameter $p_amount float the corresponding column in quant_purchase
* @parameter $p_accounting string is the accounting counterpart for this not deductible fee($p_counterpart)
*/
public function testInsertPurchase_No_Ded_reverse($p_attribut , $p_value,$p_column,$p_amount,$p_counterpart,$p_accounting)
{
global $g_connection;
static $scenario=0;
$scenario++;
//-- modify card 29 : ELECTR
$fiche=new Fiche($g_connection,29);
$fiche->set_f_enable("1");
$fiche->setAttribut($p_attribut,$p_value);
$fiche->setAttribut($p_counterpart,$p_accounting);
$a_attribut=$fiche->to_array();
$this->assertEquals($a_attribut['av_text'.$p_attribut],$p_value,"Attribut $p_attribut not set to $p_value%");
$fiche->update($a_attribut);
$this->assertEquals($p_value,
$g_connection->get_value("select ad_value
from fiche_detail
where f_id=$1 and ad_id=$2",[29,$p_attribut]),
"Attribut ad_id $p_attribut not inserted");
$array=$this->array;
$array['e_comm']="scenario [$scenario]";
$array['e_march0']='ELECTR';
$array['e_march0_tva_id']='5';
$array['tva_march0']=bcmul($array['e_march0_tva_amount'],0.21,2);
$array['tvac_march0']=bcmul ($array['htva_march0'],1.21,2);
$array['mt']='no-ded-33'.$scenario;
$this->clean_operation($array['mt']);
$this->object->insert($array);
$row_quant=$g_connection->get_row("select * from quant_purchase where qp_internal in
( select jr_internal from jrn where jr_mt=$1)",[$array["mt"]]);
$this->assertFalse(empty($row_quant)," row not inserted in quant_purchase");
// unit price not rounded
$this->assertEquals(603.8990,$row_quant['qp_unit']);
// rounded to 2 decimal
$this->assertEquals(603.9000,$row_quant['qp_price']);
$this->assertEquals($p_amount,$row_quant[$p_column]);
$this->clean_operation($array['mt']);
}
/**
* @covers Acc_Ledger_Purchase::input
*/
@ -706,22 +763,22 @@ class Acc_Ledger_PurchaseTest extends TestCase
select count(*)
from jrnx j1 join jrn j2 on (j1.j_grpt=j2.jr_grpt_id)
where
j2.jr_mt ='1572704002.1732'
j2.jr_mt = $1
and j1.j_poste ='4119999'
and j1.j_debit ='f'
";
$this->assertEquals(1, $g_connection->get_value($sql),'fails : reversed account credit is wrong');
$this->assertEquals(1, $g_connection->get_value($sql,[$array["mt"]]),'fails : reversed account credit is wrong');
// check that the accounting for reverse VAT is only 45142
$sql="
select count(*)
from jrnx j1 join jrn j2 on (j1.j_grpt=j2.jr_grpt_id)
where
j2.jr_mt ='1572704002.1732'
j2.jr_mt = $1
and j1.j_poste ='41142'
and j1.j_debit ='t'
";
$this->assertEquals(1, $g_connection->get_value($sql),'fails : reversed account credit is wrong');
$this->assertEquals(1, $g_connection->get_value($sql,[$array["mt"]]),'fails : reversed account credit is wrong');
$this->clean_operation();
@ -735,12 +792,13 @@ class Acc_Ledger_PurchaseTest extends TestCase
function testInsertReverseVAT4() {
global $g_connection;
$array=$this->array1;
$array['mt']='testInsertReverseVAT4';
$old_autoreverse=$g_connection->get_value("select tva_both_side from tva_rate where tva_id=3 ");
// set autoreverse to 1
$g_connection->get_value("update tva_rate set tva_both_side = 1 where tva_id=3 ");
// clean
$g_connection->exec_sql("delete from jrn where jr_mt=$1",[1734717784.385]);
$g_connection->exec_sql("delete from jrn where jr_mt=$1",[ $array['mt'] ]);
$this->object->insert($array);
$accounting=new \Acc_Operation($g_connection);
@ -768,7 +826,7 @@ class Acc_Ledger_PurchaseTest extends TestCase
// cancel change
$g_connection->get_value("update tva_rate set tva_both_side = $1 where tva_id=3 ",[$old_autoreverse]);
$g_connection->exec_sql("delete from jrn where jr_mt=$1",[1734717784.385]);
$g_connection->exec_sql("delete from jrn where jr_mt=$1",[$array['mt']]);
}
@ -782,22 +840,23 @@ class Acc_Ledger_PurchaseTest extends TestCase
$array=$this->array1;
$array['e_march1_tva_id']=5;
$array['mt']='testInsertReverseVAT5';
// clean
$g_connection->exec_sql("delete from jrn where jr_mt=$1",[1734717784.385]);
$g_connection->exec_sql("delete from jrn where jr_mt=$1",[ $array['mt'] ]);
$this->object->insert($array);
$accounting=new \Acc_Operation($g_connection);
$accounting->jr_id=$this->object->jr_id;
$aResult=$accounting->get_jrnx_detail();
$this->assertTrue(count($aResult)==7, 'Number of rows is '.count($aResult)."instead of 7");
$this->assertTrue(count($aResult)==5, 'Number of rows is '.count($aResult)."instead of 5");
foreach($aResult as $result) {
switch ($result['j_poste']) {
case '41142':
if ( $result['debit']=='D')
$this->assertEquals(25.20, $result['j_montant'],"erreur account {$result['j_poste']}");
$this->assertEquals(23.10, $result['j_montant'],"erreur account {$result['j_poste']}");
else
$this->assertEquals(2.1, $result['j_montant'],"erreur account {$result['j_poste']}");
break;
@ -814,8 +873,7 @@ class Acc_Ledger_PurchaseTest extends TestCase
}
// cancel change
$g_connection->exec_sql("delete from jrn where jr_mt=$1",[1734717784.385]);
$g_connection->exec_sql("delete from jrn where jr_mt=$1",[ $array['mt'] ]);
}

View file

@ -137,7 +137,7 @@ class FollowupTest extends TestCase
$content=ob_get_contents();
ob_end_clean();
$this->assertStringContainsString("BONDEC3-1", $content);
$this->assertTrue(mb_strlen($content)==1613,"error result not valid $content size = ".mb_strlen($content));
$this->assertTrue(mb_strlen($content)==1620,"error result not valid $content size = ".mb_strlen($content));
}