Merge pull request #9392 from turbo124/v5-develop

Fixes for payment validation
This commit is contained in:
David Bomba 2024-03-20 22:12:37 +11:00 committed by GitHub
commit 40f441cb13
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 556 additions and 309 deletions

View File

@ -200,14 +200,16 @@ class InvoiceFilters extends QueryFilters
*/ */
public function payable(string $client_id = ''): Builder public function payable(string $client_id = ''): Builder
{ {
if (strlen($client_id) == 0) { if (strlen($client_id) == 0) {
return $this->builder; return $this->builder;
} }
return $this->builder->whereIn('status_id', [Invoice::STATUS_DRAFT, Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) return $this->builder
->where('balance', '>', 0) ->where('client_id', $this->decodePrimaryKey($client_id))
->whereIn('status_id', [Invoice::STATUS_DRAFT, Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
->where('is_deleted', 0) ->where('is_deleted', 0)
->where('client_id', $this->decodePrimaryKey($client_id)); ->where('balance', '>', 0);
} }

View File

@ -43,7 +43,7 @@ class ContactLoginController extends Controller
if ($request->session()->has('company_key')) { if ($request->session()->has('company_key')) {
MultiDB::findAndSetDbByCompanyKey($request->session()->get('company_key')); MultiDB::findAndSetDbByCompanyKey($request->session()->get('company_key'));
$company = Company::where('company_key', $request->input('company_key'))->first(); $company = Company::where('company_key', $request->session()->get('company_key'))->first();
} elseif ($request->has('company_key')) { } elseif ($request->has('company_key')) {
MultiDB::findAndSetDbByCompanyKey($request->input('company_key')); MultiDB::findAndSetDbByCompanyKey($request->input('company_key'));
$company = Company::where('company_key', $request->input('company_key'))->first(); $company = Company::where('company_key', $request->input('company_key'))->first();

View File

@ -57,8 +57,6 @@ class RefundPaymentRequest extends Request
if (isset($input['credits'])) { if (isset($input['credits'])) {
unset($input['credits']); unset($input['credits']);
// foreach($input['credits'] as $key => $credit)
// $input['credits'][$key]['credit_id'] = $this->decodePrimaryKey($credit['credit_id']);
} }
$this->replace($input); $this->replace($input);

View File

@ -16,7 +16,6 @@ use App\Http\ValidationRules\Credit\CreditsSumRule;
use App\Http\ValidationRules\Credit\ValidCreditsRules; use App\Http\ValidationRules\Credit\ValidCreditsRules;
use App\Http\ValidationRules\Payment\ValidInvoicesRules; use App\Http\ValidationRules\Payment\ValidInvoicesRules;
use App\Http\ValidationRules\PaymentAmountsBalanceRule; use App\Http\ValidationRules\PaymentAmountsBalanceRule;
use App\Http\ValidationRules\ValidCreditsPresentRule;
use App\Http\ValidationRules\ValidPayableInvoicesRule; use App\Http\ValidationRules\ValidPayableInvoicesRule;
use App\Models\Payment; use App\Models\Payment;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
@ -39,6 +38,41 @@ class StorePaymentRequest extends Request
return $user->can('create', Payment::class); return $user->can('create', Payment::class);
} }
public function rules()
{
/** @var \App\Models\User $user */
$user = auth()->user();
$rules = [
'client_id' => ['bail','required',Rule::exists('clients','id')->where('company_id',$user->company()->id)->where('is_deleted', 0)],
'amount' => ['bail', 'numeric', new PaymentAmountsBalanceRule()],
'invoices.*.amount' => ['bail','required'],
'invoices.*.invoice_id' => ['bail','required','distinct',new ValidInvoicesRules($this->all()),Rule::exists('invoices','id')->where('company_id', $user->company()->id)->where('client_id', request()->input('client_id'))],
'credits.*.credit_id' => ['bail','required','distinct',new ValidCreditsRules($this->all()),Rule::exists('credits','id')->where('company_id', $user->company()->id)->where('client_id', request()->input('client_id'))],
'credits.*.amount' => ['bail','required', new CreditsSumRule($this->all())],
'invoices' => ['bail','sometimes','array', new ValidPayableInvoicesRule()],
'number' => ['bail', 'nullable', Rule::unique('payments')->where('company_id', $user->company()->id)],
'idempotency_key' => ['nullable', 'bail', 'string','max:64', Rule::unique('payments')->where('company_id', $user->company()->id)],
];
if ($this->file('documents') && is_array($this->file('documents'))) {
$rules['documents.*'] = $this->fileValidation();
} elseif ($this->file('documents')) {
$rules['documents'] = $this->fileValidation();
}else {
$rules['documents'] = 'bail|sometimes|array';
}
if ($this->file('file') && is_array($this->file('file'))) {
$rules['file.*'] = $this->fileValidation();
} elseif ($this->file('file')) {
$rules['file'] = $this->fileValidation();
}
return $rules;
}
public function prepareForValidation() public function prepareForValidation()
{ {
@ -78,7 +112,6 @@ class StorePaymentRequest extends Request
foreach ($input['credits'] as $key => $value) { foreach ($input['credits'] as $key => $value) {
if (array_key_exists('credit_id', $input['credits'][$key])) { if (array_key_exists('credit_id', $input['credits'][$key])) {
$input['credits'][$key]['credit_id'] = $this->decodePrimaryKey($value['credit_id']); $input['credits'][$key]['credit_id'] = $this->decodePrimaryKey($value['credit_id']);
$credits_total += $value['amount']; $credits_total += $value['amount'];
} }
} }
@ -103,39 +136,5 @@ class StorePaymentRequest extends Request
$this->replace($input); $this->replace($input);
} }
public function rules()
{
/** @var \App\Models\User $user */
$user = auth()->user();
$rules = [
'amount' => ['numeric', 'bail', new PaymentAmountsBalanceRule(), new ValidCreditsPresentRule($this->all())],
'client_id' => 'bail|required|exists:clients,id,company_id,'.$user->company()->id.',is_deleted,0',
'invoices.*.invoice_id' => 'bail|required|distinct|exists:invoices,id',
'invoices.*.amount' => 'bail|required',
'invoices.*.invoice_id' => new ValidInvoicesRules($this->all()),
'credits.*.credit_id' => 'bail|required|exists:credits,id',
'credits.*.credit_id' => new ValidCreditsRules($this->all()),
'credits.*.amount' => ['bail','required', new CreditsSumRule($this->all())],
'invoices' => new ValidPayableInvoicesRule(),
'number' => ['nullable', 'bail', Rule::unique('payments')->where('company_id', $user->company()->id)],
'idempotency_key' => ['nullable', 'bail', 'string','max:64', Rule::unique('payments')->where('company_id', $user->company()->id)],
];
if ($this->file('documents') && is_array($this->file('documents'))) {
$rules['documents.*'] = $this->fileValidation();
} elseif ($this->file('documents')) {
$rules['documents'] = $this->fileValidation();
}else {
$rules['documents'] = 'bail|sometimes|array';
}
if ($this->file('file') && is_array($this->file('file'))) {
$rules['file.*'] = $this->fileValidation();
} elseif ($this->file('file')) {
$rules['file'] = $this->fileValidation();
}
return $rules;
}
} }

View File

@ -13,7 +13,6 @@ namespace App\Http\Requests\Payment;
use App\Http\Requests\Request; use App\Http\Requests\Request;
use App\Http\ValidationRules\PaymentAppliedValidAmount; use App\Http\ValidationRules\PaymentAppliedValidAmount;
use App\Http\ValidationRules\ValidCreditsPresentRule;
use App\Utils\Traits\ChecksEntityStatus; use App\Utils\Traits\ChecksEntityStatus;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use Illuminate\Validation\Rule; use Illuminate\Validation\Rule;
@ -43,14 +42,15 @@ class UpdatePaymentRequest extends Request
$user = auth()->user(); $user = auth()->user();
$rules = [ $rules = [
'invoices' => ['array', new PaymentAppliedValidAmount($this->all()), new ValidCreditsPresentRule($this->all())], 'client_id' => ['sometimes', 'bail', Rule::in([$this->payment->client_id])],
'invoices.*.invoice_id' => 'distinct', 'number' => ['sometimes', 'bail', Rule::unique('payments')->where('company_id', $user->company()->id)->ignore($this->payment->id)],
'invoices' => ['sometimes', 'bail', 'array', new PaymentAppliedValidAmount($this->all())],
'invoices.*.invoice_id' => ['sometimes','distinct',Rule::exists('invoices','id')->where('company_id', $user->company()->id)->where('client_id', request()->input('client_id'))],
'invoices.*.amount' => ['sometimes','numeric','min:0'],
'credits.*.credit_id' => ['sometimes','bail','distinct',Rule::exists('credits','id')->where('company_id', $user->company()->id)->where('client_id', request()->input('client_id'))],
'credits.*.amount' => ['required', 'bail'],
]; ];
if ($this->number) {
$rules['number'] = Rule::unique('payments')->where('company_id', $user->company()->id)->ignore($this->payment->id);
}
if ($this->file('documents') && is_array($this->file('documents'))) { if ($this->file('documents') && is_array($this->file('documents'))) {
$rules['documents.*'] = $this->fileValidation(); $rules['documents.*'] = $this->fileValidation();
} elseif ($this->file('documents')) { } elseif ($this->file('documents')) {
@ -74,10 +74,6 @@ class UpdatePaymentRequest extends Request
$input = $this->decodePrimaryKeys($input); $input = $this->decodePrimaryKeys($input);
if (isset($input['client_id'])) {
unset($input['client_id']);
}
if (isset($input['amount'])) { if (isset($input['amount'])) {
unset($input['amount']); unset($input['amount']);
} }
@ -85,7 +81,6 @@ class UpdatePaymentRequest extends Request
if (isset($input['invoices']) && is_array($input['invoices']) !== false) { if (isset($input['invoices']) && is_array($input['invoices']) !== false) {
foreach ($input['invoices'] as $key => $value) { foreach ($input['invoices'] as $key => $value) {
if(isset($input['invoices'][$key]['invoice_id'])) { if(isset($input['invoices'][$key]['invoice_id'])) {
// if (array_key_exists('invoice_id', $input['invoices'][$key])) {
$input['invoices'][$key]['invoice_id'] = $this->decodePrimaryKey($value['invoice_id']); $input['invoices'][$key]['invoice_id'] = $this->decodePrimaryKey($value['invoice_id']);
} }
} }
@ -93,7 +88,6 @@ class UpdatePaymentRequest extends Request
if (isset($input['credits']) && is_array($input['credits']) !== false) { if (isset($input['credits']) && is_array($input['credits']) !== false) {
foreach ($input['credits'] as $key => $value) { foreach ($input['credits'] as $key => $value) {
// if (array_key_exists('credits', $input['credits'][$key])) {
if (isset($input['credits'][$key]['credit_id'])) { if (isset($input['credits'][$key]['credit_id'])) {
$input['credits'][$key]['credit_id'] = $this->decodePrimaryKey($value['credit_id']); $input['credits'][$key]['credit_id'] = $this->decodePrimaryKey($value['credit_id']);
} }

View File

@ -57,9 +57,6 @@ class ValidRefundableRequest implements Rule
if ($payment->invoices()->exists()) { if ($payment->invoices()->exists()) {
$this->checkInvoice($payment->invoices, $request_invoices); $this->checkInvoice($payment->invoices, $request_invoices);
// foreach ($payment->invoices as $paymentable_invoice) {
// $this->checkInvoice($paymentable_invoice, $request_invoices);
// }
} }
foreach ($request_invoices as $request_invoice) { foreach ($request_invoices as $request_invoice) {

View File

@ -61,7 +61,10 @@ class PaymentAppliedValidAmount implements Rule
$payment_amounts = 0; $payment_amounts = 0;
$invoice_amounts = 0; $invoice_amounts = 0;
$payment_amounts = $payment->amount - $payment->refunded - $payment->applied; // $payment_amounts = $payment->amount - $payment->refunded - $payment->applied;
//20-03-2024 - applied amounts are never tainted by refunded amount.
$payment_amounts = $payment->amount - $payment->applied;
if (request()->has('credits') if (request()->has('credits')
&& is_array(request()->input('credits')) && is_array(request()->input('credits'))
@ -84,10 +87,6 @@ class PaymentAppliedValidAmount implements Rule
$inv = $inv_collection->firstWhere('id', $invoice['invoice_id']); $inv = $inv_collection->firstWhere('id', $invoice['invoice_id']);
nlog($inv->status_id);
nlog($inv->amount);
nlog($invoice['amount']);
if($inv->status_id == Invoice::STATUS_DRAFT && $inv->amount >= $invoice['amount']) { if($inv->status_id == Invoice::STATUS_DRAFT && $inv->amount >= $invoice['amount']) {
} elseif ($inv->balance < $invoice['amount']) { } elseif ($inv->balance < $invoice['amount']) {

View File

@ -17,6 +17,7 @@ use Illuminate\Contracts\Validation\Rule;
/** /**
* Class ValidCreditsPresentRule. * Class ValidCreditsPresentRule.
* @deprecated 20-03-2024
*/ */
class ValidCreditsPresentRule implements Rule class ValidCreditsPresentRule implements Rule
{ {
@ -49,11 +50,8 @@ class ValidCreditsPresentRule implements Rule
private function validCreditsPresent(): bool private function validCreditsPresent(): bool
{ {
//todo need to ensure the clients credits are here not random ones!
if (array_key_exists('credits', $this->input) && is_array($this->input['credits']) && count($this->input['credits']) > 0) { if (array_key_exists('credits', $this->input) && is_array($this->input['credits']) && count($this->input['credits']) > 0) {
$credit_collection = Credit::query()->whereIn('id', array_column($this->input['credits'], 'credit_id'))->count(); $credit_collection = Credit::query()->whereIn('id', array_column($this->input['credits'], 'credit_id'))->count();
return $credit_collection == count($this->input['credits']); return $credit_collection == count($this->input['credits']);
} }

View File

@ -69,6 +69,9 @@ class UpdateCalculatedFields
$project->save(); $project->save();
}); });
//Clean password resets table
\DB::connection($db)->table('password_resets')->where('created_at', '<', now()->subHour())->delete();
} }
} }
} }

View File

@ -12,6 +12,7 @@
namespace App\Models; namespace App\Models;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use Carbon\CarbonInterval;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
@ -248,6 +249,7 @@ class Task extends BaseModel
$duration += max($end_time - $start_time, 0); $duration += max($end_time - $start_time, 0);
} }
// return CarbonInterval::seconds(round($duration))->locale($this->company->locale())->cascade()->forHumans();
return round($duration); return round($duration);
} }

View File

@ -292,7 +292,32 @@ class PayPalPPCPPaymentDriver extends BaseDriver
} }
try {
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}/capture", 'post', ['body' => '']); $r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}/capture", 'post', ['body' => '']);
} catch(\Exception $e) {
//Rescue for duplicate invoice_id
if(stripos($e->getMessage(), 'DUPLICATE_INVOICE_ID') !== false) {
$_invoice = collect($this->payment_hash->data->invoices)->first();
$invoice = Invoice::withTrashed()->find($this->decodePrimaryKey($_invoice->invoice_id));
$new_invoice_number = $invoice->number."_".Str::random(5);
$update_data =
[[
"op" => "replace",
"path" => "/purchase_units/@reference_id=='default'/invoice_id",
"value" => $new_invoice_number,
]];
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}", 'patch', $update_data);
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}/capture", 'post', ['body' => '']);
}
}
$response = $r; $response = $r;

