Merge branch 'production' of https://git.abbauf.com/Magang-2025/Kasir into production

This commit is contained in:
adityaalfarison 2025-09-11 11:42:29 +07:00
commit dbd4d46048
7 changed files with 61 additions and 51 deletions

View File

@ -23,7 +23,7 @@ class KategoriController extends Controller
public function store(Request $request) public function store(Request $request)
{ {
$validated = $request->validate([ $validated = $request->validate([
'nama' => 'required|string|max:100', 'nama' => 'required|string|max:50',
], ],
[ [
'nama' => 'Nama kategori harus diisi.' 'nama' => 'Nama kategori harus diisi.'
@ -31,7 +31,7 @@ class KategoriController extends Controller
Kategori::create($validated); Kategori::create($validated);
return response()->json([ return response()->json([
'message' => 'Kategori berhasil dibuat' 'message' => 'Kategori berhasil dibuat'
],201); ],201);
@ -53,7 +53,7 @@ class KategoriController extends Controller
public function update(Request $request, int $id) public function update(Request $request, int $id)
{ {
$validated = $request->validate([ $validated = $request->validate([
'nama' => 'required|string|max:100', 'nama' => 'required|string|max:50',
], ],
[ [
'nama' => 'Nama Kategori harus diisi.' 'nama' => 'Nama Kategori harus diisi.'
@ -74,9 +74,9 @@ class KategoriController extends Controller
public function destroy(int $id) public function destroy(int $id)
{ {
Kategori::findOrFail($id)->delete(); Kategori::findOrFail($id)->delete();
return response()->json([ return response()->json([
'message' => 'Kategori berhasil dihapus' 'message' => 'Kategori berhasil dihapus'
], 204); ], 200);
} }
} }

View File

@ -89,12 +89,12 @@ class LaporanController extends Controller
{ {
try { try {
return $this->laporanService->exportPerNampan($request->validate([ return $this->laporanService->exportPerNampan($request->validate([
'tanggal' => 'nullable|string', 'tanggal' => 'required|string',
'sales_id' => 'nullable|integer|exists:sales,id',
'produk_id' => 'nullable|integer|exists:produk,id',
'nama_pembeli' => 'nullable|string|max:255',
'format' => 'required|string|in:pdf,xlsx,csv', 'format' => 'required|string|in:pdf,xlsx,csv',
'page' => 'nullable|integer|min:1', 'page' => 'required|integer|min:1',
'sales_id' => 'nullable|integer|exists:sales,id',
'produk_id' => 'nullable|integer|exists:produks,id',
'nama_pembeli' => 'nullable|string|max:255',
])); ]));
} catch (\Exception $e) { } catch (\Exception $e) {
@ -107,12 +107,12 @@ class LaporanController extends Controller
{ {
try { try {
return $this->laporanService->exportPerProduk($request->validate([ return $this->laporanService->exportPerProduk($request->validate([
'tanggal' => 'nullable|string', 'tanggal' => 'required|string',
'sales_id' => 'nullable|integer|exists:sales,id',
'nampan_id' => 'nullable|integer|exists:nampan,id',
'nama_pembeli' => 'nullable|string|max:255',
'format' => 'required|string|in:pdf,xlsx,csv', 'format' => 'required|string|in:pdf,xlsx,csv',
'page' => 'nullable|integer|min:1', 'page' => 'required|integer|min:1',
'sales_id' => 'nullable|integer|exists:sales,id',
'nampan_id' => 'nullable|integer|exists:nampans,id',
'nama_pembeli' => 'nullable|string|max:255',
])); ]));
} catch (\Exception $e) { } catch (\Exception $e) {

View File

@ -24,7 +24,7 @@ class NampanController extends Controller
public function store(Request $request) public function store(Request $request)
{ {
$validated = $request->validate([ $validated = $request->validate([
'nama' => 'required|string|max:100', 'nama' => 'required|string|max:10',
], ],
[ [
'nama' => 'Nama nampan harus diisi.' 'nama' => 'Nama nampan harus diisi.'
@ -32,7 +32,7 @@ class NampanController extends Controller
Nampan::create($validated); Nampan::create($validated);
return response()->json([ return response()->json([
'message' => 'Nampan berhasil dibuat' 'message' => 'Nampan berhasil dibuat'
],201); ],201);
@ -54,7 +54,7 @@ class NampanController extends Controller
public function update(Request $request, int $id) public function update(Request $request, int $id)
{ {
$validated = $request->validate([ $validated = $request->validate([
'nama' => 'required|string|max:100', 'nama' => 'required|string|max:10',
], ],
[ [
'nama' => 'Nama nampan harus diisi.' 'nama' => 'Nama nampan harus diisi.'
@ -75,13 +75,13 @@ class NampanController extends Controller
public function destroy(int $id) public function destroy(int $id)
{ {
$nampan = Nampan::findOrFail($id); $nampan = Nampan::findOrFail($id);
$nampan->items()->each(function ($item) { $nampan->items()->each(function ($item) {
$item->update(['id_nampan' => null]); $item->update(['id_nampan' => null]);
}); });
$nampan->delete(); $nampan->delete();
return response()->json([ return response()->json([
'message' => 'Nampan berhasil dihapus' 'message' => 'Nampan berhasil dihapus'
], 204); ], 204);

View File

@ -22,6 +22,13 @@ class UserController extends Controller
'nama' => 'required|string|unique:users', 'nama' => 'required|string|unique:users',
'password' => 'required|min:6', 'password' => 'required|min:6',
'role' => 'required|in:owner,kasir', 'role' => 'required|in:owner,kasir',
], [
'nama.require' => 'Nama wajib diisi',
'nama.unique' => 'Nama sudah digunakan',
'password.require' => 'Password wajib diisi',
'password.min' => 'Password minimal 6 karakter',
'role.require' => 'Role wajib diisi',
'role.in' => 'Role harus owner atau kasir',
]); ]);
User::create([ User::create([
@ -44,6 +51,12 @@ class UserController extends Controller
'nama' => 'required|string|unique:users,nama,' . $id, 'nama' => 'required|string|unique:users,nama,' . $id,
'password' => 'nullable|min:6', 'password' => 'nullable|min:6',
'role' => 'required|in:owner,kasir', 'role' => 'required|in:owner,kasir',
], [
'nama.require' => 'Nama wajib diisi',
'nama.unique' => 'Nama sudah digunakan',
'password.min' => 'Password minimal 6 karakter',
'role.require' => 'Role wajib diisi',
'role.in' => 'Role harus owner atau kasir',
]); ]);
$data = [ $data = [
@ -52,7 +65,7 @@ class UserController extends Controller
]; ];
if ($request->filled('password')) { if ($request->filled('password')) {
$data['password'] = $request->password; $data['password'] = $request->password;
} }
$user->update($data); $user->update($data);

View File

@ -175,9 +175,8 @@ const data = ref(null);
const loading = ref(false); const loading = ref(false);
const loadingExport = ref(false); const loadingExport = ref(false);
// Sorting state
const sortBy = ref(null); const sortBy = ref(null);
const sortOrder = ref('asc'); // 'asc' or 'desc' const sortOrder = ref('asc');
const pagination = ref({ const pagination = ref({
current_page: 1, current_page: 1,
@ -188,14 +187,14 @@ const pagination = ref({
const pendapatanWidth = ref(0); const pendapatanWidth = ref(0);
const pendapatanElements = ref([]); const pendapatanElements = ref([]);
const salesDipilih = ref(null); const salesDipilih = ref(0);
const opsiSales = ref([ const opsiSales = ref([
{ label: 'Semua Sales', value: null, selected: true }, { label: 'Semua Sales', value: 0 },
]); ]);
const produkDipilih = ref(null); const produkDipilih = ref(0);
const opsiProduk = ref([ const opsiProduk = ref([
{ label: 'Semua Produk', value: null, selected: true }, { label: 'Semua Produk', value: 0 },
]); ]);
const namaPembeli = ref(null); const namaPembeli = ref(null);
@ -278,10 +277,8 @@ watch(nampan, async (newValue) => {
// --- Methods --- // --- Methods ---
const handleSort = (column) => { const handleSort = (column) => {
if (sortBy.value === column) { if (sortBy.value === column) {
// If same column, toggle sort order
sortOrder.value = sortOrder.value === 'asc' ? 'desc' : 'asc'; sortOrder.value = sortOrder.value === 'asc' ? 'desc' : 'asc';
} else { } else {
// If different column, set new column and default to ascending
sortBy.value = column; sortBy.value = column;
sortOrder.value = 'asc'; sortOrder.value = 'asc';
} }
@ -308,7 +305,7 @@ const fetchSales = async () => {
}); });
const salesData = response.data; const salesData = response.data;
opsiSales.value = [ opsiSales.value = [
{ label: 'Semua Sales', value: null }, { label: 'Semua Sales', value: 0 },
...salesData.map(sales => ({ ...salesData.map(sales => ({
label: sales.nama, label: sales.nama,
value: sales.id, value: sales.id,
@ -328,7 +325,7 @@ const fetchProduk = async () => {
}); });
const produkData = response.data; const produkData = response.data;
opsiProduk.value = [ opsiProduk.value = [
{ label: 'Semua Produk', value: null }, { label: 'Semua Produk', value: 0 },
...produkData.map(produk => ({ ...produkData.map(produk => ({
label: produk.nama, label: produk.nama,
value: produk.id, value: produk.id,
@ -346,8 +343,8 @@ const fetchData = async (page = 1) => {
pendapatanElements.value = []; pendapatanElements.value = [];
let queryParams = `tanggal=${tanggalDipilih.value}&page=${page}`; let queryParams = `tanggal=${tanggalDipilih.value}&page=${page}`;
if (salesDipilih.value) queryParams += `&sales_id=${salesDipilih.value}`; if (salesDipilih.value != 0 ) queryParams += `&sales_id=${salesDipilih.value}`;
if (produkDipilih.value) queryParams += `&produk_id=${produkDipilih.value}`; if (produkDipilih.value != 0) queryParams += `&produk_id=${produkDipilih.value}`;
if (namaPembeli.value) queryParams += `&nama_pembeli=${encodeURIComponent(namaPembeli.value)}`; if (namaPembeli.value) queryParams += `&nama_pembeli=${encodeURIComponent(namaPembeli.value)}`;
try { try {
@ -400,14 +397,14 @@ const selectExport = async (option) => {
loadingExport.value = true; loadingExport.value = true;
try { try {
const response = await axios.get('/api/laporan/export/detail-pernampan', { const response = await axios.get(`/api/laporan/export/detail-pernampan`, {
params: { params: {
tanggal: tanggalDipilih.value, tanggal: tanggalDipilih.value,
sales_id: salesDipilih.value,
produk_id: produkDipilih.value,
nama_pembeli: namaPembeli.value,
format: exportFormat.value, format: exportFormat.value,
page: pagination.value.current_page, page: pagination.value.current_page,
sales_id: salesDipilih.value != 0 ? salesDipilih.value : null,
produk_id: produkDipilih.value != 0 ? produkDipilih.value : null,
nama_pembeli: namaPembeli.value || null,
}, },
headers: { headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`, Authorization: `Bearer ${localStorage.getItem("token")}`,

View File

@ -183,14 +183,14 @@ const pagination = ref({
const pendapatanWidth = ref(0); const pendapatanWidth = ref(0);
const pendapatanElements = ref([]); const pendapatanElements = ref([]);
const salesDipilih = ref(null); const salesDipilih = ref(0);
const opsiSales = ref([ const opsiSales = ref([
{ label: 'Semua Sales', value: null, selected: true }, { label: 'Semua Sales', value: 0, selected: true },
]); ]);
const nampanDipilih = ref(null); const nampanDipilih = ref(0);
const opsiNampan = ref([ const opsiNampan = ref([
{ label: 'Semua Nampan', value: null, selected: true }, { label: 'Semua Nampan', value: 0, selected: true },
]); ]);
const namaPembeli = ref(null); const namaPembeli = ref(null);
@ -301,7 +301,7 @@ const fetchSales = async () => {
}); });
const salesData = response.data; const salesData = response.data;
opsiSales.value = [ opsiSales.value = [
{ label: 'Semua Sales', value: null }, { label: 'Semua Sales', value: 0 },
...salesData.map(sales => ({ ...salesData.map(sales => ({
label: sales.nama, label: sales.nama,
value: sales.id, value: sales.id,
@ -321,7 +321,7 @@ const fetchNampan = async () => {
}); });
const nampanData = response.data; const nampanData = response.data;
opsiNampan.value = [ opsiNampan.value = [
{ label: 'Semua Nampan', value: null }, { label: 'Semua Nampan', value: 0 },
{ label: 'Brankas', value: 0 }, { label: 'Brankas', value: 0 },
...nampanData.map(nampan => ({ ...nampanData.map(nampan => ({
label: nampan.nama, label: nampan.nama,
@ -340,9 +340,9 @@ const fetchData = async (page = 1) => {
pendapatanElements.value = []; pendapatanElements.value = [];
let queryParams = `tanggal=${tanggalDipilih.value}&page=${page}`; let queryParams = `tanggal=${tanggalDipilih.value}&page=${page}`;
if (salesDipilih.value != null) queryParams += `&sales_id=${salesDipilih.value}`; if (salesDipilih.value != 0 ) queryParams += `&sales_id=${salesDipilih.value}`;
if (nampanDipilih.value != null) queryParams += `&nampan_id=${nampanDipilih.value}`; if (nampanDipilih.value != 0) queryParams += `&produk_id=${produkDipilih.value}`;
if (namaPembeli.value != null || namaPembeli.value != '') queryParams += `&nama_pembeli=${encodeURIComponent(namaPembeli.value)}`; if (namaPembeli.value) queryParams += `&nama_pembeli=${encodeURIComponent(namaPembeli.value)}`;
try { try {
const response = await axios.get(`/api/laporan/detail-per-produk?${queryParams}`, { const response = await axios.get(`/api/laporan/detail-per-produk?${queryParams}`, {
@ -395,10 +395,11 @@ const selectExport = async (option) => {
const response = await axios.get('/api/laporan/export/detail-perproduk', { const response = await axios.get('/api/laporan/export/detail-perproduk', {
params: { params: {
tanggal: tanggalDipilih.value, tanggal: tanggalDipilih.value,
sales_id: salesDipilih.value,
nampan_id: nampanDipilih.value,
nama_pembeli: namaPembeli.value,
format: exportFormat.value, format: exportFormat.value,
page: pagination.value.current_page,
sales_id: salesDipilih.value != 0 ? salesDipilih.value : null,
nampan_id: nampanDipilih.value != 0 ? nampanDipilih.value : null,
nama_pembeli: namaPembeli.value || null,
}, },
headers: { headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`, Authorization: `Bearer ${localStorage.getItem("token")}`,

View File

@ -10,7 +10,6 @@ use App\Http\Controllers\SalesController;
use App\Http\Controllers\UserController; use App\Http\Controllers\UserController;
use App\Http\Controllers\TransaksiController; use App\Http\Controllers\TransaksiController;
use App\Http\Controllers\LaporanController; use App\Http\Controllers\LaporanController;
use App\Models\Kategori;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
@ -43,7 +42,7 @@ Route::prefix('api')->group(function () {
Route::get('ringkasan', [LaporanController::class, 'ringkasan']); Route::get('ringkasan', [LaporanController::class, 'ringkasan']);
Route::get('detail-per-produk', [LaporanController::class, 'detailPerProduk']); Route::get('detail-per-produk', [LaporanController::class, 'detailPerProduk']);
Route::get('detail-per-nampan', [LaporanController::class, 'detailPerNampan']); Route::get('detail-per-nampan', [LaporanController::class, 'detailPerNampan']);
Route::get('export/ringkasan', [LaporanController::class, 'exportRingkasan']); Route::get('export/ringkasan', [LaporanController::class, 'exportRingkasan']);
Route::get('export/detail-pernampan', [LaporanController::class, 'exportDetailNampan']); Route::get('export/detail-pernampan', [LaporanController::class, 'exportDetailNampan']);
Route::get('export/detail-perproduk', [LaporanController::class, 'exportDetailProduk']); Route::get('export/detail-perproduk', [LaporanController::class, 'exportDetailProduk']);