Commit 3bcde21e authored by Sai Srinivas's avatar Sai Srinivas
Browse files

03-09-2025 org structure and finance test cases

parent 332a8e91
class ogresponse {
String? id;
String? name;
String? title;
String? profile;
List<Children>? children;
String? error;
String? message;
int? sessionExists;
ogresponse(
{this.id,
this.name,
this.title,
this.profile,
this.children,
this.error,
this.message,
this.sessionExists});
ogresponse.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
title = json['title'];
profile = json['profile'];
if (json['children'] != null) {
children = <Children>[];
json['children'].forEach((v) {
children!.add(new Children.fromJson(v));
});
}
error = json['error'];
message = json['message'];
sessionExists = json['session_exists'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
data['title'] = this.title;
data['profile'] = this.profile;
if (this.children != null) {
data['children'] = this.children!.map((v) => v.toJson()).toList();
}
data['error'] = this.error;
data['message'] = this.message;
data['session_exists'] = this.sessionExists;
return data;
}
}
class Children {
String? id;
String? name;
String? title;
String? profile;
List<Children>? children;
Children({this.id, this.name, this.title, this.profile, this.children});
Children.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
title = json['title'];
profile = json['profile'];
if (json['children'] != null) {
children = <Children>[];
json['children'].forEach((v) {
children!.add(new Children.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
data['title'] = this.title;
data['profile'] = this.profile;
if (this.children != null) {
data['children'] = this.children!.map((v) => v.toJson()).toList();
}
return data;
}
}
......@@ -9,7 +9,7 @@ import '../Utils/BackgroundLocationService.dart';
class LogoutNotifier extends ChangeNotifier{
bool _logoutButtonClicked = true;
bool _logoutButtonClicked = false;
bool _isLoading = false;
bool get isLoading => _isLoading;
......
......@@ -16,7 +16,7 @@ import 'approveRejectPaymentRequestResponse.dart';
class Requesitionlidtdetailsprovider extends ChangeNotifier {
bool _showMoreDetails = false;
final numberFormat = NumberFormat.decimalPattern();
TextEditingController requestedAmount = TextEditingController();
TextEditingController approvedAmountReadonly = TextEditingController();
TextEditingController proposedPaymentAccount = TextEditingController();
......@@ -35,6 +35,13 @@ class Requesitionlidtdetailsprovider extends ChangeNotifier {
TextEditingController bankHolderName = TextEditingController();
TextEditingController paymentAccountSearchController =
TextEditingController();
TextEditingController editPaymentRequestedAmountController = TextEditingController();
TextEditingController editPaymentRequestedEditableAmountController = TextEditingController();
bool _editPaymentProcessLoading = false;
String? editableAmountError;
String? proposedAmountError;
PaymentDetails _paymentDetails = PaymentDetails();
RequestDetails _requestDetails = RequestDetails();
......@@ -61,12 +68,19 @@ String? proposedAmountError;
bool get showMoreDetails => _showMoreDetails;
bool get editPaymentProcessLoading => _editPaymentProcessLoading;
int get imagePicked => _image_picked;
File? get imagePath => _imageName;
File? get imageFilePath => _image;
set editPaymentProcessLoading(bool value){
_editPaymentProcessLoading = value;
notifyListeners();
}
set imagePicked(int value) {
_image_picked = value;
notifyListeners();
......@@ -329,6 +343,9 @@ String? proposedAmountError;
} catch (e, s) {}
}
String? remarksError;
String? ApprovedAmountError;
String? selectpaymentAccountError;
......@@ -407,6 +424,95 @@ String? proposedAmountError;
} catch (e, s) {}
}
editPrevalues(){
editPaymentRequestedAmountController.text = _requestDetails.requestedAmount ?? "-";
editPaymentRequestedEditableAmountController.text = _requestDetails.requestedAmount ?? "-";
notifyListeners();
}
onChangeEditableAmount(value,context){
var provider = Provider.of<HomescreenNotifier>(context, listen: false);
if(provider.empId=="5" || provider.empId=="130" || provider.empId=="131"||provider.empId =="6"){
editableAmountError =
"";
}else{
if (numberFormat.parse(editPaymentRequestedAmountController.text) <
numberFormat.parse(editPaymentRequestedEditableAmountController.text)) {
editableAmountError =
"Approved Amount should not be greater than amount";
} else {
editableAmountError = null;
}
}
_editPaymentProcessLoading = false;
notifyListeners();
}
bool validateEditprocessPayment(context){
bool isValid = true;
editableAmountError = null;
var provider = Provider.of<HomescreenNotifier>(context, listen: false);
if(editPaymentRequestedEditableAmountController.text.isNotEmpty){
if(provider.empId=="5" || provider.empId=="130" || provider.empId=="131" ||provider.empId =="6"){
editableAmountError = null;
}else{
if (numberFormat.parse(editPaymentRequestedAmountController.text) <
numberFormat.parse(editPaymentRequestedEditableAmountController.text)) {
editableAmountError =
"Approved Amount should not be greater than amount";
isValid = false;
} else {
editableAmountError = null;
}
}
}
_editPaymentProcessLoading = false;
notifyListeners();
return isValid;
}
Future<void> editProcessedPaymentAmountAPIFunction(context,
payment_request_id,approval_amount) async {
try {
_editPaymentProcessLoading = true;
notifyListeners();
if(!validateEditprocessPayment(context)){
return;
}
var provider = Provider.of<HomescreenNotifier>(context, listen: false);
final data = await ApiCalling.editProcessedRequestAmountAPI(
provider.empId,
provider.session,
payment_request_id,
approval_amount
);
if (data != null) {
if (data.error == "0") {
_editPaymentProcessLoading = false;
paymentRequesitionDetails(context, payment_request_id);
resetAll();
toast(context, data.message);
Navigator.pop(context,true);
notifyListeners();
}else{
_editPaymentProcessLoading = false;
notifyListeners();
}
}else{
_editPaymentProcessLoading = false;
notifyListeners();
}
} catch (e, s) {
_editPaymentProcessLoading = false;
notifyListeners();
}
}
bool validateApproval(approved_amount,
approve_remarks,
proposed_payment_account_id,){
......@@ -476,6 +582,10 @@ String? proposedAmountError;
resetAll() {
checkDropDownReset();
editPaymentRequestedAmountController.clear();
editPaymentRequestedEditableAmountController.clear();
_editPaymentProcessLoading = false;
editableAmountError = null;
requestedAmount.clear();
proposedPaymentAccount.clear();
approvedAmountReadonly.clear();
......
......@@ -576,14 +576,12 @@ class Requestionlistprovider extends ChangeNotifier {
payment_date,
) async {
try {
_submitClicked = true;
notifyListeners();
if (!validateDirectForm(context)) {
print("came here");
_submitClicked = false;
return;
}
_submitClicked = true;
notifyListeners();
var homeProvider = Provider.of<HomescreenNotifier>(
context,
listen: false,
......@@ -1132,14 +1130,16 @@ class Requestionlistprovider extends ChangeNotifier {
isValid = false;
_submitClicked = false;
}
if (["Cheque", "RTGS", "IMPS", "NEFT"].contains(_paymentModeValue)) {
if (bankNameController.text.trim().isEmpty) {
bankNameError = "Please enter bank name";
isValid = false;
_submitClicked = false;
}
if (["Cheque", "RTGS", "IMPS", "NEFT"].contains(_paymentModeValue)) {
if (bankBranchController.text.trim().isEmpty) {
bankBranchError = "Please enter bank branch";
isValid = false;
......@@ -1271,6 +1271,7 @@ class Requestionlistprovider extends ChangeNotifier {
// FileError = "Please attach a file";
// isValid = false;
// }
_submitClicked = false;
notifyListeners();
return isValid;
}
......
......@@ -479,11 +479,12 @@ class Paymentreceiptsprovider extends ChangeNotifier {
receipt_date,
) async {
try {
_submitClicked = true;
notifyListeners();
if (!validatereceiptForm(context)) {
return;
}
_submitClicked = true;
notifyListeners();
var homeProvider = Provider.of<HomescreenNotifier>(
context,
......@@ -515,15 +516,15 @@ class Paymentreceiptsprovider extends ChangeNotifier {
notifyListeners();
Navigator.of(context).pop(context);
} else {
_submitClicked = true;
_submitClicked = false;
notifyListeners();
}
} else {
_submitClicked = true;
_submitClicked = false;
notifyListeners();
}
} catch (e, s) {
_submitClicked = true;
_submitClicked = false;
notifyListeners();
}
}
......@@ -816,57 +817,47 @@ class Paymentreceiptsprovider extends ChangeNotifier {
bool isValid = true;
if (_selectedreceiptAccounts == null || _receiptAccountID.trim().isEmpty) {
selectAccountError = "Please select an Account";
_submitClicked = false;
isValid = false;
}
if (_selectreceiptPaymentAccounts == null ||
_receiptPaymentAccountsID.isEmpty) {
selectPaymentAccountError = "Please select an Account";
_submitClicked = false;
isValid = false;
}
if (amountController.text.trim().isEmpty) {
amountError = "Please enter an amount";
_submitClicked = false;
isValid = false;
}
if (dateController.text.trim().isEmpty || _formattedDate!.isEmpty) {
dateError = "Please select Date";
isValid = false;
_submitClicked = false;
}
if (_selectreceiptPaymentModes == null || _receiptPaymentModesID.isEmpty) {
selectPaymentError = "Please select a payment mode";
isValid = false;
_submitClicked = false;
}
if (["Cheque", "RTGS", "IMPS", "NEFT"].contains(_paymentModeValue)) {
if (bankNameController.text.trim().isEmpty) {
bankNameError = "Please enter bank name";
isValid = false;
_submitClicked = false;
}
if (bankBranchController.text.trim().isEmpty) {
bankBranchError = "Please enter bank branch";
isValid = false;
_submitClicked = false;
}
if (bankAccNumberController.text.trim().isEmpty) {
bankNumberError = "Please enter account number";
isValid = false;
_submitClicked = false;
}
if (bankIfscController.text.trim().isEmpty) {
bankIFSCError = "Please enter IFSC code";
isValid = false;
_submitClicked = false;
}
if (bankAcHolderController.text.trim().isEmpty) {
bankHolderError = "Please enter account holder name";
isValid = false;
_submitClicked = false;
}
}
......@@ -874,18 +865,15 @@ class Paymentreceiptsprovider extends ChangeNotifier {
if (bankUpiController.text.trim().isEmpty) {
UPIError = "Please enter UPI ID";
isValid = false;
_submitClicked = false;
}
}
if (paymentReferenceController.text.trim().isEmpty) {
paymentreferenceError = "please enter refernce number";
isValid = false;
_submitClicked = false;
}
if (descController.text.trim().isEmpty) {
descriptionError = "Please Enter Description";
isValid = false;
_submitClicked = false;
}
_submitClicked = false;
notifyListeners();
......
import 'package:flutter/foundation.dart';
import 'package:provider/provider.dart';
import '../../Models/hrmmodels/ogresponse.dart';
import '../../services/api_calling.dart';
import '../HomeScreenNotifier.dart';
class Orgprovider extends ChangeNotifier{
List<Children> _employees=[];
String? _rootName;
String? _rootId;
String? _rootTitle;
String? _rootProfile;
List<Children> get employees => _employees;
String? get rootName => _rootName;
String? get rootID => _rootId;
String? get rootTitle => _rootTitle;
String? get rootProfile => _rootProfile;
Future<void> ogChart(context) async{
try{
var homeProvider = Provider.of<HomescreenNotifier>(
context,
listen: false,
);
final data = await ApiCalling.ogChartAPI(homeProvider.empId, homeProvider.session);
if(data!=null){
if(data.error=="0"){
_rootName = data.name!;
_rootId = data.id!;
_rootProfile = data.profile!;
_rootTitle = data.title!;
_employees = data.children!;
notifyListeners();
}
}
}catch(e,s){
}
}
}
\ No newline at end of file
......@@ -141,7 +141,10 @@ PreferredSizeWidget appbar2New(BuildContext context, title, reset, widget,int co
InkResponse(
onTap: () {
HapticFeedback.selectionClick();
if(reset!=null){
reset();
}
Navigator.pop(context, true);
},
child: SvgPicture.asset("assets/svg/appbar_back_button.svg", height: 25),
......@@ -152,7 +155,10 @@ PreferredSizeWidget appbar2New(BuildContext context, title, reset, widget,int co
child: InkResponse(
onTap: () {
HapticFeedback.selectionClick();
if(reset!=null){
reset();
}
Navigator.pop(context, true);
},
child: Text(
......
......@@ -233,6 +233,7 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider(create: (_) => TourExpensesDetailsProvider()),
ChangeNotifierProvider(create: (_) => RewardListProvider()),
ChangeNotifierProvider(create: (_) => LeaveApplicationListProvider()),
ChangeNotifierProvider(create: (_) => Orgprovider()),
],
child: Builder(
builder: (BuildContext context) {
......
......@@ -335,7 +335,6 @@ class _PaymentrequestionlistdetailsState
Expanded(
child: InkResponse(
onTap: () {
if (provider.Headings[j] == "Attachment") {
HapticFeedback.selectionClick();
Navigator.push(
......@@ -1126,7 +1125,7 @@ class _PaymentrequestionlistdetailsState
SvgPicture.asset(
"assets/svg/finance/level_reject_ic.svg",
),
SizedBox(width: 5,),
SizedBox(width: 5),
Center(
child: Text(
"Reject",
......@@ -1141,7 +1140,7 @@ class _PaymentrequestionlistdetailsState
),
),
),
SizedBox(width: 10),
SizedBox(width: 6),
if ([
"apr_lvl1",
......@@ -1151,7 +1150,7 @@ class _PaymentrequestionlistdetailsState
SvgPicture.asset(
"assets/svg/crm/vertical_line_ic.svg",
),
SizedBox(width: 10),
SizedBox(width: 6),
Expanded(
child: InkResponse(
onTap: () {
......@@ -1181,7 +1180,7 @@ class _PaymentrequestionlistdetailsState
SvgPicture.asset(
"assets/svg/finance/level_approve_ic.svg",
),
SizedBox(width: 5,),
SizedBox(width: 5),
Center(
child: Text(
"Approve",
......@@ -1196,12 +1195,12 @@ class _PaymentrequestionlistdetailsState
),
),
),
SizedBox(width: 10),
SizedBox(width: 6),
] else if (widget.mode == "process") ...[
SvgPicture.asset(
"assets/svg/crm/vertical_line_ic.svg",
),
SizedBox(width: 10),
SizedBox(width: 6),
Expanded(
child: InkResponse(
onTap: () {
......@@ -1229,14 +1228,59 @@ class _PaymentrequestionlistdetailsState
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset("assets/svg/finance/level_add_payment_ic.svg"),
SizedBox(width: 5,),
SvgPicture.asset(
"assets/svg/finance/level_add_payment_ic.svg",
),
SizedBox(width: 5),
Center(
child: Text(
"Add Payment",
style: TextStyle(
color: AppColors.semi_black,
fontSize: 14
fontSize: 14,
),
),
),
],
),
),
),
),
SizedBox(width: 6),
SvgPicture.asset(
"assets/svg/crm/vertical_line_ic.svg",
),
SizedBox(width: 6),
Expanded(
child: InkResponse(
onTap: () {
// provider
// .approveRejectPaymentRequestAPIFunction(
// context,
// provider.requestsDetails.id,
// );
provider.editPrevalues();
_showEditPaymentSheet(
context,
provider.requestsDetails.id,
);
},
child: Container(
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
"assets/svg/crm/lead_details_edit_ic.svg",
),
SizedBox(width: 5),
Center(
child: Text(
"Edit Amount",
style: TextStyle(
color: AppColors.semi_black,
fontSize: 14,
),
),
),
......@@ -2111,7 +2155,14 @@ class _PaymentrequestionlistdetailsState
return Center(child: CircularProgressIndicator());
}
return Container(
return Padding(
padding: EdgeInsets.only(
bottom:
MediaQuery.of(
context,
).viewInsets.bottom,
),
child: Container(
// Constrain the height to avoid overflow
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 0.8,
......@@ -2566,6 +2617,129 @@ class _PaymentrequestionlistdetailsState
),
],
),
),
);
},
),
);
},
);
},
);
}
Future<void> _showEditPaymentSheet(BuildContext context, paymentID) {
return showModalBottomSheet(
useSafeArea: true,
isDismissible: true,
isScrollControlled: true,
showDragHandle: true,
backgroundColor: Colors.white,
enableDrag: true,
context: context,
builder: (context) {
return StatefulBuilder(
builder: (context, setState) {
return SafeArea(
child: Consumer<Requesitionlidtdetailsprovider>(
builder: (context, provider, child) {
return Padding(
padding: EdgeInsets.only(
bottom:
MediaQuery.of(
context,
).viewInsets.bottom,
),
child: Container(
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 0.3,
),
margin: EdgeInsets.only(
bottom: 15,
left: 15,
right: 15,
top: 10,
),
child: Column(
children: [
Align(
alignment: Alignment.topLeft,
child: Text(
"Edit Processed Amount",
style: TextStyle(
color: AppColors.app_blue,
fontSize: 16,
),
),
),
textControllerReadonlyWidget(
context,
provider.editPaymentRequestedAmountController,
"Requested Amount",
(p0) {},
),
textControllerWidget(
context,
provider.editPaymentRequestedEditableAmountController,
"Approved Amount",
"Enter Approved Amount",
(p0) {
provider.onChangeEditableAmount(p0, context);
},
TextInputType.numberWithOptions(),
false,
null,
),
errorWidget(context, provider.editableAmountError),
Padding(
padding: EdgeInsets.only(
left: 5.0,
right: 5.0,
top: 5.0,
bottom: 5.0,
),
child: InkWell(
onTap:
provider.editPaymentProcessLoading
? null
: () {
provider.editPaymentProcessLoading = true;
provider.editProcessedPaymentAmountAPIFunction(
context,
paymentID,
provider
.editPaymentRequestedEditableAmountController
.text,
);
},
child: Container(
height: 45,
decoration: BoxDecoration(
color: AppColors.app_blue,
borderRadius: BorderRadius.circular(14.0),
),
child: Center(
child:
provider.editPaymentProcessLoading
? CircularProgressIndicator.adaptive(
valueColor: AlwaysStoppedAnimation(
AppColors.white,
),
)
: Text(
"Submit",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
),
),
),
),
),
],
),
),
);
},
),
......
......@@ -43,6 +43,7 @@ class _AddpaymentreceiptlistState extends State<Addpaymentreceiptlist> {
listen: false,
);
provider.addReceiptPaymentRequestionViewAPI(context);
provider.submitClicked = false;
});
}
......@@ -628,6 +629,7 @@ class _AddpaymentreceiptlistState extends State<Addpaymentreceiptlist> {
? null
: () {
provider.submitClicked = true;
provider.notifyListeners();
provider.addReceiptPaymentRequestionSubmitAPI(
context,
provider.formattedDateToSend,
......
......@@ -646,7 +646,7 @@ class _DirectpaymentrequesitionlistState
child:
provider.submitClicked
? CircularProgressIndicator.adaptive(
valueColor: AlwaysStoppedAnimation(AppColors.app_blue),
valueColor: AlwaysStoppedAnimation(AppColors.white),
)
: Text(
"Submit",
......
......@@ -432,7 +432,7 @@ class _FinancedashboardState extends State<Financedashboard> {
) => Allpaymentrequesitionlistsbymodes(
mode: "process",
pageTitleName:
"Payment Requisition List (Self)",
"Payment Requisition List (Process)",
),
),
);
......
......@@ -7,6 +7,7 @@ import 'AttendanceRequestDetail.dart';
import 'LeaveApplicationScreen.dart';
import 'TourExpensesListScreen.dart';
import 'attendancelist.dart';
import 'oggchart.dart';
class HrmdashboardScreen extends StatefulWidget {
const HrmdashboardScreen({super.key});
......@@ -127,7 +128,7 @@ class _HrmdashboardScreenState extends State<HrmdashboardScreen> {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => OrganizationStructureScreen(),
builder: (context) => OrgChartt(),
),
);
},
......
import 'dart:io';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:generp/Utils/app_colors.dart';
import 'package:generp/screens/commom/accountsListDetails.dart';
import 'package:graphview/GraphView.dart';
import 'package:provider/provider.dart';
import '../../Models/hrmmodels/ogresponse.dart';
import '../../Notifiers/hrmprovider/orgprovider.dart';
import '../../Utils/commonServices.dart';
import '../../Utils/commonWidgets.dart';
class OrgChartt extends StatefulWidget {
const OrgChartt({super.key});
@override
State<OrgChartt> createState() => _OrgCharttState();
}
class _OrgCharttState extends State<OrgChartt> {
Map _source = {ConnectivityResult.none: false};
final MyConnectivity _connectivity = MyConnectivity.instance;
final Graph graph = Graph();
final Map<String, Node> nodeMap = {};
String connection = 'Offline';
bool _isGraphReady = false;
final Map<String, GlobalKey> nodeKeys = {};
final TransformationController _transformationController =
TransformationController();
final builder =
BuchheimWalkerConfiguration()
..levelSeparation = 50
..siblingSeparation = 20
..subtreeSeparation = 30
..orientation = BuchheimWalkerConfiguration.ORIENTATION_TOP_BOTTOM;
@override
void initState() {
super.initState();
_connectivity.initialise();
_connectivity.myStream.listen((source) {
setState(() => _source = source);
});
_transformationController.value = Matrix4.identity()..scale(0.5);
WidgetsBinding.instance.addPostFrameCallback((_) {
Provider.of<Orgprovider>(context, listen: false).ogChart(context).then((
_,
) {
setState(() {
_isGraphReady = true;
});
});
_centerOnRoot("130");
});
}
void _centerOnRoot(String rootId) {
if (!nodeKeys.containsKey(rootId)) return;
final key = nodeKeys[rootId]!;
final context = key.currentContext;
if (context == null) return;
final renderBox = context.findRenderObject() as RenderBox;
final rootPosition = renderBox.localToGlobal(Offset.zero);
final screenSize = MediaQuery.of(context).size;
final rootSize = renderBox.size;
final screenCenter = Offset(screenSize.width / 2, screenSize.height / 2);
final rootCenter =
rootPosition + Offset(rootSize.width / 2, rootSize.height / 2);
final dx = screenCenter.dx - rootCenter.dx;
final dy = screenCenter.dy - rootCenter.dy;
_transformationController.value = Matrix4.identity()..translate(dx, dy);
}
@override
Widget build(BuildContext context) {
switch (_source.keys.toList()[0]) {
case ConnectivityResult.mobile:
case ConnectivityResult.wifi:
connection = 'Online';
break;
case ConnectivityResult.none:
default:
connection = 'Offline';
}
return Platform.isAndroid
? WillPopScope(
onWillPop: () => onBackPressed(context),
child: SafeArea(top: false, bottom: true, child: _scaffold(context)),
)
: _scaffold(context);
}
Widget _scaffold(BuildContext context) {
return Consumer<Orgprovider>(
builder: (context, provider, child) {
graph.nodes.clear();
graph.edges.clear();
nodeMap.clear();
if (provider.rootID != null && provider.employees.isNotEmpty) {
_buildGraph(provider);
if (kDebugMode) {
print(
'Graph built with ${graph.nodes.length} nodes and ${graph.edges.length} edges',
);
}
}
return Scaffold(
backgroundColor: Color(0xFFF6F6F8),
appBar: appbar2New(
context,
"Organisation Chart",
null,
SizedBox.shrink(),
0xFFFFFFF,
),
body:
provider.rootID == null && provider.employees.isEmpty
? Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation(AppColors.app_blue),
),
)
: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (graph.nodes.isNotEmpty && _isGraphReady)
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * 0.8,
child: InteractiveViewer(
boundaryMargin: const EdgeInsets.all(
double.infinity,
),
panEnabled: true,
scaleEnabled: true,
constrained: false,
minScale: 0.1,
scaleFactor: 1,
transformationController:
_transformationController,
maxScale: 5,
panAxis: PanAxis.free,
// scaleEnabled: true,
// panAxis: PanAxis.free
child: GraphView(
graph: graph,
algorithm: BuchheimWalkerAlgorithm(
builder,
TreeEdgeRenderer(builder),
),
paint:
Paint()
..color = AppColors.grey_thick
..strokeWidth = 1
..style = PaintingStyle.stroke,
builder: (Node node) {
final key = GlobalKey();
nodeKeys[node.key!.value] = key;
final employee = _getEmployeeById(
node.key!.value,
provider,
);
if (employee == null) {
if (kDebugMode) {
print(
'No employee found for node ID: ${node.key!.value}',
);
}
return Container(
width: 50,
height: 82,
color: Colors.transparent,
child: const Center(
child: Text('Invalid Node'),
),
);
}
return InkResponse(
onTap: () {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder:
// (context) =>
// employeeDetails(
// accountID: employee.id,
// ),
// ),
// );
},
child: Container(
key: key,
width: 200,
padding: const EdgeInsets.all(8.0),
// Reduced padding
child: Column(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: 100,
height: 100,
child: ClipRRect(
borderRadius:
BorderRadius.circular(50),
child: CachedNetworkImage(
cacheKey:
employee.profile ?? '',
fit: BoxFit.cover,
imageUrl:
employee.profile ?? '',
useOldImageOnUrlChange: false,
placeholder:
(context, url) =>
CircularProgressIndicator.adaptive(),
errorWidget:
(context, url, error) =>
Icon(Icons.error),
),
),
),
const SizedBox(height: 8),
Row(
children: [
Expanded(
child: Text(
employee.name ?? 'Unknown',
maxLines: 2,
textAlign: TextAlign.center,
overflow:
TextOverflow.ellipsis,
style: TextStyle(
color:
AppColors.semi_black,
fontFamily:
"JakartaMedium",
fontSize: 25,
),
),
),
],
),
SizedBox(height: 10),
Row(
children: [
Expanded(
child: Text(
employee.title ?? '',
maxLines: 2,
textAlign: TextAlign.center,
overflow:
TextOverflow.ellipsis,
style: TextStyle(
color:
AppColors.grey_thick,
fontSize: 18,
), // Reduced font size
),
),
],
),
],
),
),
);
},
),
),
),
),
],
),
),
);
},
);
}
void _buildGraph(Orgprovider provider) {
final rootNode = Node.Id(provider.rootID!);
nodeMap[provider.rootID!] = rootNode;
graph.addNode(rootNode);
_addChildren(provider.employees, rootNode, provider);
}
void _addChildren(
List<Children> children,
Node parentNode,
Orgprovider provider,
) {
for (var child in children) {
if (child.id == null || child.id!.isEmpty) {
if (kDebugMode) {
print('Skipping invalid child with null or empty ID');
}
continue;
}
if (nodeMap.containsKey(child.id)) {
if (kDebugMode) {
print('Skipping duplicate node ID: ${child.id}');
}
continue;
}
final childNode = Node.Id(child.id!);
nodeMap[child.id!] = childNode;
graph.addNode(childNode);
graph.addEdge(
parentNode,
childNode,
paint: Paint()..color = AppColors.grey_thick,
);
if (child.children != null && child.children!.isNotEmpty) {
_addChildren(child.children!, childNode, provider);
}
}
}
Children? _getEmployeeById(String id, Orgprovider provider) {
if (id == provider.rootID) {
return Children(
id: provider.rootID,
name: provider.rootName,
title: provider.rootTitle,
profile: provider.rootProfile,
);
}
return _findEmployeeInList(id, provider.employees);
}
Children? _findEmployeeInList(String id, List<Children> employees) {
for (var employee in employees) {
if (employee.id == id) {
return employee;
}
if (employee.children != null && employee.children!.isNotEmpty) {
final found = _findEmployeeInList(id, employee.children!);
if (found != null) {
return found;
}
}
}
return null;
}
}
......@@ -65,3 +65,5 @@ export 'package:generp/Notifiers/hrmProvider/rewardListProvider.dart';
export 'package:generp/Notifiers/hrmProvider/LeaveApplicationListProvider.dart';
export 'package:generp/Notifiers/hrmProvider/LeaveApplicationDetailsProvider.dart';
export 'package:generp/Notifiers/hrmprovider/orgprovider.dart';
......@@ -102,6 +102,7 @@ import '../Models/financeModels/paymentRequisitionPaymentsReceiptsListResponse.d
import '../Models/generatorComplaintResponse.dart';
import '../Models/hrmModels/attendanceRequestDetailsResponse.dart';
import '../Models/hrmModels/hrmAccessiblePagesResponse.dart';
import '../Models/hrmmodels/ogresponse.dart';
import '../Models/loadGeneratorDetailsResponse.dart';
import '../Models/financeModels/financeDashboardPagesResponse.dart';
import '../Models/ordersModels/AddOrderPaymentSelectAccountResponse.dart';
......@@ -1943,6 +1944,34 @@ class ApiCalling {
return null;
}
}
static Future<CommonResponse?> editProcessedRequestAmountAPI(
empId,
session,
process_payment_id,
approval_amount,
) async {
try {
Map<String, String> data = {
'emp_id': (empId).toString(),
'session_id': (session).toString(),
'process_payment_id': process_payment_id.toString(),
'approval_amount': approval_amount.toString(),
};
print("Process EDIT:${data}");
var res = await post(data, paymentRequesitionEditProcessedPaymentUrl, {});
if (res != null) {
return CommonResponse.fromJson(jsonDecode(res.body));
} else {
debugPrint("Null Response");
return null;
}
} catch (e) {
debugPrint('hello bev=bug $e ');
return null;
}
}
///common Module
static Future<commonAccessiblePagesResponse?> commonDashboardPagesAPI(
......@@ -4912,6 +4941,30 @@ class ApiCalling {
///hrm modules
///
///
static Future<ogresponse?> ogChartAPI(
empId,
session,
) async {
try {
Map<String, String> data = {
'emp_id': (empId).toString(),
'session_id': (session).toString(),
};
final res = await post(data, ogcharturl, {});
if (res != null) {
print(data);
debugPrint(res.body);
return ogresponse.fromJson(jsonDecode(res.body));
} else {
debugPrint("Null Response");
return null;
}
} catch (e) {
debugPrint('hello bev=bug $e ');
return null;
}
}
static Future<hrmAccessiblePagesResponse?> hrmAccessiblePagesAPI(
empId,
session,
......
......@@ -72,6 +72,7 @@ const paymentRequesitionPaymentsListUrl = "${baseUrl_test}payment_requistion_pay
const paymentRequesitionPaymentsDetailsUrl = "${baseUrl_test}payment_requisition_payment_details";
const paymentRequesitionPaymentsReceiptsListUrl = "${baseUrl_test}payment_receipts_list";
const paymentRequesitionPaymentsReceiptsDetailsUrl = "${baseUrl_test}payment_receipt_details";
const paymentRequesitionEditProcessedPaymentUrl = "${baseUrl_test}edit_processes_payment";
///common Module
......@@ -177,6 +178,8 @@ const crmNearbyOpenLeadsUrl = "${baseUrl_test}nearby_crm_open_leads";
const crmDashboardFollowUpUrl = "${baseUrl_test}crm_dashboard_followup_list";
const crmDashboardQuotationsUrl = "${baseUrl_test}crm_dashboard_quotations_list";
const ogcharturl = "${baseUrl_test}organisation_structures";
///HRM
//Attendance
......
......@@ -1016,6 +1016,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.2"
graphview:
dependency: "direct main"
description:
name: graphview
sha256: bdba183583b23c30c71edea09ad5f0beef612572d3e39e855467a925bd08392f
url: "https://pub.dev"
source: hosted
version: "1.2.0"
html:
dependency: transitive
description:
......
......@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.99+107
version: 1.0.101+109
environment:
sdk: ^3.7.2
......@@ -89,6 +89,7 @@ dependencies:
pinput: ^5.0.1
build_runner: ^2.4.0
build_web_compilers: ^4.0.4
graphview: ^1.2.0
file_picker: ^8.0.0
dev_dependencies:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment