Merge pull request #8261 from turbo124/v5-develop

Fixes for webhooks
This commit is contained in:
David Bomba 2023-02-08 23:43:58 +11:00 committed by GitHub
commit 3e1b983955
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 349 additions and 79 deletions

View File

@ -834,7 +834,6 @@ class CompanySettings extends BaseSettings
'$client.address1', '$client.address1',
'$client.address2', '$client.address2',
'$client.city_state_postal', '$client.city_state_postal',
'$client.postal_city',
'$client.country', '$client.country',
'$client.phone', '$client.phone',
'$contact.email', '$contact.email',
@ -846,7 +845,6 @@ class CompanySettings extends BaseSettings
'$vendor.address1', '$vendor.address1',
'$vendor.address2', '$vendor.address2',
'$vendor.city_state_postal', '$vendor.city_state_postal',
'$vendor.postal_city',
'$vendor.country', '$vendor.country',
'$vendor.phone', '$vendor.phone',
'$contact.email', '$contact.email',
@ -871,7 +869,6 @@ class CompanySettings extends BaseSettings
'$company.address1', '$company.address1',
'$company.address2', '$company.address2',
'$company.city_state_postal', '$company.city_state_postal',
'$company.postal_city',
'$company.country', '$company.country',
], ],
'invoice_details' => [ 'invoice_details' => [

View File

@ -195,4 +195,56 @@ class Request extends FormRequest
public function prepareForValidation() public function prepareForValidation()
{ {
} }
public function checkTimeLog(array $log): bool
{
if(count($log) == 0)
return true;
/*Get first value of all arrays*/
$result = array_column($log, 0);
/*Sort the array in ascending order*/
asort($result);
$new_array = [];
/*Rebuild the array in order*/
foreach($result as $key => $value)
$new_array[] = $log[$key];
/*Iterate through the array and perform checks*/
foreach($new_array as $key => $array)
{
/*Flag which helps us know if there is a NEXT timelog*/
$next = false;
/* If there are more than 1 time log in the array, ensure the last timestamp is not zero*/
if(count($new_array) >1 && $array[1] == 0)
return false;
/* Check if the start time is greater than the end time */
/* Ignore the last value for now, we'll do a separate check for this */
if($array[0] > $array[1] && $array[1] != 0)
return false;
/* Find the next time log value - if it exists */
if(array_key_exists($key+1, $new_array))
$next = $new_array[$key+1];
/* check the next time log and ensure the start time is GREATER than the end time of the previous record */
if($next && $next[0] < $array[1])
return false;
/* Get the last row of the timelog*/
$last_row = end($new_array);
/*If the last value is NOT zero, ensure start time is not GREATER than the endtime */
if($last_row[1] != 0 && $last_row[0] > $last_row[1])
return false;
return true;
}
}
} }

View File

@ -53,6 +53,9 @@ class StoreTaskRequest extends Request
$fail('The '.$attribute.' - '.print_r($k,1).' is invalid. Unix timestamps only.'); $fail('The '.$attribute.' - '.print_r($k,1).' is invalid. Unix timestamps only.');
} }
if(!$this->checkTimeLog($values))
$fail('Please correct overlapping values');
}]; }];

View File

@ -59,6 +59,9 @@ class UpdateTaskRequest extends Request
$fail('The '.$attribute.' - '.print_r($k,1).' is invalid. Unix timestamps only.'); $fail('The '.$attribute.' - '.print_r($k,1).' is invalid. Unix timestamps only.');
} }
if(!$this->checkTimeLog($values))
$fail('Please correct overlapping values');
}]; }];
return $this->globalRules($rules); return $this->globalRules($rules);

View File

