Expand taxdata object to accept nexus information
This commit is contained in:
parent
75ba84082e
commit
39bdbb9c21
|
|
@ -39,6 +39,10 @@ class BaseRule implements RuleInterface
|
|||
|
||||
public string $client_subregion = '';
|
||||
|
||||
private string $nexus = '';
|
||||
|
||||
private string $country_nexus = '';
|
||||
|
||||
public array $eu_country_codes = [
|
||||
'AT', // Austria
|
||||
'BE', // Belgium
|
||||
|
|
@ -187,7 +191,6 @@ class BaseRule implements RuleInterface
|
|||
|
||||
$this->resolveRegions();
|
||||
|
||||
|
||||
if (!$this->isTaxableRegion()) {
|
||||
$this->tax_data = null;
|
||||
$this->tax_rate1 = 0;
|
||||
|
|
@ -234,7 +237,6 @@ class BaseRule implements RuleInterface
|
|||
* Destination - Client Tax Data
|
||||
*
|
||||
*/
|
||||
|
||||
$tax_data = false;
|
||||
|
||||
if ($this->seller_region == 'US' && $this->client_region == 'US') {
|
||||
|
|
@ -252,20 +254,36 @@ class BaseRule implements RuleInterface
|
|||
if ($company->origin_tax_data->originDestination == 'O' && ($company->tax_data?->seller_subregion == $this->client_subregion)) {
|
||||
|
||||
$tax_data = $company->origin_tax_data;
|
||||
$tax_data->nexus = $tax_data->geoState;
|
||||
$tax_data->country_nexus = 'US';
|
||||
|
||||
} elseif ($this->invoice->location && $this->invoice->location->is_shipping_location && $this->invoice->location->tax_data) {
|
||||
|
||||
$tax_data = $this->invoice->location->tax_data;
|
||||
|
||||
} elseif ($this->client->tax_data) {
|
||||
$tax_data->nexus = $tax_data->geoState;
|
||||
$tax_data->country_nexus = 'US';
|
||||
|
||||
} elseif ($this->client->tax_data) {
|
||||
|
||||
$tax_data = $this->client->tax_data;
|
||||
|
||||
$tax_data->nexus = $tax_data->geoState;
|
||||
$tax_data->country_nexus = 'US';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$this->saveTaxData($tax_data);
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
private function saveTaxData(mixed $tax_data): self
|
||||
{
|
||||
|
||||
/** Applies the tax data to the invoice */
|
||||
if (($this->invoice instanceof Invoice || $this->invoice instanceof Quote) && $tax_data) {
|
||||
|
||||
|
|
@ -283,10 +301,8 @@ class BaseRule implements RuleInterface
|
|||
}
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resolve Regions & Subregions
|
||||
*
|
||||
|
|
@ -361,6 +377,9 @@ class BaseRule implements RuleInterface
|
|||
$this->tax_rate1 = $this->client->company->tax_data->regions->AU->subregions->AU->tax_rate;
|
||||
$this->tax_name1 = $this->client->company->tax_data->regions->AU->subregions->AU->tax_name;
|
||||
|
||||
$this->nexus = 'AU';
|
||||
$this->country_nexus = 'AU';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
@ -380,18 +399,33 @@ class BaseRule implements RuleInterface
|
|||
if ($is_b2c && $is_over_threshold) {
|
||||
$this->tax_rate1 = $this->client->company->tax_data->regions->{$this->client_region}->subregions->{$this->client_subregion}->tax_rate;
|
||||
$this->tax_name1 = $this->client->company->tax_data->regions->{$this->client_region}->subregions->{$this->client_subregion}->tax_name;
|
||||
|
||||
$this->nexus = $this->client_subregion;
|
||||
$this->country_nexus = $this->client_region;
|
||||
}
|
||||
// Otherwise, use origin country tax rates
|
||||
elseif (in_array($company_country_code, $this->eu_country_codes)) {
|
||||
$this->tax_rate1 = $this->client->company->tax_data->regions->{$this->client_region}->subregions->{$company_country_code}->tax_rate;
|
||||
$this->tax_name1 = $this->client->company->tax_data->regions->{$this->client_region}->subregions->{$company_country_code}->tax_name;
|
||||
|
||||
$this->nexus = $company_country_code;
|
||||
$this->country_nexus = $company_country_code;
|
||||
|
||||
} elseif ($is_over_threshold) {
|
||||
$this->tax_rate1 = $this->client->company->tax_data->regions->{$this->client_region}->subregions->{$this->client_subregion}->tax_rate;
|
||||
$this->tax_name1 = $this->client->company->tax_data->regions->{$this->client_region}->subregions->{$this->client_subregion}->tax_name;
|
||||
|
||||
$this->nexus = $this->client_subregion;
|
||||
$this->country_nexus = $this->client_region;
|
||||
|
||||
}
|
||||
} else {
|
||||
$this->tax_rate1 = $this->client->company->tax_data->regions->{$this->client_region}->subregions->{$this->client_subregion}->tax_rate;
|
||||
$this->tax_name1 = $this->client->company->tax_data->regions->{$this->client_region}->subregions->{$this->client_subregion}->tax_name;
|
||||
|
||||
$this->nexus = $this->client_subregion;
|
||||
$this->country_nexus = $this->client_region;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,9 @@ class Response
|
|||
public float $district5UseTax = 0;
|
||||
/* US SPECIFIC TAX CODES */
|
||||
|
||||
public string $nexus = "";
|
||||
public string $country_nexus = "";
|
||||
|
||||
public string $originDestination = "D"; // defines if the client origin is the locale where the tax is remitted to
|
||||
|
||||
public function __construct($data = null)
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ use Illuminate\Contracts\Translation\HasLocalePreference;
|
|||
* @property string|null $private_notes
|
||||
* @property string|null $public_notes
|
||||
* @property string|null $client_hash
|
||||
* @property string|null $classification
|
||||
* @property string|null $logo
|
||||
* @property string|null $phone
|
||||
* @property string|null $routing_id
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@ class TaxReport
|
|||
|
||||
private array $data = [];
|
||||
|
||||
private string $currency_format;
|
||||
|
||||
private string $number_format;
|
||||
|
||||
public function __construct(public Company $company, public TaxSummaryReport $tsr, public Builder $query)
|
||||
{
|
||||
}
|
||||
|
|
@ -34,6 +38,7 @@ class TaxReport
|
|||
$this->spreadsheet = new Spreadsheet();
|
||||
|
||||
$this->buildData()
|
||||
->setCurrencyFormat()
|
||||
->createSummarySheet()
|
||||
->createInvoiceSummarySheetAccrual()
|
||||
->createInvoiceSummarySheetCash()
|
||||
|
|
@ -46,12 +51,29 @@ class TaxReport
|
|||
|
||||
}
|
||||
|
||||
public function setCurrencyFormat()
|
||||
{
|
||||
$currency = $this->company->currency();
|
||||
|
||||
$formatted = number_format(9990.00, $currency->precision, $currency->decimal_separator, $currency->thousand_separator);
|
||||
$formatted = str_replace('9', '#', $formatted);
|
||||
$this->number_format = $formatted;
|
||||
|
||||
$formatted = "{$currency->symbol}{$formatted}";
|
||||
$this->currency_format = $formatted;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function createSummarySheet()
|
||||
{
|
||||
|
||||
$worksheet = $this->spreadsheet->getActiveSheet();
|
||||
$worksheet->setTitle(ctrans('texts.tax_summary'));
|
||||
|
||||
// Add summary data and formatting here if needed
|
||||
// For now, this sheet is empty but could be populated with summary statistics
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
@ -59,9 +81,15 @@ class TaxReport
|
|||
public function createInvoiceSummarySheetAccrual()
|
||||
{
|
||||
|
||||
$newWorksheet = $this->spreadsheet->createSheet();
|
||||
$newWorksheet->setTitle(ctrans('texts.invoice')." ".ctrans('texts.cash_vs_accrual'));
|
||||
$newWorksheet->fromArray($this->data['invoices'], null, 'A1');
|
||||
$worksheet = $this->spreadsheet->createSheet();
|
||||
$worksheet->setTitle(ctrans('texts.invoice')." ".ctrans('texts.cash_vs_accrual'));
|
||||
$worksheet->fromArray($this->data['invoices'], null, 'A1');
|
||||
|
||||
$worksheet->getStyle('B:B')->getNumberFormat()->setFormatCode($this->company->date_format()); // Invoice date column
|
||||
$worksheet->getStyle('C:C')->getNumberFormat()->setFormatCode($this->currency_format); // Invoice total column
|
||||
$worksheet->getStyle('D:D')->getNumberFormat()->setFormatCode($this->currency_format); // Paid amount column
|
||||
$worksheet->getStyle('E:E')->getNumberFormat()->setFormatCode($this->currency_format); // Total taxes column
|
||||
$worksheet->getStyle('F:F')->getNumberFormat()->setFormatCode($this->currency_format); // Tax paid column
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
@ -73,18 +101,33 @@ class TaxReport
|
|||
return $invoice[3] != 0;
|
||||
})->toArray();
|
||||
|
||||
$newWorksheet = $this->spreadsheet->createSheet();
|
||||
$newWorksheet->setTitle(ctrans('texts.invoice')." ".ctrans('texts.cash_accounting'));
|
||||
$newWorksheet->fromArray($cash_invoices, null, 'A1');
|
||||
$worksheet = $this->spreadsheet->createSheet();
|
||||
$worksheet->setTitle(ctrans('texts.invoice')." ".ctrans('texts.cash_accounting'));
|
||||
$worksheet->fromArray($cash_invoices, null, 'A1');
|
||||
$worksheet->getStyle('B:B')->getNumberFormat()->setFormatCode($this->company->date_format()); // Invoice date column
|
||||
$worksheet->getStyle('C:C')->getNumberFormat()->setFormatCode($this->currency_format); // Invoice total column
|
||||
$worksheet->getStyle('D:D')->getNumberFormat()->setFormatCode($this->currency_format); // Paid amount column
|
||||
$worksheet->getStyle('E:E')->getNumberFormat()->setFormatCode($this->currency_format); // Total taxes column
|
||||
$worksheet->getStyle('F:F')->getNumberFormat()->setFormatCode($this->currency_format); // Tax paid column
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function createInvoiceItemSummarySheetAccrual()
|
||||
{
|
||||
|
||||
$newWorksheet = $this->spreadsheet->createSheet();
|
||||
$newWorksheet->setTitle(ctrans('texts.invoice_item')." ".ctrans('texts.cash_vs_accrual'));
|
||||
$newWorksheet->fromArray($this->data['invoice_items'], null, 'A1');
|
||||
$worksheet = $this->spreadsheet->createSheet();
|
||||
$worksheet->setTitle(ctrans('texts.invoice_item')." ".ctrans('texts.cash_vs_accrual'));
|
||||
$worksheet->fromArray($this->data['invoice_items'], null, 'A1');
|
||||
|
||||
$worksheet->getStyle('B:B')->getNumberFormat()->setFormatCode($this->company->date_format()); // Invoice date column
|
||||
$worksheet->getStyle('C:C')->getNumberFormat()->setFormatCode($this->currency_format); // Invoice total column
|
||||
$worksheet->getStyle('D:D')->getNumberFormat()->setFormatCode($this->currency_format); // Paid amount column
|
||||
$worksheet->getStyle('F:F')->getNumberFormat()->setFormatCode($this->number_format."%"); // Tax rate column
|
||||
$worksheet->getStyle('G:G')->getNumberFormat()->setFormatCode($this->currency_format); // Tax amount column
|
||||
$worksheet->getStyle('H:H')->getNumberFormat()->setFormatCode($this->currency_format); // Tax paid column
|
||||
$worksheet->getStyle('I:I')->getNumberFormat()->setFormatCode($this->currency_format); // Taxable amount column
|
||||
// Column J (tax_nexus) is text, so no special formatting needed
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
@ -96,9 +139,18 @@ class TaxReport
|
|||
return $invoice_item[3] != 0;
|
||||
})->toArray();
|
||||
|
||||
$newWorksheet = $this->spreadsheet->createSheet();
|
||||
$newWorksheet->setTitle(ctrans('texts.invoice_item')." ".ctrans('texts.cash_accounting'));
|
||||
$newWorksheet->fromArray($cash_invoice_items, null, 'A1');
|
||||
$worksheet = $this->spreadsheet->createSheet();
|
||||
$worksheet->setTitle(ctrans('texts.invoice_item')." ".ctrans('texts.cash_accounting'));
|
||||
$worksheet->fromArray($cash_invoice_items, null, 'A1');
|
||||
|
||||
$worksheet->getStyle('B:B')->getNumberFormat()->setFormatCode($this->company->date_format()); // Invoice date column
|
||||
$worksheet->getStyle('C:C')->getNumberFormat()->setFormatCode($this->currency_format); // Invoice total column
|
||||
$worksheet->getStyle('D:D')->getNumberFormat()->setFormatCode($this->currency_format); // Paid amount column
|
||||
$worksheet->getStyle('F:F')->getNumberFormat()->setFormatCode($this->number_format."%"); // Tax rate column
|
||||
$worksheet->getStyle('G:G')->getNumberFormat()->setFormatCode($this->currency_format); // Tax amount column
|
||||
$worksheet->getStyle('H:H')->getNumberFormat()->setFormatCode($this->currency_format); // Tax paid column
|
||||
$worksheet->getStyle('I:I')->getNumberFormat()->setFormatCode($this->currency_format); // Taxable amount column
|
||||
// Column J (tax_nexus) is text, so no special formatting needed
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
@ -130,6 +182,7 @@ class TaxReport
|
|||
ctrans('texts.tax_amount'),
|
||||
ctrans('texts.tax_paid'),
|
||||
ctrans('texts.taxable_amount'),
|
||||
ctrans('texts.tax_nexus'),
|
||||
];
|
||||
|
||||
$offset = $this->company->timezone_offset();
|
||||
|
|
@ -181,6 +234,7 @@ class TaxReport
|
|||
$tax['total'],
|
||||
$tax['total'] * $pro_rata_payment_ratio,
|
||||
$tax['base_amount'] ?? $calc->getNetSubtotal(),
|
||||
$tax['nexus'] ?? '',
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -192,16 +246,20 @@ class TaxReport
|
|||
public function getXlsFile()
|
||||
{
|
||||
|
||||
$tempFile = tempnam(sys_get_temp_dir(), 'tax_report_');
|
||||
|
||||
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($this->spreadsheet);
|
||||
$writer->save('/tmp/tax_report.xlsx');
|
||||
$writer->save($tempFile);
|
||||
|
||||
// return $this->spreadsheet;
|
||||
// Use output buffering to capture the file content
|
||||
// ob_start();
|
||||
// $this->spreadsheet->save('php://output');
|
||||
// $fileContent = ob_get_clean();
|
||||
$writer->save('/home/david/ttx.xslx');
|
||||
// Read file content
|
||||
$fileContent = file_get_contents($tempFile);
|
||||
|
||||
nlog($tempFile);
|
||||
// Clean up temp file
|
||||
// unlink($tempFile);
|
||||
|
||||
return $fileContent;
|
||||
|
||||
// return $fileContent;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5611,6 +5611,7 @@ $lang = array(
|
|||
'auto_send_help' => 'Automatically emails the invoice to the client',
|
||||
'include_project_tasks' => 'Include Project Tasks',
|
||||
'include_project_tasks_help' => 'Also invoice tasks that are part of a project',
|
||||
'tax_nexus' => 'Tax Nexus',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
|
|
|||
Loading…
Reference in New Issue