WIP: initial model, request and migration setup for Coupons

This commit is contained in:
kusowl 2026-03-25 18:40:34 +05:30
parent 5d6f75bdc2
commit 79f012e6d4
16 changed files with 417 additions and 0 deletions

View File

@ -0,0 +1,39 @@
<?php
namespace App\Http\Controllers;
use App\Http\Requests\CampaignRequest;
use App\Http\Resources\CampaignResource;
use App\Models\Campaign;
class CampaignController extends Controller
{
public function index()
{
return CampaignResource::collection(Campaign::all());
}
public function store(CampaignRequest $request)
{
return new CampaignResource(Campaign::create($request->validated()));
}
public function show(Campaign $campaign)
{
return new CampaignResource($campaign);
}
public function update(CampaignRequest $request, Campaign $campaign)
{
$campaign->update($request->validated());
return new CampaignResource($campaign);
}
public function destroy(Campaign $campaign)
{
$campaign->delete();
return response()->json();
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace App\Http\Controllers;
use App\Http\Requests\CouponRequest;
use App\Http\Resources\CouponResource;
use App\Models\Coupon;
class CouponController extends Controller
{
public function index()
{
return CouponResource::collection(Coupon::all());
}
public function store(CouponRequest $request)
{
return new CouponResource(Coupon::create($request->validated()));
}
public function show(Coupon $coupon)
{
return new CouponResource($coupon);
}
public function update(CouponRequest $request, Coupon $coupon)
{
$coupon->update($request->validated());
return new CouponResource($coupon);
}
public function destroy(Coupon $coupon)
{
$coupon->delete();
return response()->json();
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CampaignRequest extends FormRequest
{
public function rules(): array
{
return [
'name' => ['required'],
'discount_type_id' => ['required', 'exists:discount_types'],
'discount_value' => ['required', 'numeric'],
'max_discount' => ['nullable', 'numeric'],
'min_order_value' => ['nullable', 'numeric'],
'start_time' => ['required', 'date'],
'end_time' => ['required', 'date'],
'total_usage_limit' => ['nullable', 'integer'],
'per_user_limit' => ['nullable', 'integer'],
'campaign_status_id' => ['required', 'exists:campaign_statuses'],
];
}
public function authorize(): bool
{
return true;
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CouponRequest extends FormRequest
{
public function rules(): array
{
return [
'campaign_id' => ['required', 'exists:campaigns'],
'code' => ['required'],
];
}
public function authorize(): bool
{
return true;
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace App\Http\Resources;
use App\Models\Campaign;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
/** @mixin Campaign */
class CampaignResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'discount_value' => $this->dicount_value,
'max_discount' => $this->max_discount,
'min_order_value' => $this->min_order_value,
'start_time' => $this->start_time,
'end_time' => $this->end_time,
'total_usage_limit' => $this->total_usage_limit,
'per_user_limit' => $this->per_user_limit,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'discount_type_id' => $this->discount_type_id,
'campaign_status_id' => $this->campaign_status_id,
];
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace App\Http\Resources;
use App\Models\Coupon;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
/** @mixin Coupon */
class CouponResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'code' => $this->code,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'campaign_id' => $this->campaign_id,
'campaign' => new CampaignResource($this->whenLoaded('campaign')),
];
}
}

View File

@ -0,0 +1,40 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Campaign extends Model
{
protected $fillable = [
'name',
'discount_type_id',
'discount_value',
'max_discount',
'min_order_value',
'start_time',
'end_time',
'total_usage_limit',
'per_user_limit',
'campaign_status_id',
];
public function discountType(): BelongsTo
{
return $this->belongsTo(DiscountType::class);
}
public function campaignStatus(): BelongsTo
{
return $this->belongsTo(CampaignStatus::class);
}
protected function casts(): array
{
return [
'start_time' => 'datetime',
'end_time' => 'datetime',
];
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class CampaignStatus extends Model
{
protected $fillable = [
'value',
];
}

View File

@ -0,0 +1,19 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Coupon extends Model
{
protected $fillable = [
'campaign_id',
'code',
];
public function campaign(): BelongsTo
{
return $this->belongsTo(Campaign::class);
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class DiscountType extends Model
{
protected $fillable = [
'value',
];
}

View File

@ -0,0 +1,30 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class RedemptionLog extends Model
{
protected $fillable = [
'user_id',
'coupon_id',
'order_id',
];
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function coupon(): BelongsTo
{
return $this->belongsTo(Coupon::class);
}
public function order(): BelongsTo
{
return $this->belongsTo(Order::class);
}
}

View File

@ -0,0 +1,21 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(): void
{
Schema::create('campaign_statuses', function (Blueprint $table) {
$table->id();
$table->string('value');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('campaign_statuses');
}
};

View File

@ -0,0 +1,21 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(): void
{
Schema::create('discount_types', function (Blueprint $table) {
$table->id();
$table->string('value');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('discount_types');
}
};

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(): void
{
Schema::create('campaigns', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->foreignId('discount_type_id');
$table->float('discount_value');
$table->float('max_discount')->nullable();
$table->float('min_order_value')->nullable();
$table->dateTime('start_time');
$table->dateTime('end_time');
$table->integer('total_usage_limit')->nullable();
$table->integer('per_user_limit')->nullable();
$table->foreignId('campaign_status_id');
$table->timestamps();
$table->index(['campaign_status_id', 'start_time', 'end_time'], 'campaign_validity_index');
$table->index(['name']);
});
}
public function down(): void
{
Schema::dropIfExists('campaigns');
}
};

View File

@ -0,0 +1,23 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(): void
{
Schema::create('coupons', function (Blueprint $table) {
$table->id();
$table->foreignId('campaign_id');
$table->string('code');
$table->timestamps();
$table->index(['code']);
});
}
public function down(): void
{
Schema::dropIfExists('coupons');
}
};

View File

@ -0,0 +1,23 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(): void
{
Schema::create('redemption_logs', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id');
$table->foreignId('coupon_id');
$table->foreignId('order_id');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('redemption_logs');
}
};