From 86f0b28ae4d6659255d4c480b191587ad4d9986a Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 17 Feb 2022 10:07:43 +1100 Subject: [PATCH] Add Google Analytics to client portal pages if tracking ID is implemented --- app/Import/Providers/BaseImport.php | 17 +- app/Import/Providers/Zoho.php | 98 ++++- app/Import/Transformer/BaseTransformer.php | 40 +- .../Transformer/Zoho/ClientTransformer.php | 74 ++++ .../Transformer/Zoho/InvoiceTransformer.php | 78 ++++ tests/Feature/Import/Zoho/ZohoTest.php | 347 ++++++++++++++++++ 6 files changed, 625 insertions(+), 29 deletions(-) create mode 100644 app/Import/Transformer/Zoho/ClientTransformer.php create mode 100644 app/Import/Transformer/Zoho/InvoiceTransformer.php create mode 100644 tests/Feature/Import/Zoho/ZohoTest.php diff --git a/app/Import/Providers/BaseImport.php b/app/Import/Providers/BaseImport.php index 66f244b2a2ff..de59c5698b35 100644 --- a/app/Import/Providers/BaseImport.php +++ b/app/Import/Providers/BaseImport.php @@ -154,12 +154,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][] = [ @@ -247,10 +242,12 @@ class BaseImport unset($invoice_data['client']); } - $validator = Validator::make( - $invoice_data, - (new StoreInvoiceRequest())->rules() - ); + // $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, 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..fa73f9afb6c7 100644 --- a/app/Import/Transformer/BaseTransformer.php +++ b/app/Import/Transformer/BaseTransformer.php @@ -65,26 +65,30 @@ class BaseTransformer public function getClient($client_name, $client_email) { - // nlog("searching for {$client_name} with email {$client_email}"); + nlog("client name = {$client_name} - email {$client_email}"); - $client_id_search = $this->company - ->clients() - ->where('id_number', $client_name); + if(!empty($client_name)) + { + nlog("client name = {$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', @@ -92,7 +96,7 @@ class BaseTransformer )->where('email', $client_email); if ($contacts->count() >= 1) { - // nlog("found via contact {$contacts->first()->client_id}"); + nlog("found via contact {$contacts->first()->client_id}"); return $contacts->first()->client_id; } } diff --git a/app/Import/Transformer/Zoho/ClientTransformer.php b/app/Import/Transformer/Zoho/ClientTransformer.php new file mode 100644 index 000000000000..2328f41202c6 --- /dev/null +++ b/app/Import/Transformer/Zoho/ClientTransformer.php @@ -0,0 +1,74 @@ +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']; + } + +nlog($settings); + + 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/tests/Feature/Import/Zoho/ZohoTest.php b/tests/Feature/Import/Zoho/ZohoTest.php new file mode 100644 index 000000000000..e976f086c2e5 --- /dev/null +++ b/tests/Feature/Import/Zoho/ZohoTest.php @@ -0,0 +1,347 @@ +withoutMiddleware(ThrottleRequests::class); + + config(['database.default' => config('ninja.db.default')]); + + $this->makeTestData(); + + $this->withoutExceptionHandling(); + } + + public function testClientZohoImport() + { + $csv = file_get_contents( + base_path() . '/tests/Feature/Import/zoho_contacts.csv' + ); + $hash = Str::random(32); + + $column_map = [ + 0 => 'Created Time', + 1 => 'Last Modified Time', + 2 => 'Display Name', + 3 => 'Company Name', + 4 => 'Salutation', + 5 => 'First Name', + 6 => 'Last Name', + 7 => 'Phone', + 8 => 'Currency Code', + 9 => 'Notes', + 10 => 'Website', + 11 => 'Status', + 12 => 'Credit Limit', + 13 => 'Customer Sub Type', + 14 => 'Billing Attention', + 15 => 'Billing Address', + 16 => 'Billing Street2', + 17 => 'Billing City', + 18 => 'Billing State', + 19 => 'Billing Country', + 20 => 'Billing Code', + 21 => 'Billing Phone', + 22 => 'Billing Fax', + 23 => 'Shipping Attention', + 24 => 'Shipping Address', + 25 => 'Shipping Street2', + 26 => 'Shipping City', + 27 => 'Shipping State', + 28 => 'Shipping Country', + 29 => 'Shipping Code', + 30 => 'Shipping Phone', + 31 => 'Shipping Fax', + 32 => 'Skype Identity', + 33 => 'Facebook', + 34 => 'Twitter', + 35 => 'Department', + 36 => 'Designation', + 37 => 'Price List', + 38 => 'Payment Terms', + 39 => 'Payment Terms Label', + 40 => 'Last Sync Time', + 41 => 'Owner Name', + 42 => 'EmailID', + 43 => 'MobilePhone', + 44 => 'Customer ID', + 45 => 'Customer Name', + 46 => 'Contact Type', + 47 => 'Customer Address ID', + 48 => 'Source', + 49 => 'Reference ID', + 50 => 'Payment Reminder', + ]; + + $data = [ + 'hash' => $hash, + 'column_map' => ['client' => ['mapping' => $column_map]], + 'skip_header' => true, + 'import_type' => 'zoho', + ]; + + Cache::put($hash . '-client', base64_encode($csv), 360); + + $csv_importer = new Zoho($data, $this->company); + + $count = $csv_importer->import('client'); + + $base_transformer = new BaseTransformer($this->company); + + $this->assertTrue($base_transformer->hasClient('Defenders')); + $this->assertTrue($base_transformer->hasClient('Avengers')); + $this->assertTrue($base_transformer->hasClient('Highlander')); + $this->assertTrue($base_transformer->hasClient('Simpsons Baking Co')); + + $client_id = $base_transformer->getClient('', 'jessica@jones.net'); + + $client = Client::find($client_id); + + $this->assertInstanceOf(Client::class, $client); + $this->assertEquals('1', $client->settings->currency_id); + $this->assertEquals('888-867-5309', $client->phone); + + + } + + public function testInvoiceZohoImport() + { + //first import all the clients + $csv = file_get_contents( + base_path() . '/tests/Feature/Import/zoho_contacts.csv' + ); + $hash = Str::random(32); + + $column_map = [ + 0 => 'Created Time', + 1 => 'Last Modified Time', + 2 => 'Display Name', + 3 => 'Company Name', + 4 => 'Salutation', + 5 => 'First Name', + 6 => 'Last Name', + 7 => 'Phone', + 8 => 'Currency Code', + 9 => 'Notes', + 10 => 'Website', + 11 => 'Status', + 12 => 'Credit Limit', + 13 => 'Customer Sub Type', + 14 => 'Billing Attention', + 15 => 'Billing Address', + 16 => 'Billing Street2', + 17 => 'Billing City', + 18 => 'Billing State', + 19 => 'Billing Country', + 20 => 'Billing Code', + 21 => 'Billing Phone', + 22 => 'Billing Fax', + 23 => 'Shipping Attention', + 24 => 'Shipping Address', + 25 => 'Shipping Street2', + 26 => 'Shipping City', + 27 => 'Shipping State', + 28 => 'Shipping Country', + 29 => 'Shipping Code', + 30 => 'Shipping Phone', + 31 => 'Shipping Fax', + 32 => 'Skype Identity', + 33 => 'Facebook', + 34 => 'Twitter', + 35 => 'Department', + 36 => 'Designation', + 37 => 'Price List', + 38 => 'Payment Terms', + 39 => 'Payment Terms Label', + 40 => 'Last Sync Time', + 41 => 'Owner Name', + 42 => 'EmailID', + 43 => 'MobilePhone', + 44 => 'Customer ID', + 45 => 'Customer Name', + 46 => 'Contact Type', + 47 => 'Customer Address ID', + 48 => 'Source', + 49 => 'Reference ID', + 50 => 'Payment Reminder', + ]; + + $data = [ + 'hash' => $hash, + 'column_map' => ['client' => ['mapping' => $column_map]], + 'skip_header' => true, + 'import_type' => 'zoho', + ]; + + Cache::put($hash . '-client', base64_encode($csv), 360); + + $csv_importer = new Zoho($data, $this->company); + + $count = $csv_importer->import('client'); + + //now import the invoices + + $csv = file_get_contents( + base_path() . '/tests/Feature/Import/zoho_invoices.csv' + ); + $hash = Str::random(32); + + $column_map = [ + 0 => 'Invoice Date', + 1 => 'Invoice ID', + 2 => 'Invoice Number', + 3 => 'Estimate Number', + 4 => 'Invoice Status', + 5 => 'Customer Name', + 6 => 'Company Name', + 7 => 'Customer ID', + 8 => 'Branch ID', + 9 => 'Branch Name', + 10 => 'Due Date', + 11 => 'Expected Payment Date', + 12 => 'PurchaseOrder', + 13 => 'Template Name', + 14 => 'Currency Code', + 15 => 'Exchange Rate', + 16 => 'Discount Type', + 17 => 'Is Discount Before Tax', + 18 => 'Entity Discount Percent', + 19 => 'Entity Discount Amount', + 20 => 'Item Name', + 21 => 'Item Desc', + 22 => 'Quantity', + 23 => 'Usage unit', + 24 => 'Item Price', + 25 => 'Discount', + 26 => 'Discount Amount', + 27 => 'Expense Reference ID', + 28 => 'Project ID', + 29 => 'Project Name', + 30 => 'Item Total', + 31 => 'SubTotal', + 32 => 'Total', + 33 => 'Balance', + 34 => 'Shipping Charge', + 35 => 'Adjustment', + 36 => 'Adjustment Description', + 37 => 'Round Off', + 38 => 'Sales person', + 39 => 'Payment Terms', + 40 => 'Payment Terms Label', + 41 => 'Last Payment Date', + 42 => 'Notes', + 43 => 'Terms & Conditions', + 44 => 'Subject', + 45 => 'LateFee Name', + 46 => 'LateFee Type', + 47 => 'LateFee Rate', + 48 => 'LateFee Amount', + 49 => 'LateFee Frequency', + 50 => 'WriteOff Date', + 51 => 'WriteOff Exchange Rate', + 52 => 'WriteOff Amount', + 53 => 'Recurrence Name', + 54 => 'PayPal', + 55 => 'Authorize.Net', + 56 => 'Google Checkout', + 57 => 'Payflow Pro', + 58 => 'Stripe', + 59 => '2Checkout', + 60 => 'Braintree', + 61 => 'Forte', + 62 => 'WorldPay', + 63 => 'Payments Pro', + 64 => 'Square', + 65 => 'WePay', + 66 => 'Razorpay', + 67 => 'GoCardless', + 68 => 'Partial Payments', + 69 => 'Billing Address', + 70 => 'Billing City', + 71 => 'Billing State', + 72 => 'Billing Country', + 73 => 'Billing Code', + 74 => 'Billing Fax', + 75 => 'Billing Phone', + 76 => 'Shipping Address', + 77 => 'Shipping City', + 78 => 'Shipping State', + 79 => 'Shipping Country', + 80 => 'Shipping Code', + 81 => 'Shipping Fax', + 82 => 'Shipping Phone Number', + ]; + + $data = [ + 'hash' => $hash, + 'column_map' => ['invoice' => ['mapping' => $column_map]], + 'skip_header' => true, + 'import_type' => 'zoho', + ]; + + Cache::put($hash . '-invoice', base64_encode($csv), 360); + + $csv_importer = new Zoho($data, $this->company); + + $count = $csv_importer->import('invoice'); + + $base_transformer = new BaseTransformer($this->company); + + $this->assertTrue($base_transformer->hasInvoice("INV-000001")); + $this->assertTrue($base_transformer->hasInvoice("INV-000002")); + $this->assertTrue($base_transformer->hasInvoice("INV-000003")); + + $invoice_id = $base_transformer->getInvoiceId("INV-000003"); + $invoice = Invoice::find($invoice_id); + +nlog($invoice->toArray()); + + $this->assertEquals(390 , $invoice->amount); + // $this->assertEquals(390 , $invoice->balance); + $this->assertEquals(4 , count($invoice->line_items)); + + $this->assertFalse($invoice->payments()->exists()); + // $this->assertEquals(3500.41, $invoice->payments->first()->amount); + + } + + +} +