@ -39,6 +39,8 @@ class StoreWebhookRequest extends Request
{ {
$input = $this->all(); $input = $this->all();
if(!isset($input['rest_method']))
$input['rest_method'] = 'post';
// if(isset($input['headers']) && count($input['headers']) == 0) // if(isset($input['headers']) && count($input['headers']) == 0)
// $input['headers'] = null; // $input['headers'] = null;

View File

@ -44,6 +44,9 @@ class UpdateWebhookRequest extends Request
{ {
$input = $this->all(); $input = $this->all();
if(!isset($input['rest_method']))
$input['rest_method'] = 'post';
// if(isset($input['headers']) && count($input['headers']) == 0) // if(isset($input['headers']) && count($input['headers']) == 0)
// $input['headers'] = null; // $input['headers'] = null;

View File

@ -18,7 +18,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
class BankTransactionRule extends BaseModel class BankTransactionRule extends BaseModel
{ {
use SoftDeletes; use SoftDeletes;
use MakesHash;
use Filterable; use Filterable;
protected $fillable = [ protected $fillable = [
@ -66,6 +65,37 @@ class BankTransactionRule extends BaseModel
private array $search_results = []; private array $search_results = [];
public function getEntityType()
{
return self::class;
}
public function company()
{
return $this->belongsTo(Company::class);
}
public function vendor()
{
return $this->belongsTo(Vendor::class);
}
public function client()
{
return $this->belongsTo(Client::class);
}
public function user()
{
return $this->belongsTo(User::class)->withTrashed();
}
public function expense_category()
{
return $this->belongsTo(ExpenseCategory::class, 'category_id')->withTrashed();
}
// rule object looks like this: // rule object looks like this:
//[ //[
// { // {
@ -138,34 +168,5 @@ class BankTransactionRule extends BaseModel
// } // }
// } // }
public function getEntityType()
{
return self::class;
}
public function company()
{
return $this->belongsTo(Company::class);
}
public function vendor()
{
return $this->belongsTo(Vendor::class);
}
public function client()
{
return $this->belongsTo(Client::class);
}
public function user()
{
return $this->belongsTo(User::class)->withTrashed();
}
public function expense_category()
{
return $this->belongsTo(ExpenseCategory::class, 'category_id', 'id')->withTrashed();
}
} }

View File

@ -206,12 +206,22 @@ class BaseModel extends Model
return ctrans('texts.item'); return ctrans('texts.item');
} }
public function sendEvent($event_id, $additional_data=""){ /**
* Model helper to send events for webhooks
*
* @param int $event_id
* @param string $additional_data optional includes
*
* @return void
*/
public function sendEvent(int $event_id, string $additional_data = ""): void
{
$subscriptions = Webhook::where('company_id', $this->company_id) $subscriptions = Webhook::where('company_id', $this->company_id)
->where('event_id', $event_id) ->where('event_id', $event_id)
->exists(); ->exists();
if ($subscriptions) { if ($subscriptions) {
WebhookHandler::dispatch($event_id, $this, $this->company, $additional_data)->delay(0); WebhookHandler::dispatch($event_id, $this, $this->company, $additional_data);
} }
} }

View File

@ -59,7 +59,7 @@ class ClientObserver
->exists(); ->exists();
if ($subscriptions) if ($subscriptions)
WebhookHandler::dispatch($event, $client, $client->company)->delay(0); WebhookHandler::dispatch($event, $client, $client->company, 'client')->delay(0);
} }

View File

@ -58,7 +58,7 @@ class InvoiceObserver
->exists(); ->exists();
if ($subscriptions) if ($subscriptions)
WebhookHandler::dispatch($event, $invoice, $invoice->company)->delay(0); WebhookHandler::dispatch($event, $invoice, $invoice->company, 'client')->delay(0);
} }
/** /**

View File

@ -13,10 +13,13 @@ namespace App\Transformers;
use App\Models\BankTransaction; use App\Models\BankTransaction;
use App\Models\BankTransactionRule; use App\Models\BankTransactionRule;
use App\Models\Client;
use App\Models\Company; use App\Models\Company;
use App\Models\ExpenseCategory; use App\Models\ExpenseCategory;
use App\Transformers\VendorTransformer; use App\Models\Vendor;
use App\Transformers\ExpenseCategoryTransformer;
use App\Transformers\ExpenseCateogryTransformer; use App\Transformers\ExpenseCateogryTransformer;
use App\Transformers\VendorTransformer;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
/** /**
@ -74,31 +77,34 @@ class BankTransactionRuleTransformer extends EntityTransformer
public function includeClient(BankTransactionRule $bank_transaction_rule) public function includeClient(BankTransactionRule $bank_transaction_rule)
{ {
$transformer = new ClientTransformer($this->serializer);
if(!$bank_transaction_rule->client) if(!$bank_transaction_rule->client)
return null; return null;
return $this->includeItem($bank_transaction_rule->expense, $transformer, Client::class); $transformer = new ClientTransformer($this->serializer);
return $this->includeItem($bank_transaction_rule->client, $transformer, Client::class);
} }
public function includeVendor(BankTransactionRule $bank_transaction_rule) public function includeVendor(BankTransactionRule $bank_transaction_rule)
{ {
$transformer = new VendorTransformer($this->serializer);
if(!$bank_transaction_rule->vendor) if(!$bank_transaction_rule->vendor)
return null; return null;
$transformer = new VendorTransformer($this->serializer);
return $this->includeItem($bank_transaction_rule->vendor, $transformer, Vendor::class); return $this->includeItem($bank_transaction_rule->vendor, $transformer, Vendor::class);
} }
public function includeExpenseCategory(BankTransactionRule $bank_transaction_rule) public function includeExpenseCategory(BankTransactionRule $bank_transaction_rule)
{ {
$transformer = new ExpenseCategoryTransformer($this->serializer);
if(!$bank_transaction_rule->expense_cateogry) if(!$bank_transaction_rule->expense_category)
return null; return null;
$transformer = new ExpenseCategoryTransformer($this->serializer);
return $this->includeItem($bank_transaction_rule->expense_category, $transformer, ExpenseCategory::class); return $this->includeItem($bank_transaction_rule->expense_category, $transformer, ExpenseCategory::class);
} }

View File

@ -223,15 +223,15 @@ class Number
/* 08-01-2022 allow increased precision for unit price*/ /* 08-01-2022 allow increased precision for unit price*/
$v = rtrim(sprintf('%f', $value), '0'); $v = rtrim(sprintf('%f', $value), '0');
// $precision = strlen(substr(strrchr($v, $decimal), 1));
if ($v < 1) { /* 08-02-2023 special if block to render $0.5 to $0.50*/
if ($v < 1 && strlen($v) == 3) {
$precision = 2;
}
elseif ($v < 1) {
$precision = strlen($v) - strrpos($v, '.') - 1; $precision = strlen($v) - strrpos($v, '.') - 1;
} }
// if($precision == 1)
// $precision = 2;
$value = number_format($v, $precision, $decimal, $thousand); $value = number_format($v, $precision, $decimal, $thousand);
$symbol = $currency->symbol; $symbol = $currency->symbol;