View File

@ -18,6 +18,7 @@ use App\Models\Invoice;
use App\Models\SystemLog; use App\Models\SystemLog;
use App\Models\GatewayType; use App\Models\GatewayType;
use App\Models\PaymentType; use App\Models\PaymentType;
use Illuminate\Support\Str;
use App\Jobs\Util\SystemLogger; use App\Jobs\Util\SystemLogger;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use App\Exceptions\PaymentFailed; use App\Exceptions\PaymentFailed;
@ -212,6 +213,7 @@ class PayPalRestPaymentDriver extends BaseDriver
$request['gateway_response'] = str_replace("Error: ", "", $request['gateway_response']); $request['gateway_response'] = str_replace("Error: ", "", $request['gateway_response']);
$response = json_decode($request['gateway_response'], true); $response = json_decode($request['gateway_response'], true);
// nlog($response);
//capture //capture
$orderID = $response['orderID']; $orderID = $response['orderID'];
@ -235,7 +237,33 @@ class PayPalRestPaymentDriver extends BaseDriver
} }
try{
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}/capture", 'post', ['body' => '']); $r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}/capture", 'post', ['body' => '']);
}
catch(\Exception $e) {
//Rescue for duplicate invoice_id
if(stripos($e->getMessage(), 'DUPLICATE_INVOICE_ID') !== false){
$_invoice = collect($this->payment_hash->data->invoices)->first();
$invoice = Invoice::withTrashed()->find($this->decodePrimaryKey($_invoice->invoice_id));
$new_invoice_number = $invoice->number."_".Str::random(5);
$update_data =
[[
"op" => "replace",
"path" => "/purchase_units/@reference_id=='default'/invoice_id",
"value" => $new_invoice_number,
]];
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}", 'patch', $update_data);
$r = $this->gatewayRequest("/v2/checkout/orders/{$orderID}/capture", 'post', ['body' => '']);
}
}
$response = $r; $response = $r;

