From afee58f7461a293b5a7a153592a3e913eed06641 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 9 Apr 2020 22:04:26 +1000 Subject: [PATCH] Google Analytics (#3610) * Working on google analytics * google analytics implementation --- app/Http/Controllers/InvoiceController.php | 23 +++--- .../Controllers/OpenAPI/CompanySchema.php | 2 +- .../Controllers/SubscriptionController.php | 14 ++-- app/Listeners/Payment/PaymentNotification.php | 67 +++++++++++++++++ app/Models/Company.php | 2 +- app/Transformers/CompanyTransformer.php | 2 +- config/ninja.php | 1 + ...deleted_column_to_company_tokens_table.php | 4 ++ tests/Feature/SubscriptionAPITest.php | 2 - tests/Unit/GoogleAnalyticsTest.php | 72 +++++++++++++++++++ 10 files changed, 166 insertions(+), 23 deletions(-) create mode 100644 tests/Unit/GoogleAnalyticsTest.php diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index f23589f2a5c9..ea20eb2cdcaf 100644 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -1,4 +1,5 @@ invoice_repo->save($request->all(), InvoiceFactory::create(auth()->user()->company()->id, auth()->user()->id)); - $invoice = StoreInvoice::dispatchNow($invoice, $request->all(), $invoice->company);//todo potentially this may return mixed ie PDF/$invoice... need to revisit when we implement UI + $invoice = StoreInvoice::dispatchNow($invoice, $request->all(), $invoice->company); //todo potentially this may return mixed ie PDF/$invoice... need to revisit when we implement UI event(new InvoiceWasCreated($invoice, $invoice->company)); @@ -527,7 +528,7 @@ class InvoiceController extends BaseController if ($action == 'download' && $invoices->count() > 1) { $invoices->each(function ($invoice) { if (auth()->user()->cannot('view', $invoice)) { - return response()->json(['message'=>'Insufficient privileges to access invoice '. $invoice->number]); + return response()->json(['message' => 'Insufficient privileges to access invoice ' . $invoice->number]); } }); @@ -679,16 +680,16 @@ class InvoiceController extends BaseController case 'cancel': $invoice = $invoice->service()->handleCancellation()->save(); - if(!$bulk){ - $this->itemResponse($invoice); - } + if (!$bulk) { + $this->itemResponse($invoice); + } break; case 'reverse': $invoice = $invoice->service()->handleReversal()->save(); - if(!$bulk){ - $this->itemResponse($invoice); - } + if (!$bulk) { + $this->itemResponse($invoice); + } break; case 'email': @@ -711,7 +712,7 @@ class InvoiceController extends BaseController default: return response()->json(['message' => "The requested action `{$action}` is not available."], 400); - break; + break; } } diff --git a/app/Http/Controllers/OpenAPI/CompanySchema.php b/app/Http/Controllers/OpenAPI/CompanySchema.php index 85dc661201b6..8eaf9293c228 100644 --- a/app/Http/Controllers/OpenAPI/CompanySchema.php +++ b/app/Http/Controllers/OpenAPI/CompanySchema.php @@ -7,7 +7,7 @@ * @OA\Property(property="size_id", type="string", example="1", description="The company size ID"), * @OA\Property(property="industry_id", type="string", example="1", description="The company industry ID"), * @OA\Property(property="slack_webhook_url", type="string", example="https://slack.com/sh328sj", description="The slack webhook notification URL"), - * @OA\Property(property="google_analytics_url", type="string", example="1", description="The google analytics webhook notification URL"), + * @OA\Property(property="google_analytics_key", type="string", example="1", description="The google analytics key"), * @OA\Property(property="portal_mode", type="string", example="subdomain", description="Determines the client facing urls ie: subdomain,domain,iframe"), * @OA\Property(property="subdomain", type="string", example="aceme", description="Specifies the first part of the company domain ie acme in acme.domain.com"), * @OA\Property(property="portal_domain", type="string", example="https://subdomain.invoicing.co", description="The fully qualified domain for client facing URLS"), diff --git a/app/Http/Controllers/SubscriptionController.php b/app/Http/Controllers/SubscriptionController.php index cd36a1fda971..2410389ba925 100644 --- a/app/Http/Controllers/SubscriptionController.php +++ b/app/Http/Controllers/SubscriptionController.php @@ -1,4 +1,5 @@ input('action'); - + $ids = request()->input('ids'); $subscriptions = Subscription::withTrashed()->find($this->transformKeys($ids)); - + $subscriptions->each(function ($subscription, $key) use ($action) { if (auth()->user()->can('edit', $subscription)) { $this->base_repo->{$action}($subscription); } }); - + return $this->listResponse(Subscription::withTrashed()->whereIn('id', $this->transformKeys($ids))); } @@ -521,8 +522,8 @@ class SubscriptionController extends BaseController $event_id = $request->input('event_id'); $target_url = $request->input('target_url'); - if (! in_array($event_id, Subscription::$valid_events)) { - return response()->json("Invalid event",400); + if (!in_array($event_id, Subscription::$valid_events)) { + return response()->json("Invalid event", 400); } $subscription = new Subscription; @@ -537,7 +538,6 @@ class SubscriptionController extends BaseController } return $this->itemResponse($subscription); - } /** @@ -595,4 +595,4 @@ class SubscriptionController extends BaseController return $this->itemResponse($subscription); } -} \ No newline at end of file +} diff --git a/app/Listeners/Payment/PaymentNotification.php b/app/Listeners/Payment/PaymentNotification.php index 19944e4d4796..fd758ee92ad9 100644 --- a/app/Listeners/Payment/PaymentNotification.php +++ b/app/Listeners/Payment/PaymentNotification.php @@ -16,6 +16,7 @@ use App\Models\Invoice; use App\Models\Payment; use App\Notifications\Admin\NewPaymentNotification; use App\Repositories\ActivityRepository; +use App\Utils\Ninja; use App\Utils\Traits\Notifications\UserNotifies; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Queue\InteractsWithQueue; @@ -43,7 +44,9 @@ class PaymentNotification implements ShouldQueue { $payment = $event->payment; + /*User notifications*/ foreach ($payment->company->company_users as $company_user) { + $user = $company_user->user; $notification = new NewPaymentNotification($payment, $payment->company); @@ -52,11 +55,75 @@ class PaymentNotification implements ShouldQueue if ($user) { $user->notify($notification); } + } + /*Company Notifications*/ if (isset($payment->company->slack_webhook_url)) { Notification::route('slack', $payment->company->slack_webhook_url) ->notify(new NewPaymentNotification($payment, $payment->company, true)); } + + /*Google Analytics Track Revenue*/ + + if (isset($payment->company->google_analytics_key)) + $this->trackRevenue($event); + + } + + private function trackRevenue($event) + { + $payment = $event->payment; + $invoice = $payment->invoice; + $company = $payment->company; + + $analytics_id = $company->google_analytics_key; + + $client = $payment->client; + $amount = $payment->amount; + + if($invoice){ + $items = $invoice->line_items; + $item = end($items)->product_key; + $entity_number = $invoice->number; + } + else{ + $item = $payment->number; + $entity_number = $item; + } + + $currency_code = $client->getCurrencyCode(); + + if (Ninja::isHosted()) { + $item .= ' [R]'; + } + + $base = "v=1&tid={$analytics_id}&cid={$client->id}&cu={$currency_code}&ti={$entity_number}"; + + $url = $base . "&t=transaction&ta=ninja&tr={$amount}"; + $this->sendAnalytics($url); + + $url = $base . "&t=item&in={$item}&ip={$amount}&iq=1"; + $this->sendAnalytics($url); + } + + /** + * @param $data + */ + private function sendAnalytics($data) + { + $data = utf8_encode($data); + $curl = curl_init(); + + $opts = [ + CURLOPT_URL => config('ninja.google_analytics_url'), + CURLOPT_RETURNTRANSFER => true, + CURLOPT_POST => 'POST', + CURLOPT_POSTFIELDS => $data, + ]; + + curl_setopt_array($curl, $opts); + curl_exec($curl); + curl_close($curl); } } diff --git a/app/Models/Company.php b/app/Models/Company.php index 995879a7add1..35862f5e9611 100644 --- a/app/Models/Company.php +++ b/app/Models/Company.php @@ -94,7 +94,7 @@ class Company extends BaseModel 'first_day_of_week', 'first_month_of_year', 'slack_webhook_url', - 'google_analytics_url', + 'google_analytics_key', ]; diff --git a/app/Transformers/CompanyTransformer.php b/app/Transformers/CompanyTransformer.php index 89ccb6b9dd09..091f768a952d 100644 --- a/app/Transformers/CompanyTransformer.php +++ b/app/Transformers/CompanyTransformer.php @@ -110,7 +110,7 @@ class CompanyTransformer extends EntityTransformer 'archived_at' => (int)$company->deleted_at, 'created_at' =>(int)$company->created_at, 'slack_webhook_url' => (string)$company->slack_webhook_url, - 'google_analytics_url' => (string)$company->google_analytics_url, + 'google_analytics_key' => (string)$company->google_analytics_key, ]; } diff --git a/config/ninja.php b/config/ninja.php index 913b2ff825ea..94afdf5bb73d 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -16,6 +16,7 @@ return [ 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', ''), 'google_maps_api_key' => env('GOOGLE_MAPS_API_KEY'), + 'google_analytics_url' => env('GOOGLE_ANALYTICS_URL', 'https://www.google-analytics.com/collect'), 'key_length' => 64, 'date_format' => 'Y-m-d', 'date_time_format' => 'Y-m-d H:i', diff --git a/database/migrations/2020_04_08_234530_add_is_deleted_column_to_company_tokens_table.php b/database/migrations/2020_04_08_234530_add_is_deleted_column_to_company_tokens_table.php index c9df14d60e46..ebd78e55d674 100644 --- a/database/migrations/2020_04_08_234530_add_is_deleted_column_to_company_tokens_table.php +++ b/database/migrations/2020_04_08_234530_add_is_deleted_column_to_company_tokens_table.php @@ -32,6 +32,10 @@ class AddIsDeletedColumnToCompanyTokensTable extends Migration $table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade'); }); + + Schema::table('companies', function (Blueprint $table) { + $table->renameColumn('google_analytics_url', 'google_analytics_key'); + }); } /** diff --git a/tests/Feature/SubscriptionAPITest.php b/tests/Feature/SubscriptionAPITest.php index 09aa65646d19..87f422b67d5e 100644 --- a/tests/Feature/SubscriptionAPITest.php +++ b/tests/Feature/SubscriptionAPITest.php @@ -108,8 +108,6 @@ class SubscriptionAPITest extends TestCase $arr = $response->json(); -\Log::error(print_r($arr,1)); - $this->assertEquals(0,$arr['data'][0]['archived_at']); diff --git a/tests/Unit/GoogleAnalyticsTest.php b/tests/Unit/GoogleAnalyticsTest.php new file mode 100644 index 000000000000..6bd349ad066c --- /dev/null +++ b/tests/Unit/GoogleAnalyticsTest.php @@ -0,0 +1,72 @@ +makeTestData(); + + } + + public function testGoogleAnalyticsLogic() + { + + + $analytics_id = "analytics_id"; + $invoice = $this->invoice; + $client = $this->client; + + $invoice->service()->markPaid()->save(); + + $payment = $invoice->payments->first(); + + $amount = $payment->amount; + + if($invoice){ + $items = $invoice->line_items; + $item = end($items)->product_key; + $entity_number = $invoice->number; + } + else{ + $item = $payment->number; + $entity_number = $item; + } + + $currency_code = $client->getCurrencyCode(); + + if (Ninja::isHosted()) { + $item .= ' [R]'; + } + + $base = "v=1&tid={$analytics_id}&cid={$client->id}&cu={$currency_code}&ti={$entity_number}"; + + $url = $base . "&t=transaction&ta=ninja&tr={$amount}"; + + $url = $base . "&t=item&in={$item}&ip={$amount}&iq=1"; + + $this->assertNotNull($url); + } +} + + +