Skip to content

Commit

Permalink
Add Purchase Order Management to Accounting System
Browse files Browse the repository at this point in the history
  • Loading branch information
sweep-ai[bot] authored Dec 24, 2024
1 parent ffa4f48 commit ba7349c
Show file tree
Hide file tree
Showing 5 changed files with 245 additions and 0 deletions.
102 changes: 102 additions & 0 deletions app/Filament/App/Resources/PurchaseOrderResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@


<?php

namespace App\Filament\App\Resources;

use App\Filament\App\Resources\PurchaseOrderResource\Pages;
use App\Models\PurchaseOrder;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;

class PurchaseOrderResource extends Resource
{
protected static ?string $model = PurchaseOrder::class;

protected static ?string $navigationIcon = 'heroicon-o-shopping-cart';

public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\Select::make('supplier_id')
->relationship('supplier', 'supplier_first_name')
->required(),
Forms\Components\TextInput::make('po_number')
->default(fn () => PurchaseOrder::generatePoNumber())
->disabled()
->required(),
Forms\Components\DatePicker::make('order_date')
->required(),
Forms\Components\DatePicker::make('expected_delivery_date'),
Forms\Components\Select::make('status')
->options([
'draft' => 'Draft',
'sent' => 'Sent',
'received' => 'Received',
'cancelled' => 'Cancelled',
])
->required(),
Forms\Components\Repeater::make('items')
->relationship()
->schema([
Forms\Components\TextInput::make('description')
->required(),
Forms\Components\TextInput::make('quantity')
->numeric()
->required(),
Forms\Components\TextInput::make('unit_price')
->numeric()
->required(),
])
->columns(3),
Forms\Components\Textarea::make('notes'),
]);
}

public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('po_number')
->searchable(),
Tables\Columns\TextColumn::make('supplier.supplier_first_name')
->searchable(),
Tables\Columns\TextColumn::make('order_date')
->date(),
Tables\Columns\TextColumn::make('total_amount')
->money(),
Tables\Columns\BadgeColumn::make('status')
->colors([
'warning' => 'draft',
'primary' => 'sent',
'success' => 'received',
'danger' => 'cancelled',
]),
])
->filters([
Tables\Filters\SelectFilter::make('status'),
])
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\DeleteAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}

public static function getPages(): array
{
return [
'index' => Pages\ListPurchaseOrders::route('/'),
'create' => Pages\CreatePurchaseOrder::route('/create'),
'edit' => Pages\EditPurchaseOrder::route('/{record}/edit'),
];
}
}
63 changes: 63 additions & 0 deletions app/Models/PurchaseOrder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@


<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class PurchaseOrder extends Model
{
use HasFactory;

protected $primaryKey = 'purchase_order_id';

protected $fillable = [
'supplier_id',
'po_number',
'order_date',
'expected_delivery_date',
'total_amount',
'status',
'notes'
];

protected $casts = [
'order_date' => 'date',
'expected_delivery_date' => 'date',
'total_amount' => 'decimal:2',
];

public function supplier()
{
return $this->belongsTo(Supplier::class, 'supplier_id');
}

public function items()
{
return $this->hasMany(PurchaseOrderItem::class, 'purchase_order_id');
}

public function transactions()
{
return $this->hasMany(Transaction::class, 'purchase_order_id');
}

public static function generatePoNumber()
{
$prefix = 'PO';
$year = date('Y');
$lastPo = self::whereYear('created_at', $year)
->orderBy('po_number', 'desc')
->first();

if (!$lastPo) {
$number = 1;
} else {
$number = (int)substr($lastPo->po_number, -4) + 1;
}

return $prefix . $year . str_pad($number, 4, '0', STR_PAD_LEFT);
}
}
33 changes: 33 additions & 0 deletions app/Models/PurchaseOrderItem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@


<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class PurchaseOrderItem extends Model
{
use HasFactory;

protected $primaryKey = 'item_id';

protected $fillable = [
'purchase_order_id',
'description',
'quantity',
'unit_price',
'total_price'
];

protected $casts = [
'unit_price' => 'decimal:2',
'total_price' => 'decimal:2',
];

public function purchaseOrder()
{
return $this->belongsTo(PurchaseOrder::class, 'purchase_order_id');
}
}
6 changes: 6 additions & 0 deletions app/Models/Transaction.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class Transaction extends Model
'reconciled',
'discrepancy_notes',
'exchange_rate',
'purchase_order_id',
];

protected $casts = [
Expand Down Expand Up @@ -48,6 +49,11 @@ public function categories()
return $this->belongsToMany(Category::class);
}

public function purchaseOrder()
{
return $this->belongsTo(PurchaseOrder::class, 'purchase_order_id');
}

public function getAmountInDefaultCurrency()
{
$defaultCurrency = Currency::where('is_default', true)->first();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@


<?php

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

return new class extends Migration
{
public function up()
{
Schema::create('purchase_orders', function (Blueprint $table) {
$table->id('purchase_order_id');
$table->foreignId('supplier_id')->constrained('suppliers', 'supplier_id');
$table->string('po_number')->unique();
$table->date('order_date');
$table->date('expected_delivery_date')->nullable();
$table->decimal('total_amount', 15, 2);
$table->string('status')->default('draft');
$table->text('notes')->nullable();
$table->timestamps();
});

Schema::create('purchase_order_items', function (Blueprint $table) {
$table->id('item_id');
$table->foreignId('purchase_order_id')->constrained('purchase_orders', 'purchase_order_id')->onDelete('cascade');
$table->string('description');
$table->integer('quantity');
$table->decimal('unit_price', 15, 2);
$table->decimal('total_price', 15, 2);
$table->timestamps();
});
}

public function down()
{
Schema::dropIfExists('purchase_order_items');
Schema::dropIfExists('purchase_orders');
}
};

0 comments on commit ba7349c

Please sign in to comment.