View File

@ -185,7 +185,7 @@ class BankTransactionRuleTest extends TestCase
$response = $this->withHeaders([ $response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'), 'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token, 'X-API-TOKEN' => $this->token,
])->putJson('/api/v1/bank_transaction_rules/'. $br->hashed_id, $data); ])->putJson('/api/v1/bank_transaction_rules/'. $br->hashed_id. '?include=expense_category', $data);
} catch (ValidationException $e) { } catch (ValidationException $e) {
$message = json_decode($e->validator->getMessageBag(), 1); $message = json_decode($e->validator->getMessageBag(), 1);
@ -194,7 +194,7 @@ class BankTransactionRuleTest extends TestCase
if($response){ if($response){
$arr = $response->json(); $arr = $response->json();
nlog($arr);
$response->assertStatus(200); $response->assertStatus(200);
} }

View File

@ -43,6 +43,198 @@ class TaskApiTest extends TestCase
Model::reguard(); Model::reguard();
} }
private function checkTimeLog(array $log): bool
{
if(count($log) == 0)
return true;
/*Get first value of all arrays*/
$result = array_column($log, 0);
/*Sort the array in ascending order*/
asort($result);
$new_array = [];
/*Rebuild the array in order*/
foreach($result as $key => $value)
$new_array[] = $log[$key];
/*Iterate through the array and perform checks*/
foreach($new_array as $key => $array)
{
/*Flag which helps us know if there is a NEXT timelog*/
$next = false;
/* If there are more than 1 time log in the array, ensure the last timestamp is not zero*/
if(count($new_array) >1 && $array[1] == 0)
return false;
/* Check if the start time is greater than the end time */
/* Ignore the last value for now, we'll do a separate check for this */
if($array[0] > $array[1] && $array[1] != 0)
return false;
/* Find the next time log value - if it exists */
if(array_key_exists($key+1, $new_array))
$next = $new_array[$key+1];
/* check the next time log and ensure the start time is GREATER than the end time of the previous record */
if($next && $next[0] < $array[1])
return false;
/* Get the last row of the timelog*/
$last_row = end($new_array);
/*If the last value is NOT zero, ensure start time is not GREATER than the endtime */
if($last_row[1] != 0 && $last_row[0] > $last_row[1])
return false;
return true;
}
}
public function testTimeLogChecker1()
{
$log = [
[50,0]
];
$this->assertTrue($this->checkTimeLog($log));
}
public function testTimeLogChecker2()
{
$log = [
[4,5],
[5,1]
];
$this->assertFalse($this->checkTimeLog($log));
}
public function testTimeLogChecker3()
{
$log = [
[4,5],
[3,50]
];
$this->assertFalse($this->checkTimeLog($log));
}
public function testTimeLogChecker4()
{
$log = [
[4,5],
[3,0]
];
$this->assertFalse($this->checkTimeLog($log));
}
public function testTimeLogChecker5()
{
$log = [
[4,5],
[3,1]
];
$this->assertFalse($this->checkTimeLog($log));
}
public function testTimeLogChecker6()
{
$log = [
[4,5],
[1,3],
];
$this->assertTrue($this->checkTimeLog($log));
}
public function testTimeLogChecker7()
{
$log = [
[1,3],
[4,5]
];
$this->assertTrue($this->checkTimeLog($log));
}
public function testTimeLogChecker8()
{
$log = [
[1,3],
[50,0]
];
$this->assertTrue($this->checkTimeLog($log));
}
public function testTimeLogChecker9()
{
$log = [
[4,5,'bb'],
[50,0,'aa'],
];
$this->assertTrue($this->checkTimeLog($log));
}
public function testTimeLogChecker10()
{
$log = [
[4,5,'5'],
[50,0,'3'],
];
$this->assertTrue($this->checkTimeLog($log));
}
public function testTimeLogChecker11()
{
$log = [
[1,2,'a'],
[3,4,'d'],
];
$this->assertTrue($this->checkTimeLog($log));
}
public function testTaskListClientStatus() public function testTaskListClientStatus()

