Skip to content

Commit

Permalink
feat: add transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
halivert committed Jul 6, 2023
1 parent 016ee4b commit 3bc2174
Show file tree
Hide file tree
Showing 9 changed files with 391 additions and 0 deletions.
64 changes: 64 additions & 0 deletions app/API/Transaction/Transaction.php
@@ -0,0 +1,64 @@
<?php

namespace App\API\Transaction;

use App\API\CreditCard\CreditCard;
use App\Models\User;
use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOneThrough;

class Transaction extends Model
{
use HasFactory, HasUuids;

protected $fillable = [
'concept',
'datetime',
'amount',
'deadline_months',
'commission',
'interest_rate',
'parent_transaction_id',
];

protected $casts = [
'amount' => 'decimal:4',
'deadline_months' => 'integer',
'commission' => 'decimal:4',
'commission' => 'decimal:2',
];

public function credit_card(): BelongsTo
{
return $this->belongsTo(CreditCard::class);
}

public function user(): HasOneThrough
{
return $this->hasOneThrough(
User::class,
CreditCard::class,
'id',
'id',
'credit_card_id',
'user_id'
);
}

public function parent_transaction(): BelongsTo
{
return $this->belongsTo(Transaction::class);
}

/**
* Create a new factory instance for the model.
*/
protected static function newFactory(): Factory
{
return TransactionFactory::new();
}
}
42 changes: 42 additions & 0 deletions app/API/Transaction/TransactionFactory.php
@@ -0,0 +1,42 @@
<?php

namespace App\API\Transaction;

use App\API\CreditCard\CreditCard;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\API\Transaction\Transaction>
*/
class TransactionFactory extends Factory
{
protected $model = Transaction::class;

/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'credit_card_id' => CreditCard::factory(),
'concept' => fake()->paragraph(4),
'datetime' => fake()->dateTimeThisYear(),
'amount' => fake()->randomFloat(2, 1, 10000),
];
}

/**
* Indicate the transaction has a deadline months, commission and
* interest rate
*/
public function withDeadlineMonths(): static
{
return $this->state(fn () => [
'commission' => fake()->randomFloat(2, 0, 1000),
'deadline_months' => fake()->numberBetween(0, 24),
'interest_rate' => fake()->randomFloat(2, 0, 100),
]);
}
}
61 changes: 61 additions & 0 deletions app/API/Transaction/TransactionPolicy.php
@@ -0,0 +1,61 @@
<?php

namespace App\API\Transaction;

use App\API\CreditCard\CreditCard;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
use Illuminate\Auth\Access\Response;

class TransactionPolicy
{
use HandlesAuthorization;

/**
* Determine whether the user can view any models.
*/
public function viewAny(User $user): Response
{
return $user->exists ? $this->allow() : $this->denyAsNotFound();
}

/**
* Determine whether the user can view the model.
*/
public function view(User $user, Transaction $transaction): Response
{
return $transaction->user->is($user)
? $this->allow()
: $this->denyAsNotFound();
}

/**
* Determine whether the user can create models.
*/
public function create(User $user, CreditCard $creditCard): Response
{
return $creditCard->user->is($user)
? $this->allow()
: $this->denyAsNotFound();
}

/**
* Determine whether the user can update the model.
*/
public function update(User $user, Transaction $transaction): Response
{
return $transaction->user->is($user)
? $this->allow()
: $this->denyAsNotFound();
}

/**
* Determine whether the user can delete the model.
*/
public function delete(User $user, Transaction $transaction): Response
{
return $transaction->user->is($user)
? $this->allow()
: $this->denyAsNotFound();
}
}
49 changes: 49 additions & 0 deletions app/API/Transaction/v1/StoreTransactionRequest.php
@@ -0,0 +1,49 @@
<?php

namespace App\API\Transaction\v1;

use App\API\Transaction\Transaction;
use Illuminate\Foundation\Http\FormRequest;

class StoreTransactionRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return $this->user()->can(
'create',
[Transaction::class, $this->credit_card]
);
}