View File

@ -109,14 +109,35 @@ class ACH
public function verificationView(ClientGatewayToken $token) public function verificationView(ClientGatewayToken $token)
{ {
//double check here if we need to show the verification view.
$this->stripe->init();
if(substr($token->token,0,2) == 'pm'){
$pm = $this->stripe->getStripePaymentMethod($token->token);
if(!$pm->customer){
$meta = $token->meta;
$meta->state = 'unauthorized';
$token->meta = $meta;
$token->save();
return redirect()
->route('client.payment_methods.show', $token->hashed_id);
}
if (isset($token->meta->state) && $token->meta->state === 'authorized') { if (isset($token->meta->state) && $token->meta->state === 'authorized') {
return redirect() return redirect()
->route('client.payment_methods.show', $token->hashed_id) ->route('client.payment_methods.show', $token->hashed_id)
->with('message', __('texts.payment_method_verified')); ->with('message', __('texts.payment_method_verified'));
} }
//double check here if we need to show the verification view. if($token->meta->next_action)
$this->stripe->init(); return redirect($token->meta->next_action);
}
$bank_account = Customer::retrieveSource($token->gateway_customer_reference, $token->token, [], $this->stripe->stripe_connect_auth); $bank_account = Customer::retrieveSource($token->gateway_customer_reference, $token->token, [], $this->stripe->stripe_connect_auth);
@ -319,6 +340,9 @@ class ACH
$data['message'] = 'Too many requests made to the API too quickly'; $data['message'] = 'Too many requests made to the API too quickly';
break; break;
case $e instanceof InvalidRequestException: case $e instanceof InvalidRequestException:
return redirect()->route('client.payment_methods.verification', ['payment_method' => $cgt->hashed_id, 'method' => GatewayType::BANK_TRANSFER]);
$data['message'] = 'Invalid parameters were supplied to Stripe\'s API'; $data['message'] = 'Invalid parameters were supplied to Stripe\'s API';
break; break;
case $e instanceof AuthenticationException: case $e instanceof AuthenticationException:

View File

@ -92,7 +92,8 @@ class AccountTransformer extends EntityTransformer
'account_sms_verified' => (bool) $account->account_sms_verified, 'account_sms_verified' => (bool) $account->account_sms_verified,
'has_iap_plan' => (bool)$account->inapp_transaction_id, 'has_iap_plan' => (bool)$account->inapp_transaction_id,
'tax_api_enabled' => (bool) config('services.tax.zip_tax.key') ? true : false, 'tax_api_enabled' => (bool) config('services.tax.zip_tax.key') ? true : false,
'nordigen_enabled' => (bool) (config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key')) ? true : false 'nordigen_enabled' => (bool) (config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key')) ? true : false,
'upload_extensions' => (string) config('ninja.upload_extensions'),
]; ];
} }

