Improvements for rounding calculations for discounted item amounts

This commit is contained in:
David Bomba 2024-11-05 19:25:15 +11:00
parent ffc1f4789a
commit d93ac9ae59
7 changed files with 231 additions and 363 deletions

View File

@ -207,46 +207,6 @@ class InvoiceItemSum
return $this;
}
private function calculateNexus()
{
$company_country_code = $this->invoice->company->country()->iso_3166_2;
$client_country_code = $this->client->country->iso_3166_2;
$base_rule = new \App\DataMapper\Tax\BaseRule();
$eu_countries = $base_rule->eu_country_codes;
$nexus_rule = $company_country_code;
if ($client_country_code == $company_country_code) {
//Domestic Sales
$nexus_rule = $company_country_code;
} elseif (in_array($company_country_code, $eu_countries) && !in_array($client_country_code, $eu_countries)) {
//NON-EU Sale
$nexus_rule = $company_country_code;
} elseif (in_array($company_country_code, $eu_countries) && in_array($client_country_code, $eu_countries)) {
//EU Sale
// Invalid VAT number = seller country nexus
if(isset($this->client->has_valid_vat_number) && !$this->client->has_valid_vat_number){
$nexus_rule = $company_country_code;
}
elseif (isset($this->invoice->company->tax_data->regions->EU->has_sales_above_threshold) && $this->invoice->company->tax_data->regions->EU->has_sales_above_threshold) { //over threshold - tax in buyer country
$nexus_rule = $client_country_code;
} elseif (isset($this->invoice->company->tax_data->regions->EU->has_sales_above_threshold) && !$this->invoice->company->tax_data->regions->EU->has_sales_above_threshold) {
$nexus_rule = $company_country_code;
} elseif ($this->client->classification != 'individual' && (isset($this->client->has_valid_vat_number) && !$this->client->has_valid_vat_number)){
$nexus_rule = $company_country_code;
} else {
$nexus_rule = $company_country_code;
}
}
nlog($nexus_rule);
$class = "App\DataMapper\Tax\\".str_replace("-", "_", $nexus_rule)."\\Rule";
return $class;
}
private function push(): self
{
$this->sub_total += round($this->getLineTotal(), $this->currency->precision);
@ -335,7 +295,7 @@ class InvoiceItemSum
$item_tax += $item_tax_rate1_total;
if (strlen($this->item->tax_name1) > 1) {
$this->groupTax($this->item->tax_name1, $this->item->tax_rate1, $item_tax_rate1_total);
$this->groupTax($this->item->tax_name1, $this->item->tax_rate1, $item_tax_rate1_total, $amount, $this->item->tax_id);
}
$item_tax_rate2_total = $this->calcAmountLineTax($this->item->tax_rate2, $amount);
@ -343,7 +303,7 @@ class InvoiceItemSum
$item_tax += $item_tax_rate2_total;
if (strlen($this->item->tax_name2) > 1) {
$this->groupTax($this->item->tax_name2, $this->item->tax_rate2, $item_tax_rate2_total);
$this->groupTax($this->item->tax_name2, $this->item->tax_rate2, $item_tax_rate2_total, $amount, $this->item->tax_id);
}
$item_tax_rate3_total = $this->calcAmountLineTax($this->item->tax_rate3, $amount);
@ -351,7 +311,7 @@ class InvoiceItemSum
$item_tax += $item_tax_rate3_total;
if (strlen($this->item->tax_name3) > 1) {
$this->groupTax($this->item->tax_name3, $this->item->tax_rate3, $item_tax_rate3_total);
$this->groupTax($this->item->tax_name3, $this->item->tax_rate3, $item_tax_rate3_total, $amount, $this->item->tax_id);
}
$this->setTotalTaxes($this->formatValue($item_tax, $this->currency->precision));
@ -375,6 +335,7 @@ class InvoiceItemSum
->map(fn ($i) => [
'name' => $item->{"tax_name{$i}"} ?? '',
'percentage' => $item->{"tax_rate{$i}"} ?? 0,
'tax_id' => $item->tax_id ?? '1',
])
->filter(fn ($tax) => strlen($tax['name']) > 1);
})
@ -400,21 +361,23 @@ class InvoiceItemSum
$tax_component += round($this->invoice->custom_surcharge4 * ($tax['percentage'] / 100), 2);
}
$amount = $this->invoice->custom_surcharge4 + $this->invoice->custom_surcharge3 + $this->invoice->custom_surcharge2 + $this->invoice->custom_surcharge1;
if($tax_component > 0)
$this->groupTax($tax['name'], $tax['percentage'], $tax_component);
$this->groupTax($tax['name'], $tax['percentage'], $tax_component, $amount, $tax['tax_id']);
});
return $this;
}
private function groupTax($tax_name, $tax_rate, $tax_total)
private function groupTax($tax_name, $tax_rate, $tax_total, $amount, $tax_id = '')
{
$group_tax = [];
$key = str_replace(' ', '', $tax_name.$tax_rate);
$group_tax = ['key' => $key, 'total' => $tax_total, 'tax_name' => $tax_name.' '.Number::formatValueNoTrailingZeroes(floatval($tax_rate), $this->client).'%'];
$group_tax = ['key' => $key, 'total' => $tax_total, 'tax_name' => $tax_name.' '.Number::formatValueNoTrailingZeroes(floatval($tax_rate), $this->client).'%', 'tax_id' => $tax_id, 'tax_rate' => $tax_rate, 'base_amount' => $amount];
$this->tax_collection->push(collect($group_tax));
}
@ -516,7 +479,7 @@ class InvoiceItemSum
$item_tax += $item_tax_rate1_total;
if ($item_tax_rate1_total != 0) {
$this->groupTax($this->item->tax_name1, $this->item->tax_rate1, $item_tax_rate1_total);
$this->groupTax($this->item->tax_name1, $this->item->tax_rate1, $item_tax_rate1_total, $amount, $this->item->tax_id);
}
$item_tax_rate2_total = $this->calcAmountLineTax($this->item->tax_rate2, $amount);
@ -524,7 +487,7 @@ class InvoiceItemSum
$item_tax += $item_tax_rate2_total;
if ($item_tax_rate2_total != 0) {
$this->groupTax($this->item->tax_name2, $this->item->tax_rate2, $item_tax_rate2_total);
$this->groupTax($this->item->tax_name2, $this->item->tax_rate2, $item_tax_rate2_total, $amount, $this->item->tax_id);
}
$item_tax_rate3_total = $this->calcAmountLineTax($this->item->tax_rate3, $amount);
@ -532,7 +495,7 @@ class InvoiceItemSum
$item_tax += $item_tax_rate3_total;
if ($item_tax_rate3_total != 0) {
$this->groupTax($this->item->tax_name3, $this->item->tax_rate3, $item_tax_rate3_total);
$this->groupTax($this->item->tax_name3, $this->item->tax_rate3, $item_tax_rate3_total, $amount, $this->item->tax_id);
}
$this->item->gross_line_total = $this->getLineTotal() + $item_tax;

