From 0558017aab07f0bb494e3cf1908621425fe10dd0 Mon Sep 17 00:00:00 2001 From: Bagas Udi Sahsangka Date: Sun, 15 Sep 2019 13:45:53 +0700 Subject: [PATCH] add members --- .env-prod | 44 +++ app/GroupMember.php | 10 + .../Controllers/GroupMemberController.php | 72 +++++ .../Controllers/MemberVehicleController.php | 14 + .../Controllers/ParkingGateController.php | 4 + .../Controllers/ParkingMemberController.php | 80 +++-- app/Http/Requests/GroupMemberRequest.php | 30 ++ app/Http/Requests/MemberVehicleRequest.php | 36 +++ app/Http/Requests/ParkingMemberRequest.php | 18 +- app/MemberVehicle.php | 14 + app/ParkingMember.php | 13 +- ...9_07_154619_create_group_members_table.php | 36 +++ ...11_103028_create_member_vehicles_table.php | 38 +++ ...27_drop_some_columns_on_parking_member.php | 45 +++ install.sh | 61 ++++ parking | 36 +++ parking.conf | 3 + resources/js/App.vue | 8 +- .../js/components/ParkingMemberDetail.vue | 57 ++++ resources/js/pages/GateOutApp.vue | 17 - resources/js/pages/GroupMember.vue | 221 +++++++++++++ resources/js/pages/Member.vue | 18 -- resources/js/pages/Notification.vue | 4 +- resources/js/pages/ParkingGate.vue | 32 +- resources/js/pages/ParkingMember.vue | 298 +++++++++++++----- resources/js/pages/ParkingTransaction.vue | 2 +- resources/js/pages/Setting.vue | 20 +- resources/js/pages/User.vue | 4 +- resources/js/router.js | 6 +- resources/js/store.js | 7 +- routes/web.php | 5 +- storage/app/.gitignore | 0 storage/app/public/.gitignore | 0 storage/framework/.gitignore | 0 storage/framework/cache/.gitignore | 0 storage/framework/cache/data/.gitignore | 0 storage/framework/sessions/.gitignore | 0 storage/framework/testing/.gitignore | 0 storage/framework/views/.gitignore | 0 storage/logs/.gitignore | 0 40 files changed, 1066 insertions(+), 187 deletions(-) create mode 100644 .env-prod create mode 100644 app/GroupMember.php create mode 100644 app/Http/Controllers/GroupMemberController.php create mode 100644 app/Http/Controllers/MemberVehicleController.php create mode 100644 app/Http/Requests/GroupMemberRequest.php create mode 100644 app/Http/Requests/MemberVehicleRequest.php create mode 100644 app/MemberVehicle.php create mode 100644 database/migrations/2019_09_07_154619_create_group_members_table.php create mode 100644 database/migrations/2019_09_11_103028_create_member_vehicles_table.php create mode 100644 database/migrations/2019_09_11_105527_drop_some_columns_on_parking_member.php create mode 100755 install.sh create mode 100755 parking create mode 100644 parking.conf create mode 100644 resources/js/components/ParkingMemberDetail.vue create mode 100644 resources/js/pages/GroupMember.vue delete mode 100644 resources/js/pages/Member.vue mode change 100644 => 100755 storage/app/.gitignore mode change 100644 => 100755 storage/app/public/.gitignore mode change 100644 => 100755 storage/framework/.gitignore mode change 100644 => 100755 storage/framework/cache/.gitignore mode change 100644 => 100755 storage/framework/cache/data/.gitignore mode change 100644 => 100755 storage/framework/sessions/.gitignore mode change 100644 => 100755 storage/framework/testing/.gitignore mode change 100644 => 100755 storage/framework/views/.gitignore mode change 100644 => 100755 storage/logs/.gitignore diff --git a/.env-prod b/.env-prod new file mode 100644 index 00000000..55fd5012 --- /dev/null +++ b/.env-prod @@ -0,0 +1,44 @@ +APP_NAME="MITRATEKNIK PARKING SYSTEM" +APP_ENV=local +APP_KEY= +APP_DEBUG=true +APP_URL=http://localhost + +LOG_CHANNEL=stack + +DB_CONNECTION=mysql +DB_HOST=127.0.0.1 +DB_PORT=3306 +DB_DATABASE=parking_system +DB_USERNAME=parking_system +DB_PASSWORD="Bismillah1@#$%" + +BROADCAST_DRIVER=log +CACHE_DRIVER=file +QUEUE_CONNECTION=sync +SESSION_DRIVER=file +SESSION_LIFETIME=120 + +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 + +MAIL_DRIVER=smtp +MAIL_HOST=smtp.mailtrap.io +MAIL_PORT=2525 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= + +PUSHER_APP_ID= +PUSHER_APP_KEY= +PUSHER_APP_SECRET= +PUSHER_APP_CLUSTER=mt1 + +MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" +MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" diff --git a/app/GroupMember.php b/app/GroupMember.php new file mode 100644 index 00000000..89b23391 --- /dev/null +++ b/app/GroupMember.php @@ -0,0 +1,10 @@ +middleware('role:1'); + } + + /** + * Display a listing of the resource. + * + * @return \Illuminate\Http\Response + */ + public function index(Request $request) + { + $sort = $request->sort ? $request->sort : 'name'; + $order = $request->order == 'ascending' ? 'asc' : 'desc'; + + return GroupMember::when($request->keyword, function ($q) use ($request) { + return $q->where('name', 'LIKE', '%' . $request->keyword . '%') + ->orWhere('description', 'LIKE', '%' . $request->keyword . '%'); + })->orderBy($sort, $order)->paginate($request->pageSize); + } + + /** + * Store a newly created resource in storage. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function store(GroupMemberRequest $request) + { + return GroupMember::create($request->all()); + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param int $id + * @return \Illuminate\Http\Response + */ + public function update(GroupMemberRequest $request, GroupMember $groupMember) + { + $groupMember->update($request->all()); + return $groupMember; + } + + /** + * Remove the specified resource from storage. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function destroy(GroupMember $groupMember) + { + $groupMember->delete(); + return ['message' => 'Data telah dihapus']; + } + + public function getList() + { + return GroupMember::orderBy('name', 'ASC')->get(); + } +} diff --git a/app/Http/Controllers/MemberVehicleController.php b/app/Http/Controllers/MemberVehicleController.php new file mode 100644 index 00000000..2cffa7d7 --- /dev/null +++ b/app/Http/Controllers/MemberVehicleController.php @@ -0,0 +1,14 @@ +delete(); + return ['message' => 'Data berhasil disimpan']; + } +} diff --git a/app/Http/Controllers/ParkingGateController.php b/app/Http/Controllers/ParkingGateController.php index eb61cdf9..b4aca782 100644 --- a/app/Http/Controllers/ParkingGateController.php +++ b/app/Http/Controllers/ParkingGateController.php @@ -122,6 +122,10 @@ public function testCamera(ParkingGate $parkingGate) public function testPrinter(ParkingGate $parkingGate) { + if ($parkingGate->type == 'IN' && $parkingGate->printer_type == 'local') { + return response(['message' => 'PRINTER GATE IN SERIAL TIDAK BISA DITEST DARI WEB'], 500); + } + try { if ($parkingGate->printer_type == "network") { $connector = new NetworkPrintConnector($parkingGate->printer_ip_address, 9100); diff --git a/app/Http/Controllers/ParkingMemberController.php b/app/Http/Controllers/ParkingMemberController.php index 99311e32..ba3efd10 100644 --- a/app/Http/Controllers/ParkingMemberController.php +++ b/app/Http/Controllers/ParkingMemberController.php @@ -5,6 +5,7 @@ use Illuminate\Http\Request; use App\ParkingMember; use App\Http\Requests\ParkingMemberRequest; +use Illuminate\Support\Facades\DB; class ParkingMemberController extends Controller { @@ -23,14 +24,21 @@ public function index(Request $request) $sort = $request->sort ? $request->sort : 'name'; $order = $request->order == 'ascending' ? 'asc' : 'desc'; - return ParkingMember::when($request->keyword, function ($q) use ($request) { - return $q->where('name', 'LIKE', '%' . $request->keyword . '%') - ->orWhere('card_number', 'LIKE', '%' . $request->keyword . '%') - ->orWhere('plate_number', 'LIKE', '%' . $request->keyword . '%'); + return ParkingMember::selectRaw(' + parking_members.*, + group_members.name AS `group`, + CASE WHEN expiry_date < DATE(NOW()) THEN 1 ELSE 0 END AS `expired` + ') + ->join('group_members', 'group_members.id', '=', 'parking_members.group_member_id', 'LEFT') + ->when($request->keyword, function ($q) use ($request) { + return $q->where('parking_members.name', 'LIKE', '%' . $request->keyword . '%') + ->orWhere('parking_members.card_number', 'LIKE', '%' . $request->keyword . '%'); })->when($request->is_active, function ($q) use ($request) { - return $q->whereIn('is_active', $request->is_active); - })->when($request->vehicle_type, function ($q) use ($request) { - return $q->whereIn('vehicle_type', $request->vehicle_type); + return $q->whereIn('parking_members.is_active', $request->is_active); + })->when($request->expired == ['y'], function ($q) { + return $q->whereRaw('parking_members.expiry_date < DATE(NOW())'); + })->when($request->expired == ['n'], function ($q) { + return $q->whereRaw('parking_members.expiry_date >= DATE(NOW())'); })->orderBy($sort, $order)->paginate($request->pageSize); } @@ -42,7 +50,24 @@ public function index(Request $request) */ public function store(ParkingMemberRequest $request) { - return ParkingMember::create($request->all()); + try { + DB::transaction(function () use ($request) { + $id = DB::table('parking_members')->insertGetId($request->only([ + 'group_member_id', 'name', 'card_number', + 'is_active', 'expiry_date', 'email', 'phone', + 'paid', 'register_date', 'billing_cycle', 'fare' + ])); + + DB::table('member_vehicles')->insert(array_map(function($vehicle) use ($id) { + $vehicle['parking_member_id'] = $id; + return $vehicle; + }, $request->vehicles)); + }); + } catch (\Exception $e) { + return response(['message' => 'Data gagal disimpan. ' . $e->getMessage()], 500); + } + + return ['message' => 'Data berhasil disimpan']; } /** @@ -58,17 +83,14 @@ public function show(ParkingMember $parkingMember) public function search(Request $request) { - // harus salah 1, kalo gak plat ya kartu - if (!$request->plate_number && !$request->card_number) { + if (!$request->card_number) { return response(['message' => 'No member found'], 404); } - $member = ParkingMember::when($request->plate_number, function($q) use ($request) { - return $q->where('plate_number', $request->plate_number); - })->when($request->card_number, function($q) use ($request) { - return $q->where('card_number', 'LIKE', '%'.$request->card_number.'%'); - })->where('expiry_date', '>=', date('Y-m-d')) - ->where('is_active', 1)->first(); + $member = ParkingMember::where('is_active', 1) + ->where('expiry_date', '>=', date('Y-m-d')) + ->where('card_number', 'LIKE', '%'.$request->card_number) + ->first(); if (!$member) { return response(['message' => 'No member found'], 404); @@ -86,8 +108,30 @@ public function search(Request $request) */ public function update(ParkingMemberRequest $request, ParkingMember $parkingMember) { - $parkingMember->update($request->all()); - return $parkingMember; + try { + DB::transaction(function () use ($request, $parkingMember) { + DB::table('parking_members') + ->where('id', $parkingMember->id) + ->update($request->only([ + 'group_member_id', 'name', 'card_number', + 'is_active', 'expiry_date', 'email', 'phone', + 'paid', 'register_date', 'billing_cycle', 'fare' + ])); + + DB::table('member_vehicles') + ->where('parking_member_id', $parkingMember->id) + ->delete(); + + DB::table('member_vehicles')->insert(array_map(function($vehicle) use ($parkingMember) { + $vehicle['parking_member_id'] = $parkingMember->id; + return $vehicle; + }, $request->vehicles)); + }); + } catch (\Exception $e) { + return response(['message' => 'Data gagal disimpan. ' . $e->getMessage()], 500); + } + + return ['message' => 'Data berhasil disimpan']; } /** diff --git a/app/Http/Requests/GroupMemberRequest.php b/app/Http/Requests/GroupMemberRequest.php new file mode 100644 index 00000000..4aa03dac --- /dev/null +++ b/app/Http/Requests/GroupMemberRequest.php @@ -0,0 +1,30 @@ +check(); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + 'name' => 'required' + ]; + } +} diff --git a/app/Http/Requests/MemberVehicleRequest.php b/app/Http/Requests/MemberVehicleRequest.php new file mode 100644 index 00000000..ecf9734b --- /dev/null +++ b/app/Http/Requests/MemberVehicleRequest.php @@ -0,0 +1,36 @@ +check(); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + 'parking_member_id' => 'required|exists:parking_members,id', + 'vehicle_type' => 'required', + 'plate_number' => 'required', + 'merk' => 'required', + 'type' => 'required', + 'tahun' => 'required|digits:4', + 'warna' => 'required', + ]; + } +} diff --git a/app/Http/Requests/ParkingMemberRequest.php b/app/Http/Requests/ParkingMemberRequest.php index 50d109ea..4f4f71d1 100644 --- a/app/Http/Requests/ParkingMemberRequest.php +++ b/app/Http/Requests/ParkingMemberRequest.php @@ -26,12 +26,15 @@ public function rules() return [ 'name' => 'required', 'card_number' => 'required', - 'plate_number' => 'required', - 'vehicle_type' => 'required|in:MOBIL,MOTOR', 'is_active' => 'boolean', 'expiry_date' => 'required|date', 'phone' => 'required', - 'email' => 'required|email' + 'email' => 'required|email', + 'group_member_id' => 'required', + 'paid' => 'boolean', + 'register_date' => 'required|date', + 'billing_cycle' => 'numeric', + 'fare' => 'numeric' ]; } @@ -40,12 +43,15 @@ public function attributes() return [ 'name' => 'Nama', 'card_number' => 'Nomor Kartu', - 'plate_number' => 'Nomor Plat', - 'vehicle_type' => 'Jenis Kendaraan', 'is_active' => 'Aktif', 'expiry_date' => 'Tanggal Kedaluarsa', 'phone' => 'Nomor HP', - 'email' => 'ALamat Email' + 'email' => 'ALamat Email', + 'group_member_id' => 'Group', + 'paid' => 'Berbayar', + 'register_date' => 'Tanggal Daftar', + 'billing_cycle' => 'Siklus Pembayaran', + 'fare' => 'Tarif' ]; } } diff --git a/app/MemberVehicle.php b/app/MemberVehicle.php new file mode 100644 index 00000000..2835573f --- /dev/null +++ b/app/MemberVehicle.php @@ -0,0 +1,14 @@ +hasMany(MemberVehicle::class); + } } diff --git a/database/migrations/2019_09_07_154619_create_group_members_table.php b/database/migrations/2019_09_07_154619_create_group_members_table.php new file mode 100644 index 00000000..4dedf526 --- /dev/null +++ b/database/migrations/2019_09_07_154619_create_group_members_table.php @@ -0,0 +1,36 @@ +bigIncrements('id'); + $table->string('name'); + $table->string('description')->nullable(); + $table->string('contact_person_name')->nullable(); + $table->string('contact_person_phone')->nullable(); + $table->string('contact_person_email')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('group_members'); + } +} diff --git a/database/migrations/2019_09_11_103028_create_member_vehicles_table.php b/database/migrations/2019_09_11_103028_create_member_vehicles_table.php new file mode 100644 index 00000000..519d60b8 --- /dev/null +++ b/database/migrations/2019_09_11_103028_create_member_vehicles_table.php @@ -0,0 +1,38 @@ +bigIncrements('id'); + $table->bigInteger('parking_member_id'); + $table->string('vehicle_type'); + $table->string('plate_number'); + $table->string('merk'); + $table->string('type'); + $table->string('tahun', 4); + $table->string('warna'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('member_vehicles'); + } +} diff --git a/database/migrations/2019_09_11_105527_drop_some_columns_on_parking_member.php b/database/migrations/2019_09_11_105527_drop_some_columns_on_parking_member.php new file mode 100644 index 00000000..392647fc --- /dev/null +++ b/database/migrations/2019_09_11_105527_drop_some_columns_on_parking_member.php @@ -0,0 +1,45 @@ +dropColumn(['plate_number', 'vehicle_type']); + $table->bigInteger('group_member_id')->nullable(); + $table->bigInteger('fare')->default(0); + $table->boolean('paid')->default(0); + $table->date('register_date')->nullable(); + $table->tinyInteger('billing_cycle')->default(1); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('parking_members', function (Blueprint $table) { + + $table->dropColumn([ + 'group_member_id', 'paid', + 'register_date', 'billing_cycle', + 'fare' + ]); + + $table->string('plate_number')->nullable(); + $table->string('vehicle_type')->nullable(); + }); + } +} diff --git a/install.sh b/install.sh new file mode 100755 index 00000000..276095e9 --- /dev/null +++ b/install.sh @@ -0,0 +1,61 @@ +#!/bin/sh + +# Install dependency +cd ~ +sudo apt install -y \ + php \ + php-curl \ + php-json \ + php-mbstring \ + php-mysql \ + php-xml \ + php-zip \ + apache2 \ + libapache2-mohp \ + mysql-server \ + python3-pip \ + git \ + composer \ + sed + +sudo pip3 install python-escpos +git clone https://github.com/udibagas/parking-system.git +cd parking-system +composer install +cp .env-prod .env +php artisan key:generate +php artisan jwt:secret + +# prepare database server +sudo mysql -uroot -e 'create database parking_system' +sudo mysql -uroot -e 'grant all on parking_system.* to parking_system@localhost identified by "Bismillah1@#$%"' +sudo mysql -uroot -e 'flush privileges' + +# migrate then populate db +php artisan migrate +php artisan db:seed + +# prepare document root +sudo mv /var/www/html /var/www/html-bak +sudo ln -s `pwd`/public /var/www/html +mkdir `pwd`/public/snapshot +chmod 777 `pwd`/public/snapshot +sudo chmod 777 storage -R + +# prepare web server +sudo sed -i 172s/None/All/ /etc/apache2/apache2.conf +sudo a2enmod rewrite +# allow web to access serial & printer +sudo usermod -a -G dialout www-data +sudo usermod -a -G root www-data +sudo usermod -a -G lp www-data +sudo systemctl restart apache2 + +# upstart +chmod +x parking +sed -i "4 a DAEMON=`pwd`/parking.py" parking +sudo cp parking /etc/init.d/ +chown root:root /etc/init.d/parking +sudo cp parking.conf /etc/init/ +chown root:root /etc/init/parking.conf +reboot diff --git a/parking b/parking new file mode 100755 index 00000000..4c65549f --- /dev/null +++ b/parking @@ -0,0 +1,36 @@ +#!/bin/sh +# put this file to /etc/init.d/ +# chmod +x + +PIDFILE=/var/run/parking.pid + +case "${1}" in + start) + if [ -f ${PIDFILE} ]; then + echo "Service already running with pid" `cat ${PIDFILE}` + exit 0 + fi + start-stop-daemon --start --background --pidfile ${PIDFILE} --make-pidfile --exec ${DAEMON} + echo "Service started with pid" `cat ${PIDFILE}` + ;; + stop) + start-stop-daemon --stop --pidfile ${PIDFILE} + rm ${PIDFILE} + echo "Service stopped" + ;; + restart) + ${0} stop + ${0} start + ;; + status) + if [ -f ${PIDFILE} ]; then + echo "Service is running with pid" `cat ${PIDFILE}` + exit 0 + fi + echo "Service stopped" + ;; + *) + echo "Usage : ${0} {start|stop|restart|status}" + exit 1 + ;; +esac diff --git a/parking.conf b/parking.conf new file mode 100644 index 00000000..05c71c30 --- /dev/null +++ b/parking.conf @@ -0,0 +1,3 @@ +# put this file to /etc/init/ +start on started apache2 +exec /etc/init.d/parking start diff --git a/resources/js/App.vue b/resources/js/App.vue index 0ac2ebcf..cc88e7d5 100644 --- a/resources/js/App.vue +++ b/resources/js/App.vue @@ -8,8 +8,8 @@
- -
+ {{$store.state.user.name}}
{{$store.state.user.email}}
@@ -72,6 +72,8 @@ export default { if (this.$store.state.user.role == 1) { menus.push( + {label: 'User', icon: 'el-icon-user', path: 'user' }, + {label: 'Notifikasi', icon: 'el-icon-bell', path: 'notification' }, {label: 'Setting', icon: 'el-icon-setting', path: 'setting' }, ) } @@ -157,7 +159,7 @@ export default { } .brand-box { - height: 220px; + height: 160px; background-color: #060446; text-align: center; color: #fff; diff --git a/resources/js/components/ParkingMemberDetail.vue b/resources/js/components/ParkingMemberDetail.vue new file mode 100644 index 00000000..a58b759f --- /dev/null +++ b/resources/js/components/ParkingMemberDetail.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/resources/js/pages/GateOutApp.vue b/resources/js/pages/GateOutApp.vue index 1f747136..3ffc6be0 100644 --- a/resources/js/pages/GateOutApp.vue +++ b/resources/js/pages/GateOutApp.vue @@ -51,7 +51,6 @@ - @@ -199,22 +198,6 @@ export default { // }) // }, checkPlate(e) { - if (!this.formModel.plate_number) { - return - } - - let params = { plate_number: this.formModel.plate_number } - axios.get('/parkingMember/search', { params: params }).then(r => { - this.formModel.fare = 0; - this.formModel.is_member = 1; - this.formModel.parking_member_id = r.data.id; - this.$forceUpdate(); - }).catch(e => { - this.formModel.is_member = 0; - this.formModel.parking_member_id = null; - this.$forceUpdate(); - }) - document.getElementById('ticket-number').focus() }, setFare() { diff --git a/resources/js/pages/GroupMember.vue b/resources/js/pages/GroupMember.vue new file mode 100644 index 00000000..3075900d --- /dev/null +++ b/resources/js/pages/GroupMember.vue @@ -0,0 +1,221 @@ + + + + + + diff --git a/resources/js/pages/Member.vue b/resources/js/pages/Member.vue deleted file mode 100644 index 00da54e3..00000000 --- a/resources/js/pages/Member.vue +++ /dev/null @@ -1,18 +0,0 @@ - - - - - diff --git a/resources/js/pages/Notification.vue b/resources/js/pages/Notification.vue index 4e5dd0db..b1eaae7c 100644 --- a/resources/js/pages/Notification.vue +++ b/resources/js/pages/Notification.vue @@ -1,5 +1,7 @@ - - - - + + + + - + - - - - - - - - - + + + + + + + + + - + - + diff --git a/resources/js/pages/ParkingMember.vue b/resources/js/pages/ParkingMember.vue index caad54d2..253d090b 100644 --- a/resources/js/pages/ParkingMember.vue +++ b/resources/js/pages/ParkingMember.vue @@ -1,8 +1,10 @@ diff --git a/resources/js/pages/ParkingTransaction.vue b/resources/js/pages/ParkingTransaction.vue index 5d8660ef..c846c9fa 100644 --- a/resources/js/pages/ParkingTransaction.vue +++ b/resources/js/pages/ParkingTransaction.vue @@ -50,7 +50,7 @@ - +