169
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "ef338cb66991ec0e28b96643ac5a5c6f", "content-hash": "b5347cd9ca42d75b5c80691e6b64dae5",
"packages": [ "packages": [
{ {
"name": "adrienrn/php-mimetyper", "name": "adrienrn/php-mimetyper",
@ -409,21 +409,22 @@
}, },
{ {
"name": "amphp/parallel", "name": "amphp/parallel",
"version": "v2.2.7", "version": "v2.2.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/amphp/parallel.git", "url": "https://github.com/amphp/parallel.git",
"reference": "ffda869c33c30627b6eb5c25f096882d885681dc" "reference": "efd71b342b64c2e46d904e4eb057ed5ab20f8e2d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/amphp/parallel/zipball/ffda869c33c30627b6eb5c25f096882d885681dc", "url": "https://api.github.com/repos/amphp/parallel/zipball/efd71b342b64c2e46d904e4eb057ed5ab20f8e2d",
"reference": "ffda869c33c30627b6eb5c25f096882d885681dc", "reference": "efd71b342b64c2e46d904e4eb057ed5ab20f8e2d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"amphp/amp": "^3", "amphp/amp": "^3",
"amphp/byte-stream": "^2", "amphp/byte-stream": "^2",
"amphp/cache": "^2",
"amphp/parser": "^1", "amphp/parser": "^1",
"amphp/pipeline": "^1", "amphp/pipeline": "^1",
"amphp/process": "^2", "amphp/process": "^2",
@ -480,7 +481,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/amphp/parallel/issues", "issues": "https://github.com/amphp/parallel/issues",
"source": "https://github.com/amphp/parallel/tree/v2.2.7" "source": "https://github.com/amphp/parallel/tree/v2.2.8"
}, },
"funding": [ "funding": [
{ {
@ -488,7 +489,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-03-16T16:15:46+00:00" "time": "2024-03-19T16:09:34+00:00"
}, },
{ {
"name": "amphp/parser", "name": "amphp/parser",
@ -747,16 +748,16 @@
}, },
{ {
"name": "amphp/socket", "name": "amphp/socket",
"version": "v2.2.4", "version": "v2.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/amphp/socket.git", "url": "https://github.com/amphp/socket.git",
"reference": "4223324c627cc26d44800630411e64856d3344bc" "reference": "acc0a2f65ab498025ba5641f7cce499c4b1ed4b5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/amphp/socket/zipball/4223324c627cc26d44800630411e64856d3344bc", "url": "https://api.github.com/repos/amphp/socket/zipball/acc0a2f65ab498025ba5641f7cce499c4b1ed4b5",
"reference": "4223324c627cc26d44800630411e64856d3344bc", "reference": "acc0a2f65ab498025ba5641f7cce499c4b1ed4b5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -819,7 +820,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/amphp/socket/issues", "issues": "https://github.com/amphp/socket/issues",
"source": "https://github.com/amphp/socket/tree/v2.2.4" "source": "https://github.com/amphp/socket/tree/v2.3.0"
}, },
"funding": [ "funding": [
{ {
@ -827,7 +828,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-02-28T15:56:06+00:00" "time": "2024-03-19T20:01:53+00:00"
}, },
{ {
"name": "amphp/sync", "name": "amphp/sync",
@ -1383,16 +1384,16 @@
}, },
{ {
"name": "aws/aws-sdk-php", "name": "aws/aws-sdk-php",
"version": "3.301.1", "version": "3.301.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/aws/aws-sdk-php.git", "url": "https://github.com/aws/aws-sdk-php.git",
"reference": "0a910d2b35e7087337cdf3569dc9b6ce232aafba" "reference": "6b21e34d24a73ea66492869be90443069034fdb3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/0a910d2b35e7087337cdf3569dc9b6ce232aafba", "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/6b21e34d24a73ea66492869be90443069034fdb3",
"reference": "0a910d2b35e7087337cdf3569dc9b6ce232aafba", "reference": "6b21e34d24a73ea66492869be90443069034fdb3",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1472,9 +1473,9 @@
"support": { "support": {
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
"issues": "https://github.com/aws/aws-sdk-php/issues", "issues": "https://github.com/aws/aws-sdk-php/issues",
"source": "https://github.com/aws/aws-sdk-php/tree/3.301.1" "source": "https://github.com/aws/aws-sdk-php/tree/3.301.3"
}, },
"time": "2024-03-15T18:14:42+00:00 "time": "2024-03-19T18:05:04+00:00"
}, },
{ {
"name": "bacon/bacon-qr-code", "name": "bacon/bacon-qr-code",
@ -3541,16 +3542,16 @@
}, },
{ {
"name": "google/apiclient-services", "name": "google/apiclient-services",
"version": "v0.339.0", "version": "v0.340.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/googleapis/google-api-php-client-services.git", "url": "https://github.com/googleapis/google-api-php-client-services.git",
"reference": "5662d2ab3da41ac0e0e99db221a8c22c511c8f9c" "reference": "c89999ea477da2b0803b2b4f14c9e7fc23b6344a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/5662d2ab3da41ac0e0e99db221a8c22c511c8f9c", "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/c89999ea477da2b0803b2b4f14c9e7fc23b6344a",
"reference": "5662d2ab3da41ac0e0e99db221a8c22c511c8f9c", "reference": "c89999ea477da2b0803b2b4f14c9e7fc23b6344a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3579,9 +3580,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/googleapis/google-api-php-client-services/issues", "issues": "https://github.com/googleapis/google-api-php-client-services/issues",
"source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.339.0" "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.340.0"
}, },
"time": "2024-03-10T01:06:17+00:00" "time": "2024-03-17T00:56:17+00:00"
}, },
{ {
"name": "google/auth", "name": "google/auth",
@ -4403,16 +4404,16 @@
}, },
{ {
"name": "horstoeko/orderx", "name": "horstoeko/orderx",
"version": "v1.0.18", "version": "v1.0.19",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/horstoeko/orderx.git", "url": "https://github.com/horstoeko/orderx.git",
"reference": "0a8535c1cda5574d31e8002e7d03f8bbaafd30ed" "reference": "7b4ed00ca98df5a88c916733d31728a16a3845b4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/horstoeko/orderx/zipball/0a8535c1cda5574d31e8002e7d03f8bbaafd30ed", "url": "https://api.github.com/repos/horstoeko/orderx/zipball/7b4ed00ca98df5a88c916733d31728a16a3845b4",
"reference": "0a8535c1cda5574d31e8002e7d03f8bbaafd30ed", "reference": "7b4ed00ca98df5a88c916733d31728a16a3845b4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -4465,9 +4466,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/horstoeko/orderx/issues", "issues": "https://github.com/horstoeko/orderx/issues",
"source": "https://github.com/horstoeko/orderx/tree/v1.0.18" "source": "https://github.com/horstoeko/orderx/tree/v1.0.19"
}, },
"time": "2024-01-27T09:26:23+00:00" "time": "2024-03-20T04:07:11+00:00"
}, },
{ {
"name": "horstoeko/stringmanagement", "name": "horstoeko/stringmanagement",
@ -4753,23 +4754,23 @@
}, },
{ {
"name": "imdhemy/google-play-billing", "name": "imdhemy/google-play-billing",
"version": "1.5.1", "version": "1.5.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/imdhemy/google-play-billing.git", "url": "https://github.com/imdhemy/google-play-billing.git",
"reference": "bb94f3b6ddb021605815e528f31b8c930c41677c" "reference": "7f2b032354568fa50858e0f6dd25592d975b3979"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/imdhemy/google-play-billing/zipball/bb94f3b6ddb021605815e528f31b8c930c41677c", "url": "https://api.github.com/repos/imdhemy/google-play-billing/zipball/7f2b032354568fa50858e0f6dd25592d975b3979",
"reference": "bb94f3b6ddb021605815e528f31b8c930c41677c", "reference": "7f2b032354568fa50858e0f6dd25592d975b3979",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-json": "*", "ext-json": "*",
"google/auth": "^1.26", "google/auth": "^1.26",
"guzzlehttp/guzzle": "^7.5.1", "guzzlehttp/guzzle": "^7.5.1",
"nesbot/carbon": "^2.66", "nesbot/carbon": "^2.66|^3.0",
"php": ">=8.0" "php": ">=8.0"
}, },
"require-dev": { "require-dev": {
@ -4798,9 +4799,9 @@
"description": "Google Play Billing", "description": "Google Play Billing",
"support": { "support": {
"issues": "https://github.com/imdhemy/google-play-billing/issues", "issues": "https://github.com/imdhemy/google-play-billing/issues",
"source": "https://github.com/imdhemy/google-play-billing/tree/1.5.1" "source": "https://github.com/imdhemy/google-play-billing/tree/1.5.2"
}, },
"time": "2023-12-15T10:25:05+00:00" "time": "2024-03-19T17:56:34+00:00"
}, },
{ {
"name": "imdhemy/laravel-purchases", "name": "imdhemy/laravel-purchases",
@ -7491,16 +7492,16 @@
}, },
{ {
"name": "mollie/mollie-api-php", "name": "mollie/mollie-api-php",
"version": "v2.65.0", "version": "v2.66.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/mollie/mollie-api-php.git", "url": "https://github.com/mollie/mollie-api-php.git",
"reference": "3920816c311ec785f47f160204296d1b7f918da5" "reference": "d7d09ac62a565e818bf49d04acb2f0432da758a9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/mollie/mollie-api-php/zipball/3920816c311ec785f47f160204296d1b7f918da5", "url": "https://api.github.com/repos/mollie/mollie-api-php/zipball/d7d09ac62a565e818bf49d04acb2f0432da758a9",
"reference": "3920816c311ec785f47f160204296d1b7f918da5", "reference": "d7d09ac62a565e818bf49d04acb2f0432da758a9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -7577,9 +7578,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/mollie/mollie-api-php/issues", "issues": "https://github.com/mollie/mollie-api-php/issues",
"source": "https://github.com/mollie/mollie-api-php/tree/v2.65.0" "source": "https://github.com/mollie/mollie-api-php/tree/v2.66.0"
}, },
"time": "2024-01-23T12:39:48+00:00" "time": "2024-03-19T13:33:42+00:00"
}, },
{ {
"name": "moneyphp/money", "name": "moneyphp/money",
@ -11946,16 +11947,16 @@
}, },
{ {
"name": "spatie/laravel-package-tools", "name": "spatie/laravel-package-tools",
"version": "1.16.3", "version": "1.16.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/spatie/laravel-package-tools.git", "url": "https://github.com/spatie/laravel-package-tools.git",
"reference": "59db18c2e20d49a0b6d447bb1c654f6c123beb9e" "reference": "ddf678e78d7f8b17e5cdd99c0c3413a4a6592e53"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/59db18c2e20d49a0b6d447bb1c654f6c123beb9e", "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/ddf678e78d7f8b17e5cdd99c0c3413a4a6592e53",
"reference": "59db18c2e20d49a0b6d447bb1c654f6c123beb9e", "reference": "ddf678e78d7f8b17e5cdd99c0c3413a4a6592e53",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -11994,7 +11995,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/spatie/laravel-package-tools/issues", "issues": "https://github.com/spatie/laravel-package-tools/issues",
"source": "https://github.com/spatie/laravel-package-tools/tree/1.16.3" "source": "https://github.com/spatie/laravel-package-tools/tree/1.16.4"
}, },
"funding": [ "funding": [
{ {
@ -12002,7 +12003,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-03-07T07:35:57+00:00" "time": "2024-03-20T07:29:11+00:00"
}, },
{ {
"name": "spatie/php-structure-discoverer", "name": "spatie/php-structure-discoverer",
@ -16568,16 +16569,16 @@
}, },
{ {
"name": "composer/pcre", "name": "composer/pcre",
"version": "3.1.2", "version": "3.1.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/composer/pcre.git", "url": "https://github.com/composer/pcre.git",
"reference": "4775f35b2d70865807c89d32c8e7385b86eb0ace" "reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/composer/pcre/zipball/4775f35b2d70865807c89d32c8e7385b86eb0ace", "url": "https://api.github.com/repos/composer/pcre/zipball/5b16e25a5355f1f3afdfc2f954a0a80aec4826a8",
"reference": "4775f35b2d70865807c89d32c8e7385b86eb0ace", "reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -16619,7 +16620,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/composer/pcre/issues", "issues": "https://github.com/composer/pcre/issues",
"source": "https://github.com/composer/pcre/tree/3.1.2" "source": "https://github.com/composer/pcre/tree/3.1.3"
}, },
"funding": [ "funding": [
{ {
@ -16635,7 +16636,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-03-07T15:38:35+00:00" "time": "2024-03-19T10:26:25+00:00"
}, },
{ {
"name": "composer/semver", "name": "composer/semver",
@ -16918,16 +16919,16 @@
}, },
{ {
"name": "friendsofphp/php-cs-fixer", "name": "friendsofphp/php-cs-fixer",
"version": "v3.51.0", "version": "v3.52.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "127fa74f010da99053e3f5b62672615b72dd6efd" "reference": "6e77207f0d851862ceeb6da63e6e22c01b1587bc"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/127fa74f010da99053e3f5b62672615b72dd6efd", "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/6e77207f0d851862ceeb6da63e6e22c01b1587bc",
"reference": "127fa74f010da99053e3f5b62672615b72dd6efd", "reference": "6e77207f0d851862ceeb6da63e6e22c01b1587bc",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -16998,7 +16999,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.51.0" "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.52.1"
}, },
"funding": [ "funding": [
{ {
@ -17006,7 +17007,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-02-28T19:50:06+00:00" "time": "2024-03-19T21:02:43+00:00"
}, },
{ {
"name": "hamcrest/hamcrest-php", "name": "hamcrest/hamcrest-php",
@ -17061,25 +17062,25 @@
}, },
{ {
"name": "laracasts/cypress", "name": "laracasts/cypress",
"version": "3.0.1", "version": "3.0.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laracasts/cypress.git", "url": "https://github.com/laracasts/cypress.git",
"reference": "dd4e61188d4edaf65ffa18851a5df38d0fa0619a" "reference": "449f9d69da75091c77327093e5727a5c739a4cf8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laracasts/cypress/zipball/dd4e61188d4edaf65ffa18851a5df38d0fa0619a", "url": "https://api.github.com/repos/laracasts/cypress/zipball/449f9d69da75091c77327093e5727a5c739a4cf8",
"reference": "dd4e61188d4edaf65ffa18851a5df38d0fa0619a", "reference": "449f9d69da75091c77327093e5727a5c739a4cf8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0", "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0",
"php": "^8.0" "php": "^8.0"
}, },
"require-dev": { "require-dev": {
"orchestra/testbench": "^6.0|^7.0|^8.0", "orchestra/testbench": "^6.0|^7.0|^8.0|^9.0",
"phpunit/phpunit": "^8.0|^9.5.10", "phpunit/phpunit": "^8.0|^9.5.10|^10.5",
"spatie/laravel-ray": "^1.29" "spatie/laravel-ray": "^1.29"
}, },
"type": "library", "type": "library",
@ -17114,9 +17115,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/laracasts/cypress/issues", "issues": "https://github.com/laracasts/cypress/issues",
"source": "https://github.com/laracasts/cypress/tree/3.0.1" "source": "https://github.com/laracasts/cypress/tree/3.0.2"
}, },
"time": "2023-02-16T20:00:16+00:00" "time": "2024-03-19T14:07:37+00:00"
}, },
{ {
"name": "larastan/larastan", "name": "larastan/larastan",
@ -17288,16 +17289,16 @@
}, },
{ {
"name": "mockery/mockery", "name": "mockery/mockery",
"version": "1.6.9", "version": "1.6.10",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/mockery/mockery.git", "url": "https://github.com/mockery/mockery.git",
"reference": "0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06" "reference": "47065d1be1fa05def58dc14c03cf831d3884ef0b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/mockery/mockery/zipball/0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06", "url": "https://api.github.com/repos/mockery/mockery/zipball/47065d1be1fa05def58dc14c03cf831d3884ef0b",
"reference": "0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06", "reference": "47065d1be1fa05def58dc14c03cf831d3884ef0b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -17309,8 +17310,8 @@
"phpunit/phpunit": "<8.0" "phpunit/phpunit": "<8.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^8.5 || ^9.6.10", "phpunit/phpunit": "^8.5 || ^9.6.17",
"symplify/easy-coding-standard": "^12.0.8" "symplify/easy-coding-standard": "^12.1.14"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
@ -17367,7 +17368,7 @@
"security": "https://github.com/mockery/mockery/security/advisories", "security": "https://github.com/mockery/mockery/security/advisories",
"source": "https://github.com/mockery/mockery" "source": "https://github.com/mockery/mockery"
}, },
"time": "2023-12-10T02:24:34+00:00" "time": "2024-03-19T16:15:45+00:00"
}, },
{ {
"name": "myclabs/deep-copy", "name": "myclabs/deep-copy",
@ -17732,16 +17733,16 @@
}, },
{ {
"name": "phpstan/phpstan", "name": "phpstan/phpstan",
"version": "1.10.62", "version": "1.10.63",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpstan.git", "url": "https://github.com/phpstan/phpstan.git",
"reference": "cd5c8a1660ed3540b211407c77abf4af193a6af9" "reference": "ad12836d9ca227301f5fb9960979574ed8628339"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/cd5c8a1660ed3540b211407c77abf4af193a6af9", "url": "https://api.github.com/repos/phpstan/phpstan/zipball/ad12836d9ca227301f5fb9960979574ed8628339",
"reference": "cd5c8a1660ed3540b211407c77abf4af193a6af9", "reference": "ad12836d9ca227301f5fb9960979574ed8628339",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -17790,7 +17791,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-03-13T12:27:20+00:00" "time": "2024-03-18T16:53:53+00:00"
}, },
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",
@ -19704,5 +19705,5 @@
"platform-dev": { "platform-dev": {
"php": "^8.1|^8.2" "php": "^8.1|^8.2"
}, },
"plugin-api-version": "2.6.0" "plugin-api-version": "2.3.0"
} }

