mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Google Analytics (#3610)
* Working on google analytics * google analytics implementation
This commit is contained in:
parent
05443d69ec
commit
afee58f746
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoice Ninja (https://invoiceninja.com)
|
* Invoice Ninja (https://invoiceninja.com)
|
||||||
*
|
*
|
||||||
@ -49,9 +50,9 @@ class InvoiceController extends BaseController
|
|||||||
{
|
{
|
||||||
use MakesHash;
|
use MakesHash;
|
||||||
|
|
||||||
protected $entity_type = Invoice::class ;
|
protected $entity_type = Invoice::class;
|
||||||
|
|
||||||
protected $entity_transformer = InvoiceTransformer::class ;
|
protected $entity_transformer = InvoiceTransformer::class;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var InvoiceRepository
|
* @var InvoiceRepository
|
||||||
@ -211,7 +212,7 @@ class InvoiceController extends BaseController
|
|||||||
|
|
||||||
$invoice = $this->invoice_repo->save($request->all(), InvoiceFactory::create(auth()->user()->company()->id, auth()->user()->id));
|
$invoice = $this->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));
|
event(new InvoiceWasCreated($invoice, $invoice->company));
|
||||||
|
|
||||||
@ -527,7 +528,7 @@ class InvoiceController extends BaseController
|
|||||||
if ($action == 'download' && $invoices->count() > 1) {
|
if ($action == 'download' && $invoices->count() > 1) {
|
||||||
$invoices->each(function ($invoice) {
|
$invoices->each(function ($invoice) {
|
||||||
if (auth()->user()->cannot('view', $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':
|
case 'cancel':
|
||||||
$invoice = $invoice->service()->handleCancellation()->save();
|
$invoice = $invoice->service()->handleCancellation()->save();
|
||||||
|
|
||||||
if(!$bulk){
|
if (!$bulk) {
|
||||||
$this->itemResponse($invoice);
|
$this->itemResponse($invoice);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'reverse':
|
case 'reverse':
|
||||||
$invoice = $invoice->service()->handleReversal()->save();
|
$invoice = $invoice->service()->handleReversal()->save();
|
||||||
|
|
||||||
if(!$bulk){
|
if (!$bulk) {
|
||||||
$this->itemResponse($invoice);
|
$this->itemResponse($invoice);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'email':
|
case 'email':
|
||||||
|
|
||||||
@ -711,7 +712,7 @@ class InvoiceController extends BaseController
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
return response()->json(['message' => "The requested action `{$action}` is not available."], 400);
|
return response()->json(['message' => "The requested action `{$action}` is not available."], 400);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* @OA\Property(property="size_id", type="string", example="1", description="The company size ID"),
|
* @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="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="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="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="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"),
|
* @OA\Property(property="portal_domain", type="string", example="https://subdomain.invoicing.co", description="The fully qualified domain for client facing URLS"),
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoice Ninja (https://invoiceninja.com)
|
* Invoice Ninja (https://invoiceninja.com)
|
||||||
*
|
*
|
||||||
@ -467,16 +468,16 @@ class SubscriptionController extends BaseController
|
|||||||
public function bulk()
|
public function bulk()
|
||||||
{
|
{
|
||||||
$action = request()->input('action');
|
$action = request()->input('action');
|
||||||
|
|
||||||
$ids = request()->input('ids');
|
$ids = request()->input('ids');
|
||||||
$subscriptions = Subscription::withTrashed()->find($this->transformKeys($ids));
|
$subscriptions = Subscription::withTrashed()->find($this->transformKeys($ids));
|
||||||
|
|
||||||
$subscriptions->each(function ($subscription, $key) use ($action) {
|
$subscriptions->each(function ($subscription, $key) use ($action) {
|
||||||
if (auth()->user()->can('edit', $subscription)) {
|
if (auth()->user()->can('edit', $subscription)) {
|
||||||
$this->base_repo->{$action}($subscription);
|
$this->base_repo->{$action}($subscription);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return $this->listResponse(Subscription::withTrashed()->whereIn('id', $this->transformKeys($ids)));
|
return $this->listResponse(Subscription::withTrashed()->whereIn('id', $this->transformKeys($ids)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,8 +522,8 @@ class SubscriptionController extends BaseController
|
|||||||
$event_id = $request->input('event_id');
|
$event_id = $request->input('event_id');
|
||||||
$target_url = $request->input('target_url');
|
$target_url = $request->input('target_url');
|
||||||
|
|
||||||
if (! in_array($event_id, Subscription::$valid_events)) {
|
if (!in_array($event_id, Subscription::$valid_events)) {
|
||||||
return response()->json("Invalid event",400);
|
return response()->json("Invalid event", 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
$subscription = new Subscription;
|
$subscription = new Subscription;
|
||||||
@ -537,7 +538,6 @@ class SubscriptionController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
return $this->itemResponse($subscription);
|
return $this->itemResponse($subscription);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -595,4 +595,4 @@ class SubscriptionController extends BaseController
|
|||||||
|
|
||||||
return $this->itemResponse($subscription);
|
return $this->itemResponse($subscription);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ use App\Models\Invoice;
|
|||||||
use App\Models\Payment;
|
use App\Models\Payment;
|
||||||
use App\Notifications\Admin\NewPaymentNotification;
|
use App\Notifications\Admin\NewPaymentNotification;
|
||||||
use App\Repositories\ActivityRepository;
|
use App\Repositories\ActivityRepository;
|
||||||
|
use App\Utils\Ninja;
|
||||||
use App\Utils\Traits\Notifications\UserNotifies;
|
use App\Utils\Traits\Notifications\UserNotifies;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
@ -43,7 +44,9 @@ class PaymentNotification implements ShouldQueue
|
|||||||
{
|
{
|
||||||
$payment = $event->payment;
|
$payment = $event->payment;
|
||||||
|
|
||||||
|
/*User notifications*/
|
||||||
foreach ($payment->company->company_users as $company_user) {
|
foreach ($payment->company->company_users as $company_user) {
|
||||||
|
|
||||||
$user = $company_user->user;
|
$user = $company_user->user;
|
||||||
|
|
||||||
$notification = new NewPaymentNotification($payment, $payment->company);
|
$notification = new NewPaymentNotification($payment, $payment->company);
|
||||||
@ -52,11 +55,75 @@ class PaymentNotification implements ShouldQueue
|
|||||||
if ($user) {
|
if ($user) {
|
||||||
$user->notify($notification);
|
$user->notify($notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*Company Notifications*/
|
||||||
if (isset($payment->company->slack_webhook_url)) {
|
if (isset($payment->company->slack_webhook_url)) {
|
||||||
Notification::route('slack', $payment->company->slack_webhook_url)
|
Notification::route('slack', $payment->company->slack_webhook_url)
|
||||||
->notify(new NewPaymentNotification($payment, $payment->company, true));
|
->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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ class Company extends BaseModel
|
|||||||
'first_day_of_week',
|
'first_day_of_week',
|
||||||
'first_month_of_year',
|
'first_month_of_year',
|
||||||
'slack_webhook_url',
|
'slack_webhook_url',
|
||||||
'google_analytics_url',
|
'google_analytics_key',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ class CompanyTransformer extends EntityTransformer
|
|||||||
'archived_at' => (int)$company->deleted_at,
|
'archived_at' => (int)$company->deleted_at,
|
||||||
'created_at' =>(int)$company->created_at,
|
'created_at' =>(int)$company->created_at,
|
||||||
'slack_webhook_url' => (string)$company->slack_webhook_url,
|
'slack_webhook_url' => (string)$company->slack_webhook_url,
|
||||||
'google_analytics_url' => (string)$company->google_analytics_url,
|
'google_analytics_key' => (string)$company->google_analytics_key,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ return [
|
|||||||
'terms_version' => '1.0.1',
|
'terms_version' => '1.0.1',
|
||||||
'api_secret' => env('API_SECRET', ''),
|
'api_secret' => env('API_SECRET', ''),
|
||||||
'google_maps_api_key' => env('GOOGLE_MAPS_API_KEY'),
|
'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,
|
'key_length' => 64,
|
||||||
'date_format' => 'Y-m-d',
|
'date_format' => 'Y-m-d',
|
||||||
'date_time_format' => 'Y-m-d H:i',
|
'date_time_format' => 'Y-m-d H:i',
|
||||||
|
@ -32,6 +32,10 @@ class AddIsDeletedColumnToCompanyTokensTable extends Migration
|
|||||||
|
|
||||||
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
|
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Schema::table('companies', function (Blueprint $table) {
|
||||||
|
$table->renameColumn('google_analytics_url', 'google_analytics_key');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -108,8 +108,6 @@ class SubscriptionAPITest extends TestCase
|
|||||||
|
|
||||||
$arr = $response->json();
|
$arr = $response->json();
|
||||||
|
|
||||||
\Log::error(print_r($arr,1));
|
|
||||||
|
|
||||||
$this->assertEquals(0,$arr['data'][0]['archived_at']);
|
$this->assertEquals(0,$arr['data'][0]['archived_at']);
|
||||||
|
|
||||||
|
|
||||||
|
72
tests/Unit/GoogleAnalyticsTest.php
Normal file
72
tests/Unit/GoogleAnalyticsTest.php
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Unit;
|
||||||
|
|
||||||
|
use App\DataMapper\ClientSettings;
|
||||||
|
use App\DataMapper\CompanySettings;
|
||||||
|
use App\Models\GroupSetting;
|
||||||
|
use App\Utils\Ninja;
|
||||||
|
use App\Utils\Traits\ClientGroupSettingsSaver;
|
||||||
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Tests\MockAccountData;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @covers App\Listeners\Payment\PaymentNotification
|
||||||
|
*/
|
||||||
|
class GoogleAnalyticsTest extends TestCase
|
||||||
|
{
|
||||||
|
use MockAccountData;
|
||||||
|
use DatabaseTransactions;
|
||||||
|
|
||||||
|
public function setUp() :void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user