From 81dd189025d958c2d3a4d1069af95071b34969e0 Mon Sep 17 00:00:00 2001 From: WaseemAbbasi22 Date: Mon, 10 Nov 2025 10:33:45 +0300 Subject: [PATCH] internal audit api's implementation in progress --- lib/controllers/api_routes/urls.dart | 5 +- lib/main.dart | 4 +- .../models/audit_form_model.dart | 56 +++ .../equipment_internal_audit_data_model.dart | 10 +- .../models/internal_audit_timer_model.dart | 35 ++ .../system_internal_audit_data_model.dart | 122 +++++++ .../system_internal_audit_form_model.dart | 123 ++++++- .../equipment_internal_audit_detail_page.dart | 42 +-- .../equipment_internal_audit_item_view.dart | 1 - .../update_equipment_internal_audit_page.dart | 342 ++++++++++++++++++ .../create_system_internal_audit_form.dart | 58 +-- .../system_internal_audit_detail_page.dart | 20 +- .../system_internal_audit_item_view.dart | 1 - .../update_system_internal_audit_page.dart} | 32 +- .../provider/internal_audit_provider.dart | 65 ++++ .../tasks_wo/update_task_request_view.dart | 2 +- .../widgets/request_item_view_list.dart | 16 +- 17 files changed, 836 insertions(+), 98 deletions(-) create mode 100644 lib/modules/internal_audit_module/models/audit_form_model.dart create mode 100644 lib/modules/internal_audit_module/models/internal_audit_timer_model.dart create mode 100644 lib/modules/internal_audit_module/models/system_internal_audit_data_model.dart create mode 100644 lib/modules/internal_audit_module/pages/equipment_internal_audit/update_equipment_internal_audit_page.dart rename lib/modules/internal_audit_module/pages/{update_internal_audit_page.dart => system_internal_audit/update_system_internal_audit_page.dart} (89%) diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index dad15d8d..36d8e431 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -314,11 +314,14 @@ class URLs { //internal Audit static get getInternalAuditEquipmentById => "$_baseUrl/InternalAuditEquipments/GetInternalAuditEquipmentById"; - static get getInternalAuditSystemById => "$_baseUrl/InternalAuditSystems/GetInternalAuditSystemById"; + static get getInternalAuditSystemById => "$_baseUrl/InternalAuditSystems/GetInternalAuditSystemByIdV2"; static get getInternalAuditChecklist => "$_baseUrl/Lookups/GetLookup?lookupEnum=43"; static get getInternalAuditWoType => "$_baseUrl/Lookups/GetLookup?lookupEnum=2500"; static get getInternalAuditFindingType => "$_baseUrl/Lookups/GetLookup?lookupEnum=2502"; static get addOrUpdateEquipmentInternalAudit => "$_baseUrl/InternalAuditEquipments/AddOrUpdateAuditEquipment"; + static get addOrUpdateInternalAuditSystem => "$_baseUrl/InternalAuditSystems/AddOrUpdateInternalAuditSystem"; static get getWoAutoComplete => "$_baseUrl/InternalAuditSystems/AutoCompleteAllWorkOrder"; + static get updateAuditEquipmentsEngineer => "$_baseUrl/InternalAuditEquipments/UpdateAuditEquipmentsEngineer"; + static get loadAllWorkOrderDetailsByID => "$_baseUrl/InternalAuditSystems/LoadAllWorkOrderDetailsByID"; } diff --git a/lib/main.dart b/lib/main.dart index a2f9bdca..c5b39ef2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -103,7 +103,7 @@ import 'controllers/providers/api/gas_refill_comments.dart'; import 'controllers/providers/api/user_provider.dart'; import 'controllers/providers/settings/setting_provider.dart'; import 'dashboard_latest/dashboard_provider.dart'; -import 'modules/internal_audit_module/pages/update_internal_audit_page.dart'; +import 'modules/internal_audit_module/pages/equipment_internal_audit/update_equipment_internal_audit_page.dart'; import 'modules/internal_audit_module/provider/internal_audit_checklist_provider.dart'; import 'new_views/pages/gas_refill_request_form.dart'; import 'providers/lookups/classification_lookup_provider.dart'; @@ -365,7 +365,7 @@ class MyApp extends StatelessWidget { HelpCenterPage.id: (_) => const HelpCenterPage(), CreateEquipmentInternalAuditForm.id: (_) => const CreateEquipmentInternalAuditForm(), CreateSystemInternalAuditForm.id: (_) => const CreateSystemInternalAuditForm(), - UpdateInternalAuditPage.id: (_) => const UpdateInternalAuditPage(), + UpdateEquipmentInternalAuditPage.id: (_) => UpdateEquipmentInternalAuditPage(), // SwipeSuccessView.routeName: (_) => const SwipeSuccessView(), // SwipeHistoryView.routeName: (_) => const SwipeHistoryView(), }, diff --git a/lib/modules/internal_audit_module/models/audit_form_model.dart b/lib/modules/internal_audit_module/models/audit_form_model.dart new file mode 100644 index 00000000..dd3e6975 --- /dev/null +++ b/lib/modules/internal_audit_module/models/audit_form_model.dart @@ -0,0 +1,56 @@ +import 'package:test_sa/models/timer_model.dart'; +import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart'; + +class AuditFormModel { + int? id; + String? createdDate; + int? requestId; + String? debrief; + DateTime? startTime; + DateTime? endTime; + double? totalHours; + List? attachments; + bool? isComplete; + TimerModel? auditTimerModel = TimerModel(); + + AuditFormModel({ + this.id, + this.requestId, + this.debrief, + this.startTime, + this.endTime, + this.totalHours, + this.createdDate, + this.attachments, + this.isComplete, + this.auditTimerModel, + }); + + AuditFormModel.fromJson(Map json) { + id = json['id']; + requestId = json['requestId']; + debrief = json['debrief']; + startTime = json['startTime'] != null ? DateTime.tryParse(json['startTime']) : null; + endTime = json['endTime'] != null ? DateTime.tryParse(json['endTime']) : null; + totalHours = json['totalHours']?.toDouble(); + if (json['attachments'] != null) { + attachments = (json['attachments'] as List) + .map((e) => InternalAuditAttachments.fromJson(e)) + .toList(); + } + isComplete = json['isComplete']; + } + + Map toJson() { + return { + 'id': id, + 'requestId': requestId, + 'debrief': debrief, + 'startTime': startTime?.toIso8601String(), + 'endTime': endTime?.toIso8601String(), + 'totalHours': totalHours, + 'attachments': attachments?.map((e) => e.toJson()).toList(), + 'isComplete': isComplete, + }; + } +} \ No newline at end of file diff --git a/lib/modules/internal_audit_module/models/equipment_internal_audit_data_model.dart b/lib/modules/internal_audit_module/models/equipment_internal_audit_data_model.dart index 411789ec..be9c00bb 100644 --- a/lib/modules/internal_audit_module/models/equipment_internal_audit_data_model.dart +++ b/lib/modules/internal_audit_module/models/equipment_internal_audit_data_model.dart @@ -1,4 +1,8 @@ - class EquipmentInternalAuditDataModel { + import 'package:test_sa/models/timer_model.dart'; +import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart'; +import 'package:test_sa/modules/internal_audit_module/models/internal_audit_timer_model.dart'; + +class EquipmentInternalAuditDataModel { int? id; String? requestNo; String? createdDate; @@ -10,7 +14,7 @@ dynamic manufacture; String? remarks; List? equipmentsFindings; - List? attachments; + List? attachments; EquipmentInternalAuditDataModel({ this.id, @@ -44,7 +48,7 @@ equipmentsFindings!.add(EquipmentsFinding.fromJson(v)); }); } - attachments = json['attachments'] != null ? List.from(json['attachments']) : []; + // attachments = json['attachments'] != null ? List.from(json['attachments']) : []; } Map toJson() { diff --git a/lib/modules/internal_audit_module/models/internal_audit_timer_model.dart b/lib/modules/internal_audit_module/models/internal_audit_timer_model.dart new file mode 100644 index 00000000..708ab2d1 --- /dev/null +++ b/lib/modules/internal_audit_module/models/internal_audit_timer_model.dart @@ -0,0 +1,35 @@ +class InternalAuditTimerModel { + int? id; + String? startDate; + String? endDate; + double? totalWorkingHour; + String? comment; + + InternalAuditTimerModel({ + this.id, + this.startDate, + this.endDate, + this.totalWorkingHour, + this.comment, + }); + + factory InternalAuditTimerModel.fromJson(Map json) { + return InternalAuditTimerModel( + id: json['id'] as int?, + startDate: json['startDate'], + endDate: json['endDate'], + totalWorkingHour: (json['totalWorkingHours'] as num?)?.toDouble(), + comment: json['comment'] as String?, + ); + } + + Map toJson() { + return { + 'id': id, + 'startDate': startDate, + 'endDate': endDate, + 'totalWorkingHours': totalWorkingHour, + 'comment': comment, + }; + } +} \ No newline at end of file diff --git a/lib/modules/internal_audit_module/models/system_internal_audit_data_model.dart b/lib/modules/internal_audit_module/models/system_internal_audit_data_model.dart new file mode 100644 index 00000000..ae84e97f --- /dev/null +++ b/lib/modules/internal_audit_module/models/system_internal_audit_data_model.dart @@ -0,0 +1,122 @@ +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/modules/internal_audit_module/models/system_internal_audit_form_model.dart'; + +class SystemInternalAuditDataModel { + int? id; + int? assetGroupId; + String? requestNo; + int? requestNoSequence; + Auditor? auditor; + Lookup? status; + Lookup? findingType; + String? findingDescription; + Lookup? workOrderType; + Auditor? assignEmployee; + SystemAuditWorkOrderDetailModel? workOrderDetails; // Already exists as a separate model + String? createdBy; + String? createdDate; + String? modifiedBy; + String? modifiedDate; + + SystemInternalAuditDataModel({ + this.id, + this.assetGroupId, + this.requestNo, + this.requestNoSequence, + this.auditor, + this.status, + this.findingType, + this.findingDescription, + this.workOrderType, + this.assignEmployee, + this.workOrderDetails, + this.createdBy, + this.createdDate, + this.modifiedBy, + this.modifiedDate, + }); + + SystemInternalAuditDataModel.fromJson(Map json) { + id = json['id']; + assetGroupId = json['assetGroupId']; + requestNo = json['requestNo']; + requestNoSequence = json['requestNoSequence']; + auditor = json['auditor'] != null ? Auditor.fromJson(json['auditor']) : null; + status = json['status'] != null ? Lookup.fromJson(json['status']) : null; + findingType = json['findingType'] != null ? Lookup.fromJson(json['findingType']) : null; + findingDescription = json['findingDescription']; + workOrderType = json['workOrderType'] != null ? Lookup.fromJson(json['workOrderType']) : null; + assignEmployee = json['assignEmployee'] != null ? Auditor.fromJson(json['assignEmployee']) : null; + workOrderDetails = json['workOrderDetails'] != null ? SystemAuditWorkOrderDetailModel.fromJson(json['workOrderDetails']) : null; // Keep as-is + createdBy = json['createdBy']; + createdDate = json['createdDate']; + modifiedBy = json['modifiedBy']; + modifiedDate = json['modifiedDate']; + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['assetGroupId'] = assetGroupId; + data['requestNo'] = requestNo; + data['requestNoSequence'] = requestNoSequence; + if (auditor != null) data['auditor'] = auditor!.toJson(); + if (status != null) data['status'] = status!.toJson(); + if (findingType != null) data['findingType'] = findingType!.toJson(); + data['findingDescription'] = findingDescription; + if (workOrderType != null) data['workOrderType'] = workOrderType!.toJson(); + if (assignEmployee != null) data['assignEmployee'] = assignEmployee!.toJson(); + data['workOrderDetails'] = workOrderDetails; + data['createdBy'] = createdBy; + data['createdDate'] = createdDate; + data['modifiedBy'] = modifiedBy; + data['modifiedDate'] = modifiedDate; + return data; + } +} + +class Auditor { + String? userId; + String? userName; + String? email; + String? employeeId; + int? languageId; + String? extensionNo; + String? phoneNumber; + bool? isActive; + + Auditor({ + this.userId, + this.userName, + this.email, + this.employeeId, + this.languageId, + this.extensionNo, + this.phoneNumber, + this.isActive, + }); + + Auditor.fromJson(Map json) { + userId = json['userId']; + userName = json['userName']; + email = json['email']; + employeeId = json['employeeId']; + languageId = json['languageId']; + extensionNo = json['extensionNo']; + phoneNumber = json['phoneNumber']; + isActive = json['isActive']; + } + + Map toJson() { + final Map data = {}; + data['userId'] = userId; + data['userName'] = userName; + data['email'] = email; + data['employeeId'] = employeeId; + data['languageId'] = languageId; + data['extensionNo'] = extensionNo; + data['phoneNumber'] = phoneNumber; + data['isActive'] = isActive; + return data; + } +} diff --git a/lib/modules/internal_audit_module/models/system_internal_audit_form_model.dart b/lib/modules/internal_audit_module/models/system_internal_audit_form_model.dart index 9750e9e0..4082eb03 100644 --- a/lib/modules/internal_audit_module/models/system_internal_audit_form_model.dart +++ b/lib/modules/internal_audit_module/models/system_internal_audit_form_model.dart @@ -4,7 +4,7 @@ import 'dart:developer'; import 'package:test_sa/models/lookup.dart'; class SystemInternalAuditFormModel { - int? id = 0; + int? id; String? auditorId; String? assignEmployeeId; Lookup? findingType; @@ -18,6 +18,7 @@ class SystemInternalAuditFormModel { int? gasRefillId; int? planRecurrentTaskId; int? statusId; + SystemAuditWorkOrderDetailModel ?workOrderDetailModel; SystemInternalAuditFormModel({ this.id, @@ -33,12 +34,13 @@ class SystemInternalAuditFormModel { this.taskAlertJobId, this.gasRefillId, this.planRecurrentTaskId, + this.workOrderDetailModel, this.statusId, }); Map toJson() { return { - 'id': id, + // 'id': id, 'auditorId': auditorId, 'assignEmployeeId': assignEmployeeId, 'findingTypeId': findingType?.id, @@ -77,6 +79,123 @@ class WoAutoCompleteModel { return data; } } +class SystemAuditWorkOrderDetailModel { + String? createdBy; + DateTime? createdDate; + String? modifiedBy; + DateTime? modifiedDate; + int? id; + String? workOrderNo; + String? woAssignedEngineer; + String? woAssetNo; + String? wosn; + String? woAssetName; + String? woModel; + String? woManufacturer; + String? woSite; + String? woDepartment; + String? wOPMScheduleDate; + String? wOPMActualVisitDate; + String? wOAssetTransferDestinationSite; + String? wOAssetTransferSenderEngineer; + String? wOAssetTransferReceiverEngineer; + String? wOTaskAlertJobImpactedStatus; + String? wOTaskAlertJobAcknowledgment; + String? wOGasRefillType; + String? wORecurrentTaskTaskType; + String? wORecurrentTaskPlanNo; + String? wORecurrentTaskPlanName; + String? wORecurrentTaskStatus; + + SystemAuditWorkOrderDetailModel({ + this.createdBy, + this.createdDate, + this.modifiedBy, + this.modifiedDate, + this.id, + this.workOrderNo, + this.woAssignedEngineer, + this.woAssetNo, + this.wosn, + this.woAssetName, + this.woModel, + this.woManufacturer, + this.woSite, + this.woDepartment, + this.wOPMScheduleDate, + this.wOPMActualVisitDate, + this.wOAssetTransferDestinationSite, + this.wOAssetTransferSenderEngineer, + this.wOAssetTransferReceiverEngineer, + this.wOTaskAlertJobImpactedStatus, + this.wOTaskAlertJobAcknowledgment, + this.wOGasRefillType, + this.wORecurrentTaskTaskType, + this.wORecurrentTaskPlanNo, + this.wORecurrentTaskPlanName, + this.wORecurrentTaskStatus, + }); + + SystemAuditWorkOrderDetailModel.fromJson(Map json) { + createdBy = json['createdBy']; + createdDate = json['createdDate'] != null ? DateTime.tryParse(json['createdDate']) : null; + modifiedBy = json['modifiedBy']; + modifiedDate = json['modifiedDate'] != null ? DateTime.tryParse(json['modifiedDate']) : null; + id = json['id']; + workOrderNo = json['workOrderNo']; + woAssignedEngineer = json['woAssignedEngineer']; + woAssetNo = json['woAssetNo']; + wosn = json['wosn']; + woAssetName = json['woAssetName']; + woModel = json['woModel']; + woManufacturer = json['woManufacturer']; + woSite = json['woSite']; + woDepartment = json['woDepartment']; + wOPMScheduleDate = json['wO_PM_ScheduleDate']; + wOPMActualVisitDate = json['wO_PM_ActualVisitDate']; + wOAssetTransferDestinationSite = json['wO_AssetTransfer_DestinationSite']; + wOAssetTransferSenderEngineer = json['wO_AssetTransfer_SenderEngineer']; + wOAssetTransferReceiverEngineer = json['wO_AssetTransfer_ReceiverEngineer']; + wOTaskAlertJobImpactedStatus = json['wO_TaskAlertJob_ImpactedStatus']; + wOTaskAlertJobAcknowledgment = json['wO_TaskAlertJob_Acknowledgment']; + wOGasRefillType = json['wO_GasRefill_Type']; + wORecurrentTaskTaskType = json['wO_RecurrentTask_TaskType']; + wORecurrentTaskPlanNo = json['wO_RecurrentTask_PlanNo']; + wORecurrentTaskPlanName = json['wO_RecurrentTask_PlanName']; + wORecurrentTaskStatus = json['wO_RecurrentTask_Status']; + } + + Map toJson() { + return { + 'createdBy': createdBy, + 'createdDate': createdDate?.toIso8601String(), + 'modifiedBy': modifiedBy, + 'modifiedDate': modifiedDate?.toIso8601String(), + 'id': id, + 'workOrderNo': workOrderNo, + 'woAssignedEngineer': woAssignedEngineer, + 'woAssetNo': woAssetNo, + 'wosn': wosn, + 'woAssetName': woAssetName, + 'woModel': woModel, + 'woManufacturer': woManufacturer, + 'woSite': woSite, + 'woDepartment': woDepartment, + 'wO_PM_ScheduleDate': wOPMScheduleDate, + 'wO_PM_ActualVisitDate': wOPMActualVisitDate, + 'wO_AssetTransfer_DestinationSite': wOAssetTransferDestinationSite, + 'wO_AssetTransfer_SenderEngineer': wOAssetTransferSenderEngineer, + 'wO_AssetTransfer_ReceiverEngineer': wOAssetTransferReceiverEngineer, + 'wO_TaskAlertJob_ImpactedStatus': wOTaskAlertJobImpactedStatus, + 'wO_TaskAlertJob_Acknowledgment': wOTaskAlertJobAcknowledgment, + 'wO_GasRefill_Type': wOGasRefillType, + 'wO_RecurrentTask_TaskType': wORecurrentTaskTaskType, + 'wO_RecurrentTask_PlanNo': wORecurrentTaskPlanNo, + 'wO_RecurrentTask_PlanName': wORecurrentTaskPlanName, + 'wO_RecurrentTask_Status': wORecurrentTaskStatus, + }; + } +} diff --git a/lib/modules/internal_audit_module/pages/equipment_internal_audit/equipment_internal_audit_detail_page.dart b/lib/modules/internal_audit_module/pages/equipment_internal_audit/equipment_internal_audit_detail_page.dart index 6d842b29..5d788a6f 100644 --- a/lib/modules/internal_audit_module/pages/equipment_internal_audit/equipment_internal_audit_detail_page.dart +++ b/lib/modules/internal_audit_module/pages/equipment_internal_audit/equipment_internal_audit_detail_page.dart @@ -9,13 +9,13 @@ import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart'; import 'package:test_sa/modules/internal_audit_module/models/equipment_internal_audit_data_model.dart'; -import 'package:test_sa/modules/internal_audit_module/pages/update_internal_audit_page.dart'; +import 'package:test_sa/modules/internal_audit_module/pages/equipment_internal_audit/update_equipment_internal_audit_page.dart'; import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_provider.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; -import 'package:test_sa/views/widgets/images/files_list.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart'; +import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; class EquipmentInternalAuditDetailPage extends StatefulWidget { static const String id = "/details-internal-audit"; @@ -62,7 +62,8 @@ class _EquipmentInternalAuditDetailPageState extends State provider.isLoading, builder: (_, isLoading, __) { if (isLoading) return const ALoading(); - return Column( + if (model==null) return NoDataFound(message: context.translation.noDataFound).center; + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SingleChildScrollView( @@ -74,25 +75,24 @@ class _EquipmentInternalAuditDetailPageState extends State URLs.getFileUrl(e.attachmentName ?? '') ?? '').toList() ?? []), + //TODO need to check for attachments backend need to fix the name they are sending wrong string + // if (model!.attachments!.isNotEmpty) ...[ + // const Divider().defaultStyle(context), + // Text( + // "Attachments".addTranslation, + // style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + // ), + // 8.height, + // FilesList(images: model!.attachments!.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []), // ], ], ).paddingAll(0).toShadowContainer(context), @@ -104,7 +104,7 @@ class _EquipmentInternalAuditDetailPageState extends State UpdateEquipmentInternalAuditPage(model: model))); }), ), ], diff --git a/lib/modules/internal_audit_module/pages/equipment_internal_audit/equipment_internal_audit_item_view.dart b/lib/modules/internal_audit_module/pages/equipment_internal_audit/equipment_internal_audit_item_view.dart index 4c4bbb57..a17407a2 100644 --- a/lib/modules/internal_audit_module/pages/equipment_internal_audit/equipment_internal_audit_item_view.dart +++ b/lib/modules/internal_audit_module/pages/equipment_internal_audit/equipment_internal_audit_item_view.dart @@ -22,7 +22,6 @@ class EquipmentInternalAuditItemView extends StatelessWidget { @override Widget build(BuildContext context) { //TODO need to refactor this code repetation @waseem - log('request details ${requestDetails?.toJson()}'); if (requestData != null) { return Column( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/modules/internal_audit_module/pages/equipment_internal_audit/update_equipment_internal_audit_page.dart b/lib/modules/internal_audit_module/pages/equipment_internal_audit/update_equipment_internal_audit_page.dart new file mode 100644 index 00000000..02115d62 --- /dev/null +++ b/lib/modules/internal_audit_module/pages/equipment_internal_audit/update_equipment_internal_audit_page.dart @@ -0,0 +1,342 @@ +import 'dart:convert'; +import 'dart:developer'; +import 'dart:io'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/string_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/generic_attachment_model.dart'; +import 'package:test_sa/models/timer_model.dart'; +import 'package:test_sa/modules/cm_module/utilities/service_request_utils.dart'; +import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart'; +import 'package:test_sa/modules/internal_audit_module/models/audit_form_model.dart'; +import 'package:test_sa/modules/internal_audit_module/models/equipment_internal_audit_data_model.dart'; +import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart'; +import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_provider.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; +import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; +import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; +import 'package:test_sa/new_views/common_widgets/working_time_tile.dart'; +import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import 'package:test_sa/views/widgets/timer/app_timer.dart'; +import 'package:test_sa/views/widgets/total_working_time_detail_bottomsheet.dart'; + +class UpdateEquipmentInternalAuditPage extends StatefulWidget { + static const String id = "update-equipment-internal-audit"; + EquipmentInternalAuditDataModel? model; + + UpdateEquipmentInternalAuditPage({Key? key,this.model}) : super(key: key); + + @override + State createState() => _UpdateEquipmentInternalAuditPageState(); +} + +class _UpdateEquipmentInternalAuditPageState extends State { + final bool _isLoading = false; + double totalWorkingHours = 0.0; + AuditFormModel formModel = AuditFormModel(); + final TextEditingController _workingHoursController = TextEditingController(); + final GlobalKey _formKey = GlobalKey(); + final GlobalKey _scaffoldKey = GlobalKey(); + List _attachments = []; + //TODO need to check if it's needed or not.. + List timerList = []; + + @override + void initState() { + populateForm(); + super.initState(); + } + void populateForm(){ + formModel.requestId = widget.model?.id; + formModel.id = widget.model?.id; + _attachments = widget.model?.attachments?.map((e) => GenericAttachmentModel(id: e.id?.toInt()??0, name: e.name!)).toList() ?? []; + + } + void calculateWorkingTime() { + // final timers = _formModel.gasRefillTimers ?? []; + // totalWorkingHours = timers.fold(0.0, (sum, item) { + // if (item.startDate == null || item.endDate == null) return sum; + // try { + // final start = DateTime.parse(item.startDate!); + // final end = DateTime.parse(item.endDate!); + // final diffInHours = end.difference(start).inSeconds / 3600.0; // convert to hours + // return sum + diffInHours; + // } catch (_) { + // return sum; + // } + // }); + // + // timerList = timers.map((e) { + // return TimerHistoryModel( + // id: e.id, + // startTime: e.startDate, + // endTime: e.endDate, + // workingHours: e.workingHours, + // ); + // }).toList(); + } + + + _onSubmit(BuildContext context) async { + bool isTimerPickerEnable = ApiManager.instance.assetGroup?.enabledEngineerTimer ?? false; + InternalAuditProvider provider = Provider.of(context,listen: false); + + _formKey.currentState!.save(); + formModel.attachments = []; + for (var item in _attachments) { + String fileName = ServiceRequestUtils.isLocalUrl(item.name ?? '') + ? ("${item.name?.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") + : item.name ?? ''; + formModel.attachments!.add( + InternalAuditAttachments( + id: item.id, + originalName: fileName, + // name: fileName, + ), + ); + } + provider.updateEquipmentInternalAudit(model: formModel); + + log('payload ${formModel.toJson()}'); + + + + // if (isTimerPickerEnable) { + // if (_formModel.timer?.startAt == null && _formModel.gasRefillTimePicker == null) { + // Fluttertoast.showToast(msg: "Working Hours Required"); + // return false; + // } + // if (_formModel.gasRefillTimePicker == null) { + // if (_formModel.timer?.startAt == null) { + // Fluttertoast.showToast(msg: "Working Hours Required"); + // return false; + // } + // if (_formModel.timer?.endAt == null) { + // Fluttertoast.showToast(msg: "Please Stop The Timer"); + // return false; + // } + // } + // } else { + // if (_formModel.timer?.startAt == null) { + // Fluttertoast.showToast(msg: "Working Hours Required"); + // return false; + // } + // if (_formModel.timer?.endAt == null) { + // Fluttertoast.showToast(msg: "Please Stop The Timer"); + // return false; + // } + // } + // + // if (_currentDetails.deliverdQty == null) { + // await Fluttertoast.showToast(msg: "Delivered Quantity is Required"); + // return false; + // } + // _formModel.gasRefillDetails = []; + // _formModel.gasRefillDetails?.add(_currentDetails); + // + // showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); + // _formModel.gasRefillTimers = _formModel.gasRefillTimers ?? []; + // if (_formModel.gasRefillTimePicker != null) { + // int durationInSecond = _formModel.gasRefillTimePicker!.endAt!.difference(_formModel.gasRefillTimePicker!.startAt!).inSeconds; + // _formModel.gasRefillTimers?.add( + // GasRefillTimer( + // id: 0, + // startDate: _formModel.gasRefillTimePicker!.startAt!.toIso8601String(), // Handle potential null + // endDate: _formModel.gasRefillTimePicker!.endAt?.toIso8601String(), // Handle potential null + // workingHours: ((durationInSecond) / 60 / 60), + // ), + // ); + // } + // _formModel.timerModelList?.forEach((timer) { + // int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds; + // _formModel.gasRefillTimers?.add( + // GasRefillTimer( + // id: 0, + // startDate: timer.startAt!.toIso8601String(), // Handle potential null + // endDate: timer.endAt?.toIso8601String(), // Handle potential null + // workingHours: ((durationInSecond) / 60 / 60), + // ), + // ); + // }); + // _formModel.gasRefillAttachments = []; + // for (var item in _attachments) { + // String fileName = ServiceRequestUtils.isLocalUrl(item.name??'') ? ("${item.name??''.split("/").last}|${base64Encode(File(item.name??'').readAsBytesSync())}") :item.name??''; + // _formModel.gasRefillAttachments?.add(GasRefillAttachments( + // id: item.id, gasRefillId: _formModel.id ?? 0, attachmentName: fileName)); + // } + + // await _gasRefillProvider?.updateGasRefill(status: status, model: _formModel).then((success) { + // Navigator.pop(context); + // if (success) { + // if (status == 1) { + // AllRequestsProvider allRequestsProvider = Provider.of(context, listen: false); + // // when click complete then this request remove from the list and status changes to closed.. + // _gasRefillProvider?.reset(); + // allRequestsProvider.getAllRequests(context, typeTransaction: 2); + // } + // Navigator.pop(context); + // } + // }); + } + + @override + void dispose() { + _workingHoursController.dispose(); + super.dispose(); + } + + void updateTimer({TimerModel? timer}) { + if (timer?.startAt != null && timer?.endAt != null) { + final start = timer!.startAt!; + final end = timer.endAt!; + + final difference = end.difference(start); + final totalHours = difference.inSeconds / 3600.0; + formModel.startTime = start; + formModel.endTime = end; + formModel.totalHours = totalHours; + } + } + + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: DefaultAppBar( + title: 'Update Information'.addTranslation, + onWillPopScope: () { + formModel.isComplete = false; + _onSubmit(context); + }, + ), + key: _scaffoldKey, + body: Form( + key: _formKey, + child: LoadingManager( + isLoading: _isLoading, + isFailedLoading: false, + stateCode: 200, + onRefresh: () async {}, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + 8.height, + AppTextFormField( + labelText: 'Debrief'.addTranslation, + textInputType: TextInputType.multiline, + hintStyle: TextStyle(color: context.isDark ? AppColor.white10 : AppColor.black10), + labelStyle: TextStyle(color: context.isDark ? AppColor.white10 : AppColor.black10), + alignLabelWithHint: true, + initialValue: formModel.debrief, + backgroundColor: AppColor.fieldBgColor(context), + showShadow: false, + onSaved: (value) { + formModel.debrief = value; + }, + ), + 8.height, + _timerWidget(context, totalWorkingHours), + 16.height, + AttachmentPicker( + label: context.translation.attachFiles, + attachment: _attachments, + buttonColor: AppColor.primary10, + onlyImages: false, + buttonIcon: 'image-plus'.toSvgAsset( + color: AppColor.primary10, + ), + ), + 8.height, + ], + ).toShadowContainer(context), + ).expanded, + FooterActionButton.footerContainer( + context: context, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + AppFilledButton( + label: context.translation.save, + buttonColor: context.isDark ? AppColor.neutral70 : AppColor.white60, + textColor: context.isDark ? AppColor.white10 : AppColor.black10, + onPressed: (){ + formModel.isComplete = false; + _onSubmit(context); + } + ).expanded, + 12.width, + AppFilledButton( + label: context.translation.complete, + buttonColor: AppColor.primary10, + onPressed: (){ + formModel.isComplete = true; + _onSubmit(context); + } + ).expanded, + ], + ), + ), + ], + )), + ), + ).handlePopScope( + cxt: context, + onSave: () { + formModel.isComplete=false; + _onSubmit(context); + }); + } + + Widget _timerWidget(BuildContext context, double totalWorkingHours) { + TimerModel? timer = TimerModel(); + TimerModel? timerPicker; + List? timerModelList = []; + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + AppTimer( + label: context.translation.workingHours, + timer: timer, + pickerFromDate: DateTime.tryParse(widget.model?.createdDate ?? ''), + pickerTimer: timerPicker, + onPick: (time) { + updateTimer(timer: timer); + + }, + width: double.infinity, + decoration: BoxDecoration( + color: AppColor.fieldBgColor(context), + borderRadius: BorderRadius.circular(10), + ), + timerProgress: (isRunning) {}, + onChange: (timer) async { + updateTimer(timer: timer); + log('here onChange ${timer.startAt}'); + + return true; + }, + ), + if (totalWorkingHours > 0.0) ...[ + 12.height, + WorkingTimeTile( + timerList: timerList, + totalWorkingTime: totalWorkingHours, + ), + ], + ], + ); + } +} diff --git a/lib/modules/internal_audit_module/pages/system_internal_audit/create_system_internal_audit_form.dart b/lib/modules/internal_audit_module/pages/system_internal_audit/create_system_internal_audit_form.dart index 64e8408b..a443588d 100644 --- a/lib/modules/internal_audit_module/pages/system_internal_audit/create_system_internal_audit_form.dart +++ b/lib/modules/internal_audit_module/pages/system_internal_audit/create_system_internal_audit_form.dart @@ -91,7 +91,8 @@ class _CreateSystemInternalAuditFormState extends State(context, listen: false); + setState(() { + showLoading = true; + }); + _model.workOrderDetailModel = await provider.loadAllWorkOrderDetailsByID(workOrderId: wo.id!, workOrderTypeId: _model.workOrderType!.value!); + updateWorkOrderReference(woTypeId: _model.workOrderType?.value, selectedId: wo.id); + + setState(() { + showLoading = false; + }); }, ), 12.height, @@ -166,14 +175,16 @@ class _CreateSystemInternalAuditFormState extends State _submit() async { + InternalAuditProvider internalAuditProvider = Provider.of(context, listen: false); if (_formKey.currentState!.validate()) { _formKey.currentState!.save(); - List attachement = []; - for (var item in _deviceImages) { - String fileName = ServiceRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? ''; - // attachement.add(WorkOrderAttachments(id: 0, name: fileName)); + showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); + _model.auditorId = context.userProvider.user?.userID; + bool status = await internalAuditProvider.addSystemInternalAudit(context: context, request: _model); + Navigator.pop(context); + if (status) { + Navigator.pop(context); } - // showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); } } @@ -193,7 +204,7 @@ class _CreateSystemInternalAuditFormState extends State { bool isWoType = true; + // EquipmentInternalAuditDataModel? model; + late InternalAuditProvider _internalAuditProvider; @override void initState() { super.initState(); - //TODO need to get and assign data . - // Provider.of(context, listen: false).getInternalAuditById(widget.auditId); + _internalAuditProvider = Provider.of(context, listen: false); + WidgetsBinding.instance.addPostFrameCallback((_) { + getAuditData(); + }); + } + + Future getAuditData() async { + await _internalAuditProvider.getInternalSystemAuditById(widget.auditId); } @override @@ -69,7 +77,7 @@ class _SystemInternalAuditDetailPageState extends State URLs.getFileUrl(e.attachmentName ?? '') ?? '').toList() ?? []), @@ -94,7 +102,7 @@ class _SystemInternalAuditDetailPageState extends State { final bool _isLoading = false; double totalWorkingHours = 0.0; late UserProvider _userProvider; - - // GasRefillDetails _currentDetails = GasRefillDetails(); final TextEditingController _commentController = TextEditingController(); final TextEditingController _workingHoursController = TextEditingController(); - - // final GasRefillModel _formModel = GasRefillModel(gasRefillDetails: []); final GlobalKey _formKey = GlobalKey(); final GlobalKey _scaffoldKey = GlobalKey(); bool _firstTime = true; @@ -51,18 +49,6 @@ class _UpdateInternalAuditPageState extends State { @override void initState() { super.initState(); - // if (widget.gasRefillModel != null) { - // _formModel.fromGasRefillModel(widget.gasRefillModel!); - // _commentController.text = _formModel.techComment ?? ""; - // calculateWorkingTime(); - // try { - // _deliveredQuantity = deliveredQuantity.singleWhere((element) => element.value == _formModel.gasRefillDetails![0].deliverdQty); - // _currentDetails.deliverdQty = _deliveredQuantity!.value; - // } catch (ex) {} - // } - // if (_formModel.gasRefillAttachments != null && _formModel.gasRefillAttachments!.isNotEmpty) { - // _attachments.addAll(_formModel.gasRefillAttachments!.map((e) => GenericAttachmentModel(id:e.id,name:e.attachmentName!)).toList()); - // } } void calculateWorkingTime() { @@ -194,16 +180,6 @@ class _UpdateInternalAuditPageState extends State { @override Widget build(BuildContext context) { _userProvider = Provider.of(context); - if (_firstTime) { - String? clientName; - // if (widget.gasRefillModel != null) { - // _gasRefillProvider!.expectedDateTime = DateTime.tryParse(_formModel.expectedDate ?? ""); - // _formModel.timer = TimerModel(startAt: DateTime.tryParse(widget.gasRefillModel?.startDate ?? ""), endAt: DateTime.tryParse(widget.gasRefillModel?.endDate ?? "")); - // } else { - // _formModel.timer = null; - // } - } - return Scaffold( appBar: DefaultAppBar( title: 'Update Information'.addTranslation, diff --git a/lib/modules/internal_audit_module/provider/internal_audit_provider.dart b/lib/modules/internal_audit_module/provider/internal_audit_provider.dart index 6f2a9b9d..314fb2d9 100644 --- a/lib/modules/internal_audit_module/provider/internal_audit_provider.dart +++ b/lib/modules/internal_audit_module/provider/internal_audit_provider.dart @@ -10,6 +10,7 @@ import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/models/device/asset_search.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/new_models/asset_nd_auto_complete_by_dynamic_codes_model.dart'; +import 'package:test_sa/modules/internal_audit_module/models/audit_form_model.dart'; import 'package:test_sa/modules/internal_audit_module/models/equipment_internal_audit_data_model.dart'; import 'package:test_sa/modules/internal_audit_module/models/equipment_internal_audit_form_model.dart'; import 'package:test_sa/modules/internal_audit_module/models/system_internal_audit_form_model.dart'; @@ -71,6 +72,47 @@ class InternalAuditProvider extends ChangeNotifier { return -1; } } + Future loadAllWorkOrderDetailsByID({required int workOrderTypeId,required int workOrderId}) async { + try { + isLoading = true; + notifyListeners(); + Response response = await ApiManager.instance.get("${URLs.loadAllWorkOrderDetailsByID}?workOrderTypeId=$workOrderTypeId&workOrderId=$workOrderId"); + if (response.statusCode >= 200 && response.statusCode < 300) { + final decodedBody = jsonDecode(response.body); + SystemAuditWorkOrderDetailModel model = SystemAuditWorkOrderDetailModel.fromJson(decodedBody["data"]); + isLoading = false; + notifyListeners(); + return model; + } else { + isLoading = false; + notifyListeners(); + return null; + } + } catch (error) { + isLoading = false; + notifyListeners(); + return null; + } + } + Future updateEquipmentInternalAudit({required AuditFormModel model}) async { + isLoading = true; + Response response; + try { + response = await ApiManager.instance.put(URLs.updateAuditEquipmentsEngineer, body: model.toJson()); + stateCode = response.statusCode; + isLoading = false; + notifyListeners(); + if (stateCode == 200) { + return true; + } + return false; + } catch (error) { + isLoading = false; + stateCode = -1; + notifyListeners(); + return false; + } + } Future addEquipmentInternalAudit({ required BuildContext context, @@ -95,6 +137,29 @@ class InternalAuditProvider extends ChangeNotifier { return status; } } + Future addSystemInternalAudit({ + required BuildContext context, + required SystemInternalAuditFormModel request, + }) async { + bool status = false; + Response response; + try { + response = await ApiManager.instance.post(URLs.addOrUpdateInternalAuditSystem, body: request.toJson()); + if (response.statusCode >= 200 && response.statusCode < 300) { + status = true; + notifyListeners(); + } else { + Fluttertoast.showToast(msg: "${context.translation.failedRequestMessage} :${json.decode(response.body)['message']}"); + status = false; + } + return status; + } catch (error) { + print(error); + status = false; + notifyListeners(); + return status; + } + } Future> getWorkOrderByWoType({String? text, required int? woId}) async { late Response response; diff --git a/lib/modules/tm_module/tasks_wo/update_task_request_view.dart b/lib/modules/tm_module/tasks_wo/update_task_request_view.dart index d25049df..40871d70 100644 --- a/lib/modules/tm_module/tasks_wo/update_task_request_view.dart +++ b/lib/modules/tm_module/tasks_wo/update_task_request_view.dart @@ -271,7 +271,7 @@ class _UpdateTaskRequestState extends State { taskModel?.timerModelList?.forEach((timer) { int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds; taskModel.taskJobActivityEngineerTimers?.add( - TaskJobActivityEngineerTimer( + TaskJobActivityEngineerTimer ( id: 0, startDate: timer.startAt!.toIso8601String(), endDate: timer.endAt?.toIso8601String(), totalWorkingHour: ((durationInSecond) / 60 / 60), comment: timer.comments ?? comments), ); }); diff --git a/lib/new_views/pages/land_page/widgets/request_item_view_list.dart b/lib/new_views/pages/land_page/widgets/request_item_view_list.dart index ec9b9d31..54639c40 100644 --- a/lib/new_views/pages/land_page/widgets/request_item_view_list.dart +++ b/lib/new_views/pages/land_page/widgets/request_item_view_list.dart @@ -33,14 +33,14 @@ class RequestItemViewList extends StatelessWidget { shrinkWrap: true, itemBuilder: (cxt, index) { if (isLoading) return const SizedBox().toRequestShimmer(cxt, isLoading); - if (list[index].transactionType == null) { - return EquipmentInternalAuditItemView(requestDetails: list[index]); - // return Container( - // height: 100, - // width: double.infinity, - // color: AppColor.neutral40, - // ); - } + // if (list[index].transactionType == null) { + // return EquipmentInternalAuditItemView(requestDetails: list[index]); + // // return Container( + // // height: 100, + // // width: double.infinity, + // // color: AppColor.neutral40, + // // ); + // } switch (list[index].transactionType) { case 1: return ServiceRequestItemView(requestDetails: list[index]);