diff --git a/app/Http/Controllers/admin/InvoiceController.php b/app/Http/Controllers/admin/InvoiceController.php index 958e609..b4b132b 100644 --- a/app/Http/Controllers/admin/InvoiceController.php +++ b/app/Http/Controllers/admin/InvoiceController.php @@ -4,10 +4,13 @@ namespace App\Http\Controllers\admin; use App\Http\Controllers\Controller; use App\Http\Requests\InvoiceRequest; +use App\Models\Customer; +use App\Models\Payment; use App\Repositories\Invoice\InvoiceRepositoryInterface; use App\Repositories\Order\OrderRepositoryInterface; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; +use Yajra\DataTables\Facades\DataTables; class InvoiceController extends Controller { @@ -31,6 +34,46 @@ class InvoiceController extends Controller return view('administrator.pages.invoice.index', compact('title', 'invoices')); } + public function create() + { + $title = 'Add new Invoice'; + $customer = Customer::select('id', 'fullname')->where('status', 1)->get(); + $payment = Payment::select('id', 'name')->where('status', 1)->get(); + + return view('administrator.pages.invoice.add', compact('title', 'customer', 'payment')); + } + + public function store(Request $request) + { + $validated = $request->validate([ + 'customer_id' => 'required|numeric', + 'payment_id' => 'required|numeric', + 'sub_total' => 'required|numeric', + 'total' => 'required|numeric', + ]); + + $invoiceData = [ + 'date' => time(), + 'due_date' => time() + (7 * 24 * 60 * 60), + 'sub_total' => $validated['sub_total'], + 'tax' => $validated['sub_total'] * 0.1, + 'total' => $validated['total'], + 'payment_id' => $validated['payment_id'], + 'customer_id' => $validated['customer_id'], + 'status' => 0, + ]; + + DB::beginTransaction(); + try { + $invoice = $this->invoiceRepository->create($invoiceData); + DB::commit(); + return redirect()->route('administrator.pages.invoice.edit', ['id' => $invoice->id])->with('success', 'Invoice created successfully'); + } catch (\Exception $error) { + DB::rollBack(); + return back()->withErrors($error->getMessage()); + } + } + public function edit(int $id = 0) { $invoice = $this->invoiceRepository->findWithRelationships($id, ['payment', 'invoiceItem', 'customer']); @@ -96,4 +139,40 @@ class InvoiceController extends Controller return redirect()->route('administrator.pages.invoice.index')->with('success', 'Invoice deleted successfully'); } + + public function datatable(Request $request) + { + $query = $this->invoiceRepository->filter( + $request->all(), + ['payment', 'customer'], + [], + ['*'], + true + ); + + return DataTables::eloquent($query) + ->addColumn('invoice_num', function ($d) { + return view('administrator.pages.invoice.datatable.invoice_num', ['row' => $d])->render(); + }) + ->addColumn('date', function ($d) { + return view('administrator.pages.invoice.datatable.date', ['row' => $d])->render(); + }) + ->addColumn('customer', function ($d) { + return view('administrator.pages.invoice.datatable.customer', ['row' => $d])->render(); + }) + ->addColumn('payment', function ($d) { + return view('administrator.pages.invoice.datatable.payment', ['row' => $d])->render(); + }) + ->addColumn('total', function ($d) { + return view('administrator.pages.invoice.datatable.total', ['row' => $d])->render(); + }) + ->addColumn('status', function ($d) { + return view('administrator.pages.invoice.datatable.status', ['row' => $d])->render(); + }) + ->addColumn('action', function ($d) { + return view('administrator.pages.invoice.datatable.action', ['row' => $d])->render(); + }) + ->rawColumns(['invoice_num', 'date', 'customer', 'payment', 'total', 'status', 'action']) + ->make(true); + } } diff --git a/app/Repositories/Invoice/InvoiceCachedRepository.php b/app/Repositories/Invoice/InvoiceCachedRepository.php index a7b9b03..ea525a6 100644 --- a/app/Repositories/Invoice/InvoiceCachedRepository.php +++ b/app/Repositories/Invoice/InvoiceCachedRepository.php @@ -16,8 +16,12 @@ class InvoiceCachedRepository extends BaseCachedRepository implements InvoiceRep { return $this->invoiceRepository->getModel(); } - public function filter(array $data = [], array $relationships = [], array $withCount = [], array $select = ['*']) + public function filter(array $data = [], array $relationships = [], array $withCount = [], array $select = ['*'], bool $returnQuery = false) { + if ($returnQuery) { + return $this->invoiceRepository->filter($data, $relationships, $withCount, $select, $returnQuery); + } + $cacheKey = $this->getCacheKey(md5(json_encode([ 'filterItem' => [ 'data' => $data, diff --git a/app/Repositories/Invoice/InvoiceRepository.php b/app/Repositories/Invoice/InvoiceRepository.php index 425af94..73a9915 100644 --- a/app/Repositories/Invoice/InvoiceRepository.php +++ b/app/Repositories/Invoice/InvoiceRepository.php @@ -12,10 +12,13 @@ class InvoiceRepository extends BaseRepository implements InvoiceRepositoryInter { return Invoice::class; } - public function filter(array $data = [], array $relationships = [], array $withCount = [], array $select = ['*']) + public function filter(array $data = [], array $relationships = [], array $withCount = [], array $select = ['*'], bool $returnQuery = false) { $model = $this->model->with($relationships)->select($select); + if (isset($data['client']) && ! empty($data['client'])) { + $model = $model->where("customer_id", $data['client']); + } if (isset($data['invoice_type'])) { $model = $model->where("invoice_type", $data['invoice_type']); } @@ -86,6 +89,11 @@ class InvoiceRepository extends BaseRepository implements InvoiceRepositoryInter if (count($withCount) > 0) { $model = $model->withCount($withCount); } + + if ($returnQuery) { + return $model; + } + if (isset($data['limit']) && $data['limit']) { return $model->latest('id')->take($data['limit'])->get(); } diff --git a/app/Repositories/Invoice/InvoiceRepositoryInterface.php b/app/Repositories/Invoice/InvoiceRepositoryInterface.php index 3c2e673..bf55feb 100644 --- a/app/Repositories/Invoice/InvoiceRepositoryInterface.php +++ b/app/Repositories/Invoice/InvoiceRepositoryInterface.php @@ -5,7 +5,7 @@ namespace App\Repositories\Invoice; use App\Repositories\BaseRepositoryInterface; interface InvoiceRepositoryInterface extends BaseRepositoryInterface{ - public function filter(array $data = [],array $relationships = [],array $withCount = [],array $select = ['*']); + public function filter(array $data = [],array $relationships = [],array $withCount = [],array $select = ['*'], bool $returnQuery = false); public function get_billing_year(int $year = 0); public function get_billing_month(int $month = 0); public function get_billing_day(int|string $day = ''); diff --git a/resources/sass/_fonts.scss b/resources/sass/_fonts.scss index a17b90b..9c9a366 100644 --- a/resources/sass/_fonts.scss +++ b/resources/sass/_fonts.scss @@ -1,125 +1 @@ -@font-face { - font-family: 'Be Vietnam Pro'; - src: url('/fonts/bevietnampro/BeVietnamPro-Thin.ttf') format('truetype'); - font-weight: 100; - font-style: normal; -} - -@font-face { - font-family: 'Be Vietnam Pro'; - src: url('/fonts/bevietnampro/BeVietnamPro-ThinItalic.ttf') format('truetype'); - font-weight: 100; - font-style: italic; -} - -@font-face { - font-family: 'Be Vietnam Pro'; - src: url('/fonts/bevietnampro/BeVietnamPro-ExtraLight.ttf') format('truetype'); - font-weight: 200; - font-style: normal; -} - -@font-face { - font-family: 'Be Vietnam Pro'; - src: url('/fonts/bevietnampro/BeVietnamPro-ExtraLightItalic.ttf') format('truetype'); - font-weight: 200; - font-style: italic; -} - -@font-face { - font-family: 'Be Vietnam Pro'; - src: url('/fonts/bevietnampro/BeVietnamPro-Light.ttf') format('truetype'); - font-weight: 300; - font-style: normal; -} - -@font-face { - font-family: 'Be Vietnam Pro'; - src: url('/fonts/bevietnampro/BeVietnamPro-LightItalic.ttf') format('truetype'); - font-weight: 300; - font-style: italic; -} - -@font-face { - font-family: 'Be Vietnam Pro'; - src: url('/fonts/bevietnampro/BeVietnamPro-Regular.ttf') format('truetype'); - font-weight: 400; - font-style: normal; -} - -@font-face { - font-family: 'Be Vietnam Pro'; - src: url('/fonts/bevietnampro/BeVietnamPro-Italic.ttf') format('truetype'); - font-weight: 400; - font-style: italic; -} - -@font-face { - font-family: 'Be Vietnam Pro'; - src: url('/fonts/bevietnampro/BeVietnamPro-Medium.ttf') format('truetype'); - font-weight: 500; - font-style: normal; -} - -@font-face { - font-family: 'Be Vietnam Pro'; - src: url('/fonts/bevietnampro/BeVietnamPro-MediumItalic.ttf') format('truetype'); - font-weight: 500; - font-style: italic; -} - -@font-face { - font-family: 'Be Vietnam Pro'; - src: url('/fonts/bevietnampro/BeVietnamPro-SemiBold.ttf') format('truetype'); - font-weight: 600; - font-style: normal; -} - -@font-face { - font-family: 'Be Vietnam Pro'; - src: url('/fonts/bevietnampro/BeVietnamPro-SemiBoldItalic.ttf') format('truetype'); - font-weight: 600; - font-style: italic; -} - -@font-face { - font-family: 'Be Vietnam Pro'; - src: url('/fonts/bevietnampro/BeVietnamPro-Bold.ttf') format('truetype'); - font-weight: 700; - font-style: normal; -} - -@font-face { - font-family: 'Be Vietnam Pro'; - src: url('/fonts/bevietnampro/BeVietnamPro-BoldItalic.ttf') format('truetype'); - font-weight: 700; - font-style: italic; -} - -@font-face { - font-family: 'Be Vietnam Pro'; - src: url('/fonts/bevietnampro/BeVietnamPro-ExtraBold.ttf') format('truetype'); - font-weight: 800; - font-style: normal; -} - -@font-face { - font-family: 'Be Vietnam Pro'; - src: url('/fonts/bevietnampro/BeVietnamPro-ExtraBoldItalic.ttf') format('truetype'); - font-weight: 800; - font-style: italic; -} - -@font-face { - font-family: 'Be Vietnam Pro'; - src: url('/fonts/bevietnampro/BeVietnamPro-Black.ttf') format('truetype'); - font-weight: 900; - font-style: normal; -} - -@font-face { - font-family: 'Be Vietnam Pro'; - src: url('/fonts/bevietnampro/BeVietnamPro-BlackItalic.ttf') format('truetype'); - font-weight: 900; - font-style: italic; -} +@import url('https://fonts.googleapis.com/css2?family=Inter+Tight:ital,wght@0,100..900;1,100..900&display=swap'); diff --git a/resources/sass/_variables.scss b/resources/sass/_variables.scss index abfc971..6a1a181 100644 --- a/resources/sass/_variables.scss +++ b/resources/sass/_variables.scss @@ -233,7 +233,7 @@ $component-hover-bg: rgba($secondary, .2); // custom variable // Font, line-height, and color for body text, headings, and more. // Font family -$font-family-sans-serif: "Be Vietnam Pro", Helvetica, sans-serif !default; +$font-family-sans-serif: "Inter Tight", Helvetica, sans-serif !default; $font-size-base: 0.875rem !default; // 14px $font-size-lg: 1rem !default; // 16px diff --git a/resources/views/administrator/components/data-table.blade.php b/resources/views/administrator/components/data-table.blade.php index c02fa65..ecbdaa1 100644 --- a/resources/views/administrator/components/data-table.blade.php +++ b/resources/views/administrator/components/data-table.blade.php @@ -1,14 +1,21 @@ @php - $dtColumns = collect($columns)->map(function ($c) { + $dtColumns = collect($columns)->map(function ($c, $index) { return [ 'data' => $c['key'], 'name' => $c['key'], 'orderable' => $c['orderable'] ?? true, 'searchable' => $c['searchable'] ?? true, + 'visible' => $c['visible'] ?? true, ]; })->values(); @endphp +
| - - | -Invoice # | -Client Name | -Date | -Payment Method | -Total | -Status | -- | - |
|---|---|---|---|---|---|---|---|---|
| - - | -- $item->id]) }}" - title="View Order"> {{ $item->id }} - | -- @isset($item->customer->firstname) - {{ $item->customer->firstname . ' ' . $item->customer->lastname }} - @endisset - | -- @time($item->date) - | -- {{ $item->payment->name ?? 'VN Pay' }} - | -- {{ number_format($item->total,0,',','.') }}đ - | -- {!! $item->getStatus() !!} - | -- - - - | -- @if(auth()->guard('admins')->user()->can("delete invoice")) - - @endif - | -