View File

@ -1,98 +0,0 @@
<?php
return [
/*
* This value will be sent along with your trace.
*
* When set to `null`, the app name will be used
*/
'default_trace_name' => null,
/*
* A driver is responsible for transmitting any measurements.
*/
'drivers' => [
Spatie\OpenTelemetry\Drivers\HttpDriver::class => [
'url' => 'http://localhost:9411/api/v2/spans',
// 'url' => 'http://localhost:4318/v1/traces'
],
],
/*
* This class determines if your measurements should actually be sent
* to the reporting drivers.
*/
'sampler' => Spatie\OpenTelemetry\Support\Samplers\AlwaysSampler::class,
/*
* Tags can be added to any measurement. These classes will determine the
* values of the tags when a new trace starts.
*/
'trace_tag_providers' => [
\Spatie\OpenTelemetry\Support\TagProviders\DefaultTagsProvider::class,
],
/*
* Tags can be added to any measurement. These classes will determine the
* values of the tags when a new span starts.
*/
'span_tag_providers' => [
],
'queue' => [
/*
* When enabled, any measurements (spans) you make in a queued job that implements
* `TraceAware` will automatically belong to the same trace that was
* started in the process that dispatched the job.
*/
'make_queue_trace_aware' => true,
/*
* When this is set to `false`, only jobs the implement
* `TraceAware` will be trace aware.
*/
'all_jobs_are_trace_aware_by_default' => true,
/*
* When set to `true` all jobs will
* automatically start a span.
*/
'all_jobs_auto_start_a_span' => true,
/*
* These jobs will be trace aware even if they don't
* implement the `TraceAware` interface.
*/
'trace_aware_jobs' => [
],
/*
* These jobs will never trace aware, regardless of `all_jobs_are_trace_aware_by_default`.
*/
'not_trace_aware_jobs' => [
],
],
/*
* These actions can be overridden to have fine-grained control over how
* the package performs certain tasks.
*
* In most cases, you should use the default values.
*/
'actions' => [
'make_queue_trace_aware' => Spatie\OpenTelemetry\Actions\MakeQueueTraceAwareAction::class,
],
/*
* This class determines how the package measures time.
*/
'stopwatch' => Spatie\OpenTelemetry\Support\Stopwatch::class,
/*
* This class generates IDs for traces and spans.
*/
'id_generator' => Spatie\OpenTelemetry\Support\IdGenerator::class,
];

