1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-05 18:52:44 +01:00

Working on Payments

This commit is contained in:
David Bomba 2019-05-03 17:57:55 +10:00
parent 9f9f3439b4
commit ac05fc6ff6
15 changed files with 604 additions and 9 deletions

View File

@ -0,0 +1,35 @@
<?php
namespace App\Factory;
use App\DataMapper\ClientSettings;
use App\DataMapper\CompanySettings;
use App\Models\Payment;
use Illuminate\Support\Facades\Log;
class PaymentFactory
{
public static function create(int $company_id, int $user_id) :Payment
{
$payment = new Payment();
$payment->company_id = $company_id;
$payment->user_id = $user_id;
$payment->client_id = 0;
$payment->client_contact_id = null;
$payment->invitation_id = null;
$payment->account_gateway_id = null;
$payment->payment_type_id = null;
$payment->is_deleted = false;
$payment->amount = 0;
$payment->payment_date = null;
$payment->transaction_reference = null;
$payment->payer_id = null;
$payment->invoice_id = 0;
return $payment;
}
}

View File

@ -0,0 +1,111 @@
<?php
namespace App\Filters;
use App\Models\User;
use Illuminate\Database\Eloquent\Builder;
/**
* PaymentFilters
*/
class PaymentFilters extends QueryFilters
{
/**
* Filter based on search text
*
* @param string query filter
* @return Illuminate\Database\Query\Builder
* @deprecated
*
*/
public function filter(string $filter = '') : Builder
{
if(strlen($filter) == 0)
return $this->builder;
return $this->builder->where(function ($query) use ($filter) {
$query->where('payments.custom_value1', 'like', '%'.$filter.'%')
->orWhere('payments.custom_value2', 'like' , '%'.$filter.'%')
->orWhere('payments.custom_value3', 'like' , '%'.$filter.'%')
->orWhere('payments.custom_value4', 'like' , '%'.$filter.'%');
});
}
/**
* Filters the list based on the status
* archived, active, deleted
*
* @param string filter
* @return Illuminate\Database\Query\Builder
*/
public function status(string $filter = '') : Builder
{
if(strlen($filter) == 0)
return $this->builder;
$table = 'payments';
$filters = explode(',', $filter);
return $this->builder->where(function ($query) use ($filters, $table) {
$query->whereNull($table . '.id');
if (in_array(parent::STATUS_ACTIVE, $filters)) {
$query->orWhereNull($table . '.deleted_at');
}
if (in_array(parent::STATUS_ARCHIVED, $filters)) {
$query->orWhere(function ($query) use ($table) {
$query->whereNotNull($table . '.deleted_at');
if (! in_array($table, ['users'])) {
$query->where($table . '.is_deleted', '=', 0);
}
});
}
if (in_array(parent::STATUS_DELETED, $filters)) {
$query->orWhere($table . '.is_deleted', '=', 1);
}
});
}
/**
* Sorts the list based on $sort
*
* @param string sort formatted as column|asc
* @return Illuminate\Database\Query\Builder
*/
public function sort(string $sort) : Builder
{
$sort_col = explode("|", $sort);
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
}
/**
* Returns the base query
*
* @param int company_id
* @return Illuminate\Database\Query\Builder
* @deprecated
*/
public function baseQuery(int $company_id, User $user) : Builder
{
}
/**
* Filters the query by the users company ID
*
* @param $company_id The company Id
* @return Illuminate\Database\Query\Builder
*/
public function entityFilter()
{
return $this->builder->whereCompanyId(auth()->user()->company()->id);
}
}

View File

