diff --git a/app/Http/Controllers/ImportController.php b/app/Http/Controllers/ImportController.php index 0b462c594c13..c745f8b012ab 100644 --- a/app/Http/Controllers/ImportController.php +++ b/app/Http/Controllers/ImportController.php @@ -14,6 +14,7 @@ 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; use Illuminate\Support\Str; @@ -116,7 +117,9 @@ class ImportController extends Controller { } } - CSVImport::dispatch( $data, auth()->user()->company() ); + unset($data['files']); + // CSVImport::dispatch( $data, auth()->user()->company() ); + CSVIngest::dispatch( $data, auth()->user()->company() ); return response()->json( [ 'message' => ctrans( 'texts.import_started' ) ], 200 ); } diff --git a/app/Http/Middleware/CheckClientExistence.php b/app/Http/Middleware/CheckClientExistence.php index f7aab8161afc..3944a4470edc 100644 --- a/app/Http/Middleware/CheckClientExistence.php +++ b/app/Http/Middleware/CheckClientExistence.php @@ -29,12 +29,14 @@ class CheckClientExistence public function handle(Request $request, Closure $next) { + if(session()->has('multiple_contacts')) + return $next($request); + $multiple_contacts = ClientContact::query() ->with('client.gateway_tokens','company') ->where('email', auth()->guard('contact')->user()->email) ->whereNotNull('email') ->where('email', '<>', '') - // ->whereNull('deleted_at') ->distinct('company_id') ->distinct('email') ->whereNotNull('company_id') diff --git a/app/Import/Providers/BaseImport.php b/app/Import/Providers/BaseImport.php index 66f244b2a2ff..0b4d43082106 100644 --- a/app/Import/Providers/BaseImport.php +++ b/app/Import/Providers/BaseImport.php @@ -80,6 +80,8 @@ class BaseImport public function getCsvData($entity_type) { + nlog("get csv data = entity name = " . $entity_type); + $base64_encoded_csv = Cache::pull($this->hash . '-' . $entity_type); if (empty($base64_encoded_csv)) { return null; @@ -123,6 +125,9 @@ class BaseImport private function groupInvoices($csvData, $key) { + if(!$key) + return $csvData; + // Group by invoice. $grouped = []; @@ -154,12 +159,7 @@ class BaseImport try { $entity = $this->transformer->transform($record); - /** @var \App\Http\Requests\Request $request */ - $request = new $this->request_name(); - - // Pass entity data to request so it can be validated - $request->query = $request->request = new ParameterBag($entity); - $validator = Validator::make($entity, $request->rules()); + $validator = $this->request_name::runFormRequest($entity); if ($validator->fails()) { $this->error_array[$entity_type][] = [ @@ -220,8 +220,9 @@ class BaseImport foreach ($invoices as $raw_invoice) { try { + $invoice_data = $invoice_transformer->transform($raw_invoice); - nlog($invoice_data); + $invoice_data['line_items'] = $this->cleanItems( $invoice_data['line_items'] ?? [] ); @@ -247,10 +248,8 @@ class BaseImport unset($invoice_data['client']); } - $validator = Validator::make( - $invoice_data, - (new StoreInvoiceRequest())->rules() - ); + $validator = $this->request_name::runFormRequest($invoice_data); + if ($validator->fails()) { $this->error_array['invoice'][] = [ 'invoice' => $invoice_data, @@ -519,22 +518,41 @@ class BaseImport public function preTransform(array $data, $entity_type) { - if (empty($this->column_map[$entity_type])) { - return false; - } - - if ($this->skip_header) { - array_shift($data); - } - //sort the array by key - $keys = $this->column_map[$entity_type]; + // $keys = $this->column_map[$entity_type]; + + $keys = array_shift( $data ); ksort($keys); - $data = array_map(function ($row) use ($keys) { - return array_combine($keys, array_intersect_key($row, $keys)); - }, $data); + return array_map( function ( $values ) use ( $keys ) { + return array_combine( $keys, $values ); + }, $data ); + - return $data; } + + public function preTransformCsv(array $data, $entity_type) + { + + if ( empty( $this->column_map[ $entity_type ] ) ) { + return false; + } + + if ( $this->skip_header ) { + array_shift( $data ); + } + + //sort the array by key + $keys = $this->column_map[ $entity_type ]; + ksort( $keys ); + + $data = array_map( function ( $row ) use ( $keys ) { + return array_combine( $keys, array_intersect_key( $row, $keys ) ); + }, $data ); + + + return $data; + + } + } diff --git a/app/Import/Providers/Csv.php b/app/Import/Providers/Csv.php index 7d50261227fd..68a366488624 100644 --- a/app/Import/Providers/Csv.php +++ b/app/Import/Providers/Csv.php @@ -71,7 +71,8 @@ class Csv extends BaseImport implements ImportInterface $data = $this->getCsvData($entity_type); - $data = $this->preTransform($data, $entity_type); + if(is_array($data)) + $data = $this->preTransformCsv($data, $entity_type); if (empty($data)) { $this->entity_count['clients'] = 0; @@ -98,7 +99,8 @@ class Csv extends BaseImport implements ImportInterface $data = $this->getCsvData($entity_type); - $data = $this->preTransform($data, $entity_type); + if(is_array($data)) + $data = $this->preTransformCsv($data, $entity_type); if (empty($data)) { $this->entity_count['products'] = 0; @@ -125,7 +127,8 @@ class Csv extends BaseImport implements ImportInterface $data = $this->getCsvData($entity_type); - $data = $this->preTransform($data, $entity_type); + if(is_array($data)) + $data = $this->preTransformCsv($data, $entity_type); if (empty($data)) { $this->entity_count['invoices'] = 0; @@ -152,7 +155,8 @@ class Csv extends BaseImport implements ImportInterface $data = $this->getCsvData($entity_type); - $data = $this->preTransform($data, $entity_type); + if(is_array($data)) + $data = $this->preTransformCsv($data, $entity_type); if (empty($data)) { $this->entity_count['payments'] = 0; @@ -179,7 +183,8 @@ class Csv extends BaseImport implements ImportInterface $data = $this->getCsvData($entity_type); - $data = $this->preTransform($data, $entity_type); + if(is_array($data)) + $data = $this->preTransformCsv($data, $entity_type); if (empty($data)) { $this->entity_count['vendors'] = 0; @@ -206,7 +211,8 @@ class Csv extends BaseImport implements ImportInterface $data = $this->getCsvData($entity_type); - $data = $this->preTransform($data, $entity_type); + if(is_array($data)) + $data = $this->preTransformCsv($data, $entity_type); if (empty($data)) { $this->entity_count['expenses'] = 0; diff --git a/app/Import/Providers/Freshbooks.php b/app/Import/Providers/Freshbooks.php index bb7759489141..503d967f5bb3 100644 --- a/app/Import/Providers/Freshbooks.php +++ b/app/Import/Providers/Freshbooks.php @@ -10,6 +10,104 @@ */ namespace App\Import\Providers; +use App\Factory\ClientFactory; +use App\Factory\InvoiceFactory; +use App\Http\Requests\Client\StoreClientRequest; +use App\Http\Requests\Invoice\StoreInvoiceRequest; +use App\Import\Transformer\Freshbooks\ClientTransformer; +use App\Import\Transformer\Freshbooks\InvoiceTransformer; +use App\Repositories\ClientRepository; +use App\Repositories\InvoiceRepository; + class Freshbooks extends BaseImport { + + public array $entity_count = []; + + public function import(string $entity) + { + if ( + in_array($entity, [ + 'client', + 'invoice', + // 'product', + // 'payment', + // 'vendor', + // 'expense', + ]) + ) { + $this->{$entity}(); + } + + //collate any errors + + $this->finalizeImport(); + } + + public function client() + { + $entity_type = 'client'; + + $data = $this->getCsvData($entity_type); + $data = $this->preTransform($data, $entity_type); + + if (empty($data)) { + $this->entity_count['clients'] = 0; + return; + } + + $this->request_name = StoreClientRequest::class; + $this->repository_name = ClientRepository::class; + $this->factory_name = ClientFactory::class; + + $this->repository = app()->make($this->repository_name); + $this->repository->import_mode = true; + + $this->transformer = new ClientTransformer($this->company); + + $client_count = $this->ingest($data, $entity_type); + + $this->entity_count['clients'] = $client_count; + + } + + + public function invoice() { + + //make sure we update and create products with wave + $initial_update_products_value = $this->company->update_products; + $this->company->update_products = true; + + $this->company->save(); + + $entity_type = 'invoice'; + + $data = $this->getCsvData($entity_type); + + $data = $this->preTransform($data, $entity_type); + + if (empty($data)) { + $this->entity_count['invoices'] = 0; + return; + } + + $this->request_name = StoreInvoiceRequest::class; + $this->repository_name = InvoiceRepository::class; + $this->factory_name = InvoiceFactory::class; + + $this->repository = app()->make($this->repository_name); + $this->repository->import_mode = true; + + $this->transformer = new InvoiceTransformer($this->company); + + $invoice_count = $this->ingestInvoices($data, 'Invoice #'); + + $this->entity_count['invoices'] = $invoice_count; + + $this->company->update_products = $initial_update_products_value; + $this->company->save(); + + } + + } diff --git a/app/Import/Providers/Invoice2Go.php b/app/Import/Providers/Invoice2Go.php index d2e97435c13a..47336cc6f59b 100644 --- a/app/Import/Providers/Invoice2Go.php +++ b/app/Import/Providers/Invoice2Go.php @@ -10,7 +10,75 @@ */ namespace App\Import\Providers; +use App\Factory\ClientFactory; +use App\Factory\InvoiceFactory; +use App\Http\Requests\Client\StoreClientRequest; +use App\Http\Requests\Invoice\StoreInvoiceRequest; +use App\Import\Transformer\Invoice2Go\InvoiceTransformer; +use App\Repositories\ClientRepository; +use App\Repositories\InvoiceRepository; + class Invoice2Go extends BaseImport { - + public array $entity_count = []; + + public function import(string $entity) + { + if ( + in_array($entity, [ + //'client', + 'invoice', + // 'product', + // 'payment', + // 'vendor', + // 'expense', + ]) + ) { + $this->{$entity}(); + } + + //collate any errors + + $this->finalizeImport(); + } + + + public function invoice() { + + //make sure we update and create products with wave + $initial_update_products_value = $this->company->update_products; + $this->company->update_products = true; + + $this->company->save(); + + $entity_type = 'invoice'; + + $data = $this->getCsvData($entity_type); + + $data = $this->preTransform($data, 'invoice'); + + if (empty($data)) { + $this->entity_count['invoices'] = 0; + return; + } + + $this->request_name = StoreInvoiceRequest::class; + $this->repository_name = InvoiceRepository::class; + $this->factory_name = InvoiceFactory::class; + + $this->repository = app()->make($this->repository_name); + $this->repository->import_mode = true; + + $this->transformer = new InvoiceTransformer($this->company); + + $invoice_count = $this->ingestInvoices($data, false); + + $this->entity_count['invoices'] = $invoice_count; + + $this->company->update_products = $initial_update_products_value; + $this->company->save(); + + } + + } \ No newline at end of file diff --git a/app/Import/Providers/Invoicely.php b/app/Import/Providers/Invoicely.php index 55feff8f76cc..09ed7f1cba15 100644 --- a/app/Import/Providers/Invoicely.php +++ b/app/Import/Providers/Invoicely.php @@ -10,7 +10,101 @@ */ namespace App\Import\Providers; +use App\Factory\ClientFactory; +use App\Factory\InvoiceFactory; +use App\Http\Requests\Client\StoreClientRequest; +use App\Http\Requests\Invoice\StoreInvoiceRequest; +use App\Import\Transformer\Invoicely\ClientTransformer; +use App\Import\Transformer\Invoicely\InvoiceTransformer; +use App\Repositories\ClientRepository; +use App\Repositories\InvoiceRepository; + class Invoicely extends BaseImport { - + public function import(string $entity) + { + if ( + in_array($entity, [ + 'client', + 'invoice', + // 'product', + // 'payment', + // 'vendor', + // 'expense', + ]) + ) { + $this->{$entity}(); + } + + //collate any errors + + $this->finalizeImport(); + } + + public function client() + { + $entity_type = 'client'; + + $data = $this->getCsvData($entity_type); + + $data = $this->preTransform($data, $entity_type); + + if (empty($data)) { + $this->entity_count['clients'] = 0; + return; + } + + $this->request_name = StoreClientRequest::class; + $this->repository_name = ClientRepository::class; + $this->factory_name = ClientFactory::class; + + $this->repository = app()->make($this->repository_name); + $this->repository->import_mode = true; + + $this->transformer = new ClientTransformer($this->company); + + $client_count = $this->ingest($data, $entity_type); + + $this->entity_count['clients'] = $client_count; + + } + + + public function invoice() { + + //make sure we update and create products with wave + $initial_update_products_value = $this->company->update_products; + $this->company->update_products = true; + + $this->company->save(); + + $entity_type = 'invoice'; + + $data = $this->getCsvData($entity_type); + + $data = $this->preTransform($data, $entity_type); + + if (empty($data)) { + $this->entity_count['invoices'] = 0; + return; + } + + $this->request_name = StoreInvoiceRequest::class; + $this->repository_name = InvoiceRepository::class; + $this->factory_name = InvoiceFactory::class; + + $this->repository = app()->make($this->repository_name); + $this->repository->import_mode = true; + + $this->transformer = new InvoiceTransformer($this->company); + + $invoice_count = $this->ingestInvoices($data, false); + + $this->entity_count['invoices'] = $invoice_count; + + $this->company->update_products = $initial_update_products_value; + $this->company->save(); + + } + } \ No newline at end of file diff --git a/app/Import/Providers/Wave.php b/app/Import/Providers/Wave.php index 7e12ff74e064..bed0e1fdf67c 100644 --- a/app/Import/Providers/Wave.php +++ b/app/Import/Providers/Wave.php @@ -218,8 +218,6 @@ class Wave extends BaseImport implements ImportInterface $expenses = $this->groupExpenses($data); -// nlog($expenses); -// exit; foreach ($expenses as $raw_expense) { try { diff --git a/app/Import/Providers/Zoho.php b/app/Import/Providers/Zoho.php index bb7b18515e43..87b35e4faca1 100644 --- a/app/Import/Providers/Zoho.php +++ b/app/Import/Providers/Zoho.php @@ -10,7 +10,103 @@ */ namespace App\Import\Providers; +use App\Factory\ClientFactory; +use App\Factory\InvoiceFactory; +use App\Http\Requests\Client\StoreClientRequest; +use App\Http\Requests\Invoice\StoreInvoiceRequest; +use App\Import\Transformer\Zoho\ClientTransformer; +use App\Import\Transformer\Zoho\InvoiceTransformer; +use App\Repositories\ClientRepository; +use App\Repositories\InvoiceRepository; + class Zoho extends BaseImport { - + public array $entity_count = []; + + public function import(string $entity) + { + if ( + in_array($entity, [ + 'client', + 'invoice', + // 'product', + // 'payment', + // 'vendor', + // 'expense', + ]) + ) { + $this->{$entity}(); + } + + //collate any errors + + $this->finalizeImport(); + } + + public function client() + { + $entity_type = 'client'; + + $data = $this->getCsvData($entity_type); + + $data = $this->preTransform($data, $entity_type); + + if (empty($data)) { + $this->entity_count['clients'] = 0; + return; + } + + $this->request_name = StoreClientRequest::class; + $this->repository_name = ClientRepository::class; + $this->factory_name = ClientFactory::class; + + $this->repository = app()->make($this->repository_name); + $this->repository->import_mode = true; + + $this->transformer = new ClientTransformer($this->company); + + $client_count = $this->ingest($data, $entity_type); + + $this->entity_count['clients'] = $client_count; + + } + + public function invoice() { + + //make sure we update and create products with wave + $initial_update_products_value = $this->company->update_products; + $this->company->update_products = true; + + $this->company->save(); + + $entity_type = 'invoice'; + + $data = $this->getCsvData($entity_type); + + $data = $this->preTransform($data, $entity_type); + + if (empty($data)) { + $this->entity_count['invoices'] = 0; + return; + } + + $this->request_name = StoreInvoiceRequest::class; + $this->repository_name = InvoiceRepository::class; + $this->factory_name = InvoiceFactory::class; + + $this->repository = app()->make($this->repository_name); + $this->repository->import_mode = true; + + $this->transformer = new InvoiceTransformer($this->company); + + $invoice_count = $this->ingestInvoices($data, 'Invoice Number'); + + $this->entity_count['invoices'] = $invoice_count; + + $this->company->update_products = $initial_update_products_value; + $this->company->save(); + + } + + } \ No newline at end of file diff --git a/app/Import/Transformer/BaseTransformer.php b/app/Import/Transformer/BaseTransformer.php index 179c991fa85b..2762ce893878 100644 --- a/app/Import/Transformer/BaseTransformer.php +++ b/app/Import/Transformer/BaseTransformer.php @@ -65,26 +65,28 @@ class BaseTransformer public function getClient($client_name, $client_email) { - // nlog("searching for {$client_name} with email {$client_email}"); - $client_id_search = $this->company - ->clients() - ->where('id_number', $client_name); + if(!empty($client_name)) + { - if ($client_id_search->count() >= 1) { - // nlog("found via id number => {$client_id_search->first()->id}"); - return $client_id_search->first()->id; + $client_id_search = $this->company + ->clients() + ->where('id_number', $client_name); + + if ($client_id_search->count() >= 1) { + // nlog("found via id number => {$client_id_search->first()->id}"); + return $client_id_search->first()->id; + } + + $client_name_search = $this->company + ->clients() + ->where('name', $client_name); + + if ($client_name_search->count() >= 1) { + // nlog("found via name {$client_name_search->first()->id}"); + return $client_name_search->first()->id; + } } - - $client_name_search = $this->company - ->clients() - ->where('name', $client_name); - - if ($client_name_search->count() >= 1) { - // nlog("found via name {$client_name_search->first()->id}"); - return $client_name_search->first()->id; - } - if (!empty($client_email)) { $contacts = ClientContact::where( 'company_id', diff --git a/app/Import/Transformer/Freshbooks/ClientTransformer.php b/app/Import/Transformer/Freshbooks/ClientTransformer.php new file mode 100644 index 000000000000..d5b053232ad0 --- /dev/null +++ b/app/Import/Transformer/Freshbooks/ClientTransformer.php @@ -0,0 +1,55 @@ +hasClient( $data['Organization'] ) ) { + throw new ImportException('Client already exists'); + } + + return [ + 'company_id' => $this->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' ), + ], + ], + ]; + } +} diff --git a/app/Import/Transformer/Freshbooks/InvoiceTransformer.php b/app/Import/Transformer/Freshbooks/InvoiceTransformer.php new file mode 100644 index 000000000000..58f3667204bd --- /dev/null +++ b/app/Import/Transformer/Freshbooks/InvoiceTransformer.php @@ -0,0 +1,86 @@ +hasInvoice( $invoice_data['Invoice #'] ) ) { + throw new ImportException( 'Invoice number already exists' ); + } + + $invoiceStatusMap = [ + 'sent' => Invoice::STATUS_SENT, + 'draft' => Invoice::STATUS_DRAFT, + ]; + + $transformed = [ + 'company_id' => $this->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]; + } + +} diff --git a/app/Import/Transformer/Invoice2Go/InvoiceTransformer.php b/app/Import/Transformer/Invoice2Go/InvoiceTransformer.php new file mode 100644 index 000000000000..bb6b4d0a0606 --- /dev/null +++ b/app/Import/Transformer/Invoice2Go/InvoiceTransformer.php @@ -0,0 +1,94 @@ +hasInvoice( $invoice_data['DocumentNumber'] ) ) { + throw new ImportException( 'Invoice number already exists' ); + } + + $invoiceStatusMap = [ + 'unsent' => Invoice::STATUS_DRAFT, + 'sent' => Invoice::STATUS_SENT, + ]; + + $transformed = [ + 'company_id' => $this->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' => $this->getFloat( $invoice_data, 'TotalAmount' ), + 'status_id' => $invoiceStatusMap[ $status = + strtolower( $this->getString( $invoice_data, 'DocumentStatus' ) ) ] ?? Invoice::STATUS_SENT, + // 'viewed' => $status === 'viewed', + 'line_items' => [ + [ + 'cost' => $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 { + + $settings = new \stdClass; + $settings->currency_id = $this->getCurrencyByCode( $invoice_data, 'Currency' ); + + $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' => $settings, + 'client_hash' => Str::random( 40 ), + 'contacts' => [ + [ + 'email' => $this->getString( $invoice_data, 'EmailRecipient' ), + ], + ], + ]; + } + 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; + } +} diff --git a/app/Import/Transformer/Invoicely/ClientTransformer.php b/app/Import/Transformer/Invoicely/ClientTransformer.php new file mode 100644 index 000000000000..eb1e0fa71e43 --- /dev/null +++ b/app/Import/Transformer/Invoicely/ClientTransformer.php @@ -0,0 +1,50 @@ +hasClient( $data['Client Name'] ) ) { + throw new ImportException('Client already exists'); + } + + $transformed = [ + 'company_id' => $this->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' ), + ], + ], + ]; + + return $transformed; + } +} diff --git a/app/Import/Transformer/Invoicely/InvoiceTransformer.php b/app/Import/Transformer/Invoicely/InvoiceTransformer.php new file mode 100644 index 000000000000..9559ced5ddd3 --- /dev/null +++ b/app/Import/Transformer/Invoicely/InvoiceTransformer.php @@ -0,0 +1,58 @@ +hasInvoice( $data['Details'] ) ) { + throw new ImportException( 'Invoice number already exists' ); + } + + $transformed = [ + 'company_id' => $this->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; + } +} diff --git a/app/Import/Transformer/Zoho/ClientTransformer.php b/app/Import/Transformer/Zoho/ClientTransformer.php new file mode 100644 index 000000000000..8612833e3802 --- /dev/null +++ b/app/Import/Transformer/Zoho/ClientTransformer.php @@ -0,0 +1,72 @@ +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->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, 'EmailID' ), + 'phone' => $this->getString( $data, 'Phone' ), + ], + ], + ]; + } +} \ No newline at end of file diff --git a/app/Import/Transformer/Zoho/InvoiceTransformer.php b/app/Import/Transformer/Zoho/InvoiceTransformer.php new file mode 100644 index 000000000000..35143350dfcc --- /dev/null +++ b/app/Import/Transformer/Zoho/InvoiceTransformer.php @@ -0,0 +1,78 @@ +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->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; + } +} + diff --git a/app/Jobs/Import/CSVIngest.php b/app/Jobs/Import/CSVIngest.php index c30871e29958..0c13c1eda642 100644 --- a/app/Jobs/Import/CSVIngest.php +++ b/app/Jobs/Import/CSVIngest.php @@ -37,11 +37,13 @@ class CSVIngest implements ShouldQueue { public ?string $skip_header; - public array $column_map; + public $column_map; + + public array $request; public function __construct( array $request, Company $company ) { $this->company = $company; - $this->request = $request; + $this->request = $request; $this->hash = $request['hash']; $this->import_type = $request['import_type']; $this->skip_header = $request['skip_header'] ?? null; diff --git a/app/PaymentDrivers/BraintreePaymentDriver.php b/app/PaymentDrivers/BraintreePaymentDriver.php index ede26a56eca8..c4d797b6fb65 100644 --- a/app/PaymentDrivers/BraintreePaymentDriver.php +++ b/app/PaymentDrivers/BraintreePaymentDriver.php @@ -267,8 +267,8 @@ class BraintreePaymentDriver extends BaseDriver nlog("braintree webhook"); - if($webhookNotification) - nlog($webhookNotification->kind); + // if($webhookNotification) + // nlog($webhookNotification->kind); // // Example values for webhook notification properties // $message = $webhookNotification->kind; // "subscription_went_past_due" diff --git a/app/PaymentDrivers/PayFast/Token.php b/app/PaymentDrivers/PayFast/Token.php index 35433cae9fa8..99c78137a11c 100644 --- a/app/PaymentDrivers/PayFast/Token.php +++ b/app/PaymentDrivers/PayFast/Token.php @@ -57,7 +57,7 @@ class Token $header['signature'] = $this->payfast->generateTokenSignature(array_merge($body, $header)); - nlog($header['signature']); + // nlog($header['signature']); $result = $this->send($header, $body, $cgt->token); @@ -95,7 +95,7 @@ class Token $parameter_string = rtrim( $parameter_string, '&' ); } - nlog($parameter_string); + // nlog($parameter_string); return $parameter_string; diff --git a/app/PaymentDrivers/WePay/CreditCard.php b/app/PaymentDrivers/WePay/CreditCard.php index c2c74fc15140..19b1691d1434 100644 --- a/app/PaymentDrivers/WePay/CreditCard.php +++ b/app/PaymentDrivers/WePay/CreditCard.php @@ -47,7 +47,7 @@ use WePayCommon; $data = $request->all(); // authorize the credit card - nlog($data); + // nlog($data); /* '_token' => '1Fk5CRj34up5ntKPvrFyMIAJhDdUNF3boqT3iIN3', 'company_gateway_id' => '39', diff --git a/app/Services/Credit/GetCreditPdf.php b/app/Services/Credit/GetCreditPdf.php index 10517aaa7267..22d60ea52cac 100644 --- a/app/Services/Credit/GetCreditPdf.php +++ b/app/Services/Credit/GetCreditPdf.php @@ -46,8 +46,6 @@ class GetCreditPdf extends AbstractService $file_path = CreateEntityPdf::dispatchNow($this->invitation); -nlog($file_path); return $file_path; - // return Storage::disk($disk)->path($file_path); } } diff --git a/resources/views/portal/ninja2020/layout/app.blade.php b/resources/views/portal/ninja2020/layout/app.blade.php index e12b2d244360..5a0dcbcb52ea 100644 --- a/resources/views/portal/ninja2020/layout/app.blade.php +++ b/resources/views/portal/ninja2020/layout/app.blade.php @@ -122,6 +122,31 @@ })} ); + + @if($company && $company->google_analytics_key) + + @endif +