View File

@ -62,6 +62,127 @@ class PaymentTest extends TestCase
); );
} }
public function testClientIdValidation()
{
$p = Payment::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $this->client->id,
'status_id' => Payment::STATUS_COMPLETED,
'amount' => 100
]);
$data = [
'date' => now()->addDay()->format('Y-m-d')
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->putJson('/api/v1/payments/'.$p->hashed_id, $data);
$response->assertStatus(200);
$data = [
'date' => now()->addDay()->format('Y-m-d'),
'client_id' => $this->client->hashed_id,
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->putJson('/api/v1/payments/'.$p->hashed_id, $data);
$response->assertStatus(200);
$c = Client::factory()->create([
'user_id' => $this->user->id,
'company_id' => $this->company->id,
]);
$data = [
'date' => now()->addDay()->format('Y-m-d'),
'client_id' => $c->hashed_id,
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->putJson('/api/v1/payments/'.$p->hashed_id, $data);
$response->assertStatus(422);
}
public function testNegativeAppliedAmounts()
{
$p = Payment::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $this->client->id,
'status_id' => Payment::STATUS_COMPLETED,
'amount' => 100
]);
$i = Invoice::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $this->client->id,
'status_id' => Invoice::STATUS_SENT,
]);
$i->calc()->getInvoice()->service()->markSent()->save();
$this->assertGreaterThan(0, $i->balance);
$data = [
'amount' => 5,
'client_id' => $this->client->hashed_id,
'invoices' => [
[
'invoice_id' => $this->invoice->hashed_id,
'amount' => 5,
],
],
'date' => '2020/12/11',
'idempotency_key' => \Illuminate\Support\Str::uuid()->toString()
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/payments/', $data);
$response->assertStatus(200);
$payment_id = $response->json()['data']['id'];
$payment = Payment::find($this->decodePrimaryKey($payment_id));
$this->assertNotNull($payment);
$data = [
'client_id' => $this->client->hashed_id,
'invoices' => [
[
'invoice_id' => $this->invoice->hashed_id,
'amount' => -5,
],
],
'date' => '2020/12/11',
'idempotency_key' => \Illuminate\Support\Str::uuid()->toString()
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->putJson('/api/v1/payments/'.$payment_id, $data);
$response->assertStatus(422);
}
public function testCompletedPaymentLogic() public function testCompletedPaymentLogic()
{ {
@ -1395,8 +1516,9 @@ class PaymentTest extends TestCase
$invoice_calc = new InvoiceSum($invoice); $invoice_calc = new InvoiceSum($invoice);
$invoice_calc->build(); $invoice_calc->build();
$invoice = $invoice_calc->getInvoice(); $invoice = $invoice_calc->getInvoice()->service()->markSent()->save();
$invoice->save(); $this->assertEquals(10, $invoice->amount);
$this->assertEquals(10, $invoice->balance);
$credit = CreditFactory::create($this->company->id, $this->user->id); $credit = CreditFactory::create($this->company->id, $this->user->id);
$credit->client_id = $client->id; $credit->client_id = $client->id;
@ -1410,8 +1532,10 @@ class PaymentTest extends TestCase
$credit_calc = new InvoiceSum($credit); $credit_calc = new InvoiceSum($credit);
$credit_calc->build(); $credit_calc->build();
$credit = $credit_calc->getCredit(); $credit = $credit_calc->getCredit()->service()->markSent()->save(); //$10 credit
$credit->save(); //$10 credit
$this->assertEquals(10, $credit->amount);
$this->assertEquals(10, $credit->balance);
$data = [ $data = [
'amount' => $invoice->amount, 'amount' => $invoice->amount,

View File

@ -163,17 +163,10 @@ class CreditPaymentTest extends TestCase
'date' => '2019/12/12', 'date' => '2019/12/12',
]; ];
$response = false;
try {
$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,
])->post('/api/v1/payments/', $data); ])->postJson('/api/v1/payments/', $data);
} catch (ValidationException $e) {
$message = json_decode($e->validator->getMessageBag(), 1);
nlog($e->validator->getMessageBag());
}
$response->assertStatus(200); $response->assertStatus(200);