@ -3,6 +3,7 @@
namespace App\Http\Controllers;
use App\Filters\PaymentFilters;
use App\Http\Requests\Payment\ActionPaymentRequest;
use App\Http\Requests\Payment\CreatePaymentRequest;
use App\Http\Requests\Payment\DestroyPaymentRequest;
@ -13,6 +14,7 @@ use App\Http\Requests\Payment\UpdatePaymentRequest;
use App\Jobs\Entity\ActionEntity;
use App\Models\Payment;
use App\Repositories\BaseRepository;
use App\Transformers\PaymentTransformer;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Request;
@ -28,14 +30,13 @@ class PaymentController extends BaseController
protected $entity_type = Payment::class;
protected $entity_transformer = Paymentransformer::class;
protected $entity_transformer = PaymentTransformer::class;
/**
* @var PaymentRepository
*/
protected $payment_repo;
protected $base_repo;
/**
* PaymentController constructor.
@ -61,7 +62,7 @@ class PaymentController extends BaseController
public function index(PaymentFilters $filters)
{
$payments = Invoice::filter($filters);
$payments = Payment::filter($filters);
return $this->listResponse($payments);

View File

@ -0,0 +1,21 @@
<?php
namespace App\Http\Requests\Payment;
use App\Http\Requests\Request;
use App\Models\Payment;
class ActionPaymentRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize() : bool
{
return auth()->user()->can('edit', $this->payment);
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace App\Http\Requests\Payment;
use App\Http\Requests\Request;
use App\Models\Payment;
class CreatePaymentRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize() : bool
{
return auth()->user()->can('create', Payment::class);
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace App\Http\Requests\Payment;
use App\Http\Requests\Request;
use App\Models\Payment;
class DestroyPaymentRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize() : bool
{
return auth()->user()->can('edit', $this->payment);
}
}

View File

@ -0,0 +1,40 @@
<?php
namespace App\Http\Requests\Payment;
use App\Http\Requests\Request;
use App\Models\Payment;
class EditPaymentRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return auth()->user()->can('edit', $this->payment);
}
public function rules()
{
$rules = [];
return $rules;
}
public function sanitize()
{
$input = $this->all();
//$input['id'] = $this->encodePrimaryKey($input['id']);
//$this->replace($input);
return $this->all();
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace App\Http\Requests\Payment;
use App\Http\Requests\Request;
use App\Models\Payment;
class ShowPaymentRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize() : bool
{
return auth()->user()->can('view', $this->payment);
}
}

View File

@ -0,0 +1,41 @@
<?php
namespace App\Http\Requests\Payment;
use App\Http\Requests\Request;
use App\Models\Payment;
class StorePaymentRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize() : bool
{
return auth()->user()->can('create', Payment::class);
}
public function rules()
{
return [
'documents' => 'mimes:png,ai,svg,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx',
];
}
public function sanitize()
{
//do post processing of Payment request here, ie. Payment_items
}
public function messages()
{
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace App\Http\Requests\Payment;
use App\Http\Requests\Request;
use Illuminate\Validation\Rule;
class UpdatePaymentRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize() : bool
{
return auth()->user()->can('edit', $this->payment);
}
public function rules()
{
return [
'documents' => 'mimes:png,ai,svg,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx',
];
}
}

View File

@ -2,27 +2,32 @@
namespace App\Models;
use App\Models\Filterable;
use App\Utils\Traits\MakesHash;
use Illuminate\Database\Eloquent\Model;
class Payment extends BaseModel
{
use MakesHash;
use Filterable;
protected $guarded = [
'id',
];
protected $appends = ['payment_id'];
public function getRouteKeyName()
public function client()
{
return 'payment_id';
return $this->belongsTo(Client::class);
}
public function getPaymentIdAttribute()
public function company()
{
return $this->encodePrimaryKey($this->id);
return $this->belongsTo(Company::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function documents()

View File

@ -0,0 +1,25 @@
<?php
namespace App\Policies;
use App\Models\Payment;
use App\Models\User;
/**
* Class PaymentPolicy
* @package App\Policies
*/
class PaymentPolicy extends EntityPolicy
{
/**
* Checks if the user has create permissions
*
* @param User $user
* @return bool
*/
public function create(User $user) : bool
{
return $user->isAdmin() || $user->hasPermission('create_payment');
}
}

View File

@ -4,12 +4,14 @@ namespace App\Providers;
use App\Models\Client;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\Product;
use App\Models\Quote;
use App\Models\RecurringInvoice;
use App\Models\User;
use App\Policies\ClientPolicy;
use App\Policies\InvoicePolicy;
use App\Policies\PaymentPolicy;
use App\Policies\ProductPolicy;
use App\Policies\QuotePolicy;
use App\Policies\RecurringInvoicePolicy;
@ -28,6 +30,7 @@ class AuthServiceProvider extends ServiceProvider
Client::class => ClientPolicy::class,
Product::class => ProductPolicy::class,
Invoice::class => InvoicePolicy::class,
Payment::class => PaymentPolicy::class,
RecurringInvoice::class => RecurringInvoicePolicy::class,
Quote::class => QuotePolicy::class,
User::class => UserPolicy::class,

View File

@ -0,0 +1,17 @@
<?php
use App\DataMapper\ClientSettings;
use App\DataMapper\CompanySettings;
use Faker\Generator as Faker;
$factory->define(App\Models\Payment::class, function (Faker $faker) {
return [
'id_deleted' => false,
'amount' => $faker->numberBetween(1,10),
'payment_date' => $faker->date(),
'transaction_reference' => $faker->text(10),
'invoice_id' => $faker->numberBetween(1,10)
];
});

