mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-10 13:12:50 +01:00
Merge branch 'cleanup_deprecated_import' into v5-develop
This commit is contained in:
commit
fadc039eba
@ -13,7 +13,6 @@ namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\Import\ImportRequest;
|
||||
use App\Http\Requests\Import\PreImportRequest;
|
||||
use App\Jobs\Import\CSVImport;
|
||||
use App\Jobs\Import\CSVIngest;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
@ -20,7 +20,7 @@ use App\Http\Requests\Quote\StoreQuoteRequest;
|
||||
use App\Import\ImportException;
|
||||
use App\Jobs\Mail\NinjaMailerJob;
|
||||
use App\Jobs\Mail\NinjaMailerObject;
|
||||
use App\Mail\Import\ImportCompleted;
|
||||
use App\Mail\Import\CsvImportCompleted;
|
||||
use App\Models\Company;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Quote;
|
||||
@ -187,6 +187,10 @@ class BaseImport
|
||||
|
||||
try {
|
||||
$entity = $this->transformer->transform($record);
|
||||
|
||||
if(!$entity)
|
||||
continue;
|
||||
|
||||
$validator = $this->runValidation($entity);
|
||||
|
||||
if ($validator->fails()) {
|
||||
@ -282,6 +286,8 @@ class BaseImport
|
||||
|
||||
public function ingestInvoices($invoices, $invoice_number_key)
|
||||
{
|
||||
$count = 0;
|
||||
|
||||
$invoice_transformer = $this->transformer;
|
||||
|
||||
/** @var PaymentRepository $payment_repository */
|
||||
@ -343,6 +349,7 @@ class BaseImport
|
||||
}
|
||||
$invoice_repository->save($invoice_data, $invoice);
|
||||
|
||||
$count++;
|
||||
// If we're doing a generic CSV import, only import payment data if we're not importing a payment CSV.
|
||||
// If we're doing a platform-specific import, trust the platform to only return payment info if there's not a separate payment CSV.
|
||||
if (
|
||||
@ -404,6 +411,9 @@ class BaseImport
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $count;
|
||||
|
||||
}
|
||||
|
||||
private function actionInvoiceStatus(
|
||||
@ -475,6 +485,8 @@ class BaseImport
|
||||
|
||||
public function ingestQuotes($quotes, $quote_number_key)
|
||||
{
|
||||
$count = 0;
|
||||
|
||||
$quote_transformer = $this->transformer;
|
||||
|
||||
/** @var ClientRepository $client_repository */
|
||||
@ -532,6 +544,8 @@ class BaseImport
|
||||
$quote->status_id = $quote_data['status_id'];
|
||||
}
|
||||
$quote_repository->save($quote_data, $quote);
|
||||
|
||||
$count++;
|
||||
|
||||
$this->actionQuoteStatus(
|
||||
$quote,
|
||||
@ -552,7 +566,11 @@ class BaseImport
|
||||
'error' => $message,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $count;
|
||||
|
||||
}
|
||||
|
||||
protected function getUserIDForRecord($record)
|
||||
@ -586,10 +604,11 @@ class BaseImport
|
||||
$data = [
|
||||
'errors' => $this->error_array,
|
||||
'company' => $this->company,
|
||||
'entity_count' => $this->entity_count
|
||||
];
|
||||
|
||||
$nmo = new NinjaMailerObject;
|
||||
$nmo->mailable = new ImportCompleted($this->company, $data);
|
||||
$nmo->mailable = new CsvImportCompleted($this->company, $data);
|
||||
$nmo->company = $this->company;
|
||||
$nmo->settings = $this->company->settings;
|
||||
$nmo->to_user = $this->company->owner();
|
||||
|
@ -37,7 +37,7 @@ use App\Import\Transformer\Csv\PaymentTransformer;
|
||||
use App\Import\Transformer\Csv\ProductTransformer;
|
||||
use App\Import\Transformer\Csv\QuoteTransformer;
|
||||
use App\Import\Transformer\Csv\VendorTransformer;
|
||||
use App\Import\Transformers\Bank\BankTransformer;
|
||||
use App\Import\Transformer\Bank\BankTransformer;
|
||||
use App\Repositories\BankTransactionRepository;
|
||||
use App\Repositories\ClientRepository;
|
||||
use App\Repositories\ExpenseRepository;
|
||||
|
@ -66,7 +66,6 @@ class Wave extends BaseImport implements ImportInterface
|
||||
|
||||
if (empty($data)) {
|
||||
$this->entity_count['clients'] = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -170,11 +169,16 @@ class Wave extends BaseImport implements ImportInterface
|
||||
$entity_type = 'expense';
|
||||
|
||||
$data = $this->getCsvData($entity_type);
|
||||
|
||||
if(!$data){
|
||||
$this->entity_count['expense'] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
$data = $this->preTransform($data, $entity_type);
|
||||
|
||||
if (empty($data)) {
|
||||
$this->entity_count['expense'] = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -212,6 +216,8 @@ class Wave extends BaseImport implements ImportInterface
|
||||
|
||||
public function ingestExpenses($data)
|
||||
{
|
||||
$count = 0;
|
||||
|
||||
$key = 'Transaction ID';
|
||||
|
||||
$expense_transformer = $this->transformer;
|
||||
@ -255,6 +261,7 @@ class Wave extends BaseImport implements ImportInterface
|
||||
);
|
||||
|
||||
$expense_repository->save($expense_data, $expense);
|
||||
$count++;
|
||||
}
|
||||
} catch (\Exception $ex) {
|
||||
if ($ex instanceof ImportException) {
|
||||
@ -270,5 +277,8 @@ class Wave extends BaseImport implements ImportInterface
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $count;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Bank;
|
||||
namespace App\Import\Transformer\Bank;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformer\BaseTransformer;
|
@ -28,6 +28,11 @@ class InvoiceTransformer extends BaseTransformer
|
||||
*/
|
||||
public function transform($invoice_data)
|
||||
{
|
||||
|
||||
if (!isset($invoice_data['DocumentNumber'])) {
|
||||
throw new ImportException('DocumentNumber key not found in this import file.');
|
||||
}
|
||||
|
||||
if ($this->hasInvoice($invoice_data['DocumentNumber'])) {
|
||||
throw new ImportException('Invoice number already exists');
|
||||
}
|
||||
|
@ -28,7 +28,8 @@ class ClientTransformer extends BaseTransformer
|
||||
public function transform($data)
|
||||
{
|
||||
if (isset($data['customer_name']) && $this->hasClient($data['customer_name'])) {
|
||||
throw new ImportException('Client already exists');
|
||||
return false;
|
||||
// throw new ImportException('Client already exists');
|
||||
}
|
||||
|
||||
$settings = new \stdClass;
|
||||
|
@ -1,430 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers;
|
||||
|
||||
use App\Models\ClientContact;
|
||||
use App\Utils\Number;
|
||||
use Carbon;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class BaseTransformer.
|
||||
*/
|
||||
class BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
protected $maps;
|
||||
|
||||
/**
|
||||
* BaseTransformer constructor.
|
||||
*
|
||||
* @param $maps
|
||||
*/
|
||||
public function __construct($maps)
|
||||
{
|
||||
$this->maps = $maps;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @param $field
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getString($data, $field)
|
||||
{
|
||||
return (isset($data[$field]) && $data[$field]) ? $data[$field] : '';
|
||||
}
|
||||
|
||||
public function getInvoiceTypeId($data, $field)
|
||||
{
|
||||
return (isset($data[$field]) && $data[$field]) ? $data[$field] : '1';
|
||||
}
|
||||
|
||||
public function getCurrencyByCode($data, $key = 'client.currency_id')
|
||||
{
|
||||
$code = array_key_exists($key, $data) ? $data[$key] : false;
|
||||
|
||||
return $this->maps['currencies'][$code] ?? $this->maps['company']->settings->currency_id;
|
||||
}
|
||||
|
||||
public function getClient($client_name, $client_email)
|
||||
{
|
||||
$clients = $this->maps['company']->clients;
|
||||
|
||||
$client_id_search = $clients->where('id_number', $client_name);
|
||||
|
||||
if ($client_id_search->count() >= 1) {
|
||||
return $client_id_search->first()->id;
|
||||
}
|
||||
|
||||
$client_name_search = $clients->where('name', $client_name);
|
||||
|
||||
if ($client_name_search->count() >= 1) {
|
||||
return $client_name_search->first()->id;
|
||||
}
|
||||
|
||||
if (! empty($client_email)) {
|
||||
$contacts = ClientContact::where('company_id', $this->maps['company']->id)
|
||||
->where('email', $client_email);
|
||||
|
||||
if ($contacts->count() >= 1) {
|
||||
return $contacts->first()->client_id;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasClient($name)
|
||||
{
|
||||
$name = trim(strtolower($name));
|
||||
|
||||
return isset($this->maps['client'][$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasVendor($name)
|
||||
{
|
||||
$name = trim(strtolower($name));
|
||||
|
||||
return isset($this->maps['vendor'][$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasProduct($key)
|
||||
{
|
||||
$key = trim(strtolower($key));
|
||||
|
||||
return isset($this->maps['product'][$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @param $field
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getNumber($data, $field)
|
||||
{
|
||||
return (isset($data->$field) && $data->$field) ? $data->$field : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @param $field
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getFloat($data, $field)
|
||||
{
|
||||
if (array_key_exists($field, $data)) {
|
||||
$number = preg_replace('/[^0-9-.]+/', '', $data[$field]);
|
||||
} else {
|
||||
$number = 0;
|
||||
}
|
||||
|
||||
return Number::parseFloat($number);
|
||||
}
|
||||
|
||||
public function getFloatWithSamePrecision($data, $field)
|
||||
{
|
||||
$precision = (int) strpos(strrev($data[$field]), ".");
|
||||
|
||||
return round($data[$field], $precision);
|
||||
}
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getClientId($name)
|
||||
{
|
||||
$name = strtolower(trim($name));
|
||||
|
||||
return isset($this->maps['client'][$name]) ? $this->maps['client'][$name] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getProduct($data, $key, $field, $default = false)
|
||||
{
|
||||
$productKey = trim(strtolower($data->$key));
|
||||
|
||||
if (! isset($this->maps['product'][$productKey])) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$product = $this->maps['product'][$productKey];
|
||||
|
||||
return $product->$field ?: $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getContact($email)
|
||||
{
|
||||
$email = trim(strtolower($email));
|
||||
|
||||
if (! isset($this->maps['contact'][$email])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->maps['contact'][$email];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getCustomer($key)
|
||||
{
|
||||
$key = trim($key);
|
||||
|
||||
if (! isset($this->maps['customer'][$key])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->maps['customer'][$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getCountryId($name)
|
||||
{
|
||||
$name = strtolower(trim($name));
|
||||
|
||||
if (strlen($name) == 2) {
|
||||
return $this->getCountryIdBy2($name);
|
||||
}
|
||||
|
||||
return isset($this->maps['countries'][$name]) ? $this->maps['countries'][$name] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getCountryIdBy2($name)
|
||||
{
|
||||
$name = strtolower(trim($name));
|
||||
|
||||
return isset($this->maps['countries2'][$name]) ? $this->maps['countries2'][$name] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getTaxRate($name)
|
||||
{
|
||||
$name = strtolower(trim($name));
|
||||
|
||||
return isset($this->maps['tax_rates'][$name]) ? $this->maps['tax_rates'][$name] : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getTaxName($name)
|
||||
{
|
||||
$name = strtolower(trim($name));
|
||||
|
||||
return isset($this->maps['tax_names'][$name]) ? $this->maps['tax_names'][$name] : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getFirstName($name)
|
||||
{
|
||||
$name = Utils::splitName($name);
|
||||
|
||||
return $name[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $date
|
||||
* @param string $format
|
||||
* @param mixed $data
|
||||
* @param mixed $field
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getDate($data, $field)
|
||||
{
|
||||
if ($date = data_get($data, $field)) {
|
||||
try {
|
||||
$date = new Carbon($date);
|
||||
} catch (Exception $e) {
|
||||
// if we fail to parse return blank
|
||||
$date = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $date ? $date->format('Y-m-d') : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLastName($name)
|
||||
{
|
||||
$name = Utils::splitName($name);
|
||||
|
||||
return $name[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $number
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getInvoiceNumber($number)
|
||||
{
|
||||
return $number ? ltrim(trim($number), '0') : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $invoiceNumber
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getInvoiceId($invoiceNumber)
|
||||
{
|
||||
$invoiceNumber = $this->getInvoiceNumber($invoiceNumber);
|
||||
$invoiceNumber = strtolower($invoiceNumber);
|
||||
|
||||
return isset($this->maps['invoice'][$invoiceNumber]) ? $this->maps['invoice'][$invoiceNumber] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $invoiceNumber
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getInvoicePublicId($invoiceNumber)
|
||||
{
|
||||
$invoiceNumber = $this->getInvoiceNumber($invoiceNumber);
|
||||
$invoiceNumber = strtolower($invoiceNumber);
|
||||
|
||||
return isset($this->maps['invoice'][$invoiceNumber]) ? $this->maps['invoices'][$invoiceNumber]->public_id : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $invoiceNumber
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasInvoice($invoiceNumber)
|
||||
{
|
||||
$invoiceNumber = $this->getInvoiceNumber($invoiceNumber);
|
||||
$invoiceNumber = strtolower($invoiceNumber);
|
||||
|
||||
return $this->maps['invoice'][$invoiceNumber] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $invoiceNumber
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getInvoiceClientId($invoiceNumber)
|
||||
{
|
||||
$invoiceNumber = $this->getInvoiceNumber($invoiceNumber);
|
||||
$invoiceNumber = strtolower($invoiceNumber);
|
||||
|
||||
return $this->maps['invoice_client'][$invoiceNumber] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getVendorId($name)
|
||||
{
|
||||
$name = strtolower(trim($name));
|
||||
|
||||
return $this->maps['vendor'][$name] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getExpenseCategoryId($name)
|
||||
{
|
||||
$name = strtolower(trim($name));
|
||||
|
||||
return $this->maps['expense_category'][$name] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getProjectId($name)
|
||||
{
|
||||
$name = strtolower(trim($name));
|
||||
|
||||
return $this->maps['project'][$name] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getPaymentTypeId($name)
|
||||
{
|
||||
$name = strtolower(trim($name));
|
||||
|
||||
return $this->maps['payment_type'][$name] ?? null;
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Class ClientTransformer.
|
||||
*/
|
||||
class ClientTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return bool|Item
|
||||
*/
|
||||
public function transform($data)
|
||||
{
|
||||
if (isset($data->name) && $this->hasClient($data->name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$settings = new \stdClass;
|
||||
$settings->currency_id = (string) $this->getCurrencyByCode($data);
|
||||
|
||||
return [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'name' => $this->getString($data, 'client.name'),
|
||||
'phone' => $this->getString($data, 'client.phone'),
|
||||
'address1' => $this->getString($data, 'client.address1'),
|
||||
'address2' => $this->getString($data, 'client.address2'),
|
||||
'city' => $this->getString($data, 'client.city'),
|
||||
'state' => $this->getString($data, 'client.state'),
|
||||
'shipping_address1' => $this->getString($data, 'client.shipping_address1'),
|
||||
'shipping_address2' => $this->getString($data, 'client.shipping_address2'),
|
||||
'shipping_city' => $this->getString($data, 'client.shipping_city'),
|
||||
'shipping_state' => $this->getString($data, 'client.shipping_state'),
|
||||
'shipping_postal_code' => $this->getString($data, 'client.shipping_postal_code'),
|
||||
'public_notes' => $this->getString($data, 'client.public_notes'),
|
||||
'private_notes' => $this->getString($data, 'client.private_notes'),
|
||||
'website' => $this->getString($data, 'client.website'),
|
||||
'vat_number' => $this->getString($data, 'client.vat_number'),
|
||||
'id_number' => $this->getString($data, 'client.id_number'),
|
||||
'custom_value1' => $this->getString($data, 'client.custom1'),
|
||||
'custom_value2' => $this->getString($data, 'client.custom2'),
|
||||
'custom_value3' => $this->getString($data, 'client.custom3'),
|
||||
'custom_value4' => $this->getString($data, 'client.custom4'),
|
||||
'balance' => $this->getFloat($data, 'client.balance'),
|
||||
'paid_to_date' => $this->getFloat($data, 'client.paid_to_date'),
|
||||
'credit_balance' => 0,
|
||||
'settings' => $settings,
|
||||
'client_hash' => Str::random(40),
|
||||
'contacts' => [
|
||||
[
|
||||
'first_name' => $this->getString($data, 'contact.first_name'),
|
||||
'last_name' => $this->getString($data, 'contact.last_name'),
|
||||
'email' => $this->getString($data, 'contact.email'),
|
||||
'phone' => $this->getString($data, 'contact.phone'),
|
||||
'custom_value1' => $this->getString($data, 'contact.custom1'),
|
||||
'custom_value2' => $this->getString($data, 'contact.custom2'),
|
||||
'custom_value3' => $this->getString($data, 'contact.custom3'),
|
||||
'custom_value4' => $this->getString($data, 'contact.custom4'),
|
||||
],
|
||||
],
|
||||
'country_id' => isset($data->country_id) ? $this->getCountryId($data->country_id) : null,
|
||||
'shipping_country_id' => isset($data->shipping_country_id) ? $this->getCountryId($data->shipping_country_id) : null,
|
||||
];
|
||||
}
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* client Ninja (https://clientninja.com).
|
||||
*
|
||||
* @link https://github.com/clientninja/clientninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. client Ninja LLC (https://clientninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Csv;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Class ClientTransformer.
|
||||
*/
|
||||
class ClientTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public function transform($data)
|
||||
{
|
||||
if (isset($data->name) && $this->hasClient($data->name)) {
|
||||
throw new ImportException('Client already exists');
|
||||
}
|
||||
|
||||
$settings = new \stdClass();
|
||||
$settings->currency_id = (string) $this->getCurrencyByCode($data);
|
||||
|
||||
return [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'name' => $this->getString($data, 'client.name'),
|
||||
'phone' => $this->getString($data, 'client.phone'),
|
||||
'address1' => $this->getString($data, 'client.address1'),
|
||||
'address2' => $this->getString($data, 'client.address2'),
|
||||
'postal_code' => $this->getString($data, 'client.postal_code'),
|
||||
'city' => $this->getString($data, 'client.city'),
|
||||
'state' => $this->getString($data, 'client.state'),
|
||||
'shipping_address1' => $this->getString(
|
||||
$data,
|
||||
'client.shipping_address1'
|
||||
),
|
||||
'shipping_address2' => $this->getString(
|
||||
$data,
|
||||
'client.shipping_address2'
|
||||
),
|
||||
'shipping_city' => $this->getString($data, 'client.shipping_city'),
|
||||
'shipping_state' => $this->getString(
|
||||
$data,
|
||||
'client.shipping_state'
|
||||
),
|
||||
'shipping_postal_code' => $this->getString(
|
||||
$data,
|
||||
'client.shipping_postal_code'
|
||||
),
|
||||
'public_notes' => $this->getString($data, 'client.public_notes'),
|
||||
'private_notes' => $this->getString($data, 'client.private_notes'),
|
||||
'website' => $this->getString($data, 'client.website'),
|
||||
'vat_number' => $this->getString($data, 'client.vat_number'),
|
||||
'id_number' => $this->getString($data, 'client.id_number'),
|
||||
'custom_value1' => $this->getString($data, 'client.custom_value1'),
|
||||
'custom_value2' => $this->getString($data, 'client.custom_value2'),
|
||||
'custom_value3' => $this->getString($data, 'client.custom_value3'),
|
||||
'custom_value4' => $this->getString($data, 'client.custom_value4'),
|
||||
'balance' => preg_replace(
|
||||
'/[^0-9,.]+/',
|
||||
'',
|
||||
$this->getFloat($data, 'client.balance')
|
||||
),
|
||||
'paid_to_date' => preg_replace(
|
||||
'/[^0-9,.]+/',
|
||||
'',
|
||||
$this->getFloat($data, 'client.paid_to_date')
|
||||
),
|
||||
'credit_balance' => 0,
|
||||
'settings' => $settings,
|
||||
'client_hash' => Str::random(40),
|
||||
'contacts' => [
|
||||
[
|
||||
'first_name' => $this->getString(
|
||||
$data,
|
||||
'contact.first_name'
|
||||
),
|
||||
'last_name' => $this->getString($data, 'contact.last_name'),
|
||||
'email' => $this->getString($data, 'contact.email'),
|
||||
'phone' => $this->getString($data, 'contact.phone'),
|
||||
'custom_value1' => $this->getString(
|
||||
$data,
|
||||
'contact.custom_value1'
|
||||
),
|
||||
'custom_value2' => $this->getString(
|
||||
$data,
|
||||
'contact.custom_value2'
|
||||
),
|
||||
'custom_value3' => $this->getString(
|
||||
$data,
|
||||
'contact.custom_value3'
|
||||
),
|
||||
'custom_value4' => $this->getString(
|
||||
$data,
|
||||
'contact.custom_value4'
|
||||
),
|
||||
],
|
||||
],
|
||||
'country_id' => isset($data['client.country'])
|
||||
? $this->getCountryId($data['client.country'])
|
||||
: null,
|
||||
'shipping_country_id' => isset($data['client.shipping_country'])
|
||||
? $this->getCountryId($data['client.shipping_country'])
|
||||
: null,
|
||||
];
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Import\Transformers\Csv;
|
||||
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
|
||||
/**
|
||||
* Class InvoiceTransformer.
|
||||
*/
|
||||
class ExpenseTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return bool|array
|
||||
*/
|
||||
public function transform($data)
|
||||
{
|
||||
$clientId = isset($data['expense.client']) ? $this->getClientId($data['expense.client']) : null;
|
||||
|
||||
return [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'amount' => $this->getFloat($data, 'expense.amount'),
|
||||
'currency_id' => $this->getCurrencyByCode($data, 'expense.currency_id'),
|
||||
'vendor_id' => isset($data['expense.vendor']) ? $this->getVendorId($data['expense.vendor']) : null,
|
||||
'client_id' => isset($data['expense.client']) ? $this->getClientId($data['expense.client']) : null,
|
||||
'date' => isset($data['expense.date']) ? date('Y-m-d', strtotime($data['expense.date'])) : null,
|
||||
'public_notes' => $this->getString($data, 'expense.public_notes'),
|
||||
'private_notes' => $this->getString($data, 'expense.private_notes'),
|
||||
'category_id' => isset($data['expense.category']) ? $this->getExpenseCategoryId($data['expense.category']) : null,
|
||||
'project_id' => isset($data['expense.project']) ? $this->getProjectId($data['expense.project']) : null,
|
||||
'payment_type_id' => isset($data['expense.payment_type']) ? $this->getPaymentTypeId($data['expense.payment_type']) : null,
|
||||
'payment_date' => isset($data['expense.payment_date']) ? date('Y-m-d', strtotime($data['expense.payment_date'])) : null,
|
||||
'custom_value1' => $this->getString($data, 'expense.custom_value1'),
|
||||
'custom_value2' => $this->getString($data, 'expense.custom_value2'),
|
||||
'custom_value3' => $this->getString($data, 'expense.custom_value3'),
|
||||
'custom_value4' => $this->getString($data, 'expense.custom_value4'),
|
||||
'transaction_reference' => $this->getString($data, 'expense.transaction_reference'),
|
||||
'should_be_invoiced' => $clientId ? true : false,
|
||||
];
|
||||
}
|
||||
}
|
@ -1,133 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* client Ninja (https://clientninja.com).
|
||||
*
|
||||
* @link https://github.com/clientninja/clientninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. client Ninja LLC (https://clientninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Csv;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
use App\Models\Invoice;
|
||||
|
||||
/**
|
||||
* Class InvoiceTransformer.
|
||||
*/
|
||||
class InvoiceTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return bool|array
|
||||
*/
|
||||
public function transform($line_items_data)
|
||||
{
|
||||
$invoice_data = reset($line_items_data);
|
||||
|
||||
if ($this->hasInvoice($invoice_data['invoice.number'])) {
|
||||
throw new ImportException('Invoice number already exists');
|
||||
}
|
||||
|
||||
$invoiceStatusMap = [
|
||||
'sent' => Invoice::STATUS_SENT,
|
||||
'draft' => Invoice::STATUS_DRAFT,
|
||||
];
|
||||
|
||||
$transformed = [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'number' => $this->getString($invoice_data, 'invoice.number'),
|
||||
'user_id' => $this->getString($invoice_data, 'invoice.user_id'),
|
||||
'amount' => $amount = $this->getFloat($invoice_data, 'invoice.amount'),
|
||||
'balance' => isset($invoice_data['invoice.balance']) ? $this->getFloat($invoice_data, 'invoice.balance') : $amount,
|
||||
'client_id' => $this->getClient($this->getString($invoice_data, 'client.name'), $this->getString($invoice_data, 'client.email')),
|
||||
'discount' => $this->getFloat($invoice_data, 'invoice.discount'),
|
||||
'po_number' => $this->getString($invoice_data, 'invoice.po_number'),
|
||||
'date' => isset($invoice_data['invoice.date']) ? date('Y-m-d', strtotime($invoice_data['invoice.date'])) : now()->format('Y-m-d'),
|
||||
'due_date' => isset($invoice_data['invoice.due_date']) ? date('Y-m-d', strtotime($invoice_data['invoice.due_date'])) : null,
|
||||
'terms' => $this->getString($invoice_data, 'invoice.terms'),
|
||||
'public_notes' => $this->getString($invoice_data, 'invoice.public_notes'),
|
||||
// 'is_sent' => $this->getString( $invoice_data, 'invoice.is_sent' ),
|
||||
'private_notes' => $this->getString($invoice_data, 'invoice.private_notes'),
|
||||
'tax_name1' => $this->getString($invoice_data, 'invoice.tax_name1'),
|
||||
'tax_rate1' => $this->getFloat($invoice_data, 'invoice.tax_rate1'),
|
||||
'tax_name2' => $this->getString($invoice_data, 'invoice.tax_name2'),
|
||||
'tax_rate2' => $this->getFloat($invoice_data, 'invoice.tax_rate2'),
|
||||
'tax_name3' => $this->getString($invoice_data, 'invoice.tax_name3'),
|
||||
'tax_rate3' => $this->getFloat($invoice_data, 'invoice.tax_rate3'),
|
||||
'custom_value1' => $this->getString($invoice_data, 'invoice.custom_value1'),
|
||||
'custom_value2' => $this->getString($invoice_data, 'invoice.custom_value2'),
|
||||
'custom_value3' => $this->getString($invoice_data, 'invoice.custom_value3'),
|
||||
'custom_value4' => $this->getString($invoice_data, 'invoice.custom_value4'),
|
||||
'footer' => $this->getString($invoice_data, 'invoice.footer'),
|
||||
'partial' => $this->getFloat($invoice_data, 'invoice.partial'),
|
||||
'partial_due_date' => $this->getString($invoice_data, 'invoice.partial_due_date'),
|
||||
'custom_surcharge1' => $this->getString($invoice_data, 'invoice.custom_surcharge1'),
|
||||
'custom_surcharge2' => $this->getString($invoice_data, 'invoice.custom_surcharge2'),
|
||||
'custom_surcharge3' => $this->getString($invoice_data, 'invoice.custom_surcharge3'),
|
||||
'custom_surcharge4' => $this->getString($invoice_data, 'invoice.custom_surcharge4'),
|
||||
'exchange_rate' => $this->getString($invoice_data, 'invoice.exchange_rate'),
|
||||
'status_id' => $invoiceStatusMap[$status =
|
||||
strtolower($this->getString($invoice_data, 'invoice.status'))] ??
|
||||
Invoice::STATUS_SENT,
|
||||
// 'viewed' => $status === 'viewed',
|
||||
'archived' => $status === 'archived',
|
||||
];
|
||||
|
||||
if (isset($invoice_data['payment.amount'])) {
|
||||
$transformed['payments'] = [
|
||||
[
|
||||
'date' => isset($invoice_data['payment.date']) ? date('Y-m-d', strtotime($invoice_data['payment.date'])) : date('y-m-d'),
|
||||
'transaction_reference' => $this->getString($invoice_data, 'payment.transaction_reference'),
|
||||
'amount' => $this->getFloat($invoice_data, 'payment.amount'),
|
||||
],
|
||||
];
|
||||
} elseif ($status === 'paid') {
|
||||
$transformed['payments'] = [
|
||||
[
|
||||
'date' => isset($invoice_data['payment.date']) ? date('Y-m-d', strtotime($invoice_data['payment.date'])) : date('y-m-d'),
|
||||
'transaction_reference' => $this->getString($invoice_data, 'payment.transaction_reference'),
|
||||
'amount' => $this->getFloat($invoice_data, 'invoice.amount'),
|
||||
],
|
||||
];
|
||||
} elseif (isset($transformed['amount']) && isset($transformed['balance']) && ($transformed['amount'] != $transformed['balance'])) {
|
||||
$transformed['payments'] = [
|
||||
[
|
||||
'date' => isset($invoice_data['payment.date']) ? date('Y-m-d', strtotime($invoice_data['payment.date'])) : date('y-m-d'),
|
||||
'transaction_reference' => $this->getString($invoice_data, 'payment.transaction_reference'),
|
||||
'amount' => $transformed['amount'] - $transformed['balance'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
$line_items = [];
|
||||
foreach ($line_items_data as $record) {
|
||||
$line_items[] = [
|
||||
'quantity' => $this->getFloat($record, 'item.quantity'),
|
||||
'cost' => $this->getFloat($record, 'item.cost'),
|
||||
'product_key' => $this->getString($record, 'item.product_key'),
|
||||
'notes' => $this->getString($record, 'item.notes'),
|
||||
'discount' => $this->getFloat($record, 'item.discount'),
|
||||
'is_amount_discount' => filter_var($this->getString($record, 'item.is_amount_discount'), FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE),
|
||||
'tax_name1' => $this->getString($record, 'item.tax_name1'),
|
||||
'tax_rate1' => $this->getFloat($record, 'item.tax_rate1'),
|
||||
'tax_name2' => $this->getString($record, 'item.tax_name2'),
|
||||
'tax_rate2' => $this->getFloat($record, 'item.tax_rate2'),
|
||||
'tax_name3' => $this->getString($record, 'item.tax_name3'),
|
||||
'tax_rate3' => $this->getFloat($record, 'item.tax_rate3'),
|
||||
'custom_value1' => $this->getString($record, 'item.custom_value1'),
|
||||
'custom_value2' => $this->getString($record, 'item.custom_value2'),
|
||||
'custom_value3' => $this->getString($record, 'item.custom_value3'),
|
||||
'custom_value4' => $this->getString($record, 'item.custom_value4'),
|
||||
'type_id' => $this->getInvoiceTypeId($record, 'item.type_id'),
|
||||
];
|
||||
}
|
||||
$transformed['line_items'] = $line_items;
|
||||
|
||||
return $transformed;
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* client Ninja (https://clientninja.com).
|
||||
*
|
||||
* @link https://github.com/clientninja/clientninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. client Ninja LLC (https://clientninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Csv;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
|
||||
/**
|
||||
* Class PaymentTransformer.
|
||||
*/
|
||||
class PaymentTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function transform($data)
|
||||
{
|
||||
$client_id =
|
||||
$this->getClient($this->getString($data, 'payment.client_id'), $this->getString($data, 'payment.client_id'));
|
||||
|
||||
if (empty($client_id)) {
|
||||
throw new ImportException('Could not find client.');
|
||||
}
|
||||
|
||||
$transformed = [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'number' => $this->getString($data, 'payment.number'),
|
||||
'user_id' => $this->getString($data, 'payment.user_id'),
|
||||
'amount' => $this->getFloat($data, 'payment.amount'),
|
||||
'refunded' => $this->getFloat($data, 'payment.refunded'),
|
||||
'applied' => $this->getFloat($data, 'payment.applied'),
|
||||
'transaction_reference' => $this->getString($data, 'payment.transaction_reference '),
|
||||
'date' => $this->getString($data, 'payment.date'),
|
||||
'private_notes' => $this->getString($data, 'payment.private_notes'),
|
||||
'custom_value1' => $this->getString($data, 'payment.custom_value1'),
|
||||
'custom_value2' => $this->getString($data, 'payment.custom_value2'),
|
||||
'custom_value3' => $this->getString($data, 'payment.custom_value3'),
|
||||
'custom_value4' => $this->getString($data, 'payment.custom_value4'),
|
||||
'client_id' => $client_id,
|
||||
];
|
||||
|
||||
if (isset($data['payment.invoice_number']) &&
|
||||
$invoice_id = $this->getInvoiceId($data['payment.invoice_number'])) {
|
||||
$transformed['invoices'] = [
|
||||
[
|
||||
'invoice_id' => $invoice_id,
|
||||
'amount' => $transformed['amount'] ?? null,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return $transformed;
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Csv;
|
||||
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
|
||||
/**
|
||||
* Class ProductTransformer.
|
||||
*/
|
||||
class ProductTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function transform($data)
|
||||
{
|
||||
return [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'product_key' => $this->getString($data, 'product.product_key'),
|
||||
'notes' => $this->getString($data, 'product.notes'),
|
||||
'cost' => $this->getFloat($data, 'product.cost'),
|
||||
'price' => $this->getFloat($data, 'product.price'),
|
||||
'quantity' => $this->getFloat($data, 'product.quantity'),
|
||||
'tax_name1' => $this->getString($data, 'product.tax_name1'),
|
||||
'tax_rate1' => $this->getFloat($data, 'product.tax_rate1'),
|
||||
'tax_name2' => $this->getString($data, 'product.tax_name2'),
|
||||
'tax_rate2' => $this->getFloat($data, 'product.tax_rate2'),
|
||||
'tax_name3' => $this->getString($data, 'product.tax_name3'),
|
||||
'tax_rate3' => $this->getFloat($data, 'product.tax_rate3'),
|
||||
'custom_value1' => $this->getString($data, 'product.custom_value1'),
|
||||
'custom_value2' => $this->getString($data, 'product.custom_value2'),
|
||||
'custom_value3' => $this->getString($data, 'product.custom_value3'),
|
||||
'custom_value4' => $this->getString($data, 'product.custom_value4'),
|
||||
];
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Import\Transformers\Csv;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
|
||||
/**
|
||||
* Class VendorTransformer.
|
||||
*/
|
||||
class VendorTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public function transform($data)
|
||||
{
|
||||
if (isset($data->name) && $this->hasVendor($data->name)) {
|
||||
throw new ImportException('Vendor already exists');
|
||||
}
|
||||
|
||||
return [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'name' => $this->getString($data, 'vendor.name'),
|
||||
'phone' => $this->getString($data, 'vendor.phone'),
|
||||
'id_number' => $this->getString($data, 'vendor.id_number'),
|
||||
'vat_number' => $this->getString($data, 'vendor.vat_number'),
|
||||
'website' => $this->getString($data, 'vendor.website'),
|
||||
'currency_id' => $this->getCurrencyByCode($data, 'vendor.currency_id'),
|
||||
'public_notes' => $this->getString($data, 'vendor.public_notes'),
|
||||
'private_notes' => $this->getString($data, 'vendor.private_notes'),
|
||||
'address1' => $this->getString($data, 'vendor.address1'),
|
||||
'address2' => $this->getString($data, 'vendor.address2'),
|
||||
'city' => $this->getString($data, 'vendor.city'),
|
||||
'state' => $this->getString($data, 'vendor.state'),
|
||||
'postal_code' => $this->getString($data, 'vendor.postal_code'),
|
||||
'custom_value1' => $this->getString($data, 'vendor.custom_value1'),
|
||||
'custom_value2' => $this->getString($data, 'vendor.custom_value2'),
|
||||
'custom_value3' => $this->getString($data, 'vendor.custom_value3'),
|
||||
'custom_value4' => $this->getString($data, 'vendor.custom_value4'),
|
||||
'vendor_contacts' => [
|
||||
[
|
||||
'first_name' => $this->getString($data, 'vendor.first_name'),
|
||||
'last_name' => $this->getString($data, 'vendor.last_name'),
|
||||
'email' => $this->getString($data, 'vendor.email'),
|
||||
'phone' => $this->getString($data, 'vendor.phone'),
|
||||
],
|
||||
],
|
||||
'country_id' => isset($data['vendor.country_id']) ? $this->getCountryId($data['vendor.country_id']) : null,
|
||||
];
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://clientninja.com).
|
||||
*
|
||||
* @link https://github.com/clientninja/clientninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. client Ninja LLC (https://clientninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Freshbooks;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Class ClientTransformer.
|
||||
*/
|
||||
class ClientTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public function transform($data)
|
||||
{
|
||||
if (isset($data['Organization']) && $this->hasClient($data['Organization'])) {
|
||||
throw new ImportException('Client already exists');
|
||||
}
|
||||
|
||||
return [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'name' => $this->getString($data, 'Organization'),
|
||||
'phone' => $this->getString($data, 'Phone'),
|
||||
'address1' => $this->getString($data, 'Street'),
|
||||
'city' => $this->getString($data, 'City'),
|
||||
'state' => $this->getString($data, 'Province/State'),
|
||||
'postal_code' => $this->getString($data, 'Postal Code'),
|
||||
'country_id' => isset($data['Country']) ? $this->getCountryId($data['Country']) : null,
|
||||
'private_notes' => $this->getString($data, 'Notes'),
|
||||
'credit_balance' => 0,
|
||||
'settings' => new \stdClass,
|
||||
'client_hash' => Str::random(40),
|
||||
'contacts' => [
|
||||
[
|
||||
'first_name' => $this->getString($data, 'First Name'),
|
||||
'last_name' => $this->getString($data, 'Last Name'),
|
||||
'email' => $this->getString($data, 'Email'),
|
||||
'phone' => $this->getString($data, 'Phone'),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* client Ninja (https://clientninja.com).
|
||||
*
|
||||
* @link https://github.com/clientninja/clientninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. client Ninja LLC (https://clientninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Freshbooks;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
use App\Models\Invoice;
|
||||
use App\Utils\Number;
|
||||
|
||||
/**
|
||||
* Class InvoiceTransformer.
|
||||
*/
|
||||
class InvoiceTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $line_items_data
|
||||
*
|
||||
* @return bool|array
|
||||
*/
|
||||
public function transform($line_items_data)
|
||||
{
|
||||
$invoice_data = reset($line_items_data);
|
||||
|
||||
if ($this->hasInvoice($invoice_data['Invoice #'])) {
|
||||
throw new ImportException('Invoice number already exists');
|
||||
}
|
||||
|
||||
$invoiceStatusMap = [
|
||||
'sent' => Invoice::STATUS_SENT,
|
||||
'draft' => Invoice::STATUS_DRAFT,
|
||||
];
|
||||
|
||||
$transformed = [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'client_id' => $this->getClient($this->getString($invoice_data, 'Client Name'), null),
|
||||
'number' => $this->getString($invoice_data, 'Invoice #'),
|
||||
'date' => isset($invoice_data['Date Issued']) ? date('Y-m-d', strtotime($invoice_data['Date Issued'])) : null,
|
||||
'currency_id' => $this->getCurrencyByCode($invoice_data, 'Currency'),
|
||||
'amount' => 0,
|
||||
'status_id' => $invoiceStatusMap[$status =
|
||||
strtolower($this->getString($invoice_data, 'Invoice Status'))] ?? Invoice::STATUS_SENT,
|
||||
// 'viewed' => $status === 'viewed',
|
||||
];
|
||||
|
||||
$line_items = [];
|
||||
foreach ($line_items_data as $record) {
|
||||
$line_items[] = [
|
||||
'product_key' => $this->getString($record, 'Item Name'),
|
||||
'notes' => $this->getString($record, 'Item Description'),
|
||||
'cost' => $this->getFreshbookQuantityFloat($record, 'Rate'),
|
||||
'quantity' => $this->getFreshbookQuantityFloat($record, 'Quantity'),
|
||||
'discount' => $this->getFreshbookQuantityFloat($record, 'Discount Percentage'),
|
||||
'is_amount_discount' => false,
|
||||
'tax_name1' => $this->getString($record, 'Tax 1 Type'),
|
||||
'tax_rate1' => $this->getFreshbookQuantityFloat($record, 'Tax 1 Amount'),
|
||||
'tax_name2' => $this->getString($record, 'Tax 2 Type'),
|
||||
'tax_rate2' => $this->getFreshbookQuantityFloat($record, 'Tax 2 Amount'),
|
||||
];
|
||||
$transformed['amount'] += $this->getFreshbookQuantityFloat($record, 'Line Total');
|
||||
}
|
||||
$transformed['line_items'] = $line_items;
|
||||
|
||||
if (! empty($invoice_data['Date Paid'])) {
|
||||
$transformed['payments'] = [[
|
||||
'date' => date('Y-m-d', strtotime($invoice_data['Date Paid'])),
|
||||
'amount' => $transformed['amount'],
|
||||
]];
|
||||
}
|
||||
|
||||
return $transformed;
|
||||
}
|
||||
|
||||
/** @return float */
|
||||
public function getFreshbookQuantityFloat($data, $field)
|
||||
{
|
||||
return $data[$field];
|
||||
}
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* client Ninja (https://clientninja.com).
|
||||
*
|
||||
* @link https://github.com/clientninja/clientninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. client Ninja LLC (https://clientninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Invoice2Go;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
use App\Models\Invoice;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Class InvoiceTransformer.
|
||||
*/
|
||||
class InvoiceTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $line_items_data
|
||||
*
|
||||
* @return bool|array
|
||||
*/
|
||||
public function transform($invoice_data)
|
||||
{
|
||||
if ($this->hasInvoice($invoice_data['DocumentNumber'])) {
|
||||
throw new ImportException('Invoice number already exists');
|
||||
}
|
||||
|
||||
$invoiceStatusMap = [
|
||||
'unsent' => Invoice::STATUS_DRAFT,
|
||||
'sent' => Invoice::STATUS_SENT,
|
||||
];
|
||||
|
||||
$transformed = [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'number' => $this->getString($invoice_data, 'DocumentNumber'),
|
||||
'notes' => $this->getString($invoice_data, 'Comment'),
|
||||
'date' => isset($invoice_data['DocumentDate']) ? date('Y-m-d', strtotime($invoice_data['DocumentDate'])) : null,
|
||||
'currency_id' => $this->getCurrencyByCode($invoice_data, 'Currency'),
|
||||
'amount' => 0,
|
||||
'status_id' => $invoiceStatusMap[$status =
|
||||
strtolower($this->getString($invoice_data, 'DocumentStatus'))] ?? Invoice::STATUS_SENT,
|
||||
// 'viewed' => $status === 'viewed',
|
||||
'line_items' => [
|
||||
[
|
||||
'amount' => $amount = $this->getFloat($invoice_data, 'TotalAmount'),
|
||||
'quantity' => 1,
|
||||
'discount' => $this->getFloat($invoice_data, 'DiscountValue'),
|
||||
'is_amount_discount' => false,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$client_id =
|
||||
$this->getClient($this->getString($invoice_data, 'Name'), $this->getString($invoice_data, 'EmailRecipient'));
|
||||
|
||||
if ($client_id) {
|
||||
$transformed['client_id'] = $client_id;
|
||||
} else {
|
||||
$transformed['client'] = [
|
||||
'name' => $this->getString($invoice_data, 'Name'),
|
||||
'address1' => $this->getString($invoice_data, 'DocumentRecipientAddress'),
|
||||
'shipping_address1' => $this->getString($invoice_data, 'ShipAddress'),
|
||||
'credit_balance' => 0,
|
||||
'settings' => new \stdClass,
|
||||
'client_hash' => Str::random(40),
|
||||
'contacts' => [
|
||||
[
|
||||
'email' => $this->getString($invoice_data, 'Email'),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
if (! empty($invoice_data['Date Paid'])) {
|
||||
$transformed['payments'] = [
|
||||
[
|
||||
'date' => date('Y-m-d', strtotime($invoice_data['DatePaid'])),
|
||||
'amount' => $this->getFloat($invoice_data, 'Payments'),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return $transformed;
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers;
|
||||
|
||||
/**
|
||||
* Class InvoiceItemTransformer.
|
||||
*/
|
||||
class InvoiceItemTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return bool|Item
|
||||
*/
|
||||
public function transform($data)
|
||||
{
|
||||
return [
|
||||
'quantity' => $this->getFloat($data, 'item.quantity'),
|
||||
'cost' => $this->getFloat($data, 'item.cost'),
|
||||
'product_key' => $this->getString($data, 'item.product_key'),
|
||||
'notes' => $this->getString($data, 'item.notes'),
|
||||
'discount' => $this->getFloat($data, 'item.discount'),
|
||||
'is_amount_discount' => $this->getString($data, 'item.is_amount_discount'),
|
||||
'tax_name1' => $this->getString($data, 'item.tax_name1'),
|
||||
'tax_rate1' => $this->getFloat($data, 'item.tax_rate1'),
|
||||
'tax_name2' => $this->getString($data, 'item.tax_name2'),
|
||||
'tax_rate2' => $this->getFloat($data, 'item.tax_rate2'),
|
||||
'tax_name3' => $this->getString($data, 'item.tax_name3'),
|
||||
'tax_rate3' => $this->getFloat($data, 'item.tax_rate3'),
|
||||
'custom_value1' => $this->getString($data, 'item.custom_value1'),
|
||||
'custom_value2' => $this->getString($data, 'item.custom_value2'),
|
||||
'custom_value3' => $this->getString($data, 'item.custom_value3'),
|
||||
'custom_value4' => $this->getString($data, 'item.custom_value4'),
|
||||
'type_id' => $this->getInvoiceTypeId($data, 'item.type_id'),
|
||||
];
|
||||
}
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers;
|
||||
|
||||
/**
|
||||
* Class InvoiceTransformer.
|
||||
*/
|
||||
class InvoiceTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return bool|Item
|
||||
*/
|
||||
public function transform($data)
|
||||
{
|
||||
return [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'number' => $this->getString($data, 'invoice.number'),
|
||||
'user_id' => $this->getString($data, 'invoice.user_id'),
|
||||
'amount' => $this->getFloat($data, 'invoice.amount'),
|
||||
'balance' => $this->getFloat($data, 'invoice.balance'),
|
||||
'client_id' => $this->getClient($this->getString($data, 'client.name'), $this->getString($data, 'client.email')),
|
||||
'discount' => $this->getFloat($data, 'invoice.discount'),
|
||||
'po_number' => $this->getString($data, 'invoice.po_number'),
|
||||
'date' => $this->getString($data, 'invoice.date'),
|
||||
'due_date' => $this->getString($data, 'invoice.due_date'),
|
||||
'terms' => $this->getString($data, 'invoice.terms'),
|
||||
'public_notes' => $this->getString($data, 'invoice.public_notes'),
|
||||
'is_sent' => $this->getString($data, 'invoice.is_sent'),
|
||||
'private_notes' => $this->getString($data, 'invoice.private_notes'),
|
||||
'tax_name1' => $this->getString($data, 'invoice.tax_name1'),
|
||||
'tax_rate1' => $this->getFloatWithSamePrecision($data, 'invoice.tax_rate1'),
|
||||
'tax_name2' => $this->getString($data, 'invoice.tax_name2'),
|
||||
'tax_rate2' => $this->getFloatWithSamePrecision($data, 'invoice.tax_rate2'),
|
||||
'tax_name3' => $this->getString($data, 'invoice.tax_name3'),
|
||||
'tax_rate3' => $this->getFloatWithSamePrecision($data, 'invoice.tax_rate3'),
|
||||
'custom_value1' => $this->getString($data, 'invoice.custom_value1'),
|
||||
'custom_value2' => $this->getString($data, 'invoice.custom_value2'),
|
||||
'custom_value3' => $this->getString($data, 'invoice.custom_value3'),
|
||||
'custom_value4' => $this->getString($data, 'invoice.custom_value4'),
|
||||
'footer' => $this->getString($data, 'invoice.footer'),
|
||||
'partial' => $this->getFloat($data, 'invoice.partial'),
|
||||
'partial_due_date' => $this->getString($data, 'invoice.partial_due_date'),
|
||||
'custom_surcharge1' => $this->getString($data, 'invoice.custom_surcharge1'),
|
||||
'custom_surcharge2' => $this->getString($data, 'invoice.custom_surcharge2'),
|
||||
'custom_surcharge3' => $this->getString($data, 'invoice.custom_surcharge3'),
|
||||
'custom_surcharge4' => $this->getString($data, 'invoice.custom_surcharge4'),
|
||||
'exchange_rate' => $this->getString($data, 'invoice.exchange_rate'),
|
||||
];
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://clientninja.com).
|
||||
*
|
||||
* @link https://github.com/clientninja/clientninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. client Ninja LLC (https://clientninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Invoicely;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Class ClientTransformer.
|
||||
*/
|
||||
class ClientTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public function transform($data)
|
||||
{
|
||||
if (isset($data['Client Name']) && $this->hasClient($data['Client Name'])) {
|
||||
throw new ImportException('Client already exists');
|
||||
}
|
||||
|
||||
return [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'name' => $this->getString($data, 'Client Name'),
|
||||
'phone' => $this->getString($data, 'Phone'),
|
||||
'country_id' => isset($data['Country']) ? $this->getCountryIdBy2($data['Country']) : null,
|
||||
'credit_balance' => 0,
|
||||
'settings' => new \stdClass,
|
||||
'client_hash' => Str::random(40),
|
||||
'contacts' => [
|
||||
[
|
||||
'email' => $this->getString($data, 'Email'),
|
||||
'phone' => $this->getString($data, 'Phone'),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* client Ninja (https://clientninja.com).
|
||||
*
|
||||
* @link https://github.com/clientninja/clientninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. client Ninja LLC (https://clientninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Invoicely;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
use App\Models\Invoice;
|
||||
|
||||
/**
|
||||
* Class InvoiceTransformer.
|
||||
*/
|
||||
class InvoiceTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return bool|array
|
||||
*/
|
||||
public function transform($data)
|
||||
{
|
||||
if ($this->hasInvoice($data['Details'])) {
|
||||
throw new ImportException('Invoice number already exists');
|
||||
}
|
||||
|
||||
$transformed = [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'client_id' => $this->getClient($this->getString($data, 'Client'), null),
|
||||
'number' => $this->getString($data, 'Details'),
|
||||
'date' => isset($data['Date']) ? date('Y-m-d', strtotime($data['Date'])) : null,
|
||||
'due_date' => isset($data['Due']) ? date('Y-m-d', strtotime($data['Due'])) : null,
|
||||
'status_id' => Invoice::STATUS_SENT,
|
||||
'line_items' => [
|
||||
[
|
||||
'cost' => $amount = $this->getFloat($data, 'Total'),
|
||||
'quantity' => 1,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
if (strtolower($data['Status']) === 'paid') {
|
||||
$transformed['payments'] = [
|
||||
[
|
||||
'date' => date('Y-m-d'),
|
||||
'amount' => $amount,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return $transformed;
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers;
|
||||
|
||||
/**
|
||||
* Class PaymentTransformer.
|
||||
*/
|
||||
class PaymentTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return bool|Item
|
||||
*/
|
||||
public function transform($data)
|
||||
{
|
||||
return [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'number' => $this->getString($data, 'payment.number'),
|
||||
'user_id' => $this->getString($data, 'payment.user_id'),
|
||||
'amount' => $this->getFloat($data, 'payment.amount'),
|
||||
'refunded' => $this->getFloat($data, 'payment.refunded'),
|
||||
'applied' => $this->getFloat($data, 'payment.applied'),
|
||||
'transaction_reference' => $this->getString($data, 'payment.transaction_reference '),
|
||||
'date' => $this->getString($data, 'payment.date'),
|
||||
'private_notes' => $this->getString($data, 'payment.private_notes'),
|
||||
'number' => $this->getString($data, 'number'),
|
||||
'custom_value1' => $this->getString($data, 'custom_value1'),
|
||||
'custom_value2' => $this->getString($data, 'custom_value2'),
|
||||
'custom_value3' => $this->getString($data, 'custom_value3'),
|
||||
'custom_value4' => $this->getString($data, 'custom_value4'),
|
||||
'client_id' => $this->getString($data, 'client_id'),
|
||||
'invoice_number' => $this->getString($data, 'payment.invoice_number'),
|
||||
'method' => $this,
|
||||
];
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://clientninja.com).
|
||||
*
|
||||
* @link https://github.com/clientninja/clientninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. client Ninja LLC (https://clientninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Waveaccounting;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Class ClientTransformer.
|
||||
*/
|
||||
class ClientTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public function transform($data)
|
||||
{
|
||||
if (isset($data['customer_name']) && $this->hasClient($data['customer_name'])) {
|
||||
throw new ImportException('Client already exists');
|
||||
}
|
||||
|
||||
$settings = new \stdClass;
|
||||
$settings->currency_id = (string) $this->getCurrencyByCode($data, 'customer_currency');
|
||||
|
||||
if (strval($data['Payment Terms'] ?? '') > 0) {
|
||||
$settings->payment_terms = $data['Payment Terms'];
|
||||
}
|
||||
|
||||
return [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'name' => $this->getString($data, 'customer_name'),
|
||||
'number' => $this->getString($data, 'account_number'),
|
||||
'phone' => $this->getString($data, 'phone'),
|
||||
'website' => $this->getString($data, 'website'),
|
||||
'country_id' => ! empty($data['country']) ? $this->getCountryId($data['country']) : null,
|
||||
'state' => $this->getString($data, 'province/state'),
|
||||
'address1' => $this->getString($data, 'address_line_1'),
|
||||
'address2' => $this->getString($data, 'address_line_2'),
|
||||
'city' => $this->getString($data, 'city'),
|
||||
'postal_code' => $this->getString($data, 'postal_code/zip_code'),
|
||||
|
||||
'shipping_country_id' => ! empty($data['ship-to_country']) ? $this->getCountryId($data['country']) : null,
|
||||
'shipping_state' => $this->getString($data, 'ship-to_province/state'),
|
||||
'shipping_address1' => $this->getString($data, 'ship-to_address_line_1'),
|
||||
'shipping_address2' => $this->getString($data, 'ship-to_address_line_2'),
|
||||
'shipping_city' => $this->getString($data, 'ship-to_city'),
|
||||
'shipping_postal_code' => $this->getString($data, 'ship-to_postal_code/zip_code'),
|
||||
'public_notes' => $this->getString($data, 'delivery_instructions'),
|
||||
|
||||
'credit_balance' => 0,
|
||||
'settings' =>$settings,
|
||||
'client_hash' => Str::random(40),
|
||||
'contacts' => [
|
||||
[
|
||||
'first_name' => $this->getString($data, 'contact_first_name'),
|
||||
'last_name' => $this->getString($data, 'contact_last_name'),
|
||||
'email' => $this->getString($data, 'email'),
|
||||
'phone' => $this->getString($data, 'phone'),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* client Ninja (https://clientninja.com).
|
||||
*
|
||||
* @link https://github.com/clientninja/clientninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. client Ninja LLC (https://clientninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Waveaccounting;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
use App\Models\Invoice;
|
||||
|
||||
/**
|
||||
* Class InvoiceTransformer.
|
||||
*/
|
||||
class InvoiceTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $line_items_data
|
||||
*
|
||||
* @return bool|array
|
||||
*/
|
||||
public function transform($line_items_data)
|
||||
{
|
||||
$invoice_data = reset($line_items_data);
|
||||
|
||||
if ($this->hasInvoice($invoice_data['Invoice Number'])) {
|
||||
throw new ImportException('Invoice number already exists');
|
||||
}
|
||||
|
||||
$transformed = [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'client_id' => $this->getClient($customer_name = $this->getString($invoice_data, 'Customer'), null),
|
||||
'number' => $invoice_number = $this->getString($invoice_data, 'Invoice Number'),
|
||||
'date' => date('Y-m-d', strtotime($invoice_data['Transaction Date'])) ?: now()->format('Y-m-d'), //27-01-2022
|
||||
// 'date' => isset( $invoice_data['Invoice Date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['Transaction Date'] ) ) : null,
|
||||
'currency_id' => $this->getCurrencyByCode($invoice_data, 'Currency'),
|
||||
'status_id' => Invoice::STATUS_SENT,
|
||||
];
|
||||
|
||||
$line_items = [];
|
||||
$payments = [];
|
||||
foreach ($line_items_data as $record) {
|
||||
if ($record['Account Type'] === 'Income') {
|
||||
$description = $this->getString($record, 'Transaction Line Description');
|
||||
|
||||
// Remove duplicate data from description
|
||||
if (substr($description, 0, strlen($customer_name) + 3) === $customer_name.' - ') {
|
||||
$description = substr($description, strlen($customer_name) + 3);
|
||||
}
|
||||
|
||||
if (substr($description, 0, strlen($invoice_number) + 3) === $invoice_number.' - ') {
|
||||
$description = substr($description, strlen($invoice_number) + 3);
|
||||
}
|
||||
|
||||
$line_items[] = [
|
||||
'notes' => $description,
|
||||
'cost' => $this->getFloat($record, 'Amount Before Sales Tax'),
|
||||
'tax_name1' => $this->getString($record, 'Sales Tax Name'),
|
||||
'tax_rate1' => $this->getFloat($record, 'Sales Tax Amount'),
|
||||
|
||||
'quantity' => 1,
|
||||
];
|
||||
} elseif ($record['Account Type'] === 'System Receivable Invoice') {
|
||||
// This is a payment
|
||||
$payments[] = [
|
||||
'date' => date('Y-m-d', strtotime($invoice_data['Transaction Date'])),
|
||||
'amount' => $this->getFloat($record, 'Amount (One column)'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$transformed['line_items'] = $line_items;
|
||||
$transformed['payments'] = $payments;
|
||||
|
||||
return $transformed;
|
||||
}
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://clientninja.com).
|
||||
*
|
||||
* @link https://github.com/clientninja/clientninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. client Ninja LLC (https://clientninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Zoho;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Class ClientTransformer.
|
||||
*/
|
||||
class ClientTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public function transform($data)
|
||||
{
|
||||
if (isset($data['Company Name']) && $this->hasClient($data['Company Name'])) {
|
||||
throw new ImportException('Client already exists');
|
||||
}
|
||||
|
||||
$settings = new \stdClass;
|
||||
$settings->currency_id = (string) $this->getCurrencyByCode($data, 'Currency');
|
||||
|
||||
if (strval($data['Payment Terms'] ?? '') > 0) {
|
||||
$settings->payment_terms = $data['Payment Terms'];
|
||||
}
|
||||
|
||||
return [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'name' => $this->getString($data, 'Company Name'),
|
||||
'phone' => $this->getString($data, 'Phone'),
|
||||
'private_notes' => $this->getString($data, 'Notes'),
|
||||
'website' => $this->getString($data, 'Website'),
|
||||
'id_number' => $this->getString($data, 'Customer ID'),
|
||||
'address1' => $this->getString($data, 'Billing Address'),
|
||||
'address2' => $this->getString($data, 'Billing Street2'),
|
||||
'city' => $this->getString($data, 'Billing City'),
|
||||
'state' => $this->getString($data, 'Billing State'),
|
||||
'postal_code' => $this->getString($data, 'Billing Code'),
|
||||
'country_id' => isset($data['Billing Country']) ? $this->getCountryId($data['Billing Country']) : null,
|
||||
|
||||
'shipping_address1' => $this->getString($data, 'Shipping Address'),
|
||||
'shipping_address2' => $this->getString($data, 'Shipping Street2'),
|
||||
'shipping_city' => $this->getString($data, 'Shipping City'),
|
||||
'shipping_state' => $this->getString($data, 'Shipping State'),
|
||||
'shipping_postal_code' => $this->getString($data, 'Shipping Code'),
|
||||
'shipping_country_id' => isset($data['Shipping Country']) ? $this->getCountryId($data['Shipping Country']) : null,
|
||||
'credit_balance' => 0,
|
||||
'settings' => $settings,
|
||||
'client_hash' => Str::random(40),
|
||||
'contacts' => [
|
||||
[
|
||||
'first_name' => $this->getString($data, 'First Name'),
|
||||
'last_name' => $this->getString($data, 'Last Name'),
|
||||
'email' => $this->getString($data, 'Email'),
|
||||
'phone' => $this->getString($data, 'Phone'),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* client Ninja (https://clientninja.com).
|
||||
*
|
||||
* @link https://github.com/clientninja/clientninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. client Ninja LLC (https://clientninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Zoho;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
use App\Models\Invoice;
|
||||
|
||||
/**
|
||||
* Class InvoiceTransformer.
|
||||
*/
|
||||
class InvoiceTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $line_items_data
|
||||
*
|
||||
* @return bool|array
|
||||
*/
|
||||
public function transform($line_items_data)
|
||||
{
|
||||
$invoice_data = reset($line_items_data);
|
||||
|
||||
if ($this->hasInvoice($invoice_data['Invoice Number'])) {
|
||||
throw new ImportException('Invoice number already exists');
|
||||
}
|
||||
|
||||
$invoiceStatusMap = [
|
||||
'sent' => Invoice::STATUS_SENT,
|
||||
'draft' => Invoice::STATUS_DRAFT,
|
||||
];
|
||||
|
||||
$transformed = [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'client_id' => $this->getClient($this->getString($invoice_data, 'Customer ID'), null),
|
||||
'number' => $this->getString($invoice_data, 'Invoice Number'),
|
||||
'date' => isset($invoice_data['Invoice Date']) ? date('Y-m-d', strtotime($invoice_data['Invoice Date'])) : null,
|
||||
'due_date' => isset($invoice_data['Due Date']) ? date('Y-m-d', strtotime($invoice_data['Due Date'])) : null,
|
||||
'po_number' => $this->getString($invoice_data, 'PurchaseOrder'),
|
||||
'public_notes' => $this->getString($invoice_data, 'Notes'),
|
||||
// 'currency_id' => $this->getCurrencyByCode($invoice_data, 'Currency'),
|
||||
'amount' => $this->getFloat($invoice_data, 'Total'),
|
||||
'balance' => $this->getFloat($invoice_data, 'Balance'),
|
||||
'status_id' => $invoiceStatusMap[$status =
|
||||
strtolower($this->getString($invoice_data, 'Invoice Status'))] ?? Invoice::STATUS_SENT,
|
||||
// 'viewed' => $status === 'viewed',
|
||||
];
|
||||
|
||||
$line_items = [];
|
||||
foreach ($line_items_data as $record) {
|
||||
$line_items[] = [
|
||||
'product_key' => $this->getString($record, 'Item Name'),
|
||||
'notes' => $this->getString($record, 'Item Description'),
|
||||
'cost' => round($this->getFloat($record, 'Item Price'), 2),
|
||||
'quantity' => $this->getFloat($record, 'Quantity'),
|
||||
'discount' => $this->getString($record, 'Discount Amount'),
|
||||
'is_amount_discount' => true,
|
||||
];
|
||||
}
|
||||
$transformed['line_items'] = $line_items;
|
||||
|
||||
if ($transformed['balance'] < $transformed['amount']) {
|
||||
$transformed['payments'] = [[
|
||||
'date' => isset($invoice_data['Last Payment Date']) ? date('Y-m-d', strtotime($invoice_data['Invoice Date'])) : date('Y-m-d'),
|
||||
'amount' => $transformed['amount'] - $transformed['balance'],
|
||||
]];
|
||||
}
|
||||
|
||||
return $transformed;
|
||||
}
|
||||
}
|
@ -1,627 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Jobs\Import;
|
||||
|
||||
use App\Factory\ClientFactory;
|
||||
use App\Factory\InvoiceFactory;
|
||||
use App\Factory\PaymentFactory;
|
||||
use App\Http\Requests\Invoice\StoreInvoiceRequest;
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
use App\Jobs\Mail\NinjaMailerJob;
|
||||
use App\Jobs\Mail\NinjaMailerObject;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Mail\Import\ImportCompleted;
|
||||
use App\Models\Client;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\Company;
|
||||
use App\Models\Country;
|
||||
use App\Models\Currency;
|
||||
use App\Models\ExpenseCategory;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\PaymentType;
|
||||
use App\Models\Product;
|
||||
use App\Models\Project;
|
||||
use App\Models\TaxRate;
|
||||
use App\Models\User;
|
||||
use App\Models\Vendor;
|
||||
use App\Repositories\BaseRepository;
|
||||
use App\Repositories\ClientRepository;
|
||||
use App\Repositories\InvoiceRepository;
|
||||
use App\Repositories\PaymentRepository;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Traits\CleanLineItems;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
use League\Csv\Reader;
|
||||
use League\Csv\Statement;
|
||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class CSVImport implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, CleanLineItems;
|
||||
|
||||
public $invoice;
|
||||
|
||||
public $company;
|
||||
|
||||
public $hash;
|
||||
|
||||
public $import_type;
|
||||
|
||||
public $skip_header;
|
||||
|
||||
public $column_map;
|
||||
|
||||
public $import_array;
|
||||
|
||||
public $error_array = [];
|
||||
|
||||
public $maps;
|
||||
|
||||
public function __construct(array $request, Company $company)
|
||||
{
|
||||
$this->company = $company;
|
||||
$this->hash = $request['hash'];
|
||||
$this->import_type = $request['import_type'];
|
||||
$this->skip_header = $request['skip_header'] ?? null;
|
||||
$this->column_map =
|
||||
! empty($request['column_map']) ?
|
||||
array_combine(array_keys($request['column_map']), array_column($request['column_map'], 'mapping')) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
MultiDB::setDb($this->company->db);
|
||||
|
||||
Auth::login($this->company->owner(), true);
|
||||
|
||||
auth()->user()->setCompany($this->company);
|
||||
|
||||
$this->buildMaps();
|
||||
|
||||
nlog('import '.$this->import_type);
|
||||
foreach (['client', 'product', 'invoice', 'payment', 'vendor', 'expense'] as $entityType) {
|
||||
$csvData = $this->getCsvData($entityType);
|
||||
|
||||
if (! empty($csvData)) {
|
||||
$importFunction = 'import'.Str::plural(Str::title($entityType));
|
||||
$preTransformFunction = 'preTransform'.Str::title($this->import_type);
|
||||
|
||||
if (method_exists($this, $preTransformFunction)) {
|
||||
$csvData = $this->$preTransformFunction($csvData, $entityType);
|
||||
}
|
||||
|
||||
if (empty($csvData)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (method_exists($this, $importFunction)) {
|
||||
// If there's an entity-specific import function, use that.
|
||||
$this->$importFunction($csvData);
|
||||
} else {
|
||||
// Otherwise, use the generic import function.
|
||||
$this->importEntities($csvData, $entityType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$data = [
|
||||
'errors' => $this->error_array,
|
||||
'company' => $this->company,
|
||||
];
|
||||
|
||||
$nmo = new NinjaMailerObject;
|
||||
$nmo->mailable = new ImportCompleted($this->company, $data);
|
||||
$nmo->company = $this->company;
|
||||
$nmo->settings = $this->company->settings;
|
||||
$nmo->to_user = $this->company->owner();
|
||||
|
||||
NinjaMailerJob::dispatch($nmo);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
private function preTransformCsv($csvData, $entityType)
|
||||
{
|
||||
if (empty($this->column_map[$entityType])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->skip_header) {
|
||||
array_shift($csvData);
|
||||
}
|
||||
|
||||
//sort the array by key
|
||||
$keys = $this->column_map[$entityType];
|
||||
ksort($keys);
|
||||
|
||||
$csvData = array_map(function ($row) use ($keys) {
|
||||
return array_combine($keys, array_intersect_key($row, $keys));
|
||||
}, $csvData);
|
||||
|
||||
if ($entityType === 'invoice') {
|
||||
$csvData = $this->groupInvoices($csvData, 'invoice.number');
|
||||
}
|
||||
|
||||
return $csvData;
|
||||
}
|
||||
|
||||
private function preTransformFreshbooks($csvData, $entityType)
|
||||
{
|
||||
$csvData = $this->mapCSVHeaderToKeys($csvData);
|
||||
|
||||
if ($entityType === 'invoice') {
|
||||
$csvData = $this->groupInvoices($csvData, 'Invoice #');
|
||||
}
|
||||
|
||||
return $csvData;
|
||||
}
|
||||
|
||||
private function preTransformInvoicely($csvData, $entityType)
|
||||
{
|
||||
$csvData = $this->mapCSVHeaderToKeys($csvData);
|
||||
|
||||
return $csvData;
|
||||
}
|
||||
|
||||
private function preTransformInvoice2go($csvData, $entityType)
|
||||
{
|
||||
$csvData = $this->mapCSVHeaderToKeys($csvData);
|
||||
|
||||
return $csvData;
|
||||
}
|
||||
|
||||
private function preTransformZoho($csvData, $entityType)
|
||||
{
|
||||
$csvData = $this->mapCSVHeaderToKeys($csvData);
|
||||
|
||||
if ($entityType === 'invoice') {
|
||||
$csvData = $this->groupInvoices($csvData, 'Invoice Number');
|
||||
}
|
||||
|
||||
return $csvData;
|
||||
}
|
||||
|
||||
private function preTransformWaveaccounting($csvData, $entityType)
|
||||
{
|
||||
$csvData = $this->mapCSVHeaderToKeys($csvData);
|
||||
|
||||
if ($entityType === 'invoice') {
|
||||
$csvData = $this->groupInvoices($csvData, 'Invoice Number');
|
||||
}
|
||||
|
||||
return $csvData;
|
||||
}
|
||||
|
||||
private function groupInvoices($csvData, $key)
|
||||
{
|
||||
// Group by invoice.
|
||||
$grouped = [];
|
||||
|
||||
foreach ($csvData as $line_item) {
|
||||
if (empty($line_item[$key])) {
|
||||
$this->error_array['invoice'][] = ['invoice' => $line_item, 'error' => 'No invoice number'];
|
||||
} else {
|
||||
$grouped[$line_item[$key]][] = $line_item;
|
||||
}
|
||||
}
|
||||
|
||||
return $grouped;
|
||||
}
|
||||
|
||||
private function mapCSVHeaderToKeys($csvData)
|
||||
{
|
||||
$keys = array_shift($csvData);
|
||||
|
||||
return array_map(function ($values) use ($keys) {
|
||||
return array_combine($keys, $values);
|
||||
}, $csvData);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
private function importInvoices($invoices)
|
||||
{
|
||||
$invoice_transformer = $this->getTransformer('invoice');
|
||||
|
||||
/** @var PaymentRepository $payment_repository */
|
||||
$payment_repository = app()->make(PaymentRepository::class);
|
||||
$payment_repository->import_mode = true;
|
||||
|
||||
/** @var ClientRepository $client_repository */
|
||||
$client_repository = app()->make(ClientRepository::class);
|
||||
$client_repository->import_mode = true;
|
||||
|
||||
$invoice_repository = new InvoiceRepository();
|
||||
$invoice_repository->import_mode = true;
|
||||
|
||||
foreach ($invoices as $raw_invoice) {
|
||||
try {
|
||||
$invoice_data = $invoice_transformer->transform($raw_invoice);
|
||||
|
||||
$invoice_data['line_items'] = $this->cleanItems($invoice_data['line_items'] ?? []);
|
||||
|
||||
// If we don't have a client ID, but we do have client data, go ahead and create the client.
|
||||
if (empty($invoice_data['client_id']) && ! empty($invoice_data['client'])) {
|
||||
$client_data = $invoice_data['client'];
|
||||
$client_data['user_id'] = $this->getUserIDForRecord($invoice_data);
|
||||
|
||||
$client_repository->save(
|
||||
$client_data,
|
||||
$client = ClientFactory::create($this->company->id, $client_data['user_id'])
|
||||
);
|
||||
$invoice_data['client_id'] = $client->id;
|
||||
unset($invoice_data['client']);
|
||||
}
|
||||
|
||||
$validator = Validator::make($invoice_data, ( new StoreInvoiceRequest() )->rules());
|
||||
if ($validator->fails()) {
|
||||
$this->error_array['invoice'][] =
|
||||
['invoice' => $invoice_data, 'error' => $validator->errors()->all()];
|
||||
} else {
|
||||
$invoice = InvoiceFactory::create($this->company->id, $this->getUserIDForRecord($invoice_data));
|
||||
if (! empty($invoice_data['status_id'])) {
|
||||
$invoice->status_id = $invoice_data['status_id'];
|
||||
}
|
||||
$invoice_repository->save($invoice_data, $invoice);
|
||||
$this->addInvoiceToMaps($invoice);
|
||||
|
||||
// If we're doing a generic CSV import, only import payment data if we're not importing a payment CSV.
|
||||
// If we're doing a platform-specific import, trust the platform to only return payment info if there's not a separate payment CSV.
|
||||
if ($this->import_type !== 'csv' || empty($this->column_map['payment'])) {
|
||||
// Check for payment columns
|
||||
if (! empty($invoice_data['payments'])) {
|
||||
foreach ($invoice_data['payments'] as $payment_data) {
|
||||
$payment_data['user_id'] = $invoice->user_id;
|
||||
$payment_data['client_id'] = $invoice->client_id;
|
||||
$payment_data['invoices'] = [
|
||||
[
|
||||
'invoice_id' => $invoice->id,
|
||||
'amount' => $payment_data['amount'] ?? null,
|
||||
],
|
||||
];
|
||||
|
||||
/* Make sure we don't apply any payments to invoices with a Zero Amount*/
|
||||
if ($invoice->amount > 0) {
|
||||
$payment_repository->save(
|
||||
$payment_data,
|
||||
PaymentFactory::create($this->company->id, $invoice->user_id, $invoice->client_id)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->actionInvoiceStatus($invoice, $invoice_data, $invoice_repository);
|
||||
}
|
||||
} catch (\Exception $ex) {
|
||||
if ($ex instanceof ImportException) {
|
||||
$message = $ex->getMessage();
|
||||
} else {
|
||||
report($ex);
|
||||
$message = 'Unknown error';
|
||||
}
|
||||
|
||||
$this->error_array['invoice'][] = ['invoice' => $raw_invoice, 'error' => $message];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function actionInvoiceStatus($invoice, $invoice_data, $invoice_repository)
|
||||
{
|
||||
if (! empty($invoice_data['archived'])) {
|
||||
$invoice_repository->archive($invoice);
|
||||
$invoice->fresh();
|
||||
}
|
||||
|
||||
if (! empty($invoice_data['viewed'])) {
|
||||
$invoice = $invoice->service()->markViewed()->save();
|
||||
}
|
||||
|
||||
if ($invoice->status_id === Invoice::STATUS_DRAFT) {
|
||||
} elseif ($invoice->status_id === Invoice::STATUS_SENT) {
|
||||
$invoice = $invoice->service()->markSent()->save();
|
||||
} elseif ($invoice->status_id <= Invoice::STATUS_SENT && $invoice->amount > 0) {
|
||||
if ($invoice->balance <= 0) {
|
||||
$invoice->status_id = Invoice::STATUS_PAID;
|
||||
$invoice->save();
|
||||
} elseif ($invoice->balance != $invoice->amount) {
|
||||
$invoice->status_id = Invoice::STATUS_PARTIAL;
|
||||
$invoice->save();
|
||||
}
|
||||
}
|
||||
|
||||
return $invoice;
|
||||
}
|
||||
|
||||
private function importEntities($records, $entity_type)
|
||||
{
|
||||
$entity_type = Str::slug($entity_type, '_');
|
||||
$formatted_entity_type = Str::title($entity_type);
|
||||
|
||||
$request_name = "\\App\\Http\\Requests\\${formatted_entity_type}\\Store${formatted_entity_type}Request";
|
||||
$repository_name = '\\App\\Repositories\\'.$formatted_entity_type.'Repository';
|
||||
$factoryName = '\\App\\Factory\\'.$formatted_entity_type.'Factory';
|
||||
|
||||
/** @var BaseRepository $repository */
|
||||
$repository = app()->make($repository_name);
|
||||
$repository->import_mode = true;
|
||||
|
||||
$transformer = $this->getTransformer($entity_type);
|
||||
|
||||
foreach ($records as $record) {
|
||||
try {
|
||||
$entity = $transformer->transform($record);
|
||||
|
||||
/** @var \App\Http\Requests\Request $request */
|
||||
// $request = new $request_name();
|
||||
// $request->prepareForValidation();
|
||||
|
||||
// Pass entity data to request so it can be validated
|
||||
// $request->query = $request->request = new ParameterBag( $entity );
|
||||
// $validator = Validator::make( $entity, $request->rules() );
|
||||
$validator = $request_name::runFormRequest($entity);
|
||||
|
||||
if ($validator->fails()) {
|
||||
$this->error_array[$entity_type][] =
|
||||
[$entity_type => $record, 'error' => $validator->errors()->all()];
|
||||
} else {
|
||||
$entity =
|
||||
$repository->save(
|
||||
array_diff_key($entity, ['user_id' => false]),
|
||||
$factoryName::create($this->company->id, $this->getUserIDForRecord($entity)));
|
||||
|
||||
$entity->save();
|
||||
if (method_exists($this, 'add'.$formatted_entity_type.'ToMaps')) {
|
||||
$this->{'add'.$formatted_entity_type.'ToMaps'}($entity);
|
||||
}
|
||||
}
|
||||
} catch (\Exception $ex) {
|
||||
if ($ex instanceof ImportException) {
|
||||
$message = $ex->getMessage();
|
||||
} else {
|
||||
report($ex);
|
||||
$message = 'Unknown error';
|
||||
}
|
||||
|
||||
$this->error_array[$entity_type][] = [$entity_type => $record, 'error' => $message];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $entity_type
|
||||
*
|
||||
* @return BaseTransformer
|
||||
*/
|
||||
private function getTransformer($entity_type)
|
||||
{
|
||||
$formatted_entity_type = Str::title($entity_type);
|
||||
$formatted_import_type = Str::title($this->import_type);
|
||||
$transformer_name =
|
||||
'\\App\\Import\\Transformers\\'.$formatted_import_type.'\\'.$formatted_entity_type.'Transformer';
|
||||
|
||||
return new $transformer_name($this->maps);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
private function buildMaps()
|
||||
{
|
||||
$this->maps = [
|
||||
'company' => $this->company,
|
||||
'client' => [],
|
||||
'contact' => [],
|
||||
'invoice' => [],
|
||||
'invoice_client' => [],
|
||||
'product' => [],
|
||||
'countries' => [],
|
||||
'countries2' => [],
|
||||
'currencies' => [],
|
||||
'client_ids' => [],
|
||||
'invoice_ids' => [],
|
||||
'vendors' => [],
|
||||
'expense_categories' => [],
|
||||
'payment_types' => [],
|
||||
'tax_rates' => [],
|
||||
'tax_names' => [],
|
||||
];
|
||||
|
||||
Client::where('company_id', $this->company->id)->cursor()->each(function ($client) {
|
||||
$this->addClientToMaps($client);
|
||||
});
|
||||
|
||||
ClientContact::where('company_id', $this->company->id)->cursor()->each(function ($contact) {
|
||||
$this->addContactToMaps($contact);
|
||||
});
|
||||
|
||||
Invoice::where('company_id', $this->company->id)->cursor()->each(function ($invoice) {
|
||||
$this->addInvoiceToMaps($invoice);
|
||||
});
|
||||
|
||||
Product::where('company_id', $this->company->id)->cursor()->each(function ($product) {
|
||||
$this->addProductToMaps($product);
|
||||
});
|
||||
|
||||
Project::where('company_id', $this->company->id)->cursor()->each(function ($project) {
|
||||
$this->addProjectToMaps($project);
|
||||
});
|
||||
|
||||
Country::all()->each(function ($country) {
|
||||
$this->maps['countries'][strtolower($country->name)] = $country->id;
|
||||
$this->maps['countries2'][strtolower($country->iso_3166_2)] = $country->id;
|
||||
});
|
||||
|
||||
Currency::all()->each(function ($currency) {
|
||||
$this->maps['currencies'][strtolower($currency->code)] = $currency->id;
|
||||
});
|
||||
|
||||
PaymentType::all()->each(function ($payment_type) {
|
||||
$this->maps['payment_types'][strtolower($payment_type->name)] = $payment_type->id;
|
||||
});
|
||||
|
||||
Vendor::where('company_id', $this->company->id)->cursor()->each(function ($vendor) {
|
||||
$this->addVendorToMaps($vendor);
|
||||
});
|
||||
|
||||
ExpenseCategory::where('company_id', $this->company->id)->cursor()->each(function ($category) {
|
||||
$this->addExpenseCategoryToMaps($category);
|
||||
});
|
||||
|
||||
TaxRate::where('company_id', $this->company->id)->cursor()->each(function ($taxRate) {
|
||||
$name = trim(strtolower($taxRate->name));
|
||||
$this->maps['tax_rates'][$name] = $taxRate->rate;
|
||||
$this->maps['tax_names'][$name] = $taxRate->name;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Invoice $invoice
|
||||
*/
|
||||
private function addInvoiceToMaps(Invoice $invoice)
|
||||
{
|
||||
if ($number = strtolower(trim($invoice->number))) {
|
||||
$this->maps['invoices'][$number] = $invoice;
|
||||
$this->maps['invoice'][$number] = $invoice->id;
|
||||
$this->maps['invoice_client'][$number] = $invoice->client_id;
|
||||
$this->maps['invoice_ids'][$invoice->public_id] = $invoice->id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Client $client
|
||||
*/
|
||||
private function addClientToMaps(Client $client)
|
||||
{
|
||||
if ($name = strtolower(trim($client->name))) {
|
||||
$this->maps['client'][$name] = $client->id;
|
||||
$this->maps['client_ids'][$client->public_id] = $client->id;
|
||||
}
|
||||
if ($client->contacts->count()) {
|
||||
$contact = $client->contacts[0];
|
||||
if ($email = strtolower(trim($contact->email))) {
|
||||
$this->maps['client'][$email] = $client->id;
|
||||
}
|
||||
if ($name = strtolower(trim($contact->first_name.' '.$contact->last_name))) {
|
||||
$this->maps['client'][$name] = $client->id;
|
||||
}
|
||||
$this->maps['client_ids'][$client->public_id] = $client->id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClientContact $contact
|
||||
*/
|
||||
private function addContactToMaps(ClientContact $contact)
|
||||
{
|
||||
if ($key = strtolower(trim($contact->email))) {
|
||||
$this->maps['contact'][$key] = $contact;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Product $product
|
||||
*/
|
||||
private function addProductToMaps(Product $product)
|
||||
{
|
||||
if ($key = strtolower(trim($product->product_key))) {
|
||||
$this->maps['product'][$key] = $product;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Project $project
|
||||
*/
|
||||
private function addProjectToMaps(Project $project)
|
||||
{
|
||||
if ($key = strtolower(trim($project->name))) {
|
||||
$this->maps['project'][$key] = $project;
|
||||
}
|
||||
}
|
||||
|
||||
private function addVendorToMaps(Vendor $vendor)
|
||||
{
|
||||
$this->maps['vendor'][strtolower($vendor->name)] = $vendor->id;
|
||||
}
|
||||
|
||||
private function addExpenseCategoryToMaps(ExpenseCategory $category)
|
||||
{
|
||||
if ($name = strtolower($category->name)) {
|
||||
$this->maps['expense_category'][$name] = $category->id;
|
||||
}
|
||||
}
|
||||
|
||||
private function getUserIDForRecord($record)
|
||||
{
|
||||
if (! empty($record['user_id'])) {
|
||||
return $this->findUser($record['user_id']);
|
||||
} else {
|
||||
return $this->company->owner()->id;
|
||||
}
|
||||
}
|
||||
|
||||
private function findUser($user_hash)
|
||||
{
|
||||
$user = User::where('account_id', $this->company->account->id)
|
||||
->where(\DB::raw('CONCAT_WS(" ", first_name, last_name)'), 'like', '%'.$user_hash.'%')
|
||||
->first();
|
||||
|
||||
if ($user) {
|
||||
return $user->id;
|
||||
} else {
|
||||
return $this->company->owner()->id;
|
||||
}
|
||||
}
|
||||
|
||||
private function getCsvData($entityType)
|
||||
{
|
||||
$base64_encoded_csv = Cache::pull($this->hash.'-'.$entityType);
|
||||
if (empty($base64_encoded_csv)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$csv = base64_decode($base64_encoded_csv);
|
||||
$csv = Reader::createFromString($csv);
|
||||
|
||||
$stmt = new Statement();
|
||||
$data = iterator_to_array($stmt->process($csv));
|
||||
|
||||
if (count($data) > 0) {
|
||||
$headers = $data[0];
|
||||
|
||||
// Remove Invoice Ninja headers
|
||||
if (count($headers) && count($data) > 4 && $this->import_type === 'csv') {
|
||||
$firstCell = $headers[0];
|
||||
if (strstr($firstCell, config('ninja.app_name'))) {
|
||||
array_shift($data); // Invoice Ninja...
|
||||
array_shift($data); // <blank line>
|
||||
array_shift($data); // Enitty Type Header
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
@ -23,7 +23,6 @@ use App\Libraries\MultiDB;
|
||||
use App\Models\Client;
|
||||
use App\Models\Company;
|
||||
use App\Models\Vendor;
|
||||
use App\Utils\Ninja;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
|
93
app/Mail/Import/CsvImportCompleted.php
Normal file
93
app/Mail/Import/CsvImportCompleted.php
Normal file
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Mail\Import;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Utils\Ninja;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\App;
|
||||
|
||||
class CsvImportCompleted extends Mailable
|
||||
{
|
||||
// use Queueable, SerializesModels;
|
||||
|
||||
/** @var Company */
|
||||
public $company;
|
||||
|
||||
/**
|
||||
* @var array $data Array containing the necessary params.
|
||||
*
|
||||
* $data = [
|
||||
* 'errors' => (array) $errors,
|
||||
* 'company' => Company $company,
|
||||
* 'entity_count' => (array) $entity_count
|
||||
* ];
|
||||
*/
|
||||
public $data;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Company $company, $data)
|
||||
{
|
||||
$this->company = $company;
|
||||
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
App::forgetInstance('translator');
|
||||
App::setLocale($this->company->getLocale());
|
||||
|
||||
$t = app('translator');
|
||||
$t->replace(Ninja::transformTranslations($this->company->settings));
|
||||
|
||||
$data = array_merge($this->data, [
|
||||
'logo' => $this->company->present()->logo(),
|
||||
'settings' => $this->company->settings,
|
||||
'company' => $this->company,
|
||||
'client_count' => isset($this->data['entity_count']['clients']) ? $this->data['entity_count']['clients'] : false,
|
||||
'product_count' => isset($this->data['entity_count']['products']) ? $this->data['entity_count']['products'] : false,
|
||||
'invoice_count' => isset($this->data['entity_count']['invoices']) ? $this->data['entity_count']['invoices'] : false,
|
||||
'quote_count' => isset($this->data['entity_count']['quotes']) ? $this->data['entity_count']['quotes'] : false,
|
||||
'credit_count' => isset($this->data['entity_count']['credits']) ? $this->data['entity_count']['credits'] : false,
|
||||
'project_count' => isset($this->data['entity_count']['projects']) ? $this->data['entity_count']['projects'] : false,
|
||||
'task_count' => isset($this->data['entity_count']['tasks']) ? $this->data['entity_count']['tasks'] : false,
|
||||
'vendor_count' => isset($this->data['entity_count']['vendors']) ? $this->data['entity_count']['vendors'] : false,
|
||||
'payment_count' => isset($this->data['entity_count']['payments']) ? $this->data['entity_count']['payments'] : false,
|
||||
'recurring_invoice_count' => isset($this->data['entity_count']['recurring_invoices']) ? $this->data['entity_count']['recurring_invoices'] : false,
|
||||
'expense_count' => isset($this->data['entity_count']['expenses']) ? $this->data['entity_count']['expenses'] : false,
|
||||
'company_gateway_count' => isset($this->data['entity_count']['company_gateways']) ? $this->data['entity_count']['company_gateways'] : false,
|
||||
'client_gateway_token_count' => isset($this->data['entity_count']['client_gateway_tokens']) ? $this->data['entity_count']['client_gateway_tokens'] : false,
|
||||
'tax_rate_count' => isset($this->data['entity_count']['tax_rates']) ? $this->data['entity_count']['tax_rates'] : false,
|
||||
'document_count' => isset($this->data['entity_count']['documents']) ? $this->data['entity_count']['documents'] : false,
|
||||
'transaction_count' => isset($this->data['entity_count']['transactions']) ? $this->data['entity_count']['transactions'] : false,
|
||||
]);
|
||||
|
||||
return $this
|
||||
->subject(ctrans('texts.import_completed'))
|
||||
->from(config('mail.from.address'), config('mail.from.name'))
|
||||
->text('email.import.csv_completed_text')
|
||||
->view('email.import.csv_completed', $data);
|
||||
}
|
||||
}
|
@ -4923,7 +4923,7 @@ $LANG = array(
|
||||
'matomo_id' => 'Matomo Id',
|
||||
'action_add_to_invoice' => 'Add To Invoice',
|
||||
'danger_zone' => 'Danger Zone',
|
||||
|
||||
'import_completed' => 'Import completed',
|
||||
);
|
||||
|
||||
|
||||
|
102
resources/views/email/import/csv_completed.blade.php
Normal file
102
resources/views/email/import/csv_completed.blade.php
Normal file
@ -0,0 +1,102 @@
|
||||
@component('email.template.admin', ['logo' => $logo, 'settings' => $settings, 'company' => $company ?? ''])
|
||||
<div class="center">
|
||||
<h1>{{ ctrans('texts.import_complete') }}</h1>
|
||||
|
||||
<p><img src="{{ $logo }}"></p>
|
||||
|
||||
@if($client_count)
|
||||
<p><b>{{ ctrans('texts.clients') }}:</b> {{ $client_count }} </p>
|
||||
@endif
|
||||
|
||||
@if($product_count)
|
||||
<p><b>{{ ctrans('texts.products') }}:</b> {{ $product_count }} </p>
|
||||
@endif
|
||||
|
||||
@if($invoice_count)
|
||||
<p><b>{{ ctrans('texts.invoices') }}:</b> {{ $invoice_count }} </p>
|
||||
@endif
|
||||
|
||||
@if($payment_count)
|
||||
<p><b>{{ ctrans('texts.payments') }}:</b> {{ $payment_count }} </p>
|
||||
@endif
|
||||
|
||||
@if($recurring_invoice_count)
|
||||
<p><b>{{ ctrans('texts.recurring_invoices') }}:</b> {{ $recurring_invoice_count }} </p>
|
||||
@endif
|
||||
|
||||
@if($quote_count)
|
||||
<p><b>{{ ctrans('texts.quotes') }}:</b> {{ $quote_count }} </p>
|
||||
@endif
|
||||
|
||||
@if($credit_count)
|
||||
<p><b>{{ ctrans('texts.credits') }}:</b> {{ $credit_count }} </p>
|
||||
@endif
|
||||
|
||||
@if($project_count)
|
||||
<p><b>{{ ctrans('texts.projects') }}:</b> {{ $project_count }} </p>
|
||||
@endif
|
||||
|
||||
@if($task_count)
|
||||
<p><b>{{ ctrans('texts.tasks') }}:</b> {{ $task_count }} </p>
|
||||
@endif
|
||||
|
||||
@if($vendor_count)
|
||||
<p><b>{{ ctrans('texts.vendors') }}:</b> {{ $vendor_count }} </p>
|
||||
@endif
|
||||
|
||||
@if($expense_count)
|
||||
<p><b>{{ ctrans('texts.expenses') }}:</b> {{ $expense_count }} </p>
|
||||
@endif
|
||||
|
||||
@if($company_gateway_count)
|
||||
<p><b>{{ ctrans('texts.gateways') }}:</b> {{ $company_gateway_count }} </p>
|
||||
@endif
|
||||
|
||||
@if($client_gateway_token_count)
|
||||
<p><b>{{ ctrans('texts.tokens') }}:</b> {{ $client_gateway_token_count }} </p>
|
||||
@endif
|
||||
|
||||
@if($tax_rate_count)
|
||||
<p><b>{{ ctrans('texts.tax_rates') }}:</b> {{ $tax_rate_count }} </p>
|
||||
@endif
|
||||
|
||||
@if($document_count)
|
||||
<p><b>{{ ctrans('texts.documents') }}:</b> {{ $document_count }} </p>
|
||||
@endif
|
||||
|
||||
@if($transaction_count)
|
||||
<p><b>{{ ctrans('texts.documents') }}:</b> {{ $transaction_count }} </p>
|
||||
@endif
|
||||
|
||||
@if(!empty($errors) )
|
||||
<p>{{ ctrans('texts.failed_to_import') }}</p>
|
||||
<p>{{ ctrans('texts.error') }}:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Data</th>
|
||||
<th>Error</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($errors as $entityType=>$entityErrors)
|
||||
@foreach($entityErrors as $error)
|
||||
<tr>
|
||||
<td>{{$entityType}}</td>
|
||||
<td>{{json_encode($error[$entityType]??null)}}</td>
|
||||
<td>{{json_encode($error['error'])}}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
@endif
|
||||
|
||||
<a href="{{ url('/') }}" target="_blank" class="button">{{ ctrans('texts.account_login')}}</a>
|
||||
|
||||
<p>{{ ctrans('texts.email_signature')}}</p>
|
||||
<p>{{ ctrans('texts.email_from') }}</p>
|
||||
</div>
|
||||
@endcomponent
|
||||
|
98
resources/views/email/import/csv_completed_text.blade.php
Normal file
98
resources/views/email/import/csv_completed_text.blade.php
Normal file
@ -0,0 +1,98 @@
|
||||
{{ ctrans('texts.import_complete') }}
|
||||
|
||||
@if($client_count)
|
||||
{{ ctrans('texts.clients') }}: {{ $client_count }}
|
||||
@endif
|
||||
|
||||
@if($product_count)
|
||||
{{ ctrans('texts.products') }}: {{ $product_count }}
|
||||
@endif
|
||||
|
||||
@if($invoice_count)
|
||||
{{ ctrans('texts.invoices') }}: {{ $invoice_count }}
|
||||
@endif
|
||||
|
||||
@if($payment_count)
|
||||
{{ ctrans('texts.payments') }}: {{ $payment_count }}
|
||||
@endif
|
||||
|
||||
@if($recurring_invoice_count)
|
||||
{{ ctrans('texts.recurring_invoices') }}: {{ $recurring_invoice_count }}
|
||||
@endif
|
||||
|
||||
@if($quote_count)
|
||||
{{ ctrans('texts.quotes') }}: {{ $quote_count }}
|
||||
@endif
|
||||
|
||||
@if($credit_count)
|
||||
{{ ctrans('texts.credits') }}: {{ $credit_count }}
|
||||
@endif
|
||||
|
||||
@if($project_count)
|
||||
{{ ctrans('texts.projects') }}: {{ $project_count }}
|
||||
@endif
|
||||
|
||||
@if($task_count)
|
||||
{{ ctrans('texts.tasks') }}: {{ $task_count }}
|
||||
@endif
|
||||
|
||||
@if($vendor_count)
|
||||
{{ ctrans('texts.vendors') }}: {{ $vendor_count }}
|
||||
@endif
|
||||
|
||||
@if($expense_count)
|
||||
{{ ctrans('texts.expenses') }}: {{ $expense_count }}
|
||||
@endif
|
||||
|
||||
@if($company_gateway_count)
|
||||
{{ ctrans('texts.gateways') }}: {{ $company_gateway_count }}
|
||||
@endif
|
||||
|
||||
@if($client_gateway_token_count)
|
||||
{{ ctrans('texts.tokens') }}: {{ $client_gateway_token_count }}
|
||||
@endif
|
||||
|
||||
@if($tax_rate_count)
|
||||
{{ ctrans('texts.tax_rates') }}: {{ $tax_rate_count }}
|
||||
@endif
|
||||
|
||||
@if($document_count)
|
||||
{{ ctrans('texts.documents') }}: {{ $document_count }}
|
||||
@endif
|
||||
|
||||
@if($transaction_count)
|
||||
{{ ctrans('texts.documents') }}: {{ $transaction_count }}
|
||||
@endif
|
||||
|
||||
@if(!empty($errors))
|
||||
<p>{{ ctrans('texts.failed_to_import') }}</p>
|
||||
<p>{{ ctrans('texts.error') }}:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Data</th>
|
||||
<th>Error</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($errors as $entityType=>$entityErrors)
|
||||
@foreach($entityErrors as $error)
|
||||
<tr>
|
||||
<td>{{$entityType}}</td>
|
||||
<td>{{json_encode($error[$entityType]??null)}}</td>
|
||||
<td>{{json_encode($error['error'])}}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
@endif
|
||||
|
||||
{!! url('/') !!}
|
||||
|
||||
{!! ctrans('texts.email_signature') !!}
|
||||
|
||||
{!! ctrans('texts.email_from') !!}
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
namespace Tests\Feature\Import\CSV;
|
||||
|
||||
use App\Import\Transformer\BaseTransformer;
|
||||
use App\Jobs\Import\CSVImport;
|
||||
use App\Models\Client;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\Expense;
|
||||
@ -285,35 +284,4 @@ class BaseTransformerTest extends TestCase
|
||||
$this->assertEquals($vendor->id, $base_transformer->getVendorId('Magic'));
|
||||
$this->assertEquals($vendor->id, $base_transformer->getVendorId('Ma gi c '));
|
||||
}
|
||||
|
||||
// public function testClientCsvImport()
|
||||
// {
|
||||
// $csv = file_get_contents(base_path().'/tests/Feature/Import/clients.csv');
|
||||
// $hash = Str::random(32);
|
||||
// $column_map = [
|
||||
// 1 => 'client.balance',
|
||||
// 2 => 'client.paid_to_date',
|
||||
// 0 => 'client.name',
|
||||
// 19 => 'client.currency_id',
|
||||
// 20 => 'client.public_notes',
|
||||
// 21 => 'client.private_notes',
|
||||
// 22 => 'contact.first_name',
|
||||
// 23 => 'contact.last_name',
|
||||
// ];
|
||||
|
||||
// $data = [
|
||||
// 'hash' => $hash,
|
||||
// 'column_map' => [ 'client' => [ 'mapping' => $column_map ] ],
|
||||
// 'skip_header' => true,
|
||||
// 'import_type' => 'csv',
|
||||
// ];
|
||||
|
||||
// $pre_import = Client::count();
|
||||
|
||||
// Cache::put( $hash . '-client', base64_encode( $csv ), 360 );
|
||||
|
||||
// CSVImport::dispatchNow( $data, $this->company );
|
||||
|
||||
// $this->assertGreaterThan( $pre_import, Client::count() );
|
||||
// }
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ namespace Tests\Feature\Import\CSV;
|
||||
|
||||
use App\Import\Providers\Csv;
|
||||
use App\Import\Transformer\BaseTransformer;
|
||||
use App\Jobs\Import\CSVImport;
|
||||
use App\Models\Client;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\Expense;
|
||||
@ -319,34 +318,3 @@ class CsvImportTest extends TestCase
|
||||
$this->assertEquals(51.03, round($invoice->payments()->sum('payments.amount'),2));
|
||||
}
|
||||
}
|
||||
|
||||
// public function testClientCsvImport()
|
||||
// {
|
||||
// $csv = file_get_contents(base_path().'/tests/Feature/Import/clients.csv');
|
||||
// $hash = Str::random(32);
|
||||
// $column_map = [
|
||||
// 1 => 'client.balance',
|
||||
// 2 => 'client.paid_to_date',
|
||||
// 0 => 'client.name',
|
||||
// 19 => 'client.currency_id',
|
||||
// 20 => 'client.public_notes',
|
||||
// 21 => 'client.private_notes',
|
||||
// 22 => 'contact.first_name',
|
||||
// 23 => 'contact.last_name',
|
||||
// ];
|
||||
|
||||
// $data = [
|
||||
// 'hash' => $hash,
|
||||
// 'column_map' => [ 'client' => [ 'mapping' => $column_map ] ],
|
||||
// 'skip_header' => true,
|
||||
// 'import_type' => 'csv',
|
||||
// ];
|
||||
|
||||
// $pre_import = Client::count();
|
||||
|
||||
// Cache::put( $hash . '-client', base64_encode( $csv ), 360 );
|
||||
|
||||
// CSVImport::dispatchNow( $data, $this->company );
|
||||
|
||||
// $this->assertGreaterThan( $pre_import, Client::count() );
|
||||
// }
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
namespace Tests\Feature\Import;
|
||||
|
||||
use App\Jobs\Import\CSVImport;
|
||||
use App\Models\Account;
|
||||
use App\Models\Activity;
|
||||
use App\Models\Backup;
|
||||
|
@ -1,358 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace Tests\Feature\Import;
|
||||
|
||||
use App\Jobs\Import\CSVImport;
|
||||
use App\Models\Client;
|
||||
use App\Models\Expense;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Models\Product;
|
||||
use App\Models\Vendor;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Str;
|
||||
use League\Csv\Reader;
|
||||
use League\Csv\Statement;
|
||||
use Tests\MockAccountData;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @covers App\Http\Controllers\ImportController
|
||||
*/
|
||||
class ImportCsvTest extends TestCase
|
||||
{
|
||||
use MakesHash;
|
||||
use MockAccountData;
|
||||
|
||||
protected function setUp() :void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->withoutMiddleware(
|
||||
ThrottleRequests::class
|
||||
);
|
||||
config(['database.default' => config('ninja.db.default')]);
|
||||
|
||||
// $this->faker = \Faker\Factory::create();
|
||||
|
||||
$this->makeTestData();
|
||||
|
||||
$this->markTestSkipped('Skipping CSV Import to improve test speed');
|
||||
|
||||
$this->withoutExceptionHandling();
|
||||
}
|
||||
|
||||
public function testCsvRead()
|
||||
{
|
||||
$csv = file_get_contents(base_path().'/tests/Feature/Import/invoice.csv');
|
||||
|
||||
$this->assertTrue(is_array($this->getCsvData($csv)));
|
||||
}
|
||||
|
||||
public function testClientCsvImport()
|
||||
{
|
||||
$csv = file_get_contents(base_path().'/tests/Feature/Import/clients.csv');
|
||||
$hash = Str::random(32);
|
||||
$column_map = [
|
||||
1 => 'client.balance',
|
||||
2 => 'client.paid_to_date',
|
||||
0 => 'client.name',
|
||||
19 => 'client.currency_id',
|
||||
20 => 'client.public_notes',
|
||||
21 => 'client.private_notes',
|
||||
22 => 'contact.first_name',
|
||||
23 => 'contact.last_name',
|
||||
];
|
||||
|
||||
$data = [
|
||||
'hash' => $hash,
|
||||
'column_map' => ['client' => ['mapping' => $column_map]],
|
||||
'skip_header' => true,
|
||||
'import_type' => 'csv',
|
||||
];
|
||||
|
||||
$pre_import = Client::count();
|
||||
|
||||
Cache::put($hash.'-client', base64_encode($csv), 360);
|
||||
|
||||
CSVImport::dispatchSync($data, $this->company);
|
||||
|
||||
$this->assertGreaterThan($pre_import, Client::count());
|
||||
}
|
||||
|
||||
public function testInvoiceCsvImport()
|
||||
{
|
||||
/*Need to import clients first*/
|
||||
$csv = file_get_contents(base_path().'/tests/Feature/Import/clients.csv');
|
||||
$hash = Str::random(32);
|
||||
$column_map = [
|
||||
1 => 'client.balance',
|
||||
2 => 'client.paid_to_date',
|
||||
0 => 'client.name',
|
||||
19 => 'client.currency_id',
|
||||
20 => 'client.public_notes',
|
||||
21 => 'client.private_notes',
|
||||
22 => 'contact.first_name',
|
||||
23 => 'contact.last_name',
|
||||
];
|
||||
|
||||
$data = [
|
||||
'hash' => $hash,
|
||||
'column_map' => ['client' => ['mapping' => $column_map]],
|
||||
'skip_header' => true,
|
||||
'import_type' => 'csv',
|
||||
];
|
||||
|
||||
Cache::put($hash.'-client', base64_encode($csv), 360);
|
||||
|
||||
CSVImport::dispatchSync($data, $this->company);
|
||||
|
||||
/*Now import invoices*/
|
||||
$csv = file_get_contents(base_path().'/tests/Feature/Import/invoice.csv');
|
||||
$hash = Str::random(32);
|
||||
|
||||
$column_map = [
|
||||
1 => 'client.email',
|
||||
3 => 'payment.amount',
|
||||
5 => 'invoice.po_number',
|
||||
8 => 'invoice.due_date',
|
||||
9 => 'item.discount',
|
||||
11 => 'invoice.partial_due_date',
|
||||
12 => 'invoice.public_notes',
|
||||
13 => 'invoice.private_notes',
|
||||
0 => 'client.name',
|
||||
2 => 'invoice.number',
|
||||
7 => 'invoice.date',
|
||||
14 => 'item.product_key',
|
||||
15 => 'item.notes',
|
||||
16 => 'item.cost',
|
||||
17 => 'item.quantity',
|
||||
];
|
||||
|
||||
$data = [
|
||||
'hash' => $hash,
|
||||
'column_map' => ['invoice' => ['mapping' => $column_map]],
|
||||
'skip_header' => true,
|
||||
'import_type' => 'csv',
|
||||
];
|
||||
|
||||
$pre_import = Invoice::count();
|
||||
|
||||
Cache::put($hash.'-invoice', base64_encode($csv), 360);
|
||||
|
||||
CSVImport::dispatchSync($data, $this->company);
|
||||
|
||||
$this->assertGreaterThan($pre_import, Invoice::count());
|
||||
}
|
||||
|
||||
public function testVendorCsvImport()
|
||||
{
|
||||
$csv = file_get_contents(base_path().'/tests/Feature/Import/vendors.csv');
|
||||
$hash = Str::random(32);
|
||||
$column_map = [
|
||||
0 => 'vendor.name',
|
||||
19 => 'vendor.currency_id',
|
||||
20 => 'vendor.public_notes',
|
||||
21 => 'vendor.private_notes',
|
||||
22 => 'vendor.first_name',
|
||||
23 => 'vendor.last_name',
|
||||
];
|
||||
|
||||
$data = [
|
||||
'hash' => $hash,
|
||||
'column_map' => ['vendor' => ['mapping' => $column_map]],
|
||||
'skip_header' => true,
|
||||
'import_type' => 'csv',
|
||||
];
|
||||
|
||||
$pre_import = Vendor::count();
|
||||
|
||||
Cache::put($hash.'-vendor', base64_encode($csv), 360);
|
||||
|
||||
CSVImport::dispatchSync($data, $this->company);
|
||||
|
||||
$this->assertGreaterThan($pre_import, Vendor::count());
|
||||
}
|
||||
|
||||
public function testProductCsvImport()
|
||||
{
|
||||
$csv = file_get_contents(base_path().'/tests/Feature/Import/products.csv');
|
||||
$hash = Str::random(32);
|
||||
|
||||
$column_map = [
|
||||
2 => 'product.notes',
|
||||
3 => 'product.cost',
|
||||
];
|
||||
|
||||
$data = [
|
||||
'hash' => $hash,
|
||||
'column_map' => ['product' => ['mapping' => $column_map]],
|
||||
'skip_header' => true,
|
||||
'import_type' => 'csv',
|
||||
];
|
||||
|
||||
$pre_import = Product::count();
|
||||
|
||||
Cache::put($hash.'-product', base64_encode($csv), 360);
|
||||
|
||||
CSVImport::dispatchSync($data, $this->company);
|
||||
|
||||
$this->assertGreaterThan($pre_import, Product::count());
|
||||
}
|
||||
|
||||
public function testExpenseCsvImport()
|
||||
{
|
||||
$csv = file_get_contents(base_path().'/tests/Feature/Import/expenses.csv');
|
||||
$hash = Str::random(32);
|
||||
|
||||
$column_map = [
|
||||
2 => 'expense.public_notes',
|
||||
3 => 'expense.amount',
|
||||
];
|
||||
|
||||
$data = [
|
||||
'hash' => $hash,
|
||||
'column_map' => ['expense' => ['mapping' => $column_map]],
|
||||
'skip_header' => true,
|
||||
'import_type' => 'csv',
|
||||
];
|
||||
|
||||
$pre_import = Expense::count();
|
||||
|
||||
Cache::put($hash.'-expense', base64_encode($csv), 360);
|
||||
|
||||
CSVImport::dispatchSync($data, $this->company);
|
||||
|
||||
$this->assertGreaterThan($pre_import, Expense::count());
|
||||
}
|
||||
|
||||
public function testPaymentCsvImport()
|
||||
{
|
||||
|
||||
/*Need to import clients first*/
|
||||
$csv = file_get_contents(base_path().'/tests/Feature/Import/clients.csv');
|
||||
$hash = Str::random(32);
|
||||
$column_map = [
|
||||
1 => 'client.balance',
|
||||
2 => 'client.paid_to_date',
|
||||
0 => 'client.name',
|
||||
19 => 'client.currency_id',
|
||||
20 => 'client.public_notes',
|
||||
21 => 'client.private_notes',
|
||||
22 => 'contact.first_name',
|
||||
23 => 'contact.last_name',
|
||||
];
|
||||
|
||||
$data = [
|
||||
'hash' => $hash,
|
||||
'column_map' => ['client' => ['mapping' => $column_map]],
|
||||
'skip_header' => true,
|
||||
'import_type' => 'csv',
|
||||
];
|
||||
|
||||
Cache::put($hash.'-client', base64_encode($csv), 360);
|
||||
|
||||
CSVImport::dispatchSync($data, $this->company);
|
||||
|
||||
/*Now import invoices*/
|
||||
$csv = file_get_contents(base_path().'/tests/Feature/Import/invoice.csv');
|
||||
$hash = Str::random(32);
|
||||
|
||||
$column_map = [
|
||||
1 => 'client.email',
|
||||
3 => 'payment.amount',
|
||||
5 => 'invoice.po_number',
|
||||
8 => 'invoice.due_date',
|
||||
9 => 'item.discount',
|
||||
11 => 'invoice.partial_due_date',
|
||||
12 => 'invoice.public_notes',
|
||||
13 => 'invoice.private_notes',
|
||||
0 => 'client.name',
|
||||
2 => 'invoice.number',
|
||||
7 => 'invoice.date',
|
||||
14 => 'item.product_key',
|
||||
15 => 'item.notes',
|
||||
16 => 'item.cost',
|
||||
17 => 'item.quantity',
|
||||
];
|
||||
|
||||
$data = [
|
||||
'hash' => $hash,
|
||||
'column_map' => ['invoice' => ['mapping' => $column_map]],
|
||||
'skip_header' => true,
|
||||
'import_type' => 'csv',
|
||||
];
|
||||
|
||||
$pre_import = Invoice::count();
|
||||
|
||||
Cache::put($hash.'-invoice', base64_encode($csv), 360);
|
||||
|
||||
CSVImport::dispatchSync($data, $this->company);
|
||||
|
||||
/* Test Now import payments*/
|
||||
|
||||
$csv = file_get_contents(base_path().'/tests/Feature/Import/payments.csv');
|
||||
$hash = Str::random(32);
|
||||
|
||||
$column_map = [
|
||||
0 => 'payment.client_id',
|
||||
1 => 'payment.invoice_number',
|
||||
2 => 'payment.amount',
|
||||
3 => 'payment.date',
|
||||
];
|
||||
|
||||
$data = [
|
||||
'hash' => $hash,
|
||||
'column_map' => ['payment' => ['mapping' => $column_map]],
|
||||
'skip_header' => true,
|
||||
'import_type' => 'csv',
|
||||
];
|
||||
|
||||
$pre_import = Payment::count();
|
||||
|
||||
Cache::put($hash.'-payment', base64_encode($csv), 360);
|
||||
|
||||
CSVImport::dispatchSync($data, $this->company);
|
||||
|
||||
$this->assertGreaterThan($pre_import, Payment::count());
|
||||
}
|
||||
|
||||
private function getCsvData($csvfile)
|
||||
{
|
||||
if (! ini_get('auto_detect_line_endings')) {
|
||||
ini_set('auto_detect_line_endings', '1');
|
||||
}
|
||||
|
||||
$csv = Reader::createFromString($csvfile);
|
||||
$stmt = new Statement();
|
||||
$data = iterator_to_array($stmt->process($csv));
|
||||
|
||||
if (count($data) > 0) {
|
||||
$headers = $data[0];
|
||||
|
||||
// Remove Invoice Ninja headers
|
||||
if (count($headers) && count($data) > 4) {
|
||||
$firstCell = $headers[0];
|
||||
if (strstr($firstCell, config('ninja.app_name'))) {
|
||||
array_shift($data); // Invoice Ninja...
|
||||
array_shift($data); // <blank line>
|
||||
array_shift($data); // Enitty Type Header
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user