/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array|string>
*/
public function rules(): array
{
return [
'concept' => 'required|string|max:255',
'datetime' => 'required|date|before_or_equal:today',
'amount' => 'required|decimal:2,4|min:1',
'deadline_months' => 'sometimes|nullable|integer',
'commission' => 'sometimes|nullable|decimal:2,4',
'interest_rate' => 'sometimes|nullable|decimal:2',
];
}

public function attributes(): array
{
return [
'concept' => __('labels.concept'),
'datetime' => __('labels.datetime'),
'amount' => __('labels.amount'),
'deadline_months' => __('labels.deadline_months'),
'commission' => __('labels.commission'),
'interest_rate' => __('labels.interest_rate'),
];
}
}
59 changes: 59 additions & 0 deletions app/API/Transaction/v1/TransactionController.php
@@ -0,0 +1,59 @@
<?php

namespace App\API\Transaction\v1;

use App\API\CreditCard\CreditCard;
use App\API\Transaction\Transaction;
use App\Http\Controllers\Controller;

class TransactionController extends Controller
{
public function __construct()
{
$this->authorizeResource([Transaction::class, 'credit_card']);
}

/**
* Display a listing of the resource.
*/
public function index(CreditCard $creditCard)
{
//
}

/**
* Store a newly created resource in storage.
*/
public function store(
CreditCard $creditCard,
StoreTransactionRequest $request
) {
//
}

/**
* Display the specified resource.
*/
public function show(Transaction $transaction)
{
//
}

/**
* Update the specified resource in storage.
*/
public function update(
UpdateTransactionRequest $request,
Transaction $transaction
) {
//
}

/**
* Remove the specified resource from storage.
*/
public function destroy(Transaction $transaction)
{
//
}
}
45 changes: 45 additions & 0 deletions app/API/Transaction/v1/UpdateTransactionRequest.php
@@ -0,0 +1,45 @@
<?php

namespace App\API\Transaction\v1;

use Illuminate\Foundation\Http\FormRequest;

class UpdateTransactionRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return $this->user()->can('update', $this->transaction);
}

/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array|string>
*/
public function rules(): array
{
return [
'concept' => 'sometimes|required|string|max:255',
'datetime' => 'sometimes|required|date|before_or_equal:today',
'amount' => 'sometimes|required|decimal:2,4|min:1',
'deadline_months' => 'sometimes|nullable|integer',
'commission' => 'sometimes|nullable|decimal:2,4',
'interest_rate' => 'sometimes|nullable|decimal:2',
];
}

public function attributes(): array
{
return [
'concept' => __('labels.concept'),
'datetime' => __('labels.datetime'),
'amount' => __('labels.amount'),
'deadline_months' => __('labels.deadline_months'),
'commission' => __('labels.commission'),
'interest_rate' => __('labels.interest_rate'),
];
}
}
@@ -0,0 +1,35 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('transactions', function (Blueprint $table) {
$table->uuid('id');
$table->foreignUuid('credit_card_id')->constrained();
$table->string('concept');
$table->dateTime('datetime');
$table->decimal('amount', 19, 4);
$table->integer('deadline_months')->nullable();
$table->decimal('commission', 19, 4)->nullable();
$table->decimal('interest_rate', 6, 2)->nullable();
$table->foreignUuid('parent_transaction_id')->nullable();
$table->timestamps(3);
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('transactions');
}
};
16 changes: 16 additions & 0 deletions database/seeders/TransactionSeeder.php
@@ -0,0 +1,16 @@
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class TransactionSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
//
}
}
20 changes: 20 additions & 0 deletions tests/Feature/Models/TransactionTest.php
@@ -0,0 +1,20 @@
<?php

namespace Tests\Feature\Models;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

class TransactionTest extends TestCase
{
/**
* A basic feature test example.
*/
public function test_example(): void
{
$response = $this->get('/');

$response->assertStatus(200);
}
}

0 comments on commit 3bc2174

Please sign in to comment.