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_cx_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