mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2026-03-03 03:07:01 +00:00
Working on additional helper to debug bad imports
This commit is contained in:
@@ -236,7 +236,7 @@ class PayPalBalanceAffecting
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// $csv = Reader::createFromString($csvFile);
|
// $csv = Reader::fromString($csvFile);
|
||||||
// // $csvdelimiter = self::detectDelimiter($csvfile);
|
// // $csvdelimiter = self::detectDelimiter($csvfile);
|
||||||
// $csv->setDelimiter(",");
|
// $csv->setDelimiter(",");
|
||||||
// $stmt = new Statement();
|
// $stmt = new Statement();
|
||||||
|
|||||||
@@ -11,37 +11,42 @@
|
|||||||
|
|
||||||
namespace App\Helpers\Cache;
|
namespace App\Helpers\Cache;
|
||||||
|
|
||||||
|
use Illuminate\Contracts\Redis\Factory as RedisFactory;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Support\Facades\Redis;
|
|
||||||
|
|
||||||
class Atomic
|
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);
|
$new_ttl = now()->addSeconds($ttl);
|
||||||
|
|
||||||
try {
|
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) {
|
} catch (\Throwable) {
|
||||||
return Cache::add($key, $value, $new_ttl) ? true : false;
|
return Cache::add($key, $value, $new_ttl) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function get($key)
|
public static function get(string $key): mixed
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return Redis::connection('sentinel-cache')->get($key);
|
/** @var RedisFactory $redis */
|
||||||
|
$redis = app('redis');
|
||||||
|
return $redis->connection('sentinel-cache')->command('get', [$key]);
|
||||||
} catch (\Throwable) {
|
} catch (\Throwable) {
|
||||||
return Cache::get($key);
|
return Cache::get($key);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function del($key)
|
public static function del(string $key): mixed
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return Redis::connection('sentinel-cache')->del($key);
|
/** @var RedisFactory $redis */
|
||||||
|
$redis = app('redis');
|
||||||
|
return $redis->connection('sentinel-cache')->command('del', [$key]);
|
||||||
} catch (\Throwable) {
|
} catch (\Throwable) {
|
||||||
return Cache::forget($key);
|
return Cache::forget($key);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -446,7 +446,6 @@ class ImportController extends Controller
|
|||||||
|
|
||||||
$csv = Reader::fromString($csvfile);
|
$csv = Reader::fromString($csvfile);
|
||||||
|
|
||||||
// $csv = Reader::createFromString($csvfile);
|
|
||||||
$csvdelimiter = self::detectDelimiter($csvfile);
|
$csvdelimiter = self::detectDelimiter($csvfile);
|
||||||
$csv->setDelimiter($csvdelimiter);
|
$csv->setDelimiter($csvdelimiter);
|
||||||
$stmt = new Statement();
|
$stmt = new Statement();
|
||||||
|
|||||||
@@ -12,33 +12,35 @@
|
|||||||
|
|
||||||
namespace App\Import\Providers;
|
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 App\Factory\ClientFactory;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
use App\Factory\InvoiceFactory;
|
use App\Factory\InvoiceFactory;
|
||||||
use App\Factory\PaymentFactory;
|
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\Import\ImportException;
|
||||||
use App\Jobs\Mail\NinjaMailerJob;
|
use App\Jobs\Mail\NinjaMailerJob;
|
||||||
use App\Jobs\Mail\NinjaMailerObject;
|
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\Repositories\TaskRepository;
|
||||||
use App\Utils\Traits\CleanLineItems;
|
use App\Utils\Traits\CleanLineItems;
|
||||||
use Illuminate\Support\Carbon;
|
use App\Repositories\QuoteRepository;
|
||||||
use Illuminate\Support\Facades\Cache;
|
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 Illuminate\Support\Facades\Validator;
|
||||||
use League\Csv\Reader;
|
use App\Http\Requests\Quote\StoreQuoteRequest;
|
||||||
use League\Csv\Statement;
|
use App\Repositories\RecurringInvoiceRepository;
|
||||||
|
use App\Notifications\Ninja\GenericNinjaAdminNotification;
|
||||||
|
|
||||||
class BaseImport
|
class BaseImport
|
||||||
{
|
{
|
||||||
@@ -70,6 +72,8 @@ class BaseImport
|
|||||||
|
|
||||||
public array $entity_count = [];
|
public array $entity_count = [];
|
||||||
|
|
||||||
|
public bool $store_import_for_research = false;
|
||||||
|
|
||||||
public function __construct(array $request, Company $company)
|
public function __construct(array $request, Company $company)
|
||||||
{
|
{
|
||||||
$this->company = $company;
|
$this->company = $company;
|
||||||
@@ -107,7 +111,7 @@ class BaseImport
|
|||||||
$csv = base64_decode($base64_encoded_csv);
|
$csv = base64_decode($base64_encoded_csv);
|
||||||
// $csv = mb_convert_encoding($csv, 'UTF-8', 'UTF-8');
|
// $csv = mb_convert_encoding($csv, 'UTF-8', 'UTF-8');
|
||||||
|
|
||||||
$csv = Reader::createFromString($csv);
|
$csv = Reader::fromString($csv);
|
||||||
$csvdelimiter = self::detectDelimiter($csv);
|
$csvdelimiter = self::detectDelimiter($csv);
|
||||||
|
|
||||||
$csv->setDelimiter($csvdelimiter);
|
$csv->setDelimiter($csvdelimiter);
|
||||||
@@ -119,7 +123,8 @@ class BaseImport
|
|||||||
|
|
||||||
// Remove Invoice Ninja headers
|
// Remove Invoice Ninja headers
|
||||||
if (
|
if (
|
||||||
count($headers) &&
|
is_array($headers) &&
|
||||||
|
count($headers) > 0 &&
|
||||||
count($data) > 4 &&
|
count($data) > 4 &&
|
||||||
$this->import_type === 'csv'
|
$this->import_type === 'csv'
|
||||||
) {
|
) {
|
||||||
@@ -320,7 +325,8 @@ class BaseImport
|
|||||||
$entity->saveQuietly();
|
$entity->saveQuietly();
|
||||||
$count++;
|
$count++;
|
||||||
}
|
}
|
||||||
} catch (\Exception $ex) {
|
}
|
||||||
|
catch (\Exception $ex) {
|
||||||
if (\DB::connection(config('database.default'))->transactionLevel() > 0) {
|
if (\DB::connection(config('database.default'))->transactionLevel() > 0) {
|
||||||
\DB::connection(config('database.default'))->rollBack();
|
\DB::connection(config('database.default'))->rollBack();
|
||||||
}
|
}
|
||||||
@@ -339,6 +345,20 @@ class BaseImport
|
|||||||
|
|
||||||
nlog("Ingest {$ex->getMessage()}");
|
nlog("Ingest {$ex->getMessage()}");
|
||||||
nlog($record);
|
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();
|
$nmo->to_user = $this->company->owner();
|
||||||
|
|
||||||
NinjaMailerJob::dispatch($nmo, true);
|
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)
|
public function preTransform(array $data, $entity_type)
|
||||||
|
|||||||
@@ -382,7 +382,6 @@ class Csv extends BaseImport implements ImportInterface
|
|||||||
|
|
||||||
$this->entity_count['tasks'] = $task_count;
|
$this->entity_count['tasks'] = $task_count;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function transform(array $data)
|
public function transform(array $data)
|
||||||
|
|||||||
@@ -937,11 +937,10 @@ Código seguro de verificación (CSV): {$verifactu_log->status}";
|
|||||||
$tax_label = '';
|
$tax_label = '';
|
||||||
|
|
||||||
if (collect($this->entity->line_items)->contains('tax_id', \App\Models\Product::PRODUCT_TYPE_REVERSE_TAX)) {
|
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>";
|
||||||
}
|
}
|
||||||
|
else if ((int)$this->client->country_id !== (int)$this->company->settings->country_id) {
|
||||||
if ((int)$this->client->country_id !== (int)$this->company->settings->country_id) {
|
$tax_label .= ctrans('texts.intracommunity_tax_info') . " <br>";
|
||||||
$tax_label .= ctrans('texts.intracommunity_tax_info') . "<br>";
|
|
||||||
|
|
||||||
if ($this->entity_calc->getTotalTaxes() > 0) {
|
if ($this->entity_calc->getTotalTaxes() > 0) {
|
||||||
$tax_label = '';
|
$tax_label = '';
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ input:checked ~ .dot {
|
|||||||
Enterprise Plan
|
Enterprise Plan
|
||||||
</h3>
|
</h3>
|
||||||
<p class="text-5xl font-bold text-center text-white" id="y_plan_price">
|
<p class="text-5xl font-bold text-center text-white" id="y_plan_price">
|
||||||
$140
|
$180
|
||||||
</p>
|
</p>
|
||||||
<p class="text-xs text-center uppercase text-white">
|
<p class="text-xs text-center uppercase text-white">
|
||||||
yearly
|
yearly
|
||||||
@@ -275,12 +275,12 @@ document.getElementById('handleProYearlyClick').addEventListener('click', functi
|
|||||||
});
|
});
|
||||||
const price_map = new Map();
|
const price_map = new Map();
|
||||||
//monthly
|
//monthly
|
||||||
price_map.set('7LDdwRb1YK', '$16');
|
price_map.set('7LDdwRb1YK', '$18');
|
||||||
price_map.set('MVyb8mdvAZ', '$32');
|
price_map.set('MVyb8mdvAZ', '$32');
|
||||||
price_map.set('WpmbkR5azJ', '$54');
|
price_map.set('WpmbkR5azJ', '$54');
|
||||||
price_map.set('k8mepY2aMy', '$84');
|
price_map.set('k8mepY2aMy', '$84');
|
||||||
//yearly
|
//yearly
|
||||||
price_map.set('LYqaQWldnj', '$160');
|
price_map.set('LYqaQWldnj', '$180');
|
||||||
price_map.set('kQBeX6mbyK', '$320');
|
price_map.set('kQBeX6mbyK', '$320');
|
||||||
price_map.set('GELe32Qd69', '$540');
|
price_map.set('GELe32Qd69', '$540');
|
||||||
price_map.set('MVyb86oevA', '$840');
|
price_map.set('MVyb86oevA', '$840');
|
||||||
|
|||||||
@@ -1134,7 +1134,7 @@ class ReportCsvGenerationTest extends TestCase
|
|||||||
|
|
||||||
$csv = $response->body();
|
$csv = $response->body();
|
||||||
|
|
||||||
$reader = Reader::createFromString($csv);
|
$reader = Reader::fromString($csv);
|
||||||
$reader->setHeaderOffset(0);
|
$reader->setHeaderOffset(0);
|
||||||
|
|
||||||
$res = $reader->fetchColumnByName('Street');
|
$res = $reader->fetchColumnByName('Street');
|
||||||
@@ -1983,7 +1983,7 @@ class ReportCsvGenerationTest extends TestCase
|
|||||||
$csv = $response->body();
|
$csv = $response->body();
|
||||||
|
|
||||||
|
|
||||||
$reader = Reader::createFromString($csv);
|
$reader = Reader::fromString($csv);
|
||||||
$reader->setHeaderOffset(0);
|
$reader->setHeaderOffset(0);
|
||||||
|
|
||||||
$res = $reader->fetchColumnByName('Contact First Name');
|
$res = $reader->fetchColumnByName('Contact First Name');
|
||||||
@@ -2014,7 +2014,7 @@ class ReportCsvGenerationTest extends TestCase
|
|||||||
|
|
||||||
private function getFirstValueByColumn($csv, $column)
|
private function getFirstValueByColumn($csv, $column)
|
||||||
{
|
{
|
||||||
$reader = Reader::createFromString($csv);
|
$reader = Reader::fromString($csv);
|
||||||
$reader->setHeaderOffset(0);
|
$reader->setHeaderOffset(0);
|
||||||
|
|
||||||
$res = $reader->fetchColumnByName($column);
|
$res = $reader->fetchColumnByName($column);
|
||||||
|
|||||||
Reference in New Issue
Block a user