Working on additional helper to debug bad imports

This commit is contained in:
David Bomba
2026-01-14 18:31:50 +11:00
parent 33d300f4e6
commit f6f888decc
8 changed files with 98 additions and 42 deletions

View File

@@ -236,7 +236,7 @@ class PayPalBalanceAffecting
// $csv = Reader::createFromString($csvFile);
// $csv = Reader::fromString($csvFile);
// // $csvdelimiter = self::detectDelimiter($csvfile);
// $csv->setDelimiter(",");
// $stmt = new Statement();

View File

@@ -11,37 +11,42 @@
namespace App\Helpers\Cache;
use Illuminate\Contracts\Redis\Factory as RedisFactory;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Redis;
class Atomic
{
public static function set($key, $value = true, $ttl = 1): bool
public static function set(string $key, mixed $value = true, int $ttl = 1): bool
{
$new_ttl = now()->addSeconds($ttl);
try {
return Redis::connection('sentinel-cache')->set($key, $value, 'EX', $ttl, 'NX') ? true : false;
/** @var RedisFactory $redis */
$redis = app('redis');
$result = $redis->connection('sentinel-cache')->command('set', [$key, $value, 'EX', $ttl, 'NX']);
return (bool) $result;
} catch (\Throwable) {
return Cache::add($key, $value, $new_ttl) ? true : false;
}
}
public static function get($key)
public static function get(string $key): mixed
{
try {
return Redis::connection('sentinel-cache')->get($key);
/** @var RedisFactory $redis */
$redis = app('redis');
return $redis->connection('sentinel-cache')->command('get', [$key]);
} catch (\Throwable) {
return Cache::get($key);
}
}
public static function del($key)
public static function del(string $key): mixed
{
try {
return Redis::connection('sentinel-cache')->del($key);
/** @var RedisFactory $redis */
$redis = app('redis');
return $redis->connection('sentinel-cache')->command('del', [$key]);
} catch (\Throwable) {
return Cache::forget($key);
}

View File

@@ -446,7 +446,6 @@ class ImportController extends Controller
$csv = Reader::fromString($csvfile);
// $csv = Reader::createFromString($csvfile);
$csvdelimiter = self::detectDelimiter($csvfile);
$csv->setDelimiter($csvdelimiter);
$stmt = new Statement();

View File

@@ -12,33 +12,35 @@
namespace App\Import\Providers;
use App\Models\User;
use App\Utils\Ninja;
use App\Models\Quote;
use League\Csv\Reader;
use App\Models\Company;
use App\Models\Invoice;
use League\Csv\Statement;
use App\Factory\TaskFactory;
use App\Factory\QuoteFactory;
use App\Factory\ClientFactory;
use Illuminate\Support\Carbon;
use App\Factory\InvoiceFactory;
use App\Factory\PaymentFactory;
use App\Factory\QuoteFactory;
use App\Factory\RecurringInvoiceFactory;
use App\Factory\TaskFactory;
use App\Http\Requests\Quote\StoreQuoteRequest;
use App\Import\ImportException;
use App\Jobs\Mail\NinjaMailerJob;
use App\Jobs\Mail\NinjaMailerObject;
use App\Mail\Import\CsvImportCompleted;
use App\Models\Company;
use App\Models\Invoice;
use App\Models\Quote;
use App\Models\User;
use App\Repositories\ClientRepository;
use App\Repositories\InvoiceRepository;
use App\Repositories\PaymentRepository;
use App\Repositories\QuoteRepository;
use App\Repositories\RecurringInvoiceRepository;
use App\Repositories\TaskRepository;
use App\Utils\Traits\CleanLineItems;
use Illuminate\Support\Carbon;
use App\Repositories\QuoteRepository;
use Illuminate\Support\Facades\Cache;
use App\Repositories\ClientRepository;
use App\Mail\Import\CsvImportCompleted;
use App\Repositories\InvoiceRepository;
use App\Repositories\PaymentRepository;
use App\Factory\RecurringInvoiceFactory;
use Illuminate\Support\Facades\Validator;
use League\Csv\Reader;
use League\Csv\Statement;
use App\Http\Requests\Quote\StoreQuoteRequest;
use App\Repositories\RecurringInvoiceRepository;
use App\Notifications\Ninja\GenericNinjaAdminNotification;
class BaseImport
{
@@ -70,6 +72,8 @@ class BaseImport
public array $entity_count = [];
public bool $store_import_for_research = false;
public function __construct(array $request, Company $company)
{
$this->company = $company;
@@ -107,7 +111,7 @@ class BaseImport
$csv = base64_decode($base64_encoded_csv);
// $csv = mb_convert_encoding($csv, 'UTF-8', 'UTF-8');
$csv = Reader::createFromString($csv);
$csv = Reader::fromString($csv);
$csvdelimiter = self::detectDelimiter($csv);
$csv->setDelimiter($csvdelimiter);
@@ -119,7 +123,8 @@ class BaseImport
// Remove Invoice Ninja headers
if (
count($headers) &&
is_array($headers) &&
count($headers) > 0 &&
count($data) > 4 &&
$this->import_type === 'csv'
) {
@@ -320,7 +325,8 @@ class BaseImport
$entity->saveQuietly();
$count++;
}
} catch (\Exception $ex) {
}
catch (\Exception $ex) {
if (\DB::connection(config('database.default'))->transactionLevel() > 0) {
\DB::connection(config('database.default'))->rollBack();
}
@@ -339,6 +345,20 @@ class BaseImport
nlog("Ingest {$ex->getMessage()}");
nlog($record);
$this->store_import_for_research = true;
}
catch(\Throwable $ex){
if (\DB::connection(config('database.default'))->transactionLevel() > 0) {
\DB::connection(config('database.default'))->rollBack();
}
nlog("Throwable:: Ingest {$ex->getMessage()}");
nlog($record);
$this->store_import_for_research = true;
}
}
@@ -945,6 +965,40 @@ class BaseImport
$nmo->to_user = $this->company->owner();
NinjaMailerJob::dispatch($nmo, true);
if (Ninja::isHosted() && $this->store_import_for_research) {
$content = [
'company_key' => $this->company->company_key,
'class_name' => class_basename($this),
'hash' => $this->hash,
];
$potential_imports = [
'client',
'product',
'invoice',
'payment',
'vendor',
'expense',
'quote',
'bank_transaction',
'task',
'recurring_invoice',
];
foreach ($potential_imports as $import) {
if(Cache::has($this->hash.'-'.$import)) {
// store on s3
// Cache::put($this->hash.'-'.$import, Cache::get($this->hash.'-'.$import), 60*60*24*2);
}
}
$this->company->notification(new GenericNinjaAdminNotification($content))->ninja();
}
}
public function preTransform(array $data, $entity_type)

View File

@@ -382,7 +382,6 @@ class Csv extends BaseImport implements ImportInterface
$this->entity_count['tasks'] = $task_count;
}
public function transform(array $data)