View File

@ -244,7 +244,7 @@ class InvoiceItemSumInclusive
$item_tax += $this->formatValue($item_tax_rate1_total, $this->currency->precision);
if (strlen($this->item->tax_name1) > 1) {
$this->groupTax($this->item->tax_name1, $this->item->tax_rate1, $item_tax_rate1_total);
$this->groupTax($this->item->tax_name1, $this->item->tax_rate1, $item_tax_rate1_total, $amount, $this->item->tax_id);
}
$item_tax_rate2_total = $this->calcInclusiveLineTax($this->item->tax_rate2, $amount);
@ -252,7 +252,7 @@ class InvoiceItemSumInclusive
$item_tax += $this->formatValue($item_tax_rate2_total, $this->currency->precision);
if (strlen($this->item->tax_name2) > 1) {
$this->groupTax($this->item->tax_name2, $this->item->tax_rate2, $item_tax_rate2_total);
$this->groupTax($this->item->tax_name2, $this->item->tax_rate2, $item_tax_rate2_total, $amount, $this->item->tax_id);
}
$item_tax_rate3_total = $this->calcInclusiveLineTax($this->item->tax_rate3, $amount);
@ -260,7 +260,7 @@ class InvoiceItemSumInclusive
$item_tax += $this->formatValue($item_tax_rate3_total, $this->currency->precision);
if (strlen($this->item->tax_name3) > 1) {
$this->groupTax($this->item->tax_name3, $this->item->tax_rate3, $item_tax_rate3_total);
$this->groupTax($this->item->tax_name3, $this->item->tax_rate3, $item_tax_rate3_total, $amount, $this->item->tax_id);
}
$this->item->tax_amount = $this->formatValue($item_tax, $this->currency->precision);
@ -270,13 +270,13 @@ class InvoiceItemSumInclusive
return $this;
}
private function groupTax($tax_name, $tax_rate, $tax_total)
private function groupTax($tax_name, $tax_rate, $tax_total, $amount, $tax_id = '')
{
$group_tax = [];
$key = str_replace(' ', '', $tax_name.$tax_rate);
$group_tax = ['key' => $key, 'total' => $tax_total, 'tax_name' => $tax_name.' '.Number::formatValueNoTrailingZeroes(floatval($tax_rate), $this->client).'%'];
$group_tax = ['key' => $key, 'total' => $tax_total, 'tax_name' => $tax_name.' '.Number::formatValueNoTrailingZeroes(floatval($tax_rate), $this->client).'%', 'tax_id' => $tax_id, 'base_amoount' => $amount];
$this->tax_collection->push(collect($group_tax));
}
@ -376,7 +376,7 @@ class InvoiceItemSumInclusive
$item_tax += $item_tax_rate1_total;
if ($item_tax_rate1_total != 0) {
$this->groupTax($this->item->tax_name1, $this->item->tax_rate1, $item_tax_rate1_total);
$this->groupTax($this->item->tax_name1, $this->item->tax_rate1, $item_tax_rate1_total, $amount, $this->item->tax_id);
}
$item_tax_rate2_total = $this->calcInclusiveLineTax($this->item->tax_rate2, $amount);
@ -384,7 +384,7 @@ class InvoiceItemSumInclusive
$item_tax += $item_tax_rate2_total;
if ($item_tax_rate2_total != 0) {
$this->groupTax($this->item->tax_name2, $this->item->tax_rate2, $item_tax_rate2_total);
$this->groupTax($this->item->tax_name2, $this->item->tax_rate2, $item_tax_rate2_total, $amount, $this->item->tax_id);
}
$item_tax_rate3_total = $this->calcInclusiveLineTax($this->item->tax_rate3, $amount);
@ -392,7 +392,7 @@ class InvoiceItemSumInclusive
$item_tax += $item_tax_rate3_total;
if ($item_tax_rate3_total != 0) {
$this->groupTax($this->item->tax_name3, $this->item->tax_rate3, $item_tax_rate3_total);
$this->groupTax($this->item->tax_name3, $this->item->tax_rate3, $item_tax_rate3_total, $amount, $this->item->tax_id);
}
$this->setTotalTaxes($this->getTotalTaxes() + $item_tax);

