Bladeren bron

fix: report master

Muhammad Iqbal Afandi 4 jaren geleden
bovenliggende
commit
a0c0c4788d

+ 1
- 1
app/Http/Controllers/CustomerController.php Bestand weergeven

22
     {
22
     {
23
         return inertia("Customers/Index", [
23
         return inertia("Customers/Index", [
24
             "initialSearch" => request("search"),
24
             "initialSearch" => request("search"),
25
-            "customers" => Customer::filter(request()->only("search"))
25
+            "customers" => Customer::search(request()->only("search"))
26
                 ->latest()
26
                 ->latest()
27
                 ->paginate(10)
27
                 ->paginate(10)
28
                 ->withQueryString()
28
                 ->withQueryString()

+ 1
- 1
app/Http/Controllers/ProductController.php Bestand weergeven

23
     {
23
     {
24
         return inertia("Products/Index", [
24
         return inertia("Products/Index", [
25
             "initialSearch" => request("search"),
25
             "initialSearch" => request("search"),
26
-            "products" => Product::filter(request()->only("search"))
26
+            "products" => Product::search(request()->only("search"))
27
                 ->latest()
27
                 ->latest()
28
                 ->paginate(10)
28
                 ->paginate(10)
29
                 ->withQueryString()
29
                 ->withQueryString()

+ 4
- 4
app/Http/Controllers/PurchaseController.php Bestand weergeven

34
     {
34
     {
35
         return inertia("Purchases/Index", [
35
         return inertia("Purchases/Index", [
36
             "initialSearch" => request("search"),
36
             "initialSearch" => request("search"),
37
-            "purchases" => Purchase::filter(request()->only("search"))
37
+            "purchases" => Purchase::search(request()->only("search"))
38
                 ->latest()
38
                 ->latest()
39
                 ->paginate(10)
39
                 ->paginate(10)
40
                 ->withQueryString()
40
                 ->withQueryString()
66
             "ppn" => Ppn::first()->ppn,
66
             "ppn" => Ppn::first()->ppn,
67
             "productNumber" => "PDK" . now()->format("YmdHis"),
67
             "productNumber" => "PDK" . now()->format("YmdHis"),
68
             "suppliers" => Inertia::lazy(
68
             "suppliers" => Inertia::lazy(
69
-                fn() => Supplier::filter([
69
+                fn() => Supplier::search([
70
                     "search" => request("supplier"),
70
                     "search" => request("supplier"),
71
                 ])->get()
71
                 ])->get()
72
             ),
72
             ),
73
             "products" => Inertia::lazy(
73
             "products" => Inertia::lazy(
74
-                fn() => Product::filter(["search" => request("product")])->get()
74
+                fn() => Product::search(["search" => request("product")])->get()
75
             ),
75
             ),
76
             "productPurchase" => Inertia::lazy(
76
             "productPurchase" => Inertia::lazy(
77
                 fn() => PurchaseDetail::historyProductPurchase(
77
                 fn() => PurchaseDetail::historyProductPurchase(
181
             "ppnChecked" => $purchase->ppn ? true : false,
181
             "ppnChecked" => $purchase->ppn ? true : false,
182
             "supplier" => $purchase->supplier,
182
             "supplier" => $purchase->supplier,
183
             "products" => Inertia::lazy(
183
             "products" => Inertia::lazy(
184
-                fn() => Product::filter(["search" => request("product")])->get()
184
+                fn() => Product::search(["search" => request("product")])->get()
185
             ),
185
             ),
186
             "purchaseDetail" => $purchase->purchaseDetail->transform(
186
             "purchaseDetail" => $purchase->purchaseDetail->transform(
187
                 fn($purchase) => [
187
                 fn($purchase) => [

+ 45
- 4
app/Http/Controllers/SalesController.php Bestand weergeven

12
 use App\Http\Requests\Sales\StoreSaleRequest;
12
 use App\Http\Requests\Sales\StoreSaleRequest;
13
 use App\Http\Requests\Sales\UpdateSaleRequest;
13
 use App\Http\Requests\Sales\UpdateSaleRequest;
14
 use App\Models\Company;
14
 use App\Models\Company;
15
+use App\Models\SaleDetail;
15
 use App\Services\FunctionService;
16
 use App\Services\FunctionService;
16
 use App\Services\SaleService;
17
 use App\Services\SaleService;
17
 use Barryvdh\DomPDF\Facade\Pdf;
18
 use Barryvdh\DomPDF\Facade\Pdf;
32
     {
33
     {
33
         return inertia("Sales/Index", [
34
         return inertia("Sales/Index", [
34
             "initialSearch" => request("search"),
35
             "initialSearch" => request("search"),
35
-            "sales" => Sale::filter(request()->only("search"))
36
+            "sales" => Sale::search(request()->only("search"))
36
                 ->latest()
37
                 ->latest()
37
                 ->paginate(10)
38
                 ->paginate(10)
38
                 ->withQueryString()
39
                 ->withQueryString()
63
             "number" => "PJN" . now()->format("YmdHis"),
64
             "number" => "PJN" . now()->format("YmdHis"),
64
             "ppn" => Ppn::first()->ppn,
65
             "ppn" => Ppn::first()->ppn,
65
             "customers" => Inertia::lazy(
66
             "customers" => Inertia::lazy(
66
-                fn() => Customer::filter([
67
+                fn() => Customer::search([
67
                     "search" => request("customer"),
68
                     "search" => request("customer"),
68
                 ])->get()
69
                 ])->get()
69
             ),
70
             ),
70
             "stockProducts" => Inertia::lazy(
71
             "stockProducts" => Inertia::lazy(
71
-                fn() => StockProduct::filter([
72
+                fn() => StockProduct::search([
72
                     "search" => request("stockProduct"),
73
                     "search" => request("stockProduct"),
73
                 ])
74
                 ])
74
                     ->get()
75
                     ->get()
229
 
230
 
230
     public function report()
231
     public function report()
231
     {
232
     {
232
-        return inertia("Sales/Report");
233
+        return inertia("Sales/Report", [
234
+            "params" => [
235
+                "filters" => request()->only("start_date", "end_date"),
236
+            ],
237
+            "sales" => Inertia::lazy(
238
+                fn() => SaleDetail::filter(
239
+                    request()->only("start_date", "end_date")
240
+                )
241
+                    ->latest()
242
+                    ->paginate(10)
243
+                    ->withQueryString()
244
+                    ->through(
245
+                        fn($saleDetail) => [
246
+                            "updatedAt" => $saleDetail->updated_at,
247
+                            "totalPrice" => FunctionService::rupiahFormat(
248
+                                $saleDetail->price * $saleDetail->qty
249
+                            ),
250
+                            "status" => $saleDetail->sale->status,
251
+                        ]
252
+                    )
253
+            ),
254
+            // "data" => [
255
+            //     "sales" => Inertia::lazy(
256
+            //         fn() => SaleDetail::filter(
257
+            //             request()->only("start_date", "end_date")
258
+            //         )
259
+            //             ->latest()
260
+            //             ->paginate(10)
261
+            //             ->withQueryString()
262
+            //             ->through(
263
+            //                 fn($saleDetail) => [
264
+            //                     "updatedAt" => $saleDetail->updated_at,
265
+            //                     "totalPrice" => FunctionService::rupiahFormat(
266
+            //                         $saleDetail->price * $saleDetail->qty
267
+            //                     ),
268
+            //                     "status" => $saleDetail->sale->status,
269
+            //                 ]
270
+            //             )
271
+            //     ),
272
+            // ],
273
+        ]);
233
     }
274
     }
234
 
275
 
235
     public function reportExcel()
276
     public function reportExcel()

+ 1
- 1
app/Http/Controllers/StockProductController.php Bestand weergeven

22
     {
22
     {
23
         return inertia("StockProducts/Index", [
23
         return inertia("StockProducts/Index", [
24
             "initialSearch" => request("search"),
24
             "initialSearch" => request("search"),
25
-            "stockProducts" => StockProduct::filter(request()->only("search"))
25
+            "stockProducts" => StockProduct::search(request()->only("search"))
26
                 ->latest()
26
                 ->latest()
27
                 ->paginate(10)
27
                 ->paginate(10)
28
                 ->withQueryString()
28
                 ->withQueryString()

+ 1
- 1
app/Http/Controllers/UserController.php Bestand weergeven

26
     {
26
     {
27
         return inertia("Users/Index", [
27
         return inertia("Users/Index", [
28
             "initialSearch" => request("search"),
28
             "initialSearch" => request("search"),
29
-            "users" => User::filter(request()->only("search"))
29
+            "users" => User::search(request()->only("search"))
30
                 ->latest()
30
                 ->latest()
31
                 ->paginate(10)
31
                 ->paginate(10)
32
                 ->withQueryString()
32
                 ->withQueryString()

+ 1
- 1
app/Models/Customer.php Bestand weergeven

18
         return $this->hasMany(Sale::class);
18
         return $this->hasMany(Sale::class);
19
     }
19
     }
20
 
20
 
21
-    public function scopeFilter($query, array $filters)
21
+    public function scopeSearch($query, array $filters)
22
     {
22
     {
23
         $query->when($filters["search"] ?? null, function ($query, $search) {
23
         $query->when($filters["search"] ?? null, function ($query, $search) {
24
             $query->where(function ($query) use ($search) {
24
             $query->where(function ($query) use ($search) {

+ 1
- 1
app/Models/Product.php Bestand weergeven

35
         return $this->hasMany(SaleDetail::class, "product_number", "number");
35
         return $this->hasMany(SaleDetail::class, "product_number", "number");
36
     }
36
     }
37
 
37
 
38
-    public function scopeFilter($query, array $filters)
38
+    public function scopeSearch($query, array $filters)
39
     {
39
     {
40
         $query->when($filters["search"] ?? null, function ($query, $search) {
40
         $query->when($filters["search"] ?? null, function ($query, $search) {
41
             $query->where(function ($query) use ($search) {
41
             $query->where(function ($query) use ($search) {

+ 1
- 1
app/Models/Purchase.php Bestand weergeven

38
         return $this->belongsTo(Supplier::class);
38
         return $this->belongsTo(Supplier::class);
39
     }
39
     }
40
 
40
 
41
-    public function scopeFilter($query, array $filters)
41
+    public function scopeSearch($query, array $filters)
42
     {
42
     {
43
         $query->when($filters["search"] ?? null, function ($query, $search) {
43
         $query->when($filters["search"] ?? null, function ($query, $search) {
44
             $query
44
             $query

+ 1
- 1
app/Models/Sale.php Bestand weergeven

34
         return $this->belongsTo(Customer::class);
34
         return $this->belongsTo(Customer::class);
35
     }
35
     }
36
 
36
 
37
-    public function scopeFilter($query, array $filters)
37
+    public function scopeSearch($query, array $filters)
38
     {
38
     {
39
         $query->when($filters["search"] ?? null, function ($query, $search) {
39
         $query->when($filters["search"] ?? null, function ($query, $search) {
40
             $query
40
             $query

+ 22
- 1
app/Models/SaleDetail.php Bestand weergeven

2
 
2
 
3
 namespace App\Models;
3
 namespace App\Models;
4
 
4
 
5
+use Carbon\Carbon;
5
 use App\Services\FunctionService;
6
 use App\Services\FunctionService;
7
+use Illuminate\Database\Eloquent\Model;
6
 use Illuminate\Database\Eloquent\Casts\Attribute;
8
 use Illuminate\Database\Eloquent\Casts\Attribute;
7
 use Illuminate\Database\Eloquent\Factories\HasFactory;
9
 use Illuminate\Database\Eloquent\Factories\HasFactory;
8
-use Illuminate\Database\Eloquent\Model;
9
 
10
 
10
 class SaleDetail extends Model
11
 class SaleDetail extends Model
11
 {
12
 {
13
 
14
 
14
     protected $fillable = ["price", "qty", "sale_number", "product_number"];
15
     protected $fillable = ["price", "qty", "sale_number", "product_number"];
15
 
16
 
17
+    protected function updatedAt(): Attribute
18
+    {
19
+        return Attribute::make(
20
+            get: fn($value) => Carbon::parse($value)->translatedFormat(
21
+                "l d/m/y"
22
+            )
23
+        );
24
+    }
25
+
16
     protected function price(): Attribute
26
     protected function price(): Attribute
17
     {
27
     {
18
         return Attribute::make(
28
         return Attribute::make(
51
                 });
61
                 });
52
             });
62
             });
53
     }
63
     }
64
+
65
+    public function scopeFilter($query, array $filters)
66
+    {
67
+        $query
68
+            ->when($filters["start_date"] ?? null, function ($query, $search) {
69
+                $query->whereDate("created_at", ">=", $search);
70
+            })
71
+            ->when($filters["end_date"] ?? null, function ($query, $search) {
72
+                $query->whereDate("created_at", "<=", $search);
73
+            });
74
+    }
54
 }
75
 }

+ 1
- 1
app/Models/StockProduct.php Bestand weergeven

40
         return $this->belongsTo(Product::class, "product_number", "number");
40
         return $this->belongsTo(Product::class, "product_number", "number");
41
     }
41
     }
42
 
42
 
43
-    public function scopeFilter($query, array $filters)
43
+    public function scopeSearch($query, array $filters)
44
     {
44
     {
45
         $query
45
         $query
46
             ->when($filters["search"] ?? null, function ($query, $search) {
46
             ->when($filters["search"] ?? null, function ($query, $search) {

+ 1
- 1
app/Models/Supplier.php Bestand weergeven

18
         return $this->hasMany(Purchase::class);
18
         return $this->hasMany(Purchase::class);
19
     }
19
     }
20
 
20
 
21
-    public function scopeFilter($query, array $filters)
21
+    public function scopeSearch($query, array $filters)
22
     {
22
     {
23
         $query->when($filters["search"] ?? null, function ($query, $search) {
23
         $query->when($filters["search"] ?? null, function ($query, $search) {
24
             $query->where(function ($query) use ($search) {
24
             $query->where(function ($query) use ($search) {

+ 1
- 1
app/Models/User.php Bestand weergeven

45
         return $this->belongsTo(Role::class);
45
         return $this->belongsTo(Role::class);
46
     }
46
     }
47
 
47
 
48
-    public function scopeFilter($query, array $filters)
48
+    public function scopeSearch($query, array $filters)
49
     {
49
     {
50
         $query->when($filters["search"] ?? null, function ($query, $search) {
50
         $query->when($filters["search"] ?? null, function ($query, $search) {
51
             $query->where(function ($query) use ($search) {
51
             $query->where(function ($query) use ($search) {

+ 79
- 0
resources/js/components/AppFilterDateRange.vue Bestand weergeven

1
+<script setup>
2
+import { onMounted, reactive, watch } from 'vue'
3
+import { Inertia } from '@inertiajs/inertia'
4
+import dayjs from 'dayjs'
5
+import { pickBy } from 'lodash'
6
+
7
+const props = defineProps({
8
+  initialFilter: {
9
+    type: Object,
10
+    required: true,
11
+  },
12
+  refreshData: {
13
+    type: String,
14
+    required: true,
15
+  },
16
+})
17
+
18
+const filters = reactive({
19
+  dates: null,
20
+  startDate: null,
21
+  endDate: null,
22
+})
23
+
24
+onMounted(() => {
25
+  if (props.initialFilter.start_date || props.initialFilter.end_date) {
26
+    if (props.initialFilter.end_date) {
27
+      filters.dates = [
28
+        new Date(props.initialFilter.start_date),
29
+        new Date(props.initialFilter.end_date),
30
+      ]
31
+    } else {
32
+      filters.dates = [new Date(props.initialFilter.start_date), null]
33
+    }
34
+  }
35
+})
36
+
37
+watch(
38
+  () => filters.dates,
39
+  () => {
40
+    if (filters.dates[1]) {
41
+      filters.startDate = dayjs(filters.dates[0]).format('YYYY-MM-DD')
42
+
43
+      filters.endDate = dayjs(filters.dates[1]).format('YYYY-MM-DD')
44
+    } else if (filters.dates[0]) {
45
+      filters.startDate = dayjs(filters.dates[0]).format('YYYY-MM-DD')
46
+
47
+      filters.endDate = null
48
+
49
+      removeParams('end_date')
50
+    }
51
+
52
+    Inertia.reload({
53
+      data: pickBy({
54
+        start_date: filters.startDate,
55
+        end_date: filters.endDate,
56
+      }),
57
+      only: [props.refreshData],
58
+    })
59
+  }
60
+)
61
+
62
+const removeParams = (...params) => {
63
+  const urlParams = new URLSearchParams(location.search)
64
+
65
+  params.forEach((value) => urlParams.delete(value))
66
+
67
+  window.history.replaceState({}, '', `${location.pathname}?${urlParams}`)
68
+}
69
+</script>
70
+
71
+<template>
72
+  <Calendar
73
+    class="w-full"
74
+    selection-mode="range"
75
+    date-format="dd/mm/yy"
76
+    :manual-input="false"
77
+    v-model="filters.dates"
78
+  />
79
+</template>

+ 0
- 45
resources/js/composables/useDateRangeFilter.js Bestand weergeven

1
-import { onMounted, watch, ref } from 'vue'
2
-import dayjs from 'dayjs'
3
-
4
-export function useDateRangeFilter(props) {
5
-  const dates = ref(null)
6
-
7
-  const startDate = ref(null)
8
-
9
-  const endDate = ref(null)
10
-
11
-  onMounted(() => {
12
-    if (!props.initialDateRange) {
13
-      return
14
-    }
15
-
16
-    if (props.initialDateRange[0] || props.initialDateRange[1]) {
17
-      if (props.initialDateRange[1]) {
18
-        dates.value = [
19
-          new Date(props.initialDateRange[0]),
20
-          new Date(props.initialDateRange[1]),
21
-        ]
22
-      } else {
23
-        dates.value = [new Date(props.props.initialDateRange[1]), null]
24
-      }
25
-    }
26
-  })
27
-
28
-  watch(dates, () => {
29
-    if (dates.value[1]) {
30
-      startDate.value = dayjs(dates.value[0]).format('YYYY-MM-DD')
31
-
32
-      endDate.value = dayjs(dates.value[1]).format('YYYY-MM-DD')
33
-    } else if (dates.value[0]) {
34
-      startDate.value = dayjs(dates.value[0]).format('YYYY-MM-DD')
35
-
36
-      endDate.value = null
37
-    }
38
-  })
39
-
40
-  return {
41
-    dates,
42
-    startDate,
43
-    endDate,
44
-  }
45
-}

+ 34
- 1
resources/js/pages/Sales/Report.vue Bestand weergeven

1
 <script setup>
1
 <script setup>
2
+import { reportTable } from './config'
3
+import AppFilterDateRange from '@/components/AppFilterDateRange.vue'
2
 import DashboardLayout from '@/layouts/Dashboard/DashboardLayout.vue'
4
 import DashboardLayout from '@/layouts/Dashboard/DashboardLayout.vue'
5
+
6
+defineProps({
7
+  params: Object,
8
+  sales: Object,
9
+})
3
 </script>
10
 </script>
4
 
11
 
5
 <template>
12
 <template>
6
   <DashboardLayout title="Laporan Penjualan">
13
   <DashboardLayout title="Laporan Penjualan">
7
-    <h1>Laporan Penjualan</h1>
14
+    <DataTable
15
+      responsive-layout="scroll"
16
+      column-resize-mode="expand"
17
+      :rowHover="true"
18
+      :stripedRows="true"
19
+    >
20
+      <template #header>
21
+        <h1>Laporan Penjualan</h1>
22
+
23
+        <div class="grid">
24
+          <div class="col-12 sm:col-6 lg:col-4">
25
+            <AppFilterDateRange
26
+              placeholder="filter waktu..."
27
+              refresh-data="sales"
28
+              :initial-filter="params.filters"
29
+            />
30
+          </div>
31
+        </div>
32
+      </template>
33
+
34
+      <Column
35
+        v-for="value in reportTable"
36
+        :field="value.field"
37
+        :header="value.header"
38
+        :key="value.field"
39
+      />
40
+    </DataTable>
8
   </DashboardLayout>
41
   </DashboardLayout>
9
 </template>
42
 </template>

+ 6
- 0
resources/js/pages/Sales/config.js Bestand weergeven

24
   { field: 'qty', header: 'Kuantitas' },
24
   { field: 'qty', header: 'Kuantitas' },
25
   { field: 'unit', header: 'Satuan' },
25
   { field: 'unit', header: 'Satuan' },
26
 ]
26
 ]
27
+
28
+export const reportTable = [
29
+  { field: 'updatedAt', header: 'Tanggal' },
30
+  { field: 'totalPrice', header: 'Total Harga' },
31
+  { field: 'status', header: 'Status' },
32
+]

+ 8
- 0
resources/js/utils/helpers.js Bestand weergeven

22
   }
22
   }
23
 }
23
 }
24
 
24
 
25
+export function removeParams(...params) {
26
+  const urlParams = new URLSearchParams(location.search)
27
+
28
+  params.forEach((value) => urlParams.delete(value))
29
+
30
+  window.history.replaceState({}, '', `${location.pathname}?${urlParams}`)
31
+}
32
+
25
 export class FormValidationError extends Error {
33
 export class FormValidationError extends Error {
26
   constructor(message, errors) {
34
   constructor(message, errors) {
27
     super(message)
35
     super(message)

+ 3
- 3
routes/web.php Bestand weergeven

54
 
54
 
55
     Route::resource("/customers", CustomerController::class);
55
     Route::resource("/customers", CustomerController::class);
56
 
56
 
57
-    Route::resource("/purchases", PurchaseController::class);
58
-
59
     Route::get("/purchases/pdf/invoice/{purchase}", [
57
     Route::get("/purchases/pdf/invoice/{purchase}", [
60
         PurchaseController::class,
58
         PurchaseController::class,
61
         "invoice",
59
         "invoice",
73
 
71
 
74
     Route::get("/purchases/report", [PurchaseController::class, "report"]);
72
     Route::get("/purchases/report", [PurchaseController::class, "report"]);
75
 
73
 
76
-    Route::resource("/sales", SalesController::class);
74
+    Route::resource("/purchases", PurchaseController::class);
77
 
75
 
78
     Route::get("/sales/pdf/invoice/{sale}", [
76
     Route::get("/sales/pdf/invoice/{sale}", [
79
         SalesController::class,
77
         SalesController::class,
92
 
90
 
93
     Route::get("/sales/report", [SalesController::class, "report"]);
91
     Route::get("/sales/report", [SalesController::class, "report"]);
94
 
92
 
93
+    Route::resource("/sales", SalesController::class);
94
+
95
     Route::resource("/suppliers", SupplierController::class);
95
     Route::resource("/suppliers", SupplierController::class);
96
 
96
 
97
     Route::resource("/stock-products", StockProductController::class);
97
     Route::resource("/stock-products", StockProductController::class);

+ 0
- 2
storage/framework/cache/data/.gitignore Bestand weergeven

1
-*
2
-!.gitignore