View File

@ -11,22 +11,24 @@
namespace Tests\Feature; namespace Tests\Feature;
use App\Factory\ClientFactory; use Tests\TestCase;
use App\Factory\CreditFactory; use App\Models\Client;
use App\Factory\InvoiceFactory;
use App\Helpers\Invoice\InvoiceSum;
use App\Models\ClientContact;
use App\Models\Credit; use App\Models\Credit;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Payment; use App\Models\Payment;
use Tests\MockAccountData;
use App\Models\ClientContact;
use App\Factory\ClientFactory;
use App\Factory\CreditFactory;
use App\DataMapper\InvoiceItem;
use App\Factory\InvoiceFactory;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use App\Helpers\Invoice\InvoiceSum;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Support\Facades\Session; use Illuminate\Support\Facades\Session;
use Illuminate\Validation\ValidationException; use Illuminate\Validation\ValidationException;
use Tests\MockAccountData; use Illuminate\Routing\Middleware\ThrottleRequests;
use Tests\TestCase; use Illuminate\Foundation\Testing\DatabaseTransactions;
/** /**
* @test * @test
@ -59,6 +61,132 @@ class RefundTest extends TestCase
// $this->withoutExceptionHandling(); // $this->withoutExceptionHandling();
} }
public function testRefundAndAppliedAmounts()
{
$data = [
'amount' => 500,
'client_id' => $this->client->hashed_id,
'date' => '2020/12/12',
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/payments', $data);
$response->assertStatus(200);
$arr = $response->json();
$payment_id = $arr['data']['id'];
$item = new InvoiceItem;
$item->cost = 300;
$item->quantity = 1;
$i = Invoice::factory()
->create([
'user_id' => $this->user->id,
'company_id' => $this->company->id,
'client_id' => $this->client->id,
'line_items' => [$item],
'discount' => 0,
'tax_name1' => '',
'tax_name2' => '',
'tax_name3' => '',
'tax_rate1' => 0,
'tax_rate2' => 0,
'tax_rate3' => 0,
]);
$i->calc()->getInvoice();
$i->service()->markSent()->save();
$this->assertEquals(300, $i->balance);
$data = [
'client_id' => $this->client->hashed_id,
'invoices' => [
[
'invoice_id' => $i->hashed_id,
'amount' => 300
],
]
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->putJson('/api/v1/payments/'.$payment_id, $data);
$response->assertStatus(200);
$i = $i->fresh();
$this->assertEquals(0, $i->balance);
$payment = Payment::find($this->decodePrimaryKey($payment_id));
$this->assertNotNull($payment);
$this->assertEquals(500, $payment->amount);
$this->assertEquals(300, $payment->applied);
$this->assertEquals(0, $payment->refunded);
$data = [
'id' => $this->encodePrimaryKey($payment->id),
'invoices' => [
[
'invoice_id' => $i->hashed_id,
'amount' => $i->amount,
],
],
'date' => '2020/12/12',
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/payments/refund', $data);
$response->assertStatus(200);
$payment = $payment->fresh();
$i = $i->fresh();
$this->assertEquals(300, $payment->refunded);
$this->assertEquals(300, $i->balance);
$this->assertEquals(2, $i->status_id);
$data = [
'client_id' => $this->client->hashed_id,
'invoices' => [
[
'invoice_id' => $i->hashed_id,
'amount' => 200
],
]
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->putJson('/api/v1/payments/'.$payment_id, $data);
$response->assertStatus(200);
$payment = $payment->fresh();
$i = $i->fresh();
$this->assertEquals(300, $payment->refunded);
$this->assertEquals(100, $i->balance);
$this->assertEquals(3, $i->status_id);
$this->assertEquals(500, $payment->applied);
}
/** /**
* Test that a simple payment of $50 * Test that a simple payment of $50
* is able to be refunded. * is able to be refunded.
@ -552,29 +680,22 @@ class RefundTest extends TestCase
$this->invoice = InvoiceFactory::create($this->company->id, $this->user->id); //stub the company and user_id $this->invoice = InvoiceFactory::create($this->company->id, $this->user->id); //stub the company and user_id
$this->invoice->client_id = $client->id; $this->invoice->client_id = $client->id;
$this->invoice->status_id = Invoice::STATUS_SENT;
$this->invoice->line_items = $this->buildLineItems(); $this->invoice->line_items = $this->buildLineItems();
$this->invoice->uses_inclusive_taxes = false; $this->invoice->uses_inclusive_taxes = false;
$this->invoice->client_id = $client->id; $this->invoice->client_id = $client->id;
$this->invoice->save(); $this->invoice->calc()->getInvoice()->service()->markSent()->save();
$invoice_calc = new InvoiceSum($this->invoice);
$invoice_calc->build();
$this->invoice = $invoice_calc->getInvoice();
$this->invoice->save();
$this->credit = CreditFactory::create($this->company->id, $this->user->id); $this->credit = CreditFactory::create($this->company->id, $this->user->id);
$this->credit->client_id = $client->id; $this->credit->client_id = $client->id;
$this->credit->status_id = 2;
$this->credit->line_items = $this->buildLineItems(); $this->credit->line_items = $this->buildLineItems();
$this->credit->amount = 10;
$this->credit->balance = 10;
$this->credit->uses_inclusive_taxes = false; $this->credit->uses_inclusive_taxes = false;
$this->credit->save(); $this->credit->date = now()->format('Y-m-d');
$this->credit->due_date = now()->addMonth()->format('Y-m-d');
$this->credit->calc()->getCredit()->service()->markSent()->save();
$this->assertEquals(10, $this->credit->amount);
$this->assertEquals(10, $this->credit->balance);
$data = [ $data = [
'amount' => 50, 'amount' => 50,
@ -656,26 +777,62 @@ class RefundTest extends TestCase
public function testRefundsWhenCreditsArePresent() public function testRefundsWhenCreditsArePresent()
{ {
$cl = Client::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
]);
nlog($cl->id);
$i = Invoice::factory()->create([ $i = Invoice::factory()->create([
'company_id' => $this->company->id, 'company_id' => $this->company->id,
'user_id' => $this->user->id, 'user_id' => $this->user->id,
'client_id' => $this->client->id, 'client_id' => $cl->id,
'status_id' => Invoice::STATUS_SENT, 'status_id' => Invoice::STATUS_SENT,
'amount' => 1000, 'amount' => 1000,
'balance' => 1000, 'balance' => 1000,
]); ]);
$item = new InvoiceItem;
$item->cost = 1000;
$item->quantity = 1;
$i->line_items = [$item];
$i->service()->markSent()->save();
$this->assertEquals(1000, $i->balance);
$c = Credit::factory()->create([ $c = Credit::factory()->create([
'company_id' => $this->company->id, 'company_id' => $this->company->id,
'user_id' => $this->user->id, 'user_id' => $this->user->id,
'client_id' => $this->client->id, 'client_id' => $cl->id,
'status_id' => Invoice::STATUS_SENT, 'status_id' => Invoice::STATUS_SENT,
'amount' => 100, 'amount' => 100,
'balance' => 100, 'balance' => 100,
'date' => now()->format('Y-m-d'),
'due_date' => now()->addMonth()->format('Y-m-d'),
]); ]);
$item = new InvoiceItem();
$item->cost = 100;
$item->quantity = 1;
$c->line_items = [$item];
$c->service()->markSent()->save();
$this->assertEquals(100, $c->balance);
$this->assertNotNull($c);
$this->assertEquals(2, $c->status_id);
$this->assertEquals($cl->id, $c->client_id);
$this->assertEquals($cl->id, $i->client_id);
$data = [ $data = [
'client_id' => $this->client->hashed_id, 'amount' => 900,
'client_id' => $cl->hashed_id,
'invoices' => [ 'invoices' => [
[ [
'invoice_id' => $i->hashed_id, 'invoice_id' => $i->hashed_id,
@ -706,7 +863,7 @@ class RefundTest extends TestCase
$refund = [ $refund = [
'id' => $payment_id, 'id' => $payment_id,
'client_id' => $this->client->hashed_id, 'client_id' => $cl->hashed_id,
'amount' => 10, 'amount' => 10,
'date' => now()->format('Y-m-d'), 'date' => now()->format('Y-m-d'),
'invoices' => [ 'invoices' => [