View File

@ -349,11 +349,25 @@ class InvoiceSum
return $value['key'] == $key;
})->pluck('tax_name')->first();
$tax_rate = $values->filter(function ($value, $k) use ($key) {
return $value['key'] == $key;
})->pluck('tax_rate')->first();
$tax_id = $values->filter(function ($value, $k) use ($key) {
return $value['key'] == $key;
})->pluck('tax_id')->first();
$total_line_tax = $values->filter(function ($value, $k) use ($key) {
return $value['key'] == $key;
})->sum('total');
$this->tax_map[] = ['name' => $tax_name, 'total' => $total_line_tax];
$base_amount = $values->filter(function ($value, $k) use ($key) {
return $value['key'] == $key;
})->sum('base_amount');
$tax_id = $values->first()['tax_id'] ?? '';
$this->tax_map[] = ['name' => $tax_name, 'total' => $total_line_tax, 'tax_id' => $tax_id, 'tax_rate' => $tax_rate, 'base_amount' => $base_amount];
$this->total_taxes += $total_line_tax;
}

View File

@ -368,19 +368,33 @@ class InvoiceSumInclusive
$values = $this->invoice_items->getGroupedTaxes();
foreach ($keys as $key) {
$tax_name = $values->filter(function ($value, $k) use ($key) {
return $value['key'] == $key;
})->pluck('tax_name')->first();
$tax_rate = $values->filter(function ($value, $k) use ($key) {
return $value['key'] == $key;
})->pluck('tax_rate')->first();
$tax_id = $values->filter(function ($value, $k) use ($key) {
return $value['key'] == $key;
})->pluck('tax_id')->first();
$total_line_tax = $values->filter(function ($value, $k) use ($key) {
return $value['key'] == $key;
})->sum('total');
//$total_line_tax -= $this->discount($total_line_tax);
$base_amount = $values->filter(function ($value, $k) use ($key) {
return $value['key'] == $key;
})->sum('base_amount');
$this->tax_map[] = ['name' => $tax_name, 'total' => $total_line_tax];
$tax_id = $values->first()['tax_id'] ?? '';
$this->tax_map[] = ['name' => $tax_name, 'total' => $total_line_tax, 'tax_id' => $tax_id, 'tax_rate' => $tax_rate, 'base_amount' => $base_amount];
$this->total_taxes += $total_line_tax;
}
return $this;

View File

@ -174,10 +174,6 @@ class Peppol extends AbstractService
$this->getJurisdiction(); //Sets the nexus object into the Peppol document.
$this->getAllUsedTaxes(); //Maps all used line item taxes
nlog("amount: {$this->invoice->amount}");
nlog("taxes: {$this->invoice->total_taxes}");
nlog("exclusive = {$this->invoice->amount} -{$this->invoice->total_taxes}");
/** Invoice Level Props */
$id = new \InvoiceNinja\EInvoice\Models\Peppol\IdentifierType\CustomizationID();
$id->value = $this->customizationID;
@ -723,159 +719,6 @@ class Peppol extends AbstractService
}
/**
* getInvoiceLines
*
* Compiles the invoice line items of the document
*
* @return array
*/
private function getInvoiceLinesx(): array
{
$lines = [];
foreach($this->invoice->line_items as $key => $item) {
$base_price_amount = (string)$this->calculateAdjustedBaseAmount($item);
$_item = new Item();
$_item->Name = $item->product_key;
$_item->Description = $item->notes;
$ctc = new ClassifiedTaxCategory();
$ctc->ID = new ID();
$ctc->ID->value = $this->getTaxType($item->tax_id);
if($item->tax_rate1 > 0)
$ctc->Percent = (string)$item->tax_rate1;
$ts = new TaxScheme();
$id = new ID();
$id->value = $this->standardizeTaxSchemeId($item->tax_name1);
$ts->ID = $id;
$ctc->TaxScheme = $ts;
if(floatval($item->tax_rate1) === 0.0)
{
$ctc = $this->resolveTaxExemptReason($item, $ctc);
if($this->tax_category_id == 'O')
unset($ctc->Percent);
}
$_item->ClassifiedTaxCategory[] = $ctc;
if ($item->tax_rate2 > 0) {
$ctc = new ClassifiedTaxCategory();
$ctc->ID = new ID();
$ctc->ID->value = $this->getTaxType($item->tax_id);
$ctc->Percent = (string)$item->tax_rate2;
$ts = new TaxScheme();
$id = new ID();
$id->value = $this->standardizeTaxSchemeId($item->tax_name2);
$ts->ID = $id;
$ctc->TaxScheme = $ts;
$_item->ClassifiedTaxCategory[] = $ctc;
}
if ($item->tax_rate3 > 0) {
$ctc = new ClassifiedTaxCategory();
$ctc->ID = new ID();
$ctc->ID->value = $this->getTaxType($item->tax_id);
$ctc->Percent = (string)$item->tax_rate3;
$ts = new TaxScheme();
$id = new ID();
$id->value = $this->standardizeTaxSchemeId($item->tax_name3);
$ts->ID = $id;
$ctc->TaxScheme = $ts;
$_item->ClassifiedTaxCategory[] = $ctc;
}
$line = new InvoiceLine();
$id = new ID();
$id->value = (string) ($key+1);
$line->ID = $id;
$iq = new \InvoiceNinja\EInvoice\Models\Peppol\QuantityType\InvoicedQuantity();
$iq->amount = $item->quantity;
$iq->unitCode = $item->unit_code ?? 'C62';
$line->InvoicedQuantity = $iq;
$lea = new LineExtensionAmount();
$lea->currencyID = $this->invoice->client->currency()->code;
$lea->amount = $this->invoice->uses_inclusive_taxes ? $item->line_total - $this->calcInclusiveLineTax($item->tax_rate1, $item->line_total) : $item->line_total;
$line->LineExtensionAmount = $lea;
$line->Item = $_item;
/** Builds the tax map for the document */
$this->getItemTaxes($item);
// Handle Price and Discounts
if ($item->discount > 0) {
// Base Price (before discount)
$basePrice = new Price();
$basePriceAmount = new PriceAmount();
$basePriceAmount->currencyID = $this->invoice->client->currency()->code;
$basePriceAmount->amount = (string)$item->cost;
$basePrice->PriceAmount = $basePriceAmount;
// Add Allowance Charge to Price
$allowanceCharge = new \InvoiceNinja\EInvoice\Models\Peppol\AllowanceChargeType\AllowanceCharge();
$allowanceCharge->ChargeIndicator = 'false'; // false = discount
$allowanceCharge->Amount = new \InvoiceNinja\EInvoice\Models\Peppol\AmountType\Amount();
$allowanceCharge->Amount->currencyID = $this->invoice->client->currency()->code;
$allowanceCharge->Amount->amount = (string)number_format($this->calculateTotalItemDiscountAmount($item),2, '.', '');
$this->allowance_total += $this->calculateTotalItemDiscountAmount($item);
// Add percentage if available
if ($item->discount > 0 && !$item->is_amount_discount) {
$allowanceCharge->BaseAmount = new \InvoiceNinja\EInvoice\Models\Peppol\AmountType\BaseAmount();
$allowanceCharge->BaseAmount->currencyID = $this->invoice->client->currency()->code;
$allowanceCharge->BaseAmount->amount = (string)round(($item->cost * $item->quantity),2);
$mfn = new \InvoiceNinja\EInvoice\Models\Peppol\NumericType\MultiplierFactorNumeric();
$mfn->value = (string) round($item->discount,2);
$allowanceCharge->MultiplierFactorNumeric = $mfn; // Convert percentage to decimal
}
// }
// Required reason
$allowanceCharge->AllowanceChargeReason = ctrans('texts.discount');
$line->Price = $basePrice;
$line->AllowanceCharge[] = $allowanceCharge;
} else {
// No discount case
$price = new Price();
$pa = new PriceAmount();
$pa->currencyID = $this->invoice->client->currency()->code;
$pa->amount = (string)$item->cost;
$price->PriceAmount = $pa;
$line->Price = $price;
}
$lines[] = $line;
}
return $lines;
}
/**
* getInvoiceLines
*
@ -889,8 +732,6 @@ class Peppol extends AbstractService
foreach($this->invoice->line_items as $key => $item) {
$base_price_amount = (string)$this->calculateAdjustedBaseAmount($item);
$_item = new Item();
$_item->Name = $item->product_key;
$_item->Description = $item->notes;
@ -969,7 +810,7 @@ class Peppol extends AbstractService
$line->Item = $_item;
/** Builds the tax map for the document */
$this->getItemTaxes($item);
// $this->getItemTaxes($item);
// Handle Price and Discounts
if ($item->discount > 0) {
@ -1154,161 +995,161 @@ class Peppol extends AbstractService
*
* @param object $item
* @return array
*/
private function getItemTaxes(object $item): array
{
$item_taxes = [];
// */
// private function getItemTaxes(object $item): array
// {
// $item_taxes = [];
$adjusted_base_amount = $this->calculateAdjustedBaseAmount($item);
// $adjusted_base_amount = $this->calculateAdjustedBaseAmount($item);
// if(strlen($item->tax_name1 ?? '') > 1) {
// // if(strlen($item->tax_name1 ?? '') > 1) {
$tax_amount = new TaxAmount();
$tax_amount->currencyID = $this->invoice->client->currency()->code;
$tax_amount->amount = $this->invoice->uses_inclusive_taxes ? $this->calcInclusiveLineTax($item->tax_rate1, $adjusted_base_amount) : $this->calcAmountLineTax($item->tax_rate1, $adjusted_base_amount);
$tax_subtotal = new TaxSubtotal();
$tax_subtotal->TaxAmount = $tax_amount;
// $tax_amount = new TaxAmount();
// $tax_amount->currencyID = $this->invoice->client->currency()->code;
// $tax_amount->amount = $this->invoice->uses_inclusive_taxes ? $this->calcInclusiveLineTax($item->tax_rate1, $adjusted_base_amount) : $this->calcAmountLineTax($item->tax_rate1, $adjusted_base_amount);
// $tax_subtotal = new TaxSubtotal();
// $tax_subtotal->TaxAmount = $tax_amount;
$taxable_amount = new TaxableAmount();
$taxable_amount->currencyID = $this->invoice->client->currency()->code;
$taxable_amount->amount = $this->invoice->uses_inclusive_taxes ? $adjusted_base_amount - $tax_amount->amount : $adjusted_base_amount;
$tax_subtotal->TaxableAmount = $taxable_amount;
// $taxable_amount = new TaxableAmount();
// $taxable_amount->currencyID = $this->invoice->client->currency()->code;
// $taxable_amount->amount = $this->invoice->uses_inclusive_taxes ? $adjusted_base_amount - $tax_amount->amount : $adjusted_base_amount;
// $tax_subtotal->TaxableAmount = $taxable_amount;
$tc = new TaxCategory();
// $tc = new TaxCategory();
$id = new ID();
$id->value = $this->getTaxType($item->tax_id);
// $id = new ID();
// $id->value = $this->getTaxType($item->tax_id);
if(floatval($item->tax_rate1) === 0.0)
$id->value = $this->resolveTaxExemptReason($item);
// if(floatval($item->tax_rate1) === 0.0)
// $id->value = $this->resolveTaxExemptReason($item);
$tc->ID = $id;
$tc->Percent = (string)$item->tax_rate1;
$ts = new TaxScheme();
// $tc->ID = $id;
// $tc->Percent = (string)$item->tax_rate1;
// $ts = new TaxScheme();
$id = new ID();
$id->value = $this->standardizeTaxSchemeId($item->tax_name1);
// $id = new ID();
// $id->value = $this->standardizeTaxSchemeId($item->tax_name1);
$jurisdiction = $this->getJurisdiction();
$ts->JurisdictionRegionAddress[] = $jurisdiction;
// $jurisdiction = $this->getJurisdiction();
// $ts->JurisdictionRegionAddress[] = $jurisdiction;
$ts->ID = $id;
$tc->TaxScheme = $ts;
$tax_subtotal->TaxCategory = $tc;
// $ts->ID = $id;
// $tc->TaxScheme = $ts;
// $tax_subtotal->TaxCategory = $tc;
$tax_total = new TaxTotal();
$tax_total->TaxAmount = $tax_amount;
$tax_total->TaxSubtotal[] = $tax_subtotal;
// $tax_total = new TaxTotal();
// $tax_total->TaxAmount = $tax_amount;
// $tax_total->TaxSubtotal[] = $tax_subtotal;
$this->tax_map[] = [
'taxableAmount' => $taxable_amount->amount,
'taxAmount' => $tax_amount->amount,
'percentage' => $item->tax_rate1,
];
// $this->tax_map[] = [
// 'taxableAmount' => $taxable_amount->amount,
// 'taxAmount' => $tax_amount->amount,
// 'percentage' => $item->tax_rate1,
// ];
$item_taxes[] = $tax_total;
// $item_taxes[] = $tax_total;
// }
// // }
if(strlen($item->tax_name2 ?? '') > 1) {
// if(strlen($item->tax_name2 ?? '') > 1) {
$tax_amount = new TaxAmount();
$tax_amount->currencyID = $this->invoice->client->currency()->code;
$tax_amount->amount = $this->invoice->uses_inclusive_taxes ? $this->calcInclusiveLineTax($item->tax_rate2, $item->line_total) : $this->calcAmountLineTax($item->tax_rate2, $item->line_total);
$tax_subtotal = new TaxSubtotal();
$tax_subtotal->TaxAmount = $tax_amount;
// $tax_amount = new TaxAmount();
// $tax_amount->currencyID = $this->invoice->client->currency()->code;
// $tax_amount->amount = $this->invoice->uses_inclusive_taxes ? $this->calcInclusiveLineTax($item->tax_rate2, $item->line_total) : $this->calcAmountLineTax($item->tax_rate2, $item->line_total);
// $tax_subtotal = new TaxSubtotal();
// $tax_subtotal->TaxAmount = $tax_amount;
$taxable_amount = new TaxableAmount();
$taxable_amount->currencyID = $this->invoice->client->currency()->code;
$taxable_amount->amount = $item->line_total;
$tax_subtotal->TaxableAmount = $taxable_amount;
// $taxable_amount = new TaxableAmount();
// $taxable_amount->currencyID = $this->invoice->client->currency()->code;
// $taxable_amount->amount = $item->line_total;
// $tax_subtotal->TaxableAmount = $taxable_amount;
$tc = new TaxCategory();
// $tc = new TaxCategory();
$id = new ID();
$id->value = $this->getTaxType($item->tax_id);
// $id = new ID();
// $id->value = $this->getTaxType($item->tax_id);
$tc->ID = $id;
$tc->Percent = (string)$item->tax_rate2;
$ts = new TaxScheme();
// $tc->ID = $id;
// $tc->Percent = (string)$item->tax_rate2;
// $ts = new TaxScheme();
$id = new ID();
$id->value = $this->standardizeTaxSchemeId($item->tax_name2);
// $id = new ID();
// $id->value = $this->standardizeTaxSchemeId($item->tax_name2);
$jurisdiction = $this->getJurisdiction();
$ts->JurisdictionRegionAddress[] = $jurisdiction;
// $jurisdiction = $this->getJurisdiction();
// $ts->JurisdictionRegionAddress[] = $jurisdiction;
$ts->ID = $id;
$tc->TaxScheme = $ts;
$tax_subtotal->TaxCategory = $tc;
// $ts->ID = $id;
// $tc->TaxScheme = $ts;
// $tax_subtotal->TaxCategory = $tc;
$tax_total = new TaxTotal();
$tax_total->TaxAmount = $tax_amount;
$tax_total->TaxSubtotal[] = $tax_subtotal;
// $tax_total = new TaxTotal();
// $tax_total->TaxAmount = $tax_amount;
// $tax_total->TaxSubtotal[] = $tax_subtotal;
$this->tax_map[] = [
'taxableAmount' => $taxable_amount->amount,
'taxAmount' => $tax_amount->amount,
'percentage' => $item->tax_rate2,
];
// $this->tax_map[] = [
// 'taxableAmount' => $taxable_amount->amount,
// 'taxAmount' => $tax_amount->amount,
// 'percentage' => $item->tax_rate2,
// ];
$item_taxes[] = $tax_total;
// $item_taxes[] = $tax_total;
}
// }
if(strlen($item->tax_name3 ?? '') > 1) {
// if(strlen($item->tax_name3 ?? '') > 1) {
$tax_amount = new TaxAmount();
$tax_amount->currencyID = $this->invoice->client->currency()->code;
// $tax_amount = new TaxAmount();
// $tax_amount->currencyID = $this->invoice->client->currency()->code;
$tax_amount->amount = $this->invoice->uses_inclusive_taxes ? $this->calcInclusiveLineTax($item->tax_rate3, $item->line_total) : $this->calcAmountLineTax($item->tax_rate3, $item->line_total);
// $tax_amount->amount = $this->invoice->uses_inclusive_taxes ? $this->calcInclusiveLineTax($item->tax_rate3, $item->line_total) : $this->calcAmountLineTax($item->tax_rate3, $item->line_total);
$tax_subtotal = new TaxSubtotal();
$tax_subtotal->TaxAmount = $tax_amount;
// $tax_subtotal = new TaxSubtotal();
// $tax_subtotal->TaxAmount = $tax_amount;
$taxable_amount = new TaxableAmount();
$taxable_amount->currencyID = $this->invoice->client->currency()->code;
$taxable_amount->amount = $item->line_total;
$tax_subtotal->TaxableAmount = $taxable_amount;
// $taxable_amount = new TaxableAmount();
// $taxable_amount->currencyID = $this->invoice->client->currency()->code;
// $taxable_amount->amount = $item->line_total;
// $tax_subtotal->TaxableAmount = $taxable_amount;
$tc = new TaxCategory();
// $tc = new TaxCategory();
$id = new ID();
$id->value = $this->getTaxType($item->tax_id);
// $id = new ID();
// $id->value = $this->getTaxType($item->tax_id);
$tc->ID = $id;
$tc->Percent = (string)$item->tax_rate3;
$ts = new TaxScheme();
// $tc->ID = $id;
// $tc->Percent = (string)$item->tax_rate3;
// $ts = new TaxScheme();
$id = new ID();
$id->value = $this->standardizeTaxSchemeId($item->tax_name3);
// $id = new ID();
// $id->value = $this->standardizeTaxSchemeId($item->tax_name3);
$jurisdiction = $this->getJurisdiction();
$ts->JurisdictionRegionAddress[] = $jurisdiction;
// $jurisdiction = $this->getJurisdiction();
// $ts->JurisdictionRegionAddress[] = $jurisdiction;
$ts->ID = $id;
$tc->TaxScheme = $ts;
$tax_subtotal->TaxCategory = $tc;
// $ts->ID = $id;
// $tc->TaxScheme = $ts;
// $tax_subtotal->TaxCategory = $tc;
$tax_total = new TaxTotal();
$tax_total->TaxAmount = $tax_amount;
$tax_total->TaxSubtotal[] = $tax_subtotal;
// $tax_total = new TaxTotal();
// $tax_total->TaxAmount = $tax_amount;
// $tax_total->TaxSubtotal[] = $tax_subtotal;
$this->tax_map[] = [
'taxableAmount' => $taxable_amount->amount,
'taxAmount' => $tax_amount->amount,
'percentage' => $item->tax_rate3,
];
// $this->tax_map[] = [
// 'taxableAmount' => $taxable_amount->amount,
// 'taxAmount' => $tax_amount->amount,
// 'percentage' => $item->tax_rate3,
// ];
$item_taxes[] = $tax_total;
// $item_taxes[] = $tax_total;
}
// }
return $item_taxes;
}
// return $item_taxes;
// }
/**
* getAccountingSupplierParty
@ -1627,49 +1468,29 @@ class Peppol extends AbstractService
{
$tax_total = new TaxTotal();
$taxes = $this->calc->getTaxMap();
$taxes = collect($this->tax_map)
->groupBy('percentage')
->map(function ($group) {
return [
'taxableAmount' => $group->sum('taxableAmount'),
'taxAmount' => $group->sum('taxAmount'),
'percentage' => $group->first()['percentage'],
];
});
foreach($taxes as $grouped_tax)
if(count($taxes) < 1)
{
// Required: TaxAmount (BT-110)
$tax_amount = new TaxAmount();
$tax_amount->currencyID = $this->invoice->client->currency()->code;
$tax_amount->amount = (string)$grouped_tax['taxAmount'];
$tax_amount->amount = (string)0;
$tax_total->TaxAmount = $tax_amount;
// Required: TaxSubtotal (BG-23)
$tax_subtotal = new TaxSubtotal();
// Required: TaxableAmount (BT-116)
$taxable_amount = new TaxableAmount();
$taxable_amount->currencyID = $this->invoice->client->currency()->code;
if (floatval($grouped_tax['taxAmount']) === 0.0) {
$taxable_amount->amount = (string)round($this->invoice->amount - $this->invoice->total_taxes, 2);
}
else
$taxable_amount->amount = (string)$grouped_tax['taxableAmount'];
$taxable_amount->amount = (string)round($this->invoice->amount - $this->invoice->total_taxes, 2);
$tax_subtotal->TaxableAmount = $taxable_amount;
// Required: TaxAmount (BT-117)
$subtotal_tax_amount = new TaxAmount();
$subtotal_tax_amount->currencyID = $this->invoice->client->currency()->code;
$subtotal_tax_amount->amount = (string)$grouped_tax['taxAmount'];
$subtotal_tax_amount->amount = (string)0;
$tax_subtotal->TaxAmount = $subtotal_tax_amount;
@ -1678,17 +1499,14 @@ class Peppol extends AbstractService
// Required: TaxCategory ID (BT-118)
$category_id = new ID();
$category_id->value = 'S'; // Standard rate
if(floatval($grouped_tax['taxAmount']) === 0.0){
$category_id->value = $this->tax_category_id; // Exempt
}
$category_id->value = $this->tax_category_id; // Exempt
$tax_category->ID = $category_id;
// Required: TaxCategory Rate (BT-119)
if($grouped_tax['percentage'] > 0)
$tax_category->Percent = (string)$grouped_tax['percentage'];
// if ($grouped_tax['tax_rate'] > 0) {
// $tax_category->Percent = (string)$grouped_tax['tax_rate'];
// }
// Required: TaxScheme (BG-23)
$tax_scheme = new TaxScheme();
@ -1703,6 +1521,63 @@ class Peppol extends AbstractService
$tax_total->TaxSubtotal[] = $tax_subtotal;
$this->p_invoice->TaxTotal[] = $tax_total;
return $this;
}
foreach($taxes as $grouped_tax)
{
// Required: TaxAmount (BT-110)
$tax_amount = new TaxAmount();
$tax_amount->currencyID = $this->invoice->client->currency()->code;
$tax_amount->amount = (string)$grouped_tax['total'];
$tax_total->TaxAmount = $tax_amount;
// Required: TaxSubtotal (BG-23)
$tax_subtotal = new TaxSubtotal();
// Required: TaxableAmount (BT-116)
$taxable_amount = new TaxableAmount();
$taxable_amount->currencyID = $this->invoice->client->currency()->code;
$taxable_amount->amount = (string)round($grouped_tax['base_amount'],2);
$tax_subtotal->TaxableAmount = $taxable_amount;
// Required: TaxAmount (BT-117)
$subtotal_tax_amount = new TaxAmount();
$subtotal_tax_amount->currencyID = $this->invoice->client->currency()->code;
$subtotal_tax_amount->amount = (string)round($grouped_tax['total'],2);
$tax_subtotal->TaxAmount = $subtotal_tax_amount;
// Required: TaxCategory (BG-23)
$tax_category = new TaxCategory();
// Required: TaxCategory ID (BT-118)
$category_id = new ID();
$category_id->value = $this->getTaxType($grouped_tax['tax_id']); // Standard rate
$tax_category->ID = $category_id;
// Required: TaxCategory Rate (BT-119)
if($grouped_tax['tax_rate'] > 0)
$tax_category->Percent = (string)$grouped_tax['tax_rate'];
// Required: TaxScheme (BG-23)
$tax_scheme = new TaxScheme();
$scheme_id = new ID();
$scheme_id->value = $this->standardizeTaxSchemeId("taxname");
$tax_scheme->ID = $scheme_id;
$tax_category->TaxScheme = $tax_scheme;
$tax_subtotal->TaxCategory = $this->globalTaxCategories[0];
$tax_total->TaxSubtotal[] = $tax_subtotal;
$this->p_invoice->TaxTotal[] = $tax_total;
}
return $this;

View File

@ -55,7 +55,7 @@ return [
|
*/
'after_commit' => false,
'after_commit' => true,
/*
|--------------------------------------------------------------------------

View File

@ -269,7 +269,7 @@ class PeppolTest extends TestCase
}
for($x=0; $x<100; $x++){
for($x=0; $x<1000; $x++){
$scenario = $scenarios[0];
@ -292,6 +292,8 @@ class PeppolTest extends TestCase
$validator->validate();
if (count($validator->getErrors()) > 0) {
nlog("index {$x}");
nlog($invoice->withoutRelations()->toArray());
nlog($p->toXml());
nlog($validator->getErrors());
}