101 Commits

Author SHA1 Message Date
e501e91673 Update dependency althinect/filament-spatie-roles-permissions to v3
Some checks failed
renovate/artifacts Artifact file update failure
Gemini PR Review / Gemini PR Review (pull_request) Failing after 19s
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Successful in 11s
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Successful in 10s
Laravel Pint / pint (pull_request) Failing after 1m57s
Laravel Larastan / larastan (pull_request) Failing after 2m5s
2026-02-22 08:38:36 +00:00
8a0e7d6878 Merge pull request 'Updated scrap_quantity as '0' when rework_status is 'No'' (#367) from ranjith-dev into master
All checks were successful
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Successful in 15s
Reviewed-on: #367
2026-02-21 13:21:19 +00:00
dhanabalan
81d2f4bd2c Updated scrap_quantity as '0' when rework_status is 'No'
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Successful in 16s
Gemini PR Review / Gemini PR Review (pull_request) Failing after 23s
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Successful in 12s
Laravel Pint / pint (pull_request) Successful in 2m52s
Laravel Larastan / larastan (pull_request) Failing after 3m46s
2026-02-21 18:50:58 +05:30
d1031d8a6e Merge pull request 'Updated validation logic while create and update' (#366) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #366
2026-02-21 11:25:40 +00:00
dhanabalan
c3d4a97277 Updated validation logic while create and update
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Successful in 11s
Gemini PR Review / Gemini PR Review (pull_request) Failing after 18s
Laravel Pint / pint (pull_request) Successful in 2m39s
Laravel Larastan / larastan (pull_request) Failing after 3m46s
2026-02-21 16:54:30 +05:30
fa06c2c6cb Merge pull request 'Updated laser part validation import / create page / report view function' (#365) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #365
2026-02-20 19:02:15 +00:00
dhanabalan
d243f53f2f Updated laser part validation import / create page / report view function
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-21 00:31:45 +05:30
e06a458fc0 Merge pull request 'Updated default plant load logic against resource files' (#364) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #364
2026-02-20 16:01:58 +00:00
dhanabalan
878e12eff5 Updated default plant load logic against resource files
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-20 21:31:41 +05:30
36dd07817b Merge pull request 'Updated validation logic against created_by and updated_by columns on importer' (#363) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #363
2026-02-20 15:36:02 +00:00
dhanabalan
cddc8a1b70 Updated validation logic against created_by and updated_by columns on importer
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-20 21:04:41 +05:30
51a20219db Merge pull request 'Updated validation logic if coil_number is 0 on importer' (#362) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #362
2026-02-20 15:25:46 +00:00
dhanabalan
95217ce722 Updated validation logic if coil_number is 0 on importer
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-20 20:55:27 +05:30
dc564f9c28 Merge pull request 'ranjith-dev' (#361) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #361
2026-02-20 14:27:16 +00:00
dhanabalan
9ba54dabf1 Updated validation logic on importer
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-20 19:55:34 +05:30
dhanabalan
3c4a4bf136 Updated validation logic on importer file
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-20 19:18:37 +05:30
dhanabalan
0e651e8bcc Updated column order on exporter file
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-20 18:44:01 +05:30
bab5b879e6 Merge pull request 'Updated validation logic on importer and exporter' (#360) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #360
2026-02-20 11:41:24 +00:00
dhanabalan
c3a4985f45 Updated validation logic on importer and exporter
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-20 17:11:05 +05:30
a09264a053 Merge pull request 'Changed label name of machine' (#359) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #359
2026-02-20 10:04:10 +00:00
dhanabalan
95c27d6821 Changed label name of machine
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-20 15:33:56 +05:30
82f776ef41 Merge pull request 'Changed logic in process order importer' (#358) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #358
2026-02-20 10:02:56 +00:00
dhanabalan
8fedc01efd Changed logic in process order importer
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-20 15:32:42 +05:30
952b9a01a5 Merge pull request 'Updated validation logic on inmporter and exporter' (#357) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #357
2026-02-20 09:39:29 +00:00
dhanabalan
4abdd1b81e Updated validation logic on inmporter and exporter
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-20 14:35:59 +05:30
2b8a3a2838 Merge pull request 'ranjith-dev' (#356) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #356
2026-02-20 09:02:18 +00:00
dhanabalan
10c2abb881 Changed logic in process order importer
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-20 14:31:06 +05:30
dhanabalan
934447d0b2 Changed logic in process order importer and exporter
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-20 13:06:06 +05:30
4acb66c464 Merge pull request 'Added migration file for allowing null value in shift_id column in table production plans' (#355) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #355
2026-02-19 07:03:07 +00:00
dhanabalan
b4acea8144 Added migration file for allowing null value in shift_id column in table production plans
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-19 12:32:47 +05:30
ea64aea9ce Merge pull request 'Added sub group name of production' (#354) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #354
2026-02-19 06:31:05 +00:00
dhanabalan
9e59f3d0fb Added sub group name of production
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-19 12:00:45 +05:30
72e6621cc0 Merge pull request 'Added save button and calender script file' (#353) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #353
2026-02-19 06:28:11 +00:00
dhanabalan
e6bf48055f Added save button and calender script file
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-19 11:57:51 +05:30
2c49e6b272 Merge pull request 'Added production calendar and production target permission' (#352) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #352
2026-02-19 06:24:12 +00:00
dhanabalan
c3fa25090d Added production calendar and production target permission
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-19 11:53:45 +05:30
d6ec50c20e Merge pull request 'Added production plan export page' (#351) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #351
2026-02-19 06:20:40 +00:00
dhanabalan
14da244965 Added production plan export page
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-19 11:50:16 +05:30
19382d0644 Merge pull request 'ranjith-dev' (#350) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #350
2026-02-19 06:20:04 +00:00
dhanabalan
8d1e1e6e53 Added production target plan live wire page and blade file
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-19 11:49:06 +05:30
dhanabalan
58e6e9df56 Added production target page and blade file
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-19 11:47:51 +05:30
dhanabalan
bec1a17970 Added production calender and blade file
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-19 11:45:30 +05:30
408e426545 Merge pull request 'ranjith-dev' (#349) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #349
2026-02-19 06:13:05 +00:00
dhanabalan
3c971e2ce7 Removed custom last scanned qr code
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-19 11:42:25 +05:30
dhanabalan
7793477c2d Added mahcine id in production quantity page
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-19 11:35:38 +05:30
dhanabalan
8204043122 removed required for block in line resource page
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-19 11:34:22 +05:30
dhanabalan
fd1c3a8094 Added block select box and line capacity in resource file
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-19 11:33:07 +05:30
dhanabalan
8f34ec0d86 Added production plan importer and resource file with updated logic
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-19 11:31:59 +05:30
62b338be22 Merge pull request 'Added columns in model files of Item and line and production plan and production quantity' (#348) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #348
2026-02-19 06:00:20 +00:00
dhanabalan
5ba59e10bd Added columns in model files of Item and line and production plan and production quantity
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-19 11:29:02 +05:30
c407f9c6c2 Merge pull request 'Added columns in production plan and lines and items and production quantities migration file' (#347) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #347
2026-02-19 05:50:36 +00:00
dhanabalan
b9812cbe32 Added columns in production plan and lines and items and production quantities migration file
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-19 11:19:45 +05:30
a09adf0ea5 Merge pull request 'ranjith-dev' (#346) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #346
2026-02-18 05:23:05 +00:00
dhanabalan
a297734bad Added searchable option for plant_id and line_id
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-18 10:48:39 +05:30
dhanabalan
20b02bfd7a Added searchable option for plant_id
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-18 10:40:27 +05:30
b864bda85e Merge pull request 'Refactor characteristic value form validation' (#345) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #345
2026-02-18 04:47:00 +00:00
dhanabalan
87cfe556ae Refactor characteristic value form validation
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-18 10:14:52 +05:30
734ab9dfdc Merge pull request 'Added status column auto updation logic based on observed_value' (#344) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #344
2026-02-17 12:13:58 +00:00
dhanabalan
b9a9a2fd5f Added status column auto updation logic based on observed_value
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-17 17:42:50 +05:30
6907083ec0 Merge pull request 'Updated plant label on report view' (#343) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #343
2026-02-17 04:18:35 +00:00
dhanabalan
e07bdb3310 Updated plant label on report view
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-17 09:47:57 +05:30
bd7e0422e6 Merge pull request 'Updated capacitor focus logic' (#342) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #342
2026-02-17 04:14:22 +00:00
dhanabalan
84e547ec4b Updated capacitor focus logic
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-17 09:43:53 +05:30
53f14711b2 Merge pull request 'ranjith-dev' (#341) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #341
2026-02-17 03:27:38 +00:00
dhanabalan
0dd49c2ebf Added searchable to respective columns and created_by column added on report view
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-17 08:56:12 +05:30
dhanabalan
db15039d81 Updated fillable order
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-17 08:51:50 +05:30
a39a10d104 Merge pull request 'ranjith-dev' (#340) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #340
2026-02-17 03:10:13 +00:00
dhanabalan
8d2489b16f Added updated_by column on view report and create_at column position changed
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-17 08:38:57 +05:30
dhanabalan
4a0be04a22 Added searchable to created_by and updated_by column
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-17 08:35:55 +05:30
17bca76d06 Merge pull request 'ranjith-dev' (#339) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #339
2026-02-16 09:15:53 +00:00
dhanabalan
0938f0955d Updated plant null exception and strict xlsx file allow logic on invoice import
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-16 14:41:39 +05:30
dhanabalan
ab70705e5a Updated material invoice upload logic
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-16 14:30:28 +05:30
500a2ae3ca Merge pull request 'ranjith-dev' (#338) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #338
2026-02-16 08:49:55 +00:00
dhanabalan
20dac4a9bf Updated default value as logged user name in updated_by column
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-16 14:19:15 +05:30
dhanabalan
a54ddb2f55 Updated created_at column visible by default on report
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-16 12:44:00 +05:30
0adb82afcf Merge pull request 'ranjith-dev' (#337) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #337
2026-02-16 07:09:49 +00:00
dhanabalan
018c51b75b Added id column in hidden and updated_by name updated on every control afterStateUpdated and searchable() method added on select controls
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-16 12:39:29 +05:30
dhanabalan
7c086ceb28 Commented unwanted mount function
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-16 12:22:23 +05:30
dhanabalan
67ffbf68fd Updated fillable order in model file
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-16 12:21:36 +05:30
cc7fd5b16d Merge pull request 'ranjith-dev' (#336) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #336
2026-02-16 04:54:24 +00:00
dhanabalan
f5d9adb516 Enhance approval email view logic and update HTML templates for better user feedback
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-16 10:20:18 +05:30
dhanabalan
787296abf9 Enhance request approval email design logic
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-16 10:16:44 +05:30
dhanabalan
ea39fb92de Enhance approval email logic and update HTML templates for better user feedback
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-16 10:14:25 +05:30
70d38c7a7b Merge pull request 'Updated machine work_center from machine name on export' (#335) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #335
2026-02-16 04:35:52 +00:00
dhanabalan
9212e2f937 Updated machine work_center from machine name on export
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-16 10:05:30 +05:30
efba8af539 Merge pull request 'ranjith-dev' (#334) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #334
2026-02-14 07:44:54 +00:00
dhanabalan
2acd3c8bb4 Add 'Spec. Value' column to CharacteristicValueResource table using ProductCharacteristicsMaster
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-14 13:07:31 +05:30
dhanabalan
d511b915e2 Refactor CharacteristicApprovalMail to include additional properties for pending approvers and subject line
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-13 19:52:21 +05:30
dhanabalan
8315b835b1 Updated alignment on GET and POST structure
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-13 19:49:50 +05:30
caac5ad7eb Merge pull request 'Updated order_quantity validation against process_order' (#333) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #333
2026-02-12 14:06:03 +00:00
dhanabalan
55a16800f8 Updated order_quantity validation against process_order
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-12 19:35:43 +05:30
7e799d507a Merge pull request 'Updated rework coil functionality' (#332) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #332
2026-02-12 13:29:23 +00:00
dhanabalan
56a5e40ec0 Updated rework coil functionality
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-12 18:58:59 +05:30
358d31cb71 Merge pull request 'Added coil_number and rework_status on advanced filters' (#331) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #331
2026-02-12 12:41:32 +00:00
dhanabalan
e20132d1f6 Added coil_number and rework_status on advanced filters
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-12 17:37:30 +05:30
4ffc2d7a92 Merge pull request 'ranjith-dev' (#330) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #330
2026-02-12 05:41:41 +00:00
dhanabalan
96aca2697f Changed logic in get api of process order
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-12 11:11:22 +05:30
dhanabalan
21ffd1763e Added default '-' for characteristic_name, current_value, update_value on quantity request type
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-11 14:30:30 +05:30
be5d02bc50 Merge pull request 'ranjith-dev' (#329) from ranjith-dev into master
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Reviewed-on: #329
2026-02-11 08:57:40 +00:00
dhanabalan
bd0e6b7c2e Removed commented code
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
2026-02-11 14:27:14 +05:30
dhanabalan
fcb88cef80 Updated table alignment towards center and display quantity value as integer for individual or bundle material type
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
2026-02-11 14:25:28 +05:30
58 changed files with 4853 additions and 1756 deletions

View File

@@ -38,25 +38,61 @@ class TriggerPendingApprovalMails extends Command
public $pdfPath;
public $subjectLine;
public $wfId;
public function handle()
{
$this->info('Approval mail job started');
$records = RequestCharacteristic::whereNull('approver_status1')
->whereNull('approver_status2')
->whereNull('approver_status3')
// .. Characteristic Mail trigger logic
// $records = RequestCharacteristic::whereNull('approver_status1')
// ->whereNull('approver_status2')
// ->whereNull('approver_status3')
// ->get();
$records = RequestCharacteristic::where(function ($q) {
$q->whereNull('approver_status1')
->orWhere('approver_status1', 'Hold');
})
->where(function ($q) {
$q->whereNull('approver_status2')
->orWhere('approver_status2', 'Hold');
})
->where(function ($q) {
$q->whereNull('approver_status3')
->orWhere('approver_status3', 'Hold');
})
->get();
$records = $records->filter(function ($item) {
$approver = CharacteristicApproverMaster::find($item->characteristic_approver_master_id);
return $approver && $approver->approver_type == 'Characteristic';
});
if ($records->isEmpty()) {
$this->info('No pending approvals');
return;
}
$grouped = $records->groupBy(function ($item) {
$this->wfId = $item->work_flow_id;
return $item->plant_id . '|' . $item->machine_id . '|' . $item->aufnr . '|' . $item->work_flow_id;
});
$pendingApprovers = RequestCharacteristic::where('work_flow_id', $this->wfId)->latest()->first();
$this->info($pendingApprovers->approver_status1, $pendingApprovers->approver_status2);
$approverNameFromMaster = null;
if ($pendingApprovers && $pendingApprovers->characteristic_approver_master_id) {
$approverNameFromMaster = CharacteristicApproverMaster::find($pendingApprovers->characteristic_approver_master_id);
}
$rows = [];
foreach ($grouped as $groupRecords) {
@@ -92,9 +128,6 @@ class TriggerPendingApprovalMails extends Command
$name = $approver->name1;
$updateData['mail_status'] = 'Sent';
// $updateData['trigger_at'] = $approver->duration1 > 0
// ? $now->copy()->addMinutes($approver->duration1 * 10)
// : null;
if ($approver->duration1 > 0)
{
@@ -118,19 +151,184 @@ class TriggerPendingApprovalMails extends Command
// --- SECOND MAIL ---
elseif (
$first->mail_status == 'Sent' &&
is_null($first->approver_status1) &&
(is_null($first->approver_status1) || $first->approver_status1 == 'Hold') &&
$first->trigger_at &&
\Carbon\Carbon::parse($first->trigger_at)->lte($now)
) {
$this->info(
"mail_status: {$first->mail_status}, ".
"approver_status1: {$first->approver_status1}, ".
"trigger_at: {$first->trigger_at}, ".
"now: {$now}"
);
$level = 2;
$mail = $approver->mail2;
$name = $approver->name2;
if ($approver->duration2 > 0) {
$duration = number_format((float)$approver->duration2, 2, '.', '');
[$hours, $minutes] = explode('.', $duration);
$totalMinutes = ((int)$hours * 60) + (int)$minutes;
$updateData['trigger_at'] = $now->copy()->addMinutes($totalMinutes);
} else {
$updateData['trigger_at'] = null;
}
$updateData['mail_status'] = 'Sent-Mail2';
}
// --- THIRD MAIL ---
elseif (
$first->mail_status == 'Sent-Mail2' &&
(is_null($first->approver_status1) || $first->approver_status1 == 'Hold') &&
(is_null($first->approver_status2) || $first->approver_status2 == 'Hold') &&
$first->trigger_at &&
\Carbon\Carbon::parse($first->trigger_at)->lte($now)
) {
$level = 3;
$mail = $approver->mail3;
$name = $approver->name3;
$updateData['trigger_at'] = null;
$updateData['mail_status'] = 'Sent-Mail3';
}
if (!$level || !$mail) {
continue;
}
$pdfPath = 'uploads/LaserDocs/' . $first->work_flow_id . '.pdf';
$subjectLine = 'Characteristic Approval Mail';
Mail::to($mail)->send(
new CharacteristicApprovalMail(
$first,
$name,
$level,
$pdfPath,
$pendingApprovers,
$approverNameFromMaster,
$subjectLine,
$characteristics
)
);
RequestCharacteristic::whereIn('id', $groupRecords->pluck('id'))
->update($updateData);
$rows[] = [
$first->id,
$first->plant_id,
$first->machine_id,
"Level $level",
$mail,
'SENT'
];
}
// .. Quality Mail trigger logic
$qualityRecords = RequestCharacteristic::where(function ($q) {
$q->whereNull('approver_status1')
->orWhere('approver_status1', 'Hold');
})
->where(function ($q) {
$q->whereNull('approver_status2')
->orWhere('approver_status2', 'Hold');
})
->where(function ($q) {
$q->whereNull('approver_status3')
->orWhere('approver_status3', 'Hold');
})
->get();
$qualityRecords = $qualityRecords->filter(function ($item) {
$approver = CharacteristicApproverMaster::find($item->characteristic_approver_master_id);
return $approver && $approver->approver_type == 'Quality';
});
if ($qualityRecords->isEmpty()) {
$this->info('No quality pending approvals');
return;
}
$grouped = $qualityRecords->groupBy(function ($item) {
$this->wfId = $item->work_flow_id;
return $item->plant_id . '|' . $item->machine_id . '|' . $item->aufnr . '|' . $item->work_flow_id;
});
$pendingApprovers = RequestCharacteristic::where('work_flow_id', $this->wfId)->latest()->first();
$approverNameFromMaster = null;
if ($pendingApprovers && $pendingApprovers->characteristic_approver_master_id) {
$approverNameFromMaster = CharacteristicApproverMaster::find($pendingApprovers->characteristic_approver_master_id);
}
$rows = [];
foreach ($grouped as $groupRecords) {
$first = $groupRecords->first();
$approver = CharacteristicApproverMaster::where('plant_id', $first->plant_id)
->where('machine_id', $first->machine_id)
->where('id', $first->characteristic_approver_master_id)
->first();
if (!$approver) {
continue;
}
$level = null;
$mail = null;
$name = null;
$updateData = [];
$now = Carbon::now();
// --- FIRST MAIL ---
if (is_null($first->mail_status)){
$level = 1;
$mail = $approver->mail1;
$name = $approver->name1;
$updateData['mail_status'] = 'Sent';
if ($approver->duration1 > 0)
{
$duration = number_format((float)$approver->duration1, 2, '.', '');
[$hours, $minutes] = explode('.', $duration);
$totalMinutes = ((int)$hours * 60) + (int)$minutes;
$updateData['trigger_at'] = $now
->copy()
->addMinutes($totalMinutes)
->startOfMinute();
}
else
{
$updateData['trigger_at'] = null;
}
}
// --- SECOND MAIL ---
elseif (
$first->mail_status == 'Sent' &&
(is_null($first->approver_status1) || $first->approver_status1 == 'Hold') &&
$first->trigger_at &&
\Carbon\Carbon::parse($first->trigger_at)->lte($now)
// $first->trigger_at <= $now
) {
$level = 2;
$mail = $approver->mail2;
$name = $approver->name2;
// $updateData['trigger_at'] = $approver->duration2 > 0
// ? $now->copy()->addMinutes($approver->duration2 * 10)
// : null;
// $updateData['mail_status'] = 'Sent-Mail2';
if ($approver->duration2 > 0) {
@@ -151,10 +349,9 @@ class TriggerPendingApprovalMails extends Command
// --- THIRD MAIL ---
elseif (
$first->mail_status == 'Sent-Mail2' &&
is_null($first->approver_status1) &&
is_null($first->approver_status2) &&
(is_null($first->approver_status1) || $first->approver_status1 == 'Hold') &&
(is_null($first->approver_status2) || $first->approver_status2 == 'Hold') &&
$first->trigger_at &&
// $first->trigger_at <= $now
\Carbon\Carbon::parse($first->trigger_at)->lte($now)
) {
$level = 3;
@@ -169,7 +366,13 @@ class TriggerPendingApprovalMails extends Command
continue;
}
$pdfPath = 'uploads/LaserDocs/' . $first->work_flow_id . '.pdf';
$pdfPath = ($f = glob(storage_path('app/private/uploads/LaserDocs/' . $first->work_flow_id . '.*')))
? 'uploads/LaserDocs/' . basename($f[0])
: null;
$this->info( $pdfPath);
$subjectLine = 'Quality Approval Mail';
Mail::to($mail)->send(
new CharacteristicApprovalMail(
@@ -177,6 +380,9 @@ class TriggerPendingApprovalMails extends Command
$name,
$level,
$pdfPath,
$pendingApprovers,
$approverNameFromMaster,
$subjectLine,
$characteristics
)
);

View File

@@ -0,0 +1,61 @@
<?php
namespace App\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\FromArray;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
class ProductionPlanExport implements FromArray, WithHeadings, WithMapping
{
protected array $data;
protected array $dates;
public function __construct(array $data, array $dates)
{
$this->data = $data;
$this->dates = $dates;
}
public function array(): array
{
return $this->data;
}
public function headings(): array
{
$headings = [
'Plant Name',
'Line Name',
'Item Code',
];
// Add dynamic headings for each date: Target / Produced
foreach ($this->dates as $date) {
$headings[] = $date . ' - Line Capacity';
$headings[] = $date . ' - Target Plan';
$headings[] = $date . ' - Produced Quantity';
}
return $headings;
}
public function map($row): array
{
$mapped = [
$row['plant_name'] ?? '',
$row['line_name'] ?? '',
$row['item_code'] ?? '',
];
foreach ($this->dates as $date) {
$mapped[] = $row['daily_line_capacity'][$date] ?? '-';
$mapped[] = $row['daily_target_dynamic'][$date] ?? '-';
$mapped[] = $row['produced_quantity'][$date] ?? '-';
}
return $mapped;
}
}

View File

@@ -28,7 +28,7 @@ class CharacteristicValueExporter extends Exporter
->label('LINE NAME'),
ExportColumn::make('item.code')
->label('ITEM CODE'),
ExportColumn::make('machine.name')
ExportColumn::make('machine.work_center')
->label('WORK CENTER'),
ExportColumn::make('process_order')
->label('PROCESS ORDER'),
@@ -36,12 +36,14 @@ class CharacteristicValueExporter extends Exporter
->label('COIL NUMBER'),
ExportColumn::make('status')
->label('STATUS'),
ExportColumn::make('observed_value')
->label('OBSERVED VALUE'),
ExportColumn::make('created_at')
->label('CREATED AT'),
ExportColumn::make('updated_at')
->label('UPDATED AT'),
ExportColumn::make('created_by')
->label('CREATED BY'),
ExportColumn::make('updated_at')
->label('UPDATED AT'),
ExportColumn::make('updated_by')
->label('UPDATED BY'),
ExportColumn::make('deleted_at')

View File

@@ -24,6 +24,8 @@ class ProcessOrderExporter extends Exporter
}),
ExportColumn::make('plant.code')
->label('PLANT CODE'),
ExportColumn::make('line.name')
->label('LINE NAME'),
ExportColumn::make('item.code')
->label('ITEM CODE'),
ExportColumn::make('process_order')
@@ -37,13 +39,17 @@ class ProcessOrderExporter extends Exporter
ExportColumn::make('sfg_number')
->label('SFG NUMBER'),
ExportColumn::make('machine_name')
->label('MACHINE ID'),
->label('MACHINE NAME'),
ExportColumn::make('scrap_quantity')
->label('SCRAP QUANTITY'),
ExportColumn::make('rework_status')
->label('REWORK STATUS'),
ExportColumn::make('created_at')
->label('CREATED AT'),
ExportColumn::make('updated_at')
->label('UPDATED AT'),
ExportColumn::make('created_by')
->label('CREATED BY'),
ExportColumn::make('updated_at')
->label('UPDATED AT'),
ExportColumn::make('updated_by')
->label('UPDATED BY'),
ExportColumn::make('deleted_at')

View File

@@ -29,7 +29,7 @@ class ProductCharacteristicsMasterExporter extends Exporter
ExportColumn::make('line.name')
->label('LINE NAME'), // machine.workGroupMaster.name
ExportColumn::make('machine.workGroupMaster.name')
->label('WORK GROUP MASTER'),
->label('GROUP WORK CENTER'),
ExportColumn::make('machine.work_center')
->label('WORK CENTER'),
ExportColumn::make('characteristics_type')

View File

@@ -8,10 +8,14 @@ use App\Models\Line;
use App\Models\Machine;
use App\Models\Plant;
use App\Models\ProcessOrder;
use App\Models\ProductCharacteristicsMaster;
use App\Models\User;
use Carbon\Carbon;
use Filament\Actions\Imports\Exceptions\RowImportFailedException;
use Filament\Actions\Imports\ImportColumn;
use Filament\Actions\Imports\Importer;
use Filament\Actions\Imports\Models\Import;
use Filament\Facades\Filament;
use Str;
class CharacteristicValueImporter extends Importer
@@ -64,11 +68,28 @@ class CharacteristicValueImporter extends Importer
->exampleHeader('Status')
->example('Ok')
->label('Status'),
ImportColumn::make('observed_value')
->requiredMapping()
->exampleHeader('Observed Value')
->example('RAW01234')
->label('Observed Value'),
ImportColumn::make('created_by')
->requiredMapping()
->exampleHeader('Created By')
->example('RAW01234')
->label('Created By'),
ImportColumn::make('created_at')
->requiredMapping()
->exampleHeader('Created DateTime')
->example('01-01-2025 08:00:00')
->label('Created DateTime')
->rules(['required']),
ImportColumn::make('updated_at')
->requiredMapping()
->exampleHeader('Updated DateTime')
->example('01-01-2025 08:00:00')
->label('Updated DateTime')
->rules(['required']),
];
}
@@ -82,30 +103,39 @@ class CharacteristicValueImporter extends Importer
$warnMsg = [];
$plantId = null;
$itemId = null;
$LineId = null;
$lineId = null;
$machineId = null;
$itemAgainstPlant = null;
// $itemAgainstPlant = null;
$plantCode = $this->data['plant'];
$processOrder = trim($this->data['process_order'] ?? '');
$iCode = trim($this->data['item']);
$workCenter = trim($this->data['machine']);
$lineName = trim($this->data['line']);
$coilNo = trim($this->data['coil_number']);
$obserVal = trim($this->data['observed_value']);
$status = trim($this->data['status']);
$createdBy = trim($this->data['created_by']);
$coilNo = trim($this->data['coil_number']);
if ($plantCode == null || $plantCode == '') {
$warnMsg[] = 'Plant code cannot be empty';
} elseif ($iCode == null || $iCode == '') {
} elseif ($iCode == null || $iCode == '') {// process_order
$warnMsg[] = 'Item code cannot be empty';
} elseif ($processOrder == null || $processOrder == '') {//
$warnMsg[] = 'Process Order cannot be empty';
} elseif ($workCenter == null || $workCenter == '') {
$warnMsg[] = 'Work center cannot be empty';
} elseif ($lineName == null || $lineName == '') {
$warnMsg[] = 'Line cannot be empty';
$warnMsg[] = 'Line name cannot be empty';
} elseif ($coilNo == null || $coilNo == '') {
$warnMsg[] = 'Coil number cannot be empty';
} elseif ($obserVal == null || $obserVal == '') {
$warnMsg[] = 'Observed value cannot be empty';
} elseif ($status == null || $status == '') {
$warnMsg[] = 'Status cannot be empty';
}
if (Str::length($plantCode) < 4 || ! is_numeric($plantCode) || ! preg_match('/^[1-9]\d{3,}$/', $plantCode)) {
if (Str::length($plantCode) > 0 && (Str::length($plantCode) < 4 || ! is_numeric($plantCode) || ! preg_match('/^[1-9]\d{3,}$/', $plantCode))) {
$warnMsg[] = 'Invalid plant code found';
} else {
$plant = Plant::where('code', $plantCode)->first();
@@ -116,7 +146,7 @@ class CharacteristicValueImporter extends Importer
}
}
if (Str::length($iCode) < 6 || ! ctype_alnum($iCode)) {
if (Str::length($iCode) > 0 && (Str::length($iCode) < 6 || ! ctype_alnum($iCode))) {
$warnMsg[] = 'Invalid item code found';
} else {
$itemCode = Item::where('code', $iCode)->first();
@@ -124,11 +154,11 @@ class CharacteristicValueImporter extends Importer
$warnMsg[] = 'Item code not found';
} else {
if ($plantId) {
$itemAgainstPlant = Item::where('code', $iCode)->where('plant_id', $plantId)->first();
if (! $itemAgainstPlant) {
$itemCode = Item::where('code', $iCode)->where('plant_id', $plantId)->first();
if (! $itemCode) {
$warnMsg[] = 'Item code not found for the given plant';
} else {
$itemId = $itemAgainstPlant->id;
$itemId = $itemCode->id;
}
}
}
@@ -143,7 +173,7 @@ class CharacteristicValueImporter extends Importer
if (! $lineAgainstPlant) {
$warnMsg[] = 'Line name not found for the given plant';
} else {
$LineId = $lineAgainstPlant->id;
$lineId = $lineAgainstPlant->id;
}
}
}
@@ -163,9 +193,9 @@ class CharacteristicValueImporter extends Importer
// $MachineId = $workCenterAgainstPlant->id;
// }
if ($plantId != null && $LineId != null) {
if ($plantId != null && $lineId != null) {
$machineAgaPlantLine = Machine::where('plant_id', $plantId)
->where('line_id', $LineId)
->where('line_id', $lineId)
->where('work_center', $workCenter)
->first();
@@ -176,34 +206,66 @@ class CharacteristicValueImporter extends Importer
}
}
if ($processOrder == null || $processOrder == '') {
$warnMsg[] = 'Process Order cannot be empty';
}
if ($coilNo == null || $coilNo == '') {
$warnMsg[] = 'Coil No cannot be empty';
} elseif (! is_numeric($coilNo)) {
if (Str::length($coilNo) > 0 && ! is_numeric($coilNo)) {
$warnMsg[] = 'Coil number should contain only numeric values!';
}
if ($status == null || $status == '' || ! $status) {
$warnMsg[] = 'Status cannot be empty';
} elseif (! in_array($status, ['Ok', 'NotOk'], true)) {
if (Str::length($obserVal) > 0 && ! is_numeric($obserVal)) {
$warnMsg[] = 'Observed value should contain only numeric values!';
}
if (Str::length($status) > 0 && ! in_array($status, ['Ok', 'NotOk'], true)) {
$warnMsg[] = "Status must be either 'Ok' or 'NotOk'!";
}
// else {
// if (Str::length($status) <= 0 || ! is_numeric($status) || ! preg_match('/^\d+(\.\d+)?$/', $status)
// ) {
// $status = 'NotOk';
// } else {
// $specVal = ProductCharacteristicsMaster::where('plant_id', $plantId)->where('item_id', $itemId)->where('line_id', $lineId)->where('machine_id', $machineId)->first();
// if (! $specVal) {
// $status = 'NotOk';
// }
// $lowLimit = $specVal?->lower ?? 0;
// $uppLimit = $specVal?->upper ?? 0;
// if (Str::length($lowLimit) <= 0 || ! is_numeric($lowLimit) || ! preg_match('/^\d+(\.\d+)?$/', $lowLimit)
// ) {
// $status = 'NotOk';
// } elseif (Str::length($uppLimit) <= 0 || ! is_numeric($uppLimit) || ! preg_match('/^\d+(\.\d+)?$/', $uppLimit)
// ) {
// $status = 'NotOk';
// }
// if (($lowLimit == 0 && $uppLimit == 0) || ($uppLimit == 0)) {
// $status = 'NotOk';
// }
// if ($lowLimit > $obserVal || $uppLimit < $obserVal) {
// $status = 'NotOk';
// }
// $status = 'Ok';
// }
// }
if ($createdBy == null || $createdBy == '' || ! $createdBy) {
$warnMsg[] = 'Created By cannot be empty';
}
// $existing = CharacteristicValue::where('plant_id', $plantId)
// ->where('process_order', $processOrder)
// ->where('coil_number', $coilNo)
// ->first();
if ($plantId) {
$user = User::where('name', $createdBy)->first();
// if ($existing) {
// $warnMsg[] = "Process order '{$processOrder}' with coil number '{$coilNo}' already exist for the plant code '{$plantCode}'!";
// }
$userPlant = User::where('name', $createdBy)->where('plant_id', $plantId)->first();
if (! $user) {
$warnMsg[] = 'Created By user name not found!';
} elseif (! $userPlant && ! $user->hasRole('Super Admin')) {
$warnMsg[] = "Created By user '{$createdBy}' not found for Plant '{$plantCode}'!";
} elseif (! $user->hasRole(['Super Admin', 'Process Quality Manager', 'Process Manager', 'Process Supervisor', 'Process Employee'])) {
$warnMsg[] = 'Created By user does not have rights!';
}
}
if ($plantId && $processOrder) {
$existing = CharacteristicValue::where('plant_id', $plantId)
@@ -216,30 +278,80 @@ class CharacteristicValueImporter extends Importer
}
}
if ($plant && $itemCode && $processOrder != '') {
if ($plant && $itemCode && $processOrder != '' && $processOrder != null) {
$existingOrder = ProcessOrder::where('plant_id', $plant->id)
$existingOrder = ProcessOrder::where('plant_id', $plantId)
->where('process_order', $processOrder)
->first();
if ($existingOrder && $existingOrder->item_id !== ($itemCode->id ?? null)) {
if ($existingOrder && $existingOrder->item_id !== ($itemId ?? null)) {
$warnMsg[] = 'Same Process Order already exists for this Plant with a different Item Code';
}
}
$updatedBy = Filament::auth()->user()->name; // ?? 'Admin'
if (! $updatedBy) {
$warnMsg[] = 'Invalid updated by user name found';
}
$fromDate = $this->data['created_at'];
$toDate = $this->data['updated_at'];
$formats = ['d-m-Y H:i', 'd-m-Y H:i:s']; // '07-05-2025 08:00' or '07-05-2025 08:00:00'
$fdateTime = null;
$tdateTime = null;
// Try parsing with multiple formats
foreach ($formats as $format) {
try {
$fdateTime = Carbon::createFromFormat($format, $fromDate);
break;
} catch (\Exception $e) {
// $warnMsg[] = "Date format mismatch with format: $format";
}
}
foreach ($formats as $format) {
try {
$tdateTime = Carbon::createFromFormat($format, $toDate);
break;
} catch (\Exception $e) {
// $warnMsg[] = "Date format mismatch with format: $format";
}
}
if (! isset($fdateTime)) {
$warnMsg[] = "Invalid 'Created DateTime' format. Expected DD-MM-YYYY HH:MM:SS";
}
if (! isset($tdateTime)) {
$warnMsg[] = "Invalid 'Updated DateTime' format. Expected DD-MM-YYYY HH:MM:SS";
}
if (isset($fdateTime) && isset($tdateTime)) {
if ($fdateTime->greaterThan($tdateTime)) {
$warnMsg[] = "'Created DataTime' is greater than 'Updated DateTime'.";
}
}
if (! empty($warnMsg)) {
throw new RowImportFailedException(implode(', ', $warnMsg));
}
return CharacteristicValue::create([
return CharacteristicValue::updateOrCreate([
'plant_id' => $plantId,
'process_order' => $processOrder,
'coil_number' => $coilNo,
],
[
'item_id' => $itemId,
'line_id' => $LineId,
'line_id' => $lineId,
'machine_id' => $machineId,
'process_order' => trim($this->data['process_order']),
'coil_number' => trim($this->data['coil_number']),
'status' => trim($this->data['status']),
'created_by' => trim($this->data['created_by']),
'status' => $status,
'observed_value' => $obserVal,
'created_by' => $createdBy,
'updated_by' => $updatedBy,
'created_at' => $fdateTime->format('Y-m-d H:i:s'),
'updated_at' => $tdateTime->format('Y-m-d H:i:s'),
]);
// return null;

View File

@@ -3,6 +3,7 @@
namespace App\Filament\Imports;
use App\Models\Item;
use App\Models\Line;
use App\Models\Plant;
use App\Models\ProcessOrder;
use App\Models\User;
@@ -27,6 +28,11 @@ class ProcessOrderImporter extends Importer
->label('PLANT CODE')
->relationship(resolveUsing: 'code')
->rules(['required']),
ImportColumn::make('line')
->exampleHeader('LINE NAME')
->example(' Polywrapped line')
->label('LINE NAME')
->relationship(resolveUsing: 'name'),
ImportColumn::make('item')
->requiredMapping()
->exampleHeader('ITEM CODE')
@@ -35,20 +41,57 @@ class ProcessOrderImporter extends Importer
->relationship(resolveUsing: 'code')
->rules(['required']),
ImportColumn::make('process_order')
->requiredMapping()
->exampleHeader('PROCESS ORDER')
->example('202500123456')
->label('PROCESS ORDER')
->rules(['required']),
ImportColumn::make('coil_number')
->exampleHeader('COIL NUMBER')
->example('01')
->label('COIL NUMBER'),
ImportColumn::make('order_quantity')
->requiredMapping()
->exampleHeader('ORDER QUANTITY')
->example('100')
->label('ORDER QUANTITY')
->rules(['required']),
// ImportColumn::make('created_by')
// ->exampleHeader('CREATED BY')
// ->example('RAW01234')
// ->label('CREATED BY')
// ->rules(['required']),
ImportColumn::make('received_quantity')
->exampleHeader('RECEIVED QUANTITY')
->example('01')
->label('RECEIVED QUANTITY'),
ImportColumn::make('sfg_number')
->exampleHeader('SFG NUMBER')
->example('200000220613-72')
->label('SFG NUMBER'),
ImportColumn::make('machine_name')
->exampleHeader('MACHINE NAME')
->example('WMIWRM13 - 2-L2')
->label('MACHINE NAME'),
ImportColumn::make('scrap_quantity')
->exampleHeader('SCRAP QUANTITY')
->example('0')
->label('SCRAP QUANTITY'),
ImportColumn::make('rework_status')
->exampleHeader('REWORK STATUS')
->example('0')
->label('REWORK STATUS'),
ImportColumn::make('created_at')
->exampleHeader('CREATED AT')
->example('2026-02-20 13:00:00')
->label('CREATED AT'),
ImportColumn::make('updated_at')
->exampleHeader('UPDATED AT')
->example('2026-02-20 13:00:00')
->label('UPDATED AT'),
ImportColumn::make('created_by')
->exampleHeader('CREATED BY')
->example('RAW01234')
->label('CREATED BY'),
ImportColumn::make('updated_by')
->exampleHeader('UPDATED BY')
->example('RAW01234')
->label('UPDATED BY'),
];
}
@@ -57,10 +100,56 @@ class ProcessOrderImporter extends Importer
$warnMsg = [];
$plantCod = $this->data['plant'];
$plant = null;
$plantId = null;
$itemId = null;
$iCode = trim($this->data['item']);
$lineName = trim($this->data['line']);
$processOrder = trim($this->data['process_order'] ?? '');
$user = Filament::auth()->user();
$operatorName = $user->name;
$coilNo = trim($this->data['coil_number'] ?? '');
$sfgNo = trim($this->data['sfg_number'] ?? '');
$machineName = trim($this->data['machine_name'] ?? '');
$orderQuan = trim($this->data['order_quantity'] ?? '');
$scrapQuan = trim($this->data['scrap_quantity'] ?? '');
$reworkStatus = trim($this->data['rework_status'] ?? '');
$recQuan = trim($this->data['received_quantity'] ?? '');
$createdAt = trim($this->data['created_at'] ?? '');
$createdBy = trim($this->data['created_by'] ?? '');
$updatedAt = trim($this->data['updated_at'] ?? '');
$updatedBy = trim($this->data['updated_by'] ?? '');
// $user = Filament::auth()->user();
// $operatorName = $user->name;
if ($plantCod == null || $plantCod == '') {
$warnMsg[] = 'Plant code cannot be empty';
}
if ($iCode == null || $iCode == '') {
$warnMsg[] = 'Item code cannot be empty';
}
if ($processOrder == null || $processOrder == '') {
$warnMsg[] = 'Process order cannot be empty';
}
if ($orderQuan == null || $orderQuan == '') {
$warnMsg[] = 'Order quantity cannot be empty';
} elseif ($orderQuan == 0 || $orderQuan == '0') {
$warnMsg[] = 'Order quantity cannot be zero';
}
if ($coilNo == null || $coilNo == '') {
$coilNo = '0';
}
if ($scrapQuan == null || $scrapQuan == '') {
$scrapQuan = 0;
}
if ($recQuan == null || $recQuan == '') {
$recQuan = 0;
}
if ($reworkStatus == null || $reworkStatus = '') {
$reworkStatus = 0;
}
if ($createdBy == null || $createdBy == '') {
$createdBy = Filament::auth()->user()?->name;
$updatedBy = $createdBy;
}
if (Str::length($plantCod) < 4 || ! is_numeric($plantCod) || ! preg_match('/^[1-9]\d{3,}$/', $plantCod)) {
$warnMsg[] = 'Invalid plant code found';
@@ -68,6 +157,8 @@ class ProcessOrderImporter extends Importer
$plant = Plant::where('code', $plantCod)->first();
if (! $plant) {
$warnMsg[] = 'Plant not found';
} else {
$plantId = $plant->id;
}
}
@@ -76,43 +167,169 @@ class ProcessOrderImporter extends Importer
} else {
$itemCode = Item::where('code', $iCode)->first();
if (! $itemCode) {
$warnMsg[] = 'Item Code not found';
$warnMsg[] = 'Item code not found';
} else {
if ($plantId) {
$itemCode = Item::where('code', $iCode)->where('plant_id', $plantId)->first();
if (! $itemCode) {
$warnMsg[] = 'Item code not found for the given plant';
} else {
$itemId = $itemCode->id;
}
}
}
if ($processOrder == '') {
$warnMsg[] = 'Process Order cannot be empty';
}
// $user = User::where('name', $this->data['created_by'])->first();
// if (! $user) {
// $warnMsg[] = 'User not found';
// }
if ($plant && $itemCode && $processOrder != '') {
$existingOrder = ProcessOrder::where('plant_id', $plant->id)
$existingOrder = ProcessOrder::where('plant_id', $plantId)
->where('process_order', $processOrder)
->first();
if ($existingOrder && $existingOrder->item_id !== ($itemCode->id ?? null)) {
if ($existingOrder && $existingOrder->item_id !== ($itemId ?? null)) {
$warnMsg[] = 'Same Process Order already exists for this Plant with a different Item Code';
}
}
if ($lineName != null && $lineName != '') {
$lineExists = Line::where('name', $lineName)->first();
if (! $lineExists) {
$warnMsg[] = 'Line name not found';
} else {
if ($plantId) {
$lineAgainstPlant = Line::where('name', $lineName)->where('plant_id', $plantId)->first();
if (! $lineAgainstPlant) {
$warnMsg[] = 'Line name not found for the given plant';
} else {
$lineId = $lineAgainstPlant->id;
}
}
}
} else {
$lineId = null;
}
if ($createdBy != null && $createdBy != '') {
if ($plantId) {
$user = User::where('name', $createdBy)->first();
$userPlant = User::where('name', $createdBy)->where('plant_id', $plantId)->first();
if (! $user) {
$warnMsg[] = 'Created By user name not found!';
} elseif (! $userPlant && ! $user->hasRole('Super Admin')) {
$warnMsg[] = "Created By user '{$createdBy}' not found for Plant '{$plantCod}'!";
} elseif (! $user->hasRole(['Super Admin', 'Process Quality Manager', 'Process Manager', 'Process Supervisor', 'Process Employee'])) {
$warnMsg[] = 'Created By user does not have rights!';
}
}
$updatedBy = Filament::auth()->user()?->name;
}
if (! empty($warnMsg)) {
throw new RowImportFailedException(implode(', ', $warnMsg));
}
return ProcessOrder::create([
'plant_id' => $plant->id,
'item_id' => $itemCode->id,
'process_order' => trim($this->data['process_order']),
'coil_number' => '0',
'order_quantity' => 0,
'received_quantity' => 0,
'created_by' => $operatorName,
if ($lineName != null && $lineName != '') {
$existingCoil = ProcessOrder::where('plant_id', $plantId)
->where('process_order', $processOrder)
->where('line_id', $lineId)
->where('coil_number', $coilNo)
->first();
if (! $existingCoil) {
ProcessOrder::Create(
[
'plant_id' => $plantId,
'line_id' => $lineId,
'process_order' => $processOrder,
'item_id' => $itemId,
'coil_number' => $coilNo,
'order_quantity' => $orderQuan,
'received_quantity' => $recQuan,
'scrap_quantity' => $scrapQuan,
'sfg_number' => $sfgNo,
'machine_name' => $machineName,
'rework_status' => $reworkStatus,
'created_at' => $createdAt,
'updated_at' => $updatedAt,
'created_by' => $createdBy,
'updated_by' => $updatedBy,
]
);
} else {
ProcessOrder::where('plant_id', $plantId)
->where('process_order', $processOrder)
->where('line_id', $lineId)
->where('coil_number', $coilNo)
->update([
// 'order_quantity' => $orderQty,
'received_quantity' => $recQuan,
'scrap_quantity' => $scrapQuan,
// 'sfg_number' => $sfgNo,
// 'machine_name' => $machineId,
'rework_status' => $reworkStatus,
'updated_by' => $updatedBy,
'updated_at' => $updatedAt,
]);
}
} elseif ($lineName == null || $lineName == '') {
$existing = ProcessOrder::where('plant_id', $plantId)
->where('process_order', $processOrder)
->where('coil_number', $coilNo)
->first();
if (! $existing && $coilNo == '0' || $coilNo == 0) {
ProcessOrder::create([
'plant_id' => $plantId,
'item_id' => $itemId,
'process_order' => $processOrder,
'coil_number' => '0',
'order_quantity' => $orderQuan,
'received_quantity' => 0,
'scrap_quantity' => 0,
'created_by' => $createdBy,
'updated_by' => $updatedBy,
]);
} elseif (! $existing) {
ProcessOrder::Create(
[
'plant_id' => $plantId,
'line_id' => $lineId,
'process_order' => $processOrder,
'item_id' => $itemId,
'coil_number' => $coilNo,
'order_quantity' => $orderQuan,
'received_quantity' => $recQuan,
'scrap_quantity' => $scrapQuan ?? 0,
'sfg_number' => $sfgNo,
'machine_name' => $machineName,
'rework_status' => $reworkStatus,
'created_at' => $createdAt,
'updated_at' => $updatedAt,
'created_by' => $createdBy,
'updated_by' => $updatedBy,
]
);
} else {// $coilNo = '0'
ProcessOrder::where('plant_id', $plantId)
->where('process_order', $processOrder)
->where('coil_number', $coilNo)
->update([
// 'order_quantity' => $orderQty,
'received_quantity' => $recQuan,
'scrap_quantity' => $scrapQuan,
// 'sfg_number' => $sfgNo,
// 'machine_name' => $machineId,
'rework_status' => $reworkStatus,
'updated_by' => $updatedBy,
'updated_at' => $updatedAt,
]);
}
}
return null;
// return new ProcessOrder();
}

View File

@@ -13,7 +13,7 @@ use Filament\Actions\Imports\Exceptions\RowImportFailedException;
use Filament\Actions\Imports\ImportColumn;
use Filament\Actions\Imports\Importer;
use Filament\Actions\Imports\Models\Import;
use Illuminate\Support\Facades\Auth;
use Filament\Facades\Filament;
use Str;
class ProductCharacteristicsMasterImporter extends Importer
@@ -75,7 +75,7 @@ class ProductCharacteristicsMasterImporter extends Importer
->rules(['required']),
ImportColumn::make('lower')
->exampleHeader('Lower')
->example('-0.2')
->example('0')
->label('Lower')
->rules(['numeric']),
ImportColumn::make('middle')
@@ -86,7 +86,7 @@ class ProductCharacteristicsMasterImporter extends Importer
->rules(['numeric']),
ImportColumn::make('upper')
->exampleHeader('Upper')
->example('0.2')
->example('2')
->label('Upper')
->rules(['numeric']),
ImportColumn::make('created_by')
@@ -103,7 +103,12 @@ class ProductCharacteristicsMasterImporter extends Importer
$warnMsg = [];
$plantCod = $this->data['plant'];
$plant = null;
$updatedBy = Filament::auth()->user()->name; // ?? 'Admin'
$lower = null;
$middle = null;
$upper = null;
$plantId = null;
$name = trim($this->data['name']);
if (Str::length($plantCod) < 4 || ! is_numeric($plantCod) || ! preg_match('/^[1-9]\d{3,}$/', $plantCod)) {
$warnMsg[] = 'Invalid plant code found';
} else {
@@ -111,13 +116,14 @@ class ProductCharacteristicsMasterImporter extends Importer
if (! $plant) {
$warnMsg[] = 'Plant not found';
} else {
$plantId = $plant->id;
$itemExists = Item::where('code', $this->data['item'])->first();
if (! $itemExists) {
$warnMsg[] = 'Item not found';
}
$itemAgainstPlant = Item::where('code', $this->data['item'])
->where('plant_id', $plant->id)
->where('plant_id', $plantId)
->first();
if (! $itemAgainstPlant) {
$warnMsg[] = 'Item code not found for the given plant';
@@ -131,7 +137,7 @@ class ProductCharacteristicsMasterImporter extends Importer
}
$lineAgainstPlant = Line::where('name', $this->data['line'])
->where('plant_id', $plant->id)
->where('plant_id', $plantId)
->first();
if (! $lineAgainstPlant) {
@@ -140,7 +146,7 @@ class ProductCharacteristicsMasterImporter extends Importer
$LineId = $lineAgainstPlant->id;
}
$WorkgroupMaster = WorkGroupMaster::where('name', $this->data['work_group_master_id'])->where('plant_id', $plant->id)->first();
$WorkgroupMaster = WorkGroupMaster::where('name', $this->data['work_group_master_id'])->where('plant_id', $plantId)->first();
if (! $WorkgroupMaster) {
$warnMsg[] = 'Work Group Master value not found';
} else {
@@ -148,7 +154,7 @@ class ProductCharacteristicsMasterImporter extends Importer
$workGroupMasterId = $WorkgroupMaster->id;
// 2. Now check if this WorkGroupMaster id exists in ANY of the 10 columns
$existsInLine = Line::where('plant_id', $plant->id)
$existsInLine = Line::where('plant_id', $plantId)
->where(function ($q) use ($workGroupMasterId) {
for ($i = 1; $i <= 10; $i++) {
$q->orWhere("work_group{$i}_id", $workGroupMasterId);
@@ -171,7 +177,7 @@ class ProductCharacteristicsMasterImporter extends Importer
}
$machineAgainstPlant = Machine::where('work_center', $this->data['machine'])
->where('plant_id', $plant->id)
->where('plant_id', $plantId)
->first();
if (! $machineAgainstPlant) {
@@ -180,15 +186,24 @@ class ProductCharacteristicsMasterImporter extends Importer
$machineId = $machineAgainstPlant->id;
}
if ($name == null || $name == '') {
$warnMsg[] = "Name can't be empty";
}
$user = User::where('name', $this->data['created_by'])->first();
if (! $user) {
$warnMsg[] = 'Operator ID not found';
}
$updatedBy = Filament::auth()->user()->name; // ?? 'Admin'
if (! $updatedBy) {
$warnMsg[] = 'Invalid updated by user name found';
}
if (($this->data['inspection_type'] ?? null) == 'Value') {
$upper = $this->data['upper'] ?? null;
$lower = $this->data['lower'] ?? null;
$middle = $this->data['middle'] ?? null;
$upper = $this->data['upper'] ?? null;
if (is_null($upper) || is_null($lower) || is_null($middle)) {
$warnMsg[] = "For 'Value' inspection type, Upper, Lower, and Middle values are required.";
@@ -203,64 +218,55 @@ class ProductCharacteristicsMasterImporter extends Importer
if (! empty($warnMsg)) {
throw new RowImportFailedException(implode(', ', $warnMsg));
} else {
$record = ProductCharacteristicsMaster::firstOrNew([
'plant_id' => $plant->id,
'item_id' => $itemId,
'line_id' => $LineId,
'work_group_master_id' => $workGroupMasterId,
'machine_id' => $machineId,
]);
$currentUser = Auth::check() ? Auth::user()->name : ($this->data['created_by'] ?? 'System');
// If record is new, fill all fields
if (! $record->exists) {
$record->name = $this->data['name'];
$record->characteristics_type = $this->data['characteristics_type'];
$record->inspection_type = $this->data['inspection_type'];
$record->upper = $this->data['upper'] ?? null;
$record->lower = $this->data['lower'] ?? null;
$record->middle = $this->data['middle'] ?? null;
$record->created_by = $currentUser;
} else {
// Record exists → update only updated_by and updated_at
$record->updated_by = $currentUser;
$record->touch();
}
$record->save();
return null;
}
// else
// {
// ProductCharacteristicsMaster::updateOrCreate(
// [
// 'plant_id' => $plant->id,
// $record = ProductCharacteristicsMaster::firstOrNew([
// 'plant_id' => $plantId,
// 'item_id' => $itemId,
// 'line_id' => $LineId,
// 'work_group_master_id' => $workGroupMasterId,
// 'machine_id' => $machineId,
// ],
// [
// 'name' => $this->data['name'],
// 'characteristics_type' => $this->data['characteristics_type'],
// 'inspection_type' => $this->data['inspection_type'],
// 'upper' => $this->data['upper'] ?? null,
// 'lower' => $this->data['lower'] ?? null,
// 'middle' => $this->data['middle'] ?? null,
// //'created_by' => user ?? $this->data['created_by'],
// 'created_by' => Auth::check() ? Auth::user()->name :($this->data['created_by'] ?? null)
// ]
// );
// return null;
// ]);
// // If record is new, fill all fields
// if (! $record->exists) {
// $record->name = $name;
// $record->characteristics_type = $this->data['characteristics_type'];
// $record->inspection_type = $this->data['inspection_type'];
// $record->lower = $this->data['lower'] ?? null;
// $record->upper = $this->data['upper'] ?? null;
// $record->middle = $this->data['middle'] ?? null;
// $record->created_by = $this->data['created_by'] ?? null;
// $record->updated_by = $updatedBy ?? null;
// } else {
// // Record exists → update only updated_by and updated_at
// $record->updated_by = $updatedBy ?? null;
// $record->touch();
// }
// $record->save();
ProductCharacteristicsMaster::updateOrCreate(
[
'plant_id' => $plantId,
'item_id' => $itemId,
'line_id' => $LineId,
'work_group_master_id' => $workGroupMasterId,
'machine_id' => $machineId,
],
[
'name' => $name,
'characteristics_type' => $this->data['characteristics_type'],
'inspection_type' => $this->data['inspection_type'],
'lower' => $lower,
'middle' => $middle,
'upper' => $upper,
// 'created_by' => user ?? $this->data['created_by'],
'created_by' => $this->data['created_by'] ?? null,
'updated_by' => $updatedBy ?? null,
]);
return null;
// return new WorkGroupMaster();
// return new ProductCharacteristicsMaster();
}

View File

@@ -3,6 +3,7 @@
namespace App\Filament\Imports;
use App\Models\Block;
use App\Models\Item;
use App\Models\Line;
use App\Models\Plant;
use App\Models\ProductionPlan;
@@ -23,11 +24,33 @@ class ProductionPlanImporter extends Importer
public static function getColumns(): array
{
return [
ImportColumn::make('created_at')
// ImportColumn::make('created_at')
// ->requiredMapping()
// ->exampleHeader('Created DateTime')
// ->example(['01-01-2025 08:00:00', '01-01-2025 19:30:00'])
// ->label('Created DateTime')
// ->rules(['required']),
ImportColumn::make('plant')
->requiredMapping()
->exampleHeader('Created DateTime')
->example(['01-01-2025 08:00:00', '01-01-2025 19:30:00'])
->label('Created DateTime')
->exampleHeader('Plant Code')
->example(['1000', '1000'])
->label('Plant Code')
->relationship(resolveUsing: 'code')
->rules(['required']),
ImportColumn::make('line')
->requiredMapping()
->exampleHeader('Line Name')
->example(['4 inch pump line', '4 inch pump line'])
->label('Line Name')
->relationship(resolveUsing: 'name')
->rules(['required']),
ImportColumn::make('item')
->requiredMapping()
->exampleHeader('Item Code')
->example(['123456', '210987'])
->label('Item Code')
->relationship(resolveUsing: 'code')
->rules(['required']),
ImportColumn::make('plan_quantity')
->requiredMapping()
@@ -36,52 +59,40 @@ class ProductionPlanImporter extends Importer
->label('Plan Quantity')
->numeric()
->rules(['required', 'integer']),
ImportColumn::make('production_quantity')
->requiredMapping()
->exampleHeader('Production Quantity')
->example(['0', '0'])
->label('Production Quantity')
->numeric()
->rules(['required', 'integer']),
ImportColumn::make('line')
->requiredMapping()
->exampleHeader('Line Name')
->example(['4 inch pump line', '4 inch pump line'])
->label('Line Name')
->relationship(resolveUsing: 'name')
->rules(['required']),
ImportColumn::make('block_reference')
->requiredMapping() // Or optionalMapping() if not always present
->exampleHeader('Block Name')
->example(['Block A', 'Block A'])
->label('Block Name')
->rules(['required']), // Or remove if not required
ImportColumn::make('shift')
->requiredMapping()
->exampleHeader('Shift Name') // ID
->example(['Day', 'Night']) // '2', '7'
->label('Shift Name') // ID
->relationship(resolveUsing: 'name')
->rules(['required']),
ImportColumn::make('plant')
->requiredMapping()
->exampleHeader('Plant Code')
->example(['1000', '1000'])
->label('Plant Code')
->relationship(resolveUsing: 'code')
->rules(['required']),
ImportColumn::make('updated_at')
->requiredMapping()
->exampleHeader('Updated DateTime')
->example(['01-01-2025 08:00:00', '01-01-2025 19:30:00'])
->label('Updated DateTime')
->rules(['required']),
ImportColumn::make('operator_id')
->requiredMapping()
->exampleHeader('Operator ID')
->example([Filament::auth()->user()->name, Filament::auth()->user()->name])
->label('Operator ID')
->rules(['required']),
// ImportColumn::make('production_quantity')
// ->requiredMapping()
// ->exampleHeader('Production Quantity')
// ->example(['0', '0'])
// ->label('Production Quantity')
// ->numeric()
// ->rules(['required', 'integer']),
// ImportColumn::make('block_reference')
// ->requiredMapping() // Or optionalMapping() if not always present
// ->exampleHeader('Block Name')
// ->example(['Block A', 'Block A'])
// ->label('Block Name')
// ->rules(['required']), // Or remove if not required
// ImportColumn::make('shift')
// ->requiredMapping()
// ->exampleHeader('Shift Name') // ID
// ->example(['Day', 'Night']) // '2', '7'
// ->label('Shift Name') // ID
// ->relationship(resolveUsing: 'name')
// ->rules(['required']),
// ImportColumn::make('updated_at')
// ->requiredMapping()
// ->exampleHeader('Updated DateTime')
// ->example(['01-01-2025 08:00:00', '01-01-2025 19:30:00'])
// ->label('Updated DateTime')
// ->rules(['required']),
// ImportColumn::make('operator_id')
// ->requiredMapping()
// ->exampleHeader('Operator ID')
// ->example([Filament::auth()->user()->name, Filament::auth()->user()->name])
// ->label('Operator ID')
// ->rules(['required']),
];
}
@@ -89,6 +100,7 @@ class ProductionPlanImporter extends Importer
{
$warnMsg = [];
$plantCod = $this->data['plant'];
$itemCod = $this->data['item'];
$plant = null;
$line = null;
$block = null;
@@ -103,113 +115,52 @@ class ProductionPlanImporter extends Importer
$warnMsg[] = 'Plant not found';
} else {
$line = Line::where('name', $this->data['line'])->where('plant_id', $plant->id)->first();
// block_reference
$block = Block::where('name', $this->data['block_reference'])->where('plant_id', $plant->id)->first();
}
if (! $line) {
$warnMsg[] = 'Line not found';
}
$shift = null;
if (! $block) {
$warnMsg[] = 'Block not found';
} elseif ($plant) {
$shift = Shift::where('name', $this->data['shift'])->where('plant_id', $plant->id)->where('block_id', $block->id)->first();
if (Str::length($itemCod) < 6 || ! is_numeric($itemCod)) {
$warnMsg[] = 'Invalid item code found';
} else {
$item = Item::where('code', $itemCod)->first();
}
// $shift = Shift::where('id', $this->data['shift'])->where('plant_id', $plant->id)->first();
if (! $shift) {
$warnMsg[] = 'Shift not found';
if (! $item) {
$warnMsg[] = 'Item not found';
}
$plantId = $plant->id;
$itemAgaPlant = Item::where('plant_id', $plantId)->where('code', $itemCod)->first();
if(!$itemAgaPlant){
$warnMsg[] = 'Item not found against plant code';
}
$user = Filament::auth()->user();
$operatorName = $user->name;
if (Str::length($this->data['plan_quantity']) < 0 || ! is_numeric($this->data['plan_quantity']) || $this->data['plan_quantity'] <= 0) {
$warnMsg[] = 'Invalid plan quantity found';
}
if (Str::length($this->data['production_quantity']) < 0 || ! is_numeric($this->data['production_quantity']) || $this->data['production_quantity'] < 0) {
$warnMsg[] = 'Invalid production quantity found';
}
$fromDate = $this->data['created_at'];
$toDate = $this->data['updated_at'];
$formats = ['d-m-Y H:i', 'd-m-Y H:i:s']; // '07-05-2025 08:00' or '07-05-2025 08:00:00'
$fdateTime = null;
$tdateTime = null;
// Try parsing with multiple formats
foreach ($formats as $format) {
try {
$fdateTime = Carbon::createFromFormat($format, $fromDate);
break;
} catch (\Exception $e) {
// Optionally collect warning messages
// $warnMsg[] = "Date format mismatch with format: $format";
}
}
foreach ($formats as $format) {
try {
$tdateTime = Carbon::createFromFormat($format, $toDate);
break;
} catch (\Exception $e) {
// Optionally collect warning messages
// $warnMsg[] = "Date format mismatch with format: $format";
}
}
$fDateOnly = '';
if (! isset($fdateTime)) {
// throw new \Exception('Invalid date time format');
$warnMsg[] = "Invalid 'Created DateTime' format. Expected DD-MM-YYYY HH:MM:SS";
} else {
$fDateOnly = $fdateTime->toDateString();
}
if (! isset($tdateTime)) {
$warnMsg[] = "Invalid 'Updated DateTime' format. Expected DD-MM-YYYY HH:MM:SS";
}
if (isset($fdateTime) && isset($tdateTime)) {
if ($fdateTime->greaterThan($tdateTime)) {
$warnMsg[] = "'Created DataTime' is greater than 'Updated DateTime'.";
}
}
// if (!$fromDate) {
// $warnMsg[] = "Invalid 'Created DateTime' format. Expected DD-MM-YYYY HH:MM:SS";
// }
// else if (!$toDate) {
// $warnMsg[] = "Invalid 'Updated DateTime' format. Expected DD-MM-YYYY HH:MM:SS";
// }
$user = User::where('name', $this->data['operator_id'])->first();
if (! $user) {
$warnMsg[] = 'Operator ID not found';
}
if (! empty($warnMsg)) {
throw new RowImportFailedException(implode(', ', $warnMsg));
} else { // if (empty($warnMsg))
} else {
$productionPlan = ProductionPlan::where('plant_id', $plant->id)
->where('shift_id', $shift->id)
->where('line_id', $line->id)
->whereDate('created_at', $fDateOnly)
// ->where('plan_quantity', $productionQuantity->plan_quantity)
->where('item_id', $itemAgaPlant->id)
->latest()
->first();
if ($productionPlan) {
// if($productionPlan->production_quantity)
// {
// throw new RowImportFailedException("{$productionPlan->created_at}, {$productionPlan->production_quantity}");
// }
// $warnMsg[] = "Production plan already exist on '{$fDateOnly}'!";
$productionPlan->update([
'plan_quantity' => $this->data['plan_quantity'],
// 'production_quantity' => $productionPlan->production_quantity,
// 'created_at' => $productionPlan->created_at,//$fdateTime->format('Y-m-d H:i:s'),
// 'updated_at' => $tdateTime->format('Y-m-d H:i:s'),
'operator_id' => $this->data['operator_id'],
'operator_id' => $operatorName,
]);
$productionPlan->save();
@@ -220,21 +171,15 @@ class ProductionPlanImporter extends Importer
ProductionPlan::updateOrCreate([
'plant_id' => $plant->id,
'line_id' => $line->id,
'shift_id' => $shift->id,
'item_id' => $itemAgaPlant->id,
// 'shift_id' => $shift->id,
'plan_quantity' => $this->data['plan_quantity'],
'production_quantity' => $this->data['production_quantity'],
'created_at' => $fdateTime->format('Y-m-d H:i:s'), // $this->data['created_at'],
'updated_at' => $tdateTime->format('Y-m-d H:i:s'), // $this->data['updated_at'],
'operator_id' => $this->data['operator_id'],
'created_at' =>now(),
'updated_at' => now(),
'operator_id' => $operatorName,
]);
return null;
// return ProductionPlan::firstOrNew([
// // Update existing records, matching them by `$this->data['column_name']`
// 'email' => $this->data['email'],
// ]);
// return new ProductionPlan();
}
public static function getCompletedNotificationBody(Import $import): string

View File

@@ -205,7 +205,7 @@ class StickerMasterImporter extends Importer
} else {
$itemId = $item->id;
if (! $laserPart1) {
if (! $laserPart1 && ! (Str::length($laserPart2) == 1 && is_numeric($laserPart2))) {
$laserPart1 = $laserPart2;
$laserPart2 = null;
}

View File

@@ -0,0 +1,171 @@
<?php
namespace App\Filament\Pages;
use App\Models\CustomerPoMaster;
use App\Models\Plant;
use App\Models\ProductionPlan;
use App\Models\WireMasterPacking;
use Filament\Facades\Filament;
use Filament\Pages\Page;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Form;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Grid;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\ViewField;
use Filament\Notifications\Notification;
use Filament\Forms\Components\Actions\Action;
use Filament\Forms\Components\Hidden;
use Illuminate\Support\Facades\Auth;
class ProductionCalender extends Page
{
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static string $view = 'filament.pages.production-calender';
protected static ?string $navigationGroup = 'Production';
use InteractsWithForms;
protected $listeners = ['setWorkingDays'];
public $pId;
public array $filters = [];
public function setWorkingDays($days = null)
{
$this->form->fill([
'working_days' => $days ?? 0,
]);
}
public function form(Form $form): Form
{
return $form
->statePath('filters')
->schema([
Section::make('')
->schema([
Select::make('plant_id')
->label('Plant')
->reactive()
//->options(Plant::pluck('name', 'id'))
->options(function (callable $get) {
$userHas = Filament::auth()->user()->plant_id;
return ($userHas && strlen($userHas) > 0) ? Plant::where('id', $userHas)->pluck('name', 'id')->toArray() : Plant::pluck('name', 'id')->toArray();
})
->columnSpan(['default' => 10, 'sm' => 7])
->required()
->afterStateUpdated(function ($state, callable $set, callable $get) {
$set('working_days', null);
}),
TextInput::make('working_days')
->label('No. of Working Days')
->numeric()
->readOnly()
->columnSpan(['default' => 10, 'sm' => 2])
->required()
->minValue(0)
->maxValue(31)
->placeholder('Enter working days')
->id('working_days'),
Hidden::make('month')
->label('Month')
->id('month'),
Hidden::make('year')
->label('Year')
->id('year'),
Hidden::make('selected_dates')
->label('Selected Dates')
->id('selected_dates'),
ViewField::make('save')
->view('forms.save')
->columnSpan(['default' => 10, 'sm' => 1]),
ViewField::make('calendar')
->view('forms.calendar')
->columnspan(10),
])
->columns(10)
]);
}
public function saveWorkingDays(){
$plantId = $this->filters['plant_id'] ?? null;
$workingDays = $this->filters['working_days'] ?? null;
$month = $this->filters['month'] ?? null;
$year = $this->filters['year'] ?? null;
$dates = $this->filters['selected_dates'] ?? null;
if (!$plantId) {
Notification::make()
->title('Unknown Plant')
->body("Please select a plant first!")
->danger()
->send();
return;
}
else if (!$workingDays) {
Notification::make()
->title('Unknown Working Days')
->body("Working days can't be empty!")
->danger()
->send();
return;
}
else if (!$month) {
Notification::make()
->title('Unknown Month')
->body("month can't be empty!")
->danger()
->send();
return;
}
else if (!$year) {
Notification::make()
->title('Unknown Year')
->body("Year can't be empty!")
->danger()
->send();
return;
}
$updated = ProductionPlan::where('plant_id', $plantId)
->whereMonth('created_at', $month)
->whereYear('created_at', $year)
->update([
'working_days' => $workingDays,
'leave_dates' => $dates,
'updated_at' => now(),
]);
if ($updated) {
Notification::make()
->title('Success')
->body("Working days updated successfully!")
->success()
->send();
} else {
Notification::make()
->title('No Records Updated')
->body("No production plans found for this plant and month.")
->warning()
->send();
}
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view production calender page');
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,191 @@
<?php
namespace App\Filament\Pages;
use App\Models\Plant;
use Filament\Facades\Filament;
use Filament\Forms\Components\DatePicker;
use Filament\Pages\Page;
use Filament\Forms\Form;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Notifications\Notification;
use Illuminate\Support\Facades\Auth;
class ProductionTarget extends Page
{
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static string $view = 'filament.pages.production-target';
protected static ?string $navigationGroup = 'Production';
public array $filters = [];
public function form(Form $form): Form
{
return $form
->statePath('filters')
->schema([
Section::make('')
->schema([
Select::make('plant_id')
->label('Plant')
->relationship('plant', 'name')
->reactive()
// ->searchable()
->options(function (callable $get) {
$userHas = Filament::auth()->user()->plant_id;
return ($userHas && strlen($userHas) > 0) ? Plant::where('id', $userHas)->pluck('name', 'id')->toArray() : Plant::pluck('name', 'id')->toArray();
})
->required()
->afterStateUpdated(function ($state, callable $get, $set) {
// dd($state);
$set('line_id', null);
$set('year', null);
$set('month', null);
$this->dispatch('loadData',$state, '', '', '');
}),
Select::make('line_id')
->label('Line')
->required()
->relationship('line', 'name')
// ->searchable()
->columnSpan(1)
->options(function (callable $get) {
if (!$get('plant_id')) {
return [];
}
return \App\Models\Line::where('plant_id', $get('plant_id'))
->pluck('name', 'id')
->toArray();
})
->reactive()
->afterStateUpdated(function ($state, callable $get, $set) {
$plantId = $get('plant_id');
$set('year', null);
$set('month', null);
$this->dispatch('loadData',$plantId, $state, '', '');
}),
Select::make('year')
->label('Year')
->reactive()
// ->searchable()
->options([
'2025' => '2025',
'2026' => '2026',
'2027' => '2027',
'2028' => '2028',
'2029' => '2029',
'2030' => '2030',
'2031' => '2031',
'2032' => '2032',
'2033' => '2033',
'2034' => '2034',
'2035' => '2035',
'2036' => '2036',
'2037' => '2037',
'2038' => '2038',
'2039' => '2039',
'2040' => '2040',
])
->required()
->afterStateUpdated(function ($state, callable $get, $set) {
$set('month', null);
$plantId = $get('plant_id');
$lineId = $get('line_id');
$this->dispatch('loadData',$plantId, $lineId, $state, '');
}),
Select::make('month')
->label('Month')
->reactive()
// ->searchable()
->options([
'01' => 'January',
'02' => 'February',
'03' => 'March',
'04' => 'April',
'05' => 'May',
'06' => 'June',
'07' => 'July',
'08' => 'August',
'09' => 'September',
'10' => 'October',
'11' => 'November',
'12' => 'December',
])
->required()
->afterStateUpdated(function ($state, callable $get) {
$plantId = $get('plant_id');
$lineId = $get('line_id');
// $month = $get('month');
$year = $get('year');
$month = (int) $get('month');
if (!$month) {
return;
}
$this->dispatch('loadData', $plantId, $lineId, $month, $year);
}),
])
->columns(4)
]);
}
public function export(){
$plantId = $this->filters['plant_id'] ?? null;
$lineId = $this->filters['line_id'] ?? null;
$year = $this->filters['year'] ?? null;
$month = $this->filters['month'] ?? null;
if (! $plantId) {
Notification::make()
->title('Plant')
->body("please select plant to export data..!")
->danger()
->send();
return;
}
else if (! $lineId) {
Notification::make()
->title('Line')
->body("please select line to export data..!")
->danger()
->send();
return;
}
else if (! $year) {
Notification::make()
->title('Year')
->body("please select year to export data..!")
->danger()
->send();
return;
}
else if (! $month) {
Notification::make()
->title('Month')
->body("please select month to export data..!")
->danger()
->send();
return;
}
$this->dispatch('loadData1' ,$plantId, $lineId, $year, $month);
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view production target page');
}
}

View File

@@ -10,6 +10,7 @@ use App\Models\Item;
use App\Models\Line;
use App\Models\Machine;
use App\Models\Plant;
use App\Models\ProductCharacteristicsMaster;
use Filament\Facades\Filament;
use Filament\Forms;
use Filament\Forms\Components\DateTimePicker;
@@ -24,6 +25,8 @@ use Filament\Tables\Filters\Filter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Illuminate\Validation\Rule;
use Str;
class CharacteristicValueResource extends Resource
{
@@ -39,18 +42,29 @@ class CharacteristicValueResource extends Resource
->schema([
Forms\Components\Select::make('plant_id')
->label('Plant')
->searchable()
->relationship('plant', 'name')
->options(function (callable $get) {
$userHas = Filament::auth()->user()->plant_id;
return ($userHas && strlen($userHas) > 0) ? Plant::where('id', $userHas)->pluck('name', 'id')->toArray() : Plant::orderBy('code')->pluck('name', 'id')->toArray();
})
->default(function () {
$userHas = Filament::auth()->user()->plant_id;
return ($userHas && strlen($userHas) > 0) ? $userHas : optional(CharacteristicValue::latest()->first())->plant_id;
})
->reactive()
->afterStateUpdated(function ($state, $set, callable $get) {
$plantId = $get('plant_id');
$set('item_id', null);
$set('line_id', null);
$set('item_id', null);
$set('machine_id', null);
$set('process_order', null);
$set('coil_number', null);
$set('observed_value', null);
$set('status', 'NotOk');
$set('updated_by', Filament::auth()->user()?->name);
if (! $plantId) {
$set('poPlantError', 'Please select a plant first.');
}
@@ -63,6 +77,7 @@ class CharacteristicValueResource extends Resource
->required(),
Forms\Components\Select::make('line_id')
->label('Line')
->searchable()
->options(function (callable $get) {
if (! $get('plant_id')) {
return [];
@@ -76,7 +91,13 @@ class CharacteristicValueResource extends Resource
$plantId = $get('plant_id');
$set('item_id', null);
$set('machine_id', null);
$set('process_order', null);
$set('coil_number', null);
$set('observed_value', null);
$set('status', 'NotOk');
$set('updated_by', Filament::auth()->user()?->name);
if (! $plantId) {
$set('line_id', null);
$set('poPlantError', 'Please select a plant first.');
}
})
@@ -84,6 +105,7 @@ class CharacteristicValueResource extends Resource
->required(),
Forms\Components\Select::make('item_id')
->label('Item')
->searchable()
->options(function (callable $get) {
if (! $get('plant_id') || ! $get('line_id')) {
return [];
@@ -96,15 +118,21 @@ class CharacteristicValueResource extends Resource
->afterStateUpdated(function ($state, $set, callable $get) {
$plantId = $get('plant_id');
$set('machine_id', null);
$set('process_order', null);
$set('coil_number', null);
$set('observed_value', null);
$set('status', 'NotOk');
$set('updated_by', Filament::auth()->user()?->name);
if (! $plantId) {
$set('item_id', null);
$set('poPlantError', 'Please select a plant first.');
}
})
->reactive()
->required()
->searchable(),
->required(),
Forms\Components\Select::make('machine_id')
->label('Machine')
->searchable()
->options(function (callable $get) {
if (! $get('plant_id') || ! $get('line_id') || ! $get('item_id')) {
return [];
@@ -119,8 +147,11 @@ class CharacteristicValueResource extends Resource
$plantId = $get('plant_id');
$set('process_order', null);
$set('coil_number', null);
$set('status', null);
$set('observed_value', null);
$set('status', 'NotOk');
$set('updated_by', Filament::auth()->user()?->name);
if (! $plantId) {
$set('machine_id', null);
$set('poPlantError', 'Please select a plant first.');
}
})
@@ -132,8 +163,11 @@ class CharacteristicValueResource extends Resource
->afterStateUpdated(function ($state, $set, callable $get) {
$plantId = $get('plant_id');
$set('coil_number', null);
$set('status', null);
$set('observed_value', null);
$set('status', 'NotOk');
$set('updated_by', Filament::auth()->user()?->name);
if (! $plantId) {
$set('process_order', null);
$set('poPlantError', 'Please select a plant first.');
}
})
@@ -143,7 +177,7 @@ class CharacteristicValueResource extends Resource
// ->reactive()
// ->afterStateUpdated(function ($state, $set, callable $get) {
// $plantId = $get('plant_id');
// $set('status', null);
// $set('status', 'NotOk');
// if (! $plantId) {
// $set('poPlantError', 'Please select a plant first.');
// }
@@ -151,49 +185,119 @@ class CharacteristicValueResource extends Resource
// ->required(),
->label('Coil Number')
->default('0')
->numeric()
->reactive()
->afterStateUpdated(function ($state, $set, callable $get, $livewire) {
$plantId = $get('plant_id');
$processOrder = $get('process_order');
$coilNo = $get('coil_number');
// $coilNo = $get('coil_number');
$set('poPlantError', null);
$set('observed_value', null);
$set('status', 'NotOk');
$set('coilNumberError', null);
$set('updated_by', Filament::auth()->user()?->name);
if (! $plantId) {
$set('coil_number', null);
$set('poPlantError', 'Please select a plant first.');
} elseif (! $processOrder) {
$set('coil_number', null);
$set('poPlantError', null);
} elseif ($coilNo || $coilNo == '0') {
$existing = CharacteristicValue::where('plant_id', $plantId)
->where('process_order', $processOrder)
->where('coil_number', $coilNo)
->first();
}
// elseif ($coilNo || $coilNo == '0') {
// $existing = CharacteristicValue::where('plant_id', $plantId)
// ->where('process_order', $processOrder)
// ->where('coil_number', $coilNo)
// ->first();
if ($existing) {
$set('poPlantError', null);
$set('coil_number', null);
$set('coilNumberError', "Duplicate Coil : '{$coilNo}' found!");
} else {
$set('poPlantError', null);
$set('coilNumberError', null);
}
}
// if ($existing && ! $get('id')) {
// // $set('coil_number', null);
// $set('coilNumberError', "Duplicate Coil : '{$coilNo}' found!");
// } else {
// $set('coilNumberError', null);
// }
// }
})
->extraAttributes(fn ($get) => [
'class' => $get('coilNumberError') ? 'border-red-500' : '',
])
->hint(fn ($get) => $get('coilNumberError') ? $get('coilNumberError') : null)
->hintColor('danger')
->rule(function (callable $get) {
return Rule::unique('characteristic_values', 'coil_number')
->where('plant_id', $get('plant_id'))
->where('process_order', $get('process_order'))
->ignore($get('id')); // Ignore current record during updates
})
->required(),
Forms\Components\TextInput::make('observed_value')
->label('Observed Value')
->reactive()
->afterStateUpdated(function ($state, $set, callable $get) {
$plantId = $get('plant_id');
$itemId = $get('item_id');
$lineId = $get('line_id');
$machineId = $get('machine_id');
$set('updated_by', Filament::auth()->user()?->name);
if (! $plantId || ! $itemId || ! $lineId || ! $machineId) {
$set('observed_value', null);
$set('status', 'NotOk');
return;
}
if (Str::length($state) <= 0 || ! is_numeric($state) || ! preg_match('/^\d+(\.\d+)?$/', $state)
) {
$set('status', 'NotOk');
return;
}
$specVal = ProductCharacteristicsMaster::where('plant_id', $plantId)->where('item_id', $itemId)->where('line_id', $lineId)->where('machine_id', $machineId)->first();
if (! $specVal) {
$set('status', 'NotOk');
return;
}
$lowLimit = $specVal?->lower ?? 0;
$uppLimit = $specVal?->upper ?? 0;
if (Str::length($lowLimit) <= 0 || ! is_numeric($lowLimit) || ! preg_match('/^\d+(\.\d+)?$/', $lowLimit)
) {
$set('status', 'NotOk');
return;
} elseif (Str::length($uppLimit) <= 0 || ! is_numeric($uppLimit) || ! preg_match('/^\d+(\.\d+)?$/', $uppLimit)
) {
$set('status', 'NotOk');
return;
}
if (($lowLimit == 0 && $uppLimit == 0) || ($uppLimit == 0)) {
$set('status', 'NotOk');
return;
}
if ($lowLimit > $state || $uppLimit < $state) {
$set('status', 'NotOk');
return;
}
$set('status', 'Ok');
})
->required(),
Forms\Components\Select::make('status')
Forms\Components\TextInput::make('status')// Select
->label('Status')
->options([
'Ok' => 'OK',
'NotOk' => 'Not Ok',
])
// ->options([
// 'Ok' => 'OK',
// 'NotOk' => 'Not Ok',
// ])
->reactive()
->default('NotOk')
->readOnly()
->required(),
Forms\Components\Hidden::make('created_by')
->label('Created By')
@@ -201,6 +305,9 @@ class CharacteristicValueResource extends Resource
Forms\Components\Hidden::make('updated_by')
->label('Updated By')
->default(Filament::auth()->user()?->name),
Forms\Components\TextInput::make('id')
->hidden()
->readOnly(),
]);
}
@@ -228,7 +335,7 @@ class CharacteristicValueResource extends Resource
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('item.code')
->label('Item')
->label('Item Code')
->searchable()
->alignCenter()
->sortable(),
@@ -247,6 +354,17 @@ class CharacteristicValueResource extends Resource
->searchable()
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('machine.name')
->label('Spec. Value')
// ->searchable()
->formatStateUsing(function ($record) {
$specVal = ProductCharacteristicsMaster::where('plant_id', $record->plant_id)->where('item_id', $record->item_id)->where('line_id', $record->line_id)->where('machine_id', $record->machine_id)->first();
// return $record?->plant_id.'-'.$record?->item_id.'-'.$record->line_id.'-'.$record?->machine_id;
return $specVal?->lower.' - '.$specVal?->upper;
})
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('observed_value')
->label('Observed value')
->searchable()
@@ -255,25 +373,39 @@ class CharacteristicValueResource extends Resource
Tables\Columns\TextColumn::make('status')
->label('Status')
->searchable()
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('created_by')
->label('Created By')
->searchable()
// ->formatStateUsing(function ($record) {
// return empty($record->status == 'Ok') ? 'Ok' : 'Not Ok';
// })
->color(fn (string $state): string => match ($state) {
'Ok' => 'success',
'Not Ok' => 'danger',
'NotOk' => 'danger',
default => 'gray',
})
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('created_at')
->label('Created At')
->alignCenter()
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
->sortable(),
Tables\Columns\TextColumn::make('created_by')
->label('Created By')
->searchable()
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('updated_at')
->label('Updated At')
->alignCenter()
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('updated_by')
->label('Updated By')
->alignCenter()
->searchable()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('deleted_at')
->label('Deleted At')
->alignCenter()
@@ -285,7 +417,6 @@ class CharacteristicValueResource extends Resource
// Tables\Filters\TrashedFilter::make(),
// ])
->filters([
Tables\Filters\TrashedFilter::make(),
Filter::make('advanced_filters')
->label('Advanced Filters')

View File

@@ -43,6 +43,7 @@ class GrMasterResource extends Resource
Forms\Components\Select::make('plant_id')
->label('Plant')
->reactive()
->searchable()
->relationship('plant', 'name')
->options(function (callable $get) {
$userHas = Filament::auth()->user()->plant_id;
@@ -440,7 +441,8 @@ class GrMasterResource extends Resource
return ($currentPage - 1) * $perPage + $rowLoop->iteration;
}),
Tables\Columns\TextColumn::make('plant.name')
->label('Plant')
->label('Plant Name')
->searchable()
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('item.code')
@@ -450,33 +452,41 @@ class GrMasterResource extends Resource
->sortable(),
Tables\Columns\TextColumn::make('gr_number')
->label('GR Number')
->alignCenter()
->searchable()
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('serial_number')
->label('Serial Number')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('created_by')
->label('Created By')
->searchable()
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('status')
->label('Status')
->searchable()
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('created_at')
->label('Created At')
->alignCenter()
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
->sortable(),
Tables\Columns\TextColumn::make('created_by')
->label('Created By')
->searchable()
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('updated_at')
->label('Updated At')
->alignCenter()
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('updated_by')
->label('Updated By')
->alignCenter()
->searchable()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('deleted_at')
->label('Deleted At')
->alignCenter()

View File

@@ -385,6 +385,11 @@ class InvoiceValidationResource extends Resource
->afterStateUpdated(function ($state, callable $set, callable $get) {
$set('invoice_serial_number', null);
$plantId = $get('plant_id');
if (! $plantId) {
$set('invoice_serial_number', null);
return;
}
$plantCode = Plant::find($plantId)?->code ?? null;
$directory = "uploads/temp/{$plantCode}";
@@ -399,7 +404,7 @@ class InvoiceValidationResource extends Resource
->required()
->acceptedFileTypes([
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/vnd.ms-excel', // Legacy .xls fallback if needed
// 'application/vnd.ms-excel', // Legacy .xls fallback if needed
])
->rules(['mimes:xlsx']) // Laravel validation: extension check
->preserveFilenames() // <- this keeps the original filename
@@ -729,6 +734,11 @@ class InvoiceValidationResource extends Resource
->afterStateUpdated(function ($state, callable $set, callable $get) {
$set('invoice_material', null);
$plantId = $get('plant_id');
if (! $plantId) {
$set('invoice_material', null);
return;
}
$plantCode = Plant::find($plantId)?->code ?? null;
$directory = "uploads/temp/{$plantCode}";
@@ -741,10 +751,15 @@ class InvoiceValidationResource extends Resource
FileUpload::make('invoice_material')
->label('Invoice Material')
->required()
->acceptedFileTypes([
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
// 'application/vnd.ms-excel', // Legacy .xls fallback if needed
])
->rules(['mimes:xlsx']) // Laravel validation: extension check
->preserveFilenames() // <- this keeps the original filename
->reactive()
->storeFiles(false) // prevent auto-storing
->disk('local')
->storeFiles(false) // prevent auto-storing, we will store manually
->disk('local') // 'local' refers to the local storage disk defined in config/filesystems.php, typically pointing to storage/app.
->visible(fn (Get $get) => ! empty($get('plant_id')))
->directory(function (callable $get) {
$plant = Plant::find($get('plant_id'));
@@ -752,6 +767,7 @@ class InvoiceValidationResource extends Resource
return "uploads/temp/{$plantCode}";
})
->uploadingMessage('Uploading...')
->helperText('Only .xlsx files are allowed (Excel files).'),
])
->action(function (array $data) {

View File

@@ -5,6 +5,7 @@ namespace App\Filament\Resources;
use App\Filament\Exports\LineExporter;
use App\Filament\Imports\LineImporter;
use App\Filament\Resources\LineResource\Pages;
use App\Models\Block;
use App\Models\Line;
use App\Models\Plant;
use App\Models\WorkGroupMaster;
@@ -71,6 +72,38 @@ class LineResource extends Resource
])
->hint(fn ($get) => $get('lPlantError') ? $get('lPlantError') : null)
->hintColor('danger'),
Forms\Components\Select::make('block_id')
->label('Block')
->relationship('block', 'name')
// ->required()
// ->nullable(),
->reactive()
->options(function (callable $get) {
if (! $get('plant_id')) {
return [];
}
return Block::where('plant_id', $get('plant_id'))
->pluck('name', 'id')
->toArray();
})
->default(function () {
return optional(Block::latest()->first())->plant_id;
})
->afterStateUpdated(function ($state, callable $set, callable $get) {
$blockId = $get('block_id');
if (! $blockId) {
$set('lblockError', 'Please select a Block first.');
return;
} else {
$set('lblockError', null);
}
})
->extraAttributes(fn ($get) => [
'class' => $get('lblockError') ? 'border-red-500' : '',
])
->hint(fn ($get) => $get('lblockError') ? $get('lblockError') : null)
->hintColor('danger'),
Forms\Components\TextInput::make('name')
->required()
->placeholder('Scan the valid name')
@@ -1012,6 +1045,11 @@ class LineResource extends Resource
->alignCenter()
->sortable()
->searchable(),
Tables\Columns\TextColumn::make('block.name')
->label('Block')
->alignCenter()
->sortable()
->searchable(),
Tables\Columns\TextColumn::make('name')
->label('Line')
->alignCenter()

View File

@@ -9,6 +9,7 @@ use App\Models\Item;
use App\Models\Line;
use App\Models\Plant;
use App\Models\ProcessOrder;
use Closure;
use Filament\Facades\Filament;
use Filament\Forms;
use Filament\Forms\Components\Actions\Action;
@@ -27,9 +28,11 @@ use Filament\Tables\Filters\Filter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Illuminate\Validation\Rule;
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
use Smalot\PdfParser\Parser;
use Storage;
use Str;
// use App\Models\PalletValidation;
// use Dom\Text;
@@ -48,22 +51,38 @@ class ProcessOrderResource extends Resource
->schema([
Forms\Components\Select::make('plant_id')
->label('Plant')
->searchable()
->relationship('plant', 'name')
->options(function (callable $get) {
$userHas = Filament::auth()->user()->plant_id;
return ($userHas && strlen($userHas) > 0) ? Plant::where('id', $userHas)->pluck('name', 'id')->toArray() : Plant::orderBy('code')->pluck('name', 'id')->toArray();
})
->default(function () {
$userHas = Filament::auth()->user()->plant_id;
return ($userHas && strlen($userHas) > 0) ? $userHas : optional(ProcessOrder::latest()->first())->plant_id;
})
->reactive()
->afterStateUpdated(function ($state, $set, callable $get, $livewire) {
$plantId = $get('plant_id');
$set('coil_number', null);
$set('item_id', null);
$set('line_id', null);
$set('item_description', null);
$set('item_uom', null);
$set('process_order', null);
$set('coil_number', '0');
$set('order_quantity', '0');
$set('received_quantity', '0');
$set('scrap_quantity', '0');
$set('sfg_number', null);
$set('machine_name', null);
if (! $plantId) {
$set('poPlantError', 'Please select a plant first.');
$set('coilNumberError', null);
$set('sfgNumberError', null);
} else {
$set('poPlantError', null);
}
$set('updated_by', Filament::auth()->user()?->name);
})
@@ -75,6 +94,7 @@ class ProcessOrderResource extends Resource
->required(),
Forms\Components\Select::make('line_id')
->label('Line')
->searchable()
->options(function (callable $get) {
$plantId = $get('plant_id');
if (empty($plantId)) {
@@ -89,8 +109,10 @@ class ProcessOrderResource extends Resource
$set('item_description', null);
$set('item_uom', null);
$set('process_order', null);
$set('order_quantity', null);
$set('received_quantity', null);
$set('coil_number', '0');
$set('order_quantity', '0');
$set('received_quantity', '0');
$set('scrap_quantity', '0');
$set('sfg_number', null);
$set('machine_name', null);
$set('updated_by', Filament::auth()->user()?->name);
@@ -113,7 +135,13 @@ class ProcessOrderResource extends Resource
->afterStateUpdated(function (callable $set, callable $get, ?string $state) {
$plantId = $get('plant_id');
$itemId = $get('item_id');
// dd($plantId);
$set('process_order', null);
$set('coil_number', '0');
$set('order_quantity', '0');
$set('received_quantity', '0');
$set('scrap_quantity', '0');
$set('sfg_number', null);
$set('machine_name', null);
if ($plantId && $itemId) {
// Get the item code using item_id
@@ -141,6 +169,7 @@ class ProcessOrderResource extends Resource
Forms\Components\TextInput::make('item_description')
->label('Description')
->readOnly()
->required()
->reactive()
->afterStateHydrated(function ($component, $state, Get $get, Set $set) {
@@ -181,21 +210,42 @@ class ProcessOrderResource extends Resource
->reactive()
->numeric()
->length(12)
->readOnly(fn ($get) => ($get('plant_id') == null || $get('item_id') == null || $get('line_id') == null))
->afterStateUpdated(function ($state, $set, callable $get, $livewire) {
$plantId = $get('plant_id');
$set('coil_number', null);
$set('coil_number', '0');
$set('order_quantity', '0');
$set('received_quantity', '0');
$set('scrap_quantity', '0');
$set('sfg_number', null);
$set('machine_name', null);
if (! $plantId) {
$set('poPlantError', 'Please select a plant first.');
$set('process_order', null);
$set('coilNumberError', null);
$set('sfgNumberError', null);
// if (! $plantId) {
// $set('poPlantError', 'Please select a plant first.');
// $set('process_order', null);
// $set('coilNumberError', null);
// $set('sfgNumberError', null);
// return;
// }
$itemId = $get('item_id');
$processOrder = trim($get('process_order'));
if (! $itemId || ! $processOrder) {
return;
}
$orderExist = ProcessOrder::where('plant_id', $plantId)
->where('process_order', $processOrder)
->where('item_id', $itemId)->latest()->first();
// ->value('order_quantity') ?? 0;
if ($orderExist) {
$set('order_quantity', $orderExist->order_quantity ?? 0);
}
$set('updated_by', Filament::auth()->user()?->name);
})
->rule(function (callable $get) {
return function (string $attribute, $value, \Closure $fail) use ($get) {
return function (string $attribute, $value, Closure $fail) use ($get) {
$plantId = $get('plant_id');
$itemId = $get('item_id');
@@ -226,54 +276,99 @@ class ProcessOrderResource extends Resource
Forms\Components\TextInput::make('coil_number')
->label('Coil Number')
->default('0')
->required()
->reactive()
->numeric()
->readOnly(fn ($get) => ($get('process_order') == null))
->afterStateUpdated(function ($state, $set, callable $get, $livewire) {
$plantId = $get('plant_id');
$processOrder = $get('process_order');
$coilNo = $get('coil_number');
// $coilNo = $get('coil_number');
if (! $plantId) {
$set('poPlantError', 'Please select a plant first.');
$set('coil_number', null);
$set('sfg_number', null);
$set('machine_name', null);
$set('coilNumberError', null);
$set('sfgNumberError', null);
$set('coil_number', '0');
} elseif (! $processOrder) {
$set('coil_number', null);
$set('poPlantError', null);
$set('coil_number', '0');
}
$set('received_quantity', '0');
$set('scrap_quantity', '0');
$set('sfg_number', null);
$set('machine_name', null);
$set('poPlantError', null);
$set('coilNumberError', null);
$set('sfgNumberError', null);
} elseif ($coilNo || $coilNo == '0') {
$existing = ProcessOrder::where('plant_id', $plantId)
->where('process_order', $processOrder)
->where('coil_number', $coilNo)
->first();
// elseif ($coilNo || $coilNo == 0) {
// $existing = ProcessOrder::where('plant_id', $plantId)
// ->where('process_order', $processOrder)
// ->where('coil_number', $coilNo)
// ->first();
if ($existing) {
$set('poPlantError', null);
$set('coil_number', null);
$set('coilNumberError', "Duplicate Coil : '{$coilNo}' found!");
} else {
$set('poPlantError', null);
$set('coilNumberError', null);
}
}
// if ($existing) {
// $set('poPlantError', null);
// $set('coil_number', '0');
// $set('coilNumberError', "Duplicate Coil : '{$coilNo}' found!");
// } else {
// $set('poPlantError', null);
// $set('coilNumberError', null);
// }
// }
$set('updated_by', Filament::auth()->user()?->name);
})
->rules([
function (callable $get) {
return Rule::unique('process_orders', 'coil_number')
->where('plant_id', $get('plant_id'))
->where('process_order', $get('process_order'))
->ignore($get('id'));
},
function (callable $get): Closure {
return function (string $attribute, $value, Closure $fail) use ($get) {
$rework = $get('rework_status');
if ($value && Str::contains($value, '.') && $rework == 0) {
$fail("Rework status should be 'Yes' for rework coil number '{$value}'!");
}
};
},
])
// ->rule(function (callable $get) {
// return Rule::unique('process_orders', 'coil_number')
// ->where('plant_id', $get('plant_id'))
// ->where('process_order', $get('process_order'))
// ->ignore($get('id'));
// })
->extraAttributes(fn ($get) => [
'class' => $get('coilNumberError') ? 'border-red-500' : '',
])
->hint(fn ($get) => $get('coilNumberError') ? $get('coilNumberError') : null)
->hintColor('danger')
->required(),
->hintColor('danger'),
Forms\Components\TextInput::make('order_quantity')
->label('Order Quantity')
->default('1.000')
->required()
->reactive()
->numeric()
->readOnly(fn ($get) => ($get('process_order') == null))
->afterStateUpdated(function (callable $set, callable $get, ?string $state) {
$plantId = $get('plant_id');
$itemId = $get('item_id');
$processOrder = trim($get('process_order'));
$set('received_quantity', '0');
$set('scrap_quantity', '0');
if (! $plantId || ! $itemId || ! $processOrder) {
$set('order_quantity', '0');
}
$query = ProcessOrder::where('plant_id', $plantId)
->where('process_order', $processOrder)
->where('item_id', $itemId);
$orderExist = $query->latest()->first(); // Latest record (reuse base query)
if ($query->count() == 1 && $orderExist && ! $get('id')) {
$set('order_quantity', $orderExist->order_quantity ?? 0);
} elseif ($query->count() > 1 && $orderExist) {
$set('order_quantity', $orderExist->order_quantity ?? 0);
}
$set('updated_by', Filament::auth()->user()?->name);
}),
Forms\Components\TextInput::make('received_quantity')
@@ -281,19 +376,44 @@ class ProcessOrderResource extends Resource
->default('0.000')
->required()
->reactive()
->numeric()
->readOnly(fn ($get) => ($get('process_order') == null))
->afterStateUpdated(function (callable $set, callable $get, ?string $state) {
$set('scrap_quantity', '0');
$set('updated_by', Filament::auth()->user()?->name);
}),
Forms\Components\TextInput::make('scrap_quantity')
->label('Scrap Quantity')
->default('0.000')
->required()
->readOnly(fn ($get) => ($get('rework_status') == 0 || $get('process_order') == null))
->reactive()
->numeric()
->afterStateUpdated(function (callable $set, callable $get, ?string $state) {
$rework = $get('rework_status');
if ($rework == 0) {
$set('scrap_quantity', '0');
}
$set('updated_by', Filament::auth()->user()?->name);
})
->rule(function (callable $get) {
return function (string $attribute, $value, Closure $fail) use ($get) {
$rework = $get('rework_status');
$scrapQty = $value;
// $currentId = $get('id'); // current editing record id
if ($rework == 0 && $scrapQty != 0) {
$fail("Scrap Quanity value should be '0'!");
return;
}
};
}),
Forms\Components\TextInput::make('sfg_number')
->label('SFG Number')
->reactive()
->readOnly(fn ($get) => ($get('process_order') == null))
->afterStateUpdated(function ($state, $set, callable $get, $livewire) {
$plantId = $get('plant_id');
$sfgNo = $get('sfg_number');
@@ -327,6 +447,7 @@ class ProcessOrderResource extends Resource
Forms\Components\TextInput::make('machine_name')
->label('Machine ID')
->reactive()
->readOnly(fn ($get) => ($get('process_order') == null))
->afterStateUpdated(function (callable $set, callable $get, ?string $state) {
$set('updated_by', Filament::auth()->user()?->name);
}),
@@ -337,11 +458,55 @@ class ProcessOrderResource extends Resource
->options([0 => 'No', 1 => 'Yes'])
->reactive()
->afterStateUpdated(function (callable $set, callable $get, ?string $state) {
// if ($get('id') && $get('rework_status') == 1) {
// $set('rework_status', 1);
// }
if ($state == 0) {
$set('scrap_quantity', '0');
}
$set('updated_by', Filament::auth()->user()?->name);
})
->rule(function (callable $get, callable $set) {
return function (string $attribute, $value, Closure $fail) use ($get, $set) {
$plantId = $get('plant_id');
$lineId = $get('line_id');
$processOrder = trim($get('process_order'));
$coilNo = trim($get('coil_number'));
$status = $value;
// $currentId = $get('id'); // current editing record id
if (! $plantId || ! $lineId || ! $processOrder || Str::length($coilNo) <= 0) {
$set('rework_status', 0);
return;
} elseif ($status == 0) {
$existingCoil = ProcessOrder::where('plant_id', $plantId)
->where('line_id', $lineId)
->where('process_order', $processOrder)
->where('coil_number', $coilNo)
->first();
if ($existingCoil && $existingCoil->rework_status == 1 && $get('id')) {
$fail("Rework coil number '{$coilNo}' exist against plant and process order!");
return;
}
}
if (Str::length($coilNo) > 0 && ($status == 1 || Str::contains($coilNo, '.'))) {
$coilMain = explode('.', $coilNo)[0]; // 333
$existingCoil = ProcessOrder::where('plant_id', $plantId)
->where('line_id', $lineId)
->where('process_order', $processOrder)
->where('coil_number', $coilMain)
->first();
if (! $existingCoil) {
$fail("Coil number '{$coilMain}' not exist against plant and process order!");
} elseif ($existingCoil->rework_status == 0 && ! $get('id')) {
$fail("Rework coil number '{$coilMain}' not exist against plant and process order!");
}
}
};
})
->visible(function () {
return Filament::auth()->user()->hasRole('Super Admin'); // || Filament::auth()->user()->can('update process order rework status')
})
@@ -613,7 +778,7 @@ class ProcessOrderResource extends Resource
->label('Advanced Filters')
->form([
Select::make('Plant')
->label('Select Plant')
->label('Select Plant Name')
->nullable()
->options(function (callable $get) {
$userHas = Filament::auth()->user()->plant_id;
@@ -643,27 +808,46 @@ class ProcessOrderResource extends Resource
}),
TextInput::make('process_order')
->label('Process Order')
->placeholder('Enter Process Order'),
->reactive()
->placeholder('Enter Process Order')
->afterStateUpdated(function ($state, callable $set, callable $get) {
$set('Rework', null);
}),
TextInput::make('coil_number')
->label('Coil Number')
->reactive()
->placeholder('Enter Coil Number'),
TextInput::make('sfg_number')
->label('Sfg Number')
->placeholder(placeholder: 'Enter Sfg Number'),
->label('SFG Number')
->reactive()
->placeholder('Enter SFG Number'),
TextInput::make('machine_name')
->label('Machine Name')
->placeholder(placeholder: 'Enter Machine Name'),
->reactive()
->placeholder('Enter Machine Name'),
Select::make('rework_status')
->label('Search by Rework Status')
->nullable()
->searchable()
->reactive()
->options([
1 => 'Yes',
0 => 'No',
]),
DateTimePicker::make(name: 'created_from')
->label('Created From')
->placeholder(placeholder: 'Select From DateTime')
->placeholder('Select From DateTime')
->reactive()
->native(false),
DateTimePicker::make('created_to')
->label('Created To')
->placeholder(placeholder: 'Select To DateTime')
->placeholder('Select To DateTime')
->reactive()
->native(false),
])
->query(function ($query, array $data) {
// Hide all records initially if no filters are applied
if (empty($data['Plant']) && empty($data['Item']) && empty($data['process_order']) && empty($data['sfg_number']) && empty($data['created_from']) && empty($data['created_to']) && empty($data['machine_name'])) {
if (empty($data['Plant']) && empty($data['Item']) && empty($data['process_order']) && Str::length($data['coil_number']) <= 0 && empty($data['sfg_number']) && empty($data['machine_name']) && ($data['rework_status'] == null || $data['rework_status'] == '') && empty($data['created_from']) && empty($data['created_to'])) {
return $query->whereRaw('1 = 0');
}
@@ -682,11 +866,16 @@ class ProcessOrderResource extends Resource
}
if (! empty($data['process_order'])) {
$query->where('process_order', $data['process_order']);
$query->where('process_order', 'like', '%'.$data['process_order'].'%');
}
if (Str::length($data['coil_number']) > 0) {
// $query->where('machine_name', $data['machine_name']);
$query->where('coil_number', 'like', '%'.$data['coil_number'].'%');
}
if (! empty($data['sfg_number'])) {
$query->where('sfg_number', $data['sfg_number']);
$query->where('sfg_number', 'like', '%'.$data['sfg_number'].'%');
}
if (! empty($data['machine_name'])) {
@@ -694,6 +883,10 @@ class ProcessOrderResource extends Resource
$query->where('machine_name', 'like', '%'.$data['machine_name'].'%');
}
if ($data['rework_status'] != null && $data['rework_status'] != '') {
$query->where('rework_status', $data['rework_status']);
}
if (! empty($data['created_from'])) {
$query->where('created_at', '>=', $data['created_from']);
}
@@ -724,14 +917,22 @@ class ProcessOrderResource extends Resource
$indicators[] = 'Process Order: '.$data['process_order'];
}
if (Str::length($data['coil_number']) > 0) {
$indicators[] = 'Coil Number: '.$data['coil_number'];
}
if (! empty($data['sfg_number'])) {
$indicators[] = 'Sfg Number: '.$data['sfg_number'];
$indicators[] = 'SFG Number: '.$data['sfg_number'];
}
if (! empty($data['machine_name'])) {
$indicators[] = 'Machine Name: '.$data['machine_name'];
}
if ($data['rework_status'] != null && $data['rework_status'] != '') {
$indicators[] = ($data['rework_status'] == 1) ? 'Rework Status: Yes' : 'Rework Status: No';
}
if (! empty($data['created_from'])) {
$indicators[] = 'From: '.$data['created_from'];
}

View File

@@ -43,11 +43,20 @@ class ProductCharacteristicsMasterResource extends Resource
Forms\Components\Select::make('plant_id')
->label('Plant')
->relationship('plant', 'name')
->searchable()
->options(function (callable $get) {
$userHas = Filament::auth()->user()->plant_id;
return ($userHas && strlen($userHas) > 0) ? Plant::where('id', $userHas)->pluck('name', 'id')->toArray() : Plant::orderBy('code')->pluck('name', 'id')->toArray();
})
->default(function () {
$userHas = Filament::auth()->user()->plant_id;
return ($userHas && strlen($userHas) > 0) ? $userHas : optional(ProductCharacteristicsMaster::latest()->first())->plant_id;
})
->afterStateUpdated(function ($state, callable $set) {
$set('updated_by', Filament::auth()->user()?->name);
})
->reactive()
->required(),
Forms\Components\Select::make('item_id')
@@ -63,10 +72,14 @@ class ProductCharacteristicsMasterResource extends Resource
return \App\Models\Item::where('plant_id', $plantId)->pluck('code', 'id');
})
->afterStateUpdated(function ($state, callable $set) {
$set('updated_by', Filament::auth()->user()?->name);
})
->required(),
Forms\Components\Select::make('line_id')
->label('Line')
->reactive()
->searchable()
->options(function (callable $get) {
$plantId = $get('plant_id');
if (empty($plantId)) {
@@ -77,10 +90,10 @@ class ProductCharacteristicsMasterResource extends Resource
})
->afterStateUpdated(function ($state, callable $set, callable $get) {
$set('machine_id', null);
if (! $get('work_group_master_id')) {
$set('machine_id', null);
}
$set('updated_by', Filament::auth()->user()?->name);
})
->required(),
// ->relationship('line', 'name'),
@@ -88,6 +101,7 @@ class ProductCharacteristicsMasterResource extends Resource
->label('Group Work Center')
->required()
->reactive()
->searchable()
->options(function (callable $get) {
if (! $get('plant_id') || ! $get('line_id')) {
return [];
@@ -107,6 +121,7 @@ class ProductCharacteristicsMasterResource extends Resource
->disabled(fn (Get $get) => ! empty($get('id')))
->afterStateUpdated(function ($state, callable $set, callable $get) {
$lineId = $get('line_id');
$set('updated_by', Filament::auth()->user()?->name);
if (! $lineId) {
$set('mGroupWorkError', 'Please select a line first.');
$set('machine_id', null);
@@ -133,8 +148,8 @@ class ProductCharacteristicsMasterResource extends Resource
Forms\Components\Select::make('machine_id')
->label('Work Center')
// ->relationship('machine', 'name'),
->searchable()
->reactive()
->searchable()
->options(function (callable $get) {
$plantId = $get('plant_id');
$lineId = $get('line_id');
@@ -153,6 +168,7 @@ class ProductCharacteristicsMasterResource extends Resource
if (! $get('plant_id') || ! $get('line_id') || ! $get('work_group_master_id')) {
$set('machine_id', null);
}
$set('updated_by', Filament::auth()->user()?->name);
})
->required(),
Forms\Components\Select::make('characteristics_type')
@@ -162,16 +178,30 @@ class ProductCharacteristicsMasterResource extends Resource
'Process' => 'Process',
])
->reactive()
->searchable()
// ->preload()
->afterStateUpdated(function ($state, callable $set) {
$set('updated_by', Filament::auth()->user()?->name);
})
->required(),
Forms\Components\TextInput::make('name')
->label('Name'),
->label('Name')
->reactive()
->afterStateUpdated(function ($state, callable $set) {
$set('updated_by', Filament::auth()->user()?->name);
}),
Forms\Components\Select::make('inspection_type')
->label('Inspection Type')
->searchable()
->options([
'Visual' => 'Visual',
'Value' => 'Value',
])
->reactive()
// ->preload()
->afterStateUpdated(function ($state, callable $set) {
$set('updated_by', Filament::auth()->user()?->name);
})
->required(),
// Forms\Components\Select::make('result')
// ->label('Visual Type')
@@ -197,7 +227,11 @@ class ProductCharacteristicsMasterResource extends Resource
->default(0.0)
->minValue(0.0)
->maxValue(fn (Get $get) => $get('upper') ?? PHP_INT_MAX)
->afterStateUpdated(fn ($state, callable $set, callable $get) => $set('middle', ($state + $get('upper')) / 2))
// ->afterStateUpdated(fn ($state, callable $set, callable $get) => $set('middle', ($state + $get('upper')) / 2))
->afterStateUpdated(function ($state, callable $set, callable $get) {
$set('middle', ($state + $get('upper')) / 2);
$set('updated_by', Filament::auth()->user()?->name);
})
->visible(fn (callable $get) => $get('inspection_type') == 'Value'),
Forms\Components\TextInput::make('upper')
->label('Upper')
@@ -206,7 +240,11 @@ class ProductCharacteristicsMasterResource extends Resource
->default(0.0)
->minValue(fn (Get $get) => $get('lower') ?? 0)
->maxValue(PHP_INT_MAX)
->afterStateUpdated(fn ($state, callable $set, callable $get) => $set('middle', ($get('lower') + $state) / 2))
// ->afterStateUpdated(fn ($state, callable $set, callable $get) => $set('middle', ($get('lower') + $state) / 2))
->afterStateUpdated(function ($state, callable $set, callable $get) {
$set('middle', ($get('lower') + $state) / 2);
$set('updated_by', Filament::auth()->user()?->name);
})
->visible(fn (callable $get) => $get('inspection_type') == 'Value'),
Forms\Components\TextInput::make('middle')
->label('Middle')
@@ -228,12 +266,19 @@ class ProductCharacteristicsMasterResource extends Resource
// };
// })
->dehydrateStateUsing(fn ($state, Get $get) => ($get('lower') + $get('upper')) / 2)
->afterStateUpdated(function ($state, callable $set) {
$set('updated_by', Filament::auth()->user()?->name);
})
->visible(fn (callable $get) => $get('inspection_type') == 'Value'),
Forms\Components\Hidden::make('created_by')
->label('Created By')
->default(Filament::auth()->user()?->name),
Forms\Components\Hidden::make('updated_by')
->label('Updated By'),
->label('Updated By')
->default(Filament::auth()->user()?->name),
Forms\Components\TextInput::make('id')
->hidden()
->readOnly(),
]);
}
@@ -308,11 +353,11 @@ class ProductCharacteristicsMasterResource extends Resource
->label('Created At')
->alignCenter()
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
->sortable(),
Tables\Columns\TextColumn::make('created_by')
->label('Created By')
->alignCenter()
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('updated_at')
->label('Updated At')
@@ -323,6 +368,7 @@ class ProductCharacteristicsMasterResource extends Resource
Tables\Columns\TextColumn::make('updated_by')
->label('Updated By')
->alignCenter()
->searchable()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('deleted_at')

View File

@@ -15,27 +15,30 @@ class EditProductCharacteristicsMaster extends EditRecord
return 'Edit Characteristics'; // This will replace the "New product characteristics master"
}
public function mount(int|string $record): void
{
parent::mount($record);
// public function mount(int|string $record): void
// {
// parent::mount($record);
$model = $this->getRecord(); // actual model instance
// $model = $this->getRecord(); // actual model instance
// Step 1: Fill the actual saved fields first
$this->form->fill([
'plant_id' => $model->plant_id,
'line_id' => $model->line_id,
'item_id' => $model->item_id,
'machine_id' => $model->machine_id,
'name' => $model->name,
'type' => $model->type,
'upper' => $model->upper,
'lower' => $model->lower,
'middle' => $model->middle,
'work_group_master_id' => optional($model->machine)->work_group_master_id,
]);
}
// // Step 1: Fill the actual saved fields first
// $this->form->fill([
// 'plant_id' => $model->plant_id,
// 'item_id' => $model->item_id,
// 'line_id' => $model->line_id,
// 'machine_id' => $model->machine_id,
// 'name' => $model->name,
// 'characteristics_type' => $model->characteristics_type,
// 'inspection_type' => $model->inspection_type,
// // 'type' => $model->type,
// 'upper' => $model->upper,
// 'lower' => $model->lower,
// 'middle' => $model->middle,
// 'created_by' => $model->created_by,
// 'updated_by' => $model->updated_by,
// 'work_group_master_id' => optional($model->machine)->work_group_master_id,
// ]);
// }
protected function getHeaderActions(): array
{

View File

@@ -7,6 +7,7 @@ use App\Filament\Exports\ProductionPlanExporter;
use App\Filament\Imports\ProductionPlanImporter;
use App\Filament\Resources\ProductionPlanResource\Pages;
use App\Models\Block;
use App\Models\Item;
use App\Models\Line;
use App\Models\Plant;
use App\Models\ProductionPlan;
@@ -77,97 +78,6 @@ class ProductionPlanResource extends Resource
])
->hint(fn ($get) => $get('ppPlantError') ? $get('ppPlantError') : null)
->hintColor('danger'),
Forms\Components\Select::make('block_name')
->required()
// ->nullable()
->label('Block')
->options(function (callable $get) {
if (! $get('plant_id')) {
return [];
}
return Block::where('plant_id', $get('plant_id'))
->pluck('name', 'id')
->toArray();
})
->reactive()
->default(function () {
$latestShiftId = optional(ProductionPlan::latest()->first())->shift_id;
return optional(Shift::where('id', $latestShiftId)->first())->block_id;
})
// ->afterStateUpdated(fn ($set) => $set('shift_id', null))
->afterStateUpdated(function ($state, callable $set, callable $get) {
if ($get('id')) {
$getShift = ProductionPlan::where('id', $get('id'))->first();
$getBlock = Shift::where('id', $getShift->shift_id)->first();
if ($getBlock->block_id) {
$set('block_name', $getBlock->block_id);
$set('ppBlockError', null);
}
}
$blockId = $get('block_name');
$set('shift_id', null);
if (! $blockId) {
$set('ppBlockError', 'Please select a block first.');
return;
} else {
$set('ppBlockError', null);
}
})
->extraAttributes(fn ($get) => [
'class' => $get('ppBlockError') ? 'border-red-500' : '',
])
->hint(fn ($get) => $get('ppBlockError') ? $get('ppBlockError') : null)
->hintColor('danger'),
Forms\Components\Select::make('shift_id')
->relationship('shift', 'name')
->required()
// ->nullable()
->autofocus(true)
->options(function (callable $get) {
if (! $get('plant_id') || ! $get('block_name')) {
return [];
}
return Shift::where('plant_id', $get('plant_id'))
->where('block_id', $get('block_name'))
->pluck('name', 'id')
->toArray();
})
->reactive()
->default(function () {
return optional(ProductionPlan::latest()->first())->shift_id;
})
// ->afterStateUpdated(fn ($set) => $set('line_id', null))
->afterStateUpdated(function ($state, callable $set, callable $get) {
if ($get('id')) {
$getShift = ProductionPlan::where('id', $get('id'))->first();
if ($getShift->shift_id) {
$set('shift_id', $getShift->shift_id);
$set('ppShiftError', null);
}
}
$curShiftId = $get('shift_id');
$set('line_id', null);
if (! $curShiftId) {
$set('ppShiftError', 'Please select a shift first.');
return;
} else {
$set('ppShiftError', null);
}
})
->extraAttributes(fn ($get) => [
'class' => $get('ppShiftError') ? 'border-red-500' : '',
])
->hint(fn ($get) => $get('ppShiftError') ? $get('ppShiftError') : null)
->hintColor('danger'),
Forms\Components\Select::make('line_id')
->relationship('line', 'name')
->required()
@@ -178,7 +88,7 @@ class ProductionPlanResource extends Resource
// ->toArray() // Convert collection to array
// )
->options(function (callable $get) {
if (! $get('plant_id') || ! $get('block_name') || ! $get('shift_id')) {
if (! $get('plant_id')) {
return [];
}
@@ -190,198 +100,81 @@ class ProductionPlanResource extends Resource
// ->default(function () {
// return optional(ProductionPlan::latest()->first())->line_id;
// })
->afterStateUpdated(function ($state, callable $set, callable $get) {
if ($get('id')) {
$getShift = ProductionPlan::where('id', $get('id'))->first();
if ($getShift->line_id) {
$set('line_id', $getShift->line_id);
$set('ppLineError', null);
}
} else {
$currentDT = Carbon::now()->toDateTimeString();
$set('created_at', $currentDT);
$set('update_date', null);
}
// ->afterStateUpdated(function ($state, callable $set, callable $get) {
// if ($get('id')) {
// $getShift = ProductionPlan::where('id', $get('id'))->first();
// if ($getShift->line_id) {
// $set('line_id', $getShift->line_id);
// $set('ppLineError', null);
// }
// } else {
// $currentDT = Carbon::now()->toDateTimeString();
// $set('created_at', $currentDT);
// $set('update_date', null);
// }
$lineId = $get('line_id');
// $set('plan_quantity', null);
// $lineId = $get('line_id');
// // $set('plan_quantity', null);
if (! $lineId) {
$set('ppLineError', 'Please select a line first.');
return;
} else {
$isUpdate = ! empty($get('id'));
if (! $isUpdate) {
$exists = ProductionPlan::where('plant_id', $get('plant_id'))
->where('shift_id', $get('shift_id'))
->where('line_id', $get('line_id'))
->whereDate('created_at', today())
->latest()
->exists();
if ($exists) {
$set('line_id', null);
$set('ppLineError', 'Production plan already updated.');
return;
} else {
$existShifts = ProductionPlan::where('plant_id', $get('plant_id'))
->where('shift_id', $get('shift_id'))
->where('line_id', $get('line_id'))
->whereDate('created_at', Carbon::yesterday())
->latest()
->exists();
if ($existShifts) { // if ($existShifts->count() > 0)
// $currentDate = date('Y-m-d');
$yesterday = date('Y-m-d', strtotime('-1 days'));
$shiftId = Shift::where('id', $get('shift_id'))
->first();
[$hRs, $miNs] = explode('.', $shiftId->duration) + [0, 0];
$hRs = (int) $hRs;
// $miNs = (int) $miNs;-*/
$totalMinutes = $hRs * 60 + $miNs;
$from_dt = $yesterday.' '.$shiftId->start_time;
$to_dt = date('Y-m-d H:i:s', strtotime($from_dt." + $totalMinutes minutes"));
$currentDateTime = date('Y-m-d H:i:s');
// Check if current date time is within the range
if ($currentDateTime >= $from_dt && $currentDateTime < $to_dt) {
// echo "Choosed a valid shift...";
$set('line_id', null);
$set('ppLineError', 'Production plan already updated.');
// $set('ppLineError', 'Valid (From: '.$from_dt.', To: '.$to_dt.')');
return;
} else {
$currentDate = date('Y-m-d');
$shiftId = Shift::where('id', $get('shift_id'))
->first();
[$hRs, $miNs] = explode('.', $shiftId->duration) + [0, 0];
$hRs = (int) $hRs;
// $miNs = (int) $miNs;-*/
$totalMinutes = $hRs * 60 + $miNs;
$from_dt = $currentDate.' '.$shiftId->start_time;
$to_dt = date('Y-m-d H:i:s', strtotime($from_dt." + $totalMinutes minutes"));
$currentDateTime = date('Y-m-d H:i:s');
// Check if current date time is within the range
if (! ($currentDateTime >= $from_dt && $currentDateTime < $to_dt)) {
// echo "Choosed a valid shift...";
$set('line_id', null);
$set('ppLineError', 'Choosed a invalid shift.');
// $set('ppLineError', 'Valid (From: '.$from_dt.', To: '.$to_dt.')');
return;
}
}
$set('ppLineError', null);
return;
} else {
// $currentDate = date('Y-m-d');
$yesterday = date('Y-m-d', strtotime('-1 days'));
$shiftId = Shift::where('id', $get('shift_id'))
->first();
[$hRs, $miNs] = explode('.', $shiftId->duration) + [0, 0];
$hRs = (int) $hRs;
// $miNs = (int) $miNs;-*/
$totalMinutes = $hRs * 60 + $miNs;
$from_dt = $yesterday.' '.$shiftId->start_time;
$to_dt = date('Y-m-d H:i:s', strtotime($from_dt." + $totalMinutes minutes"));
$currentDateTime = date('Y-m-d H:i:s');
// Check if current date time is within the range
if ($currentDateTime >= $from_dt && $currentDateTime < $to_dt) {
// echo "Choosed a valid shift...";
// here i'm updating created as yesterday
$set('created_at', $from_dt);
$set('update_date', '1');
$set('ppLineError', null);
// $set('ppLineError', 'Valid (From: '.$from_dt.', To: '.$to_dt.')');
return;
} else {
$currentDate = date('Y-m-d');
$shiftId = Shift::where('id', $get('shift_id'))
->first();
[$hRs, $miNs] = explode('.', $shiftId->duration) + [0, 0];
$hRs = (int) $hRs;
// $miNs = (int) $miNs;-*/
$totalMinutes = $hRs * 60 + $miNs;
$from_dt = $currentDate.' '.$shiftId->start_time;
$to_dt = date('Y-m-d H:i:s', strtotime($from_dt." + $totalMinutes minutes"));
$currentDateTime = date('Y-m-d H:i:s');
// Check if current date time is within the range
if (! ($currentDateTime >= $from_dt && $currentDateTime < $to_dt)) {
// echo "Choosed a valid shift...";
$set('line_id', null);
$set('ppLineError', 'Choosed a invalid shift.');
// $set('ppLineError', 'Valid (From: '.$from_dt.', To: '.$to_dt.')');
return;
}
}
$set('ppLineError', null);
return;
}
// if (! $lineId) {
// $set('ppLineError', 'Please select a line first.');
// return;
// } else {
// $isUpdate = ! empty($get('id'));
// if (! $isUpdate) {
// $exists = ProductionPlan::where('plant_id', $get('plant_id'))
// //->where('shift_id', $get('shift_id'))
// ->where('shift_id', $get('shift_id'))
// ->where('line_id', $get('line_id'))
// ->whereDate('created_at', today())
// ->latest() // Orders by created_at DESC
// ->latest()
// ->exists();
// if ($exists) {
// $set('line_id', null);
// $set('ppLineError', 'Production plan already updated.');
// return;
// } else {
// $existShifts = ProductionPlan::where('plant_id', $get('plant_id'))
// ->where('shift_id', $get('shift_id'))
// ->where('line_id', $get('line_id'))
// ->whereDate('created_at', Carbon::yesterday())
// ->latest()
// ->exists();
// if ($existShifts) { // if ($existShifts->count() > 0)
// // $currentDate = date('Y-m-d');
// $yesterday = date('Y-m-d', strtotime('-1 days'));
// $shiftId = Shift::where('id', $get('shift_id'))
// ->first();
// if ($exists)
// {
// $existingShifts = ProductionPlan::where('plant_id', $get('plant_id'))
// //->where('shift_id', $get('shift_id'))
// ->where('line_id', $get('line_id'))
// // ->whereDate('created_at', today())
// ->whereDate('created_at', today())
// ->get();
// [$hRs, $miNs] = explode('.', $shiftId->duration) + [0, 0];
// $hRs = (int) $hRs;
// // $miNs = (int) $miNs;-*/
// foreach ($existingShifts as $shift) {
// $curShiftId = $shift->shift_id;
// $totalMinutes = $hRs * 60 + $miNs;
// $from_dt = $yesterday.' '.$shiftId->start_time;
// $to_dt = date('Y-m-d H:i:s', strtotime($from_dt." + $totalMinutes minutes"));
// $currentDateTime = date('Y-m-d H:i:s');
// // Check if current date time is within the range
// if ($currentDateTime >= $from_dt && $currentDateTime < $to_dt) {
// // echo "Choosed a valid shift...";
// $set('line_id', null);
// $set('ppLineError', 'Production plan already updated.');
// // $set('ppLineError', 'Valid (From: '.$from_dt.', To: '.$to_dt.')');
// return;
// } else {
// $currentDate = date('Y-m-d');
// $shiftId = \App\Models\Shift::where('id', $curShiftId)
// $shiftId = Shift::where('id', $get('shift_id'))
// ->first();
// [$hRs, $miNs] = explode('.', $shiftId->duration) + [0, 0];
@@ -397,32 +190,167 @@ class ProductionPlanResource extends Resource
// $currentDateTime = date('Y-m-d H:i:s');
// // Check if current date time is within the range
// if ($currentDateTime >= $from_dt && $currentDateTime < $to_dt) {
// if (! ($currentDateTime >= $from_dt && $currentDateTime < $to_dt)) {
// // echo "Choosed a valid shift...";
// // $set('ppLineError', 'Valid (From: '.$from_dt.', To: '.$to_dt.')');
// $set('line_id', null);
// $set('ppLineError', 'Production plan already updated.');
// $set('ppLineError', 'Choosed a invalid shift.');
// // $set('ppLineError', 'Valid (From: '.$from_dt.', To: '.$to_dt.')');
// return;
// }
// // else {
// // $set('ppLineError', 'Choosed a invalid shift...');
// }
// $set('ppLineError', null);
// return;
// } else {
// // $currentDate = date('Y-m-d');
// $yesterday = date('Y-m-d', strtotime('-1 days'));
// $shiftId = Shift::where('id', $get('shift_id'))
// ->first();
// [$hRs, $miNs] = explode('.', $shiftId->duration) + [0, 0];
// $hRs = (int) $hRs;
// // $miNs = (int) $miNs;-*/
// $totalMinutes = $hRs * 60 + $miNs;
// $from_dt = $yesterday.' '.$shiftId->start_time;
// $to_dt = date('Y-m-d H:i:s', strtotime($from_dt." + $totalMinutes minutes"));
// $currentDateTime = date('Y-m-d H:i:s');
// // Check if current date time is within the range
// if ($currentDateTime >= $from_dt && $currentDateTime < $to_dt) {
// // echo "Choosed a valid shift...";
// // here i'm updating created as yesterday
// $set('created_at', $from_dt);
// $set('update_date', '1');
// $set('ppLineError', null);
// // $set('ppLineError', 'Valid (From: '.$from_dt.', To: '.$to_dt.')');
// return;
// } else {
// $currentDate = date('Y-m-d');
// $shiftId = Shift::where('id', $get('shift_id'))
// ->first();
// [$hRs, $miNs] = explode('.', $shiftId->duration) + [0, 0];
// $hRs = (int) $hRs;
// // $miNs = (int) $miNs;-*/
// $totalMinutes = $hRs * 60 + $miNs;
// $from_dt = $currentDate.' '.$shiftId->start_time;
// $to_dt = date('Y-m-d H:i:s', strtotime($from_dt." + $totalMinutes minutes"));
// $currentDateTime = date('Y-m-d H:i:s');
// // Check if current date time is within the range
// if (! ($currentDateTime >= $from_dt && $currentDateTime < $to_dt)) {
// // echo "Choosed a valid shift...";
// $set('line_id', null);
// $set('ppLineError', 'Choosed a invalid shift.');
// // $set('ppLineError', 'Valid (From: '.$from_dt.', To: '.$to_dt.')');
// return;
// }
// }
// $set('ppLineError', null);
// return;
// }
// // $exists = ProductionPlan::where('plant_id', $get('plant_id'))
// // //->where('shift_id', $get('shift_id'))
// // ->where('line_id', $get('line_id'))
// // ->whereDate('created_at', today())
// // ->latest() // Orders by created_at DESC
// // ->first();
// // if ($exists)
// // {
// // $existingShifts = ProductionPlan::where('plant_id', $get('plant_id'))
// // //->where('shift_id', $get('shift_id'))
// // ->where('line_id', $get('line_id'))
// // // ->whereDate('created_at', today())
// // ->whereDate('created_at', today())
// // ->get();
// // foreach ($existingShifts as $shift) {
// // $curShiftId = $shift->shift_id;
// // $currentDate = date('Y-m-d');
// // $shiftId = \App\Models\Shift::where('id', $curShiftId)
// // ->first();
// // [$hRs, $miNs] = explode('.', $shiftId->duration) + [0, 0];
// // $hRs = (int) $hRs;
// // // $miNs = (int) $miNs;-*/
// // $totalMinutes = $hRs * 60 + $miNs;
// // $from_dt = $currentDate . ' ' . $shiftId->start_time;
// // $to_dt = date('Y-m-d H:i:s', strtotime($from_dt . " + $totalMinutes minutes"));
// // $currentDateTime = date('Y-m-d H:i:s');
// // // Check if current date time is within the range
// // if ($currentDateTime >= $from_dt && $currentDateTime < $to_dt) {
// // //echo "Choosed a valid shift...";
// // // $set('ppLineError', 'Valid (From: '.$from_dt.', To: '.$to_dt.')');
// // $set('line_id', null);
// // $set('ppLineError', 'Production plan already updated.');
// // return;
// // }
// // // else {
// // // $set('ppLineError', 'Choosed a invalid shift...');
// // // return;
// // // }
// // }
// // $set('ppLineError', null);
// // return;
// // }
// }
// $set('ppLineError', null);
// return;
// }
}
}
$set('ppLineError', null);
}
// $set('ppLineError', null);
// }
// })
->afterStateUpdated(function ($state, callable $set, callable $get) {
$set('item_id', null);
$set('plan_quantity', null);
})
->extraAttributes(fn ($get) => [
'class' => $get('ppLineError') ? 'border-red-500' : '',
])
->hint(fn ($get) => $get('ppLineError') ? $get('ppLineError') : null)
->hintColor('danger'),
Forms\Components\Select::make('item_id')
->label('Item')
->reactive()
->searchable()
->required()
->options(function (callable $get) {
if (! $get('plant_id')) {
return [];
}
return Item::where('plant_id', $get('plant_id'))
->pluck('code', 'id')
->toArray();
}),
Forms\Components\TextInput::make('plan_quantity')
->required()
->integer()
@@ -453,29 +381,19 @@ class ProductionPlanResource extends Resource
])
->hint(fn ($get) => $get('ppPlanQuanError') ? $get('ppPlanQuanError') : null)
->hintColor('danger'),
Forms\Components\TextInput::make('production_quantity')
->required()
->integer()
->label('Production Quantity')
->readOnly(fn (callable $get) => ! $get('id'))
->default(0),
// Forms\Components\TextInput::make('production_quantity')
// ->required()
// ->integer()
// ->label('Production Quantity')
// ->readOnly(fn (callable $get) => ! $get('id'))
// ->default(0),
Forms\Components\TextInput::make('id')
->hidden()
->readOnly(),
Forms\Components\TextInput::make('update_date')
->hidden()
->reactive()
->readOnly(),
Forms\Components\DateTimePicker::make('created_at')
->label('Created DateTime')
->hidden()
->reactive()
->required()
->readOnly(),
Forms\Components\Hidden::make('operator_id')
->default(Filament::auth()->user()->name),
])
->columns(2),
->columns(4),
]);
}
@@ -513,32 +431,52 @@ class ProductionPlanResource extends Resource
return ($currentPage - 1) * $perPage + $rowLoop->iteration;
}),
Tables\Columns\TextColumn::make('plant.name')
->label('Plant')
->alignCenter()
->sortable()
->searchable(),
Tables\Columns\TextColumn::make('line.name')
->label('Plant')
->alignCenter()
->sortable()
->searchable(),
Tables\Columns\TextColumn::make('item.code')
->label('Item')
->alignCenter()
->sortable()
->searchable(),
Tables\Columns\TextColumn::make('plan_quantity')
->label('Plan Quantity')
->alignCenter()
->numeric()
->sortable(),
->sortable()
->searchable(),
Tables\Columns\TextColumn::make('working_days')
->label('Working Days')
->alignCenter()
->numeric()
->sortable()
->searchable(),
Tables\Columns\TextColumn::make('production_quantity')
->label('Production Quantity')
->alignCenter()
->numeric()
->sortable(),
Tables\Columns\TextColumn::make('line.name')
->label('Line')
->alignCenter()
->sortable(), // ->searchable(),
Tables\Columns\TextColumn::make('shift.block.name')
->label('Block')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('shift.name')
->label('Shift')
->alignCenter()
->sortable(), // ->searchable(),
Tables\Columns\TextColumn::make('plant.name')
->label('Plant')
->alignCenter()
->sortable(), // ->searchable(),
->sortable()
->searchable(),
// Tables\Columns\TextColumn::make('line.name')
// ->label('Line')
// ->alignCenter()
// ->sortable(), // ->searchable(),
// Tables\Columns\TextColumn::make('shift.block.name')
// ->label('Block')
// ->alignCenter()
// ->sortable(),
// Tables\Columns\TextColumn::make('shift.name')
// ->label('Shift')
// ->alignCenter()
// ->sortable(), // ->searchable(),
Tables\Columns\TextColumn::make('created_at')
->label('Created At')
->dateTime()

View File

@@ -910,6 +910,7 @@ class RequestCharacteristicResource extends Resource
->sortable(),
Tables\Columns\TextColumn::make('characteristic_name')
->label('Characteristic Name')
->default('-')
->alignCenter()
->searchable()
->formatStateUsing(fn (string $state): string => strtoupper(__($state)))
@@ -917,13 +918,21 @@ class RequestCharacteristicResource extends Resource
->sortable(),
Tables\Columns\TextColumn::make('current_value')
->label('Current Value')
->default('-')
->alignCenter()
->searchable()
->formatStateUsing(function ($record) {
return empty($record->characteristic_name) ? '-' : $record->current_value;
})
->sortable(),
Tables\Columns\TextColumn::make('update_value')
->label('Update Value')
->default('-')
->alignCenter()
->searchable()
->formatStateUsing(function ($record) {
return empty($record->characteristic_name) ? '-' : $record->update_value;
})
->sortable(),
Tables\Columns\TextColumn::make('characteristicApproverMaster.name1')
->label('Approver Name 1')
@@ -1011,8 +1020,21 @@ class RequestCharacteristicResource extends Resource
->sortable(),
Tables\Columns\TextColumn::make('mail_status')
->label('Mail Status')
->default('-')
->alignCenter()
->searchable()
->formatStateUsing(function ($state) {
if (! $state || $state == '' || $state == null) {
return '-';
}
return match ($state) {
'Sent' => 'Sent-Mail1',
'Sent-Mail2' => 'Sent-Mail2',
'Sent-Mail3' => 'Sent-Mail3',
default => '-',
};
})
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('trigger_at')

View File

@@ -264,7 +264,7 @@ class StickerMasterResource extends Resource
->label('Laser Part Validation 2')
->nullable()
->reactive()
->readOnly(fn (callable $get) => empty($get('laser_part_validation1')))
// ->readOnly(fn (callable $get) => empty($get('laser_part_validation1')))
->afterStateUpdated(function ($state, callable $set, callable $get) {
$set('updated_by', Filament::auth()->user()?->name);
}),
@@ -625,11 +625,13 @@ class StickerMasterResource extends Resource
Tables\Columns\TextColumn::make('laser_part_validation1')
->label('Laser Part Validation 1')
->default('-')
->alignCenter(),
->alignCenter()
->searchable(),
Tables\Columns\TextColumn::make('laser_part_validation2')
->label('Laser Part Validation 2')
->default('-')
->alignCenter(),
->alignCenter()
->searchable(),
Tables\Columns\TextColumn::make('panel_box_code')
->label('Panel Box Code')
->default('-')

View File

@@ -112,9 +112,9 @@ class CharacteristicsController extends Controller
'characteristics_type',
'name',
'inspection_type',
'upper',
'lower',
'middle',
'upper',
]);
if ($characteristics->count() == 0) {
@@ -2284,9 +2284,9 @@ class CharacteristicsController extends Controller
'name' => $charMaster?->name ?? '',
'inspection_type' => $charMaster?->inspection_type ?? '',
'characteristics_type' => $charMaster?->characteristics_type ?? '',
'upper' => (string) $charMaster?->upper ?? '',
'lower' => (string) $charMaster?->lower ?? '',
'middle' => (string) $charMaster?->middle ?? '',
'upper' => (string) $charMaster?->upper ?? '',
];
return response()->json($output, 200);

View File

@@ -590,6 +590,13 @@ class PdfController extends Controller
->orderBy('id', 'desc')
->first();
$lastRecord1 = ProcessOrder::with('item')
->where('plant_id', $plant->id)
->where('process_order', $processOrder)
->where('rework_status', 0)
->orderBy('id', 'desc')
->first();
$totalReceivedQty = $processOrderRecords->sum('received_quantity');
// $lastRecord = $processOrderRecords->first();
$item = $lastRecord->item;
@@ -612,12 +619,14 @@ class PdfController extends Controller
$notOkQty = CharacteristicValue::where('plant_id', $plant->id)->where('process_order', $processOrder)->where('status', 'NotOk')->get()->count();
$currentCoil = ($lastRecord->rework_status == 1) ? (string) $lastRecord1->coil_number : (string) $lastRecord->coil_number;
return response()->json([
'item_code' => $item?->code ?? '',
'description' => $item?->description ?? '',
// 'coil_number' => $proOrdAgPlant->coil_number ?? "",
// 'order_quantity' => (string)$proOrdAgPlant->order_quantity ?? "",
'coil_number' => (string) $lastRecord->coil_number ?? '0',
'coil_number' => $currentCoil,
'order_quantity' => (string) $lastRecord->order_quantity ?? '0.000',
'ok_quantity' => (string) $okQty ?? '0',
'not_ok_quantity' => (string) $notOkQty ?? '0',
@@ -853,10 +862,35 @@ class PdfController extends Controller
->sum('received_quantity');
if ($orderQty == 0) {
$orderQty = ProcessOrder::where('plant_id', $plantId)
$orderExist = ProcessOrder::where('plant_id', $plantId)
->where('process_order', $processOrder)
->where('item_id', $itemId)
->value('order_quantity') ?? 0;
->where('item_id', $itemId)->latest()->first();
// ->value('order_quantity') ?? 0;
if ($orderExist) {
$orderQty = $orderExist->order_quantity ?? 0;
} else {
return response()->json([
'status_code' => 'ERROR',
'status_description' => "Order quantity can't be '0'",
], 404);
}
} else {
$orderExist = ProcessOrder::where('plant_id', $plantId)
->where('process_order', $processOrder)
->where('item_id', $itemId)->latest()->first();
// ->value('order_quantity') ?? 0;
if ($orderExist) {
$existOrderQty = $orderExist->order_quantity ?? 0;
if ($existOrderQty != $orderQty) {
return response()->json([
'status_code' => 'ERROR',
'status_description' => "Order quantity doesn't equal to exist process order '{$processOrder}'",
], 404);
}
}
}
$total = $alreadyReceived + $receivedQty;
@@ -871,7 +905,7 @@ class PdfController extends Controller
if ($rework == null || $rework == '' || ! $rework) {
return response()->json([
'status_code' => 'ERROR',
'status_description' => "Rework can't be empty!",
'status_description' => "Rework value can't be empty!",
], 404);
}
@@ -889,8 +923,61 @@ class PdfController extends Controller
}
}
$coilNo = (string) $coilNo;
try {
if ($rework == 'Yes') {
if ($coilNo && Str::contains($coilNo, '.')) {
// Contains dot
$coilMain = explode('.', $coilNo)[0]; // 333
$existingCoil = ProcessOrder::where('plant_id', $plantId)
->where('process_order', $processOrder)
->where('line_id', $lineNamePlantId)
->where('coil_number', $coilMain)
->first();
if (! $existingCoil) {
return response()->json([
'status_code' => 'ERROR',
'status_description' => "Coil number '{$coilMain}' not exist against plant code '{$plantCode}' and process order '{$processOrder}'!",
], 404);
} elseif ($existingCoil->rework_status == 0) {
return response()->json([
'status_code' => 'ERROR',
'status_description' => "Rework coil number '{$coilMain}' not exist against plant code '{$plantCode}' and process order '{$processOrder}'!",
], 404);
}
$existingCoil = ProcessOrder::where('plant_id', $plantId)
->where('process_order', $processOrder)
->where('line_id', $lineNamePlantId)
->where('coil_number', $coilNo)
->first();
if (! $existingCoil) {
ProcessOrder::Create(
[
'plant_id' => $plantId,
'line_id' => $lineNamePlantId,
'process_order' => $processOrder,
'item_id' => $itemId,
'coil_number' => $coilNo,
'order_quantity' => $orderQty,
'received_quantity' => $receivedQty,
'scrap_quantity' => $scrapQty,
'sfg_number' => $sfgNo,
'machine_name' => $machineId,
'rework_status' => 1,
'created_by' => $createdBy,
]
);
return response()->json([
'status_code' => 'SUCCESS',
'status_description' => 'Record Updated Successfully (Rework).',
]);
} else {
$updated = ProcessOrder::where('plant_id', $plantId)
->where('process_order', $processOrder)
->where('line_id', $lineNamePlantId)
@@ -905,19 +992,56 @@ class PdfController extends Controller
'updated_by' => $createdBy,
'updated_at' => now(),
]);
}
} else {
$existingCoil = ProcessOrder::where('plant_id', $plantId)
->where('process_order', $processOrder)
->where('line_id', $lineNamePlantId)
->where('coil_number', $coilNo)
->first();
if (! $existingCoil) {
return response()->json([
'status_code' => 'ERROR',
'status_description' => "Coil number '{$coilNo}' not exist against plant code '{$plantCode}' and process order '{$processOrder}'!",
], 404);
}
$updated = ProcessOrder::where('plant_id', $plantId)
->where('process_order', $processOrder)
->where('line_id', $lineNamePlantId)
->where('coil_number', $coilNo)
->update([
// 'order_quantity' => $orderQty,
'received_quantity' => $receivedQty,
'scrap_quantity' => $scrapQty,
// 'sfg_number' => $sfgNo,
// 'machine_name' => $machineId,
'rework_status' => 1,
'updated_by' => $createdBy,
'updated_at' => now(),
]);
}
if ($updated == 0) {
return response()->json([
'status_code' => 'ERROR',
'status_description' => 'No matching record found for rework coil number!',
'status_description' => "No matching record found for rework coil number '{$coilNo}'!",
], 404);
} else {
return response()->json([
'status_code' => 'SUCCESS',
'status_description' => 'Record Updated Successfully (Rework)',
'status_description' => 'Record Updated Successfully (Rework).',
]);
}
} else {
if ($coilNo && Str::contains($coilNo, '.')) {
return response()->json([
'status_code' => 'ERROR',
'status_description1' => "Rework value should be 'Yes' for rework coil number '{$coilNo}'!",
], 404);
}
$existing = ProcessOrder::where('plant_id', $plantId)
->where('process_order', $processOrder)
->where('coil_number', $coilNo)
@@ -926,7 +1050,8 @@ class PdfController extends Controller
if ($existing) {
return response()->json([
'status_code' => 'ERROR',
'status_description' => "Process order '{$processOrder}' with coil number '{$coilNo}' already exist for the plant code '{$plantCode}'!",
'status_description' => "Coil number '{$coilNo}' already exist against plant code '{$plantCode}' and process order '{$processOrder}'!",
// "Process order '{$processOrder}' with coil number '{$coilNo}' already exist for the plant code '{$plantCode}'!",
], 404);
}
@@ -949,7 +1074,7 @@ class PdfController extends Controller
return response()->json([
'status_code' => 'SUCCESS',
'status_description' => 'Record Inserted Successfully',
'status_description' => 'Record Inserted Successfully.',
]);
}
} catch (\Exception $e) {

View File

@@ -0,0 +1,310 @@
<?php
namespace App\Livewire;
use App\Exports\ProductionPlanExport;
use App\Models\ProductionPlan;
use App\Models\ProductionQuantity;
use Livewire\Component;
use Carbon\Carbon;
use DB;
use Maatwebsite\Excel\Facades\Excel;
class ProductionTargetPlan extends Component
{
public $plantId, $lineId, $month, $year;
public $records = [];
public $dates = [];
public $leaveDates = [];
public $productionPlanDates = '';
protected $listeners = [
'loadData' => 'loadProductionData',
'loadData1' => 'exportProductionData',
];
public function getMonthDates($month, $year)
{
$start = Carbon::createFromDate($year, $month, 1);
$days = $start->daysInMonth;
$dates = [];
for ($i = 1; $i <= $days; $i++) {
$dates[] = Carbon::createFromDate($year, $month, $i)
->format('Y-m-d');
}
return $dates;
}
// public function loadProductionData($plantId, $lineId, $month, $year){
// if (!$plantId || !$lineId || !$month || !$year) {
// $this->records = [];
// $this->dates = [];
// $this->leaveDates = [];
// return;
// }
// $this->dates = $this->getMonthDates($month, $year);
// $data = ProductionPlan::query()
// ->join('items', 'items.id', '=', 'production_plans.item_id')
// ->join('lines', 'lines.id', '=', 'production_plans.line_id')
// ->join('plants', 'plants.id', '=', 'production_plans.plant_id')
// ->where('production_plans.plant_id', $plantId)
// ->where('production_plans.line_id', $lineId)
// ->whereMonth('production_plans.created_at', $month)
// ->whereYear('production_plans.created_at', $year)
// ->select(
// 'production_plans.created_at',
// 'production_plans.operator_id',
// 'plants.name as plant',
// 'items.code as item_code',
// 'items.description as item_description',
// 'lines.name as line_name',
// 'production_plans.leave_dates'
// )
// ->first();
// if ($data && $data->leave_dates) {
// $this->leaveDates = array_map('trim', explode(',', $data->leave_dates));
// }
// $producedData = ProductionQuantity::selectRaw("
// plant_id,
// line_id,
// item_id,
// DATE(created_at) as prod_date,
// COUNT(*) as total_qty
// ")
// ->where('plant_id', $plantId)
// ->where('line_id', $lineId)
// ->whereMonth('created_at', $month)
// ->whereYear('created_at', $year)
// ->groupBy('plant_id', 'line_id', 'item_id', DB::raw('DATE(created_at)'))
// ->get()
// ->groupBy(function ($row) {
// return $row->plant_id . '_' . $row->line_id . '_' . $row->item_id;
// })
// ->map(function ($group) {
// return $group->keyBy('prod_date');
// });
// $this->records = ProductionPlan::query()
// ->join('items', 'items.id', '=', 'production_plans.item_id')
// ->join('lines', 'lines.id', '=', 'production_plans.line_id')
// ->join('plants', 'plants.id', '=', 'production_plans.plant_id')
// ->where('production_plans.plant_id', $plantId)
// ->where('production_plans.line_id', $lineId)
// ->whereMonth('production_plans.created_at', $month)
// ->whereYear('production_plans.created_at', $year)
// ->select(
// 'production_plans.item_id',
// 'production_plans.plant_id',
// 'production_plans.line_id',
// 'production_plans.plan_quantity',
// 'production_plans.working_days',
// 'items.code as item_code',
// 'items.description as item_description',
// 'lines.name as line_name',
// 'plants.name as plant_name'
// )
// ->get()
// ->map(function ($row) use ($producedData) {
// $row = $row->toArray();
// $remainingQty = $row['plan_quantity'];
// // $remainingDays = $row['working_days'];
// $remainingDays = (int) ($row['working_days'] ?? 0);
// $row['daily_target_dynamic'] = [];
// $row['produced_quantity'] = [];
// $key = $row['plant_id'].'_'.$row['line_id'].'_'.$row['item_id'];
// foreach ($this->dates as $date) {
// // Skip leave dates
// if (in_array($date, $this->leaveDates)) {
// $row['daily_target_dynamic'][$date] = '-';
// $row['produced_quantity'][$date] = '-';
// continue;
// }
// $todayTarget = $remainingDays > 0
// ? round($remainingQty / $remainingDays, 2)
// : 0;
// //$todayTarget = $remainingDays > 0
// // ? $remainingQty / $remainingDays
// // : 0;
// $producedQty = isset($producedData[$key][$date])
// ? $producedData[$key][$date]->total_qty
// : 0;
// $row['daily_target_dynamic'][$date] = $todayTarget;
// $row['produced_quantity'][$date] = $producedQty;
// // Carry forward pending
// $remainingQty -= $producedQty;
// if ($remainingQty < 0) {
// $remainingQty = 0;
// }
// if ($remainingDays > 0) {
// $remainingDays--;
// }
// // $remainingDays--;
// }
// return $row;
// })
// ->toArray();
// }
public function loadProductionData($plantId, $lineId, $month, $year)
{
if (!$plantId || !$lineId || !$month || !$year) {
$this->records = [];
$this->dates = [];
$this->leaveDates = [];
return;
}
$dates = $this->getMonthDates($month, $year);
$this->dates = $dates;
$plans = ProductionPlan::query()
->join('items', 'items.id', '=', 'production_plans.item_id')
->join('lines', 'lines.id', '=', 'production_plans.line_id')
->join('plants', 'plants.id', '=', 'production_plans.plant_id')
->where('production_plans.plant_id', $plantId)
->where('production_plans.line_id', $lineId)
->whereMonth('production_plans.created_at', $month)
->whereYear('production_plans.created_at', $year)
->select(
'production_plans.item_id',
'production_plans.plant_id',
'production_plans.line_id',
'production_plans.plan_quantity',
'production_plans.working_days',
'production_plans.leave_dates',
'items.code as item_code',
'items.description as item_description',
'lines.name as line_name',
'lines.line_capacity as line_capacity',
'plants.name as plant_name'
)
->get();
$leaveDates = [];
if ($plans->isNotEmpty() && $plans[0]->leave_dates) {
$leaveDates = array_map('trim', explode(',', $plans[0]->leave_dates));
}
$this->leaveDates = $leaveDates;
$producedData = ProductionQuantity::selectRaw("
plant_id,
line_id,
item_id,
DATE(created_at) as prod_date,
COUNT(*) as total_qty
")
->where('plant_id', $plantId)
->where('line_id', $lineId)
->whereMonth('created_at', $month)
->whereYear('created_at', $year)
->groupBy('plant_id', 'line_id', 'item_id', DB::raw('DATE(created_at)'))
->get()
->groupBy(fn($row) =>
$row->plant_id . '_' . $row->line_id . '_' . $row->item_id
)
->map(fn($group) => $group->keyBy('prod_date'));
$records = [];
foreach ($plans as $plan) {
$row = $plan->toArray();
$remainingQty = (float) $row['plan_quantity'];
$remainingDays = (int) ($row['working_days'] ?? 0);
$lineCapacity = (float) ($row['line_capacity'] ?? 0);
$dailyLineCapacity = (float) ($row['line_capacity'] ?? 0);
$row['daily_line_capacity'] = [];
$row['daily_target_dynamic'] = [];
$row['produced_quantity'] = [];
$key = $row['plant_id'].'_'.$row['line_id'].'_'.$row['item_id'];
foreach ($dates as $date) {
// Skip leave dates fast
if (isset($leaveDates) && in_array($date, $leaveDates)) {
$row['daily_line_capacity'][$date] = '-';
$row['daily_target_dynamic'][$date] = '-';
$row['produced_quantity'][$date] = '-';
continue;
}
$todayTarget = $remainingDays > 0
? round($remainingQty / $remainingDays, 2)
: 0;
$producedQty = $producedData[$key][$date]->total_qty ?? 0;
$row['daily_target_dynamic'][$date] = $todayTarget;
$row['produced_quantity'][$date] = $producedQty;
$row['daily_line_capacity'][$date] = $dailyLineCapacity;
// Carry forward remaining qty
$remainingQty = max(0, $remainingQty - $producedQty);
if ($remainingDays > 0) {
$remainingDays--;
}
}
$records[] = $row;
}
$this->records = $records;
}
public function exportProductionData()
{
return Excel::download(
new ProductionPlanExport($this->records, $this->dates),
'production_plan_data.xlsx'
);
}
public function render()
{
// return view('livewire.production-target-plan');
return view('livewire.production-target-plan', [
'records' => $this->records,
'dates' => $this->dates,
]);
}
}

View File

@@ -23,15 +23,24 @@ class CharacteristicApprovalMail extends Mailable
public $pdfPath;
public $tableData;
public $pendingApprovers;
public $approverNameFromMaster;
public $subjectLine;
/**
* Create a new message instance.
*/
public function __construct($request, $approverName, $level, $pdfPath = null, $characteristics = [])
public function __construct($request, $approverName, $level, $pdfPath = null, $pendingApprovers, $approverNameFromMaster, $subjectLine, $characteristics = [])
{
$this->request = $request;
$this->approverName = $approverName;
$this->level = $level;
$this->pdfPath = $pdfPath;
$this->pendingApprovers = $pendingApprovers;
$this->approverNameFromMaster = $approverNameFromMaster;
$this->subjectLine = $subjectLine;
$this->tableData = $characteristics;
}
@@ -41,7 +50,7 @@ class CharacteristicApprovalMail extends Mailable
public function envelope(): Envelope
{
return new Envelope(
subject: 'Characteristic Approval Mail',
subject: $this->subjectLine,
);
}
@@ -56,7 +65,10 @@ class CharacteristicApprovalMail extends Mailable
'company' => 'CRI Digital Manufacturing Solutions',
'greeting' => 'Dear ' . $this->approverName . ',',
'request' => $this->request,
'level' => $this->level,
'tableData' => $this->tableData,
'pendingApprovers' => $this->pendingApprovers,
'approverNameFromMaster' => $this->approverNameFromMaster,
'approveUrl' => $this->approveUrl(),
'holdUrl' => $this->holdUrl(),
'rejectUrl' => $this->rejectUrl(),
@@ -112,4 +124,7 @@ class CharacteristicApprovalMail extends Mailable
)->as(basename($this->pdfPath)),
];
}
}

View File

@@ -11,14 +11,14 @@ class GrMaster extends Model
use SoftDeletes;
protected $fillable = [
"plant_id",
"item_id",
"serial_number",
"gr_number",
"created_at",
"created_by",
"updated_by",
"updated_at"
'plant_id',
'item_id',
'serial_number',
'gr_number',
'created_at',
'created_by',
'updated_at',
'updated_by',
];
public function plant(): BelongsTo
@@ -30,5 +30,4 @@ class GrMaster extends Model
{
return $this->belongsTo(Item::class);
}
}

View File

@@ -12,6 +12,7 @@ class Item extends Model
protected $fillable = [
'plant_id',
'line_id',
'category',
'code',
'description',
@@ -19,11 +20,16 @@ class Item extends Model
'uom',
];
public function plant(): BelongsTo
public function plant()
{
return $this->belongsTo(Plant::class);
}
public function item()
{
return $this->belongsTo(Item::class, 'item_id', 'id');
}
public function stickerMasters()
{
return $this->hasMany(StickerMaster::class, 'item_id', 'id');

View File

@@ -3,30 +3,32 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
class Line extends Model
{
use SoftDeletes;
protected $fillable = [
"plant_id",
"name",
"type",
"group_work_center",
"no_of_operation",
"work_group1_id",
"work_group2_id",
"work_group3_id",
"work_group4_id",
"work_group5_id",
"work_group6_id",
"work_group7_id",
"work_group8_id",
"work_group9_id",
"work_group10_id",
'plant_id',
'block_id',
'name',
'type',
'line_capacity',
'group_work_center',
'no_of_operation',
'work_group1_id',
'work_group2_id',
'work_group3_id',
'work_group4_id',
'work_group5_id',
'work_group6_id',
'work_group7_id',
'work_group8_id',
'work_group9_id',
'work_group10_id',
];
public function plant(): BelongsTo
@@ -34,6 +36,11 @@ class Line extends Model
return $this->belongsTo(Plant::class);
}
public function block(): BelongsTo
{
return $this->belongsTo(Block::class);
}
public function testingPanelReadings()
{
return $this->hasMany(TestingPanelReading::class);

View File

@@ -5,7 +5,6 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class ProductCharacteristicsMaster extends Model
{
@@ -13,15 +12,15 @@ class ProductCharacteristicsMaster extends Model
protected $fillable = [
'plant_id',
'line_id',
'item_id',
'line_id',
'work_group_master_id',
'machine_id',
'characteristics_type',
'name',
'inspection_type',
'characteristics_type',
'upper',
'lower',
'upper',
'middle',
'created_at',
'updated_at',

View File

@@ -16,9 +16,12 @@ class ProductionPlan extends Model
protected $fillable = [
'plant_id',
'shift_id',
'item_id',
'line_id',
'plan_quantity',
'production_quantity',
'working_days',
'leave_dates',
'operator_id',
'created_at',
'updated_at',
@@ -39,6 +42,11 @@ class ProductionPlan extends Model
return $this->belongsTo(Line::class);
}
public function item(): BelongsTo
{
return $this->belongsTo(Item::class);
}
public function prunable(): Builder
{
return static::where('created_at', '<=', now()->subMonthsNoOverflow(6));

View File

@@ -22,6 +22,7 @@ class ProductionQuantity extends Model
'shift_id',
'line_id',
'item_id',
'machine_id',
'serial_number',
'production_order',
'operator_id',
@@ -53,6 +54,11 @@ class ProductionQuantity extends Model
return $this->belongsTo(Item::class);
}
public function machine(): BelongsTo
{
return $this->belongsTo(Machine::class);
}
protected static function booted()
{
static::created(function ($productionQuantity) {

View File

@@ -8,7 +8,7 @@
"require": {
"php": "^8.2",
"alperenersoy/filament-export": "^3.0",
"althinect/filament-spatie-roles-permissions": "^2.3",
"althinect/filament-spatie-roles-permissions": "^3.0",
"erag/laravel-pwa": "^1.9",
"filament/filament": "^3.3",
"intervention/image": "^3.11",

View File

@@ -0,0 +1,49 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
$sql = <<<'SQL'
ALTER TABLE production_plans
ADD COLUMN item_id BIGINT DEFAULT NULL,
ADD CONSTRAINT production_plans_item_id_fkey
FOREIGN KEY (item_id) REFERENCES items(id);
SQL;
DB::statement($sql);
$sql1 = <<<'SQL'
ALTER TABLE production_plans
ADD COLUMN working_days TEXT DEFAULT NULL
SQL;
DB::statement($sql1);
$sql2 = <<<'SQL'
ALTER TABLE production_plans
ADD COLUMN leave_dates TEXT DEFAULT NULL
SQL;
DB::statement($sql2);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// Schema::table('production_plans', function (Blueprint $table) {
// //
// });
}
};

View File

@@ -0,0 +1,40 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
$sql = <<<'SQL'
ALTER TABLE lines
ADD COLUMN block_id BIGINT DEFAULT NULL,
ADD CONSTRAINT lines_block_id_fkey
FOREIGN KEY (block_id) REFERENCES blocks(id);
SQL;
DB::statement($sql);
$sql1 = <<<'SQL'
ALTER TABLE lines
ADD COLUMN line_capacity TEXT DEFAULT NULL
SQL;
DB::statement($sql1);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// Schema::table('lines', function (Blueprint $table) {
// //
// });
}
};

View File

@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
$sql1 = <<<'SQL'
ALTER TABLE items
ADD COLUMN line_id BIGINT DEFAULT NULL,
ADD CONSTRAINT items_line_id_fkey
FOREIGN KEY (line_id) REFERENCES lines(id);
SQL;
DB::statement($sql1);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// Schema::table('items', function (Blueprint $table) {
// //
// });
}
};

View File

@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
$sql = <<<'SQL'
ALTER TABLE production_quantities
ADD COLUMN machine_id BIGINT DEFAULT NULL,
ADD CONSTRAINT production_quantities_machine_id_fkey
FOREIGN KEY (machine_id) REFERENCES machines(id);
SQL;
DB::statement($sql);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// Schema::table('production_quantities', function (Blueprint $table) {
// //
// });
}
};

View File

@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
DB::statement("
ALTER TABLE production_plans
ALTER COLUMN shift_id DROP NOT NULL
");
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// Schema::table('production_plans', function (Blueprint $table) {
// //
// });
}
};

View File

@@ -189,5 +189,8 @@ class PermissionSeeder extends Seeder
Permission::updateOrCreate(['name' => 'view import characteristic approver master']);
Permission::updateOrCreate(['name' => 'view export characteristic approver master']);
Permission::updateOrCreate(['name' => 'view production calender page']);
Permission::updateOrCreate(['name' => 'view production target page']);
}
}

View File

@@ -1,4 +1,4 @@
<!DOCTYPE html>
{{-- <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
@@ -67,25 +67,149 @@
font-size: 14px;
color: #666;
}
.approvelevel {
/* color: red; */
font-size: 18px;
font-weight: bold;
}
</style>
</head>
<body>
<div class="container">
<div class="card">
<div class="icon">⚠️</div>
<h2>Action Already Taken</h2>
<div class="approvelevel">⚠️ Action Already Taken</div>
<div class="status {{ $status }}">
Status: {{ $status }}
</div>
<div class="footer">
CRI Digital Manufacturing Solutions<br>
&copy; 2026 All Rights Reserved
</div>
</div>
</body>
</html> --}}
<!DOCTYPE html>
<html>
<head>
<title>Action Taken</title>
<style>
body {
font-family: Arial, sans-serif;
background: #f6f6f6;
padding: 20px;
}
.card {
background: #ffffff;
padding: 20px;
max-width: 500px;
margin: 50px auto;
border-radius: 6px;
text-align: center;
box-shadow: 0 0 10px rgba(0,0,0,.1);
}
.success {
color: green;
font-size: 18px;
font-weight: bold;
}
.footer {
font-size: 12px;
color: #999999;
text-align: center;
margin-top: 20px;
}
.icon {
font-size: 30px;
margin-bottom: 10px;
color: #ff9800;
}
.approvelevel {
/* color: red; */
font-size: 18px;
font-weight: bold;
}
.status {
margin-top: 15px;
padding: 10px;
border-radius: 6px;
font-weight: bold;
font-size: 16px;
}
.status.Approved {
background-color: #e8f5e9;
color: #2e7d32;
}
.status.Hold {
background-color: #fff3e0;
color: #ef6c00;
}
.status.Rejected {
background-color: #fdecea;
color: #c62828;
}
.note {
margin-top: 15px;
font-size: 15px;
color: #666;
}
.pulse-darkred {
color: orange; /* #8B0000 */
background-color: #fff; /* White bg for contrast */
display: inline-block;
padding: 0.5em 0.75em;
border-radius: 4px;
font-size: 1em;
line-height: 1;
animation: pulse 1.5s ease-in-out infinite; /* Duration, easing, infinite loop */
}
@keyframes pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.2); /* Gentle 5% expansion */
}
}
</style>
</head>
<body>
<div class="card">
<div class="approvelevel"><span class="pulse-darkred">⚠️</span> Action Already Taken</div>
{{-- <div class="status {{ $status }}">
Status: {{ $status }}
</div> --}}
<div class="status {{ $status }}">
Status: {{ $message ?? $status }}
</div>
<p class="note">
This request has already been processed.<br>
No further action is required.
</p>
<div class="footer">
CRI Digital Manufacturing Solutions<br>
&copy; 2026 All Rights Reserved
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,94 @@
<!DOCTYPE html>
<html>
<head>
<title>Request On Approve</title>
<meta name="csrf-token" content="{{ csrf_token() }}">
</head>
<body style="font-family: Arial, sans-serif; background-color: #f4f4f4; margin:0; padding:0;">
<table width="100%" cellpadding="0" cellspacing="0" style="padding: 20px 0;">
<tr>
<td align="center">
<!-- Card container -->
<table width="600" cellpadding="0" cellspacing="0" style="background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.1); border: 1px solid #e0e0e0;">
<tr>
<td style="padding: 30px; text-align: center;">
<!-- Header -->
<div style="font-size: 35px;"></div>
<h2 style="color: Green; margin: 10px 0 20px; font-size: 24px;"> Request On Approve</h2>
<!-- Message -->
{{-- <p style="font-size: 16px; color: #555555; line-height: 1.5;">
Your request has been put on reject.
</p> --}}
<!-- Remark Textbox -->
<div style="margin-top: 20px; text-align: left;">
<label for="remark" style="font-size: 14px; color: #333;">Remark</label>
<textarea id="remark" style="width:100%; height:100px; padding:10px; margin-top:5px; border:1px solid #ddd; border-radius:5px;"></textarea>
</div>
<!-- Buttons -->
<div style="margin-top: 20px;">
{{-- <button onclick="holdRequest()" style="padding: 10px 20px; margin-right: 10px; background-color:#FF8800; color:#fff; border:none; border-radius:5px; cursor:pointer;">
Hold
</button> --}}
<input type="hidden" id="requestId" value="{{ request()->query('id') }}">
<input type="hidden" id="level" value="{{ request()->query('level') }}">
<button onclick="saveRemark()" style="padding: 10px 20px; background-color:#4CAF50; color:#fff; border:none; border-radius:5px; cursor:pointer;">
Save Remark
</button>
</div>
</td>
</tr>
<!-- Footer -->
<tr>
<td style="padding: 15px; text-align: center; font-size: 12px; color: #999999;">
CRI Digital Manufacturing Solutions<br>
&copy; 2026 All Rights Reserved
</td>
</tr>
</table>
</td>
</tr>
</table>
<script>
function saveRemark() {
const remark = document.getElementById("remark").value.trim();
const id = document.getElementById("requestId").value;
const level = document.getElementById("level").value;
fetch('/characteristic/approve-save', {
method: 'POST',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
},
body: JSON.stringify({
id: id,
level: level,
remark: remark
})
})
.then(res => {
if (!res.ok) {
throw new Error("HTTP error " + res.status);
}
return res.json();
})
.then(data => {
alert('Approved saved successfully!');
window.location.href = "/approval/approve-success";
})
.catch(err => {
console.error(err);
alert('Error saving approve!');
});
}
</script>
</body>
</html>

View File

@@ -0,0 +1,99 @@
<!DOCTYPE html>
<html>
<head>
<title>Action Time Reached</title>
<style>
body {
font-family: Arial, sans-serif;
background: #f6f6f6;
padding: 20px;
}
.status {
margin-top: 15px;
padding: 10px;
border-radius: 6px;
font-weight: bold;
font-size: 16px;
}
.status.Approved {
background-color: #e8f5e9;
color: #2e7d32;
}
.status.Hold {
background-color: #fff3e0;
color: #ef6c00;
}
.status.Rejected {
background-color: #fdecea;
color: #c62828;
}
.approvelevel {
/* color: red; */
font-size: 18px;
font-weight: bold;
}
.card {
background: #ffffff;
padding: 20px;
max-width: 500px;
margin: 50px auto;
border-radius: 6px;
text-align: center;
box-shadow: 0 0 10px rgba(0,0,0,.1);
}
.success {
color: green;
font-size: 18px;
font-weight: bold;
}
.footer {
font-size: 12px;
color: #999999;
text-align: center;
margin-top: 20px;
}
.icon {
font-size: 30px;
margin-bottom: 10px;
color: #ff9800;
}
.approvelevel {
/* color: red; */
font-size: 18px;
font-weight: bold;
}
.status-message.expired {
color: #d84315;
font-weight: bold;
}
</style>
</head>
<body>
<div class="card">
<div class="approvelevel">⚠️ Action Expired</div>
<div class="status {{ $status }}">
Status:
<span class="status-message expired">
{{ $message ?? $status }}
</span>
</div>
{{-- <p>Your approval time limit has expired</p> --}}
<div class="footer">
CRI Digital Manufacturing Solutions<br>
&copy; 2026 All Rights Reserved
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,77 @@
<!DOCTYPE html>
<html>
<head>
<title>Approval</title>
<style>
body {
font-family: Arial, sans-serif;
background: #f6f6f6;
padding: 20px;
}
.card {
background: #ffffff;
padding: 20px;
max-width: 500px;
margin: 50px auto;
border-radius: 6px;
text-align: center;
box-shadow: 0 0 10px rgba(0,0,0,.1);
}
.hold {
color: Green;
font-size: 18px;
font-weight: bold;
}
.footer {
font-size: 12px;
color: #999999;
text-align: center;
margin-top: 20px;
}
a.button {
display: inline-block;
margin-top: 15px;
padding: 10px 20px;
background-color: Green;
color: #ffffff;
text-decoration: none;
border-radius: 5px;
font-weight: bold;
}
.pulse-darkred {
color: Green; /* #8B0000 */
background-color: #fff; /* White bg for contrast */
display: inline-block;
padding: 0.5em 0.75em;
border-radius: 4px;
font-size: 1em;
line-height: 1;
animation: pulse 1.5s ease-in-out infinite; /* Duration, easing, infinite loop */
}
@keyframes pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.2); /* Gentle 5% expansion */
}
}
</style>
</head>
<body>
<div class="card">
<div class="hold"><span class="pulse-darkred">🟢</span> Approved Successfully</div>
<p>Your request has been approved.</p>
<!-- Footer -->
<div class="footer">
CRI Digital Manufacturing Solutions<br>
&copy; 2026 All Rights Reserved
</div>
</div>
</body>
</html>

View File

@@ -13,13 +13,13 @@
<tr>
<td style="padding: 30px; text-align: center;">
<!-- Header -->
<div style="font-size: 40px;">🟠</div>
<h2 style="color: #FF8800; margin: 10px 0 20px; font-size: 24px;">Request On Hold</h2>
{{-- <div style="font-size: 40px;"></div> --}}
<h2 style="color: #FF8800; margin: 10px 0 20px; font-size: 24px;">🟠 Request On Hold</h2>
<!-- Message -->
<p style="font-size: 16px; color: #555555; line-height: 1.5;">
{{-- <p style="font-size: 16px; color: #555555; line-height: 1.5;">
Your request has been temporarily put on hold.
</p>
</p> --}}
<!-- Remark Textbox -->
<div style="margin-top: 20px; text-align: left;">

View File

@@ -1,36 +1,77 @@
<!DOCTYPE html>
<html>
<head>
<title>Request On Hold</title>
<title>On Hold</title>
<style>
body {
font-family: Arial, sans-serif;
background: #f6f6f6;
padding: 20px;
}
.card {
background: #ffffff;
padding: 20px;
max-width: 500px;
margin: 50px auto;
border-radius: 6px;
text-align: center;
box-shadow: 0 0 10px rgba(0,0,0,.1);
}
.hold {
color: #FF8800;
font-size: 18px;
font-weight: bold;
}
.footer {
font-size: 12px;
color: #999999;
text-align: center;
margin-top: 20px;
}
a.button {
display: inline-block;
margin-top: 15px;
padding: 10px 20px;
background-color: #FF8800;
color: #ffffff;
text-decoration: none;
border-radius: 5px;
font-weight: bold;
}
.pulse-darkred {
color: DarkRed; /* #8B0000 */
background-color: #fff; /* White bg for contrast */
display: inline-block;
padding: 0.5em 0.75em;
border-radius: 4px;
font-size: 1em;
line-height: 1;
animation: pulse 1.5s ease-in-out infinite; /* Duration, easing, infinite loop */
}
@keyframes pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.2); /* Gentle 5% expansion */
}
}
</style>
</head>
<body style="font-family: Arial, sans-serif; background-color: #f4f4f4; margin:0; padding:0;">
<table width="100%" cellpadding="0" cellspacing="0" style="padding: 20px 0;">
<tr>
<td align="center">
<!-- Card container -->
<table width="600" cellpadding="0" cellspacing="0" style="background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.1); border: 1px solid #e0e0e0;">
<tr>
<td style="padding: 30px; text-align: center;">
<!-- Header -->
<div style="font-size: 40px;">🟠</div>
<h2 style="color: #FF8800; margin: 10px 0 20px; font-size: 24px;">Request On Hold</h2>
<!-- Message -->
<p style="font-size: 16px; color: #555555; line-height: 1.5;">
Your request has been temporarily put on hold.
</p>
</td>
</tr>
<body>
<div class="card">
<div class="hold"><span class="pulse-darkred">🟠</span> Hold Successfully</div>
<p>Your request has been temporarily put on hold.</p>
<!-- Footer -->
<tr>
<td style="padding: 15px; text-align: center; font-size: 12px; color: #999999;">
<div class="footer">
CRI Digital Manufacturing Solutions<br>
&copy; 2026 All Rights Reserved
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</div>
</body>
</html>

View File

@@ -13,13 +13,13 @@
<tr>
<td style="padding: 30px; text-align: center;">
<!-- Header -->
<div style="font-size: 40px;">🟠</div>
<h2 style="color: #FF0000; margin: 10px 0 20px; font-size: 24px;">Request On Reject</h2>
<div style="font-size: 35px;"></div>
<h2 style="color: #FF0000; margin: 10px 0 20px; font-size: 24px;"> Request On Reject</h2>
<!-- Message -->
<p style="font-size: 16px; color: #555555; line-height: 1.5;">
Your request has been temporarily put on reject.
</p>
{{-- <p style="font-size: 16px; color: #555555; line-height: 1.5;">
Your request has been put on reject.
</p> --}}
<!-- Remark Textbox -->
<div style="margin-top: 20px; text-align: left;">
@@ -42,7 +42,6 @@
Save Remark
</button>
</div>
</td>
</tr>

View File

@@ -19,7 +19,7 @@
}
.rejected {
color: red;
font-size: 20px;
font-size: 18px;
font-weight: bold;
}
.footer {
@@ -38,14 +38,33 @@
border-radius: 5px;
font-weight: bold;
}
.pulse-darkred {
color: DarkRed; /* #8B0000 */
background-color: #fff; /* White bg for contrast */
display: inline-block;
padding: 0.5em 0.75em;
border-radius: 4px;
font-size: 1em;
line-height: 1;
animation: pulse 1.5s ease-in-out infinite; /* Duration, easing, infinite loop */
}
@keyframes pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.2); /* Gentle 5% expansion */
}
}
</style>
</head>
<body>
<div class="card">
<div class="rejected"> Rejected Successfully</div>
<p>The rejection has been recorded.</p>
<p>You may now close this tab.</p>
<div class="rejected"><span class="pulse-darkred"></span> Rejected Successfully</div>
{{-- 🔴 --}}
<p>Your request has been rejected successfully.</p>
<!-- Footer -->
<div class="footer">

View File

@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>Approval Recorded</title>
<title>Approved</title>
<style>
body {
font-family: Arial, sans-serif;
@@ -28,14 +28,33 @@
text-align: center;
margin-top: 20px;
}
.pulse-darkred {
color: Green; /* #8B0000 */
background-color: #fff; /* White bg for contrast */
display: inline-block;
padding: 0.5em 0.75em;
border-radius: 4px;
font-size: 1em;
line-height: 1;
animation: pulse 1.5s ease-in-out infinite; /* Duration, easing, infinite loop */
}
@keyframes pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.25); /* Gentle 5% expansion */
}
}
</style>
</head>
<body>
<div class="card">
<div class="success"> Approval Successful</div>
<p>Your action has been recorded.</p>
<p>You may now close this tab.</p>
<div class="success"><span class="pulse-darkred"></span> Approved Successfully</div>
{{-- 🟢 --}}
<p>Your request has been approved successfully.</p>
<!-- Footer -->
<div class="footer">

View File

@@ -0,0 +1,13 @@
<x-filament-panels::page>
<div class="space-y-4">
{{-- Render the Select form fields --}}
<div class="space-y-4">
{{ $this->form }}
</div>
</div>
</x-filament-panels::page>

View File

@@ -7,6 +7,8 @@
{{ $this->form }}
</div>
{{-- <livewire:notification-sound /> --}}
{{-- <input
type="text"
id="qr-scan-input"
@@ -15,7 +17,35 @@
autocomplete="off"
autofocus
/> --}}
<div class="mb-4">
{{-- <div class="mb-4">
<label for="qr-scan-input" class="block text-sm font-medium text-gray-700 mb-2">
SCAN QR CODE
</label>
<input
type="text"
id="qr-scan-input"
class="border border-gray-300 rounded px-4 py-2 text-sm w-full"
placeholder="Scan QR Code & Press Enter"
autocomplete="off"
autofocus
/>
</div> --}}
{{-- <div class="mb-4">
<label for="qr-scan-input" class="block text-sm font-medium text-gray-700 mb-2">
SCAN QR CODE
</label>
<input
type="text"
id="qr-scan-input"
class="border border-gray-300 rounded px-4 py-2 text-sm w-1/2"
placeholder="Scan QR Code & Press Enter"
autocomplete="off"
autofocus
/>
</div> --}}
<div class="flex gap-6 -mt-6">
<!-- Scan QR Code -->
<div class="w-full">
<label for="qr-scan-input" class="block text-sm font-medium text-gray-700 mb-2">
SCAN QR CODE
</label>
@@ -29,9 +59,34 @@
/>
</div>
<!-- Last Scanned QR -->
{{-- <div class="w-1/2">
<label for="recent-qr-input" class="block text-sm font-medium text-gray-700 mb-2">
LAST SCANNED QR
</label>
<input
type="text"
id="recent-qr-input"
class="border border-gray-300 rounded px-4 py-2 text-sm w-full bg-white-100 text-black"
readonly
wire:model="recent_qr"
/>
</div> --}}
</div>
@push('scripts')
<script>
window.addEventListener('focus-production-order', () => {
const wrapper = document.getElementById('production_order');
const input = wrapper?.querySelector('input,textarea');
if (input) {
input.focus();
input.select();
}
});
document.addEventListener('DOMContentLoaded', function () {
const scanInput = document.getElementById('qr-scan-input');
if (!scanInput) return;
@@ -48,6 +103,7 @@
}
}
});
});
</script>
@endpush

View File

@@ -0,0 +1,19 @@
<x-filament-panels::page>
<div class="space-y-4">
{{-- Render the Select form fields --}}
<div class="space-y-4">
{{ $this->form }}
</div>
<x-filament::button
wire:click="export"
color="primary"
class="mt-4"
>
Export
</x-filament::button>
<div class="bg-white shadow rounded-xl p-4 mt-6">
<livewire:production-target-plan />
</div>
</div>
</x-filament-panels::page>

View File

@@ -0,0 +1,121 @@
<!-- <select id="yearSelect">
<option value="">Select Year</option>
</select> -->
<div id="calendar" wire:ignore></div>
<!-- <input type="text" name="working_days" placeholder="Working Days"> -->
<link href="https://cdn.jsdelivr.net/npm/fullcalendar@6.1.8/index.global.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@6.1.8/index.global.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
let selectedDates = [];
let calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth',
height: 600,
showNonCurrentDates: true,
datesSet: function(info) {
// Clear previous month selections
selectedDates = [];
// Remove background events
calendar.removeAllEvents();
// Recalculate working days for new month
updateWorkingDays(info.view.currentStart);
},
dateClick: function(info) {
let viewMonth = calendar.view.currentStart.getMonth();
let clickedMonth = info.date.getMonth();
if (viewMonth != clickedMonth) return;
let dateStr = info.dateStr;
if (selectedDates.includes(dateStr)) {
selectedDates = selectedDates.filter(d => d !== dateStr);
calendar.getEvents().forEach(event => {
if (event.startStr == dateStr) event.remove();
});
} else {
selectedDates.push(dateStr);
calendar.addEvent({
start: dateStr,
display: 'background',
color: '#f03f17'
});
}
updateWorkingDays(info.date);
}
});
// function updateWorkingDays(date) {
// let totalDays = new Date(
// date.getFullYear(),
// date.getMonth()+1,
// 0
// ).getDate();
// let workingDays = totalDays - selectedDates.length;
// // document.querySelector('input[name="working_days"]').value = workingDays;
// const input = document.querySelector('#working_days');
// input.value = workingDays;
// input.dispatchEvent(new Event('input'));
// const monthInput = document.querySelector('#month');
// monthInput.value = date.getMonth() + 1; // 112 month number
// monthInput.dispatchEvent(new Event('input'));
// const yearInput = document.querySelector('#year');
// yearInput.value = date.getFullYear();
// yearInput.dispatchEvent(new Event('input'));
// const selectedDatesInput = document.querySelector('#selected_dates');
// selectedDatesInput.value = selectedDates.join(',');
// selectedDatesInput.dispatchEvent(new Event('input'));
// }
function updateWorkingDays(date) {
let totalDays = new Date(
date.getFullYear(),
date.getMonth() + 1,
0
).getDate();
let workingDays = totalDays - selectedDates.length;
// Set values only
document.querySelector('#working_days').value = workingDays;
document.querySelector('#month').value = date.getMonth() + 1;
document.querySelector('#year').value = date.getFullYear();
document.querySelector('#selected_dates').value = selectedDates.join(',');
// Trigger only ONE update (important)
document
.querySelector('#selected_dates')
.dispatchEvent(new Event('input'));
}
calendar.render();
});
</script>

View File

@@ -0,0 +1,9 @@
<div class="flex space-x-2 items-center">
<button
type="button"
class="inline-flex items-center px-3 py-1 bg-primary-600 text-white rounded hover:bg-primary-700"
wire:click="saveWorkingDays"
>
Save
</button>
</div>

View File

@@ -220,10 +220,10 @@
{{-- Modal for material invoice--}}
@if($materialInvoice)
{{-- <div class="flex justify-center overflow-x-auto overflow-y-visible" style="height: 385px;"> --}}
<div class="overflow-x-auto overflow-y-visible" style="height: 385px;">
{{-- <table class="min-w-[1500px] text-sm text-center border border-gray-300"> --}}
{{-- <table class="table-fixed min-w-[1500px] text-sm text-center border border-gray-300"> --}}
<table class="min-w-full text-sm text-center border border-gray-300">
{{-- <table class="min-w-full text-sm text-center border border-gray-300"> --}}
<table class="min-w-full mx-auto text-sm text-center border border-gray-300">
<thead class="bg-gray-100 font-bold">
<tr>
<th class="border px-4 py-2">No</th>
@@ -242,7 +242,13 @@
<td class="border px-4 py-2">{{ $index + 1 }}</td>
<td class="border px-4 py-2">{{ $row['code'] ?? 'N/A' }}</td>
<td class="border px-4 py-2">{{ $row['material_type'] ?? 'N/A' }}</td>
<td class="border px-4 py-2">{{ $row['quantity'] ?? 'N/A' }}</td>
<td class="border px-4 py-2">
@if(($row['material_type'] ?? '') === 'Individual' || ($row['material_type'] ?? '') === 'Bundle')
{{ number_format((float)($row['quantity'] ?? 0), 0) }}
@else
{{ $row['quantity'] ?? 'N/A' }}
@endif
</td>
<td class="border px-4 py-2">{{ $row['serial_number'] ?? 'N/A' }}</td>
<td class="border px-4 py-2">{{ $row['batch_number'] ?? 'N/A' }}</td>
<td class="border px-4 py-2">{{ $row['created_at'] ?? 'N/A' }}</td>

View File

@@ -0,0 +1,86 @@
<div class="p-4">
<h2 class="text-lg font-bold mb-4 text-gray-700 uppercase tracking-wider">
PRODUCTION PLAN TABLE:
</h2>
<div class="overflow-x-auto rounded-lg shadow">
<table class="w-full divide-y divide-gray-200 text-sm text-center">
<thead class="bg-gray-100 text-s font-semibold uppercase text-gray-700">
<tr>
<th class="border px-4 py-2" rowspan="3">No</th>
<th class="border px-4 py-2 whitespace-nowrap" rowspan="3">Plant</th>
<th class="border px-4 py-2 whitespace-nowrap" rowspan="3">Line</th>
<th class="border px-4 py-2 whitespace-nowrap" rowspan="3">Item Code</th>
<th class="border px-4 py-2 whitespace-nowrap" colspan="{{ count($dates) * 3 }}" class="text-center">
Production Plan Dates
</th>
</tr>
<tr>
@foreach($dates as $date)
{{-- <th colspan="3" class="text-center">
{{ $date }}
</th> --}}
<th colspan="3" class="text-center border-r-4 border-gray-400">
{{ $date }}
</th>
@endforeach
</tr>
<tr>
@foreach($dates as $date)
<th class="border px-4 py-2 whitespace-nowrap">Line Capacity</th>
<th class="border px-4 py-2 whitespace-nowrap">Target Plan</th>
<th class="border px-4 py-2 whitespace-nowrap border-r-4 border-gray-400">
Produced Quantity
</th>
{{-- <th class="border px-4 py-2 whitespace-nowrap">Produced Quantity</th> --}}
@endforeach
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
@forelse ($records as $index => $record)
<tr class="hover:bg-gray-50">
<td class="border px-4 py-2">{{ $index + 1 }}</td>
<td class="border px-4 py-2 whitespace-nowrap">{{ $record['plant_name'] }}</td>
<td class="border px-4 py-2 whitespace-nowrap">{{ $record['line_name'] }}</td>
<td class="border px-4 py-2 whitespace-nowrap">{{ $record['item_code'] }}</td>
{{-- @foreach($dates as $date)
<td class="border px-4 py-2 whitespace-nowrap">{{ $record['target_plan'][$date] ?? '-' }}</td>
<td class="border px-4 py-2 whitespace-nowrap">{{ $record['production_plan'][$date] ?? '-' }}</td>
@endforeach --}}
@foreach($dates as $date)
@if(in_array($date, $leaveDates))
<td class="border px-4 py-2 whitespace-nowrap">-</td>
<td class="border px-4 py-2 whitespace-nowrap">-</td>
<td class="border px-4 py-2 whitespace-nowrap">-</td>
@else
{{-- <td class="border px-4 py-2 whitespace-nowrap">{{ $record['daily_target'] ?? '-' }}</td> --}}
<td class="border px-4 py-2 whitespace-nowrap">
{{ $record['daily_line_capacity'][$date] ?? '-' }}
</td>
<td class="border px-4 py-2 whitespace-nowrap">
{{ $record['daily_target_dynamic'][$date] ?? '-' }}
</td>
<td class="border px-4 py-2 whitespace-nowrap">
{{ $record['produced_quantity'][$date] ?? '-' }}
</td>
{{-- <td class="border px-4 py-2 whitespace-nowrap">{{ $record['produced_quantity'] ?? '-' }}</td> --}}
@endif
@endforeach
</tr>
@empty
<tr>
<td colspan="10" class="px-4 py-4 text-center text-gray-500">
No production plan data found.
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>

View File

@@ -39,7 +39,7 @@
{{-- Modal for empty invoice--}}
@if ($emptyInvoice)
<div class="text-center text-red-500">
<p>No data found for invoice number <strong>{{ $invoiceNumber }}</strong>.</p>
<p>No data found for the invoice number <strong>{{ $invoiceNumber }}</strong>.</p>
</div>
@endif
@@ -84,7 +84,7 @@
@empty
<tr>
<td colspan="12" class="text-center py-4 text-gray-500">
No data found for invoice number <strong>{{ $invoiceNumber }}</strong>.
No data found for the invoice number <strong>{{ $invoiceNumber }}</strong>.
</td>
</tr>
@endforelse
@@ -164,7 +164,7 @@
@empty
<tr>
<td colspan="10" class="text-center py-4 text-gray-500">
No data found for invoice number <strong>{{ $invoiceNumber }}</strong>.
No data found for the invoice number <strong>{{ $invoiceNumber }}</strong>.
</td>
</tr>
@endforelse
@@ -182,15 +182,34 @@
});
</script> --}}
<script>
window.addEventListener('focus-capacitor-input', () => {
window.addEventListener('focus-capacitor-input', (event) => {
console.log('Item Code:', event.detail.itemCode);
const container = document.getElementById('focus-capacitor-input');
if (container) {
container.dataset.itemCode = event.detail.itemCode;
}
setTimeout(() => {
const input = document.getElementById('capacitorInput');
// const container = document.getElementById('focus-capacitor-input');
const input = container?.querySelector('input'); // gets the actual input inside
if (input) {
input.focus();
input.select();
}
}, 50);
});
// window.addEventListener('focus-capacitor-input', (event) => {
// console.log('Item Code:', event.detail.itemCode);
// setTimeout(() => {
// const input = document.querySelector('#capacitorInput input');
// if (input) {
// input.focus();
// input.select();
// }
// }, 50);
// });
window.addEventListener('focus-serial-number', () => {
setTimeout(() => {

View File

@@ -12,52 +12,54 @@
<br>
<p>{!! $greeting !!}</p>
<table border="1" width="50%" cellpadding="6" cellspacing="0">
<table style="margin-left: 3%" border="1" width="30%" cellpadding="6" cellspacing="0">
<tr>
<th width="30%">Title</th>
<th width="40%">Details</th>
</tr>
<tr>
<td>Requested Date Time</td>
<td>{{ $request->created_at->format('d-m-Y H:i:s') }}</td>
<td style="text-align: center;">{{ $request->created_at->format('d-m-Y H:i:s') }}</td>
</tr>
<tr>
<td>Plant</td>
<td>{{ $request->plant->name ?? $request->plant_id }}</td>
<td>Plant Name</td>
<td style="text-align: center;">{{ $request->plant->name ?? $request->plant_id }}</td>
</tr>
<tr>
<td>Item Code</td>
<td>{{ $request->item->code ?? $request->code }}</td>
<td style="text-align: center;">{{ $request->item->code ?? $request->code }}</td>
</tr>
<tr>
<td>Job Number</td>
<td>{{ $request->aufnr }}</td>
<td style="text-align: center;">{{ $request->aufnr }}</td>
</tr>
<tr>
<td>Work Flow ID</td>
<td style="text-align: center;">{{ $request->work_flow_id }}</td>
</tr>
</table>
<br>
<table border="1" width="50%" cellpadding="6" cellspacing="0">
@if($approverNameFromMaster && $approverNameFromMaster->approver_type == 'Characteristic')
<table style="margin-left: 3%" border="1" width="50%" cellpadding="6" cellspacing="0">
<tr>
<th>Characteristics Name</th>
<th>SAP Value</th>
<th>Update Value</th>
<th>WorkFlow ID</th>
{{-- <th>Work Flow ID</th> --}}
</tr>
@forelse ($tableData as $char)
<tr>
{{-- <td>{{ $char['characteristic_name'] ?? '-' }}</td> --}}
<td>{{ strtoupper($char['characteristic_name'] ?? '-') }}</td>
<td>{{ $char['current_value'] ?? '-' }}</td>
<td>{{ $char['update_value'] ?? '-' }}</td>
<td>{{ $char['work_flow_id'] ?? '-' }}</td>
<td style="text-align: center;">{{ strtoupper($char['characteristic_name'] ?? '-') }}</td>
<td style="text-align: center;">{{ $char['current_value'] ?? '-' }}</td>
<td style="text-align: center;">{{ $char['update_value'] ?? '-' }}</td>
{{-- <td style="text-align: center;">{{ $char['work_flow_id'] ?? '-' }}</td> --}}
{{-- @if ($loop->first)
<td rowspan="{{ count($tableData) }} "style="text-align: center; vertical-align: middle;">
{{ $char['work_flow_id'] ?? '-' }}
</td>
@endif --}}
</tr>
@empty
<tr>
@@ -66,21 +68,117 @@
@endforelse
</table>
<br>
<table border="1" width="50%" cellpadding="6" cellspacing="0">
<table style="margin-left: 3%" border="1" width="30%" cellpadding="6" cellspacing="0">
<tr>
<th>Approver Name</th>
<th>Approve Status</th>
</tr>
@if($level == 2)
<tr>
<td>{{ $approverName }}</td>
<td style="text-align: center;">{{ $approverNameFromMaster->name1 }}</td>
<td style="text-align: center;">{{ ucfirst($pendingApprovers->approver_status1 ?? '-') }}</td>
</tr>
<tr>
<td style="text-align: center;">{{ $approverName }}</td>
<td style="text-align: center;">
<a href="{{ $approveUrl }}">Approve</a> |
<a href="{{ $holdUrl }}">Hold</a> |
<a href="{{ $rejectUrl }}">Reject</a>
<a href="{{ $approveUrl }}" style="color: #28a745; font-weight: bold; text-decoration: underline;">Approve</a>
&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;
<a href="{{ $holdUrl }}" style="color: #FF8800; font-weight: bold; text-decoration: underline;">Hold</a>
&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;
<a href="{{ $rejectUrl }}" style="color: #dc3545; font-weight: bold; text-decoration: underline;">Reject</a>
</td>
</tr>
@elseif ($level == 3)
<tr>
<td style="text-align: center;">{{ $approverNameFromMaster->name1 }}</td>
<td style="text-align: center;">{{ ucfirst($pendingApprovers->approver_status1 ?? '-') }}</td>
</tr>
<tr>
<td style="text-align: center;">{{ $approverNameFromMaster->name2 }}</td>
<td style="text-align: center;">{{ ucfirst($pendingApprovers->approver_status2 ?? '-') }}</td>
</tr>
<tr>
<td style="text-align: center;">{{ $approverName }}</td>
<td style="text-align: center;">
<a href="{{ $approveUrl }}" style="color: #28a745; font-weight: bold; text-decoration: underline;">Approve</a>
&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;
<a href="{{ $holdUrl }}" style="color: #FF8800; font-weight: bold; text-decoration: underline;">Hold</a>
&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;
<a href="{{ $rejectUrl }}" style="color: #dc3545; font-weight: bold; text-decoration: underline;">Reject</a>
</td>
</tr>
@else
<tr>
<td style="text-align: center;">{{ $approverName }}</td>
<td style="text-align: center;">
<a href="{{ $approveUrl }}" style="color: #28a745; font-weight: bold; text-decoration: underline;">Approve</a>
&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;
<a href="{{ $holdUrl }}" style="color: #FF8800; font-weight: bold; text-decoration: underline;">Hold</a>
&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;
<a href="{{ $rejectUrl }}" style="color: #dc3545; font-weight: bold; text-decoration: underline;">Reject</a>
</td>
</tr>
@endif
</table>
@elseif($approverNameFromMaster && $approverNameFromMaster->approver_type == 'Quality')
<br>
<table style="margin-left: 3%" border="1" width="50%" cellpadding="6" cellspacing="0">
<tr>
<th>Approver Name</th>
<th>Approve Status</th>
</tr>
@if($level == 2)
<tr>
<td style="text-align: center;">{{ $approverNameFromMaster->name1 }}</td>
<td style="text-align: center;">{{ ucfirst($pendingApprovers->approver_status1 ?? '-') }}</td>
</tr>
<tr>
<td style="text-align: center;">{{ $approverName }}</td>
<td style="text-align: center;">
<a href="{{ $approveUrl }}" style="color: #28a745; font-weight: bold; text-decoration: underline;">Approve</a>
&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;
<a href="{{ $holdUrl }}" style="color: #FF8800; font-weight: bold; text-decoration: underline;">Hold</a>
&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;
<a href="{{ $rejectUrl }}" style="color: #dc3545; font-weight: bold; text-decoration: underline;">Reject</a>
</td>
</tr>
@elseif ($level == 3)
<tr>
<td style="text-align: center;">{{ $approverNameFromMaster->name1 }}</td>
<td style="text-align: center;">{{ ucfirst($pendingApprovers->approver_status1 ?? '-') }}</td>
</tr>
<tr>
<td style="text-align: center;">{{ $approverNameFromMaster->name2 }}</td>
<td style="text-align: center;">{{ ucfirst($pendingApprovers->approver_status2 ?? '-') }}</td>
</tr>
<tr>
<td style="text-align: center;">{{ $approverName }}</td>
<td style="text-align: center;">
<a href="{{ $approveUrl }}" style="color: #28a745; font-weight: bold; text-decoration: underline;">Approve</a>
&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;
<a href="{{ $holdUrl }}" style="color: #FF8800; font-weight: bold; text-decoration: underline;">Hold</a>
&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;
<a href="{{ $rejectUrl }}" style="color: #dc3545; font-weight: bold; text-decoration: underline;">Reject</a>
</td>
</tr>
@else
<tr>
<td style="text-align: center;">{{ $approverName }}</td>
<td style="text-align: center;">
<a href="{{ $approveUrl }}" style="color: #28a745; font-weight: bold; text-decoration: underline;">Approve</a>
&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;
<a href="{{ $holdUrl }}" style="color: #FF8800; font-weight: bold; text-decoration: underline;">Hold</a>
&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;
<a href="{{ $rejectUrl }}" style="color: #dc3545; font-weight: bold; text-decoration: underline;">Reject</a>
</td>
</tr>
@endif
</table>
@endif
<p>{!! $wishes !!}</p>
</div>