flutter app untuk unitstock
Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 

1236 linhas
61 KiB

  1. import 'dart:async';
  2. import 'dart:io';
  3. import 'package:flutter/foundation.dart';
  4. import 'package:flutter/rendering.dart';
  5. import 'package:flutter/widgets.dart';
  6. import 'package:in_app_update/in_app_update.dart';
  7. import 'package:package_info/package_info.dart';
  8. import 'package:path/path.dart';
  9. import 'package:flutter/cupertino.dart';
  10. import 'package:flutter/material.dart';
  11. import 'package:path_provider/path_provider.dart';
  12. import 'Util/DBHelper.dart';
  13. import 'Util/Util.dart';
  14. import 'Util/download_Upload_Handler.dart';
  15. import 'package:intl/intl.dart';
  16. import 'main.dart';
  17. import 'Util/Prefs.dart';
  18. import 'Util/UnitModel.dart';
  19. import 'package:permission_handler/permission_handler.dart' as pHandler;
  20. class HomePage extends StatefulWidget {
  21. // HomePage({Key key}) : super(key: key);
  22. final String title;
  23. HomePage({this.title});
  24. @override
  25. _HomePageState createState() => _HomePageState();
  26. }
  27. class _HomePageState extends State<HomePage> {
  28. Util util = new Util();
  29. StreamSubscription progressDLStream,progressULStream;
  30. String lastDownload = '';
  31. String lastUpload = '';
  32. double progressDL,progressUL;
  33. String timeString = '';
  34. bool isLoading = false;
  35. String state = '';
  36. final hostAddress = new TextEditingController();
  37. clearData(context)async{
  38. setState(() {
  39. progressDL = null;
  40. isLoading = false;
  41. });
  42. String errMsg;
  43. bool result = await showDialog(context: context,builder: (context)=>WillPopScope(
  44. onWillPop: ()async{
  45. Navigator.pop(context,false);
  46. return false;
  47. },
  48. child: AlertDialog(
  49. title: Text('Clear Data ?'),
  50. content: Text('Proceed to clear any remaining units data on this device?'),
  51. actions: <Widget>[
  52. TextButton(
  53. child: Text('Proceed'),
  54. onPressed: ()async{
  55. util.showLoading(context);
  56. await Future.sync(()async{
  57. try{
  58. Directory documentsDirectory = await getExternalStorageDirectory();
  59. String path = join(documentsDirectory.path, "UnitStocking.db");
  60. File db = File(path);
  61. if(db.existsSync()){
  62. await DBHelper.database.closeDb();
  63. db.deleteSync();
  64. await prefs.remove(keyClass.lastDownload);
  65. await prefs.remove(keyClass.lastUpload);
  66. await prefs.remove(keyClass.targetProccess);
  67. await prefs.remove(keyClass.submitProccess);
  68. await prefs.remove(keyClass.stock_id);
  69. setState(() {
  70. lastUpload = '';
  71. lastDownload = '';
  72. timeString = '';
  73. });
  74. }
  75. }
  76. catch(e){
  77. print(e);
  78. util.showFlushbar(context, 'Failed to delete database file',color: Colors.red);
  79. }
  80. });
  81. Navigator.pop(context);
  82. Navigator.pop(context,true);
  83. util.showFlushbar(context,errMsg??'Data Cleared');
  84. },
  85. ),
  86. TextButton(
  87. child: Text('Cancel'),
  88. onPressed: (){Navigator.pop(context,false);},
  89. )
  90. ],
  91. ),
  92. ));
  93. return result;
  94. }
  95. loadState()async{
  96. String company = prefs.getString(keyClass.company);
  97. if(prefs.getString(keyClass.stock_id) == null)
  98. {
  99. valueTab value = await DBHelper.database.getValue(keyClass.stock_id);
  100. if(value != null)await prefs.setString(keyClass.stock_id, value.value);
  101. }
  102. String stock_taking_id = prefs.getString(keyClass.stock_id);
  103. if(company!=null&&stock_taking_id!=null){
  104. var result = await util.JsonDataPostRaw({"company":company,"stockTakingId":stock_taking_id}, '${prefs.getString(keyClass.hostAddress)}/stock_taking/state/');
  105. if(result['STATUS']==1){
  106. setState(() {
  107. state = result['DATA'];
  108. });
  109. }
  110. }
  111. }
  112. @override
  113. void initState() {
  114. // TODO: implement initState
  115. super.initState();
  116. loadState();
  117. lastDownload = prefs.getString(keyClass.lastDownload)??'';
  118. lastUpload = prefs.getString(keyClass.lastUpload)??'';
  119. WidgetsBinding.instance.addPostFrameCallback((_) async {
  120. await _check_Update();
  121. await util.permissionCheck(context,pHandler.Permission.storage,()async{print("storage permit granted!");},customMessage: " untuk menyimpan data backup");
  122. });
  123. }
  124. _check_Update()async{
  125. if(defaultTargetPlatform == TargetPlatform.android){
  126. try{
  127. final PackageInfo info = await PackageInfo.fromPlatform();
  128. AppUpdateInfo _updateInfo = await InAppUpdate.checkForUpdate();
  129. String currentVersion = info.version.trim();
  130. String latestversion = '0.0.0';
  131. var result = await util.getMinAppVer();
  132. if(result['STATUS']==1){
  133. latestversion = result['DATA'];
  134. }
  135. var current = currentVersion.split('.');
  136. var latest = latestversion.split('.');
  137. if(int.parse(current[0])==int.parse(latest[0])){
  138. if(int.parse(current[1])==int.parse(latest[1])){
  139. if(int.parse(current[2])<int.parse(latest[2])) {
  140. await util.updateDialog(context);
  141. }
  142. else{
  143. if(_updateInfo?.updateAvailability == 2) {
  144. await InAppUpdate.startFlexibleUpdate();
  145. await InAppUpdate.completeFlexibleUpdate();
  146. }
  147. }
  148. }
  149. else if(int.parse(current[1])<int.parse(latest[1])) {
  150. await util.updateDialog(context);
  151. // await InAppUpdate.performImmediateUpdate();
  152. }
  153. else{
  154. if(_updateInfo?.updateAvailability == 2) {
  155. await InAppUpdate.startFlexibleUpdate();
  156. await InAppUpdate.completeFlexibleUpdate();
  157. }
  158. }
  159. }
  160. else if(int.parse(current[0])<int.parse(latest[0])) {
  161. await util.updateDialog(context);
  162. // await InAppUpdate.performImmediateUpdate();
  163. }
  164. else{
  165. if(_updateInfo?.updateAvailability == 2 ) {
  166. await InAppUpdate.startFlexibleUpdate();
  167. await InAppUpdate.completeFlexibleUpdate();
  168. }
  169. }
  170. }
  171. catch(e){
  172. print("error Update $e");
  173. }
  174. }
  175. }
  176. changeCabang(context)async{
  177. util.showLoading(context);
  178. var result = await util.JsonDataPostRaw({"company":prefs.getString(keyClass.company),"User":prefs.getString(keyClass.loginId)}, '${prefs.getString(keyClass.hostAddress)}/user/cabangs/');
  179. Navigator.pop(context);
  180. if(result['STATUS']==1){
  181. var selected = prefs.getString(keyClass.cabang_id)??result['DATA'][0]["RETURN_VALUE"];
  182. return await showDialog(context: context,builder: (context)=>StatefulBuilder(
  183. builder:(context,setState)=>
  184. Material(
  185. color: Colors.white.withOpacity(0.9),
  186. child: Center(
  187. child: Container(
  188. decoration: BoxDecoration(
  189. color: Colors.white,
  190. boxShadow: [
  191. BoxShadow(
  192. color: Colors.grey.withOpacity(0.5),
  193. spreadRadius: 2,
  194. blurRadius: 2,
  195. offset: Offset(0, 0), // changes position of shadow
  196. ),
  197. ],
  198. borderRadius: BorderRadius.circular(5)
  199. ),
  200. // height: MediaQuery.of(context).size.height/3.2,
  201. height:220,
  202. width: MediaQuery.of(context).size.width*0.75,
  203. child: Column(
  204. children: <Widget>[
  205. Flexible(
  206. flex:3,
  207. child: Container(
  208. padding: EdgeInsets.only(top:10,left: 10,right: 10),
  209. alignment: Alignment.center,
  210. decoration: BoxDecoration(
  211. // color: Colors.indigo,
  212. borderRadius: BorderRadius.only(topLeft: Radius.circular(5),topRight: Radius.circular(5))
  213. ),
  214. child: Column(
  215. mainAxisSize: MainAxisSize.min,
  216. crossAxisAlignment: CrossAxisAlignment.center,
  217. children: <Widget>[
  218. Icon(Icons.business,size: 70,color: Colors.indigo,),
  219. SizedBox(height: 5,),
  220. Text('Set Cabang',style: TextStyle(fontWeight: FontWeight.bold,fontSize: 16,color: Colors.indigo),)
  221. ],
  222. ),
  223. ),
  224. ),
  225. Flexible(
  226. flex: 1,
  227. child: Container(
  228. padding: EdgeInsets.only(left: 20,right: 20),
  229. alignment: Alignment.centerLeft,
  230. child: Theme(
  231. data: ThemeData(
  232. canvasColor: Colors.white,
  233. primaryColor: Colors.indigo,
  234. accentColor: Colors.indigo,
  235. hintColor: Colors.indigo
  236. ),
  237. child: DropdownButtonFormField(
  238. style: TextStyle(color: Colors.black.withOpacity(0.6),fontWeight: FontWeight.w500,fontSize: 14,),
  239. decoration: InputDecoration(
  240. contentPadding: EdgeInsets.all(8.0),
  241. ),
  242. value: selected,
  243. onChanged: (value){
  244. setState(() {
  245. selected = value;
  246. });
  247. },
  248. items: result['DATA'].map<DropdownMenuItem<dynamic>>((item){
  249. return DropdownMenuItem(
  250. value: item['RETURN_VALUE'],
  251. child: Text(item["DISPLAY_VALUE"]),
  252. );
  253. }).toList(),
  254. ),
  255. ),
  256. ),
  257. ),
  258. Flexible(
  259. flex: 1,
  260. child: Container(
  261. child: Row(
  262. mainAxisAlignment: MainAxisAlignment.end,
  263. children: <Widget>[
  264. TextButton(
  265. child: Text('OK',style: TextStyle(color: Colors.indigo),),
  266. onPressed: ()async{
  267. if(selected!=prefs.getString(keyClass.cabang_id)){
  268. prefs.setString(keyClass.cabang_id,selected);
  269. await Future.sync(()async{
  270. await prefs.remove(keyClass.lastDownload);
  271. await prefs.remove(keyClass.lastUpload);
  272. await prefs.remove(keyClass.targetProccess);
  273. await prefs.remove(keyClass.submitProccess);
  274. await prefs.remove(keyClass.stock_id);
  275. lastUpload = '';
  276. lastDownload = '';
  277. timeString = '';
  278. try{
  279. Directory documentsDirectory = await getExternalStorageDirectory();
  280. String path = join(documentsDirectory.path, "UnitStocking.db");
  281. File db = File(path);
  282. if(db.existsSync()){
  283. db.deleteSync();
  284. }
  285. }
  286. catch(e){
  287. print(e);
  288. util.showFlushbar(context, 'Failed to delete database file',color: Colors.red);
  289. }
  290. });
  291. Navigator.pop(context,true);
  292. }
  293. else{
  294. Navigator.pop(context,false);
  295. }
  296. },
  297. ),
  298. ],
  299. ),
  300. ),
  301. )
  302. ],
  303. ),
  304. ),
  305. ),
  306. ),
  307. // AlertDialog(
  308. // title: Text('Set Cabang'),
  309. // content: DropdownButtonFormField(
  310. // value: selected,
  311. // onChanged: (value){
  312. // setState(() {
  313. // selected = value;
  314. // });
  315. // },
  316. // items: result['DATA'].map<DropdownMenuItem<dynamic>>((item){
  317. // return DropdownMenuItem(
  318. // value: item['RETURN_VALUE'],
  319. // child: Text(item["DISPLAY_VALUE"]),
  320. // );
  321. // }).toList(),
  322. // ),
  323. // actions: <Widget>[
  324. // TextButton(
  325. // child: Text('OK'),
  326. // onPressed: ()async{
  327. // if(selected!=prefs.getString(keyClass.cabang_id)){
  328. // prefs.setString(keyClass.cabang_id,selected);
  329. // await Future.sync(()async{
  330. // await prefs.remove(keyClass.lastDownload);
  331. // await prefs.remove(keyClass.lastUpload);
  332. // await prefs.remove(keyClass.targetProccess);
  333. // await prefs.remove(keyClass.submitProccess);
  334. // lastUpload = '';
  335. // lastDownload = '';
  336. // timeString = '';
  337. //// var result = await DBHelper.database.deleteAll();
  338. //// if(result!=null) {
  339. //// await DBHelper.database.closeDb();
  340. //// if(result!=null){
  341. // try{
  342. // Directory documentsDirectory = await getExternalStorageDirectory();
  343. // String path = join(documentsDirectory.path, "UnitStocking.db");
  344. // File db = File(path);
  345. // if(db.existsSync()){
  346. // db.deleteSync();
  347. // }
  348. // }
  349. // catch(e){
  350. // print(e);
  351. // util.showFlushbar(context, 'Failed to delete database file',color: Colors.red);
  352. // }
  353. //// }
  354. //// else{
  355. //// errMsg = 'Failed to clear unit data';
  356. //// }
  357. //// }
  358. //// else{
  359. //// errMsg = 'Failed to clear unit data';
  360. //// }
  361. // });
  362. // Navigator.pop(context,true);
  363. // }
  364. // else{
  365. // Navigator.pop(context,false);
  366. // }
  367. //// util.showLoading(context);
  368. //
  369. //// Navigator.pop(context);
  370. // },
  371. // )
  372. // ],
  373. // ),
  374. ));
  375. }
  376. else{
  377. util.showFlushbar(context, result['DATA'],color: Colors.red);
  378. return false;
  379. }
  380. }
  381. @override
  382. Widget build(BuildContext context) {
  383. return WillPopScope(
  384. onWillPop: ()async{
  385. await showDialog(context: context,builder: (context)=>
  386. Material(
  387. color: Colors.white.withOpacity(0.9),
  388. child: Center(
  389. child: Container(
  390. decoration: BoxDecoration(
  391. color: Colors.white,
  392. boxShadow: [
  393. BoxShadow(
  394. color: Colors.grey.withOpacity(0.5),
  395. spreadRadius: 2,
  396. blurRadius: 2,
  397. offset: Offset(0, 0), // changes position of shadow
  398. ),
  399. ],
  400. borderRadius: BorderRadius.circular(5)
  401. ),
  402. // height: MediaQuery.of(context).size.height/4.8,
  403. height:220,
  404. width: MediaQuery.of(context).size.width*0.75,
  405. child: Column(
  406. children: <Widget>[
  407. Flexible(
  408. flex:3,
  409. child: Container(
  410. padding: EdgeInsets.only(top:10,left: 10,right: 10),
  411. alignment: Alignment.center,
  412. decoration: BoxDecoration(
  413. // color: Colors.indigo,
  414. borderRadius: BorderRadius.only(topLeft: Radius.circular(5),topRight: Radius.circular(5))
  415. ),
  416. child: Column(
  417. mainAxisSize: MainAxisSize.min,
  418. crossAxisAlignment: CrossAxisAlignment.center,
  419. children: <Widget>[
  420. Icon(Icons.exit_to_app,size: 70,color: Colors.indigo,),
  421. ],
  422. ),
  423. ),
  424. ),
  425. Flexible(
  426. flex: 1,
  427. child: Container(
  428. padding: EdgeInsets.only(left: 20,right: 20),
  429. alignment: Alignment.centerLeft,
  430. child: Text('Keluar dari aplikasi?',style: TextStyle(fontWeight: FontWeight.w500,fontSize: 14,color: Colors.black.withOpacity(0.6)),)
  431. ),
  432. ),
  433. Flexible(
  434. flex: 1,
  435. child: Container(
  436. padding: EdgeInsets.only(bottom:10),
  437. child: Row(
  438. mainAxisAlignment: MainAxisAlignment.end,
  439. children: <Widget>[
  440. TextButton(
  441. child: Text('Exit',style: TextStyle(color: Colors.indigo),),
  442. onPressed: ()async{
  443. Navigator.pop(context);
  444. await locationStream?.cancel();
  445. exit(0);
  446. },
  447. ),
  448. TextButton(
  449. child: Text('Cancel',style: TextStyle(color: Colors.indigo),),
  450. onPressed: (){
  451. Navigator.pop(context);
  452. },
  453. )
  454. ],
  455. ),
  456. ),
  457. )
  458. ],
  459. ),
  460. ),
  461. ),
  462. ),
  463. );
  464. return false;
  465. },
  466. child: Scaffold(
  467. body: Column(
  468. crossAxisAlignment: CrossAxisAlignment.end,
  469. children: <Widget>[
  470. Container(
  471. padding: EdgeInsets.only(bottom: 0,left: 15,right: 10,top: 10),
  472. height: MediaQuery.of(context).size.height/13,
  473. width: MediaQuery.of(context).size.width,
  474. alignment: Alignment.bottomLeft,
  475. child: Row(
  476. crossAxisAlignment: CrossAxisAlignment.end,
  477. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  478. children: <Widget>[
  479. Text('Home',style: TextStyle(color: Colors.indigo.withOpacity(0.8),fontSize: 18,fontWeight: FontWeight.bold),),
  480. PopupMenuButton(
  481. child: Padding(
  482. padding: const EdgeInsets.only(right:2.0),
  483. child: Icon(Icons.menu,color: Colors.indigo.withOpacity(0.8),),
  484. ),
  485. itemBuilder: (context){
  486. return [
  487. PopupMenuItem(
  488. value:'hostChange',
  489. child: Row(
  490. children: <Widget>[
  491. Icon(Icons.network_wifi,color: Colors.black,),
  492. SizedBox(width: 10,),
  493. Text('Change Ip Address')
  494. ],
  495. ),
  496. ),
  497. PopupMenuItem(
  498. value:'cabangChange',
  499. child: Row(
  500. children: <Widget>[
  501. Icon(Icons.business,color: Colors.black,),
  502. SizedBox(width: 10,),
  503. Text('Change Cabang')
  504. ],
  505. ),
  506. ),
  507. PopupMenuItem(
  508. value:'backup',
  509. child: Row(
  510. children: <Widget>[
  511. Icon(Icons.save,color: Colors.black,),
  512. SizedBox(width: 10,),
  513. Text('Backup Data')
  514. ],
  515. ),
  516. ),
  517. PopupMenuItem(
  518. value:'restore',
  519. child: Row(
  520. children: <Widget>[
  521. Icon(Icons.sync,color: Colors.black,),
  522. SizedBox(width: 10,),
  523. Text('Restore Data')
  524. ],
  525. ),
  526. ),
  527. PopupMenuItem(
  528. value:'logout',
  529. child: Row(
  530. children: <Widget>[
  531. Icon(Icons.exit_to_app,color: Colors.black,),
  532. SizedBox(width: 10,),
  533. Text('Logout')
  534. ],
  535. ),
  536. ),
  537. ];
  538. },
  539. onSelected: (value)async{
  540. if(value == 'hostChange'){
  541. hostAddress.text = prefs.getString(keyClass.hostAddress);
  542. await showDialog(context: context,builder: (context)=>
  543. Material(
  544. color: Colors.white.withOpacity(0.9),
  545. child: Center(
  546. child: Container(
  547. decoration: BoxDecoration(
  548. color: Colors.white,
  549. boxShadow: [
  550. BoxShadow(
  551. color: Colors.grey.withOpacity(0.5),
  552. spreadRadius: 2,
  553. blurRadius: 2,
  554. offset: Offset(0, 0), // changes position of shadow
  555. ),
  556. ],
  557. borderRadius: BorderRadius.circular(5)
  558. ),
  559. height:220,
  560. // height: MediaQuery.of(context).size.height/3.2,
  561. width: MediaQuery.of(context).size.width*0.75,
  562. child: Column(
  563. children: <Widget>[
  564. Flexible(
  565. flex:3,
  566. child: Container(
  567. padding: EdgeInsets.only(top:10,left: 10,right: 10),
  568. alignment: Alignment.center,
  569. decoration: BoxDecoration(
  570. // color: Colors.indigo,
  571. borderRadius: BorderRadius.only(topLeft: Radius.circular(5),topRight: Radius.circular(5))
  572. ),
  573. child: Column(
  574. mainAxisSize: MainAxisSize.min,
  575. crossAxisAlignment: CrossAxisAlignment.center,
  576. children: <Widget>[
  577. Icon(Icons.network_wifi,size: 70,color: Colors.indigo,),
  578. SizedBox(height: 5,),
  579. Text('Set Ip Address',style: TextStyle(fontWeight: FontWeight.bold,fontSize: 16,color: Colors.indigo),)
  580. ],
  581. ),
  582. ),
  583. ),
  584. Flexible(
  585. flex: 1,
  586. child: Container(
  587. padding: EdgeInsets.only(left: 20,right: 20),
  588. alignment: Alignment.centerLeft,
  589. child: Theme(
  590. data: ThemeData(
  591. canvasColor: Colors.white,
  592. primaryColor: Colors.indigo,
  593. accentColor: Colors.indigo,
  594. hintColor: Colors.indigo
  595. ),
  596. child: TextField(
  597. controller: hostAddress,
  598. decoration: InputDecoration(
  599. contentPadding: EdgeInsets.all(8),
  600. ),
  601. onSubmitted: (value){
  602. prefs.setString(keyClass.hostAddress,(value=='')?'https://tbg.thamringroup.web.id/ords/tbs/unit/v1':value);
  603. Navigator.pop(context);
  604. },
  605. ),
  606. ),
  607. ),
  608. ),
  609. Flexible(
  610. flex: 1,
  611. child: Container(
  612. child: Row(
  613. mainAxisAlignment: MainAxisAlignment.end,
  614. children: <Widget>[
  615. TextButton(
  616. child: Text('OK',style: TextStyle(color: Colors.indigo),),
  617. onPressed: (){
  618. prefs.setString(keyClass.hostAddress,(hostAddress.text=='')?'https://tbg.thamringroup.web.id/ords/tbs/unit/v1':hostAddress.text);
  619. Navigator.pop(context);
  620. },
  621. )
  622. ],
  623. ),
  624. ),
  625. )
  626. ],
  627. ),
  628. ),
  629. ),
  630. )
  631. // AlertDialog(
  632. // title: Text('Set IP Address'),
  633. // content: TextField(
  634. // controller: hostAddress,
  635. // onSubmitted: (value){
  636. // prefs.setString(keyClass.hostAddress,(value=='')?'https://unitstocksbackend.thamringroup.web.id':value);
  637. // Navigator.pop(context);
  638. // },
  639. // ),
  640. // actions: <Widget>[
  641. // TextButton(
  642. // child: Text('OK'),
  643. // onPressed: (){
  644. // prefs.setString(keyClass.hostAddress,(hostAddress.text=='')?'https://unitstocksbackend.thamringroup.web.id':hostAddress.text);
  645. // Navigator.pop(context);
  646. // },
  647. // )
  648. // ],
  649. // )
  650. );
  651. }
  652. if(value=="cabangChange") {
  653. var res = await changeCabang(context);
  654. if(res??false){
  655. setState(() {
  656. });
  657. }
  658. }
  659. if(value == 'logout'){
  660. prefs.remove(keyClass.cabang_id);
  661. prefs.remove(keyClass.company);
  662. prefs.remove(keyClass.loginId);
  663. prefs.setBool(keyClass.logged_in, false);
  664. Navigator.pushNamed(context, '/login');
  665. }
  666. if(value == 'backup'){
  667. var result = await DBHelper.database.backupDb(context);
  668. util.showFlushbar(context, result['MSG'],color: result["STATUS"]==1?Colors.grey:Colors.red);
  669. }
  670. if(value == 'restore'){
  671. if(prefs.getString(keyClass.stock_id) == null){
  672. util.showFlushbar(context, "Data Unit cabang tidak ditemukan. Silakan get data terlbih dahulu.");
  673. }
  674. else{
  675. if(prefs.getString(keyClass.stock_id) == prefs.getString(keyClass.backup_stock_id)){
  676. String company = prefs.getString(keyClass.company);
  677. String stock_taking_id = prefs.getString(keyClass.stock_id);
  678. String stockState = '';
  679. if(company!=null&&stock_taking_id!=null){
  680. var result = await util.JsonDataPostRaw({"company":company,"stockTakingId":stock_taking_id}, '${prefs.getString(keyClass.hostAddress)}/stock_taking/state/');
  681. if(result['STATUS']==1){
  682. stockState = result['DATA'];
  683. }
  684. }
  685. if(['Open','Submitted'].contains(stockState)){
  686. bool isRestore = await showDialog(context: context,builder: (context)=>AlertDialog(
  687. title: Text('Restore Data ?'),
  688. content: Text('Restore data akan menghapus dan mengganti data unit dan cabang yang ada dengan data backup.'),
  689. actions: <Widget>[
  690. TextButton(
  691. child: Text('Proceed'),
  692. onPressed: ()async{
  693. Navigator.pop(context,true);
  694. },
  695. ),
  696. TextButton(
  697. child: Text('Cancel'),
  698. onPressed: ()=>Navigator.pop(context,false),
  699. )
  700. ],
  701. ));
  702. if(isRestore??false){
  703. var response;
  704. bool isclear;
  705. Directory documentsDirectory = await getExternalStorageDirectory();
  706. String path = join(documentsDirectory.path, "UnitStocking.db");
  707. File db = File(path);
  708. if(db.existsSync()){
  709. isclear = await clearData(context);
  710. }
  711. else{
  712. isclear = true;
  713. }
  714. if(isclear??false){
  715. var result = await DBHelper.database.restoreDb(context);
  716. if(result["STATUS"]==1){
  717. await prefs.remove(keyClass.lastDownload);
  718. await prefs.remove(keyClass.lastUpload);
  719. await prefs.remove(keyClass.targetProccess);
  720. await prefs.remove(keyClass.submitProccess);
  721. setState(() {
  722. lastUpload = '';
  723. lastDownload = '';
  724. timeString = '';
  725. });
  726. valueTab value = await DBHelper.database.getValue(keyClass.tgl_start);
  727. if(value != null)await prefs.setString(keyClass.lastDownload, DateFormat('dd-MM-yyyy HH:mm:ss').parse(value.value).toIso8601String());
  728. else {
  729. await prefs.setString(keyClass.lastDownload, DateTime.now().toIso8601String());
  730. }
  731. value = await DBHelper.database.getValue(keyClass.stock_id);
  732. if(value != null) await prefs.setString(keyClass.stock_id,value.value);
  733. else {
  734. await prefs.setString(keyClass.stock_id,prefs.getString(keyClass.backup_stock_id));
  735. }
  736. loadState();
  737. setState(() {
  738. lastDownload = prefs.getString(keyClass.lastDownload);
  739. });
  740. }
  741. response = result["MSG"];
  742. }
  743. if(response != null)util.showFlushbar(context, response);
  744. }
  745. }
  746. else{
  747. util.showFlushbar(context, "Stocking Unit sudah selesai dan tidak perlu di restore");
  748. }
  749. }
  750. else {
  751. util.showFlushbar(context, "File Backup tidak ditemukan atau sudah selesai");
  752. }
  753. }
  754. }
  755. },
  756. ),
  757. ],
  758. ),
  759. ),
  760. (prefs.getString(keyClass.stock_id)==null)?Container():Padding(
  761. padding: const EdgeInsets.only(top: 8,right: 8),
  762. child: Container(
  763. decoration: BoxDecoration(
  764. color: Colors.indigo.withOpacity(0.9),
  765. borderRadius: BorderRadius.circular(8)
  766. // border: Border.all(),
  767. ),
  768. padding: EdgeInsets.all(8),
  769. child: Row(
  770. mainAxisSize: MainAxisSize.min,
  771. mainAxisAlignment: MainAxisAlignment.end,
  772. crossAxisAlignment: CrossAxisAlignment.center,
  773. children: <Widget>[
  774. Text('Status : ',style: TextStyle(color: Colors.white),),
  775. Text(state??'-',style: TextStyle(fontWeight: FontWeight.bold,color: Colors.white),),
  776. ],
  777. ),
  778. ),
  779. ),
  780. Expanded(
  781. child: Container(
  782. child:
  783. GridView.count(
  784. padding: EdgeInsets.all(10),
  785. crossAxisSpacing: 10,
  786. mainAxisSpacing: 10,
  787. crossAxisCount: 2,
  788. children: <Widget>[
  789. AbsorbPointer(
  790. absorbing: isLoading,
  791. child: InkWell(
  792. splashColor: Colors.black,
  793. onTap: ()async{
  794. bool getData = await showDialog(
  795. context: context,
  796. builder: (context)=>AlertDialog(
  797. title: Text("Get Data Units?"),
  798. content: Text('Fetch data unit for stocking'),
  799. actions: <Widget>[
  800. TextButton(
  801. child: Text('Proceed'),
  802. onPressed: (){
  803. Navigator.pop(context,true);
  804. },
  805. ),
  806. TextButton(
  807. child: Text('Cancel'),
  808. onPressed: (){
  809. Navigator.pop(context,false);
  810. },
  811. )
  812. ],
  813. )
  814. );
  815. if(getData??false){
  816. setState(() {
  817. isLoading = true;
  818. });
  819. var a = Stopwatch();
  820. a.start();
  821. await Future.delayed(Duration(milliseconds: 200));
  822. bool isclear;
  823. Directory documentsDirectory = await getExternalStorageDirectory();
  824. String path = join(documentsDirectory.path, "UnitStocking.db");
  825. File db = File(path);
  826. if(db.existsSync()){
  827. isclear = await clearData(context);
  828. }
  829. else{
  830. isclear = true;
  831. }
  832. if(isclear??false){
  833. print('fetching');
  834. util.showLoading(context);
  835. file_Trans_Handler trans = new file_Trans_Handler();
  836. // trans.downloadFile('UnitStocking.db',"http://172.16.1.8:14002/getSqliteDbtest/TBS/02");
  837. trans.downloadFile('UnitStocking.db',"${prefs.getString(keyClass.hostAddress)}/stock_taking/get_units/${prefs.getString(keyClass.company)}/${prefs.getString(keyClass.cabang_id)}");
  838. progressDLStream = trans.progress.listen((value)async {
  839. if(progressDL==null) {
  840. // print(['test',value]);
  841. if(value!=null) Navigator.pop(context);
  842. }
  843. setState(() {
  844. progressDL = (value!=-1.0)?value:null;
  845. });
  846. if(value!=null&&value >= 1.0) {
  847. progressDLStream.cancel();
  848. progressDL = null;
  849. setState(() {
  850. lastDownload = DateTime.now().toIso8601String();
  851. });
  852. await prefs.setString(keyClass.lastDownload, lastDownload);
  853. await DBHelper.database.closeDb();
  854. await DBHelper.database.insertUpdateValue(new valueTab(name: keyClass.tgl_start,value: DateFormat('dd-MM-yyyy HH:mm:ss').format(DateTime.parse(lastDownload))));
  855. await DBHelper.database.insertUpdateValue(new valueTab(name: 'TGL_STOCK_TAKING',value: DateFormat('dd-MM-yyyy').format(DateTime.parse(lastDownload))));
  856. util.showFlushbar(context,'Data downloaded');
  857. loadState();
  858. a.stop();
  859. if(a.elapsed.inSeconds<3){
  860. await Future.delayed(Duration(seconds: 3-a.elapsed.inSeconds));
  861. }
  862. setState(() {
  863. isLoading = false;
  864. });
  865. }
  866. if(value==-1.0){
  867. setState(() {
  868. isLoading = false;
  869. });
  870. util.showFlushbar(context,trans.error??'Data download error',color: Colors.red);
  871. }
  872. });
  873. // Navigator.popUntil(context, ModalRoute.withName('/home'));
  874. }
  875. }
  876. },
  877. child: Container(
  878. padding: EdgeInsets.all(5),
  879. decoration: BoxDecoration(
  880. boxShadow: [
  881. BoxShadow(
  882. color: Colors.grey.withOpacity(0.5),
  883. spreadRadius: 2,
  884. blurRadius: 2,
  885. offset: Offset(0, 0), // changes position of shadow
  886. ),
  887. ],
  888. borderRadius: BorderRadius.all(Radius.circular(5.0)),
  889. color: Colors.green.withAlpha(220).withOpacity(0.7),
  890. ),
  891. child: Stack(
  892. children: <Widget>[
  893. Container(
  894. alignment: (progressDL!=null)?Alignment.bottomCenter:Alignment.bottomLeft,
  895. padding: EdgeInsets.only(left: 10,right: 10,top: 10,bottom: 15),
  896. child: (progressDL!=null)?Column(
  897. mainAxisSize: MainAxisSize.min,
  898. children: <Widget>[
  899. LinearProgressIndicator(
  900. value: progressDL,
  901. ),
  902. Text('${(progressDL*100).floor()}%',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold),)
  903. ],
  904. ):(lastDownload=='')?null:Text('Last download : ${DateFormat('dd MMM yyyy HH:mm').format(DateTime.parse(lastDownload))}',style: TextStyle(color: Colors.white,fontSize: 11,fontWeight: FontWeight.bold)),
  905. ),
  906. Positioned.fill(
  907. child: Column(
  908. mainAxisAlignment: MainAxisAlignment.center,
  909. children: <Widget>[
  910. Icon(Icons.file_upload,size: MediaQuery.of(context).size.width/6,color: Colors.white,),
  911. SizedBox(height: 5,),
  912. Text('Get Data Master',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 16),),
  913. ],
  914. ),
  915. ),
  916. ],
  917. ),
  918. ),
  919. ),
  920. ),
  921. InkWell(
  922. splashColor: Colors.black,
  923. onTap: ()async{
  924. await Future.delayed(Duration(milliseconds: 200));
  925. if(lastDownload!=''){
  926. Navigator.pushNamed(context, '/stocking');
  927. }
  928. else{
  929. util.showFlushbar(context, 'Data Master tidak ditemukan. Get data master dulu.');
  930. }
  931. },
  932. child: Container(
  933. padding: EdgeInsets.all(5),
  934. decoration: BoxDecoration(
  935. boxShadow: [
  936. BoxShadow(
  937. color: Colors.grey.withOpacity(0.5),
  938. spreadRadius: 2,
  939. blurRadius: 2,
  940. offset: Offset(0, 0), // changes position of shadow
  941. ),
  942. ],
  943. borderRadius: BorderRadius.all(Radius.circular(5.0)),
  944. color: Colors.blueGrey.withAlpha(230).withOpacity(0.8),
  945. ),
  946. child: Column(
  947. mainAxisAlignment: MainAxisAlignment.center,
  948. children: <Widget>[
  949. Icon(Icons.receipt,size: MediaQuery.of(context).size.width/6,color: Colors.white,),
  950. SizedBox(height: 5,),
  951. Text('Stocking',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 16),)
  952. ],
  953. ),
  954. ),
  955. ),
  956. InkWell(
  957. splashColor: Colors.black,
  958. onTap: ()async{
  959. if(lastDownload!=''){
  960. await DBHelper.database.insertUpdateValue(new valueTab(name: 'TGL_SELESAI',value: DateFormat('dd-MM-yyyy HH:mm:ss').format(new DateTime.now())));
  961. await DBHelper.database.closeDb();
  962. file_Trans_Handler trans = new file_Trans_Handler();
  963. bool popped = false;
  964. util.showLoading(context,onwillpop:()async{
  965. await trans.cancel();
  966. popped = true;
  967. return true;
  968. });
  969. var upload = await trans.uploadFile('UnitStocking.db',"${prefs.getString(keyClass.hostAddress)}/stock_taking/upload/",prefs.getString(keyClass.company),prefs.getString(keyClass.cabang_id));
  970. if(!popped){
  971. Navigator.pop(context);
  972. util.showFlushbar(context, upload['DATA'],color:(upload['STATUS']!=1)?Colors.red:Colors.grey);
  973. if(upload['STATUS']==1){
  974. setState(() {
  975. lastUpload = new DateTime.now().toIso8601String();
  976. });
  977. prefs.setString(keyClass.lastUpload, lastUpload);
  978. prefs.setString(keyClass.targetProccess, upload[keyClass.targetProccess]);
  979. }
  980. }
  981. }
  982. else{
  983. util.showFlushbar(context, "Belum ada data yang disimpan.",color: Colors.red);
  984. }
  985. },
  986. child: Container(
  987. padding: EdgeInsets.all(5),
  988. decoration: BoxDecoration(
  989. boxShadow: [
  990. BoxShadow(
  991. color: Colors.grey.withOpacity(0.5),
  992. spreadRadius: 2,
  993. blurRadius: 2,
  994. offset: Offset(0, 0), // changes position of shadow
  995. ),
  996. ],
  997. borderRadius: BorderRadius.all(Radius.circular(5.0)),
  998. color: Colors.indigo.withAlpha(220).withOpacity(0.7),
  999. ),
  1000. child: Stack(
  1001. children: <Widget>[
  1002. Container(
  1003. alignment: (progressUL!=null)?Alignment.bottomCenter:Alignment.bottomLeft,
  1004. padding: EdgeInsets.only(left: 10,right: 10,top: 10,bottom: 0),
  1005. child: (progressUL!=null)?Column(
  1006. mainAxisSize: MainAxisSize.min,
  1007. children: <Widget>[
  1008. LinearProgressIndicator(
  1009. value: progressUL,
  1010. ),
  1011. Text('${(progressUL*100).floor()}%',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold),)
  1012. ],
  1013. ):(lastUpload=='')?null:Text('Last upload : ${DateFormat('dd MMM yyyy HH:mm').format(DateTime.parse(lastUpload))}\n${(timeString!='')?'Duration: $timeString':''}',style: TextStyle(color: Colors.white,fontSize: 11,fontWeight: FontWeight.bold)),
  1014. ),
  1015. Positioned.fill(
  1016. child: Column(
  1017. mainAxisAlignment: MainAxisAlignment.center,
  1018. children: <Widget>[
  1019. Icon(Icons.file_upload,size: MediaQuery.of(context).size.width/6,color: Colors.white,),
  1020. SizedBox(height: 5,),
  1021. Text('Send Data Stokan',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 16),),
  1022. ],
  1023. ),
  1024. ),
  1025. ],
  1026. ),
  1027. ),
  1028. ),
  1029. (prefs.getString(keyClass.targetProccess)==null&&prefs.getBool(keyClass.submitProccess)==null)?InkWell(
  1030. splashColor: Colors.black,
  1031. onTap: ()async{
  1032. await Future.delayed(Duration(milliseconds: 200));
  1033. await clearData(context);
  1034. },
  1035. child: Container(
  1036. padding: EdgeInsets.all(5),
  1037. decoration: BoxDecoration(
  1038. boxShadow: [
  1039. BoxShadow(
  1040. color: Colors.grey.withOpacity(0.5),
  1041. spreadRadius: 2,
  1042. blurRadius: 2,
  1043. offset: Offset(0, 0), // changes position of shadow
  1044. ),
  1045. ],
  1046. borderRadius: BorderRadius.all(Radius.circular(5.0)),
  1047. color: Colors.red.withAlpha(200).withOpacity(0.7),
  1048. ),
  1049. child: Column(
  1050. mainAxisAlignment: MainAxisAlignment.center,
  1051. children: <Widget>[
  1052. Icon(Icons.restore_from_trash,size: MediaQuery.of(context).size.width/6,color: Colors.white,),
  1053. SizedBox(height: 5,),
  1054. Text('Clear Data',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 16),)
  1055. ],
  1056. ),
  1057. ),
  1058. ):
  1059. (prefs.getString(keyClass.targetProccess)!=null)?InkWell(
  1060. onTap: ()async{
  1061. bool result = await showDialog(context: context,builder: (context)=>WillPopScope(
  1062. onWillPop: ()async{
  1063. Navigator.pop(context,false);
  1064. return false;
  1065. },
  1066. child: AlertDialog(
  1067. title: Text('Process Data ?'),
  1068. content: Text('Proceed to unpack the uploaded data.'),
  1069. actions: <Widget>[
  1070. TextButton(
  1071. child: Text('Proceed'),
  1072. onPressed: ()async{
  1073. Navigator.pop(context,true);
  1074. },
  1075. ),
  1076. TextButton(
  1077. child: Text('Cancel'),
  1078. onPressed: (){Navigator.pop(context,false);},
  1079. )
  1080. ],
  1081. ),
  1082. ));
  1083. if(result){
  1084. util.showLoading(context);
  1085. var unpack = await util.JsonDataPutRaw({"userId":prefs.getString(keyClass.loginId),"cabangId":prefs.getString(keyClass.cabang_id),"company":prefs.getString(keyClass.company),"dbPath":prefs.getString(keyClass.targetProccess)}, '${prefs.getString(keyClass.hostAddress)}/stock_taking/add_collection/');
  1086. Navigator.pop(context);
  1087. util.showFlushbar(context, unpack['DATA'],color:(unpack['STATUS']!=1)?Colors.red:Colors.grey);
  1088. if(unpack['STATUS']==1){
  1089. prefs.remove(keyClass.targetProccess);
  1090. prefs.setBool(keyClass.submitProccess,true);
  1091. }
  1092. setState(() {
  1093. });
  1094. }
  1095. },
  1096. child: Container(
  1097. padding: EdgeInsets.all(5),
  1098. decoration: BoxDecoration(
  1099. boxShadow: [
  1100. BoxShadow(
  1101. color: Colors.grey.withOpacity(0.5),
  1102. spreadRadius: 2,
  1103. blurRadius: 2,
  1104. offset: Offset(0, 0), // changes position of shadow
  1105. ),
  1106. ],
  1107. borderRadius: BorderRadius.all(Radius.circular(5.0)),
  1108. color: Colors.orangeAccent.withAlpha(230).withOpacity(0.7),
  1109. ),
  1110. child: Column(
  1111. mainAxisAlignment: MainAxisAlignment.center,
  1112. children: <Widget>[
  1113. Icon(Icons.arrow_forward,size: MediaQuery.of(context).size.width/6,color: Colors.white,),
  1114. SizedBox(height: 5,),
  1115. Text('Process Units',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 16),)
  1116. ],
  1117. ),
  1118. ),
  1119. ):
  1120. InkWell(
  1121. onTap: ()async{
  1122. bool result = await showDialog(context: context,builder: (context)=>WillPopScope(
  1123. onWillPop: ()async{
  1124. Navigator.pop(context,false);
  1125. return false;
  1126. },
  1127. child: AlertDialog(
  1128. title: Text('Submit Data ?'),
  1129. content: Text('Submit the uploaded data.'),
  1130. actions: <Widget>[
  1131. TextButton(
  1132. child: Text('Submit'),
  1133. onPressed: ()async{
  1134. Navigator.pop(context,true);
  1135. },
  1136. ),
  1137. TextButton(
  1138. child: Text('Cancel'),
  1139. onPressed: (){Navigator.pop(context,false);},
  1140. )
  1141. ],
  1142. ),
  1143. ));
  1144. if(result){
  1145. util.showLoading(context);
  1146. if(prefs.getString(keyClass.stock_id) == null)
  1147. {
  1148. valueTab value = await DBHelper.database.getValue(keyClass.stock_id);
  1149. await prefs.setString(keyClass.stock_id, value.value);
  1150. }
  1151. var submits = await util.JsonDataPostRaw({"stockTakingId":prefs.getString(keyClass.stock_id),"company":prefs.getString(keyClass.company),"user_id":prefs.getString(keyClass.loginId)}, '${prefs.getString(keyClass.hostAddress)}/stock_taking/submit/');
  1152. Navigator.pop(context);
  1153. util.showFlushbar(context, submits['DATA'],color:(submits['STATUS']!=1)?Colors.red:Colors.grey);
  1154. if(submits['STATUS']==1){
  1155. loadState();
  1156. prefs.remove(keyClass.submitProccess);
  1157. }
  1158. setState(() {
  1159. });
  1160. }
  1161. },
  1162. child: Container(
  1163. padding: EdgeInsets.all(5),
  1164. decoration: BoxDecoration(
  1165. boxShadow: [
  1166. BoxShadow(
  1167. color: Colors.grey.withOpacity(0.5),
  1168. spreadRadius: 2,
  1169. blurRadius: 2,
  1170. offset: Offset(0, 0), // changes position of shadow
  1171. ),
  1172. ],
  1173. borderRadius: BorderRadius.all(Radius.circular(5.0)),
  1174. color: Colors.lightGreen.withAlpha(230),
  1175. ),
  1176. child: Column(
  1177. mainAxisAlignment: MainAxisAlignment.center,
  1178. children: <Widget>[
  1179. Icon(Icons.arrow_forward,size: MediaQuery.of(context).size.width/6,color: Colors.white,),
  1180. SizedBox(height: 5,),
  1181. Text('Submit Process',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 16),)
  1182. ],
  1183. ),
  1184. ),
  1185. ),
  1186. (prefs.getString(keyClass.targetProccess)!=null||(prefs.getBool(keyClass.submitProccess)!=null&&prefs.getBool(keyClass.submitProccess)))?InkWell(
  1187. splashColor: Colors.black,
  1188. onTap: ()async{
  1189. await Future.delayed(Duration(milliseconds: 200));
  1190. await clearData(context);
  1191. },
  1192. child: Container(
  1193. padding: EdgeInsets.all(5),
  1194. decoration: BoxDecoration(
  1195. boxShadow: [
  1196. BoxShadow(
  1197. color: Colors.grey.withOpacity(0.5),
  1198. spreadRadius: 2,
  1199. blurRadius: 2,
  1200. offset: Offset(0, 0), // changes position of shadow
  1201. ),
  1202. ],
  1203. borderRadius: BorderRadius.all(Radius.circular(5.0)),
  1204. color: Colors.red.withAlpha(200),
  1205. ),
  1206. child: Column(
  1207. mainAxisAlignment: MainAxisAlignment.center,
  1208. children: <Widget>[
  1209. Icon(Icons.restore_from_trash,size: MediaQuery.of(context).size.width/6,color: Colors.white,),
  1210. SizedBox(height: 5,),
  1211. Text('Clear Data',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 16),)
  1212. ],
  1213. ),
  1214. ),
  1215. ):Container(),
  1216. ],
  1217. )),
  1218. ),
  1219. ],
  1220. ),
  1221. bottomSheet: Container(height: 22,alignment: Alignment.bottomRight,child: Opacity(opacity: 0.5,child: Padding(padding: EdgeInsets.all(5),child: Text((lastDownload!='')?'Master Data Downloaded':'No Master Data Found',style: TextStyle(fontSize: 12),)))),
  1222. ),
  1223. );
  1224. }
  1225. }