Merge branch 'refs/heads/design_3.0_internal_audit_module' into design_3.0_cx_module
# Conflicts: # lib/controllers/api_routes/urls.dart # lib/main.dart # pubspec.lock # pubspec.yamldesign_3.0_demo_module
commit
f6f5048cc8
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="17" height="20" viewBox="0 0 17 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.82353 1.94999C3.67937 1.94999 1.94118 3.69608 1.94118 5.84998V11.2125C1.94118 14.7126 4.76573 17.55 8.25 17.55C11.7343 17.55 14.5588 14.7126 14.5588 11.2125V9.75003C14.5588 9.21155 14.9934 8.77503 15.5294 8.77503C16.0655 8.77503 16.5 9.21155 16.5 9.75003V11.2125C16.5 15.7896 12.8063 19.5 8.25 19.5C3.69365 19.5 0 15.7896 0 11.2125V5.84998C0 2.61913 2.60728 0 5.82353 0C9.03978 0 11.6471 2.61913 11.6471 5.84998V11.2125C11.6471 13.0971 10.1261 14.625 8.25 14.625C6.37386 14.625 4.85294 13.0971 4.85294 11.2125V7.31248C4.85294 6.774 5.28749 6.33748 5.82353 6.33748C6.35957 6.33748 6.79412 6.774 6.79412 7.31248V11.2125C6.79412 12.0202 7.44594 12.675 8.25 12.675C9.05406 12.675 9.70588 12.0202 9.70588 11.2125V5.84998C9.70588 3.69608 7.96769 1.94999 5.82353 1.94999Z" fill="#3DA5E5"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 938 B |
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="14" height="8" viewBox="0 0 14 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M1.35372 0.305286C1.4756 0.46666 1.83951 0.948403 2.05624 1.22611C2.49031 1.78233 3.08342 2.52142 3.72323 3.25831C4.36627 3.99893 5.04178 4.72022 5.64189 5.25046C5.94281 5.51634 6.20714 5.71838 6.42527 5.84987C6.63042 5.97355 6.75161 5.99927 6.75161 5.99927C6.75161 5.99927 6.86923 5.97355 7.07437 5.84988C7.2925 5.71838 7.55684 5.51635 7.85775 5.25047C8.45786 4.72022 9.13337 3.99892 9.77642 3.2583C10.4162 2.5214 11.0093 1.7823 11.4434 1.22608C11.6601 0.948368 12.0235 0.467305 12.1454 0.305929C12.3911 -0.0275935 12.8611 -0.0995297 13.1946 0.146103C13.5281 0.391736 13.5994 0.861234 13.3537 1.19476L13.3518 1.1973C13.224 1.36655 12.8471 1.86557 12.6259 2.14892C12.1821 2.7177 11.5716 3.47861 10.9091 4.24171C10.2497 5.00109 9.52408 5.77979 8.85096 6.37454C8.51526 6.67116 8.17497 6.93788 7.8488 7.1345C7.54322 7.31872 7.15633 7.5 6.74982 7.5C6.34331 7.5 5.95642 7.31871 5.65084 7.1345C5.32468 6.93787 4.98439 6.67116 4.64869 6.37454C3.97557 5.77979 3.2499 5.0011 2.59058 4.24173C1.92803 3.47863 1.3176 2.71774 0.873719 2.14896C0.652433 1.86541 0.275507 1.36637 0.14793 1.19747L0.14628 1.19528C-0.0993546 0.861762 -0.0284591 0.391787 0.305062 0.146153C0.638573 -0.0994739 1.10808 -0.0282082 1.35372 0.305286Z" fill="#3B3D4A"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="8" height="14" viewBox="0 0 8 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M0.305286 12.1462C0.46666 12.0243 0.948403 11.6604 1.22611 11.4436C1.78233 11.0096 2.52142 10.4165 3.25831 9.77665C3.99893 9.13361 4.72022 8.4581 5.25046 7.85799C5.51634 7.55707 5.71838 7.29274 5.84987 7.07461C5.97355 6.86945 5.99927 6.74827 5.99927 6.74827C5.99927 6.74827 5.97355 6.63064 5.84988 6.4255C5.71838 6.20738 5.51635 5.94304 5.25047 5.64213C4.72022 5.04201 3.99892 4.3665 3.2583 3.72346C2.5214 3.08366 1.7823 2.49055 1.22608 2.05647C0.948368 1.83975 0.467305 1.47634 0.305929 1.35446C-0.0275935 1.10883 -0.0995297 0.63882 0.146103 0.305298C0.391736 -0.0282253 0.861234 -0.0994742 1.19476 0.146159L1.1973 0.148077C1.36655 0.275917 1.86557 0.652817 2.14892 0.873949C2.7177 1.31783 3.47861 1.92826 4.24171 2.59081C5.00109 3.25013 5.77979 3.9758 6.37454 4.64892C6.67116 4.98462 6.93788 5.32491 7.1345 5.65108C7.31872 5.95665 7.5 6.34355 7.5 6.75006C7.5 7.15657 7.31871 7.54346 7.1345 7.84904C6.93787 8.1752 6.67116 8.51549 6.37454 8.85119C5.77979 9.52431 5.0011 10.25 4.24173 10.9093C3.47863 11.5719 2.71774 12.1823 2.14896 12.6262C1.86541 12.8474 1.36637 13.2244 1.19747 13.3519L1.19528 13.3536C0.861762 13.5992 0.391787 13.5283 0.146153 13.1948C-0.0994739 12.8613 -0.0282082 12.3918 0.305286 12.1462Z" fill="#3B3D4A"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
@ -0,0 +1,53 @@
|
|||||||
|
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
|
||||||
|
|
||||||
|
class EngineerData {
|
||||||
|
int? id;
|
||||||
|
String? debrief;
|
||||||
|
String? startTime;
|
||||||
|
String? endTime;
|
||||||
|
double? totalHours;
|
||||||
|
bool? isComplete;
|
||||||
|
int? statusId;
|
||||||
|
int? requestId;
|
||||||
|
List<InternalAuditAttachments>? attachments;
|
||||||
|
|
||||||
|
EngineerData({
|
||||||
|
this.id,
|
||||||
|
this.debrief,
|
||||||
|
this.startTime,
|
||||||
|
this.endTime,
|
||||||
|
this.totalHours,
|
||||||
|
this.isComplete,
|
||||||
|
this.statusId,
|
||||||
|
this.requestId,
|
||||||
|
this.attachments,
|
||||||
|
});
|
||||||
|
|
||||||
|
EngineerData.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
debrief = json['debrief'];
|
||||||
|
startTime = json['startTime'];
|
||||||
|
endTime = json['endTime'];
|
||||||
|
totalHours = (json['totalHours'] as num?)?.toDouble();
|
||||||
|
isComplete = json['isComplete'];
|
||||||
|
statusId = json['statusId'];
|
||||||
|
requestId = json['requestId'];
|
||||||
|
attachments = json['attachments'] != null ? (json['attachments'] as List).map((e) => InternalAuditAttachments.fromJson(e)).toList() : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = {};
|
||||||
|
data['id'] = id;
|
||||||
|
data['debrief'] = debrief;
|
||||||
|
data['startTime'] = startTime;
|
||||||
|
data['endTime'] = endTime;
|
||||||
|
data['totalHours'] = totalHours;
|
||||||
|
data['isComplete'] = isComplete;
|
||||||
|
data['statusId'] = statusId;
|
||||||
|
data['requestId'] = requestId;
|
||||||
|
if (attachments != null) {
|
||||||
|
data['attachments'] = attachments!.map((e) => e.toJson()).toList();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,300 @@
|
|||||||
|
import 'package:test_sa/models/timer_model.dart';
|
||||||
|
import 'package:test_sa/modules/internal_audit_module/models/engineer_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/models/internal_audit_timer_model.dart';
|
||||||
|
|
||||||
|
class EquipmentInternalAuditDataModel {
|
||||||
|
int? id;
|
||||||
|
String? requestNo;
|
||||||
|
String? createdDate;
|
||||||
|
int? requestNoSequence;
|
||||||
|
Auditor? auditor;
|
||||||
|
Status? status;
|
||||||
|
Asset? asset;
|
||||||
|
AssignEmployee? assignEmployee;
|
||||||
|
dynamic manufacture;
|
||||||
|
String? remarks;
|
||||||
|
List<EquipmentsFinding>? equipmentsFindings;
|
||||||
|
List<InternalAuditAttachments>? attachments;
|
||||||
|
EngineerData? engineerData;
|
||||||
|
|
||||||
|
|
||||||
|
EquipmentInternalAuditDataModel({
|
||||||
|
this.id,
|
||||||
|
this.requestNo,
|
||||||
|
this.createdDate,
|
||||||
|
this.requestNoSequence,
|
||||||
|
this.auditor,
|
||||||
|
this.status,
|
||||||
|
this.asset,
|
||||||
|
this.assignEmployee,
|
||||||
|
this.manufacture,
|
||||||
|
this.remarks,
|
||||||
|
this.equipmentsFindings,
|
||||||
|
this.attachments,
|
||||||
|
this.engineerData,
|
||||||
|
});
|
||||||
|
|
||||||
|
EquipmentInternalAuditDataModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
requestNo = json['requestNo'];
|
||||||
|
createdDate = json['createdDate'];
|
||||||
|
requestNoSequence = json['requestNoSequence'];
|
||||||
|
auditor = json['auditor'] != null ? Auditor.fromJson(json['auditor']) : null;
|
||||||
|
status = json['status'] != null ? Status.fromJson(json['status']) : null;
|
||||||
|
asset = json['asset'] != null ? Asset.fromJson(json['asset']) : null;
|
||||||
|
assignEmployee = json['assignEmployee'] != null ? AssignEmployee.fromJson(json['assignEmployee']) : null;
|
||||||
|
manufacture = json['manufacture'];
|
||||||
|
remarks = json['remarks'];
|
||||||
|
if (json['equipmentsFindings'] != null) {
|
||||||
|
equipmentsFindings = <EquipmentsFinding>[];
|
||||||
|
json['equipmentsFindings'].forEach((v) {
|
||||||
|
equipmentsFindings!.add(EquipmentsFinding.fromJson(v));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
attachments = json['attachments'] != null
|
||||||
|
? (json['attachments'] as List)
|
||||||
|
.map((e) => InternalAuditAttachments.fromJson(e))
|
||||||
|
.where((e) => e.name != null) // optional filter if you want to skip null names
|
||||||
|
.toList()
|
||||||
|
: [];
|
||||||
|
engineerData = json['engineerData'] != null ? EngineerData.fromJson(json['engineerData']) : null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = {};
|
||||||
|
data['id'] = id;
|
||||||
|
data['requestNo'] = requestNo;
|
||||||
|
data['createdDate'] = createdDate;
|
||||||
|
data['requestNoSequence'] = requestNoSequence;
|
||||||
|
if (auditor != null) {
|
||||||
|
data['auditor'] = auditor!.toJson();
|
||||||
|
}
|
||||||
|
if (status != null) {
|
||||||
|
data['status'] = status!.toJson();
|
||||||
|
}
|
||||||
|
if (asset != null) {
|
||||||
|
data['asset'] = asset!.toJson();
|
||||||
|
}
|
||||||
|
if (assignEmployee != null) {
|
||||||
|
data['assignEmployee'] = assignEmployee!.toJson();
|
||||||
|
}
|
||||||
|
data['manufacture'] = manufacture;
|
||||||
|
data['remarks'] = remarks;
|
||||||
|
if (equipmentsFindings != null) {
|
||||||
|
data['equipmentsFindings'] =
|
||||||
|
equipmentsFindings!.map((v) => v.toJson()).toList();
|
||||||
|
}
|
||||||
|
data['attachments'] = attachments;
|
||||||
|
if (engineerData != null) data['engineerData'] = engineerData!.toJson();
|
||||||
|
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<String, dynamic> 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<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Status {
|
||||||
|
int? id;
|
||||||
|
String? name;
|
||||||
|
int? value;
|
||||||
|
|
||||||
|
Status({this.id, this.name, this.value});
|
||||||
|
|
||||||
|
Status.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
name = json['name'];
|
||||||
|
value = json['value'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = {};
|
||||||
|
data['id'] = id;
|
||||||
|
data['name'] = name;
|
||||||
|
data['value'] = value;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Asset {
|
||||||
|
int? id;
|
||||||
|
String? assetNumber;
|
||||||
|
String? assetSerialNo;
|
||||||
|
String? assetName;
|
||||||
|
String? modelName;
|
||||||
|
String? manufacturerName;
|
||||||
|
String? siteName;
|
||||||
|
int? siteId;
|
||||||
|
String? modelDefinition;
|
||||||
|
|
||||||
|
Asset({
|
||||||
|
this.id,
|
||||||
|
this.assetNumber,
|
||||||
|
this.assetSerialNo,
|
||||||
|
this.assetName,
|
||||||
|
this.modelName,
|
||||||
|
this.manufacturerName,
|
||||||
|
this.siteName,
|
||||||
|
this.siteId,
|
||||||
|
this.modelDefinition,
|
||||||
|
});
|
||||||
|
|
||||||
|
Asset.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
assetNumber = json['assetNumber'];
|
||||||
|
assetSerialNo = json['assetSerialNo'];
|
||||||
|
assetName = json['assetName'];
|
||||||
|
modelName = json['modelName'];
|
||||||
|
manufacturerName = json['manufacturerName'];
|
||||||
|
siteName = json['siteName'];
|
||||||
|
siteId = json['siteId'];
|
||||||
|
modelDefinition = json['modelDefinition'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = {};
|
||||||
|
data['id'] = id;
|
||||||
|
data['assetNumber'] = assetNumber;
|
||||||
|
data['assetSerialNo'] = assetSerialNo;
|
||||||
|
data['assetName'] = assetName;
|
||||||
|
data['modelName'] = modelName;
|
||||||
|
data['manufacturerName'] = manufacturerName;
|
||||||
|
data['siteName'] = siteName;
|
||||||
|
data['siteId'] = siteId;
|
||||||
|
data['modelDefinition'] = modelDefinition;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AssignEmployee {
|
||||||
|
String? userId;
|
||||||
|
String? userName;
|
||||||
|
String? email;
|
||||||
|
String? employeeId;
|
||||||
|
int? languageId;
|
||||||
|
String? extensionNo;
|
||||||
|
String? phoneNumber;
|
||||||
|
bool? isActive;
|
||||||
|
|
||||||
|
AssignEmployee({
|
||||||
|
this.userId,
|
||||||
|
this.userName,
|
||||||
|
this.email,
|
||||||
|
this.employeeId,
|
||||||
|
this.languageId,
|
||||||
|
this.extensionNo,
|
||||||
|
this.phoneNumber,
|
||||||
|
this.isActive,
|
||||||
|
});
|
||||||
|
|
||||||
|
AssignEmployee.fromJson(Map<String, dynamic> 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<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EquipmentsFinding {
|
||||||
|
int? id;
|
||||||
|
Finding? finding;
|
||||||
|
|
||||||
|
EquipmentsFinding({this.id, this.finding});
|
||||||
|
|
||||||
|
EquipmentsFinding.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
finding = json['finding'] != null ? Finding.fromJson(json['finding']) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = {};
|
||||||
|
data['id'] = id;
|
||||||
|
if (finding != null) {
|
||||||
|
data['finding'] = finding!.toJson();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Finding {
|
||||||
|
int? id;
|
||||||
|
String? name;
|
||||||
|
int? value;
|
||||||
|
|
||||||
|
Finding({this.id, this.name, this.value});
|
||||||
|
|
||||||
|
Finding.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
name = json['name'];
|
||||||
|
value = json['value'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = {};
|
||||||
|
data['id'] = id;
|
||||||
|
data['name'] = name;
|
||||||
|
data['value'] = value;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
|
import 'package:test_sa/controllers/api_routes/urls.dart';
|
||||||
|
import 'package:test_sa/extensions/context_extension.dart';
|
||||||
|
import 'package:test_sa/models/device/asset.dart';
|
||||||
|
import 'package:test_sa/models/fault_description.dart';
|
||||||
|
import 'package:test_sa/models/lookup.dart';
|
||||||
|
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
|
||||||
|
|
||||||
|
class EquipmentInternalAuditFormModel {
|
||||||
|
int? id=0;
|
||||||
|
String? deviceArName;
|
||||||
|
String? auditorId;
|
||||||
|
String? woOrderNo;
|
||||||
|
List<String>? devicePhotos;
|
||||||
|
List<Lookup> findings =[];
|
||||||
|
List<InternalAuditAttachments> attachments = [];
|
||||||
|
String? remarks;
|
||||||
|
Asset? device;
|
||||||
|
EquipmentInternalAuditFormModel({
|
||||||
|
this.id,
|
||||||
|
this.deviceArName,
|
||||||
|
this.auditorId,
|
||||||
|
this.devicePhotos,
|
||||||
|
this.woOrderNo,
|
||||||
|
this.remarks,
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'id': id??0,
|
||||||
|
'assetId': device?.id,
|
||||||
|
'auditorId': auditorId,
|
||||||
|
'findings': findings.map((e) => {'findingId': e.value}).toList(),
|
||||||
|
'attachments': attachments.map((e) => e.toJson()).toList(),
|
||||||
|
'remarks': remarks,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
class InternalAuditAttachments {
|
||||||
|
InternalAuditAttachments({this.id, this.originalName, this.name, this.createdBy});
|
||||||
|
|
||||||
|
int? id;
|
||||||
|
String? name;
|
||||||
|
String? originalName;
|
||||||
|
String? createdBy;
|
||||||
|
|
||||||
|
InternalAuditAttachments.fromJson(Map<String, dynamic> json) {
|
||||||
|
log('name is ${json['name']}');
|
||||||
|
id = json['id'];
|
||||||
|
name = (json['name'] != null && !json['name'].toString().startsWith('data:image/jpeg')) ? json['name'] : null;
|
||||||
|
originalName = json['originalName'];
|
||||||
|
createdBy = json['createdBy'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['id'] = id;
|
||||||
|
data['name'] = name;
|
||||||
|
data['originalName'] = originalName;
|
||||||
|
// data['createdBy'] = createdBy;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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<String, dynamic> 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<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'id': id,
|
||||||
|
'startDate': startDate,
|
||||||
|
'endDate': endDate,
|
||||||
|
'totalWorkingHours': totalWorkingHour,
|
||||||
|
'comment': comment,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,138 @@
|
|||||||
|
import 'package:test_sa/models/lookup.dart';
|
||||||
|
import 'package:test_sa/modules/internal_audit_module/models/engineer_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/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;
|
||||||
|
List<InternalAuditAttachments>? attachments;
|
||||||
|
EngineerData? engineerData;
|
||||||
|
|
||||||
|
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,
|
||||||
|
this.attachments,
|
||||||
|
this.engineerData,
|
||||||
|
});
|
||||||
|
|
||||||
|
SystemInternalAuditDataModel.fromJson(Map<String, dynamic> 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'];
|
||||||
|
attachments = json['attachments'] != null
|
||||||
|
? (json['attachments'] as List)
|
||||||
|
.map((e) => InternalAuditAttachments.fromJson(e))
|
||||||
|
.where((e) => e.name != null) // optional filter if you want to skip null names
|
||||||
|
.toList()
|
||||||
|
: [];
|
||||||
|
engineerData = json['engineerData'] != null ? EngineerData.fromJson(json['engineerData']) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> 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;
|
||||||
|
if (engineerData != null) data['engineerData'] = engineerData!.toJson();
|
||||||
|
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<String, dynamic> 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<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,202 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:test_sa/models/lookup.dart';
|
||||||
|
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
|
||||||
|
|
||||||
|
class SystemInternalAuditFormModel {
|
||||||
|
int? id;
|
||||||
|
String? auditorId;
|
||||||
|
String? assignEmployeeId;
|
||||||
|
Lookup? findingType;
|
||||||
|
String? findingDescription;
|
||||||
|
Lookup? workOrderType;
|
||||||
|
int? correctiveMaintenanceId;
|
||||||
|
int? planPreventiveVisitId;
|
||||||
|
int? assetTransferId;
|
||||||
|
List<InternalAuditAttachments>? attachments = [];
|
||||||
|
int? taskJobId;
|
||||||
|
int? taskAlertJobId;
|
||||||
|
int? gasRefillId;
|
||||||
|
int? planRecurrentTaskId;
|
||||||
|
int? statusId;
|
||||||
|
SystemAuditWorkOrderDetailModel? workOrderDetailModel;
|
||||||
|
|
||||||
|
SystemInternalAuditFormModel({
|
||||||
|
this.id,
|
||||||
|
this.auditorId,
|
||||||
|
this.assignEmployeeId,
|
||||||
|
this.findingType,
|
||||||
|
this.findingDescription,
|
||||||
|
this.workOrderType,
|
||||||
|
this.correctiveMaintenanceId,
|
||||||
|
this.planPreventiveVisitId,
|
||||||
|
this.assetTransferId,
|
||||||
|
this.taskJobId,
|
||||||
|
this.taskAlertJobId,
|
||||||
|
this.gasRefillId,
|
||||||
|
this.planRecurrentTaskId,
|
||||||
|
this.workOrderDetailModel,
|
||||||
|
this.statusId,
|
||||||
|
this.attachments,
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
// 'id': id,
|
||||||
|
'auditorId': auditorId,
|
||||||
|
'assignEmployeeId': assignEmployeeId,
|
||||||
|
'findingTypeId': findingType?.id,
|
||||||
|
'findingDescription': findingDescription,
|
||||||
|
'workOrderTypeId': workOrderType?.id,
|
||||||
|
'correctiveMaintenanceId': correctiveMaintenanceId,
|
||||||
|
'planPreventiveVisitId': planPreventiveVisitId,
|
||||||
|
'assetTransferId': assetTransferId,
|
||||||
|
'taskJobId': taskJobId,
|
||||||
|
'taskAlertJobId': taskAlertJobId,
|
||||||
|
'gasRefillId': gasRefillId,
|
||||||
|
'planRecurrentTaskId': planRecurrentTaskId,
|
||||||
|
'statusId': statusId,
|
||||||
|
'attachments': attachments?.map((e) => e.toJson()).toList(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WoAutoCompleteModel {
|
||||||
|
int? id;
|
||||||
|
String? workOrderNo;
|
||||||
|
String? displayName;
|
||||||
|
|
||||||
|
WoAutoCompleteModel({this.id, this.workOrderNo, this.displayName});
|
||||||
|
|
||||||
|
WoAutoCompleteModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
workOrderNo = json['workOrderNo'];
|
||||||
|
displayName = json['workOrderNo'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['id'] = id;
|
||||||
|
data['woOrderNo'] = workOrderNo;
|
||||||
|
data['displayName'] = workOrderNo;
|
||||||
|
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<String, dynamic> 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<String, dynamic> 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,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
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 AuditFormModel {
|
||||||
|
int? id;
|
||||||
|
String? createdDate;
|
||||||
|
int? requestId;
|
||||||
|
String? debrief;
|
||||||
|
DateTime? startTime;
|
||||||
|
DateTime? endTime;
|
||||||
|
double? totalHours;
|
||||||
|
List<InternalAuditAttachments>? attachments;
|
||||||
|
bool? isComplete;
|
||||||
|
TimerModel? auditTimerModel = TimerModel();
|
||||||
|
List<InternalAuditTimerModel>? auditTimers = [];
|
||||||
|
TimerModel? auditTimePicker;
|
||||||
|
List<TimerModel>? timerModelList = [];
|
||||||
|
|
||||||
|
AuditFormModel(
|
||||||
|
{this.id,
|
||||||
|
this.requestId,
|
||||||
|
this.debrief,
|
||||||
|
this.startTime,
|
||||||
|
this.endTime,
|
||||||
|
this.totalHours,
|
||||||
|
this.createdDate,
|
||||||
|
this.attachments,
|
||||||
|
this.isComplete,
|
||||||
|
this.auditTimerModel,
|
||||||
|
this.timerModelList,
|
||||||
|
this.auditTimePicker,
|
||||||
|
this.auditTimers});
|
||||||
|
|
||||||
|
AuditFormModel.fromJson(Map<String, dynamic> 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<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'id': id,
|
||||||
|
'requestId': requestId,
|
||||||
|
'debrief': debrief,
|
||||||
|
'startTime': startTime?.toIso8601String(),
|
||||||
|
'endTime': endTime?.toIso8601String(),
|
||||||
|
// 'auditTimer': auditTimers,
|
||||||
|
'totalHours': totalHours,
|
||||||
|
'attachments': attachments?.map((e) => e.toJson()).toList(),
|
||||||
|
'isComplete': isComplete,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,147 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:developer';
|
||||||
|
import 'dart:io';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/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/lookup.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/equipment_internal_audit_form_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_checklist_provider.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_lazy_loading.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/multiple_item_drop_down_menu.dart';
|
||||||
|
import 'package:test_sa/views/widgets/equipment/asset_picker.dart';
|
||||||
|
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
|
||||||
|
|
||||||
|
class CreateEquipmentInternalAuditForm extends StatefulWidget {
|
||||||
|
static const String id = "/create-equipment-internal-audit-form";
|
||||||
|
|
||||||
|
const CreateEquipmentInternalAuditForm({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_CreateEquipmentInternalAuditFormState createState() => _CreateEquipmentInternalAuditFormState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CreateEquipmentInternalAuditFormState extends State<CreateEquipmentInternalAuditForm> with TickerProviderStateMixin {
|
||||||
|
late TextEditingController _commentController;
|
||||||
|
final EquipmentInternalAuditFormModel _equipmentinternalAuditModel = EquipmentInternalAuditFormModel();
|
||||||
|
final List<GenericAttachmentModel> _attachments = [];
|
||||||
|
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||||
|
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||||
|
FocusNode auditCheckListNode = FocusNode();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_commentController = TextEditingController();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_commentController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
key: _scaffoldKey,
|
||||||
|
appBar: DefaultAppBar(title: 'Equipment Internal Audit Checklist'.addTranslation),
|
||||||
|
body: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
AssetPicker(
|
||||||
|
device: _equipmentinternalAuditModel.device,
|
||||||
|
borderColor: AppColor.black20,
|
||||||
|
buttonColor: AppColor.white936,
|
||||||
|
onPick: (asset) async {
|
||||||
|
_equipmentinternalAuditModel.device = asset;
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
16.height,
|
||||||
|
//TODO need to check layout issue...
|
||||||
|
MultipleItemDropDownMenu<Lookup, InternalAuditCheckListProvider>(
|
||||||
|
context: context,
|
||||||
|
showAsBottomSheet: true,
|
||||||
|
backgroundColor: AppColor.neutral100,
|
||||||
|
showShadow: false,
|
||||||
|
showCancel: true,
|
||||||
|
requestById: context.userProvider.user?.clientId,
|
||||||
|
title: 'Internal Audit Checklist'.addTranslation,
|
||||||
|
initialValue: _equipmentinternalAuditModel.findings,
|
||||||
|
onSelect: (value) {
|
||||||
|
_equipmentinternalAuditModel.findings = value ?? [];
|
||||||
|
},
|
||||||
|
),
|
||||||
|
16.height,
|
||||||
|
AppTextFormField(
|
||||||
|
backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
labelText: 'Remarks'.addTranslation,
|
||||||
|
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
|
||||||
|
alignLabelWithHint: true,
|
||||||
|
textInputType: TextInputType.multiline,
|
||||||
|
showShadow: false,
|
||||||
|
onSaved: (value) {
|
||||||
|
_equipmentinternalAuditModel.remarks = value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
16.height,
|
||||||
|
AttachmentPicker(
|
||||||
|
label: context.translation.attachments,
|
||||||
|
attachment: _attachments,
|
||||||
|
buttonColor: AppColor.primary10,
|
||||||
|
onlyImages: false,
|
||||||
|
onChange: (value) {},
|
||||||
|
buttonIcon: 'attachment_icon'.toSvgAsset(color: AppColor.primary10),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).toShadowContainer(context),
|
||||||
|
).expanded,
|
||||||
|
FooterActionButton.footerContainer(
|
||||||
|
context: context,
|
||||||
|
child: AppFilledButton(label: context.translation.submitRequest, buttonColor: AppColor.primary10, onPressed: _submit),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _submit() async {
|
||||||
|
InternalAuditProvider internalAuditProvider = Provider.of<InternalAuditProvider>(context, listen: false);
|
||||||
|
if (_formKey.currentState!.validate()) {
|
||||||
|
_formKey.currentState!.save();
|
||||||
|
_equipmentinternalAuditModel.attachments = [];
|
||||||
|
for (var item in _attachments) {
|
||||||
|
String fileName = ServiceRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
|
||||||
|
_equipmentinternalAuditModel.attachments.add(InternalAuditAttachments(id: item.id, name: fileName));
|
||||||
|
}
|
||||||
|
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
|
||||||
|
_equipmentinternalAuditModel.auditorId = context.userProvider.user?.userID;
|
||||||
|
bool status = await internalAuditProvider.addEquipmentInternalAudit(context: context, request: _equipmentinternalAuditModel);
|
||||||
|
Navigator.pop(context);
|
||||||
|
if(status){
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,207 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:test_sa/controllers/api_routes/urls.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/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/models/internal_audit_attachment_model.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";
|
||||||
|
|
||||||
|
final int auditId;
|
||||||
|
|
||||||
|
const EquipmentInternalAuditDetailPage({Key? key, required this.auditId}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_EquipmentInternalAuditDetailPageState createState() {
|
||||||
|
return _EquipmentInternalAuditDetailPageState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EquipmentInternalAuditDetailPageState extends State<EquipmentInternalAuditDetailPage> {
|
||||||
|
bool isWoType = true;
|
||||||
|
EquipmentInternalAuditDataModel? model;
|
||||||
|
late InternalAuditProvider _internalAuditProvider;
|
||||||
|
List<InternalAuditAttachments> allAttachments = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_internalAuditProvider = Provider.of<InternalAuditProvider>(context, listen: false);
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
getAuditData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getAuditData() async {
|
||||||
|
model = await _internalAuditProvider.getEquipmentInternalAuditById(widget.auditId);
|
||||||
|
allAttachments.clear();
|
||||||
|
allAttachments = [
|
||||||
|
...(model?.attachments ?? []),
|
||||||
|
...(model?.engineerData?.attachments ?? []),
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
//TODO need to check when implementing provider needed or not .
|
||||||
|
return Scaffold(
|
||||||
|
appBar: const DefaultAppBar(title: "Request Details"),
|
||||||
|
body: Selector<InternalAuditProvider, bool>(
|
||||||
|
selector: (_, provider) => provider.isLoading,
|
||||||
|
builder: (_, isLoading, __) {
|
||||||
|
if (isLoading) return const ALoading();
|
||||||
|
if (model == null) return NoDataFound(message: context.translation.noDataFound).center;
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
assetDetails(),
|
||||||
|
8.height,
|
||||||
|
requestDetails(),
|
||||||
|
8.height,
|
||||||
|
if (model?.remarks?.isNotEmpty ?? false) ...[
|
||||||
|
const Divider().defaultStyle(context),
|
||||||
|
model!.remarks!.bodyText(context),
|
||||||
|
8.height,
|
||||||
|
],
|
||||||
|
if (allAttachments.isNotEmpty) ...[
|
||||||
|
const Divider().defaultStyle(context),
|
||||||
|
Text(
|
||||||
|
"Attachments".addTranslation,
|
||||||
|
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
FilesList(images: allAttachments.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
).paddingAll(0).toShadowContainer(context),
|
||||||
|
).expanded,
|
||||||
|
if (context.userProvider.isEngineer)
|
||||||
|
FooterActionButton.footerContainer(
|
||||||
|
context: context,
|
||||||
|
child: AppFilledButton(
|
||||||
|
buttonColor: AppColor.primary10,
|
||||||
|
label: "Update",
|
||||||
|
onPressed: () async {
|
||||||
|
final result = await Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (_) => UpdateEquipmentInternalAuditPage(model: model),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (result == true) {
|
||||||
|
await getAuditData();
|
||||||
|
setState(() {}); // refresh UI with new model
|
||||||
|
}
|
||||||
|
// Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdateEquipmentInternalAuditPage(model: model)));
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget workOrderInformation() {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Divider().defaultStyle(context),
|
||||||
|
Text(
|
||||||
|
"WO Info",
|
||||||
|
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
|
||||||
|
),
|
||||||
|
6.height,
|
||||||
|
'${context.translation.woNumber}: ${'-'}'.bodyText(context),
|
||||||
|
'${'WO Type'.addTranslation}: ${'-'}'.bodyText(context),
|
||||||
|
'${context.translation.site}: ${'-'}'.bodyText(context),
|
||||||
|
'${context.translation.assetName}: ${'-'}'.bodyText(context),
|
||||||
|
'${context.translation.manufacture}: ${'-'}'.bodyText(context),
|
||||||
|
'${context.translation.model}: ${'-'}'.bodyText(context),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget requestDetails() {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Divider().defaultStyle(context),
|
||||||
|
Text(
|
||||||
|
"Request Details",
|
||||||
|
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
|
||||||
|
),
|
||||||
|
6.height,
|
||||||
|
if (model != null && model!.equipmentsFindings != null && model!.equipmentsFindings!.isNotEmpty)
|
||||||
|
...model!.equipmentsFindings!.map((item) {
|
||||||
|
final findingName = item.finding?.name ?? 'Unknown';
|
||||||
|
return checklistWidget(value: findingName.addTranslation);
|
||||||
|
}).toList()
|
||||||
|
else
|
||||||
|
Text('No findings available'.addTranslation),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget assetDetails() {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Asset Details",
|
||||||
|
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
|
||||||
|
),
|
||||||
|
6.height,
|
||||||
|
'${context.translation.assetName}: ${model?.asset?.assetName ?? '-'}'.bodyText(context),
|
||||||
|
'${context.translation.assetNo}: ${model?.asset?.assetNumber ?? '-'}'.bodyText(context),
|
||||||
|
'${context.translation.manufacture}: ${model?.asset?.manufacturerName ?? '-'}'.bodyText(context),
|
||||||
|
'${context.translation.model}: ${model?.asset?.modelName ?? '-'}'.bodyText(context),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget checklistWidget({required String value}) {
|
||||||
|
return Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Checkbox(
|
||||||
|
value: true,
|
||||||
|
activeColor: AppColor.neutral120,
|
||||||
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
visualDensity: const VisualDensity(horizontal: -4, vertical: -3),
|
||||||
|
onChanged: (value) {},
|
||||||
|
),
|
||||||
|
value.bodyText(context),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,115 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:flutter/material.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/all_requests_and_count_model.dart';
|
||||||
|
import 'package:test_sa/models/new_models/dashboard_detail.dart';
|
||||||
|
import 'package:test_sa/modules/internal_audit_module/pages/equipment_internal_audit/equipment_internal_audit_detail_page.dart';
|
||||||
|
import 'package:test_sa/new_views/app_style/app_color.dart';
|
||||||
|
import 'package:test_sa/views/widgets/requests/request_status.dart';
|
||||||
|
|
||||||
|
class EquipmentInternalAuditItemView extends StatelessWidget {
|
||||||
|
final Data? requestData;
|
||||||
|
final RequestsDetails? requestDetails;
|
||||||
|
final bool showShadow;
|
||||||
|
|
||||||
|
const EquipmentInternalAuditItemView({Key? key, this.requestData, this.requestDetails, this.showShadow = true}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
//TODO need to refactor this code repetation @waseem
|
||||||
|
if (requestData != null) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
StatusLabel(
|
||||||
|
label: requestData!.statusName!,
|
||||||
|
textColor: AppColor.getRequestStatusTextColorByName(context, requestData!.statusName!),
|
||||||
|
backgroundColor: AppColor.getRequestStatusColorByName(context, requestData!.statusName!),
|
||||||
|
),
|
||||||
|
1.width.expanded,
|
||||||
|
Text(
|
||||||
|
requestData!.transactionDate?.toServiceRequestCardFormat ?? "",
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
(requestData?.typeTransaction ?? "Internal Audit Request").heading5(context),
|
||||||
|
infoWidget(label: context.translation.assetNumber, value: requestData?.assetNumber, context: context),
|
||||||
|
|
||||||
|
8.height,
|
||||||
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
context.translation.viewDetails,
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)),
|
||||||
|
),
|
||||||
|
4.width,
|
||||||
|
Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).toShadowContainer(context, withShadow: showShadow).onPress(() async {
|
||||||
|
Navigator.push(context, MaterialPageRoute(builder: (context) => EquipmentInternalAuditDetailPage(auditId: requestDetails!.id!)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
StatusLabel(
|
||||||
|
label: requestDetails!.status!,
|
||||||
|
textColor: AppColor.getRequestStatusTextColorByName(context, requestDetails?.status!),
|
||||||
|
backgroundColor: AppColor.getRequestStatusColorByName(context, requestDetails?.status!),
|
||||||
|
),
|
||||||
|
1.width.expanded,
|
||||||
|
Text(
|
||||||
|
requestDetails!.date?.toServiceRequestCardFormat ?? "",
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
(requestDetails?.nameOfType ?? "Internal Audit Request").heading5(context),
|
||||||
|
8.height,
|
||||||
|
infoWidget(label: context.translation.assetNumber, value: requestDetails!.assetNo, context: context),
|
||||||
|
infoWidget(label: context.translation.assetSN, value: requestDetails!.assetSN, context: context),
|
||||||
|
infoWidget(label: context.translation.model, value: requestDetails!.model, context: context),
|
||||||
|
8.height,
|
||||||
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
context.translation.viewDetails,
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)),
|
||||||
|
),
|
||||||
|
4.width,
|
||||||
|
Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).toShadowContainer(context, withShadow: showShadow).onPress(() async {
|
||||||
|
Navigator.push(context, MaterialPageRoute(builder: (context) => EquipmentInternalAuditDetailPage(auditId: requestDetails!.id!)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget infoWidget({required String label, String? value, required BuildContext context}) {
|
||||||
|
if (value != null && value.isNotEmpty) {
|
||||||
|
return '$label: $value'.bodyText(context);
|
||||||
|
}
|
||||||
|
return const SizedBox();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,322 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:developer';
|
||||||
|
import 'dart:io';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:test_sa/controllers/api_routes/api_manager.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/internal_audit_timer_model.dart';
|
||||||
|
import 'package:test_sa/modules/internal_audit_module/models/update_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_lazy_loading.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<UpdateEquipmentInternalAuditPage> createState() => _UpdateEquipmentInternalAuditPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UpdateEquipmentInternalAuditPageState extends State<UpdateEquipmentInternalAuditPage> {
|
||||||
|
final bool _isLoading = false;
|
||||||
|
double totalWorkingHours = 0.0;
|
||||||
|
AuditFormModel formModel = AuditFormModel();
|
||||||
|
final TextEditingController _workingHoursController = TextEditingController();
|
||||||
|
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||||
|
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||||
|
List<GenericAttachmentModel> _attachments = [];
|
||||||
|
|
||||||
|
//TODO need to check if it's needed or not..
|
||||||
|
List<TimerHistoryModel> timerList = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
populateForm();
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void populateForm() {
|
||||||
|
formModel.requestId = widget.model?.id;
|
||||||
|
formModel.id = widget.model?.id;
|
||||||
|
_attachments = widget.model?.engineerData?.attachments?.map((e) => GenericAttachmentModel(id: e.id?.toInt() ?? 0, name: e.name!)).toList() ?? [];
|
||||||
|
|
||||||
|
calculateWorkingTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
void calculateWorkingTime() {
|
||||||
|
final helperModel = formModel;
|
||||||
|
final timers = helperModel.auditTimers ?? [];
|
||||||
|
totalWorkingHours = timers.fold<double>(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.startDate,
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
_onSubmit(BuildContext context) async {
|
||||||
|
bool isTimerPickerEnable = ApiManager.instance.assetGroup?.enabledEngineerTimer ?? false;
|
||||||
|
InternalAuditProvider provider = Provider.of<InternalAuditProvider>(context, listen: false);
|
||||||
|
|
||||||
|
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
|
||||||
|
formModel.auditTimers ??= [];
|
||||||
|
if (formModel.auditTimePicker != null) {
|
||||||
|
int durationInSecond = formModel.auditTimePicker!.endAt!.difference(formModel.auditTimePicker!.startAt!).inSeconds;
|
||||||
|
formModel.auditTimers?.add(
|
||||||
|
InternalAuditTimerModel(
|
||||||
|
id: 0,
|
||||||
|
startDate: formModel.auditTimePicker!.startAt!.toIso8601String(), // Handle potential null
|
||||||
|
endDate: formModel.auditTimePicker!.endAt?.toIso8601String(), // Handle potential null
|
||||||
|
totalWorkingHour: ((durationInSecond) / 60 / 60),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
formModel.timerModelList?.forEach((timer) {
|
||||||
|
int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds;
|
||||||
|
formModel.auditTimers?.add(
|
||||||
|
InternalAuditTimerModel(
|
||||||
|
id: 0,
|
||||||
|
startDate: timer.startAt!.toIso8601String(), // Handle potential null
|
||||||
|
endDate: timer.endAt?.toIso8601String(), // Handle potential null
|
||||||
|
totalWorkingHour: ((durationInSecond) / 60 / 60),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
_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,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
final success = await provider.updateEquipmentInternalAudit(model: formModel);
|
||||||
|
Navigator.pop(context);
|
||||||
|
if (formModel.isComplete == true) {
|
||||||
|
//Navigate to List screen.
|
||||||
|
} else if (formModel.isComplete == false) {
|
||||||
|
//Navigate to Detail screen.
|
||||||
|
if (success) {
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
} else {
|
||||||
|
Fluttertoast.showToast(msg: 'Failed to update');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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: 'Upload Attachment',
|
||||||
|
attachment: _attachments,
|
||||||
|
buttonColor: AppColor.primary10,
|
||||||
|
onlyImages: false,
|
||||||
|
buttonIcon: 'attachment_icon'.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) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
//TODO multiple timer ..
|
||||||
|
// AppTimer(
|
||||||
|
// label: context.translation.timer,
|
||||||
|
// timer: formModel.auditTimerModel,
|
||||||
|
// // enabled: enableTimer,
|
||||||
|
// pickerTimer: formModel.auditTimePicker,
|
||||||
|
// pickerFromDate: DateTime.tryParse(widget.model?.createdDate ?? ''),
|
||||||
|
// onPick: (time) {
|
||||||
|
// formModel.auditTimePicker = time;
|
||||||
|
// setState(() {});
|
||||||
|
// log('Time picker start ${formModel.auditTimePicker?.startAt}');
|
||||||
|
// log('Time picker end ${formModel.auditTimePicker?.endAt}');
|
||||||
|
// },
|
||||||
|
// timerProgress: (isRunning) {},
|
||||||
|
// onChange: (timer) async {
|
||||||
|
// formModel.auditTimerModel = timer;
|
||||||
|
// log('start ${formModel.auditTimerModel?.startAt}');
|
||||||
|
// log('end ${formModel.auditTimerModel?.endAt}');
|
||||||
|
// if (timer.startAt != null && timer.endAt != null) {
|
||||||
|
// formModel.timerModelList = formModel.timerModelList ?? [];
|
||||||
|
// formModel.timerModelList!.add(timer);
|
||||||
|
// }
|
||||||
|
// setState(() {});
|
||||||
|
// log('list length ${formModel.timerModelList?.length}');
|
||||||
|
// return true;
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
AppTimer(
|
||||||
|
label: context.translation.workingHours,
|
||||||
|
timer: formModel.auditTimerModel,
|
||||||
|
pickerFromDate: DateTime.tryParse(widget.model?.createdDate ?? ''),
|
||||||
|
pickerTimer: formModel.auditTimePicker,
|
||||||
|
showPicker: false,
|
||||||
|
onPick: (timer) {
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,278 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:developer';
|
||||||
|
import 'dart:io';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/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/device/asset.dart';
|
||||||
|
import 'package:test_sa/models/generic_attachment_model.dart';
|
||||||
|
import 'package:test_sa/models/helper_data_models/workorder/work_order_helper_models.dart';
|
||||||
|
import 'package:test_sa/models/lookup.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/equipment_internal_audit_form_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/system_internal_audit_form_model.dart';
|
||||||
|
import 'package:test_sa/modules/internal_audit_module/pages/system_internal_audit/system_audit_work_order_auto_complete_field.dart';
|
||||||
|
import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_checklist_provider.dart';
|
||||||
|
import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_finding_type_provider.dart';
|
||||||
|
import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_provider.dart';
|
||||||
|
import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_wo_type_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_lazy_loading.dart';
|
||||||
|
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
|
||||||
|
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
|
||||||
|
import 'package:test_sa/views/widgets/equipment/asset_picker.dart';
|
||||||
|
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
|
||||||
|
import 'package:test_sa/views/widgets/parts/auto_complete_parts_field.dart';
|
||||||
|
import '../../../../../../../new_views/common_widgets/default_app_bar.dart';
|
||||||
|
|
||||||
|
class CreateSystemInternalAuditForm extends StatefulWidget {
|
||||||
|
static const String id = "/create-system-audit-view";
|
||||||
|
|
||||||
|
const CreateSystemInternalAuditForm({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_CreateSystemInternalAuditFormState createState() => _CreateSystemInternalAuditFormState();
|
||||||
|
}
|
||||||
|
//TODO remove unnecessary code
|
||||||
|
|
||||||
|
class _CreateSystemInternalAuditFormState extends State<CreateSystemInternalAuditForm> with TickerProviderStateMixin {
|
||||||
|
late TextEditingController _commentController;
|
||||||
|
late InternalAuditProvider _internalAuditProvider;
|
||||||
|
final SystemInternalAuditFormModel _model = SystemInternalAuditFormModel();
|
||||||
|
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||||
|
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||||
|
final List<GenericAttachmentModel> _attachments = [];
|
||||||
|
late TextEditingController _woAutoCompleteController;
|
||||||
|
bool showLoading = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_commentController = TextEditingController();
|
||||||
|
_woAutoCompleteController = TextEditingController();
|
||||||
|
_internalAuditProvider = Provider.of<InternalAuditProvider>(context, listen: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_commentController.dispose();
|
||||||
|
_woAutoCompleteController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
key: _scaffoldKey,
|
||||||
|
appBar: DefaultAppBar(title: 'System Internal Audit Checklist'.addTranslation),
|
||||||
|
body: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
SingleItemDropDownMenu<Lookup, InternalAuditWoTypeProvider>(
|
||||||
|
context: context,
|
||||||
|
height: 56.toScreenHeight,
|
||||||
|
title: 'Wo Type'.addTranslation,
|
||||||
|
showShadow: false,
|
||||||
|
backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
showAsBottomSheet: true,
|
||||||
|
initialValue: _model.workOrderType,
|
||||||
|
onSelect: (status) {
|
||||||
|
if (status != null) {
|
||||||
|
_model.workOrderType = status;
|
||||||
|
_model.workOrderDetailModel = SystemAuditWorkOrderDetailModel();
|
||||||
|
_clearWorkOrderSelectionIds();
|
||||||
|
_woAutoCompleteController.clear();
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
12.height,
|
||||||
|
SystemAuditWoAutoCompleteField(
|
||||||
|
woTypeId: _model.workOrderType?.value,
|
||||||
|
controller: _woAutoCompleteController,
|
||||||
|
clearAfterPick: false,
|
||||||
|
initialValue: '',
|
||||||
|
onPick: (wo) async {
|
||||||
|
InternalAuditProvider provider = Provider.of<InternalAuditProvider>(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,
|
||||||
|
// if(_internalAuditModel.woOrderNo!=null)
|
||||||
|
_workOrderInfoWidget(context),
|
||||||
|
12.height,
|
||||||
|
SingleItemDropDownMenu<Lookup, InternalAuditFindingTypeProvider>(
|
||||||
|
context: context,
|
||||||
|
height: 56.toScreenHeight,
|
||||||
|
title: 'Finding Type'.addTranslation,
|
||||||
|
showShadow: false,
|
||||||
|
backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
showAsBottomSheet: true,
|
||||||
|
initialValue: _model.findingType,
|
||||||
|
onSelect: (status) {
|
||||||
|
if (status != null) {
|
||||||
|
_model.findingType = status;
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
12.height,
|
||||||
|
AppTextFormField(
|
||||||
|
backgroundColor: AppColor.fieldBgColor(context),
|
||||||
|
labelText: 'Finding Description'.addTranslation,
|
||||||
|
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
|
||||||
|
alignLabelWithHint: true,
|
||||||
|
textInputType: TextInputType.multiline,
|
||||||
|
showShadow: false,
|
||||||
|
onSaved: (value) {
|
||||||
|
_model.findingDescription = value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
16.height,
|
||||||
|
AttachmentPicker(
|
||||||
|
label: context.translation.attachments,
|
||||||
|
attachment: _attachments,
|
||||||
|
buttonColor: AppColor.primary10,
|
||||||
|
onlyImages: false,
|
||||||
|
buttonIcon: 'attachment_icon'.toSvgAsset(color: AppColor.primary10),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).toShadowContainer(context),
|
||||||
|
).expanded,
|
||||||
|
FooterActionButton.footerContainer(
|
||||||
|
context: context,
|
||||||
|
child: AppFilledButton(
|
||||||
|
buttonColor: AppColor.primary10,
|
||||||
|
label: context.translation.submitRequest,
|
||||||
|
onPressed: _submit,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _submit() async {
|
||||||
|
InternalAuditProvider internalAuditProvider = Provider.of<InternalAuditProvider>(context, listen: false);
|
||||||
|
if (_formKey.currentState!.validate()) {
|
||||||
|
_formKey.currentState!.save();
|
||||||
|
_model.attachments=[];
|
||||||
|
for (var item in _attachments) {
|
||||||
|
String fileName = ServiceRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
|
||||||
|
_model.attachments?.add(InternalAuditAttachments(id: item.id, 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _workOrderInfoWidget(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(12),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: showLoading ? Colors.white : const Color(0xffF4F6FC),
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(
|
||||||
|
color: const Color(0xff212936).withOpacity(.03),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
_model.workOrderType?.name ?? 'WO Type',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14.toScreenWidth,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
fontStyle: FontStyle.normal,
|
||||||
|
color: Colors.black87,
|
||||||
|
decoration: TextDecoration.none,
|
||||||
|
),
|
||||||
|
).expanded,
|
||||||
|
const Icon(
|
||||||
|
Icons.info,
|
||||||
|
color: Color(0xff7D859A),
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
6.height,
|
||||||
|
"${context.translation.site}: ${_model.workOrderDetailModel?.woSite ?? '-'}".bodyText(context),
|
||||||
|
"${'Eng. Name'.addTranslation}: ${_model.workOrderDetailModel?.woAssignedEngineer ?? '-'}".bodyText(context),
|
||||||
|
"${'Asset Name'.addTranslation}: ${_model.workOrderDetailModel?.woAssetName ?? '-'}".bodyText(context),
|
||||||
|
"${context.translation.model}: ${_model.workOrderDetailModel?.woModel ?? '-'}".bodyText(context),
|
||||||
|
"${context.translation.manufacture}: ${_model.workOrderDetailModel?.woManufacturer ?? '-'}".bodyText(context),
|
||||||
|
"${'SN'.addTranslation}: ${_model.workOrderDetailModel?.wosn ?? '-'}".bodyText(context),
|
||||||
|
"${context.translation.assetNo}: ${_model.workOrderDetailModel?.woAssetNo ?? '-'}".bodyText(context),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
).toShimmer(isShow: showLoading, context: context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateWorkOrderReference({int? woTypeId, int? selectedId}) {
|
||||||
|
_clearWorkOrderSelectionIds();
|
||||||
|
if (woTypeId == null || selectedId == null) return;
|
||||||
|
switch (woTypeId) {
|
||||||
|
case 1: // CM
|
||||||
|
_model.correctiveMaintenanceId = selectedId;
|
||||||
|
break;
|
||||||
|
case 2: // Gas Refill
|
||||||
|
_model.gasRefillId = selectedId;
|
||||||
|
break;
|
||||||
|
case 3: // Asset Transfer
|
||||||
|
_model.assetTransferId = selectedId;
|
||||||
|
break;
|
||||||
|
case 4: // PPM Request
|
||||||
|
_model.planPreventiveVisitId = selectedId;
|
||||||
|
break;
|
||||||
|
case 5: // Recurrent WOx
|
||||||
|
_model.planRecurrentTaskId = selectedId;
|
||||||
|
break;
|
||||||
|
case 6: // Task
|
||||||
|
_model.taskJobId = selectedId;
|
||||||
|
break;
|
||||||
|
case 7: // Recall & Alert
|
||||||
|
_model.taskAlertJobId = selectedId;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _clearWorkOrderSelectionIds() {
|
||||||
|
_model.correctiveMaintenanceId = null;
|
||||||
|
_model.planPreventiveVisitId = null;
|
||||||
|
_model.assetTransferId = null;
|
||||||
|
_model.taskJobId = null;
|
||||||
|
_model.taskAlertJobId = null;
|
||||||
|
_model.gasRefillId = null;
|
||||||
|
_model.planRecurrentTaskId = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,149 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:test_sa/controllers/api_routes/urls.dart';
|
||||||
|
import 'package:test_sa/extensions/context_extension.dart';
|
||||||
|
import 'package:test_sa/extensions/int_extensions.dart';
|
||||||
|
import 'package:test_sa/extensions/text_extensions.dart';
|
||||||
|
import 'package:test_sa/extensions/widget_extensions.dart';
|
||||||
|
import 'package:test_sa/modules/internal_audit_module/models/system_internal_audit_form_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/app_style/app_text_style.dart';
|
||||||
|
import 'package:test_sa/views/app_style/sizing.dart';
|
||||||
|
|
||||||
|
class SystemAuditWoAutoCompleteField extends StatefulWidget {
|
||||||
|
final String initialValue;
|
||||||
|
final int? woTypeId;
|
||||||
|
final TextEditingController controller;
|
||||||
|
final bool clearAfterPick;
|
||||||
|
final Function(WoAutoCompleteModel) onPick;
|
||||||
|
|
||||||
|
const SystemAuditWoAutoCompleteField({Key? key, required this.initialValue, this.woTypeId, required this.onPick, this.clearAfterPick = true, required this.controller}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_SystemAuditWoAutoCompleteFieldState createState() => _SystemAuditWoAutoCompleteFieldState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SystemAuditWoAutoCompleteFieldState extends State<SystemAuditWoAutoCompleteField> {
|
||||||
|
late InternalAuditProvider _provider;
|
||||||
|
|
||||||
|
//
|
||||||
|
// late TextEditingController _controller;
|
||||||
|
|
||||||
|
bool loading = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
// w controller = widget.controller ?? TextEditingController(text: widget.initialValue);
|
||||||
|
super.initState();
|
||||||
|
_provider = Provider.of<InternalAuditProvider>(context, listen: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(covariant SystemAuditWoAutoCompleteField oldWidget) {
|
||||||
|
// if (widget.initialValue != oldWidget.initialValue) {
|
||||||
|
// // _controller = widget.controller ?? TextEditingController(text: widget.initialValue);
|
||||||
|
// }
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
if (widget.controller == null) {
|
||||||
|
// _controller.dispose();
|
||||||
|
}
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final border = UnderlineInputBorder(borderSide: BorderSide.none, borderRadius: BorderRadius.circular(10));
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.background(context),
|
||||||
|
borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)),
|
||||||
|
// boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)],
|
||||||
|
),
|
||||||
|
child: Autocomplete<WoAutoCompleteModel>(
|
||||||
|
optionsBuilder: (TextEditingValue textEditingValue) async {
|
||||||
|
if (textEditingValue.text.isEmpty) {
|
||||||
|
if (loading) {
|
||||||
|
setState(() {
|
||||||
|
loading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return const Iterable<WoAutoCompleteModel>.empty();
|
||||||
|
}
|
||||||
|
if (!loading) {
|
||||||
|
setState(() {
|
||||||
|
loading = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
List<WoAutoCompleteModel> workOrders = (await _provider.getWorkOrderByWoType(text: textEditingValue.text, woId:widget.woTypeId));
|
||||||
|
setState(() {
|
||||||
|
loading = false;
|
||||||
|
});
|
||||||
|
return workOrders;
|
||||||
|
},
|
||||||
|
displayStringForOption: (WoAutoCompleteModel option) => option.displayName ?? '',
|
||||||
|
fieldViewBuilder: (BuildContext context, TextEditingController fieldTextEditingController, FocusNode fieldFocusNode, VoidCallback onFieldSubmitted) {
|
||||||
|
return TextField(
|
||||||
|
controller: widget.controller,
|
||||||
|
focusNode: fieldFocusNode,
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: AppColor.black10),
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: border,
|
||||||
|
disabledBorder: border,
|
||||||
|
focusedBorder: border,
|
||||||
|
enabledBorder: border,
|
||||||
|
errorBorder: border,
|
||||||
|
contentPadding: EdgeInsets.symmetric(vertical: 8.toScreenHeight, horizontal: 16.toScreenWidth),
|
||||||
|
constraints: const BoxConstraints(),
|
||||||
|
suffixIconConstraints: const BoxConstraints(maxHeight: 24, maxWidth: 24 + 8),
|
||||||
|
filled: true,
|
||||||
|
fillColor: AppColor.fieldBgColor(context),
|
||||||
|
errorStyle: AppTextStyle.tiny.copyWith(color: context.isDark ? AppColor.red50 : AppColor.red60),
|
||||||
|
floatingLabelStyle: AppTextStyle.body1.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? null : AppColor.neutral20),
|
||||||
|
labelText: context.translation.woNumber,
|
||||||
|
labelStyle: AppTextStyles.tinyFont.copyWith(color: AppColor.textColor(context)),
|
||||||
|
suffixIcon: loading ? const CircularProgressIndicator(color: AppColor.primary10, strokeWidth: 3.0).paddingOnly(end: 8) : null,
|
||||||
|
),
|
||||||
|
textInputAction: TextInputAction.search,
|
||||||
|
onChanged: (text) {
|
||||||
|
fieldTextEditingController.text = text;
|
||||||
|
},
|
||||||
|
onSubmitted: (String value) {
|
||||||
|
onFieldSubmitted();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onSelected: (WoAutoCompleteModel selection) {
|
||||||
|
if (widget.clearAfterPick) {
|
||||||
|
widget.controller.clear();
|
||||||
|
} else {
|
||||||
|
widget.controller.text = (selection.displayName ?? "");
|
||||||
|
}
|
||||||
|
widget.onPick(selection);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// String getUrl(int? woTypeId) {
|
||||||
|
// if (woTypeId == null) return '';
|
||||||
|
// String base = URLs.woAutoCompleteBase;
|
||||||
|
// var urlMap = {
|
||||||
|
// 1: '$base/ServiceRequest/WorkOrderAutoComplete', // CM
|
||||||
|
// 2: '$base/GasRefill/GetGasRefillAutoComplete', // Gas Refill
|
||||||
|
// 3: '$base/AssetTransfer/GetAssetTransferAutoComplete', // Asset Transfer
|
||||||
|
// 4: '$base/PlanPreventiveVisit/GetAutoCompletePlanPreventiveVisit', // PPM Request
|
||||||
|
// 5: '$base/PlanRecurrentTasks/GetPlanRecurrentTask', // Recurrent WO
|
||||||
|
// 6: '$base/TaskJobs/AutocompleteTaskJob', // Task
|
||||||
|
// 7: '$base/TaskJobs/AutocompleteTaskJob', // Recall & Alert
|
||||||
|
// };
|
||||||
|
// return urlMap[woTypeId] ?? '';
|
||||||
|
// }
|
||||||
|
}
|
||||||
@ -0,0 +1,219 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:test_sa/controllers/api_routes/urls.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/modules/cm_module/views/components/action_button/footer_action_button.dart';
|
||||||
|
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
|
||||||
|
import 'package:test_sa/modules/internal_audit_module/models/system_internal_audit_data_model.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/pages/system_internal_audit/update_system_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';
|
||||||
|
|
||||||
|
class SystemInternalAuditDetailPage extends StatefulWidget {
|
||||||
|
static const String id = "/details-system-internal-audit";
|
||||||
|
final int auditId;
|
||||||
|
|
||||||
|
SystemInternalAuditDetailPage({Key? key, required this.auditId}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_SystemInternalAuditDetailPageState createState() {
|
||||||
|
return _SystemInternalAuditDetailPageState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SystemInternalAuditDetailPageState extends State<SystemInternalAuditDetailPage> {
|
||||||
|
bool isWoType = true;
|
||||||
|
SystemInternalAuditDataModel? model;
|
||||||
|
late InternalAuditProvider _internalAuditProvider;
|
||||||
|
List<InternalAuditAttachments> allAttachments = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_internalAuditProvider = Provider.of<InternalAuditProvider>(context, listen: false);
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
getAuditData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getAuditData() async {
|
||||||
|
model = await _internalAuditProvider.getInternalSystemAuditById(widget.auditId);
|
||||||
|
allAttachments.clear();
|
||||||
|
allAttachments = [
|
||||||
|
...(model?.attachments ?? []),
|
||||||
|
...(model?.engineerData?.attachments ?? []),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
//TODO need to check when implementing provider needed or not .
|
||||||
|
return Scaffold(
|
||||||
|
appBar: const DefaultAppBar(title: "Request Details"),
|
||||||
|
body: Selector<InternalAuditProvider, bool>(
|
||||||
|
selector: (_, provider) => provider.isLoading,
|
||||||
|
builder: (_, isLoading, __) {
|
||||||
|
if (isLoading) return const ALoading();
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
assetInformation(),
|
||||||
|
8.height,
|
||||||
|
workOrderInformation(),
|
||||||
|
8.height,
|
||||||
|
//TODO need to check for comments
|
||||||
|
if (model?.findingDescription?.isNotEmpty ?? false) ...[
|
||||||
|
const Divider().defaultStyle(context),
|
||||||
|
// Text(
|
||||||
|
// "Comments".addTranslation,
|
||||||
|
// style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
|
||||||
|
// ),
|
||||||
|
model!.findingDescription!.bodyText(context),
|
||||||
|
],
|
||||||
|
//TODO need to check for attachments
|
||||||
|
if (allAttachments.isNotEmpty) ...[
|
||||||
|
const Divider().defaultStyle(context),
|
||||||
|
Text(
|
||||||
|
"Attachments".addTranslation,
|
||||||
|
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
FilesList(images: allAttachments.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
).paddingAll(0).toShadowContainer(context),
|
||||||
|
).expanded,
|
||||||
|
if (context.userProvider.isEngineer)
|
||||||
|
FooterActionButton.footerContainer(
|
||||||
|
context: context,
|
||||||
|
child: AppFilledButton(
|
||||||
|
buttonColor: AppColor.primary10,
|
||||||
|
label: "Update",
|
||||||
|
onPressed: () async {
|
||||||
|
final result = await Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (_) => UpdateSystemInternalAuditPage(model: model),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (result == true) {
|
||||||
|
await getAuditData();
|
||||||
|
setState(() {}); // refresh UI with new model
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget workOrderInformation() {
|
||||||
|
final details = model?.workOrderDetails;
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Divider().defaultStyle(context),
|
||||||
|
Text(
|
||||||
|
"WO Info",
|
||||||
|
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
|
||||||
|
),
|
||||||
|
6.height,
|
||||||
|
labelValueText(context, context.translation.woNumber, details?.workOrderNo),
|
||||||
|
labelValueText(context, 'WO Type'.addTranslation, model?.workOrderType?.name),
|
||||||
|
labelValueText(context, context.translation.site, details?.woSite),
|
||||||
|
labelValueText(context, context.translation.assetName, details?.woAssetName),
|
||||||
|
labelValueText(context, context.translation.manufacture, details?.woManufacturer),
|
||||||
|
labelValueText(context, context.translation.model, details?.woModel),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget requestDetails() {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Divider().defaultStyle(context),
|
||||||
|
Text(
|
||||||
|
"Request Details",
|
||||||
|
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
|
||||||
|
),
|
||||||
|
6.height,
|
||||||
|
checklistWidget(value: 'Asset Tag'.addTranslation),
|
||||||
|
checklistWidget(value: 'Expired PM Tag'.addTranslation),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget assetInformation() {
|
||||||
|
final details = model?.workOrderDetails;
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Asset Details",
|
||||||
|
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
|
||||||
|
),
|
||||||
|
6.height,
|
||||||
|
labelValueText(context, context.translation.assetName, details?.woAssetName),
|
||||||
|
labelValueText(context, context.translation.assetNo, details?.woAssetNo),
|
||||||
|
labelValueText(context, context.translation.manufacture, details?.woManufacturer),
|
||||||
|
labelValueText(context, context.translation.model, details?.woModel),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget labelValueText(BuildContext context, String label, String? value) {
|
||||||
|
if (value == null || value.isEmpty) return const SizedBox.shrink();
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 4),
|
||||||
|
child: Text(
|
||||||
|
'$label: $value',
|
||||||
|
style: AppTextStyles.bodyText.copyWith(
|
||||||
|
color: context.isDark ? AppColor.neutral30 : AppColor.neutral120,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget checklistWidget({required String value}) {
|
||||||
|
return Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Checkbox(
|
||||||
|
value: true,
|
||||||
|
activeColor: AppColor.neutral120,
|
||||||
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
visualDensity: const VisualDensity(horizontal: -4, vertical: -3),
|
||||||
|
onChanged: (value) {},
|
||||||
|
),
|
||||||
|
value.bodyText(context),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,117 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:flutter/material.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/all_requests_and_count_model.dart';
|
||||||
|
import 'package:test_sa/models/new_models/dashboard_detail.dart';
|
||||||
|
import 'package:test_sa/modules/internal_audit_module/pages/equipment_internal_audit/equipment_internal_audit_detail_page.dart';
|
||||||
|
import 'package:test_sa/modules/internal_audit_module/pages/system_internal_audit/system_internal_audit_detail_page.dart';
|
||||||
|
import 'package:test_sa/new_views/app_style/app_color.dart';
|
||||||
|
import 'package:test_sa/views/widgets/requests/request_status.dart';
|
||||||
|
|
||||||
|
class SystemInternalAuditItemView extends StatelessWidget {
|
||||||
|
final Data? requestData;
|
||||||
|
final RequestsDetails? requestDetails;
|
||||||
|
final bool showShadow;
|
||||||
|
|
||||||
|
const SystemInternalAuditItemView({Key? key, this.requestData, this.requestDetails, this.showShadow = true}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
//TODO need to refactor this code repetation @waseem
|
||||||
|
if (requestData != null) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
StatusLabel(
|
||||||
|
label: requestData!.statusName!,
|
||||||
|
textColor: AppColor.getRequestStatusTextColorByName(context, requestData!.statusName!),
|
||||||
|
backgroundColor: AppColor.getRequestStatusColorByName(context, requestData!.statusName!),
|
||||||
|
),
|
||||||
|
1.width.expanded,
|
||||||
|
Text(
|
||||||
|
requestData!.transactionDate?.toServiceRequestCardFormat ?? "",
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
(requestData?.typeTransaction ?? "Internal Audit Request").heading5(context),
|
||||||
|
infoWidget(label: context.translation.assetNo, value: requestData?.assetNumber, context: context),
|
||||||
|
|
||||||
|
8.height,
|
||||||
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
context.translation.viewDetails,
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)),
|
||||||
|
),
|
||||||
|
4.width,
|
||||||
|
Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).toShadowContainer(context, withShadow: showShadow).onPress(() async {
|
||||||
|
Navigator.push(context, MaterialPageRoute(builder: (context) => SystemInternalAuditDetailPage(auditId: requestDetails!.id!)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
StatusLabel(
|
||||||
|
label: requestDetails!.status!,
|
||||||
|
textColor: AppColor.getRequestStatusTextColorByName(context, requestDetails?.status!),
|
||||||
|
backgroundColor: AppColor.getRequestStatusColorByName(context, requestDetails?.status!),
|
||||||
|
),
|
||||||
|
1.width.expanded,
|
||||||
|
Text(
|
||||||
|
requestDetails!.date?.toServiceRequestCardFormat ?? "",
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
8.height,
|
||||||
|
(requestDetails?.nameOfType ?? "Internal Audit Request").heading5(context),
|
||||||
|
infoWidget(label: context.translation.assetNumber, value: requestDetails!.assetNo, context: context),
|
||||||
|
infoWidget(label: context.translation.assetSN, value: requestDetails!.assetSN, context: context),
|
||||||
|
infoWidget(label: context.translation.model, value: requestDetails!.model, context: context),
|
||||||
|
8.height,
|
||||||
|
// infoWidget(label: context.translation.site, value: requestDetails!.site, context: context),
|
||||||
|
8.height,
|
||||||
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
context.translation.viewDetails,
|
||||||
|
style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)),
|
||||||
|
),
|
||||||
|
4.width,
|
||||||
|
Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).toShadowContainer(context, withShadow: showShadow).onPress(() async {
|
||||||
|
Navigator.push(context, MaterialPageRoute(builder: (context) => SystemInternalAuditDetailPage(auditId: requestDetails!.id!)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget infoWidget({required String label, String? value, required BuildContext context}) {
|
||||||
|
if (value != null && value.isNotEmpty) {
|
||||||
|
return '$label: $value'.bodyText(context);
|
||||||
|
}
|
||||||
|
return const SizedBox();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,316 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:developer';
|
||||||
|
import 'dart:io';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:test_sa/controllers/api_routes/api_manager.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/internal_audit_timer_model.dart';
|
||||||
|
import 'package:test_sa/modules/internal_audit_module/models/system_internal_audit_data_model.dart';
|
||||||
|
import 'package:test_sa/modules/internal_audit_module/models/update_audit_form_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_lazy_loading.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 UpdateSystemInternalAuditPage extends StatefulWidget {
|
||||||
|
static const String id = "update-system-internal-audit";
|
||||||
|
SystemInternalAuditDataModel? model;
|
||||||
|
|
||||||
|
UpdateSystemInternalAuditPage({Key? key, this.model}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<UpdateSystemInternalAuditPage> createState() => _UpdateSystemInternalAuditPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UpdateSystemInternalAuditPageState extends State<UpdateSystemInternalAuditPage> {
|
||||||
|
final bool _isLoading = false;
|
||||||
|
double totalWorkingHours = 0.0;
|
||||||
|
AuditFormModel formModel = AuditFormModel();
|
||||||
|
final TextEditingController _workingHoursController = TextEditingController();
|
||||||
|
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||||
|
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||||
|
List<GenericAttachmentModel> _attachments = [];
|
||||||
|
|
||||||
|
//TODO need to check if it's needed or not..
|
||||||
|
List<TimerHistoryModel> timerList = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
populateForm();
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void populateForm() {
|
||||||
|
formModel.requestId = widget.model?.id;
|
||||||
|
formModel.id = widget.model?.id;
|
||||||
|
_attachments = widget.model?.engineerData?.attachments?.map((e) => GenericAttachmentModel(id: e.id?.toInt() ?? 0, name: e.name!)).toList() ?? [];
|
||||||
|
|
||||||
|
calculateWorkingTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
void calculateWorkingTime() {
|
||||||
|
final helperModel = formModel;
|
||||||
|
final timers = helperModel.auditTimers ?? [];
|
||||||
|
totalWorkingHours = timers.fold<double>(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.startDate,
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
_onSubmit(BuildContext context) async {
|
||||||
|
bool isTimerPickerEnable = ApiManager.instance.assetGroup?.enabledEngineerTimer ?? false;
|
||||||
|
InternalAuditProvider provider = Provider.of<InternalAuditProvider>(context, listen: false);
|
||||||
|
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
|
||||||
|
|
||||||
|
formModel.auditTimers ??= [];
|
||||||
|
if (formModel.auditTimePicker != null) {
|
||||||
|
int durationInSecond = formModel.auditTimePicker!.endAt!.difference(formModel.auditTimePicker!.startAt!).inSeconds;
|
||||||
|
formModel.auditTimers?.add(
|
||||||
|
InternalAuditTimerModel(
|
||||||
|
id: 0,
|
||||||
|
startDate: formModel.auditTimePicker!.startAt!.toIso8601String(), // Handle potential null
|
||||||
|
endDate: formModel.auditTimePicker!.endAt?.toIso8601String(), // Handle potential null
|
||||||
|
totalWorkingHour: ((durationInSecond) / 60 / 60),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
formModel.timerModelList?.forEach((timer) {
|
||||||
|
int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds;
|
||||||
|
formModel.auditTimers?.add(
|
||||||
|
InternalAuditTimerModel(
|
||||||
|
id: 0,
|
||||||
|
startDate: timer.startAt!.toIso8601String(), // Handle potential null
|
||||||
|
endDate: timer.endAt?.toIso8601String(), // Handle potential null
|
||||||
|
totalWorkingHour: ((durationInSecond) / 60 / 60),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
_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,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
log('submit press');
|
||||||
|
log('data ${formModel.toJson()}');
|
||||||
|
final success = await provider.updateSystemInternalAudit(model: formModel);
|
||||||
|
Navigator.pop(context);
|
||||||
|
if (formModel.isComplete == true) {
|
||||||
|
//Navigate to List screen.
|
||||||
|
} else if (formModel.isComplete == false) {
|
||||||
|
if (success) {
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
} else {
|
||||||
|
Fluttertoast.showToast(msg: 'Failed to update');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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: 'Upload Attachment',
|
||||||
|
attachment: _attachments,
|
||||||
|
buttonColor: AppColor.primary10,
|
||||||
|
onlyImages: false,
|
||||||
|
buttonIcon: 'attachment_icon'.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: () {
|
||||||
|
log('button press ');
|
||||||
|
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) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
///this is for multiple timers...
|
||||||
|
// AppTimer(
|
||||||
|
// label: context.translation.timer,
|
||||||
|
// timer: formModel.auditTimerModel,
|
||||||
|
// // enabled: enableTimer,
|
||||||
|
// pickerTimer: formModel.auditTimePicker,
|
||||||
|
// pickerFromDate: DateTime.tryParse(widget.model?.createdDate ?? ''),
|
||||||
|
// onPick: (time) {
|
||||||
|
// formModel.auditTimePicker = time;
|
||||||
|
// },
|
||||||
|
// timerProgress: (isRunning) {},
|
||||||
|
// onChange: (timer) async {
|
||||||
|
// formModel.auditTimerModel = timer;
|
||||||
|
// if (timer.startAt != null && timer.endAt != null) {
|
||||||
|
// formModel.timerModelList = formModel.timerModelList ?? [];
|
||||||
|
// formModel.timerModelList!.add(timer);
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
AppTimer(
|
||||||
|
label: context.translation.workingHours,
|
||||||
|
showPicker: false,
|
||||||
|
timer: formModel.auditTimerModel,
|
||||||
|
pickerFromDate: DateTime.tryParse(widget.model?.createdDate ?? ''),
|
||||||
|
pickerTimer: formModel.auditTimePicker,
|
||||||
|
onPick: (time) {
|
||||||
|
updateTimer(timer: time);
|
||||||
|
},
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:http/http.dart';
|
||||||
|
import 'package:test_sa/controllers/api_routes/api_manager.dart';
|
||||||
|
import 'package:test_sa/controllers/api_routes/urls.dart';
|
||||||
|
import 'package:test_sa/models/lookup.dart';
|
||||||
|
import 'package:test_sa/providers/loading_list_notifier.dart';
|
||||||
|
|
||||||
|
class InternalAuditCheckListProvider extends LoadingListNotifier<Lookup> {
|
||||||
|
@override
|
||||||
|
Future getData({int? id}) async {
|
||||||
|
if (loading ?? false) return -2;
|
||||||
|
loading = true;
|
||||||
|
notifyListeners();
|
||||||
|
Response response;
|
||||||
|
try {
|
||||||
|
response = await ApiManager.instance.get(URLs.getInternalAuditChecklist);
|
||||||
|
} catch (error) {
|
||||||
|
loading = false;
|
||||||
|
stateCode = -1;
|
||||||
|
notifyListeners();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
stateCode = response.statusCode;
|
||||||
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||||
|
// client's request was successfully received
|
||||||
|
List listJson = json.decode(response.body)["data"];
|
||||||
|
items = listJson.map((department) => Lookup.fromJson(department)).toList();
|
||||||
|
}
|
||||||
|
loading = false;
|
||||||
|
notifyListeners();
|
||||||
|
return response.statusCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:http/http.dart';
|
||||||
|
import 'package:test_sa/controllers/api_routes/api_manager.dart';
|
||||||
|
import 'package:test_sa/controllers/api_routes/urls.dart';
|
||||||
|
import 'package:test_sa/models/lookup.dart';
|
||||||
|
import 'package:test_sa/providers/loading_list_notifier.dart';
|
||||||
|
|
||||||
|
class InternalAuditFindingTypeProvider extends LoadingListNotifier<Lookup> {
|
||||||
|
@override
|
||||||
|
Future getData({int? id}) async {
|
||||||
|
if (loading ?? false) return -2;
|
||||||
|
loading = true;
|
||||||
|
notifyListeners();
|
||||||
|
Response response;
|
||||||
|
try {
|
||||||
|
response = await ApiManager.instance.get(URLs.getInternalAuditFindingType);
|
||||||
|
} catch (error) {
|
||||||
|
loading = false;
|
||||||
|
stateCode = -1;
|
||||||
|
notifyListeners();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
stateCode = response.statusCode;
|
||||||
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||||
|
// client's request was successfully received
|
||||||
|
List listJson = json.decode(response.body)["data"];
|
||||||
|
items = listJson.map((department) => Lookup.fromJson(department)).toList();
|
||||||
|
}
|
||||||
|
loading = false;
|
||||||
|
notifyListeners();
|
||||||
|
return response.statusCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,211 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
|
import 'package:http/http.dart';
|
||||||
|
import 'package:test_sa/controllers/api_routes/api_manager.dart';
|
||||||
|
import 'package:test_sa/controllers/api_routes/urls.dart';
|
||||||
|
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/update_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_data_model.dart';
|
||||||
|
import 'package:test_sa/modules/internal_audit_module/models/system_internal_audit_form_model.dart';
|
||||||
|
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
|
||||||
|
|
||||||
|
class InternalAuditProvider extends ChangeNotifier {
|
||||||
|
final pageItemNumber = 10;
|
||||||
|
final searchPageItemNumber = 10;
|
||||||
|
int pageNo = 1;
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
pageNo = 1;
|
||||||
|
stateCode = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int? stateCode;
|
||||||
|
bool isDetailLoading = false;
|
||||||
|
bool nextPage = false;
|
||||||
|
bool isNextPageLoading = false;
|
||||||
|
bool isLoading = false;
|
||||||
|
|
||||||
|
Future<EquipmentInternalAuditDataModel?> getEquipmentInternalAuditById(int id) async {
|
||||||
|
try {
|
||||||
|
isLoading = true;
|
||||||
|
notifyListeners();
|
||||||
|
Response response = await ApiManager.instance.get(
|
||||||
|
"${URLs.getInternalAuditEquipmentById}?internalAuditEquipmentId=$id",
|
||||||
|
);
|
||||||
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||||
|
final decodedBody = jsonDecode(response.body);
|
||||||
|
EquipmentInternalAuditDataModel model = EquipmentInternalAuditDataModel.fromJson(decodedBody["data"]);
|
||||||
|
isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
return model;
|
||||||
|
} else {
|
||||||
|
isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<SystemInternalAuditDataModel?> getInternalSystemAuditById(int id) async {
|
||||||
|
try {
|
||||||
|
isLoading = true;
|
||||||
|
notifyListeners();
|
||||||
|
Response response = await ApiManager.instance.get("${URLs.getInternalAuditSystemById}?AuditSystemId=$id");
|
||||||
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||||
|
final decodedBody = jsonDecode(response.body);
|
||||||
|
SystemInternalAuditDataModel model = SystemInternalAuditDataModel.fromJson(decodedBody["data"]);
|
||||||
|
isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
return model;
|
||||||
|
} else {
|
||||||
|
isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<SystemAuditWorkOrderDetailModel?> 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<bool> 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<bool> updateSystemInternalAudit({required AuditFormModel model}) async {
|
||||||
|
isLoading = true;
|
||||||
|
Response response;
|
||||||
|
try {
|
||||||
|
response = await ApiManager.instance.put(URLs.updateAuditSystemEngineer, body: model.toJson());
|
||||||
|
stateCode = response.statusCode;
|
||||||
|
isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
log('status code ${stateCode}');
|
||||||
|
if (stateCode == 200) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (error) {
|
||||||
|
isLoading = false;
|
||||||
|
stateCode = -1;
|
||||||
|
notifyListeners();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> addEquipmentInternalAudit({
|
||||||
|
required BuildContext context,
|
||||||
|
required EquipmentInternalAuditFormModel request,
|
||||||
|
}) async {
|
||||||
|
bool status = false;
|
||||||
|
Response response;
|
||||||
|
try {
|
||||||
|
response = await ApiManager.instance.post(URLs.addOrUpdateEquipmentInternalAudit, 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<bool> 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<List<WoAutoCompleteModel>> getWorkOrderByWoType({String? text, required int? woId}) async {
|
||||||
|
late Response response;
|
||||||
|
try {
|
||||||
|
Response response = await ApiManager.instance.get("${URLs.getWoAutoComplete}?workOrderTypeId=$woId&search=$text");
|
||||||
|
// response = await ApiManager.instance.post(url, body: {"search": text});
|
||||||
|
List<WoAutoCompleteModel> woOrderList = [];
|
||||||
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||||
|
List categoriesListJson = json.decode(response.body)["data"];
|
||||||
|
woOrderList = categoriesListJson.map((wo) => WoAutoCompleteModel.fromJson(wo)).toList();
|
||||||
|
}
|
||||||
|
return woOrderList;
|
||||||
|
} catch (error) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:http/http.dart';
|
||||||
|
import 'package:test_sa/controllers/api_routes/api_manager.dart';
|
||||||
|
import 'package:test_sa/controllers/api_routes/urls.dart';
|
||||||
|
import 'package:test_sa/models/lookup.dart';
|
||||||
|
import 'package:test_sa/providers/loading_list_notifier.dart';
|
||||||
|
|
||||||
|
class InternalAuditWoTypeProvider extends LoadingListNotifier<Lookup> {
|
||||||
|
@override
|
||||||
|
Future getData({int? id}) async {
|
||||||
|
if (loading ?? false) return -2;
|
||||||
|
loading = true;
|
||||||
|
notifyListeners();
|
||||||
|
Response response;
|
||||||
|
try {
|
||||||
|
response = await ApiManager.instance.get(URLs.getInternalAuditWoType);
|
||||||
|
} catch (error) {
|
||||||
|
loading = false;
|
||||||
|
stateCode = -1;
|
||||||
|
notifyListeners();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
stateCode = response.statusCode;
|
||||||
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||||
|
List listJson = json.decode(response.body)["data"];
|
||||||
|
items = listJson.map((department) => Lookup.fromJson(department)).toList();
|
||||||
|
}
|
||||||
|
loading = false;
|
||||||
|
notifyListeners();
|
||||||
|
return response.statusCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,172 @@
|
|||||||
|
class AssetAnalytics {
|
||||||
|
num? assetId;
|
||||||
|
String? assetNumber;
|
||||||
|
String? assetName;
|
||||||
|
num? lastPrice;
|
||||||
|
String? lastPONo;
|
||||||
|
String? lastPODate;
|
||||||
|
num? sameAssetQuantity;
|
||||||
|
String? slaStatus;
|
||||||
|
String? contractNumber;
|
||||||
|
String? contractStartDate;
|
||||||
|
String? contractEndDate;
|
||||||
|
num? assetAgeInDays;
|
||||||
|
String? assetAgeDescription;
|
||||||
|
num? totalMaintenanceCost;
|
||||||
|
num? sparePartCost;
|
||||||
|
num? laborCost;
|
||||||
|
num? exchangeCost;
|
||||||
|
num? travelCost;
|
||||||
|
num? netBookValue;
|
||||||
|
num? purchasedPrice;
|
||||||
|
num? lifeSpan;
|
||||||
|
num? mtbf;
|
||||||
|
String? mtbfDescription;
|
||||||
|
num? totalCMWorkOrders;
|
||||||
|
num? downTimeHours;
|
||||||
|
String? downTimeDescription;
|
||||||
|
num? upTimeHours;
|
||||||
|
String? upTimeDescription;
|
||||||
|
num? operationHours;
|
||||||
|
String? installationDate;
|
||||||
|
String? modelName;
|
||||||
|
String? manufacturerName;
|
||||||
|
String? serialNumber;
|
||||||
|
String? departmentName;
|
||||||
|
String? siteName;
|
||||||
|
num? id;
|
||||||
|
String? createdBy;
|
||||||
|
String? createdDate;
|
||||||
|
String? modifiedBy;
|
||||||
|
String? modifiedDate;
|
||||||
|
|
||||||
|
AssetAnalytics(
|
||||||
|
{this.assetId,
|
||||||
|
this.assetNumber,
|
||||||
|
this.assetName,
|
||||||
|
this.lastPrice,
|
||||||
|
this.lastPONo,
|
||||||
|
this.lastPODate,
|
||||||
|
this.sameAssetQuantity,
|
||||||
|
this.slaStatus,
|
||||||
|
this.contractNumber,
|
||||||
|
this.contractStartDate,
|
||||||
|
this.contractEndDate,
|
||||||
|
this.assetAgeInDays,
|
||||||
|
this.assetAgeDescription,
|
||||||
|
this.totalMaintenanceCost,
|
||||||
|
this.sparePartCost,
|
||||||
|
this.laborCost,
|
||||||
|
this.exchangeCost,
|
||||||
|
this.travelCost,
|
||||||
|
this.netBookValue,
|
||||||
|
this.purchasedPrice,
|
||||||
|
this.lifeSpan,
|
||||||
|
this.mtbf,
|
||||||
|
this.mtbfDescription,
|
||||||
|
this.totalCMWorkOrders,
|
||||||
|
this.downTimeHours,
|
||||||
|
this.downTimeDescription,
|
||||||
|
this.upTimeHours,
|
||||||
|
this.upTimeDescription,
|
||||||
|
this.operationHours,
|
||||||
|
this.installationDate,
|
||||||
|
this.modelName,
|
||||||
|
this.manufacturerName,
|
||||||
|
this.serialNumber,
|
||||||
|
this.departmentName,
|
||||||
|
this.siteName,
|
||||||
|
this.id,
|
||||||
|
this.createdBy,
|
||||||
|
this.createdDate,
|
||||||
|
this.modifiedBy,
|
||||||
|
this.modifiedDate});
|
||||||
|
|
||||||
|
AssetAnalytics.fromJson(Map<String, dynamic> json) {
|
||||||
|
assetId = json['assetId'];
|
||||||
|
assetNumber = json['assetNumber'];
|
||||||
|
assetName = json['assetName'];
|
||||||
|
lastPrice = json['lastPrice'];
|
||||||
|
lastPONo = json['lastPONo'];
|
||||||
|
lastPODate = json['lastPODate'];
|
||||||
|
sameAssetQuantity = json['sameAssetQuantity'];
|
||||||
|
slaStatus = json['slaStatus'];
|
||||||
|
contractNumber = json['contractNumber'];
|
||||||
|
contractStartDate = json['contractStartDate'];
|
||||||
|
contractEndDate = json['contractEndDate'];
|
||||||
|
assetAgeInDays = json['assetAgeInDays'];
|
||||||
|
assetAgeDescription = json['assetAgeDescription'];
|
||||||
|
totalMaintenanceCost = json['totalMaintenanceCost'];
|
||||||
|
sparePartCost = json['sparePartCost'];
|
||||||
|
laborCost = json['laborCost'];
|
||||||
|
exchangeCost = json['exchangeCost'];
|
||||||
|
travelCost = json['travelCost'];
|
||||||
|
netBookValue = json['netBookValue'];
|
||||||
|
purchasedPrice = json['purchasedPrice'];
|
||||||
|
lifeSpan = json['lifeSpan'];
|
||||||
|
mtbf = json['mtbf'];
|
||||||
|
mtbfDescription = json['mtbfDescription'];
|
||||||
|
totalCMWorkOrders = json['totalCMWorkOrders'];
|
||||||
|
downTimeHours = json['downTimeHours'];
|
||||||
|
downTimeDescription = json['downTimeDescription'];
|
||||||
|
upTimeHours = json['upTimeHours'];
|
||||||
|
upTimeDescription = json['upTimeDescription'];
|
||||||
|
operationHours = json['operationHours'];
|
||||||
|
installationDate = json['installationDate'];
|
||||||
|
modelName = json['modelName'];
|
||||||
|
manufacturerName = json['manufacturerName'];
|
||||||
|
serialNumber = json['serialNumber'];
|
||||||
|
departmentName = json['departmentName'];
|
||||||
|
siteName = json['siteName'];
|
||||||
|
id = json['id'];
|
||||||
|
createdBy = json['createdBy'];
|
||||||
|
createdDate = json['createdDate'];
|
||||||
|
modifiedBy = json['modifiedBy'];
|
||||||
|
modifiedDate = json['modifiedDate'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['assetId'] = this.assetId;
|
||||||
|
data['assetNumber'] = this.assetNumber;
|
||||||
|
data['assetName'] = this.assetName;
|
||||||
|
data['lastPrice'] = this.lastPrice;
|
||||||
|
data['lastPONo'] = this.lastPONo;
|
||||||
|
data['lastPODate'] = this.lastPODate;
|
||||||
|
data['sameAssetQuantity'] = this.sameAssetQuantity;
|
||||||
|
data['slaStatus'] = this.slaStatus;
|
||||||
|
data['contractNumber'] = this.contractNumber;
|
||||||
|
data['contractStartDate'] = this.contractStartDate;
|
||||||
|
data['contractEndDate'] = this.contractEndDate;
|
||||||
|
data['assetAgeInDays'] = this.assetAgeInDays;
|
||||||
|
data['assetAgeDescription'] = this.assetAgeDescription;
|
||||||
|
data['totalMaintenanceCost'] = this.totalMaintenanceCost;
|
||||||
|
data['sparePartCost'] = this.sparePartCost;
|
||||||
|
data['laborCost'] = this.laborCost;
|
||||||
|
data['exchangeCost'] = this.exchangeCost;
|
||||||
|
data['travelCost'] = this.travelCost;
|
||||||
|
data['netBookValue'] = this.netBookValue;
|
||||||
|
data['purchasedPrice'] = this.purchasedPrice;
|
||||||
|
data['lifeSpan'] = this.lifeSpan;
|
||||||
|
data['mtbf'] = this.mtbf;
|
||||||
|
data['mtbfDescription'] = this.mtbfDescription;
|
||||||
|
data['totalCMWorkOrders'] = this.totalCMWorkOrders;
|
||||||
|
data['downTimeHours'] = this.downTimeHours;
|
||||||
|
data['downTimeDescription'] = this.downTimeDescription;
|
||||||
|
data['upTimeHours'] = this.upTimeHours;
|
||||||
|
data['upTimeDescription'] = this.upTimeDescription;
|
||||||
|
data['operationHours'] = this.operationHours;
|
||||||
|
data['installationDate'] = this.installationDate;
|
||||||
|
data['modelName'] = this.modelName;
|
||||||
|
data['manufacturerName'] = this.manufacturerName;
|
||||||
|
data['serialNumber'] = this.serialNumber;
|
||||||
|
data['departmentName'] = this.departmentName;
|
||||||
|
data['siteName'] = this.siteName;
|
||||||
|
data['id'] = this.id;
|
||||||
|
data['createdBy'] = this.createdBy;
|
||||||
|
data['createdDate'] = this.createdDate;
|
||||||
|
data['modifiedBy'] = this.modifiedBy;
|
||||||
|
data['modifiedDate'] = this.modifiedDate;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue