Compare commits

...

186 Commits

Author SHA1 Message Date
arifal
285e89d5d0 done restructure calculation retribution 2025-06-19 13:48:35 +07:00
arifal hidayat
4c3443c2d6 restructure retribution calculations table 2025-06-18 22:53:44 +07:00
arifal
df70a47bd1 add build 2025-06-18 15:45:12 +07:00
arifal
e71dd7d213 count spatial plannings business and non business and create pbg task detail and add to syncrone daily 2025-06-18 13:45:35 +07:00
arifal hidayat
f2eb998ac5 build and add init spatial 2025-06-18 02:57:30 +07:00
arifal hidayat
fc54e20fa4 add spatial plannings retribution calculations 2025-06-18 02:54:41 +07:00
arifal
6946fa7074 update retribution calculation spatial plannings 2025-06-17 17:58:37 +07:00
arifal
236b6f9bfc add build frontend 2025-06-17 12:04:55 +07:00
arifal
285ff46c2b fix data setting get datatable using api token 2025-06-17 11:54:02 +07:00
arifal hidayat
a8b02afad9 add build production manifest 2025-06-14 04:22:57 +07:00
arifal hidayat
a0666e78d2 fix value dashboard verified component 2025-06-14 04:20:26 +07:00
arifal hidayat
799e409ce2 create build script 2025-06-14 02:48:00 +07:00
arifal hidayat
780ba60224 add sync to leader dashboard new from google spreadsheet 2025-06-14 02:15:49 +07:00
arifal
baed8cc487 fix 401 hit api 2025-06-13 20:43:16 +07:00
arifal
e17f5beaf0 production code 2025-06-13 13:36:27 +00:00
arifal
766e1a430c fix permision deploy 2025-06-13 20:08:14 +07:00
arifal
6677c320fc build and create deploy production 2025-06-13 19:53:23 +07:00
arifal hidayat
9437eb949f add docker 2025-06-06 22:42:41 +07:00
arifal
6f77120c33 backup database 2025-06-02 15:41:03 +07:00
arifal
f8d0573e5c remove description body response on datatable 2025-06-02 15:30:43 +07:00
arifal
ca74d0143f hot fix show all chart growth 2025-05-20 11:59:50 +07:00
arifal
34e082c31b fix bug sync google sheet and handle to long data address on pbg task 2025-05-20 11:13:21 +07:00
arifal
c4d865bf2b fix get menu id and height auto chart growth 2025-05-15 18:09:28 +07:00
arifal
a103b38265 create page growth report 2025-05-15 17:02:02 +07:00
arifal
9aa3d32b6e add link in potential dashboard 2025-05-15 14:18:27 +07:00
arifal
99e2c214b6 create redirect link for dashboard pimpinan 2025-05-14 20:56:36 +07:00
arifal
501a76bc81 partial update circle chart can click 2025-05-06 17:29:39 +07:00
arifal
460267992e handle null value on detail quick search 2025-05-06 15:32:03 +07:00
arifal
becc368069 last update feat quick search 2025-05-06 15:06:59 +07:00
arifal
2618ac06d0 partial update create page quick search 2025-05-05 18:36:56 +07:00
arifal
d95676d477 fix show page document pbg 2025-04-10 15:44:51 +07:00
arifal
7737fee30f add validation topic on send prompt if not relevan 2025-04-10 01:59:57 +07:00
arifal
48293386c7 fix change chatbot to top 2025-04-09 21:22:26 +07:00
arifal
84870b95b1 add feat upload pbg task 2025-04-09 21:10:20 +07:00
arifal
6294d2f950 add new users on seeder for role user and superadmin 2025-03-27 17:19:27 +07:00
arifal
7b70591be5 add readme and backup schema local 2025-03-27 15:28:21 +07:00
arifal
3b67bfd1fb remove duplicate use timeout when running queue 2025-03-26 15:20:03 +07:00
arifal
45e22096ed add column to model import datasources 2025-03-26 11:51:57 +07:00
arifal
c7a8d6d249 add condition show button retry 2025-03-25 22:46:34 +07:00
arifal
091b1f305e fix handle retry button 2025-03-25 15:54:02 +07:00
arifal
e7950e22f2 add flatpicker for edit pbg task data 2025-03-24 21:16:05 +07:00
arifal
b68641db03 backup local db and add global setting seeder to run default 2025-03-24 11:08:10 +07:00
arifal
fefb85ac7a remove get sample data from service 2025-03-21 19:10:17 +07:00
arifal
d28a08a24c fix add bigdata resume after syncronize 2025-03-21 19:08:18 +07:00
arifal
654d2efe19 fix syncronize using worker and add duration syncronize 2025-03-21 18:44:28 +07:00
arifal
0a080763cd try catch handle refresh token fail to login again 2025-03-21 16:03:10 +07:00
arifal
f3ef21d1be fix style error message when failed login 2025-03-21 15:10:28 +07:00
arifal
d7bff86741 fix menu with parent data and remove action google sheet not available feature 2025-03-21 14:54:18 +07:00
arifal
f36f250700 fix supervisorctl syntax on deploy 2025-03-20 20:19:38 +07:00
arifal
2c5da87856 fix reload php service on deploy 2025-03-20 20:18:09 +07:00
arifal
a195559c4b fix running syntax seeder on automation deploy syntax 2025-03-20 20:15:30 +07:00
arifal
088f173fec fix add params filter date on grid js, export excel and pdf payment recaps 2025-03-20 20:12:42 +07:00
arifal
eadfddb3a4 add export excel and pdf district payment recaps 2025-03-19 18:55:51 +07:00
arifal
47a9fb1dfb add export excel and pdf report director 2025-03-19 18:22:00 +07:00
arifal
1713e32b67 add export pdf report tourisms and report ptsp 2025-03-19 17:15:10 +07:00
arifal
cf998455e0 add export excel report tourisms 2025-03-19 16:16:10 +07:00
arifal
5e1c9f3a2e fix dashboard pbg, add soft delete users, fix js create pbg task 2025-03-19 14:06:10 +07:00
arifal
e940b8d6c7 fix handle sync using button 2025-03-18 08:10:06 +07:00
arifal
5e139bc29c change command scraping 2025-03-18 06:47:53 +07:00
arifal
f9e1aa1604 fix service scraping data 2025-03-18 06:42:42 +07:00
arifal
2e385f80cd fix optimize syncronize 2025-03-14 19:10:28 +07:00
arifal
e2c26e0eff fix reklame route index 2025-03-13 16:23:17 +07:00
arifal
ca5b8ad403 fix deploy code and readme 2025-03-13 15:59:11 +07:00
arifal
e97b7eb70d fix redirect back spatial plannings 2025-03-13 15:48:53 +07:00
arifal
0258ca9f04 fix redirect back umkm 2025-03-13 15:39:32 +07:00
arifal
0116147e06 fix redirect back reklame and tourisms 2025-03-13 15:24:59 +07:00
arifal
7787db02a3 fix redirect back business or industries 2025-03-13 14:13:06 +07:00
arifal
e47ab36d5e fix pdam redirect back and advertisement partial update redirect 2025-03-13 13:57:53 +07:00
arifal
e5db2294b4 fix redirect back data settings 2025-03-12 21:39:52 +07:00
arifal
4db457d7bd fix redirect back users crud 2025-03-12 21:17:49 +07:00
arifal
7a82ad5302 fix redirect back roles 2025-03-12 20:30:16 +07:00
arifal
b0d4d4c23b fix redirect back with params menu id 2025-03-12 17:52:11 +07:00
arifal
68ffc1c090 fix 503 page 2025-03-12 15:57:31 +07:00
arifal
a1f4bd7f81 fix seeder menu role and user assign, create 503 page and fix redirect home 2025-03-12 15:37:22 +07:00
arifal
238aaba96c fix seeder users role menu 2025-03-12 12:01:28 +07:00
arifal
c7152d9dbe fix resources report payment recaps 2025-03-12 11:50:56 +07:00
arifal
2a4b96d0b2 fix vite resources 2025-03-12 11:43:11 +07:00
arifal
dd940ebdb6 fix inside and outside dashboard 2025-03-12 11:38:07 +07:00
arifal
dce5409248 done all view dummy new modul 2025-03-12 00:32:50 +07:00
arifal
b8f7d7f655 fix back button 2025-03-11 01:17:16 +07:00
arifal
65600f1b4f add view list data from google sheet 2025-03-11 00:26:48 +07:00
arifal
b0f15a9221 fix sidebar permission user 2025-03-10 16:33:53 +07:00
arifal
bf55eb228e fix width dashboard outside sy system and loading when load maps pariwisata, backup localdb 2025-03-07 18:00:30 +07:00
arifal
755720bac9 fix failed build images from leaflet 2025-03-07 16:41:52 +07:00
arifal
098b4c605b fix missing scss on vite 2025-03-07 15:39:26 +07:00
arifal
4632e102eb add use package missing 2025-03-07 15:00:26 +07:00
arifal
0431945a42 fix conflict 2025-03-07 14:52:51 +07:00
@jamaludinarifrohman6661
fbfa2a37bb feature: set role previledge access 2025-03-07 14:39:46 +07:00
arifal
c529a5d511 add readme 2025-03-07 14:39:23 +07:00
arifal
ff244039ff add readme and env example 2025-03-07 14:37:26 +07:00
arifal
55902042f4 add readme 2025-03-07 14:27:49 +07:00
arifal
c67aa979c2 change column type expertise and fix syncronize simbg service 2025-03-07 14:04:37 +07:00
arifal
fbaa33ae13 fix height scrollbar table grid js 2025-03-07 01:55:46 +07:00
arifal
9516b6f575 fix task assignment table on pbg task 2025-03-07 01:03:22 +07:00
arifal
ffc08f26cc add dashboard inside and outside system and fix timeout when search filter 2025-03-06 23:33:31 +07:00
@jamaludinarifrohman6661
dceb46ab86 change-request: add custom geo layer 2025-03-06 16:50:13 +07:00
arifal
e0c35b8897 fix search filter on page big data resume 2025-03-06 14:39:36 +07:00
arifal
22ee7502ad Merge remote-tracking branch 'origin/feature/chatbot-sidebar' into fix/sync-task-assignment 2025-03-06 11:45:34 +07:00
arifal
2f3bc172eb add search filter 2025-03-06 11:42:59 +07:00
@jamaludinarifrohman6661
bba932b2ba Merge remote-tracking branch 'origin/dev' into feature/chatbot-sidebar 2025-03-06 11:20:45 +07:00
@jamaludinarifrohman6661
3f5d0eb1cd fix: inserting chat history into the answer generation process 2025-03-06 11:06:45 +07:00
arifal
1f33d0de4e add sync task assignment pbg 2025-03-06 00:13:13 +07:00
arifal
86d694bcac add new menu chat bedas and view 2025-03-04 17:56:30 +07:00
arifal
cb5a3243fc Merge remote-tracking branch 'origin/feature/chatbot-sidebar' into dev 2025-03-04 17:32:37 +07:00
@jamaludinarifrohman6661
15210a56ee feature: chatbot pimpinan 2025-03-04 17:31:40 +07:00
arifal
a08f2cb2b7 fix optimizing deployment 2025-03-04 16:45:32 +07:00
arifal
632433c496 fix routing spatial-plannings 2025-03-04 16:23:00 +07:00
arifal
5b4780495e fix routing spatial-plannings 2025-03-04 16:17:47 +07:00
arifal
0a7012a57c fix tourisms routing 2025-03-04 16:13:17 +07:00
arifal
435a19346b fix route umkm 2025-03-04 16:05:21 +07:00
arifal
8fcf8859d6 hot fix advertisement route conflict 2025-03-04 15:58:30 +07:00
arifal
43a246d234 add permission deployment file 2025-03-04 08:49:51 +00:00
arifal
d6d0acf8fb hot fix conflict routing web and api advertisements 2025-03-04 15:46:35 +07:00
arifal
b4ec7a9d25 merge chatbot sidebar 2025-03-04 15:19:11 +07:00
arifal
5203babe11 Merge remote-tracking branch 'origin/feature/chatbot-sidebar' into dev 2025-03-04 15:15:32 +07:00
arifal
c0faafdbd7 hot fix add time midnight scheduler 2025-03-04 15:13:33 +07:00
arifal
c5e3fdd915 create file automation deployment using sh 2025-03-04 15:05:13 +07:00
@jamaludinarifrohman6661
572b86299c add:setting main chatbot
fix:chatbot ui
2025-03-04 14:46:29 +07:00
arifal
cdd84d02da fix parsing separator 2025-03-04 14:30:41 +07:00
arifal
ee1a395c75 add per page 50 and add some column onn laporan pimpinan 2025-03-04 10:41:52 +07:00
arifal
3bfcaddba4 fix queue execute scraping syncronize simbg add new column to resume 2025-03-03 22:55:57 +07:00
arifal
9ea7e96af1 add vite and merge chatbot jamal 2025-02-28 18:39:23 +07:00
arifal
e0d11af7d2 Merge remote-tracking branch 'origin/feature/chatbot' into dev 2025-02-28 18:14:29 +07:00
@jamaludinarifrohman6661
fefef609ac feature: chatbot 2025-02-28 17:53:16 +07:00
arifal
f5790cda94 fix filter year dashboard 2025-02-28 15:46:31 +07:00
arifal
f3db3783f9 deployed 2025-02-28 2025-02-28 04:49:28 +00:00
arifal
101e76c0fa add js to vite 2025-02-28 11:45:55 +07:00
arifal
4cc698a623 fix handle disable button when upload business industries 2025-02-28 10:37:41 +07:00
arifal
544ad1db46 fix upload business and industry with chunk 2025-02-28 00:35:09 +07:00
arifal
30ca819aa1 fix color on maps 2025-02-27 20:14:37 +07:00
arifal
b0bab784d1 partial update add page laporan pimpinan and fix upload big data excel pdam 2025-02-27 19:23:06 +07:00
arifal
01fda22c89 partial update add loading on maps and add color for zone type maps 2025-02-26 23:52:48 +07:00
arifal
de300c2c32 fix dashboard style and resume bigdata 2025-02-26 21:52:23 +07:00
arifal
7f8a2e4936 Merge branch 'feature/dashboard-pbg' into dev 2025-02-25 11:34:08 +07:00
@jamaludinarifrohman6661
38948b6633 bug-fix: map tourisms 2025-02-25 11:32:39 +07:00
arifal
aa9943ba45 hot fix vite config js resources 2025-02-25 04:18:15 +00:00
arifal
9e55ea0dbb fix change api route data settings 2025-02-25 10:41:59 +07:00
arifal
93f0ac5ef7 Merge branch 'feature/dashboard-pbg' into fix/dashboard-resume 2025-02-25 10:23:41 +07:00
@jamaludinarifrohman6661
8bae33519f feature: sebaran lokasi project pariwisata 2025-02-24 21:47:24 +07:00
@jamaludinarifrohman6661
6865e353e6 feature: first check point 2025-02-24 20:03:36 +07:00
arifal
bb4ab5c769 add filter date for dashboard 2025-02-24 19:00:09 +07:00
arifal hidayat
e743b82087 add remove disabled if error on data settings 2025-02-23 07:11:14 +07:00
arifal hidayat
c3c7b8e3ec fix js roles and add back button on card header 2025-02-23 07:08:50 +07:00
arifal hidayat
d49035ce8d fix js menus and handle api menus 2025-02-23 06:42:13 +07:00
arifal hidayat
ffd9d3514c fix business industries and data settings front end 2025-02-22 16:08:59 +07:00
arifal
675477c734 fix service sync simbg upsert integrations 2025-02-21 18:49:42 +07:00
arifal
4350c466e3 add backup db from local 2025-02-21 18:18:45 +07:00
arifal
5ab407d672 change get value dashboard pimpinan from resume bigdata 2025-02-21 18:09:32 +07:00
arifal
2aaa487746 fix get total data from api 2025-02-21 14:49:09 +07:00
arifal
080582f7ab add new menu peta in dashboard 2025-02-21 11:12:35 +07:00
arifal
91475aeead Merge branch 'dev' into feat/load-map-from-kmz 2025-02-21 10:43:06 +07:00
arifal
a7afbd69fb fix conflict spatial-plannings jamal 2025-02-21 09:07:15 +07:00
arifal
1ff5587050 merge conflix spatial-plannings 2025-02-21 08:42:08 +07:00
arifal
9c8a1a3f3f add vite js customers 2025-02-21 00:49:29 +07:00
arifal
5c4be7635b partial update crud customer data 2025-02-21 00:46:33 +07:00
@jamaludinarifrohman6661
ba315b1dee Fix: upload bulk in column date, and fix template 2025-02-20 22:54:41 +07:00
@jamaludinarifrohman6661
33b7131c33 feature: crud spatial planning and fix search in tourism and umkm 2025-02-20 16:16:06 +07:00
arifal
7a56735099 done crud spatial plannings 2025-02-20 15:35:06 +07:00
@jamaludinarifrohman6661
dd331b4a08 create message error validation on advertisementrequest and tourismsrequest 2025-02-20 10:59:32 +07:00
@jamaludinarifrohman6661
dcd93d66e2 fix: change path download template and add template pariwisata 2025-02-20 10:36:56 +07:00
arifal
5d50d6d6cc fix height card 2025-02-19 15:34:28 +07:00
arifal
39717d184c partial update create google map from kmz file 2025-02-19 14:31:12 +07:00
arifal
54146c8c08 partial update spatial plannings crud 2025-02-19 12:08:18 +07:00
arifal
e8da7193ef fix crud users 2025-02-19 11:23:15 +07:00
arifal
006c008542 done dashboard-potential 2025-02-19 07:22:06 +07:00
root
39bb8e6d5f hot fix vite and create view 2025-02-18 23:49:48 +00:00
arifal
7994a62cea change name dashboard 2025-02-19 06:24:44 +07:00
arifal
3a09e2e68a Merge branch 'bug-fix/tourisms' into feat/dashboard-kekurangan-potensi 2025-02-19 06:17:16 +07:00
arifal
116dc1c8c7 add dashboard potential 2025-02-19 06:15:35 +07:00
@jamaludinarifrohman6661
f10bc153b4 fix: tourisms 2025-02-19 01:39:27 +07:00
@jamaludinarifrohman6661
06a3bb8c8b fix:pariwisata and report pariwisata 2025-02-19 01:07:20 +07:00
arifal
6c936d4c14 add more handle if zero devided 2025-02-18 03:40:20 +07:00
arifal
d4d0a485cd fix vite resources 2025-02-18 03:32:00 +07:00
arifal
864fb26471 add local db backup 2025-02-18 02:58:11 +07:00
arifal
fd97a34344 add vite resources 2025-02-18 02:50:34 +07:00
arifal
1dd971fb73 create update tourisms 2025-02-18 02:45:39 +07:00
arifal
aff31e08ef merge feature umkm 2025-02-18 00:46:51 +07:00
@jamaludinarifrohman6661
2fb8aeceaa feature: viewnya ketinggalan 2025-02-18 00:35:50 +07:00
@jamaludinarifrohman6661
ecc243d1cc Upload Pariwisata dan report pariwisata 2025-02-17 23:58:31 +07:00
arifal
beac71d182 add business industry crud 2025-02-17 18:40:00 +07:00
@jamaludinarifrohman6661
8c236c460d feature: umkm crud and add template file for reklame 2025-02-17 13:03:54 +07:00
arifal hidayat
154b7f40df add sync data setting 2025-02-17 01:52:49 +07:00
arifal
59e9431b2d fetch data from data setting and make seeder realisasi terbit, menunggu klik dpmptsp, proses dinas teknis 2025-02-14 18:28:14 +07:00
arifal
074edc607d add hardcode number for realisasi terbit, proses dinas teknis, menunggu klik dashboards 2025-02-14 17:04:49 +07:00
arifal
625d182d81 fix service google sheet, add uemail to profile, fix detail pbg view, backupdb local last migrate, create menu and role request 2025-02-14 16:22:34 +07:00
@jamaludinarifrohman6661
41ddbaef24 feature/create-migration-and-crud-api 2025-02-12 16:46:06 +07:00
693 changed files with 313610 additions and 8794 deletions

0
.editorconfig Executable file → Normal file
View File

3
.env.example Executable file → Normal file
View File

@@ -67,4 +67,5 @@ AWS_USE_PATH_STYLE_ENDPOINT=false
VITE_APP_NAME="${APP_NAME}"
API_KEY_GOOGLE="xxxxx"
SPREAD_SHEET_ID="xxxxx"
SPREAD_SHEET_ID="xxxxx"
OPENAI_API_KEY="xxxxx"

76
.env.local.backup Normal file
View File

@@ -0,0 +1,76 @@
APP_NAME=SIBEDAS-PBG
APP_ENV=local
APP_KEY=base64:xqCpwixWKqgu1Ca22gFizoOt44p7h+cgTOKuhS/P0Jw=
APP_DEBUG=true
APP_TIMEZONE=Asia/Jakarta
APP_URL=http://localhost:8000
API_URL=http://localhost:8000
APP_LOCALE=en
APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=en_US
APP_MAINTENANCE_DRIVER=file
# APP_MAINTENANCE_STORE=database
PHP_CLI_SERVER_WORKERS=4
BCRYPT_ROUNDS=12
LOG_CHANNEL=stack
LOG_STACK=single
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mariadb
DB_HOST=db
DB_PORT=3306
DB_DATABASE=sibedas_db
DB_USERNAME=root
DB_PASSWORD=root
SESSION_DRIVER=database
SESSION_LIFETIME=120
SESSION_ENCRYPT=false
SESSION_PATH=/
SESSION_DOMAIN=null
BROADCAST_CONNECTION=log
FILESYSTEM_DISK=local
QUEUE_CONNECTION=database
CACHE_STORE=database
CACHE_PREFIX=
MEMCACHED_HOST=127.0.0.1
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=log
MAIL_HOST=127.0.0.1
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
VITE_APP_NAME="${APP_NAME}"
SIMBG_HOST="https://simbg.pu.go.id/"
SIMBG_EMAIL="dputr@bandungkab.go.id"
SIMBG_PASSWORD="Simbg123"
API_KEY_GOOGLE="AIzaSyBxfEShFkKmykkc7RJR3lVzkQ_xGHK3qr0"
SPREAD_SHEET_ID="1QoXzuLdEX3MK70Yrfigz0Qj5rAt4T819jX85vubBNdY"
OPENAI_API_KEY="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"

0
.gitattributes vendored Executable file → Normal file
View File

0
.gitignore vendored Executable file → Normal file
View File

View File

@@ -0,0 +1,42 @@
no,pemohon,alamat,activities,luas_lahan,bcr_kawasan,area,no_tapak,no_skkl,no_ukl,fungsi_bangunan,sub_fungsi_bangunan,jumlah_lantai
01/222,PT CIPTA INDAH PERTIWI No Telpon : 082217633434,Jl Salam No 51 Desa/Kel. Cihapit Kec. Bandung wetan Kota Bandung,PERUMAHAN LA LA TOWN,16629,0.2449,4072.4421,648.11./222 - SP /TR 07 Januari 2025;644.2./207 - SP /TR 02 Januari 2025,500.10.29.15/631-REKTEK/TR Tanggal 14 Februari 2023;500.10.29.15/2837-REKTEK/Bid. Taru Tanggal 25 Juli 2024,14022310313204030 Tanggal 14 Februari 2023;500.10.29.7/Kep.618-DLH/2024 Tanggal 13 Desember 2024;161023087545 Tanggal 16 Oktober2023,Fungsi Hunian,Fungsi Hunian,1
03/481,MUHAMAD GUNTUR JULIADI No Telpon : 081223334486,Cangkuang Residence RT 004/003 Ds Cangkuang Wetan Kec. Dayeuhkolot Kab. Bandung,PERUMAHAN CANGKUANG RESIDENCE 2,2360,0.5924,1398.064,648.11./481 - SP /TR 15 Januari 2025;647./226 - SP /TR 07 Januari 2025;647/225 - SP /TR 07 Januari 2025;644/221 - SP /TR 07 Januari 2025;645.4/557 - SP /TR 20 Januari 2025,500.10.29.15/2894-REKTEK/Bid. Taru Tanggal 08 Agustus 2024;400.7.22/4927-KRK/04/Bid.Taru Tanggal 06 Desember 2024;500.10.29.15/2619-REKTEK/Bid. Taru Tanggal 10 Juli 2024;500.10.29.15/4155-REKTEK/Bid. Taru Tanggal 18 Nopember 2024;503/123/III-DPMPTSP/2020 Tanggal 24 MAret 2020,167240099471 Tanggal 16 Juli 2024;9120111161314 Tanggal 11 Nopember 2019;8120312190151 Tanggal 04 Desember 2023;500.10.29.7/Kep.614-DLH/2024 Tanggal 20 Nopember 2024;2910240290118 Tanggal 29 Oktober 2024;8120001992981 Tanggal 12 Juli 2024;SK.294/Menlhk/Setjen/PLA.4/5/2021 Tanggal 31 Mei 2021,Fungsi Hunian,Fungsi Hunian,1
08/480,PT SURYA KHARISMA PARAHYANGAN No Telpon : 081394461006 ,Jalan Cibaligo No 48 Desa /Kel. Cigugur tengah Kec. Cimahi tengah kota Cimahi ,PERUMAHAN PARAHYANGAN GARDEN CITY,116360,0.5164,60088.304,648.11./480 - SP /TR 15 Januari 2025,500.10.29.15/603-REKTEK/TR Tanggal 05 Desember 2023,1810220245722 Tanggal 18 Oktober 2022;500.10.29.7/Kep.632-DLH/2024 Tanggal 24 Desember 2024,Fungsi Hunian,Fungsi Hunian,2
09/223,PT CLARICHEM INDONESIA No Telpon : 081315399694,Kawasan pergudangan taman tekno sektor XI blok L2 No 30 Ds/Kel. Setu Kec. Setu kota Tangerag Banten ,PERGUDANGAN DAN PENYIMPANAN,1586,0.7017,1112.8962,644./223 - SP /TR 07 Januari 2025,400.7.22/4427-KRK/03/Bid.Taru Tanggal 06 Desember 2024,9120008832767 Tanggal 26 Nopember 2024,Usaha Besar (Non-Mikro),Fungsi Usaha,1
10/657,PT HALKA GITA No Telpon : 0816734374,Jl Raya Majalaya KM 2 RT 02/09 Desa Hegarmanah Kec. Cikancung Kab. Bandung,REVISI 1 KOMPLEK PERGUDANGAN,19100,0.699,13350.9,644./657 - SP /TR 23 Januari 2025,500.10.29.15/6750-REKTEK/TR Tanggal 21 Desember 2023,9120300510839 Tanggal 16 Desember 2023;500.10.29.7/Kep.609-DLH/2024 Tanggal 12 Nopember 2024,Usaha Besar (Non-Mikro),Fungsi Usaha,2
11/658,PT SURYA TIRTA KENCANA No Telpon : 08986155493,Kutawaringin Industrial Park Kav. 276-277 Desa Jelegong Kec. Kutawaringin Kab. Bandung,PERGUDANGAN DAN PENYIMPANAN BAHAN KIMIA,3932,0.6995,2750.434,644./658 - SP /TR 23 Januari 2025;640/540 - SP /TR 20 Januari 2025,10112410113204010 Tanggal 10 Nopember 2024;591.4/031/IX-DPMPTSP/2020 Tanggal 03 Sseptember 2020,8120017120594 Tanggal 31 Agustus 2018;600.4.5/056/6838-Ktr/TL Tanggal 24 Desember 2024;0220305221438 Tanggal 20 Nopember 2021;500.10.29.7/4295/TL Tanggal 21 September 2024,Usaha Besar (Non-Mikro),Fungsi Usaha,1
13 / 550,PT BERKAH SEPUH JAYA No Telpon : 082118781624,Ruko komplek dewaadru blok R3 RT 005 ds/kec. Bojongsoang kab. Bandung,REVISI 1 PERUMAHAN VILLA CEMARA ASRI,17379,0.5476,9516.7404,648.11/550 - SP/TR 20 Januari 2025,150223101113204049 Tanggal 15 Februari 2023,1233000451657 Tanggal 5 Mei 2023;500.10.29.7/kep.392-DLH/2025 Tgl. 2 Januari 2025,Fungsi Hunian,Fungsi Hunian,2
14 / 655,PT RISKI ANUGERAH SEDJAHTERA No Telpon : 082118781624,Griya permata asri blok C2 No 18 Ds Lengkong Kec. Bojongsoang Kab. Bandung,REVISI 1 PERUMAHAN TAMAN KATAPANG INDAH,28425,0.6532,18567.21,648.11 /655 - SP /TR 23 Januari 2025,500.10.29.15/2333-REKTEK/TR Tanggal 22 Mei 2024;500.10.29.15/3811-REKTEK/Bid. Taru Tanggal 10 Oktober 2024,1205000302875 Tanggal 02 April 2024;500.10.29.7/Kep.408-DLH/2025 Tanggal 10 Januari 2025,Fungsi Hunian,Fungsi Hunian,2
15 / 551,PT BUMI SUWARNA SEJAHTERA No Telpon : 082118781624,Jl Ciwastra no 73 Kel. Mekarmulya kec. Rancasari kota bandung,REVISI 1 PERUMAHAN BUMI KARA RESIDENCE,29711,0.5424,16115.2464,648.11/551-SP/TR 20 Januari 2025,500.10.29.15/6097-REKTEK/TR Tanggal 27 Nopember 2023,1311230078306 Tgl 13 Nopember 2023;500.10.29.7/Kep.493-DLH/2024 Tanggal 20 Maret 2024,Fungsi Hunian,Fungsi Hunian,2
16 / 656,PT AMBER HASYA No Telpon : 081312411661,Jl Sarijadi raya No 111 Kel. Sarijadi Kec. Sukasarii kota bandung,REVISI 1 PERUMAHAN GREEN HARMONI RESIDENCE ,39520,0.2726,10773.152,648.11/656-SP/TR 23 Januari 2025,500.10.29.15/2732-REKTEK/Bid. Taru Tanggal 19 Juli 2024,9120004882226 Tgl 22 Agustus 2019;500.10.29.7/Kep.617-DLH/2024 Tanggal 4 Desember 2024,Fungsi Hunian,Fungsi Hunian,2
17 / 224,PT KARYA UTAMA SEJATI JAYA No Telpon : 081320772222,Kp. Andir DS/Kel. Manggahang Kec. Baleendah Kab. Bandung,PERUMAHAN GRAND CIPARAY RESIDENCE,12045,0.5945,7160.7525,648.11/224-SP/TR 07 Januari 2025;644/822-SP/TR 13 Februari 2025;640/524-SP/TR 17 Januari 2025;642/763-SP/TR 11 Februari 2025,500/5300-PERTEKTR/2022/TR Tanggal 04 Agustus 2022;400.7.22/4872-KRK/25/Bid.TR Tanggal 24 Desember 2024;Pu.650/7580-REKTEK/TR Tanggal 20 Desember 2022;01112410113204120 Tanggal 1 November 2024,1801220061544 Tgl 05 September 2022;600.4.5/052/1722-Ktr/TL Tanggal 20 Mei 2024;9120401971173 Tgl 11 Desember 2024;1406220076826 Tgl 15 November 2022;8120103802893 Tgl 29 Agustus 2018,Fungsi Hunian,Fungsi Hunian,2
21 / 688,PT PRAKARSA FAJAR PROPERTINDO No Telpon : 082315094712,Jl. Otto Iskandardinata No 429 Kel. Pungkur Kec. Regol Kota Bandung,PERUMAHAN ALAM BUMI CIPARAY,17417,0.6793,11831.3681,648.11/688-SP/TR 03 Februari 2025,500.10.29.15/1075-REKTEK/TR Tanggal 04 Maret 2024,9120007841259 Tgl 15 Agustus 2019;500.10.29.7/Kep.405-DLH/2025 Tanggal 06 Januari 2025,Fungsi Hunian,Fungsi Hunian,2
22 / 767,PT CITRA SENTOSA JAYATAMA No Telpon : 087825393706,Jl. Nyengseret No 29 RT 01 Kel. Pelindung hewaqn Kota Bandung,PERUMAHAN CITRA ASRI RESIDENCE,28900,0.692,19998.8,648.11/767-SP/TR 12 Februari 2025,500.10.29.15/2617-REKTEK/Bid. Taru Tanggal 10 Juli 2024,9120107971097 Tgl 19 September 2019;500.10.29.7/Kep.612-DLH/2024 Tanggal 18 November 2024,Fungsi Hunian,Fungsi Hunian,2
23/ 641,PT PESONA MITRA KEMBAR MAS No Telpon : 081220763283,Jl Kembar mas IV No 2A RT 05/09 Kel. Pasirluyu Kec. Regol Kota Bandung,REVISI 5 PERUMAHAN PODOMORO PARK,1160011,0.6691,776163.3601,648.11/641- SP/TR 22 Januari 2025,591/057-DPMPTSP/2017 Tanggal 28 Desember 2017,650/Kep.628-DLH/2018 Tanggal 30 Nopember 2018,Fungsi Hunian,Fungsi Hunian,2
24 / 659,PT PAVITRA PARA ARTHA No Telpon : 081809063866,Jl . Kubang Beureum No 39 RT 007 / 011 Kelurahan Sekejati Kecamatan Buahbatu,REVISI 4 PERUMAHAN PRIVATE VILLAGE,88245,0.5819,51349.7655,648.11/659 - SP/TR 23 Januari 2025;645/932 - SP/TR 21 Februari 2025;645/552-SP/TR 20 Januari 2025;647/640-SP/TR 22 Januari 2025;647/930-SP/TR 21 Februari 2025,591.4/001-BPMP/2014 Tanggal 06 Januari 2014;591.4/031-DPMPTSP/2019 Tanggal 10 Juli 2019;503/104/XII-DPMPTSP/2019- Tgl 20 Desember 2019;400.1.22/4521-KRK/15/Bid.Taru Tgl 16 Desember 2024;650/2597-KRTR/2021/TR Tgl 9 Desember 2021;500.10.29.15/2839-REKTEK/Bid.TAru Tgl 2 Agustus 2024,500.10.29.6/4898/TL Tanggal 08 Nopember 2023;667/2995/TL Tanggal 11 Agustus 2020;9120000431996 Tanggal 20 Oktober 2021;500.10.29.7/Kep.629-DLH/2024;9120605793306 Tanggal 9 Mei 2023;1601240112040181 Tanggal 16 Januari 2024;8120215192631 Tanggal 3 Januari 2022;34/LH.01.06.05/DLH Tanggal 3 Januari 2025;9120101841825 Tanggal 18 Oktober 2023,Fungsi Hunian,Fungsi Hunian,2
29 / 931,PT KARYA HAFANA INTAN MANDIRI No Telpon : 082120002925 ,Kp./Desa Ciluluk Kecamatan Cikancung Kabupaten Bandung,PERUMAHAN GRIYA CIHANYIR PERMAI,24432.33,0.5945,14525.02019,648.11/931 - SP/TR 21 Februari 2025,400.7.22/4840-KRK/21/Bid.Taru Tgl. 18 Desember 2024,2908210007625 Tanggal 06 Mei 2024;500.10.29.7/Kep.414-DLH/2025 Tanggal 30 Januari 2025,Fungsi Hunian,Fungsi Hunian,2
30 / 933,PT ARUM JAYA PROPERTI No Telpon : 085100942672,Perumahan Banyu Arum Residence Blok A Kp. Tegal Tengah RT 003/013 Desa Cangkuang Kec. Rancaekek,REVISI 1 PERUMAHAN BUMI ARUM REGENCY,58899,0.4838,28495.3362,648.11/933 - SP/PR 21 FEBRUARI 2025,591.4/026-DPMPTSP/2018 Tgl 24 September 2018,667/7210/TL Tanggal 16 Nopember 2018;500.10.29.6/Kep.420-DLH/2025 Tanmggal 3 Februari 2025,Fungsi Hunian,Fungsi Hunian,2
31 / 762,SANDY SALMAN No Telpon : 082118781624,Jl Kembar VIII No 26 RT 005/010 Kel Cigereleng Kec. Regol Kota Bandung 40253,REVISI 1 PERUMAHAN D HEUVEL WIWAHA PADASUKA,3095,0.4295,1329.3025,648.11/ 762 - SP / PR 11 Februari 2025;648/523-SP/TR 17 Januari 2025;647/1140-SP/TR 27 Februari 2025;647/934-SP/TR 21 Februari 2025;647/1233-SP/TR 06 Maret 2025,"650/5689-PETEKTR/2022/TR Tanggal 30 Agustus 2022;650/2748-KRTR/2021/TR Tgl 21 Desember 2021;593.SK.93-BKPMD/90 Tanggal 11 April 1990;593/SK.225-BKPMD/1991 Tanggal 28 Juni 1991;591,4/009-BPMP/2014 Tanggal 27 Maret 2014;500.10.29.15/711-REKTEK/TR Tanggal 15 Februari 2024;500.10.29.15/2877-REKTEK/Bid.Taru Tanggal 19 Agustus 2024 ",LH.01.04/5866-SPPL/TL Tanggal 27 Desember 2022;1402220064386 Tanggal 04 Februari 2022;500.10.29.7/Kep.593-DLH/2024 Tanggal 27 September 2024;667/3257/BPLH Tanggal 06 Oktober 2014;2711230388253 Tanggal 27 Nopember 2023;500.10.29.7/Kep.630-DLH/2024 Tanggal 20 Desember 2024;9120312050674 Tanggal 07 Oktober 2019;500.10.29.7/Kep.426-DLH/2025 Tanggal 14 Februari 2025,Fungsi Hunian,Fungsi Hunian,1
36/ 1141,HANDRIAWAN No Telpon : 081313350382,Jalan Taman Holis Indah E-5 No 4-5 RT 03/06 Ds/Kel. Cigondewah Kec. Bandung kulon. Kota Bandung,TOKO DAN GUDANG,2025,0.7848,1589.22,647/1141-SP/TR 27 Februari 2025;647/1211-SP/TR 04 Maret 2025;648.2/1091-SP/TR 25 Februari 2025,400.7.22/559-KRK/14/Bid.Taru Tanggal 17 Januari 2025;400.7.22/859-KRK/38/Bid.Taru Tanggal 17 Februari 2025;500.10.29.15/4064 - REKTEK/Bid.Taru Tanggal 25 Nopember 2024,1401250067962 Tanggal 14 Januari 2025;1812240057832 Tanggal 18 Desember 2024;1611210013009 Tanggal 16 Nopember 2021,Usaha Besar (Non-Mikro),Fungsi Usaha,1
39/ 1232,JOHANSJAH SUGIANTO No Telpon : 081314974495,Jalan Kepodang VI/6 blok k2 Rengas Kec. Ciputat timur kota Tangerang selatan,TOKO,2490,21.9,54531,644.2/1232-SP/TR 06 Maret 2025;644.2/1234-SP/TR 06 Maret 2025,400.7.22/1089 - KRK/45//Bid.Taru Tanggal 24 Februari 2025;503/0017-PKKPRNB/DPMPTSP/II/2025 Tanggal 12 Februari 2025,3101250002573 Tanggal 31 Januari 2025;2107230112343 Tanggal 21 Juli 2023,Tidak Diketahui,Tidak Diketahui,3
41 / 1090,TIM AD HOC PERUMAHAN SUKAWANGI RESIDENCE No Telpon : 08112255770,Kp. Cihalimun RT 02/04 Ds. Cibeureum Kec. Kertasari Kab. Bandung,PERUMAHAN SUKAWANGI RESIDENCE,,1,,648.11/ 1090 - SP / PR 25 Februari 2025,,,Fungsi Hunian,Fungsi Hunian,2
42 / 1298,PT TIGA REKAN INDONESIA No Telpon : 08122444717,Jl Gradiul No 40 RT 04/07 Kel. Rancaekek Kencana Kec. Rancaekek Kab. Bandung,PERUMAHAN GREEN HILL VILLAGE,16548,0.5917,9791.4516,648.11/1298 - SP/TR 17 Maret 2025,50.10.29.15/2742-REKTEK/Bid. Taru Tanggal 24 Juli 2024,2505240130006 Tanggal 25 Mei 2024;600.4.5/061/832-Ktr/Bid. TL/2025 Tgl. 19 Februari 2025,Fungsi Hunian,Fungsi Hunian,2
43 / 1322,PT UNILOA ARDIYANTO INVESTAMA No Telpon : 081220180480,Jl Raya Ebah 103 Desa Sukamantri Kecamatan Paseh Kab. Bandung,PERUMAHAN MARISON CIPAKU,19209,0.6146,11805.8514,648.11/1322 - SP/TR 18 Maret 2025,24042410313204051 Tanggal 24 JApril 2024,0238010110358 Tanggal 11 Januari 2024;500.10.29.7/Kep. 451-DLH/2025 Tgl. 13 Maret 2025,Fungsi Hunian,Fungsi Hunian,2
44 / 1323,PT RADINAKA KRAMAT ABADI No Telpon : 082118781624,Jl. Sukamukti RT 01/06 Desa Sukamukti Kec. Katapang Kab. Bandung,PERUMAHAN GAHARU PALEDANG RESIDENCE,14665,0.68003,9972.63995,648.11/1323 - SP/TR 18 Maret 2025,02032510213204087 Tanggal 02 Maret 2025,0238010110358 Tanggal 11 Januari 2024;600.4.5/064/1165-Ktr/Bid. TL/2025 Tgl. 12 Maret 2025,Fungsi Hunian,Fungsi Hunian,2
45 / 1361,PT SANGKURIANG KRAMAT ABADI No Telpon : 082118781624,Kampung rancakasiat Desa Rancamulya Kec. Pameungpeuk Kab. Bandung,PERUMAHAN PONDOK ASRI SUKAMUKTI,20451,0.6806,13918.9506,648.11/1361 - SP/TR 24 Maret 2025,500.10.29.15/3451-REKTEK/Bid.Taru Tanggal 26 September 2024,0811230037204 Tanggal 08 Nopember 2023;500.10.29.7/Kep.460-DLH/2025 Tgl. 21 Maret 2025,Fungsi Hunian,Fungsi Hunian,2
46 / 1360,PT AUF ABDURACCHMAN JAYA No Telpon : 082118781624,Jl. Rancabungur rancakasiat Desa Malakasari Kec. Baleendah Kab. Bandung,PERUMAHAN BUMI SHANGRILA RESIDENCE,12846,0.6412,8236.8552,648.11/1360 - SP/TR 24 Maret 2025,400.7.22/093/1390-KRK/Bid.Taru Tanggal 17 Maret 2025,0603250028082 Tanggal 06 Maret 2025;600.4.5/072/1270-Ktr/Bid.TL/2025 Tgl. 21 Maret 2025,Fungsi Hunian,Fungsi Hunian,2
47 / 1142,ANTO DWI HARTANTO No Telpon : 082126215611,Jl. Elang V No 8 RT 08/01 Kel. Garuda Kec. Andir Kota Bandung,PERGUDANGAN DAN PENYIMPANAN,1307,0.5616,734.0112,647/1142 - SP/TR 27 Februari 2025;648.11/823 - SP/TR 13 Februari 2025;644.2/1389 - SP/TR 26 Maret 2025;644.2/1388 - SP/TR 26 Maret 2025,500.10.29.15/3827-REKTEK/Bid.Taru Tanggal 17 Oktober 2024;500.10.29.15/3944-REKTEK/Bid.Taru Tanggal 28 Oktober 2024;503/0072-DPMPTSP/XI/2023 Tanggal 29 November 2023;400.7.22/1046-KRK/Bid.Taru Tanggal 21 Februari 2025,2009240075774 Tanggal 20 September 2024 2025;2009240075774 Tanggal 20 September 2025;500.10.29.7/Hep-461-DLH/2025 Tanggal 21 Maret 2025;0298000921888 Tanggal 24 Januari 2022,Usaha Besar (Non-Mikro),Fungsi Usaha,1
51 / 1161,PT INGRIA PRATAMA CAPITALINDO Tbk No Telpon : 087722361043,Ruko Pondok Cabe Mutiara Jl Pondok cabe No 27 Kel. Pamulang Kec. Pamulang Kota Tangerang Selatan,REVISI 2 PERUMAHAN BUKIT ESMA CICALENGKA 2 ,74300,0.6292,46749.56,648.11/1161 - SP/TR 28 Februari 2025,50.10.29.15/2927-REKTEK/Bid. Taru Tanggal 14 Agustus 2024,591.4/005/IX-DPMPTSP/2019 Tanggal 09 September 2019;500.10.29.7/Kep.613-DLH/2024 Tgl. 18 November 2025,Fungsi Hunian,Fungsi Hunian,2
52 / 1441 ,PT ABADI MUKTI KIRANA No Telpon : 087821848944,Jl Terusan jamika No 88 Kel. Jamika Kec. Bojongloa kaler Kota Bandung, PERUMAHAN KOTA BARU ARJASARI,222816,1,222816,648.11/1441 - SP/TR 11 April 2025,400.7.28/1710/TR Tanggal 23 April 2024,9120108201236 Tanggal 13 Februari 2019;500.10.29.7/Kep.419-DLH/2025 Tgl. 03 Februari 2025,Fungsi Hunian,Fungsi Hunian,2
53 / 1566,PT MAKMUR INDAH DAMAI No Telpon : 081394722234,Jl. Podomoro Boulevard utara I Desa Lengkong Kec. Bojongsoang Kab. Bandung,PERUMAHAN BAROS INDAH RESIDENCE,17513,1,17513,647/1566 - SP/TR 25 April 2025,50.10.29.15/2507-REKTEK/Bid. Taru Tanggal 25 Juni 2024,2106240023693 Tanggal 21 Juni 2024;500.10.29.7/Kep.447-DLH/2024 Tgl. 10 Maret 2025,Fungsi Hunian,Fungsi Hunian,2
54 / 1343,PT KARYA BUMI BESTARI No Telpon : 08156080428,Kembar Mas IV No 2A RT 05/09 Kel. Pasirluyu Kec. Regol Kota Bandung,PERUMAHAN BESTARI MAS,26134,1,26134,648.11/1343 - SP/TR 20 Maret 2025;647/1565 - SP/TR 25 April 2025;648.1/1543 - SP/TR 17 April 2025,12042310213204004 Tanggal 12 April 2023;23122410113204057 Tanggal 23 Desember 2024;400.7.22/1047-KRK/42/Bid.Taru Tanggal 21 Februari 2025,1204230043635 Tanggal 12 April 2023;500.10.29.7/964/Bid. TL/2025 Tgl. 19 Februari 2025;9120304390956 Tanggal 05 Desember 2023;0307230050445 Tanggal 03 Juli 2023,Fungsi Hunian,Fungsi Hunian,2
57 / 1372,TENNI DIANA No Telpon : 082116106640,Cikaahuripan RT 002/005 Kec. Neglasari Kota Tangerang,PERADAGANGAN KHUSUS KARPET PERMADANI DAN PENUTUP DINDING DN LANTAI DI TOKO,1290,1,1290,644/1372 - SP/TR 26 Maret 2025;647/1557 - SP/TR 22 April 2025;640/1559 - SP/TR 22 April 2025;644/1371 - SP/TR 26 Maret 2025;644/1375 - SP/TR 26 Maret 2025;644/1373 - SP/TR 26 Maret 2025,500.10.29.15/4355-REKTEK/TR Tanggal 25 Agustus 2023;500.10.29.15/1073-REKTEK/TR Tanggal 04 Maret 2024;400.7.22/759-KRK/34/Bid.Taru Tanggal 11 Februari 2025;500.10.29.15/4654-REKTEK/Bid. Taru Tanggal 08 September 2023;500.10.29.15/4160-REKTEK/Bid. Taru Tanggal 15 Nopember 2024;500.10.29.15/2500-REKTEK/Bid. Taru Tanggal 19 Juni 2024,9120306652149 Tanggal 26 Juni 2019;0220107462528 Tanggal 08 September 2022;1283000240318 Tanggal 01 Februari 2021;600.4.5/071-KTR/Bid.TL/2025 Tgl. 05 Mei 2025;0220301251224 Tanggal 11 Agustus 2023;1263000210596 Tanggal 09 Februari 2021;1405240295325 5 Mei 2024,Tidak Diketahui,Tidak Diketahui,1
63 / 1567,Ir. BERSIH TARIGANT No Telpon : 081322777581,Jl Multatuli No 3 rt 001/001 Ds/Kel. Lebakgede Kec. Coblong Kota Bandung,PERUMAHAN TUSCANY HILL,23796,0.2428,5777.6688,648.11/1567 - SP/TR 25 April 2025,50.10.29.15/3829-REKTEK/Bid. Taru Tanggal 15 Oktober 2024,2007220014068 Tanggal 20 Juli 2025;500.10.29.7/Kep.429-DLH/2025 Tgl. 10 Maret 2025,Fungsi Hunian,Fungsi Hunian,2
64 / 1682,PT CIPTA BERKAT PROPERTI No Telpon : 081910661980,Ruko Matahari Cigado No 25 Jalan Anggadireja Kel. Baleendah Kec. Baleendah Kab. Bandung,PERUMAHAN GARDEN VIEW CICALENGKA,45666,1,45666,648.11/1682 - SP/TR 06 Mei 2025,50.10.29.15/3156-REKTEK/Bid. Taru Tanggal 05 September 2024,2310210017936 Tanggal 23 Oktober 2021;500.10.29.7/Kep.477-DLH/2025 Tgl. 17 April 2025,Fungsi Hunian,Fungsi Hunian,2
64 / 1682,PT CIPTA BERKAT PROPERTI No Telpon : 081910661980,Ruko Matahari Cigado No 25 Jalan Anggadireja Kel. Baleendah Kec. Baleendah Kab. Bandung,C. KWT PERUMAHAN,0,1,0,,,,Fungsi Hunian,Fungsi Hunian,1
65 / 1644,PT ARGUNA JAYA PROPERTY No Telpon : 081214211164,Jl Pidada IV/4 Denpasar BR/Link Sedana metra Kel. Ubung Kec. Denpasar Utara Kota Denpasar,REVISI 1 PERUMAHAN ARGUNA SINDANGPANON,8553,0.53,4533.09,648.11/1644 - SP/TR 29 April 2025;644/1558 - SP/TR 22 April 2025,503/009/II-DPMPTSP/2020 Tanggal 25 Februari 2020;50.10.29.15/4063-REKTEK/Bid. Taru Tanggal 25 Nopember 2025,9120004890734 Tanggal 03 Agustus 2019;667/2081/TL Tgl. 08 Juni 2020;0609240042720001 Tanggal 06 September 2024,Fungsi Hunian,Fungsi Hunian,1
67/ 1370,NENENG FATIMAH No Telpon : 08977980040,Jalan Batu Indah I No 26 RT 002/003 Kel. Batununggal Kec. Bandung Kidul Kota Bandung,PERGUDANGAN DAN PENYIMPANAN,2034,1,2034,644/1370 - SP/TR 26 Maret 2025,50.10.29.15/3340-REKTEK/Bid. Taru Tanggal 18 September 2025,1009240038601 Tanggal 10 September 2024,Usaha Besar (Non-Mikro),Fungsi Usaha,1
68/ 1374,LILI JOJON No Telpon : 082219855556,Kp. Cibisoro RT 004/008 Desa Nanjung Kec. Mrgaasih Kab. Bandung,PERGUDANGAN DAN PENYIMPANAN,1654,1,1654,644/1374 - SP/TR 26 Maret 2025;644.2/1683 - SP/TR 06 Mei 2025;645/1730 - SP/TR 07 Mei 2025,50.10.29.15/3210-REKTEK/Bid. Taru Tanggal 10 September 2024;400.7.22/1254-KRK/58/Bid. Taru Tanggal 10 Maret 2025;50.10.29.15/3443-REKTEK/Bid. Taru Tanggal 26 September 2024,1220000361065 Tanggal 16 Maret 2021;1712240056863 Tanggal 17 Desember 2024;0103230081544 Tanggal 01 Maret 2023;600.4.5/071/1503-Ktr/Bid. TL/2025 Tanggal 17 April 2025,Usaha Besar (Non-Mikro),Fungsi Usaha,1
71/ 1845,PT SANGKURIANG KRAMAT ABADI No Telpon : 082116602145,Kp. Rancakasiat Desa Rancamulya Kec. Pameungpeuk Kab. Bandung,PERUMAHAN CLUSTER GAHARU EMERALD,19889,1,19889,648.11 /1845 - SP/TR 19 Mei 2025,400.7.22/1526-KRK/96/Bid. Taru Tanggal 22 April 2025,0811230037204 Tanggal 08 Nopember 2023;500.10.29.7/Kep. 489-DLH/2025 Tanggal 15 Mei 2025,Fungsi Hunian,Fungsi Hunian,2
72/ 1731,PT MARGA TIRTA KENCANA No Telpon : 082130000146,Jlan BKR Lingkar selatan No 140 Kota Bandung,PERUMAHAN TAMAN CIBADUYUT INDAH 2 DAN 3,205344,1,205344,648.11 /1731 - SP/TR 07 Mei 2025;648.11 /1946 - SP/TR 22 Mei 2025;643 /1881 - SP/TR 20 Mei 2025;644 /1684 - SP/TR 06 Mei 2025;648.12 /1825 - SP/TR 16 Mei 2025,591.4/002-BPMP/2010 Tanggal 10 Januari 2010;500.10.29.15/3108-REKTEK/Bid.taru Tanggal 29 Agustus 2024;500.10.29.15/3319-REKTEK/TR Tanggal 14 Juli 2023;12092410313204101 Tanggal 12 September 2024;400.7.22/1231-KRK/Bid.Taru Tanggal 06 Maret 2025,667/3803/DLH Tanggal 22 Desember 2016;9120204202309 Tanggal 20 Februari 2019;2002230028317 Tanggal 20 Februari 2023;600.4.5/073/1562-Ktr/Bid.TL/2025 Tanggal 23 April 2025;8120006931402 Tanggal 28 September 2022;12710006324580004 Tanggal 05 Maret 2025,Fungsi Hunian,Fungsi Hunian,2
77/ 1879,PT PUTRA RAHMAN PRADANA No Telpon : 081312214962,Perum Cemerlang Permai Blok C No 16 Kel. Sukakarya Kec. Warudoyongf Kota Sukabumi,REVISI 1 PERUMAHAN BUKIT PINUS BANIARAN,90711,1,90711,648.11 /1879 - SP/TR 20 Mei 2025,22122310313204009 Tanggal 22 Desember 2023,500.10.29.7/Kep.482-DLH/2025 Tanggal 24 April 2025,Fungsi Hunian,Fungsi Hunian,2
1 no pemohon alamat activities luas_lahan bcr_kawasan area no_tapak no_skkl no_ukl fungsi_bangunan sub_fungsi_bangunan jumlah_lantai
2 01/222 PT CIPTA INDAH PERTIWI No Telpon : 082217633434 Jl Salam No 51 Desa/Kel. Cihapit Kec. Bandung wetan Kota Bandung PERUMAHAN LA LA TOWN 16629 0.2449 4072.4421 648.11./222 - SP /TR 07 Januari 2025;644.2./207 - SP /TR 02 Januari 2025 500.10.29.15/631-REKTEK/TR Tanggal 14 Februari 2023;500.10.29.15/2837-REKTEK/Bid. Taru Tanggal 25 Juli 2024 14022310313204030 Tanggal 14 Februari 2023;500.10.29.7/Kep.618-DLH/2024 Tanggal 13 Desember 2024;161023087545 Tanggal 16 Oktober2023 Fungsi Hunian Fungsi Hunian 1
3 03/481 MUHAMAD GUNTUR JULIADI No Telpon : 081223334486 Cangkuang Residence RT 004/003 Ds Cangkuang Wetan Kec. Dayeuhkolot Kab. Bandung PERUMAHAN CANGKUANG RESIDENCE 2 2360 0.5924 1398.064 648.11./481 - SP /TR 15 Januari 2025;647./226 - SP /TR 07 Januari 2025;647/225 - SP /TR 07 Januari 2025;644/221 - SP /TR 07 Januari 2025;645.4/557 - SP /TR 20 Januari 2025 500.10.29.15/2894-REKTEK/Bid. Taru Tanggal 08 Agustus 2024;400.7.22/4927-KRK/04/Bid.Taru Tanggal 06 Desember 2024;500.10.29.15/2619-REKTEK/Bid. Taru Tanggal 10 Juli 2024;500.10.29.15/4155-REKTEK/Bid. Taru Tanggal 18 Nopember 2024;503/123/III-DPMPTSP/2020 Tanggal 24 MAret 2020 167240099471 Tanggal 16 Juli 2024;9120111161314 Tanggal 11 Nopember 2019;8120312190151 Tanggal 04 Desember 2023;500.10.29.7/Kep.614-DLH/2024 Tanggal 20 Nopember 2024;2910240290118 Tanggal 29 Oktober 2024;8120001992981 Tanggal 12 Juli 2024;SK.294/Menlhk/Setjen/PLA.4/5/2021 Tanggal 31 Mei 2021 Fungsi Hunian Fungsi Hunian 1
4 08/480 PT SURYA KHARISMA PARAHYANGAN No Telpon : 081394461006 Jalan Cibaligo No 48 Desa /Kel. Cigugur tengah Kec. Cimahi tengah kota Cimahi PERUMAHAN PARAHYANGAN GARDEN CITY 116360 0.5164 60088.304 648.11./480 - SP /TR 15 Januari 2025 500.10.29.15/603-REKTEK/TR Tanggal 05 Desember 2023 1810220245722 Tanggal 18 Oktober 2022;500.10.29.7/Kep.632-DLH/2024 Tanggal 24 Desember 2024 Fungsi Hunian Fungsi Hunian 2
5 09/223 PT CLARICHEM INDONESIA No Telpon : 081315399694 Kawasan pergudangan taman tekno sektor XI blok L2 No 30 Ds/Kel. Setu Kec. Setu kota Tangerag Banten PERGUDANGAN DAN PENYIMPANAN 1586 0.7017 1112.8962 644./223 - SP /TR 07 Januari 2025 400.7.22/4427-KRK/03/Bid.Taru Tanggal 06 Desember 2024 9120008832767 Tanggal 26 Nopember 2024 Usaha Besar (Non-Mikro) Fungsi Usaha 1
6 10/657 PT HALKA GITA No Telpon : 0816734374 Jl Raya Majalaya KM 2 RT 02/09 Desa Hegarmanah Kec. Cikancung Kab. Bandung REVISI 1 KOMPLEK PERGUDANGAN 19100 0.699 13350.9 644./657 - SP /TR 23 Januari 2025 500.10.29.15/6750-REKTEK/TR Tanggal 21 Desember 2023 9120300510839 Tanggal 16 Desember 2023;500.10.29.7/Kep.609-DLH/2024 Tanggal 12 Nopember 2024 Usaha Besar (Non-Mikro) Fungsi Usaha 2
7 11/658 PT SURYA TIRTA KENCANA No Telpon : 08986155493 Kutawaringin Industrial Park Kav. 276-277 Desa Jelegong Kec. Kutawaringin Kab. Bandung PERGUDANGAN DAN PENYIMPANAN BAHAN KIMIA 3932 0.6995 2750.434 644./658 - SP /TR 23 Januari 2025;640/540 - SP /TR 20 Januari 2025 10112410113204010 Tanggal 10 Nopember 2024;591.4/031/IX-DPMPTSP/2020 Tanggal 03 Sseptember 2020 8120017120594 Tanggal 31 Agustus 2018;600.4.5/056/6838-Ktr/TL Tanggal 24 Desember 2024;0220305221438 Tanggal 20 Nopember 2021;500.10.29.7/4295/TL Tanggal 21 September 2024 Usaha Besar (Non-Mikro) Fungsi Usaha 1
8 13 / 550 PT BERKAH SEPUH JAYA No Telpon : 082118781624 Ruko komplek dewaadru blok R3 RT 005 ds/kec. Bojongsoang kab. Bandung REVISI 1 PERUMAHAN VILLA CEMARA ASRI 17379 0.5476 9516.7404 648.11/550 - SP/TR 20 Januari 2025 150223101113204049 Tanggal 15 Februari 2023 1233000451657 Tanggal 5 Mei 2023;500.10.29.7/kep.392-DLH/2025 Tgl. 2 Januari 2025 Fungsi Hunian Fungsi Hunian 2
9 14 / 655 PT RISKI ANUGERAH SEDJAHTERA No Telpon : 082118781624 Griya permata asri blok C2 No 18 Ds Lengkong Kec. Bojongsoang Kab. Bandung REVISI 1 PERUMAHAN TAMAN KATAPANG INDAH 28425 0.6532 18567.21 648.11 /655 - SP /TR 23 Januari 2025 500.10.29.15/2333-REKTEK/TR Tanggal 22 Mei 2024;500.10.29.15/3811-REKTEK/Bid. Taru Tanggal 10 Oktober 2024 1205000302875 Tanggal 02 April 2024;500.10.29.7/Kep.408-DLH/2025 Tanggal 10 Januari 2025 Fungsi Hunian Fungsi Hunian 2
10 15 / 551 PT BUMI SUWARNA SEJAHTERA No Telpon : 082118781624 Jl Ciwastra no 73 Kel. Mekarmulya kec. Rancasari kota bandung REVISI 1 PERUMAHAN BUMI KARA RESIDENCE 29711 0.5424 16115.2464 648.11/551-SP/TR 20 Januari 2025 500.10.29.15/6097-REKTEK/TR Tanggal 27 Nopember 2023 1311230078306 Tgl 13 Nopember 2023;500.10.29.7/Kep.493-DLH/2024 Tanggal 20 Maret 2024 Fungsi Hunian Fungsi Hunian 2
11 16 / 656 PT AMBER HASYA No Telpon : 081312411661 Jl Sarijadi raya No 111 Kel. Sarijadi Kec. Sukasarii kota bandung REVISI 1 PERUMAHAN GREEN HARMONI RESIDENCE 39520 0.2726 10773.152 648.11/656-SP/TR 23 Januari 2025 500.10.29.15/2732-REKTEK/Bid. Taru Tanggal 19 Juli 2024 9120004882226 Tgl 22 Agustus 2019;500.10.29.7/Kep.617-DLH/2024 Tanggal 4 Desember 2024 Fungsi Hunian Fungsi Hunian 2
12 17 / 224 PT KARYA UTAMA SEJATI JAYA No Telpon : 081320772222 Kp. Andir DS/Kel. Manggahang Kec. Baleendah Kab. Bandung PERUMAHAN GRAND CIPARAY RESIDENCE 12045 0.5945 7160.7525 648.11/224-SP/TR 07 Januari 2025;644/822-SP/TR 13 Februari 2025;640/524-SP/TR 17 Januari 2025;642/763-SP/TR 11 Februari 2025 500/5300-PERTEKTR/2022/TR Tanggal 04 Agustus 2022;400.7.22/4872-KRK/25/Bid.TR Tanggal 24 Desember 2024;Pu.650/7580-REKTEK/TR Tanggal 20 Desember 2022;01112410113204120 Tanggal 1 November 2024 1801220061544 Tgl 05 September 2022;600.4.5/052/1722-Ktr/TL Tanggal 20 Mei 2024;9120401971173 Tgl 11 Desember 2024;1406220076826 Tgl 15 November 2022;8120103802893 Tgl 29 Agustus 2018 Fungsi Hunian Fungsi Hunian 2
13 21 / 688 PT PRAKARSA FAJAR PROPERTINDO No Telpon : 082315094712 Jl. Otto Iskandardinata No 429 Kel. Pungkur Kec. Regol Kota Bandung PERUMAHAN ALAM BUMI CIPARAY 17417 0.6793 11831.3681 648.11/688-SP/TR 03 Februari 2025 500.10.29.15/1075-REKTEK/TR Tanggal 04 Maret 2024 9120007841259 Tgl 15 Agustus 2019;500.10.29.7/Kep.405-DLH/2025 Tanggal 06 Januari 2025 Fungsi Hunian Fungsi Hunian 2
14 22 / 767 PT CITRA SENTOSA JAYATAMA No Telpon : 087825393706 Jl. Nyengseret No 29 RT 01 Kel. Pelindung hewaqn Kota Bandung PERUMAHAN CITRA ASRI RESIDENCE 28900 0.692 19998.8 648.11/767-SP/TR 12 Februari 2025 500.10.29.15/2617-REKTEK/Bid. Taru Tanggal 10 Juli 2024 9120107971097 Tgl 19 September 2019;500.10.29.7/Kep.612-DLH/2024 Tanggal 18 November 2024 Fungsi Hunian Fungsi Hunian 2
15 23/ 641 PT PESONA MITRA KEMBAR MAS No Telpon : 081220763283 Jl Kembar mas IV No 2A RT 05/09 Kel. Pasirluyu Kec. Regol Kota Bandung REVISI 5 PERUMAHAN PODOMORO PARK 1160011 0.6691 776163.3601 648.11/641- SP/TR 22 Januari 2025 591/057-DPMPTSP/2017 Tanggal 28 Desember 2017 650/Kep.628-DLH/2018 Tanggal 30 Nopember 2018 Fungsi Hunian Fungsi Hunian 2
16 24 / 659 PT PAVITRA PARA ARTHA No Telpon : 081809063866 Jl . Kubang Beureum No 39 RT 007 / 011 Kelurahan Sekejati Kecamatan Buahbatu REVISI 4 PERUMAHAN PRIVATE VILLAGE 88245 0.5819 51349.7655 648.11/659 - SP/TR 23 Januari 2025;645/932 - SP/TR 21 Februari 2025;645/552-SP/TR 20 Januari 2025;647/640-SP/TR 22 Januari 2025;647/930-SP/TR 21 Februari 2025 591.4/001-BPMP/2014 Tanggal 06 Januari 2014;591.4/031-DPMPTSP/2019 Tanggal 10 Juli 2019;503/104/XII-DPMPTSP/2019- Tgl 20 Desember 2019;400.1.22/4521-KRK/15/Bid.Taru Tgl 16 Desember 2024;650/2597-KRTR/2021/TR Tgl 9 Desember 2021;500.10.29.15/2839-REKTEK/Bid.TAru Tgl 2 Agustus 2024 500.10.29.6/4898/TL Tanggal 08 Nopember 2023;667/2995/TL Tanggal 11 Agustus 2020;9120000431996 Tanggal 20 Oktober 2021;500.10.29.7/Kep.629-DLH/2024;9120605793306 Tanggal 9 Mei 2023;1601240112040181 Tanggal 16 Januari 2024;8120215192631 Tanggal 3 Januari 2022;34/LH.01.06.05/DLH Tanggal 3 Januari 2025;9120101841825 Tanggal 18 Oktober 2023 Fungsi Hunian Fungsi Hunian 2
17 29 / 931 PT KARYA HAFANA INTAN MANDIRI No Telpon : 082120002925 Kp./Desa Ciluluk Kecamatan Cikancung Kabupaten Bandung PERUMAHAN GRIYA CIHANYIR PERMAI 24432.33 0.5945 14525.02019 648.11/931 - SP/TR 21 Februari 2025 400.7.22/4840-KRK/21/Bid.Taru Tgl. 18 Desember 2024 2908210007625 Tanggal 06 Mei 2024;500.10.29.7/Kep.414-DLH/2025 Tanggal 30 Januari 2025 Fungsi Hunian Fungsi Hunian 2
18 30 / 933 PT ARUM JAYA PROPERTI No Telpon : 085100942672 Perumahan Banyu Arum Residence Blok A Kp. Tegal Tengah RT 003/013 Desa Cangkuang Kec. Rancaekek REVISI 1 PERUMAHAN BUMI ARUM REGENCY 58899 0.4838 28495.3362 648.11/933 - SP/PR 21 FEBRUARI 2025 591.4/026-DPMPTSP/2018 Tgl 24 September 2018 667/7210/TL Tanggal 16 Nopember 2018;500.10.29.6/Kep.420-DLH/2025 Tanmggal 3 Februari 2025 Fungsi Hunian Fungsi Hunian 2
19 31 / 762 SANDY SALMAN No Telpon : 082118781624 Jl Kembar VIII No 26 RT 005/010 Kel Cigereleng Kec. Regol Kota Bandung 40253 REVISI 1 PERUMAHAN D HEUVEL WIWAHA PADASUKA 3095 0.4295 1329.3025 648.11/ 762 - SP / PR 11 Februari 2025;648/523-SP/TR 17 Januari 2025;647/1140-SP/TR 27 Februari 2025;647/934-SP/TR 21 Februari 2025;647/1233-SP/TR 06 Maret 2025 650/5689-PETEKTR/2022/TR Tanggal 30 Agustus 2022;650/2748-KRTR/2021/TR Tgl 21 Desember 2021;593.SK.93-BKPMD/90 Tanggal 11 April 1990;593/SK.225-BKPMD/1991 Tanggal 28 Juni 1991;591,4/009-BPMP/2014 Tanggal 27 Maret 2014;500.10.29.15/711-REKTEK/TR Tanggal 15 Februari 2024;500.10.29.15/2877-REKTEK/Bid.Taru Tanggal 19 Agustus 2024 LH.01.04/5866-SPPL/TL Tanggal 27 Desember 2022;1402220064386 Tanggal 04 Februari 2022;500.10.29.7/Kep.593-DLH/2024 Tanggal 27 September 2024;667/3257/BPLH Tanggal 06 Oktober 2014;2711230388253 Tanggal 27 Nopember 2023;500.10.29.7/Kep.630-DLH/2024 Tanggal 20 Desember 2024;9120312050674 Tanggal 07 Oktober 2019;500.10.29.7/Kep.426-DLH/2025 Tanggal 14 Februari 2025 Fungsi Hunian Fungsi Hunian 1
20 36/ 1141 HANDRIAWAN No Telpon : 081313350382 Jalan Taman Holis Indah E-5 No 4-5 RT 03/06 Ds/Kel. Cigondewah Kec. Bandung kulon. Kota Bandung TOKO DAN GUDANG 2025 0.7848 1589.22 647/1141-SP/TR 27 Februari 2025;647/1211-SP/TR 04 Maret 2025;648.2/1091-SP/TR 25 Februari 2025 400.7.22/559-KRK/14/Bid.Taru Tanggal 17 Januari 2025;400.7.22/859-KRK/38/Bid.Taru Tanggal 17 Februari 2025;500.10.29.15/4064 - REKTEK/Bid.Taru Tanggal 25 Nopember 2024 1401250067962 Tanggal 14 Januari 2025;1812240057832 Tanggal 18 Desember 2024;1611210013009 Tanggal 16 Nopember 2021 Usaha Besar (Non-Mikro) Fungsi Usaha 1
21 39/ 1232 JOHANSJAH SUGIANTO No Telpon : 081314974495 Jalan Kepodang VI/6 blok k2 Rengas Kec. Ciputat timur kota Tangerang selatan TOKO 2490 21.9 54531 644.2/1232-SP/TR 06 Maret 2025;644.2/1234-SP/TR 06 Maret 2025 400.7.22/1089 - KRK/45//Bid.Taru Tanggal 24 Februari 2025;503/0017-PKKPRNB/DPMPTSP/II/2025 Tanggal 12 Februari 2025 3101250002573 Tanggal 31 Januari 2025;2107230112343 Tanggal 21 Juli 2023 Tidak Diketahui Tidak Diketahui 3
22 41 / 1090 TIM AD HOC PERUMAHAN SUKAWANGI RESIDENCE No Telpon : 08112255770 Kp. Cihalimun RT 02/04 Ds. Cibeureum Kec. Kertasari Kab. Bandung PERUMAHAN SUKAWANGI RESIDENCE 1 648.11/ 1090 - SP / PR 25 Februari 2025 Fungsi Hunian Fungsi Hunian 2
23 42 / 1298 PT TIGA REKAN INDONESIA No Telpon : 08122444717 Jl Gradiul No 40 RT 04/07 Kel. Rancaekek Kencana Kec. Rancaekek Kab. Bandung PERUMAHAN GREEN HILL VILLAGE 16548 0.5917 9791.4516 648.11/1298 - SP/TR 17 Maret 2025 50.10.29.15/2742-REKTEK/Bid. Taru Tanggal 24 Juli 2024 2505240130006 Tanggal 25 Mei 2024;600.4.5/061/832-Ktr/Bid. TL/2025 Tgl. 19 Februari 2025 Fungsi Hunian Fungsi Hunian 2
24 43 / 1322 PT UNILOA ARDIYANTO INVESTAMA No Telpon : 081220180480 Jl Raya Ebah 103 Desa Sukamantri Kecamatan Paseh Kab. Bandung PERUMAHAN MARISON CIPAKU 19209 0.6146 11805.8514 648.11/1322 - SP/TR 18 Maret 2025 24042410313204051 Tanggal 24 JApril 2024 0238010110358 Tanggal 11 Januari 2024;500.10.29.7/Kep. 451-DLH/2025 Tgl. 13 Maret 2025 Fungsi Hunian Fungsi Hunian 2
25 44 / 1323 PT RADINAKA KRAMAT ABADI No Telpon : 082118781624 Jl. Sukamukti RT 01/06 Desa Sukamukti Kec. Katapang Kab. Bandung PERUMAHAN GAHARU PALEDANG RESIDENCE 14665 0.68003 9972.63995 648.11/1323 - SP/TR 18 Maret 2025 02032510213204087 Tanggal 02 Maret 2025 0238010110358 Tanggal 11 Januari 2024;600.4.5/064/1165-Ktr/Bid. TL/2025 Tgl. 12 Maret 2025 Fungsi Hunian Fungsi Hunian 2
26 45 / 1361 PT SANGKURIANG KRAMAT ABADI No Telpon : 082118781624 Kampung rancakasiat Desa Rancamulya Kec. Pameungpeuk Kab. Bandung PERUMAHAN PONDOK ASRI SUKAMUKTI 20451 0.6806 13918.9506 648.11/1361 - SP/TR 24 Maret 2025 500.10.29.15/3451-REKTEK/Bid.Taru Tanggal 26 September 2024 0811230037204 Tanggal 08 Nopember 2023;500.10.29.7/Kep.460-DLH/2025 Tgl. 21 Maret 2025 Fungsi Hunian Fungsi Hunian 2
27 46 / 1360 PT AUF ABDURACCHMAN JAYA No Telpon : 082118781624 Jl. Rancabungur rancakasiat Desa Malakasari Kec. Baleendah Kab. Bandung PERUMAHAN BUMI SHANGRILA RESIDENCE 12846 0.6412 8236.8552 648.11/1360 - SP/TR 24 Maret 2025 400.7.22/093/1390-KRK/Bid.Taru Tanggal 17 Maret 2025 0603250028082 Tanggal 06 Maret 2025;600.4.5/072/1270-Ktr/Bid.TL/2025 Tgl. 21 Maret 2025 Fungsi Hunian Fungsi Hunian 2
28 47 / 1142 ANTO DWI HARTANTO No Telpon : 082126215611 Jl. Elang V No 8 RT 08/01 Kel. Garuda Kec. Andir Kota Bandung PERGUDANGAN DAN PENYIMPANAN 1307 0.5616 734.0112 647/1142 - SP/TR 27 Februari 2025;648.11/823 - SP/TR 13 Februari 2025;644.2/1389 - SP/TR 26 Maret 2025;644.2/1388 - SP/TR 26 Maret 2025 500.10.29.15/3827-REKTEK/Bid.Taru Tanggal 17 Oktober 2024;500.10.29.15/3944-REKTEK/Bid.Taru Tanggal 28 Oktober 2024;503/0072-DPMPTSP/XI/2023 Tanggal 29 November 2023;400.7.22/1046-KRK/Bid.Taru Tanggal 21 Februari 2025 2009240075774 Tanggal 20 September 2024 2025;2009240075774 Tanggal 20 September 2025;500.10.29.7/Hep-461-DLH/2025 Tanggal 21 Maret 2025;0298000921888 Tanggal 24 Januari 2022 Usaha Besar (Non-Mikro) Fungsi Usaha 1
29 51 / 1161 PT INGRIA PRATAMA CAPITALINDO Tbk No Telpon : 087722361043 Ruko Pondok Cabe Mutiara Jl Pondok cabe No 27 Kel. Pamulang Kec. Pamulang Kota Tangerang Selatan REVISI 2 PERUMAHAN BUKIT ESMA CICALENGKA 2 74300 0.6292 46749.56 648.11/1161 - SP/TR 28 Februari 2025 50.10.29.15/2927-REKTEK/Bid. Taru Tanggal 14 Agustus 2024 591.4/005/IX-DPMPTSP/2019 Tanggal 09 September 2019;500.10.29.7/Kep.613-DLH/2024 Tgl. 18 November 2025 Fungsi Hunian Fungsi Hunian 2
30 52 / 1441 PT ABADI MUKTI KIRANA No Telpon : 087821848944 Jl Terusan jamika No 88 Kel. Jamika Kec. Bojongloa kaler Kota Bandung PERUMAHAN KOTA BARU ARJASARI 222816 1 222816 648.11/1441 - SP/TR 11 April 2025 400.7.28/1710/TR Tanggal 23 April 2024 9120108201236 Tanggal 13 Februari 2019;500.10.29.7/Kep.419-DLH/2025 Tgl. 03 Februari 2025 Fungsi Hunian Fungsi Hunian 2
31 53 / 1566 PT MAKMUR INDAH DAMAI No Telpon : 081394722234 Jl. Podomoro Boulevard utara I Desa Lengkong Kec. Bojongsoang Kab. Bandung PERUMAHAN BAROS INDAH RESIDENCE 17513 1 17513 647/1566 - SP/TR 25 April 2025 50.10.29.15/2507-REKTEK/Bid. Taru Tanggal 25 Juni 2024 2106240023693 Tanggal 21 Juni 2024;500.10.29.7/Kep.447-DLH/2024 Tgl. 10 Maret 2025 Fungsi Hunian Fungsi Hunian 2
32 54 / 1343 PT KARYA BUMI BESTARI No Telpon : 08156080428 Kembar Mas IV No 2A RT 05/09 Kel. Pasirluyu Kec. Regol Kota Bandung PERUMAHAN BESTARI MAS 26134 1 26134 648.11/1343 - SP/TR 20 Maret 2025;647/1565 - SP/TR 25 April 2025;648.1/1543 - SP/TR 17 April 2025 12042310213204004 Tanggal 12 April 2023;23122410113204057 Tanggal 23 Desember 2024;400.7.22/1047-KRK/42/Bid.Taru Tanggal 21 Februari 2025 1204230043635 Tanggal 12 April 2023;500.10.29.7/964/Bid. TL/2025 Tgl. 19 Februari 2025;9120304390956 Tanggal 05 Desember 2023;0307230050445 Tanggal 03 Juli 2023 Fungsi Hunian Fungsi Hunian 2
33 57 / 1372 TENNI DIANA No Telpon : 082116106640 Cikaahuripan RT 002/005 Kec. Neglasari Kota Tangerang PERADAGANGAN KHUSUS KARPET PERMADANI DAN PENUTUP DINDING DN LANTAI DI TOKO 1290 1 1290 644/1372 - SP/TR 26 Maret 2025;647/1557 - SP/TR 22 April 2025;640/1559 - SP/TR 22 April 2025;644/1371 - SP/TR 26 Maret 2025;644/1375 - SP/TR 26 Maret 2025;644/1373 - SP/TR 26 Maret 2025 500.10.29.15/4355-REKTEK/TR Tanggal 25 Agustus 2023;500.10.29.15/1073-REKTEK/TR Tanggal 04 Maret 2024;400.7.22/759-KRK/34/Bid.Taru Tanggal 11 Februari 2025;500.10.29.15/4654-REKTEK/Bid. Taru Tanggal 08 September 2023;500.10.29.15/4160-REKTEK/Bid. Taru Tanggal 15 Nopember 2024;500.10.29.15/2500-REKTEK/Bid. Taru Tanggal 19 Juni 2024 9120306652149 Tanggal 26 Juni 2019;0220107462528 Tanggal 08 September 2022;1283000240318 Tanggal 01 Februari 2021;600.4.5/071-KTR/Bid.TL/2025 Tgl. 05 Mei 2025;0220301251224 Tanggal 11 Agustus 2023;1263000210596 Tanggal 09 Februari 2021;1405240295325 5 Mei 2024 Tidak Diketahui Tidak Diketahui 1
34 63 / 1567 Ir. BERSIH TARIGANT No Telpon : 081322777581 Jl Multatuli No 3 rt 001/001 Ds/Kel. Lebakgede Kec. Coblong Kota Bandung PERUMAHAN TUSCANY HILL 23796 0.2428 5777.6688 648.11/1567 - SP/TR 25 April 2025 50.10.29.15/3829-REKTEK/Bid. Taru Tanggal 15 Oktober 2024 2007220014068 Tanggal 20 Juli 2025;500.10.29.7/Kep.429-DLH/2025 Tgl. 10 Maret 2025 Fungsi Hunian Fungsi Hunian 2
35 64 / 1682 PT CIPTA BERKAT PROPERTI No Telpon : 081910661980 Ruko Matahari Cigado No 25 Jalan Anggadireja Kel. Baleendah Kec. Baleendah Kab. Bandung PERUMAHAN GARDEN VIEW CICALENGKA 45666 1 45666 648.11/1682 - SP/TR 06 Mei 2025 50.10.29.15/3156-REKTEK/Bid. Taru Tanggal 05 September 2024 2310210017936 Tanggal 23 Oktober 2021;500.10.29.7/Kep.477-DLH/2025 Tgl. 17 April 2025 Fungsi Hunian Fungsi Hunian 2
36 64 / 1682 PT CIPTA BERKAT PROPERTI No Telpon : 081910661980 Ruko Matahari Cigado No 25 Jalan Anggadireja Kel. Baleendah Kec. Baleendah Kab. Bandung C. KWT PERUMAHAN 0 1 0 Fungsi Hunian Fungsi Hunian 1
37 65 / 1644 PT ARGUNA JAYA PROPERTY No Telpon : 081214211164 Jl Pidada IV/4 Denpasar BR/Link Sedana metra Kel. Ubung Kec. Denpasar Utara Kota Denpasar REVISI 1 PERUMAHAN ARGUNA SINDANGPANON 8553 0.53 4533.09 648.11/1644 - SP/TR 29 April 2025;644/1558 - SP/TR 22 April 2025 503/009/II-DPMPTSP/2020 Tanggal 25 Februari 2020;50.10.29.15/4063-REKTEK/Bid. Taru Tanggal 25 Nopember 2025 9120004890734 Tanggal 03 Agustus 2019;667/2081/TL Tgl. 08 Juni 2020;0609240042720001 Tanggal 06 September 2024 Fungsi Hunian Fungsi Hunian 1
38 67/ 1370 NENENG FATIMAH No Telpon : 08977980040 Jalan Batu Indah I No 26 RT 002/003 Kel. Batununggal Kec. Bandung Kidul Kota Bandung PERGUDANGAN DAN PENYIMPANAN 2034 1 2034 644/1370 - SP/TR 26 Maret 2025 50.10.29.15/3340-REKTEK/Bid. Taru Tanggal 18 September 2025 1009240038601 Tanggal 10 September 2024 Usaha Besar (Non-Mikro) Fungsi Usaha 1
39 68/ 1374 LILI JOJON No Telpon : 082219855556 Kp. Cibisoro RT 004/008 Desa Nanjung Kec. Mrgaasih Kab. Bandung PERGUDANGAN DAN PENYIMPANAN 1654 1 1654 644/1374 - SP/TR 26 Maret 2025;644.2/1683 - SP/TR 06 Mei 2025;645/1730 - SP/TR 07 Mei 2025 50.10.29.15/3210-REKTEK/Bid. Taru Tanggal 10 September 2024;400.7.22/1254-KRK/58/Bid. Taru Tanggal 10 Maret 2025;50.10.29.15/3443-REKTEK/Bid. Taru Tanggal 26 September 2024 1220000361065 Tanggal 16 Maret 2021;1712240056863 Tanggal 17 Desember 2024;0103230081544 Tanggal 01 Maret 2023;600.4.5/071/1503-Ktr/Bid. TL/2025 Tanggal 17 April 2025 Usaha Besar (Non-Mikro) Fungsi Usaha 1
40 71/ 1845 PT SANGKURIANG KRAMAT ABADI No Telpon : 082116602145 Kp. Rancakasiat Desa Rancamulya Kec. Pameungpeuk Kab. Bandung PERUMAHAN CLUSTER GAHARU EMERALD 19889 1 19889 648.11 /1845 - SP/TR 19 Mei 2025 400.7.22/1526-KRK/96/Bid. Taru Tanggal 22 April 2025 0811230037204 Tanggal 08 Nopember 2023;500.10.29.7/Kep. 489-DLH/2025 Tanggal 15 Mei 2025 Fungsi Hunian Fungsi Hunian 2
41 72/ 1731 PT MARGA TIRTA KENCANA No Telpon : 082130000146 Jlan BKR Lingkar selatan No 140 Kota Bandung PERUMAHAN TAMAN CIBADUYUT INDAH 2 DAN 3 205344 1 205344 648.11 /1731 - SP/TR 07 Mei 2025;648.11 /1946 - SP/TR 22 Mei 2025;643 /1881 - SP/TR 20 Mei 2025;644 /1684 - SP/TR 06 Mei 2025;648.12 /1825 - SP/TR 16 Mei 2025 591.4/002-BPMP/2010 Tanggal 10 Januari 2010;500.10.29.15/3108-REKTEK/Bid.taru Tanggal 29 Agustus 2024;500.10.29.15/3319-REKTEK/TR Tanggal 14 Juli 2023;12092410313204101 Tanggal 12 September 2024;400.7.22/1231-KRK/Bid.Taru Tanggal 06 Maret 2025 667/3803/DLH Tanggal 22 Desember 2016;9120204202309 Tanggal 20 Februari 2019;2002230028317 Tanggal 20 Februari 2023;600.4.5/073/1562-Ktr/Bid.TL/2025 Tanggal 23 April 2025;8120006931402 Tanggal 28 September 2022;12710006324580004 Tanggal 05 Maret 2025 Fungsi Hunian Fungsi Hunian 2
42 77/ 1879 PT PUTRA RAHMAN PRADANA No Telpon : 081312214962 Perum Cemerlang Permai Blok C No 16 Kel. Sukakarya Kec. Warudoyongf Kota Sukabumi REVISI 1 PERUMAHAN BUKIT PINUS BANIARAN 90711 1 90711 648.11 /1879 - SP/TR 20 Mei 2025 22122310313204009 Tanggal 22 Desember 2023 500.10.29.7/Kep.482-DLH/2025 Tanggal 24 April 2025 Fungsi Hunian Fungsi Hunian 2

56
Dockerfile Normal file
View File

@@ -0,0 +1,56 @@
FROM node:18 AS node-base
# Development stage
FROM node-base AS development
WORKDIR /var/www
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 5173
CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"]
# Production stage
FROM php:8.2-fpm AS production
WORKDIR /var/www
# Install PHP extensions
RUN apt-get update && apt-get install -y \
git curl zip unzip libpng-dev libonig-dev libxml2-dev libzip-dev \
&& docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip
# Install Node.js
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \
&& apt-get install -y nodejs
# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Copy application files
COPY . .
# Install dependencies
RUN composer install --no-dev --optimize-autoloader
# Install and build frontend assets
RUN npm install \
&& npm run build \
&& ls -la public/build \
&& mkdir -p public/assets \
&& cp -r public/build/* public/assets/ \
&& ls -la public/assets \
&& rm -rf node_modules \
&& rm -rf public/build
# Laravel caches
RUN php artisan config:clear \
&& php artisan route:clear \
&& php artisan view:clear \
&& php artisan optimize
RUN php artisan storage:link
# Permissions
RUN chown -R www-data:www-data /var/www && chmod -R 755 /var/www/storage /var/www/public
EXPOSE 9000
CMD ["php-fpm"]

View File

@@ -0,0 +1,210 @@
# Struktur Tabel Retribusi PBG yang Dioptimalkan
## Ringkasan Optimasi
Struktur tabel baru ini **lebih sederhana**, **fokus pada perhitungan**, dan **menghilangkan redundansi** dari struktur sebelumnya.
## Perbandingan Struktur
### SEBELUM (Kompleks)
- `building_functions` - 8 kolom + relationship kompleks
- `building_function_parameters` - 12 kolom dengan mismatch model/migration
- `retribution_formulas` - Menyimpan formula sebagai string
- `retribution_proposals` - 15+ kolom dengan banyak redundansi
- `floor_height_indices` - OK, tidak berubah
### SESUDAH (Sederhana)
- `building_types` - **7 kolom**, hierarki sederhana
- `retribution_indices` - **6 kolom**, parameter calculation saja
- `height_indices` - **3 kolom**, sama seperti sebelumnya
- `retribution_configs` - **5 kolom**, konfigurasi global
- `retribution_calculations` - **8 kolom**, hasil perhitungan saja
---
## Detail Struktur Tabel Baru
### 1. `building_types`
**Fungsi:** Menyimpan jenis fungsi bangunan dengan hierarki sederhana
| Kolom | Tipe | Keterangan |
| ------------- | ------------ | ---------------------------------- |
| `id` | bigint | Primary key |
| `code` | varchar(10) | Kode unik (UMKM, KEAGAMAAN, dll) |
| `name` | varchar(100) | Nama fungsi bangunan |
| `parent_id` | bigint | ID parent (untuk hierarki) |
| `level` | tinyint | Level hierarki (1=parent, 2=child) |
| `coefficient` | decimal(8,4) | **Koefisien untuk perhitungan** |
| `is_free` | boolean | **Apakah gratis (keagamaan, MBR)** |
### 2. `retribution_indices`
**Fungsi:** Menyimpan parameter indeks untuk perhitungan (1:1 dengan building_types)
| Kolom | Tipe | Keterangan |
| ----------------------- | ------------ | ---------------------------------- |
| `id` | bigint | Primary key |
| `building_type_id` | bigint | FK ke building_types |
| `ip_permanent` | decimal(8,4) | **Indeks Permanensi** |
| `ip_complexity` | decimal(8,4) | **Indeks Kompleksitas** |
| `locality_index` | decimal(8,4) | **Indeks Lokalitas** |
| `infrastructure_factor` | decimal(8,4) | **Faktor prasarana (default 50%)** |
### 3. `height_indices`
**Fungsi:** Indeks ketinggian per lantai (sama seperti sebelumnya)
| Kolom | Tipe | Keterangan |
| -------------- | ------------ | ---------------------------------------- |
| `id` | bigint | Primary key |
| `floor_number` | tinyint | Nomor lantai (1,2,3,4,5,6) |
| `height_index` | decimal(8,6) | **IP Ketinggian (1.0, 1.09, 1.12, dst)** |
### 4. `retribution_configs`
**Fungsi:** Konfigurasi global untuk perhitungan (menggantikan hard-coded values)
| Kolom | Tipe | Keterangan |
| ------------- | ------------- | --------------------- |
| `id` | bigint | Primary key |
| `key` | varchar(50) | Kunci konfigurasi |
| `value` | decimal(15,2) | **Nilai konfigurasi** |
| `description` | varchar(200) | Deskripsi |
**Data yang disimpan:**
- `BASE_VALUE` = 70350 (nilai dasar)
- `INFRASTRUCTURE_MULTIPLIER` = 0.5 (50% prasarana)
- `HEIGHT_MULTIPLIER` = 0.5 (pengali indeks ketinggian)
### 5. `retribution_calculations`
**Fungsi:** Hasil perhitungan retribusi (history)
| Kolom | Tipe | Keterangan |
| -------------------- | ------------- | -------------------------------- |
| `id` | bigint | Primary key |
| `calculation_id` | varchar(20) | ID unik perhitungan |
| `building_type_id` | bigint | FK ke building_types |
| `floor_number` | tinyint | Lantai yang dipilih |
| `building_area` | decimal(12,2) | **Luas bangunan input** |
| `retribution_amount` | decimal(15,2) | **Hasil perhitungan** |
| `calculation_detail` | json | **Detail breakdown perhitungan** |
| `calculated_at` | timestamp | Waktu perhitungan |
---
## Formula Perhitungan
### Formula Excel yang Diimplementasikan:
```
H13 = coefficient * (ip_permanent + ip_complexity + (0.5 * height_index))
Main Calculation = building_area * (locality_index * BASE_VALUE * H13)
Infrastructure = INFRASTRUCTURE_MULTIPLIER * Main Calculation
Total Retribution = Main Calculation + Infrastructure
```
### Implementasi dalam Service:
```php
// Step 1: Calculate H13 coefficient
$h13 = $buildingType->coefficient * (
$indices->ip_permanent +
$indices->ip_complexity +
(0.5 * $heightIndex)
);
// Step 2: Main calculation
$mainCalculation = $buildingArea * ($indices->locality_index * $baseValue * $h13);
// Step 3: Infrastructure (50% additional)
$infrastructureCalculation = 0.5 * $mainCalculation;
// Step 4: Total
$totalRetribution = $mainCalculation + $infrastructureCalculation;
```
---
## Keuntungan Struktur Baru
### ✅ **Simplicity**
- **5 tabel** vs 8+ tabel sebelumnya
- **Kolom minimal** hanya yang diperlukan untuk perhitungan
- **No redundant data** seperti ip_ketinggian di proposals
### ✅ **Performance**
- **Proper indexes** untuk query yang sering digunakan
- **Normalized structure** mengurangi storage
- **Cached configs** untuk values yang jarang berubah
### ✅ **Maintainability**
- **Clear separation** antara master data dan calculation results
- **Configurable values** tidak hard-coded lagi
- **Single responsibility** setiap tabel punya tujuan jelas
### ✅ **Flexibility**
- **Easy to extend** untuk fungsi bangunan baru
- **Configurable formulas** lewat RetributionConfig
- **Audit trail** lewat calculation history
### ✅ **Data Integrity**
- **Proper constraints** untuk validasi data
- **Foreign key relationships** yang benar
- **No model-migration mismatch**
---
## Migration Guide
### Langkah Implementasi:
1. **Run Migration:** `php artisan migrate` untuk tabel baru
2. **Seed Data:** Data master berdasarkan Excel akan otomatis ter-seed
3. **Update Code:** Ganti penggunaan model lama dengan model baru
4. **Test Calculation:** Verifikasi hasil perhitungan sama dengan Excel
5. **Deploy:** Struktur siap production
### Data Migration (Optional):
Jika ada data existing di tabel lama yang perlu dipindahkan, buat script migration untuk transfer data dari struktur lama ke struktur baru.
---
## Usage Example
```php
// Initialize service
$calculator = new RetributionCalculatorService();
// Calculate retribution
$result = $calculator->calculate(
buildingTypeId: 8, // UMKM
floorNumber: 2, // 2 lantai
buildingArea: 100.50, // 100.5 m2
saveResult: true // Simpan ke database
);
// Result structure
[
'building_type' => [...],
'total_retribution' => 31658.25,
'formatted_amount' => 'Rp 31,658.25',
'calculation_steps' => [...],
'calculation_id' => 'RTB-20250130140530-123'
]
```
Struktur ini **jauh lebih clean**, **mudah dipahami**, dan **optimal untuk perhitungan retribusi PBG**!

136
README.md Executable file → Normal file
View File

@@ -1,66 +1,112 @@
<p align="center"><a href="https://laravel.com" target="_blank"><img src="https://raw.githubusercontent.com/laravel/art/master/logo-lockup/5%20SVG/2%20CMYK/1%20Full%20Color/laravel-logolockup-cmyk-red.svg" width="400" alt="Laravel Logo"></a></p>
# Usage icon
<p align="center">
<a href="https://github.com/laravel/framework/actions"><img src="https://github.com/laravel/framework/workflows/tests/badge.svg" alt="Build Status"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/dt/laravel/framework" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/v/laravel/framework" alt="Latest Stable Version"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/l/laravel/framework" alt="License"></a>
</p>
search or pick icon in <a href="https://icon-sets.iconify.design/mingcute/?keyword=mingcute">here</a>
## About Laravel
# Set up queue for running automatically
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:
- Install Supervisor
- [Simple, fast routing engine](https://laravel.com/docs/routing).
- [Powerful dependency injection container](https://laravel.com/docs/container).
- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage.
- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent).
- Database agnostic [schema migrations](https://laravel.com/docs/migrations).
- [Robust background job processing](https://laravel.com/docs/queues).
- [Real-time event broadcasting](https://laravel.com/docs/broadcasting).
```
sudo apt update && sudo apt install supervisor -y
```
Laravel is accessible, powerful, and provides tools required for large, robust applications.
- Create Supervisor Config
## Learning Laravel
```
sudo nano /etc/supervisor/conf.d/laravel-worker.conf
Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework.
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /home/arifal/development/sibedas-pbg-web/artisan queue:work --queue=default --timeout=82800 --tries=1
autostart=true
autorestart=true
numprocs=1
redirect_stderr=true
stdout_logfile=/home/arifal/development/sibedas-pbg-web/storage/logs/worker.log
stopasgroup=true
killasgroup=true
```
You may also try the [Laravel Bootcamp](https://bootcamp.laravel.com), where you will be guided through building a modern Laravel application from scratch.
- Reload Supervisor
If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains thousands of video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library.
```
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-worker
sudo supervisorctl restart laravel-worker
sudo supervisorctl status
```
## Laravel Sponsors
# How to running
We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the [Laravel Partners program](https://partners.laravel.com).
- Install composer package
### Premium Partners
```
composer install
```
- **[Vehikl](https://vehikl.com/)**
- **[Tighten Co.](https://tighten.co)**
- **[WebReinvent](https://webreinvent.com/)**
- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)**
- **[64 Robots](https://64robots.com)**
- **[Curotec](https://www.curotec.com/services/technologies/laravel/)**
- **[Cyber-Duck](https://cyber-duck.co.uk)**
- **[DevSquad](https://devsquad.com/hire-laravel-developers)**
- **[Jump24](https://jump24.co.uk)**
- **[Redberry](https://redberry.international/laravel/)**
- **[Active Logic](https://activelogic.com)**
- **[byte5](https://byte5.de)**
- **[OP.GG](https://op.gg)**
- Install npm package
## Contributing
```
npm install && npm run build
```
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
- Create symlinks storage
## Code of Conduct
```
php artisan storage:link
```
In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).
- Running migration
## Security Vulnerabilities
```
php artisan migrate
```
If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed.
- Running seeder
## License
```
php artisan db:seed
```
The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
- Create view table
- excute all sql queries on folder database/view_query
# Add ENV variable
- API_KEY_GOOGLE
```
Get api key from google developer console for and turn on spreadsheet api or feaature for google sheet
```
- SPREAD_SHEET_ID
```
Get spreadsheet id from google sheet link
```
- OPENAI_API_KEY
```
Get OpenAI API key from chatgpt subscription
```
- ENV
```
API_KEY_GOOGLE="xxxxx"
SPREAD_SHEET_ID="xxxxx"
OPENAI_API_KEY="xxxxx"
```
# Technology version
- php 8.3
- Laravel 11
- node v22.13.0
- npm 10.9.2
- mariadb Ver 15.1 Distrib 10.6.18-MariaDB, for debian-linux-gnu (x86_64) using EditLine wrapper
- Ubuntu 24.04

View File

@@ -0,0 +1,467 @@
<?php
namespace App\Console\Commands;
use App\Models\SpatialPlanning;
use App\Models\RetributionCalculation;
use App\Models\BuildingType;
use App\Services\RetributionCalculatorService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class AssignSpatialPlanningsToCalculation extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'spatial-planning:assign-calculations
{--force : Force assign even if already has calculation}
{--recalculate : Recalculate existing calculations with new values}
{--chunk=100 : Process in chunks}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Assign retribution calculations to spatial plannings (supports recalculate for existing calculations)';
protected $calculatorService;
public function __construct(RetributionCalculatorService $calculatorService)
{
parent::__construct();
$this->calculatorService = $calculatorService;
}
/**
* Execute the console command.
*/
public function handle()
{
$this->info('🏗️ Starting spatial planning calculation assignment...');
// Get processing options
$force = $this->option('force');
$recalculate = $this->option('recalculate');
$chunkSize = (int) $this->option('chunk');
// Get spatial plannings query
$query = SpatialPlanning::query();
if ($recalculate) {
// Recalculate mode: only process those WITH active calculations
$query->whereHas('retributionCalculations', function ($q) {
$q->where('is_active', true);
});
$this->info('🔄 Recalculate mode: Processing spatial plannings with existing calculations');
} elseif (!$force) {
// Normal mode: only process those without active calculations
$query->whereDoesntHave('retributionCalculations', function ($q) {
$q->where('is_active', true);
});
$this->info(' Normal mode: Processing spatial plannings without calculations');
} else {
// Force mode: process all
$this->info('🔥 Force mode: Processing ALL spatial plannings');
}
$totalRecords = $query->count();
if ($totalRecords === 0) {
$this->warn('No spatial plannings found to process.');
return 0;
}
$this->info("Found {$totalRecords} spatial planning(s) to process");
if (!$this->confirm('Do you want to continue?')) {
$this->info('Operation cancelled.');
return 0;
}
// Process in chunks
$processed = 0;
$errors = 0;
$reused = 0;
$created = 0;
$buildingTypeStats = [];
$progressBar = $this->output->createProgressBar($totalRecords);
$progressBar->start();
$recalculated = 0;
$query->chunk($chunkSize, function ($spatialPlannings) use (&$processed, &$errors, &$reused, &$created, &$recalculated, &$buildingTypeStats, $progressBar, $recalculate) {
foreach ($spatialPlannings as $spatialPlanning) {
try {
$result = $this->assignCalculationToSpatialPlanning($spatialPlanning, $recalculate);
if ($result['reused']) {
$reused++;
} elseif (isset($result['recalculated']) && $result['recalculated']) {
$recalculated++;
} else {
$created++;
}
// Track building type statistics
$buildingTypeName = $result['building_type_name'] ?? 'Unknown';
if (!isset($buildingTypeStats[$buildingTypeName])) {
$buildingTypeStats[$buildingTypeName] = 0;
}
$buildingTypeStats[$buildingTypeName]++;
$processed++;
} catch (\Exception $e) {
$errors++;
$this->error("Error processing ID {$spatialPlanning->id}: " . $e->getMessage());
}
$progressBar->advance();
}
});
$progressBar->finish();
// Show summary
$this->newLine(2);
$this->info('✅ Assignment completed!');
if ($recalculate) {
$this->table(
['Metric', 'Count'],
[
['Total Processed', $processed],
['Recalculated (Changed)', $recalculated],
['Unchanged', $reused],
['Errors', $errors],
]
);
} else {
$this->table(
['Metric', 'Count'],
[
['Total Processed', $processed],
['Calculations Created', $created],
['Calculations Reused', $reused],
['Errors', $errors],
]
);
}
// Show building type statistics
if (!empty($buildingTypeStats)) {
$this->newLine();
$this->info('📊 Building Type Distribution:');
$statsRows = [];
arsort($buildingTypeStats); // Sort by count descending
foreach ($buildingTypeStats as $typeName => $count) {
$percentage = round(($count / $processed) * 100, 1);
$statsRows[] = [$typeName, $count, $percentage . '%'];
}
$this->table(['Building Type', 'Count', 'Percentage'], $statsRows);
}
return 0;
}
/**
* Assign calculation to a spatial planning
*/
private function assignCalculationToSpatialPlanning(SpatialPlanning $spatialPlanning, bool $recalculate = false): array
{
// 1. Detect building type
$buildingType = $this->detectBuildingType($spatialPlanning->building_function);
// 2. Get calculation parameters (round to 2 decimal places)
$floorNumber = $spatialPlanning->number_of_floors ?: 1;
$buildingArea = round($spatialPlanning->getCalculationArea(), 2);
if ($buildingArea <= 0) {
throw new \Exception("Invalid building area: {$buildingArea}");
}
$reused = false;
$isRecalculated = false;
if ($recalculate) {
// Recalculate mode: Always create new calculation
$calculationResult = $this->performCalculation($spatialPlanning, $buildingType);
// Check if spatial planning has existing active calculation
$currentActiveCalculation = $spatialPlanning->activeRetributionCalculation;
if ($currentActiveCalculation) {
$oldAmount = $currentActiveCalculation->retributionCalculation->retribution_amount;
$oldArea = $currentActiveCalculation->retributionCalculation->building_area;
$newAmount = $calculationResult['amount'];
// Check if there's a significant difference (more than 1 rupiah)
if (abs($oldAmount - $newAmount) > 1) {
// Create new calculation
$calculation = RetributionCalculation::create([
'building_type_id' => $buildingType->id,
'floor_number' => $floorNumber,
'building_area' => $buildingArea,
'retribution_amount' => $calculationResult['amount'],
'calculation_detail' => $calculationResult['detail'],
]);
// Assign new calculation
$spatialPlanning->assignRetributionCalculation(
$calculation,
"Recalculated: Area {$oldArea}{$buildingArea}, Amount {$oldAmount}{$newAmount}"
);
$isRecalculated = true;
} else {
// No significant difference, keep existing
$calculation = $currentActiveCalculation->retributionCalculation;
$reused = true;
}
} else {
// No existing calculation, create new
$calculation = RetributionCalculation::create([
'building_type_id' => $buildingType->id,
'floor_number' => $floorNumber,
'building_area' => $buildingArea,
'retribution_amount' => $calculationResult['amount'],
'calculation_detail' => $calculationResult['detail'],
]);
$spatialPlanning->assignRetributionCalculation(
$calculation,
'Recalculated (new calculation)'
);
}
} else {
// Normal mode: Check if calculation already exists with same parameters
$existingCalculation = RetributionCalculation::where([
'building_type_id' => $buildingType->id,
'floor_number' => $floorNumber,
])
->whereBetween('building_area', [
$buildingArea * 0.99, // 1% tolerance
$buildingArea * 1.01
])
->first();
if ($existingCalculation) {
// Reuse existing calculation
$calculation = $existingCalculation;
$reused = true;
} else {
// Create new calculation
$calculationResult = $this->performCalculation($spatialPlanning, $buildingType);
$calculation = RetributionCalculation::create([
'building_type_id' => $buildingType->id,
'floor_number' => $floorNumber,
'building_area' => $buildingArea,
'retribution_amount' => $calculationResult['amount'],
'calculation_detail' => $calculationResult['detail'],
]);
}
// Assign to spatial planning
$spatialPlanning->assignRetributionCalculation(
$calculation,
$reused ? 'Auto-assigned (reused calculation)' : 'Auto-assigned (new calculation)'
);
}
return [
'calculation' => $calculation,
'reused' => $reused,
'recalculated' => $isRecalculated,
'building_type_name' => $buildingType->name,
'building_type_code' => $buildingType->code,
];
}
/**
* Detect building type based on building function using database
*/
private function detectBuildingType(string $buildingFunction = null): BuildingType
{
$function = strtolower($buildingFunction ?? '');
// Mapping building functions to building type codes from database
$mappings = [
// Religious
'masjid' => 'KEAGAMAAN',
'gereja' => 'KEAGAMAAN',
'vihara' => 'KEAGAMAAN',
'pura' => 'KEAGAMAAN',
'keagamaan' => 'KEAGAMAAN',
'religious' => 'KEAGAMAAN',
// Residential/Housing
'rumah' => 'HUN_SEDH', // Default to simple housing
'perumahan' => 'HUN_SEDH',
'hunian' => 'HUN_SEDH',
'residential' => 'HUN_SEDH',
'tinggal' => 'HUN_SEDH',
'mbr' => 'MBR', // Specifically for MBR
'masyarakat berpenghasilan rendah' => 'MBR',
// Commercial/Business - default to UMKM
'toko' => 'UMKM',
'warung' => 'UMKM',
'perdagangan' => 'UMKM',
'dagang' => 'UMKM',
'usaha' => 'UMKM',
'komersial' => 'UMKM',
'commercial' => 'UMKM',
'pasar' => 'UMKM',
'kios' => 'UMKM',
// Large commercial
'mall' => 'USH_BESAR',
'plaza' => 'USH_BESAR',
'supermarket' => 'USH_BESAR',
'department' => 'USH_BESAR',
'hotel' => 'USH_BESAR',
'resort' => 'USH_BESAR',
// Office
'kantor' => 'UMKM', // Can be UMKM or USH_BESAR depending on size
'perkantoran' => 'UMKM',
'office' => 'UMKM',
// Industry (usually big business)
'industri' => 'USH_BESAR',
'pabrik' => 'USH_BESAR',
'gudang' => 'USH_BESAR',
'warehouse' => 'USH_BESAR',
'manufacturing' => 'USH_BESAR',
// Social/Cultural
'sekolah' => 'SOSBUDAYA',
'pendidikan' => 'SOSBUDAYA',
'universitas' => 'SOSBUDAYA',
'kampus' => 'SOSBUDAYA',
'rumah sakit' => 'SOSBUDAYA',
'klinik' => 'SOSBUDAYA',
'kesehatan' => 'SOSBUDAYA',
'puskesmas' => 'SOSBUDAYA',
'museum' => 'SOSBUDAYA',
'perpustakaan' => 'SOSBUDAYA',
'gedung olahraga' => 'SOSBUDAYA',
// Mixed use
'campuran' => 'CAMP_KECIL', // Default to small mixed
'mixed' => 'CAMP_KECIL',
];
// Try to match building function
$detectedCode = null;
foreach ($mappings as $keyword => $code) {
if (str_contains($function, $keyword)) {
$detectedCode = $code;
break;
}
}
// Find building type in database by code
if ($detectedCode) {
$buildingType = BuildingType::where('code', $detectedCode)
->whereHas('indices') // Only types with indices
->first();
if ($buildingType) {
return $buildingType;
}
}
// Default to "UMKM" type if not detected (most common business type)
$defaultType = BuildingType::where('code', 'UMKM')
->whereHas('indices')
->first();
if ($defaultType) {
return $defaultType;
}
// Fallback to any available type with indices
$fallbackType = BuildingType::whereHas('indices')
->where('is_active', true)
->first();
if (!$fallbackType) {
throw new \Exception('No building types with indices found in database. Please run: php artisan db:seed --class=RetributionDataSeeder');
}
return $fallbackType;
}
/**
* Perform calculation using RetributionCalculatorService
*/
private function performCalculation(SpatialPlanning $spatialPlanning, BuildingType $buildingType): array
{
// Round area to 2 decimal places to match database storage format
$buildingArea = round($spatialPlanning->getCalculationArea(), 2);
$floorNumber = $spatialPlanning->number_of_floors ?: 1;
try {
// Use the same calculation service as TestRetributionCalculation
$result = $this->calculatorService->calculate(
$buildingType->id,
$floorNumber,
$buildingArea,
false // Don't save to database, we'll handle that separately
);
return [
'amount' => $result['total_retribution'],
'detail' => [
'building_type_id' => $buildingType->id,
'building_type_name' => $buildingType->name,
'building_type_code' => $buildingType->code,
'coefficient' => $result['indices']['coefficient'],
'ip_permanent' => $result['indices']['ip_permanent'],
'ip_complexity' => $result['indices']['ip_complexity'],
'locality_index' => $result['indices']['locality_index'],
'height_index' => $result['input_parameters']['height_index'],
'infrastructure_factor' => $result['indices']['infrastructure_factor'],
'building_area' => $buildingArea,
'floor_number' => $floorNumber,
'building_function' => $spatialPlanning->building_function,
'calculation_steps' => $result['calculation_detail'],
'base_value' => $result['input_parameters']['base_value'],
'is_free' => $buildingType->is_free,
'calculation_date' => now()->toDateTimeString(),
'total' => $result['total_retribution'],
]
];
} catch (\Exception $e) {
// Fallback to basic calculation if service fails
$this->warn("Calculation service failed for {$spatialPlanning->name}: {$e->getMessage()}. Using fallback calculation.");
// Basic fallback calculation
$totalAmount = $buildingType->is_free ? 0 : ($buildingArea * 50000);
return [
'amount' => $totalAmount,
'detail' => [
'building_type_id' => $buildingType->id,
'building_type_name' => $buildingType->name,
'building_type_code' => $buildingType->code,
'building_area' => $buildingArea,
'floor_number' => $floorNumber,
'building_function' => $spatialPlanning->building_function,
'calculation_method' => 'fallback',
'error_message' => $e->getMessage(),
'is_free' => $buildingType->is_free,
'calculation_date' => now()->toDateTimeString(),
'total' => $totalAmount,
]
];
}
}
}

View File

@@ -2,6 +2,7 @@
namespace App\Console\Commands;
use App\Jobs\SyncronizeSIMBG;
use App\Services\ServiceSIMBG;
use Illuminate\Console\Command;
use \Illuminate\Support\Facades\Log;
@@ -28,13 +29,12 @@ class ExecuteScraping extends Command
private $service_simbg;
public function __construct(ServiceSIMBG $service_simbg){
$this->service_simbg = $service_simbg;
public function __construct(){
parent::__construct();
}
public function handle()
{
SyncronizeSIMBG::dispatch()->onQueue('default');
Log::info("running scheduler daily scraping");
$this->service_simbg->syncTaskList();
}
}

View File

@@ -0,0 +1,317 @@
<?php
namespace App\Console\Commands;
use App\Models\SpatialPlanning;
use Illuminate\Console\Command;
use Maatwebsite\Excel\Facades\Excel;
use Illuminate\Support\Facades\DB;
use Exception;
class InitSpatialPlanningDatas extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'spatial:init {file? : Path to the CSV/Excel file} {--truncate : Clear existing data before import} {--safe-truncate : Clear only spatial plannings without retribution proposals} {--force-truncate : Force truncate by disabling foreign key checks}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Import spatial planning data from CSV/Excel file for retribution';
/**
* Execute the console command.
*/
public function handle()
{
$filePath = $this->argument('file') ?? 'public/templates/Data_2025___Estimasi_Jumlah_Lantai.csv';
$fullPath = storage_path('app/' . $filePath);
// Check if file exists
if (!file_exists($fullPath)) {
$this->error("File not found: {$fullPath}");
$this->info("Available files in templates:");
$this->listAvailableFiles();
return 1;
}
// Handle truncate options
if (($this->option('truncate') && $this->option('safe-truncate')) ||
($this->option('truncate') && $this->option('force-truncate')) ||
($this->option('safe-truncate') && $this->option('force-truncate'))) {
$this->error('Cannot use multiple truncate options together. Choose only one.');
return 1;
}
// Confirm truncate if requested
if ($this->option('truncate')) {
if ($this->confirm('This will delete all existing spatial planning data and related retribution proposals. Continue?')) {
$this->info('Truncating tables...');
try {
// First delete retribution proposals that reference spatial plannings
$deletedProposals = DB::table('retribution_proposals')
->whereNotNull('spatial_planning_id')
->count();
if ($deletedProposals > 0) {
DB::table('retribution_proposals')
->whereNotNull('spatial_planning_id')
->delete();
$this->info("Deleted {$deletedProposals} retribution proposals linked to spatial plannings.");
}
// Method 1: Try truncate with disabled foreign key checks
try {
DB::statement('SET FOREIGN_KEY_CHECKS = 0');
DB::table('spatial_plannings')->truncate();
DB::statement('SET FOREIGN_KEY_CHECKS = 1');
$this->info('Spatial plannings table truncated successfully.');
} catch (\Exception $truncateError) {
// Method 2: Fallback to delete if truncate fails
$this->warn('Truncate failed, using delete method...');
$deletedSpatial = DB::table('spatial_plannings')->delete();
$this->info("Deleted {$deletedSpatial} spatial planning records.");
// Reset auto increment
DB::statement('ALTER TABLE spatial_plannings AUTO_INCREMENT = 1');
}
} catch (\Exception $e) {
$this->error('Failed to truncate tables: ' . $e->getMessage());
return 1;
}
} else {
$this->info('Operation cancelled.');
return 0;
}
}
// Force truncate - disable foreign key checks and truncate everything
if ($this->option('force-truncate')) {
if ($this->confirm('This will FORCE truncate ALL spatial planning data by disabling foreign key checks. This is risky! Continue?')) {
$this->info('Force truncating with disabled foreign key checks...');
try {
DB::beginTransaction();
// Disable foreign key checks
DB::statement('SET FOREIGN_KEY_CHECKS = 0');
// Truncate both tables
DB::table('retribution_proposals')->truncate();
DB::table('spatial_plannings')->truncate();
// Re-enable foreign key checks
DB::statement('SET FOREIGN_KEY_CHECKS = 1');
$this->info('Force truncate completed successfully.');
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
// Make sure to re-enable foreign key checks even on error
try {
DB::statement('SET FOREIGN_KEY_CHECKS = 1');
} catch (\Exception $fkError) {
$this->error('Failed to re-enable foreign key checks: ' . $fkError->getMessage());
}
$this->error('Failed to force truncate: ' . $e->getMessage());
return 1;
}
} else {
$this->info('Operation cancelled.');
return 0;
}
}
// Safe truncate - only delete spatial plannings without retribution proposals
if ($this->option('safe-truncate')) {
if ($this->confirm('This will delete only spatial planning data that have no retribution proposals. Continue?')) {
$this->info('Safe truncating spatial plannings...');
try {
DB::beginTransaction();
// Count spatial plannings with retribution proposals
$withProposals = DB::table('spatial_plannings')
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('retribution_proposals')
->whereColumn('retribution_proposals.spatial_planning_id', 'spatial_plannings.id');
})
->count();
// Delete spatial plannings without retribution proposals
$deletedCount = DB::table('spatial_plannings')
->whereNotExists(function ($query) {
$query->select(DB::raw(1))
->from('retribution_proposals')
->whereColumn('retribution_proposals.spatial_planning_id', 'spatial_plannings.id');
})
->delete();
$this->info("Deleted {$deletedCount} spatial plannings without retribution proposals.");
$this->info("Kept {$withProposals} spatial plannings that have retribution proposals.");
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
$this->error('Failed to safe truncate: ' . $e->getMessage());
return 1;
}
} else {
$this->info('Operation cancelled.');
return 0;
}
}
$this->info("Starting import from: {$filePath}");
$this->info("Full path: {$fullPath}");
try {
DB::beginTransaction();
$data = Excel::toArray([], $fullPath);
if (empty($data) || empty($data[0])) {
$this->error('No data found in the file.');
return 1;
}
$rows = $data[0]; // Get first sheet
$headers = array_shift($rows); // Remove header row
$this->info("Found " . count($rows) . " data rows to import.");
$this->info("Headers: " . implode(', ', $headers));
$progressBar = $this->output->createProgressBar(count($rows));
$progressBar->start();
$imported = 0;
$skipped = 0;
foreach ($rows as $index => $row) {
try {
// Skip empty rows
if (empty(array_filter($row))) {
$skipped++;
$progressBar->advance();
continue;
}
// Map CSV columns to model attributes
$spatialData = [
'name' => $this->cleanString($row[1] ?? ''), // pemohon
'location' => $this->cleanString($row[2] ?? ''), // alamat
'activities' => $this->cleanString($row[3] ?? ''), // activities
'land_area' => $this->cleanNumber($row[4] ?? 0), // luas_lahan
'site_bcr' => $this->cleanNumber($row[5] ?? 0), // bcr_kawasan
'area' => $this->cleanNumber($row[6] ?? 0), // area
'no_tapak' => $this->cleanString($row[7] ?? ''), // no_tapak
'no_skkl' => $this->cleanString($row[8] ?? ''), // no_skkl
'no_ukl' => $this->cleanString($row[9] ?? ''), // no_ukl
'building_function' => $this->cleanString($row[10] ?? ''), // fungsi_bangunan
'sub_building_function' => $this->cleanString($row[11] ?? ''), // sub_fungsi_bangunan
'number_of_floors' => $this->cleanNumber($row[12] ?? 1), // jumlah_lantai
'number' => $this->cleanString($row[0] ?? ''), // no
'date' => now(), // Set current date
'kbli' => null, // Not in CSV, set as null
];
// Validate required fields
if (empty($spatialData['name']) && empty($spatialData['activities'])) {
$skipped++;
$progressBar->advance();
continue;
}
SpatialPlanning::create($spatialData);
$imported++;
} catch (Exception $e) {
$this->newLine();
$this->error("Error importing row " . ($index + 2) . ": " . $e->getMessage());
$skipped++;
}
$progressBar->advance();
}
$progressBar->finish();
$this->newLine(2);
DB::commit();
$this->info("Import completed successfully!");
$this->info("Imported: {$imported} records");
$this->info("Skipped: {$skipped} records");
return 0;
} catch (Exception $e) {
DB::rollBack();
$this->error("Import failed: " . $e->getMessage());
return 1;
}
}
/**
* Clean string data
*/
private function cleanString($value)
{
if (is_null($value)) return null;
return trim(str_replace(["\n", "\r", "\t"], ' ', $value));
}
/**
* Clean numeric data
*/
private function cleanNumber($value)
{
if (is_null($value) || $value === '') return 0;
// Remove non-numeric characters except decimal point
$cleaned = preg_replace('/[^0-9.]/', '', $value);
return is_numeric($cleaned) ? (float) $cleaned : 0;
}
/**
* List available template files
*/
private function listAvailableFiles()
{
$templatesPath = storage_path('app/public/templates');
if (is_dir($templatesPath)) {
$this->info("Files in storage/app/public/templates:");
$extensions = ['csv', 'xlsx', 'xls'];
foreach ($extensions as $ext) {
$files = glob($templatesPath . '/*.' . $ext);
foreach ($files as $file) {
$this->line(' - ' . basename($file));
}
}
}
$publicTemplatesPath = public_path('templates');
if (is_dir($publicTemplatesPath)) {
$this->info("Files in public/templates:");
$extensions = ['csv', 'xlsx', 'xls'];
foreach ($extensions as $ext) {
$files = glob($publicTemplatesPath . '/*.' . $ext);
foreach ($files as $file) {
$this->line(' - ' . basename($file));
}
}
}
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace App\Console\Commands;
use App\Jobs\ScrapingDataJob;
use App\Models\ImportDatasource;
use App\Services\ServiceGoogleSheet;
use App\Services\ServicePbgTask;
use App\Services\ServiceTabPbgTask;
use App\Services\ServiceTokenSIMBG;
use GuzzleHttp\Client; // Import Guzzle Client
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
class ScrapingData extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'app:scraping-data';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Inject dependencies.
*/
public function __construct(
) {
parent::__construct();
}
public function handle()
{
dispatch(new ScrapingDataJob());
$this->info("Scraping job dispatched successfully");
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace App\Console\Commands;
use App\Services\ServiceGoogleSheet;
use Illuminate\Console\Command;
class ScrapingLeaderData extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'app:scraping-leader-data';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Scraping leader data from google spreadsheet and save to database';
/**
* Execute the console command.
*/
public function handle()
{
$service_google_sheet = app(ServiceGoogleSheet::class);
$service_google_sheet->sync_leader_data();
$this->info('Leader data synced successfully');
}
}

View File

@@ -0,0 +1,265 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Services\RetributionCalculatorService;
use App\Models\BuildingType;
class TestRetributionCalculation extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'retribution:test
{--area= : Luas bangunan dalam m2}
{--floor= : Jumlah lantai (1-6)}
{--type= : ID atau kode building type}
{--all : Test semua building types}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Test perhitungan retribusi PBG dengan input luas bangunan dan tinggi lantai';
protected $calculatorService;
public function __construct(RetributionCalculatorService $calculatorService)
{
parent::__construct();
$this->calculatorService = $calculatorService;
}
/**
* Execute the console command.
*/
public function handle()
{
$this->info('🏢 SISTEM TEST PERHITUNGAN RETRIBUSI PBG');
$this->info('=' . str_repeat('=', 50));
// Test all building types if --all flag is used
if ($this->option('all')) {
return $this->testAllBuildingTypes();
}
// Get input parameters
$area = $this->getArea();
$floor = $this->getFloor();
$buildingTypeId = $this->getBuildingType();
if (!$area || !$floor || !$buildingTypeId) {
$this->error('❌ Parameter tidak lengkap!');
return 1;
}
// Perform calculation
$this->performCalculation($buildingTypeId, $floor, $area);
return 0;
}
protected function getArea()
{
$area = $this->option('area');
if (!$area) {
$area = $this->ask('📐 Masukkan luas bangunan (m²)');
}
if (!is_numeric($area) || $area <= 0) {
$this->error('❌ Luas bangunan harus berupa angka positif!');
return null;
}
return (float) $area;
}
protected function getFloor()
{
$floor = $this->option('floor');
if (!$floor) {
$floor = $this->ask('🏗️ Masukkan jumlah lantai (1-6)');
}
if (!is_numeric($floor) || $floor < 1 || $floor > 6) {
$this->error('❌ Jumlah lantai harus antara 1-6!');
return null;
}
return (int) $floor;
}
protected function getBuildingType()
{
$type = $this->option('type');
if (!$type) {
$this->showBuildingTypes();
$type = $this->ask('🏢 Masukkan ID atau kode building type');
}
// Try to find by ID first, then by code
$buildingType = null;
if (is_numeric($type)) {
$buildingType = BuildingType::find($type);
} else {
$buildingType = BuildingType::where('code', strtoupper($type))->first();
}
if (!$buildingType) {
$this->error('❌ Building type tidak ditemukan!');
return null;
}
return $buildingType->id;
}
protected function showBuildingTypes()
{
$this->info('📋 DAFTAR BUILDING TYPES:');
$this->line('');
$buildingTypes = BuildingType::with('indices')
->whereHas('indices') // Only types that have indices
->get();
$headers = ['ID', 'Kode', 'Nama', 'Coefficient', 'Free'];
$rows = [];
foreach ($buildingTypes as $type) {
$rows[] = [
$type->id,
$type->code,
$type->name,
$type->indices ? number_format($type->indices->coefficient, 4) : 'N/A',
$type->is_free ? '✅' : '❌'
];
}
$this->table($headers, $rows);
$this->line('');
}
protected function performCalculation($buildingTypeId, $floor, $area)
{
try {
// Round area to 2 decimal places to match database storage format
$roundedArea = round($area, 2);
$result = $this->calculatorService->calculate($buildingTypeId, $floor, $roundedArea, false);
$this->displayResults($result, $roundedArea, $floor);
} catch (\Exception $e) {
$this->error('❌ Error: ' . $e->getMessage());
return 1;
}
}
protected function displayResults($result, $area, $floor)
{
$this->info('');
$this->info('📊 HASIL PERHITUNGAN RETRIBUSI');
$this->info('=' . str_repeat('=', 40));
// Building info
$this->line('🏢 <fg=cyan>Building Type:</> ' . $result['building_type']['name']);
$this->line('📐 <fg=cyan>Luas Bangunan:</> ' . number_format($area, 0) . ' m²');
$this->line('🏗️ <fg=cyan>Jumlah Lantai:</> ' . $floor);
if (isset($result['building_type']['is_free']) && $result['building_type']['is_free']) {
$this->line('');
$this->info('🎉 GRATIS - Building type ini tidak dikenakan retribusi');
$this->line('💰 <fg=green>Total Retribusi: Rp 0</fg=green>');
return;
}
$this->line('');
// Parameters
$this->info('📋 PARAMETER PERHITUNGAN:');
$indices = $result['indices'];
$this->line('• Coefficient: ' . number_format($indices['coefficient'], 4));
$this->line('• IP Permanent: ' . number_format($indices['ip_permanent'], 4));
$this->line('• IP Complexity: ' . number_format($indices['ip_complexity'], 4));
$this->line('• Locality Index: ' . number_format($indices['locality_index'], 4));
$this->line('• Height Index: ' . number_format($result['input_parameters']['height_index'], 4));
$this->line('');
// Calculation steps
$this->info('🔢 LANGKAH PERHITUNGAN:');
$detail = $result['calculation_detail'];
$this->line('1. H5 Raw: ' . number_format($detail['h5_raw'], 6));
$this->line('2. H5 Rounded: ' . number_format($detail['h5'], 4));
$this->line('3. Main Calculation: Rp ' . number_format($detail['main'], 2));
$this->line('4. Infrastructure (50%): Rp ' . number_format($detail['infrastructure'], 2));
$this->line('');
// Final result
$this->info('💰 <fg=green>TOTAL RETRIBUSI: ' . $result['formatted_amount'] . '</fg=green>');
$this->line('📈 <fg=yellow>Per m²: Rp ' . number_format($result['total_retribution'] / $area, 2) . '</fg=yellow>');
}
protected function testAllBuildingTypes()
{
$area = round($this->option('area') ?: 100, 2);
$floor = $this->option('floor') ?: 2;
$this->info("🧪 TESTING SEMUA BUILDING TYPES");
$this->info("📐 Luas: {$area} m² | 🏗️ Lantai: {$floor}");
$this->info('=' . str_repeat('=', 60));
$buildingTypes = BuildingType::with('indices')
->whereHas('indices') // Only types that have indices
->orderBy('level')
->orderBy('name')
->get();
$headers = ['Kode', 'Nama', 'Coefficient', 'Total Retribusi', 'Per m²'];
$rows = [];
foreach ($buildingTypes as $type) {
try {
$result = $this->calculatorService->calculate($type->id, $floor, $area, false);
if ($type->is_free) {
$rows[] = [
$type->code,
$type->name,
'FREE',
'Rp 0',
'Rp 0'
];
} else {
$rows[] = [
$type->code,
$type->name,
number_format($result['indices']['coefficient'], 4),
'Rp ' . number_format($result['total_retribution'], 0),
'Rp ' . number_format($result['total_retribution'] / $area, 0)
];
}
} catch (\Exception $e) {
$rows[] = [
$type->code,
$type->name,
'ERROR',
$e->getMessage(),
'-'
];
}
}
$this->table($headers, $rows);
return 0;
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace App\Enums;
enum PbgTaskApplicationTypes: string
{
case PERSETUJUAN_BG = '1';
case PERUBAHAN_BG = '2';
case SLF_BB = '4';
case SLF = '5';
public static function labels(): array
{
return [
null => "Pilih Application Type",
self::PERSETUJUAN_BG->value => 'Persetujuan Bangunan Gedung',
self::PERUBAHAN_BG->value => 'Perubahan Bangunan Gedung',
self::SLF_BB->value => 'Sertifikat Laik Fungsi - Bangunan Baru',
self::SLF->value => 'Sertifikat Laik Fungsi',
];
}
public static function getLabel(?string $status): ?string
{
return self::labels()[$status] ?? null;
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace App\Enums;
enum PbgTaskFilterData : string
{
case non_business = 'non-business';
case business = 'business';
case verified = 'verified';
case non_verified = 'non-verified';
case all = 'all';
public static function getAllOptions() : array {
return [
self::all->value => 'Potensi Berkas',
self::business->value => 'Usaha',
self::non_business->value => 'Bukan Usaha',
self::verified->value => 'Terverifikasi',
self::non_verified->value => 'Belum Terverifikasi',
];
}
}

View File

@@ -0,0 +1,59 @@
<?php
namespace App\Enums;
enum PbgTaskStatus: int
{
case VERIFIKASI_KELENGKAPAN = 1;
case PERBAIKAN_DOKUMEN = 2;
case PERMOHONAN_DIBATALKAN = 3;
case MENUNGGU_PENUGASAN_TPT_TPA = 4;
case MENUNGGU_JADWAL_KONSULTASI = 5;
case PELAKSANAAN_KONSULTASI = 6;
case PERBAIKAN_DOKUMEN_KONSULTASI = 8;
case PERMOHONAN_DITOLAK = 9;
case PERHITUNGAN_RETRIBUSI = 10;
case MENUNGGU_PEMBAYARAN_RETRIBUSI = 14;
case VERIFIKASI_PEMBAYARAN_RETRIBUSI = 15;
case RETRIBUSI_TIDAK_SESUAI = 16;
case VERIFIKASI_SK_PBG = 18;
case PENERBITAN_SK_PBG = 19;
case SK_PBG_TERBIT = 20;
case PENERBITAN_SPPST = 24;
case PROSES_PENERBITAN_SKRD = 25;
case MENUNGGU_PENUGASAN_TPT = 26;
case VERIFIKASI_DATA_TPT = 27;
case SERTIFIKAT_SLF_TERBIT = 28;
public static function getStatuses(): array
{
return [
null => "Pilih Status",
self::VERIFIKASI_KELENGKAPAN->value => "Verifikasi Kelengkapan Dokumen",
self::PERBAIKAN_DOKUMEN->value => "Perbaikan Dokumen",
self::PERMOHONAN_DIBATALKAN->value => "Permohonan Dibatalkan",
self::MENUNGGU_PENUGASAN_TPT_TPA->value => "Menunggu Penugasan TPT/TPA",
self::MENUNGGU_JADWAL_KONSULTASI->value => "Menunggu Jadwal Konsultasi",
self::PELAKSANAAN_KONSULTASI->value => "Pelaksanaan Konsultasi",
self::PERBAIKAN_DOKUMEN_KONSULTASI->value => "Perbaikan Dokumen Konsultasi",
self::PERMOHONAN_DITOLAK->value => "Permohonan Ditolak",
self::PERHITUNGAN_RETRIBUSI->value => "Perhitungan Retribusi",
self::MENUNGGU_PEMBAYARAN_RETRIBUSI->value => "Menunggu Pembayaran Retribusi",
self::VERIFIKASI_PEMBAYARAN_RETRIBUSI->value => "Verifikasi Pembayaran Retribusi",
self::RETRIBUSI_TIDAK_SESUAI->value => "Retribusi Tidak Sesuai",
self::VERIFIKASI_SK_PBG->value => "Verifikasi SK PBG",
self::PENERBITAN_SK_PBG->value => "Penerbitan SK PBG",
self::SK_PBG_TERBIT->value => "SK PBG Terbit",
self::PENERBITAN_SPPST->value => "Penerbitan SPPST",
self::PROSES_PENERBITAN_SKRD->value => "Proses Penerbitan SKRD",
self::MENUNGGU_PENUGASAN_TPT->value => "Menunggu Penugasan TPT",
self::VERIFIKASI_DATA_TPT->value => "Verifikasi Data TPT",
self::SERTIFIKAT_SLF_TERBIT->value => "Sertifikat SLF Terbit",
];
}
public static function getLabel(?int $status): ?string
{
return self::getStatuses()[$status] ?? null;
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace App\Exports;
use App\Models\PbgTaskGoogleSheet;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
class DistrictPaymentRecapExport implements FromCollection, WithHeadings
{
/**
* @return \Illuminate\Support\Collection
*/
public function collection()
{
return PbgTaskGoogleSheet::select(
'kecamatan',
DB::raw('SUM(nilai_retribusi_keseluruhan_simbg) as total')
)
->groupBy('kecamatan')->get();
}
public function headings(): array{
return [
'Kecamatan',
'Total'
];
}
}

View File

@@ -0,0 +1,90 @@
<?php
namespace App\Exports;
use App\Models\BigdataResume;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
class ReportDirectorExport implements FromCollection, WithHeadings, WithMapping
{
/**
* @return \Illuminate\Support\Collection
*/
public function collection()
{
return BigdataResume::select(
'potention_count',
'potention_sum',
'non_verified_count',
'non_verified_sum',
'verified_count',
'verified_sum',
'business_count',
'business_sum',
'non_business_count',
'non_business_sum',
'spatial_count',
'spatial_sum',
'waiting_click_dpmptsp_count',
'waiting_click_dpmptsp_sum',
'issuance_realization_pbg_count',
'issuance_realization_pbg_sum',
'process_in_technical_office_count',
'process_in_technical_office_sum',
'year',
'created_at'
)->orderBy('id', 'desc')->get();
}
public function headings(): array{
return [
"Jumlah Potensi" ,
"Total Potensi" ,
"Jumlah Berkas Belum Terverifikasi" ,
"Total Berkas Belum Terverifikasi" ,
"Jumlah Berkas Terverifikasi" ,
"Total Berkas Terverifikasi" ,
"Jumlah Usaha" ,
"Total Usaha" ,
"Jumlah Non Usaha" ,
"Total Non Usaha" ,
"Jumlah Tata Ruang" ,
"Total Tata Ruang" ,
"Jumlah Menunggu Klik DPMPTSP" ,
"Total Menunggu Klik DPMPTSP" ,
"Jumlah Realisasi Terbit PBG" ,
"Total Realisasi Terbit PBG" ,
"Jumlah Proses Dinas Teknis" ,
"Total Proses Dinas Teknis",
"Tahun",
"Created"
];
}
public function map($row): array
{
return [
$row->potention_count,
$row->potention_sum,
$row->non_verified_count,
$row->non_verified_sum,
$row->verified_count,
$row->verified_sum,
$row->business_count,
$row->business_sum,
$row->non_business_count,
$row->non_business_sum,
$row->spatial_count,
$row->spatial_sum,
$row->waiting_click_dpmptsp_count,
$row->waiting_click_dpmptsp_sum,
$row->issuance_realization_pbg_count,
$row->issuance_realization_pbg_sum,
$row->process_in_technical_office_count,
$row->process_in_technical_office_sum,
$row->year,
$row->created_at ? $row->created_at->format('Y-m-d H:i:s') : null, // Format created_at as Y-m-d
];
}
}

View File

@@ -0,0 +1,71 @@
<?php
namespace App\Exports;
use App\Models\BigdataResume;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
class ReportPaymentRecapExport implements FromCollection, WithHeadings
{
/**
* @return \Illuminate\Support\Collection
*/
protected $startDate;
protected $endDate;
public function __construct($startDate, $endDate){
$this->startDate = $startDate;
$this->endDate = $endDate;
}
public function collection()
{
$query = BigdataResume::query()->orderBy('id', 'desc');
if ($this->startDate && $this->endDate) {
$query->whereBetween('created_at', [$this->startDate, $this->endDate]);
}
$items = $query->get();
$categoryMap = [
'potention_sum' => 'Potensi',
'non_verified_sum' => 'Belum Terverifikasi',
'verified_sum' => 'Terverifikasi',
'business_sum' => 'Usaha',
'non_business_sum' => 'Non Usaha',
'spatial_sum' => 'Tata Ruang',
'waiting_click_dpmptsp_sum' => 'Menunggu Klik DPMPTSP',
'issuance_realization_pbg_sum' => 'Realisasi Terbit PBG',
'process_in_technical_office_sum' => 'Proses Di Dinas Teknis',
];
// Restructure response
$data = [];
foreach ($items as $item) {
$createdAt = $item->created_at;
$id = $item->id;
foreach ($item->toArray() as $key => $value) {
// Only include columns with "sum" in their names
if (strpos($key, 'sum') !== false) {
$data[] = [
'category' => $categoryMap[$key] ?? $key, // Map category
'nominal' => number_format($value, 0, ',', '.'), // Format number
'created_at' => $createdAt->format('Y-m-d H:i:s'), // Format date
];
}
}
}
return collect($data);
}
public function headings(): array{
return [
'Kategori',
'Nominal',
'Created'
];
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace App\Exports;
use App\Models\PbgTask;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
class ReportPbgPtspExport implements FromCollection, WithHeadings
{
/**
* @return \Illuminate\Support\Collection
*/
public function collection()
{
return PbgTask::select(
'status_name',
DB::raw('COUNT(*) as total')
)
->groupBy('status', 'status_name')
->get();
}
public function headings(): array
{
return [
'Status Name',
'Total'
];
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace App\Exports;
use App\Models\TourismBasedKBLI;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
class ReportTourismExport implements FromCollection, WithHeadings
{
/**
* @return \Illuminate\Support\Collection
*/
public function collection()
{
return TourismBasedKBLI::select('kbli_title', 'total_records')->get();
}
public function headings(): array{
return [
'Jenis Bisnis Pariwisata',
'Jumlah Total'
];
}
}

View File

@@ -53,7 +53,7 @@ class AdvertisementController extends Controller
$advertisement->village_name = $village ? $village->village_name : null;
$district = DB::table('districts')->where('district_code', $advertisement->district_code)->first();
$advertisement->district_name = $district ? $district->district_name : null;
$advertisement->district_name = $district ? $district->district_name : null;
return $advertisement;
});
@@ -75,10 +75,10 @@ class AdvertisementController extends Controller
{
$data = $request->validated();
// Cari village_code berdasarkan village_name
$village_code = DB::table('villages')->where('village_name', $data['village_name'])->value('village_code');
// Cari district_code berdasarkan district_name
$district_code = DB::table('districts')->where('district_name', $data['district_name'])->value('district_code');
// Cari village_code berdasarkan village_name
$village_code = DB::table('villages')->where('village_name', $data['village_name'])->where('district_code', $district_code)->value('village_code');
// Tambahkan village_code dan district_code ke data
$data['village_code'] = $village_code;
@@ -142,10 +142,10 @@ class AdvertisementController extends Controller
{
$data = $request->validated();
// Cari village_code berdasarkan village_name
$village_code = DB::table('villages')->where('village_name', $data['village_name'])->value('village_code');
// Cari district_code berdasarkan district_name
$district_code = DB::table('districts')->where('district_name', $data['district_name'])->value('district_code');
// Cari village_code berdasarkan village_name
$village_code = DB::table('villages')->where('village_name', $data['village_name'])->where('district_code', $district_code)->value('village_code');
// Tambahkan village_code dan district_code ke data
$data['village_code'] = $village_code;
@@ -196,4 +196,17 @@ class AdvertisementController extends Controller
return response()->json($results);
}
public function downloadExcelAdvertisement()
{
$filePath = public_path('templates/template_reklame.xlsx');
// Cek apakah file ada
if (!file_exists($filePath)) {
return response()-> json(['message' => 'File tidak ditemukan!'], Response::HTTP_NOT_FOUND);
}
// Return file to download
return response()->download($filePath);
}
}

View File

@@ -0,0 +1,382 @@
<?php
namespace App\Http\Controllers\Api;
use App\Exports\ReportDirectorExport;
use App\Exports\ReportPaymentRecapExport;
use App\Http\Controllers\Controller;
use App\Http\Resources\BigdataResumeResource;
use App\Models\BigdataResume;
use App\Models\DataSetting;
use Barryvdh\DomPDF\Facade\Pdf;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Maatwebsite\Excel\Facades\Excel;
class BigDataResumeController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
try{
$filterDate = $request->get("filterByDate");
if (!$filterDate || $filterDate === "latest") {
$big_data_resume = BigdataResume::where('year', 'leader')->latest()->first();
if (!$big_data_resume) {
return $this->response_empty_resume();
}
} else {
$big_data_resume = BigdataResume::where('year', 'leader')
->whereDate('created_at', $filterDate)
->orderBy('id', 'desc')
->first();
if (!$big_data_resume) {
return $this->response_empty_resume();
}
}
$data_settings = DataSetting::all();
if($data_settings->isEmpty()){
return response()->json(['message' => 'No data setting found']);
}
function cleanNumber($value) {
return floatval(str_replace('.', '', $value));
}
$target_pad = floatval(optional($data_settings->where('key', 'TARGET_PAD')->first())->value);
$realisasi_terbit_pbg_sum = cleanNumber(optional($data_settings->where('key', 'REALISASI_TERBIT_PBG_SUM')->first())->value);
$realisasi_terbit_pbg_count = cleanNumber(optional($data_settings->where('key', 'REALISASI_TERBIT_PBG_COUNT')->first())->value);
$menunggu_klik_dpmptsp_sum = cleanNumber(optional($data_settings->where('key', 'MENUNGGU_KLIK_DPMPTSP_SUM')->first())->value);
$menunggu_klik_dpmptsp_count = cleanNumber(optional($data_settings->where('key', 'MENUNGGU_KLIK_DPMPTSP_COUNT')->first())->value);
$proses_dinas_teknis_sum = cleanNumber(optional($data_settings->where('key', 'PROSES_DINAS_TEKNIS_SUM')->first())->value);
$proses_dinas_teknis_count = cleanNumber(optional($data_settings->where('key', 'PROSES_DINAS_TEKNIS_COUNT')->first())->value);
$tata_ruang = $big_data_resume->spatial_sum;
$kekurangan_potensi = $target_pad - $big_data_resume->potention_sum;
// percentage kekurangan potensi
$kekurangan_potensi_percentage = $target_pad > 0 && $target_pad > 0
? round(($kekurangan_potensi / $target_pad) * 100, 2) : 0;
// percentage total potensi
$total_potensi_percentage = $big_data_resume->potention_sum > 0 && $target_pad > 0
? round(($big_data_resume->potention_sum / $target_pad) * 100, 2) : 0;
// percentage verified document
$verified_percentage = $big_data_resume->verified_sum > 0 && $big_data_resume->potention_sum > 0
? round(($big_data_resume->verified_sum / $big_data_resume->potention_sum) * 100, 2) : 0;
// percentage non-verified document
$non_verified_percentage = $big_data_resume->non_verified_sum > 0 && $big_data_resume->potention_sum > 0
? round(($big_data_resume->non_verified_sum / $big_data_resume->potention_sum) * 100, 2) : 0;
// percentage business document
$business_percentage = $big_data_resume->business_sum > 0 && $big_data_resume->non_verified_sum > 0
? round(($big_data_resume->business_sum / $big_data_resume->non_verified_sum) * 100, 2) : 0;
// percentage non-business document
$non_business_percentage = $big_data_resume->non_business_sum > 0 && $big_data_resume->potention_sum > 0
? round(($big_data_resume->non_business_sum / $big_data_resume->potention_sum) * 100, 2) : 0;
// percentage tata ruang
$tata_ruang_percentage = $tata_ruang > 0 && $big_data_resume->potention_sum > 0
? round(($tata_ruang / $big_data_resume->potention_sum) * 100, 2) : 0;
// percentage realisasi terbit pbg
$realisasi_terbit_percentage = $big_data_resume->verified_sum > 0 && $realisasi_terbit_pbg_sum > 0
? round(($realisasi_terbit_pbg_sum / $big_data_resume->verified_sum) * 100, 2) : 0;
// percentage menunggu klik dpmptsp
$menunggu_klik_dpmptsp_percentage = $big_data_resume->verified_sum > 0 && $menunggu_klik_dpmptsp_sum > 0
? round(($menunggu_klik_dpmptsp_sum / $big_data_resume->verified_sum) * 100, 2) : 0;
// percentage proses_dinas_teknis
$proses_dinas_teknis_percentage = $big_data_resume->verified_sum > 0 && $proses_dinas_teknis_sum > 0
? round(($proses_dinas_teknis_sum / $big_data_resume->verified_sum) * 100, 2) : 0;
$result = [
'target_pad' => [
'sum' => $target_pad,
'percentage' => 100,
],
'tata_ruang' => [
'sum' => $big_data_resume->spatial_sum,
'count' => $big_data_resume->spatial_count,
'percentage' => $tata_ruang_percentage,
],
'kekurangan_potensi' => [
'sum' => $kekurangan_potensi,
'percentage' => $kekurangan_potensi_percentage
],
'total_potensi' => [
'sum' => (float) $big_data_resume->potention_sum,
'count' => $big_data_resume->potention_count,
'percentage' => $total_potensi_percentage
],
'verified_document' => [
'sum' => (float) $big_data_resume->verified_sum,
'count' => $big_data_resume->verified_count,
'percentage' => $verified_percentage
],
'non_verified_document' => [
'sum' => (float) $big_data_resume->non_verified_sum,
'count' => $big_data_resume->non_verified_count,
'percentage' => $non_verified_percentage
],
'business_document' => [
'sum' => (float) $big_data_resume->business_sum,
'count' => $big_data_resume->business_count,
'percentage' => $business_percentage
],
'non_business_document' => [
'sum' => (float) $big_data_resume->non_business_sum,
'count' => $big_data_resume->non_business_count,
'percentage' => $non_business_percentage
],
'realisasi_terbit' => [
'sum' => $realisasi_terbit_pbg_sum,
'count' => $realisasi_terbit_pbg_count,
'percentage' => $realisasi_terbit_percentage
],
'menunggu_klik_dpmptsp' => [
'sum' => $menunggu_klik_dpmptsp_sum,
'count' => $menunggu_klik_dpmptsp_count,
'percentage' => $menunggu_klik_dpmptsp_percentage
],
'proses_dinas_teknis' => [
'sum' => $proses_dinas_teknis_sum,
'count' => $proses_dinas_teknis_count,
'percentage' => $proses_dinas_teknis_percentage
]
];
return response()->json($result);
}catch(\Exception $e){
return response()->json(['message' => 'Error when fetching data'], 500);
}
}
public function bigdata_report(Request $request){
try{
$query = BigdataResume::query()->orderBy('id', 'desc');
if($request->filled('search')){
$query->where('year', 'LIKE', '%'.$request->input('search').'%');
}
$query = $query->paginate(config('app.paginate_per_page', 50));
return BigdataResumeResource::collection($query)->response()->getData(true);
}catch(\Exception $e){
Log::error($e->getMessage());
return response()->json(['message' => 'Error when fetching data'], 500);
}
}
public function payment_recaps(Request $request)
{
try {
$query = BigdataResume::query()->orderBy('id', 'desc');
if ($request->filled('start_date') && $request->filled('end_date')) {
$startDate = Carbon::parse($request->input('start_date'))->startOfDay();
$endDate = Carbon::parse($request->input('end_date'))->endOfDay();
$query->whereBetween('created_at', [$startDate, $endDate]);
}
$data = $query->paginate(50);
// Restructure response
$transformedData = [];
foreach ($data as $item) {
$createdAt = $item->created_at;
$id = $item->id;
foreach ($item->toArray() as $key => $value) {
// Only include columns with "sum" in their names
if (strpos($key, 'sum') !== false) {
$transformedData[] = [
'id' => $id,
'category' => $key,
'nominal' => $value,
'created_at' => $createdAt,
];
}
}
}
return response()->json([
'data' => $transformedData, // Flat array
'pagination' => [
'total' => count($transformedData),
'per_page' => $data->perPage(),
'current_page' => $data->currentPage(),
'last_page' => $data->lastPage(),
]
]);
} catch (\Exception $e) {
Log::error($e->getMessage());
return response()->json(['message' => 'Error when fetching data'], 500);
}
}
public function export_excel_payment_recaps(Request $request)
{
$startDate = null;
$endDate = null;
if ($request->filled('start_date') && $request->filled('end_date')) {
$startDate = Carbon::parse($request->input('start_date'))->startOfDay();
$endDate = Carbon::parse($request->input('end_date'))->endOfDay();
}
return Excel::download(new ReportPaymentRecapExport($startDate, $endDate), 'laporan-rekap-pembayaran.xlsx');
}
public function export_pdf_payment_recaps(Request $request){
$query = BigdataResume::query()->orderBy('id', 'desc');
if ($request->filled('start_date') && $request->filled('end_date')) {
$startDate = Carbon::parse($request->input('start_date'))->startOfDay();
$endDate = Carbon::parse($request->input('end_date'))->endOfDay();
$query->whereBetween('created_at', [$startDate, $endDate]);
}
$items = $query->get();
// Define category mapping
$categoryMap = [
'potention_sum' => 'Potensi',
'non_verified_sum' => 'Belum Terverifikasi',
'verified_sum' => 'Terverifikasi',
'business_sum' => 'Usaha',
'non_business_sum' => 'Non Usaha',
'spatial_sum' => 'Tata Ruang',
'waiting_click_dpmptsp_sum' => 'Menunggu Klik DPMPTSP',
'issuance_realization_pbg_sum' => 'Realisasi Terbit PBG',
'process_in_technical_office_sum' => 'Proses Di Dinas Teknis',
];
// Restructure response
$data = [];
foreach ($items as $item) {
$createdAt = $item->created_at;
$id = $item->id;
foreach ($item->toArray() as $key => $value) {
// Only include columns with "sum" in their names
if (strpos($key, 'sum') !== false) {
$data[] = [
'id' => $id,
'category' => $categoryMap[$key] ?? $key, // Map category
'nominal' => $value, // Format number
'created_at' => $createdAt->format('Y-m-d H:i:s'), // Format date
];
}
}
}
$pdf = Pdf::loadView('exports.payment_recaps_report', compact('data'));
return $pdf->download('laporan-rekap-pembayaran.pdf');
}
public function export_excel_report_director(){
return Excel::download(new ReportDirectorExport, 'laporan-pimpinan.xlsx');
}
public function export_pdf_report_director(){
$data = BigdataResume::select(
'potention_count',
'potention_sum',
'non_verified_count',
'non_verified_sum',
'verified_count',
'verified_sum',
'business_count',
'business_sum',
'non_business_count',
'non_business_sum',
'spatial_count',
'spatial_sum',
'waiting_click_dpmptsp_count',
'waiting_click_dpmptsp_sum',
'issuance_realization_pbg_count',
'issuance_realization_pbg_sum',
'process_in_technical_office_count',
'process_in_technical_office_sum',
'year',
'created_at'
)->orderBy('id', 'desc')->get();
$pdf = Pdf::loadView('exports.director_report', compact('data'))->setPaper('a4', 'landscape');
return $pdf->download('laporan-pimpinan.pdf');
}
private function response_empty_resume(){
$result = [
'target_pad' => [
'sum' => 0,
'percentage' => 100,
],
'tata_ruang' => [
'sum' => 0,
'percentage' => 0,
],
'kekurangan_potensi' => [
'sum' => 0,
'percentage' => 0
],
'total_potensi' => [
'sum' => 0,
'count' => 0,
'percentage' => 0
],
'verified_document' => [
'sum' => 0,
'count' => 0,
'percentage' => 0
],
'non_verified_document' => [
'sum' => 0,
'count' => 0,
'percentage' => 0
],
'business_document' => [
'sum' => 0,
'count' => 0,
'percentage' => 0
],
'non_business_document' => [
'sum' => 0,
'count' => 0,
'percentage' => 0
],
'realisasi_terbit' => [
'sum' => 0,
'count' => 0,
'percentage' => 0
],
'menunggu_klik_dpmptsp' => [
'sum' => 0,
'count' => 0,
'percentage' => 0
],
'proses_dinas_teknis' => [
'sum' => 0,
'count' => 0,
'percentage' => 0
]
];
return response()->json($result);
}
}

View File

@@ -0,0 +1,107 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Requests\BusinessIndustryRequest;
use App\Imports\BusinessIndustriesImport;
use App\Models\BusinessOrIndustry;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;
use \Illuminate\Support\Facades\Validator;
use App\Http\Requests\ExcelUploadRequest;
class BusinessOrIndustriesController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$query = BusinessOrIndustry::query()->orderBy('id', 'desc');
if ($request->has("search") && !empty($request->get("search"))) {
$search = $request->get("search");
info($request); // Debugging log
$query->where(function ($q) use ($search) {
$q->where("nop", "LIKE", "%{$search}%")
->orWhere("nama_kecamatan", "LIKE", "%{$search}%")
->orWhere("nama_kelurahan", "LIKE", "%{$search}%");
});
}
return response()->json($query->paginate(config('app.paginate_per_page', 50)));
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(BusinessIndustryRequest $request, string $id)
{
try{
$data = BusinessOrIndustry::findOrFail($id);
$data->update($request->validated());
return response()->json(['message' => 'Data updated successfully.'], 200);
}catch(\Exception $e){
\Log::error($e->getMessage());
return response()->json(['message' => 'Failed to update data'],500);
}
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
try{
$data = BusinessOrIndustry::findOrFail($id);
$data->delete();
return response()->json(['message' => 'Data deleted successfully.'], 200);
}catch(\Exception $e){
\Log::error($e->getMessage());
return response()->json(['message' => 'Failed to delete data'],500);
}
}
public function upload(ExcelUploadRequest $request){
try {
if(!$request->hasFile('file')){
return response()->json([
'error' => 'No file provided'
], 400);
}
$file = $request->file('file');
Excel::import(new BusinessIndustriesImport, $file);
// Jika sukses, kembalikan respons sukses
return response()->json([
'message' => 'File uploaded and imported successfully!'
], 200);
} catch (\Exception $e) {
// Jika ada error, kembalikan error response
return response()->json([
'message' => 'Error during file import.',
'error' => $e->getMessage()
], 500);
}
}
}

View File

@@ -0,0 +1,117 @@
<?php
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Services\OpenAIService;
use App\Http\Controllers\Controller;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class ChatbotController extends Controller
{
protected $openAIService;
public function __construct(OpenAIService $openAIService)
{
$this->openAIService = $openAIService;
}
public function generateText(Request $request)
{
$request->validate([
'tab_active' => 'required|string',
'prompt' => 'required|string',
]);
$tab_active = $request->input('tab_active');
$main_content = match ($tab_active) {
"count-retribusi" => "RETRIBUTION",
"document-validation" => "DOCUMENT VALIDATION",
"data-information" => "DATA SUMMARY",
default => "UNKNOWN",
};
$chatHistory = $request->input('chatHistory');
Log::info('Chat history sebelum disimpan:', ['history' => $chatHistory]);
if ($main_content === "UNKNOWN") {
return response()->json(['response' => 'Invalid tab_active value.'], 400);
}
// info($main_content);
$queryResponse = $this->openAIService->generateQueryBasedMainContent($request->input('prompt'), $main_content, $chatHistory);
if (str_contains($queryResponse, 'tidak relevan') || str_contains($queryResponse, 'tidak valid') || str_starts_with($queryResponse, 'Prompt')) {
return response()->json(['response' => $queryResponse], 400);
}
$formattedResultQuery = "[]";
$queryResponse = str_replace(['```sql', '```'], '', $queryResponse);
$resultQuery = DB::select($queryResponse);
$formattedResultQuery = json_encode($resultQuery, JSON_PRETTY_PRINT);
info($formattedResultQuery);
$nlpResult = $this->openAIService->generateNLPFromQuery($request->input('prompt'), $formattedResultQuery);
$finalGeneratedText =$this->openAIService->generateFinalText($nlpResult);
return response()->json(['response' => $finalGeneratedText, 'nlpResponse' => $queryResponse]);
}
public function mainGenerateText(Request $request)
{
// Log hanya data yang relevan
info("Received prompt: " . $request->input('prompt'));
// Validasi input
$request->validate([
'prompt' => 'required|string',
]);
try {
// Panggil service untuk generate text
$classifyResponse = $this->openAIService->classifyMainGenerateText($request->input('prompt'));
info($classifyResponse);
// Pastikan hasil klasifikasi valid sebelum melanjutkan
$validCategories = [
'reklame', 'business_or_industries', 'customers',
'pbg', 'retribusi', 'spatial_plannings',
'tourisms', 'umkms'
];
if (!in_array($classifyResponse, $validCategories)) {
return response()->json([
'error' => ''
], 400);
}
$chatHistory = $request->input('chatHistory');
Log::info('Chat history sebelum disimpan:', ['history' => $chatHistory]);
$queryResponse = $this->openAIService->createMainQuery($classifyResponse, $request->input('prompt'), $chatHistory);
info($queryResponse);
$formattedResultQuery = "[]";
$queryResponse = str_replace(['```sql', '```'], '', $queryResponse);
$queryResult = DB::select($queryResponse);
$formattedResultQuery = json_encode($queryResult, JSON_PRETTY_PRINT);
$nlpResult = $this->openAIService->generateNLPFromQuery($request->input('prompt'), $formattedResultQuery);
$finalGeneratedText =$this->openAIService->generateFinalText($nlpResult);
return response()->json(['response' => $finalGeneratedText, 'nlpResponse' => $queryResponse]);
} catch (\Exception $e) {
// Tangani error dan log exception
\Log::error("Error generating text: " . $e->getMessage());
return response()->json([
'error' => ''
], 500);
}
}
}

View File

@@ -0,0 +1,130 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Requests\CustomersRequest;
use App\Http\Requests\ExcelUploadRequest;
use App\Http\Resources\CustomersResource;
use App\Imports\CustomersImport;
use App\Models\Customer;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;
class CustomersController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$query = Customer::query()->orderBy('id', 'desc');
if ($request->has('search') &&!empty($request->get('search'))) {
$query = $query->where('nomor_pelanggan', 'LIKE', '%'.$request->get('search').'%')
->orWhere('nama', 'LIKE', '%'.$request->get('search').'%')
->orWhere('kota_pelayanan', 'LIKE', '%'.$request->get('search').'%');
}
return CustomersResource::collection($query->paginate(config('app.paginate_per_page', 50)));
}
/**
* Store a newly created resource in storage.
*/
public function store(CustomersRequest $request)
{
try{
$customer = Customer::create($request->validated());
return response()->json(['message' => 'Successfully created', new CustomersResource($customer)]);
}catch(\Exception $e){
return response()->json([
'message' => 'Failed to create customer',
'error' => $e->getMessage()
], 500);
}
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
try{
$customer = Customer::find($id);
if($customer){
return new CustomersResource($customer);
} else {
return response()->json(['message' => 'Customer not found'], 404);
}
}catch(\Exception $e){
return response()->json([
'message' => 'Failed to retrieve customer',
'error' => $e->getMessage()
], 500);
}
}
/**
* Update the specified resource in storage.
*/
public function update(CustomersRequest $request, string $id)
{
try{
$customer = Customer::find($id);
if($customer){
$customer->update($request->validated());
return response()->json(['message' => 'Successfully updated', new CustomersResource($customer)]);
} else {
return response()->json(['message' => 'Customer not found'], 404);
}
}catch(\Exception $e) {
return response()->json([
'message' => 'Failed to update customer',
'error' => $e->getMessage()
], 500);
}
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
try{
$customer = Customer::find($id);
if($customer){
$customer->delete();
return response()->json(['message' => 'Successfully deleted']);
}else {
return response()->json(['message' => 'Customer not found'], 404);
}
}catch(\Exception $e) {
return response()->json([
'message' => 'Failed to delete customer',
'error' => $e->getMessage()
], 500);
}
}
public function upload(ExcelUploadRequest $request){
try{
if(!$request->hasFile('file')){
return response()->json([
'error' => 'No file provided'
], 400);
}
$file = $request->file('file');
Excel::import(new CustomersImport, $file);
return response()->json([
'message' => 'File uploaded successfully',
]);
}catch(\Exception $e){
\Log::info($e->getMessage());
return response()->json([
'error' => 'Failed to upload file',
'message' => $e->getMessage()
], 500);
}
}
}

View File

@@ -34,7 +34,7 @@ class GlobalSettingsController extends Controller
try {
$data = GlobalSetting::create($request->validated());
return new GlobalSettingResource($data);
} catch (\Exception $e) {
} catch (Exception $e) {
return $this->resError($e->getMessage(), null, $e->getCode());
}
}

View File

@@ -3,33 +3,15 @@
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Services\GoogleSheetService;
use Illuminate\Http\Request;
class GoogleSheetController extends Controller
{
protected $googleSheetService;
public function __construct(GoogleSheetService $googleSheetService){
$this->googleSheetService = $googleSheetService;
}
/**
* Display a listing of the resource.
*/
public function index()
public function index(Request $request)
{
$dataCollection = $this->googleSheetService->getSheetDataCollection();
$result = [
"last_row" => $this->googleSheetService->getLastRowByColumn("C"),
"last_column" => $this->googleSheetService->getLastColumn(),
"header" => $this->googleSheetService->getHeader(),
"data_collection" => $dataCollection
];
return response()->json($result);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//

View File

@@ -0,0 +1,91 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\BigdataResume;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class GrowthReportAPIController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
// Get current date
$today = Carbon::today();
// Define default range: 1 month back from today
$defaultStart = $today->copy()->subMonth();
$defaultEnd = $today;
// Use request values if provided, else use defaults
// $startDate = $request->input('start_date', $defaultStart->toDateString());
// $endDate = $request->input('end_date', $defaultEnd->toDateString());
// Optional year filter (used if specified)
$year = $request->input('year', now()->year);
// $query = BigdataResume::selectRaw("
// DATE(created_at) as date,
// SUM(potention_sum) as potention_sum,
// SUM(verified_sum) as verified_sum,
// SUM(non_verified_sum) as non_verified_sum
// ")
// ->whereBetween('created_at', [$startDate, $endDate]);
$query = BigdataResume::selectRaw("
DATE(created_at) as date,
SUM(potention_sum) as potention_sum,
SUM(verified_sum) as verified_sum,
SUM(non_verified_sum) as non_verified_sum
");
$query->whereNotNull('year')
->where('year', '!=', 'all');
$data = $query->groupBy(DB::raw('DATE(created_at)'))
->orderBy(DB::raw('DATE(created_at)'))
->get()
->map(function ($item) {
$item->date = Carbon::parse($item->date)->format('d M Y');
return $item;
});
return response()->json($data);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}

View File

@@ -24,7 +24,7 @@ class ImportDatasourceController extends Controller
$search = $request->get("search");
$query->where('status', 'like', "%".$search."%");
}
return ImportDatasourceResource::collection($query->paginate());
return ImportDatasourceResource::collection($query->paginate(config('app.paginate_per_page', 50)));
}
public function checkImportDatasource(){

View File

@@ -0,0 +1,38 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Advertisement;
use App\Models\Customer;
use App\Models\SpatialPlanning;
use Illuminate\Http\Request;
use App\Models\TourismBasedKBLI;
class LackOfPotentialController extends Controller
{
public function count_lack_of_potential(){
try{
$total_reklame = Advertisement::count();
$total_pdam = Customer::count();
$total_tata_ruang = SpatialPlanning::count();
$total_tata_ruang_usaha = SpatialPlanning::where('building_function','like', '%usaha%')->count();
$total_tata_ruang_non_usaha = SpatialPlanning::where('building_function','like', '%hunian%')->count();
$data_report_tourism = TourismBasedKBLI::all();
return response()->json([
'total_reklame' => $total_reklame,
'total_pdam' => $total_pdam,
'total_tata_ruang' => $total_tata_ruang,
'total_tata_ruang_usaha' => $total_tata_ruang_usaha,
'total_tata_ruang_non_usaha' => $total_tata_ruang_non_usaha,
'data_report' => $data_report_tourism,
], 200);
}catch(\Exception $e){
return response()->json([
'message' => 'Error: '.$e->getMessage()
], 500);
}
}
}

View File

@@ -3,8 +3,11 @@
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Requests\MenuRequest;
use App\Http\Resources\MenuResource;
use App\Models\Menu;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class MenusController extends Controller
{
@@ -13,21 +16,28 @@ class MenusController extends Controller
*/
public function index(Request $request)
{
$query = Menu::query();
$query = Menu::query()->orderBy('id', 'desc');
if($request->has("search") && !empty($request->get("search"))){
$query = $query->where("name", "like", "%".$request->get("search")."%");
}
return response()->json($query->paginate());
// return response()->json($query->paginate(config('app.paginate_per_page', 50)));
return MenuResource::collection($query->paginate(config('app.paginate_per_page',50)));
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
public function store(MenuRequest $request)
{
//
try{
$menu = Menu::create($request->validated());
return response()->json(['message' => 'Menu created successfully', 'data' => new MenuResource($menu)]);
}catch(\Exception $e){
Log::error($e);
return response()->json(['message' => 'Error when creating menu'], 500);
}
}
/**
@@ -35,15 +45,37 @@ class MenusController extends Controller
*/
public function show(string $id)
{
//
try{
$menu = Menu::find($id);
if($menu){
return response()->json(['message' => 'Menu found', 'data' => new MenuResource($menu)]);
} else {
return response()->json(['message' => 'Menu not found'], 404);
}
}catch(\Exception $e){
Log::error($e);
Log::error($e->getMessage());
return response()->json(['message' => 'Error when finding menu'], 500);
}
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
public function update(MenuRequest $request, string $id)
{
//
try{
$menu = Menu::findOrFail($id);
if($menu){
$menu->update($request->validated());
return response()->json(['message' => 'Menu updated successfully', 'data' => new MenuResource($menu)]);
} else {
return response()->json(['message' => 'Menu not found'], 404);
}
}catch(\Exception $e){
Log::error($e);
return response()->json(['message' => 'Error when updating menu'], 500);
}
}
/**
@@ -51,6 +83,28 @@ class MenusController extends Controller
*/
public function destroy(string $id)
{
//
try{
$menu = Menu::findOrFail($id);
if($menu){
$this->deleteChildren($menu);
$menu->roles()->detach();
$menu->delete();
return response()->json(['message' => 'Menu deleted successfully']);
} else {
return response()->json(['message' => 'Menu not found'], 404);
}
}catch(\Exception $e){
Log::error($e);
return response()->json(['message' => 'Error when deleting menu'], 500);
}
}
private function deleteChildren($menu)
{
foreach ($menu->children as $child) {
$this->deleteChildren($child); // Recursively delete its children
$child->roles()->detach(); // Detach roles before deleting
$child->delete();
}
}
}

View File

@@ -0,0 +1,109 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\PbgTaskAttachment;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\Response;
class PbgTaskAttachmentsController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request, $pbg_task_id)
{
try{
$request->validate([
'file' => 'required|file|mimes:jpg,png,pdf|max:5120',
'pbg_type' => 'string'
]);
$attachment = PbgTaskAttachment::create([
'pbg_task_id' => $pbg_task_id,
'file_name' => $request->file('file')->getClientOriginalName(),
'file_path' => '', // empty path initially
'pbg_type' => $request->pbg_type == 'bukti_bayar' ? 'bukti_bayar' : 'berita_acara'
]);
$file = $request->file('file');
$path = $file->store("uploads/pbg-tasks/{$pbg_task_id}/{$attachment->id}", "public");
$attachment->update([
'file_path' => $path,
]);
return response()->json([
'message' => 'File uploaded successfully.',
'attachment' => [
'id' => $attachment->id,
'file_name' => $attachment->file_name,
'file_url' => Storage::url($attachment->file_path),
'pbg_type' => $attachment->pbg_type
]
]);
}catch(\Exception $e){
\Log::error($e->getMessage());
return response()->json([
"success" => false,
"message" => $e->getTraceAsString()
]);
}
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
public function download(string $id)
{
try {
$data = PbgTaskAttachment::findOrFail($id);
$filePath = $data->file_path; // already relative to 'public' disk
if (!Storage::disk('public')->exists($filePath)) {
return response()->json([
"success" => false,
"message" => "File not found on server"
], Response::HTTP_NOT_FOUND);
}
return Storage::disk('public')->download($filePath, $data->file_name);
} catch (\Exception $e) {
return response()->json([
"success" => false,
"message" => $e->getMessage()
]);
}
}
}

View File

@@ -3,9 +3,12 @@
namespace App\Http\Controllers\Api;
use App\Enums\ImportDatasourceStatus;
use App\Enums\PbgTaskApplicationTypes;
use App\Enums\PbgTaskStatus;
use App\Http\Controllers\Controller;
use App\Http\Requests\PbgTaskMultiStepRequest;
use App\Http\Resources\PbgTaskResource;
use App\Models\DataSetting;
use App\Models\ImportDatasource;
use App\Models\PbgTask;
use App\Models\PbgTaskGoogleSheet;
@@ -13,6 +16,7 @@ use App\Services\GoogleSheetService;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rules\Enum;
class PbgTaskController extends Controller
{
@@ -20,9 +24,35 @@ class PbgTaskController extends Controller
public function __construct(GoogleSheetService $googleSheetService){
$this->googleSheetService = $googleSheetService;
}
public function index()
public function index(Request $request)
{
//
info($request);
$isLastUpdated = filter_var($request->query('isLastUpdated', false), FILTER_VALIDATE_BOOLEAN);
$query = PbgTask::query();
if ($isLastUpdated) {
$query->orderBy('updated_at', 'desc');
} else {
$query->where('status', 20);
}
// Ambil maksimal 10 data
$pbg_task = $query->limit(10)->get();
$totalData = $pbg_task->count();
// Tambahkan nomor urut
$data = $pbg_task->map(function ($item, $index) {
return array_merge($item->toArray(), ['no' => $index + 1]);
});
return response()->json([
'data' => $data,
'meta' => [
'total' => $totalData
]
]);
}
/**
@@ -89,9 +119,63 @@ class PbgTaskController extends Controller
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
public function update(Request $request, string $task_uuid)
{
//
try{
$pbg_task = PbgTask::where('uuid',$task_uuid)->first();
if(!$pbg_task){
return response()->json([
"success"=> false,
"message"=> "Data PBG Task tidak ditemukan",
], 404);
}
$validated = $request->validate([
'name' => 'required|string|max:255',
'owner_name' => 'required|string|max:255',
'application_type' => ['nullable', new Enum(PbgTaskApplicationTypes::class)],
'condition' => 'required|string|max:255',
'registration_number' => 'required|string|max:255',
'document_number' => 'required|string|max:255',
'status' => ['nullable', new Enum(PbgTaskStatus::class)],
'address' => 'required|string|max:255',
'slf_status_name' => 'nullable|string|max:255',
'function_type' => 'required|string|max:255',
'consultation_type' => 'required|string|max:255',
'due_date' => 'nullable|date|after_or_equal:today',
]);
$statusLabel = $validated['status'] !== null ? PbgTaskStatus::getLabel($validated['status']) : null;
$applicationLabel = $validated['application_type'] !== null ? PbgTaskApplicationTypes::getLabel($validated['application_type']) : null;
$pbg_task->update([
'name' => $validated['name'],
'owner_name' => $validated['owner_name'],
'application_type' => $validated['application_type'],
'application_type_name' => $applicationLabel, // Automatically set application_type_name
'condition' => $validated['condition'],
'registration_number' => $validated['registration_number'],
'document_number' => $validated['document_number'],
'status' => $validated['status'],
'status_name' => $statusLabel, // Automatically set status_name
'address' => $validated['address'],
'slf_status_name' => $validated['slf_status_name'],
'function_type' => $validated['function_type'],
'consultation_type' => $validated['consultation_type'],
'due_date' => $validated['due_date'],
]);
return response()->json([
"success"=> true,
"message"=> "Data berhasil diubah",
"data"=> $pbg_task
]);
}catch(\Exception $e){
return response()->json([
"success"=> false,
"message"=> $e->getMessage(),
]);
}
}
/**
@@ -108,218 +192,4 @@ class PbgTaskController extends Controller
]);
}
public function syncPbgFromGoogleSheet(){
try{
$totalRowCount = $this->googleSheetService->getLastRowByColumn("C");
$sheetData = $this->googleSheetService->getSheetDataCollection($totalRowCount);
$mapToUpsert = [];
$count = 0;
$import_datasource = ImportDatasource::create([
"message" => "initialization",
"response_body" => null,
"status" => ImportDatasourceStatus::Processing->value,
]);
foreach($sheetData as $data){
$mapToUpsert[] =
[
'no_registrasi' => $data['no__registrasi'] ?? null,
'jenis_konsultasi' => $data['jenis_konsultasi'] ?? null,
'fungsi_bg' => $data['fungsi_bg'] ?? null,
'tgl_permohonan' => $this->convertToDate($data['tgl_permohonan']),
'status_verifikasi' => $data['status_verifikasi'] ?? null,
'status_permohonan' => $this->convertToDate($data['status_permohonan']),
'alamat_pemilik' => $data['alamat_pemilik'] ?? null,
'no_hp' => $data['no__hp'] ?? null,
'email' => $data['e_mail'] ?? null,
'tanggal_catatan' => $this->convertToDate($data['tanggal_catatan']),
'catatan_kekurangan_dokumen' => $data['catatan_kekurangan_dokumen'] ?? null,
'gambar' => $data['gambar'] ?? null,
'krk_kkpr' => $data['krk_kkpr'] ?? null,
'no_krk' => $data['no__krk'] ?? null,
'lh' => $data['lh'] ?? null,
'ska' => $data['ska'] ?? null,
'keterangan' => $data['keterangan'] ?? null,
'helpdesk' => $data['helpdesk'] ?? null,
'pj' => $data['pj'] ?? null,
'kepemilikan' => $data['kepemilikan'] ?? null,
'potensi_taru' => $data['potensi_taru'] ?? null,
'validasi_dinas' => $data['validasi_dinas'] ?? null,
'kategori_retribusi' => $data['kategori_retribusi'] ?? null,
'no_urut_ba_tpt' => $data['no__urut_ba_tpt__2024_0001_'] ?? null,
'tanggal_ba_tpt' => $this->convertToDate($data['tanggal_ba_tpt']),
'no_urut_ba_tpa' => $data['no__urut_ba_tpa'] ?? null,
'tanggal_ba_tpa' => $this->convertToDate($data['tanggal_ba_tpa']),
'no_urut_skrd' => $data['no__urut_skrd__2024_0001_'] ?? null,
'tanggal_skrd' => $this->convertToDate($data['tanggal_skrd']),
'ptsp' => $data['ptsp'] ?? null,
'selesai_terbit' => $data['selesai_terbit'] ?? null,
'tanggal_pembayaran' => $this->convertToDate($data['tanggal_pembayaran__yyyy_mm_dd_']),
'format_sts' => $data['format_sts'] ?? null,
'tahun_terbit' => (int) $data['tahun_terbit'] ?? null,
'tahun_berjalan' => (int) $data['tahun_berjalan'] ?? null,
'kelurahan' => $data['kelurahan'] ?? null,
'kecamatan' => $data['kecamatan'] ?? null,
'lb' => $this->convertToDecimal($data['lb']) ?? null,
'tb' => $this->convertToDecimal($data['tb']) ?? null,
'jlb' => (int) $data['jlb'] ?? null,
'unit' => (int) $data['unit'] ?? null,
'usulan_retribusi' => (int) $data['usulan_retribusi'] ?? null,
'nilai_retribusi_keseluruhan_simbg' => $this->convertToDecimal($data['nilai_retribusi_keseluruhan__simbg_']) ?? null,
'nilai_retribusi_keseluruhan_pad' => $this->convertToDecimal($data['nilai_retribusi_keseluruhan__pad_']) ?? null,
'denda' => $this->convertToDecimal($data['denda']) ?? null,
'latitude' => $data['latitude'] ?? null,
'longitude' => $data['longitude'] ?? null,
'nik_nib' => $data['nik_nib'] ?? null,
'dok_tanah' => $data['dok__tanah'] ?? null,
'temuan' => $data['temuan'] ?? null,
];
}
DB::beginTransaction();
$batchSize = 1000;
$chunks = array_chunk($mapToUpsert, $batchSize);
foreach($chunks as $chunk){
PbgTaskGoogleSheet::upsert($chunk, ["no_registrasi"],[
'jenis_konsultasi',
'nama_pemilik',
'lokasi_bg',
'fungsi_bg',
'nama_bangunan',
'tgl_permohonan',
'status_verifikasi',
'status_permohonan',
'alamat_pemilik',
'no_hp',
'email',
'tanggal_catatan',
'catatan_kekurangan_dokumen',
'gambar',
'krk_kkpr',
'no_krk',
'lh',
'ska',
'keterangan',
'helpdesk',
'pj',
'kepemilikan',
'potensi_taru',
'validasi_dinas',
'kategori_retribusi',
'no_urut_ba_tpt',
'tanggal_ba_tpt',
'no_urut_ba_tpa',
'tanggal_ba_tpa',
'no_urut_skrd',
'tanggal_skrd',
'ptsp',
'selesai_terbit',
'tanggal_pembayaran',
'format_sts',
'tahun_terbit',
'tahun_berjalan',
'kelurahan',
'kecamatan',
'lb',
'tb',
'jlb',
'unit',
'usulan_retribusi',
'nilai_retribusi_keseluruhan_simbg',
'nilai_retribusi_keseluruhan_pad',
'denda',
'latitude',
'longitude',
'nik_nib',
'dok_tanah',
'temuan',
]);
}
$total_data = count($mapToUpsert);
$import_datasource->update([
"message" => "Successfully imported {$total_data}",
"status" => ImportDatasourceStatus::Success->value,
]);
DB::commit();
return response()->json([
"success" => true,
"message" => "Data berhasil disimpan ke database"
], 200);
}catch(\Exception $ex){
DB::rollBack();
$import_datasource->update([
"message" => "Failed to importing",
"response_body" => $ex->getMessage(),
"status" => ImportDatasourceStatus::Failed->value,
]);
return response()->json([
"success" => false,
"message" => "Gagal menyimpan data",
"error" => $ex->getMessage()
], 500);
}
}
protected function convertToDecimal(?string $value): ?float
{
if (empty($value)) {
return null; // Return null if the input is empty
}
// Remove all non-numeric characters except comma and dot
$value = preg_replace('/[^0-9,\.]/', '', $value);
// If the number contains both dot (.) and comma (,)
if (strpos($value, '.') !== false && strpos($value, ',') !== false) {
$value = str_replace('.', '', $value); // Remove thousands separator
$value = str_replace(',', '.', $value); // Convert decimal separator to dot
}
// If only a dot is present (assumed as thousands separator)
elseif (strpos($value, '.') !== false) {
$value = str_replace('.', '', $value); // Remove all dots (treat as thousands separators)
}
// If only a comma is present (assumed as decimal separator)
elseif (strpos($value, ',') !== false) {
$value = str_replace(',', '.', $value); // Convert comma to dot (decimal separator)
}
// Ensure the value is numeric before returning
return is_numeric($value) ? (float) number_format((float) $value, 2, '.', '') : null;
}
protected function convertToInteger($value) {
// Check if the value is an empty string, and return null if true
if (trim($value) === "") {
return null;
}
// Otherwise, cast to integer
return (int) $value;
}
protected function convertToDate($dateString)
{
try {
// Check if the string is empty
if (empty($dateString)) {
return null;
}
// Try to parse the date string
$date = Carbon::parse($dateString);
// Return the Carbon instance
return $date->format('Y-m-d');
} catch (\Exception $e) {
// Return null if an error occurs during parsing
return null;
}
}
}

View File

@@ -0,0 +1,61 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Resources\PbgTaskGoogleSheetResource;
use App\Models\PbgTaskGoogleSheet;
use Illuminate\Http\Request;
class PbgTaskGoogleSheetsController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$query = PbgTaskGoogleSheet::query()->orderBy('id', 'desc');
if ($request->filled('search')) {
$query->where('no_registrasi', 'like', "%{$request->get('search')}%");
}
return PbgTaskGoogleSheetResource::collection($query->paginate(config('app.paginate_per_page', 50)));
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
try{
$data = PbgTaskGoogleSheet::find($id);
$data->delete();
return response()->json(['message' => 'Data deleted successfully'], 200);
}catch(\Exception $e){
return response()->json(['message' => 'Failed to delete data'], 500);
}
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace App\Http\Controllers\Api;
use App\Exports\ReportPbgPtspExport;
use App\Http\Controllers\Controller;
use App\Models\PbgTask;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Facades\Excel;
class ReportPbgPtspController extends Controller
{
public function export_excel(){
return Excel::download(new ReportPbgPtspExport, 'laporan-ptsp.xlsx');
}
public function export_pdf(){
$data = PbgTask::select(
'status',
'status_name', // Keeping this column
DB::raw('COUNT(*) as total')
)
->groupBy('status', 'status_name')
->get();
$pdf = Pdf::loadView('exports.ptsp_report', compact('data'));
return $pdf->download('laporan-ptsp.pdf');
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace App\Http\Controllers\Api;
use App\Exports\ReportTourismExport;
use App\Http\Controllers\Controller;
use App\Models\TourismBasedKBLI;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;
class ReportTourismsController extends Controller
{
public function export_excel(){
return Excel::download(new ReportTourismExport, 'laporan-pariwisata.xlsx');
}
public function export_pdf(){
$data = TourismBasedKBLI::all();
$pdf = Pdf::loadView('exports.tourisms_report', compact('data'));
return $pdf->download('laporan-pariwisata.pdf');
}
}

View File

@@ -2,10 +2,17 @@
namespace App\Http\Controllers\Api;
use App\Exports\DistrictPaymentRecapExport;
use App\Http\Controllers\Controller;
use App\Http\Resources\RequestAssignmentResouce;
use App\Models\PbgTask;
use App\Models\PbgTaskGoogleSheet;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Support\Facades\DB;
use Exception;
use Illuminate\Http\Request;
use Log;
use Maatwebsite\Excel\Facades\Excel;
class RequestAssignmentController extends Controller
{
@@ -14,14 +21,112 @@ class RequestAssignmentController extends Controller
*/
public function index(Request $request)
{
$query = PbgTask::query()->orderBy('id', 'desc');
if($request->has('search') && !empty($request->get("search"))){
$query->where('name', 'LIKE', '%'.$request->get('search').'%')
->orWhere('registration_number', 'LIKE', '%'.$request->get('search').'%');
$query = PbgTask::with([
'attachments' => function ($q) {
$q->whereIn('pbg_type', ['berita_acara', 'bukti_bayar']);
},
'googleSheet'
])->orderBy('id', 'desc');
if ($request->has('filter') && !empty($request->get('filter'))) {
$filter = strtolower($request->get('filter'));
switch ($filter) {
case 'non-business':
$query->whereRaw("LOWER(function_type) != ?", ['sebagai tempat usaha'])->orWhereNull('function_type');
break;
case 'business':
$query->whereRaw("LOWER(function_type) = ?", ['sebagai tempat usaha']);
break;
case 'verified':
$query->whereHas('googleSheet', function ($q) {
$q->whereRaw("LOWER(status_verifikasi) = ?", ['selesai verifikasi']);
});
break;
case 'non-verified':
$query->where(function ($q) {
$q->whereDoesntHave('googleSheet')
->orWhereHas('googleSheet', function ($q2) {
$q2->whereRaw("LOWER(status_verifikasi) != ?", ['selesai verifikasi'])->orWhereNull('status_verifikasi');
});
});
break;
}
}
if ($request->has('search') && !empty($request->get("search"))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('name', 'LIKE', "%$search%")
->orWhere('registration_number', 'LIKE', "%$search%")
->orWhere('document_number', 'LIKE', "%$search%");
});
}
return RequestAssignmentResouce::collection($query->paginate());
}
public function report_payment_recaps(Request $request)
{
try {
// Query dengan group by kecamatan dan sum nilai_retribusi_keseluruhan_simbg
$query = PbgTaskGoogleSheet::select(
'kecamatan',
DB::raw('SUM(nilai_retribusi_keseluruhan_simbg) as total')
)
->groupBy('kecamatan')
->paginate(10);
// Return hasil dalam JSON format
return response()->json([
'success' => true,
'data' => $query
]);
} catch (Exception $e) {
Log::error($e->getMessage());
return response()->json(['message' => 'Terjadi kesalahan: ' . $e->getMessage()], 500);
}
}
public function export_excel_district_payment_recaps(){
return Excel::download(new DistrictPaymentRecapExport, 'laporan-rekap-data-pembayaran.xlsx');
}
public function export_pdf_district_payment_recaps(){
$data = PbgTaskGoogleSheet::select(
'kecamatan',
DB::raw('SUM(nilai_retribusi_keseluruhan_simbg) as total')
)
->groupBy('kecamatan')->get();
$pdf = Pdf::loadView('exports.district_payment_report', compact('data'));
return $pdf->download('laporan-rekap-data-pembayaran.pdf');
}
public function report_pbg_ptsp()
{
try {
// Query dengan group by status dan count total per status
$query = PbgTask::select(
'status',
'status_name',
DB::raw('COUNT(*) as total')
)
->groupBy('status', 'status_name')
->paginate(10);
// Return hasil dalam JSON format
return response()->json([
'success' => true,
'data' => $query
]);
} catch (Exception $e) {
Log::error($e->getMessage());
return response()->json(['message' => 'Terjadi kesalahan: ' . $e->getMessage()], 500);
}
}
/**
* Store a newly created resource in storage.
*/

View File

@@ -3,6 +3,7 @@
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Requests\RoleRequest;
use App\Models\Role;
use Illuminate\Http\Request;
@@ -13,21 +14,26 @@ class RolesController extends Controller
*/
public function index(Request $request)
{
$query = Role::query();
$query = Role::query()->orderBy('id', 'desc');
if($request->has('search') && !empty($request->get('search'))){
$query = $query->where('name', 'like', '%'. $request->get('search') . '%');
}
return response()->json($query->paginate());
return response()->json($query->paginate(config('app.paginate_per_page', 50)));
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
public function store(RoleRequest $request)
{
//
try{
$role = Role::create($request->validated());
return response()->json(['message' => 'Successfully created', 'data' => $role]);
}catch(\Exception $e){
return response()->json(['message' => 'Error when creating role', 'error' => $e->getMessage()], 500);
}
}
/**
@@ -35,15 +41,34 @@ class RolesController extends Controller
*/
public function show(string $id)
{
//
try{
$role = Role::find($id);
if($role){
return response()->json(['data' => $role]);
} else {
return response()->json(['message' => 'Role not found'], 404);
}
}catch(\Exception $e){
return response()->json(['message' => 'Error when getting role', 'error' => $e->getMessage()], 500);
}
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
public function update(RoleRequest $request, string $id)
{
//
try{
$role = Role::find($id);
if($role){
$role->update($request->validated());
return response()->json(['message' => 'Successfully updated', 'data' => $role]);
} else {
return response()->json(['message' => 'Role not found'], 404);
}
}catch(\Exception $e){
return response()->json(['message' => 'Error when updating role', 'error' => $e->getMessage()], 500);
}
}
/**
@@ -51,6 +76,16 @@ class RolesController extends Controller
*/
public function destroy(string $id)
{
//
try{
$role = Role::find($id);
if($role){
$role->delete();
return response()->json(['message' => 'Successfully deleted']);
} else {
return response()->json(['message' => 'Role not found'], 404);
}
}catch(\Exception $e){
return response()->json(['message' => 'Error when deleting role', 'error' => $e->getMessage()], 500);
}
}
}

View File

@@ -4,8 +4,16 @@ namespace App\Http\Controllers\Api;
use App\Enums\ImportDatasourceStatus;
use App\Http\Controllers\Controller;
use App\Jobs\RetrySyncronizeJob;
use App\Jobs\ScrapingDataJob;
use App\Jobs\SyncronizeSIMBG;
use App\Models\ImportDatasource;
use App\Traits\GlobalApiResponse;
use App\Services\ServiceTokenSIMBG;
use GuzzleHttp\Client;
use App\Services\ServiceGoogleSheet;
use App\Services\ServicePbgTask;
use App\Services\ServiceTabPbgTask;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Http\Request;
@@ -22,40 +30,33 @@ class ScrapingController extends Controller
return $this->resError("Failed to execute while processing another scraping");
}
// run service artisan command
Artisan::call("app:execute-scraping");
return $this->resSuccess("Success execute scraping service please wait");
// use ole schema synchronization
// dispatch(new SyncronizeSIMBG());
// use new schema synchronization
dispatch(new ScrapingDataJob());
return $this->resSuccess(["message" => "Success execute scraping service on background, check status for more"]);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
public function retry_syncjob(string $import_datasource_id){
try{
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
$import_datasource = ImportDatasource::find($import_datasource_id);
if(!$import_datasource){
return $this->resError("Invalid import datasource id", null, 404);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
dispatch(new RetrySyncronizeJob($import_datasource->id));
return response()->json([
"success" => true,
"message" => "Retrying scrape job on background, check status for more"
]);
}catch(\Exception $e){
return response()->json([
"success" => false,
"message" => "Failed to retry sync job",
"error" => $e->getMessage()
]);
}
}
}

View File

@@ -0,0 +1,146 @@
<?php
namespace App\Http\Controllers\Api;
use App\Models\SpatialPlanning;
use Illuminate\Http\Request;
use App\Http\Requests\SpatialPlanningRequest;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use App\Http\Resources\SpatialPlanningResource;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Facades\Excel;
use App\Imports\SpatialPlanningImport;
use Illuminate\Support\Facades\Storage;
class SpatialPlanningController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
info($request);
$perPage = $request->input('per_page', 15);
$search = $request->input('search', '');
$query = SpatialPlanning::query();
if ($search) {
$query->where(function ($q) use ($search) {
$q->where('name', 'like', "%$search%")
->orWhere('kbli', 'like', "%$search%")
->orWhere('activities', 'like', "%$search%")
->orWhere('area', 'like', "%$search%")
->orWhere('location', 'like', "%$search%")
->orWhere('number', 'like', "%$search%");
});
}
$spatialPlannings = $query->paginate($perPage);
// Menambhakan nomor urut (No)
$start = ($spatialPlannings->currentPage()-1) * $perPage + 1;
// Tambahkan nomor urut ke dalam data
$data = $spatialPlannings->map(function ($item, $index) use ($start) {
return array_merge($item->toArray(), ['no' => $start + $index]);
});
info($data);
return response()->json([
'data' => $data,
'meta' => [
'total' => $spatialPlannings->total(),
'per_page' => $spatialPlannings->perPage(),
'current_page' => $spatialPlannings->currentPage(),
'last_page'=>$spatialPlannings->lastPage(),
]
]);
}
/**
* Store a newly created resource in storage.
*/
public function store(SpatialPlanningRequest $request): SpatialPlanning
{
$data = $request->validated();
return SpatialPlanning::create($data);
}
/**
* import spatial planning from excel
*/
public function importFromFile(Request $request)
{
info($request);
//validasi file
$validator = Validator::make($request->all(), [
'file' => 'required|mimes:xlsx, xls|max:10240'
]);
if ($validator->fails()) {
return response()->json([
'message'=>'File vaildation failed.',
"errors"=>$validator->errors()
], 400);
}
try {
$file = $request->file('file');
Excel::import(new SpatialPlanningImport, $file);
return response()->json([
'message'=>'File uploaded and imported successfully!'
], 200);
} catch (\Exception $e) {
return response()->json([
'message'=>'Error during file import.',
'error'=>$e->getMessage()
], 500);
}
}
/**
* Display the specified resource.
*/
public function show(SpatialPlanning $spatialPlanning): SpatialPlanning
{
return $spatialPlanning;
}
/**
* Update the specified resource in storage.
*/
public function update(SpatialPlanningRequest $request, SpatialPlanning $spatialPlanning): SpatialPlanning
{
info($request);
$data = $request->validated();
info($data);
$spatialPlanning->update($data);
return $spatialPlanning;
}
public function destroy(SpatialPlanning $spatialPlanning): Response
{
$spatialPlanning->delete();
return response()->noContent();
}
public function downloadExcelSpatialPlanning()
{
$filePath = public_path('templates/template_spatial_planning.xlsx');
info(sprintf("File Path: %s | Exists: %s", $filePath, file_exists($filePath) ? 'Yes' : 'No'));
// Cek apakah file ada
if (!file_exists($filePath)) {
return response()-> json(['message' => 'File tidak ditemukan!'], Response::HTTP_NOT_FOUND);
}
// Return file to download
return response()->download($filePath);
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Resources\TaskAssignmentsResource;
use App\Models\TaskAssignment;
use Illuminate\Http\Request;
class TaskAssignmentsController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request, $uuid)
{
try{
$query = TaskAssignment::query()
->where('pbg_task_uid', $uuid)
->orderBy('id', 'desc');
if ($request->filled('search')) {
$query->where('name', 'like', "%{$request->get('search')}%")
->orWhere('email', 'like', "%{$request->get('search')}%");
}
return TaskAssignmentsResource::collection($query->paginate(config('app.paginate_per_page', 50)));
}catch(\Exception $exception){
return response()->json(['message' => $exception->getMessage()], 500);
}
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}

View File

@@ -0,0 +1,169 @@
<?php
namespace App\Http\Controllers\Api;
use App\Models\Tourism;
use Illuminate\Http\Request;
use App\Http\Requests\TourismRequest;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use App\Http\Resources\TourismResource;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Facades\Excel;
use App\Imports\TourismImport;
use Illuminate\Support\Facades\Storage;
class TourismController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$perPage = $request->input('per_page', 15);
$search = $request->input('search', '');
$query = Tourism::query();
if ($search) {
$query->where(function ($q) use ($search) {
$q->where('business_name', 'like', "%$search%")
->orWhere('project_name', 'like', "%$search%")
->orWhere('business_address', 'like', "%$search%");
});
}
$tourisms = $query->paginate($perPage);
$tourisms->getCollection()->transform(function ($tourisms) {
$village = DB::table('villages')->where('village_code', $tourisms->village_code)->first();
$tourisms->village_name = $village ? $village->village_name : null;
$district = DB::table('districts')->where('district_code', $tourisms->district_code)->first();
$tourisms->district_name = $district ? $district->district_name : null;
return $tourisms;
});
$start = ($tourisms->currentPage()-1) * $perPage + 1;
$data = $tourisms->map(function ($item, $index) use ($start) {
return array_merge($item->toArray(), ['no' => $start + $index]);
});
return response()->json([
'data' => $data,
'meta' => [
'total' => $tourisms->total(),
'per_page' => $tourisms->perPage(),
'current_page' => $tourisms->currentPage(),
'last_page'=>$tourisms->lastPage(),
]
]);
}
/**
* Store a newly created resource in storage.
*/
public function store(TourismRequest $request): Tourism
{
$data = $request->validated();
$district_code = DB::table('districts')->where('district_name', $data['district_name'])->value('district_code');
$village_code = DB::table('villages')->where('village_name', $data['village_name'])->where('district_code', $district_code)->value('village_code');
$data['district_code'] = $district_code;
$data['village_code'] = $village_code;
return Tourism::create($data);
}
/**
* Import advertisements from Excel
*/
public function importFromFile(Request $request)
{
//Validasi file
$validator = Validator::make($request->all(), [
'file' => 'required|mimes:xlsx, xls|max:10240'
]);
if ($validator->fails()) {
return response()->json([
'message'=>'File validation failed.',
'errors'=>$validator->errors()
], 400);
}
try {
$file = $request->file('file');
Excel::import(new TourismImport, $file);
return response()->json([
'message'=>'File uploaded and imported successfully!'
], 200);
} catch (\Exception $e) {
return response()->json([
'message'=>'Error during file import.',
'error'=>$e->getMessage()
], 500);
}
}
public function getAllLocation()
{
$locations = Tourism::whereNotNull('longitude')
->whereNotNull('latitude')
->select('project_name', 'longitude', 'latitude')
->get();
return response()->json([
'data' => $locations
]);
}
/**
* Display the specified resource.
*/
public function show(Tourism $tourism): Tourism
{
return $tourism;
}
/**
* Update the specified resource in storage.
*/
public function update(TourismRequest $request, Tourism $tourism): Tourism
{
$data = $request->validated();
// Cari district_code berdasarkan district_name
$district_code = DB::table('districts')->where('district_name', $data['district_name'])->value('district_code');
// Cari village_code berdasarkan village_name
$village_code = DB::table('villages')->where('village_name', $data['village_name'])->where('district_code', $district_code)->value('village_code');
// Tambahkan village_code dan district_code ke data
$data['village_code'] = $village_code;
$data['district_code'] = $district_code;
$tourism->update($data);
return $tourism;
}
public function destroy(Tourism $tourism): Response
{
$tourism->delete();
return response()->noContent();
}
public function downloadExcelTourism()
{
$filePath = public_path('templates/template_pariwisata.xlsx');
info(sprintf("File Path: %s | Exists: %s", $filePath, file_exists($filePath) ? 'Yes' : 'No'));
// Cek apakah file ada
if (!file_exists($filePath)) {
return response()-> json(['message' => 'File tidak ditemukan!'], Response::HTTP_NOT_FOUND);
}
// Return file to download
return response()->download($filePath);
}
}

View File

@@ -0,0 +1,206 @@
<?php
namespace App\Http\Controllers\Api;
use App\Models\Umkm;
use Illuminate\Http\Request;
use App\Http\Requests\UmkmRequest;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use App\Http\Resources\UmkmResource;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Facades\Excel;
use App\Imports\UmkmImport;
use Illuminate\Support\Facades\Storage;
class UmkmController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
info($request);
$perPage = $request->input('per_page', 15);
$search = $request->input('search', '');
$query = Umkm::query();
if ($search) {
$query->where(function ($q) use ($search) {
$q->where('business_name', 'like', "%$search%")
->orWhere('business_address', 'like', "%$search%")
->orWhere('business_desc', 'like', "%$search%")
->orWhere('business_id_number', 'like', "%$search%")
->orWhere('owner_id', 'like', "%$search%")
->orWhere('owner_name', 'like', "%$search%");
});
}
$umkm = $query->paginate($perPage);
$umkm->getCollection()->transform(function ($umkm) {
$village = DB::table('villages')->where('village_code', $umkm->village_code)->first();
$umkm->village_name = $village ? $village->village_name : null;
$district = DB::table('districts')->where('district_code', $umkm->district_code)->first();
$umkm->district_name = $district ? $district->district_name : null;
$business_scale = DB::table('business_scale')->where('id', $umkm->business_scale_id)->first();
$umkm->business_scale = $business_scale ? $business_scale->business_scale : null;
$permit_status = DB::table('permit_status')->where('id', $umkm->permit_status_id)->first();
$umkm->permit_status = $permit_status ? $permit_status->permit_status : null;
$business_form = DB::table('business_form')->where('id', $umkm->business_form_id)->first();
$umkm->business_form = $business_form ? $business_form->business_form : null;
return $umkm;
});
$start = ($umkm->currentPage()-1) * $perPage + 1;
$data = $umkm->map(function ($item, $index) use ($start) {
return array_merge($item->toArray(), ['no' => $start + $index]);
});
return response()->json([
'data' => $data,
'meta' => [
'total' => $umkm->total(),
'per_page' => $umkm->perPage(),
'current_page' => $umkm->currentPage(),
'last_page' => $umkm->lastPage(),
]
]);
}
/**
* Store a newly created resource in storage.
*/
public function store(UmkmRequest $request): Umkm
{
info($request);
$data = $request->validated();
// Cari kode berdasarkan nama
$district_code = DB::table('districts')->where('district_name', $data['district_name'])->value('district_code');
$village_code = DB::table('villages')->where('village_name', $data['village_name'])->where('district_code', $district_code)->value('village_code');
$business_scale_id = DB::table('business_scale')->where('id', $data['business_scale_id'])->value('id');
$permit_status_id = DB::table('permit_status')->where('id', $data['permit_status_id'])->value('id');
$business_form_id = DB::table('business_form')->where('id', $data['business_form_id'])->value('id');
info($business_scale_id);
// Update data dengan kode yang ditemukan
$data['village_code'] = $village_code;
$data['district_code'] = $district_code;
$data['land_area'] = (double) $request['land_area'];
$data['business_scale_id'] = (int) $business_scale_id;
$data['permit_status_id'] = (int) $permit_status_id;
$data['business_form_id'] = (int) $business_form_id;
info($data);
// Simpan ke database
return Umkm::create($data);
}
/**
* Import advertisements from Excel or CSV.
*/
public function importFromFile(Request $request)
{
// Validasi file
$validator = Validator::make($request->all(), [
'file' => 'required|mimes:xlsx, xls|max:10240',
]);
if ($validator->fails()) {
return response()->json([
'message' => 'File validation failed.',
'errors' => $validator->errors()
], 400);
}
try {
// Ambil file dari request
$file = $request->file('file');
// Menggunakan Laravel Excel untuk mengimpor file
Excel::import(new UmkmImport, $file);
// Jika sukses, kembalikan response sukses
return response()->json([
'message' => 'File uploaded and imported successfully!'
], 200);
} catch (\Exception $e) {
return response()->json([
'message' => 'Error during file import.',
'error' => $e->getMessage()
], 500);
}
}
/**
* Display the specified resource.
*/
public function show(Umkm $umkm): Umkm
{
return $umkm;
}
/**
* Update the specified resource in storage.
*/
public function update(UmkmRequest $request, Umkm $umkm): Umkm
{
info($request);
$data = $request->validated();
// Cari district_code berdasarkan district_name
$district_code = DB::table('districts')->where('district_name', $data['district_name'])->value('district_code');
// Cari village_code berdasarkan village_name
$village_code = DB::table('villages')->where('village_name', $data['village_name'])->where('district_code', $district_code)->value('village_code');
$business_scale_id = DB::table('business_scale')->where('id', $data['business_scale_id'])->value('id');
$permit_status_id = DB::table('permit_status')->where('id', $data['permit_status_id'])->value('id');
$business_form_id = DB::table('business_form')->where('id', $data['business_form_id'])->value('id');
// Tambahkan village_code dan district_code ke data
$data['village_code'] = $village_code;
$data['district_code'] = $district_code;
$data['land_area'] = (double) $request['land_area'];
$data['business_scale_id'] = (int) $business_scale_id;
$data['permit_status_id'] = (int) $permit_status_id;
$data['business_form_id'] = (int) $business_form_id;
// Log data setelah transformasi
info($data);
$umkm->update($data);
return $umkm;
}
public function destroy(Umkm $umkm): Response
{
$umkm->delete();
return response()->noContent();
}
public function downloadExcelUmkm()
{
$filePath = public_path('templates/template_umkm.xlsx');
// Cek apakah file ada
if (!file_exists($filePath)) {
return response()-> json(['message' => 'File tidak ditemukan!'], Response::HTTP_NOT_FOUND);
}
// Return file to download
return response()->download($filePath);
}
}

View File

@@ -4,11 +4,14 @@ namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\LoginRequest;
use App\Http\Requests\UsersRequest;
use App\Http\Resources\UserResource;
use App\Models\User;
use App\Traits\GlobalApiResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class UsersController extends Controller
{
@@ -27,12 +30,72 @@ class UsersController extends Controller
public function index(Request $request){
$query = User::query();
if($request->has('search') && !empty($request->get("search"))){
$query->where('name', 'LIKE', '%'.$request->get('search').'%');
$query->where('name', 'LIKE', '%'.$request->get('search').'%')
->orWhere('email', 'LIKE', '%'.$request->get('search').'%');
}
return UserResource::collection($query->paginate());
return UserResource::collection($query->paginate(config('app.paginate_per_page', 50)));
}
public function logout(Request $request){
$request->user()->tokens()->delete();
return response()->json(['message' => 'logged out successfully']);
}
public function store(UsersRequest $request){
$validate_data = $request->validated();
DB::beginTransaction();
try{
$user = User::create([
'name' => $validate_data['name'],
'email' => $validate_data['email'],
'password' => Hash::make($validate_data['password']),
'firstname' => $validate_data['firstname'],
'lastname' => $validate_data['lastname'],
'position' => $validate_data['position'],
]);
$user->roles()->attach((int) $validate_data['role_id']);
DB::commit();
return response()->json(['message' => 'Successfully created'],201);
}catch(\Exception $e){
DB::rollBack();
return response()->json(['message' => $e->getMessage()],500);
};
}
public function update(UsersRequest $request, $id){
try{
$validate_data = $request->validated();
$user = User::findOrFail($id);
DB::beginTransaction();
$user->update([
'name' => $validate_data['name'],
'email' => $validate_data['email'],
'firstname' => $validate_data['firstname'],
'lastname' => $validate_data['lastname'],
'position' => $validate_data['position']
]);
$user->roles()->sync($request->role_id);
DB::commit();
return response()->json(['message' => 'Successfully updated'], 200);
}catch(\Exception $e){
DB::rollBack();
return response()->json(['message' => $e->getMessage()],500);
}
}
public function destroy($id){
try{
$user = User::findOrFail($id);
DB::beginTransaction();
$user->delete();
DB::commit();
return response()->json(['message' => 'Successfully deleted'], 200);
}catch(\Exception $e){
Log::error('Failed to delete user: '. $e->getMessage());
return response()->json(['message' => 'Failed to delete user'],500);
}
}
}

