Easy and Quick POS System Using Laravel Filament

Programmer TeloProgrammer Telo
3 min read

Step 1: Create the Laravel Project

To create a new Laravel project named laravel-pos, run:

laravel new laravel-pos

Alternatively, you can use Composer:

composer create-project laravel/laravel=11.3.2 laravel-pos

Step 2: Open the Project in Your Code Editor

Navigate into the project directory and open it in your code editor:

cd laravel-pos
code .
npm install && npm run build
composer run dev

Step 3: Configure the Database

Open the .env file in your project root and update the database settings. Since Laravel's installer already configured the database and ran migrations during setup, this step is complete.

Step 3: Install Filament

  1. Install Filament: Run the following command to install Filament version 3.2:

     composer require filament/filament:"^3.2" -W
    
  2. Install Admin Panel: Install the Filament admin panel using the command:

     php artisan filament:install --panels
    

Step 4: Create Admin User

To create an admin user for your Filament admin panel, run the following command:

php artisan make:filament-user

Step 5: Create Location Management

To set up models, migrations, and seeders for Provinces, Regencies, Districts, and Villages, follow these steps:

1. Generate Models and Migrations

Run the following commands to create the models with their corresponding migrations and seeders:

php artisan make:model Province -ms
php artisan make:model Regency -ms
php artisan make:model District -ms
php artisan make:model Village -ms

2. Define Migrations

Replace the content of the generated migration files as follows:

Provinces Migration:

<?php

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

class CreateProvincesTable extends Migration
{
    public function up()
    {
        Schema::create('provinces', function (Blueprint $table) {
            $table->char('id', 2)->index();
            $table->string('name');
        });
    }

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

Regencies Migration:

<?php

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

class CreateRegenciesTable extends Migration
{
    public function up()
    {
        Schema::create('regencies', function (Blueprint $table) {
            $table->char('id', 4)->index();
            $table->char('province_id', 2);
            $table->string('name', 50);
            $table->foreign('province_id')
                ->references('id')
                ->on('provinces')
                ->onUpdate('cascade')
                ->onDelete('restrict');
        });
    }

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

Districts Migration:

<?php

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

class CreateDistrictsTable extends Migration
{
    public function up()
    {
        Schema::create('districts', function (Blueprint $table) {
            $table->char('id', 7)->index();
            $table->char('regency_id', 4);
            $table->string('name', 50);
            $table->foreign('regency_id')
                ->references('id')
                ->on('regencies')
                ->onUpdate('cascade')
                ->onDelete('restrict');
        });
    }

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

Villages Migration:

<?php

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

class CreateVillagesTable extends Migration
{
    public function up()
    {
        Schema::create('villages', function (Blueprint $table) {
            $table->char('id', 10)->index();
            $table->char('district_id', 7);
            $table->string('name', 50);
            $table->foreign('district_id')
                ->references('id')
                ->on('districts')
                ->onUpdate('cascade')
                ->onDelete('restrict');
        });
    }

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

3. Prepare Seeder Data

Create a directory for seeder data:

mkdir database/seeders/data

Download seeder data using the following commands:

curl -o "database/seeders/data/laravel_pos_districts.sql" "https://raw.githubusercontent.com/CahBantul/laravel-pos/feature/system-management/database/seeders/data/laravel_pos_districts.sql"
curl -o "database/seeders/data/laravel_pos_provinces.sql" "https://raw.githubusercontent.com/CahBantul/laravel-pos/feature/system-management/database/seeders/data/laravel_pos_provinces.sql"
curl -o "database/seeders/data/laravel_pos_regencies.sql" "https://raw.githubusercontent.com/CahBantul/laravel-pos/feature/system-management/database/seeders/data/laravel_pos_regencies.sql"
curl -o "database/seeders/data/laravel_pos_villages.sql" "https://raw.githubusercontent.com/CahBantul/laravel-pos/feature/system-management/database/seeders/data/laravel_pos_villages.sql"

4. Define Seeders

Edit the seeders for each table as follows:

ProvinceSeeder:

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;

class ProvinceSeeder extends Seeder
{
    public function run(): void
    {
        $sqlPath = database_path('seeders/data/laravel_pos_provinces.sql');
        if (File::exists($sqlPath)) {
            DB::unprepared(File::get($sqlPath));
            $this->command->info('Provinces data seeded successfully!');
        } else {
            $this->command->error('Provinces SQL file not found.');
        }
    }
}

Similarly, edit RegencySeeder, DistrictSeeder, and VillageSeeder, updating the $sqlPath and success/error messages accordingly.

5. Add Seeders to DatabaseSeeder

Edit the DatabaseSeeder file to include the new seeders:

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        $this->call(ProvinceSeeder::class);
        $this->call(RegencySeeder::class);
        $this->call(DistrictSeeder::class);
        $this->call(VillageSeeder::class);
    }
}

6. Run Migrations and Seeders

Run the following commands to apply migrations and seed the database:

php artisan migrate
php artisan db:seed
0
Subscribe to my newsletter

Read articles from Programmer Telo directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Programmer Telo
Programmer Telo