622 Commits

Author SHA1 Message Date
8fa1f54b81 Merge pull request 'action/kingfisher' (#7) from action/kingfisher into master
All checks were successful
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Successful in 10s
Reviewed-on: #7
2025-11-25 08:22:15 +00:00
5f23856b09 Update .github/workflows/kingfisher-secrets-scan.yaml
All checks were successful
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Successful in 3m48s
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Successful in 11s
2025-11-25 08:17:04 +00:00
8c2e42c47e Add .github/workflows/kingfisher-secrets-scan.yaml
All checks were successful
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Successful in 5m51s
2025-11-25 08:10:33 +00:00
158590a399 Merge pull request 'Configure Renovate' (#4) from renovate/configure into master
Reviewed-on: #4
2025-11-25 08:02:19 +00:00
4f4fe60aa0 Add renovate.json 2025-11-25 08:01:40 +00:00
dhanabalan
39a2fed9a8 Added mail trigegr lofic agisnt Quality validation 2025-11-24 10:50:02 +05:30
dhanabalan
6c928e16ea issue solved in part validation error 2025-11-24 10:10:00 +05:30
dhanabalan
dce5b1af45 issue solved in part validation for loadign image 2025-11-24 09:42:43 +05:30
dhanabalan
232befdf8f added filter logic and upload part validation image 2025-11-24 09:27:56 +05:30
dhanabalan
6638569367 Addded quality mail page for quality validation 2025-11-24 09:25:23 +05:30
dhanabalan
921f70c8eb Added partvalidation image in route web url 2025-11-24 09:24:12 +05:30
dhanabalan
d5738a381d Added part validation mail trigger logic and image uploading 2025-11-24 09:12:56 +05:30
dhanabalan
be5b7751a1 Added part validation error images 2025-11-24 09:10:34 +05:30
dhanabalan
e031e57557 issue solved added live debounce in users screen to avoid text clearing 2025-11-24 08:47:35 +05:30
dhanabalan
5b2f86569a Added searchable in process order 2025-11-22 14:31:24 +05:30
dhanabalan
3958a73a2c Added validation logic in process order importer 2025-11-22 12:02:24 +05:30
dhanabalan
8596c9109f removed columns coilnumber and order quantity,received quantity in import 2025-11-22 11:45:07 +05:30
dhanabalan
affa38251d Update invoice data handling to include onCapFocus parameter and adjust focus function and timing for input fields 2025-11-21 17:18:31 +05:30
dhanabalan
376ee84e63 Re-Updating Capacitor QR focus issue 2025-11-21 16:00:14 +05:30
dhanabalan
7ff3b95aea Updating Capacitor QR focus issue 2025-11-21 15:56:43 +05:30
dhanabalan
97348d39ae Solving Capacitor QR focus issue 2025-11-21 15:54:18 +05:30
dhanabalan
21ff5fa21f Updated focus invoice and serial number logic in throughout invoice validation related pages (resource, create, livewire, blade) 2025-11-20 19:45:04 +05:30
dhanabalan
c7391b113f Refactor invoice processing to reset form fields after completion 2025-11-20 18:08:52 +05:30
dhanabalan
e20e402233 Added description loaded logic in editing in process order screen 2025-11-20 17:40:48 +05:30
dhanabalan
098daae653 Added minimum length validation for name and description fields in WorkGroupMasterResource form 2025-11-20 17:18:28 +05:30
dhanabalan
18e232ffb3 Added numeric type for received quantity 2025-11-20 12:29:26 +05:30
dhanabalan
5c6c6e56ac changed data type of column received_quantity in process orders table 2025-11-20 12:16:43 +05:30
dhanabalan
4f5791a260 added import and export permissions for process order 2025-11-19 14:45:59 +05:30
dhanabalan
3be0066eee modified logic in process order 2025-11-19 14:22:21 +05:30
dhanabalan
0be804d81c added received quantity logic in api 2025-11-19 13:38:20 +05:30
dhanabalan
b89d96f859 modified logic in process order 2025-11-19 11:31:03 +05:30
dhanabalan
dc8627dd0a Refactored invoice processing logic to ensure file deletion occurs correctly and added additional condition for marking serial numbers. 2025-11-19 10:42:28 +05:30
dhanabalan
b6c711fc6f Refactored invoice processing logic to ensure file deletion occurs correctly and added additional condition for marking serial numbers. 2025-11-19 10:40:06 +05:30
dhanabalan
5f1fcf4be4 Added all validations in process order 2025-11-18 10:35:47 +05:30
dhanabalan
1f64c3b36d Added validation logic in process order importer 2025-11-18 09:48:31 +05:30
dhanabalan
918d216474 changed import column name for item_id as item in process order 2025-11-18 09:10:04 +05:30
dhanabalan
afdfd51e5a Added process order importer and exporter 2025-11-18 09:04:12 +05:30
dhanabalan
cba366037f Added process order exporter 2025-11-18 09:03:40 +05:30
dhanabalan
0f4e475ab8 Added process order importer 2025-11-18 09:03:14 +05:30
dhanabalan
e47ab43aa3 Added logic for total received quantity in process order 2025-11-17 14:16:18 +05:30
dhanabalan
85876ca47f added get and post api link for process order in api.php file 2025-11-17 14:02:38 +05:30
dhanabalan
533ad72ca8 Added get and post api for process order 2025-11-17 14:00:46 +05:30
dhanabalan
fac2b36956 Added columns in resource page of process order 2025-11-17 13:59:47 +05:30
dhanabalan
84398f8b45 added column snames in model file of process order 2025-11-17 13:58:48 +05:30
dhanabalan
b940e0519c Added columns coil_number,order_quantity,received_quantity in table process_orders 2025-11-17 13:57:23 +05:30
dhanabalan
23e823d2ea Add file handling for invoice processing and cleanup in LocatorInvoiceValidation 2025-11-15 20:25:16 +05:30
dhanabalan
3e41bad7f1 Refactor code structure for improved readability and maintainability and Commented imported invoice logic on warning 2025-11-15 20:04:30 +05:30
dhanabalan
43ee1a3502 Refactor code structure for improved readability and maintainability and Commented imported invoice logic on warning 2025-11-15 19:27:48 +05:30
dhanabalan
95e18838ca Sort work centers by name in get_data method of MachineController 2025-11-15 17:29:45 +05:30
dhanabalan
a6d8d57fd5 Add new route to retrieve machine data against plant and line in MachineController 2025-11-15 17:10:14 +05:30
dhanabalan
7c773f2cca Enhance MachineController with detailed validation and Machine Data Retrieval against plant and line 2025-11-15 17:07:25 +05:30
dhanabalan
b2ad2ef6ce Refactor work group visibility logic in LineResource form 2025-11-15 17:02:44 +05:30
dhanabalan
41f9ec2990 Added location column in invoice data report 2025-11-15 10:09:09 +05:30
dhanabalan
6160570a7d Fix sticker type checkbox state updates in StickerMasterResource form 2025-11-15 08:55:29 +05:30
dhanabalan
3a5c796d2f Commented out disabled conditions for checkbox components in StickerMasterResource form 2025-11-14 19:17:00 +05:30
dhanabalan
62156bbb63 Added location column in exporter of invoice data validations 2025-11-14 18:59:44 +05:30
dhanabalan
3e81effde4 Added location form in resource page in invoice data validations 2025-11-14 18:55:45 +05:30
dhanabalan
39bf9c3baa Added location column in model file of invoice data validations 2025-11-14 18:54:47 +05:30
dhanabalan
01d217dce8 Added location column in invoice data validations 2025-11-14 18:53:14 +05:30
dhanabalan
7af5e9ec64 Correct capitalization in invoice data table package count messages 2025-11-14 18:30:16 +05:30
dhanabalan
d5159a2cdc issue solved for updating in capacitor scanned quanity in invoice validation 2025-11-14 18:21:56 +05:30
dhanabalan
40bf30e10f Update export action label in ItemResource from 'Import Items' to 'Export Items' 2025-11-14 17:58:18 +05:30
dhanabalan
3bdc0d1859 Refactor invoice validation logic and clean up commented code 2025-11-14 16:34:27 +05:30
dhanabalan
fc8b6382ac Added no of packages serial invoice validation and notification time increased 2025-11-14 15:19:57 +05:30
dhanabalan
cd48b9bdf6 modified logic in upload ocr 2025-11-14 10:56:22 +05:30
dhanabalan
adf1b57fd5 Added comma in verify method 2025-11-14 10:49:29 +05:30
dhanabalan
7d432de245 modified logic in ocr 2025-11-14 10:48:38 +05:30
dhanabalan
6f624b4514 Added verify method and optimized method in ocr 2025-11-14 10:27:52 +05:30
dhanabalan
19af7051a9 Added verify method in ocr 2025-11-14 10:25:42 +05:30
dhanabalan
9491b37a89 modified total method logic camera capture in ocr 2025-11-14 10:20:58 +05:30
dhanabalan
6bd3ca61f7 modified logic in camera capture for ocr 2025-11-14 10:07:02 +05:30
dhanabalan
f39ac5ee2f Update invoice email subject to include STO invoice reference 2025-11-13 17:35:27 +05:30
dhanabalan
fa05a667b1 Added permissions for import and export of sticker mapping master 2025-11-13 16:37:19 +05:30
dhanabalan
68cd0b81a2 1. Added import and export actions with labels and warning colors for the following resources:
- LineResource
  - LineStopResource
  - LocatorResource
  - MachineResource
  - MfmMeterResource
  - MfmParameterResource
  - MotorTestingMasterResource
  - PlantResource
  - ProductionLineStopResource
  - ProductionPlanResource
  - ProductionQuantityResource
  - QualityValidationResource
  - SerialValidationResource
  - ShiftResource
  - StickerMasterResource
  - UserResource
  - WorkGroupMasterResource
2. Updated camera capture functionality to ensure overlay canvas size syncs with video size.
2025-11-13 16:27:48 +05:30
dhanabalan
d9e1190d92 removed material in filter for serial validation 2025-11-13 12:09:37 +05:30
dhanabalan
00d236dfd5 Added logs method in production report 2025-11-13 11:08:13 +05:30
dhanabalan
b756a6f128 increased max execution limit in production report 2025-11-13 10:22:20 +05:30
dhanabalan
4046d68656 changed subject name of the invoice data report 2025-11-13 09:37:50 +05:30
dhanabalan
5b26179ffb setting up pwa in laravel in new method 2025-11-13 09:01:14 +05:30
dhanabalan
2b36d73c5d chnaged url in admin panel provider 2025-11-13 08:50:42 +05:30
dhanabalan
55321ebb59 modified logic in admin panel provider 2025-11-13 08:45:13 +05:30
dhanabalan
51c97cf1a2 removed plant checking in invoice out validations 2025-11-12 15:50:45 +05:30
dhanabalan
9a7ea00846 Added customer code column and no of days pending and indication colour messages 2025-11-12 09:45:24 +05:30
dhanabalan
9eaf86d347 Enhance InvoiceDataMail to accept a dynamic subject and update SendInvoiceDataReport command accordingly 2025-11-11 09:32:46 +05:30
dhanabalan
26ad8b2ed8 Refactor SendInvoiceDataReport command for improved readability and consistency 2025-11-08 20:23:11 +05:30
dhanabalan
af0db6275f Refactor duplicate entry handling and improve error notifications in InvoiceDataValidationResource 2025-11-08 18:27:23 +05:30
dhanabalan
3291c47d2c Improve error messages for clarity and consistency in InvoiceOutValidationResource 2025-11-08 17:51:12 +05:30
dhanabalan
317e877255 Refactor duplicate QR code messages for consistency in wording and clarity 2025-11-08 16:20:00 +05:30
dhanabalan
b25b42083f Fix notification message for successful import by adding a period at the end 2025-11-08 16:03:32 +05:30
dhanabalan
7830631cdc Remove commented-out Plant ID column from AlertMailRuleResource table for cleaner code 2025-11-08 16:02:33 +05:30
dhanabalan
fbab6e6591 Remove commented-out Plant ID column from AlertMailRuleResource table for cleaner code 2025-11-08 13:08:49 +05:30
dhanabalan
4c64602dfd Enhance AlertMailRuleResource table columns with improved labels and added Plant ID column for better clarity and searchability 2025-11-08 13:00:23 +05:30
dhanabalan
ec1dfe0146 Refactor PlantResource table to remove commented 'id' column and enhance 'id' column with label, alignment, sorting, and searchability options 2025-11-08 12:49:24 +05:30
dhanabalan
b7a8c933ff Enhance invoice out validation table with searchable 'updated_by' column and improved duplicate handling logic on import 2025-11-08 12:21:24 +05:30
dhanabalan
d8a66e7678 removed challan in invoice data dashboard 2025-11-08 01:46:30 +05:30
dhanabalan
3da1616a9f Added logic for duplicate validation in invoice out validation screen 2025-11-08 01:37:07 +05:30
dhanabalan
2004d490b6 Added duplicate document number logic in invoice out validation screen 2025-11-08 01:28:12 +05:30
dhanabalan
e4b4a9c5d9 removed unwanted commented lines in send invoice data report 2025-11-08 01:14:58 +05:30
dhanabalan
b4a2cf132c Added logic for checking document number against plant in invoice data validations screen 2025-11-08 01:12:53 +05:30
dhanabalan
afb45a2d5b changed logic for distributions in invoice data validations 2025-11-08 00:10:05 +05:30
dhanabalan
aaf8f52228 issue solved for no column 2025-11-07 23:57:50 +05:30
dhanabalan
26a84c64e6 Added no in table report 2025-11-07 23:52:40 +05:30
dhanabalan
e38c96f2ca Update end date calculation in SendInvoiceDataReport to add one day and set time to 10:00 AM 2025-11-07 23:14:11 +05:30
dhanabalan
f6c2f10f5a Refactor invoice retrieval in SendInvoiceDataReport to use unique document numbers and maintain order 2025-11-07 23:04:54 +05:30
dhanabalan
3e93e924fc Refactor invoice data handling in SendInvoiceDataReport to improve document number processing and remove commented-out code 2025-11-07 23:02:03 +05:30
dhanabalan
e27504d46d Add duplicate entry checks in InvoiceDataValidationResource for database and file uploads 2025-11-07 22:37:46 +05:30
dhanabalan
be2b02c1c9 Refactor invoice data handling in SendInvoiceDataReport to improve filtering and sorting of invoices 2025-11-07 22:35:58 +05:30
dhanabalan
713429b453 Enhance invoice data report styling by adding left text alignment for customer trade name 2025-11-07 20:14:00 +05:30
dhanabalan
6770aaa25a Refactor plant selection logic in InvoiceValidationResource to improve readability and maintainability 2025-11-07 15:21:20 +05:30
dhanabalan
4ac8dde11e Add invalid-serial email template for notifications on serial validation 2025-11-07 15:09:23 +05:30
dhanabalan
59a864917b Add InvalidSerialMail class for dynamic email notifications based on serial number validation 2025-11-07 15:05:26 +05:30
dhanabalan
e8a0d4eae6 Add email notification for invalid serial numbers in processSerialNumber method 2025-11-07 14:52:53 +05:30
dhanabalan
11ab8ce326 Refactor invoice query in SendInvoiceDataReport to use groupBy and orderBy for improved data retrieval 2025-11-06 13:58:19 +05:30
dhanabalan
f82dd74d9d Refactor status color logic in SendInvoiceDataReport to improve document date comparison 2025-11-06 13:52:03 +05:30
dhanabalan
8ba21630d8 Fix column reference for plant in InvoiceOutValidationExporter 2025-11-06 12:28:40 +05:30
dhanabalan
c51e05f058 Add searchable functionality to scanned_at, scanned_by, created_at, and created_by columns in InvoiceOutValidationResource table 2025-11-06 11:55:10 +05:30
dhanabalan
f1e64bd830 Refactor AlertMailRuleResource form and table to enhance CC emails input and add searchable functionality to multiple columns 2025-11-06 10:14:49 +05:30
dhanabalan
570ce9473d Refactor SendInvoiceDataReport and InvoiceDataMail to dynamically set date range for daily reports and improve email content formatting 2025-11-06 09:51:19 +05:30
dhanabalan
7c1946d879 Update daily invoice data report scheduling time to 10:00 2025-11-05 18:04:22 +05:30
dhanabalan
a1ba7318ec Add searchable functionality to document number column in InvoiceDataValidationResource table 2025-11-05 18:01:47 +05:30
dhanabalan
5aa45834fe Refactor invoice data report to improve status handling and styling 2025-11-05 17:39:33 +05:30
dhanabalan
59430dec32 Update greeting and report period messages in InvoiceDataMail for clarity and consistency 2025-11-05 17:28:42 +05:30
dhanabalan
bd555564a0 Enhance SendInvoiceDataReport to include 'WOS' distribution and improve email handling logic 2025-11-05 17:27:30 +05:30
dhanabalan
7e66c8f2ea Refactor invoice data query for 'Challan' distribution to handle null or empty distribution channel descriptions 2025-11-05 14:44:49 +05:30
dhanabalan
0b034a7963 Add support for 'WOS' distribution in InvoiceDataChart for comprehensive invoice tracking 2025-11-05 14:40:04 +05:30
dhanabalan
cbb3a62997 Add 'WOS' to the list of distributions in SendInvoiceDataReport for enhanced reporting options 2025-11-05 14:34:39 +05:30
dhanabalan
ce2acaa642 Update time settings (from 8 to 10) in SendInvoiceDataReport and InvoiceDataMail for daily schedule to improve report accuracy 2025-11-05 13:20:50 +05:30
dhanabalan
f31ed4090b Add searchable functionality to invoice data table columns for improved user experience 2025-11-05 13:09:03 +05:30
dhanabalan
516b3fd514 Comment out 'Distribution Type' and 'Customer Code' columns in invoice data report for improved clarity 2025-11-05 12:37:37 +05:30
dhanabalan
211baa58ed Remove 'distribution_type' and 'customer_code' from invoice data report for improved clarity 2025-11-05 12:26:55 +05:30
dhanabalan
7473abcc94 Remove 'Distribution Type' and 'Customer Code' columns from invoice data report table for improved clarity 2025-11-05 12:20:13 +05:30
dhanabalan
9b2e7b4e98 Refactor SendInvoiceDataReport command to streamline email recipient handling and improve clarity in processing mail rules 2025-11-05 11:17:17 +05:30
dhanabalan
d8acd8ed52 Fix typo in install prompt message for PWA 2025-11-04 18:45:08 +05:30
dhanabalan
1d0f19b097 Remove PWAServiceProvider as part of PWA integration refactor 2025-11-04 17:59:06 +05:30
dhanabalan
b00c819388 Refactor PWAServiceProvider and AdminPanelProvider to enable PWA integration with render hooks for service worker and manifest 2025-11-04 17:19:26 +05:30
dhanabalan
ba60c41951 Add PWAServiceProvider and pwa-install.js for PWA integration 2025-11-04 17:11:22 +05:30
dhanabalan
9cf5e34568 Refactor app.blade.php to comment out existing PWA manifest and service worker registration, and add new commented-out HTML structure for PWA integration 2025-11-04 16:48:21 +05:30
dhanabalan
6dc9b89851 Add install popup for PWA in AdminPanelProvider 2025-11-04 16:32:02 +05:30
dhanabalan
e92ab121d6 Update icons in manifest.json to use correct logo file names 2025-11-04 16:23:49 +05:30
dhanabalan
fc97a18b74 Update start_url in manifest.json to point to root and restructure icons array 2025-11-04 16:05:00 +05:30
dhanabalan
9c78996300 Update start_url in manifest.json to point to /admin 2025-11-04 15:41:40 +05:30
dhanabalan
73c85c9c92 Fix favicon registration and update service worker registration logging in AdminPanelProvider 2025-11-04 15:37:25 +05:30
dhanabalan
6a9d077c59 Inject PWA manifest and service worker registration into AdminPanelProvider 2025-11-04 15:31:38 +05:30
dhanabalan
420ab6c27b Inject PWA manifest and service worker registration into Filament head section 2025-11-04 15:07:38 +05:30
dhanabalan
98b379919b Remove PWA related render hook for manifest and service worker registration from AdminPanelProvider 2025-11-04 14:58:39 +05:30
dhanabalan
a7c9e14271 Add PWA support by registering service worker and including manifest link in head 2025-11-04 14:54:31 +05:30
dhanabalan
dec1a436a3 Refactor service worker to streamline caching logic and improve offline support 2025-11-04 14:25:05 +05:30
dhanabalan
e729742aa3 Enable PWA support by un-commenting manifest link and updating service worker registration path 2025-11-04 14:19:38 +05:30
dhanabalan
15c2a80b3b Refactor app layout to enable PWA support with updated meta tags and service worker registration 2025-11-04 14:10:08 +05:30
dhanabalan
54e0760f94 Enhance invoice validation by adding plant type checks and improving error handling for imports 2025-11-04 10:41:56 +05:30
dhanabalan
f83df4498b Refactor service worker to improve caching strategy and offline support 2025-11-04 09:55:06 +05:30
dhanabalan
aed8c36089 Add PWA support with service worker, manifest, and offline page 2025-11-04 09:44:37 +05:30
dhanabalan
f47f5182a2 Refactor SendInvoiceDataReport command to correctly handle CC emails and improve email fetching logic 2025-11-02 17:37:02 +05:30
dhanabalan
123572011e Add 'CC Emails' field to AlertMailRule form and table display 2025-11-02 17:02:59 +05:30
dhanabalan
08ad41ef58 Fix duplicate entry of 'cc_emails' in fillable attributes of AlertMailRule model 2025-11-02 16:59:34 +05:30
dhanabalan
853cdcf1a1 Add cc_emails column to alert_mail_rules table in migration 2025-11-02 16:57:07 +05:30
dhanabalan
92bcbc0e8d Update invoice data report references in command and scheduling logic 2025-11-02 16:51:40 +05:30
dhanabalan
1cb54f5101 Add condition to filter invoice data rules by 'InvoiceDataMail' in scheduling 2025-11-02 16:47:38 +05:30
dhanabalan
9f38cda857 Add SendInvoiceDataReport command and InvoiceDataMail class with HTML view for invoice data reporting 2025-11-02 16:33:12 +05:30
dhanabalan
4f51643254 Added 'Invoice Data Mail' option into rule name in AlertMailRuleResource 2025-11-02 16:23:21 +05:30
dhanabalan
b430e38291 Refactor routes in api.php for clarity and organization 2025-11-02 16:20:48 +05:30
dhanabalan
4749e459fe Remove unnecessary blank line in cameraCapture function 2025-11-02 16:07:36 +05:30
dhanabalan
ff69f2b58f Add new permissions for invoice validation and web capture 2025-11-02 16:01:12 +05:30
dhanabalan
a8953b9b2c Remove unnecessary blank line in filesystems configuration 2025-11-02 15:58:20 +05:30
dhanabalan
966e756bf2 Fix error message for empty GR Number in getGRSerial response 2025-11-02 15:40:28 +05:30
dhanabalan
8356fc858d Clear invoice number and refresh invoice data on serial number processing! 2025-11-02 15:37:57 +05:30
dhanabalan
5658012473 Refactor pallet number query to filter by prefix and change sorting order 2025-11-02 15:20:54 +05:30
dhanabalan
8834381ddd Added static row number initialization in SerialValidationExporter 2025-11-02 15:15:05 +05:30
dhanabalan
43f02e0d13 added validation for to show unique plant codes in error response in invoice out validation 2025-10-31 17:58:10 +05:30
dhanabalan
e7d549c4c8 Added invoice data widget chart 2025-10-31 17:45:51 +05:30
dhanabalan
3cf34dedb3 Added invoice data dashboard page 2025-10-31 17:45:05 +05:30
dhanabalan
3ea3e6519d Added invoice out validation policy file 2025-10-31 17:43:07 +05:30
dhanabalan
e661fb2c6d Added invoice out validation exporter 2025-10-31 17:42:15 +05:30
dhanabalan
05202c371d Added resource file of invoice out validation 2025-10-31 17:41:42 +05:30
dhanabalan
4ebe709e0f Added model file for invoice out validation 2025-10-31 17:40:40 +05:30
dhanabalan
9d7fb3596f added migration file of invoice out validation 2025-10-31 17:40:08 +05:30
dhanabalan
b95265d6a9 Added invoice data validation policy 2025-10-31 17:38:15 +05:30
dhanabalan
225cca9c4e Added invoice data validation exporter 2025-10-31 17:37:40 +05:30
dhanabalan
6b8c4de985 Added resource file of invoice data validation 2025-10-31 17:37:05 +05:30
dhanabalan
11b03a26b1 Added model file of invoice data validation 2025-10-31 17:35:27 +05:30
dhanabalan
1b68572a82 Added migration file of invoice data validations 2025-10-31 17:34:55 +05:30
dhanabalan
0845b90985 changed logic in ocr 2025-10-30 14:54:11 +05:30
dhanabalan
58951dcdc4 chnaged logic in ocr 2025-10-30 14:51:56 +05:30
dhanabalan
477bcb3f9d change dlogic in ocr for verify 2025-10-30 14:49:11 +05:30
dhanabalan
6ae7690146 added render hook in pds 2025-10-30 13:57:21 +05:30
dhanabalan
d56ee5ed61 Added search bar in pds 2025-10-30 13:55:31 +05:30
dhanabalan
e7b4f1c716 Fix: Ensure group work center is retrieved when plant is found 2025-10-29 16:36:59 +05:30
dhanabalan
d166b7461c changed logic in ocr 2025-10-29 11:57:56 +05:30
dhanabalan
dd07989e7a changed logic in ocr 2025-10-29 11:56:18 +05:30
dhanabalan
48790e417f checking dd in ocr 2025-10-29 11:55:15 +05:30
dhanabalan
de891afb79 changed logic in ocr 2025-10-29 11:53:37 +05:30
dhanabalan
7c802419da modified logic in ocr 2025-10-29 11:52:44 +05:30
dhanabalan
5780850c27 modified logic in ocr 2025-10-29 11:48:23 +05:30
dhanabalan
bb3fa0e703 for checking i kept dd in ocr 2025-10-29 11:46:17 +05:30
dhanabalan
253e856410 modified logic in ocr 2025-10-29 11:45:27 +05:30
dhanabalan
650a165155 added upload pdf button in ocr 2025-10-29 11:39:14 +05:30
dhanabalan
d5b1903d32 changed logic in ocr 2025-10-29 09:19:10 +05:30
dhanabalan
b44c193aa2 chnaged logic in ocr 2025-10-29 09:18:01 +05:30
dhanabalan
c44a6d71dd changed logic for single pdf in ocr 2025-10-29 09:17:18 +05:30
dhanabalan
ec8cab20bd changed position fro single pdf serial number 2025-10-29 09:16:30 +05:30
dhanabalan
ed0d63a5b4 changed logic in ocr 2025-10-29 09:10:48 +05:30
dhanabalan
1a1361ce05 changed logic in ocr 2025-10-29 09:09:58 +05:30
dhanabalan
4c634eba85 changed ocr logic for single pdf 2025-10-29 09:09:09 +05:30
dhanabalan
6e33448f39 changed logic in ocr 2025-10-29 09:07:56 +05:30
dhanabalan
0418ba2756 qr code position moved in single pdf 2025-10-29 09:06:27 +05:30
dhanabalan
461290486e added single pdf logic in ocr 2025-10-29 08:58:24 +05:30
dhanabalan
27e87e585f modified logic for signle pdf in ocr 2025-10-29 08:30:15 +05:30
dhanabalan
a0aaf262bf modified logic in ocr 2025-10-28 14:21:26 +05:30
dhanabalan
e99ddb7003 changed logic in ocr 2025-10-28 14:08:59 +05:30
dhanabalan
dc7fa88ffc modified logic in ocr 2025-10-28 14:07:13 +05:30
dhanabalan
52c2a72908 changed to svg for qr code 2025-10-28 14:06:14 +05:30
dhanabalan
82ba5b43c4 changed logic in ocr for capture 2025-10-28 12:11:20 +05:30
dhanabalan
18909905aa modified ocr logic for passing data 2025-10-28 12:09:30 +05:30
dhanabalan
835735b51f removed dd in ocr resource page 2025-10-28 12:07:53 +05:30
dhanabalan
f069c3e84b modified logic in ocr for capture 2025-10-28 12:05:32 +05:30
dhanabalan
0680aff803 changed logic of serial_numbers in routes 2025-10-28 12:00:02 +05:30
dhanabalan
d4e56bb7f4 changed logic in ocr 2025-10-27 18:42:30 +05:30
dhanabalan
b0d45c697d changed logic in ocr 2025-10-27 18:41:31 +05:30
dhanabalan
06bce66b34 modified logic in ocr 2025-10-27 18:40:42 +05:30
dhanabalan
b058bb3c8a Added logic in ocr create page 2025-10-27 18:26:40 +05:30
dhanabalan
a126050963 call start detection method in ocr 2025-10-27 16:28:08 +05:30
dhanabalan
a9421963a7 added retake photo functionality and improved capture logic in camera capture component 2025-10-27 16:24:05 +05:30
dhanabalan
39eedf1fe9 added logic in ocr 2025-10-27 11:57:22 +05:30
dhanabalan
e332637d48 added logic in ocr 2025-10-27 11:52:54 +05:30
dhanabalan
967519a5ec modified logic in ocr 2025-10-27 11:42:55 +05:30
dhanabalan
2dc70a6a8c changed logic in ocr 2025-10-27 11:15:07 +05:30
dhanabalan
cefac4e8f3 Added logic of init camera in ocr 2025-10-27 11:10:15 +05:30
dhanabalan
bd34dbfc4d added comma in ocr 2025-10-27 11:08:28 +05:30
dhanabalan
cf01272419 Added logic in ocr for capture 2025-10-27 11:07:52 +05:30
dhanabalan
d22b060ec8 Added logic in camera in ocr 2025-10-27 11:05:47 +05:30
dhanabalan
403fc503f9 changed logic in ocr 2025-10-27 11:02:26 +05:30
dhanabalan
f4b99afbeb added logic in ocr 2025-10-27 10:58:35 +05:30
dhanabalan
f6e00a3b9a added logic in ocr 2025-10-27 10:55:20 +05:30
dhanabalan
b4d4902991 Added logic in ocr 2025-10-27 10:39:44 +05:30
dhanabalan
410161d024 Added capture logic in ocr 2025-10-27 10:29:20 +05:30
dhanabalan
a24218bc3f modified logic in ocr 2025-10-27 09:57:28 +05:30
dhanabalan
0cfe16c203 Added capture photo in ocr 2025-10-27 09:53:49 +05:30
dhanabalan
7c846115d7 issue solved in ocr for stop detection 2025-10-27 09:40:09 +05:30
dhanabalan
240ed50782 removed stopdetection in ocr 2025-10-27 09:38:26 +05:30
dhanabalan
f208252657 Added stop detection method in ocr 2025-10-27 09:35:14 +05:30
dhanabalan
14a39b30f8 added logic in ocr 2025-10-25 18:09:15 +05:30
dhanabalan
9c85ea9631 added logic in ocr 2025-10-25 18:01:47 +05:30
dhanabalan
917ce3535f added crt logic in ocr 2025-10-25 17:58:18 +05:30
dhanabalan
8bceaf1e3a added logic in resource page 2025-10-25 17:40:15 +05:30
dhanabalan
eb6c796efb changed logic in ocr 2025-10-25 17:39:51 +05:30
dhanabalan
4cda17bdf8 changed logic in ocr resource 2025-10-25 17:35:26 +05:30
dhanabalan
ba0af41006 changed logic in ocr 2025-10-25 17:34:59 +05:30
dhanabalan
9f4d7e2151 added alert in ocr 2025-10-25 17:26:05 +05:30
dhanabalan
1fb8c43b28 added logic for passing serial number 2025-10-25 17:23:08 +05:30
dhanabalan
15965fcd05 changed logic in ocr 2025-10-25 16:54:14 +05:30
dhanabalan
28d07533f0 changed logic in ocr 2025-10-25 16:49:38 +05:30
dhanabalan
f8fda97181 changed logic in ocr 2025-10-25 16:40:22 +05:30
dhanabalan
72c94f170f remove alphine version 2025-10-25 09:53:39 +05:30
dhanabalan
947b4d1108 changed logic in ocr 2025-10-25 09:53:04 +05:30
dhanabalan
10f83b27c5 changed logic in oicr 2025-10-25 09:49:14 +05:30
dhanabalan
929ecece7e modified logic in ocr 2025-10-25 09:48:03 +05:30
dhanabalan
67b40a5350 chnage dlogic in ocr 2025-10-25 09:45:30 +05:30
dhanabalan
0d9df371ee changed whole logic in ocr 2025-10-25 09:23:26 +05:30
dhanabalan
0438be6c5f Added logic in ocr 2025-10-25 09:16:31 +05:30
dhanabalan
0a68f3c5e0 define tesseract in ocr 2025-10-25 09:15:14 +05:30
dhanabalan
c5e84a18ba modified logic in ocr 2025-10-25 09:13:42 +05:30
dhanabalan
ed98fd5cfa Added camera logic in ocr 2025-10-25 09:11:02 +05:30
dhanabalan
2bf73c3ac2 changed logic for detect text 2025-10-25 09:02:56 +05:30
dhanabalan
ffc742914f added ocr in canvas 2025-10-25 08:57:47 +05:30
dhanabalan
0aefc5d4ba added ocr logic in canvas 2025-10-25 08:55:13 +05:30
dhanabalan
48ecd57782 Added logic in ocr for lens 2025-10-25 08:49:19 +05:30
dhanabalan
f1cfa8499b chnage dlogic in ocr for camera crop 2025-10-25 08:42:00 +05:30
dhanabalan
e970f253c0 chnaged logic in ocr 2025-10-25 08:38:02 +05:30
dhanabalan
4dee5620d6 added logic in ocr 2025-10-25 08:36:38 +05:30
dhanabalan
1922b9d7fc modified logic in ocr 2025-10-25 08:33:02 +05:30
dhanabalan
e313b0be4b added detect text in ocr 2025-10-25 08:31:28 +05:30
dhanabalan
b8339b8b0c added serialinput in ocr 2025-10-24 18:39:53 +05:30
dhanabalan
998d1ed629 changed logic in resource page 2025-10-24 18:39:23 +05:30
dhanabalan
e1c8a973ef Added serial fill form in ocr 2025-10-24 18:29:27 +05:30
dhanabalan
dbe9383a10 changed logic in ocr 2025-10-24 18:29:05 +05:30
dhanabalan
1bac8ee1db added livewire component in reosurce 2025-10-24 18:26:30 +05:30
dhanabalan
0c00c47aa3 passed four serial numbers from blade to reosurce page 2025-10-24 18:25:59 +05:30
dhanabalan
6fe4289567 added logic in ocr for cropping 2025-10-24 17:45:35 +05:30
dhanabalan
e1bc838737 modified logic in ocr capture photo 2025-10-24 17:42:12 +05:30
dhanabalan
979c65e781 modified logic in ocr 2025-10-24 17:40:50 +05:30
dhanabalan
a3732936ac modified capture photo method logic in ocr 2025-10-24 17:37:51 +05:30
dhanabalan
8d49937a68 added image width in ocr 2025-10-24 17:35:37 +05:30
dhanabalan
c3259710f6 modified logic in ocr 2025-10-24 17:12:56 +05:30
dhanabalan
bb7e5cc12d changed logic in ocr for cropping 2025-10-24 17:09:44 +05:30
dhanabalan
d2b68c8c63 Added file uploaded button in ocr screen 2025-10-24 17:06:17 +05:30
dhanabalan
2062af55a1 added cropper logic in ocr 2025-10-24 16:52:50 +05:30
dhanabalan
095929805f Added png instead of jpeg in ocr 2025-10-24 11:32:46 +05:30
dhanabalan
50cfc60f04 removed unwanted logic in ocr 2025-10-24 11:19:57 +05:30
dhanabalan
8164aaed04 increased quality for jpeg image in ocr 2025-10-24 11:17:17 +05:30
dhanabalan
5af67e2ae9 modified logic in ocr upload button 2025-10-23 16:05:12 +05:30
dhanabalan
a983d116cf Added one more repsonse for empty invalid image 2025-10-23 15:57:28 +05:30
dhanabalan
9aff6dfb67 modified logic in ocr for serials 2025-10-23 15:51:35 +05:30
dhanabalan
4c32400f37 Added logic fo serils 2025-10-23 15:41:08 +05:30
dhanabalan
21c73c4744 modified logic in ocr 2025-10-23 15:37:11 +05:30
dhanabalan
b71fe09498 Added api logic in ocr 2025-10-23 15:32:14 +05:30
dhanabalan
82551f5abe Changed return json response in ocr 2025-10-23 15:29:02 +05:30
dhanabalan
e18a42ea6c Added logic for verfication serials 2025-10-23 15:26:49 +05:30
dhanabalan
48a6391bb1 changed logic in api in ocr 2025-10-23 15:20:26 +05:30
dhanabalan
a25e3ccdbf Added logic in ocr for config 2025-10-23 15:17:00 +05:30
dhanabalan
b7e9062c9e Added psm in ocr 2025-10-23 15:06:57 +05:30
dhanabalan
a7dafd0e60 Added snapshot capture in ocr 2025-10-23 15:05:09 +05:30
dhanabalan
583544fbc7 removed logic in ocr for showing snapshot 2025-10-23 15:03:58 +05:30
dhanabalan
23e0fd08c9 Added show capture photo in ocr 2025-10-23 15:02:32 +05:30
dhanabalan
12863eaafb changed logic in ocr 2025-10-23 14:38:15 +05:30
dhanabalan
d8416b983c changed env path in ocr api 2025-10-23 14:22:17 +05:30
dhanabalan
1edd808c28 Added env path for ocr 2025-10-23 14:20:39 +05:30
dhanabalan
69ec903794 Added debug route for ocr 2025-10-23 14:06:40 +05:30
dhanabalan
a0d77f8df7 Added debug env for ocr 2025-10-23 14:03:46 +05:30
dhanabalan
ef81309cf8 changed logic in verify ocr 2025-10-23 13:59:55 +05:30
dhanabalan
4f3db02780 modified logic in ocr 2025-10-18 12:02:51 +05:30
dhanabalan
d05876cccd changed logic in ocr 2025-10-18 11:59:48 +05:30
dhanabalan
5bda5a5a05 removed old logic 2025-10-18 11:26:36 +05:30
dhanabalan
2b048814bd alter logic in ocr for route 2025-10-18 11:13:39 +05:30
dhanabalan
269e800c87 Added logic in ocr 2025-10-18 11:11:05 +05:30
dhanabalan
d364e1952d Added env path in ocr 2025-10-18 11:07:18 +05:30
dhanabalan
721b9b4fd1 addeed file path of ocr 2025-10-18 10:58:57 +05:30
dhanabalan
7152322da7 changed logic in ocr 2025-10-18 10:55:14 +05:30
dhanabalan
4a80164419 route post logic for verify ocr 2025-10-18 10:50:22 +05:30
dhanabalan
d097318646 changed logic in ocr fro automatical verify 2025-10-18 10:49:59 +05:30
dhanabalan
98d5d48569 Added route logic in web.php for ocr 2025-10-18 10:29:12 +05:30
dhanabalan
aa269dd61e Alter logic in ocr 2025-10-18 10:27:12 +05:30
dhanabalan
d6f34b58ac Added to save jpeg image logic in ocr 2025-10-18 10:20:02 +05:30
dhanabalan
1df45cd9e7 Added logic in ocr fro camera function 2025-10-18 09:58:58 +05:30
dhanabalan
b6dadd464c changed logic in ocr related to init camera 2025-10-18 09:53:52 +05:30
dhanabalan
095aac2270 Changed logic in ocr for capture 2025-10-18 09:51:31 +05:30
dhanabalan
a621df56fd changed init camera logic in ocr 2025-10-18 09:48:58 +05:30
dhanabalan
df45f150f1 chnaged logic in ocr for capturing image in high quality 2025-10-18 09:44:51 +05:30
dhanabalan
41fce18aa2 commented ocr veify in filament 2025-10-17 12:14:07 +05:30
dhanabalan
f32cf7ca7d changed colour of the button in ocr 2025-10-17 12:12:34 +05:30
dhanabalan
1ff84d4fba Added ne wlogic in ocr blade file 2025-10-17 12:02:01 +05:30
dhanabalan
bb521ca555 Added ocr capture logic 2025-10-17 10:42:52 +05:30
dhanabalan
a3f5f92080 Added logic in ocr for capture 2025-10-17 10:40:21 +05:30
dhanabalan
054a83d688 changed logic in ocr in capture 2025-10-17 10:37:14 +05:30
dhanabalan
d486c4cdfb added logic in ocr for capture 2025-10-17 10:34:52 +05:30
dhanabalan
cf7a123a58 added ocr old logic 2025-10-17 10:33:31 +05:30
dhanabalan
86b5284a5e changed logic in ocr 2025-10-17 10:32:14 +05:30
dhanabalan
6a2de53e8e changed logic in ocr 2025-10-17 10:31:01 +05:30
dhanabalan
a7bd814706 changed logic in ocr 2025-10-17 10:28:05 +05:30
dhanabalan
3d0c67a6d8 changed logic in ocr 2025-10-17 10:24:45 +05:30
dhanabalan
c3d47a3787 changed logic in ocr 2025-10-17 10:23:37 +05:30
dhanabalan
fbc6ca82e1 Added camera capture in ocr 2025-10-17 10:21:28 +05:30
dhanabalan
1dec47a05f Added camera capture in ocr 2025-10-17 10:18:45 +05:30
dhanabalan
1fb3930098 declare public property in ocr 2025-10-17 10:08:44 +05:30
dhanabalan
9efc878600 added form of verify 2025-10-17 10:01:46 +05:30
dhanabalan
96a19f8566 changed capture logic of ocr 2025-10-17 10:01:26 +05:30
dhanabalan
83cc18b93c added one form form in ocr 2025-10-17 09:53:23 +05:30
dhanabalan
5237808e8c Added verify button in ocr 2025-10-17 09:41:21 +05:30
dhanabalan
d7b70f47ed Added camera capture logic 2025-10-17 09:36:02 +05:30
dhanabalan
04693f960a Added relevant packages for ocr 2025-10-17 09:35:23 +05:30
dhanabalan
7d5629400e changed logic in camera capture 2025-10-17 09:05:53 +05:30
dhanabalan
e084ed8ae8 Added camera capture for ocr 2025-10-16 18:04:04 +05:30
dhanabalan
a5cd90689d Added file of ocr capture 2025-10-16 18:01:05 +05:30
dhanabalan
171a09ed3b Added ocr policy 2025-10-16 18:00:30 +05:30
dhanabalan
84adab1875 added ocr resource pages 2025-10-16 18:00:02 +05:30
dhanabalan
e8fef2722d Added ocr model file 2025-10-16 17:58:56 +05:30
dhanabalan
d7783a2ef9 Added ocr migration file 2025-10-16 17:58:33 +05:30
dhanabalan
52cd51d7d1 Update serial number validation regex to allow optional trailing pipe character 2025-10-16 14:54:14 +05:30
dhanabalan
d79c7101b4 Remove unused test method and its associated code from ObdController 2025-10-13 15:57:18 +05:30
dhanabalan
4ed84d3053 Added sftp package for to read dat from sftp 2025-10-10 16:01:36 +05:30
dhanabalan
df4bd9874f Added module list file name 2025-10-10 15:25:47 +05:30
dhanabalan
9306a476f9 Add permissions for serial validation invoice import and export 2025-10-08 18:25:22 +05:30
dhanabalan
5e48861589 Refactor plant selection logic to filter by user-specific plant ID in various resources 2025-10-08 18:22:22 +05:30
dhanabalan
98dc59538f Added required mapping for import columns and Updated plant selection logic in various resources on Advanced Filters 2025-10-08 17:46:19 +05:30
dhanabalan
377fd4c615 Added status column in export 2025-10-08 13:42:52 +05:30
dhanabalan
bcd5b40da8 Added required for gr master 2025-10-08 10:24:23 +05:30
dhanabalan
ffec5e1cd3 Added proper messages for get pdf for gr number 2025-10-08 10:11:21 +05:30
dhanabalan
24f1813a14 Added file deletion logic if pdf is not valid 2025-10-08 10:07:01 +05:30
dhanabalan
9d283fdadb Added gr master validation logic for import 2025-10-08 10:04:37 +05:30
dhanabalan
fbab44ab12 Added required for pdf upload attachment 2025-10-08 09:20:37 +05:30
dhanabalan
75829a468c Addeded searchable for gr master 2025-10-07 15:42:08 +05:30
dhanabalan
767082d703 Added completed logic for gr master api 2025-10-04 15:34:46 +05:30
dhanabalan
e18ee0dd3a Added status column in table 2025-10-04 15:14:30 +05:30
dhanabalan
d148828ef1 Added status column to update 2025-10-04 15:12:40 +05:30
dhanabalan
bb9a3d3503 Removed name for item code in grmaster importer 2025-10-04 15:10:35 +05:30
dhanabalan
c53f9c107b Added status column in gr master table 2025-10-04 15:03:44 +05:30
dhanabalan
4645965bf7 Added permission name for export 2025-10-04 09:25:15 +05:30
dhanabalan
6c4db40ba7 Added serial validation exporter 2025-10-03 17:01:43 +05:30
dhanabalan
7171b9e052 Added permissions for import and export for serial validation page 2025-10-03 16:18:41 +05:30
dhanabalan
775a96d806 removed unwanted lines of code in serial validation 2025-10-03 16:14:18 +05:30
dhanabalan
98449fcd2d Added serial validation policy 2025-10-03 16:10:20 +05:30
dhanabalan
638e4fdc38 Added create serial invoice validation page for filament 2025-10-03 16:07:34 +05:30
dhanabalan
c3e0429421 Added livewire page for serial validation 2025-10-03 16:06:41 +05:30
dhanabalan
b9aa549705 Add SerialValidation resource pages for editing, listing, and viewing
- Created EditSerialValidation page for editing serial validation records with view, delete, force delete, and restore actions.
- Created ListSerialValidations page for listing serial validation records with a create action.
- Created ViewSerialValidation page for viewing serial validation records with an edit action.
2025-10-03 16:05:40 +05:30
dhanabalan
181c0a2e4c Add SerialValidation model with fillable attributes and relationships 2025-10-03 16:03:45 +05:30
dhanabalan
90e96f8a66 Create migration for serial_validations table with necessary fields and constraints 2025-10-03 16:03:08 +05:30
dhanabalan
346e1baec0 Enhance pallet validation logic in ReworkLocatorInvoiceValidationResource form to include detailed notifications for invalid pallet and serial numbers, and handle pallet status updates more effectively. 2025-09-30 14:52:15 +05:30
dhanabalan
b31b723a2c Remove unnecessary blank line in processPalletno method 2025-09-30 14:50:57 +05:30
dhanabalan
fad5bec0de Refactor plant selection options in multiple dashboards to filter by authenticated user's plant ID. 2025-09-30 14:50:16 +05:30
dhanabalan
355ce26475 Update label for plant name in StickerMasterExporter to be more descriptive 2025-09-30 14:17:33 +05:30
dhanabalan
effa8bebeb Remove enter key hint from scan serial number input in ReworkLocatorInvoiceValidationResource form 2025-09-30 11:52:30 +05:30
dhanabalan
2ad38c51c1 Add enter key hint for scan serial number input in ReworkLocatorInvoiceValidationResource form to testing purpose 2025-09-30 11:49:13 +05:30
dhanabalan
85ebccd22c Refactor plant selection options by authenticated user's plant ID. 2025-09-29 18:26:35 +05:30
dhanabalan
ece893ae84 Refactor plant selection options in InvoiceFinder to filter by authenticated user's plant ID. 2025-09-29 18:21:13 +05:30
dhanabalan
368d115124 removed unwanted action export from testing panel 2025-09-29 17:48:32 +05:30
dhanabalan
1802c1443c Add plant code retrieval in user controller to enhance user data response 2025-09-29 17:21:44 +05:30
dhanabalan
9f98348600 added item code in an array for getting serial number 2025-09-29 17:17:03 +05:30
dhanabalan
7845b86a79 Addded item code logic in get serial number 2025-09-29 17:06:13 +05:30
dhanabalan
a9803f927f Refactor plant selection options across multiple resources to display plants based on the authenticated user's plant ID, ensuring users only see relevant options. 2025-09-29 16:35:55 +05:30
dhanabalan
a4afe2f3c7 Refactor Plant model to ensure proper formatting and maintain consistency in method definitions 2025-09-29 12:33:13 +05:30
dhanabalan
168e9266fe Fix plant code validation logic in UserImporter 2025-09-29 12:28:18 +05:30
dhanabalan
af3ce0ea40 Add plant code column to UserExporter and implement plant validation in UserImporter 2025-09-29 12:18:09 +05:30
dhanabalan
5f4945d997 Add plant relationship to UserResource form and table 2025-09-29 11:41:30 +05:30
dhanabalan
f62f88aa55 Add plant relationship to User model 2025-09-29 11:37:11 +05:30
dhanabalan
5f666ff313 Add migration to add foreign key constraint for plant_id in users table 2025-09-29 11:36:26 +05:30
dhanabalan
53cb04b14e Update error message for user not found in updateGR method for clarity 2025-09-27 16:53:08 +05:30
dhanabalan
64003ca776 Add validation for item codes in updateGR method to ensure they are at least 6 digits and numeric 2025-09-27 16:51:18 +05:30
dhanabalan
0d9fd498d6 Refactor user retrieval in updateGR method to simplify query by removing unnecessary plant_id condition 2025-09-27 16:49:17 +05:30
dhanabalan
071627ccd4 Add user validation in updateGR method to ensure scanned_by exists for the given plant 2025-09-27 16:30:59 +05:30
dhanabalan
f58c36383b Add validation for existing GR numbers and check for missing serials in updateGR method 2025-09-27 16:26:34 +05:30
dhanabalan
aa4e42d790 Add 'Created By' column to GrMasterResource table for better tracking 2025-09-27 16:09:03 +05:30
dhanabalan
52912e7700 Add route for updating GR serial numbers in api.php 2025-09-27 16:08:19 +05:30
dhanabalan
0c84421719 Add updateGR method to PdfController for updating serial numbers with validation 2025-09-27 16:08:01 +05:30
dhanabalan
61e9995892 Remove status_code from getGRSerial response in PdfController 2025-09-27 15:07:27 +05:30
dhanabalan
cf6c9b81b1 Add route for retrieving GR serial numbers in api.php 2025-09-27 15:04:22 +05:30
dhanabalan
034db8f879 Add getGRSerial method to PdfController for retrieving serial numbers by GR number and plant code with authorization 2025-09-27 15:04:01 +05:30
dhanabalan
71f29243e2 Add route for retrieving GR PDFs in api.php 2025-09-27 14:35:40 +05:30
dhanabalan
388d91f8a4 Add getGRPdf method to PdfController for retrieving GR PDFs with authorization 2025-09-27 14:35:19 +05:30
dhanabalan
be892cb662 Add GrMasterPolicy class to manage authorization for GrMaster actions 2025-09-27 14:01:48 +05:30
dhanabalan
584d4faa07 Add GrMaster importer and exporter classes with column definitions and notification messages 2025-09-27 14:01:25 +05:30
dhanabalan
3f1b46873e Add GrMaster resource with CRUD pages and functionality for managing GR records 2025-09-27 14:00:31 +05:30
dhanabalan
9d69ce89ae Add GrMaster model with fillable attributes and relationships to Plant and Item 2025-09-27 13:59:19 +05:30
dhanabalan
e14814e529 Add migration for creating gr_masters table with necessary fields and foreign keys 2025-09-27 13:58:41 +05:30
dhanabalan
98feb7bfc5 Remove user3 seeding from UserSeeder to streamline user creation process 2025-09-27 13:42:21 +05:30
dhanabalan
998fbf814c Refactor validation logic in CreateInvoiceValidation to include additional checks for package types (use pack_slip if tube_sticker does not exist) and streamline code structure 2025-09-26 18:59:33 +05:30
dhanabalan
d2c7f85917 Fix validation for 'No of Operation' in resolveRecord method to include actual value in error message 2025-09-26 16:30:53 +05:30
dhanabalan
5b8bb29aeb Add validation for serial numbers in readFiles method and return error response for invalid entries 2025-09-26 12:09:41 +05:30
dhanabalan
b2cf4dc18e Refactor readFiles method to streamline CSV row processing and ensure unique remaining row is returned 2025-09-26 11:57:28 +05:30
dhanabalan
9774cda2ad Refactor readFiles method to enhance CSV row validation and ensure unique remaining rows are collected 2025-09-26 11:49:31 +05:30
dhanabalan
bbe05d62b1 Enhance readFiles method to validate CSV row structure and return error response for insufficient columns 2025-09-26 11:40:00 +05:30
dhanabalan
f353a699a2 Refactor readFiles method to handle file content processing and return structured response with serial numbers and remaining rows 2025-09-26 11:38:14 +05:30
dhanabalan
956c282005 Add debug response for file reading in readFiles method and improve error handling for file accessibility 2025-09-26 11:22:52 +05:30
dhanabalan
c9b5a59bf2 Refactor readFiles method to dynamically set file path and improve file handling 2025-09-26 11:16:06 +05:30
dhanabalan
086910122e Implement file reading and database insertion in readFiles method 2025-09-26 11:13:38 +05:30
dhanabalan
92a3b5a448 Refactor error responses in readFiles method to standardize status descriptions 2025-09-26 10:48:52 +05:30
dhanabalan
64237c3da0 Improve error handling in readFiles method for directory access and readability 2025-09-26 10:47:35 +05:30
dhanabalan
3d21975096 Validate plant code in readFiles method and update response structure 2025-09-26 10:43:52 +05:30
dhanabalan
0710c3a7a1 Add authorization check to readFiles method in SapFileController 2025-09-26 10:35:22 +05:30
dhanabalan
18eb234df4 Fix readFiles method to correctly concatenate file path for reading file contents 2025-09-26 10:30:58 +05:30
dhanabalan
8a3c0639ad Refactor readFiles method to improve .txt file filtering logic 2025-09-26 10:26:04 +05:30
dhanabalan
f50fbf5771 Fix readFiles method to add missing slash in file path for correct .txt file filtering 2025-09-26 10:22:23 +05:30
dhanabalan
3a115241a9 Fix readFiles method to add missing slash in file path for correct .txt file filtering 2025-09-26 10:21:07 +05:30
dhanabalan
062f35cb4d Fix readFiles method to correctly filter .txt files by adding missing slash in path 2025-09-26 10:15:34 +05:30
dhanabalan
062f143dbb Refactor readFiles method in SapFileController to streamline file filtering logic 2025-09-26 10:13:41 +05:30
dhanabalan
7406f4c97e Update readFiles method in SapFileController to change directory path and improve debug information 2025-09-26 10:06:29 +05:30
dhanabalan
831c88f0fd Add migration to enforce unique constraint on plant_id and serial_number in quality_validations table 2025-09-25 11:00:56 +05:30
dhanabalan
733cc45e60 Update readFiles method in SapFileController to change the directory path for file access 2025-09-23 12:17:23 +05:30
dhanabalan
0f3b516614 Update readFiles method in SapFileController to improve user identification in error responses 2025-09-23 10:55:56 +05:30
dhanabalan
8187aca5d4 Update readFiles method in SapFileController to enhance error reporting and adjust file path 2025-09-23 10:46:24 +05:30
dhanabalan
1d998d6478 Enhance readFiles method in SapFileController with improved error handling and debugging information 2025-09-23 09:48:24 +05:30
dhanabalan
86ad06def7 Refactor readFiles method in SapFileController for improved error handling and code clarity 2025-09-23 09:42:57 +05:30
dhanabalan
6a70b45f4f Refactor readFiles method in SapFileController for improved file handling and readability 2025-09-23 09:38:47 +05:30
dhanabalan
7e1852cfed Add SapFileController and route for reading SAP files 2025-09-23 09:34:17 +05:30
dhanabalan
7ca806449c Update export and import columns in TestingPanelReadingExporter and TestingPanelReadingImporter for improved data mapping 2025-09-21 16:00:08 +05:30
dhanabalan
90899c87f5 Remove commented-out route for characteristics master data in api.php 2025-09-21 15:50:18 +05:30
dhanabalan
fad3cf4ed6 Add relationships for equipment masters in Machine and Plant models 2025-09-21 15:46:01 +05:30
dhanabalan
2e7c37c6f1 Refactor export actions in TestingPanelReadingResource for improved readability and maintainability 2025-09-21 15:40:47 +05:30
dhanabalan
4c1950bf29 Fix indentation for dispatching warning sound in processInvoice method 2025-09-21 15:38:19 +05:30
dhanabalan
d13f502db8 Update ProcessOrderResource form fields and notification message 2025-09-21 15:35:25 +05:30
dhanabalan
4da6e97e6e Add EquipmentMasterController with authorization and equipment retrieval logic with relevant API 2025-09-21 15:32:18 +05:30
dhanabalan
f670793ff5 Add importer and exporter file for Equipment Masters 2025-09-21 15:24:30 +05:30
dhanabalan
2abc5199eb Add policy class for EquipmentMaster with permission checks 2025-09-21 15:23:02 +05:30
dhanabalan
d4192d3002 Add resource file for Equipment Masters 2025-09-21 15:21:37 +05:30
dhanabalan
eaba6b8396 Add model file for Equipment Masters 2025-09-21 15:18:23 +05:30
dhanabalan
237fb1a7b3 Add migration file for equipment masters 2025-09-21 15:14:44 +05:30
dhanabalan
b178130e8d Add searchable functionality to WorkGroupMaster table columns 2025-09-18 17:11:57 +05:30
dhanabalan
4c1a0a0282 Add warning notification sound: warning.mp3 2025-09-16 15:10:08 +05:30
dhanabalan
af719c2d33 Add audio notification sounds: click.mp3, ding.mp3, and scanner-beep.mp3 2025-09-16 15:05:12 +05:30
dhanabalan
bbd192148c Add NotificationSound Livewire component to create-invoice-validation page for audio notifications 2025-09-16 15:04:46 +05:30
dhanabalan
93b1138752 Add NotificationSound component and associated Blade view for audio notifications 2025-09-16 15:04:20 +05:30
dhanabalan
40ef91a60b Add notification sound dispatches in processInvoice and processSerialNumber methods for better user feedback 2025-09-16 15:01:52 +05:30
dhanabalan
012ce6d865 Add winded_serial_number to fillable attributes in TestingPanelReading model 2025-09-16 12:40:16 +05:30
dhanabalan
e8637874f4 Add winded_serial_number field to TestingPanelReadingResource form and table for enhanced data tracking 2025-09-16 12:39:27 +05:30
dhanabalan
5a7050a5b4 Add winded_serial_number to store method in TestingPanelController for enhanced data tracking 2025-09-16 12:04:50 +05:30
dhanabalan
24b9b5194a Add winded_serial_number column to testing_panel_readings table 2025-09-16 11:58:15 +05:30
dhanabalan
9a6e364f52 Refactored store method in TestingPanelController to improve validation for line and machine names, replacing Line model with WorkGroupMaster for accurate data handling. 2025-09-15 17:40:52 +05:30
dhanabalan
d4582292a4 Updated validation checks in WorkGroupMasterImporter to ensure name and operation number are not empty 2025-09-15 15:55:29 +05:30
dhanabalan
b222c78d4b Removed redundant unique rule for 'name' in WorkGroupMasterResource form validation for improved clarity 2025-09-15 15:53:08 +05:30
dhanabalan
d827c9368f Updated MachineController to replace 'line' with 'workGroupMaster' for accurate data retrieval to get all group and individual work center 2025-09-15 14:42:26 +05:30
dhanabalan
b48392a40c Updated navigation sort order for GuardNameResource and TestingPanelReadingResource for consistent display in the Master Entries and Testing Panel groups 2025-09-15 14:26:33 +05:30
dhanabalan
dc0b4ea75e Updated navigation sort order for CheckPointNameResource and CheckPointTimeResource for consistent display in the Master Entries group 2025-09-15 13:24:55 +05:30
dhanabalan
49fea7fcdb Updated column headers in ProductionQuantityImporter for consistency and clarity 2025-09-15 13:23:05 +05:30
dhanabalan
3848898f37 Refactored PalletValidationImporter by commenting out unused methods for clarity and maintainability 2025-09-15 13:20:55 +05:30
dhanabalan
4bb3b60391 Added work group center foreign key column to Machine export and import functionality with validation and error handling 2025-09-15 13:18:23 +05:30
dhanabalan
0381530463 Enhanced Line export and import functionality by adding multiple work group foreign key columns and no_of_operation field with validation. 2025-09-15 13:15:06 +05:30
dhanabalan
2244d82af0 Added no_of_operation field and work group center foreign key with validation in Line resource file 2025-09-15 12:59:10 +05:30
dhanabalan
594cc252a9 Added validation error handling in CreateLine page before record creation 2025-09-15 12:54:11 +05:30
dhanabalan
21bbbb24c2 Added no_of_operation and foreign key constraints for work group columns in line model for enhanced data association 2025-09-15 12:37:36 +05:30
dhanabalan
3b0501ef9e Added no_of_operation and foreign key constraints for work group columns in lines table 2025-09-15 12:29:58 +05:30
dhanabalan
23fa24ca46 Added workGroupMaster functionality in resource and Updated navigation sort 2025-09-15 12:27:10 +05:30
dhanabalan
55c0ebfa6d Added workGroupMaster foreignKey and belongsTo relationship to Machine model 2025-09-15 12:20:59 +05:30
dhanabalan
db3a69d47f Add workGroupMasters hasMany relationship to Plant model and comment out rejectReasons method 2025-09-15 12:18:41 +05:30
dhanabalan
5ba9db0278 Added migration to create work_group_master_id foreign key and plant with work_center unique constraint for machines table 2025-09-15 12:14:25 +05:30
dhanabalan
6a195d00c5 Remove group_work_center column from lines table 2025-09-15 12:07:20 +05:30
dhanabalan
386b9c4a09 Added importer and exporter file for work group masters 2025-09-15 11:57:27 +05:30
dhanabalan
853a1542bb Add WorkGroupMasterPolicy to manage permissions for WorkGroupMaster models 2025-09-15 11:47:17 +05:30
dhanabalan
d3e9237bff Add ProcessOrderPolicy to manage permissions for ProcessOrder models 2025-09-15 11:46:46 +05:30
dhanabalan
c76ae58118 Added resource file for work group masters 2025-09-15 11:41:13 +05:30
dhanabalan
d2fc4e0b40 Added model file for work group masters 2025-09-15 11:05:50 +05:30
dhanabalan
bd1d7e61b4 Add migration file for work group masters 2025-09-15 10:50:58 +05:30
dhanabalan
bac7c610f8 Refactor QualityValidationImporter to improve record uniqueness on update logic 2025-09-13 11:16:22 +05:30
dhanabalan
36006e6e08 Uncomment testing routes for user data retrieval and machine data access 2025-09-10 16:59:23 +05:30
dhanabalan
319aea377a Update file path in getPdf method to use ProcessOrder directory for PDF retrieval 2025-09-10 15:59:42 +05:30
dhanabalan
444b4a4804 Add smalot/pdfparser dependency for PDF parsing functionality 2025-09-10 15:27:40 +05:30
dhanabalan
21e048549d Add PdfController with getPdf method for PDF retrieval and authorization handling 2025-09-10 15:24:54 +05:30
dhanabalan
ba453ef505 Add PDF retrieval route and clean up commented testing routes in api.php 2025-09-10 15:22:49 +05:30
dhanabalan
e5a3d212d0 Add ProcessOrder resource with CRUD pages and form handling 2025-09-10 15:18:17 +05:30
dhanabalan
367d103c75 Add ProcessOrder model with fillable attributes and relationships 2025-09-10 15:16:51 +05:30
dhanabalan
365d5b19ab Add migration for process_orders table with necessary fields and foreign keys 2025-09-10 15:14:39 +05:30
dhanabalan
8c488e1ced Enhance MotorTestingMasterResource with advanced filtering options and improved form validation 2025-09-10 10:30:09 +05:30
dhanabalan
1bd14d5f73 Update MotorTestingMasterExporter and MotorTestingMasterImporter to use plant code and improve validation logic 2025-09-10 10:24:07 +05:30
dhanabalan
aaa162a3f2 Remove commented-out 'asc' parameter from created_at orderBy in QualityValidationResource table query 2025-09-10 08:55:36 +05:30
dhanabalan
8813567f0b Add missing created_at and updated_at fields to fillable attributes in ProductionQuantity model 2025-09-09 19:03:13 +05:30
dhanabalan
ffa2b1f783 Remove redundant 'asc' parameter from created_at orderBy in QualityValidationResource table query 2025-09-09 18:01:19 +05:30
dhanabalan
e29c16c79a Add sorting by created_at in QualityValidationResource table query 2025-09-09 17:55:53 +05:30
dhanabalan
4d516e955c added created_at and updated_at column in quality validation model 2025-09-09 10:56:22 +05:30
dhanabalan
b0d73dbbc6 Add searchable functionality to line name column in QualityValidationResource table 2025-09-09 10:39:20 +05:30
dhanabalan
37c91afe25 Rename subassembly_code to mot_subassembly_code in get_motor_master method for clarity 2025-09-09 10:23:58 +05:30
dhanabalan
77064399cd Update example header for line column in ConfigurationImporter 2025-09-09 08:41:22 +05:30
dhanabalan
3398a60d1b Update label for laser part validation input in StickerMasterResource 2025-09-06 16:25:52 +05:30
dhanabalan
65aafbeb65 Add required validation to load rate input in StickerMasterResource resource 2025-09-06 16:16:35 +05:30
dhanabalan
ad72d38193 Update plant column references in ConfigurationExporter and ConfigurationImporter to use 'code' instead of 'name' 2025-09-06 11:30:07 +05:30
dhanabalan
cac91722c3 Refactor form schema in StickerMasterResource for improved clarity and organization 2025-09-05 17:27:24 +05:30
dhanabalan
bb2b81d0f2 updated header name for leak current limit in motor testing master 2025-09-05 14:41:27 +05:30
dhanabalan
2150f6098f Added required isi model column for motor testing importer and exporter 2025-09-05 14:32:47 +05:30
dhanabalan
a0a1e87440 Added subassembly code to motor master output in TestingPanelController 2025-09-05 14:03:54 +05:30
dhanabalan
8da3c746b9 Added sub assembly column in import and export 2025-09-05 09:35:06 +05:30
dhanabalan
d05623f920 Added subassembly code in resource page of motor testing master 2025-09-05 09:33:16 +05:30
dhanabalan
e3d29cba81 Added subassembly code in model file in motor testing master 2025-09-05 09:31:06 +05:30
dhanabalan
5cbae18532 Added subassembly code column motor testing master 2025-09-05 09:28:50 +05:30
dhanabalan
7e688683d7 corrected bundle logic for invoice quantity 2025-08-27 08:37:21 +05:30
dhanabalan
ab5a8c0874 Removed unwanted column in bundle data in invoice mail 2025-08-26 19:06:51 +05:30
dhanabalan
19e1f12f5d Refactor invoice report generation to include quantity metrics and enhance email content structure 2025-08-26 18:08:06 +05:30
dhanabalan
e57962f023 Merge branch 'master' of ssh://172.31.31.31:2222/poc/pds 2025-08-26 18:01:43 +05:30
dhanabalan
c5a730b71d Added roles column in view reports and Refactor User table columns for improved sorting and searching functionality 2025-08-26 17:57:16 +05:30
root
967a429595 Merge branch 'master' of https://git.iotsignin.com/poc/pds 2025-08-26 16:35:02 +05:30
root
7f0d138383 WIP: local changes before pull 2025-08-26 16:21:53 +05:30
dhanabalan
d5c0303be4 Merge branch 'master' of ssh://172.31.31.31:2222/poc/pds 2025-08-26 16:10:31 +05:30
dhanabalan
c2f9b77e1f Create motor_testing_masters table with comprehensive fields for motor testing data 2025-08-26 16:09:10 +05:30
3053098cfb Updated file name to work migration functionality in order 2025-08-26 10:32:46 +00:00
a5ded4a20a Added plant column with BIGINT type and its default value as 0 2025-08-26 10:25:05 +00:00
dhanabalan
d419973ab5 Add getRedirectUrl method to resource creation classes for consistent redirection 2025-08-26 15:44:51 +05:30
dhanabalan
86e458037f Removed unnecessary lines in alert_mail_rules table 2025-08-25 20:09:24 +05:30
dhanabalan
e6ba543589 Added roles on UserExporter and UserImporter for consistency and enhanced functionality 2025-08-25 17:00:00 +05:30
dhanabalan
1cee8dc71d Enhance item description field to auto-populate based on selected item ID 2025-08-25 12:17:49 +05:30
dhanabalan
3a009543ea Update MachineResource refine line selection logic 2025-08-25 11:43:09 +05:30
dhanabalan
d4045b7b0f Update validation for line stop code to require a minimum length of 3 characters 2025-08-22 14:47:01 +05:30
dhanabalan
a831f6e787 Testing 2025-08-21 18:07:08 +05:30
dhanabalan
b399141c7e Add UserExporter and UserImporter classes with export/import functionality 2025-08-21 17:07:34 +05:30
dhanabalan
8fd2212ec4 Refactor PermissionSeeder to update permissions for user, plant, and block views 2025-08-21 16:32:32 +05:30
dhanabalan
e6f78c60d5 Fix email address for admin in UserSeeder 2025-08-21 16:07:43 +05:30
dhanabalan
a3a421af88 Added logic in quality validation screen to scan capacitor qr code in part validation 5 2025-08-21 14:06:23 +05:30
dhanabalan
d4eeee7d05 Refactor root redirect logic to simplify default behavior 2025-08-20 19:53:01 +05:30
dhanabalan
bd17af8945 Update root redirect logic to handle specific host 2025-08-20 19:49:28 +05:30
dhanabalan
95f1e09304 Added policy file for eb reading 2025-08-12 17:27:36 +05:30
dhanabalan
fc42e7db6c Add TempLiveReadingResource files from qds branch 2025-08-12 17:21:22 +05:30
dhanabalan
0d3e58e7af Add EbReadingImporter and EbReadingExporter from qds branch 2025-08-12 17:18:02 +05:30
dhanabalan
658d7cb42c Add EbReadingResource related files from qds branch 2025-08-12 17:14:40 +05:30
dhanabalan
679d532b17 Add EbReading.php model file from qds branch 2025-08-12 17:07:54 +05:30
dhanabalan
50ddd51f04 Add eb_readings migration from qds branch 2025-08-12 16:52:39 +05:30
dhanabalan
dc9f929fa2 Update sequences column logic in guard patrol entry table for accurate display 2025-08-07 10:50:00 +05:30
dhanabalan
e58dbfbebd Added sticker reprint updated logic and added blade file 2025-08-07 09:25:25 +05:30
dhanabalan
15af1edb8f Rename identification fields to Aadhar Number and PAN Number for clarity 2025-08-07 09:20:53 +05:30
dhanabalan
705cc8c3a4 Added blank line for improved readability 2025-08-05 12:09:44 +05:30
dhanabalan
6e61f83e3a Validate production order length to be between 7 and 14 digits in both ProductionQuantityImporter and QualityValidationImporter 2025-08-05 12:03:49 +05:30
dhanabalan
197184e2ed Refactor Invoice Validation Logic and Update UI for Serial and Material Invoices
- Improved conditional checks for invoice processing in InvoiceValidationResource on completion (or pending).
- Enhanced notifications for completed scanning processes for both serial and material invoices.
- Updated CreateInvoiceValidation page to pass invoice type to serial and material invoice on completion (or pending).
- Modified InvoiceDataTable to include a new property for serial/material invoice handling.
- Adjusted Blade view to dynamically display the correct title and messages based on invoice type (serial/material).
2025-08-05 12:00:26 +05:30
dhanabalan
d6c77bd6c3 Enhance production order validation to require numeric values with 7 to 14 digits across multiple resources 2025-08-04 19:35:50 +05:30
dhanabalan
68d4240ab0 Add removed all line for production line stop count and production order count 2025-08-04 18:23:51 +05:30
dhanabalan
68ba8fa89d Added Serial Invoice Api for invoice validation 2025-08-04 12:26:49 +05:30
dhanabalan
8c84e48f8e Refactor pallet number generation to include LocatorInvoiceValidation for improved uniqueness 2025-08-02 12:49:26 +05:30
dhanabalan
2e7859656a Disablked the delete at for export page 2025-07-31 18:21:11 +05:30
dhanabalan
4bfbebb254 Added No column for all resource tables page 2025-07-31 18:16:51 +05:30
dhanabalan
1ea00b6901 Added device name column for mfm parameter resource and import and export 2025-07-31 18:14:02 +05:30
dhanabalan
5084aa9c0e Added import and export in device master resource page 2025-07-31 18:05:06 +05:30
dhanabalan
c844a23556 Added device master importer and exporter 2025-07-31 18:04:21 +05:30
dhanabalan
76649651f1 Added line type column in production mail table 2025-07-31 17:32:26 +05:30
dhanabalan
e15c866078 Add column for table line type 2025-07-31 17:26:00 +05:30
dhanabalan
04af1c7c34 modified names of live reading for view page 2025-07-31 17:22:00 +05:30
dhanabalan
8871389fe3 chngaed name of edit live readings page 2025-07-31 17:20:32 +05:30
dhanabalan
ec2fd4d3ca modifiednavigation names for live readings page 2025-07-31 17:18:44 +05:30
dhanabalan
5c1f77796f Arranged text input box for mfm parameter page 2025-07-31 17:09:16 +05:30
dhanabalan
530bca4c4b Added required for trend line analysis page 2025-07-31 17:07:02 +05:30
dhanabalan
ccceff9edc Added required for trend chart analysis chart page 2025-07-31 17:05:22 +05:30
dhanabalan
c53f40d8a0 Added module for trend line analysis chart 2025-07-31 17:02:56 +05:30
dhanabalan
6b67d94476 Added permissions for ems trend line and trend chart page 2025-07-31 16:59:12 +05:30
dhanabalan
b2d2ab7e05 Added trend line analysis page and blade file 2025-07-31 16:57:51 +05:30
dhanabalan
573b02a97a Added trend line chart analysis chart page 2025-07-31 16:57:08 +05:30
dhanabalan
96a5dacf95 Add trend chart analysis page and blade file 2025-07-31 16:56:01 +05:30
dhanabalan
58cdcec6ed Added trend chart analysis chart file 2025-07-31 16:52:58 +05:30
dhanabalan
c67e8fcc59 Added device master logic for mfm parameter controller 2025-07-31 16:43:53 +05:30
dhanabalan
d5588e0b25 modified logic for mfm parameter resource page 2025-07-31 16:43:07 +05:30
dhanabalan
9ff7f88840 modified logic for mfm meter resource file 2025-07-31 16:42:36 +05:30
dhanabalan
03e53e0bb1 Added mfm parameter exporter file 2025-07-31 16:41:13 +05:30
dhanabalan
33b2b6399d Added mfm meter importer and exporter file 2025-07-31 16:38:23 +05:30
dhanabalan
2437bdf85f added column device_master_id for mfm_parameter model file 2025-07-31 16:35:51 +05:30
dhanabalan
f51aea626b Added foreign key device_master_id for mfm_parameter table 2025-07-31 16:33:58 +05:30
dhanabalan
77129cb70b Added mfm meter model file 2025-07-31 16:30:59 +05:30
dhanabalan
bb462a6c45 Added foreign and unique key for mfm_meters table 2025-07-31 16:30:04 +05:30
dhanabalan
9a2a6bdd9b Add device master policy file 2025-07-31 16:21:14 +05:30
dhanabalan
0a414a6804 Added device master resource file 2025-07-31 16:18:25 +05:30
dhanabalan
f4bb7a7a78 Added device master model file 2025-07-31 16:17:35 +05:30
dhanabalan
8aad6cf1e6 Add device master migration file 2025-07-31 16:14:47 +05:30
dhanabalan
3b18411141 Added logic for invoice report for daily report 2025-07-31 15:00:03 +05:30
dhanabalan
162eaa0c9c added unwanted line 2025-07-31 13:59:14 +05:30
dhanabalan
d5f55fbf98 added commented line for git checking 2025-07-31 13:58:18 +05:30
dhanabalan
cf5cfac555 Removed unwanted lines for production send report 2025-07-31 13:53:41 +05:30
dhanabalan
7bf2e8182b Updated QR validation functionality to allow with and without item code 2025-07-31 12:26:16 +05:30
dhanabalan
216b62f8bf Added notification for missing invoice type in filter options 2025-07-31 12:22:23 +05:30
dhanabalan
cad7f19ab5 Added invoice_type radio filter and scanned_status select filter to Invoice Validation 2025-07-31 08:53:40 +05:30
dhanabalan
ca9695c922 Added operator_id and scanned_status filter fields to Invoice validaitons resources and Alignment changed in filter option for Production Quantity / Quality Validation 2025-07-30 15:18:26 +05:30
dhanabalan
d1f9a3176f Added operator_id field to ProductionQuantity and QualityValidation in report filter 2025-07-30 12:32:17 +05:30
dhanabalan
0b9d0f9995 modified size of the qr code of scan pallet 2025-07-29 18:02:42 +05:30
dhanabalan
897aa77217 Modified qr code size for pallet 2025-07-29 15:52:44 +05:30
dhanabalan
000533ef7c Added scan pallet print pdf 2025-07-29 15:36:29 +05:30
dhanabalan
a78cb75bdd Added reprint for scan pallet 2025-07-29 13:56:30 +05:30
dhanabalan
ab769d2287 Added 2 copies of pallet number print for scan pallet 2025-07-29 13:26:13 +05:30
dhanabalan
0bde54cf1a removed logic against the production order 2025-07-29 11:47:26 +05:30
dhanabalan
48942307e1 modified sticker reprint controller logic 2025-07-29 11:46:44 +05:30
dhanabalan
8c5f2b5b39 commented production order text input box as mandatory 2025-07-29 11:35:13 +05:30
dhanabalan
b1df9f8b87 Added production sticker reprint page 2025-07-29 11:33:28 +05:30
dhanabalan
c0d13db2f3 Added created_at, updated_at, email while data response with roles 2025-07-28 18:33:15 +05:30
dhanabalan
b4bf170c89 Added kiosk for scan pallet 2025-07-28 18:10:54 +05:30
dhanabalan
b0d2132e25 Refactor QR code PDF generation to improve layout and add automatic print functionality 2025-07-28 18:01:50 +05:30
293 changed files with 31725 additions and 2962 deletions

View File

@@ -0,0 +1,62 @@
# Filename: .github/workflows/kingfisher-secrets-scan.yaml
# Gitea Actions workflow for ACT Runner to scan for leaked secrets using Kingfisher
name: Scan for leaked secrets using Kingfisher
on:
push:
pull_request:
workflow_dispatch:
jobs:
kingfisher-secrets-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v5
- name: Get Kingfisher version and arch
id: get_version_arch
run: |
VERSION=$(curl -s https://api.github.com/repos/mongodb/kingfisher/releases/latest | jq -r '.tag_name')
echo "version=$VERSION" >> $GITHUB_OUTPUT
ARCH_RAW=$(arch)
if [ "$ARCH_RAW" = "x86_64" ]; then
ARCH="x64"
elif [ "$ARCH_RAW" = "aarch64" ]; then
ARCH="arm64"
else
echo "Unsupported architecture: $ARCH_RAW"
exit 1
fi
echo "arch=$ARCH" >> $GITHUB_OUTPUT
cat $GITHUB_OUTPUT
- name: Cache kingfisher binary
id: cache
uses: actions/cache@v4
with:
path: /usr/local/bin
key: ${{ runner.os }}-kingfisher-${{ steps.get_version_arch.outputs.version }}-${{ steps.get_version_arch.outputs.arch }}
restore-keys: |
${{ runner.os }}-kingfisher-${{ steps.get_version_arch.outputs.arch }}
- name: Install kingfisher if cache missed
if: steps.cache.outputs.cache-hit != 'true'
run: |
URL=$(curl -s https://api.github.com/repos/mongodb/kingfisher/releases/latest | \
jq -r --arg arch "${{ steps.get_version_arch.outputs.arch }}" '.assets[] |
select(.name | test("kingfisher-linux-" + $arch + "\\.tgz")) |
.browser_download_url')
echo "Downloading Kingfisher from $URL"
curl -sL $URL | tar -xz -C /usr/local/bin kingfisher
chmod +x /usr/local/bin/kingfisher
- name: Run Kingfisher scan
continue-on-error: true
run: |
kingfisher scan -n -r ${{ github.workspace }} \
--exclude='composer.lock' \
--exclude='package-lock.json'

View File

@@ -0,0 +1,249 @@
<?php
namespace App\Console\Commands;
use App\Mail\InvoiceDataMail;
use App\Models\AlertMailRule;
use App\Models\InvoiceDataValidation;
use App\Models\InvoiceOutValidation;
use App\Models\Line;
use App\Models\Plant;
use App\Models\ProductionPlan;
use App\Models\ProductionQuantity;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Mail;
class SendInvoiceDataReport extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'send:invoice-data-report {schedule_type} {plant}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Execute the console command.
*/
public function handle()
{
// ini_set('max_execution_time', 0); // disable limit
// set_time_limit(0);
$scheduleType = $this->argument('schedule_type');
$plantId = (int) $this->argument('plant');
$mailRules = AlertMailRule::where('module', 'InvoiceDataReport')
->where('rule_name', 'InvoiceDataMail')
->where('schedule_type', $scheduleType)
->where('plant', $plantId)
->get();
$plants = ($plantId == 0) ? Plant::all() : Plant::where('id', $plantId)->get();
if ($plants->isEmpty()) {
$this->error("No valid plant(s) found.");
return;
}
// if (strtolower($scheduleType) == 'daily') {
// $startDate = now()->subDay()->setTime(10, 0, 0);//8:00
// $endDate = now()->setTime(10, 0, 0);//8
// }
if (strtolower($scheduleType) == 'daily')
{
$firstRecord = InvoiceDataValidation::orderBy('document_date', 'asc')->first();
$lastRecord = InvoiceDataValidation::orderBy('document_date', 'desc')->first();
if ($firstRecord && $lastRecord) {
$startDate = \Carbon\Carbon::parse($firstRecord->document_date)->startOfDay();
//$endDate = \Carbon\Carbon::parse($lastRecord->document_date)->endOfDay();
$endDate = \Carbon\Carbon::parse($lastRecord->document_date)
->addDay()
->setTime(10, 0, 0);
}
else
{
$startDate = now()->startOfDay();
$endDate = now()->endOfDay();
}
}
else
{
$startDate = now()->setTime(8, 0, 0);
$endDate = now()->copy()->addDay()->setTime(8, 0, 0);
}
//..
foreach ($plants as $plant)
{
$tableData = [];
// $distributions = ['Direct Sale', 'Branch Sale', 'Internal Transfer', 'WOS', ''];
$distributions = InvoiceDataValidation::whereNotNull('distribution_channel_desc')
->distinct()
->pluck('distribution_channel_desc')
->filter(fn($val) => trim($val) != '')
->values()
->toArray();
$distributions[] = '';
foreach ($distributions as $selectedDistribution)
{
//where('plant_id', $plant->id)
$invoices = InvoiceDataValidation::where('plant_id', $plant->id)
->where('distribution_channel_desc', $selectedDistribution)
->whereBetween('document_date', [$startDate, $endDate])
->orderBy('document_date', 'asc')
->select('customer_code', 'document_number', 'document_date', 'customer_trade_name', 'customer_location', 'location')
->get()
->unique('document_number')
->values();
if ($invoices->isEmpty()) {
continue;
}
// Filter invoices directly — exclude ones with '-' in document_number
$invoices = $invoices->filter(function ($inv) {
return !empty($inv->document_number) && !str_contains($inv->document_number, '-');
});
if (trim($selectedDistribution) == '' || $selectedDistribution == null) {
$invoices = $invoices->filter(function ($inv) {
return str_starts_with($inv->document_number, '7');
});
}
if ($invoices->isEmpty()) {
continue;
}
$invoiceNumbers = $invoices
->pluck('document_number')
->map(fn($n) => preg_replace('/\s+/', '', strtoupper((string) $n)))
->toArray();
//where('plant_id', $plant->id)
$wentOutInvoices = InvoiceOutValidation::whereIn('qr_code', $invoiceNumbers)
//->whereBetween('scanned_at', [$startDate, $endDate])
->distinct('qr_code')
->pluck('qr_code')
->map(fn($n) => preg_replace('/\s+/', '', strtoupper((string) $n)))
->toArray();
// if (!empty($wentOutInvoices)) {
// $deletedValidations = InvoiceDataValidation::whereIn('document_number', $wentOutInvoices)
// ->delete();
// $deletedOuts = InvoiceOutValidation::whereIn('qr_code', $wentOutInvoices)
// ->delete();
// $this->info("Deleted {$deletedValidations} from invoice_data_validations and {$deletedOuts} from invoice_out_validations for plant {$plant->name} ({$selectedDistribution}).");
// }
// $pendingInvoices = $invoices->filter(function ($inv) use ($wentOutInvoices) {
// return !in_array($inv->document_number, $wentOutInvoices);
// });
// $pendingInvoices = $invoices->filter(function ($inv) use ($wentOutInvoices) {
// return !in_array(strtoupper(trim($inv->document_number)), $wentOutInvoices);
// });
$pendingInvoices = $invoices->filter(function ($inv) use ($wentOutInvoices) {
$doc = preg_replace('/\s+/', '', strtoupper((string) $inv->document_number));
return !in_array($doc, $wentOutInvoices, true);
});
if ($pendingInvoices->isEmpty()) {
continue;
}
foreach ($pendingInvoices as $inv)
{
$yesterday = now()->subDay()->toDateString();
$today = now()->toDateString();
$documentDate = \Carbon\Carbon::parse($inv->document_date);
if (in_array($documentDate->toDateString(), [$today, $yesterday])) {
$statusColor = 'status-pending-yellow';
} else {
$statusColor = 'status-pending-red';
}
$tableData[] = [
//'no' => $no++,
'plant' => $plant->name,
// 'distribution_type' => $selectedDistribution,
'customer_code' => $inv->customer_code,
'document_number' => $inv->document_number,
'document_date' => $inv->document_date,
'customer_trade_name' => $inv->customer_trade_name,
'customer_location' => $inv->customer_location,
'location' => $inv->location,
'no_of_days_pending' => abs((int)now()->diffInDays($documentDate)),
'status' => 'Pending',
'status_class' => $statusColor,
];
}
}
$tableData = collect($tableData)
->sortBy('document_date')
->values()
->map(function ($item, $index) {
$item['no'] = $index + 1;
return $item;
})
->toArray();
$mailSubject = "Despatch Pending Sale Invoice & STO Invoice as on Date ({$plant->name})";
$mail = new InvoiceDataMail($scheduleType, $tableData, $mailSubject);
$contentVars = $mail->content()->with;
$this->info($contentVars['greeting'] ?? 'Invoice Data Report');
$this->table(
['No', 'Plant', 'Customer Code', 'Document Number', 'Document Date', 'Trade Name', 'Location', 'Pending Days', 'Status'],//'Distribution Type'
$tableData
);
$this->info($contentVars['wishes'] ?? '');
foreach ($mailRules as $rule)
{
$toEmails = collect(explode(',', $rule->email))
->map(fn($e) => trim($e))
->filter()
->unique()
->values()
->toArray();
$ccEmails = collect(explode(',', $rule->cc_emails))
->map(fn($e) => trim($e))
->filter()
->unique()
->values()
->toArray();
if (empty($toEmails)) {
$this->warn("Skipping rule ID {$rule->id} — no valid To emails found.");
continue;
}
\Mail::to($toEmails)->cc($ccEmails)->send($mail);
$this->info("Mail sent for rule ID {$rule->id} → To: " . implode(', ', $toEmails) . ($ccEmails ? " | CC: " . implode(', ', $ccEmails) : ''));
}
}
}
}

View File

@@ -30,258 +30,17 @@ class SendInvoiceReport extends Command
* Execute the console command.
*/
// public function handle()
// {
// $schedule = $this->argument('schedule_type');
// $plantid = $this->argument('plant');
// $mailRules = \App\Models\AlertMailRule::where('module', 'InvoiceValidation')->get()->groupBy('rule_name');
// $startDate = now()->setTime(8, 0, 0);
// $endDate = now()->copy()->addDay()->setTime(8, 0, 0);
// $plants = InvoiceValidation::select('plant_id')->distinct()->pluck('plant_id');
// $serialTableData = [];
// $materialTableData = [];
// $bundleTableData = [];
// $noSerial = 1;
// $noMaterial = 1;
// $noBundle = 1;
// foreach ($plants as $plantId) {
// $plant = Plant::find($plantId);
// $plantName = $plant ? $plant->name : $plantId;
// //..Serial Invoice
// $totalSerialCount = InvoiceValidation::where('plant_id', $plantId)
// ->whereNull('quantity')
// ->whereBetween('created_at', [$startDate, $endDate])
// ->distinct('invoice_number')
// ->count('invoice_number');
// $scannedSerialCount = InvoiceValidation::select('invoice_number')
// ->where('plant_id', $plantId)
// ->whereNull('quantity')
// ->whereBetween('updated_at', [$startDate, $endDate])
// ->groupBy('invoice_number')
// ->havingRaw(
// "COUNT(*) = SUM(CASE WHEN scanned_status = 'Scanned' THEN 1 ELSE 0 END)"
// )
// ->count();
// $serialTableData[] = [
// 'no' => $noSerial++,
// 'plant' => $plantName,
// 'totalInvoice' => $totalSerialCount,
// 'scannedInvoice' => $scannedSerialCount,
// ];
// //..Individual Invoice
// $TotalMatCount = InvoiceValidation::where('plant_id', $plantId)
// ->where('quantity', 1)
// ->whereBetween('created_at', [$startDate, $endDate])
// ->distinct('invoice_number')
// ->count('invoice_number');
// $scannedMatCount = InvoiceValidation::select('invoice_number')
// ->where('plant_id', $plantId)
// ->where('quantity', 1)
// ->whereBetween('updated_at', [$startDate, $endDate])
// ->groupBy('invoice_number')
// ->havingRaw(
// "COUNT(*) = SUM(CASE WHEN serial_number IS NOT NULL AND serial_number != '' THEN 1 ELSE 0 END)"
// )
// ->count();
// $materialTableData[] = [
// 'no' => $noMaterial++,
// 'plant' => $plantName,
// 'totalInvoice' => $TotalMatCount,
// 'scannedInvoice' => $scannedMatCount,
// ];
// //..BUndle Invoice
// $totalBundleCount = InvoiceValidation::where('plant_id', $plantId)
// ->where('quantity', '>', 1)
// ->whereBetween('created_at', [$startDate, $endDate])
// ->distinct('invoice_number')
// ->count('invoice_number');
// $scannedBundleCount = InvoiceValidation::select('invoice_number')
// ->where('plant_id', $plantId)
// ->where('quantity', '>', 1)
// ->whereBetween('updated_at', [$startDate, $endDate])
// ->groupBy('invoice_number')
// ->havingRaw(
// "COUNT(*) = SUM(CASE WHEN serial_number IS NOT NULL AND serial_number != '' THEN 1 ELSE 0 END)"
// )
// ->count();
// $bundleTableData[] = [
// 'no' => $noBundle++,
// 'plant' => $plantName,
// 'totalInvoice' => $totalBundleCount,
// 'scannedInvoice' => $scannedBundleCount,
// ];
// }
// // Send to SerialInvoiceMail recipients
// if ($mailRules->has('SerialInvoiceMail')) {
// $emails = $mailRules['SerialInvoiceMail']->pluck('email')->unique()->toArray();
// foreach ($emails as $email) {
// Mail::to($email)->send(new test($serialTableData, [], []));
// }
// }
// // Send to MaterialInvoiceMail recipients (material + bundle table)
// if ($mailRules->has('MaterialInvoiceMail')) {
// $emails = $mailRules['MaterialInvoiceMail']->pluck('email')->unique()->toArray();
// foreach ($emails as $email) {
// Mail::to($email)->send(new test([], $materialTableData, $bundleTableData));
// }
// }
// // Send to InvoiceMail recipients (all three tables)
// if ($mailRules->has('InvoiceMail')) {
// $emails = $mailRules['InvoiceMail']->pluck('email')->unique()->toArray();
// foreach ($emails as $email) {
// Mail::to($email)->send(new test($serialTableData, $materialTableData, $bundleTableData));
// }
// }
// //$this->info(json_encode($materialTableData));
// }
// public function handle()
// {
// $schedule = $this->argument('schedule_type');
// $plantId = $this->argument('plant');
// $mailRules = \App\Models\AlertMailRule::where('module', 'InvoiceValidation')->get()->groupBy('rule_name');
// $startDate = now()->setTime(8, 0, 0);
// $endDate = now()->copy()->addDay()->setTime(8, 0, 0);
// $serialTableData = [];
// $materialTableData = [];
// $bundleTableData = [];
// $plant = Plant::find($plantId);
// $plantName = $plant ? $plant->name : $plantId;
// // Serial Invoice
// $totalSerialCount = InvoiceValidation::where('plant_id', $plantId)
// ->whereNull('quantity')
// ->whereBetween('created_at', [$startDate, $endDate])
// ->distinct('invoice_number')
// ->count('invoice_number');
// $scannedSerialCount = InvoiceValidation::select('invoice_number')
// ->where('plant_id', $plantId)
// ->whereNull('quantity')
// ->whereBetween('updated_at', [$startDate, $endDate])
// ->groupBy('invoice_number')
// ->havingRaw(
// "COUNT(*) = SUM(CASE WHEN scanned_status = 'Scanned' THEN 1 ELSE 0 END)"
// )
// ->count();
// $serialTableData[] = [
// 'no' => 1,
// 'plant' => $plantName,
// 'totalInvoice' => $totalSerialCount,
// 'scannedInvoice' => $scannedSerialCount,
// ];
// // Individual Material Invoice
// $TotalMatCount = InvoiceValidation::where('plant_id', $plantId)
// ->where('quantity', 1)
// ->whereBetween('created_at', [$startDate, $endDate])
// ->distinct('invoice_number')
// ->count('invoice_number');
// $scannedMatCount = InvoiceValidation::select('invoice_number')
// ->where('plant_id', $plantId)
// ->where('quantity', 1)
// ->whereBetween('updated_at', [$startDate, $endDate])
// ->groupBy('invoice_number')
// ->havingRaw(
// "COUNT(*) = SUM(CASE WHEN serial_number IS NOT NULL AND serial_number != '' THEN 1 ELSE 0 END)"
// )
// ->count();
// $materialTableData[] = [
// 'no' => 1,
// 'plant' => $plantName,
// 'totalInvoice' => $TotalMatCount,
// 'scannedInvoice' => $scannedMatCount,
// ];
// // Bundle Invoice
// $totalBundleCount = InvoiceValidation::where('plant_id', $plantId)
// ->where('quantity', '>', 1)
// ->whereBetween('created_at', [$startDate, $endDate])
// ->distinct('invoice_number')
// ->count('invoice_number');
// $scannedBundleCount = InvoiceValidation::select('invoice_number')
// ->where('plant_id', $plantId)
// ->where('quantity', '>', 1)
// ->whereBetween('updated_at', [$startDate, $endDate])
// ->groupBy('invoice_number')
// ->havingRaw(
// "COUNT(*) = SUM(CASE WHEN serial_number IS NOT NULL AND serial_number != '' THEN 1 ELSE 0 END)"
// )
// ->count();
// $bundleTableData[] = [
// 'no' => 1,
// 'plant' => $plantName,
// 'totalInvoice' => $totalBundleCount,
// 'scannedInvoice' => $scannedBundleCount,
// ];
// // Send to SerialInvoiceMail recipients
// if ($mailRules->has('SerialInvoiceMail')) {
// $emails = $mailRules['SerialInvoiceMail']->pluck('email')->unique()->toArray();
// foreach ($emails as $email) {
// Mail::to($email)->send(new test($serialTableData, [], []));
// }
// }
// // Send to MaterialInvoiceMail recipients (material + bundle table)
// if ($mailRules->has('MaterialInvoiceMail')) {
// $emails = $mailRules['MaterialInvoiceMail']->pluck('email')->unique()->toArray();
// foreach ($emails as $email) {
// Mail::to($email)->send(new test([], $materialTableData, $bundleTableData));
// }
// }
// // Send to InvoiceMail recipients (all three tables)
// if ($mailRules->has('InvoiceMail')) {
// $emails = $mailRules['InvoiceMail']->pluck('email')->unique()->toArray();
// foreach ($emails as $email) {
// Mail::to($email)->send(new test($serialTableData, $materialTableData, $bundleTableData));
// }
// }
// // $this->table(
// // ['No', 'Plant', 'Total Invoice', 'Scanned Invoice'],
// // $serialTableData
// // );
// }
public function handle()
{
$schedule = $this->argument('schedule_type');
//$scheduleType = $this->argument('scheduleType');
$plantIdArg = (int) $this->argument('plant'); // can be 0 for all plants
$mailRules = \App\Models\AlertMailRule::where('module', 'InvoiceValidation')->get()->groupBy('rule_name');
$startDate = now()->setTime(8, 0, 0);
$endDate = now()->copy()->addDay()->setTime(8, 0, 0);
// $startDate = now()->setTime(8, 0, 0);
// $endDate = now()->copy()->addDay()->setTime(8, 0, 0);
$serialTableData = [];
$materialTableData = [];
@@ -293,7 +52,18 @@ class SendInvoiceReport extends Command
: [$plantIdArg];
$no = 1;
foreach ($plantIds as $plantId) {
if (strtolower($schedule) == 'daily')
{
$startDate = now()->subDay()->setTime(8, 0, 0);
$endDate = now()->setTime(8, 0, 0);
}
else
{
$startDate = now()->setTime(8, 0, 0);
$endDate = now()->copy()->addDay()->setTime(8, 0, 0);
}
foreach ($plantIds as $plantId)
{
$plant = Plant::find($plantId);
$plantName = $plant ? $plant->name : $plantId;
@@ -312,11 +82,27 @@ class SendInvoiceReport extends Command
->havingRaw("COUNT(*) = SUM(CASE WHEN scanned_status = 'Scanned' THEN 1 ELSE 0 END)")
->count();
$serialInvoiceQuan = InvoiceValidation::where('plant_id', $plantId)
->where('quantity', null)
->whereBetween('created_at', [$startDate, $endDate])
->count();
$scannedInvoiceQuan = InvoiceValidation::where('plant_id', $plantId)
->where('scanned_status', 'Scanned')
->where(function($query) {
$query->whereNull('quantity')
->orWhere('quantity', 0);
})
->whereBetween('updated_at', [$startDate, $endDate])
->count();
$serialTableData[] = [
'no' => $no,
'plant' => $plantName,
'totalInvoice' => $totalSerialCount,
'scannedInvoice' => $scannedSerialCount,
'totalInvoiceQuan' => $serialInvoiceQuan,
'scannedInvoiceQuan' => $scannedInvoiceQuan,
];
// Material Invoice
@@ -334,11 +120,25 @@ class SendInvoiceReport extends Command
->havingRaw("COUNT(*) = SUM(CASE WHEN serial_number IS NOT NULL AND serial_number != '' THEN 1 ELSE 0 END)")
->count();
$totalMatInvoiceQuan = InvoiceValidation::where('plant_id', $plantId)
->where('quantity', 1)
->whereBetween('created_at', [$startDate, $endDate])
->count();
$scannedMatInvoiceQuan = InvoiceValidation::where('plant_id', $plantId)
->where('quantity', 1)
->whereNotNull('serial_number')
->where('serial_number','!=', '')
->whereBetween('updated_at', [$startDate, $endDate])
->count();
$materialTableData[] = [
'no' => $no,
'plant' => $plantName,
'totalInvoice' => $totalMatCount,
'scannedInvoice' => $scannedMatCount,
'totalInvoiceQuan' => $totalMatInvoiceQuan,
'scannedInvoiceQuan' => $scannedMatInvoiceQuan,
];
// Bundle Invoice
@@ -356,29 +156,49 @@ class SendInvoiceReport extends Command
->havingRaw("COUNT(*) = SUM(CASE WHEN serial_number IS NOT NULL AND serial_number != '' THEN 1 ELSE 0 END)")
->count();
$totalBundleInvoiceQuan = InvoiceValidation::where('plant_id', $plantId)
->where('quantity', '>', 1)
->whereBetween('created_at', [$startDate, $endDate])
->count();
$scannedBundleInvoiceQuan = InvoiceValidation::where('plant_id', $plantId)
->where('quantity', '>', 1)
->whereNotNull('serial_number')
->where('serial_number','!=', '')
->whereBetween('updated_at', [$startDate, $endDate])
->count();
$bundleTableData[] = [
'no' => $no,
'plant' => $plantName,
'totalInvoice' => $totalBundleCount,
'scannedInvoice' => $scannedBundleCount,
'totalInvoiceQuan' => $totalBundleInvoiceQuan,
'scannedInvoiceQuan' => $scannedBundleInvoiceQuan,
];
$no++;
}
$mail = new test($serialTableData, $materialTableData, $bundleTableData, $schedule);
$contentVars = $mail->content()->with;
$this->info($contentVars['greeting'] ?? 'Invoice Report');
// Send to SerialInvoiceMail recipients
if ($mailRules->has('SerialInvoiceMail')) {
$emails = $mailRules['SerialInvoiceMail']->pluck('email')->unique()->toArray();
foreach ($emails as $email) {
Mail::to($email)->send(new test($serialTableData, [], []));
Mail::to($email)->send(new test($serialTableData, [], [], $schedule));
}
}
// Send to MaterialInvoiceMail recipients (material + bundle table)
if ($mailRules->has('MaterialInvoiceMail')) {
$emails = $mailRules['MaterialInvoiceMail']->pluck('email')->unique()->toArray();
foreach ($emails as $email) {
Mail::to($email)->send(new test([], $materialTableData, $bundleTableData));
Mail::to($email)->send(new test([], $materialTableData, $bundleTableData, $schedule));
}
}
@@ -386,19 +206,21 @@ class SendInvoiceReport extends Command
if ($mailRules->has('InvoiceMail')) {
$emails = $mailRules['InvoiceMail']->pluck('email')->unique()->toArray();
foreach ($emails as $email) {
Mail::to($email)->send(new test($serialTableData, $materialTableData, $bundleTableData));
Mail::to($email)->send(new test($serialTableData, $materialTableData, $bundleTableData, $schedule));
}
}
// Show preview in console
$this->info('--- Serial Invoice Table ---');
$this->table(['#', 'Plant', 'Total Invoice', 'Scanned Invoice'], $serialTableData);
$this->table(['#', 'Plant', 'Total Invoice', 'Scanned Invoice','TotalInvoice Quantity', 'ScannedInvoice Quantity'], $serialTableData);
$this->info('--- Material Invoice Table ---');
$this->table(['#', 'Plant', 'Total Invoice', 'Scanned Invoice'], $materialTableData);
$this->table(['#', 'Plant', 'Total Invoice', 'Scanned Invoice','TotalInvoice Quantity', 'ScannedInvoice Quantity'], $materialTableData);
$this->info('--- Bundle Invoice Table ---');
$this->table(['#', 'Plant', 'Total Invoice', 'Scanned Invoice'], $bundleTableData);
$this->table(['#', 'Plant', 'Total Invoice', 'Scanned Invoice','TotalInvoice Quantity', 'ScannedInvoice Quantity'], $bundleTableData);
$this->info($contentVars['wishes'] ?? '');
}

View File

@@ -33,79 +33,11 @@ class SendProductionReport extends Command
* Execute the console command.
*/
// public function handle()
// {
// $scheduleType = $this->argument('schedule_type');
// $plantId = $this->argument('plant');
// $mailRules = \App\Models\AlertMailRule::where('module', 'ProductionQuantities')
// ->where('rule_name', 'ProductionMail')
// ->where('plant', $plantId)
// ->where('schedule_type', $scheduleType)
// ->get();
// $emails = $mailRules->pluck('email')->unique()->toArray();
// $plant = Plant::find($plantId);
// if (!$plant) {
// $this->error("Invalid plant ID: $plantId");
// return;
// }
// $lines = Line::where('plant_id', $plantId)->get();
// $startDate = now()->setTime(8, 0, 0);
// $endDate = now()->copy()->addDay()->setTime(8, 0, 0);
// $PlanstartDate = now()->setTime(8, 0, 0);
// $planendDate = now()->copy()->addDay()->setTime(7, 59, 00);
// $tableData = [];
// $no = 1;
// foreach ($lines as $line) {
// $lineId = $line->id;
// $lineName = $line->name;
// $targetQuantity = ProductionPlan::where('plant_id', $plantId)
// ->where('line_id', $lineId)
// ->whereBetween('created_at', [$PlanstartDate, $planendDate])
// ->sum('plan_quantity');
// $productionQuantity = ProductionQuantity::where('plant_id', $plantId)
// ->where('line_id', $lineId)
// ->whereBetween('created_at', [$startDate, $endDate])
// ->count();
// $tableData[] = [
// 'no' => $no++,
// 'plant' => $plant->name,
// 'line' => $lineName,
// 'targetQuantity' => $targetQuantity,
// 'productionQuantity' => $productionQuantity,
// ];
// }
// // $this->table(
// // ['No', 'Plant', 'Line', 'Target Quantity', 'Production Quantity'],
// // $tableData
// // );
// if (!empty($emails)) {
// foreach ($emails as $email) {
// Mail::to($email)->send(new ProductionMail($tableData));
// }
// } else {
// $this->info('No recipients found for ProductionMailAlert.');
// }
// $this->info("Production report sent to " . count($emails) . " recipient(s).");
// }
public function handle()
{
ini_set('max_execution_time', 0); // disable limit
set_time_limit(0);
$scheduleType = $this->argument('schedule_type');
$plantId = (int) $this->argument('plant'); // cast to int for safety
@@ -146,53 +78,7 @@ class SendProductionReport extends Command
$tableData = [];
$no = 1;
// foreach ($plants as $plant) {
// $lines = Line::where('plant_id', $plant->id)->get();
// foreach ($lines as $line) {
// $targetQuantity = ProductionPlan::where('plant_id', $plant->id)
// ->where('line_id', $line->id)
// ->whereBetween('created_at', [$PlanstartDate, $planendDate])
// ->sum('plan_quantity');
// $productionQuantity = ProductionQuantity::where('plant_id', $plant->id)
// ->where('line_id', $line->id)
// ->whereBetween('created_at', [$startDate, $endDate])
// ->count();
// $tableData[] = [
// 'no' => $no++,
// 'plant' => $plant->name,
// 'line' => $line->name,
// 'targetQuantity' => $targetQuantity,
// 'productionQuantity' => $productionQuantity,
// ];
// }
// }
// $fgTableData = []; // store FG Line related data
// foreach ($plants as $plant) {
// // ✅ Only get FG Lines
// $fgLines = Line::where('plant_id', $plant->id)
// ->where('type', 'FG Line')
// ->get();
// foreach ($fgLines as $line) {
// $validationCount = \App\Models\QualityValidation::where('plant_id', $plant->id)
// ->where('line_id', $line->id)
// ->whereBetween('created_at', [$startDate, $endDate])
// ->count();
// $fgTableData[] = [
// 'no' => $no++,
// 'plant' => $plant->name,
// 'line' => $line->name,
// 'targetQuantity' => $targetQuantity,
// 'productionQuantity' => $validationCount,
// ];
// }
// }
//.
foreach ($plants as $plant)
{
@@ -204,7 +90,7 @@ class SendProductionReport extends Command
->whereBetween('created_at', [$PlanstartDate, $planendDate])
->sum('plan_quantity');
if (strtolower($line->type) === 'fg line') {
if (strtolower($line->type) == 'fg line') {
$productionQuantity = \App\Models\QualityValidation::where('plant_id', $plant->id)
->where('line_id', $line->id)
->whereBetween('created_at', [$startDate, $endDate])
@@ -220,6 +106,7 @@ class SendProductionReport extends Command
'no' => $no++,
'plant' => $plant->name,
'line' => $line->name,
'type' => $line->type,
'targetQuantity' => $targetQuantity,
'productionQuantity' => $productionQuantity,
];
@@ -228,20 +115,38 @@ class SendProductionReport extends Command
///$this->table(['No', 'Plant', 'Line', 'Target Quantity', 'Production Quantity'], $fgTableData);
//$this->table(['No', 'Plant', 'Line', 'Target Quantity', 'Production Quantity'], $fgTableData);
$this->table(['No', 'Plant', 'Line', 'Target Quantity', 'Production Quantity'], $tableData);
// $this->table(['No', 'Plant', 'Line', 'Target Quantity', 'Production Quantity'], $tableData);
// if (!empty($emails)) {
// foreach ($emails as $email) {
// Mail::to($email)->send(new ProductionMail($tableData));
// }
// } else {
// $this->info('No recipients found for ProductionMailAlert.');
// }
// $this->info("Production report sent to " . count($emails) . " recipient(s).");
// Preview in console
$mail = new ProductionMail($scheduleType, $tableData);
$contentVars = $mail->content()->with;
$this->info($contentVars['greeting'] ?? 'Production Report');
$this->table(
['No', 'Plant', 'Line', 'Type', 'Target Quantity', 'Production Quantity'],
$tableData
);
$this->info($contentVars['wishes'] ?? '');
// Send mails
if (!empty($emails)) {
foreach ($emails as $email) {
Mail::to($email)->send(new ProductionMail($tableData));
Mail::to($email)->send(new ProductionMail($scheduleType, $tableData));
}
$this->info("Production report sent to " . count($emails) . " recipient(s).");
} else {
$this->info('No recipients found for ProductionMailAlert.');
$this->warn('No recipients found for ProductionMailAlert.');
}
$this->info("Production report sent to " . count($emails) . " recipient(s).");
}
}

View File

@@ -22,7 +22,7 @@ class ConfigurationExporter extends Exporter
// Increment and return the row number
return ++$rowNumber;
}),
ExportColumn::make('plant.name')
ExportColumn::make('plant.code')
->label('PLANT'),
ExportColumn::make('line.name')
->label('LINE'),

View File

@@ -0,0 +1,54 @@
<?php
namespace App\Filament\Exports;
use App\Models\DeviceMaster;
use Filament\Actions\Exports\ExportColumn;
use Filament\Actions\Exports\Exporter;
use Filament\Actions\Exports\Models\Export;
class DeviceMasterExporter extends Exporter
{
protected static ?string $model = DeviceMaster::class;
public static function getColumns(): array
{
static $rowNumber = 0;
return [
ExportColumn::make('no')
->label('NO')
->state(function ($record) use (&$rowNumber) {
// Increment and return the row number
return ++$rowNumber;
}),
ExportColumn::make('plant.name')
->label('PLANT'),
ExportColumn::make('name')
->label('DEVICE NAME'),
ExportColumn::make('mac_address')
->label('MAC ADDRESS'),
ExportColumn::make('ip_address')
->label('IP ADDRESS'),
ExportColumn::make('created_at')
->label('CREATED AT'),
ExportColumn::make('updated_at')
->label('UPDATED AT'),
ExportColumn::make('deleted_at')
->enabledByDefault(false)
->label('DELETED AT'),
ExportColumn::make('created_by')
->label('CREATED BY'),
];
}
public static function getCompletedNotificationBody(Export $export): string
{
$body = 'Your device master export has completed and ' . number_format($export->successful_rows) . ' ' . str('row')->plural($export->successful_rows) . ' exported.';
if ($failedRowsCount = $export->getFailedRowsCount()) {
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to export.';
}
return $body;
}
}

View File

@@ -0,0 +1,140 @@
<?php
namespace App\Filament\Exports;
use App\Models\EbReading;
use Filament\Actions\Exports\ExportColumn;
use Filament\Actions\Exports\Exporter;
use Filament\Actions\Exports\Models\Export;
class EbReadingExporter extends Exporter
{
protected static ?string $model = EbReading::class;
static $rowNumber = 0;
public static function getColumns(): array
{
return [
ExportColumn::make('no')
->label('NO')
->state(function ($record) use (&$rowNumber) {
// Increment and return the row number
return ++$rowNumber;
}),
ExportColumn::make('plant.name')
->label('PLANT'),
ExportColumn::make('lcd_segment_check')
->label('LCD SEGMENT CHECK'),
ExportColumn::make('meter_serial_no')
->label('METER SERIAL NO'),
ExportColumn::make('eb_date_time')
->label('EB DATE TIME'),
ExportColumn::make('ph_seq_of_volt')
->label('PH SEQ OF VOLT'),
ExportColumn::make('ph_assoc_conn_check')
->label('PH ASSOC CONN CHECK'),
ExportColumn::make('instantaneous_ph_volt')
->label('INSTANTANEOUS PH VOLT'),
ExportColumn::make('instantaneous_curr')
->label('INSTANTANEOUS CURR'),
ExportColumn::make('instantaneous_freq')
->label('INSTANTANEOUS FREQ'),
ExportColumn::make('instantaneous_kw_with_sign')
->label('INSTANTANEOUS KW WITH SIGN'),
ExportColumn::make('instantaneous_kva')
->label('INSTANTANEOUS KVA'),
ExportColumn::make('instantaneous_kv_ar')
->label('INSTANTANEOUS KV AR'),
ExportColumn::make('instantaneous_pf_with_sign')
->label('INSTANTANEOUS PF WITH SIGN'),
ExportColumn::make('rd_with_elapsed_time_kva')
->label('RD WITH ELAPSED TIME KVA'),
ExportColumn::make('cum_active_import_energy')
->label('CUM ACTIVE IMPORT ENERGY'),
ExportColumn::make('tod1_active_energy_6_9')
->label('TOD1 ACTIVE ENERGY 6-9'),
ExportColumn::make('tod2_active_energy_18_21')
->label('TOD2 ACTIVE ENERGY 18-21'),
ExportColumn::make('tod3_active_energy_21_22')
->label('TOD3 ACTIVE ENERGY 21-22'),
ExportColumn::make('tod4_active_energy_5_6_9_18')
->label('TOD4 ACTIVE ENERGY 5-6-9-18'),
ExportColumn::make('tod5_active_energy_22_5')
->label('TOD5 ACTIVE ENERGY 22-5'),
ExportColumn::make('cum_reac_lag_energy')
->label('CUM REAC LAG ENERGY'),
ExportColumn::make('cum_reac_lead_energy')
->label('CUM REAC LEAD ENERGY'),
ExportColumn::make('cum_appar_energy')
->label('CUM APPAR ENERGY'),
ExportColumn::make('tod1_appar_energy_6_9')
->label('TOD1 APPAR ENERGY 6-9'),
ExportColumn::make('tod2_appar_energy_18_21')
->label('TOD2 APPAR ENERGY 18-21'),
ExportColumn::make('tod3_appar_energy_21_22')
->label('TOD3 APPAR ENERGY 21-22'),
ExportColumn::make('tod4_appar_energy_5_6_9_18')
->label('TOD4 APPAR ENERGY 5-6-9-18'),
ExportColumn::make('tod5_appar_energy_22_5')
->label('TOD5 APPAR ENERGY 22-5'),
ExportColumn::make('avg_pow_factor')
->label('AVG POW FACTOR'),
ExportColumn::make('avg_freq_15min_last_ip')
->label('AVG FREQ 15MIN LAST IP'),
ExportColumn::make('net_kv_arh_high')
->label('NET KV ARH HIGH'),
ExportColumn::make('net_kv_arh_low')
->label('NET KV ARH LOW'),
ExportColumn::make('cum_md_kva')
->label('CUM MD KVA'),
ExportColumn::make('present_md_kva')
->label('PRESENT MD KVA'),
ExportColumn::make('present_md_kva_date_time')
->label('PRESENT MD KVA DATE TIME'),
ExportColumn::make('tod1_md_kva_6_9')
->label('TOD1 MD KVA 6-9'),
ExportColumn::make('tod2_md_kva_18_21')
->label('TOD2 MD KVA 18-21'),
ExportColumn::make('tod3_md_kva_21_22')
->label('TOD3 MD KVA 21-22'),
ExportColumn::make('tod4_md_kva_5_6_9_18')
->label('TOD4 MD KVA 5-6-9-18'),
ExportColumn::make('tod5_md_kva_22_5')
->label('TOD5 MD KVA 22-5'),
ExportColumn::make('total_pow_off_hours')
->label('TOTAL POW OFF HOURS'),
ExportColumn::make('programming_count')
->label('PROGRAMMING COUNT'),
ExportColumn::make('last_occ_res_event_type')
->label('LAST OCC RES EVENT TYPE'),
ExportColumn::make('last_occ_res_event_date_time')
->label('LAST OCC RES EVENT DATE TIME'),
ExportColumn::make('tamper_count')
->label('TAMPER COUNT'),
ExportColumn::make('reset_count')
->label('RESET COUNT'),
ExportColumn::make('last_md_reset_date_time')
->label('LAST MD RESET DATE TIME'),
ExportColumn::make('electrician_sign')
->label('ELECTRICIAN SIGN'),
ExportColumn::make('created_at')
->label('CREATED AT'),
ExportColumn::make('updated_at')
->label('UPDATED AT'),
ExportColumn::make('deleted_at')
->enabledByDefault(false),
ExportColumn::make('updated_by')
->label('UPDATED BY'),
];
}
public static function getCompletedNotificationBody(Export $export): string
{
$body = 'Your eb reading export has completed and ' . number_format($export->successful_rows) . ' ' . str('row')->plural($export->successful_rows) . ' exported.';
if ($failedRowsCount = $export->getFailedRowsCount()) {
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to export.';
}
return $body;
}
}

View File

@@ -0,0 +1,74 @@
<?php
namespace App\Filament\Exports;
use App\Models\EquipmentMaster;
use Filament\Actions\Exports\ExportColumn;
use Filament\Actions\Exports\Exporter;
use Filament\Actions\Exports\Models\Export;
class EquipmentMasterExporter extends Exporter
{
protected static ?string $model = EquipmentMaster::class;
public static function getColumns(): array
{
static $rowNumber = 0;
return [
ExportColumn::make('no')
->label('NO')
->state(function ($record) use (&$rowNumber) {
// Increment and return the row number
return ++$rowNumber;
}),
ExportColumn::make('plant.name')
->label('PLANT'),
ExportColumn::make('machine.name')
->label('MACHINE NAME'),
ExportColumn::make('name')
->label('NAME'),
ExportColumn::make('description')
->label('DESCRIPTION'),
ExportColumn::make('make')
->label('MAKE'),
ExportColumn::make('model')
->label('MODEL'),
ExportColumn::make('equipment_number')
->label('EQUIPMENT NUMBER'),
ExportColumn::make('instrument_serial_number')
->label('INSTRUMENT SERIAL NUMBER'),
ExportColumn::make('calibrated_on')
->label('CALIBRATED ON'),
ExportColumn::make('frequency')
->label('FREQUENCY'),
ExportColumn::make('next_calibration_date')
->label('NEXT CALIBRATION DATE'),
ExportColumn::make('calibrated_by')
->label('CALIBRATED BY'),
ExportColumn::make('calibration_certificate')
->label('CALIBRATION CERTIFICATE'),
ExportColumn::make('created_at')
->label('CREATED AT'),
ExportColumn::make('updated_at')
->label('UPDATED AT'),
ExportColumn::make('created_by')
->label('CREATED BY'),
ExportColumn::make('updated_by')
->label('UPDATED BY'),
ExportColumn::make('deleted_at')
->label('DELETED AT')
->enabledByDefault(false),
];
}
public static function getCompletedNotificationBody(Export $export): string
{
$body = 'Your equipment master export has completed and ' . number_format($export->successful_rows) . ' ' . str('row')->plural($export->successful_rows) . ' exported.';
if ($failedRowsCount = $export->getFailedRowsCount()) {
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to export.';
}
return $body;
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace App\Filament\Exports;
use App\Models\GrMaster;
use Filament\Actions\Exports\ExportColumn;
use Filament\Actions\Exports\Exporter;
use Filament\Actions\Exports\Models\Export;
class GrMasterExporter extends Exporter
{
protected static ?string $model = GrMaster::class;
public static function getColumns(): array
{
static $rowNumber = 0;
return [
ExportColumn::make('no')
->label('NO')
->state(function ($record) use (&$rowNumber) {
// Increment and return the row number
return ++$rowNumber;
}),
ExportColumn::make('plant.name')
->label('PLANT'),
ExportColumn::make('item.code')
->label('ITEM'),
ExportColumn::make('serial_number')
->label('SERIAL NUMBER'),
ExportColumn::make('gr_number')
->label('GR NUMBER'),
ExportColumn::make('status')
->label('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_by')
->label('UPDATED BY'),
ExportColumn::make('deleted_at')
->label('DELETED AT')
->enabledByDefault(false),
];
}
public static function getCompletedNotificationBody(Export $export): string
{
$body = 'Your gr master export has completed and ' . number_format($export->successful_rows) . ' ' . str('row')->plural($export->successful_rows) . ' exported.';
if ($failedRowsCount = $export->getFailedRowsCount()) {
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to export.';
}
return $body;
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace App\Filament\Exports;
use App\Models\InvoiceDataValidation;
use Filament\Actions\Exports\ExportColumn;
use Filament\Actions\Exports\Exporter;
use Filament\Actions\Exports\Models\Export;
class InvoiceDataValidationExporter extends Exporter
{
protected static ?string $model = InvoiceDataValidation::class;
public static function getColumns(): array
{
static $rowNumber = 0;
return [
ExportColumn::make('no')
->label('NO')
->state(function ($record) use (&$rowNumber) {
// Increment and return the row number
return ++$rowNumber;
}),
ExportColumn::make('plant.code')
->label('PLANT'),
ExportColumn::make('distribution_channel_desc')
->label('DISTRIBUTION CHANNEL DESC'),
ExportColumn::make('customer_code')
->label('CUSTOMER CODE'),
ExportColumn::make('document_number')
->label('DOCUMENT NUMBER'),
ExportColumn::make('document_date')
->label('DOCUMENT DATE'),
ExportColumn::make('customer_trade_name')
->label('CUSTOMER TRADE NAME'),
ExportColumn::make('customer_location')
->label('CUSTOMER LOCATION'),
ExportColumn::make('location')
->label('LOCATION'),
ExportColumn::make('created_at')
->label('CREATED AT'),
ExportColumn::make('updated_at')
->label('UPDATED AT'),
ExportColumn::make('created_by')
->label('CREATED BY'),
ExportColumn::make('updated_by')
->label('UPDATED BY'),
ExportColumn::make('deleted_at')
->enabledByDefault(false)
->label('DELETED AT'),
];
}
public static function getCompletedNotificationBody(Export $export): string
{
$body = 'Your invoice data validation export has completed and ' . number_format($export->successful_rows) . ' ' . str('row')->plural($export->successful_rows) . ' exported.';
if ($failedRowsCount = $export->getFailedRowsCount()) {
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to export.';
}
return $body;
}
}

View File

@@ -0,0 +1,56 @@
<?php
namespace App\Filament\Exports;
use App\Models\InvoiceOutValidation;
use Filament\Actions\Exports\ExportColumn;
use Filament\Actions\Exports\Exporter;
use Filament\Actions\Exports\Models\Export;
class InvoiceOutValidationExporter extends Exporter
{
protected static ?string $model = InvoiceOutValidation::class;
public static function getColumns(): array
{
static $rowNumber = 0;
return [
ExportColumn::make('no')
->label('NO')
->state(function ($record) use (&$rowNumber) {
// Increment and return the row number
return ++$rowNumber;
}),
ExportColumn::make('plant.code')
->label('PLANT'),
ExportColumn::make('qr_code')
->label('QR CODE'),
ExportColumn::make('scanned_at')
->label('SCANNED AT'),
ExportColumn::make('scanned_by')
->label('SCANNED BY'),
ExportColumn::make('created_at')
->label('CREATED AT'),
ExportColumn::make('updated_at')
->label('UPDATED AT'),
ExportColumn::make('created_by')
->label('CREATED BY'),
ExportColumn::make('updated_by')
->label('UPDATED BY'),
ExportColumn::make('deleted_at')
->enabledByDefault(false)
->label('DELETED AT'),
];
}
public static function getCompletedNotificationBody(Export $export): string
{
$body = 'Your invoice out validation export has completed and ' . number_format($export->successful_rows) . ' ' . str('row')->plural($export->successful_rows) . ' exported.';
if ($failedRowsCount = $export->getFailedRowsCount()) {
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to export.';
}
return $body;
}
}

View File

@@ -30,8 +30,48 @@ class LineExporter extends Exporter
->label('NAME'),
ExportColumn::make('type')
->label('TYPE'),
ExportColumn::make('group_work_center')
->label('GROUP WORK CENTER'),
ExportColumn::make('no_of_operation')
->label('NO OF OPERATION'),
ExportColumn::make('workGroup1.name')
->label('WORK GROUP CENTER 1'),
ExportColumn::make('workGroup1.operation_number')
->label('OPERATION NUMBER 1'),
ExportColumn::make('workGroup2.name')
->label('WORK GROUP CENTER 2'),
ExportColumn::make('workGroup2.operation_number')
->label('OPERATION NUMBER 2'),
ExportColumn::make('workGroup3.name')
->label('WORK GROUP CENTER 3'),
ExportColumn::make('workGroup3.operation_number')
->label('OPERATION NUMBER 3'),
ExportColumn::make('workGroup4.name')
->label('WORK GROUP CENTER 4'),
ExportColumn::make('workGroup4.operation_number')
->label('OPERATION NUMBER 4'),
ExportColumn::make('workGroup5.name')
->label('WORK GROUP CENTER 5'),
ExportColumn::make('workGroup5.operation_number')
->label('OPERATION NUMBER 5'),
ExportColumn::make('workGroup6.name')
->label('WORK GROUP CENTER 6'),
ExportColumn::make('workGroup6.operation_number')
->label('OPERATION NUMBER 6'),
ExportColumn::make('workGroup7.name')
->label('WORK GROUP CENTER 7'),
ExportColumn::make('workGroup7.operation_number')
->label('OPERATION NUMBER 7'),
ExportColumn::make('workGroup8.name')
->label('WORK GROUP CENTER 8'),
ExportColumn::make('workGroup8.operation_number')
->label('OPERATION NUMBER 8'),
ExportColumn::make('workGroup9.name')
->label('WORK GROUP CENTER 9'),
ExportColumn::make('workGroup9.operation_number')
->label('OPERATION NUMBER 9'),
ExportColumn::make('workGroup10.name')
->label('WORK GROUP CENTER 10'),
ExportColumn::make('workGroup10.operation_number')
->label('OPERATION NUMBER 10'),
ExportColumn::make('created_at')
->label('CREATED AT'),
ExportColumn::make('updated_at')

View File

@@ -30,6 +30,8 @@ class MachineExporter extends Exporter
->label('MACHINE'),
ExportColumn::make('work_center')
->label('WORK CENTER'),
ExportColumn::make('workGroupMaster.name')
->label('WORK GROUP CENTER'),
ExportColumn::make('created_at')
->label('CREATED AT'),
ExportColumn::make('updated_at')

View File

@@ -0,0 +1,54 @@
<?php
namespace App\Filament\Exports;
use App\Models\MfmMeter;
use Filament\Actions\Exports\ExportColumn;
use Filament\Actions\Exports\Exporter;
use Filament\Actions\Exports\Models\Export;
class MfmMeterExporter extends Exporter
{
protected static ?string $model = MfmMeter::class;
public static function getColumns(): array
{
static $rowNumber = 0;
return [
ExportColumn::make('no')
->label('NO')
->state(function ($record) use (&$rowNumber) {
// Increment and return the row number
return ++$rowNumber;
}),
ExportColumn::make('plant.name')
->label('PLANT'),
ExportColumn::make('device.name')
->label('DEVICE NAME'),
ExportColumn::make('sequence')
->label('SEQUENCE'),
ExportColumn::make('name')
->label('NAME'),
ExportColumn::make('created_at')
->label('CREATED AT'),
ExportColumn::make('updated_at')
->label('UPDATED AT'),
ExportColumn::make('deleted_at')
->label('DELETED AT')
->enabledByDefault(false),
ExportColumn::make('created_by')
->label('CREATED BY'),
];
}
public static function getCompletedNotificationBody(Export $export): string
{
$body = 'Your mfm meter export has completed and ' . number_format($export->successful_rows) . ' ' . str('row')->plural($export->successful_rows) . ' exported.';
if ($failedRowsCount = $export->getFailedRowsCount()) {
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to export.';
}
return $body;
}
}

View File

@@ -13,20 +13,40 @@ class MfmParameterExporter extends Exporter
public static function getColumns(): array
{
static $rowNumber = 0;
return [
ExportColumn::make('id')
->label('ID'),
ExportColumn::make('plant.name'),
ExportColumn::make('name'),
ExportColumn::make('register_id'),
ExportColumn::make('identifier'),
ExportColumn::make('byte_to_convert'),
ExportColumn::make('type_to_convert'),
ExportColumn::make('decimal_to_display'),
ExportColumn::make('created_at'),
ExportColumn::make('updated_at'),
ExportColumn::make('deleted_at'),
ExportColumn::make('mfmMeter.name'),
ExportColumn::make('no')
->label('NO')
->state(function ($record) use (&$rowNumber) {
// Increment and return the row number
return ++$rowNumber;
}),
ExportColumn::make('plant.name')
->label('PLANT'),
ExportColumn::make('deviceName.name')
->label('Device Name'),
ExportColumn::make('name')
->label('NAME'),
ExportColumn::make('mfmMeter.name')
->label('MFM METER'),
ExportColumn::make('register_id')
->label('REGISTER ID'),
ExportColumn::make('identifier')
->label('IDENTIFIER'),
ExportColumn::make('byte_to_convert')
->label('BYTE TO CONVERT'),
ExportColumn::make('type_to_convert')
->label('TYPE TO CONVERT'),
ExportColumn::make('decimal_to_display')
->label('DECIMAL TO DISPLAY'),
ExportColumn::make('created_at')
->label('CREATED AT'),
ExportColumn::make('updated_at')
->label('UPDATED AT'),
ExportColumn::make('deleted_at')
->label('DELETED AT')
->enabledByDefault(false),
];
}

View File

@@ -22,12 +22,14 @@ class MotorTestingMasterExporter extends Exporter
// Increment and return the row number
return ++$rowNumber;
}),
ExportColumn::make('plant.name')
ExportColumn::make('plant.code')
->label('PLANT'),
ExportColumn::make('item.category')
->label('CATEGORY'),
ExportColumn::make('item.code')
->label('ITEM CODE'),
ExportColumn::make('subassembly_code')
->label('SUBASSEMBLY CODE'),
ExportColumn::make('item.description')
->label('DESCRIPTION'),
ExportColumn::make('isi_model')
@@ -69,9 +71,9 @@ class MotorTestingMasterExporter extends Exporter
ExportColumn::make('res_br_ul')
->label('RESISTANCE BR UL'),
ExportColumn::make('lock_volt_limit')
->label('LOCK VOLT Limit'),
->label('LOCK VOLT LIMIT'),
ExportColumn::make('leak_cur_limit')
->label('Leak CURRENT Limit'),
->label('LEAK CURRENT LIMIT'),
ExportColumn::make('lock_cur_ll')
->label('LOCK CURRENT LL'),
ExportColumn::make('lock_cur_ul')

View File

@@ -0,0 +1,61 @@
<?php
namespace App\Filament\Exports;
use App\Models\ProcessOrder;
use Filament\Actions\Exports\ExportColumn;
use Filament\Actions\Exports\Exporter;
use Filament\Actions\Exports\Models\Export;
class ProcessOrderExporter extends Exporter
{
protected static ?string $model = ProcessOrder::class;
public static function getColumns(): array
{
static $rowNumber = 0;
return [
ExportColumn::make('no')
->label('NO')
->state(function ($record) use (&$rowNumber) {
// Increment and return the row number
return ++$rowNumber;
}),
ExportColumn::make('plant.name')
->label('PLANT NAME'),
ExportColumn::make('item.code')
->label('ITEM CODE'),
ExportColumn::make('process_order')
->label('PROCESS ORDER'),
ExportColumn::make('coil_number')
->label('COIL NUMBER'),
ExportColumn::make('order_quantity')
->label('ORDER QUANTITY'),
ExportColumn::make('received_quantity')
->label('RECEIVED QUANTITY'),
ExportColumn::make('created_at')
->label('CREATED AT'),
ExportColumn::make('updated_at')
->label('UPDATED AT'),
ExportColumn::make('created_by')
->label('CREATED BY'),
ExportColumn::make('updated_by')
->label('UPDATED BY'),
ExportColumn::make('deleted_at')
->enabledByDefault(false)
->label('DELETED AT'),
];
}
public static function getCompletedNotificationBody(Export $export): string
{
$body = 'Your process order export has completed and ' . number_format($export->successful_rows) . ' ' . str('row')->plural($export->successful_rows) . ' exported.';
if ($failedRowsCount = $export->getFailedRowsCount()) {
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to export.';
}
return $body;
}
}

View File

@@ -0,0 +1,78 @@
<?php
namespace App\Filament\Exports;
use App\Models\SerialValidation;
use Filament\Actions\Exports\ExportColumn;
use Filament\Actions\Exports\Exporter;
use Filament\Actions\Exports\Models\Export;
class SerialValidationExporter extends Exporter
{
protected static ?string $model = SerialValidation::class;
public static function getColumns(): array
{
static $rowNumber = 0;
return [
ExportColumn::make('no')
->label('NO')
->state(function ($record) use (&$rowNumber) {
// Increment and return the row number
return ++$rowNumber;
}),
ExportColumn::make('plant.name')
->label('PLANT'),
ExportColumn::make('invoice_number')
->label('INVOICE NUMBER'),
ExportColumn::make('serial_number')
->label('SERIAL NUMBER'),
ExportColumn::make('stickerMaster.item.code')
->label('ITEM CODE'),
ExportColumn::make('motor_scanned_status')
->label('MOTOR SCANNED STATUS'),
ExportColumn::make('pump_scanned_status')
->label('PUMP SCANNED STATUS'),
ExportColumn::make('scanned_status_set')
->label('PUMPSET SCANNED STATUS'),
ExportColumn::make('capacitor_scanned_status')
->label('CAPACITOR SCANNED STATUS'),
ExportColumn::make('scanned_status')
->label('SCANNED STATUS'),
ExportColumn::make('panel_box_supplier')
->label('PANEL BOX SUPPLIER'),
ExportColumn::make('panel_box_serial_number')
->label('PANEL BOX SERIAL NUMBER'),
ExportColumn::make('load_rate')
->label('LOAD RATE'),
ExportColumn::make('upload_status')
->label('UPLOAD STATUS'),
ExportColumn::make('batch_number')
->label('BATCH NUMBER'),
ExportColumn::make('quantity')
->label('QUANTITY'),
ExportColumn::make('operator_id')
->label('OPERATOR ID'),
ExportColumn::make('created_at')
->label('CREATED AT'),
//->dateTimeFormat('d-m-Y H:i:s'),
ExportColumn::make('updated_at')
->label('UPDATED AT'),
//->dateTimeFormat('d-m-Y H:i:s'),
ExportColumn::make('deleted_at')
->enabledByDefault(false)
->label('DELETED AT'),
];
}
public static function getCompletedNotificationBody(Export $export): string
{
$body = 'Your serial validation export has completed and ' . number_format($export->successful_rows) . ' ' . str('row')->plural($export->successful_rows) . ' exported.';
if ($failedRowsCount = $export->getFailedRowsCount()) {
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to export.';
}
return $body;
}
}

View File

@@ -25,7 +25,7 @@ class StickerMasterExporter extends Exporter
return ++$rowNumber;
}),
ExportColumn::make('plant.name')
->label('PLANT'),
->label('PLANT NAME'),
ExportColumn::make('item.code')
->label('ITEM CODE'),
ExportColumn::make('serial_number_motor')

View File

@@ -30,23 +30,25 @@ class TestingPanelReadingExporter extends Exporter
->label('LINE'),
ExportColumn::make('machine.name')
->label('MACHINE'),
ExportColumn::make('item.code')
ExportColumn::make('motorTestingMaster.item.code')
->label('ITEM CODE'),
ExportColumn::make('item.description')
ExportColumn::make('motorTestingMaster.item.description')
->label('MODEL'),
ExportColumn::make('output')
->label('OUTPUT'),
ExportColumn::make('serial_number')
->label('SERIAL NUMBER'),
ExportColumn::make('item.kw')
ExportColumn::make('winded_serial_number')
->label('WINDED SERIAL NUMBER'),
ExportColumn::make('motorTestingMaster.kw')
->label('KW'),
ExportColumn::make('item.hp')
ExportColumn::make('motorTestingMaster.hp')
->label('HP'),
ExportColumn::make('item.phase')
ExportColumn::make('motorTestingMaster.phase')
->label('PHASE'),
ExportColumn::make('item.connection')
ExportColumn::make('motorTestingMaster.connection')
->label('CONNECTION'),
ExportColumn::make('item.isi_model')
ExportColumn::make('motorTestingMaster.isi_model')
->label('ISI MODEL'),
ExportColumn::make('before_fr_volt')
->label('BEFORE FR VOLT'),

View File

@@ -0,0 +1,61 @@
<?php
namespace App\Filament\Exports;
use App\Models\User;
use Filament\Actions\Exports\ExportColumn;
use Filament\Actions\Exports\Exporter;
use Filament\Actions\Exports\Models\Export;
class UserExporter extends Exporter
{
protected static ?string $model = User::class;
public static function getColumns(): array
{
static $rowNumber = 0;
return [
// ExportColumn::make('id')
// ->label('ID'),
ExportColumn::make('no')
->label('NO')
->state(function ($record) use (&$rowNumber) {
// Increment and return the row number
return ++$rowNumber;
}),
ExportColumn::make('plant.code')
->label('PLANT CODE'),
ExportColumn::make('name')
->label('NAME'),
ExportColumn::make('email')
->label('E-MAIL'),
ExportColumn::make('password')
->label('PASSWORD'),
ExportColumn::make('roles')
->label('ROLES')
->state(function ($record) {
// Assuming Spatie\Permission: roles() relationship
return $record->roles->pluck('name')->join(', ');
}),
ExportColumn::make('created_at')
->label('CREATED AT'),
ExportColumn::make('updated_at')
->label('UPDATED AT'),
ExportColumn::make('deleted_at')
->enabledByDefault(false)
->label('DELETED AT'),
];
}
public static function getCompletedNotificationBody(Export $export): string
{
$body = 'Your user export has completed and ' . number_format($export->successful_rows) . ' ' . str('row')->plural($export->successful_rows) . ' exported.';
if ($failedRowsCount = $export->getFailedRowsCount()) {
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to export.';
}
return $body;
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace App\Filament\Exports;
use App\Models\WorkGroupMaster;
use Filament\Actions\Exports\ExportColumn;
use Filament\Actions\Exports\Exporter;
use Filament\Actions\Exports\Models\Export;
class WorkGroupMasterExporter extends Exporter
{
protected static ?string $model = WorkGroupMaster::class;
public static function getColumns(): array
{
static $rowNumber = 0;
return [
ExportColumn::make('no')
->label('NO')
->state(function ($record) use (&$rowNumber) {
// Increment and return the row number
return ++$rowNumber;
}),
ExportColumn::make('plant.name')
->label('PLANT'),
ExportColumn::make('name')
->label('NAME'),
ExportColumn::make('description')
->label('DESCRIPTION'),
ExportColumn::make('operation_number')
->label('OPERATION NUMBER'),
ExportColumn::make('created_by')
->label('CREATED BY'),
ExportColumn::make('created_at')
->label('CREATED AT'),
ExportColumn::make('updated_at')
->label('UPDATED AT'),
ExportColumn::make('deleted_at')
->label('DELETED AT')
->enabledByDefault(false),
];
}
public static function getCompletedNotificationBody(Export $export): string
{
$body = 'Your work group master export has completed and ' . number_format($export->successful_rows) . ' ' . str('row')->plural($export->successful_rows) . ' exported.';
if ($failedRowsCount = $export->getFailedRowsCount()) {
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to export.';
}
return $body;
}
}

View File

@@ -41,15 +41,15 @@ class ConfigurationImporter extends Importer
ImportColumn::make('line')
->requiredMapping()
->relationship(resolveUsing: 'name')
->exampleHeader('Plant')
->exampleHeader('Line')
->example(['4 inch pump line'])
->label('Line')
->rules(['required']),
ImportColumn::make('plant')
->requiredMapping()
->relationship(resolveUsing: 'name')
->relationship(resolveUsing: 'code')
->exampleHeader('Plant')
->example(['Ransar Industries-I'])
->example(['1000'])
->label('Plant')
->rules(['required']),
];

View File

@@ -0,0 +1,69 @@
<?php
namespace App\Filament\Imports;
use App\Models\DeviceMaster;
use Filament\Actions\Imports\ImportColumn;
use Filament\Actions\Imports\Importer;
use Filament\Actions\Imports\Models\Import;
class DeviceMasterImporter extends Importer
{
protected static ?string $model = DeviceMaster::class;
public static function getColumns(): array
{
return [
ImportColumn::make('plant')
->requiredMapping()
->exampleHeader('Plant Name')
->example('Ransar Industries-I')
->label('Plant Name')
->relationship(resolveUsing:'name')
->rules(['required']),
ImportColumn::make('name')
->requiredMapping()
->exampleHeader('Device Name')
->label('Device Name')
->rules(['required']),
ImportColumn::make('mac_address')
->requiredMapping()
->exampleHeader('MAC Address')
->example('00:1A:2B:3C:4D:5E')
->label('MAC Address')
->rules(['required', 'mac_address']),
ImportColumn::make('ip_address')
->requiredMapping()
->exampleHeader('IP Address')
->label('IP Address')
->rules(['required', 'ip']),
ImportColumn::make('created_by')
->requiredMapping()
->exampleHeader('Created By')
->example('Admin')
->label('Created By')
->rules(['required']),
];
}
public function resolveRecord(): ?DeviceMaster
{
// return DeviceMaster::firstOrNew([
// // Update existing records, matching them by `$this->data['column_name']`
// 'email' => $this->data['email'],
// ]);
return new DeviceMaster();
}
public static function getCompletedNotificationBody(Import $import): string
{
$body = 'Your device master import has completed and ' . number_format($import->successful_rows) . ' ' . str('row')->plural($import->successful_rows) . ' imported.';
if ($failedRowsCount = $import->getFailedRowsCount()) {
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to import.';
}
return $body;
}
}

View File

@@ -0,0 +1,243 @@
<?php
namespace App\Filament\Imports;
use App\Models\EbReading;
use Filament\Actions\Imports\ImportColumn;
use Filament\Actions\Imports\Importer;
use Filament\Actions\Imports\Models\Import;
class EbReadingImporter extends Importer
{
protected static ?string $model = EbReading::class;
public static function getColumns(): array
{
return [
ImportColumn::make('plant')
->requiredMapping()
->exampleHeader('Plant Name')
->example('Ransar Industries-I')
->label('Plant Name')
->relationship(resolveUsing:'name')
->rules(['required']),
ImportColumn::make('lcd_segment_check')
->label('LCD Segment Check')
->example('Ok')
->exampleHeader('LCD Segment Check'),
ImportColumn::make('meter_serial_no')
->label('Meter Serial No')
->example('572880')
->exampleHeader('Meter Serial No'),
ImportColumn::make('eb_date_time')
->label('EB Date Time')
->example('2025-08-05 08:32:58')
->exampleHeader('EB Date Time')
->requiredMapping()
->rules(['required', 'datetime']),
ImportColumn::make('ph_seq_of_volt')
->label('Phase Sequence of Volt')
->example('RYB')
->exampleHeader('Phase Sequence of Volt'),
ImportColumn::make('ph_assoc_conn_check')
->example('GOOD')
->exampleHeader('Phase Associated Connection Check')
->label('Phase Associated Connection Check'),
ImportColumn::make('instantaneous_ph_volt')
->exampleHeader('Instantaneous Phase Volt')
->example('64.35,64.91,64.93')
->label('Instantaneous Phase Volt'),
ImportColumn::make('instantaneous_curr')
->exampleHeader('Instantaneous Current')
->example('1.02,1.00,0.94')
->label('Instantaneous Current'),
ImportColumn::make('instantaneous_freq')
->exampleHeader('Instantaneous Frequency')
->example('50.07')
->label('Instantaneous Frequency'),
ImportColumn::make('instantaneous_kw_with_sign')
->exampleHeader('Instantaneous KW with Sign')
->example('0.176')
->label('Instantaneous KW with Sign'),
ImportColumn::make('instantaneous_kva')
->exampleHeader('Instantaneous KVA')
->example('0.176')
->label('Instantaneous KVA'),
ImportColumn::make('instantaneous_kv_ar')
->exampleHeader('Instantaneous KV AR')
->example('0.02')
->label('Instantaneous KV AR'),
ImportColumn::make('instantaneous_pf_with_sign')
->exampleHeader('Instantaneous PF with Sign')
->example('0.99')
->label('Instantaneous PF with Sign'),
ImportColumn::make('rd_with_elapsed_time_kva')
->exampleHeader('RD with Elapsed Time KVA')
->example('0.047')
->label('RD with Elapsed Time KVA'),
ImportColumn::make('cum_active_import_energy')
->exampleHeader('Cumulative Active Import Energy')
->example('13246.46')
->label('Cumulative Active Import Energy'),
ImportColumn::make('tod1_active_energy_6_9')
->exampleHeader('TOD1 Active Energy 6-9')
->example('1367.75')
->label('TOD1 Active Energy 6-9'),
ImportColumn::make('tod2_active_energy_18_21')
->exampleHeader('TOD2 Active Energy 18-21')
->example('1759.08')
->label('TOD2 Active Energy 18-21'),
ImportColumn::make('tod3_active_energy_21_22')
->exampleHeader('TOD3 Active Energy 21-22')
->example('457.67')
->label('TOD3 Active Energy 21-22'),
ImportColumn::make('tod4_active_energy_5_6_9_18')
->exampleHeader('TOD4 Active Energy 5-6-9-18')
->example('6253.85')
->label('TOD4 Active Energy 5-6-9-18'),
ImportColumn::make('tod5_active_energy_22_5')
->exampleHeader('TOD5 Active Energy 22-5')
->example('3408.11')
->label('TOD5 Active Energy 22-5'),
ImportColumn::make('cum_reac_lag_energy')
->exampleHeader('Cumulative Reactive Lag Energy')
->example('685.11')
->label('Cumulative Reactive Lag Energy'),
ImportColumn::make('cum_reac_lead_energy')
->exampleHeader('Cumulative Reactive Lead Energy')
->example('426.1')
->label('Cumulative Reactive Lead Energy'),
ImportColumn::make('cum_appar_energy')
->exampleHeader('Cumulative Apparent Energy')
->example('13306.57')
->label('Cumulative Apparent Energy'),
ImportColumn::make('tod1_appar_energy_6_9')
->exampleHeader('TOD1 Apparent Energy 6-9')
->example('1374.63')
->label('TOD1 Apparent Energy 6-9'),
ImportColumn::make('tod2_appar_energy_18_21')
->exampleHeader('TOD2 Apparent Energy 18-21')
->example('1766.61')
->label('TOD2 Apparent Energy 18-21'),
ImportColumn::make('tod3_appar_energy_21_22')
->exampleHeader('TOD3 Apparent Energy 21-22')
->example('459.47')
->label('TOD3 Apparent Energy 21-22'),
ImportColumn::make('tod4_appar_energy_5_6_9_18')
->exampleHeader('TOD4 Apparent Energy 5-6-9-18')
->example('6283.28')
->label('TOD4 Apparent Energy 5-6-9-18'),
ImportColumn::make('tod5_appar_energy_22_5')
->exampleHeader('TOD5 Apparent Energy 22-5')
->example('3422.56')
->label('TOD5 Apparent Energy 22-5'),
ImportColumn::make('avg_pow_factor')
->exampleHeader('Average Power Factor')
->example('0.98')
->label('Average Power Factor'),
ImportColumn::make('avg_freq_15min_last_ip')
->exampleHeader('Average Frequency 15min Last IP')
->example('50')
->label('Average Frequency 15min Last IP'),
ImportColumn::make('net_kv_arh_high')
->exampleHeader('Net KV ARH High')
->example('2.99')
->label('Net KV ARH High'),
ImportColumn::make('net_kv_arh_low')
->exampleHeader('Net KV ARH Low')
->example('143.14')
->label('Net KV ARH Low'),
ImportColumn::make('cum_md_kva')
->exampleHeader('Cumulative MD KVA')
->example('43.816')
->label('Cumulative MD KVA'),
ImportColumn::make('present_md_kva')
->exampleHeader('Present MD KVA')
->example('0.379')
->label('Present MD KVA'),
ImportColumn::make('present_md_kva_date_time')
->label('Present MD KVA Date Time')
->exampleHeader('Present MD KVA Date Time')
->example('2025-08-05 08:32:58')
->requiredMapping()
->rules(['required', 'datetime']),
ImportColumn::make('tod1_md_kva_6_9')
->exampleHeader('TOD1 MD KVA 6-9')
->example('0.282')
->label('TOD1 MD KVA 6-9'),
ImportColumn::make('tod2_md_kva_18_21')
->exampleHeader('TOD2 MD KVA 18-21')
->example('0.268')
->label('TOD2 MD KVA 18-21'),
ImportColumn::make('tod3_md_kva_21_22')
->exampleHeader('TOD3 MD KVA 21-22')
->example('0')
->label('TOD3 MD KVA 21-22'),
ImportColumn::make('tod4_md_kva_5_6_9_18')
->exampleHeader('TOD4 MD KVA 5-6-9-18')
->example('0.379')
->label('TOD4 MD KVA 5-6-9-18'),
ImportColumn::make('tod5_md_kva_22_5')
->exampleHeader('TOD5 MD KVA 22-5')
->example('0.379')
->label('TOD5 MD KVA 22-5'),
ImportColumn::make('total_pow_off_hours')
->exampleHeader('Total Power Off Hours')
->example('6480.56')
->label('Total Power Off Hours'),
ImportColumn::make('programming_count')
->exampleHeader('Programming Count')
->example('3')
->label('Programming Count'),
ImportColumn::make('last_occ_res_event_type')
->exampleHeader('Last Occurrence/Reset Event Type')
->example('-')
->label('Last Occurrence/Reset Event Type'),
ImportColumn::make('last_occ_res_event_date_time')
->label('Last Occurrence/Reset Event Date Time')
->example('2025-08-05 08:32:58')
->exampleHeader('Last Occurrence/Reset Event Date Time')
->requiredMapping()
->rules(['required', 'datetime']),
ImportColumn::make('tamper_count')
->exampleHeader('Tamper Count')
->example('24')
->label('Tamper Count'),
ImportColumn::make('reset_count')
->exampleHeader('Reset Count')
->example('108')
->label('Reset Count'),
ImportColumn::make('last_md_reset_date_time')
->exampleHeader('Last MD Reset Date Time')
->example('2025-08-05 08:32:58')
->label('Last MD Reset Date Time')
->requiredMapping()
->rules(['required', 'datetime']),
ImportColumn::make('electrician_sign')
->exampleHeader('Electrician Sign')
->example('Admin')
->label('Electrician Sign'),
];
}
public function resolveRecord(): ?EbReading
{
// return EbReading::firstOrNew([
// // Update existing records, matching them by `$this->data['column_name']`
// 'email' => $this->data['email'],
// ]);
return new EbReading();
}
public static function getCompletedNotificationBody(Import $import): string
{
$body = 'Your eb reading import has completed and ' . number_format($import->successful_rows) . ' ' . str('row')->plural($import->successful_rows) . ' imported.';
if ($failedRowsCount = $import->getFailedRowsCount()) {
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to import.';
}
return $body;
}
}

View File

@@ -0,0 +1,109 @@
<?php
namespace App\Filament\Imports;
use App\Models\EquipmentMaster;
use Filament\Actions\Imports\ImportColumn;
use Filament\Actions\Imports\Importer;
use Filament\Actions\Imports\Models\Import;
class EquipmentMasterImporter extends Importer
{
protected static ?string $model = EquipmentMaster::class;
public static function getColumns(): array
{
return [
ImportColumn::make('plant')
->requiredMapping()
->exampleHeader('Plant Name')
->example('Ransar Industries-I')
->label('Plant Name')
->relationship(resolveUsing:'name')
->rules(['required']),
ImportColumn::make('machine')
->requiredMapping()
->exampleHeader('Machine Name')
->example('1006378')
->label('Machine Name')
->relationship(resolveUsing:'name')
->rules(['required']),
ImportColumn::make('name')
->label('Name')
->exampleHeader('Name')
->example('463605 E-E-078'),
ImportColumn::make('description')
->label('Description')
->exampleHeader('Description')
->example('FIN.6INCH.HOUSING LOWER 150R3+ CI RUN-OUT CHECKING FIXTURE'),
ImportColumn::make('make')
->label('Make')
->exampleHeader('Make')
->example('Ok'),
ImportColumn::make('model')
->label('Model')
->exampleHeader('Model')
->example('Ok'),
ImportColumn::make('equipment_number')
->label('Equipment Number')
->exampleHeader('Equipment Number')
->example('463605 E-E-078'),
ImportColumn::make('instrument_serial_number')
->label('Instrument Serial Number')
->exampleHeader('Instrument Serial Number')
->example('131548498'),
ImportColumn::make('calibrated_on')
->label('Calibrated On')
->exampleHeader('Calibrated On')
->example('01-09-2025 08:00:00')
->requiredMapping()
->rules(['required', 'datetime']),
ImportColumn::make('frequency')
->label('Frequency')
->exampleHeader('Frequency')
->example('15')
->requiredMapping()
->numeric()
->rules(['required', 'integer']),
ImportColumn::make('next_calibration_date')
->label('Next Calibration Date')
->exampleHeader('Next Calibration Date')
->requiredMapping()
->example('16-09-2025 08:00:00')
->rules(['required', 'datetime']),
ImportColumn::make('calibrated_by')
->label('Calibration By')
->example('Sri Venkateswara Tools')
->exampleHeader('Calibration By'),
ImportColumn::make('calibration_certificate')
->label('Calibration Certificate')
->example('1231CRI651')
->exampleHeader('Calibration Certificate'),
ImportColumn::make('created_by')
->label('Created By')
->example('RAS00296')
->exampleHeader('Created By'),
];
}
public function resolveRecord(): ?EquipmentMaster
{
// return EquipmentMaster::firstOrNew([
// // Update existing records, matching them by `$this->data['column_name']`
// 'email' => $this->data['email'],
// ]);
return new EquipmentMaster();
}
public static function getCompletedNotificationBody(Import $import): string
{
$body = 'Your equipment master import has completed and ' . number_format($import->successful_rows) . ' ' . str('row')->plural($import->successful_rows) . ' imported.';
if ($failedRowsCount = $import->getFailedRowsCount()) {
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to import.';
}
return $body;
}
}

View File

@@ -0,0 +1,129 @@
<?php
namespace App\Filament\Imports;
use App\Models\GrMaster;
use Filament\Actions\Imports\ImportColumn;
use Filament\Actions\Imports\Importer;
use Filament\Actions\Imports\Models\Import;
use App\Models\Plant;
use App\Models\Item;
use Str;
use Filament\Actions\Imports\Exceptions\RowImportFailedException;
use App\Models\User;
class GrMasterImporter extends Importer
{
protected static ?string $model = GrMaster::class;
public static function getColumns(): array
{
return [
ImportColumn::make('plant')
->requiredMapping()
->exampleHeader('Plant Name')
->example('Ransar Industries-I')
->label('Plant Name')
->relationship(resolveUsing:'name')
->rules(['required']),
ImportColumn::make('item')
->requiredMapping()
->exampleHeader('Item Code')
->example('630214')
->label('Item Code')
->relationship(resolveUsing:'code')
->rules(['required']),
ImportColumn::make('serial_number')
->requiredMapping()
->exampleHeader('Serial Number')
->example('11023567567567')
->label('Serial Number')
->rules(['required']),
ImportColumn::make('gr_number')
->requiredMapping()
->exampleHeader('GR Number')
->example('67345237')
->label('GR Number')
->rules(['required']),
ImportColumn::make('created_by')
->requiredMapping()
->exampleHeader('Created By')
->example('Admin')
->label('Created By')
->rules(['required']),
//ImportColumn::make('updated_by'),
];
}
public function resolveRecord(): ?GrMaster
{
// return GrMaster::firstOrNew([
// // Update existing records, matching them by `$this->data['column_name']`
// 'email' => $this->data['email'],
// ]);
$warnMsg = [];
$plant = Plant::where('name', $this->data['plant'])->first();
if (!$plant) {
$warnMsg[] = "Plant not found";
}
$item = null;
if ($plant) {
$item = Item::where('code', $this->data['item'])->where('plant_id', $plant->id)->first();
}
if (!$item) {
$warnMsg[] = "Item not found";
}
if (Str::length($this->data['serial_number']) < 9 || !ctype_alnum($this->data['serial_number'])) {
$warnMsg[] = "Invalid serial number found";
}
if (empty($this->data['gr_number'])) {
$warnMsg[] = "GR Number cannot be empty.";
}
$user = User::where('name', $this->data['created_by'])->first();
if (!$user) {
$warnMsg[] = "User not found";
}
if (!empty($warnMsg)) {
throw new RowImportFailedException(implode(', ', $warnMsg));
}
else { //if (empty($warnMsg))
$grMaster = GrMaster::where('plant_id', $plant->id)
->where('serial_number', $this->data['serial_number'])
->latest()
->first();
if ($grMaster) {
throw new RowImportFailedException("Serial number already exist!");
}
}
GrMaster::updateOrCreate([
'plant_id' => $plant->id,
'item_id' => $item->id,
'serial_number' => $this->data['serial_number'],
'gr_number' => $this->data['gr_number'] ?? null,
'created_by' => $this->data['created_by'],
]);
return null;
//return new GrMaster();
}
public static function getCompletedNotificationBody(Import $import): string
{
$body = 'Your gr master import has completed and ' . number_format($import->successful_rows) . ' ' . str('row')->plural($import->successful_rows) . ' imported.';
if ($failedRowsCount = $import->getFailedRowsCount()) {
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to import.';
}
return $body;
}
}

View File

@@ -4,6 +4,7 @@ namespace App\Filament\Imports;
use App\Models\Line;
use App\Models\Plant;
use App\Models\WorkGroupMaster;
use Filament\Actions\Imports\Exceptions\RowImportFailedException;
use Filament\Actions\Imports\ImportColumn;
use Filament\Actions\Imports\Importer;
@@ -29,11 +30,61 @@ class LineImporter extends Importer
->example('Domestic Assembly')
->label('Line Type')
->rules(['required']),
ImportColumn::make('group_work_center')
ImportColumn::make('no_of_operation')
->requiredMapping()
->exampleHeader('Group Work Center')
->example('RMGCEABC')
->label('Group Work Center'),
->exampleHeader('No of Operation')
->example('10')
->label('No of Operation'),
ImportColumn::make('work_group1_id')
->requiredMapping()
->exampleHeader('Work Group Center 1')
->example('RMGCGABC')
->label('Work Group Center 1'),
ImportColumn::make('work_group2_id')
->requiredMapping()
->exampleHeader('Work Group Center 2')
->example('RMGCGABC1')
->label('Work Group Center 2'),
ImportColumn::make('work_group3_id')
->requiredMapping()
->exampleHeader('Work Group Center 3')
->example('RMGCGABC2')
->label('Work Group Center 3'),
ImportColumn::make('work_group4_id')
->requiredMapping()
->exampleHeader('Work Group Center 4')
->example('RMGCGABC1')
->label('Work Group Center 4'),
ImportColumn::make('work_group5_id')
->requiredMapping()
->exampleHeader('Work Group Center 5')
->example('RMGCGABC5')
->label('Work Group Center 5'),
ImportColumn::make('work_group6_id')
->requiredMapping()
->exampleHeader('Work Group Center 6')
->example('RMGCGABC6')
->label('Work Group Center 6'),
ImportColumn::make('work_group7_id')
->requiredMapping()
->exampleHeader('Work Group Center 7')
->example('RMGCGABC7')
->label('Work Group Center 7'),
ImportColumn::make('work_group8_id')
->requiredMapping()
->exampleHeader('Work Group Center 8')
->example('RMGCGABC8')
->label('Work Group Center 8'),
ImportColumn::make('work_group9_id')
->requiredMapping()
->exampleHeader('Work Group Center 9')
->example('RMGCGABC9')
->label('Work Group Center 9'),
ImportColumn::make('work_group10_id')
->requiredMapping()
->exampleHeader('Work Group Center 10')
->example('RMGCGABC10')
->label('Work Group Center 10'),
ImportColumn::make('plant')
->requiredMapping()
->exampleHeader('Plant Name')
@@ -47,34 +98,110 @@ class LineImporter extends Importer
public function resolveRecord(): ?Line
{
$warnMsg = [];
$plant = Plant::where('name', $this->data['plant'])->first();
if (!$plant) {
$warnMsg[] = "Plant '" . $this->data['plant'] . "' not found";
throw new RowImportFailedException("Plant '{$this->data['plant']}' not found");
}
if (Str::length($this->data['name']) < 0) {
$warnMsg[] = "Line name not found";
if (Str::length($this->data['name'] ?? '') <= 0) {
throw new RowImportFailedException("Line name not found");
}
if (Str::length($this->data['type']) < 0) {
$warnMsg[] = "Line type not found";
if (Str::length($this->data['type'] ?? '') <= 0) {
throw new RowImportFailedException("Line type not found");
}
if (!empty($warnMsg)) {
$noOfOps = (int) ($this->data['no_of_operation'] ?? 0);
if (($noOfOps == null || $noOfOps == '' || !is_numeric($noOfOps)) && $noOfOps != 0) {
throw new RowImportFailedException("'No of Operation' is required and must be a number $noOfOps");
}
if ($noOfOps > 10)
{
throw new RowImportFailedException("Invalid 'No Of Operation' value: {$noOfOps}, maximum allowed is 10");
}
// Validate required work groups
$missingGroups = [];
for ($i = 1; $i <= $noOfOps; $i++) {
if (empty($this->data["work_group{$i}_id"])) {
$missingGroups[] = "work_group{$i}_id";
}
}
if (!empty($missingGroups)) {
throw new RowImportFailedException(
"Invalid data: Required work groups missing values in: " . implode(', ', $missingGroups)
);
}
// Ensure no extra work groups are filled
$invalidGroups = [];
for ($i = $noOfOps + 1; $i <= 10; $i++) {
if (!empty($this->data["work_group{$i}_id"])) {
$invalidGroups[] = "work_group{$i}_id";
}
}
if (!empty($invalidGroups)) {
throw new RowImportFailedException(
"Invalid data: Only first {$noOfOps} work groups should be filled, but values found in: " . implode(', ', $invalidGroups)
);
}
for ($i = 1; $i <= 10; $i++) {
$workGroupName = $this->data["work_group{$i}_id"] ?? null;
if (!$workGroupName) {
continue;
}
$workGroupRecord = WorkGroupMaster::where('name', $workGroupName)
->where('plant_id', $plant->id)
->first();
if (!$workGroupRecord) {
throw new RowImportFailedException("Work group '{$workGroupName}' not found in plant '{$this->data['plant']}'");
}
$existsInLines = Line::where('plant_id', $plant->id)
->where('name', '!=', $this->data['name'])
->where("work_group{$i}_id", $workGroupRecord->id)
->first();
if ($existsInLines) {
$warnMsg[] = "Work group '{$workGroupName}' is already assigned to another line in plant '{$this->data['plant']}'";
}
$this->data["work_group{$i}_id"] = $workGroupRecord->id;
}
if (!empty($warnMsg))
{
throw new RowImportFailedException(implode(', ', $warnMsg));
}
return Line::updateOrCreate([
Line::updateOrCreate(
[
'name' => $this->data['name'],
'plant_id' => $plant->id
],
[
'type' => $this->data['type'],
'group_work_center' => $this->data['group_work_center']
'no_of_operation' => $noOfOps,
'work_group1_id' => $this->data['work_group1_id'] ?? null,
'work_group2_id' => $this->data['work_group2_id'] ?? null,
'work_group3_id' => $this->data['work_group3_id'] ?? null,
'work_group4_id' => $this->data['work_group4_id'] ?? null,
'work_group5_id' => $this->data['work_group5_id'] ?? null,
'work_group6_id' => $this->data['work_group6_id'] ?? null,
'work_group7_id' => $this->data['work_group7_id'] ?? null,
'work_group8_id' => $this->data['work_group8_id'] ?? null,
'work_group9_id' => $this->data['work_group9_id'] ?? null,
'work_group10_id' => $this->data['work_group10_id'] ?? null,
]
);
// return Line::firstOrNew([
// // Update existing records, matching them by `$this->data['column_name']`
// 'email' => $this->data['email'],
// ]);
// return new Line();
return null;
}
public static function getCompletedNotificationBody(Import $import): string

View File

@@ -35,7 +35,7 @@ class LineStopImporter extends Importer
public function resolveRecord(): ?LineStop
{
$warnMsg = [];
if (Str::length($this->data['code']) < 6 || !ctype_alnum($this->data['code'])) {
if (Str::length($this->data['code']) < 3 || !ctype_alnum($this->data['code'])) {
$warnMsg[] = "Invalid line stop code found";
}
if (Str::length($this->data['reason']) < 5) {

View File

@@ -5,6 +5,7 @@ namespace App\Filament\Imports;
use App\Models\Line;
use App\Models\Machine;
use App\Models\Plant;
use App\Models\WorkGroupMaster;
use Filament\Actions\Imports\Exceptions\RowImportFailedException;
use Filament\Actions\Imports\ImportColumn;
use Filament\Actions\Imports\Importer;
@@ -28,7 +29,15 @@ class MachineImporter extends Importer
->requiredMapping()
->exampleHeader('Work Center')
->example('RMGCE001')
->label('Work Center'),
->label('Work Center')
->rules(['required']),
ImportColumn::make('workGroupMaster')
->requiredMapping()
->relationship(resolveUsing: 'name')
->exampleHeader('Work Group Center')
->example(['RMGCGABC'])
->label('Work Group Center')
->rules(['required']),
ImportColumn::make('line')
->requiredMapping()
->relationship(resolveUsing: 'name')
@@ -53,26 +62,53 @@ class MachineImporter extends Importer
$line = null;
$machine = $this->data['name'];
$workCenter = $this->data['work_center'];
$groupWorkCenter = WorkGroupMaster::where('name', $this->data['workGroupMaster'])->first();
if (!$plant) {
$warnMsg[] = "Plant not found";
$warnMsg[] = "Plant not found!";
}
else {
$groupWorkCenter = WorkGroupMaster::where('name', $this->data['workGroupMaster'])->where('plant_id', $plant->id)->first();
$line = Line::where('name', $this->data['line'])->where('plant_id', $plant->id)->first();
if ($line) {
$grpWrkCnr = $line->group_work_center;
if (!$grpWrkCnr || Str::length($grpWrkCnr) < 1)
$grpWrkCnr = $line->no_of_operation;
if (!$grpWrkCnr || $grpWrkCnr < 1)//Str::length($grpWrkCnr) < 1)
{
$warnMsg[] = "Group work center line not found";
$warnMsg[] = "Group work center line not found!";
}
else if (!$groupWorkCenter) {
$warnMsg[] = "Group work center not found!";
}
else {
$dupMachine = Machine::where('plant_id', $plant->id)->where('work_center', '!=', $workCenter)->where('name', $machine)->first();
if ($dupMachine) {
$warnMsg[] = "Duplicate machine name found!";
}
else {
$isValidGroupWork = false;
for ($i = 1; $i <= $line->no_of_operation; $i++) {
$column = "work_group{$i}_id";
if (!empty($line->$column)) {
if ($line->$column == $groupWorkCenter->id) {
$isValidGroupWork = true;
break;
}
}
}
if (!$isValidGroupWork) {
$warnMsg[] = "Group work center does not match with line!";
}
}
}
}
else
{
$warnMsg[] = "Line not found";
$warnMsg[] = "Line not found!";
}
}
if (Str::length($machine) <= 0) {
$warnMsg[] = "Machine name not found";
$warnMsg[] = "Machine name not found!";
}
if (!empty($warnMsg)) {
@@ -81,12 +117,13 @@ class MachineImporter extends Importer
Machine::updateOrCreate(
[
'name' => $machine,
'plant_id' => $plant->id,
'line_id' => $line->id
'work_center' => $workCenter
],
[
'work_center' => $workCenter
'line_id' => $line->id,
'name' => $machine,
'work_group_master_id' => $groupWorkCenter->id
]
);
return null;

View File

@@ -0,0 +1,72 @@
<?php
namespace App\Filament\Imports;
use App\Models\MfmMeter;
use Filament\Actions\Imports\ImportColumn;
use Filament\Actions\Imports\Importer;
use Filament\Actions\Imports\Models\Import;
class MfmMeterImporter extends Importer
{
protected static ?string $model = MfmMeter::class;
public static function getColumns(): array
{
return [
ImportColumn::make('plant')
->requiredMapping()
->exampleHeader('Plant Name')
->example('Ransar Industries-I')
->label('Plant Name')
->relationship(resolveUsing:'name')
->rules(['required']),
ImportColumn::make('Device Name')
->requiredMapping()
->exampleHeader('Device Name')
->example('REG001')
->label('Device Name')
->relationship(resolveUsing:'name')
->rules(['required']),
ImportColumn::make('sequence')
->requiredMapping()
->exampleHeader('Sequence')
->example('1')
->label('Sequence')
->rules(['required']),
ImportColumn::make('name')
->requiredMapping()
->exampleHeader('Meter Name')
->example('Display SSB')
->label('Meter Name')
->rules(['required']),
ImportColumn::make('created_by')
->requiredMapping()
->exampleHeader('Created By')
->example('Admin')
->label('Created By')
->rules(['required']),
];
}
public function resolveRecord(): ?MfmMeter
{
// return MfmMeter::firstOrNew([
// // Update existing records, matching them by `$this->data['column_name']`
// 'email' => $this->data['email'],
// ]);
return new MfmMeter();
}
public static function getCompletedNotificationBody(Import $import): string
{
$body = 'Your mfm meter import has completed and ' . number_format($import->successful_rows) . ' ' . str('row')->plural($import->successful_rows) . ' imported.';
if ($failedRowsCount = $import->getFailedRowsCount()) {
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to import.';
}
return $body;
}
}

View File

@@ -21,6 +21,13 @@ class MfmParameterImporter extends Importer
->label('Plant Name')
->relationship(resolveUsing:'name')
->rules(['required']),
ImportColumn::make('deviceName')
->requiredMapping()
->exampleHeader('Device Name')
->example('REG001')
->label('Device Name')
->relationship(resolveUsing:'name')
->rules(['required']),
ImportColumn::make('mfmMeter')
->requiredMapping()
->exampleHeader('Mfm Meter Sequence')

View File

@@ -2,11 +2,17 @@
namespace App\Filament\Imports;
use App\Models\Item;
use App\Models\MotorTestingMaster;
use App\Models\Plant;
use App\Models\User;
use DateTime;
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 MotorTestingMasterImporter extends Importer
{
@@ -22,7 +28,14 @@ class MotorTestingMasterImporter extends Importer
->label('Item Code')
->relationship(resolveUsing: 'code')
->rules(['required']),
ImportColumn::make('subassembly_code')
->requiredMapping()
->exampleHeader('SubAssembly Code')
->example(['123456'])
->label('SubAssembly Code')
->rules(['required']),
ImportColumn::make('isi_model')
->requiredMapping()
->boolean()
->exampleHeader('ISI Model')
->example(['Y','N','Y'])
@@ -144,8 +157,8 @@ class MotorTestingMasterImporter extends Importer
->rules(['required']),
ImportColumn::make('leak_cur_limit')
->requiredMapping()
->exampleHeader('Leakage Current Limit')
->label('Leakage Current Limit')
->exampleHeader('Leak Current Limit')
->label('Leak Current Limit')
->example(['50','50','50'])
->rules(['required']),
ImportColumn::make('lock_cur_ll')
@@ -199,9 +212,9 @@ class MotorTestingMasterImporter extends Importer
ImportColumn::make('plant')
->requiredMapping()
->exampleHeader('Plant')
->example(['Ransar Industries-I','Ransar Industries-I','Ransar Industries-I'])
->example(['1000','1010','1020'])
->label('Plant')
->relationship(resolveUsing: 'name')
->relationship(resolveUsing: 'code')
->rules(['required']),
ImportColumn::make('created_by')
->requiredMapping()
@@ -220,12 +233,245 @@ class MotorTestingMasterImporter extends Importer
public function resolveRecord(): ?MotorTestingMaster
{
// return MotorTestingMaster::firstOrNew([
// // Update existing records, matching them by `$this->data['column_name']`
// 'email' => $this->data['email'],
// ]);
$warnMsg = [];
$plantCod = trim($this->data['plant']);
$iCode = trim($this->data['item']);
$sCode = trim($this->data['subassembly_code']);
$isiModel = (trim($this->data['isi_model']) == "1") ? true : false;
$phase = trim($this->data['phase']);
$kw = trim($this->data['kw']);
$hp = trim($this->data['hp']);
$volt = trim($this->data['volt']);
$current = trim($this->data['current']);
$rpm = trim($this->data['rpm']);
$torque = trim($this->data['torque']);
$frequency = trim($this->data['frequency']);
$connection = trim($this->data['connection']);
$insResType = trim($this->data['ins_res_type']);
$insResLimit = trim($this->data['ins_res_limit']);
$routineTestTime = trim($this->data['routine_test_time']);
$resRyLl = trim($this->data['res_ry_ll']);
$resRyUl = trim($this->data['res_ry_ul']);
$resYbLl = trim($this->data['res_yb_ll']);
$resYbUl = trim($this->data['res_yb_ul']);
$resBrLl = trim($this->data['res_br_ll']);
$resBrUl = trim($this->data['res_br_ul']);
$lockVoltLimit = trim($this->data['lock_volt_limit']);
$leakCurLimit = trim($this->data['leak_cur_limit']);
$lockCurLl = trim($this->data['lock_cur_ll']);
$lockCurUl = trim($this->data['lock_cur_ul']);
$noloadCurLl = trim($this->data['noload_cur_ll']);
$noloadCurUl = trim($this->data['noload_cur_ul']);
$noloadPowLl = trim($this->data['noload_pow_ll']);
$noloadPowUl = trim($this->data['noload_pow_ul']);
$noloadSpdLl = trim($this->data['noload_spd_ll']);
$noloadSpdUl = trim($this->data['noload_spd_ul']);
$createdBy = trim($this->data['created_by']);
$updatedBy = trim($this->data['updated_by']);
return new MotorTestingMaster();
$plant = null;
if (Str::length($plantCod) < 4 || !is_numeric($plantCod) || !preg_match('/^[1-9]\d{3,}$/', $plantCod))
{
$warnMsg[] = "Invalid plant code found";
}
else if (Str::length($iCode) < 6 || !ctype_alnum($iCode))
{
$warnMsg[] = "Invalid item code found";
}
else if (Str::length($sCode) < 6 || !ctype_alnum($sCode))
{
$warnMsg[] = "Invalid sub-assembly code found";
}
else
{
$plant = Plant::where('code', $plantCod)->first();
$codeExist = Item::where('code', $iCode)->first();
if ($plant)
{
$iCode = Item::where('code', $iCode)->where('plant_id', $plant->id)->first();
}
if (!$plant)
{
$warnMsg[] = "Plant not found";
}
else if (!$codeExist)
{
$warnMsg[] = "Item code not found";
}
else if (!$iCode)
{
$warnMsg[] = "Item code not found for choosed plant";
}
else
{
// if (Str::length($isiModel) <= 0 || $isiModel == "0" || $isiModel == "1") {
// $warnMsg[] = "Invalid ISI Model found";
// }
// else
// {
// $isiModel = ($isiModel == "1");
// }
if (Str::length($phase) <= 0 || ($phase != "Single" && $phase != "Three")) {//!is_string($phase) ||
$warnMsg[] = "Invalid phase found";
}
if (Str::length($hp) <= 0 || !is_numeric($hp)) {
$warnMsg[] = "Invalid HP found";
}
if (Str::length($kw) <= 0 || !is_numeric($kw)) {
$warnMsg[] = "Invalid KW found";
}
if (Str::length($volt) <= 0 || !is_numeric($volt)) {
$warnMsg[] = "Invalid volt found";
}
if (Str::length($current) <= 0 || !is_numeric($current)) {
$warnMsg[] = "Invalid current found";
}
if (Str::length($rpm) <= 0 || !is_numeric($rpm)) {
$warnMsg[] = "Invalid RPM found";
}
if (Str::length($torque) <= 0 || !is_numeric($torque)) {
$warnMsg[] = "Invalid torque found";
}
if (Str::length($frequency) <= 0 || !is_numeric($frequency)) {
$warnMsg[] = "Invalid frequency found";
}
if (Str::length($connection) <= 0 || ($connection != "Star-Delta" && $connection != "Star" && $connection != "Delta")) {
$warnMsg[] = "Invalid connection found";
}
if (Str::length($insResLimit) <= 0 || !is_numeric($insResLimit)) {
$warnMsg[] = "Invalid insulation resistance limit found";
}
if (Str::length($insResType) <= 0 || ($insResType != "O" && $insResType != "M" && $insResType != "G")) {
$warnMsg[] = "Invalid insulation resistance type found";
}
if (Str::length($routineTestTime) <= 0 || !isValidTimeFormat($routineTestTime)) {
$warnMsg[] = "Invalid routine test time found";
}
if (Str::length($resRyLl) <= 0 || !is_numeric($resRyLl)) {
$warnMsg[] = "Invalid resistance RY lower limit found";
}
if (Str::length($resRyUl) <= 0 || !is_numeric($resRyUl)) {
$warnMsg[] = "Invalid resistance RY upper limit found";
}
if (Str::length($resYbLl) <= 0 || !is_numeric($resYbLl)) {
$warnMsg[] = "Invalid resistance YB lower limit found";
}
if (Str::length($resYbUl) <= 0 || !is_numeric($resYbUl)) {
$warnMsg[] = "Invalid resistance YB upper limit found";
}
if (Str::length($resBrLl) <= 0 || !is_numeric($resBrLl)) {
$warnMsg[] = "Invalid resistance BR lower limit found";
}
if (Str::length($resBrUl) <= 0 || !is_numeric($resBrUl)) {
$warnMsg[] = "Invalid resistance BR upper limit found";
}
if (Str::length($lockVoltLimit) <= 0 || !is_numeric($lockVoltLimit)) {
$warnMsg[] = "Invalid locked volt limit found";
}
if (Str::length($leakCurLimit) <= 0 || !is_numeric($leakCurLimit)) {
$warnMsg[] = "Invalid leakage current limit found";
}
if (Str::length($lockCurLl) <= 0 || !is_numeric($lockCurLl)) {
$warnMsg[] = "Invalid locked current lower limit found";
}
if (Str::length($lockCurUl) <= 0 || !is_numeric($lockCurUl)) {
$warnMsg[] = "Invalid locked current upper limit found";
}
if (Str::length($noloadCurLl) <= 0 || !is_numeric($noloadCurLl)) {
$warnMsg[] = "Invalid no load current lower limit found";
}
if (Str::length($noloadCurUl) <= 0 || !is_numeric($noloadCurUl)) {
$warnMsg[] = "Invalid no load current upper limit found";
}
if (Str::length($noloadPowLl) <= 0 || !is_numeric($noloadPowLl)) {
$warnMsg[] = "Invalid no load power lower limit found";
}
if (Str::length($noloadPowUl) <= 0 || !is_numeric($noloadPowUl)) {
$warnMsg[] = "Invalid no load power upper limit found";
}
if (Str::length($noloadSpdLl) <= 0 || !is_numeric($noloadSpdLl)) {
$warnMsg[] = "Invalid no load speed lower limit found";
}
if (Str::length($noloadSpdUl) <= 0 || !is_numeric($noloadSpdUl)) {
$warnMsg[] = "Invalid no load speed upper limit found";
}
$oldCode = MotorTestingMaster::where('item_id', $iCode->id)->where('plant_id', $plant->id)->first();
if ($oldCode) {
$created = $oldCode->created_by ? User::where('name', $oldCode->created_by)->first() : null;
if (!$created) {
$warnMsg[] = "Created by not found on update";
}
$updated = User::where('name', $updatedBy)->first();
if (!$updated) {
$warnMsg[] = "Updated by not found on update";
}
}
else
{
$created = User::where('name', $createdBy)->first();
if (!$created) {
$warnMsg[] = "Created by not found";
}
$updated = User::where('name', $updatedBy)->first();
if (!$updated) {
$warnMsg[] = "Updated by not found";
}
}
}
}
if (!empty($warnMsg)) {
throw new RowImportFailedException(implode(', ', $warnMsg));
}
MotorTestingMaster::updateOrCreate([
'plant_id' => $plant->id,
'item_id' => $iCode->id
],
[
'subassembly_code' => $sCode,
'isi_model' => $isiModel,
'phase' => $phase,
'kw' => $kw,
'hp' => $hp,
'volt' => $volt,
'current' => $current,
'rpm' => $rpm,
'torque' => $torque,
'frequency' => $frequency,
'connection' => $connection,
'ins_res_limit' => $insResLimit,
'ins_res_type' => $insResType,
'routine_test_time' => $routineTestTime,
'res_ry_ll' => $resRyLl,
'res_ry_ul' => $resRyUl,
'res_yb_ll' => $resYbLl,
'res_yb_ul' => $resYbUl,
'res_br_ll' => $resBrLl,
'res_br_ul' => $resBrUl,
'lock_volt_limit' => $lockVoltLimit,
'leak_cur_limit' => $leakCurLimit,
'lock_cur_ll' => $lockCurLl,
'lock_cur_ul' => $lockCurUl,
'noload_cur_ll' => $noloadCurLl,
'noload_cur_ul' => $noloadCurUl,
'noload_pow_ll' => $noloadPowLl,
'noload_pow_ul' => $noloadPowUl,
'noload_spd_ll' => $noloadSpdLl,
'noload_spd_ul' => $noloadSpdUl,
'created_by' => $created->name,
'updated_by' => $updated->name,
]
);
return null;
// // return MotorTestingMaster::firstOrNew([
// // // Update existing records, matching them by `$this->data['column_name']`
// // 'email' => $this->data['email'],
// // ]);
// return new MotorTestingMaster();
}
public static function getCompletedNotificationBody(Import $import): string
@@ -239,3 +485,13 @@ class MotorTestingMasterImporter extends Importer
return $body;
}
}
function isValidTimeFormat($time) {
// If time starts with a single digit hour without leading zero, pad it
if (preg_match('/^\d(:\d{2}:\d{2})$/', $time, $matches)) {
$time = '0' . $time;
}
$dateTime = DateTime::createFromFormat('H:i:s', $time);
return $dateTime && $dateTime->format('H:i:s') === $time;
}

View File

@@ -12,10 +12,21 @@ use Filament\Actions\Imports\Importer;
use Filament\Actions\Imports\Models\Import;
use Str;
class PalletValidationImporter extends Importer
{
protected static ?string $model = PalletValidation::class;
// public static function canQueue(): bool
// {
// return true; // allows this importer to be queued
// }
// public static function getChunkSize(): ?int
// {
// return 1000;
// }
public static function getColumns(): array
{
return [

View File

@@ -0,0 +1,115 @@
<?php
namespace App\Filament\Imports;
use App\Models\Item;
use App\Models\Plant;
use App\Models\ProcessOrder;
use App\Models\User;
use Filament\Actions\Imports\ImportColumn;
use Filament\Actions\Imports\Importer;
use Filament\Actions\Imports\Models\Import;
use Str;
use Filament\Actions\Imports\Exceptions\RowImportFailedException;
class ProcessOrderImporter extends Importer
{
protected static ?string $model = ProcessOrder::class;
public static function getColumns(): array
{
return [
ImportColumn::make('plant')
->requiredMapping()
->exampleHeader('Plant Code')
->example('1000')
->label('Plant Code')
->relationship(resolveUsing:'code')
->rules(['required']),
ImportColumn::make('item')
->requiredMapping()
->exampleHeader('Item Code')
->example('123456')
->label('Item Code')
->relationship(resolveUsing: 'code')
->rules(['required']),
ImportColumn::make('process_order')
->exampleHeader('Process Order')
->example('200000166843')
->label('Process Order')
->rules(['required']),
ImportColumn::make('created_by')
->exampleHeader('Created By')
->example('RAW01234')
->label('Created By'),
];
}
public function resolveRecord(): ?ProcessOrder
{
$warnMsg = [];
$plant = Plant::where('code', $this->data['plant'])->first();
$itemCode = Item::where('code', $this->data['item'])->first();
$iCode = trim($this->data['item']);
if (!$plant) {
$warnMsg[] = "Plant not found";
}
else if (Str::length($iCode) < 6 || !ctype_alnum($iCode)) {
$warnMsg[] = "Invalid item code found";
}
else if(!$itemCode)
{
$warnMsg[] = "Item Code not found";
}
$processOrder = trim($this->data['process_order'] ?? '');
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 && $processOrder != '') {
$existingOrder = ProcessOrder::where('plant_id', $plant->id)
->where('process_order', $processOrder)
->first();
if ($existingOrder && $existingOrder->item_id !== ($itemCode->id ?? null)) {
$warnMsg[] = "Same Process Order already exists for this Plant with a different Item Code";
}
}
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' => $user->name,
]);
//return new ProcessOrder();
}
public static function getCompletedNotificationBody(Import $import): string
{
$body = 'Your process order import has completed and ' . number_format($import->successful_rows) . ' ' . str('row')->plural($import->successful_rows) . ' imported.';
if ($failedRowsCount = $import->getFailedRowsCount()) {
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to import.';
}
return $body;
}
}

View File

@@ -59,9 +59,9 @@ class ProductionQuantityImporter extends Importer
->rules(['required']),
ImportColumn::make('block_reference')
->requiredMapping() // Or optionalMapping() if not always present
->exampleHeader('Block Name')
->exampleHeader('Block')
->example(['Block A', 'Block A'])
->label('Block Name')
->label('Block')
->rules(['required']), // Or remove if not required
ImportColumn::make('shift')
->requiredMapping()
@@ -130,7 +130,7 @@ class ProductionQuantityImporter extends Importer
if (Str::length($this->data['serial_number']) < 9 || !ctype_alnum($this->data['serial_number'])) {
$warnMsg[] = "Invalid serial number found";
}
if (Str::length($this->data['production_order']) > 0 && (Str::length($this->data['production_order']) < 7 || !is_numeric($this->data['production_order']))) {
if (Str::length($this->data['production_order']) > 0 && (Str::length($this->data['production_order']) < 7 || Str::length($this->data['production_order']) > 14 || !is_numeric($this->data['production_order']))) {
$warnMsg[] = "Invalid production order found";
}

View File

@@ -193,9 +193,9 @@ class QualityValidationImporter extends Importer
$line = Line::where('name', $this->data['line'])->where('plant_id', $plant->id)->first();
$uniqueCode = trim($this->data['sticker_master_id_code']);// stickerMaster.item
$stickMaster = StickerMaster::select('id')->with('item')
->whereHas('item', function ($query) use ($uniqueCode, $plant) {
$query->where('code', $uniqueCode)->where('plant_id', $plant->id);
})->value('id');
->whereHas('item', function ($query) use ($uniqueCode, $plant) {
$query->where('code', $uniqueCode)->where('plant_id', $plant->id);
})->value('id');
}
if (!$line) {
@@ -206,7 +206,7 @@ class QualityValidationImporter extends Importer
$warnMsg[] = "Sticker item code not found";
}
if (!is_numeric($this->data['production_order']) || Str::length($this->data['production_order']) < 7) {
if (!is_numeric($this->data['production_order']) || Str::length($this->data['production_order']) < 7 || Str::length($this->data['production_order']) > 14) {
$warnMsg[] = "Invalid production order found";
}
@@ -281,11 +281,13 @@ class QualityValidationImporter extends Importer
QualityValidation::updateOrCreate([
'plant_id' => $plant->id,
'line_id' => $line->id,
'sticker_master_id' => $stickMaster,//->id
'serial_number' => $this->data['serial_number']
],
[
'line_id' => $line->id,
'uom' => $this->data['uom'],
'production_order' => $this->data['production_order'],
'serial_number' => $this->data['serial_number'],
'serial_number_motor' => $this->data['serial_number_motor'],
'serial_number_pump' => $this->data['serial_number_pump'],
'serial_number_pumpset' => $this->data['serial_number_pumpset'],

View File

@@ -26,107 +26,107 @@ class StickerMasterImporter extends Importer
->relationship(resolveUsing: 'code')
->rules(['required']),
ImportColumn::make('serial_number_motor')
// ->requiredMapping()
->requiredMapping()
->exampleHeader('Serial Number Motor')
->label('SERIAL NUMBER MOTOR')
->example('1'),
ImportColumn::make('serial_number_pump')
//->requiredMapping()
->requiredMapping()
->exampleHeader('Serial Number Pump')
->label('SERIAL NUMBER PUMP')
->example('1'),
ImportColumn::make('serial_number_pumpset')
//->requiredMapping()
->requiredMapping()
->exampleHeader('Serial Number PumpSet')
->label('SERIAL NUMBER PUMPSET')
->example(''),
ImportColumn::make('pack_slip_motor')
//->requiredMapping()
->requiredMapping()
->exampleHeader('Pack Slip Motor')
->label('PACK SLIP MOTOR')
->example('1'),
ImportColumn::make('pack_slip_pump')
//->requiredMapping()
->requiredMapping()
->exampleHeader('Pack Slip Pump')
->label('PACK SLIP PUMP')
->example('1'),
ImportColumn::make('pack_slip_pumpset')
//->requiredMapping()
->requiredMapping()
->exampleHeader('Pack Slip PumpSet')
->label('PACK SLIP PUMPSET')
->example(''),
ImportColumn::make('name_plate_motor')
// ->requiredMapping()
->requiredMapping()
->exampleHeader('Name Plate Motor')
->label('NAME PLATE MOTOR')
->example('1'),
ImportColumn::make('name_plate_pump')
// ->requiredMapping()
->requiredMapping()
->exampleHeader('Name Plate Pump')
->label('NAME PLATE PUMP')
->example('1'),
ImportColumn::make('name_plate_pumpset')
// ->requiredMapping()
->requiredMapping()
->exampleHeader('Name Plate PumpSet')
->label('NAME PLATE PUMPSET')
->example(''),
ImportColumn::make('tube_sticker_motor')
// ->requiredMapping()
->requiredMapping()
->exampleHeader('Tube Sticker Motor')
->label('TUBE STICKER MOTOR')
->example('1'),
ImportColumn::make('tube_sticker_pump')
// ->requiredMapping()
->requiredMapping()
->exampleHeader('Tube Sticker Pump')
->label('TUBE STICKER PUMP')
->example('1'),
ImportColumn::make('tube_sticker_pumpset')
// ->requiredMapping()
->requiredMapping()
->exampleHeader('Tube Sticker PumpSet')
->label('TUBE STICKER PUMPSET')
->example(''),
ImportColumn::make('warranty_card')
// ->requiredMapping()
->requiredMapping()
->exampleHeader('Warranty Card')
->label('WARRANTY CARD')
->example('1'),
ImportColumn::make('part_validation1')
// ->requiredMapping()
->requiredMapping()
->exampleHeader('Part Validation 1')
->label('PART VALIDATION 1')
->example('12345'),
ImportColumn::make('part_validation2')
// ->requiredMapping()
->requiredMapping()
->exampleHeader('Part Validation 2')
->label('PART VALIDATION 2')
->example('23456'),
ImportColumn::make('part_validation3')
// ->requiredMapping()
->requiredMapping()
->exampleHeader('Part Validation 3')
->label('PART VALIDATION 3')
->example('34567'),
ImportColumn::make('part_validation4')
// ->requiredMapping()
->requiredMapping()
->exampleHeader('Part Validation 4')
->label('PART VALIDATION 4')
->example('45678'),
ImportColumn::make('part_validation5')
// ->requiredMapping()
->requiredMapping()
->exampleHeader('Part Validation 5')
->label('PART VALIDATION 5')
->example('56789'),
ImportColumn::make('laser_part_validation1')
// ->requiredMapping()
->requiredMapping()
->exampleHeader('Laser Part Validation 1')
->label('LASER PART VALIDATION 1')
->example('67890'),
ImportColumn::make('laser_part_validation2')
// ->requiredMapping()
->requiredMapping()
->exampleHeader('Laser Part Validation 2')
->label('LASER PART VALIDATION 2')
->example('78901'),
ImportColumn::make('panel_box_code')
// ->requiredMapping()
->requiredMapping()
->exampleHeader('Panel Box Code')
->label('PANEL BOX CODE')
->example('123456'),
@@ -138,13 +138,13 @@ class StickerMasterImporter extends Importer
->example('0')
->rules(['required']),
ImportColumn::make('material_type')
// ->requiredMapping()
->requiredMapping()
->integer()
->exampleHeader('Material Type')
->label('MATERIAL TYPE')
->example(''),
ImportColumn::make('bundle_quantity')
// ->requiredMapping()
->requiredMapping()
->integer()
->exampleHeader('Bundle Quantity')
->label('BUNDLE QUANTITY')

View File

@@ -14,11 +14,11 @@ class TestingPanelReadingImporter extends Importer
public static function getColumns(): array
{
return [
ImportColumn::make('item')
ImportColumn::make('machine')
->requiredMapping()
->relationship()
->rules(['required']),
ImportColumn::make('machine')
ImportColumn::make('motorTestingMaster.item.code')
->requiredMapping()
->relationship()
->rules(['required']),
@@ -28,6 +28,9 @@ class TestingPanelReadingImporter extends Importer
ImportColumn::make('serial_number')
->requiredMapping()
->rules(['required']),
ImportColumn::make('winded_serial_number')
->requiredMapping()
->rules(['required']),
ImportColumn::make('before_fr_volt'),
ImportColumn::make('before_fr_cur'),
ImportColumn::make('before_fr_pow'),

View File

@@ -0,0 +1,138 @@
<?php
namespace App\Filament\Imports;
use App\Models\Plant;
use App\Models\User;
use Filament\Actions\Imports\Exceptions\RowImportFailedException;
use Filament\Actions\Imports\ImportColumn;
use Filament\Actions\Imports\Importer;
use Filament\Actions\Imports\Models\Import;
use Spatie\Permission\Models\Role;
use Str;
class UserImporter extends Importer
{
protected static ?string $model = User::class;
public static function getColumns(): array
{
return [
ImportColumn::make('plant')
->requiredMapping()
->exampleHeader('Plant Code')
->example('1000')
->label('PLANT CODE')
->relationship(resolveUsing: 'code'),
ImportColumn::make('name')
->requiredMapping()
->exampleHeader('Name')
->example('RAW00001')
->label('Name')
->rules(['required']),//, 'max:255'
ImportColumn::make('email')
->requiredMapping()
->exampleHeader('E-Mail')
->example('RAW00001@cripumps.com')
->label('E-Mail')
->rules(['required', 'email']),//, 'max:255'
ImportColumn::make('password')
->requiredMapping()
->exampleHeader('Password')
->example('RAW00001')
->label('Password')
->rules(['required']),//, 'max:255'
ImportColumn::make('roles')
->requiredMapping()
->exampleHeader('Roles')
->example('Employee')
->label('Roles')
->rules(['nullable', 'string']), // Optional roles
];
}
public function resolveRecord(): ?User
{
$warnMsg = [];
$plant = null;
if (Str::length($this->data['plant']) > 0) {
if (Str::length($this->data['plant']) < 4 || !is_numeric($this->data['plant']) || !preg_match('/^[1-9]\d{3,}$/', $this->data['plant'])) {
$warnMsg[] = "Invalid plant code found!";
}
else {
$plant = Plant::where('code', $this->data['plant'])->first();
if (!$plant) {
$warnMsg[] = "Plant not found";
}
else {
$plant = $plant->id ?? null;
}
}
}
if (Str::length($this->data['name']) < 1) {
$warnMsg[] = "User name not found!";
}
// || !is_numeric($this->data['code']) || !preg_match('/^[1-9]\d{3,}$/', $this->data['code'])
if (Str::length($this->data['email']) < 5) {
$warnMsg[] = "Invalid email found!";
}
if (Str::length($this->data['password']) < 3) {
$warnMsg[] = "Invalid password found!";
}
// Validate roles if provided
$roles = [];
if (!empty($this->data['roles'])) {
$roles = collect(explode(',', $this->data['roles']))
->map(fn($role) => trim($role))
->filter()
->toArray();
foreach ($roles as $roleName) {
if (!Role::where('name', $roleName)->exists()) {
$warnMsg[] = "Role : '{$roleName}' does not exist!";
}
}
}
else {
$warnMsg[] = "User roles not found!";
}
if (!empty($warnMsg)) {
throw new RowImportFailedException(implode(', ', $warnMsg));
}
$user = User::updateOrCreate([
'email' => $this->data['email'],
],
[
'name' => $this->data['name'],
'password' => $this->data['password'],
'plant_id' => $plant,
]);
// Assign roles
if (!empty($roles)) {
$user->syncRoles($roles);
}
return null;
// return User::firstOrNew([
// // Update existing records, matching them by `$this->data['column_name']`
// 'email' => $this->data['email'],
// ]);
//return new User();
}
public static function getCompletedNotificationBody(Import $import): string
{
$body = 'Your user import has completed and ' . number_format($import->successful_rows) . ' ' . str('row')->plural($import->successful_rows) . ' imported.';
if ($failedRowsCount = $import->getFailedRowsCount()) {
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to import.';
}
return $body;
}
}

View File

@@ -0,0 +1,154 @@
<?php
namespace App\Filament\Imports;
use App\Models\Plant;
use App\Models\User;
use App\Models\WorkGroupMaster;
use Filament\Actions\Imports\Exceptions\RowImportFailedException;
use Filament\Actions\Imports\ImportColumn;
use Filament\Actions\Imports\Importer;
use Filament\Actions\Imports\Models\Import;
use Str;
class WorkGroupMasterImporter extends Importer
{
protected static ?string $model = WorkGroupMaster::class;
public static function getColumns(): array
{
return [
ImportColumn::make('plant')
->requiredMapping()
->exampleHeader('Plant Name')
->example('Ransar Industries-I')
->label('Plant Name')
->relationship(resolveUsing:'name')
->rules(['required']),
ImportColumn::make('name')
->requiredMapping()
->exampleHeader('Name')
->example('RMGCEABC')
->label('Name')
->rules(['required']),
ImportColumn::make('description')
->requiredMapping()
->exampleHeader('Description')
->example('Testing Model 1')
->label('Description')
->rules(['required']),
ImportColumn::make('operation_number')
->requiredMapping()
->exampleHeader('Operation Number')
->example('0020')
->label('Operation Number')
->rules(['required']),
ImportColumn::make('created_by')
->requiredMapping()
->exampleHeader('Created By')
->example('Admin')
->label('Created By')
->rules(['required']),
];
}
public function resolveRecord(): ?WorkGroupMaster
{
// return WorkGroupMaster::firstOrNew([
// // Update existing records, matching them by `$this->data['column_name']`
// 'email' => $this->data['email'],
// ]);
$warnMsg = [];
$plant = Plant::where('name', $this->data['plant'])->first();
if (!$plant) {
$warnMsg[] = "Plant not found";
}
if (Str::length($this->data['name']) <= 0) { //|| !ctype_alnum($this->data['description'])
$warnMsg[] = "Invalid name found";
}
if (Str::length(trim($this->data['description'])) <= 0) {
$warnMsg[] = "Invalid description found";
}
$desc = trim($this->data['description']);
if (Str::length($desc) > 44) {
$warnMsg[] = "Description should be less than 44 digits.";
}
if (Str::length($this->data['operation_number']) <= 0) {
$warnMsg[] = "Invalid operation number found";
}
if(!is_numeric($this->data['operation_number']))
{
$warnMsg[] = "Invalid operation number found must be numeric";
}
$user = User::where('name', $this->data['created_by'])->first();
if (!$user) {
$warnMsg[] = "Operator ID not found";
}
if (!empty($warnMsg)) {
throw new RowImportFailedException(implode(', ', $warnMsg));
}
else
{
//Check (plant_id, name)
$existingByName = WorkGroupMaster::where('plant_id', $plant->id)
->where('name', $this->data['name'])
->first();
if ($existingByName) {
throw new RowImportFailedException("Work group name already exists for this plant!");
}
//Check (plant_id, operation_number)
$existingByOpNum = WorkGroupMaster::where('plant_id', $plant->id)
->where('operation_number', $this->data['operation_number'])
->where('name', $this->data['name'])
->first();
if ($existingByOpNum) {
throw new RowImportFailedException("Operation number already exists for this plant!");
}
//Check (plant_id)
$existingByOperator = WorkGroupMaster::where('plant_id', $plant->id)
->where('name', $this->data['name'])
->first();
if ($existingByOperator) {
throw new RowImportFailedException("Already work group name assigned to another plant!");
}
}
WorkGroupMaster::updateOrCreate([
'plant_id' => $plant->id,
'name' => $this->data['name'],
'description' => $this->data['description'],
'operation_number' => $this->data['operation_number'],
'created_by' => $this->data['created_by'],
]);
return null;
//return new WorkGroupMaster();
}
public static function getCompletedNotificationBody(Import $import): string
{
$body = 'Your work group master import has completed and ' . number_format($import->successful_rows) . ' ' . str('row')->plural($import->successful_rows) . ' imported.';
if ($failedRowsCount = $import->getFailedRowsCount()) {
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to import.';
}
return $body;
}
}

View File

@@ -53,6 +53,7 @@ class Dashboard extends \Filament\Pages\Dashboard
{
return 'Production Line Count';
}
public function getWidgets(): array
{
$widgets = [];

View File

@@ -7,6 +7,7 @@ use App\Models\Plant;
use App\Models\ProductionQuantity;
use App\Models\QualityValidation;
use App\Models\StickerMaster;
use Filament\Facades\Filament;
use Filament\Forms\Components\Actions;
use Filament\Forms\Components\Actions\Action;
use Filament\Forms\Form;
@@ -55,8 +56,12 @@ class DataSendToSap extends Page implements HasForms
->statePath('data')
->schema([
Select::make('plant_id')
->options(Plant::pluck('name', 'id'))
->label('Plant')
// ->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();
})
->reactive()
->required()
->afterStateUpdated(function ($state, $set, callable $get) {

View File

@@ -4,6 +4,7 @@ namespace App\Filament\Pages;
use App\Filament\Widgets\GuardPatrolDayChart;
use App\Models\Plant;
use Filament\Facades\Filament;
use Filament\Pages\Page;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use Filament\Forms\Form;
@@ -34,13 +35,17 @@ class GuardPatrolDayCount extends Page
->statePath('filters')
->schema([
Select::make('plant')
->options(Plant::pluck('name', 'id'))
->label('Select Plant')
->reactive()
->afterStateUpdated(function ($state) {
session(['selected_plant' => $state]);
$this->dispatch('patrolEntryChart');
}),
->label('Select Plant')
// ->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();
})
->reactive()
->afterStateUpdated(function ($state) {
session(['selected_plant' => $state]);
$this->dispatch('patrolEntryChart');
}),
]);
}

View File

@@ -5,6 +5,7 @@ namespace App\Filament\Pages;
use App\Models\GuardPatrolEntry;
use App\Models\Plant;
use Carbon\Carbon;
use Filament\Facades\Filament;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\Select;
@@ -38,8 +39,12 @@ class GuardPatrolEntryDashboard extends Page
->statePath('filters') // Explicitly set where to store form data
->schema([
Select::make('plant')
->options(Plant::pluck('name', 'id'))
->label('Select Plant')
// ->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();
})
->reactive()
->required()
->afterStateUpdated(function ($state, callable $set, callable $get){

View File

@@ -8,6 +8,7 @@ use App\Models\CheckPointTime;
use App\Models\GuardPatrolEntry;
use App\Models\Plant;
use Carbon\Carbon;
use Filament\Facades\Filament;
use Filament\Pages\Page;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use Filament\Forms\Form;
@@ -47,8 +48,12 @@ class GuardPatrolHourlyCount extends Page
->statePath('filters')
->schema([
Select::make('plant')
->options(Plant::pluck('name', 'id'))
->label('Select Plant')
//->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();
})
->reactive()
->required()
->afterStateUpdated(function ($state,callable $set) {

View File

@@ -4,6 +4,7 @@ namespace App\Filament\Pages;
use App\Models\Plant;
use Filament\Facades\Filament;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
@@ -38,8 +39,12 @@ class InvoiceDashboard extends Page
->statePath('filters') // Explicitly set where to store form data
->schema([
Select::make('plant')
->options(Plant::pluck('name', 'id'))
->label('Select Plant')
//->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();
})
->reactive()
->afterStateUpdated(function ($state) {
session(['selec_plant' => $state]);

View File

@@ -0,0 +1,124 @@
<?php
namespace App\Filament\Pages;
use App\Filament\Widgets\InvoiceDataChart;
use App\Models\InvoiceDataValidation;
use App\Models\Plant;
use Filament\Pages\Page;
use Filament\Forms\Form;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use Filament\Forms\Components\Select;
use Illuminate\Support\Facades\Auth;
use Filament\Facades\Filament;
use Filament\Forms\Components\Section;
class InvoiceDataDashboard extends Page
{
use HasFiltersForm;
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static string $view = 'filament.pages.invoice-data-dashboard';
protected static ?string $navigationGroup = 'Invoice Management';
public function mount(): void
{
session()->forget(['selected_plant','dist_channel']);
$this->filtersForm->fill([
'plant' => null,
'distribution_channel' => null,
]);
}
public function filtersForm(Form $form): Form
{
return $form
->statePath('filters') // Store form state in 'filters'
->schema([
Section::make('')
->schema([
Select::make('plant')
->label('Select 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();
})
->afterStateUpdated(function ($state,callable $set) {
session(['selected_plant' => $state]);
$set('distribution_channel', null);
session()->forget('distribution_channel');
}),
Select::make('distribution_channel')
->label('Distribution Channel')
// ->options(function (callable $get) {
// $plant = $get('plant');
// if (!$plant) {
// return [];
// }
// $options = InvoiceDataValidation::where('plant_id', $plant)
// ->whereNotNull('distribution_channel_desc')
// ->where('distribution_channel_desc', '!=', '')
// ->select('distribution_channel_desc')
// ->distinct()
// ->pluck('distribution_channel_desc', 'distribution_channel_desc')
// ->toArray();
// $hasEmpty = InvoiceDataValidation::where('plant_id', $plant)
// ->where(function ($q) {
// $q->whereNull('distribution_channel_desc')
// ->orWhere('distribution_channel_desc', '');
// })
// ->exists();
// if ($hasEmpty) {
// $options['Challan'] = 'Challan';
// }
// return $options;
// })
->options(function (callable $get) {
$plant = $get('plant');
if (!$plant) {
return [];
}
// Fetch unique, non-empty distribution_channel_desc values
return InvoiceDataValidation::where('plant_id', $plant)
->whereNotNull('distribution_channel_desc')
->where('distribution_channel_desc', '!=', '')
->distinct()
->pluck('distribution_channel_desc', 'distribution_channel_desc')
->toArray();
})
->afterStateUpdated(callback: function ($state,callable $set) {
session(['dist_channel' => $state]);
})
->reactive(),
])
->columns(2),
]);
}
public static function getNavigationLabel(): string
{
return 'Invoice Data Dashboard';
}
public function getHeading(): string
{
return 'Invoice Data Dashboard';
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view invoice data dashboard');
}
}

View File

@@ -5,6 +5,7 @@ namespace App\Filament\Pages;
use App\Models\LocatorInvoiceValidation;
use App\Models\PalletValidation;
use App\Models\Plant;
use Filament\Facades\Filament;
use Illuminate\Support\Facades\Auth;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Concerns\InteractsWithForms;
@@ -41,8 +42,12 @@ class InvoiceFinder extends Page implements HasForms
Section::make('') // You can give your section a title or leave it blank
->schema([
Select::make('plant_id')
->options(Plant::pluck('name', 'id'))
->label('Plant')
//->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();
})
->reactive()
->required(),
TextInput::make('scan_invoice')

View File

@@ -3,6 +3,7 @@
namespace App\Filament\Pages;
use App\Models\Plant;
use Filament\Facades\Filament;
use Filament\Pages\Page;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use Filament\Forms\Form;
@@ -35,8 +36,12 @@ class InvoiceQuantityDashboard extends Page
->statePath('filters') // Explicitly set where to store form data
->schema([
Select::make('plant')
->options(Plant::pluck('name', 'id'))
->label('Select Plant')
//->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();
})
->reactive()
->afterStateUpdated(function ($state) {
session(['selec_plant' => $state]);

View File

@@ -69,7 +69,11 @@ class LocatorValidation extends Page implements HasForms
Select::make('plant_id')
->label('Plant')
->reactive()
->options(Plant::pluck('name', 'id'))
//->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();
})
->required(),
TextInput::make('scan_pallet_no')
->label('Scan Pallet No')

View File

@@ -64,11 +64,15 @@ class PalletFromLocator extends Page implements HasForms
Section::make('')
->schema([
Select::make('plant_id')
->options(Plant::pluck('name', 'id'))
->label('Plant')
->reactive()
->required()
->columnSpan(1)
//->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();
})
->disabled(fn (Get $get) => $get('plant_id'))
->afterStateUpdated(function ($state, callable $set, callable $get) {
$plantId = $get('plant_id');
@@ -726,13 +730,27 @@ class PalletFromLocator extends Page implements HasForms
$month = now()->format('m');
$prefix = "EP-{$year}{$month}";
$lastPallet = PalletValidation::where('pallet_number', 'like', "{$prefix}%")->orderByDesc('pallet_number')->first(); //->where('plant_id', $plantId)
$lastPallet1 = PalletValidation::where('pallet_number', 'like', "{$prefix}%")->orderByDesc('pallet_number')->first(); //->where('plant_id', $plantId)
$lastPallet2 = LocatorInvoiceValidation::where('pallet_number', 'like', "{$prefix}%")->orderByDesc('pallet_number')->first();
$newNumber = '001'; // $lastPallet ? str_pad(intval(substr($lastPallet->pallet_number, -3)) + 1, 3, '0', STR_PAD_LEFT) : '001';
if ($lastPallet) {
$serialPart = substr($lastPallet->pallet_number, strlen($prefix));
if ($lastPallet1 && $lastPallet2) {
$serialPart1 = substr($lastPallet1->pallet_number, strlen($prefix));
$serialPart2 = substr($lastPallet2->pallet_number, strlen($prefix));
if (intval($serialPart1) > intval($serialPart2)) {
$newNumber = str_pad(intval($serialPart1) + 1, strlen($serialPart1), '0', STR_PAD_LEFT);
} else {
$newNumber = str_pad(intval($serialPart2) + 1, strlen($serialPart2), '0', STR_PAD_LEFT);
}
}
else if ($lastPallet1) {
$serialPart1 = substr($lastPallet1->pallet_number, strlen($prefix));
// OR
// $serialPart = str_replace($prefix, '', $lastPallet->pallet_number);
$newNumber = str_pad(intval($serialPart) + 1, strlen($serialPart), '0', STR_PAD_LEFT);
$newNumber = str_pad(intval($serialPart1) + 1, strlen($serialPart1), '0', STR_PAD_LEFT);
}
else if ($lastPallet2) {
$serialPart2 = substr($lastPallet2->pallet_number, strlen($prefix));
$newNumber = str_pad(intval($serialPart2) + 1, strlen($serialPart2), '0', STR_PAD_LEFT);
}
$newPalletNumber = "{$prefix}{$newNumber}";

View File

@@ -7,6 +7,7 @@ use App\Models\Plant;
use App\Models\ProductionQuantity;
use App\Models\QualityValidation;
use App\Models\StickerMaster;
use Filament\Facades\Filament;
use Filament\Forms\Components\Actions;
use Filament\Forms\Components\Actions\Action;
use Filament\Forms\Form;
@@ -55,10 +56,14 @@ class ProductionDataSap extends Page implements HasForms
->statePath('data')
->schema([
Select::make('plant_id')
->options(Plant::pluck('name', 'id'))
->label('Plant')
->reactive()
->required()
//->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();
})
->afterStateUpdated(function ($state, $set, callable $get) {
$plantId = $get('plant_id');
if (!$plantId) {

View File

@@ -3,6 +3,7 @@
namespace App\Filament\Pages;
use App\Models\Plant;
use Filament\Facades\Filament;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
@@ -38,8 +39,12 @@ class ProductionLineStopCount extends Page
->schema([
Select::make('plant')
->options(Plant::pluck('name', 'id'))
->label('Select Plant')
//->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();
})
->reactive()
->afterStateUpdated(function ($state) {
session(['selected_plant' => $state]);

View File

@@ -320,23 +320,44 @@ class ProductionQuantityPage extends Page implements HasForms
->hintColor('danger'),
TextInput::make('production_order')
->label('Production Order')
->reactive()
->required()
//->columnSpan(1)
->columnSpan(['default' => 1, 'sm' => 1])
->afterStateUpdated(function ($state, callable $get, callable $set): void {
$set('item_code', null);
$set('item_id', null);
// $set('item_description', null);
$set('serial_number', null);
$set('validationError', null);
$this->prodOrder = $state;
return;
// if (empty($state)) {
// }
}),
->label('Production Order')
->reactive()
->required()
->minLength(7)
->maxLength(14)
//->columnSpan(1)
->columnSpan(['default' => 1, 'sm' => 1])
->afterStateUpdated(function ($state, callable $get, callable $set): void {
if(!is_numeric($get('production_order')) || !preg_match('/^[1-9][0-9]{6,13}$/', $get('production_order')))
{
$set('productionError', "Must be a numeric value with 7 to 14 digits.");
$set('production_order', null);
$set('item_code', null);
$set('item_id', null);
// $set('item_description', null);
$set('serial_number', null);
$set('validationError', null);
$this->prodOrder = null;
}
else
{
$set('productionError', null);
$set('production_order', $state);
$set('item_code', null);
$set('item_id', null);
// $set('item_description', null);
$set('serial_number', null);
$set('validationError', null);
$this->prodOrder = $state;
// if (empty($state)) {
// }
}
})
->extraAttributes(fn ($get) => [
'class' => $get('productionError') ? 'border-red-500' : '',
])
->hint(fn ($get) => $get('productionError') ? $get('productionError') : null)
->hintColor('danger'),
// TextInput::make('item_code')
// ->label('Item Code')
@@ -592,7 +613,7 @@ class ProductionQuantityPage extends Page implements HasForms
->send();
return;
}
else if (!preg_match('/^[1-9][0-9]{6,}$/', $this->prodOrder))
else if (!preg_match('/^[1-9][0-9]{6,13}$/', $this->prodOrder))
{
$this->form->fill([
'plant_id'=> $this->pId,
@@ -611,7 +632,7 @@ class ProductionQuantityPage extends Page implements HasForms
Notification::make()
->title('Invalid Production Order')
->body("Must contain at least 7 digits.<br>Must start with a non-zero digit.")
->body("Must be a numeric value with 7 to 14 digits.<br>Must start with a non-zero digit.")
->danger()
->send();
return;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,133 @@
<?php
namespace App\Filament\Pages;
use App\Filament\Widgets\TrendChartAnalysis;
use App\Models\MfmMeter;
use Filament\Facades\Filament;
use Filament\Pages\Page;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use App\Models\Plant;
use Filament\Forms\Components\Select;
use Filament\Forms\Form;
use Filament\Forms\Components\DateTimePicker;
use Illuminate\Support\Facades\Auth;
class TrendChartAnalys extends Page
{
use HasFiltersForm;
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static string $view = 'filament.pages.trend-chart-analys';
protected static ?string $navigationGroup = 'EMS DashBoard';
// use HasFiltersForm;
public function mount(): void
{
session()->forget(['selected_plant', 'selected_meter', 'from_datetime', 'to_datetime', 'parameter']);
$this->filtersForm->fill([
'selected_plant' => null,
'selected_meter' => null,
'from_datetime' => null,
'to_datetime' => null,
'parameter' => null,
]);
}
public function filtersForm(Form $form): Form
{
return $form
->statePath('filters')
->schema([
DateTimePicker::make('from_datetime')
->label('From DateTime')
->required()
->before('to_datetime')
->reactive()
->afterStateUpdated(function ($state) {
$formatted = \Carbon\Carbon::parse($state)->format('Y-m-d H:i:s');
session(['from_datetime' => $formatted]);
}),
DateTimePicker::make('to_datetime')
->label('To DateTime')
->required()
->after('from_datetime')
->reactive()
->afterStateUpdated(function ($state) {
$formatted = \Carbon\Carbon::parse($state)->format('Y-m-d H:i:s');
session(['to_datetime' => $formatted]);
}),
Select::make('plant')
->label('Select Plant')
->reactive()
->required()
//->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();
})
->afterStateUpdated(function ($state, callable $set) {
session(['selected_plant' => $state]);
// When plant changes, also reset meter_name
$set('meter_name', null);
session(['selected_meter' => null]);
// dd($state);
}),
Select::make('meter_name')
->options(function ($get) {
$plantId = $get('plant');
// Return meter name/id pairs from mfm_meters where plant_id matches selected plant
return $plantId ? MfmMeter::where('plant_id', $plantId)->pluck('name', 'id') : [];
})
->label('Select Meter')
->reactive()
->required()
->afterStateUpdated(function ($state) {
session(['selected_meter' => $state]);
}),
Select::make('parameter')
->options([
'Phase Voltage' => 'Phase Voltage',
'Line Voltage' => 'Line Voltage',
'Current' => 'Current',
'Active Power' => 'Active Power',
'Power Factor' => 'Power Factor',
'Units' => 'Units',
])
->label('Select Parameter')
->reactive()
->required()
->afterStateUpdated(function ($state) {
session(['parameter' => $state]);
}),
])
->columns(5);
}
public static function getNavigationLabel(): string
{
return 'Trend Chart Analysis';
}
public function getHeading(): string
{
return 'Trend Chart Analysis';
}
public function getWidgets(): array
{
$widgets = [];
if (TrendChartAnalysis::canView()) {
$widgets[] = TrendChartAnalysis::class;
}
return $widgets;
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view ems trend chart analysis dashboard');
}
}

View File

@@ -0,0 +1,131 @@
<?php
namespace App\Filament\Pages;
use App\Filament\Widgets\TrendLineChart;
use Filament\Facades\Filament;
use Filament\Pages\Page;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use App\Models\Plant;
use Filament\Forms\Components\Select;
use Filament\Forms\Form;
use Filament\Forms\Components\DateTimePicker;
use App\Models\MfmMeter;
use Illuminate\Support\Facades\Auth;
class TrendLineAnalysis extends Page
{
use HasFiltersForm;
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static string $view = 'filament.pages.trend-line-analysis';
protected static ?string $navigationGroup = 'EMS DashBoard';
public function mount(): void
{
session()->forget(['selected_plant', 'selected_meter', 'from_datetime', 'to_datetime', 'parameter']);
$this->filtersForm->fill([
'selected_plant' => null,
'selected_meter' => null,
'from_datetime' => null,
'to_datetime' => null,
'parameter' => null,
]);
}
public function filtersForm(Form $form): Form
{
return $form
->statePath('filters')
->schema([
DateTimePicker::make('from_datetime')
->label('From DateTime')
->required()
->before('to_datetime')
->reactive()
->afterStateUpdated(function ($state) {
$formatted = \Carbon\Carbon::parse($state)->format('Y-m-d H:i:s');
session(['from_datetime' => $formatted]);
}),
DateTimePicker::make('to_datetime')
->label('To DateTime')
->required()
->after('from_datetime')
->reactive()
->afterStateUpdated(function ($state) {
$formatted = \Carbon\Carbon::parse($state)->format('Y-m-d H:i:s');
session(['to_datetime' => $formatted]);
}),
Select::make('plant')
->label('Select Plant')
->reactive()
->required()
//->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();
})
->afterStateUpdated(function ($state, callable $set) {
session(['selected_plant' => $state]);
// When plant changes, also reset meter_name
$set('meter_name', null);
session(['selected_meter' => null]);
// dd($state);
}),
Select::make('meter_name')
->options(function ($get) {
$plantId = $get('plant');
// Return meter name/id pairs from mfm_meters where plant_id matches selected plant
return $plantId ? MfmMeter::where('plant_id', $plantId)->pluck('name', 'id') : [];
})
->label('Select Meter')
->reactive()
->required()
->afterStateUpdated(function ($state) {
session(['selected_meter' => $state]);
}),
Select::make('parameter')
->options([
'Phase Voltage' => 'Phase Voltage',
'Line Voltage' => 'Line Voltage',
'Current' => 'Current',
'Active Power' => 'Active Power',
'Power Factor' => 'Power Factor',
'Units' => 'Units',
])
->label('Select Parameter')
->reactive()
->required()
->afterStateUpdated(function ($state) {
session(['parameter' => $state]);
}),
])
->columns(5);
}
// public static function getNavigationLabel(): string
// {
// return 'Trend Chart Analysis';
// }
// public function getHeading(): string
// {
// return 'Trend Chart Analysis';
// }
public function getWidgets(): array
{
$widgets = [];
if (TrendLineChart::canView()) {
$widgets[] = TrendLineChart::class;
}
return $widgets;
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view ems trend line analysis dashboard');
}
}

View File

@@ -54,10 +54,14 @@ class UploadSerialLocator extends Page implements HasForms
Section::make('') // You can give your section a title or leave it blank
->schema([
Select::make('plant_id')
->options(Plant::pluck('name', 'id'))
->label('Plant')
->reactive()
->required()
//->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();
})
->disabled(fn (Get $get) => $get('scan_serial_number') || $get('scan_locator')) //!empty($get('scan_serial_number'))
->afterStateUpdated(function ($state, callable $set, callable $get) {
$set('scan_serial_number', null);

View File

@@ -36,7 +36,10 @@ class AlertMailRuleResource extends Resource
Forms\Components\Select::make('plant')
->label('Plant')
->reactive()
->options(fn () => Plant::pluck('name', 'id')->toArray())
->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(fn ($get) => ! $get('is_active'))
->afterStateUpdated(fn ($state, callable $set) => $state ? $set('is_active', false) : null),
// ->options(fn () => Plant::pluck('id', 'name')->toArray()),
@@ -45,20 +48,26 @@ class AlertMailRuleResource extends Resource
->required()
->options([
'InvoiceValidation' => 'InvoiceValidation',
'InvoiceDataReport' => 'InvoiceDataReport',
'ProductionQuantities' => 'ProductionQuantities',
//'Calibration' => 'Calibration',
]),
Forms\Components\Select::make('rule_name')
->label('Rule Name')
->options([
->options([
'InvoiceMail' => 'Invoice Mail',
'SerialInvoiceMail' => 'Serial Invoice Mail',
'MaterialInvoiceMail' => 'Material Invoice Mail',
'ProductionMail' => 'Production Mail',
'InvoiceDataMail' => 'Invoice Data Mail',
//'CalibrationMail' => 'Calibration Mail',
])
->required(),
Forms\Components\TextInput::make('email')
->label('Email')
->required(),
Forms\Components\Textarea::make('cc_emails')
->label('CC Emails'),
Forms\Components\Select::make('schedule_type')
->label('Schedule Type')
->required()
@@ -76,7 +85,7 @@ class AlertMailRuleResource extends Resource
Forms\Components\Hidden::make('updated_by')
->default(fn () => Filament::auth()->user()?->name),
])
->columns(5),
->columns(6),
]);
}
@@ -94,12 +103,18 @@ class AlertMailRuleResource extends Resource
{
return $table
->columns([
Tables\Columns\TextColumn::make('id')
->label('ID')
->numeric()
->sortable(),
Tables\Columns\TextColumn::make('No.')
->label('No.')
->getStateUsing(function ($record, $livewire, $column, $rowLoop) {
$paginator = $livewire->getTableRecords();
$perPage = method_exists($paginator, 'perPage') ? $paginator->perPage() : 10;
$currentPage = method_exists($paginator, 'currentPage') ? $paginator->currentPage() : 1;
return ($currentPage - 1) * $perPage + $rowLoop->iteration;
}),
Tables\Columns\TextColumn::make('plant')
->label('Plant')
->label('Plant Name')
->alignCenter()
->searchable()
->sortable()
->formatStateUsing(function ($state) {
static $plants;
@@ -109,32 +124,54 @@ class AlertMailRuleResource extends Resource
return $plants[$state] ?? 'All Plants';
}),
Tables\Columns\TextColumn::make('module')
->label('Module')
->label('Module Name')
->alignCenter()
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('rule_name')
->label('Rule Name')
->alignCenter()
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('email')
->label('Email')
->label('TO Emails')
->searchable()
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('cc_emails')
->label('CC Emails')
->searchable()
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('schedule_type')
->label('Schedule Type')
->searchable()
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('created_at')
->label('Created At')
->alignCenter()
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
->toggleable(isToggledHiddenByDefault: false),
Tables\Columns\TextColumn::make('created_by')
->label('Created By')
->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')
->sortable(),
->alignCenter()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('deleted_at')
->label('Deleted At')
->alignCenter()
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),

View File

@@ -12,11 +12,15 @@ class CreateAlertMailRule extends CreateRecord
protected function mutateFormDataBeforeCreate(array $data): array
{
if ($data['is_active']) {
$data['plant'] = 0;
}
return $data;
}
protected function getRedirectUrl(): string
{
return $this->getResource()::getUrl('create');
}
}

View File

@@ -6,6 +6,7 @@ use App\Filament\Exports\BlockExporter;
use App\Filament\Imports\BlockImporter;
use App\Filament\Resources\BlockResource\Pages;
use App\Models\Block;
use App\Models\Plant;
use Filament\Facades\Filament;
use Filament\Forms;
use Filament\Forms\Form;
@@ -69,6 +70,10 @@ class BlockResource extends Resource
// ->unique(ignoreRecord: true)
->required()
->reactive()
->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();
})
->default(function () {
return optional(Block::latest()->first())->plant_id;
})
@@ -159,11 +164,15 @@ class BlockResource extends Resource
])
->headerActions([
ImportAction::make()
->label('Import Blocks')
->color('warning')
->importer(BlockImporter::class)
->visible(function() {
return Filament::auth()->user()->can('view import block');
}),
ExportAction::make()
->label('Export Blocks')
->color('warning')
->exporter(BlockExporter::class)
->visible(function() {
return Filament::auth()->user()->can('view export block');

View File

@@ -9,4 +9,9 @@ use Filament\Resources\Pages\CreateRecord;
class CreateBlock extends CreateRecord
{
protected static string $resource = BlockResource::class;
protected function getRedirectUrl(): string
{
return $this->getResource()::getUrl('create');
}
}

View File

@@ -7,6 +7,7 @@ use App\Filament\Imports\CheckPointNameImporter;
use App\Filament\Resources\CheckPointNameResource\Pages;
use App\Filament\Resources\CheckPointNameResource\RelationManagers;
use App\Models\CheckPointName;
use App\Models\Plant;
use Filament\Facades\Filament;
use Filament\Forms;
use Filament\Forms\Form;
@@ -28,7 +29,7 @@ class CheckPointNameResource extends Resource
protected static ?string $navigationGroup = 'Master Entries';
protected static ?int $navigationSort = 14;
protected static ?int $navigationSort = 15;
public static function form(Form $form): Form
{
@@ -39,6 +40,10 @@ class CheckPointNameResource extends Resource
->relationship('plant', 'name')
->required()
->reactive()
->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();
})
->default(function () {
return optional(CheckPointName::where('created_by', Filament::auth()->user()?->name)->latest()->first())->plant_id;
})
@@ -148,11 +153,15 @@ class CheckPointNameResource extends Resource
])
->headerActions([
ImportAction::make()
->label('Import Check Point Names')
->color('warning')
->importer(CheckPointNameImporter::class)
->visible(function() {
return Filament::auth()->user()->can('view import check point name');
}),
ExportAction::make()
->label('Export Check Point Names')
->color('warning')
->exporter(CheckPointNameExporter::class)
->visible(function() {
return Filament::auth()->user()->can('view export check point name');

View File

@@ -8,6 +8,7 @@ use App\Filament\Resources\CheckPointTimeResource\Pages;
use App\Filament\Resources\CheckPointTimeResource\RelationManagers;
use App\Models\CheckPointName;
use App\Models\CheckPointTime;
use App\Models\Plant;
use Filament\Facades\Filament;
use Filament\Forms;
use Filament\Forms\Form;
@@ -29,7 +30,7 @@ class CheckPointTimeResource extends Resource
protected static ?string $navigationGroup = 'Master Entries';
protected static ?int $navigationSort = 15;
protected static ?int $navigationSort = 16;
public static function form(Form $form): Form
{
@@ -40,6 +41,10 @@ class CheckPointTimeResource extends Resource
->relationship('plant', 'name')
->required()
->reactive()
->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();
})
->default(function () {
return optional(CheckPointTime::where('created_by', Filament::auth()->user()?->name)->latest()->first())->plant_id;
})
@@ -379,11 +384,15 @@ class CheckPointTimeResource extends Resource
])
->headerActions([
ImportAction::make()
->label('Import Check Point Times')
->color('warning')
->importer(CheckPointTimeImporter::class)
->visible(function() {
return Filament::auth()->user()->can('view import check point time');
}),
ExportAction::make()
->label('Export Check Point Times')
->color('warning')
->exporter(CheckPointTimeExporter::class)
->visible(function() {
return Filament::auth()->user()->can('view export check point time');

View File

@@ -121,11 +121,15 @@ class CompanyResource extends Resource
])
->headerActions([
ImportAction::make()
->label('Import Companies')
->color('warning')
->importer(CompanyImporter::class)
->visible(function() {
return Filament::auth()->user()->can('view import company');
}),
ExportAction::make()
->label('Export Companies')
->color('warning')
->exporter(CompanyExporter::class)
->visible(function() {
return Filament::auth()->user()->can('view export company');

View File

@@ -9,4 +9,9 @@ use Filament\Resources\Pages\CreateRecord;
class CreateCompany extends CreateRecord
{
protected static string $resource = CompanyResource::class;
protected function getRedirectUrl(): string
{
return $this->getResource()::getUrl('create');
}
}

View File

@@ -8,6 +8,7 @@ use App\Filament\Resources\ConfigurationResource\Pages;
use App\Filament\Resources\ConfigurationResource\RelationManagers;
use App\Models\Configuration;
use App\Models\Line;
use App\Models\Plant;
use Filament\Facades\Filament;
use Filament\Forms;
use Filament\Forms\Form;
@@ -37,6 +38,10 @@ class ConfigurationResource extends Resource
->relationship('plant', 'name')
->required()
->reactive()
->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();
})
->default(function () {
return optional(Configuration::latest()->first())->plant_id;
})
@@ -178,11 +183,15 @@ class ConfigurationResource extends Resource
])
->headerActions([
ImportAction::make()
->label('Import Configurations')
->color('warning')
->importer(ConfigurationImporter::class)
->visible(function() {
return Filament::auth()->user()->can('view import configuration');
}),
ExportAction::make()
->label('Export Configurations')
->color('warning')
->exporter(ConfigurationExporter::class)
->visible(function() {
return Filament::auth()->user()->can('view export configuration');

View File

@@ -9,4 +9,9 @@ use Filament\Resources\Pages\CreateRecord;
class CreateConfiguration extends CreateRecord
{
protected static string $resource = ConfigurationResource::class;
protected function getRedirectUrl(): string
{
return $this->getResource()::getUrl('create');
}
}

View File

@@ -0,0 +1,160 @@
<?php
namespace App\Filament\Resources;
use App\Filament\Exports\DeviceMasterExporter;
use App\Filament\Imports\DeviceMasterImporter;
use App\Filament\Resources\DeviceMasterResource\Pages;
use App\Filament\Resources\DeviceMasterResource\RelationManagers;
use App\Models\DeviceMaster;
use App\Models\Plant;
use Filament\Facades\Filament;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Filament\Forms\Components\Section;
use Filament\Tables\Actions\ImportAction;
use Filament\Tables\Actions\ExportAction;
class DeviceMasterResource extends Resource
{
protected static ?string $model = DeviceMaster::class;
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
protected static ?string $navigationGroup = 'Power House';
public static function form(Form $form): Form
{
return $form
->schema([
Section::make('')
->schema([
Forms\Components\Select::make('plant_id')
->label('Plant')
->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::pluck('name', 'id')->toArray();
})
->required(),
Forms\Components\TextInput::make('name')
->label('Device Name')
->required(),
Forms\Components\TextInput::make('mac_address')
->label('MAC Address'),
Forms\Components\TextInput::make('ip_address')
->label('IP Address'),
Forms\Components\Hidden::make('created_by')
->default(Filament::auth()->user()?->name),
])
->columns(4),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('No.')
->label('No.')
->getStateUsing(function ($record, $livewire, $column, $rowLoop) {
$paginator = $livewire->getTableRecords();
$perPage = method_exists($paginator, 'perPage') ? $paginator->perPage() : 10;
$currentPage = method_exists($paginator, 'currentPage') ? $paginator->currentPage() : 1;
return ($currentPage - 1) * $perPage + $rowLoop->iteration;
}),
Tables\Columns\TextColumn::make('plant.name')
->label('Plant')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('name')
->label('Device Name')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('mac_address')
->label('MAC Address')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('ip_address')
->label('IP Address')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('created_at')
->label('Created At')
->alignCenter()
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('updated_at')
->label('Updated At')
->alignCenter()
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('deleted_at')
->dateTime()
->alignCenter()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
Tables\Filters\TrashedFilter::make(),
])
->actions([
Tables\Actions\ViewAction::make(),
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
Tables\Actions\ForceDeleteBulkAction::make(),
Tables\Actions\RestoreBulkAction::make(),
]),
])
->headerActions([
ImportAction::make()
->label('Import Device Masters')
->color('warning')
->importer(DeviceMasterImporter::class)
->visible(function() {
return Filament::auth()->user()->can('view import device master');
}),
ExportAction::make()
->label('Export Device Masters')
->color('warning')
->exporter(DeviceMasterExporter::class)
->visible(function() {
return Filament::auth()->user()->can('view export device master');
}),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListDeviceMasters::route('/'),
'create' => Pages\CreateDeviceMaster::route('/create'),
'view' => Pages\ViewDeviceMaster::route('/{record}'),
'edit' => Pages\EditDeviceMaster::route('/{record}/edit'),
];
}
public static function getEloquentQuery(): Builder
{
return parent::getEloquentQuery()
->withoutGlobalScopes([
SoftDeletingScope::class,
]);
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace App\Filament\Resources\DeviceMasterResource\Pages;
use App\Filament\Resources\DeviceMasterResource;
use Filament\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateDeviceMaster extends CreateRecord
{
protected static string $resource = DeviceMasterResource::class;
protected function getRedirectUrl(): string
{
return $this->getResource()::getUrl('create');
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace App\Filament\Resources\DeviceMasterResource\Pages;
use App\Filament\Resources\DeviceMasterResource;
use Filament\Actions;
use Filament\Resources\Pages\EditRecord;
class EditDeviceMaster extends EditRecord
{
protected static string $resource = DeviceMasterResource::class;
protected function getHeaderActions(): array
{
return [
Actions\ViewAction::make(),
Actions\DeleteAction::make(),
Actions\ForceDeleteAction::make(),
Actions\RestoreAction::make(),
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\DeviceMasterResource\Pages;
use App\Filament\Resources\DeviceMasterResource;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
class ListDeviceMasters extends ListRecords
{
protected static string $resource = DeviceMasterResource::class;
protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\DeviceMasterResource\Pages;
use App\Filament\Resources\DeviceMasterResource;
use Filament\Actions;
use Filament\Resources\Pages\ViewRecord;
class ViewDeviceMaster extends ViewRecord
{
protected static string $resource = DeviceMasterResource::class;
protected function getHeaderActions(): array
{
return [
Actions\EditAction::make(),
];
}
}

View File

@@ -0,0 +1,455 @@
<?php
namespace App\Filament\Resources;
use App\Filament\Exports\EbReadingExporter;
use App\Filament\Imports\EbReadingImporter;
use App\Filament\Resources\EbReadingResource\Pages;
use App\Filament\Resources\EbReadingResource\RelationManagers;
use App\Models\EbReading;
use App\Models\Plant;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Filament\Tables\Actions\ImportAction;
use Filament\Tables\Actions\ExportAction;
use Filament\Facades\Filament;
use Filament\Tables\Filters\Filter;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\DateTimePicker;
class EbReadingResource extends Resource
{
protected static ?string $model = EbReading::class;
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
protected static ?string $navigationGroup = 'Power House';
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\Select::make('plant_id')
->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::pluck('name', 'id')->toArray();
})
->required(),
Forms\Components\TextInput::make('lcd_segment_check')
->label('LCD Segment Check'),
Forms\Components\TextInput::make('meter_serial_no')
->label('Meter Serial No'),
Forms\Components\DateTimePicker::make('eb_date_time')
->required()
->label('EB Date Time'),
Forms\Components\TextInput::make('ph_seq_of_volt')
->label('PH Sequence of Volt'),
Forms\Components\TextInput::make('ph_assoc_conn_check')
->label('PH Association Connection Check'),
Forms\Components\TextInput::make('instantaneous_ph_volt')
->label('Instantaneous PH Volt'),
Forms\Components\TextInput::make('instantaneous_curr')
->label('Instantaneous Current'),
Forms\Components\TextInput::make('instantaneous_freq')
->label('Instantaneous Frequency'),
Forms\Components\TextInput::make('instantaneous_kw_with_sign')
->label('Instantaneous KW with Sign'),
Forms\Components\TextInput::make('instantaneous_kva')
->label('Instantaneous KVA'),
Forms\Components\TextInput::make('instantaneous_kv_ar')
->label('Instantaneous KV AR'),
Forms\Components\TextInput::make('instantaneous_pf_with_sign')
->label('Instantaneous PF with Sign'),
Forms\Components\TextInput::make('rd_with_elapsed_time_kva')
->label('RD with Elapsed Time KVA'),
Forms\Components\TextInput::make('cum_active_import_energy')
->label('Cumulative Active Import Energy'),
Forms\Components\TextInput::make('tod1_active_energy_6_9')
->label('TOD1 Active Energy 6-9'),
Forms\Components\TextInput::make('tod2_active_energy_18_21')
->label('TOD2 Active Energy 18-21'),
Forms\Components\TextInput::make('tod3_active_energy_21_22')
->label('TOD3 Active Energy 21-22'),
Forms\Components\TextInput::make('tod4_active_energy_5_6_9_18')
->label('TOD4 Active Energy 5-6-9-18'),
Forms\Components\TextInput::make('tod5_active_energy_22_5')
->label('TOD5 Active Energy 22-5'),
Forms\Components\TextInput::make('cum_reac_lag_energy')
->label('Cumulative Reactive Lag Energy'),
Forms\Components\TextInput::make('cum_reac_lead_energy')
->label('Cumulative Reactive Lead Energy'),
Forms\Components\TextInput::make('cum_appar_energy')
->label('Cumulative Apparent Energy'),
Forms\Components\TextInput::make('tod1_appar_energy_6_9')
->label('TOD1 Apparent Energy 6-9'),
Forms\Components\TextInput::make('tod2_appar_energy_18_21')
->label('TOD2 Apparent Energy 18-21'),
Forms\Components\TextInput::make('tod3_appar_energy_21_22')
->label('TOD3 Apparent Energy 21-22'),
Forms\Components\TextInput::make('tod4_appar_energy_5_6_9_18')
->label('TOD4 Apparent Energy 5-6-9-18'),
Forms\Components\TextInput::make('tod5_appar_energy_22_5')
->label('TOD5 Apparent Energy 22-5'),
Forms\Components\TextInput::make('avg_pow_factor')
->label('Average Power Factor'),
Forms\Components\TextInput::make('avg_freq_15min_last_ip')
->label('Average Frequency 15min Last IP'),
Forms\Components\TextInput::make('net_kv_arh_high')
->label('Net KV ARH High'),
Forms\Components\TextInput::make('net_kv_arh_low')
->label('Net KV ARH Low'),
Forms\Components\TextInput::make('cum_md_kva')
->label('Cumulative MD KVA'),
Forms\Components\TextInput::make('present_md_kva')
->label('Present MD KVA'),
Forms\Components\DateTimePicker::make('present_md_kva_date_time')
->label('Present MD KVA Date Time')
->required(),
Forms\Components\TextInput::make('tod1_md_kva_6_9')
->label('TOD1 MD KVA 6-9'),
Forms\Components\TextInput::make('tod2_md_kva_18_21')
->label('TOD2 MD KVA 18-21'),
Forms\Components\TextInput::make('tod3_md_kva_21_22')
->label('TOD3 MD KVA 21-22'),
Forms\Components\TextInput::make('tod4_md_kva_5_6_9_18')
->label('TOD4 MD KVA 5-6-9-18'),
Forms\Components\TextInput::make('tod5_md_kva_22_5')
->label('TOD5 MD KVA 22-5'),
Forms\Components\TextInput::make('total_pow_off_hours')
->label('Total Power Off Hours'),
Forms\Components\TextInput::make('programming_count')
->label('Programming Count'),
Forms\Components\TextInput::make('last_occ_res_event_type')
->label('Last Occurrence/Reset Event Type'),
Forms\Components\DateTimePicker::make('last_occ_res_event_date_time')
->label('Last Occurrence/Reset Event Date Time')
->required(),
Forms\Components\TextInput::make('tamper_count')
->label('Tamper Count'),
Forms\Components\TextInput::make('reset_count')
->label('Reset Count'),
Forms\Components\DateTimePicker::make('last_md_reset_date_time')
->label('Last MD Reset Date Time')
->required(),
Forms\Components\Hidden::make('electrician_sign')
->default(Filament::auth()->user()?->name),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('No.')
->label('No.')
->alignCenter()
->getStateUsing(function ($record, $livewire, $column, $rowLoop) {
$paginator = $livewire->getTableRecords();
$perPage = method_exists($paginator, 'perPage') ? $paginator->perPage() : 10;
$currentPage = method_exists($paginator, 'currentPage') ? $paginator->currentPage() : 1;
return ($currentPage - 1) * $perPage + $rowLoop->iteration;
}),
Tables\Columns\TextColumn::make('plant.name')
->label('Plant')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('lcd_segment_check')
->alignCenter()
->label('LCD Segment Check'),
Tables\Columns\TextColumn::make('meter_serial_no')
->alignCenter()
->label('Meter Serial No'),
Tables\Columns\TextColumn::make('eb_date_time')
->alignCenter()
->label('EB Date Time'),
Tables\Columns\TextColumn::make('ph_seq_of_volt')
->alignCenter()
->label('PH Sequence of Volt'),
Tables\Columns\TextColumn::make('ph_assoc_conn_check')
->alignCenter()
->label('PH Association Connection Check'),
Tables\Columns\TextColumn::make('instantaneous_ph_volt')
->alignCenter()
->label('Instantaneous PH Volt'),
Tables\Columns\TextColumn::make('instantaneous_curr')
->alignCenter()
->label('Instantaneous Current'),
Tables\Columns\TextColumn::make('instantaneous_freq')
->alignCenter()
->label('Instantaneous Frequency'),
Tables\Columns\TextColumn::make('instantaneous_kw_with_sign')
->alignCenter()
->label('Instantaneous KW with Sign'),
Tables\Columns\TextColumn::make('instantaneous_kva')
->alignCenter()
->label('Instantaneous KVA'),
Tables\Columns\TextColumn::make('instantaneous_kv_ar')
->alignCenter()
->label('Instantaneous KV AR'),
Tables\Columns\TextColumn::make('instantaneous_pf_with_sign')
->alignCenter()
->label('Instantaneous PF with Sign'),
Tables\Columns\TextColumn::make('rd_with_elapsed_time_kva')
->alignCenter()
->label('RD with Elapsed Time KVA'),
Tables\Columns\TextColumn::make('cum_active_import_energy')
->alignCenter()
->label('Cumulative Active Import Energy'),
Tables\Columns\TextColumn::make('tod1_active_energy_6_9')
->alignCenter()
->label('TOD1 Active Energy 6-9'),
Tables\Columns\TextColumn::make('tod2_active_energy_18_21')
->alignCenter()
->label('TOD2 Active Energy 18-21'),
Tables\Columns\TextColumn::make('tod3_active_energy_21_22')
->alignCenter()
->label('TOD3 Active Energy 21-22'),
Tables\Columns\TextColumn::make('tod4_active_energy_5_6_9_18')
->alignCenter()
->label('TOD4 Active Energy 5-6-9-18'),
Tables\Columns\TextColumn::make('tod5_active_energy_22_5')
->alignCenter()
->label('TOD5 Active Energy 22-5'),
Tables\Columns\TextColumn::make('cum_reac_lag_energy')
->alignCenter()
->label('Cumulative Reactive Lag Energy'),
Tables\Columns\TextColumn::make('cum_reac_lead_energy')
->alignCenter()
->label('Cumulative Reactive Lead Energy'),
Tables\Columns\TextColumn::make('cum_appar_energy')
->alignCenter()
->label('Cumulative Apparent Energy'),
Tables\Columns\TextColumn::make('tod1_appar_energy_6_9')
->alignCenter()
->label('TOD1 Apparent Energy 6-9'),
Tables\Columns\TextColumn::make('tod2_appar_energy_18_21')
->alignCenter()
->label('TOD2 Apparent Energy 18-21'),
Tables\Columns\TextColumn::make('tod3_appar_energy_21_22')
->alignCenter()
->label('TOD3 Apparent Energy 21-22'),
Tables\Columns\TextColumn::make('tod4_appar_energy_5_6_9_18')
->alignCenter()
->label('TOD4 Apparent Energy 5-6-9-18'),
Tables\Columns\TextColumn::make('tod5_appar_energy_22_5')
->alignCenter()
->label('TOD5 Apparent Energy 22-5'),
Tables\Columns\TextColumn::make('avg_pow_factor')
->alignCenter()
->label('Average Power Factor'),
Tables\Columns\TextColumn::make('avg_freq_15min_last_ip')
->alignCenter()
->label('Average Frequency 15min Last IP'),
Tables\Columns\TextColumn::make('net_kv_arh_high')
->alignCenter()
->label('Net KV ARH High'),
Tables\Columns\TextColumn::make('net_kv_arh_low')
->alignCenter()
->label('Net KV ARH Low'),
Tables\Columns\TextColumn::make('cum_md_kva')
->alignCenter()
->label('Cumulative MD KVA'),
Tables\Columns\TextColumn::make('present_md_kva')
->alignCenter()
->label('Present MD KVA'),
Tables\Columns\TextColumn::make('present_md_kva_date_time')
->alignCenter()
->label('Present MD KVA Date Time'),
Tables\Columns\TextColumn::make('tod1_md_kva_6_9')
->alignCenter()
->label('TOD1 MD KVA 6-9'),
Tables\Columns\TextColumn::make('tod2_md_kva_18_21')
->alignCenter()
->label('TOD2 MD KVA 18-21'),
Tables\Columns\TextColumn::make('tod3_md_kva_21_22')
->alignCenter()
->label('TOD3 MD KVA 21-22'),
Tables\Columns\TextColumn::make('tod4_md_kva_5_6_9_18')
->alignCenter()
->label('TOD4 MD KVA 5-6-9-18'),
Tables\Columns\TextColumn::make('tod5_md_kva_22_5')
->alignCenter()
->label('TOD5 MD KVA 22-5'),
Tables\Columns\TextColumn::make('total_pow_off_hours')
->alignCenter()
->label('Total Power Off Hours'),
Tables\Columns\TextColumn::make('programming_count')
->alignCenter()
->label('Programming Count'),
Tables\Columns\TextColumn::make('last_occ_res_event_type')
->alignCenter()
->label('Last Occurrence/Reset Event Type'),
Tables\Columns\TextColumn::make('last_occ_res_event_date_time')
->alignCenter()
->label('Last Occurrence/Reset Event Date Time'),
Tables\Columns\TextColumn::make('tamper_count')
->alignCenter()
->label('Tamper Count'),
Tables\Columns\TextColumn::make('reset_count')
->alignCenter()
->label('Reset Count'),
Tables\Columns\TextColumn::make('last_md_reset_date_time')
->alignCenter()
->label('Last MD Reset Date Time'),
Tables\Columns\TextColumn::make('electrician_sign')
->alignCenter()
->label('Created By'),
Tables\Columns\TextColumn::make('created_at')
->alignCenter()
->label('Created At')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('updated_at')
->dateTime()
->alignCenter()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('deleted_at')
->dateTime()
->alignCenter()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
// ->filters([
// Tables\Filters\TrashedFilter::make(),
// ])
->filters([
Tables\Filters\TrashedFilter::make(),
Filter::make('advanced_filters')
->label('Advanced Filters')
->form([
Select::make('Plant')
->label('Select Plant')
->nullable()
// ->options(function () {
// return 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();
})
->reactive()
->afterStateUpdated(function ($state, callable $set, callable $get) {
$set('electrician_sign', null);
}),
TextInput::make('electrician_sign')
->label('Created By'),
DateTimePicker::make(name: 'created_from')
->label('Created From')
->placeholder(placeholder: 'Select From DateTime')
->reactive()
->native(false),
DateTimePicker::make('created_to')
->label('Created To')
->placeholder(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['electrician_sign'])) {
return $query->whereRaw('1 = 0');
}
if (!empty($data['Plant'])) {
$query->where('plant_id', $data['Plant']);
}
if (!empty($data['created_from'])) {
$query->where('created_at', '>=', $data['created_from']);
}
if (!empty($data['created_to'])) {
$query->where('created_at', '<=', $data['created_to']);
}
if (!empty($data['electrician_sign'])) {
$query->where('electrician_sign', $data['electrician_sign']);
}
})
->indicateUsing(function (array $data) {
$indicators = [];
if (!empty($data['Plant'])) {
$indicators[] = 'Plant: ' . Plant::where('id', $data['Plant'])->value('name');
}
if (!empty($data['electrician_sign'])) {
$indicators[] = 'Created By: ' . $data['electrician_sign'];
}
if (!empty($data['created_from'])) {
$indicators[] = 'From: ' . $data['created_from'];
}
if (!empty($data['created_to'])) {
$indicators[] = 'To: ' . $data['created_to'];
}
return $indicators;
})
])
->filtersFormMaxHeight('280px')
->actions([
Tables\Actions\ViewAction::make(),
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
Tables\Actions\ForceDeleteBulkAction::make(),
Tables\Actions\RestoreBulkAction::make(),
]),
])
->headerActions([
ImportAction::make()
->label('Import EB Readings')
->color('warning')
->importer(EbReadingImporter::class)
->visible(function() {
return Filament::auth()->user()->can('view import eb reading');
}),
ExportAction::make()
->label('Export EB Readings')
->color('warning')
->exporter(EbReadingExporter::class)
->visible(function() {
return Filament::auth()->user()->can('view export eb reading');
}),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListEbReadings::route('/'),
'create' => Pages\CreateEbReading::route('/create'),
'view' => Pages\ViewEbReading::route('/{record}'),
'edit' => Pages\EditEbReading::route('/{record}/edit'),
];
}
public static function getEloquentQuery(): Builder
{
return parent::getEloquentQuery()
->withoutGlobalScopes([
SoftDeletingScope::class,
]);
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace App\Filament\Resources\EbReadingResource\Pages;
use App\Filament\Resources\EbReadingResource;
use Filament\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateEbReading extends CreateRecord
{
protected static string $resource = EbReadingResource::class;
protected function getRedirectUrl(): string
{
return $this->getResource()::getUrl('create');
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace App\Filament\Resources\EbReadingResource\Pages;
use App\Filament\Resources\EbReadingResource;
use Filament\Actions;
use Filament\Resources\Pages\EditRecord;
class EditEbReading extends EditRecord
{
protected static string $resource = EbReadingResource::class;
protected function getHeaderActions(): array
{
return [
Actions\ViewAction::make(),
Actions\DeleteAction::make(),
Actions\ForceDeleteAction::make(),
Actions\RestoreAction::make(),
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\EbReadingResource\Pages;
use App\Filament\Resources\EbReadingResource;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
class ListEbReadings extends ListRecords
{
protected static string $resource = EbReadingResource::class;
protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\EbReadingResource\Pages;
use App\Filament\Resources\EbReadingResource;
use Filament\Actions;
use Filament\Resources\Pages\ViewRecord;
class ViewEbReading extends ViewRecord
{
protected static string $resource = EbReadingResource::class;
protected function getHeaderActions(): array
{
return [
Actions\EditAction::make(),
];
}
}

View File

@@ -0,0 +1,514 @@
<?php
namespace App\Filament\Resources;
use App\Filament\Exports\EquipmentMasterExporter;
use App\Filament\Imports\EquipmentMasterImporter;
use App\Filament\Resources\EquipmentMasterResource\Pages;
use App\Filament\Resources\EquipmentMasterResource\RelationManagers;
use App\Models\EquipmentMaster;
use App\Models\Plant;
use Carbon\Carbon;
use Filament\Forms\Components\Actions\Action;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Filament\Facades\Filament;
use Filament\Notifications\Notification;
use Filament\Tables\Actions\ImportAction;
use Filament\Tables\Actions\ExportAction;
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
use Storage;
use Illuminate\Validation\Rule;
class EquipmentMasterResource extends Resource
{
protected static ?string $model = EquipmentMaster::class;
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
protected static ?string $navigationGroup = 'Testing Panel';
protected static ?int $navigationSort = 2;
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\Select::make('plant_id')
->label('Plant')
->reactive()
->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::pluck('name', 'id')->toArray();
})
->required(),
Forms\Components\Select::make('machine_id')
//->relationship('machine', 'name')
->label('Work Center')
->reactive()
->options(function (callable $get) {
$plantId = $get('plant_id');
if (empty($plantId)) {
return [];
}
return \App\Models\Machine::where('plant_id', $plantId)->pluck('work_center', 'id');
})
->required(),
Forms\Components\TextInput::make('name')
->label('Name'),
Forms\Components\TextInput::make('description')
->label('Description'),
Forms\Components\TextInput::make('make')
->label('Make'),
Forms\Components\TextInput::make('model')
->label('Model'),
Forms\Components\TextInput::make('equipment_number')
->label('Equipment Number')
->reactive()
->rules(function (callable $get) {
return [
Rule::unique('equipment_masters', 'equipment_number')
->where(function ($query) use ($get) {
return $query->where('plant_id', $get('plant_id'));
})
->ignore($get('id')),
];
})
->afterStateUpdated(function ($state, callable $set) {
if (! $state) {
return;
}
$model = EquipmentMaster::where('equipment_number', $state)->first();
if ($model?->attachment) {
$set('attachment', $model->attachment);
} else {
$set('attachment', null);
}
}),
//->afterStateUpdated(function ($state, callable $set) {
// if (! $state) {
// return;
// }
// $model = EquipmentMaster::where('equipment_number', $state)->first();
// if ($model?->attachment) {
// $set('attachment', $model->attachment);
// } else {
// $set('attachment', null);
// }
// }),
Forms\Components\TextInput::make('instrument_serial_number')
->label('Instrument Serial Number'),
// Forms\Components\DateTimePicker::make('calibrated_on')
// ->label('Calibrated On')
// ->required(),
// Forms\Components\TextInput::make('frequency')
// ->label('Frequency')
// ->required()
// ->numeric()
// ->default(1),
// Forms\Components\DateTimePicker::make('next_calibration_date')
// ->label('Next Calibration Date')
// ->required(),
Forms\Components\DateTimePicker::make('calibrated_on')
->label('Calibrated On')
->required()
->reactive()
->afterStateUpdated(function ($state, callable $set, callable $get) {
$frequency = $get('frequency') ?? '1';
$nextDate = self::calculateNextCalibrationDate($state, $frequency);
$set('next_calibration_date', $nextDate);
}),
// ->afterStateUpdated(function ($state, callable $get, callable $set) {
// $frequency = (int) $get('frequency');
// if ($state && $frequency != 0) {
// $calibratedOn = $state instanceof Carbon ? $state : Carbon::parse($state);
// $nextDate = $calibratedOn->copy()->addDays($frequency);
// $set('next_calibration_date', $nextDate);
// } else {
// $set('next_calibration_date', null);
// }
// }),
Forms\Components\TextInput::make('frequency')
->label('Frequency (days)')
->required()
->numeric()
->minValue(1)
->default(1)
->reactive()
->afterStateUpdated(function ($state, callable $set, callable $get) {
$calibratedOn = $get('calibrated_on');
$nextDate = self::calculateNextCalibrationDate($calibratedOn, $state);
$set('next_calibration_date', $nextDate);
}),
// ->afterStateUpdated(function ($state, callable $get, callable $set) {
// $calibratedOn = $get('calibrated_on');
// $frequency = (int) $state;
// if ($calibratedOn && $frequency !== 0) {
// $calibratedOn = $calibratedOn instanceof Carbon ? $calibratedOn : Carbon::parse($calibratedOn);
// $nextDate = $calibratedOn->copy()->addDays($frequency);
// $set('next_calibration_date', $nextDate);
// }
// else
// {
// $set('next_calibration_date', null);
// }
// }),
Forms\Components\DateTimePicker::make('next_calibration_date')
->label('Next Calibration Date')
->readOnly()
->required(),
Forms\Components\TextInput::make('calibrated_by')
->label('Calibrated By'),
Forms\Components\Textarea::make('calibration_certificate')
->label('Calibration Certificate'),
Forms\Components\FileUpload::make('attachment')
->label('PDF Upload')
->acceptedFileTypes(['application/pdf'])
->storeFiles(false)
->disk('local')
->directory('uploads/temp')
->preserveFilenames()
->reactive(),
// Forms\Components\Actions::make([
// Action::make('uploadNow')
// ->label('Upload PDF Now')
// ->action(function ($get, callable $set) {
// $uploadedFiles = $get('attachment');
// if (is_array($uploadedFiles) && count($uploadedFiles) > 0) {
// $uploaded = reset($uploadedFiles);
// if ($uploaded instanceof TemporaryUploadedFile) {
// $originalName = $uploaded->getClientOriginalName();
// $storedPath = $uploaded->storeAs(
// 'uploads/temp',
// $originalName,
// 'local'
// );
// }
// }
// }),
// ]),
// Forms\Components\Actions::make([
// Action::make('downloadAttachment')
// ->label('Download PDF')
// ->action(function ($get) {
// $uploadedFiles = $get('attachment');
// $equipmentNumber = $get('equipment_number');
// if (!$equipmentNumber) {
// Notification::make()
// ->title('No equipment number entered')
// ->danger()
// ->send();
// return;
// }
// $files = Storage::disk('local')->files('uploads/temp');
// $fileToDownload = null;
// foreach ($files as $file) {
// if (str_contains($file, $equipmentNumber)) {
// $fileToDownload = $file;
// break;
// }
// }
// if (!$fileToDownload) {
// Notification::make()
// ->title('PDF not found for this equipment')
// ->danger()
// ->send();
// return;
// }
// return response()->download(Storage::disk('local')->path($fileToDownload));
// }),
// ]),
Forms\Components\Actions::make([
Action::make('uploadNow')
->label('Upload PDF Now')
// ->action(function ($get, callable $set) {
// $uploadedFiles = $get('attachment');
// if (is_array($uploadedFiles) && count($uploadedFiles) > 0) {
// $uploaded = reset($uploadedFiles);
// if ($uploaded instanceof TemporaryUploadedFile) {
// $originalName = $uploaded->getClientOriginalName();
// $storedPath = $uploaded->storeAs(
// 'uploads/temp',
// $originalName,
// 'local'
// );
// }
// }
// }),
->action(function ($get, callable $set) {
$uploadedFiles = $get('attachment');
if (is_array($uploadedFiles) && count($uploadedFiles) > 0) {
$uploaded = reset($uploadedFiles);
if ($uploaded instanceof TemporaryUploadedFile) {
$originalName = $uploaded->getClientOriginalName();
$storedPath = $uploaded->storeAs(
'uploads/temp',
$originalName,
'local'
);
Notification::make()
->title('PDF uploaded successfully')
->success()
->send();
return;
}
}
else
{
Notification::make()
->title('No file selected to upload')
->warning()
->send();
return;
}
}),
Action::make('downloadAttachment')
->label('Download PDF')
->action(function ($get) {
$equipmentNumber = $get('equipment_number');
if (!$equipmentNumber) {
Notification::make()
->title('No equipment number entered')
->danger()
->send();
return;
}
$files = Storage::disk('local')->files('uploads/temp');
$fileToDownload = null;
foreach ($files as $file) {
if (str_contains($file, $equipmentNumber)) {
$fileToDownload = $file;
break;
}
}
if (!$fileToDownload) {
Notification::make()
->title('PDF not found for this equipment')
->danger()
->send();
return;
}
return response()->download(Storage::disk('local')->path($fileToDownload));
}),
])
->columns(2),
Forms\Components\Hidden::make('created_by')
->label('Created By')
->default(Filament::auth()->user()?->name),
Forms\Components\Hidden::make('updated_by')
->label('Updated By'),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('No.')
->label('No.')
->getStateUsing(function ($record, $livewire, $column, $rowLoop) {
$paginator = $livewire->getTableRecords();
$perPage = method_exists($paginator, 'perPage') ? $paginator->perPage() : 10;
$currentPage = method_exists($paginator, 'currentPage') ? $paginator->currentPage() : 1;
return ($currentPage - 1) * $perPage + $rowLoop->iteration;
}),
Tables\Columns\TextColumn::make('plant.name')
->label('Plant')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('machine.work_center')
->label('Work Center')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('name')
->label('Name')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('description')
->label('Description')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('make')
->label('Make')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('model')
->label('Model')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('equipment_number')
->label('Equipment Number')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('instrument_serial_number')
->label('Instrument Serial Number')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('calibrated_on')
->label('Calibrated On')
->alignCenter()
->dateTime()
->sortable(),
Tables\Columns\TextColumn::make('frequency')
->label('Frequency')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('next_calibration_date')
->label('Next Calibration Date')
->alignCenter()
->dateTime()
->sortable(),
Tables\Columns\TextColumn::make('calibrated_by')
->label('Calibrated By')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('calibration_certificate')
->label('Calibration Certificate')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('created_by')
->label('Created Bys')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('updated_by')
->label('Updated By')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('created_at')
->label('Created At')
->dateTime()
->alignCenter()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('updated_at')
->label('Updated At')
->dateTime()
->alignCenter()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
Tables\Filters\TrashedFilter::make(),
])
->actions([
Tables\Actions\ViewAction::make(),
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
Tables\Actions\ForceDeleteBulkAction::make(),
Tables\Actions\RestoreBulkAction::make(),
]),
])
->headerActions([
ImportAction::make()
->label('Import Equipment Masters')
->color('warning')
->importer(EquipmentMasterImporter::class)
->visible(function() {
return Filament::auth()->user()->can('view import equipment master');
}),
ExportAction::make()
->label('Export Equipment Masters')
->color('warning')
->exporter(EquipmentMasterExporter::class)
->visible(function() {
return Filament::auth()->user()->can('view export equipment master');
}),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListEquipmentMasters::route('/'),
'create' => Pages\CreateEquipmentMaster::route('/create'),
'view' => Pages\ViewEquipmentMaster::route('/{record}'),
'edit' => Pages\EditEquipmentMaster::route('/{record}/edit'),
];
}
public static function getEloquentQuery(): Builder
{
return parent::getEloquentQuery()
->withoutGlobalScopes([
SoftDeletingScope::class,
]);
}
protected static function calculateNextCalibrationDate(?string $startDateTime, ?string $durationDays): ?string
{
if (!$startDateTime || !$durationDays) {
return null;
}
try
{
$startDateTimeCarbon = Carbon::parse($startDateTime);
$durationDays = str_replace(',', '.', $durationDays);
if(!is_numeric($durationDays))
{
return null;
}
$nextCalibrationDate = $startDateTimeCarbon->addDays(floatval($durationDays));
return $nextCalibrationDate->format('Y-m-d H:i:s');
}
catch (\Exception $e)
{
return null;
}
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace App\Filament\Resources\EquipmentMasterResource\Pages;
use App\Filament\Resources\EquipmentMasterResource;
use Filament\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateEquipmentMaster extends CreateRecord
{
protected static string $resource = EquipmentMasterResource::class;
protected function getRedirectUrl(): string
{
return $this->getResource()::getUrl('create');
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace App\Filament\Resources\EquipmentMasterResource\Pages;
use App\Filament\Resources\EquipmentMasterResource;
use Filament\Actions;
use Filament\Resources\Pages\EditRecord;
class EditEquipmentMaster extends EditRecord
{
protected static string $resource = EquipmentMasterResource::class;
protected function getHeaderActions(): array
{
return [
Actions\ViewAction::make(),
Actions\DeleteAction::make(),
Actions\ForceDeleteAction::make(),
Actions\RestoreAction::make(),
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\EquipmentMasterResource\Pages;
use App\Filament\Resources\EquipmentMasterResource;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
class ListEquipmentMasters extends ListRecords
{
protected static string $resource = EquipmentMasterResource::class;
protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\EquipmentMasterResource\Pages;
use App\Filament\Resources\EquipmentMasterResource;
use Filament\Actions;
use Filament\Resources\Pages\ViewRecord;
class ViewEquipmentMaster extends ViewRecord
{
protected static string $resource = EquipmentMasterResource::class;
protected function getHeaderActions(): array
{
return [
Actions\EditAction::make(),
];
}
}

View File

@@ -0,0 +1,546 @@
<?php
namespace App\Filament\Resources;
use App\Filament\Exports\GrMasterExporter;
use App\Filament\Imports\GrMasterImporter;
use App\Filament\Resources\GrMasterResource\Pages;
use App\Filament\Resources\GrMasterResource\RelationManagers;
use App\Models\GrMaster;
use App\Models\Item;
use App\Models\Plant;
use Filament\Facades\Filament;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Filament\Notifications\Notification;
use Filament\Forms\Components\Actions\Action;
use Storage;
use Smalot\PdfParser\Parser;
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
use Filament\Tables\Actions\ImportAction;
use Filament\Tables\Actions\ExportAction;
use Illuminate\Validation\Rule;
use thiagoalessio\TesseractOCR\TesseractOCR;
use setasign\Fpdi\Fpdi;
use setasign\Fpdi\PdfReader;
use SimpleSoftwareIO\QrCode\Facades\QrCode;
class GrMasterResource extends Resource
{
protected static ?string $model = GrMaster::class;
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\Select::make('plant_id')
->label('Plant')
->reactive()
->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::pluck('name', 'id')->toArray();
})
->required(),
Forms\Components\Select::make('item_id')
->label('Item Code')
//->relationship('item', 'id')
->reactive()
->searchable()
->options(function (callable $get) {
$plantId = $get('plant_id');
if (empty($plantId)) {
return [];
}
return Item::where('plant_id', $plantId)->pluck('code', 'id');
})
->required(),
Forms\Components\TextInput::make('gr_number')
->label('GR Number')
->minLength(7)
->required(),
Forms\Components\TextInput::make('serial_number')
->label('Serial Number')
->rule(function (callable $get) {
return Rule::unique('gr_masters', 'serial_number')
->where('plant_id', $get('plant_id'))
->ignore($get('id')); // Ignore current record during updates
}),
Forms\Components\FileUpload::make('attachment')
->label('PDF Upload')
->acceptedFileTypes(['application/pdf'])
->storeFiles(false)
->disk('local')
->directory('uploads/temp')
->preserveFilenames()
->reactive(),
Forms\Components\Actions::make([
Action::make('uploadNow')
->label('Upload PDF Now')
->action(function ($get, callable $set) {
$uploadedFiles = $get('attachment');
if (is_array($uploadedFiles) && count($uploadedFiles) > 0)
{
$uploaded = reset($uploadedFiles);
if ($uploaded instanceof TemporaryUploadedFile) {
$grNumber = $get('gr_number');
$safeName = preg_replace('/[^A-Za-z0-9_\-]/', '_', $grNumber);
// $originalName = $uploaded->getClientOriginalName();
// $path = 'uploads/GRNumber/' . $originalName;
$finalFileName = $safeName . '.pdf';
$finalPath = 'uploads/GRNumber/' . $finalFileName;
if (Storage::disk('local')->exists($finalPath)) {
Notification::make()
->title('Duplicate File')
->body("The file '{$finalFileName}' already exists in uploads/GRNumber.")
->warning()
->send();
return; // Stop here
}
$storedPath = $uploaded->storeAs(
'uploads/GRNumber',
$finalFileName,
'local'
);
// $fullPath = storage_path('app/' . $storedPath);
$fullPath = storage_path('app/private/' . $storedPath);
$parser = new Parser();
//$pdf = $parser->parseContent(file_get_contents($uploaded->getRealPath()));
$pdf = $parser->parseFile($fullPath);
$text = $pdf->getText();
//dd($text);
if (preg_match('/Item code\s*:\s*(\S+)/i', $text, $matches)) {
$item1 = $matches[1];
}
// else if (preg_match('/E CODE\s*:\s*(\S+)/i', $text, $matches)) {
// $item2 = $matches[1];
// dd($item2);
// }
else
{
Notification::make()
->title('Item Code Not Found')
->body('Could not find Item code in uploaded PDF.')
->warning()
->send();
if (Storage::disk('local')->exists($storedPath)) {
Storage::disk('local')->delete($storedPath);
}
return;
}
$processOrder = $get('gr_number');
$itemId = $get('item_id');
$plant = $get('plant_id');
$item = Item::find($itemId);
$plant = Plant::find($plant);
if ($item)
{
$itemCode = $item->code;
}
else
{
$itemCode = null;
Notification::make()
->title('Item Not Found')
->body("Item not found in uploaded pdf.")
->warning()
->send();
if (Storage::disk('local')->exists($storedPath)) {
Storage::disk('local')->delete($storedPath);
}
return;
}
$storedPath = $uploaded->storeAs(
'uploads/GRNumber',
$finalFileName,
'local'
);
if($itemCode == $item1)
{
Notification::make()
->title('Success')
->body("Gr Number '$processOrder' PDF uploaded successfully.")
->success()
->send();
return;
}
else
{
Notification::make()
->title('Item Code not matched')
->body("Item Code: {$item->code} not matched with the uploaded pdf code $item1.")
->danger()
->send();
if (Storage::disk('local')->exists($storedPath)) {
Storage::disk('local')->delete($storedPath);
}
return;
}
}
}
else
{
Notification::make()
->title('No file selected to upload')
->warning()
->send();
return;
}
}),
// Action::make('uploadNow1')
// ->label('Upload OCR')
// ->action(function ($get, callable $set) {
// $uploadedFiles = $get('photo');
// if (is_array($uploadedFiles) && count($uploadedFiles) > 0)
// {
// $uploaded = reset($uploadedFiles);
// if ($uploaded instanceof TemporaryUploadedFile) {
// $grNumber = $get('gr_number');
// $safeName = preg_replace('/[^A-Za-z0-9_\-]/', '_', $grNumber);
// // $originalName = $uploaded->getClientOriginalName();
// // $path = 'uploads/GRNumber/' . $originalName;
// $finalFileName = $safeName . '.jpg';
// $finalPath = 'uploads/OCR/' . $finalFileName;
// // if (Storage::disk('local')->exists($finalPath)) {
// // Notification::make()
// // ->title('Duplicate File')
// // ->body("The file '{$finalFileName}' already exists in uploads/GRNumber.")
// // ->warning()
// // ->send();
// // return; // Stop here
// // }
// $storedPath = $uploaded->storeAs(
// 'uploads/OCR',
// $finalFileName,
// 'local'
// );
// // $storedPath = $uploaded->storeAs('uploads/OCR', $finalFileName, 'local');
// // $fullPath = storage_path('app/' . $storedPath);
// $storedPath = $uploaded->storeAs('uploads/OCR', $finalFileName, 'local');
// $fullPath = storage_path('app/private/' . $storedPath);
// $text = (new TesseractOCR($fullPath))->lang('eng')->run();
// $rawText = $text;
// preg_match_all('/\d+/', $rawText, $matches);
// $serialNumbers = $matches[0];
// $serialNumbers = array_slice($serialNumbers, 0, 4);
// //dd($serialNumbers);
// $processOrder = $get('gr_number');
// $itemId = $get('item_id');
// $plant = $get('plant_id');
// $item = Item::find($itemId);
// $plant = Plant::find($plant);
// $templatePath = storage_path('app/private/uploads/StickerTemplateOcr/multi.pdf');
// $outputPath = storage_path('app/private/uploads/StickerTemplateOcr/multi_filled.pdf');
// $storedPath = $uploaded->storeAs(
// 'uploads/GRNumber',
// $finalFileName,
// 'local'
// );
// $pdf = new Fpdi('P', 'mm', [90, 90]);
// $templateId = $pdf->setSourceFile($templatePath);
// $templatePage = $pdf->importPage(1);
// $pdf->AddPage();
// $pdf->useTemplate($templatePage, 0, 0, 90, 90);
// $pdf->SetFont('Helvetica', '', 10);
// $pdf->SetTextColor(0, 0, 0);
// $slots = [
// ['x' => 5.7, 'y' => 41.9, 'w' => 46.5, 'h' => 3.5], // 1st serial
// ['x' => 50, 'y' => 41.5, 'w' => 46.6, 'h' => 3.9], // 2nd serial
// ['x' => 5.7, 'y' => 60, 'w' => 46.5, 'h' => 3.5], // 3rd serial
// ['x' => 50, 'y' => 60, 'w' => 46.6, 'h' => 3.5], // 4rd serial
// ];
// $qrSlots = [
// ['x' => 17.3, 'y' => 29.2, 'size' => 11.4],
// ['x' => 61.5, 'y' => 29, 'size' => 11.5],
// ['x' => 17.7, 'y' => 46.7, 'size' => 11.4],
// ['x' => 61.7, 'y' => 46.7, 'size' => 11.4],
// ];
// // foreach ($serialNumbers as $i => $serial) {
// // if (isset($slots[$i])) {
// // $pdf->SetFillColor(255, 255, 255); // erase old serial
// // $pdf->Rect($slots[$i]['x'], $slots[$i]['y'], $slots[$i]['w'], $slots[$i]['h'], 'F');
// // $pdf->SetXY($slots[$i]['x'], $slots[$i]['y']);
// // // $pdf->Write(0, $serial);
// // $pdf->Cell($slots[$i]['w'], $slots[$i]['h'], $serial, 0, 0, 'L');
// // }
// // }
// // $pdf->Output('F', $outputPath);
// // return response()->download($outputPath);
// //
// // foreach ($serialNumbers as $i => $serial) {
// // if (!isset($slots[$i]) || !isset($qrSlots[$i])) continue;
// // //Generate QR code PNG temporarily
// // $qrPath = storage_path("app/private/uploads/QR/qr_$serial.png");
// // QrCode::format('png')->size(100)->generate($serial, $qrPath);
// // //Place QR code above serial
// // $pdf->Image($qrPath, $qrSlots[$i]['x'], $qrSlots[$i]['y'], $qrSlots[$i]['size'], $qrSlots[$i]['size']);
// // //Erase old serial
// // $pdf->SetFillColor(255, 255, 255);
// // $pdf->Rect($slots[$i]['x'], $slots[$i]['y'], $slots[$i]['w'], $slots[$i]['h'], 'F');
// // //Write new serial number
// // $pdf->SetXY($slots[$i]['x'], $slots[$i]['y']);
// // $pdf->Cell($slots[$i]['w'], $slots[$i]['h'], $serial, 0, 0, 'L');
// // }
// foreach ($serialNumbers as $i => $serial) {
// if (!isset($slots[$i]) || !isset($qrSlots[$i])) continue;
// // Erase old QR completely (slightly larger)
// $pdf->SetFillColor(255, 255, 255);
// $pdf->Rect($qrSlots[$i]['x']-1, $qrSlots[$i]['y']-1, $qrSlots[$i]['size']+2, $qrSlots[$i]['size']+2, 'F');
// // Generate new QR code
// $qrPath = storage_path("app/private/uploads/QR/qr_$serial.png");
// $qrDir = storage_path('app/private/uploads/QR');
// if (!file_exists($qrDir)) mkdir($qrDir, 0777, true);
// QrCode::format('png')->size(100)->generate($serial, $qrPath);
// // Place QR code
// $pdf->Image($qrPath, $qrSlots[$i]['x'], $qrSlots[$i]['y'], $qrSlots[$i]['size'], $qrSlots[$i]['size']);
// // Erase old serial
// $pdf->SetFillColor(255, 255, 255);
// $pdf->Rect($slots[$i]['x'], $slots[$i]['y'], $slots[$i]['w'], $slots[$i]['h'], 'F');
// // Write new serial
// $pdf->SetXY($slots[$i]['x'], $slots[$i]['y']);
// $pdf->Cell($slots[$i]['w'], $slots[$i]['h'], $serial, 0, 0, 'L');
// }
// // Save the final PDF
// $pdf->Output('F', $outputPath);
// // Download
// return response()->download($outputPath);
// }
// }
// else
// {
// Notification::make()
// ->title('No file selected to upload')
// ->warning()
// ->send();
// return;
// }
// }),
Action::make('downloadAttachment')
->label('Download PDF')
->action(function ($get) {
$equipmentNumber = $get('gr_number');
if (!$equipmentNumber) {
Notification::make()
->title('No GR Number entered')
->danger()
->send();
return;
}
$files = Storage::disk('local')->files('uploads/GRNumber');
$fileToDownload = null;
foreach ($files as $file) {
if (str_contains($file, $equipmentNumber)) {
$fileToDownload = $file;
break;
}
}
if (!$fileToDownload) {
Notification::make()
->title('PDF not found for this process order')
->danger()
->send();
return;
}
return response()->download(Storage::disk('local')->path($fileToDownload));
}),
]),
Forms\Components\Hidden::make('created_by')
->label('Created By')
->default(Filament::auth()->user()?->name),
Forms\Components\Hidden::make('updated_by')
->default(Filament::auth()->user()?->name),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('No.')
->label('No.')
->getStateUsing(function ($record, $livewire, $column, $rowLoop) {
$paginator = $livewire->getTableRecords();
$perPage = method_exists($paginator, 'perPage') ? $paginator->perPage() : 10;
$currentPage = method_exists($paginator, 'currentPage') ? $paginator->currentPage() : 1;
return ($currentPage - 1) * $perPage + $rowLoop->iteration;
}),
Tables\Columns\TextColumn::make('plant.name')
->label('Plant')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('item.code')
->label('Item Code')
->searchable()
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('gr_number')
->label('GR Number')
->alignCenter()
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('serial_number')
->label('Serial Number')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('created_by')
->label('Created By')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('status')
->label('Status')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('created_at')
->label('Created At')
->alignCenter()
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('updated_at')
->label('Updated At')
->alignCenter()
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('deleted_at')
->label('Deleted At')
->alignCenter()
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
Tables\Filters\TrashedFilter::make(),
])
->actions([
Tables\Actions\ViewAction::make(),
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
Tables\Actions\ForceDeleteBulkAction::make(),
Tables\Actions\RestoreBulkAction::make(),
]),
])
->headerActions([
ImportAction::make()
->label('Import GR Masters')
->color('warning')
->importer(GrMasterImporter::class)
->visible(function() {
return Filament::auth()->user()->can('view import gr master');
}),
ExportAction::make()
->label('Export GR Masters')
->color('warning')
->exporter(GrMasterExporter::class)
->visible(function() {
return Filament::auth()->user()->can('view export gr master');
}),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListGrMasters::route('/'),
'create' => Pages\CreateGrMaster::route('/create'),
'view' => Pages\ViewGrMaster::route('/{record}'),
'edit' => Pages\EditGrMaster::route('/{record}/edit'),
];
}
public static function getEloquentQuery(): Builder
{
return parent::getEloquentQuery()
->withoutGlobalScopes([
SoftDeletingScope::class,
]);
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace App\Filament\Resources\GrMasterResource\Pages;
use App\Filament\Resources\GrMasterResource;
use Filament\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateGrMaster extends CreateRecord
{
protected static string $resource = GrMasterResource::class;
}

View File

@@ -0,0 +1,22 @@
<?php
namespace App\Filament\Resources\GrMasterResource\Pages;
use App\Filament\Resources\GrMasterResource;
use Filament\Actions;
use Filament\Resources\Pages\EditRecord;
class EditGrMaster extends EditRecord
{
protected static string $resource = GrMasterResource::class;
protected function getHeaderActions(): array
{
return [
Actions\ViewAction::make(),
Actions\DeleteAction::make(),
Actions\ForceDeleteAction::make(),
Actions\RestoreAction::make(),
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\GrMasterResource\Pages;
use App\Filament\Resources\GrMasterResource;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
class ListGrMasters extends ListRecords
{
protected static string $resource = GrMasterResource::class;
protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\GrMasterResource\Pages;
use App\Filament\Resources\GrMasterResource;
use Filament\Actions;
use Filament\Resources\Pages\ViewRecord;
class ViewGrMaster extends ViewRecord
{
protected static string $resource = GrMasterResource::class;
protected function getHeaderActions(): array
{
return [
Actions\EditAction::make(),
];
}
}

View File

@@ -7,6 +7,7 @@ use App\Filament\Imports\GuardNameImporter;
use App\Filament\Resources\GuardNameResource\Pages;
use App\Filament\Resources\GuardNameResource\RelationManagers;
use App\Models\GuardName;
use App\Models\Plant;
use Filament\Facades\Filament;
use Filament\Forms;
use Filament\Forms\Form;
@@ -28,7 +29,7 @@ class GuardNameResource extends Resource
protected static ?string $navigationGroup = 'Master Entries';
protected static ?int $navigationSort = 13;
protected static ?int $navigationSort = 14;
public static function form(Form $form): Form
{
@@ -39,6 +40,10 @@ class GuardNameResource extends Resource
->relationship('plant', 'name')
->required()
->reactive()
->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();
})
->default(function () {
return optional(GuardName::latest()->first())->plant_id;
})
@@ -73,14 +78,14 @@ class GuardNameResource extends Resource
->ignore($get('id'));
}),
Forms\Components\TextInput::make('identification1')
->label('Identification-1')
->label('Aadhar Number')
->required()
->reactive()
->afterStateUpdated(function ($state, callable $set, callable $get) {
$set('created_by', Filament::auth()->user()?->name);
}),
Forms\Components\TextInput::make('identification2')
->label('Identification-2')
->label('PAN Number')
->reactive()
->afterStateUpdated(function ($state, callable $set, callable $get) {
$set('created_by', Filament::auth()->user()?->name);
@@ -161,11 +166,15 @@ class GuardNameResource extends Resource
])
->headerActions([
ImportAction::make()
->label('Import Guard Names')
->color('warning')
->importer(GuardNameImporter::class)
->visible(function() {
return Filament::auth()->user()->can('view import guard name');
}),
ExportAction::make()
->label('Export Guard Names')
->color('warning')
->exporter(GuardNameExporter::class)
->visible(function() {
return Filament::auth()->user()->can('view export guard name');

View File

@@ -52,6 +52,10 @@ class GuardPatrolEntryResource extends Resource
->relationship('plant', 'name')
->required()
->reactive()
->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();
})
->default(function () {
return optional(GuardPatrolEntry::where('created_by', Filament::auth()->user()?->name)->latest()->first())->plant_id;
})
@@ -279,8 +283,12 @@ class GuardPatrolEntryResource extends Resource
Select::make('Plant')
->label('Select Plant')
->nullable()
->options(function () {
return Plant::pluck('name', 'id');
// ->options(function () {
// return 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();
})
->reactive(),
// ->afterStateUpdated(function ($state, callable $set, callable $get) {
@@ -411,7 +419,11 @@ class GuardPatrolEntryResource extends Resource
->label('Import Guard Patrol Entries')
->form([
Select::make('plant_id')
->options(Plant::pluck('name', 'id')->toArray())
// ->options(Plant::pluck('name', 'id')->toArray())
->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();
})
->label('Select Plant')
->reactive()
->required()

View File

@@ -0,0 +1,622 @@
<?php
namespace App\Filament\Resources;
use App\Filament\Exports\InvoiceDataValidationExporter;
use App\Filament\Resources\InvoiceDataValidationResource\Pages;
use App\Filament\Resources\InvoiceDataValidationResource\RelationManagers;
use App\Models\InvoiceDataValidation;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Filament\Facades\Filament;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\Select;
use Filament\Notifications\Notification;
use App\Models\Plant;
use Filament\Forms\Get;
use Illuminate\Support\Facades\Storage;
use Maatwebsite\Excel\Facades\Excel;
use App\Models\StickerMaster;
use App\Models\User;
use DB;
use Filament\Tables\Actions\ExportAction;
class InvoiceDataValidationResource extends Resource
{
protected static ?string $model = InvoiceDataValidation::class;
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
protected static ?string $navigationGroup = 'Invoice Management';
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\Select::make('plant_id')
->label('Plant')
->relationship('plant', 'name')
->required(),
Forms\Components\TextInput::make('distribution_channel_desc')
->label('Distribution Channel Description')
->required(),
Forms\Components\TextInput::make('customer_code')
->label('Customer Code')
->required(),
Forms\Components\TextInput::make('document_number')
->label('Document Number')
->required(),
Forms\Components\DatePicker::make('document_date')
->label('Document Date')
->required(),
Forms\Components\TextInput::make('customer_trade_name')
->label('Customer Trade Name')
->required(),
Forms\Components\TextInput::make('customer_location')
->label('Customer Location')
->required(),
Forms\Components\TextInput::make('location')
->label('Location')
->required(),
Forms\Components\Hidden::make('created_by')
->label('Created By')
->default(Filament::auth()->user()?->name),
Forms\Components\Hidden::make('updated_by')
->default(Filament::auth()->user()?->name),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('No.')
->label('No.')
->getStateUsing(function ($record, $livewire, $column, $rowLoop) {
$paginator = $livewire->getTableRecords();
$perPage = method_exists($paginator, 'perPage') ? $paginator->perPage() : 10;
$currentPage = method_exists($paginator, 'currentPage') ? $paginator->currentPage() : 1;
return ($currentPage - 1) * $perPage + $rowLoop->iteration;
}),
Tables\Columns\TextColumn::make('plant.code')
->label('Plant')
->alignCenter()
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('distribution_channel_desc')
->label('Distribution Channel Description')
->alignCenter()
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('customer_code')
->label('Customer Code')
->alignCenter()
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('document_number')
->label('Document Number')
->searchable()
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('document_date')
->label('Document Date')
->alignCenter()
->searchable()
->date()
->sortable(),
Tables\Columns\TextColumn::make('customer_trade_name')
->label('Customer Trade Name')
->alignCenter()
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('customer_location')
->label('Customer Location')
->alignCenter()
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('location')
->label('Location')
->alignCenter()
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('created_at')
->label('Created At')
->alignCenter()
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('updated_at')
->label('Updated At')
->alignCenter()
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('deleted_at')
->label('Deleted At')
->alignCenter()
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
Tables\Filters\TrashedFilter::make(),
])
->actions([
Tables\Actions\ViewAction::make(),
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
Tables\Actions\ForceDeleteBulkAction::make(),
Tables\Actions\RestoreBulkAction::make(),
]),
])
->headerActions([
Tables\Actions\Action::make('Import Invoice Data')
->label('Import Invoice Data')
->form([
FileUpload::make('invoice_data_file')
->label('Invoice Data File')
// ->required()
->preserveFilenames()
->storeFiles(false)
->reactive()
->required()
->disk('local')
//->visible(fn (Get $get) => !empty($get('plant_id')))
->directory('uploads/temp'),
])
->action(function (array $data) {
$uploadedFile = $data['invoice_data_file'];
$disk = Storage::disk('local');
$user = Filament::auth()->user();
$operatorName = $user->name;
// Get original filename
$originalName = $uploadedFile->getClientOriginalName(); // e.g. 3RA0018732.xlsx
$originalNameOnly = pathinfo($originalName, PATHINFO_FILENAME);
// Store manually using storeAs to keep original name
$path = $uploadedFile->storeAs('uploads/temp', $originalName, 'local'); // returns relative path
$fullPath = Storage::disk('local')->path($path);
if ($fullPath && file_exists($fullPath))
{
$rows = Excel::toArray(null, $fullPath)[0];
if ((count($rows) - 1) <= 0)
{
Notification::make()
->title('Records Not Found')
->body("Import the valid 'Invoice Data' file to proceed..!")
->danger()
->send();
if ($disk->exists($path)) {
$disk->delete($path);
}
return;
}
$invalidPlantCode = [];
$invalidPlaCoFound = [];
$invalidDisChaDesc = [];
$invalidCustomerCode = [];
$invalidDocNo = [];
$invalidDocDate = [];
$invalidCusTradeName = [];
$invalidCusLocation = [];
$invalidUser = [];
$userNotFound = [];
$invalidPlantType = [];
$invalidLocation = [];
$seenPlantDoc = [];
//$duplicateEntries = [];
$duplicateEntriesExcel = [];
foreach ($rows as $index => $row)
{
if ($index == 0) continue; // Skip header
$DisChaDesc = trim($row[3]);
$plantCode = trim($row[4]);
$CustomerCode = trim($row[5]);
$DocNo = trim($row[6]);
$DocDate = trim($row[7]);
$CusTradeName = trim($row[9]);
$CusLocation = trim($row[10]);
$Location = trim($row[36]);
// if (empty($plantCode)) $invalidPlantCode[] = "Row {$index}";
if (empty($DisChaDesc)){
$invalidDisChaDesc[] = "Row {$index}";
}
if (empty($CustomerCode)){
$invalidCustomerCode[] = "Row {$index}";
}
if (empty($DocNo))
{
$invalidDocNo[] = "Row {$index}";
}
if (empty($CusTradeName))
{
$invalidCusTradeName[] = "Row {$index}";
}
if (empty($CusLocation))
{
$invalidCusLocation[] = "Row {$index}";
}
if (empty($Location))
{
$invalidLocation[] = "Row {$index}";
}
// if (empty($createdBy)) $invalidUser[] = "Row {$index}";
if (strlen($plantCode) < 4) {
$invalidPlantCode[] = $plantCode;
}
if (!is_numeric($plantCode)) {
$invalidPlantType[] = $plantCode;
}
else if (!Plant::where('code', $plantCode)->first())
{
$invalidPlaCoFound[] = $plantCode;
}
// --- Find Plant by code ---
$plant = Plant::where('code', $plantCode)->first();
// //Duplicate Check in DB ---
// $exists = InvoiceDataValidation::where('plant_id', $plant->id)
// ->where('document_number', $DocNo)
// ->first();
// if ($exists)
// {
// $duplicateEntries[] = "Duplicate record: Document Number '{$DocNo}' already exists for Plant '{$plant->name}'";
// }
//Also check duplicates within the same file ---
$uniqueKey = $plantCode . '_' . $DocNo;
if (in_array($uniqueKey, $seenPlantDoc)) {
$duplicateEntriesExcel[] = "Duplicate in file at Row {$index}: Document Number '{$DocNo}' already exists for Plant '{$plant->name}'";
}
$seenPlantDoc[] = $uniqueKey;
}
if (!empty($invalidCustomerCode) || !empty($invalidDocNo) || !empty($invalidDocDate) || !empty($invalidCusTradeName) || !empty($invalidCusLocation))
{
$errorMsg = '';
//if (!empty($invalidDisChaDesc)) $errorMsg .= 'Missing Distribution Channel Description in rows: ' . implode(', ', $invalidDisChaDesc) . '<br>';
if (!empty($invalidCustomerCode)) $errorMsg .= 'Missing Customer Code in rows: ' . implode(', ', $invalidCustomerCode) . '<br>';
if (!empty($invalidDocNo)) $errorMsg .= 'Missing Document Number in rows: ' . implode(', ', $invalidDocNo) . '<br>';
if (!empty($invalidDocDate)) $errorMsg .= 'Missing Document Date in rows: ' . implode(', ', $invalidDocDate) . '<br>';
if (!empty($invalidCusTradeName)) $errorMsg .= 'Missing Customer Trade Name in rows: ' . implode(', ', $invalidCusTradeName) . '<br>';
if (!empty($invalidCusLocation)) $errorMsg .= 'Missing Customer Location in rows: ' . implode(', ', $invalidCusLocation) . '<br>';
if (!empty($invalidLocation)) $errorMsg .= 'Missing Location in rows: ' . implode(', ', $invalidLocation) . '<br>';
Notification::make()
->title('Missing Mandatory Fields')
->body($errorMsg)
->danger()
->send();
if ($disk->exists($path)) {
$disk->delete($path);
}
return;
}
else if (!empty($invalidPlantCode))
{
$invalidPlantCode = array_unique($invalidPlantCode);
Notification::make()
->title('Invalid Plant Codes')
->body('The following plant codes should contain minimum 4 digits:<br>' . implode(', ', $invalidPlantCode))
->danger()
->send();
if ($disk->exists($path)) {
$disk->delete($path);
}
return;
}
else if (!empty($invalidPlantType))
{
$invalidPlantType = array_unique($invalidPlantType);
Notification::make()
->title('Invalid Plant Codes')
->body('The following plant codes should contain numeric values:<br>' . implode(', ', $invalidPlantType))
->danger()
->send();
if ($disk->exists($path)) {
$disk->delete($path);
}
return;
}
else if (!empty($invalidPlaCoFound))
{
$invalidPlaCoFound = array_unique($invalidPlaCoFound);
Notification::make()
->title('Invalid Plant Codes')
->body('The following plant codes not found in plants:<br>' . implode(', ', $invalidPlaCoFound))
->danger()
->send();
if ($disk->exists($path)) {
$disk->delete($path);
}
return;
}
// if (!empty($duplicateEntries))
// {
// $duplicateGroupedByPlant = [];
// foreach ($duplicateEntries as $message)
// {
// if (preg_match("/Document Number '([^']+)' already exists for Plant '([^']+)'/", $message, $matches)) {
// $docNo = $matches[1];
// $plantName = trim($matches[2]);
// $duplicateGroupedByPlant[$plantName][] = $docNo;
// }
// }
// $errorMsg = 'Duplicate Document Number found in Database :<br>';
// foreach ($duplicateGroupedByPlant as $plant => $docNumbers) {
// $count = count($docNumbers);
// if ($count > 10)
// {
// $errorMsg .= "Duplicate record(s) for Plant <b>{$plant}</b> : {$count} document numbers already exist in DB<br>";
// }
// else
// {
// $errorMsg .= "Duplicate record(s) for Plant <b>{$plant}</b> : "
// . implode(', ', $docNumbers)
// . " already exist<br>";
// }
// }
// Notification::make()
// //->title('Duplicate Entries in Database')
// ->body($errorMsg)
// ->danger()
// ->send();
// if ($disk->exists($path)) {
// $disk->delete($path);
// }
// return;
// }
if (!empty($duplicateEntriesExcel))
{
$duplicateGroupedByPlantExcel = [];
foreach ($duplicateEntriesExcel as $message) {//"/Document Number '([^']+)' already exist(?:s)?(?: for Plant (.+))?/"
if (preg_match("/Document Number '([^']+)' already exists for Plant '([^']+)'/", $message, $matches)) {
$docNo = $matches[1];
$plantName = $matches[2] ?? 'Unknown';
$duplicateGroupedByPlantExcel[$plantName][] = $docNo;
}
}
$errorMsg = 'Duplicate Document Number found in Uploaded File :<br>';
foreach ($duplicateGroupedByPlantExcel as $plant => $docNumbers)
{
// Remove duplicate document numbers for each plant
$uniqueDocNumbers = array_unique($docNumbers);
$count = count($uniqueDocNumbers);
if ($count > 10) {
$errorMsg .= "Duplicate Document Numbers for Plant <b>{$plant}</b> : {$count} Document Numbers already exist in uploaded file<br>";
} else {
$errorMsg .= "Duplicate Document Numbers for Plant <b>{$plant}</b> : '"
. implode(', ', $uniqueDocNumbers)
. "' already exist in uploaded file<br>";
}
}
Notification::make()
//->title('Duplicate Document Number in Uploaded File')
->body($errorMsg)
->danger()
->send();
if ($disk->exists($path)) {
$disk->delete($path);
}
return;
}
// if (!empty($duplicateEntriesExcel))
// {
// //$errorMsg = 'Duplicate Document Number found in the uploaded file:<br>' . implode('<br>', $duplicateEntriesExcel);
// $errorMsg = buildDuplicateMessage($duplicateEntriesExcel, 'Duplicate Document Number found in Uploaded File');
// Notification::make()
// ->title('Duplicate Document Number in Uploaded File')
// ->body($errorMsg)
$successCount = 0;
$failedRecords = [];
DB::beginTransaction();
try
{
foreach ($rows as $index => $row) {
if ($index == 0) continue;
$rowNumber = $index + 1;
try {
$DisChaDesc = trim($row[3]);
$plantCode = trim($row[4]);
$CustomerCode = trim($row[5]);
$DocNo = trim($row[6]);
$DocDate = trim($row[7]);
$CusTradeName = trim($row[9]);
$CusLocation = trim($row[10]);
$Location = trim($row[36]);
if (empty($DocNo)) {
throw new \Exception("Row '{$rowNumber}' Missing QR Code");
}
$plant = Plant::where('code', $plantCode)->first();
if (!$plant) {
throw new \Exception("Invalid plant code : '{$plantCode}'");
}
if (!empty($DocDate)) {
if (preg_match('/^\d{2}[-\/]\d{2}[-\/]\d{4}$/', $DocDate)) {
[$day, $month, $year] = preg_split('/[-\/]/', $DocDate);
$formattedDate = "{$year}-{$month}-{$day}";
} elseif (is_numeric($DocDate)) {
$formattedDate = \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($DocDate)->format('Y-m-d');
} else {
$formattedDate = date('Y-m-d', strtotime($DocDate));
}
} else {
$formattedDate = null;
}
$record = InvoiceDataValidation::where('plant_id', $plant->id)
->where('document_number', $DocNo)
->first();
$curStat = $record ? 'Updation' : 'Insertion';
if ($record) {
$record->update([
'distribution_channel_desc' => $DisChaDesc,
'customer_code' => $CustomerCode,
'document_date' => $formattedDate,
'customer_trade_name' => $CusTradeName,
'customer_location' => $CusLocation,
'location' => $Location,
'updated_by' => $operatorName
]);
$inserted = $record;
} else {
// Record does not exist, create with 'created_by'
$inserted = InvoiceDataValidation::create([
'plant_id' => $plant->id,
'document_number' => $DocNo,
'distribution_channel_desc' => $DisChaDesc,
'customer_code' => $CustomerCode,
'document_date' => $formattedDate,
'customer_trade_name' => $CusTradeName,
'customer_location' => $CusLocation,
'location' => $Location,
'created_by' => $operatorName
]);
}
// $inserted = InvoiceDataValidation::create([
// 'plant_id' => $plant->id,
// 'document_number' => $DocNo,
// 'distribution_channel_desc' => $DisChaDesc,
// 'customer_code' => $CustomerCode,
// 'document_date' => $formattedDate,
// 'customer_trade_name' => $CusTradeName,
// 'customer_location' => $CusLocation,
// 'created_by' => $operatorName
// ]);
if (!$inserted) {
throw new \Exception("{$curStat} failed for Document Number : {$DocNo}");
}
$successCount++;
} catch (\Exception $e) {
$failedRecords[] = [
'row' => $rowNumber,
'document_number' => $DocNo ?? null,
'error' => $e->getMessage()
];
}
}
DB::commit();
if (count($failedRecords) > 0) {
$failedSummary = collect($failedRecords)
->map(fn($f) => "Row {$f['row']} ({$f['document_number']}) : {$f['error']}")
->take(5) // limit preview to first 5 errors
->implode("\n");
Notification::make()
->title('Partial Import Warning')
->body("'{$successCount}' records inserted. " . count($failedRecords) . " failed.\n\n{$failedSummary}")
->warning()
->send();
} else {
Notification::make()
->title('Import Success')
->body("Successfully imported '{$successCount}' records.")
->success()
->send();
}
}
catch (\Exception $e)
{
DB::rollBack();
Notification::make()
->title('Import Failed')
->body("No records were inserted. Error : {$e->getMessage()}")
->danger()
->send();
}
}
})
->visible(function() {
return Filament::auth()->user()->can('view import invoice data validation');
}),
ExportAction::make()
->label('Export Invoice Data')
->color('warning')
->exporter(InvoiceDataValidationExporter::class)
->visible(function() {
return Filament::auth()->user()->can('view export invoice data validation');
}),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListInvoiceDataValidations::route('/'),
'create' => Pages\CreateInvoiceDataValidation::route('/create'),
'view' => Pages\ViewInvoiceDataValidation::route('/{record}'),
'edit' => Pages\EditInvoiceDataValidation::route('/{record}/edit'),
];
}
public static function getEloquentQuery(): Builder
{
return parent::getEloquentQuery()
->withoutGlobalScopes([
SoftDeletingScope::class,
]);
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace App\Filament\Resources\InvoiceDataValidationResource\Pages;
use App\Filament\Resources\InvoiceDataValidationResource;
use Filament\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateInvoiceDataValidation extends CreateRecord
{
protected static string $resource = InvoiceDataValidationResource::class;
}

View File

@@ -0,0 +1,22 @@
<?php
namespace App\Filament\Resources\InvoiceDataValidationResource\Pages;
use App\Filament\Resources\InvoiceDataValidationResource;
use Filament\Actions;
use Filament\Resources\Pages\EditRecord;
class EditInvoiceDataValidation extends EditRecord
{
protected static string $resource = InvoiceDataValidationResource::class;
protected function getHeaderActions(): array
{
return [
Actions\ViewAction::make(),
Actions\DeleteAction::make(),
Actions\ForceDeleteAction::make(),
Actions\RestoreAction::make(),
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\InvoiceDataValidationResource\Pages;
use App\Filament\Resources\InvoiceDataValidationResource;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
class ListInvoiceDataValidations extends ListRecords
{
protected static string $resource = InvoiceDataValidationResource::class;
protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\InvoiceDataValidationResource\Pages;
use App\Filament\Resources\InvoiceDataValidationResource;
use Filament\Actions;
use Filament\Resources\Pages\ViewRecord;
class ViewInvoiceDataValidation extends ViewRecord
{
protected static string $resource = InvoiceDataValidationResource::class;
protected function getHeaderActions(): array
{
return [
Actions\EditAction::make(),
];
}
}

View File

@@ -0,0 +1,537 @@
<?php
namespace App\Filament\Resources;
use App\Filament\Exports\InvoiceOutValidationExporter;
use App\Filament\Resources\InvoiceOutValidationResource\Pages;
use App\Filament\Resources\InvoiceOutValidationResource\RelationManagers;
use App\Models\InvoiceOutValidation;
use App\Models\Plant;
use App\Models\User;
use Carbon\Carbon;
use DB;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Filament\Facades\Filament;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\Section;
use Filament\Notifications\Notification;
use Maatwebsite\Excel\Facades\Excel;
use Storage;
use Filament\Tables\Actions\ExportAction;
use PhpOffice\PhpSpreadsheet\Shared\Date as ExcelDate;
class InvoiceOutValidationResource extends Resource
{
protected static ?string $model = InvoiceOutValidation::class;
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
protected static ?string $navigationGroup = 'Invoice Management';
public static function form(Form $form): Form
{
return $form
->schema([
Section::make('')
->schema([
Forms\Components\Select::make('plant_id')
->label('Plant')
->relationship('plant', 'name')
->required(),
Forms\Components\TextInput::make('qr_code')
->label('QR Code'),
Forms\Components\DateTimePicker::make('scanned_at')
->label('Scanned At'),
Forms\Components\TextInput::make('scanned_by')
->label('Scanned By'),
Forms\Components\Hidden::make('created_by')
->label('Created By')
->default(Filament::auth()->user()?->name),
Forms\Components\Hidden::make('updated_by')
->default(Filament::auth()->user()?->name),
])
->columns(4),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('No.')
->label('No.')
->getStateUsing(function ($record, $livewire, $column, $rowLoop) {
$paginator = $livewire->getTableRecords();
$perPage = method_exists($paginator, 'perPage') ? $paginator->perPage() : 10;
$currentPage = method_exists($paginator, 'currentPage') ? $paginator->currentPage() : 1;
return ($currentPage - 1) * $perPage + $rowLoop->iteration;
}),
Tables\Columns\TextColumn::make('plant.code')
->label('Plant')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('qr_code')
->label('QR Code')
->alignCenter()
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('scanned_at')
->label('Scanned At')
->searchable()
->alignCenter()
->dateTime()
->sortable(),
Tables\Columns\TextColumn::make('scanned_by')
->label('Scanned By')
->searchable()
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('created_at')
->searchable()
->dateTime()
->sortable(),
//->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('created_by')
->label('Created By')
->searchable()
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('updated_at')
->dateTime()
->searchable()
->sortable(),
// ->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('updated_by')
->label('Updated By')
->searchable()
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('deleted_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
Tables\Filters\TrashedFilter::make(),
])
->actions([
Tables\Actions\ViewAction::make(),
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
Tables\Actions\ForceDeleteBulkAction::make(),
Tables\Actions\RestoreBulkAction::make(),
]),
])
->headerActions([
Tables\Actions\Action::make('Import Invoice Out Data')
->label('Import Invoice Out Data')
->form([
FileUpload::make('invoice_data_file')
->label('Invoice Out Data')
// ->required()
->preserveFilenames()
->storeFiles(false)
->reactive()
->required()
->disk('local')
//->visible(fn (Get $get) => !empty($get('plant_id')))
->directory('uploads/temp'),
])
->action(function (array $data) {
$uploadedFile = $data['invoice_data_file'];
$disk = Storage::disk('local');
$user = Filament::auth()->user();
$operatorName = $user->name;
// Get original filename
$originalName = $uploadedFile->getClientOriginalName(); // e.g. 3RA0018732.xlsx
$originalNameOnly = pathinfo($originalName, PATHINFO_FILENAME);
// Store manually using storeAs to keep original name
$path = $uploadedFile->storeAs('uploads/temp', $originalName, 'local'); // returns relative path
$fullPath = Storage::disk('local')->path($path);
if ($fullPath && file_exists($fullPath))
{
$rows = Excel::toArray(null, $fullPath)[0];
if ((count($rows) - 1) <= 0)
{
Notification::make()
->title('Records Not Found')
->body("Import the valid 'Invoice Data' file to proceed..!")
->danger()
->send();
if ($disk->exists($path)) {
$disk->delete($path);
}
return;
}
$invalidPlantCode = [];
$invalidPlaCoFound = [];
$invalidqrCode = [];
$invalidScannedAt = [];
$invalidScannedBy = [];
$invalidUser = [];
$userNotFound = [];
$seenPlantQr = [];
$duplicateQrExcel = [];
//$duplicateQrDb = [];
foreach ($rows as $index => $row)
{
if ($index == 0) continue;
$qrCode = trim($row[1]);
$plantCode = trim($row[2]);
$scannedAt = trim($row[3]);
$scannedby = trim($row[4]);
if (empty($plantCode)) $invalidPlantCode[] = "Row {$index}";
if (empty($qrCode)) $invalidqrCode[] = "Row {$index}";
if (empty($scannedAt)) $invalidScannedAt[] = "Row {$index}";
if (empty($scannedby)) $invalidScannedBy[] = "Row {$index}";
if (strlen($plantCode) < 4) {
$invalidPlantCode[] = $plantCode;
}
else if(!Plant::where('code', $plantCode)->first())
{
$invalidPlaCoFound[] = $plantCode;
}
$plant = Plant::where('code', $plantCode)->first();
$plantId = $plant->id;
$uniqueKey = $plantCode . '_' . $qrCode;
if (in_array($uniqueKey, $seenPlantQr)) {
$duplicateQrExcel[] = "Duplicate in file at Row {$index}: Document Number '{$qrCode}' already exists for Plant '{$plant->name}'";
}
$seenPlantQr[] = $uniqueKey;
// $existsInDb = InvoiceOutValidation::where('plant_id', $plantId)
// ->where('qr_code', $qrCode)
// ->first();
// if ($existsInDb) {
// $duplicateQrDb[] = "Document Numbers '{$qrCode}' already exists in DB for Plant '{$plant->name}'";
// }
}
if (!empty($invalidqrCode) || !empty($invalidScannedAt) || !empty($invalidScannedBy) || !empty($invalidUser))
{
$errorMsg = '';
if (!empty($invalidqrCode)) $errorMsg .= 'Missing Qr code in rows: '.implode(', ', $invalidqrCode) . '<br>';
if (!empty($invalidScannedAt)) $errorMsg .= 'Missing Scanned At in rows: '.implode(', ', $invalidScannedAt) . '<br>';
if (!empty($invalidScannedBy)) $errorMsg .= 'Missing Scanned By in rows: '.implode(', ', $invalidScannedBy) . '<br>';
Notification::make()
->title('Missing Mandatory Fields')
->body($errorMsg)
->danger()
->send();
if ($disk->exists($path)) {
$disk->delete($path);
}
return;
}
if (!empty($invalidPlantCode)) {
$invalidPlantCode = array_unique($invalidPlantCode);
Notification::make()
->title('Invalid Plant Codes')
->body('The following plant codes should contain minimum 4 digits:<br>' . implode(', ', $invalidPlantCode))
->danger()
->send();
if ($disk->exists($path)) {
$disk->delete($path);
}
return;
}
if (!empty($invalidPlaCoFound)) {
$invalidPlaCoFound = array_unique($invalidPlaCoFound);
Notification::make()
->title('Invalid Plant Codes')
->body('The following plant codes not found in plants:<br>' . implode(', ', $invalidPlaCoFound))
->danger()
->send();
if ($disk->exists($path)) {
$disk->delete($path);
}
return;
}
if (!empty($userNotFound)) {
$userNotFound = array_unique($userNotFound);
Notification::make()
->title('Invalid User')
->body('The following user not found:<br>' . implode(', ', $userNotFound))
->danger()
->send();
if ($disk->exists($path)) {
$disk->delete($path);
}
return;
}
if (!empty($duplicateQrExcel))
{
$duplicateGroupedByPlantQr = [];
foreach ($duplicateQrExcel as $message) {//"/Document Numbers '([^']+)' already exists for Plant Code (\S+)/"
if (preg_match("/Document Number '([^']+)' already exists for Plant '([^']+)'/", $message, $matches)) {
$qrCode = $matches[1];
$plantCode = $matches[2];
$duplicateGroupedByPlantQr[$plantCode][] = $qrCode;
}
}
$errorMsg = 'Duplicate Document Number found in Uploaded File :<br>';
foreach ($duplicateGroupedByPlantQr as $plantCode => $qrCodes) {
$uniqueQrCodes = array_unique($qrCodes);
$count = count($uniqueQrCodes);
if ($count > 10) {
$errorMsg .= "Duplicate Document Numbers for Plant <b>{$plantCode}</b> : {$count} Document Numbers already exist in uploaded file<br>";
} else {
$errorMsg .= "Duplicate Document Numbers for Plant <b>{$plantCode}</b> : '"
. implode(', ', $uniqueQrCodes)
. "' already exist in uploaded file<br>";
}
}
Notification::make()
//->title('Duplicate Document Number in Uploaded File')
->body($errorMsg)
->danger()
->send();
if ($disk->exists($path)) {
$disk->delete($path);
}
return;
}
// if (!empty($duplicateQrDb)) {
// $duplicateGroupedByPlantDb = [];
// foreach ($duplicateQrDb as $message) {
// if (preg_match("/Document Numbers '([^']+)' already exists in DB for Plant '([^']+)'/", $message, $matches)) {
// $qrCode = $matches[1];
// $plantCode = $matches[2];
// $duplicateGroupedByPlantDb[$plantCode][] = $qrCode;
// }
// }
// $errorMsg = 'Duplicate Document Numbers found in Database:<br>';
// foreach ($duplicateGroupedByPlantDb as $plantCode => $qrCodes) {
// $uniqueQrCodes = array_unique($qrCodes);
// $count = count($uniqueQrCodes);
// if ($count > 10) {
// $errorMsg .= "Duplicate Document Numbers for Plant <b>{$plantCode}</b>: {$count} Document Numbers already exist in DB<br>";
// } else {
// $errorMsg .= "Duplicate Document Numbers for Plant <b>{$plantCode}</b>: "
// . implode(', ', $uniqueQrCodes)
// . " already exist in DB<br>";
// }
// }
// Notification::make()
// // ->title('Duplicate Document Numbers in Database')
// ->body($errorMsg)
// ->danger()
// ->send();
// if ($disk->exists($path)) {
// $disk->delete($path);
// }
// return;
// }
$successCount = 0;
$failedRecords = [];
DB::beginTransaction();
try
{
foreach ($rows as $index => $row) {
if ($index == 0) continue;
$rowNumber = $index + 1;
try {
$qrcode = trim($row[1]);
$plantCode = trim($row[2]);
$scannedAt = trim($row[3]);
$scannedBy = trim($row[4]);
if (empty($qrcode)) {
throw new \Exception("Row '{$rowNumber}' Missing QR Code");
}
$plant = Plant::where('code', $plantCode)->first();
if (!$plant) {
throw new \Exception("Invalid plant code : '{$plantCode}'");
}
$formattedDate = null;
if (!empty($scannedAt)) {
try {
// $formattedDate = Carbon::createFromFormat('d-m-Y H:i:s', $scannedAt)
// ->format('Y-m-d H:i:s');
if (is_numeric($scannedAt)) {
$formattedDate = ExcelDate::excelToDateTimeObject($scannedAt)
->format('Y-m-d H:i:s');
} else {
// Or handle as manual string date (d-m-Y H:i:s)
$formattedDate = Carbon::createFromFormat('d-m-Y H:i:s', $scannedAt)
->format('Y-m-d H:i:s');
}
} catch (\Exception $e) {
throw new \Exception("Invalid date format : '{$scannedAt}'");
}
}
$record = InvoiceOutValidation::where('plant_id', $plant->id)
->where('qr_code', $qrcode)
->first();
$curStat = $record ? 'Updation' : 'Insertion';
if ($record) {
$record->update([
'scanned_at' => $formattedDate,
'scanned_by' => $scannedBy,
'updated_by' => $operatorName
]);
$inserted = $record;
} else {
// Record does not exist, create with 'created_by'
$inserted = InvoiceOutValidation::create([
'plant_id' => $plant->id,
'qr_code' => $qrcode,
'scanned_at' => $formattedDate,
'scanned_by' => $scannedBy,
'created_by' => $operatorName
]);
}
// $inserted = InvoiceOutValidation::create([
// 'plant_id' => $plant->id,
// 'qr_code' => $qrcode,
// 'scanned_at' => $formattedDate,
// 'scanned_by' => $scannedBy,
// 'created_by' => $operatorName
// ]);
if (!$inserted) {
throw new \Exception("{$curStat} failed for QR : {$qrcode}");
}
$successCount++;
} catch (\Exception $e) {
$failedRecords[] = [
'row' => $rowNumber,
'qrcode' => $qrcode ?? null,
'error' => $e->getMessage()
];
}
}
DB::commit();
if (count($failedRecords) > 0) {
$failedSummary = collect($failedRecords)
->map(fn($f) => "Row {$f['row']} ({$f['qrcode']}) : {$f['error']}")
->take(5) // limit preview to first 5 errors
->implode("\n");
Notification::make()
->title('Partial Import Warning')
->body("'{$successCount}' records inserted. " . count($failedRecords) . " failed.\n\n{$failedSummary}")
->warning()
->send();
} else {
Notification::make()
->title('Import Success')
->body("Successfully imported '{$successCount}' records.")
->success()
->send();
}
}
catch (\Exception $e)
{
DB::rollBack();
Notification::make()
->title('Import Failed')
->body("No records were inserted. Error : {$e->getMessage()}")
->danger()
->send();
}
}
})
->visible(function() {
return Filament::auth()->user()->can('view import invoice out validation');
}),
ExportAction::make()
->label('Export Invoice Out Data')
->color('warning')
->exporter(InvoiceOutValidationExporter::class)
->visible(function() {
return Filament::auth()->user()->can('view export invoice out validation');
}),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListInvoiceOutValidations::route('/'),
'create' => Pages\CreateInvoiceOutValidation::route('/create'),
'view' => Pages\ViewInvoiceOutValidation::route('/{record}'),
'edit' => Pages\EditInvoiceOutValidation::route('/{record}/edit'),
];
}
public static function getEloquentQuery(): Builder
{
return parent::getEloquentQuery()
->withoutGlobalScopes([
SoftDeletingScope::class,
]);
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace App\Filament\Resources\InvoiceOutValidationResource\Pages;
use App\Filament\Resources\InvoiceOutValidationResource;
use Filament\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateInvoiceOutValidation extends CreateRecord
{
protected static string $resource = InvoiceOutValidationResource::class;
}

View File

@@ -0,0 +1,22 @@
<?php
namespace App\Filament\Resources\InvoiceOutValidationResource\Pages;
use App\Filament\Resources\InvoiceOutValidationResource;
use Filament\Actions;
use Filament\Resources\Pages\EditRecord;
class EditInvoiceOutValidation extends EditRecord
{
protected static string $resource = InvoiceOutValidationResource::class;
protected function getHeaderActions(): array
{
return [
Actions\ViewAction::make(),
Actions\DeleteAction::make(),
Actions\ForceDeleteAction::make(),
Actions\RestoreAction::make(),
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\InvoiceOutValidationResource\Pages;
use App\Filament\Resources\InvoiceOutValidationResource;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
class ListInvoiceOutValidations extends ListRecords
{
protected static string $resource = InvoiceOutValidationResource::class;
protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}

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