View File

@ -0,0 +1,202 @@
<?php
namespace Tests\Feature;
use App\DataMapper\ClientSettings;
use App\DataMapper\CompanySettings;
use App\Models\Account;
use App\Models\Client;
use App\Models\Payment;
use App\Utils\Traits\MakesHash;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Session;
use Tests\TestCase;
/**
* @test
* @covers App\Http\Controllers\PaymentController
*/
class PaymentTest extends TestCase
{
use MakesHash;
use DatabaseTransactions;
public function setUp() :void
{
parent::setUp();
Session::start();
$this->faker = \Faker\Factory::create();
Model::reguard();
}
public function testPaymentList()
{
$data = [
'first_name' => $this->faker->firstName,
'last_name' => $this->faker->lastName,
'email' => $this->faker->unique()->safeEmail,
'password' => 'ALongAndBrilliantPassword123',
'_token' => csrf_token(),
'privacy_policy' => 1,
'terms_of_service' => 1
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
])->post('/api/v1/signup', $data);
$acc = $response->json();
$account = Account::find($this->decodePrimaryKey($acc['data']['id']));
$company_token = $account->default_company->tokens()->first();
$token = $company_token->token;
$company = $company_token->company;
$user = $company_token->user;
$this->assertNotNull($company_token);
$this->assertNotNull($token);
$this->assertNotNull($user);
$this->assertNotNull($company);
$this->assertNotNull($user->tokens->first()->company);
factory(\App\Models\Client::class, 1)->create(['user_id' => $user->id, 'company_id' => $company->id])->each(function ($c) use ($user, $company){
factory(\App\Models\ClientContact::class,1)->create([
'user_id' => $user->id,
'client_id' => $c->id,
'company_id' => $company->id,
'is_primary' => 1
]);
factory(\App\Models\ClientContact::class,1)->create([
'user_id' => $user->id,
'client_id' => $c->id,
'company_id' => $company->id
]);
});
$client = Client::all()->first();
factory(\App\Models\Payment::class, 1)->create(['user_id' => $user->id, 'company_id' => $company->id, 'client_id' => $client->id]);
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $token,
])->get('/api/v1/payments');
$response->assertStatus(200);
}
public function testPaymentRESTEndPoints()
{
$data = [
'first_name' => $this->faker->firstName,
'last_name' => $this->faker->lastName,
'email' => $this->faker->unique()->safeEmail,
'password' => 'ALongAndBrilliantPassword123',
'_token' => csrf_token(),
'privacy_policy' => 1,
'terms_of_service' => 1
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
])->post('/api/v1/signup', $data);
$acc = $response->json();
$account = Account::find($this->decodePrimaryKey($acc['data']['id']));
$company_token = $account->default_company->tokens()->first();
$token = $company_token->token;
$company = $company_token->company;
$user = $company_token->user;
$this->assertNotNull($company_token);
$this->assertNotNull($token);
$this->assertNotNull($user);
$this->assertNotNull($company);
$this->assertNotNull($user->tokens->first()->company);
factory(\App\Models\Client::class, 1)->create(['user_id' => $user->id, 'company_id' => $company->id])->each(function ($c) use ($user, $company){
factory(\App\Models\ClientContact::class,1)->create([
'user_id' => $user->id,
'client_id' => $c->id,
'company_id' => $company->id,
'is_primary' => 1
]);
factory(\App\Models\ClientContact::class,1)->create([
'user_id' => $user->id,
'client_id' => $c->id,
'company_id' => $company->id
]);
});
$client = Client::all()->first();
factory(\App\Models\Payment::class, 1)->create(['user_id' => $user->id, 'company_id' => $company->id, 'client_id' => $client->id]);
$Payment = Payment::where('user_id',$user->id)->first();
$Payment->settings = $client->getMergedSettings();
$Payment->save();
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $token,
])->get('/api/v1/payments/'.$this->encodePrimaryKey($Payment->id));
$response->assertStatus(200);
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $token,
])->get('/api/v1/payments/'.$this->encodePrimaryKey($Payment->id).'/edit');
$response->assertStatus(200);
$Payment_update = [
'amount' => 10
];
$this->assertNotNull($Payment);
$this->assertNotNull($Payment->settings);
$this->assertTrue(property_exists($Payment->settings, 'custom_taxes1'));
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $token,
])->put('/api/v1/payments/'.$this->encodePrimaryKey($Payment->id), $Payment_update)
->assertStatus(200);
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $token,
])->delete('/api/v1/payments/'.$this->encodePrimaryKey($Payment->id));
$response->assertStatus(200);
}
}