View File

@@ -937,11 +937,10 @@ Código seguro de verificación (CSV): {$verifactu_log->status}";
$tax_label = '';
if (collect($this->entity->line_items)->contains('tax_id', \App\Models\Product::PRODUCT_TYPE_REVERSE_TAX)) {
$tax_label .= ctrans('texts.reverse_tax_info') . "<br>";
$tax_label .= ctrans('texts.reverse_tax_info') . " <br>";
}
if ((int)$this->client->country_id !== (int)$this->company->settings->country_id) {
$tax_label .= ctrans('texts.intracommunity_tax_info') . "<br>";
else if ((int)$this->client->country_id !== (int)$this->company->settings->country_id) {
$tax_label .= ctrans('texts.intracommunity_tax_info') . " <br>";
if ($this->entity_calc->getTotalTaxes() > 0) {
$tax_label = '';

View File

@@ -178,7 +178,7 @@ input:checked ~ .dot {
Enterprise Plan
</h3>
<p class="text-5xl font-bold text-center text-white" id="y_plan_price">
$140
$180
</p>
<p class="text-xs text-center uppercase text-white">
yearly
@@ -275,12 +275,12 @@ document.getElementById('handleProYearlyClick').addEventListener('click', functi
});
const price_map = new Map();
//monthly
price_map.set('7LDdwRb1YK', '$16');
price_map.set('7LDdwRb1YK', '$18');
price_map.set('MVyb8mdvAZ', '$32');
price_map.set('WpmbkR5azJ', '$54');
price_map.set('k8mepY2aMy', '$84');
//yearly
price_map.set('LYqaQWldnj', '$160');
price_map.set('LYqaQWldnj', '$180');
price_map.set('kQBeX6mbyK', '$320');
price_map.set('GELe32Qd69', '$540');
price_map.set('MVyb86oevA', '$840');

View File

@@ -1134,7 +1134,7 @@ class ReportCsvGenerationTest extends TestCase
$csv = $response->body();
$reader = Reader::createFromString($csv);
$reader = Reader::fromString($csv);
$reader->setHeaderOffset(0);
$res = $reader->fetchColumnByName('Street');
@@ -1983,7 +1983,7 @@ class ReportCsvGenerationTest extends TestCase
$csv = $response->body();
$reader = Reader::createFromString($csv);
$reader = Reader::fromString($csv);
$reader->setHeaderOffset(0);
$res = $reader->fetchColumnByName('Contact First Name');
@@ -2014,7 +2014,7 @@ class ReportCsvGenerationTest extends TestCase
private function getFirstValueByColumn($csv, $column)
{
$reader = Reader::createFromString($csv);
$reader = Reader::fromString($csv);
$reader->setHeaderOffset(0);
$res = $reader->fetchColumnByName($column);