View File

@ -49,33 +49,6 @@ class WebhookAPITest extends TestCase
$this->withoutExceptionHandling(); $this->withoutExceptionHandling();
} }
// public function testClientWebhooks()
// {
// // client archived = 37
// $data = [
// 'target_url' => 'http://hook.com',
// 'event_id' => 37,
// 'rest_method' => 'post',
// 'format' => 'JSON',
// ];
// $response = $this->withHeaders([
// 'X-API-SECRET' => config('ninja.api_secret'),
// 'X-API-TOKEN' => $this->token,
// ])->post('/api/v1/webhooks', $data);
// $repo = new ClientRepository(new ClientContactRepository());
// $repo->archive($this->client);
// \Illuminate\Support\Facades\Queue::after(function (WebhookHandler $event) {
// $this->assertTrue($event->job->isReleased());
// });
// \Illuminate\Support\Facades\Queue::assertPushed(WebhookHandler::class);
// }
public function testWebhookGetFilter() public function testWebhookGetFilter()
{ {
$response = $this->withHeaders([ $response = $this->withHeaders([
@ -98,6 +71,20 @@ class WebhookAPITest extends TestCase
public function testWebhookPostRoute() public function testWebhookPostRoute()
{ {
$data = [
'target_url' => 'http://hook.com',
'event_id' => 1,
'format' => 'JSON',
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/webhooks', $data);
$response->assertStatus(200);
$data = [ $data = [
'target_url' => 'http://hook.com', 'target_url' => 'http://hook.com',
'event_id' => 1, 'event_id' => 1,
@ -116,6 +103,20 @@ class WebhookAPITest extends TestCase
$this->assertEquals(1, $arr['data']['event_id']); $this->assertEquals(1, $arr['data']['event_id']);
$data = [
'target_url' => 'http://hook.com',
'event_id' => 2,
'format' => 'JSON',
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->put('/api/v1/webhooks/'.$arr['data']['id'], $data);
$response->assertStatus(200);
$data = [ $data = [
'target_url' => 'http://hook.com', 'target_url' => 'http://hook.com',
'event_id' => 2, 'event_id' => 2,