2020-05-29 07:45:27 +06:30
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 ' ;
2020-09-04 01:42:58 +06:30
import ' package:fcs/fcs/common/services/services.dart ' ;
2020-06-26 16:04:40 +06:30
import ' package:fcs/vo/payment_method.dart ' ;
2020-05-29 07:45:27 +06:30
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 ' ;
2020-09-04 15:30:10 +06:30
import ' ../fcs/common/helpers/api_helper.dart ' ;
2020-05-29 07:45:27 +06:30
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 ;
2020-05-29 16:14:17 +06:30
User customer = User (
name: " Ko Myo Min " ,
phoneNumber: ' +95 9 444444444 ' ,
fcsID: ' FCS-0203-390-2 ' ,
shippingAddress:
2020-05-31 15:00:11 +06:30
' 154-19 64th Ave.Flushing, \n NY 11367 \n TEL. +1 (929) 215-2247 ' ,
2020-05-29 16:14:17 +06:30
deliveryAddress: ' 39 42th St. Kyaut Ta Thar Township Yangon ' ) ;
2020-06-01 14:42:42 +06:30
User recipient = User (
name: " Ko Myo Min " ,
phoneNumber: ' +95 9 444444444 ' ,
shippingAddress: ' 154-19 64th Ave.Flushing, \n NY 11367 ' ,
deliveryAddress: ' 39 42th St. Kyaut Ta Thar Township Yangon ' ) ;
2020-06-03 00:42:31 +06:30
Setting setting = Setting (
terms:
' [{"insert":"* Minimum shipping weight is 1lbs. \n * Oversized goods, Light weight/Large volume items, laptops, phones, tablets may incur extra charges based on pecifications.Please contact us for pricing. \n * Goods with lithium battary needs extra packaging and declaration. Please inform us ahead of time so that we can process your package accordingly. \n * Loose Batteries, Drones, and Prescription medicines are not allowed on aircraft. \n * Payment: We accept money orders, any US bank transfers via Zelle, AYA, KBZ and CB. No COD except for pick-ups. \n *Payments made in Myanmar will incur 2% tranfer fee \n "}] ' ) ;
2020-05-29 07:45:27 +06:30
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();
// });
2020-05-31 15:00:11 +06:30
_loadFcs ( ) ;
2020-09-12 03:34:52 +06:30
Services . instance . authService . onAuthStatus ( ) . listen ( ( event ) { } ) ;
2020-06-01 14:42:42 +06:30
}
2020-05-31 15:00:11 +06:30
2020-06-26 16:04:40 +06:30
List < PaymentMethod > get paymentMethods {
List < PaymentMethod > methods = [
PaymentMethod (
name: ' AYA Bank ' ,
2020-06-29 16:03:41 +06:30
accountName: ' FCS ' ,
2020-06-26 16:04:40 +06:30
account: ' 100 23404320548398 ' ,
phone: ' +959123456789 ' ,
mail: ' aya@gmail.com ' ) ,
PaymentMethod (
name: ' KBZ Bank ' ,
2020-06-29 16:03:41 +06:30
accountName: ' FCS ' ,
2020-06-26 16:04:40 +06:30
account: ' 100 23404320548398 ' ,
phone: ' +959123456789 ' ,
mail: ' kbz@gmail.com ' ) ,
PaymentMethod (
2020-08-30 21:26:37 +06:30
name: ' PayPal ' ,
accountName: ' FCS ' ,
link: ' https://www.paypal.com/donate/buttons ' ,
) ,
2020-06-26 16:04:40 +06:30
] ;
return methods ;
}
2020-05-31 15:00:11 +06:30
_loadFcs ( ) async {
user = await SharedPref . getUser ( ) ;
notifyListeners ( ) ;
}
saveUser ( String pin , String phone ) {
if ( pin = = " 000000 " ) {
user = User ( name: " Owner " , phoneNumber: phone ) ;
SharedPref . saveUser ( user ) ;
} else {
user = User ( name: " Customer " , phoneNumber: phone ) ;
SharedPref . saveUser ( user ) ;
}
notifyListeners ( ) ;
2020-05-29 07:45:27 +06:30
}
resetPinTimer ( ) {
if ( pinTimer ! = null & & pinTimer . isActive ) {
pinTimer . cancel ( ) ;
}
pinRequired = false ;
pinTimer = Timer ( Duration ( minutes: PIN_TIME_MIN ) , ( ) {
pinRequired = true ;
} ) ;
}
bool isLogin ( ) {
2020-05-31 15:00:11 +06:30
return this . user ! = null ;
2020-05-29 07:45:27 +06:30
}
2020-06-03 00:42:31 +06:30
bool isCustomer ( ) {
return user ! = null & & user . name ! = " Owner " ;
}
bool isOwner ( ) {
return user ! = null & & user . name = = " Owner " ;
}
2020-05-29 07:45:27 +06:30
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 ) ;
}
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 ( ) {
2020-09-04 01:42:58 +06:30
super . dispose ( ) ;
2020-05-29 07:45:27 +06:30
// 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
2020-09-10 02:13:22 +06:30
// AuthResult r = await this.auth.signInWithCustomToken(token: token);
// this.firebaseUser = r.user;
2020-05-29 07:45:27 +06:30
isLoaded = false ;
_loadUser ( ) ;
_logUser ( this . firebaseUser ) ;
}
Future < FirebaseUser > getProfile ( FirebaseUser firebaseUser ) async {
2020-09-10 02:13:22 +06:30
// IdTokenResult idtoken = await firebaseUser.getIdToken();
2020-05-29 07:45:27 +06:30
var data = await requestAPI (
" /profile " ,
" GET " ,
2020-09-10 02:13:22 +06:30
token: " " , //idtoken.token,
2020-05-29 07:45:27 +06:30
) ;
var _token = data [ " Token " ] ;
2020-09-10 02:13:22 +06:30
// AuthResult a = await this.auth.signInWithCustomToken(token: _token);
// return a.user;
return null ;
2020-05-29 07:45:27 +06:30
}
Future < void > _logUser ( FirebaseUser firebaseUser ) async {
2020-09-10 02:13:22 +06:30
// IdTokenResult idtoken = await firebaseUser.getIdToken();
2020-05-29 07:45:27 +06:30
await requestAPI (
" /log " ,
" GET " ,
2020-09-10 02:13:22 +06:30
token: " " , //idtoken.token,
2020-05-29 07:45:27 +06:30
) ;
}
Future < void > logout ( ) async {
2020-05-31 15:00:11 +06:30
this . user = null ;
notifyListeners ( ) ;
return ;
2020-05-29 07:45:27 +06:30
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 ( ) ) ;
}
}