add structure
This commit is contained in:
61
lib/model/announcement_model.dart
Normal file
61
lib/model/announcement_model.dart
Normal file
@@ -0,0 +1,61 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:fcs/vo/announcement.dart';
|
||||
|
||||
import 'base_model.dart';
|
||||
import 'constants.dart';
|
||||
import 'firebase_helper.dart';
|
||||
|
||||
class AnnouncementModel extends BaseModel {
|
||||
List<Announcement> announcements = [];
|
||||
|
||||
void initUser(user) {
|
||||
super.initUser(user);
|
||||
_loadAnnouncements();
|
||||
}
|
||||
|
||||
@override
|
||||
logout() async {
|
||||
announcements = [];
|
||||
}
|
||||
|
||||
Future<void> _loadAnnouncements() async {
|
||||
Stream<QuerySnapshot> snapshots = Firestore.instance
|
||||
.collection(
|
||||
"/$biz_collection/${setting.okEnergyId}/$announcement_collection")
|
||||
.snapshots();
|
||||
|
||||
snapshots.listen((snaps) async {
|
||||
announcements = snaps.documents.map((documentSnapshot) {
|
||||
var data = Announcement.fromMap(
|
||||
documentSnapshot.data, documentSnapshot.documentID);
|
||||
return data;
|
||||
}).toList();
|
||||
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Future<Announcement> getAnnouncement(String id) async {
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$announcement_collection";
|
||||
var snap = await getDocSnap(path, id);
|
||||
return Announcement.fromMap(snap.data, snap.documentID);
|
||||
}
|
||||
|
||||
Future<void> createAnnouncement(Announcement announcement) async {
|
||||
await request("/announcement", "POST",
|
||||
payload: announcement.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> updateAnnouncement(Announcement announcement) async {
|
||||
await request("/announcement", "PUT",
|
||||
payload: announcement.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> deleteAnnouncement(Announcement announcement) async {
|
||||
await request("/announcement", "DELETE",
|
||||
payload: announcement.toMap(), token: await getToken());
|
||||
}
|
||||
}
|
||||
147
lib/model/api_helper.dart
Normal file
147
lib/model/api_helper.dart
Normal file
@@ -0,0 +1,147 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:device_info/device_info.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:fcs/vo/status.dart';
|
||||
|
||||
import '../config.dart';
|
||||
|
||||
final log = Logger('requestAPI');
|
||||
|
||||
// request makes http request
|
||||
// if token is null
|
||||
Future<dynamic> requestAPI(
|
||||
String path,
|
||||
method, {
|
||||
dynamic payload,
|
||||
String token,
|
||||
String url,
|
||||
}) async {
|
||||
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
|
||||
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
|
||||
String deviceName = "${androidInfo.model}(${androidInfo.id})";
|
||||
log.info("device:${androidInfo.androidId},deviceName:$deviceName");
|
||||
|
||||
Map<String, dynamic> headers = {};
|
||||
if (token != null) {
|
||||
headers["Token"] = token;
|
||||
}
|
||||
if (androidInfo.androidId != null) {
|
||||
headers["Device"] = androidInfo.androidId + ":" + deviceName;
|
||||
}
|
||||
headers["Project-ID"] = Config.instance.reportProjectID;
|
||||
|
||||
BaseOptions options = new BaseOptions(
|
||||
method: method,
|
||||
baseUrl: url == null ? Config.instance.apiURL : url,
|
||||
connectTimeout: 10000,
|
||||
receiveTimeout: 10000,
|
||||
headers: headers,
|
||||
);
|
||||
log.info("baseUrl:${options.baseUrl}, path:$path");
|
||||
try {
|
||||
Dio dio = new Dio(options);
|
||||
Response response = await dio.request(
|
||||
path,
|
||||
data: payload,
|
||||
);
|
||||
var data = Status.fromJson(response.data);
|
||||
if (data.status == 'Ok') {
|
||||
return response.data["data"];
|
||||
} else {
|
||||
throw Exception(data.message);
|
||||
}
|
||||
} catch (e) {
|
||||
log.warning("path:$path, api:$e");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// request makes http request
|
||||
// if token is null
|
||||
Future<dynamic> requestDownloadAPI(String path, method,
|
||||
{dynamic payload, String token, String url, String filePath}) async {
|
||||
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
|
||||
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
|
||||
String deviceName = "${androidInfo.model}(${androidInfo.id})";
|
||||
log.info("device:${androidInfo.androidId},deviceName:$deviceName");
|
||||
|
||||
var bytes = utf8.encode(payload);
|
||||
var base64Str = base64.encode(bytes);
|
||||
String escapePayload = HtmlEscape().convert(base64Str);
|
||||
|
||||
try {
|
||||
String baseUrl = url == null ? Config.instance.apiURL : url;
|
||||
log.info("Path:$baseUrl$path");
|
||||
HttpClient client = new HttpClient();
|
||||
var _downloadData = StringBuffer();
|
||||
var fileSave = new File(filePath);
|
||||
var request = await client.getUrl(Uri.parse("$baseUrl$path"));
|
||||
request.headers.set("Project-ID", Config.instance.reportProjectID);
|
||||
request.headers
|
||||
.set(HttpHeaders.contentTypeHeader, "application/json; charset=UTF-8");
|
||||
if (token != null) {
|
||||
request.headers.set("Token", token);
|
||||
}
|
||||
if (androidInfo.androidId != null) {
|
||||
request.headers.set("Device", androidInfo.androidId + ":" + deviceName);
|
||||
}
|
||||
request.headers.set("payload", escapePayload);
|
||||
var response = await request.close();
|
||||
print("headers:${response.headers}");
|
||||
response.transform(utf8.decoder).listen((d) => _downloadData.write(d),
|
||||
onDone: () {
|
||||
fileSave.writeAsString(_downloadData.toString());
|
||||
});
|
||||
} catch (e) {
|
||||
log.warning("path:$path, api:$e");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// request makes http request
|
||||
// if token is null
|
||||
Future<dynamic> requestDownloadPDFAPI(String path, method,
|
||||
{dynamic payload, String token, String url, String filePath}) async {
|
||||
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
|
||||
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
|
||||
String deviceName = "${androidInfo.model}(${androidInfo.id})";
|
||||
log.info("device:${androidInfo.androidId},deviceName:$deviceName");
|
||||
|
||||
var bytes = utf8.encode(payload);
|
||||
var base64Str = base64.encode(bytes);
|
||||
String escapePayload = HtmlEscape().convert(base64Str);
|
||||
|
||||
try {
|
||||
String baseUrl = url == null ? Config.instance.apiURL : url;
|
||||
log.info("Path:$baseUrl$path");
|
||||
HttpClient client = new HttpClient();
|
||||
// var _downloadData = StringBuffer();
|
||||
var fileSave = new File(filePath);
|
||||
var request = await client.getUrl(Uri.parse("$baseUrl$path"));
|
||||
request.headers.set("Project-ID", Config.instance.reportProjectID);
|
||||
if (token != null) {
|
||||
request.headers.set("Token", token);
|
||||
}
|
||||
if (androidInfo.androidId != null) {
|
||||
request.headers.set("Device", androidInfo.androidId + ":" + deviceName);
|
||||
}
|
||||
request.headers.set("payload", escapePayload);
|
||||
var response = await request.close();
|
||||
print("headers:${response.headers}");
|
||||
var _downloadData = List<int>();
|
||||
|
||||
response.listen((d) => _downloadData.addAll(d), onDone: () {
|
||||
fileSave.writeAsBytes(_downloadData);
|
||||
});
|
||||
// response.transform(utf8.decoder).listen((d) => _downloadData.write(d),
|
||||
// onDone: () {
|
||||
// fileSave.writeAsString(_downloadData.toString());
|
||||
// });
|
||||
} catch (e) {
|
||||
log.warning("path:$path, api:$e");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
36
lib/model/base_model.dart
Normal file
36
lib/model/base_model.dart
Normal file
@@ -0,0 +1,36 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:fcs/model/api_helper.dart';
|
||||
import 'package:fcs/model/main_model.dart';
|
||||
|
||||
import '../vo/setting.dart';
|
||||
import '../vo/user.dart';
|
||||
|
||||
abstract class BaseModel extends ChangeNotifier {
|
||||
User user;
|
||||
Setting setting;
|
||||
MainModel mainModel;
|
||||
|
||||
void initUser(User user) async {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
void initSetting(Setting setting) async {
|
||||
this.setting = setting;
|
||||
}
|
||||
|
||||
void logout();
|
||||
|
||||
// request makes http request
|
||||
// if token is null
|
||||
dynamic request(
|
||||
String path,
|
||||
method, {
|
||||
dynamic payload,
|
||||
String token,
|
||||
String url,
|
||||
}) async {
|
||||
mainModel.resetPinTimer();
|
||||
return await requestAPI(path, method,
|
||||
payload: payload, token: token, url: url);
|
||||
}
|
||||
}
|
||||
177
lib/model/buyer_model.dart
Normal file
177
lib/model/buyer_model.dart
Normal file
@@ -0,0 +1,177 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert' show HtmlEscape, base64, utf8;
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:fcs/config.dart';
|
||||
import 'package:fcs/theme/theme.dart';
|
||||
import 'package:fcs/vo/buyer.dart';
|
||||
import 'package:fcs/vo/popup_menu.dart';
|
||||
|
||||
import 'base_model.dart';
|
||||
import 'constants.dart';
|
||||
import 'firebase_helper.dart';
|
||||
|
||||
class BuyerModel extends BaseModel {
|
||||
final log = Logger('BuyerModel');
|
||||
|
||||
StreamSubscription<QuerySnapshot> listener;
|
||||
|
||||
List<Buyer> buyers = [];
|
||||
PopupMenu popupMenu = new PopupMenu(index: 0);
|
||||
PopupMenu sortMenu = new PopupMenu();
|
||||
Buyer searchBuyer;
|
||||
void initUser(user) {
|
||||
super.initUser(user);
|
||||
_loadBuyers();
|
||||
}
|
||||
|
||||
Future<void> _loadBuyers() async {
|
||||
if (!user.isOwnerAndAbove() && !user.hasBuyer()) {
|
||||
return;
|
||||
}
|
||||
|
||||
listener = getQuerySnapshotByOrder(
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection",
|
||||
'user_name')
|
||||
.listen((snaps) async {
|
||||
buyers.clear();
|
||||
snaps.documents.forEach((d) {
|
||||
buyers.add(Buyer.fromMap(d.data, d.documentID));
|
||||
});
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
logout() async {
|
||||
if (listener != null) await listener.cancel();
|
||||
buyers = [];
|
||||
}
|
||||
|
||||
Future<Buyer> getBuyer(String buyerID) async {
|
||||
var snap = await getDocSnap(
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection", buyerID);
|
||||
return Buyer.fromMap(snap.data, snap.documentID);
|
||||
}
|
||||
|
||||
Future<Buyer> loadBuyerProducts(Buyer buyer, {bool force = false}) async {
|
||||
if (!force && buyer.buyerProducts != null && buyer.buyerProducts.length > 0)
|
||||
return buyer;
|
||||
var snaps = await getSnapshot(
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection/${buyer.id}/$product_collection");
|
||||
buyer.buyerProducts = snaps.documents
|
||||
.map((s) => BuyerProduct.fromMap(s.data, s.documentID))
|
||||
.toList();
|
||||
return buyer;
|
||||
}
|
||||
|
||||
Future<void> delete(Buyer buyer) async {
|
||||
await request("/buyer/${buyer.id}", "DELETE", token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> approve(Buyer buyer) async {
|
||||
await request("/buyer/approve", "PUT",
|
||||
payload: buyer.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> reject(Buyer buyer) async {
|
||||
await request("/buyer/reject", "POST",
|
||||
payload: buyer.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> allocate(Buyer buyer) async {
|
||||
await request("/buyer/allocate", "POST",
|
||||
payload: buyer.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
void filterStatus(String status, int _selectedIndex, int _sleectedSortIndex) {
|
||||
this.sortMenu.index = _sleectedSortIndex;
|
||||
buyers.clear();
|
||||
if (listener != null) {
|
||||
listener.cancel();
|
||||
}
|
||||
|
||||
this.popupMenu.index = _selectedIndex;
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$buyer_collection";
|
||||
listener = getFilterStatusSnapshot(path, status, 'user_name')
|
||||
.listen((snaps) async {
|
||||
buyers.clear();
|
||||
snaps.documents.forEach((d) {
|
||||
buyers.add(Buyer.fromMap(d.data, d.documentID));
|
||||
});
|
||||
notifyListeners();
|
||||
});
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<List<Buyer>> search(String searchBuyer) async {
|
||||
if (searchBuyer == null || searchBuyer == '') return List();
|
||||
|
||||
var bytes = utf8.encode(searchBuyer);
|
||||
var base64Str = base64.encode(bytes);
|
||||
HtmlEscape htmlEscape = const HtmlEscape();
|
||||
String escapeBuyer = htmlEscape.convert(base64Str);
|
||||
|
||||
int limit = 20;
|
||||
List<Buyer> _buyers = [];
|
||||
|
||||
try {
|
||||
var data = await request(
|
||||
"/api/fts/$buyer_collection/$escapeBuyer/$limit", "GET",
|
||||
token: await getToken(), url: Config.instance.reportURL);
|
||||
if (data == null) return List();
|
||||
|
||||
data.forEach((buyer) {
|
||||
var _buyer = Buyer.fromJson(buyer);
|
||||
_buyers.add(_buyer);
|
||||
});
|
||||
} catch (e) {
|
||||
// permission error
|
||||
log.warning("buyer error:" + e.toString());
|
||||
return null;
|
||||
}
|
||||
return _buyers;
|
||||
}
|
||||
|
||||
void filterSorting(int _sleectedSortIndex, int _selectedIndex) {
|
||||
this.popupMenu.index = _selectedIndex;
|
||||
buyers.clear();
|
||||
if (listener != null) {
|
||||
listener.cancel();
|
||||
}
|
||||
String _fieldName;
|
||||
bool descending = false;
|
||||
|
||||
if (_sleectedSortIndex == 0) {
|
||||
_fieldName = 'user_name';
|
||||
descending = false;
|
||||
}
|
||||
if (_sleectedSortIndex == 1) {
|
||||
_fieldName = 'user_name';
|
||||
descending = true;
|
||||
}
|
||||
if (_sleectedSortIndex == 2) {
|
||||
_fieldName = 'phone_number';
|
||||
descending = false;
|
||||
}
|
||||
if (_sleectedSortIndex == 3) {
|
||||
_fieldName = 'phone_number';
|
||||
descending = true;
|
||||
}
|
||||
|
||||
this.sortMenu.index = _sleectedSortIndex;
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$buyer_collection";
|
||||
listener =
|
||||
getFilterSnapshot(path, descending, _fieldName).listen((snaps) async {
|
||||
buyers.clear();
|
||||
snaps.documents.forEach((d) {
|
||||
buyers.add(Buyer.fromMap(d.data, d.documentID));
|
||||
notifyListeners();
|
||||
});
|
||||
|
||||
notifyListeners();
|
||||
});
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
244
lib/model/chart_model.dart
Normal file
244
lib/model/chart_model.dart
Normal file
@@ -0,0 +1,244 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:fcs/config.dart';
|
||||
import 'package:fcs/model/firebase_helper.dart';
|
||||
import 'package:fcs/vo/po.dart';
|
||||
import 'package:fcs/vo/po_do_count.dart';
|
||||
import 'package:fcs/vo/revenue.dart';
|
||||
|
||||
import 'base_model.dart';
|
||||
import 'constants.dart';
|
||||
import 'firebase_helper.dart';
|
||||
|
||||
class ChartModel extends BaseModel {
|
||||
final log = Logger('ChartModel');
|
||||
|
||||
List<POChartData> chartSummary = [];
|
||||
|
||||
Revenue revenue = new Revenue();
|
||||
PODOCount podoCount = new PODOCount();
|
||||
void initUser(user) async {
|
||||
super.initUser(user);
|
||||
revenue = new Revenue();
|
||||
podoCount = new PODOCount();
|
||||
|
||||
_loadRev();
|
||||
_loadPODOCount();
|
||||
if (user.hasPO() || user.isOwnerAndAbove()) {
|
||||
_getSummary();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadRev() async {
|
||||
try {
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$report_collection";
|
||||
String reportID = "revenue";
|
||||
|
||||
if (user.isBuyer()) {
|
||||
path =
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$report_collection";
|
||||
reportID = "spending";
|
||||
}
|
||||
|
||||
getDocSnapshot(path, reportID).listen((DocumentSnapshot snapshot) async {
|
||||
if (snapshot.data == null) {
|
||||
return;
|
||||
}
|
||||
revenue = Revenue.fromMap(snapshot.data, snapshot.documentID);
|
||||
notifyListeners();
|
||||
}).onError((e) {
|
||||
log.warning("Error! $e");
|
||||
});
|
||||
} catch (e) {
|
||||
log.warning("Error!! $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadPODOCount() async {
|
||||
try {
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$report_collection";
|
||||
String reportID = "po_do_count";
|
||||
|
||||
if (user.isBuyer()) {
|
||||
path =
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$report_collection";
|
||||
}
|
||||
|
||||
getDocSnapshot(path, reportID).listen((DocumentSnapshot snapshot) async {
|
||||
if (snapshot.data == null) {
|
||||
return;
|
||||
}
|
||||
podoCount = PODOCount.fromMap(snapshot.data, snapshot.documentID);
|
||||
notifyListeners();
|
||||
}).onError((e) {
|
||||
log.warning("Error! $e");
|
||||
});
|
||||
} catch (e) {
|
||||
log.warning("Error!! $e");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
logout() async {
|
||||
chartSummary = [];
|
||||
revenue = new Revenue();
|
||||
podoCount = new PODOCount();
|
||||
}
|
||||
|
||||
_getSummary() async {
|
||||
chartSummary.clear();
|
||||
try {
|
||||
var data = {
|
||||
"fields": 'quantity,product_id,product_name,color',
|
||||
"aggfuns": "sum,,,",
|
||||
"groupbys": 'product_id',
|
||||
};
|
||||
var result = await request("/api/data/po_product_view", "POST",
|
||||
token: await getToken(),
|
||||
url: Config.instance.reportURL,
|
||||
payload: jsonEncode(data));
|
||||
if (result == null) return;
|
||||
chartSummary.clear();
|
||||
result.forEach((chart) {
|
||||
var _list = POChartData.fromJson(chart, "quantity_sum");
|
||||
chartSummary.add(_list);
|
||||
});
|
||||
} catch (e) {
|
||||
log.warning("Error get Summary>>>>${e.toString()}");
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<POChartData>> loadSummary() async {
|
||||
List<POChartData> _list = List();
|
||||
try {
|
||||
var data = {
|
||||
"fields": 'quantity,product_id,product_name,color',
|
||||
"aggfuns": "sum,,,",
|
||||
"groupbys": 'product_id',
|
||||
};
|
||||
var result = await request("/api/data/po_product_view", "POST",
|
||||
token: await getToken(),
|
||||
url: Config.instance.reportURL,
|
||||
payload: jsonEncode(data));
|
||||
if (result != null) {
|
||||
result.forEach((chart) {
|
||||
var _data = POChartData.fromJson(chart, "quantity_sum");
|
||||
_list.add(_data);
|
||||
});
|
||||
}
|
||||
return _list;
|
||||
} catch (e) {
|
||||
log.warning("Error>>>>${e.toString()}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<POChartData>> loadUsers() async {
|
||||
List<POChartData> _list = List();
|
||||
var data = {
|
||||
"fields": 'quantity,user_name,product_name',
|
||||
"aggfuns": "sum,,",
|
||||
"groupbys": 'product_id,user_id',
|
||||
};
|
||||
try {
|
||||
var result = await request("/api/data/po_product_view", "POST",
|
||||
token: await getToken(),
|
||||
url: Config.instance.reportURL,
|
||||
payload: jsonEncode(data));
|
||||
|
||||
result.forEach((chart) {
|
||||
var _buyer = POChartData.fromJson(chart, "quantity_sum");
|
||||
_list.add(_buyer);
|
||||
});
|
||||
return _list;
|
||||
} catch (e) {
|
||||
log.warning("Error load>>>>${e.toString()}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<POBuyerData>> loadPOBalancesForBuyer_() async {
|
||||
List<POBuyerData> _list = List();
|
||||
try {
|
||||
var data = {
|
||||
"fields": 'amount,status',
|
||||
"aggfuns": "sum,",
|
||||
"groupbys": 'status',
|
||||
"filters": [
|
||||
{"field": "user_id", "compare": "==", "value": user.docID}
|
||||
]
|
||||
};
|
||||
var result = await request("/api/data/po_buyer_view", "POST",
|
||||
token: await getToken(),
|
||||
url: Config.instance.reportURL,
|
||||
payload: jsonEncode(data));
|
||||
|
||||
if (result != null) {
|
||||
result.forEach((chart) {
|
||||
var _data = POBuyerData.fromJson(chart, "amount_sum");
|
||||
_list.add(_data);
|
||||
});
|
||||
}
|
||||
return _list;
|
||||
} catch (e) {
|
||||
log.warning("Error>>>>${e.toString()}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<POChartData>> loadPOBalancesForBuyer() async {
|
||||
List<POChartData> _list = List();
|
||||
try {
|
||||
var data = {
|
||||
"fields": 'quantity,product_id,product_name,user_id,color',
|
||||
"aggfuns": "sum,,,,",
|
||||
"groupbys": 'product_id,user_id',
|
||||
"filters": [
|
||||
{"field": "user_id", "compare": "==", "value": user.docID}
|
||||
]
|
||||
};
|
||||
var result = await request("/api/data/po_product_view", "POST",
|
||||
token: await getToken(),
|
||||
url: Config.instance.reportURL,
|
||||
payload: jsonEncode(data));
|
||||
if (result != null) {
|
||||
result.forEach((chart) {
|
||||
var _data = POChartData.fromJson(chart, "quantity_sum");
|
||||
_list.add(_data);
|
||||
});
|
||||
}
|
||||
return _list;
|
||||
} catch (e) {
|
||||
log.warning("Error>>>>${e.toString()}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<POChartData>> loadPOBalProductsForBuyer() async {
|
||||
List<POChartData> _list = List();
|
||||
var data = {
|
||||
"fields": 'quantity,user_name,user_id,product_name',
|
||||
"aggfuns": "sum,,,",
|
||||
"groupbys": 'product_id,user_id',
|
||||
"filters": [
|
||||
{"field": "user_id", "compare": "==", "value": user.docID}
|
||||
]
|
||||
};
|
||||
try {
|
||||
var result = await request("/api/data/po_product_view", "POST",
|
||||
token: await getToken(),
|
||||
url: Config.instance.reportURL,
|
||||
payload: jsonEncode(data));
|
||||
result.forEach((chart) {
|
||||
var _buyer = POChartData.fromJson(chart, "quantity_sum");
|
||||
_list.add(_buyer);
|
||||
});
|
||||
return _list;
|
||||
} catch (e) {
|
||||
log.warning("Error load>>>>${e.toString()}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
37
lib/model/constants.dart
Normal file
37
lib/model/constants.dart
Normal file
@@ -0,0 +1,37 @@
|
||||
const ok_doc_id = "ok";
|
||||
const setting_doc_id = "ok_setting";
|
||||
|
||||
const config_collection = "configs";
|
||||
const biz_collection = "bizs";
|
||||
const product_collection = "products";
|
||||
const user_collection = "users";
|
||||
const privilege_collection = "privileges";
|
||||
const user_level_collection = "user_levels";
|
||||
const storage_collection = "storages";
|
||||
const buyer_collection = "buyers";
|
||||
const buying_pos = "buying_pos";
|
||||
const selling_pos = "selling_pos";
|
||||
const inventory_takings = "inventory_takings";
|
||||
const inventory_lines = "inventory_lines";
|
||||
const pds_collection = "pds";
|
||||
const pos_collection = "pos";
|
||||
const dos_collection = "dos";
|
||||
const notification_collection = "notifications";
|
||||
const log_collection = "logs";
|
||||
const report_collection = "reports";
|
||||
const po_product_collection = "po_products";
|
||||
const device_collection = "devices";
|
||||
const do_po_lines_collection = "do_po_lines";
|
||||
const reports_collection = "reports";
|
||||
const announcement_collection = "announcements";
|
||||
const report_user_collection = "report_users";
|
||||
|
||||
const po_files_path = "/ok/po";
|
||||
const reg_files_path = "/ok/reg";
|
||||
const do_files_path = "/ok/do";
|
||||
const sign_files_path = "/ok/sign";
|
||||
const bank_images_path = "/ok/banks";
|
||||
|
||||
const po_approved_status = "approved";
|
||||
const po_closed_status = "closed";
|
||||
const do_approved_status = "approved";
|
||||
140
lib/model/delivery_model.dart
Normal file
140
lib/model/delivery_model.dart
Normal file
@@ -0,0 +1,140 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:path/path.dart' as Path;
|
||||
import 'package:fcs/model/constants.dart';
|
||||
import 'package:fcs/vo/do.dart';
|
||||
import 'package:fcs/vo/popup_menu.dart';
|
||||
|
||||
import 'base_model.dart';
|
||||
import 'firebase_helper.dart';
|
||||
|
||||
class DeliveryModel extends BaseModel {
|
||||
StreamSubscription<QuerySnapshot> listener;
|
||||
|
||||
List<DOSubmission> dos = [];
|
||||
PopupMenu popupMenu = new PopupMenu(index: 0);
|
||||
int dateIndex = 0;
|
||||
DateTime selectedDate = DateTime.now();
|
||||
int timber = 0;
|
||||
|
||||
void initUser(user) async {
|
||||
super.initUser(user);
|
||||
_loadDOs();
|
||||
}
|
||||
|
||||
Future<void> _loadDOs() async {
|
||||
if (!user.isOwnerAndAbove() && !user.hasDelivery()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$dos_collection";
|
||||
|
||||
var startDate = new DateTime(
|
||||
selectedDate.year, selectedDate.month, selectedDate.day, 0, 0, 0);
|
||||
var endDate = new DateTime(
|
||||
selectedDate.year, selectedDate.month, selectedDate.day, 23, 59, 59);
|
||||
|
||||
listener = getDeliverySnapshot(
|
||||
path, 'delivery_date', startDate, endDate, 'do_number')
|
||||
.listen((snaps) async {
|
||||
dos.clear();
|
||||
snaps.documents.forEach((d) {
|
||||
dos.add(DOSubmission.fromMap(d.data, d.documentID));
|
||||
});
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
logout() async {
|
||||
if (listener != null) await listener.cancel();
|
||||
dos = [];
|
||||
}
|
||||
|
||||
Future<DOSubmission> getDO(String id) async {
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$dos_collection";
|
||||
if (user.isBuyer()) {
|
||||
path =
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$dos_collection";
|
||||
}
|
||||
var doSnap = await getDocSnap(path, id);
|
||||
return DOSubmission.fromMap(doSnap.data, doSnap.documentID);
|
||||
}
|
||||
|
||||
Future<void> endDelivery(DOSubmission doObj, Uint8List img) async {
|
||||
String path = Path.join(do_files_path, user.docID);
|
||||
String imgUrl = await uploadStorageData(path, img, fileName: doObj.id);
|
||||
doObj.doReceiptUrl = imgUrl;
|
||||
await request("/do/ended", "POST",
|
||||
payload: doObj.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
void filterData(
|
||||
String status, DateTime dateTime, int _selectedIndex, int _dateIndex) {
|
||||
dos.clear();
|
||||
|
||||
var startDate =
|
||||
new DateTime(dateTime.year, dateTime.month, dateTime.day, 0, 0, 0);
|
||||
var endDate =
|
||||
new DateTime(dateTime.year, dateTime.month, dateTime.day, 23, 59, 59);
|
||||
|
||||
if (listener != null) {
|
||||
listener.cancel();
|
||||
}
|
||||
|
||||
this.popupMenu.index = _selectedIndex;
|
||||
this.dateIndex = _dateIndex;
|
||||
this.selectedDate = dateTime == null
|
||||
? new DateTime(
|
||||
selectedDate.year, selectedDate.month, selectedDate.day, 0, 0, 0)
|
||||
: dateTime;
|
||||
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$dos_collection";
|
||||
if (user.isBuyer()) {
|
||||
path =
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$dos_collection";
|
||||
}
|
||||
|
||||
if (status != null && dateTime == null) {
|
||||
listener = getDeliveryStatusSnapshot(path, status, 'do_number')
|
||||
.listen((snaps) async {
|
||||
dos.clear();
|
||||
snaps.documents.forEach((d) {
|
||||
dos.add(DOSubmission.fromMap(d.data, d.documentID));
|
||||
});
|
||||
notifyListeners();
|
||||
});
|
||||
} else if (dateTime != null && status == null) {
|
||||
listener = getDeliveryDateSnapshot(
|
||||
path, 'delivery_date', startDate, endDate, 'do_number')
|
||||
.listen((snaps) async {
|
||||
dos.clear();
|
||||
snaps.documents.forEach((d) {
|
||||
dos.add(DOSubmission.fromMap(d.data, d.documentID));
|
||||
});
|
||||
notifyListeners();
|
||||
});
|
||||
} else if (status != null && dateTime != null) {
|
||||
listener = getDeliveryDataSnapshot(
|
||||
path, status, 'delivery_date', startDate, endDate, 'do_number')
|
||||
.listen((snaps) async {
|
||||
dos.clear();
|
||||
snaps.documents.forEach((d) {
|
||||
dos.add(DOSubmission.fromMap(d.data, d.documentID));
|
||||
});
|
||||
notifyListeners();
|
||||
});
|
||||
} else {
|
||||
listener =
|
||||
getQuerySnapshotByOrder(path, 'do_number').listen((snaps) async {
|
||||
dos.clear();
|
||||
snaps.documents.forEach((d) {
|
||||
dos.add(DOSubmission.fromMap(d.data, d.documentID));
|
||||
});
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
76
lib/model/device_model.dart
Normal file
76
lib/model/device_model.dart
Normal file
@@ -0,0 +1,76 @@
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:device_info/device_info.dart';
|
||||
import 'package:fcs/vo/device.dart';
|
||||
|
||||
import 'base_model.dart';
|
||||
import 'constants.dart';
|
||||
import 'firebase_helper.dart';
|
||||
|
||||
class PhoneDeviceModel extends BaseModel {
|
||||
List<PhoneDevice> devices = new List();
|
||||
|
||||
bool isLogout = false;
|
||||
void initUser(user) {
|
||||
super.initUser(user);
|
||||
_loadDevices();
|
||||
}
|
||||
|
||||
Future<void> _loadDevices() async {
|
||||
Stream<QuerySnapshot> snapshots = Firestore.instance
|
||||
.collection(
|
||||
"/$biz_collection/${setting.okEnergyId}/$user_collection/${user.docID}/$device_collection")
|
||||
.where("primary_device", isEqualTo: false)
|
||||
.snapshots();
|
||||
|
||||
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
|
||||
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
|
||||
|
||||
snapshots.listen((snaps) async {
|
||||
devices = snaps.documents.map((documentSnapshot) {
|
||||
var data = PhoneDevice.fromMap(
|
||||
documentSnapshot.data, documentSnapshot.documentID);
|
||||
if (!data.deviceOn &&
|
||||
!data.primaryDevice &&
|
||||
data.id == androidInfo.androidId &&
|
||||
!documentSnapshot.metadata.isFromCache) {
|
||||
this.isLogout = true;
|
||||
this.mainModel.logout();
|
||||
notifyListeners();
|
||||
}
|
||||
return data;
|
||||
}).toList();
|
||||
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
logout() async {
|
||||
devices = [];
|
||||
}
|
||||
|
||||
bool isLogoutDevice() {
|
||||
return this.isLogout;
|
||||
}
|
||||
|
||||
setDevice(bool status) {
|
||||
this.isLogout = status;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> confirmDevice(String id, String deviceID) async {
|
||||
await request("/dev/on", "POST",
|
||||
payload: {"id": id, "device_id": deviceID}, token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> logoutDevice(String id, String deviceID) async {
|
||||
await request("/dev/off", "POST",
|
||||
payload: {"id": id, "device_id": deviceID}, token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> setPrimaryDevice(String id, String deviceID) async {
|
||||
await request("/dev", "PUT",
|
||||
payload: {"id": id, "device_id": deviceID}, token: await getToken());
|
||||
}
|
||||
}
|
||||
258
lib/model/do_model.dart
Normal file
258
lib/model/do_model.dart
Normal file
@@ -0,0 +1,258 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:path/path.dart' as Path;
|
||||
import 'package:fcs/model/api_helper.dart';
|
||||
import 'package:fcs/model/constants.dart';
|
||||
import 'package:fcs/pages/do/do_files.dart';
|
||||
import 'package:fcs/vo/do.dart';
|
||||
import 'package:fcs/vo/popup_menu.dart';
|
||||
|
||||
import 'base_model.dart';
|
||||
import 'firebase_helper.dart';
|
||||
|
||||
class DOModel extends BaseModel {
|
||||
StreamSubscription<QuerySnapshot> listener;
|
||||
|
||||
List<DOSubmission> dos = [];
|
||||
PopupMenu popupMenu = new PopupMenu(index: 0);
|
||||
int dateIndex = 0;
|
||||
DateTime selectedDate = DateTime.now();
|
||||
int timber = 0;
|
||||
|
||||
void initUser(user) async {
|
||||
super.initUser(user);
|
||||
_loadDOs();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
logout() async {
|
||||
if (listener != null) await listener.cancel();
|
||||
dos = [];
|
||||
}
|
||||
|
||||
Future<void> _loadDOs() async {
|
||||
String path;
|
||||
if (user.hasDO() || user.isOwnerAndAbove()) {
|
||||
path = "/$biz_collection/${setting.okEnergyId}/$dos_collection";
|
||||
}
|
||||
if (user.isBuyer()) {
|
||||
path =
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$dos_collection";
|
||||
}
|
||||
var startDate = new DateTime(
|
||||
selectedDate.year, selectedDate.month, selectedDate.day, 0, 0, 0);
|
||||
var endDate = new DateTime(
|
||||
selectedDate.year, selectedDate.month, selectedDate.day, 23, 59, 59);
|
||||
|
||||
listener =
|
||||
getFilterDateSnapshot(path, 'do_date', startDate, endDate, 'do_number')
|
||||
.listen((snaps) async {
|
||||
dos.clear();
|
||||
snaps.documents.forEach((d) {
|
||||
dos.add(DOSubmission.fromMap(d.data, d.documentID));
|
||||
});
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
Future<DOSubmission> loadDOPOLines(DOSubmission doSub) async {
|
||||
String path =
|
||||
"/$biz_collection/${setting.okEnergyId}/$dos_collection/${doSub.id}/$do_po_lines_collection";
|
||||
if (user.isBuyer()) {
|
||||
path =
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$dos_collection/${doSub.id}/$do_po_lines_collection";
|
||||
}
|
||||
var snaps = await getSnapshot(path);
|
||||
doSub.dopoLies =
|
||||
snaps.documents.map((s) => DOPOLine.fromMap(s.data)).toList();
|
||||
return doSub;
|
||||
}
|
||||
|
||||
Future<DOSubmission> getDO(String id) async {
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$dos_collection";
|
||||
if (user.isBuyer()) {
|
||||
path =
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$dos_collection";
|
||||
}
|
||||
var doSnap = await getDocSnap(path, id);
|
||||
return DOSubmission.fromMap(doSnap.data, doSnap.documentID);
|
||||
}
|
||||
|
||||
Future<void> createDO(DOSubmission doSubmission, DOFiles files) async {
|
||||
doSubmission.userID = user.docID;
|
||||
String path = Path.join(do_files_path, user.docID);
|
||||
|
||||
if (files.storageChargeFile != null) {
|
||||
String url = await uploadStorage(path, files.storageChargeFile);
|
||||
doSubmission.storageReceiptUrl = url;
|
||||
}
|
||||
if (files.licenseFile != null) {
|
||||
String url = await uploadStorage(path, files.licenseFile);
|
||||
doSubmission.driverLicenceUrl = url;
|
||||
}
|
||||
|
||||
await request("/do", "POST",
|
||||
payload: doSubmission.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> updateDO(DOSubmission doSubmission, DOFiles files) async {
|
||||
String path = Path.join(do_files_path, user.docID);
|
||||
if (files.storageFileChanged) {
|
||||
if (doSubmission.storageReceiptUrl != null &&
|
||||
doSubmission.storageReceiptUrl != '') {
|
||||
await deleteStorageFromUrl(doSubmission.storageReceiptUrl);
|
||||
}
|
||||
doSubmission.storageReceiptUrl = null;
|
||||
String url = await uploadStorage(path, files.storageChargeFile);
|
||||
doSubmission.storageReceiptUrl = url;
|
||||
}
|
||||
|
||||
if (files.licenseFileChanged) {
|
||||
if (doSubmission.driverLicenceUrl != null &&
|
||||
doSubmission.driverLicenceUrl != '') {
|
||||
await deleteStorageFromUrl(doSubmission.driverLicenceUrl);
|
||||
}
|
||||
doSubmission.driverLicenceUrl = null;
|
||||
String url = await uploadStorage(path, files.licenseFile);
|
||||
doSubmission.driverLicenceUrl = url;
|
||||
}
|
||||
await request("/do", "PUT",
|
||||
payload: doSubmission.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> approveDO(DOSubmission doObj) async {
|
||||
await request("/do/approved", "POST",
|
||||
payload: doObj.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> rejectDO(DOSubmission doObj) async {
|
||||
await request("/do/rejected", "POST",
|
||||
payload: doObj.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> cancelDO(DOSubmission doObj) async {
|
||||
await request("/do/canceled", "POST",
|
||||
payload: doObj.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> initDelivery(DOSubmission doObj) async {
|
||||
String path = Path.join(do_files_path, user.docID);
|
||||
String imgUrl =
|
||||
await uploadStorage(path, doObj.driverImg, fileName: doObj.id);
|
||||
doObj.driverImgUrl = imgUrl;
|
||||
await request("/do/initiated", "POST",
|
||||
payload: doObj.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> startDelivery(DOSubmission doObj) async {
|
||||
await request("/do/started", "POST",
|
||||
payload: doObj.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> endDelivery(DOSubmission doObj, Uint8List img) async {
|
||||
String path = Path.join(do_files_path, user.docID);
|
||||
String imgUrl = await uploadStorageData(path, img, fileName: doObj.id);
|
||||
doObj.doReceiptUrl = imgUrl;
|
||||
await request("/do/ended", "POST",
|
||||
payload: doObj.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
void filterData(
|
||||
String status, DateTime dateTime, int _selectedIndex, int _dateIndex) {
|
||||
dos.clear();
|
||||
if (listener != null) {
|
||||
listener.cancel();
|
||||
}
|
||||
|
||||
this.popupMenu.index = _selectedIndex;
|
||||
this.dateIndex = _dateIndex;
|
||||
this.selectedDate = dateTime == null
|
||||
? new DateTime(
|
||||
selectedDate.year, selectedDate.month, selectedDate.day, 0, 0, 0)
|
||||
: dateTime;
|
||||
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$dos_collection";
|
||||
if (user.isBuyer()) {
|
||||
path =
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$dos_collection";
|
||||
}
|
||||
|
||||
if (status != null && dateTime == null) {
|
||||
listener = getFilterStatusSnapshot(path, status, 'do_number')
|
||||
.listen((snaps) async {
|
||||
dos.clear();
|
||||
snaps.documents.forEach((d) {
|
||||
dos.add(DOSubmission.fromMap(d.data, d.documentID));
|
||||
});
|
||||
notifyListeners();
|
||||
});
|
||||
} else if (dateTime != null && status == null) {
|
||||
var endDate =
|
||||
new DateTime(dateTime.year, dateTime.month, dateTime.day, 23, 59, 59);
|
||||
listener =
|
||||
getFilterDateSnapshot(path, 'do_date', dateTime, endDate, 'do_number')
|
||||
.listen((snaps) async {
|
||||
dos.clear();
|
||||
snaps.documents.forEach((d) {
|
||||
dos.add(DOSubmission.fromMap(d.data, d.documentID));
|
||||
});
|
||||
notifyListeners();
|
||||
});
|
||||
} else if (status != null && dateTime != null) {
|
||||
var endDate =
|
||||
new DateTime(dateTime.year, dateTime.month, dateTime.day, 23, 59, 59);
|
||||
listener = getFilterDataSnapshot(
|
||||
path, status, 'do_date', dateTime, endDate, 'do_number')
|
||||
.listen((snaps) async {
|
||||
dos.clear();
|
||||
snaps.documents.forEach((d) {
|
||||
dos.add(DOSubmission.fromMap(d.data, d.documentID));
|
||||
});
|
||||
notifyListeners();
|
||||
});
|
||||
} else {
|
||||
listener =
|
||||
getQuerySnapshotByOrder(path, 'do_number').listen((snaps) async {
|
||||
dos.clear();
|
||||
snaps.documents.forEach((d) {
|
||||
dos.add(DOSubmission.fromMap(d.data, d.documentID));
|
||||
});
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
addTimber(int count) {
|
||||
timber = count;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<List<DOSubmission>> getDOForDelivery(DateTime dateTime) async {
|
||||
List<DOSubmission> dos = [];
|
||||
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$dos_collection";
|
||||
if (user.isBuyer()) {
|
||||
path =
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$dos_collection";
|
||||
}
|
||||
DateTime date = DateTime(dateTime.year, dateTime.month, dateTime.day);
|
||||
DateTime dateAddOne = date.add(Duration(days: 1));
|
||||
|
||||
QuerySnapshot snapshots = await Firestore.instance
|
||||
.collection(path)
|
||||
.where("status", isEqualTo: do_approved_status)
|
||||
.where("delivery_date", isGreaterThanOrEqualTo: date)
|
||||
.where("delivery_date", isLessThan: dateAddOne)
|
||||
.orderBy("delivery_date").orderBy("user_name")
|
||||
.limit(100)
|
||||
.getDocuments();
|
||||
snapshots.documents.forEach((d) {
|
||||
dos.add(DOSubmission.fromMap(d.data, d.documentID));
|
||||
});
|
||||
return dos;
|
||||
}
|
||||
}
|
||||
59
lib/model/employee_model.dart
Normal file
59
lib/model/employee_model.dart
Normal file
@@ -0,0 +1,59 @@
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:fcs/vo/user.dart';
|
||||
|
||||
import 'base_model.dart';
|
||||
import 'constants.dart';
|
||||
import 'firebase_helper.dart';
|
||||
|
||||
class EmployeeModel extends BaseModel {
|
||||
final log = Logger('EmployeeModel');
|
||||
|
||||
List<User> employees = [];
|
||||
|
||||
void initUser(user) async {
|
||||
super.initUser(user);
|
||||
_loadEmployees();
|
||||
}
|
||||
|
||||
@override
|
||||
logout() async {
|
||||
employees = [];
|
||||
}
|
||||
|
||||
Future<void> _loadEmployees() async {
|
||||
if (!user.isOwnerAndAbove() && !user.hasAccount()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Firestore.instance
|
||||
.collection("/$biz_collection/${setting.okEnergyId}/$user_collection")
|
||||
.where("is_employee", isEqualTo: true)
|
||||
.snapshots()
|
||||
.listen((QuerySnapshot snapshot) {
|
||||
employees.clear();
|
||||
employees = snapshot.documents.map((documentSnapshot) {
|
||||
var user =
|
||||
User.fromMap(documentSnapshot.data, documentSnapshot.documentID);
|
||||
return user;
|
||||
}).toList();
|
||||
notifyListeners();
|
||||
}).onError((e) {
|
||||
log.warning("Error! $e");
|
||||
});
|
||||
} catch (e) {
|
||||
log.warning("Error!! $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updatePrivileges(String userID, List<String> privileges) async {
|
||||
try {
|
||||
await request("/employee/privileges", "PUT",
|
||||
payload: {"id": userID, "privileges": privileges},
|
||||
token: await getToken());
|
||||
} catch (e) {
|
||||
throw Exception(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
269
lib/model/firebase_helper.dart
Normal file
269
lib/model/firebase_helper.dart
Normal file
@@ -0,0 +1,269 @@
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:firebase_storage/firebase_storage.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
final log = Logger('firebaseHelper');
|
||||
|
||||
final FirebaseAuth auth = FirebaseAuth.instance;
|
||||
|
||||
Future<String> getToken() async {
|
||||
FirebaseUser firebaseUser = await auth.currentUser();
|
||||
IdTokenResult token = await firebaseUser.getIdToken();
|
||||
return token.token;
|
||||
}
|
||||
|
||||
Stream<QuerySnapshot> getQuerySnapshot(String path) {
|
||||
log.info("getQuerySnapshot Path: $path");
|
||||
Stream<QuerySnapshot> snapshots =
|
||||
Firestore.instance.collection(path).snapshots();
|
||||
return snapshots;
|
||||
}
|
||||
|
||||
Stream<QuerySnapshot> getQuerySnapshotByOrder(String path, String orderName) {
|
||||
log.info("getQuerySnapshotByOrder Path: $path");
|
||||
Stream<QuerySnapshot> snapshots = Firestore.instance
|
||||
.collection(path)
|
||||
.orderBy(orderName, descending: true)
|
||||
.snapshots();
|
||||
return snapshots;
|
||||
}
|
||||
|
||||
Stream<QuerySnapshot> getFilterStatusSnapshot(
|
||||
String path, String searchStatus, String orderName) {
|
||||
log.info("getFilterStatusSnapshot Path: $path");
|
||||
Stream<QuerySnapshot> snapshots = Firestore.instance
|
||||
.collection(path)
|
||||
.where('status', isEqualTo: searchStatus)
|
||||
.orderBy(orderName, descending: true)
|
||||
.snapshots();
|
||||
return snapshots;
|
||||
}
|
||||
|
||||
Stream<QuerySnapshot> getFilterSnapshot(
|
||||
String path, bool descending, String orderName) {
|
||||
log.info("getFilterSnapshot Path: $path");
|
||||
Stream<QuerySnapshot> snapshots = Firestore.instance
|
||||
.collection(path)
|
||||
.orderBy(orderName, descending: descending)
|
||||
.snapshots();
|
||||
return snapshots;
|
||||
}
|
||||
|
||||
Stream<QuerySnapshot> getDeliveryStatusSnapshot(
|
||||
String path, String searchStatus, String orderName) {
|
||||
log.info("getDeliveryStatusSnapshot Path: $path");
|
||||
Stream<QuerySnapshot> snapshots = Firestore.instance
|
||||
.collection(path)
|
||||
.where('status', isEqualTo: searchStatus)
|
||||
.where("in_delivery", isEqualTo: true)
|
||||
.orderBy(orderName, descending: true)
|
||||
.snapshots();
|
||||
return snapshots;
|
||||
}
|
||||
|
||||
Stream<QuerySnapshot> getFilterDateSnapshot(String path, String type,
|
||||
DateTime startDate, DateTime endDate, String orderName) {
|
||||
log.info("getFilterDateSnapshot Path: $path");
|
||||
Firestore.instance
|
||||
.collection(path)
|
||||
.where(type, isGreaterThanOrEqualTo: startDate)
|
||||
.where(type, isLessThanOrEqualTo: endDate)
|
||||
.orderBy(type, descending: true)
|
||||
.orderBy(orderName, descending: true)
|
||||
.limit(1)
|
||||
.getDocuments()
|
||||
.then((s) {});
|
||||
|
||||
Stream<QuerySnapshot> snapshots = Firestore.instance
|
||||
.collection(path)
|
||||
.where(type, isGreaterThanOrEqualTo: startDate)
|
||||
.where(type, isLessThanOrEqualTo: endDate)
|
||||
.orderBy(type, descending: true)
|
||||
.orderBy(orderName, descending: true)
|
||||
.snapshots();
|
||||
return snapshots;
|
||||
}
|
||||
|
||||
Stream<QuerySnapshot> getDeliveryDateSnapshot(String path, String type,
|
||||
DateTime startDate, DateTime endDate, String orderName) {
|
||||
log.info("getDeliveryDateSnapshot Path: $path");
|
||||
Firestore.instance
|
||||
.collection(path)
|
||||
.where(type, isGreaterThanOrEqualTo: startDate)
|
||||
.where(type, isLessThanOrEqualTo: endDate)
|
||||
.where("in_delivery", isEqualTo: true)
|
||||
.orderBy(type, descending: true)
|
||||
.orderBy(orderName, descending: true)
|
||||
.limit(1)
|
||||
.getDocuments()
|
||||
.then((s) {});
|
||||
|
||||
Stream<QuerySnapshot> snapshots = Firestore.instance
|
||||
.collection(path)
|
||||
.where(type, isGreaterThanOrEqualTo: startDate)
|
||||
.where(type, isLessThanOrEqualTo: endDate)
|
||||
.where("in_delivery", isEqualTo: true)
|
||||
.orderBy(type, descending: true)
|
||||
.orderBy(orderName, descending: true)
|
||||
.snapshots();
|
||||
return snapshots;
|
||||
}
|
||||
|
||||
Stream<QuerySnapshot> getDeliverySnapshot(String path, String type,
|
||||
DateTime startDate, DateTime endDate, String orderName) {
|
||||
log.info("getDeliverySnapshot Path: $path");
|
||||
Firestore.instance
|
||||
.collection(path)
|
||||
.where(type, isGreaterThanOrEqualTo: startDate)
|
||||
.where(type, isLessThanOrEqualTo: endDate)
|
||||
.where("in_delivery", isEqualTo: true)
|
||||
.orderBy(type, descending: true)
|
||||
.orderBy(orderName, descending: true)
|
||||
.limit(1)
|
||||
.getDocuments()
|
||||
.then((s) {});
|
||||
|
||||
Stream<QuerySnapshot> snapshots = Firestore.instance
|
||||
.collection(path)
|
||||
.where(type, isGreaterThanOrEqualTo: startDate)
|
||||
.where(type, isLessThanOrEqualTo: endDate)
|
||||
.where("in_delivery", isEqualTo: true)
|
||||
.orderBy(type, descending: true)
|
||||
.orderBy(orderName, descending: true)
|
||||
.snapshots();
|
||||
return snapshots;
|
||||
}
|
||||
|
||||
Stream<QuerySnapshot> getFilterDataSnapshot(String path, String status,
|
||||
String type, DateTime startDate, DateTime endDate, String orderName) {
|
||||
log.info("getFilterDateSnapshot Path: $path");
|
||||
Stream<QuerySnapshot> snapshots = Firestore.instance
|
||||
.collection(path)
|
||||
.where('status', isEqualTo: status)
|
||||
.where(type, isGreaterThanOrEqualTo: startDate)
|
||||
.where(type, isLessThanOrEqualTo: endDate)
|
||||
.orderBy(type, descending: true)
|
||||
.orderBy(orderName, descending: true)
|
||||
.snapshots();
|
||||
return snapshots;
|
||||
}
|
||||
|
||||
Stream<QuerySnapshot> getDeliveryDataSnapshot(String path, String status,
|
||||
String type, DateTime startDate, DateTime endDate, String orderName) {
|
||||
log.info("getDeliveryDataSnapshot Path: $path");
|
||||
Stream<QuerySnapshot> snapshots = Firestore.instance
|
||||
.collection(path)
|
||||
.where('status', isEqualTo: status)
|
||||
.where("in_delivery", isEqualTo: true)
|
||||
.where(type, isGreaterThanOrEqualTo: startDate)
|
||||
.where(type, isLessThanOrEqualTo: endDate)
|
||||
.orderBy(type, descending: true)
|
||||
.orderBy(orderName, descending: true)
|
||||
.snapshots();
|
||||
return snapshots;
|
||||
}
|
||||
|
||||
Stream<QuerySnapshot> getsearchBuyerSnapshot(String path, String buyer) {
|
||||
log.info("getFilterDateSnapshot Path: $path");
|
||||
Stream<QuerySnapshot> snapshots = Firestore.instance
|
||||
.collection(path)
|
||||
.where("user_name", isEqualTo: buyer)
|
||||
.snapshots();
|
||||
return snapshots;
|
||||
}
|
||||
|
||||
Stream<DocumentSnapshot> getDocSnapshot(String path, String id) {
|
||||
log.info("getDocSnapshot Path: $path, ID: $id");
|
||||
Stream<DocumentSnapshot> snapshot =
|
||||
Firestore.instance.collection(path).document(id).snapshots();
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
Stream<QuerySnapshot> getQuerySnapshotF(String path, accountID) {
|
||||
log.info("getQuerySnapshot Path: $path");
|
||||
Stream<QuerySnapshot> snapshots = Firestore.instance
|
||||
.collection(path)
|
||||
.where("account_id", isEqualTo: accountID)
|
||||
.snapshots();
|
||||
return snapshots;
|
||||
}
|
||||
|
||||
Stream<QuerySnapshot> getFilterDateSnapshotF(String path, String accountID,
|
||||
String type, DateTime startDate, DateTime endDate, String orderName) {
|
||||
log.info("getFilterDateSnapshot Path: $path");
|
||||
Stream<QuerySnapshot> snapshots = Firestore.instance
|
||||
.collection(path)
|
||||
.where("account_id", isEqualTo: accountID)
|
||||
.where(type, isGreaterThanOrEqualTo: startDate)
|
||||
.where(type, isLessThanOrEqualTo: endDate)
|
||||
.orderBy(orderName, descending: true)
|
||||
.snapshots();
|
||||
return snapshots;
|
||||
}
|
||||
|
||||
Future<QuerySnapshot> getSnapshot(String path) {
|
||||
log.info("getSnapshot Path: $path");
|
||||
Future<QuerySnapshot> snapshots =
|
||||
Firestore.instance.collection(path).getDocuments();
|
||||
|
||||
return snapshots;
|
||||
}
|
||||
|
||||
Future<DocumentSnapshot> getDocSnap(String path, String id) {
|
||||
log.info("getDocSnap Path: $path");
|
||||
return Firestore.instance.collection(path).document(id).get();
|
||||
}
|
||||
|
||||
Future<String> uploadStorage(String path, File file, {String fileName}) async {
|
||||
if (fileName == null) {
|
||||
fileName = Uuid().v4();
|
||||
}
|
||||
StorageReference storageReference =
|
||||
FirebaseStorage.instance.ref().child('$path/$fileName');
|
||||
StorageUploadTask uploadTask = storageReference.putFile(file);
|
||||
await uploadTask.onComplete;
|
||||
String downloadUrl = await storageReference.getDownloadURL();
|
||||
print("name:${await storageReference.getName()}");
|
||||
print("bucket:${await storageReference.getBucket()}");
|
||||
print("path:${await storageReference.getPath()}");
|
||||
print("meta:${await storageReference.getMetadata()}");
|
||||
return downloadUrl;
|
||||
}
|
||||
|
||||
Future<String> uploadStorageData(String path, Uint8List data,
|
||||
{String fileName}) async {
|
||||
if (fileName == null) {
|
||||
fileName = Uuid().v4();
|
||||
}
|
||||
StorageReference storageReference =
|
||||
FirebaseStorage.instance.ref().child('$path/$fileName');
|
||||
StorageUploadTask uploadTask = storageReference.putData(data);
|
||||
await uploadTask.onComplete;
|
||||
String downloadUrl = await storageReference.getDownloadURL();
|
||||
return downloadUrl;
|
||||
}
|
||||
|
||||
Future<void> deleteStorage(String path, name) async {
|
||||
try {
|
||||
StorageReference storageReference =
|
||||
FirebaseStorage.instance.ref().child('$path/$name');
|
||||
await storageReference.delete();
|
||||
} catch (e) {
|
||||
log.warning("deleteStorage:$e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteStorageFromUrl(String url) async {
|
||||
try {
|
||||
StorageReference storageReference =
|
||||
await FirebaseStorage.instance.getReferenceFromUrl(url);
|
||||
await storageReference.delete();
|
||||
} catch (e) {
|
||||
log.warning("deleteStorage:$e");
|
||||
}
|
||||
}
|
||||
45
lib/model/language_model.dart
Normal file
45
lib/model/language_model.dart
Normal file
@@ -0,0 +1,45 @@
|
||||
import 'package:flutter/painting.dart';
|
||||
import 'package:fcs/model/base_model.dart';
|
||||
import 'package:fcs/model/shared_pref.dart';
|
||||
import 'package:fcs/vo/setting.dart';
|
||||
import 'package:fcs/widget/localization/transalation.dart';
|
||||
|
||||
class LanguageModel extends BaseModel {
|
||||
String language;
|
||||
bool isEng = true;
|
||||
static final List<String> languageCodesList =
|
||||
Translation().supportedLanguagesCodes;
|
||||
static final List<String> languagesList = Translation().supportedLanguages;
|
||||
|
||||
final Map<dynamic, dynamic> languagesMap = {
|
||||
languagesList[0]: languageCodesList[0],
|
||||
languagesList[1]: languageCodesList[1],
|
||||
};
|
||||
|
||||
void initSetting(Setting setting) async {
|
||||
this.language = await load();
|
||||
this.isEng = this.language == "English";
|
||||
Translation().onLocaleChanged(Locale(languagesMap[language]));
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
logout() async {
|
||||
}
|
||||
|
||||
Future<String> load() async {
|
||||
var data =await SharedPref.getLang();
|
||||
if (data == null) return languagesList[1];
|
||||
return data;
|
||||
}
|
||||
|
||||
void saveLanguage(String language) async {
|
||||
Translation().onLocaleChanged(Locale(languagesMap[language]));
|
||||
|
||||
SharedPref.saveLang(language);
|
||||
this.language = language;
|
||||
this.isEng = this.language == "English";
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
59
lib/model/log_model.dart
Normal file
59
lib/model/log_model.dart
Normal file
@@ -0,0 +1,59 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:fcs/vo/document_log.dart';
|
||||
import 'package:fcs/vo/log.dart';
|
||||
|
||||
import 'base_model.dart';
|
||||
import 'constants.dart';
|
||||
|
||||
class LogModel extends BaseModel {
|
||||
List<Log> logs = [];
|
||||
List<DocLog> docLogs = [];
|
||||
|
||||
void initUser(user) {
|
||||
super.initUser(user);
|
||||
_loadLogs();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
logout() async {
|
||||
logs = [];
|
||||
docLogs=[];
|
||||
}
|
||||
Future<void> _loadLogs() async {
|
||||
Stream<QuerySnapshot> snapshots = Firestore.instance
|
||||
.collection(
|
||||
"/$biz_collection/${setting.okEnergyId}/$user_collection/${user.docID}/$log_collection")
|
||||
.orderBy("active_time", descending: true)
|
||||
.limit(30)
|
||||
.snapshots();
|
||||
|
||||
snapshots.listen((snaps) async {
|
||||
logs = snaps.documents
|
||||
.map((documentSnapshot) =>
|
||||
Log.fromMap(documentSnapshot.data, documentSnapshot.documentID))
|
||||
.toList();
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> loadDocLogs(String docID) async {
|
||||
Stream<QuerySnapshot> snapshots = Firestore.instance
|
||||
.collection("/$biz_collection/${setting.okEnergyId}/$log_collection")
|
||||
.where('doc_id', isEqualTo: docID)
|
||||
.orderBy('date', descending: true)
|
||||
.limit(30)
|
||||
.snapshots();
|
||||
|
||||
snapshots.listen((snaps) async {
|
||||
docLogs.clear();
|
||||
docLogs = snaps.documents
|
||||
.map((documentSnapshot) => DocLog.fromMap(
|
||||
documentSnapshot.data, documentSnapshot.documentID))
|
||||
.toList();
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
}
|
||||
450
lib/model/main_model.dart
Normal file
450
lib/model/main_model.dart
Normal file
@@ -0,0 +1,450 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:device_info/device_info.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:package_info/package_info.dart';
|
||||
import 'package:path/path.dart' as Path;
|
||||
import 'package:fcs/model/shared_pref.dart';
|
||||
import 'package:fcs/util.dart';
|
||||
import 'package:fcs/vo/bank_account.dart';
|
||||
import 'package:fcs/vo/buyer.dart';
|
||||
import 'package:fcs/vo/setting.dart';
|
||||
import 'package:fcs/widget/NetworkConnectivity.dart';
|
||||
|
||||
import '../config.dart';
|
||||
import '../vo/status.dart';
|
||||
import '../vo/user.dart';
|
||||
import 'api_helper.dart';
|
||||
import 'base_model.dart';
|
||||
import 'constants.dart';
|
||||
import 'firebase_helper.dart';
|
||||
|
||||
class ImplementInterfaceModel {
|
||||
void initUser(User user) => {};
|
||||
void initSetting(Setting setting) => {};
|
||||
}
|
||||
|
||||
class MainModel extends ChangeNotifier {
|
||||
final log = Logger('MainModel');
|
||||
|
||||
final FirebaseAuth auth = FirebaseAuth.instance;
|
||||
FirebaseMessaging firebaseMessaging;
|
||||
|
||||
List<BaseModel> models = [];
|
||||
User user;
|
||||
Buyer buyer;
|
||||
FirebaseUser firebaseUser;
|
||||
StreamSubscription<DocumentSnapshot> userListener;
|
||||
StreamSubscription<DocumentSnapshot> buyerListener;
|
||||
bool pinRequired;
|
||||
Timer pinTimer;
|
||||
|
||||
Setting setting;
|
||||
PackageInfo packageInfo;
|
||||
bool isLoaded = true;
|
||||
bool isOnline = true;
|
||||
|
||||
static const PIN_TIME_MIN = 10;
|
||||
|
||||
MainModel() {
|
||||
// NetworkConnectivity.instance.statusStream.listen((data) {
|
||||
// bool _isOnline = data["isOnline"];
|
||||
// if (_isOnline && !this.isOnline) {
|
||||
// init();
|
||||
// }
|
||||
// this.isOnline = _isOnline;
|
||||
// notifyListeners();
|
||||
// });
|
||||
}
|
||||
|
||||
resetPinTimer() {
|
||||
if (pinTimer != null && pinTimer.isActive) {
|
||||
pinTimer.cancel();
|
||||
}
|
||||
pinRequired = false;
|
||||
pinTimer = Timer(Duration(minutes: PIN_TIME_MIN), () {
|
||||
pinRequired = true;
|
||||
});
|
||||
}
|
||||
|
||||
bool isLogin() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hasEmail() {
|
||||
return this.user != null && this.user.isEmail();
|
||||
}
|
||||
|
||||
bool agreedTerm() {
|
||||
return this.user != null && this.user.agreeTerms;
|
||||
}
|
||||
|
||||
bool isBuyer() {
|
||||
return this.user == null || this.user.isBuyer();
|
||||
}
|
||||
|
||||
bool isRegBuyer() {
|
||||
return isBuyer() && buyer != null;
|
||||
}
|
||||
|
||||
bool isApprovedBuyer() {
|
||||
return isBuyer() && buyer != null && buyer.isApproved();
|
||||
}
|
||||
|
||||
bool isSysAdmin() {
|
||||
return this.user != null && this.user.isSysAdmin();
|
||||
}
|
||||
|
||||
bool isSysSupport() {
|
||||
return this.user != null && this.user.isSysSupport();
|
||||
}
|
||||
|
||||
bool isBizAdmin() {
|
||||
return this.user != null && this.user.isBizAdmin();
|
||||
}
|
||||
|
||||
bool isOwnerAndAbove() {
|
||||
return this.user != null && this.user.isOwnerAndAbove();
|
||||
}
|
||||
|
||||
bool isAdmin() {
|
||||
return this.user != null && this.user.hasAdmin();
|
||||
}
|
||||
|
||||
bool showHistoryBtn() {
|
||||
return isSysAdmin() || isSysSupport() || isBizAdmin();
|
||||
}
|
||||
|
||||
init() async {
|
||||
// await _loadSetting();
|
||||
// _loadUser();
|
||||
// resetPinTimer();
|
||||
}
|
||||
|
||||
void addModel(BaseModel model) {
|
||||
models.add(model);
|
||||
model.mainModel = this;
|
||||
}
|
||||
|
||||
void _initUser(User user) {
|
||||
models.forEach((m) => m.initUser(user));
|
||||
|
||||
if (firebaseMessaging != null) {
|
||||
firebaseMessaging.subscribeToTopic(user.docID);
|
||||
}
|
||||
}
|
||||
|
||||
void _initSetting(Setting setting) {
|
||||
models.forEach((m) => m.initSetting(setting));
|
||||
}
|
||||
|
||||
Future<void> _loadSetting() async {
|
||||
this.setting = await _getSetting();
|
||||
this.packageInfo = await PackageInfo.fromPlatform();
|
||||
_initSetting(setting);
|
||||
}
|
||||
|
||||
void _loadUser() async {
|
||||
this.firebaseUser = await auth.currentUser();
|
||||
if (this.firebaseUser == null) {
|
||||
this.isLoaded = true;
|
||||
notifyListeners();
|
||||
return;
|
||||
}
|
||||
|
||||
_logUser(this.firebaseUser);
|
||||
|
||||
// load from local, if successful,notify listeners
|
||||
User _user = await SharedPref.getUser();
|
||||
if (_user != null) {
|
||||
await _user.setFirebaseUser(this.firebaseUser);
|
||||
_initUser(_user);
|
||||
this.user = _user;
|
||||
|
||||
if (this.user.isRegisteredBuyer()) {
|
||||
_loadBuyer();
|
||||
}
|
||||
this.isLoaded = true;
|
||||
notifyListeners();
|
||||
log.info("user loaded from shared pref!");
|
||||
}
|
||||
|
||||
_listenUser();
|
||||
}
|
||||
|
||||
void _listenUser() {
|
||||
if (this.userListener != null) {
|
||||
this.userListener.cancel();
|
||||
}
|
||||
|
||||
this.userListener = getDocSnapshot(
|
||||
"/$biz_collection/${setting.okEnergyId}/$user_collection",
|
||||
firebaseUser.uid)
|
||||
.listen((userSnap) async {
|
||||
if (userSnap.exists) {
|
||||
User _user = User.fromMap(userSnap.data, userSnap.documentID);
|
||||
|
||||
// load claims
|
||||
try {
|
||||
FirebaseUser _firebaseUser = await getProfile(this.firebaseUser);
|
||||
|
||||
await _user.setFirebaseUser(_firebaseUser);
|
||||
_initUser(_user);
|
||||
this.user = _user;
|
||||
this.firebaseUser = _firebaseUser;
|
||||
await SharedPref.saveUser(this.user);
|
||||
} catch (e) {
|
||||
log.warning(e.toString());
|
||||
}
|
||||
|
||||
log.info(
|
||||
"_loadUser => ID: ${this.user.docID}, AccountID: ${this.user.accountID},"
|
||||
"BizID: ${this.user.accountID},"
|
||||
", Privileges: ${this.user.claimPrivileges}, isSysAdmin: ${this.user.isSysAdmin()}");
|
||||
|
||||
if (this.user.isRegisteredBuyer()) {
|
||||
_loadBuyer();
|
||||
}
|
||||
this.isLoaded = true;
|
||||
notifyListeners();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _loadBuyer() async {
|
||||
if (this.user == null) return;
|
||||
if (buyerListener != null) buyerListener.cancel();
|
||||
buyerListener = getDocSnapshot(
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection",
|
||||
this.user.docID)
|
||||
.listen((buyerSnap) async {
|
||||
if (buyerSnap.exists) {
|
||||
this.buyer = Buyer.fromMap(buyerSnap.data, buyerSnap.documentID);
|
||||
} else {
|
||||
this.buyer = null;
|
||||
}
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// super.dispose();
|
||||
// if (this.userListener != null) {
|
||||
// this.userListener.cancel();
|
||||
// }
|
||||
// SharedPref.removeUser();
|
||||
// this.user = User();
|
||||
}
|
||||
|
||||
Future<void> login(String phoneNumber, String pass) async {
|
||||
var id = phoneNumber.replaceFirst("+", "");
|
||||
id = updatePhoneNumber(id);
|
||||
|
||||
var data = {"id": id, "password": pass};
|
||||
var result = await requestAPI("/login", "POST", payload: data);
|
||||
|
||||
var token = result["Token"];
|
||||
|
||||
// login with custom token
|
||||
AuthResult r = await this.auth.signInWithCustomToken(token: token);
|
||||
this.firebaseUser = r.user;
|
||||
isLoaded = false;
|
||||
_loadUser();
|
||||
_logUser(this.firebaseUser);
|
||||
}
|
||||
|
||||
Future<FirebaseUser> getProfile(FirebaseUser firebaseUser) async {
|
||||
IdTokenResult idtoken = await firebaseUser.getIdToken();
|
||||
var data = await requestAPI(
|
||||
"/profile",
|
||||
"GET",
|
||||
token: idtoken.token,
|
||||
);
|
||||
var _token = data["Token"];
|
||||
AuthResult a = await this.auth.signInWithCustomToken(token: _token);
|
||||
return a.user;
|
||||
}
|
||||
|
||||
Future<void> _logUser(FirebaseUser firebaseUser) async {
|
||||
IdTokenResult idtoken = await firebaseUser.getIdToken();
|
||||
|
||||
await requestAPI(
|
||||
"/log",
|
||||
"GET",
|
||||
token: idtoken.token,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> logout() async {
|
||||
if (this.userListener != null) {
|
||||
await this.userListener.cancel();
|
||||
}
|
||||
|
||||
await auth.signOut();
|
||||
this.user = null;
|
||||
this.buyer = null;
|
||||
this.firebaseUser = null;
|
||||
await SharedPref.removeUser();
|
||||
if (firebaseMessaging != null) {
|
||||
firebaseMessaging.unsubscribeFromTopic(user.docID);
|
||||
}
|
||||
|
||||
// logout models
|
||||
models.forEach((m) => m.logout());
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> signup(
|
||||
String name, password, confirmPassword, phoneNumber) async {
|
||||
if (password == "" || password.length < 6) {
|
||||
throw Exception("Password must be at least 6 characters");
|
||||
}
|
||||
if (password != confirmPassword) {
|
||||
throw Exception("Password mismatch");
|
||||
}
|
||||
var id = phoneNumber.replaceFirst("+", "");
|
||||
id = updatePhoneNumber(id);
|
||||
|
||||
var inputData = {"id": id, "password": password, "user_name": name};
|
||||
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
|
||||
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
|
||||
String deviceName = "${androidInfo.model}(${androidInfo.id})";
|
||||
|
||||
var url = "${Config.instance.apiURL}/signup";
|
||||
Response response = await Dio().post(url,
|
||||
data: inputData,
|
||||
options: Options(
|
||||
headers: {"Device": androidInfo.androidId + ":" + deviceName}));
|
||||
|
||||
var data = Status.fromJson(response.data);
|
||||
if (data.status != 'Ok') {
|
||||
throw Exception("${data.errorCode} : ${data.message}");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> confirmSignup(
|
||||
String phoneNumber, password, confirmSMSCode) async {
|
||||
var id = phoneNumber.replaceFirst("+", "");
|
||||
id = updatePhoneNumber(id);
|
||||
|
||||
if (confirmSMSCode == "" || confirmSMSCode.length != 6) {
|
||||
throw Exception("Password must be 6 characters");
|
||||
}
|
||||
|
||||
var inputData = {
|
||||
"id": id,
|
||||
"password": password,
|
||||
"confirmation_code": confirmSMSCode
|
||||
};
|
||||
var url = "${Config.instance.apiURL}/confirm";
|
||||
Response response = await Dio().post(
|
||||
url,
|
||||
data: inputData,
|
||||
);
|
||||
var data = Status.fromJson(response.data);
|
||||
if (data.status != 'Ok') {
|
||||
throw Exception(data.message);
|
||||
}
|
||||
}
|
||||
|
||||
bool isSupport() {
|
||||
if (packageInfo == null || setting == null) return false;
|
||||
return int.parse(packageInfo.buildNumber) >= setting.supportBuildNum;
|
||||
}
|
||||
|
||||
Future<Setting> _getSetting() async {
|
||||
var snap = await Firestore.instance
|
||||
.collection(config_collection)
|
||||
.document(setting_doc_id)
|
||||
.get();
|
||||
if (!snap.exists) {
|
||||
return null;
|
||||
}
|
||||
_listSetting();
|
||||
return Setting.fromMap(snap.data);
|
||||
}
|
||||
|
||||
void _listSetting() {
|
||||
getDocSnapshot("/configs", setting_doc_id).listen((snap) {
|
||||
this.setting = Setting.fromMap(snap.data);
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> updateProfile(String name) async {
|
||||
await requestAPI("/user", "PUT",
|
||||
payload: {"user_name": name}, token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> updateTerms(String terms) async {
|
||||
await requestAPI("/terms", "PUT",
|
||||
payload: {"terms": terms}, token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> agreeTerms() async {
|
||||
await requestAPI("/user/agree", "PUT", token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> updateContact(Setting setting) async {
|
||||
await requestAPI("/contact", "PUT",
|
||||
payload: {
|
||||
'email': setting.email,
|
||||
'facebook_url': setting.facebook,
|
||||
'web_url': setting.website,
|
||||
'phones': setting.phones,
|
||||
'bank_account_info': setting.bankAccountInfo,
|
||||
'delivery_phone': setting.deliveryPhone,
|
||||
'address': setting.address,
|
||||
},
|
||||
token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> updateSetting(Setting setting) async {
|
||||
await requestAPI("/setting", "PUT",
|
||||
payload: {
|
||||
'do_expire_hours': setting.doExpireInHours,
|
||||
'po_expire_hours': setting.poExpireInHours,
|
||||
'po_open_at': setting.poOpenAt,
|
||||
'po_close_at': setting.poCloseAt,
|
||||
'po_close_on': setting.poCloseOn,
|
||||
'first_storage_charge_in': setting.firstStorageChargeIn,
|
||||
'first_storage_charge': setting.firstStorageCharge,
|
||||
'second_storage_charge_in': setting.secondStorageChargeIn,
|
||||
'second_storage_charge': setting.secondStorageCharge,
|
||||
'latest_delivery_days': setting.latestDeliveryDay,
|
||||
},
|
||||
token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> addBankAccount(BankAccount bankAccount, File image) async {
|
||||
String url = await uploadStorage(bank_images_path, image);
|
||||
bankAccount.bankLogo = url;
|
||||
|
||||
await requestAPI("/bank_accounts", "POST",
|
||||
payload: bankAccount.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> updateBankAccount(BankAccount bankAccount, File image) async {
|
||||
if (image != null) {
|
||||
String url = await uploadStorage(bank_images_path, image);
|
||||
bankAccount.bankLogo = url;
|
||||
}
|
||||
|
||||
await requestAPI("/bank_accounts", "PUT",
|
||||
payload: bankAccount.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> deleteBankAccount(BankAccount bankAccount) async {
|
||||
await requestAPI("/bank_accounts", "DELETE",
|
||||
payload: bankAccount.toMap(), token: await getToken());
|
||||
}
|
||||
}
|
||||
234
lib/model/manual_model.dart
Normal file
234
lib/model/manual_model.dart
Normal file
@@ -0,0 +1,234 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:archive/archive_io.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:fcs/model/firebase_helper.dart';
|
||||
import 'package:fcs/vo/manual.dart';
|
||||
import 'package:fcs/vo/setting.dart';
|
||||
import 'package:path/path.dart' as Path;
|
||||
|
||||
import 'base_model.dart';
|
||||
|
||||
typedef void SlideDataCallback();
|
||||
|
||||
class ManualModel extends BaseModel {
|
||||
final log = Logger('ManualModel');
|
||||
|
||||
List<ManualItem> helps = [];
|
||||
List<ManualItem> manuals = [];
|
||||
String version;
|
||||
SlideDataCallback slideDataCallback;
|
||||
List deleteImage = [];
|
||||
|
||||
String dataDir;
|
||||
|
||||
void initSetting(Setting setting) async {
|
||||
_download(setting);
|
||||
super.initSetting(setting);
|
||||
}
|
||||
|
||||
@override
|
||||
logout() async {}
|
||||
|
||||
Future<void> _download(Setting setting) async {
|
||||
this.dataDir = (await getApplicationDocumentsDirectory()).path;
|
||||
version = setting.helpVersion;
|
||||
var file = File('$dataDir/${setting.helpFileName()}');
|
||||
if (await file.exists()) {
|
||||
_loadJsonData();
|
||||
return;
|
||||
}
|
||||
|
||||
String url = setting.helpURL;
|
||||
var req = await http.Client().get(Uri.parse(url));
|
||||
|
||||
File zippedFile = await file.writeAsBytes(req.bodyBytes);
|
||||
File prev = File('$dataDir/manual');
|
||||
if (await prev.exists()) {
|
||||
await prev.delete(recursive: true);
|
||||
}
|
||||
|
||||
var bytes = zippedFile.readAsBytesSync();
|
||||
var archive = ZipDecoder().decodeBytes(bytes);
|
||||
for (var file in archive) {
|
||||
var fileName = '$dataDir/manual/${file.name}';
|
||||
if (file.isFile) {
|
||||
var outFile = File(fileName);
|
||||
outFile = await outFile.create(recursive: true);
|
||||
await outFile.writeAsBytes(file.content);
|
||||
}
|
||||
}
|
||||
_loadJsonData();
|
||||
}
|
||||
|
||||
List<ManualItem> getHelpList(bool isBuyer) {
|
||||
return helps.where((h) => isBuyer ? h.isBuyer : true).toList();
|
||||
}
|
||||
|
||||
getSlideList(int manIndex) {
|
||||
var slides = helps[manIndex].slides;
|
||||
return slides;
|
||||
}
|
||||
|
||||
getSlideData(int manIndex, int slideIndex) {
|
||||
var slide;
|
||||
slide = helps[manIndex].slides[slideIndex];
|
||||
return slide;
|
||||
}
|
||||
|
||||
Future<void> _loadJsonData() async {
|
||||
try {
|
||||
final directory = await getApplicationDocumentsDirectory();
|
||||
File file = File('${directory.path}/manual/manual.json');
|
||||
String contents = await file.readAsString();
|
||||
|
||||
var convertArray = jsonDecode(contents);
|
||||
manuals.clear();
|
||||
convertArray.forEach((item) {
|
||||
var _list = ManualItem.fromMap(item);
|
||||
manuals.add(_list);
|
||||
});
|
||||
} catch (e) {
|
||||
log.warning("Error:${e.toString()}");
|
||||
}
|
||||
helps.clear();
|
||||
helps = manuals.map((e) => ManualItem.clone(e)).toList();
|
||||
}
|
||||
|
||||
addManualTitle(ManualItem manualItem) {
|
||||
helps.add(manualItem);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
uploadStorageManualData(String version, String dir) async {
|
||||
String fileName = 'help-v$version.zip';
|
||||
|
||||
var converthelps = [];
|
||||
for (final converthelp in helps) {
|
||||
converthelps.add(converthelp.toJson());
|
||||
}
|
||||
var json = jsonEncode(converthelps);
|
||||
|
||||
Directory myDir = new Directory('$dir/manual/img');
|
||||
List _images;
|
||||
_images = myDir.listSync(recursive: true, followLinks: false);
|
||||
|
||||
var newImgData = await convertArchiveImgFile(_images, dir, json);
|
||||
File updateImgFile = File('$dir/manual/update');
|
||||
updateImgFile.writeAsBytesSync(newImgData);
|
||||
|
||||
var bytes = updateImgFile.readAsBytesSync();
|
||||
uploadDataZip(bytes, fileName);
|
||||
}
|
||||
|
||||
convertArchiveImgFile(List imgList, String dataDir, json) async {
|
||||
File file = new File('$dataDir/update');
|
||||
if (await file.exists()) {
|
||||
await file.delete(recursive: true);
|
||||
}
|
||||
|
||||
Archive zipArchive = new Archive();
|
||||
List<int> utf8encoded = utf8.encode(json);
|
||||
ArchiveFile jsonFile =
|
||||
new ArchiveFile("manual.json", utf8encoded.length, utf8encoded);
|
||||
zipArchive.addFile(jsonFile);
|
||||
|
||||
for (var img in imgList) {
|
||||
String basename = Path.basename(img.path);
|
||||
if (deleteImage.length != 0) {
|
||||
for (var dImgName in deleteImage) {
|
||||
if (dImgName != basename) {
|
||||
Uint8List bytesPhoto = img.readAsBytesSync() as Uint8List;
|
||||
ArchiveFile jsonFile =
|
||||
new ArchiveFile("img/$basename", bytesPhoto.length, bytesPhoto);
|
||||
zipArchive.addFile(jsonFile);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Uint8List bytesPhoto = img.readAsBytesSync() as Uint8List;
|
||||
ArchiveFile jsonFile =
|
||||
new ArchiveFile("img/$basename", bytesPhoto.length, bytesPhoto);
|
||||
zipArchive.addFile(jsonFile);
|
||||
}
|
||||
}
|
||||
List<int> zipInBytes = new ZipEncoder().encode(zipArchive);
|
||||
file.writeAsBytesSync(zipInBytes);
|
||||
var bytes = file.readAsBytesSync();
|
||||
return bytes;
|
||||
}
|
||||
|
||||
uploadDataZip(Uint8List data, String fileName) async {
|
||||
String path = '/ok/img';
|
||||
String url = await uploadStorageData(path, data, fileName: fileName);
|
||||
}
|
||||
|
||||
resetManualItems() {
|
||||
helps.clear();
|
||||
//clone manauals
|
||||
helps = manuals.map((p) => ManualItem.clone(p)).toList();
|
||||
// return helps.where((h) => isBuyer ? h.isBuyer : true).toList();
|
||||
}
|
||||
|
||||
saveInstruction(int manIndex, int slideIndex, int instIndex,
|
||||
Instruction instruction, Instruction oldInst, bool isEng) {
|
||||
if (isEng) {
|
||||
var inst = helps[manIndex].slides[slideIndex].instructions.toList();
|
||||
instruction.id = oldInst.id;
|
||||
if (inst.length != 0) {
|
||||
helps[manIndex].slides[slideIndex].instructions.remove(oldInst);
|
||||
helps[manIndex]
|
||||
.slides[slideIndex]
|
||||
.instructions
|
||||
.insert(instIndex, instruction);
|
||||
} else {
|
||||
helps[manIndex].slides[slideIndex].instructions.add(instruction);
|
||||
}
|
||||
} else {
|
||||
var inst = helps[manIndex].slides[slideIndex].instructionsmm.toList();
|
||||
instruction.id = oldInst.id;
|
||||
if (inst.length != 0) {
|
||||
helps[manIndex].slides[slideIndex].instructionsmm.remove(oldInst);
|
||||
helps[manIndex]
|
||||
.slides[slideIndex]
|
||||
.instructionsmm
|
||||
.insert(instIndex, instruction);
|
||||
} else {
|
||||
helps[manIndex].slides[slideIndex].instructionsmm.add(instruction);
|
||||
}
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
saveSlideData(int manIndex, int slideIndex, SlideData slideData) {
|
||||
helps[manIndex].slides.add(slideData);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
changeSlideImage(int manIndex, int slideIndex, SlideData slideData) {
|
||||
var oldSlide = helps[manIndex].slides[slideIndex];
|
||||
helps[manIndex].slides.remove(oldSlide);
|
||||
helps[manIndex].slides.insert(slideIndex, slideData);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
deleteSlideData(int manIndex, SlideData slideData) {
|
||||
String engImage = slideData.image;
|
||||
String mmImage = slideData.imagemm;
|
||||
deleteImage.add(mmImage);
|
||||
deleteImage.add(engImage);
|
||||
helps[manIndex].slides.remove(slideData);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
deleteManualItem(ManualItem item) {
|
||||
// if(helps.isEmpty){
|
||||
// helps = new List();
|
||||
// }
|
||||
helps.remove(item);
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
35
lib/model/messaging.dart
Normal file
35
lib/model/messaging.dart
Normal file
@@ -0,0 +1,35 @@
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:fcs/vo/user.dart';
|
||||
|
||||
class MessagingFCM {
|
||||
final log = Logger('MessagingFCM');
|
||||
|
||||
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
|
||||
|
||||
MessagingFCM(User user) {
|
||||
_firebaseMessaging.configure(
|
||||
onMessage: (Map<String, dynamic> message) async {
|
||||
log.info("onMessage: $message");
|
||||
},
|
||||
// onBackgroundMessage: backgroundMessageHandler,
|
||||
onLaunch: (Map<String, dynamic> message) async {
|
||||
log.info("onLaunch: $message");
|
||||
},
|
||||
onResume: (Map<String, dynamic> message) async {
|
||||
log.info("onResume: $message");
|
||||
},
|
||||
);
|
||||
_firebaseMessaging.requestNotificationPermissions(
|
||||
const IosNotificationSettings(
|
||||
sound: true, badge: true, alert: true, provisional: true));
|
||||
_firebaseMessaging.onIosSettingsRegistered
|
||||
.listen((IosNotificationSettings settings) {
|
||||
log.info("Settings registered: $settings");
|
||||
});
|
||||
_firebaseMessaging.getToken().then((String token) {
|
||||
log.info("Token:$token");
|
||||
});
|
||||
_firebaseMessaging.subscribeToTopic(user.docID);
|
||||
}
|
||||
}
|
||||
74
lib/model/notification_model.dart
Normal file
74
lib/model/notification_model.dart
Normal file
@@ -0,0 +1,74 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:fcs/vo/notification.dart';
|
||||
|
||||
import 'base_model.dart';
|
||||
import 'constants.dart';
|
||||
import 'firebase_helper.dart';
|
||||
|
||||
class NotificationModel extends BaseModel {
|
||||
int filer=0;
|
||||
List<Notification> notifications = [];
|
||||
|
||||
var filterValues = {1: "po", 2: "do", 3: "buyer"};
|
||||
List<Notification> get notis {
|
||||
return notifications
|
||||
.where((n) => filer == 0 || n.itemType == filterValues[filer])
|
||||
.toList();
|
||||
}
|
||||
|
||||
int unseen = 0;
|
||||
|
||||
void initUser(user) {
|
||||
super.initUser(user);
|
||||
_loadNotifications();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
logout() async {
|
||||
notifications = [];
|
||||
}
|
||||
|
||||
Future<void> _loadNotifications() async {
|
||||
Stream<QuerySnapshot> snapshots = Firestore.instance
|
||||
.collection(
|
||||
"/$biz_collection/${setting.okEnergyId}/$user_collection/${user.docID}/$notification_collection")
|
||||
.orderBy("time", descending: true)
|
||||
.limit(50)
|
||||
.snapshots();
|
||||
|
||||
snapshots.listen((snaps) async {
|
||||
notifications.clear();
|
||||
unseen = 0;
|
||||
// snaps.documentChanges.forEach((c) {
|
||||
// if (c.type == DocumentChangeType.added) {
|
||||
// FlutterRingtonePlayer.play(
|
||||
// android: AndroidSounds.notification,
|
||||
// ios: IosSounds.glass,
|
||||
// );
|
||||
// }
|
||||
// });
|
||||
snaps.documents.forEach((d) {
|
||||
var n = Notification.fromMap(d.data, d.documentID);
|
||||
if (!n.seen) unseen++;
|
||||
notifications.add(n);
|
||||
});
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
void filter(int filter) {
|
||||
this.filer = filter;
|
||||
}
|
||||
|
||||
Future<void> seen() async {
|
||||
await request("/notification/seen", "POST", token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> seenID(String id) async {
|
||||
await request("/notification/seen/${user.docID}/$id", "POST",
|
||||
token: await getToken());
|
||||
}
|
||||
}
|
||||
4
lib/model/pagination/paginator.dart
Normal file
4
lib/model/pagination/paginator.dart
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
class Listener {
|
||||
|
||||
}
|
||||
88
lib/model/pd_model.dart
Normal file
88
lib/model/pd_model.dart
Normal file
@@ -0,0 +1,88 @@
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:fcs/model/constants.dart';
|
||||
import 'package:fcs/vo/pd.dart';
|
||||
import 'package:fcs/vo/user.dart';
|
||||
|
||||
import 'base_model.dart';
|
||||
import 'firebase_helper.dart';
|
||||
|
||||
class PDModel extends BaseModel {
|
||||
final log = Logger('PDModel');
|
||||
|
||||
List<PD> pds = [];
|
||||
int dateIndex = 0;
|
||||
DateTime selectedDate = DateTime.now();
|
||||
|
||||
void initUser(User user) async {
|
||||
super.initUser(user);
|
||||
loadPDs();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
logout() async {
|
||||
pds = [];
|
||||
}
|
||||
|
||||
loadPDs() {
|
||||
if (!user.isOwnerAndAbove() && !user.hasInventory()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$pds_collection";
|
||||
var startDate = new DateTime(
|
||||
selectedDate.year, selectedDate.month, selectedDate.day, 0, 0, 0);
|
||||
var endDate = new DateTime(
|
||||
selectedDate.year, selectedDate.month, selectedDate.day, 23, 59, 59);
|
||||
pds.clear();
|
||||
getFilterDateSnapshot(path, 'date', startDate, endDate, 'pd_number')
|
||||
.listen((QuerySnapshot snapshot) {
|
||||
pds = snapshot.documents.map((documentSnapshot) {
|
||||
var data =
|
||||
PD.fromMap(documentSnapshot.data, documentSnapshot.documentID);
|
||||
return data;
|
||||
}).toList();
|
||||
notifyListeners();
|
||||
}).onError((e) {
|
||||
log.warning("Error! $e");
|
||||
});
|
||||
} catch (e) {
|
||||
log.warning("Error!! $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<PD> loadPDLines(PD pd) async {
|
||||
var snaps = await getSnapshot(
|
||||
"/$biz_collection/${setting.okEnergyId}/$pds_collection/${pd.id}/$product_collection");
|
||||
pd.pdLines = snaps.documents.map((s) => PDLine.fromMap(s.data)).toList();
|
||||
return pd;
|
||||
}
|
||||
|
||||
Future<void> createPD(PD pd) async {
|
||||
await request("/pd", "POST",
|
||||
payload: pd.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
void filterDate(DateTime dateTime, int _dateIndex) {
|
||||
this.selectedDate = dateTime;
|
||||
this.dateIndex = _dateIndex;
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$pds_collection";
|
||||
var endDate =
|
||||
new DateTime(dateTime.year, dateTime.month, dateTime.day, 23, 59, 59);
|
||||
pds.clear();
|
||||
getFilterDateSnapshot(path, 'date', dateTime, endDate, 'pd_number').listen(
|
||||
(snaps) {
|
||||
pds = snaps.documents.map((documentSnapshot) {
|
||||
var data =
|
||||
PD.fromMap(documentSnapshot.data, documentSnapshot.documentID);
|
||||
return data;
|
||||
}).toList();
|
||||
notifyListeners();
|
||||
}, onError: (error) {
|
||||
log.warning("FIRESTORE ERROR>>$error");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
294
lib/model/po_model.dart
Normal file
294
lib/model/po_model.dart
Normal file
@@ -0,0 +1,294 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:path/path.dart' as Path;
|
||||
import 'package:fcs/model/constants.dart';
|
||||
import 'package:fcs/pages/po/po_files.dart';
|
||||
import 'package:fcs/vo/do.dart';
|
||||
import 'package:fcs/vo/po.dart';
|
||||
import 'package:fcs/vo/popup_menu.dart';
|
||||
|
||||
import 'base_model.dart';
|
||||
import 'constants.dart';
|
||||
import 'firebase_helper.dart';
|
||||
|
||||
class POSubmissionModel extends BaseModel {
|
||||
final log = Logger('POSubmissionModel');
|
||||
|
||||
StreamSubscription<QuerySnapshot> listener;
|
||||
|
||||
List<POSubmission> pos = [];
|
||||
List<POSubmission> approvedPOs = [];
|
||||
PopupMenu popupMenu = new PopupMenu(index: 0);
|
||||
int dateIndex = 0;
|
||||
DateTime selectedDate = DateTime.now();
|
||||
void initUser(user) async {
|
||||
super.initUser(user);
|
||||
_loadPOs();
|
||||
_loadApprovedPOs();
|
||||
}
|
||||
|
||||
@override
|
||||
logout() async {
|
||||
if (listener != null) await listener.cancel();
|
||||
pos = [];
|
||||
approvedPOs = [];
|
||||
}
|
||||
|
||||
Future<void> _loadPOs() async {
|
||||
String path;
|
||||
if (user.hasPO() || user.isOwnerAndAbove()) {
|
||||
path = "/$biz_collection/${setting.okEnergyId}/$pos_collection";
|
||||
}
|
||||
|
||||
if (user.isBuyer()) {
|
||||
path =
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$pos_collection";
|
||||
}
|
||||
var startDate = new DateTime(
|
||||
selectedDate.year, selectedDate.month, selectedDate.day, 0, 0, 0);
|
||||
var endDate = new DateTime(
|
||||
selectedDate.year, selectedDate.month, selectedDate.day, 23, 59, 59);
|
||||
listener =
|
||||
getFilterDateSnapshot(path, 'po_date', startDate, endDate, 'po_number')
|
||||
.listen((snaps) async {
|
||||
pos.clear();
|
||||
snaps.documents.forEach((d) {
|
||||
pos.add(POSubmission.fromMap(d.data, d.documentID));
|
||||
});
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _loadApprovedPOs() async {
|
||||
if (!user.isBuyer()) {
|
||||
return;
|
||||
}
|
||||
approvedPOs.clear();
|
||||
|
||||
String path =
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$pos_collection";
|
||||
var docs = await Firestore.instance
|
||||
.collection(path)
|
||||
.where("status", isEqualTo: po_approved_status)
|
||||
.orderBy("po_approved_date", descending: false)
|
||||
.limit(1)
|
||||
.getDocuments();
|
||||
|
||||
Firestore.instance
|
||||
.collection(path)
|
||||
.where("status", isEqualTo: po_approved_status)
|
||||
.orderBy("po_approved_date", descending: false)
|
||||
.limit(10)
|
||||
.snapshots(includeMetadataChanges: true)
|
||||
.listen((snaps) async {
|
||||
List<POSubmission> _approved = [];
|
||||
for (var d in snaps.documents) {
|
||||
if (d.metadata.isFromCache) continue;
|
||||
var po = POSubmission.fromMap(d.data, d.documentID);
|
||||
po.poLines = await loadPOLines(po.id);
|
||||
_approved.add(po);
|
||||
}
|
||||
approvedPOs.clear();
|
||||
approvedPOs.addAll(_approved);
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
Future<POSubmission> getPO(String id) async {
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$pos_collection";
|
||||
if (user.isBuyer()) {
|
||||
path =
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$pos_collection";
|
||||
}
|
||||
var poSnap = await getDocSnap(path, id);
|
||||
return POSubmission.fromMap(poSnap.data, poSnap.documentID);
|
||||
}
|
||||
|
||||
Future<List<POLine>> loadPOLines(String poID) async {
|
||||
String path =
|
||||
"/$biz_collection/${setting.okEnergyId}/$pos_collection/$poID/$po_product_collection";
|
||||
if (user.isBuyer()) {
|
||||
path =
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$pos_collection/$poID/$product_collection";
|
||||
}
|
||||
var snaps = await Firestore.instance.collection(path).getDocuments();
|
||||
List<POLine> poLines =
|
||||
snaps.documents.map((s) => POLine.fromMap(s.data)).toList();
|
||||
return poLines;
|
||||
}
|
||||
|
||||
Future<POSubmission> loadDOs(POSubmission po) async {
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$dos_collection";
|
||||
if (user.isBuyer()) {
|
||||
path =
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$dos_collection";
|
||||
}
|
||||
var snaps = await Firestore.instance
|
||||
.collection(path)
|
||||
.where("po_number", isEqualTo: po.poNumber)
|
||||
.orderBy('do_number', descending: true)
|
||||
.getDocuments();
|
||||
|
||||
po.dos = snaps.documents
|
||||
.map((s) => DOSubmission.fromMap(s.data, s.documentID))
|
||||
.toList();
|
||||
return po;
|
||||
}
|
||||
|
||||
Future<DOSubmission> loadDOLines(DOSubmission doSub) async {
|
||||
String path =
|
||||
"/$biz_collection/${setting.okEnergyId}/$dos_collection/${doSub.id}/$product_collection";
|
||||
if (user.isBuyer()) {
|
||||
path =
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$dos_collection/${doSub.id}/$product_collection";
|
||||
}
|
||||
var snaps = await getSnapshot(path);
|
||||
doSub.doLines = snaps.documents.map((s) => DOLine.fromMap(s.data)).toList();
|
||||
return doSub;
|
||||
}
|
||||
|
||||
Future<void> createPO(POSubmission po, List<File> files) async {
|
||||
if (files != null) {
|
||||
if (files.length > 5) throw Exception("Exceed number of file upload");
|
||||
po.poReceiptUrls = [];
|
||||
for (File f in files) {
|
||||
String path = Path.join(po_files_path, user.docID);
|
||||
String url = await uploadStorage(path, f);
|
||||
po.poReceiptUrls.add(url);
|
||||
}
|
||||
}
|
||||
|
||||
await request("/po", "POST", payload: po.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> updatePO(
|
||||
POSubmission po, List<File> files, List<String> deletedUrls) async {
|
||||
if (deletedUrls != null)
|
||||
for (String url in deletedUrls) {
|
||||
po.poReceiptUrls.remove(url);
|
||||
await deleteStorageFromUrl(url);
|
||||
}
|
||||
|
||||
if (files != null) {
|
||||
if (files.length + po.poReceiptUrls.length > 5)
|
||||
throw Exception("Exceed number of file upload");
|
||||
po.poReceiptUrls = po.poReceiptUrls == null ? [] : po.poReceiptUrls;
|
||||
for (File f in files) {
|
||||
String path = Path.join(po_files_path, user.docID);
|
||||
String url = await uploadStorage(path, f);
|
||||
po.poReceiptUrls.add(url);
|
||||
}
|
||||
}
|
||||
await request("/po", "PUT", payload: po.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> approvePO(POSubmission po) async {
|
||||
await request("/po/approved", "POST",
|
||||
payload: po.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> rejectPO(POSubmission po) async {
|
||||
await request("/po/rejected", "POST",
|
||||
payload: po.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> cancelPO(POSubmission po) async {
|
||||
await request("/po/canceled", "POST",
|
||||
payload: po.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
void filterData(
|
||||
String status, DateTime dateTime, int _selectedStatus, int _dateIndex) {
|
||||
pos.clear();
|
||||
var startDate =
|
||||
new DateTime(dateTime.year, dateTime.month, dateTime.day, 0, 0, 0);
|
||||
var endDate =
|
||||
new DateTime(dateTime.year, dateTime.month, dateTime.day, 23, 59, 59);
|
||||
|
||||
if (this.listener != null) {
|
||||
this.listener.cancel();
|
||||
}
|
||||
|
||||
this.popupMenu.index = _selectedStatus;
|
||||
this.dateIndex = _dateIndex;
|
||||
this.selectedDate = dateTime == null
|
||||
? new DateTime(
|
||||
selectedDate.year, selectedDate.month, selectedDate.day, 0, 0, 0)
|
||||
: dateTime;
|
||||
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$pos_collection";
|
||||
if (user.isBuyer()) {
|
||||
path =
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$pos_collection";
|
||||
}
|
||||
|
||||
if (status != null && dateTime == null) {
|
||||
this.listener = getFilterStatusSnapshot(path, status, 'po_number')
|
||||
.listen((snaps) async {
|
||||
pos.clear();
|
||||
snaps.documents.forEach((d) {
|
||||
pos.add(POSubmission.fromMap(d.data, d.documentID));
|
||||
});
|
||||
notifyListeners();
|
||||
});
|
||||
} else if (dateTime != null && status == null) {
|
||||
this.listener = getFilterDateSnapshot(
|
||||
path, 'po_date', startDate, endDate, 'po_number')
|
||||
.listen((snaps) async {
|
||||
pos.clear();
|
||||
snaps.documents.forEach((d) {
|
||||
pos.add(POSubmission.fromMap(d.data, d.documentID));
|
||||
});
|
||||
notifyListeners();
|
||||
});
|
||||
} else if (status != null && dateTime != null) {
|
||||
this.listener = getFilterDataSnapshot(
|
||||
path, status, 'po_date', startDate, endDate, 'po_number')
|
||||
.listen((snaps) {
|
||||
pos.clear();
|
||||
snaps.documents.forEach((d) {
|
||||
pos.add(POSubmission.fromMap(d.data, d.documentID));
|
||||
});
|
||||
notifyListeners();
|
||||
});
|
||||
} else {
|
||||
this.listener =
|
||||
getQuerySnapshotByOrder(path, 'po_number').listen((snaps) async {
|
||||
pos.clear();
|
||||
snaps.documents.forEach((d) {
|
||||
pos.add(POSubmission.fromMap(d.data, d.documentID));
|
||||
});
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<POSubmission>> getPOForRevenue(DateTime dateTime) async {
|
||||
List<POSubmission> pos = [];
|
||||
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$pos_collection";
|
||||
if (user.isBuyer()) {
|
||||
path =
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$pos_collection";
|
||||
}
|
||||
DateTime date = DateTime(dateTime.year, dateTime.month, dateTime.day);
|
||||
DateTime dateAddOne = date.add(Duration(days: 1));
|
||||
|
||||
QuerySnapshot snapshots = await Firestore.instance
|
||||
.collection(path)
|
||||
.where('status', whereIn: [po_approved_status, po_closed_status])
|
||||
.where("po_approved_date", isGreaterThanOrEqualTo: date)
|
||||
.where("po_approved_date", isLessThan: dateAddOne)
|
||||
.orderBy("po_approved_date")
|
||||
.orderBy("user_name")
|
||||
.limit(100)
|
||||
.getDocuments();
|
||||
snapshots.documents.forEach((d) {
|
||||
pos.add(POSubmission.fromMap(d.data, d.documentID));
|
||||
});
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
119
lib/model/product_model.dart
Normal file
119
lib/model/product_model.dart
Normal file
@@ -0,0 +1,119 @@
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:fcs/vo/product.dart';
|
||||
import 'package:fcs/vo/setting.dart';
|
||||
|
||||
import 'base_model.dart';
|
||||
import 'constants.dart';
|
||||
import 'firebase_helper.dart';
|
||||
|
||||
class ProductModel extends BaseModel {
|
||||
final log = Logger('ProductModel');
|
||||
|
||||
List<Product> products = [];
|
||||
List<Product> tempProducts = [];
|
||||
|
||||
List<ProductPrice> get getPrices {
|
||||
List<ProductPrice> productPrices = [];
|
||||
this.products.forEach((p) => productPrices.addAll(p.getPrices));
|
||||
productPrices.sort((p1, p2) => p1.compareTo(p2));
|
||||
return productPrices;
|
||||
}
|
||||
|
||||
String getProductName(String productID) {
|
||||
return products.firstWhere((p) => p.id == productID).name;
|
||||
}
|
||||
|
||||
Product getProduct(String productID) {
|
||||
return products.firstWhere((p) => p.id == productID);
|
||||
}
|
||||
|
||||
List<Product> get productsToEdit {
|
||||
// clone products
|
||||
tempProducts = products.map((p) => Product.clone(p)).toList();
|
||||
tempProducts.sort((p1, p2) => p1.displayOrder.compareTo(p2.displayOrder));
|
||||
// set old price with price
|
||||
tempProducts.forEach((p) {
|
||||
p.oldPirce = p.price;
|
||||
p.action = "update";
|
||||
});
|
||||
|
||||
return tempProducts;
|
||||
}
|
||||
|
||||
void saveProduct(Product product, String name, price, displayOrder, int color,
|
||||
bool isDisable) {
|
||||
if (product == null) {
|
||||
tempProducts.add(Product(
|
||||
action: "create",
|
||||
name: name,
|
||||
price: int.parse(price),
|
||||
color: color,
|
||||
displayOrder: int.parse(displayOrder),
|
||||
isDisable: isDisable));
|
||||
} else {
|
||||
Product _product = product;
|
||||
_product.name = name;
|
||||
_product.price = int.parse(price);
|
||||
_product.color = color;
|
||||
_product.displayOrder = int.parse(displayOrder);
|
||||
_product.isDisable = isDisable;
|
||||
if (_product.id == null) {
|
||||
_product.action = "create";
|
||||
} else {
|
||||
_product.action = "update";
|
||||
}
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void deleteProduct(Product product) {
|
||||
if (product == null) {
|
||||
return;
|
||||
}
|
||||
if (product.id == null) {
|
||||
tempProducts.remove(product);
|
||||
} else {
|
||||
Product _product = tempProducts.firstWhere((p) => p.id == product.id);
|
||||
_product.action = "delete";
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@override
|
||||
void initSetting(Setting setting) {
|
||||
super.initSetting(setting);
|
||||
|
||||
try {
|
||||
getQuerySnapshot(
|
||||
"/$biz_collection/${setting.okEnergyId}/$product_collection")
|
||||
.listen((QuerySnapshot snapshot) {
|
||||
products.clear();
|
||||
products = snapshot.documents.map((documentSnapshot) {
|
||||
var data = Product.fromMap(
|
||||
documentSnapshot.data, documentSnapshot.documentID);
|
||||
return data;
|
||||
}).toList();
|
||||
products.sort((p1, p2) => p1.displayOrder.compareTo(p2.displayOrder));
|
||||
notifyListeners();
|
||||
}).onError((e) {
|
||||
log.warning("Error! $e");
|
||||
});
|
||||
} catch (e) {
|
||||
log.warning("Error!! $e");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
logout() async {
|
||||
tempProducts = [];
|
||||
}
|
||||
|
||||
updateProducts(List<Product> products) async {
|
||||
var items = [];
|
||||
products.forEach((p) {
|
||||
if (p.action != null) items.add(p.toMap());
|
||||
});
|
||||
await request("/products", "PUT", payload: items, token: await getToken());
|
||||
}
|
||||
}
|
||||
86
lib/model/reg_model.dart
Normal file
86
lib/model/reg_model.dart
Normal file
@@ -0,0 +1,86 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:path/path.dart' as Path;
|
||||
import 'package:fcs/vo/buyer.dart';
|
||||
|
||||
import 'base_model.dart';
|
||||
import 'constants.dart';
|
||||
import 'firebase_helper.dart';
|
||||
|
||||
class Attachments {
|
||||
File nricFront, nricBack;
|
||||
}
|
||||
|
||||
class RegModel extends BaseModel {
|
||||
Buyer reg = Buyer();
|
||||
bool isLoaded = false;
|
||||
|
||||
StreamSubscription regListener;
|
||||
|
||||
void initUser(user) {
|
||||
super.initUser(user);
|
||||
if (user.isRegisteredBuyer()) {
|
||||
_loadReg();
|
||||
} else {
|
||||
reg = Buyer();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
logout() async {
|
||||
if (regListener != null) await regListener.cancel();
|
||||
reg = Buyer();
|
||||
}
|
||||
|
||||
Future<void> _loadReg() async {
|
||||
if (regListener != null) {
|
||||
regListener.cancel();
|
||||
}
|
||||
regListener = getDocSnapshot(
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection",
|
||||
"${user.docID}")
|
||||
.listen((snap) async {
|
||||
if (snap.exists) {
|
||||
reg = Buyer.fromMap(snap.data, snap.documentID);
|
||||
QuerySnapshot q = await getSnapshot(
|
||||
"/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$product_collection");
|
||||
reg.buyerProducts.clear();
|
||||
q.documents.forEach((d) {
|
||||
reg.buyerProducts.add(BuyerProduct.fromMap(d.data, d.documentID));
|
||||
});
|
||||
} else {
|
||||
reg = Buyer();
|
||||
}
|
||||
isLoaded = true;
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> register(Buyer buyer, Attachments attachments) async {
|
||||
String path = Path.join(reg_files_path, user.docID);
|
||||
String urlFront = await uploadStorage(path, attachments.nricFront);
|
||||
buyer.nricFrontUrl = urlFront;
|
||||
String urlBack = await uploadStorage(path, attachments.nricBack);
|
||||
buyer.nricBackUrl = urlBack;
|
||||
|
||||
await request("/reg", "POST",
|
||||
payload: buyer.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> update(Buyer buyer, Attachments attachments) async {
|
||||
String path = Path.join(reg_files_path, user.docID);
|
||||
if (attachments.nricFront != null) {
|
||||
String urlFront = await uploadStorage(path, attachments.nricFront);
|
||||
buyer.nricFrontUrl = urlFront;
|
||||
}
|
||||
if (attachments.nricBack != null) {
|
||||
String urlBack = await uploadStorage(path, attachments.nricBack);
|
||||
buyer.nricBackUrl = urlBack;
|
||||
}
|
||||
|
||||
await request("/buyer/update", "PUT",
|
||||
payload: buyer.toMap(), token: await getToken());
|
||||
}
|
||||
}
|
||||
700
lib/model/report_model.dart
Normal file
700
lib/model/report_model.dart
Normal file
@@ -0,0 +1,700 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:fcs/vo/report.dart';
|
||||
import 'package:fcs/vo/report_user.dart';
|
||||
import 'package:open_file/open_file.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:fcs/model/api_helper.dart' as api;
|
||||
import 'package:fcs/vo/report.dart';
|
||||
|
||||
import '../config.dart';
|
||||
import 'base_model.dart';
|
||||
import 'constants.dart';
|
||||
import 'firebase_helper.dart';
|
||||
import 'shared_pref.dart';
|
||||
|
||||
class ReportModel extends BaseModel {
|
||||
StreamSubscription<QuerySnapshot> listener;
|
||||
StreamSubscription<QuerySnapshot> listenerUser;
|
||||
|
||||
List<Report> reports = [];
|
||||
List<Report> userReports = [];
|
||||
List filterValue = [];
|
||||
|
||||
List<Report> get reportList {
|
||||
List<Report> _reports = [];
|
||||
if (user.isOwnerAndAbove() || user.hasAdmin()) {
|
||||
_reports = reports;
|
||||
} else {
|
||||
_reports.addAll(reports);
|
||||
userReports.forEach((r) {
|
||||
if (!_reports.contains(r)) {
|
||||
_reports.add(r);
|
||||
}
|
||||
});
|
||||
}
|
||||
_reports.sort((a, b) => a.display.compareTo(b.display));
|
||||
return _reports;
|
||||
}
|
||||
|
||||
void initUser(user) {
|
||||
super.initUser(user);
|
||||
reports = [];
|
||||
_loadReports();
|
||||
}
|
||||
|
||||
Future<void> _loadReports() async {
|
||||
if (listener != null) listener.cancel();
|
||||
if (listenerUser != null) listenerUser.cancel();
|
||||
|
||||
if (user.isOwnerAndAbove() || user.hasAdmin()) {
|
||||
listener = Firestore.instance
|
||||
.collection("/$reports_collection")
|
||||
.snapshots()
|
||||
.listen((snaps) async {
|
||||
reports.clear();
|
||||
reports = snaps.documents.map((documentSnapshot) {
|
||||
var report = Report.fromMap(
|
||||
documentSnapshot.data, documentSnapshot.documentID);
|
||||
return report;
|
||||
}).toList();
|
||||
notifyListeners();
|
||||
});
|
||||
} else {
|
||||
listener = Firestore.instance
|
||||
.collection("/$reports_collection")
|
||||
.where("for_all_users", isEqualTo: true)
|
||||
.snapshots()
|
||||
.listen((snaps) async {
|
||||
reports.clear();
|
||||
reports = snaps.documents.map((documentSnapshot) {
|
||||
var report = Report.fromMap(
|
||||
documentSnapshot.data, documentSnapshot.documentID);
|
||||
return report;
|
||||
}).toList();
|
||||
notifyListeners();
|
||||
});
|
||||
|
||||
listenerUser = Firestore.instance
|
||||
.collection("/$report_user_collection")
|
||||
.where("user_id", isEqualTo: user.docID)
|
||||
.snapshots()
|
||||
.listen((snaps) async {
|
||||
userReports.clear();
|
||||
userReports = snaps.documents.map((documentSnapshot) {
|
||||
var user = ReportUser.fromMap(
|
||||
documentSnapshot.data, documentSnapshot.documentID);
|
||||
var report = Report(id: user.reportID, display: user.reportName);
|
||||
return report;
|
||||
}).toList();
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@override
|
||||
void logout() {
|
||||
reports = [];
|
||||
if (listener != null) listener.cancel();
|
||||
if (listenerUser != null) listenerUser.cancel();
|
||||
}
|
||||
|
||||
Future<Report> getReport(String repID) async {
|
||||
String path = "/$reports_collection";
|
||||
|
||||
var snap = await Firestore.instance.collection(path).document(repID).get();
|
||||
Report report = Report.fromMap(snap.data, snap.documentID);
|
||||
return report;
|
||||
}
|
||||
|
||||
Future<List> getReportData(Report report, int limit, int offset) async {
|
||||
List reportDataList = [];
|
||||
var aggFun = [];
|
||||
var fields = [];
|
||||
var groupbys = [];
|
||||
// print('report => $report');
|
||||
try {
|
||||
report.fields.asMap().forEach((key, value) {
|
||||
if (value.aggFun == '') {
|
||||
aggFun.add('');
|
||||
} else {
|
||||
aggFun.add(value.aggFun);
|
||||
}
|
||||
});
|
||||
report.fields.asMap().forEach((key, value) {
|
||||
fields.add(value.name);
|
||||
});
|
||||
|
||||
String strFields;
|
||||
fields.forEach((element) {
|
||||
if (strFields == null) {
|
||||
strFields = element;
|
||||
} else {
|
||||
strFields = strFields + ',' + element;
|
||||
}
|
||||
});
|
||||
|
||||
String strAgg;
|
||||
aggFun.forEach((element) {
|
||||
if (strAgg == null) {
|
||||
strAgg = element;
|
||||
} else {
|
||||
strAgg = strAgg + ',' + element;
|
||||
}
|
||||
});
|
||||
|
||||
String strGroup;
|
||||
groupbys.forEach((element) {
|
||||
if (strGroup == null) {
|
||||
strGroup = element;
|
||||
} else {
|
||||
strGroup = strGroup + ',' + element;
|
||||
}
|
||||
});
|
||||
|
||||
var data = {
|
||||
"fields": strFields == null ? '' : strFields,
|
||||
"aggfuns": strAgg == null ? '' : strAgg,
|
||||
// "groupbys": strGroup == null ? '' : strGroup,
|
||||
"limit": limit,
|
||||
"offset": offset
|
||||
};
|
||||
print("payload:$data");
|
||||
|
||||
var rdata = {
|
||||
"fields": 'quantity,product_id,product_name',
|
||||
"aggfuns": ",,",
|
||||
"groupbys": 'product_id',
|
||||
"limit": limit,
|
||||
"offset": offset
|
||||
};
|
||||
var result = await request("/api/data/${report.object}", "POST",
|
||||
token: await getToken(),
|
||||
url: Config.instance.reportURL,
|
||||
payload: jsonEncode(data));
|
||||
|
||||
if (result == null) return [];
|
||||
result.forEach((rdata) {
|
||||
reportDataList.add(rdata);
|
||||
});
|
||||
// print('reportDataList => $reportDataList');
|
||||
notifyListeners();
|
||||
return reportDataList;
|
||||
} catch (e) {
|
||||
log.warning("Error get Summary>>>>${e.toString()}");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> downloadReportData(Report report) async {
|
||||
var aggFun = [];
|
||||
var fields = [];
|
||||
report.fields.asMap().forEach((key, value) {
|
||||
if (value.aggFun == '') {
|
||||
aggFun.add('');
|
||||
} else {
|
||||
aggFun.add(value.aggFun);
|
||||
}
|
||||
});
|
||||
report.fields.asMap().forEach((key, value) {
|
||||
fields.add(value.name);
|
||||
});
|
||||
|
||||
String strFields;
|
||||
fields.forEach((element) {
|
||||
if (strFields == null) {
|
||||
strFields = element;
|
||||
} else {
|
||||
strFields = strFields + ',' + element;
|
||||
}
|
||||
});
|
||||
|
||||
String strAgg;
|
||||
aggFun.forEach((element) {
|
||||
if (strAgg == null) {
|
||||
strAgg = element;
|
||||
} else {
|
||||
strAgg = strAgg + ',' + element;
|
||||
}
|
||||
});
|
||||
|
||||
// final directory = await getApplicationDocumentsDirectory();
|
||||
final directory = await getExternalStorageDirectory();
|
||||
String path = ('${directory.path}/${report.id}.pdf');
|
||||
log.info("download file path:$path");
|
||||
|
||||
var data = {
|
||||
"fields": strFields == null ? '' : strFields,
|
||||
"aggfuns": strAgg == null ? '' : strAgg,
|
||||
"greoupbys": '',
|
||||
"limit": 0,
|
||||
"offset": 0
|
||||
};
|
||||
|
||||
await api.requestDownloadPDFAPI("/api/report-pdf/${report.object}", "GET",
|
||||
filePath: path,
|
||||
url: Config.instance.reportURL,
|
||||
token: await getToken(),
|
||||
payload: jsonEncode(data));
|
||||
|
||||
final message = await OpenFile.open(path);
|
||||
log.info("Open file result:$message");
|
||||
}
|
||||
|
||||
Future<String> getJson(Report report) async {
|
||||
var aggFun = [];
|
||||
var fields = [];
|
||||
report.fields.asMap().forEach((key, value) {
|
||||
if (value.aggFun == '') {
|
||||
aggFun.add('');
|
||||
} else {
|
||||
aggFun.add(value.aggFun);
|
||||
}
|
||||
});
|
||||
report.fields.asMap().forEach((key, value) {
|
||||
fields.add(value.name);
|
||||
});
|
||||
|
||||
String strFields;
|
||||
fields.forEach((element) {
|
||||
if (strFields == null) {
|
||||
strFields = element;
|
||||
} else {
|
||||
strFields = strFields + ',' + element;
|
||||
}
|
||||
});
|
||||
|
||||
String strAgg;
|
||||
aggFun.forEach((element) {
|
||||
if (strAgg == null) {
|
||||
strAgg = element;
|
||||
} else {
|
||||
strAgg = strAgg + ',' + element;
|
||||
}
|
||||
});
|
||||
|
||||
var data = {
|
||||
"fields": strFields == null ? '' : strFields,
|
||||
"aggfuns": strAgg == null ? '' : strAgg,
|
||||
"greoupbys": '',
|
||||
"limit": 0,
|
||||
"offset": 0
|
||||
};
|
||||
return jsonEncode(data);
|
||||
}
|
||||
|
||||
Future<String> getEscapeJson(Report report) async {
|
||||
var bytes = utf8.encode(await getJson(report));
|
||||
var base64Str = base64.encode(bytes);
|
||||
return HtmlEscape().convert(base64Str);
|
||||
}
|
||||
|
||||
Future<List> getReportDataWithFilters(Report report, List filters) async {
|
||||
List reportDataList = [];
|
||||
var aggFun = [];
|
||||
var fields = [];
|
||||
var groupbys = [];
|
||||
|
||||
try {
|
||||
var data = report.convertArrayToString(report, filters);
|
||||
print('data=> $data');
|
||||
|
||||
var result = await request("/api/data/${report.object}", "POST",
|
||||
token: await getToken(),
|
||||
url: Config.instance.reportURL,
|
||||
payload: jsonEncode(data));
|
||||
|
||||
if (result == null) return [];
|
||||
result.forEach((rdata) {
|
||||
reportDataList.add(rdata);
|
||||
});
|
||||
|
||||
notifyListeners();
|
||||
return reportDataList;
|
||||
} catch (e) {
|
||||
log.warning("Error get Summary>>>>${e.toString()}");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> addreport() async {
|
||||
var data = [
|
||||
{
|
||||
"display": "Buyer Rpt",
|
||||
"object": "buyer_rpt",
|
||||
"display_filters": [
|
||||
{
|
||||
"name": "user_name",
|
||||
"display_name": "User Name",
|
||||
"compare": "==",
|
||||
"data_type": "string",
|
||||
},
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"name": "user_name",
|
||||
"display_name": "User Name",
|
||||
"to_fixed": 0,
|
||||
"type": "string",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "reg_date",
|
||||
"display_name": "Registered Date",
|
||||
"to_fixed": 0,
|
||||
"type": "intdate",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "biz_name",
|
||||
"display_name": "Business Name",
|
||||
"to_fixed": 0,
|
||||
"type": "string",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "biz_address",
|
||||
"display_name": "Business Address",
|
||||
"to_fixed": 0,
|
||||
"type": "float",
|
||||
"agg_fun": "",
|
||||
},
|
||||
],
|
||||
"display_fields": ['biz_name', 'biz_name', 'reg_date', 'user_name'],
|
||||
"sorts": [],
|
||||
"groupbys": []
|
||||
},
|
||||
{
|
||||
"display": "Delivery Rpt",
|
||||
"object": "delivery_rpt",
|
||||
"display_filters": [
|
||||
{
|
||||
"name": "user_name",
|
||||
"display_name": "User Name",
|
||||
"compare": "==",
|
||||
"data_type": "string",
|
||||
},
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"name": "user_name",
|
||||
"display_name": "User Name",
|
||||
"to_fixed": 0,
|
||||
"type": "string",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "delivery_ended_date",
|
||||
"display_name": "Delivery Ended Date",
|
||||
"to_fixed": 0,
|
||||
"type": "intdate",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "qty_92",
|
||||
"display_name": "Qty 92",
|
||||
"to_fixed": 0,
|
||||
"type": "float",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "qty_95",
|
||||
"display_name": "Qty 95",
|
||||
"to_fixed": 0,
|
||||
"type": "float",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "qty_d",
|
||||
"display_name": "Qty D",
|
||||
"to_fixed": 0,
|
||||
"type": "float",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "qty_p",
|
||||
"display_name": "Qty P",
|
||||
"to_fixed": 0,
|
||||
"type": "float",
|
||||
"agg_fun": "",
|
||||
},
|
||||
],
|
||||
"display_fields": [
|
||||
'qty_p',
|
||||
'qty_d',
|
||||
'qty_95',
|
||||
'qty_92',
|
||||
'delivery_ended_date',
|
||||
'user_name',
|
||||
],
|
||||
"sorts": [],
|
||||
"groupbys": []
|
||||
},
|
||||
{
|
||||
"display": "DOs Rpt",
|
||||
"object": "dos_rpt",
|
||||
"display_filters": [
|
||||
{
|
||||
"name": "user_name",
|
||||
"display_name": "User Name",
|
||||
"compare": "==",
|
||||
"data_type": "string",
|
||||
},
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"name": "user_name",
|
||||
"display_name": "User Name",
|
||||
"to_fixed": 0,
|
||||
"type": "string",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "doc_date",
|
||||
"display_name": "DO Date",
|
||||
"to_fixed": 0,
|
||||
"type": "intdate",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "doc_number",
|
||||
"display_name": "PO/DO Number",
|
||||
"to_fixed": 0,
|
||||
"type": "string",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "qty_92",
|
||||
"display_name": "Qty 92",
|
||||
"to_fixed": 0,
|
||||
"type": "float",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "qty_95",
|
||||
"display_name": "Qty 95",
|
||||
"to_fixed": 0,
|
||||
"type": "float",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "qty_d",
|
||||
"display_name": "Qty D",
|
||||
"to_fixed": 0,
|
||||
"type": "float",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "qty_p",
|
||||
"display_name": "Qty P",
|
||||
"to_fixed": 0,
|
||||
"type": "float",
|
||||
"agg_fun": "",
|
||||
},
|
||||
],
|
||||
"display_fields": [
|
||||
'qty_p',
|
||||
'qty_d',
|
||||
'qty_95',
|
||||
'qty_92',
|
||||
'doc_date',
|
||||
'user_name',
|
||||
'doc_number'
|
||||
],
|
||||
"sorts": [],
|
||||
"groupbys": []
|
||||
},
|
||||
{
|
||||
"display": "POs Rpt",
|
||||
"object": "pos_rpt",
|
||||
"display_filters": [
|
||||
{
|
||||
"name": "user_name",
|
||||
"display_name": "User Name",
|
||||
"compare": "==",
|
||||
"data_type": "string",
|
||||
},
|
||||
{
|
||||
"name": "po_number",
|
||||
"display_name": "PO Number",
|
||||
"compare": "==",
|
||||
"data_type": "string",
|
||||
}
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"name": "user_name",
|
||||
"display_name": "User Name",
|
||||
"to_fixed": 0,
|
||||
"type": "string",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "po_date",
|
||||
"display_name": "PO Date",
|
||||
"to_fixed": 0,
|
||||
"type": "intdate",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "po_number",
|
||||
"display_name": "PO Number",
|
||||
"to_fixed": 0,
|
||||
"type": "string",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "qty_92",
|
||||
"display_name": "Qty 92",
|
||||
"to_fixed": 0,
|
||||
"type": "float",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "qty_95",
|
||||
"display_name": "Qty 95",
|
||||
"to_fixed": 0,
|
||||
"type": "float",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "qty_d",
|
||||
"display_name": "Qty D",
|
||||
"to_fixed": 0,
|
||||
"type": "float",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "qty_p",
|
||||
"display_name": "Qty P",
|
||||
"to_fixed": 0,
|
||||
"type": "float",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "price_92",
|
||||
"display_name": "Price 92",
|
||||
"to_fixed": 0,
|
||||
"type": "integer",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "price_95",
|
||||
"display_name": "Price 95",
|
||||
"to_fixed": 0,
|
||||
"type": "integer",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "price_d",
|
||||
"display_name": "Price D",
|
||||
"to_fixed": 0,
|
||||
"type": "integer",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "price_p",
|
||||
"display_name": "Price P",
|
||||
"to_fixed": 0,
|
||||
"type": "integer",
|
||||
"agg_fun": "",
|
||||
}
|
||||
],
|
||||
"display_fields": [
|
||||
'qty_p',
|
||||
'qty_d',
|
||||
'qty_95',
|
||||
'qty_92',
|
||||
'price_p',
|
||||
'price_d',
|
||||
'price_95',
|
||||
'price_92',
|
||||
'po_date',
|
||||
'user_name',
|
||||
'po_number'
|
||||
],
|
||||
"sorts": [],
|
||||
"groupbys": []
|
||||
},
|
||||
{
|
||||
"display": "Storage Charge Rpt",
|
||||
"object": "storage_charge_rpt",
|
||||
"display_filters": [
|
||||
{
|
||||
"name": "user_name",
|
||||
"display_name": "User Name",
|
||||
"compare": "==",
|
||||
"data_type": "string",
|
||||
},
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"name": "user_name",
|
||||
"display_name": "User Name",
|
||||
"to_fixed": 0,
|
||||
"type": "string",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "total_qty",
|
||||
"display_name": "Quantity",
|
||||
"to_fixed": 3,
|
||||
"type": "float",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "rate",
|
||||
"display_name": "Rate",
|
||||
"to_fixed": 0,
|
||||
"type": "string",
|
||||
"agg_fun": "",
|
||||
},
|
||||
{
|
||||
"name": "storage_charge",
|
||||
"display_name": "Amount",
|
||||
"to_fixed": 3,
|
||||
"type": "integer",
|
||||
"agg_fun": "",
|
||||
},
|
||||
],
|
||||
"display_fields": [
|
||||
'qty_p',
|
||||
'qty_d',
|
||||
'qty_95',
|
||||
'qty_92',
|
||||
'price_p',
|
||||
'price_d',
|
||||
'price_95',
|
||||
'price_92',
|
||||
'po_date',
|
||||
'user_name',
|
||||
'po_number'
|
||||
],
|
||||
"sorts": [],
|
||||
"groupbys": []
|
||||
}
|
||||
];
|
||||
|
||||
data.asMap().forEach((key, value) {
|
||||
Firestore.instance
|
||||
.collection("/$reports_collection")
|
||||
.document()
|
||||
.setData(value);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> saveSelectedFieldsAndPosition(
|
||||
String id, List<Field> positonFields, List selectedFields) async {
|
||||
// positonFields.toJson
|
||||
ReportFieldPositionSelection report = ReportFieldPositionSelection(
|
||||
fieldPosition: positonFields, fieldSelection: selectedFields);
|
||||
await SharedPref.saveReport(report);
|
||||
}
|
||||
|
||||
Future<ReportFieldPositionSelection> loadSelectedFieldsAndPosition(
|
||||
String id) async {
|
||||
var data = await SharedPref.getReport(id);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
83
lib/model/report_user_model.dart
Normal file
83
lib/model/report_user_model.dart
Normal file
@@ -0,0 +1,83 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:fcs/model/constants.dart';
|
||||
import 'package:fcs/vo/report.dart';
|
||||
import 'package:fcs/vo/report_user.dart';
|
||||
import 'package:fcs/vo/user.dart';
|
||||
|
||||
import '../config.dart';
|
||||
import 'base_model.dart';
|
||||
import 'firebase_helper.dart';
|
||||
|
||||
class ReportUserModel extends BaseModel {
|
||||
List<ReportUser> reportUsers = [];
|
||||
void initUser(user) {
|
||||
super.initUser(user);
|
||||
}
|
||||
|
||||
@override
|
||||
logout() async {}
|
||||
|
||||
Future<List<ReportUser>> getUsersForReport(String reportID) async {
|
||||
List<ReportUser> users = [];
|
||||
String path = "/$report_user_collection";
|
||||
|
||||
QuerySnapshot snapshots = await Firestore.instance
|
||||
.collection(path)
|
||||
.where('report_id', isEqualTo: reportID)
|
||||
.getDocuments();
|
||||
snapshots.documents.forEach((d) {
|
||||
users.add(ReportUser.fromMap(d.data, d.documentID));
|
||||
});
|
||||
return users;
|
||||
}
|
||||
|
||||
Future<List<User>> findUser(String searchUser) async {
|
||||
if (searchUser == null || searchUser == '') return List();
|
||||
|
||||
var bytes = utf8.encode(searchUser);
|
||||
var base64Str = base64.encode(bytes);
|
||||
HtmlEscape htmlEscape = const HtmlEscape();
|
||||
String escapeUser = htmlEscape.convert(base64Str);
|
||||
|
||||
int limit = 20;
|
||||
List<User> _users = [];
|
||||
|
||||
try {
|
||||
var data = await request(
|
||||
"/api/fts/$user_collection/$escapeUser/$limit", "GET",
|
||||
token: await getToken(), url: Config.instance.reportURL);
|
||||
if (data == null) return List();
|
||||
|
||||
data.forEach((user) {
|
||||
var _user = User.fromUserJson(user);
|
||||
_users.add(_user);
|
||||
});
|
||||
} catch (e) {
|
||||
// permission error
|
||||
log.warning("user error:" + e.toString());
|
||||
return null;
|
||||
}
|
||||
return _users;
|
||||
}
|
||||
|
||||
Future<void> updateReportForAllUsers(Report report) async {
|
||||
await request("/report", "PUT",
|
||||
payload: {'id': report.id, 'for_all_users': report.forAllUser},
|
||||
token: await getToken());
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> assignUser(ReportUser reportUser) async {
|
||||
await request("/report_user", "POST",
|
||||
payload: reportUser.toMap(), token: await getToken());
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> deleteReportUser(ReportUser reportUser) async {
|
||||
await request("/report_user", "DELETE",
|
||||
payload: reportUser.toMap(), token: await getToken());
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
76
lib/model/shared_pref.dart
Normal file
76
lib/model/shared_pref.dart
Normal file
@@ -0,0 +1,76 @@
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:fcs/vo/report.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:fcs/vo/user.dart';
|
||||
|
||||
class SharedPref {
|
||||
static final SharedPref instance = SharedPref._();
|
||||
SharedPref._();
|
||||
|
||||
static Future<String> getLang() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
return prefs.getString('language');
|
||||
}
|
||||
|
||||
static Future<void> saveLang(String lang) async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
prefs.setString('language', lang);
|
||||
}
|
||||
|
||||
static Future<void> saveUser(User user) async {
|
||||
await _save("user", user.toJson());
|
||||
}
|
||||
|
||||
static Future<void> saveReport(ReportFieldPositionSelection report) async {
|
||||
await _save('report-${report.id}', report.toJson());
|
||||
}
|
||||
|
||||
static Future<ReportFieldPositionSelection> getReport(String id) async {
|
||||
try {
|
||||
return ReportFieldPositionSelection.fromJson(await _read("report-$id"));
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<User> getUser() async {
|
||||
try {
|
||||
return User.fromJson(await _read("user"));
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<User> removeUser() async {
|
||||
return await _remove("user");
|
||||
}
|
||||
|
||||
static Future<void> saveSkippedRecoverEmail(bool skipped) async {
|
||||
await _save("skipped_recovery_email", skipped);
|
||||
}
|
||||
|
||||
static Future<bool> getSkippedRecoverEmail() async {
|
||||
try {
|
||||
bool _skipped = await _read("skipped_recovery_email");
|
||||
return _skipped;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static _read(String key) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
return json.decode(prefs.getString(key));
|
||||
}
|
||||
|
||||
static _save(String key, value) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
prefs.setString(key, json.encode(value));
|
||||
}
|
||||
|
||||
static _remove(String key) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
prefs.remove(key);
|
||||
}
|
||||
}
|
||||
155
lib/model/storage_model.dart
Normal file
155
lib/model/storage_model.dart
Normal file
@@ -0,0 +1,155 @@
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:fcs/vo/inventory_line.dart';
|
||||
import 'package:fcs/vo/inventory_taking.dart';
|
||||
import 'package:fcs/vo/product.dart';
|
||||
import 'package:fcs/vo/storage.dart';
|
||||
|
||||
import 'base_model.dart';
|
||||
import 'constants.dart';
|
||||
import 'firebase_helper.dart';
|
||||
|
||||
class StorageModel extends BaseModel {
|
||||
final log = Logger('StorageModel');
|
||||
|
||||
List<Storage> storages = [];
|
||||
List<InventoryTaking> inventoryTakings = [];
|
||||
int selectedIndex = 0;
|
||||
DateTime selectedDate = DateTime.now();
|
||||
|
||||
List<Storage> getStorage(String productID) {
|
||||
return storages
|
||||
.where((s) => s.products.any((p) => p.id == productID))
|
||||
.toList();
|
||||
}
|
||||
|
||||
void initUser(user) async {
|
||||
super.initUser(user);
|
||||
if (!user.isOwnerAndAbove() && !user.hasInventory()) {
|
||||
return;
|
||||
}
|
||||
_loadStorages();
|
||||
_loadInventoryTakings();
|
||||
}
|
||||
|
||||
@override
|
||||
logout() async {
|
||||
storages = [];
|
||||
inventoryTakings = [];
|
||||
}
|
||||
|
||||
String getStorageName(String storageID) {
|
||||
return storages.firstWhere((s) => s.id == storageID).name;
|
||||
}
|
||||
|
||||
void _loadStorages() async {
|
||||
try {
|
||||
getQuerySnapshotF(
|
||||
"/$biz_collection/${setting.okEnergyId}/$storage_collection",
|
||||
user.accountID)
|
||||
.listen((QuerySnapshot snapshot) {
|
||||
storages.clear();
|
||||
storages = snapshot.documents.map((documentSnapshot) {
|
||||
var storage = Storage.fromMap(
|
||||
documentSnapshot.data, documentSnapshot.documentID);
|
||||
loadProducts(storage);
|
||||
return storage;
|
||||
}).toList();
|
||||
notifyListeners();
|
||||
}).onError((e) {
|
||||
log.warning("Error! $e");
|
||||
});
|
||||
} catch (e) {
|
||||
log.warning("Error!! $e");
|
||||
}
|
||||
}
|
||||
|
||||
void _loadInventoryTakings() async {
|
||||
try {
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$inventory_takings";
|
||||
var startDate = new DateTime(
|
||||
selectedDate.year, selectedDate.month, selectedDate.day, 0, 0, 0);
|
||||
var endDate = new DateTime(
|
||||
selectedDate.year, selectedDate.month, selectedDate.day, 23, 59, 59);
|
||||
|
||||
inventoryTakings.clear();
|
||||
getFilterDateSnapshotF(path, user.accountID, 'date_time', startDate,
|
||||
endDate, 'date_time')
|
||||
.listen((QuerySnapshot snapshot) {
|
||||
inventoryTakings = snapshot.documents.map((documentSnapshot) {
|
||||
var data = InventoryTaking.fromMap(
|
||||
documentSnapshot.data, documentSnapshot.documentID);
|
||||
|
||||
return data;
|
||||
}).toList();
|
||||
notifyListeners();
|
||||
}).onError((e) {
|
||||
log.warning("Error! $e");
|
||||
});
|
||||
} catch (e) {
|
||||
log.warning("Error!! $e");
|
||||
}
|
||||
}
|
||||
|
||||
loadInventoryLines(InventoryTaking inventoryTaking) async {
|
||||
if (inventoryTaking.linesLoaded) return;
|
||||
var snaps = await getSnapshot(
|
||||
"/$biz_collection/${setting.okEnergyId}/$inventory_takings/${inventoryTaking.id}/$inventory_lines");
|
||||
inventoryTaking.inventoryLines =
|
||||
snaps.documents.map((s) => InventoryLine.fromMap(s.data)).toList();
|
||||
inventoryTaking.linesLoaded = true;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
loadProducts(Storage storage) async {
|
||||
if (storage.productsLoaded) return;
|
||||
var snaps = await getSnapshot(
|
||||
"/$biz_collection/${setting.okEnergyId}/$storage_collection/${storage.id}/$product_collection");
|
||||
storage.products = snaps.documents
|
||||
.map((s) => Product.fromMap(s.data, s.documentID))
|
||||
.toList();
|
||||
storage.productsLoaded = true;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> createStorage(Storage storage) async {
|
||||
await request("/storage", "POST",
|
||||
payload: storage.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> updateStorage(Storage storage) async {
|
||||
await request("/storage", "PUT",
|
||||
payload: storage.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> deleteStorage(String storageID) async {
|
||||
await request("/storage/" + storageID, "DELETE", token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> createInventoryTaking(InventoryTaking inventoryTaking) async {
|
||||
await request("/inventory", "POST",
|
||||
payload: inventoryTaking.toMap(), token: await getToken());
|
||||
}
|
||||
|
||||
void filterDate(DateTime dateTime, int _selectedIndex) async {
|
||||
this.selectedIndex = _selectedIndex;
|
||||
this.selectedDate = dateTime;
|
||||
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$inventory_takings";
|
||||
var endDate =
|
||||
new DateTime(dateTime.year, dateTime.month, dateTime.day, 23, 59, 59);
|
||||
inventoryTakings.clear();
|
||||
getFilterDateSnapshotF(
|
||||
path, user.accountID, 'date_time', dateTime, endDate, 'date_time')
|
||||
.listen((snapshot) {
|
||||
inventoryTakings = snapshot.documents.map((documentSnapshot) {
|
||||
var data = InventoryTaking.fromMap(
|
||||
documentSnapshot.data, documentSnapshot.documentID);
|
||||
|
||||
return data;
|
||||
}).toList();
|
||||
notifyListeners();
|
||||
});
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
177
lib/model/test_model.dart
Normal file
177
lib/model/test_model.dart
Normal file
@@ -0,0 +1,177 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:faker/faker.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
import 'base_model.dart';
|
||||
|
||||
class TestModel extends BaseModel {
|
||||
final log = Logger('TestModel');
|
||||
|
||||
List<Test> tests = [];
|
||||
DocumentSnapshot prev;
|
||||
static const int row_count = 10;
|
||||
bool ended = false;
|
||||
|
||||
StreamSubscription<QuerySnapshot> listener;
|
||||
final Query queryBase = Firestore.instance.collection("/tests");
|
||||
final Query query = Firestore.instance
|
||||
.collection("/tests")
|
||||
// .orderBy("deleted")
|
||||
.orderBy("age", descending: false);
|
||||
|
||||
void initData() async {
|
||||
_clearState();
|
||||
_initListener();
|
||||
load();
|
||||
}
|
||||
|
||||
void _clearState() {
|
||||
prev = null;
|
||||
tests = [];
|
||||
ended = false;
|
||||
if (listener != null) listener.cancel();
|
||||
listener = null;
|
||||
}
|
||||
|
||||
void _initListener() {
|
||||
Query _query = queryBase.orderBy("update_time", descending: true).limit(1);
|
||||
_query.getDocuments(source: Source.server).then((QuerySnapshot snapshot) {
|
||||
int count = snapshot.documents.length;
|
||||
if (count == 1) {
|
||||
var test = Test.fromMap(
|
||||
snapshot.documents[0].data, snapshot.documents[0].documentID);
|
||||
|
||||
Query _queryListener = queryBase
|
||||
.where("update_time", isGreaterThan: test.updateTime)
|
||||
.orderBy("update_time", descending: true);
|
||||
|
||||
listener =
|
||||
_queryListener.snapshots(includeMetadataChanges: true).listen((qs) {
|
||||
qs.documentChanges.forEach((c) {
|
||||
switch (c.type) {
|
||||
case DocumentChangeType.added:
|
||||
var test = Test.fromMap(c.document.data, c.document.documentID);
|
||||
if (tests.contains(test)) {
|
||||
tests[tests.indexOf(test)].name = test.name;
|
||||
notifyListeners();
|
||||
}
|
||||
if (!tests.contains(test)) {
|
||||
tests.add(test);
|
||||
notifyListeners();
|
||||
}
|
||||
break;
|
||||
case DocumentChangeType.modified:
|
||||
var test = Test.fromMap(c.document.data, c.document.documentID);
|
||||
if (tests.contains(test)) {
|
||||
bool deleted = c.document.data["deleted"];
|
||||
if (deleted != null && deleted) {
|
||||
tests.remove(test);
|
||||
} else {
|
||||
tests[tests.indexOf(test)].name = test.name;
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
});
|
||||
});
|
||||
notifyListeners();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> load() async {
|
||||
Query _query = prev != null ? query.startAfterDocument(prev) : query;
|
||||
try {
|
||||
_query
|
||||
// .where("deleted", isNull: null)
|
||||
.limit(row_count)
|
||||
.getDocuments(source: Source.server)
|
||||
.then((QuerySnapshot snapshot) {
|
||||
int count = snapshot.documents.length;
|
||||
ended = count < row_count;
|
||||
prev = count > 0 ? snapshot.documents[count - 1] : prev;
|
||||
snapshot.documents.forEach((e) {
|
||||
var test = Test.fromMap(e.data, e.documentID);
|
||||
if (!tests.contains(test)) tests.add(test);
|
||||
});
|
||||
notifyListeners();
|
||||
});
|
||||
} catch (e) {
|
||||
log.warning("Error!! $e");
|
||||
}
|
||||
}
|
||||
|
||||
void populate() {
|
||||
for (var i = 0; i < 30; i++) {
|
||||
Firestore.instance
|
||||
.collection('tests')
|
||||
.document(faker.person.name())
|
||||
.setData({
|
||||
'name': faker.person.name(),
|
||||
'age': random.decimal(),
|
||||
'update_time': DateTime.now().microsecondsSinceEpoch
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void add() {
|
||||
Firestore.instance
|
||||
.collection('tests')
|
||||
.document(faker.person.name())
|
||||
.setData({
|
||||
'name': faker.person.name(),
|
||||
'age': random.decimal(),
|
||||
'update_time': DateTime.now().microsecondsSinceEpoch
|
||||
});
|
||||
}
|
||||
|
||||
void update() {
|
||||
Firestore.instance.collection('tests').document(tests[0].id).setData({
|
||||
'name': faker.person.name(),
|
||||
'update_time': DateTime.now().microsecondsSinceEpoch
|
||||
}, merge: true);
|
||||
}
|
||||
|
||||
void remove() {
|
||||
Firestore.instance.collection('tests').document(tests[0].id).setData(
|
||||
{'deleted': 1, 'update_time': DateTime.now().microsecondsSinceEpoch},
|
||||
merge: true);
|
||||
}
|
||||
|
||||
@override
|
||||
void logout() {
|
||||
_clearState();
|
||||
}
|
||||
}
|
||||
|
||||
class Test {
|
||||
String id;
|
||||
String name;
|
||||
double age;
|
||||
int updateTime;
|
||||
Test(this.id, {this.name, this.age, this.updateTime});
|
||||
|
||||
factory Test.fromMap(Map<String, dynamic> map, String id) {
|
||||
return Test(id,
|
||||
name: map['name'], age: map['age'], updateTime: map['update_time']);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(other) {
|
||||
if (identical(this, other)) {
|
||||
return true;
|
||||
}
|
||||
return other.id == this.id;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
int result = 17;
|
||||
result = 37 * result + id.hashCode;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
368
lib/model/user_model.dart
Normal file
368
lib/model/user_model.dart
Normal file
@@ -0,0 +1,368 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:fcs/util.dart';
|
||||
import 'package:fcs/vo/popup_menu.dart';
|
||||
import 'package:fcs/vo/role.dart';
|
||||
|
||||
import '../config.dart';
|
||||
import '../vo/user.dart';
|
||||
import 'base_model.dart';
|
||||
import 'constants.dart';
|
||||
import 'firebase_helper.dart';
|
||||
|
||||
class UserModel extends BaseModel {
|
||||
final log = Logger('UserModel');
|
||||
StreamSubscription<QuerySnapshot> listener;
|
||||
PopupMenu popupMenu = new PopupMenu();
|
||||
|
||||
List<User> users = [];
|
||||
List<Privilege> privileges = [];
|
||||
List<UserLevel> userLevels = [];
|
||||
User user = new User();
|
||||
|
||||
List<Privilege> get getPrivileges {
|
||||
return privileges
|
||||
.where((p) => !p.sysAdminOnly || user.isSysAdmin())
|
||||
.toList();
|
||||
}
|
||||
|
||||
List<dynamic> cont = [];
|
||||
|
||||
void initUser(user) async {
|
||||
super.initUser(user);
|
||||
this.user = user;
|
||||
if (user.isBuyer()) return;
|
||||
_loadUsers(user);
|
||||
_loadPrivileges();
|
||||
_loadUserLevels(user);
|
||||
}
|
||||
|
||||
@override
|
||||
logout() async {
|
||||
users = [];
|
||||
userLevels = [];
|
||||
}
|
||||
|
||||
List<Privilege> getUserPrivileges() {
|
||||
List<Privilege> result = new List();
|
||||
if (user.privilegeIds.isNotEmpty) {
|
||||
user.privilegeIds.forEach((pID) {
|
||||
privileges.forEach((p) {
|
||||
if (p.id == pID) {
|
||||
var _priv = Privilege(id: p.id, name: p.name, desc: p.desc);
|
||||
result.add(_priv);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
List<User> getBlockListUsers() {
|
||||
return users.where((u) => u.isBlock == true).toList();
|
||||
}
|
||||
|
||||
List<User> getUserList() {
|
||||
return users.where((u) => u.docID != this.user.docID).toList();
|
||||
}
|
||||
|
||||
Future<void> _loadUsers(User user) async {
|
||||
try {
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$user_collection";
|
||||
var snaps = await Firestore.instance
|
||||
.collection(path)
|
||||
.where('user_level', isLessThanOrEqualTo: user.userLevel)
|
||||
.limit(1)
|
||||
.getDocuments();
|
||||
|
||||
Stream<QuerySnapshot> snapshots = Firestore.instance
|
||||
.collection(path)
|
||||
.where('user_level', isLessThanOrEqualTo: user.userLevel)
|
||||
.snapshots();
|
||||
|
||||
snapshots.listen((snaps) async {
|
||||
users = snaps.documents.map((documentSnapshot) {
|
||||
var data =
|
||||
User.fromMap(documentSnapshot.data, documentSnapshot.documentID);
|
||||
if (data.docID == user.docID && data.isBlock) {
|
||||
this.mainModel.logout();
|
||||
notifyListeners();
|
||||
}
|
||||
return data;
|
||||
}).toList();
|
||||
notifyListeners();
|
||||
});
|
||||
} catch (e) {
|
||||
log.warning("Error!! $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<User> findUser(String phoneNumber) async {
|
||||
var _phoneNumber = updatePhoneNumber(phoneNumber);
|
||||
try {
|
||||
var data = await request("/user/find/$_phoneNumber", "GET",
|
||||
token: await getToken());
|
||||
return User.fromJson(data);
|
||||
} catch (e) {
|
||||
throw Exception(e);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadPrivileges() async {
|
||||
// if (!user.isOwner() && !user.hasAccount()) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
try {
|
||||
getQuerySnapshot("/$privilege_collection")
|
||||
.listen((QuerySnapshot snapshot) {
|
||||
privileges.clear();
|
||||
privileges = snapshot.documents.map((documentSnapshot) {
|
||||
var privilege = Privilege.fromMap(
|
||||
documentSnapshot.data, documentSnapshot.documentID);
|
||||
return privilege;
|
||||
}).toList();
|
||||
notifyListeners();
|
||||
}).onError((e) {
|
||||
log.warning("Error! $e");
|
||||
});
|
||||
} catch (e) {
|
||||
log.warning("Error!! $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadUserLevels(User user) async {
|
||||
try {
|
||||
Stream<QuerySnapshot> snapshots = Firestore.instance
|
||||
.collection("/$user_level_collection")
|
||||
.where('level', isLessThan: user.userLevel)
|
||||
.snapshots();
|
||||
|
||||
snapshots.listen((snaps) async {
|
||||
userLevels = snaps.documents
|
||||
.map((documentSnapshot) => UserLevel.fromMap(
|
||||
documentSnapshot.data, documentSnapshot.documentID))
|
||||
.toList();
|
||||
notifyListeners();
|
||||
});
|
||||
} catch (e) {
|
||||
log.warning("Error!! $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<User> getUser(String id) async {
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$user_collection";
|
||||
print("id=> $id");
|
||||
var snap = await getDocSnap(path, id);
|
||||
print("snap=> $snap");
|
||||
return User.fromMap(snap.data, snap.documentID);
|
||||
}
|
||||
|
||||
Future<void> addUserToOk(String userID, List<String> privileges) async {
|
||||
await addUserToBiz(userID, setting.okEnergyId, privileges);
|
||||
}
|
||||
|
||||
Future<void> addUserToBiz(
|
||||
String userID, bizID, List<String> privileges) async {
|
||||
try {
|
||||
await request("/user/add-biz", "POST",
|
||||
payload: {
|
||||
"user_id": userID,
|
||||
"biz_id": bizID,
|
||||
"privileges": privileges
|
||||
},
|
||||
token: await getToken());
|
||||
} catch (e) {
|
||||
throw Exception(e);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> forgetPassword(String id) async {
|
||||
var _id = updatePhoneNumber(id);
|
||||
await request("/forget", "POST", payload: {"id": _id});
|
||||
}
|
||||
|
||||
Future<void> resetPassword(
|
||||
String id, String newPassword, String confirmationCode) async {
|
||||
var _id = updatePhoneNumber(id);
|
||||
await request(
|
||||
"/reset",
|
||||
"POST",
|
||||
payload: {
|
||||
"id": _id,
|
||||
"password": newPassword,
|
||||
"confirmation_code": confirmationCode
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> changePassword(String id, String newPassword) async {
|
||||
await request(
|
||||
"/change/password",
|
||||
"POST",
|
||||
payload: {
|
||||
"id": id,
|
||||
"password": newPassword,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> changePhone(String id, String newPhone) async {
|
||||
var _newPhone = updatePhoneNumber(newPhone);
|
||||
await request(
|
||||
"/change/phone",
|
||||
"POST",
|
||||
payload: {
|
||||
"id": id,
|
||||
"phone_number": _newPhone,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> addEmail(String id, String email) async {
|
||||
await request(
|
||||
"/email",
|
||||
"PUT",
|
||||
payload: {
|
||||
"id": id,
|
||||
"email": email,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> confirmEmail(
|
||||
String id, String email, String phone, String confirmCode) async {
|
||||
var _id = updatePhoneNumber(id);
|
||||
var _phone = updatePhoneNumber(phone);
|
||||
await request(
|
||||
"/econfirm",
|
||||
"POST",
|
||||
payload: {
|
||||
"id": _id,
|
||||
"email": email == null ? '' : email,
|
||||
"phone_number": _phone == null ? '' : _phone,
|
||||
"confirmation_code": confirmCode
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> deleteStorage(String storageID) async {
|
||||
await request("/storage/" + storageID, "DELETE", token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> blockPhone(String phone) async {
|
||||
var _phone = updatePhoneNumber(phone);
|
||||
await request("/blist", "PUT",
|
||||
payload: {"phone_number": _phone}, token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> unblockPhone(String phone) async {
|
||||
var _phone = updatePhoneNumber(phone);
|
||||
await request("/wlist", "PUT",
|
||||
payload: {"phone_number": _phone}, token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> addLevel(
|
||||
String phone, String levelId, List<String> privs) async {
|
||||
var _phone = updatePhoneNumber(phone);
|
||||
await request("/lvl", "PUT",
|
||||
payload: {
|
||||
"phone_number": _phone,
|
||||
"user_level_id": levelId,
|
||||
"privileges": privs
|
||||
},
|
||||
token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> updatePin(String pin, String password) async {
|
||||
await request("/pin", "POST",
|
||||
payload: {
|
||||
"id": user.docID,
|
||||
"pin": pin,
|
||||
"password": password,
|
||||
},
|
||||
token: await getToken());
|
||||
}
|
||||
|
||||
Future<void> clearPin(String password) async {
|
||||
await request("/pin/clear", "POST",
|
||||
payload: {
|
||||
"id": user.docID,
|
||||
"password": password,
|
||||
},
|
||||
token: await getToken());
|
||||
}
|
||||
|
||||
Future<List<User>> searchUser(String searchUser) async {
|
||||
if (searchUser == null || searchUser == '') return List();
|
||||
|
||||
var bytes = utf8.encode(searchUser);
|
||||
var base64Str = base64.encode(bytes);
|
||||
HtmlEscape htmlEscape = const HtmlEscape();
|
||||
String escapeUser = htmlEscape.convert(base64Str);
|
||||
|
||||
int limit = 20;
|
||||
List<User> _users = [];
|
||||
|
||||
try {
|
||||
var data = await request(
|
||||
"/api/fts/$user_collection/$escapeUser/$limit", "GET",
|
||||
token: await getToken(), url: Config.instance.reportURL);
|
||||
if (data == null) return List();
|
||||
|
||||
data.forEach((user) {
|
||||
var _user = User.fromUserJson(user);
|
||||
_users.add(_user);
|
||||
});
|
||||
} catch (e) {
|
||||
// permission error
|
||||
log.warning("user error:" + e.toString());
|
||||
return null;
|
||||
}
|
||||
return _users;
|
||||
}
|
||||
|
||||
void filterSorting(int _selectedIndex) {
|
||||
users.clear();
|
||||
if (listener != null) {
|
||||
listener.cancel();
|
||||
}
|
||||
String _fieldName;
|
||||
bool descending = false;
|
||||
|
||||
if (_selectedIndex == 0) {
|
||||
_fieldName = 'user_name';
|
||||
descending = false;
|
||||
}
|
||||
if (_selectedIndex == 1) {
|
||||
_fieldName = 'user_name';
|
||||
descending = true;
|
||||
}
|
||||
if (_selectedIndex == 2) {
|
||||
_fieldName = 'phone_number';
|
||||
descending = false;
|
||||
}
|
||||
if (_selectedIndex == 3) {
|
||||
_fieldName = 'phone_number';
|
||||
descending = true;
|
||||
}
|
||||
|
||||
this.popupMenu.index = _selectedIndex;
|
||||
String path = "/$biz_collection/${setting.okEnergyId}/$user_collection";
|
||||
listener =
|
||||
getFilterSnapshot(path, descending, _fieldName).listen((snaps) async {
|
||||
users.clear();
|
||||
snaps.documents.forEach((d) {
|
||||
users.add(User.fromMap(d.data, d.documentID));
|
||||
notifyListeners();
|
||||
});
|
||||
users.where((user) => user.userLevel <= this.user.userLevel);
|
||||
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user