Merge branch 'production' of https://git.abbauf.com/Magang-2025/Kasir into production
This commit is contained in:
commit
b2f93c4537
82
app/Http/Controllers/KategoriController.php
Normal file
82
app/Http/Controllers/KategoriController.php
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Kategori;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class KategoriController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return response()->json(
|
||||||
|
Kategori::withCount('produk')->get()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*/
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$validated = $request->validate([
|
||||||
|
'nama' => 'required|string|max:100',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'nama' => 'Nama kategori harus diisi.'
|
||||||
|
]);
|
||||||
|
|
||||||
|
Kategori::create($validated);
|
||||||
|
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Kategori berhasil dibuat'
|
||||||
|
],201);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*/
|
||||||
|
public function show(int $id)
|
||||||
|
{
|
||||||
|
return response()->json(
|
||||||
|
Kategori::with('items.produk.foto')->find($id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*/
|
||||||
|
public function update(Request $request, int $id)
|
||||||
|
{
|
||||||
|
$validated = $request->validate([
|
||||||
|
'nama' => 'required|string|max:100',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'nama' => 'Nama Kategori harus diisi.'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$Kategori = Kategori::findOrFail($id);
|
||||||
|
|
||||||
|
$Kategori->update($validated);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Kategori berhasil diupdate'
|
||||||
|
],200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*/
|
||||||
|
public function destroy(int $id)
|
||||||
|
{
|
||||||
|
Kategori::findOrFail($id)->delete();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Kategori berhasil dihapus'
|
||||||
|
], 204);
|
||||||
|
}
|
||||||
|
}
|
@ -17,7 +17,7 @@ class ProdukController extends Controller
|
|||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
return response()->json(
|
return response()->json(
|
||||||
Produk::withCount('items')->with('foto')->get()
|
Produk::withCount('items')->with('foto', 'kategori')->get()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,16 +28,16 @@ class ProdukController extends Controller
|
|||||||
{
|
{
|
||||||
$validated = $request->validate([
|
$validated = $request->validate([
|
||||||
'nama' => 'required|string|max:100',
|
'nama' => 'required|string|max:100',
|
||||||
'kategori' => 'required|in:cincin,gelang,kalung,anting',
|
'id_kategori' => 'required|exists:users,id',
|
||||||
'berat' => 'required|numeric',
|
'berat' => 'required|numeric',
|
||||||
'kadar' => 'required|integer',
|
'kadar' => 'required|integer',
|
||||||
'harga_per_gram' => 'required|numeric',
|
'harga_per_gram' => 'required|numeric',
|
||||||
'harga_jual' => 'required|numeric',
|
'harga_jual' => 'required|numeric',
|
||||||
'id_user' => 'nullable|exists:users,id', // untuk mengambil foto sementara
|
'id_user' => 'nullable|exists:users,id',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'nama.required' => 'Nama produk harus diisi.',
|
'nama.required' => 'Nama produk harus diisi.',
|
||||||
'kategori.in' => 'Kategori harus salah satu dari cincin, gelang, kalung, atau anting.',
|
'id_kategori' => 'Kategori tidak valid.',
|
||||||
'berat.required' => 'Berat harus diisi.',
|
'berat.required' => 'Berat harus diisi.',
|
||||||
'kadar.required' => 'Kadar harus diisi',
|
'kadar.required' => 'Kadar harus diisi',
|
||||||
'harga_per_gram.required' => 'Harga per gram harus diisi',
|
'harga_per_gram.required' => 'Harga per gram harus diisi',
|
||||||
@ -49,7 +49,7 @@ class ProdukController extends Controller
|
|||||||
// Create produk
|
// Create produk
|
||||||
$produk = Produk::create([
|
$produk = Produk::create([
|
||||||
'nama' => $validated['nama'],
|
'nama' => $validated['nama'],
|
||||||
'kategori' => $validated['kategori'],
|
'id_kategori' => $validated['id_kategori'],
|
||||||
'berat' => $validated['berat'],
|
'berat' => $validated['berat'],
|
||||||
'kadar' => $validated['kadar'],
|
'kadar' => $validated['kadar'],
|
||||||
'harga_per_gram' => $validated['harga_per_gram'],
|
'harga_per_gram' => $validated['harga_per_gram'],
|
||||||
@ -92,7 +92,7 @@ class ProdukController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function show(int $id)
|
public function show(int $id)
|
||||||
{
|
{
|
||||||
$produk = Produk::with('foto', 'items')->findOrFail($id);
|
$produk = Produk::with('foto', 'items', 'kategori')->findOrFail($id);
|
||||||
return response()->json($produk);
|
return response()->json($produk);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ class ProdukController extends Controller
|
|||||||
{
|
{
|
||||||
$validated = $request->validate([
|
$validated = $request->validate([
|
||||||
'nama' => 'required|string|max:100',
|
'nama' => 'required|string|max:100',
|
||||||
'kategori' => 'required|in:cincin,gelang,kalung,anting',
|
'id_kategori' => 'required|exists:kategoris,id',
|
||||||
'berat' => 'required|numeric',
|
'berat' => 'required|numeric',
|
||||||
'kadar' => 'required|integer',
|
'kadar' => 'required|integer',
|
||||||
'harga_per_gram' => 'required|numeric',
|
'harga_per_gram' => 'required|numeric',
|
||||||
@ -113,7 +113,7 @@ class ProdukController extends Controller
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
'nama.required' => 'Nama produk harus diisi.',
|
'nama.required' => 'Nama produk harus diisi.',
|
||||||
'kategori.in' => 'Kategori harus salah satu dari cincin, gelang, kalung, atau anting.',
|
'id_kategori' => 'Kategori tidak valid.',
|
||||||
'berat.required' => 'Berat harus diisi.',
|
'berat.required' => 'Berat harus diisi.',
|
||||||
'kadar.required' => 'Kadar harus diisi',
|
'kadar.required' => 'Kadar harus diisi',
|
||||||
'harga_per_gram.required' => 'Harga per gram harus diisi',
|
'harga_per_gram.required' => 'Harga per gram harus diisi',
|
||||||
|
@ -19,10 +19,21 @@ class TransaksiController extends Controller
|
|||||||
$query->limit((int)$limit);
|
$query->limit((int)$limit);
|
||||||
}
|
}
|
||||||
$transaksi = $query->get();
|
$transaksi = $query->get();
|
||||||
$transaksi = Transaksi::with(['kasir', 'sales', 'items.item.produk'])->latest()->limit(100)->get();
|
|
||||||
return response()->json($transaksi);
|
// Mapping agar sesuai dengan kebutuhan frontend
|
||||||
|
$mapped = $transaksi->map(function ($trx) {
|
||||||
|
return [
|
||||||
|
'id' => $trx->id,
|
||||||
|
'tanggal' => $trx->created_at->format('d/m/Y'),
|
||||||
|
'kode' => 'TRX-' . str_pad($trx->id, 6, '0', STR_PAD_LEFT),
|
||||||
|
'pendapatan'=> $trx->total_harga,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
return response()->json($mapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Detail transaksi by ID
|
// Detail transaksi by ID
|
||||||
public function show($id)
|
public function show($id)
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,8 @@ class Foto extends Model
|
|||||||
'url',
|
'url',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
protected $hidden = ['created_at', 'updated_at', 'deleted_at'];
|
||||||
|
|
||||||
public function produk()
|
public function produk()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Produk::class, 'id_produk');
|
return $this->belongsTo(Produk::class, 'id_produk');
|
||||||
|
@ -10,4 +10,6 @@ class FotoSementara extends Model
|
|||||||
'id_user',
|
'id_user',
|
||||||
'url',
|
'url',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
protected $hidden = ['created_at', 'updated_at', 'deleted_at'];
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@ class Item extends Model
|
|||||||
'is_sold',
|
'is_sold',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
protected $hidden = ['created_at', 'updated_at', 'deleted_at'];
|
||||||
|
|
||||||
public function produk()
|
public function produk()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Produk::class, 'id_produk');
|
return $this->belongsTo(Produk::class, 'id_produk');
|
||||||
|
@ -16,6 +16,8 @@ class ItemTransaksi extends Model
|
|||||||
'harga_deal'
|
'harga_deal'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
protected $hidden = ['created_at', 'updated_at', 'deleted_at'];
|
||||||
|
|
||||||
public function transaksi()
|
public function transaksi()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Transaksi::class, 'id_transaksi');
|
return $this->belongsTo(Transaksi::class, 'id_transaksi');
|
||||||
|
22
app/Models/Kategori.php
Normal file
22
app/Models/Kategori.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
|
class Kategori extends Model
|
||||||
|
{
|
||||||
|
/** @use HasFactory<\Database\Factories\KategoriFactory> */
|
||||||
|
use HasFactory, SoftDeletes;
|
||||||
|
|
||||||
|
protected $fillable = ['nama'];
|
||||||
|
|
||||||
|
protected $hidden = ['created_at', 'updated_at', 'deleted_at'];
|
||||||
|
|
||||||
|
public function produks()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Produk::class, 'id_kategori');
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,7 @@ class Nampan extends Model
|
|||||||
];
|
];
|
||||||
protected $appends = ['berat_total'];
|
protected $appends = ['berat_total'];
|
||||||
|
|
||||||
|
protected $hidden = ['created_at', 'updated_at', 'deleted_at'];
|
||||||
|
|
||||||
public function items()
|
public function items()
|
||||||
{
|
{
|
||||||
|
@ -12,13 +12,15 @@ class Produk extends Model
|
|||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'nama',
|
'nama',
|
||||||
'kategori',
|
'id_kategori',
|
||||||
'berat',
|
'berat',
|
||||||
'kadar',
|
'kadar',
|
||||||
'harga_per_gram',
|
'harga_per_gram',
|
||||||
'harga_jual',
|
'harga_jual',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
protected $hidden = ['created_at', 'updated_at', 'deleted_at'];
|
||||||
|
|
||||||
public function items()
|
public function items()
|
||||||
{
|
{
|
||||||
return $this->hasMany(Item::class, 'id_produk');
|
return $this->hasMany(Item::class, 'id_produk');
|
||||||
@ -28,4 +30,9 @@ class Produk extends Model
|
|||||||
{
|
{
|
||||||
return $this->hasMany(Foto::class, 'id_produk');
|
return $this->hasMany(Foto::class, 'id_produk');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function kategori()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Kategori::class, 'id_kategori');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@ class Sales extends Model
|
|||||||
'alamat'
|
'alamat'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
protected $hidden = ['created_at', 'updated_at', 'deleted_at'];
|
||||||
|
|
||||||
public function transaksi()
|
public function transaksi()
|
||||||
{
|
{
|
||||||
return $this->hasMany(Transaksi::class, 'id_sales');
|
return $this->hasMany(Transaksi::class, 'id_sales');
|
||||||
|
@ -20,6 +20,8 @@ class Transaksi extends Model
|
|||||||
'created_at',
|
'created_at',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
protected $hidden = ['updated_at', 'deleted_at'];
|
||||||
|
|
||||||
public function kasir()
|
public function kasir()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(User::class, 'id_kasir');
|
return $this->belongsTo(User::class, 'id_kasir');
|
||||||
|
23
database/factories/KategoriFactory.php
Normal file
23
database/factories/KategoriFactory.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Kategori>
|
||||||
|
*/
|
||||||
|
class KategoriFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'nama' => $this->faker->word(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Kategori;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -18,9 +19,10 @@ class ProdukFactory extends Factory
|
|||||||
{
|
{
|
||||||
$harga_per_gram = $this->faker->numberBetween(80, 120) * 10000;
|
$harga_per_gram = $this->faker->numberBetween(80, 120) * 10000;
|
||||||
$berat = $this->faker->randomFloat(2, 1, 10);
|
$berat = $this->faker->randomFloat(2, 1, 10);
|
||||||
|
$kategoriList = Kategori::all()->pluck('id')->toArray();
|
||||||
return [
|
return [
|
||||||
'nama' => $this->faker->words(3, true),
|
'nama' => $this->faker->words(3, true),
|
||||||
'kategori' => $this->faker->randomElement(['cincin', 'gelang', 'kalung', 'anting']),
|
'id_kategori' => $this->faker->randomElement($kategoriList),
|
||||||
'berat' => $berat,
|
'berat' => $berat,
|
||||||
'kadar' => $this->faker->numberBetween(10, 24),
|
'kadar' => $this->faker->numberBetween(10, 24),
|
||||||
'harga_per_gram' => $harga_per_gram,
|
'harga_per_gram' => $harga_per_gram,
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
<?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('kategoris', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('nama', 100);
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('kategoris');
|
||||||
|
}
|
||||||
|
};
|
@ -14,7 +14,7 @@ return new class extends Migration
|
|||||||
Schema::create('produks', function (Blueprint $table) {
|
Schema::create('produks', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->string('nama', 100);
|
$table->string('nama', 100);
|
||||||
$table->enum('kategori', ['cincin', 'gelang', 'kalung', 'anting']);
|
$table->foreignId('id_kategori')->constrained('kategoris');
|
||||||
$table->float('berat');
|
$table->float('berat');
|
||||||
$table->integer('kadar');
|
$table->integer('kadar');
|
||||||
$table->double('harga_per_gram');
|
$table->double('harga_per_gram');
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace Database\Seeders;
|
namespace Database\Seeders;
|
||||||
|
|
||||||
use App\Models\Item;
|
use App\Models\Item;
|
||||||
|
use App\Models\Kategori;
|
||||||
use App\Models\Nampan;
|
use App\Models\Nampan;
|
||||||
use App\Models\Produk;
|
use App\Models\Produk;
|
||||||
use App\Models\Sales;
|
use App\Models\Sales;
|
||||||
@ -36,6 +37,13 @@ class DatabaseSeeder extends Seeder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$kategoriList = ['cincin', 'gelang', 'kalung', 'anting'];
|
||||||
|
foreach ($kategoriList as $kategori) {
|
||||||
|
Kategori::factory()->create([
|
||||||
|
'nama' => $kategori
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
Produk::factory(10)->create()->each(function ($produk) {
|
Produk::factory(10)->create()->each(function ($produk) {
|
||||||
// setiap produk punya 1-3 foto
|
// setiap produk punya 1-3 foto
|
||||||
$jumlah_foto = rand(1, 3);
|
$jumlah_foto = rand(1, 3);
|
||||||
|
BIN
public/images/logo.png
Normal file
BIN
public/images/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 138 KiB |
@ -16,6 +16,7 @@
|
|||||||
<InputField
|
<InputField
|
||||||
v-model="hargaJual"
|
v-model="hargaJual"
|
||||||
type="number"
|
type="number"
|
||||||
|
placeholder="Masukkan Harga Jual"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -53,10 +54,10 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="(item, index) in pesanan" :key="index" class="hover:bg-gray-50">
|
<tr v-for="(item, index) in pesanan" :key="index" class="hover:bg-gray-50 text-center">
|
||||||
<td class="border border-gray-200 p-2 text-center">{{ index + 1 }}</td>
|
<td class="border border-gray-200 p-2">{{ index + 1 }}</td>
|
||||||
<td class="border border-gray-200 p-2">{{ item.kode }}</td>
|
<td class="border border-gray-200 p-2">{{ item.kode }}</td>
|
||||||
<td class="border border-gray-200 p-2 text-center">{{ item.jumlah }}</td>
|
<td class="border border-gray-200 p-2">{{ item.jumlah }}</td>
|
||||||
<td class="border border-gray-200 p-2">Rp{{ item.harga.toLocaleString() }}</td>
|
<td class="border border-gray-200 p-2">Rp{{ item.harga.toLocaleString() }}</td>
|
||||||
<td class="border border-gray-200 p-2">Rp{{ (item.harga * item.jumlah).toLocaleString() }}</td>
|
<td class="border border-gray-200 p-2">Rp{{ (item.harga * item.jumlah).toLocaleString() }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -73,7 +74,7 @@
|
|||||||
import InputField from './InputField.vue'
|
import InputField from './InputField.vue'
|
||||||
|
|
||||||
const kodeItem = ref('')
|
const kodeItem = ref('')
|
||||||
const hargaJual = ref(0)
|
const hargaJual = ref(null)
|
||||||
const pesanan = ref([])
|
const pesanan = ref([])
|
||||||
|
|
||||||
const tambahItem = () => {
|
const tambahItem = () => {
|
||||||
@ -91,3 +92,4 @@ import InputField from './InputField.vue'
|
|||||||
pesanan.value.reduce((sum, item) => sum + item.harga * item.jumlah, 0)
|
pesanan.value.reduce((sum, item) => sum + item.harga * item.jumlah, 0)
|
||||||
)
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
const res = await axios.get("/api/transaksi") // GANTI URL SESUAI API
|
const res = await axios.get("/api/transaksi?limit=10") // GANTI URL SESUAI API
|
||||||
|
|
||||||
transaksi.value = res.data
|
transaksi.value = res.data
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Gagal fetch transaksi:", err)
|
console.error("Gagal fetch transaksi:", err)
|
||||||
|
Loading…
Reference in New Issue
Block a user