View File

@@ -0,0 +1,65 @@
<?php
namespace App\Http\Controllers\Approval;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class ApprovalController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
return view('approval.index');
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}

View File

@@ -36,15 +36,68 @@ class AuthenticatedSessionController extends Controller
// Ambil user yang sedang login
$user = Auth::user();
// Buat token untuk API
$token = $user->createToken(env('APP_KEY'))->plainTextToken;
// Hapus token lama jika ada
$user->tokens()->delete();
// Simpan token di session (bisa digunakan di JavaScript)
// Buat token untuk API dengan scope dan expiration
$tokenName = config('app.name', 'Laravel') . '-' . $user->id . '-' . time();
// Token dengan scope (opsional)
$token = $user->createToken($tokenName, ['*'], now()->addDays(30))->plainTextToken;
// Simpan token di session untuk digunakan di frontend
session(['api_token' => $token]);
return redirect()->intended(RouteServiceProvider::HOME);
}
/**
* Generate API token for authenticated user
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function generateApiToken(Request $request)
{
$user = Auth::user();
if (!$user) {
return response()->json(['error' => 'Unauthorized'], 401);
}
// Delete existing tokens
$user->tokens()->delete();
// Generate new token
$tokenName = config('app.name', 'Laravel') . '-' . $user->id . '-' . time();
$token = $user->createToken($tokenName, ['*'], now()->addDays(30))->plainTextToken;
return response()->json([
'token' => $token,
'token_type' => 'Bearer',
'expires_in' => 30 * 24 * 60 * 60, // 30 days in seconds
]);
}
/**
* Revoke API token for authenticated user
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function revokeApiToken(Request $request)
{
$user = Auth::user();
if (!$user) {
return response()->json(['error' => 'Unauthorized'], 401);
}
$user->tokens()->delete();
return response()->json(['message' => 'All tokens revoked successfully']);
}
/**
* Destroy an authenticated session.
*

View File

View File

View File

0
app/Http/Controllers/Auth/NewPasswordController.php Executable file → Normal file
View File

View File

0
app/Http/Controllers/Auth/RegisteredUserController.php Executable file → Normal file
View File

0
app/Http/Controllers/Auth/VerifyEmailController.php Executable file → Normal file
View File

View File

@@ -0,0 +1,48 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class BigdataResumesController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
return view('bigdata-resumes.index');
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace App\Http\Controllers;
use App\Models\BusinessOrIndustry;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
class BusinessOrIndustriesController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$menuId = $request->query('menu_id') ?? $request->input('menu_id');
$permissions = $this->permissions[$menuId]?? []; // Avoid undefined index error
$creator = $permissions['allow_create'] ?? 0;
$updater = $permissions['allow_update'] ?? 0;
$destroyer = $permissions['allow_destroy'] ?? 0;
return view('business-industries.index', compact('creator', 'updater', 'destroyer','menuId'));
}
/**
* Show the form for creating a new resource.
*/
public function create(Request $request)
{
$menuId = $request->query('menu_id') ?? $request->input('menu_id');
return view("business-industries.create", compact('menuId'));
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id, Request $request)
{
$menuId = $request->query('menu_id') ?? $request->input('menu_id');
$data = BusinessOrIndustry::findOrFail($id);
return view('business-industries.edit', compact('data', 'menuId'));
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace App\Http\Controllers\Chatbot;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class ChatbotController extends Controller
{
/**
* Displya a listing of the resource
*/
public function index()
{
return view('chatbot.index');
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace App\Http\Controllers\ChatbotPimpinan;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class ChatbotPimpinanController extends Controller
{
/**
* Display a listing of the resource
*/
public function index()
{
return view('chatbot-pimpinan.index');
}
}

49
app/Http/Controllers/Controller.php Executable file → Normal file
View File

@@ -2,7 +2,54 @@
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Auth;
abstract class Controller
{
//
protected array $permissions = [];
public function __construct()
{
if (!Auth::check()) {
return;
}
$this->setUserPermissions();
}
protected function setUserPermissions()
{
$user = Auth::user();
if (!$user) {
return;
}
$menus = $user->roles()
->with(['menus' => function ($query) {
$query->select('menus.id', 'menus.name')
->withPivot(['allow_show' ,'allow_create', 'allow_update', 'allow_destroy']);
}])
->get()
->pluck('menus')
->flatten()
->unique('id');
// Store permissions in an associative array
foreach ($menus as $menu) {
$this->permissions[$menu->id] = [
'allow_show' => $menu->pivot->allow_show ?? 0,
'allow_create' => $menu->pivot->allow_create ?? 0,
'allow_update' => $menu->pivot->allow_update ?? 0,
'allow_destroy' => $menu->pivot->allow_destroy ?? 0,
];
}
// Share permissions globally in views
view()->share('permissions', $this->permissions);
}
public function getPermissions()
{
return $this->permissions;
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace App\Http\Controllers;
use App\Models\Customer;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
class CustomersController extends Controller
{
public function index(Request $request)
{
$menuId = $request->query('menu_id') ?? $request->input('menu_id');
$permissions = $this->permissions[$menuId]?? []; // Avoid undefined index error
$creator = $permissions['allow_create'] ?? 0;
$updater = $permissions['allow_update'] ?? 0;
$destroyer = $permissions['allow_destroy'] ?? 0;
return view('customers.index', compact('creator', 'updater', 'destroyer', 'menuId'));
}
public function create(Request $request)
{
$menuId = $request->query('menu_id');
return view('customers.create', compact('menuId'));
}
public function edit(Request $request, string $id)
{
$data = Customer::findOrFail($id);
$menuId = $request->query('menu_id');
return view('customers.edit', compact('data', 'menuId'));
}
public function upload(Request $request){
$menuId = $request->query('menu_id');
return view('customers.upload', compact('menuId'));
}
}

View File

@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Dashboards;
use App\Http\Controllers\Controller;
use App\Models\ImportDatasource;
use App\Models\Menu;
use Illuminate\Http\Request;
class BigDataController extends Controller
@@ -12,10 +13,21 @@ class BigDataController extends Controller
$latest_import_datasource = ImportDatasource::latest()->first();
$latest_created = $latest_import_datasource ?
$latest_import_datasource->created_at->format("j F Y H:i:s") : null;
return view('dashboards.bigdata', compact('latest_created'));
$menus = Menu::all();
return view('dashboards.bigdata', compact('latest_created', 'menus'));
}
public function pbg(){
return view('index');
public function pbg()
{
return view('dashboards.pbg');
}
public function leader()
{
$latest_import_datasource = ImportDatasource::latest()->first();
$latest_created = $latest_import_datasource ?
$latest_import_datasource->created_at->format("j F Y H:i:s") : null;
$menus = Menu::all();
return view('dashboards.leader', compact('latest_created', 'menus'));
}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace App\Http\Controllers\Dashboards;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class LackOfPotentialController extends Controller
{
public function lack_of_potential(){
return view('dashboards.lack_of_potential');
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace App\Http\Controllers\Dashboards;
use App\Http\Controllers\Controller;
use App\Models\Menu;
use Illuminate\Http\Request;
class PotentialsController extends Controller
{
public function inside_system(){
$menus = Menu::all();
return view('dashboards.potentials.inside_system', compact('menus'));
}
public function outside_system(){
return view('dashboards.potentials.outside_system');
}
}

View File

@@ -6,15 +6,23 @@ use App\Http\Controllers\Controller;
use App\Models\Advertisement;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
class AdvertisementController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
public function index(Request $request)
{
return view('data.advertisements.index');
$menuId = $request->query('menu_id', 0);
$permissions = $this->permissions[$menuId] ?? []; // Avoid undefined index error
$creator = $permissions['allow_create'] ?? 0;
$updater = $permissions['allow_update'] ?? 0;
$destroyer = $permissions['allow_destroy'] ?? 0;
return view('data.advertisements.index', compact('creator', 'updater', 'destroyer','menuId'));
}
/**
@@ -29,8 +37,9 @@ class AdvertisementController extends Controller
/**
* Show the form for creating a new resource.
*/
public function create()
public function create(Request $request)
{
$menuId = $request->query('menu_id', 0);
$title = 'Advertisement';
$subtitle = 'Create Data';
@@ -47,14 +56,15 @@ class AdvertisementController extends Controller
// $route = 'advertisements.create';
// info("AdvertisementController@edit diakses dengan ID: $title");
return view('data.advertisements.form', compact('title', 'subtitle', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions'));
return view('data.advertisements.form', compact('title', 'subtitle', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions','menuId'));
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
public function edit(Request $request, $id)
{
$menuId = $request->query('menu_id', 0);
info("AdvertisementController@edit diakses dengan ID: $id");
$title = 'Advertisement';
$subtitle = 'Update Data';
@@ -62,7 +72,7 @@ class AdvertisementController extends Controller
// Pastikan model ditemukan
if (!$modelInstance) {
info("AdvertisementController@edit: Model tidak ditemukan.");
return redirect()->route('advertisements.index')->with('error', 'Advertisement not found');
return redirect()->route('web.advertisements.index')->with('error', 'Advertisement not found');
}
// Mengambil dan memetakan village_name dan district_name
@@ -86,7 +96,7 @@ class AdvertisementController extends Controller
// $route = 'advertisements.update'; // Menggunakan route update untuk form edit
// info("AdvertisementController@edit diakses dengan route: $route");
return view('data.advertisements.form', compact('title', 'subtitle', 'modelInstance', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions'));
return view('data.advertisements.form', compact('title', 'subtitle', 'modelInstance', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions', 'menuId'));
}
private function getFields()

View File

@@ -0,0 +1,36 @@
<?php
namespace App\Http\Controllers\Data;
use App\Http\Controllers\Controller;
use App\Models\PbgTaskGoogleSheet;
use Illuminate\Http\Request;
class GoogleSheetsController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$menu_id = $request->query('menu_id');
$user_menu_permission = $this->permissions[$menu_id];
return view('data.google-sheet.index', compact('user_menu_permission'));
}
public function create()
{
return view('data.google-sheet.create');
}
public function show(string $id)
{
$data = PbgTaskGoogleSheet::find($id);
return view('data.google-sheet.show', compact('data'));
}
public function edit(string $id)
{
return view('data.google-sheet.edit');
}
}

View File

@@ -0,0 +1,103 @@
<?php
namespace App\Http\Controllers\Data;
use App\Http\Controllers\Controller;
use App\Models\SpatialPlanning;
use Illuminate\Http\Request;
class SpatialPlanningController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$menuId = $request->query('menu_id', 0);
$permissions = $this->permissions[$menuId] ?? []; // Avoid undefined index error
$creator = $permissions['allow_create'] ?? 0;
$updater = $permissions['allow_update'] ?? 0;
$destroyer = $permissions['allow_destroy'] ?? 0;
return view('data.spatialPlannings.index', compact('creator', 'updater', 'destroyer','menuId'));
}
/**
* show the form for creating a new resource.
*/
public function bulkCreate(Request $request)
{
$menuId = $request->query('menu_id', 0);
return view('data.spatialPlannings.form-upload', compact('menuId'));
}
/**
* Show the form for creating a new resource.
*/
public function create(Request $request)
{
$menuId = $request->query('menu_id', 0);
$title = 'Rencana Tata Ruang';
$subtitle = "Create Data";
// Mengambil data untuk dropdown
$dropdownOptions = [];
$fields = $this->getFields();
$fieldTypes = $this->getFieldTypes();
$apiUrl = url('/api/spatial-plannings');
return view('data.spatialPlannings.form', compact('title', 'subtitle', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions','menuId'));
}
/**
* Show the form for editing the specified resource.
*/
public function edit(Request $request,string $id)
{
$menuId = $request->query('menu_id', 0);
$title = 'Rencana Tata Ruang';
$subtitle = 'Update Data';
$modelInstance = SpatialPlanning::find($id);
// Pastikan model ditemukan
if (!$modelInstance) {
return redirect()->route('spatialPlanning.index') ->with('error', 'Rencana tata ruang tidak ditemukan');
}
$dropdownOptions = [];
$fields = $this->getFields();
$fieldTypes = $this->getFieldTypes();
$apiUrl = url('/api/spatial-plannings');
return view('data.spatialPlannings.form', compact('title', 'subtitle', 'modelInstance', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions','menuId'));
}
private function getFields()
{
return [
"name"=> "Nama",
"kbli"=> "KBLI",
"activities"=> "Kegiatan",
"area"=> "Luas (m2)",
"location"=> "Lokasi",
"number"=> "Nomor",
"date"=> "Tanggal",
];
}
private function getFieldTypes()
{
return [
"name"=> "text",
"kbli"=> "text",
"activities"=> "text",
"area"=> "text",
"location"=> "text",
"number"=> "text",
"date"=> "date",
];
}
}

View File

@@ -0,0 +1,155 @@
<?php
namespace App\Http\Controllers\Data;
use App\Http\Controllers\Controller;
use App\Models\Tourism;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
class TourismController extends Controller
{
/**
* Display a listing of the resource
*/
public function index(Request $request)
{
$menuId = $request->query('menu_id', 0);
$permissions = $this->permissions[$menuId] ?? []; // Avoid undefined index error
$creator = $permissions['allow_create'] ?? 0;
$updater = $permissions['allow_update'] ?? 0;
$destroyer = $permissions['allow_destroy'] ?? 0;
return view('data.tourisms.index', compact('creator', 'updater', 'destroyer', 'menuId'));
}
/**
* show the form for creating a new rsource.
*/
public function bulkCreate(Request $request)
{
$menuId = $request->query('menu_id', 0);
return view('data.tourisms.form-upload', compact('menuId'));
}
/**
* Show th form for creating a new resource
*/
public function create(Request $request)
{
$menuId = $request->query('menu_id', 0);
$title = 'Pariwisata';
$subtitle = 'Create Data';
// Mengambil data untuk dropdown
$dropdownOptions = [
'village_name' => DB::table('villages')->orderBy('village_name')->pluck('village_name', 'village_code'),
'district_name' => DB::table('districts')->orderBy('district_name')->pluck('district_name', 'district_code')
];
$fields = $this->getFields();
$fieldTypes = $this->getFieldTypes();
$apiUrl = url('/api/tourisms');
return view('data.tourisms.form', compact('title', 'subtitle', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions', 'menuId'));
}
/**
* show the form for editing the specified resource.
*/
public function edit(Request $request, $id)
{
$menuId = $request->query('menu_id', 0);
$title = 'Pariwisata';
$subtitle = 'Update Data';
$modelInstance = Tourism::find($id);
// Pastikan model ditemukan
if (!$modelInstance) {
return redirect()->route('web-tourisms.index') ->with('error', 'Pariwisata tidak ditemukan');
}
// Mengambil dan memetakan village_name dan district_name
$village = DB::table('villages')->where('village_code', $modelInstance->village_code)->first();
$modelInstance->village_name = $village ? $village->village_name : null;
$district = DB::table('districts')->where('district_code', $modelInstance->district_code)->first();
$modelInstance->district_name = $district ? $district->district_name : null;
$dropdownOptions = [
'village_name' => DB::table('villages')->orderBy('village_name')->pluck('village_name', 'village_code'),
'district_name' => DB::table('districts')->orderBy('district_name')->pluck('district_name', 'district_code')
];
$fields = $this->getFields();
$fieldTypes = $this->getFieldTypes();
$apiUrl = url('/api/tourisms');
return view('data.tourisms.form', compact('title', 'subtitle', 'modelInstance', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions', 'menuId'));
}
private function getFields()
{
return [
"project_id" => "ID Proyek",
"project_type_id" => "Jenis Proyek",
"nib" => "NIB",
"business_name" => "Nama Perusahaan",
"oss_publication_date" => "Tanggal Terbit OSS",
"investment_status_description" => "Uraian Status Penanaman Modal",
"business_form" => "Uraian Jenis Perusahaan",
"project_risk" => "Risiko Proyek",
"project_name" => "Nama Proyek",
"business_scale" => "Uraian Skala Usaha",
"business_address" => "Alamat Usaha",
"district_name" => "Kecamatan",
"village_name" => "Desa",
"longitude" => "Longitude",
"latitude" => "Latitude",
"project_submission_date" => "Tanggal Pengajuan Project",
"kbli" => "KBLI",
"kbli_title" => "Judul KBLI",
"supervisory_sector" => "Sektor Pembina",
"user_name" => "Nama User",
"email" => "Email",
"contact" => "Kontak",
"land_area_in_m2" => "Luas Tanah (m2)",
"investment_amount" => "Jumlah Investasi",
"tki" => "TKI",
];
}
private function getFieldTypes()
{
return [
"project_id" => "text",
"project_type_id" => "text",
"nib" => "text",
"business_name" => "text",
"oss_publication_date" => "date",
"investment_status_description" => "text",
"business_form" => "text",
"project_risk" => "text",
"project_name" => "text",
"business_scale" => "text",
"business_address" => "text",
"district_name" => "combobox",
"village_name" => "combobox",
"longitude" => "text",
"latitude" => "text",
"project_submission_date" => "date",
"kbli" => "text",
"kbli_title" => "text",
"supervisory_sector" => "text",
"user_name" => "text",
"email" => "text",
"contact" => "text",
"land_area_in_m2" => "text",
"investment_amount" => "text",
"tki" => "text",
];
}
}

View File

@@ -0,0 +1,159 @@
<?php
namespace App\Http\Controllers\Data;
use App\Http\Controllers\Controller;
use App\Models\Umkm;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
class UmkmController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$menuId = $request->query('menu_id', 0);
$permissions = $this->permissions[$menuId] ?? []; // Avoid undefined index error
$creator = $permissions['allow_create'] ?? 0;
$updater = $permissions['allow_update'] ?? 0;
$destroyer = $permissions['allow_destroy'] ?? 0;
return view('data.umkm.index', compact('creator', 'updater', 'destroyer', 'menuId'));
}
/**
* Show the form for creating a new resource.
*/
public function bulkCreate(Request $request)
{
$menuId = $request->query('menu_id', 0);
return view('data.umkm.form-upload', compact('menuId'));
}
/**
* Show the form for creating a new resource.
*/
public function create(Request $request)
{
$menuId = $request->query('menu_id', 0);
$title = 'UMKM';
$subtitle = 'Create Data';
// Mengambil data untuk dropdown
$dropdownOptions = [
'village_name' => DB::table('villages')->orderBy('village_name')->pluck('village_name', 'village_code'),
'district_name' => DB::table('districts')->orderBy('district_name')->pluck('district_name', 'district_code'),
'business_scale_id' => DB::table('business_scale')->orderBy('business_scale')->pluck('business_scale', 'id'),
'permit_status_id' => DB::table('permit_status')->orderBy('permit_status')->pluck('permit_status', 'id'),
'business_form_id' => DB::table('business_form')->orderBy('business_form')->pluck('business_form', 'id')
];
$fields = $this->getFields();
$fieldTypes = $this->getFieldTypes();
$apiUrl = url('/api/umkm');
return view('data.umkm.form', compact('title', 'subtitle', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions','menuId'));
}
/**
* Show the form for editing the specified resource.
*/
public function edit(Request $request,$id)
{
$menuId = $request->query('menu_id', 0);
$title = 'UMKM';
$subtitle = 'Update Data';
$modelInstance = Umkm::find($id);
// Pastikan model ditemukan
if (!$modelInstance) {
return redirect()->route('web-umkm.index')->with('error', 'Umkm not found');
}
// Mengambil dan memetakan village_name dan district_name
$village = DB::table('villages')->where('village_code', $modelInstance->village_code)->first();
$modelInstance->village_name = $village ? $village->village_name : null;
$district = DB::table('districts')->where('district_code', $modelInstance->district_code)->first();
$modelInstance->district_name = $district ? $district->district_name : null;
$business_scale = DB::table('business_scale')->where('id', $modelInstance->business_scale_id)->first();
$modelInstance->business_scale_id = $business_scale ? $business_scale->id : null;
$permit_status = DB::table('permit_status')->where('id', $modelInstance->permit_status_id)->first();
$modelInstance->permit_status_id = $permit_status ? $permit_status->id : null;
$business_form = DB::table('business_form')->where('id', $modelInstance->business_form_id)->first();
$modelInstance->business_form_id = $business_form ? $business_form->id : null;
// dd($modelInstance['business_form_id']);
// Mengambil data untuk dropdown
$dropdownOptions = [
'village_name' => DB::table('villages')->orderBy('village_name')->pluck('village_name', 'village_code'),
'district_name' => DB::table('districts')->orderBy('district_name')->pluck('district_name', 'district_code'),
'business_scale_id' => DB::table('business_scale')->orderBy('business_scale')->pluck('business_scale', 'id'),
'permit_status_id' => DB::table('permit_status')->orderBy('permit_status')->pluck('permit_status', 'id'),
'business_form_id' => DB::table('business_form')->orderBy('business_form')->pluck('business_form', 'id')
];
info("AdvertisementController@edit diakses dengan Model Instance: $modelInstance");
$fields = $this->getFields();
$fieldTypes = $this->getFieldTypes();
$apiUrl = url('/api/umkm');
// dd($modelInstance->business_form_id, $dropdownOptions['business_form']);
return view('data.umkm.form', compact('title', 'subtitle', 'modelInstance', 'fields', 'fieldTypes', 'apiUrl', 'dropdownOptions','menuId'));
}
private function getFields()
{
return [
"business_name" => "Nama Usaha",
"business_address" => "Alamat Usaha",
"business_desc" => "Deskripsi Usaha",
"business_contact" => "Kontak Usaha",
"business_id_number" => "NIB",
"business_scale_id" => "Skala Usaha",
"owner_id" => "NIK",
"owner_name" => "Nama Pemilik",
"owner_address" => "Alamat Pemilik",
"owner_contact" => "Kontak Pemilik",
"business_type" => "Jenis Usaha",
"district_name" => "Kecamatan",
"village_name" => "Desa",
"number_of_employee" => "Jumlah Karyawan",
"land_area" => "Luas Tanah",
"permit_status_id" => "Ijin Status",
"business_form_id" => "Bisnis Form",
"revenue" => "Omset"
];
}
private function getFieldTypes()
{
return [
"business_name" => "text",
"business_address" => "text",
"business_desc" => "textarea",
"business_contact" => "text",
"business_id_number" => "text",
"business_scale_id" => "select",
"owner_id" => "text",
"owner_name" => "text",
"owner_address" => "text",
"owner_contact" => "text",
"business_type" => "text",
"district_name" => "combobox",
"village_name" => "combobox",
"number_of_employee" => "text",
"land_area" => "text",
"permit_status_id" => "select",
"business_form_id" => "select",
"revenue" => "text"
];
}
}

View File

@@ -8,23 +8,31 @@ use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request as IndexRequest;
class DataSettingController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
public function index(IndexRequest $request)
{
return view("data-settings.index");
$menuId = $request->query('menu_id') ?? $request->input('menu_id');
$permissions = $this->permissions[$menuId]?? []; // Avoid undefined index error
$creator = $permissions['allow_create'] ?? 0;
$updater = $permissions['allow_update'] ?? 0;
$destroyer = $permissions['allow_destroy'] ?? 0;
return view("data-settings.index", compact('creator', 'updater', 'destroyer','menuId'));
}
/**
* Show the form for creating a new resource.
*/
public function create()
public function create(IndexRequest $request)
{
return view("data-settings.create");
$menuId = $request->query('menu_id') ?? $request->input('menu_id');
return view("data-settings.create", compact('menuId'));
}
/**
@@ -57,14 +65,15 @@ class DataSettingController extends Controller
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
public function edit(IndexRequest $request,string $id)
{
try{
$data = DataSetting::findOrFail($id);
$menuId = $request->query('menu_id') ?? $request->input('menu_id');
if(empty($data)){
return redirect()->route('data-settings.index')->with('error', 'Invalid id');
}
return view("data-settings.edit", compact("data"));
return view("data-settings.edit", compact("data", 'menuId'));
}catch(Exception $ex){
return redirect()->route("data-settings.index")->with("error", "Invalid id");
}

View File

@@ -0,0 +1,12 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class GoogleApisController extends Controller
{
public function index(){
return view('maps.google-api');
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class InvitationsController extends Controller
{
public function index(Request $request){
return view('invitations.index');
}
}

View File

@@ -3,6 +3,7 @@
namespace App\Http\Controllers\Master;
use App\Http\Controllers\Controller;
use App\Http\Requests\UsersRequest;
use App\Models\Role;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
@@ -12,6 +13,7 @@ use Illuminate\Support\Facades\Hash;
use App\Models\User;
use App\Traits\GlobalApiResponse;
use Illuminate\Auth\Events\Registered;
use Illuminate\Support\Facades\Auth;
class UsersController extends Controller
{
@@ -20,15 +22,22 @@ class UsersController extends Controller
$users = User::all();
return $this->resSuccess($users);
}
public function index(){
public function index(Request $request){
$menuId = $request->query('menu_id') ?? $request->input('menu_id');
$permissions = $this->permissions[$menuId]?? []; // Avoid undefined index error
$creator = $permissions['allow_create'] ?? 0;
$updater = $permissions['allow_update'] ?? 0;
$destroyer = $permissions['allow_destroy'] ?? 0;
$users = User::paginate();
return view('master.users.index', compact('users'));
return view('master.users.index', compact('users', 'creator', 'updater', 'destroyer','menuId'));
}
public function create(){
public function create(Request $request){
$menuId = $request->query('menu_id') ?? $request->input('menu_id');
$roles = Role::all();
return view('master.users.create', compact('roles'));
return view('master.users.create', compact('roles', 'menuId'));
}
public function store(Request $request){
public function store(UsersRequest $request){
$request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
@@ -39,6 +48,7 @@ class UsersController extends Controller
'role_id' => 'required|exists:roles,id'
]);
DB::beginTransaction();
try{
$user = User::create([
@@ -63,10 +73,11 @@ class UsersController extends Controller
$user = User::find($id);
return view('master.users.show', compact('user'));
}
public function edit($id){
public function edit(Request $request, $id){
$menuId = $request->query('menu_id') ?? $request->input('menu_id');
$user = User::find($id);
$roles = Role::all();
return view('master.users.edit', compact('user', 'roles'));
return view('master.users.edit', compact('user', 'roles', 'menuId'));
}
public function update(Request $request, $id){
$user = User::find($id);

View File

@@ -2,6 +2,7 @@
namespace App\Http\Controllers;
use App\Http\Requests\MenuRequest;
use App\Models\Menu;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
@@ -11,41 +12,46 @@ class MenusController extends Controller
/**
* Display a listing of the resource.
*/
public function index()
public function index(Request $request)
{
return view('menus.index');
$menuId = (int) $request->query('menu_id', 0);
$permissions = $this->permissions[$menuId] ?? []; // Avoid undefined index error
$creator = $permissions['allow_create'] ?? 0;
$updater = $permissions['allow_update'] ?? 0;
$destroyer = $permissions['allow_destroy'] ?? 0;
return view('menus.index', compact('creator', 'updater', 'destroyer', 'menuId'));
}
/**
* Show the form for creating a new resource.
*/
public function create()
public function create(Request $request)
{
$parent_menus = Menu::whereNull('parent_id')->get();
return view("menus.create", compact('parent_menus'));
$menuId = $request->query('menu_id'); // Get menu_id from request
$menu = Menu::with('children')->find($menuId); // Find the menu
// Get IDs of all child menus to exclude
$excludedIds = $menu ? $this->getChildMenuIds($menu) : [$menuId];
// Fetch only menus that have children and are not in the excluded list
$parent_menus = Menu::whereHas('children')
->whereNotIn('id', $excludedIds)
->get();
return view("menus.create", compact('parent_menus', 'menuId'));
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
public function store(MenuRequest $request)
{
try{
$request->validate([
'name' => 'required|string|max:255',
'url' => 'nullable|string|max:255',
'icon' => 'nullable|string|max:255',
'parent_id' => 'nullable|exists:menus,id', // Ensures it's either null or a valid menu ID
'sort_order' => 'required|integer',
]);
$validated_menu = $request->validated();
DB::beginTransaction();
Menu::create([
'name' => $request->name,
'url' => $request->url,
'icon' => $request->icon,
'parent_id' => $request->parent_id ?? null,
'sort_order' => $request->sort_order,
]);
Menu::create($validated_menu);
DB::commit();
return response()->json(['message' => 'Successfully created'], 200);
}catch(\Exception $e){
@@ -67,31 +73,28 @@ class MenusController extends Controller
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
public function edit(string $id, Request $request)
{
$menu = Menu::findOrFail($id);
$parent_menus = Menu::whereNull('parent_id')->where('id','!=',$id)->get();
return view("menus.edit", compact('menu','parent_menus'));
$menuId = $request->query('menu_id');
$menu = Menu::with('children')->find($id);
$excludedIds = $menu ? $this->getChildMenuIds($menu) : [$id];
$parent_menus = Menu::whereHas('children')
->whereNotIn('id', $excludedIds)
->get();
return view("menus.edit", compact('menu','parent_menus', 'menuId'));
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
public function update(MenuRequest $request, string $id)
{
try{
$validateData = $request->validate([
'name' => 'required',
'url'=> 'required',
'icon'=> 'nullable',
'parent_id' => 'nullable',
'sort_order' => 'required',
]);
$validate_menu = $request->validated();
$menu = Menu::findOrFail($id);
DB::beginTransaction();
$menu->update($validateData);
$menu->update($validate_menu);
DB::commit();
return response()->json(['message' => 'Successfully updated'], 200);
}catch(\Exception $e){
@@ -129,4 +132,15 @@ class MenusController extends Controller
$child->delete();
}
}
private function getChildMenuIds($menu)
{
$ids = [$menu->id]; // Start with current menu ID
foreach ($menu->children as $child) {
$ids = array_merge($ids, $this->getChildMenuIds($child)); // Recursively fetch children
}
return $ids;
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PaymentRecapsController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
return view('payment-recaps.index');
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace App\Http\Controllers;
use App\Models\PbgTask;
use App\Models\PbgTaskAttachment;
use Illuminate\Http\Request;
class PbgTaskAttachmentsController extends Controller
{
public function show(string $id, Request $request){
try{
$title = $request->get('type') == "berita-acara" ? "Berita Acara" : "Bukti Bayar";
$data = PbgTaskAttachment::findOrFail($id);
$pbg = PbgTask::findOrFail($data->pbg_task_id);
return view('pbg-task-attachment.show', compact('data', 'pbg', 'title'));
}catch(\Exception $e){
return view('pages.404');
}
}
}

View File

@@ -0,0 +1,87 @@
<?php
namespace App\Http\Controllers;
use App\Enums\PbgTaskApplicationTypes;
use App\Enums\PbgTaskStatus;
use App\Http\Resources\TaskAssignmentsResource;
use App\Models\PbgTask;
use App\Models\TaskAssignment;
use Illuminate\Http\Request;
class QuickSearchController extends Controller
{
public function index(){
return view("quick-search.index");
}
public function search_result(Request $request){
$keyword = $request->get("keyword");
return view('quick-search.result', compact('keyword'));
}
public function quick_search_datatable(Request $request)
{
try {
$query = PbgTask::orderBy('id', 'desc');
if ($request->filled('search')) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('name', 'LIKE', "%$search%")
->orWhere('registration_number', 'LIKE', "%$search%")
->orWhere('address', 'LIKE', "%$search%")
->orWhere('document_number', 'LIKE', "%$search%");
});
}
return response()->json($query->paginate());
} catch (\Throwable $e) {
\Log::error("Error fetching datatable data: " . $e->getMessage());
return response()->json([
'message' => 'Terjadi kesalahan saat mengambil data.',
'error' => $e->getMessage(),
], 500);
}
}
public function show($id)
{
try {
$data = PbgTask::with([
'pbg_task_retributions',
'pbg_task_index_integrations',
'pbg_task_retributions.pbg_task_prasarana'
])->findOrFail($id);
$statusOptions = PbgTaskStatus::getStatuses();
$applicationTypes = PbgTaskApplicationTypes::labels();
return view("quick-search.detail", compact("data", 'statusOptions', 'applicationTypes'));
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
\Log::warning("PbgTask with ID {$id} not found.");
return redirect()->route('quick-search.index')->with('error', 'Data tidak ditemukan.');
} catch (\Throwable $e) {
\Log::error("Error in QuickSearchController@show: " . $e->getMessage());
return response()->view('pages.404', [], 500); // Optional: create `resources/views/errors/500.blade.php`
}
}
public function task_assignments(Request $request, $uuid){
try{
$query = TaskAssignment::query()
->where('pbg_task_uid', $uuid)
->orderBy('id', 'desc');
if ($request->filled('search')) {
$query->where('name', 'like', "%{$request->get('search')}%")
->orWhere('email', 'like', "%{$request->get('search')}%");
}
return TaskAssignmentsResource::collection($query->paginate(config('app.paginate_per_page', 50)));
}catch(\Exception $exception){
return response()->json(['message' => $exception->getMessage()], 500);
}
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace App\Http\Controllers\Report;
use App\Http\Controllers\Controller;
use App\Models\Menu;
use Illuminate\Http\Request;
class GrowthReportsController extends Controller
{
public function index(){
return view('report.growth-report.index');
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\Report;
use App\Http\Controllers\Controller;
use App\Models\TourismBasedKBLI;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class ReportTourismController extends Controller
{
/**
* Display a listring of the resource
*/
public function index()
{
$tourismBasedKBLI = TourismBasedKBLI::all();
return view('report.tourisms.index', compact('tourismBasedKBLI'));
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ReportPaymentRecapsController extends Controller
{
public function index(Request $request){
return view('report-payment-recaps.index');
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ReportPbgPTSPController extends Controller
{
public function index(Request $request){
return view('report-pbg-ptsp.index');
}
}

View File

@@ -2,18 +2,37 @@
namespace App\Http\Controllers\RequestAssignment;
use App\Enums\PbgTaskApplicationTypes;
use App\Enums\PbgTaskFilterData;
use App\Http\Controllers\Controller;
use App\Models\PbgTask;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use App\Enums\PbgTaskStatus;
class PbgTaskController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
public function index(Request $request)
{
return view('pbg_task.index');
$menuId = $request->query('menu_id') ?? $request->input('menu_id');
$filter = $request->query('filter');
$permissions = $this->permissions[$menuId]?? []; // Avoid undefined index error
$creator = $permissions['allow_create'] ?? 0;
$updater = $permissions['allow_update'] ?? 0;
$destroyer = $permissions['allow_destroy'] ?? 0;
return view('pbg_task.index', [
'creator' => $creator,
'updater' => $updater,
'destroyer' => $destroyer,
'filter' => $filter,
'filterOptions' => PbgTaskFilterData::getAllOptions(),
]);
}
/**
@@ -38,7 +57,9 @@ class PbgTaskController extends Controller
public function show(string $id)
{
$data = PbgTask::with(['pbg_task_retributions','pbg_task_index_integrations', 'pbg_task_retributions.pbg_task_prasarana'])->findOrFail($id);
return view("pbg_task.show", compact("data"));
$statusOptions = PbgTaskStatus::getStatuses();
$applicationTypes = PbgTaskApplicationTypes::labels();
return view("pbg_task.show", compact("data", 'statusOptions', 'applicationTypes'));
}
/**

View File

@@ -2,6 +2,7 @@
namespace App\Http\Controllers;
use App\Http\Requests\RoleRequest;
use App\Models\Menu;
use App\Models\Role;
use App\Models\RoleMenu;
@@ -9,38 +10,43 @@ use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Auth;
class RolesController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
public function index(Request $request)
{
return view("roles.index");
$menuId = $request->query('menu_id') ?? $request->input('menu_id');
$permissions = $this->permissions[$menuId]?? []; // Avoid undefined index error
$creator = $permissions['allow_create'] ?? 0;
$updater = $permissions['allow_update'] ?? 0;
$destroyer = $permissions['allow_destroy'] ?? 0;
return view("roles.index", compact('creator', 'updater', 'destroyer', 'menuId'));
}
/**
* Show the form for creating a new resource.
*/
public function create()
public function create(Request $request)
{
return view("roles.create");
$menuId = $request->query('menu_id');
return view("roles.create", compact('menuId'));
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
public function store(RoleRequest $request)
{
try{
$request->validate([
"name" => "required|unique:roles,name",
"description" => "nullable",
]);
$validate_role = $request->validated();
DB::beginTransaction();
Role::create($request->all());
Role::create($validate_role);
DB::commit();
return response()->json(['message' => 'Role created successfully'], 201);
}
@@ -61,27 +67,24 @@ class RolesController extends Controller
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
public function edit(string $id, Request $request)
{
$menuId = $request->query('menu_id');
$role = Role::findOrFail($id);
return view("roles.edit", compact('role'));
return view("roles.edit", compact('role', 'menuId'));
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
public function update(RoleRequest $request, string $id)
{
try{
$validate_role = $request->validated();
$role = Role::findOrFail($id);
// Validate request data
$validatedData = $request->validate([
'name' => 'required|string|max:255|unique:roles,name,' . $id, // Ensure name is unique except for the current role
'description' => 'nullable|string|max:500',
]);
DB::beginTransaction();
$role->update($validatedData);
$role->update($validate_role);
DB::commit();
return response()->json(['message' => 'Role updated successfully'], 200);
}catch(\Exception $e){
@@ -97,7 +100,7 @@ class RolesController extends Controller
{
try{
DB::beginTransaction();
$deleted = Role::findOrFail($id)->delete();
Role::findOrFail($id)->delete();
DB::commit();
return response()->json(['success' => true, "message" => "Successfully deleted"]);
}catch(\Exception $e){
@@ -106,12 +109,13 @@ class RolesController extends Controller
}
}
public function menu_permission(string $role_id){
public function menu_permission(string $role_id, Request $request){
try{
$menuId = $request->query('menu_id');
$role = Role::findOrFail($role_id);
$menus = Menu::all();
$role_menus = RoleMenu::where('role_id', $role_id)->get() ?? collect();
return view('roles.role_menu', compact('role', 'menus', 'role_menus'));
return view('roles.role_menu', compact('role', 'menus', 'role_menus', 'menuId'));
}catch(\Exception $e){
return redirect()->back()->with("error", $e->getMessage());
}
@@ -119,8 +123,9 @@ class RolesController extends Controller
public function update_menu_permission(Request $request, string $role_id){
try{
$menuId = $request->query('menu_id');
$validateData = $request->validate([
"permissions" => "array",
"permissions" => "nullable|array",
"permissions.*.allow_show" => "nullable|boolean",
"permissions.*.allow_create" => "nullable|boolean",
"permissions.*.allow_update" => "nullable|boolean",
@@ -129,6 +134,13 @@ class RolesController extends Controller
$role = Role::find($role_id);
// Jika `permissions` tidak ada atau kosong, hapus semua permissions terkait
if (!isset($validateData['permissions']) || empty($validateData['permissions'])) {
$role->menus()->detach();
return redirect()->route("roles.index", ['menu_id' => $menuId])
->with('success', 'All menu permissions have been removed.');
}
$permissionsArray = [];
foreach ($validateData['permissions'] as $menu_id => $permission) {
$permissionsArray[$menu_id] = [
@@ -143,7 +155,7 @@ class RolesController extends Controller
// Sync will update existing records and insert new ones
$role->menus()->sync($permissionsArray);
return redirect()->route("role-menu.permission", $role_id)->with('success','Menu Permission updated successfully');
return redirect()->route("roles.index", ['menu_id' => $menuId])->with('success','Menu Permission updated successfully');
}catch(\Exception $e){
Log::error("Error updating role_menu:", ["error" => $e->getMessage()]);
return redirect()->route("role-menu.permission", $role_id)->with("error", $e->getMessage());

0
app/Http/Controllers/RoutingController.php Executable file → Normal file
View File

View File

@@ -6,6 +6,8 @@ use App\Http\Controllers\Controller;
use App\Services\ServiceSIMBG;
use Illuminate\Http\Request;
use Exception;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
class SyncronizeController extends Controller
{
protected $service_simbg;
@@ -13,16 +15,36 @@ class SyncronizeController extends Controller
$this->service_simbg = $service_simbg;
}
public function index(Request $request){
return view('settings.syncronize.index');
$menuId = $request->query('menu_id');
$user = Auth::user();
$userId = $user->id;
// Ambil role_id yang dimiliki user
$roleIds = DB::table('user_role')
->where('user_id', $userId)
->pluck('role_id');
// Ambil data akses berdasarkan role_id dan menu_id
$roleAccess = DB::table('role_menu')
->whereIn('role_id', $roleIds)
->where('menu_id', $menuId)
->first();
// Pastikan roleAccess tidak null sebelum mengakses properti
$creator = $roleAccess->allow_create ?? 0;
$updater = $roleAccess->allow_update ?? 0;
$destroyer = $roleAccess->allow_destroy ?? 0;
return view('settings.syncronize.index', compact('creator', 'updater', 'destroyer'));
}
public function syncPbgTask(){
$res = $this->service_simbg->syncTaskList();
$res = $this->service_simbg->syncTaskPBG();
return $res;
}
public function syncronizeTask(Request $request){
$res = $this->service_simbg->syncTaskList();
$res = $this->service_simbg->syncTaskPBG();
return redirect()->back()->with('success', 'Processing completed successfully');
}
@@ -33,7 +55,7 @@ class SyncronizeController extends Controller
public function syncIndexIntegration(Request $request, $uuid){
$token = $request->get('token');
$res = $this->service_simbg->syncIndexIntegration($uuid, $token);
$res = $this->service_simbg->syncIndexIntegration($uuid);
return $res;
}
@@ -42,4 +64,9 @@ class SyncronizeController extends Controller
$res = $this->service_simbg->syncTaskDetailSubmit($uuid, $token);
return $res;
}
public function syncTaskAssignments($uuid){
$res = $this->service_simbg->syncTaskAssignments($uuid);
return $res;
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class TpatptsController extends Controller
{
public function index()
{
return view('tpa-tpt.index');
}
public function create()
{
//
}
public function show(string $id)
{
//
}
public function edit(string $id)
{
//
}
}

View File

@@ -40,4 +40,40 @@ class AdvertisementRequest extends FormRequest
'contact' => 'required|string',
];
}
/**
* pesan error validasi
*/
public function messages(): array
{
return [
'no.required' => 'Nomor harus diisi.',
'business_name.required' => 'Nama usaha harus diisi.',
'business_name.string' => 'Nama usaha harus berupa teks.',
'npwpd.required' => 'NPWPD harus diisi.',
'npwpd.string' => 'NPWPD harus berupa teks.',
'advertisement_type.required' => 'Jenis reklame harus diisi.',
'advertisement_type.string' => 'Jenis reklame harus berupa teks.',
'advertisement_content.required' => 'Isi reklame harus diisi.',
'advertisement_content.string' => 'Isi reklame harus berupa teks.',
'business_address.required' => 'Alamat usaha harus diisi.',
'business_address.string' => 'Alamat usaha harus berupa teks.',
'advertisement_location.required' => 'Lokasi reklame harus diisi.',
'advertisement_location.string' => 'Lokasi reklame harus berupa teks.',
'village_name.required' => 'Nama desa harus diisi.',
'district_name.required' => 'Nama kecamatan harus diisi.',
'length.required' => 'Panjang harus diisi.',
'width.required' => 'Lebar harus diisi.',
'viewing_angle.required' => 'Sudut pandang harus diisi.',
'viewing_angle.string' => 'Sudut pandang harus berupa teks.',
'face.required' => 'Jumlah sisi harus diisi.',
'face.string' => 'Jumlah sisi harus berupa teks.',
'area.required' => 'Luas harus diisi.',
'area.string' => 'Luas harus berupa teks.',
'angle.required' => 'Sudut harus diisi.',
'angle.string' => 'Sudut harus berupa teks.',
'contact.required' => 'Kontak harus diisi.',
'contact.string' => 'Kontak harus berupa teks.',
];
}
}

0
app/Http/Requests/Auth/LoginRequest.php Executable file → Normal file
View File

View File

@@ -0,0 +1,39 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class BusinessIndustryRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'nama_kecamatan' => 'required|string|max:255',
'nama_kelurahan' => 'required|string|max:255',
'nop' => 'required|string|max:255|unique:business_or_industries,nop,' . $this->route('api_business_industry'),
'nama_wajib_pajak' => 'required|string|max:255',
'alamat_wajib_pajak' => 'nullable|string|max:255',
'alamat_objek_pajak' => 'required|string|max:255',
'luas_bumi' => 'required|numeric',
'luas_bangunan' => 'required|numeric',
'njop_bumi' => 'required|numeric',
'njop_bangunan' => 'required|numeric',
'ketetapan' => 'required|string|max:255',
'tahun_pajak' => 'required|integer|min:1900|max:' . date('Y'),
];
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CustomersRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'nomor_pelanggan' => ['required', 'string'],
'kota_pelayanan' => ['required', 'string'],
'nama' => ['required', 'string'],
'alamat' => ['required', 'string'],
'latitude' => ['required', 'numeric', 'between:-90,90'],
'longitude' => ['required', 'numeric', 'between:-180,180'],
];
}
}

View File

@@ -21,7 +21,7 @@ class DataSettingRequest extends FormRequest
*/
public function rules(): array
{
$id = $this->route('data_setting');
$id = $this->route('data_setting_id');
return [
"key" => "required|unique:data_settings,key," . $id,
"value" => "required",

View File

@@ -0,0 +1,28 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ExcelUploadRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
"file" => "required|file|mimes:xlsx,xls|max:102400"
];
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class MenuRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
$menuId = $this->route('menu_id'); // Get the menu ID if updating
return [
'name' => ['required', 'string', 'max:255', Rule::unique('menus', 'name')->ignore($menuId)],
'url' => ['nullable', 'string', 'max:255'],
'icon' => ['nullable', 'string', 'max:255'],
'parent_id' => ['nullable', 'exists:menus,id'],
'sort_order' => ['required', 'integer'],
];
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class RoleRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
$roleId = $this->route('role_id');
return [
'name' => 'required|string|max:255|unique:roles,name,' . ($roleId ?? 'NULL') . ',id',
'description' => 'nullable|string',
];
}
}

View File

@@ -0,0 +1,52 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class SpatialPlanningRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'name' => 'string',
'kbli' => 'string',
'activities' => 'string',
'area' => 'string',
'location' => 'string',
'number' => 'string',
'date' => 'date_format:Y-m-d',
];
}
/**
* Get the validation messages for the defined validation rules.
*
* @return array<string, string>
*/
public function messages(): array
{
return [
'name.string' => 'Kolom Nama harus berupa teks.',
'kbli.string' => 'Kolom KBLI harus berupa teks.',
'activities.string' => 'Kolom Kegiatan harus berupa teks.',
'area.string' => 'Kolom Area harus berupa teks.',
'location.string' => 'Kolom Lokasi harus berupa teks.',
'number.string' => 'Kolom Nomor harus berupa teks.',
'date.date_format' => 'Format tanggal tidak valid, gunakan format Y-m-d H:i:s.',
];
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class SpatialPlanningsRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'name' => ['required','string','max:255'],
'kbli' => ['required','string','max:255'],
'kegiatan' => ['required','string'],
'luas' => ['required','numeric','regex:/^\d{1,16}(\.\d{1,2})?$/'],
'lokasi' => ['required','string'],
'nomor' => ['required','string','max:255',Rule::unique('spatial_plannings')->ignore($this->id)],
'sp_date' => ['required','date'],
];
}
}

View File

@@ -0,0 +1,133 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class TourismRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'project_id' => 'required|string',
'project_type_id' => 'required|string',
'nib' => 'required|string',
'business_name' => 'required|string',
'oss_publication_date' => 'required',
'investment_status_description' => 'required|string',
'business_form' => 'required|string',
'project_risk' => 'required|string',
'project_name' => 'required|string',
'business_scale' => 'required|string',
'business_address' => 'required|string',
'district_name' => 'required',
'village_name' => 'required',
'longitude' => 'required|string',
'latitude' => 'required|string',
'project_submission_date' => 'required',
'kbli' => 'required|string',
'kbli_title' => 'required|string',
'supervisory_sector' => 'required|string',
'user_name' => 'required|string',
'email' => 'required|string',
'contact' => 'required|string',
'land_area_in_m2' => 'required|string',
'investment_amount' => 'required|string',
'tki' => 'required|string',
];
}
/**
* Get the validation messages for the defined validation rules.
*
* @return array<string, string>
*/
public function messages(): array
{
return [
'project_id.required' => 'ID proyek harus diisi.',
'project_id.string' => 'ID proyek harus berupa teks.',
'project_type_id.required' => 'ID tipe proyek harus diisi.',
'project_type_id.string' => 'ID tipe proyek harus berupa teks.',
'nib.required' => 'NIB harus diisi.',
'nib.string' => 'NIB harus berupa teks.',
'business_name.required' => 'Nama usaha harus diisi.',
'business_name.string' => 'Nama usaha harus berupa teks.',
'oss_publication_date.required' => 'Tanggal publikasi OSS harus diisi.',
'investment_status_description.required' => 'Deskripsi status investasi harus diisi.',
'investment_status_description.string' => 'Deskripsi status investasi harus berupa teks.',
'business_form.required' => 'Bentuk usaha harus diisi.',
'business_form.string' => 'Bentuk usaha harus berupa teks.',
'project_risk.required' => 'Risiko proyek harus diisi.',
'project_risk.string' => 'Risiko proyek harus berupa teks.',
'project_name.required' => 'Nama proyek harus diisi.',
'project_name.string' => 'Nama proyek harus berupa teks.',
'business_scale.required' => 'Skala usaha harus diisi.',
'business_scale.string' => 'Skala usaha harus berupa teks.',
'business_address.required' => 'Alamat usaha harus diisi.',
'business_address.string' => 'Alamat usaha harus berupa teks.',
'district_name.required' => 'Nama kecamatan harus diisi.',
'village_name.required' => 'Nama desa harus diisi.',
'longitude.required' => 'Garis bujur harus diisi.',
'longitude.string' => 'Garis bujur harus berupa teks.',
'latitude.required' => 'Garis lintang harus diisi.',
'latitude.string' => 'Garis lintang harus berupa teks.',
'project_submission_date.required' => 'Tanggal pengajuan proyek harus diisi.',
'kbli.required' => 'Kode KBLI harus diisi.',
'kbli.string' => 'Kode KBLI harus berupa teks.',
'kbli_title.required' => 'Judul KBLI harus diisi.',
'kbli_title.string' => 'Judul KBLI harus berupa teks.',
'supervisory_sector.required' => 'Sektor pengawasan harus diisi.',
'supervisory_sector.string' => 'Sektor pengawasan harus berupa teks.',
'user_name.required' => 'Nama pengguna harus diisi.',
'user_name.string' => 'Nama pengguna harus berupa teks.',
'email.required' => 'Email harus diisi.',
'email.string' => 'Email harus berupa teks.',
'contact.required' => 'Kontak harus diisi.',
'contact.string' => 'Kontak harus berupa teks.',
'land_area_in_m2.required' => 'Luas lahan dalam m² harus diisi.',
'land_area_in_m2.string' => 'Luas lahan dalam m² harus berupa teks.',
'investment_amount.required' => 'Jumlah investasi harus diisi.',
'investment_amount.string' => 'Jumlah investasi harus berupa teks.',
'tki.required' => 'Jumlah tenaga kerja Indonesia harus diisi.',
'tki.string' => 'Jumlah tenaga kerja Indonesia harus berupa teks.',
];
}
}

View File

@@ -0,0 +1,106 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UmkmRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'business_name' => 'required|string',
'business_address' => 'required|string',
'business_desc' => 'required|string',
'business_contact' => 'required|string',
'business_id_number' => 'string',
'business_scale_id' => 'required',
'owner_id' => 'required|string',
'owner_name' => 'required|string',
'owner_address' => 'required|string',
'owner_contact' => 'required|string',
'business_type' => 'required|string',
'business_form_id' => 'required|string',
'revenue' => 'required|numeric|between:0,999999999999999999.99',
'village_name' => 'required|string',
'district_name' => 'required',
'number_of_employee' => 'required',
'permit_status_id' => 'required',
'land_area' => 'required|integer|between:0,99999999999',
];
}
/**
* Get the validation messages for the request.
*
* @return array<string, string>
*/
public function messages(): array
{
return [
'business_name.required' => 'Nama usaha wajib diisi.',
'business_name.string' => 'Nama usaha harus berupa teks.',
'business_address.required' => 'Alamat usaha wajib diisi.',
'business_address.string' => 'Alamat usaha harus berupa teks.',
'business_desc.required' => 'Deskripsi usaha wajib diisi.',
'business_desc.string' => 'Deskripsi usaha harus berupa teks.',
'business_contact.required' => 'Kontak usaha wajib diisi.',
'business_contact.string' => 'Kontak usaha harus berupa teks.',
'business_id_number.string' => 'Nomor ID usaha harus berupa teks.',
'business_scale_id.required' => 'Skala usaha wajib diisi.',
'owner_id.required' => 'ID pemilik wajib diisi.',
'owner_id.string' => 'ID pemilik harus berupa teks.',
'owner_name.required' => 'Nama pemilik wajib diisi.',
'owner_name.string' => 'Nama pemilik harus berupa teks.',
'owner_address.required' => 'Alamat pemilik wajib diisi.',
'owner_address.string' => 'Alamat pemilik harus berupa teks.',
'owner_contact.required' => 'Kontak pemilik wajib diisi.',
'owner_contact.string' => 'Kontak pemilik harus berupa teks.',
'business_type.required' => 'Jenis usaha wajib diisi.',
'business_type.string' => 'Jenis usaha harus berupa teks.',
'business_form.required' => 'Bentuk usaha wajib diisi.',
'business_form.string' => 'Bentuk usaha harus berupa teks.',
'revenue.required' => 'Omset wajib diisi.',
'revenue.numeric' => 'Omset harus berupa angka yang valid.',
'revenue.between' => 'Omset harus berada di antara 0 dan 9.999.999.999,99.',
'village_name.required' => 'Nama desa wajib diisi.',
'village_name.string' => 'Nama desa harus berupa teks.',
'district_name.required' => 'Nama distrik wajib diisi.',
'number_of_employee.required' => 'Jumlah karyawan wajib diisi.',
'permit_status_id.required' => 'Status izin wajib diisi.',
'land_area.required' => 'Luas lahan wajib diisi.',
'land_area.integer' => 'Luas lahan harus berupa angka bulat.',
'land_area.between' => 'Luas lahan harus berada di antara 0 dan 99.999.999.999.',
];
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class UsersRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
$userId = $this->route('users'); // Get user ID from route (used in update)
return [
'name' => ['required', 'string', 'max:255'],
'email' => [
'required',
'string',
'email',
'max:255',
Rule::unique('users')->ignore($userId)
],
'password' => [$this->isMethod('post') ? 'required' : 'nullable', 'confirmed', 'max:255'],
'firstname' => ['required', 'string', 'max:255'],
'lastname' => ['required', 'string', 'max:255'],
'position' => ['required', 'string', 'max:255'],
'role_id' => ['required', 'exists:roles,id'],
];
}
}

Some files were not shown because too many files have changed in this diff Show More