Ver Fonte

1.导入Google Analytics SDK;
2.修改Network中所有请求接口以及Upload Image、Offline独立网络请求,增加Google Analytics功能。
3.修复Edit Contact时横屏Upload Image程序崩溃。

Pen Li há 9 anos atrás
pai
commit
cb7c95accf
94 ficheiros alterados com 5736 adições e 66 exclusões
  1. BIN
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics
  2. 57 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+AppDelegate.h
  3. 102 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h
  4. 1 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalyticsConfiguration.h
  5. 1 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRApp.h
  6. 1 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRConfiguration.h
  7. 336 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h
  8. 1 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIROptions.h
  9. 369 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRParameterNames.h
  10. 13 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRUserPropertyNames.h
  11. 9 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FirebaseAnalytics.h
  12. 10 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Modules/module.modulemap
  13. BIN
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseCore/Frameworks/FirebaseCore.framework/FirebaseCore
  14. 38 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseCore/Frameworks/FirebaseCore.framework/Headers/FIRAnalyticsConfiguration.h
  15. 98 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseCore/Frameworks/FirebaseCore.framework/Headers/FIRApp.h
  16. 52 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseCore/Frameworks/FirebaseCore.framework/Headers/FIRConfiguration.h
  17. 12 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseCore/Frameworks/FirebaseCore.framework/Headers/FIRLoggerLevel.h
  18. 93 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseCore/Frameworks/FirebaseCore.framework/Headers/FIROptions.h
  19. 5 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseCore/Frameworks/FirebaseCore.framework/Headers/FirebaseCore.h
  20. 8 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseCore/Frameworks/FirebaseCore.framework/Modules/module.modulemap
  21. 33 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseInstanceID/CHANGELOG.md
  22. BIN
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseInstanceID/Frameworks/FirebaseInstanceID.framework/FirebaseInstanceID
  23. 245 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseInstanceID/Frameworks/FirebaseInstanceID.framework/Headers/FIRInstanceID.h
  24. 1 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseInstanceID/Frameworks/FirebaseInstanceID.framework/Headers/FirebaseInstanceID.h
  25. 7 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseInstanceID/Frameworks/FirebaseInstanceID.framework/Modules/module.modulemap
  26. 10 0
      RedAnt ERP Mobile/GoogleAnalytics/FirebaseInstanceID/README.md
  27. BIN
      RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLAnalytics.framework/GGLAnalytics
  28. 3 0
      RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLAnalytics.framework/Headers/GGLAnalytics.h
  29. 39 0
      RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLAnalytics.framework/Headers/GGLContext+Analytics.h
  30. 8 0
      RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLAnalytics.framework/Modules/module.modulemap
  31. BIN
      RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLCore.framework/GGLCore
  32. 45 0
      RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLCore.framework/Headers/GGLConfiguration.h
  33. 55 0
      RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLCore.framework/Headers/GGLContext.h
  34. 6 0
      RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLCore.framework/Headers/GGLCore.h
  35. 45 0
      RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLCore.framework/Headers/GGLErrorCode.h
  36. 19 0
      RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLCore.framework/Headers/GMRConfiguration.h
  37. 14 0
      RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLCore.framework/Modules/module.modulemap
  38. 15 0
      RedAnt ERP Mobile/GoogleAnalytics/Google/Headers/Analytics.h
  39. 4 0
      RedAnt ERP Mobile/GoogleAnalytics/Google/Headers/Core.h
  40. 5 0
      RedAnt ERP Mobile/GoogleAnalytics/Google/Headers/ModuleHeaders/Analytics-Module.h
  41. 5 0
      RedAnt ERP Mobile/GoogleAnalytics/Google/Headers/ModuleHeaders/Core-Module.h
  42. 5 0
      RedAnt ERP Mobile/GoogleAnalytics/Google/Headers/ModuleHeaders/SignIn-Module.h
  43. 15 0
      RedAnt ERP Mobile/GoogleAnalytics/Google/Headers/module.modulemap
  44. 66 0
      RedAnt ERP Mobile/GoogleAnalytics/Google/README.md
  45. 55 0
      RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalyst.h
  46. 119 0
      RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalyst.m
  47. 192 0
      RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalytics/Sources/GAI.h
  48. 214 0
      RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalytics/Sources/GAIDictionaryBuilder.h
  49. 124 0
      RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalytics/Sources/GAIEcommerceFields.h
  50. 102 0
      RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalytics/Sources/GAIEcommerceProduct.h
  51. 107 0
      RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalytics/Sources/GAIEcommerceProductAction.h
  52. 54 0
      RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalytics/Sources/GAIEcommercePromotion.h
  53. 133 0
      RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalytics/Sources/GAIFields.h
  54. 49 0
      RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalytics/Sources/GAILogger.h
  55. 33 0
      RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalytics/Sources/GAITrackedViewController.h
  56. 57 0
      RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalytics/Sources/GAITracker.h
  57. 199 0
      RedAnt ERP Mobile/GoogleAnalytics/GoogleToolboxForMac/Foundation/GTMNSData+zlib.h
  58. 531 0
      RedAnt ERP Mobile/GoogleAnalytics/GoogleToolboxForMac/Foundation/GTMNSData+zlib.m
  59. 392 0
      RedAnt ERP Mobile/GoogleAnalytics/GoogleToolboxForMac/GTMDefines.h
  60. 202 0
      RedAnt ERP Mobile/GoogleAnalytics/GoogleToolboxForMac/LICENSE
  61. 15 0
      RedAnt ERP Mobile/GoogleAnalytics/GoogleToolboxForMac/README.md
  62. 256 2
      RedAnt ERP Mobile/HMLG Mobile.xcodeproj/project.pbxproj
  63. 2 0
      RedAnt ERP Mobile/Pods/Pods.xcodeproj/project.pbxproj
  64. BIN
      RedAnt ERP Mobile/RedAnt ERP Mobile.xcworkspace/xcuserdata/macmini1.xcuserdatad/UserInterfaceState.xcuserstate
  65. 13 3
      RedAnt ERP Mobile/RedAnt ERP Mobile.xcworkspace/xcuserdata/macmini1.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
  66. 8 0
      RedAnt ERP Mobile/common/ERPUtils.h
  67. 263 0
      RedAnt ERP Mobile/common/ERPUtils.m
  68. 10 2
      RedAnt ERP Mobile/common/Functions/camscan/ScannerViewController.m
  69. 5 3
      RedAnt ERP Mobile/common/Functions/cart/CartViewController.m
  70. 2 0
      RedAnt ERP Mobile/common/Functions/category/CategorySearchFilterViewController.m
  71. 6 5
      RedAnt ERP Mobile/common/Functions/category/CategoryViewController.m
  72. 3 0
      RedAnt ERP Mobile/common/Functions/contact/ContactAdvanceSearchViewController.m
  73. 2 1
      RedAnt ERP Mobile/common/Functions/contact/ContactListViewController.m
  74. 1 1
      RedAnt ERP Mobile/common/Functions/contact/CustomerInfoViewController.m
  75. 9 0
      RedAnt ERP Mobile/common/Functions/home/HomeViewController.m
  76. 8 8
      RedAnt ERP Mobile/common/Functions/modelDetail/DetailHeaderCell.m
  77. 2 2
      RedAnt ERP Mobile/common/Functions/modelDetail/DetailViewController.m
  78. 1 1
      RedAnt ERP Mobile/common/Functions/offline/SelectUploadOrderViewController.m
  79. 2 2
      RedAnt ERP Mobile/common/Functions/order/CreateOrderViewController.m
  80. 2 2
      RedAnt ERP Mobile/common/Functions/order/OrderDetailViewController.m
  81. 1 0
      RedAnt ERP Mobile/common/Functions/portfolio/PDFListViewController.m
  82. 5 1
      RedAnt ERP Mobile/common/Functions/portfolio/PortfolioViewController.m
  83. 3 1
      RedAnt ERP Mobile/common/Functions/search+itemsearch/ItemSearchFilterViewController.m
  84. 6 5
      RedAnt ERP Mobile/common/Functions/search+itemsearch/ItemSearchViewController.m
  85. 7 6
      RedAnt ERP Mobile/common/Functions/search+itemsearch/SearchViewController.m
  86. 6 0
      RedAnt ERP Mobile/common/Functions/watchlist/WatchListViewController.m
  87. 3 0
      RedAnt ERP Mobile/common/Singleton.h
  88. 4 0
      RedAnt ERP Mobile/common/customUI/ImageUploadViewController.m
  89. 42 6
      RedAnt ERP Mobile/common/data_provider/iSalesNetwork.h
  90. 302 12
      RedAnt ERP Mobile/common/data_provider/iSalesNetwork.m
  91. 260 2
      RedAnt ERP Mobile/iSales-NPD.xcodeproj/project.pbxproj
  92. 45 0
      RedAnt ERP Mobile/iSales-NPD/AppDelegate.m
  93. 26 0
      RedAnt ERP Mobile/iSales-NPD/GoogleService-Info.plist
  94. 2 1
      RedAnt ERP Mobile/iSales-NPD/config.h

BIN
RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics


+ 57 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+AppDelegate.h

@@ -0,0 +1,57 @@
+#import <Foundation/Foundation.h>
+
+#import "FIRAnalytics.h"
+
+/**
+ * Provides App Delegate handlers to be used in your App Delegate.
+ *
+ * To save time integrating Firebase Analytics in an application, Firebase Analytics does not
+ * require delegation implementation from the AppDelegate. Instead this is automatically done by
+ * Firebase Analytics. Should you choose instead to delegate manually, you can turn off the App
+ * Delegate Proxy by adding FirebaseAppDelegateProxyEnabled into your app's Info.plist and setting
+ * it to NO, and adding the methods in this category to corresponding delegation handlers.
+ *
+ * To handle Universal Links, you must return YES in
+ * [UIApplicationDelegate application:didFinishLaunchingWithOptions:].
+ */
+@interface FIRAnalytics (AppDelegate)
+
+/**
+ * Handles events related to a URL session that are waiting to be processed.
+ *
+ * For optimal use of Firebase Analytics, call this method from the
+ * [UIApplicationDelegate application:handleEventsForBackgroundURLSession:completionHandler]
+ * method of the app delegate in your app.
+ *
+ * @param identifier The identifier of the URL session requiring attention.
+ * @param completionHandler The completion handler to call when you finish processing the events.
+ *     Calling this completion handler lets the system know that your app's user interface is
+ *     updated and a new snapshot can be taken.
+ */
++ (void)handleEventsForBackgroundURLSession:(NSString *)identifier
+                          completionHandler:(void (^)(void))completionHandler;
+
+/**
+ * Handles the event when the app is launched by a URL.
+ *
+ * Call this method from [UIApplicationDelegate application:openURL:options:] (on iOS 9.0 and
+ * above), or [UIApplicationDelegate application:openURL:sourceApplication:annotation:] (on iOS 8.x
+ * and below) in your app.
+ *
+ * @param url The URL resource to open. This resource can be a network resource or a file.
+ */
++ (void)handleOpenURL:(NSURL *)url;
+
+/**
+ * Handles the event when the app receives data associated with user activity that includes a
+ * Universal Link (on iOS 9.0 and above).
+ *
+ * Call this method from [UIApplication continueUserActivity:restorationHandler:] in your app
+ * delegate (on iOS 9.0 and above).
+ *
+ * @param userActivity The activity object containing the data associated with the task the user
+ *     was performing.
+ */
++ (void)handleUserActivity:(id)userActivity;
+
+@end

+ 102 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h

@@ -0,0 +1,102 @@
+#import <Foundation/Foundation.h>
+
+#import "FIREventNames.h"
+#import "FIRParameterNames.h"
+#import "FIRUserPropertyNames.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// The top level Firebase Analytics singleton that provides methods for logging events and setting
+/// user properties. See <a href="http://goo.gl/gz8SLz">the developer guides</a> for general
+/// information on using Firebase Analytics in your apps.
+@interface FIRAnalytics : NSObject
+
+/// Logs an app event. The event can have up to 25 parameters. Events with the same name must have
+/// the same parameters. Up to 500 event names are supported. Using predefined events and/or
+/// parameters is recommended for optimal reporting.
+///
+/// The following event names are reserved and cannot be used:
+/// <ul>
+///     <li>app_clear_data</li>
+///     <li>app_remove</li>
+///     <li>app_update</li>
+///     <li>error</li>
+///     <li>first_open</li>
+///     <li>in_app_purchase</li>
+///     <li>notification_dismiss</li>
+///     <li>notification_foreground</li>
+///     <li>notification_open</li>
+///     <li>notification_receive</li>
+///     <li>os_update</li>
+///     <li>session_start</li>
+///     <li>user_engagement</li>
+/// </ul>
+///
+/// @param name The name of the event. Should contain 1 to 40 alphanumeric characters or
+///     underscores. The name must start with an alphabetic character. Some event names are
+///     reserved. See FIREventNames.h for the list of reserved event names. The "firebase_" prefix
+///     is reserved and should not be used. Note that event names are case-sensitive and that
+///     logging two events whose names differ only in case will result in two distinct events.
+/// @param parameters The dictionary of event parameters. Passing nil indicates that the event has
+///     no parameters. Parameter names can be up to 40 characters long and must start with an
+///     alphabetic character and contain only alphanumeric characters and underscores. Only NSString
+///     and NSNumber (signed 64-bit integer and 64-bit floating-point number) parameter types are
+///     supported. NSString parameter values can be up to 100 characters long. The "firebase_"
+///     prefix is reserved and should not be used for parameter names.
++ (void)logEventWithName:(NSString *)name
+              parameters:(nullable NSDictionary<NSString *, NSObject *> *)parameters;
+
+/// Sets a user property to a given value. Up to 25 user property names are supported. Once set,
+/// user property values persist throughout the app lifecycle and across sessions.
+///
+/// The following user property names are reserved and cannot be used:
+/// <ul>
+///     <li>first_open_time</li>
+///     <li>last_deep_link_referrer</li>
+///     <li>user_id</li>
+/// </ul>
+///
+/// @param value The value of the user property. Values can be up to 36 characters long. Setting the
+///     value to nil removes the user property.
+/// @param name The name of the user property to set. Should contain 1 to 24 alphanumeric characters
+///     or underscores and must start with an alphabetic character. The "firebase_" prefix is
+///     reserved and should not be used for user property names.
++ (void)setUserPropertyString:(nullable NSString *)value forName:(NSString *)name;
+
+/// Sets the user ID property. This feature must be used in accordance with
+/// <a href="https://www.google.com/policies/privacy">Google's Privacy Policy</a>
+///
+/// @param userID The user ID to ascribe to the user of this app on this device, which must be
+///     non-empty and no more than 36 characters long. Setting userID to nil removes the user ID.
++ (void)setUserID:(nullable NSString *)userID;
+
+/// Sets the current screen name, which specifies the current visual context in your app. This helps
+/// identify the areas in your app where users spend their time and how they interact with your app.
+///
+/// Note that screen reporting is enabled automatically and records the class name of the current
+/// UIViewController for you without requiring you to call this method. If you implement
+/// viewDidAppear in your UIViewController but do not call [super viewDidAppear:], that screen class
+/// will not be automatically tracked. The class name can optionally be overridden by calling this
+/// method in the viewDidAppear callback of your UIViewController and specifying the
+/// screenClassOverride parameter.
+///
+/// If your app does not use a distinct UIViewController for each screen, you should call this
+/// method and specify a distinct screenName each time a new screen is presented to the user.
+///
+/// The screen name and screen class remain in effect until the current UIViewController changes or
+/// a new call to setScreenName:screenClass: is made.
+///
+/// @param screenName The name of the current screen. Should contain 1 to 100 characters. Set to nil
+///     to clear the current screen name.
+/// @param screenClassOverride The name of the screen class. Should contain 1 to 100 characters. By
+///     default this is the class name of the current UIViewController. Set to nil to revert to the
+///     default class name.
++ (void)setScreenName:(nullable NSString *)screenName
+          screenClass:(nullable NSString *)screenClassOverride;
+
+/// The unique ID for this instance of the application.
++ (NSString *)appInstanceID;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 1 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalyticsConfiguration.h

@@ -0,0 +1 @@
+#import <FirebaseCore/FIRAnalyticsConfiguration.h>

+ 1 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRApp.h

@@ -0,0 +1 @@
+#import <FirebaseCore/FIRApp.h>

+ 1 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRConfiguration.h

@@ -0,0 +1 @@
+#import <FirebaseCore/FIRConfiguration.h>

+ 336 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h

@@ -0,0 +1,336 @@
+/// @file FIREventNames.h
+///
+/// Predefined event names.
+///
+/// An Event is an important occurrence in your app that you want to measure. You can report up to
+/// 500 different types of Events per app and you can associate up to 25 unique parameters with each
+/// Event type. Some common events are suggested below, but you may also choose to specify custom
+/// Event types that are associated with your specific app. Each event type is identified by a
+/// unique name. Event names can be up to 40 characters long, may only contain alphanumeric
+/// characters and underscores ("_"), and must start with an alphabetic character. The "firebase_"
+/// prefix is reserved and should not be used.
+
+/// Add Payment Info event. This event signifies that a user has submitted their payment information
+/// to your app.
+static NSString *const kFIREventAddPaymentInfo = @"add_payment_info";
+
+/// E-Commerce Add To Cart event. This event signifies that an item was added to a cart for
+/// purchase. Add this event to a funnel with kFIREventEcommercePurchase to gauge the effectiveness
+/// of your checkout process. Note: If you supply the @c kFIRParameterValue parameter, you must
+/// also supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed
+/// accurately. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterQuantity (signed 64-bit integer as NSNumber)</li>
+///     <li>@c kFIRParameterItemID (NSString)</li>
+///     <li>@c kFIRParameterItemName (NSString)</li>
+///     <li>@c kFIRParameterItemCategory (NSString)</li>
+///     <li>@c kFIRParameterItemLocationID (NSString) (optional)</li>
+///     <li>@c kFIRParameterPrice (double as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterOrigin (NSString) (optional)</li>
+///     <li>@c kFIRParameterDestination (NSString) (optional)</li>
+///     <li>@c kFIRParameterStartDate (NSString) (optional)</li>
+///     <li>@c kFIRParameterEndDate (NSString) (optional)</li>
+/// </ul>
+static NSString *const kFIREventAddToCart = @"add_to_cart";
+
+/// E-Commerce Add To Wishlist event. This event signifies that an item was added to a wishlist.
+/// Use this event to identify popular gift items in your app. Note: If you supply the
+/// @c kFIRParameterValue parameter, you must also supply the @c kFIRParameterCurrency
+/// parameter so that revenue metrics can be computed accurately. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterQuantity (signed 64-bit integer as NSNumber)</li>
+///     <li>@c kFIRParameterItemID (NSString)</li>
+///     <li>@c kFIRParameterItemName (NSString)</li>
+///     <li>@c kFIRParameterItemCategory (NSString)</li>
+///     <li>@c kFIRParameterItemLocationID (NSString) (optional)</li>
+///     <li>@c kFIRParameterPrice (double as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+/// </ul>
+static NSString *const kFIREventAddToWishlist = @"add_to_wishlist";
+
+/// App Open event. By logging this event when an App is moved to the foreground, developers can
+/// understand how often users leave and return during the course of a Session. Although Sessions
+/// are automatically reported, this event can provide further clarification around the continuous
+/// engagement of app-users.
+static NSString *const kFIREventAppOpen = @"app_open";
+
+/// E-Commerce Begin Checkout event. This event signifies that a user has begun the process of
+/// checking out. Add this event to a funnel with your kFIREventEcommercePurchase event to gauge the
+/// effectiveness of your checkout process. Note: If you supply the @c kFIRParameterValue
+/// parameter, you must also supply the @c kFIRParameterCurrency parameter so that revenue
+/// metrics can be computed accurately. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterTransactionID (NSString) (optional)</li>
+///     <li>@c kFIRParameterStartDate (NSString) (optional)</li>
+///     <li>@c kFIRParameterEndDate (NSString) (optional)</li>
+///     <li>@c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for
+///         hotel bookings</li>
+///     <li>@c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for
+///         hotel bookings</li>
+///     <li>@c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional)
+///         for travel bookings</li>
+///     <li>@c kFIRParameterOrigin (NSString) (optional)</li>
+///     <li>@c kFIRParameterDestination (NSString) (optional)</li>
+///     <li>@c kFIRParameterTravelClass (NSString) (optional) for travel bookings</li>
+/// </ul>
+static NSString *const kFIREventBeginCheckout = @"begin_checkout";
+
+/// Campaign Detail event. Log this event to supply the referral details of a re-engagement
+/// campaign. Note: you must supply at least one of the required parameters kFIRParameterSource,
+/// kFIRParameterMedium or kFIRParameterCampaign. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterSource (NSString)</li>
+///     <li>@c kFIRParameterMedium (NSString)</li>
+///     <li>@c kFIRParameterCampaign (NSString)</li>
+///     <li>@c kFIRParameterTerm (NSString) (optional)</li>
+///     <li>@c kFIRParameterContent (NSString) (optional)</li>
+///     <li>@c kFIRParameterAdNetworkClickID (NSString) (optional)</li>
+///     <li>@c kFIRParameterCP1 (NSString) (optional)</li>
+/// </ul>
+static NSString *const kFIREventCampaignDetails = @"campaign_details";
+
+/// Earn Virtual Currency event. This event tracks the awarding of virtual currency in your app. Log
+/// this along with @c kFIREventSpendVirtualCurrency to better understand your virtual economy.
+/// Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterVirtualCurrencyName (NSString)</li>
+///     <li>@c kFIRParameterValue (signed 64-bit integer or double as NSNumber)</li>
+/// </ul>
+static NSString *const kFIREventEarnVirtualCurrency = @"earn_virtual_currency";
+
+/// E-Commerce Purchase event. This event signifies that an item was purchased by a user. Note:
+/// This is different from the in-app purchase event, which is reported automatically for App
+/// Store-based apps. Note: If you supply the @c kFIRParameterValue parameter, you must also
+/// supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed
+/// accurately. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterTransactionID (NSString) (optional)</li>
+///     <li>@c kFIRParameterTax (double as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterShipping (double as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterCoupon (NSString) (optional)</li>
+///     <li>@c kFIRParameterLocation (NSString) (optional)</li>
+///     <li>@c kFIRParameterStartDate (NSString) (optional)</li>
+///     <li>@c kFIRParameterEndDate (NSString) (optional)</li>
+///     <li>@c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for
+///         hotel bookings</li>
+///     <li>@c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for
+///         hotel bookings</li>
+///     <li>@c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional)
+///         for travel bookings</li>
+///     <li>@c kFIRParameterOrigin (NSString) (optional)</li>
+///     <li>@c kFIRParameterDestination (NSString) (optional)</li>
+///     <li>@c kFIRParameterTravelClass (NSString) (optional) for travel bookings</li>
+/// </ul>
+static NSString *const kFIREventEcommercePurchase = @"ecommerce_purchase";
+
+/// Generate Lead event. Log this event when a lead has been generated in the app to understand the
+/// efficacy of your install and re-engagement campaigns. Note: If you supply the
+/// @c kFIRParameterValue parameter, you must also supply the @c kFIRParameterCurrency
+/// parameter so that revenue metrics can be computed accurately. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+/// </ul>
+static NSString *const kFIREventGenerateLead = @"generate_lead";
+
+/// Join Group event. Log this event when a user joins a group such as a guild, team or family. Use
+/// this event to analyze how popular certain groups or social features are in your app. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterGroupID (NSString)</li>
+/// </ul>
+static NSString *const kFIREventJoinGroup = @"join_group";
+
+/// Level Up event. This event signifies that a player has leveled up in your gaming app. It can
+/// help you gauge the level distribution of your userbase and help you identify certain levels that
+/// are difficult to pass. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterLevel (signed 64-bit integer as NSNumber)</li>
+///     <li>@c kFIRParameterCharacter (NSString) (optional)</li>
+/// </ul>
+static NSString *const kFIREventLevelUp = @"level_up";
+
+/// Login event. Apps with a login feature can report this event to signify that a user has logged
+/// in.
+static NSString *const kFIREventLogin = @"login";
+
+/// Post Score event. Log this event when the user posts a score in your gaming app. This event can
+/// help you understand how users are actually performing in your game and it can help you correlate
+/// high scores with certain audiences or behaviors. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterScore (signed 64-bit integer as NSNumber)</li>
+///     <li>@c kFIRParameterLevel (signed 64-bit integer as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterCharacter (NSString) (optional)</li>
+/// </ul>
+static NSString *const kFIREventPostScore = @"post_score";
+
+/// Present Offer event. This event signifies that the app has presented a purchase offer to a user.
+/// Add this event to a funnel with the kFIREventAddToCart and kFIREventEcommercePurchase to gauge
+/// your conversion process. Note: If you supply the @c kFIRParameterValue parameter, you must
+/// also supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed
+/// accurately. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterQuantity (signed 64-bit integer as NSNumber)</li>
+///     <li>@c kFIRParameterItemID (NSString)</li>
+///     <li>@c kFIRParameterItemName (NSString)</li>
+///     <li>@c kFIRParameterItemCategory (NSString)</li>
+///     <li>@c kFIRParameterItemLocationID (NSString) (optional)</li>
+///     <li>@c kFIRParameterPrice (double as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+/// </ul>
+static NSString *const kFIREventPresentOffer = @"present_offer";
+
+/// E-Commerce Purchase Refund event. This event signifies that an item purchase was refunded.
+/// Note: If you supply the @c kFIRParameterValue parameter, you must also supply the
+/// @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately.
+/// Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterTransactionID (NSString) (optional)</li>
+/// </ul>
+static NSString *const kFIREventPurchaseRefund = @"purchase_refund";
+
+/// Search event. Apps that support search features can use this event to contextualize search
+/// operations by supplying the appropriate, corresponding parameters. This event can help you
+/// identify the most popular content in your app. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterSearchTerm (NSString)</li>
+///     <li>@c kFIRParameterStartDate (NSString) (optional)</li>
+///     <li>@c kFIRParameterEndDate (NSString) (optional)</li>
+///     <li>@c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for
+///         hotel bookings</li>
+///     <li>@c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for
+///         hotel bookings</li>
+///     <li>@c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional)
+///         for travel bookings</li>
+///     <li>@c kFIRParameterOrigin (NSString) (optional)</li>
+///     <li>@c kFIRParameterDestination (NSString) (optional)</li>
+///     <li>@c kFIRParameterTravelClass (NSString) (optional) for travel bookings</li>
+/// </ul>
+static NSString *const kFIREventSearch = @"search";
+
+/// Select Content event. This general purpose event signifies that a user has selected some content
+/// of a certain type in an app. The content can be any object in your app. This event can help you
+/// identify popular content and categories of content in your app. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterContentType (NSString)</li>
+///     <li>@c kFIRParameterItemID (NSString)</li>
+/// </ul>
+static NSString *const kFIREventSelectContent = @"select_content";
+
+/// Share event. Apps with social features can log the Share event to identify the most viral
+/// content. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterContentType (NSString)</li>
+///     <li>@c kFIRParameterItemID (NSString)</li>
+/// </ul>
+static NSString *const kFIREventShare = @"share";
+
+/// Sign Up event. This event indicates that a user has signed up for an account in your app. The
+/// parameter signifies the method by which the user signed up. Use this event to understand the
+/// different behaviors between logged in and logged out users. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterSignUpMethod (NSString)</li>
+/// </ul>
+static NSString *const kFIREventSignUp = @"sign_up";
+
+/// Spend Virtual Currency event. This event tracks the sale of virtual goods in your app and can
+/// help you identify which virtual goods are the most popular objects of purchase. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterItemName (NSString)</li>
+///     <li>@c kFIRParameterVirtualCurrencyName (NSString)</li>
+///     <li>@c kFIRParameterValue (signed 64-bit integer or double as NSNumber)</li>
+/// </ul>
+static NSString *const kFIREventSpendVirtualCurrency = @"spend_virtual_currency";
+
+/// Tutorial Begin event. This event signifies the start of the on-boarding process in your app. Use
+/// this in a funnel with kFIREventTutorialComplete to understand how many users complete this
+/// process and move on to the full app experience.
+static NSString *const kFIREventTutorialBegin = @"tutorial_begin";
+
+/// Tutorial End event. Use this event to signify the user's completion of your app's on-boarding
+/// process. Add this to a funnel with kFIREventTutorialBegin to gauge the completion rate of your
+/// on-boarding process.
+static NSString *const kFIREventTutorialComplete = @"tutorial_complete";
+
+/// Unlock Achievement event. Log this event when the user has unlocked an achievement in your
+/// game. Since achievements generally represent the breadth of a gaming experience, this event can
+/// help you understand how many users are experiencing all that your game has to offer. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterAchievementID (NSString)</li>
+/// </ul>
+static NSString *const kFIREventUnlockAchievement = @"unlock_achievement";
+
+/// View Item event. This event signifies that some content was shown to the user. This content may
+/// be a product, a webpage or just a simple image or text. Use the appropriate parameters to
+/// contextualize the event. Use this event to discover the most popular items viewed in your app.
+/// Note: If you supply the @c kFIRParameterValue parameter, you must also supply the
+/// @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately.
+/// Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterItemID (NSString)</li>
+///     <li>@c kFIRParameterItemName (NSString)</li>
+///     <li>@c kFIRParameterItemCategory (NSString)</li>
+///     <li>@c kFIRParameterItemLocationID (NSString) (optional)</li>
+///     <li>@c kFIRParameterPrice (double as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterQuantity (signed 64-bit integer as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterCurrency (NSString) (optional)</li>
+///     <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
+///     <li>@c kFIRParameterStartDate (NSString) (optional)</li>
+///     <li>@c kFIRParameterEndDate (NSString) (optional)</li>
+///     <li>@c kFIRParameterFlightNumber (NSString) (optional) for travel bookings</li>
+///     <li>@c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional)
+///         for travel bookings</li>
+///     <li>@c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for
+///         travel bookings</li>
+///     <li>@c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for
+///         travel bookings</li>
+///     <li>@c kFIRParameterOrigin (NSString) (optional)</li>
+///     <li>@c kFIRParameterDestination (NSString) (optional)</li>
+///     <li>@c kFIRParameterSearchTerm (NSString) (optional) for travel bookings</li>
+///     <li>@c kFIRParameterTravelClass (NSString) (optional) for travel bookings</li>
+/// </ul>
+static NSString *const kFIREventViewItem = @"view_item";
+
+/// View Item List event. Log this event when the user has been presented with a list of items of a
+/// certain category. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterItemCategory (NSString)</li>
+/// </ul>
+static NSString *const kFIREventViewItemList = @"view_item_list";
+
+/// View Search Results event. Log this event when the user has been presented with the results of a
+/// search. Params:
+///
+/// <ul>
+///     <li>@c kFIRParameterSearchTerm (NSString)</li>
+/// </ul>
+static NSString *const kFIREventViewSearchResults = @"view_search_results";

+ 1 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIROptions.h

@@ -0,0 +1 @@
+#import <FirebaseCore/FIROptions.h>

+ 369 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRParameterNames.h

@@ -0,0 +1,369 @@
+/// @file FIRParameterNames.h
+///
+/// Predefined event parameter names.
+///
+/// Params supply information that contextualize Events. You can associate up to 25 unique Params
+/// with each Event type. Some Params are suggested below for certain common Events, but you are
+/// not limited to these. You may supply extra Params for suggested Events or custom Params for
+/// Custom events. Param names can be up to 40 characters long, may only contain alphanumeric
+/// characters and underscores ("_"), and must start with an alphabetic character. Param values can
+/// be up to 100 characters long. The "firebase_" prefix is reserved and should not be used.
+
+/// Game achievement ID (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterAchievementID : @"10_matches_won",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterAchievementID = @"achievement_id";
+
+/// Ad Network Click ID (NSString). Used for network-specific click IDs which vary in format.
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterAdNetworkClickID : @"1234567",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterAdNetworkClickID = @"aclid";
+
+/// The individual campaign name, slogan, promo code, etc. Some networks have pre-defined macro to
+/// capture campaign information, otherwise can be populated by developer. Highly Recommended
+/// (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterCampaign : @"winter_promotion",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterCampaign = @"campaign";
+
+/// Character used in game (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterCharacter : @"beat_boss",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterCharacter = @"character";
+
+/// Campaign content (NSString).
+static NSString *const kFIRParameterContent = @"content";
+
+/// Type of content selected (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterContentType : @"news article",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterContentType = @"content_type";
+
+/// Coupon code for a purchasable item (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterCoupon : @"zz123",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterCoupon = @"coupon";
+
+/// Campaign custom parameter (NSString). Used as a method of capturing custom data in a campaign.
+/// Use varies by network.
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterCP1 : @"custom_data",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterCP1 = @"cp1";
+
+/// Purchase currency in 3-letter <a href="http://en.wikipedia.org/wiki/ISO_4217#Active_codes">
+/// ISO_4217</a> format (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterCurrency : @"USD",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterCurrency = @"currency";
+
+/// Flight or Travel destination (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterDestination : @"Mountain View, CA",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterDestination = @"destination";
+
+/// The arrival date, check-out date or rental end date for the item. This should be in
+/// YYYY-MM-DD format (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterEndDate : @"2015-09-14",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterEndDate = @"end_date";
+
+/// Flight number for travel events (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterFlightNumber : @"ZZ800",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterFlightNumber = @"flight_number";
+
+/// Group/clan/guild ID (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterGroupID : @"g1",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterGroupID = @"group_id";
+
+/// Item category (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterItemCategory : @"t-shirts",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterItemCategory = @"item_category";
+
+/// Item ID (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterItemID : @"p7654",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterItemID = @"item_id";
+
+/// The Google <a href="https://developers.google.com/places/place-id">Place ID</a> (NSString) that
+/// corresponds to the associated item. Alternatively, you can supply your own custom Location ID.
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterItemLocationID : @"ChIJiyj437sx3YAR9kUWC8QkLzQ",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterItemLocationID = @"item_location_id";
+
+/// Item name (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterItemName : @"abc",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterItemName = @"item_name";
+
+/// Level in game (signed 64-bit integer as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterLevel : @(42),
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterLevel = @"level";
+
+/// Location (NSString). The Google <a href="https://developers.google.com/places/place-id">Place ID
+/// </a> that corresponds to the associated event. Alternatively, you can supply your own custom
+/// Location ID.
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterLocation : @"ChIJiyj437sx3YAR9kUWC8QkLzQ",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterLocation = @"location";
+
+/// The advertising or marketing medium, for example: cpc, banner, email, push. Highly recommended
+/// (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterMedium : @"email",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterMedium = @"medium";
+
+/// Number of nights staying at hotel (signed 64-bit integer as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfNights : @(3),
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterNumberOfNights = @"number_of_nights";
+
+/// Number of passengers traveling (signed 64-bit integer as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfPassengers : @(11),
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterNumberOfPassengers = @"number_of_passengers";
+
+/// Number of rooms for travel events (signed 64-bit integer as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfRooms : @(2),
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterNumberOfRooms = @"number_of_rooms";
+
+/// Flight or Travel origin (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterOrigin : @"Mountain View, CA",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterOrigin = @"origin";
+
+/// Purchase price (double as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterPrice : @(1.0),
+///       kFIRParameterCurrency : @"USD",  // e.g. $1.00 USD
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterPrice = @"price";
+
+/// Purchase quantity (signed 64-bit integer as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterQuantity : @(1),
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterQuantity = @"quantity";
+
+/// Score in game (signed 64-bit integer as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterScore : @(4200),
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterScore = @"score";
+
+/// The search string/keywords used (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterSearchTerm : @"periodic table",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterSearchTerm = @"search_term";
+
+/// Shipping cost (double as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterShipping : @(9.50),
+///       kFIRParameterCurrency : @"USD",  // e.g. $9.50 USD
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterShipping = @"shipping";
+
+/// Sign up method (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterSignUpMethod : @"google",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterSignUpMethod = @"sign_up_method";
+
+/// The origin of your traffic, such as an Ad network (for example, google) or partner (urban
+/// airship). Identify the advertiser, site, publication, etc. that is sending traffic to your
+/// property. Highly recommended (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterSource : @"InMobi",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterSource = @"source";
+
+/// The departure date, check-in date or rental start date for the item. This should be in
+/// YYYY-MM-DD format (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterStartDate : @"2015-09-14",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterStartDate = @"start_date";
+
+/// Tax amount (double as NSNumber).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterTax : @(1.0),
+///       kFIRParameterCurrency : @"USD",  // e.g. $1.00 USD
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterTax = @"tax";
+
+/// If you're manually tagging keyword campaigns, you should use utm_term to specify the keyword
+/// (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterTerm : @"game",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterTerm = @"term";
+
+/// A single ID for a ecommerce group transaction (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterTransactionID : @"ab7236dd9823",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterTransactionID = @"transaction_id";
+
+/// Travel class (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterTravelClass : @"business",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterTravelClass = @"travel_class";
+
+/// A context-specific numeric value which is accumulated automatically for each event type. This is
+/// a general purpose parameter that is useful for accumulating a key metric that pertains to an
+/// event. Examples include revenue, distance, time and points. Value should be specified as signed
+/// 64-bit integer or double as NSNumber. Notes: Values for pre-defined currency-related events
+/// (such as @c kFIREventAddToCart) should be supplied using double as NSNumber and must be
+/// accompanied by a @c kFIRParameterCurrency parameter. The valid range of accumulated values is
+/// [-9,223,372,036,854.77, 9,223,372,036,854.77].
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterValue : @(3.99),
+///       kFIRParameterCurrency : @"USD",  // e.g. $3.99 USD
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterValue = @"value";
+
+/// Name of virtual currency type (NSString).
+/// <pre>
+///     NSDictionary *params = @{
+///       kFIRParameterVirtualCurrencyName : @"virtual_currency_name",
+///       // ...
+///     };
+/// </pre>
+static NSString *const kFIRParameterVirtualCurrencyName = @"virtual_currency_name";

+ 13 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRUserPropertyNames.h

@@ -0,0 +1,13 @@
+/// @file FIRUserPropertyNames.h
+///
+/// Predefined user property names.
+///
+/// A UserProperty is an attribute that describes the app-user. By supplying UserProperties, you can
+/// later analyze different behaviors of various segments of your userbase. You may supply up to 25
+/// unique UserProperties per app, and you can use the name and value of your choosing for each one.
+/// UserProperty names can be up to 24 characters long, may only contain alphanumeric characters and
+/// underscores ("_"), and must start with an alphabetic character. UserProperty values can be up to
+/// 36 characters long. The "firebase_" prefix is reserved and should not be used.
+
+/// The method used to sign in. For example, "google", "facebook" or "twitter".
+static NSString *const kFIRUserPropertySignUpMethod = @"sign_up_method";

+ 9 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FirebaseAnalytics.h

@@ -0,0 +1,9 @@
+#import "FIRAnalyticsConfiguration.h"
+#import "FIRApp.h"
+#import "FIRConfiguration.h"
+#import "FIROptions.h"
+#import "FIRAnalytics+AppDelegate.h"
+#import "FIRAnalytics.h"
+#import "FIREventNames.h"
+#import "FIRParameterNames.h"
+#import "FIRUserPropertyNames.h"

+ 10 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Modules/module.modulemap

@@ -0,0 +1,10 @@
+framework module FirebaseAnalytics {
+  umbrella header "FirebaseAnalytics.h"
+  export *
+  module * { export *}
+  link "sqlite3"
+  link "z"
+  link framework "CoreGraphics"
+  link framework "Foundation"
+  link framework "UIKit"
+}

BIN
RedAnt ERP Mobile/GoogleAnalytics/FirebaseCore/Frameworks/FirebaseCore.framework/FirebaseCore


+ 38 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseCore/Frameworks/FirebaseCore.framework/Headers/FIRAnalyticsConfiguration.h

@@ -0,0 +1,38 @@
+#import <Foundation/Foundation.h>
+
+/**
+ * This class provides configuration fields for Firebase Analytics.
+ */
+@interface FIRAnalyticsConfiguration : NSObject
+
+/**
+ * Returns the shared instance of FIRAnalyticsConfiguration.
+ */
++ (FIRAnalyticsConfiguration *)sharedInstance;
+
+/**
+ * Sets the minimum engagement time in seconds required to start a new session. The default value
+ * is 10 seconds.
+ */
+- (void)setMinimumSessionInterval:(NSTimeInterval)minimumSessionInterval;
+
+/**
+ * Sets the interval of inactivity in seconds that terminates the current session. The default
+ * value is 1800 seconds (30 minutes).
+ */
+- (void)setSessionTimeoutInterval:(NSTimeInterval)sessionTimeoutInterval;
+
+/**
+ * Sets whether analytics collection is enabled for this app on this device. This setting is
+ * persisted across app sessions. By default it is enabled.
+ */
+- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled;
+
+/**
+ * Deprecated. Sets whether measurement and reporting are enabled for this app on this device. By
+ * default they are enabled.
+ */
+- (void)setIsEnabled:(BOOL)isEnabled
+    DEPRECATED_MSG_ATTRIBUTE("Use setAnalyticsCollectionEnabled: instead.");
+
+@end

+ 98 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseCore/Frameworks/FirebaseCore.framework/Headers/FIRApp.h

@@ -0,0 +1,98 @@
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+@class FIROptions;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** A block that takes a BOOL and has no return value. */
+typedef void (^FIRAppVoidBoolCallback)(BOOL success);
+
+/**
+ * The entry point of Firebase SDKs.
+ *
+ * Initialize and configure FIRApp using +[FIRApp configure]
+ * or other customized ways as shown below.
+ *
+ * The logging system has two modes: default mode and debug mode. In default mode, only logs with
+ * log level Notice, Warning and Error will be sent to device. In debug mode, all logs will be sent
+ * to device. The log levels that Firebase uses are consistent with the ASL log levels.
+ *
+ * Enable debug mode by passing the -FIRDebugEnabled argument to the application. You can add this
+ * argument in the application's Xcode scheme. When debug mode is enabled via -FIRDebugEnabled,
+ * further executions of the application will also be in debug mode. In order to return to default
+ * mode, you must explicitly disable the debug mode with the application argument -FIRDebugDisabled.
+ *
+ * It is also possible to change the default logging level in code by calling setLoggerLevel: on
+ * the FIRConfiguration interface.
+ */
+@interface FIRApp : NSObject
+
+/**
+ * Configures a default Firebase app. Raises an exception if any configuration step fails. The
+ * default app is named "__FIRAPP_DEFAULT". This method should be called after the app is launched
+ * and before using Firebase services. This method is thread safe.
+ */
++ (void)configure;
+
+/**
+ * Configures the default Firebase app with the provided options. The default app is named
+ * "__FIRAPP_DEFAULT". Raises an exception if any configuration step fails. This method is thread
+ * safe.
+ *
+ * @param options The Firebase application options used to configure the service.
+ */
++ (void)configureWithOptions:(FIROptions *)options;
+
+/**
+ * Configures a Firebase app with the given name and options. Raises an exception if any
+ * configuration step fails. This method is thread safe.
+ *
+ * @param name The application's name given by the developer. The name should should only contain
+               Letters, Numbers and Underscore.
+ * @param options The Firebase application options used to configure the services.
+ */
++ (void)configureWithName:(NSString *)name options:(FIROptions *)options;
+
+/**
+ * Returns the default app, or nil if the default app does not exist.
+ */
++ (nullable FIRApp *)defaultApp NS_SWIFT_NAME(defaultApp());
+
+/**
+ * Returns a previously created FIRApp instance with the given name, or nil if no such app exists.
+ * This method is thread safe.
+ */
++ (nullable FIRApp *)appNamed:(NSString *)name;
+
+/**
+ * Returns the set of all extant FIRApp instances, or nil if there are no FIRApp instances. This
+ * method is thread safe.
+ */
++ (nullable NSDictionary *)allApps;
+
+/**
+ * Cleans up the current FIRApp, freeing associated data and returning its name to the pool for
+ * future use. This method is thread safe.
+ */
+- (void)deleteApp:(FIRAppVoidBoolCallback)completion;
+
+/**
+ * FIRApp instances should not be initialized directly. Call +[FIRApp configure],
+ * +[FIRApp configureWithOptions:], or +[FIRApp configureWithNames:options:] directly.
+ */
+- (instancetype)init NS_UNAVAILABLE;
+
+/**
+ * Gets the name of this app.
+ */
+@property(nonatomic, copy, readonly) NSString *name;
+
+/**
+ * Gets the options for this app.
+ */
+@property(nonatomic, readonly) FIROptions *options;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 52 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseCore/Frameworks/FirebaseCore.framework/Headers/FIRConfiguration.h

@@ -0,0 +1,52 @@
+#import <Foundation/Foundation.h>
+
+#import "FIRAnalyticsConfiguration.h"
+#import "FIRLoggerLevel.h"
+
+/**
+ * The log levels used by FIRConfiguration.
+ */
+typedef NS_ENUM(NSInteger, FIRLogLevel) {
+  /** Error */
+  kFIRLogLevelError __deprecated = 0,
+  /** Warning */
+  kFIRLogLevelWarning __deprecated,
+  /** Info */
+  kFIRLogLevelInfo __deprecated,
+  /** Debug */
+  kFIRLogLevelDebug __deprecated,
+  /** Assert */
+  kFIRLogLevelAssert __deprecated,
+  /** Max */
+  kFIRLogLevelMax __deprecated = kFIRLogLevelAssert
+} DEPRECATED_MSG_ATTRIBUTE(
+    "Use -FIRDebugEnabled and -FIRDebugDisabled or setLoggerLevel. See FIRApp.h for more details.");
+
+/**
+ * This interface provides global level properties that the developer can tweak, and the singleton
+ * of the Firebase Analytics configuration class.
+ */
+@interface FIRConfiguration : NSObject
+
+/** Returns the shared configuration object. */
++ (FIRConfiguration *)sharedInstance;
+
+/** The configuration class for Firebase Analytics. */
+@property(nonatomic, readwrite) FIRAnalyticsConfiguration *analyticsConfiguration;
+
+/** Global log level. Defaults to kFIRLogLevelError. */
+@property(nonatomic, readwrite, assign) FIRLogLevel logLevel DEPRECATED_MSG_ATTRIBUTE(
+    "Use -FIRDebugEnabled and -FIRDebugDisabled or setLoggerLevel. See FIRApp.h for more details.");
+
+/**
+ * Sets the logging level for internal Firebase logging. Firebase will only log messages
+ * that are logged at or below loggerLevel. The messages are logged both to the Xcode
+ * console and to the device's log. Note that if an app is running from AppStore, it will
+ * never log above FIRLoggerLevelNotice even if loggerLevel is set to a higher (more verbose)
+ * setting.
+ *
+ * @param loggerLevel The maximum logging level. The default level is set to FIRLoggerLevelNotice.
+ */
+- (void)setLoggerLevel:(FIRLoggerLevel)loggerLevel;
+
+@end

+ 12 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseCore/Frameworks/FirebaseCore.framework/Headers/FIRLoggerLevel.h

@@ -0,0 +1,12 @@
+/**
+ * The log levels used by internal logging.
+ */
+typedef NS_ENUM(NSInteger, FIRLoggerLevel) {
+  FIRLoggerLevelError = 3 /*ASL_LEVEL_ERR*/,
+  FIRLoggerLevelWarning = 4 /*ASL_LEVEL_WARNING*/,
+  FIRLoggerLevelNotice = 5 /*ASL_LEVEL_NOTICE*/,
+  FIRLoggerLevelInfo = 6 /*ASL_LEVEL_INFO*/,
+  FIRLoggerLevelDebug = 7 /*ASL_LEVEL_DEBUG*/,
+  FIRLoggerLevelMin = FIRLoggerLevelError,
+  FIRLoggerLevelMax = FIRLoggerLevelDebug
+};

+ 93 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseCore/Frameworks/FirebaseCore.framework/Headers/FIROptions.h

@@ -0,0 +1,93 @@
+#import <Foundation/Foundation.h>
+
+/**
+ * This class provides constant fields of Google APIs.
+ */
+@interface FIROptions : NSObject<NSCopying>
+
+/**
+ * Returns the default options.
+ */
++ (FIROptions *)defaultOptions;
+
+/**
+ * An iOS API key used for authenticating requests from your app, e.g.
+ * @"AIzaSyDdVgKwhZl0sTTTLZ7iTmt1r3N2cJLnaDk", used to identify your app to Google servers.
+ */
+@property(nonatomic, readonly, copy) NSString *APIKey;
+
+/**
+ * The OAuth2 client ID for iOS application used to authenticate Google users, for example
+ * @"12345.apps.googleusercontent.com", used for signing in with Google.
+ */
+@property(nonatomic, readonly, copy) NSString *clientID;
+
+/**
+ * The tracking ID for Google Analytics, e.g. @"UA-12345678-1", used to configure Google Analytics.
+ */
+@property(nonatomic, readonly, copy) NSString *trackingID;
+
+/**
+ * The Project Number from the Google Developer's console, for example @"012345678901", used to
+ * configure Google Cloud Messaging.
+ */
+@property(nonatomic, readonly, copy) NSString *GCMSenderID;
+
+/**
+ * The Project ID from the Firebase console, for example @"abc-xyz-123". Currently only populated
+ * when using [FIROptions defaultOptions].
+ */
+@property(nonatomic, readonly, copy) NSString *projectID;
+
+/**
+ * The Android client ID used in Google AppInvite when an iOS app has its Android version, for
+ * example @"12345.apps.googleusercontent.com".
+ */
+@property(nonatomic, readonly, copy) NSString *androidClientID;
+
+/**
+ * The Google App ID that is used to uniquely identify an instance of an app.
+ */
+@property(nonatomic, readonly, copy) NSString *googleAppID;
+
+/**
+ * The database root URL, e.g. @"http://abc-xyz-123.firebaseio.com".
+ */
+@property(nonatomic, readonly, copy) NSString *databaseURL;
+
+/**
+ * The URL scheme used to set up Durable Deep Link service.
+ */
+@property(nonatomic, readwrite, copy) NSString *deepLinkURLScheme;
+
+/**
+ * The Google Cloud Storage bucket name, e.g. @"abc-xyz-123.storage.firebase.com".
+ */
+@property(nonatomic, readonly, copy) NSString *storageBucket;
+
+/**
+ * Initializes a customized instance of FIROptions with keys. googleAppID, bundleID and GCMSenderID
+ * are required. Other keys may required for configuring specific services.
+ */
+- (instancetype)initWithGoogleAppID:(NSString *)googleAppID
+                           bundleID:(NSString *)bundleID
+                        GCMSenderID:(NSString *)GCMSenderID
+                             APIKey:(NSString *)APIKey
+                           clientID:(NSString *)clientID
+                         trackingID:(NSString *)trackingID
+                    androidClientID:(NSString *)androidClientID
+                        databaseURL:(NSString *)databaseURL
+                      storageBucket:(NSString *)storageBucket
+                  deepLinkURLScheme:(NSString *)deepLinkURLScheme;
+
+/**
+ * Initializes a customized instance of FIROptions from the file at the given plist file path.
+ * For example,
+ * NSString *filePath =
+ *     [[NSBundle mainBundle] pathForResource:@"GoogleService-Info" ofType:@"plist"];
+ * FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath];
+ * Returns nil if the plist file does not exist or is invalid.
+ */
+- (instancetype)initWithContentsOfFile:(NSString *)plistPath;
+
+@end

+ 5 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseCore/Frameworks/FirebaseCore.framework/Headers/FirebaseCore.h

@@ -0,0 +1,5 @@
+#import "FIRAnalyticsConfiguration.h"
+#import "FIRApp.h"
+#import "FIRConfiguration.h"
+#import "FIRLoggerLevel.h"
+#import "FIROptions.h"

+ 8 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseCore/Frameworks/FirebaseCore.framework/Modules/module.modulemap

@@ -0,0 +1,8 @@
+framework module FirebaseCore {
+  umbrella header "FirebaseCore.h"
+  export *
+  module * { export *}
+  link "z"
+  link framework "Foundation"
+  link framework "UIKit"
+}

+ 33 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseInstanceID/CHANGELOG.md

@@ -0,0 +1,33 @@
+# 2017-01-31 -- v1.0.9
+
+- Removed an error being mistakenly logged to the console.
+
+# 2016-07-06 -- v1.0.8
+
+- Don't store InstanceID plists in Documents folder.
+
+# 2016-06-19 -- v1.0.7
+
+- Fix remote-notifications warning on app submission.
+
+# 2016-05-16 -- v1.0.6
+
+- Fix CocoaPod linter issues for InstanceID pod.
+
+# 2016-05-13 -- v1.0.5
+
+- Fix Authorization errors for InstanceID tokens.
+
+# 2016-05-11 -- v1.0.4
+
+- Reduce wait for InstanceID token during parallel requests.
+
+# 2016-04-18 -- v1.0.3
+
+- Change flag to disable swizzling to *FirebaseAppDelegateProxyEnabled*.
+- Fix incessant Keychain errors while accessing InstanceID.
+- Fix max retries for fetching IID token.
+
+# 2016-04-18 -- v1.0.2
+
+- Register for remote notifications on iOS8+ in the SDK itself.

BIN
RedAnt ERP Mobile/GoogleAnalytics/FirebaseInstanceID/Frameworks/FirebaseInstanceID.framework/FirebaseInstanceID


+ 245 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseInstanceID/Frameworks/FirebaseInstanceID.framework/Headers/FIRInstanceID.h

@@ -0,0 +1,245 @@
+#import <Foundation/Foundation.h>
+
+/**
+ *  @memberof FIRInstanceID
+ *
+ *  The scope to be used when fetching/deleting a token for Firebase Messaging.
+ */
+FOUNDATION_EXPORT NSString * __nonnull const kFIRInstanceIDScopeFirebaseMessaging;
+
+/**
+ *  Called when the system determines that tokens need to be refreshed.
+ *  This method is also called if Instance ID has been reset in which
+ *  case, tokens and FCM topic subscriptions also need to be refreshed.
+ *
+ *  Instance ID service will throttle the refresh event across all devices
+ *  to control the rate of token updates on application servers.
+ */
+FOUNDATION_EXPORT NSString * __nonnull const kFIRInstanceIDTokenRefreshNotification;
+
+/**
+ *  @related FIRInstanceID
+ *
+ *  The completion handler invoked when the InstanceID token returns. If
+ *  the call fails we return the appropriate `error code` as described below.
+ *
+ *  @param token The valid token as returned by InstanceID backend.
+ *
+ *  @param error The error describing why generating a new token
+ *               failed. See the error codes below for a more detailed
+ *               description.
+ */
+typedef void(^FIRInstanceIDTokenHandler)( NSString * __nullable token, NSError * __nullable error);
+
+
+/**
+ *  @related FIRInstanceID
+ *
+ *  The completion handler invoked when the InstanceID `deleteToken` returns. If
+ *  the call fails we return the appropriate `error code` as described below
+ *
+ *  @param error The error describing why deleting the token failed.
+ *               See the error codes below for a more detailed description.
+ */
+typedef void(^FIRInstanceIDDeleteTokenHandler)(NSError * __nullable error);
+
+/**
+ *  @related FIRInstanceID
+ *
+ *  The completion handler invoked when the app identity is created. If the
+ *  identity wasn't created for some reason we return the appropriate error code.
+ *
+ *  @param identity A valid identity for the app instance, nil if there was an error
+ *                  while creating an identity.
+ *  @param error    The error if fetching the identity fails else nil.
+ */
+typedef void(^FIRInstanceIDHandler)(NSString * __nullable identity, NSError * __nullable error);
+
+/**
+ *  @related FIRInstanceID
+ *
+ *  The completion handler invoked when the app identity and all the tokens associated
+ *  with it are deleted. Returns a valid error object in case of failure else nil.
+ *
+ *  @param error The error if deleting the identity and all the tokens associated with
+ *               it fails else nil.
+ */
+typedef void(^FIRInstanceIDDeleteHandler)(NSError * __nullable error);
+
+/**
+ * @enum FIRInstanceIDError
+ */
+typedef NS_ENUM(NSUInteger, FIRInstanceIDError) {
+  // Http related errors.
+
+  /// Unknown error.
+  FIRInstanceIDErrorUnknown = 0,
+
+  /// Auth Error -- GCM couldn't validate request from this client.
+  FIRInstanceIDErrorAuthentication = 1,
+
+  /// NoAccess -- InstanceID service cannot be accessed.
+  FIRInstanceIDErrorNoAccess = 2,
+
+  /// Timeout -- Request to InstanceID backend timed out.
+  FIRInstanceIDErrorTimeout = 3,
+
+  /// Network -- No network available to reach the servers.
+  FIRInstanceIDErrorNetwork = 4,
+
+  /// OperationInProgress -- Another similar operation in progress,
+  /// bailing this one.
+  FIRInstanceIDErrorOperationInProgress = 5,
+
+  /// InvalidRequest -- Some parameters of the request were invalid.
+  FIRInstanceIDErrorInvalidRequest = 7,
+};
+
+/**
+ *  The APNS token type for the app. If the token type is set to `UNKNOWN`
+ *  InstanceID will implicitly try to figure out what the actual token type
+ *  is from the provisioning profile.
+ */
+typedef NS_ENUM(NSInteger, FIRInstanceIDAPNSTokenType) {
+  /// Unknown token type.
+  FIRInstanceIDAPNSTokenTypeUnknown,
+  /// Sandbox token type.
+  FIRInstanceIDAPNSTokenTypeSandbox,
+  /// Production token type.
+  FIRInstanceIDAPNSTokenTypeProd,
+};
+
+/**
+ *  Instance ID provides a unique identifier for each app instance and a mechanism
+ *  to authenticate and authorize actions (for example, sending a GCM message).
+ *
+ *  Instance ID is long lived but, may be reset if the device is not used for
+ *  a long time or the Instance ID service detects a problem.
+ *  If Instance ID is reset, the app will be notified via
+ *  `kFIRInstanceIDTokenRefreshNotification`.
+ *
+ *  If the Instance ID has become invalid, the app can request a new one and
+ *  send it to the app server.
+ *  To prove ownership of Instance ID and to allow servers to access data or
+ *  services associated with the app, call
+ *  `[FIRInstanceID tokenWithAuthorizedEntity:scope:options:handler]`.
+ */
+@interface FIRInstanceID : NSObject
+
+/**
+ *  FIRInstanceID.
+ *
+ *  @return A shared instance of FIRInstanceID.
+ */
++ (nonnull instancetype)instanceID NS_SWIFT_NAME(instanceID());
+
+/**
+ *  Unavailable. Use +instanceID instead.
+ */
+- (nonnull instancetype)init __attribute__((unavailable("Use +instanceID instead.")));
+
+/**
+ *  Set APNS token for the application. This APNS token will be used to register
+ *  with Firebase Messaging using `token` or
+ *  `tokenWithAuthorizedEntity:scope:options:handler`. If the token type is set to
+ *  `FIRInstanceIDAPNSTokenTypeUnknown` InstanceID will read the provisioning profile
+ *  to find out the token type.
+ *
+ *  @param token The APNS token for the application.
+ *  @param type  The APNS token type for the above token.
+ */
+- (void)setAPNSToken:(nonnull NSData *)token
+                type:(FIRInstanceIDAPNSTokenType)type;
+
+#pragma mark - Tokens
+
+/**
+ *  Returns a Firebase Messaging scoped token for the firebase app.
+ *
+ *  @return Null Returns null if the device has not yet been registerd with
+ *          Firebase Message else returns a valid token.
+ */
+- (nullable NSString *)token;
+
+/**
+ *  Returns a token that authorizes an Entity (example: cloud service) to perform
+ *  an action on behalf of the application identified by Instance ID.
+ *
+ *  This is similar to an OAuth2 token except, it applies to the
+ *  application instance instead of a user.
+ *
+ *  This is an asynchronous call. If the token fetching fails for some reason
+ *  we invoke the completion callback with nil `token` and the appropriate
+ *  error.
+ *
+ *  Note, you can only have one `token` or `deleteToken` call for a given
+ *  authorizedEntity and scope at any point of time. Making another such call with the
+ *  same authorizedEntity and scope before the last one finishes will result in an
+ *  error with code `OperationInProgress`.
+ *
+ *  @see FIRInstanceID deleteTokenWithAuthorizedEntity:scope:handler:
+ *
+ *  @param authorizedEntity Entity authorized by the token.
+ *  @param scope            Action authorized for authorizedEntity.
+ *  @param options          The extra options to be sent with your token request. The
+ *                          value for the `apns_token` should be the NSData object
+ *                          passed to UIApplication's
+ *                          `didRegisterForRemoteNotificationsWithDeviceToken` method.
+ *                          All other keys and values in the options dict need to be
+ *                          instances of NSString or else they will be discarded. Bundle
+ *                          keys starting with 'GCM.' and 'GOOGLE.' are reserved.
+ *  @param handler          The callback handler which is invoked when the token is
+ *                          successfully fetched. In case of success a valid `token` and
+ *                          `nil` error are returned. In case of any error the `token`
+ *                          is nil and a valid `error` is returned. The valid error
+ *                          codes have been documented above.
+ */
+- (void)tokenWithAuthorizedEntity:(nonnull NSString *)authorizedEntity
+                            scope:(nonnull NSString *)scope
+                          options:(nullable NSDictionary *)options
+                          handler:(nonnull FIRInstanceIDTokenHandler)handler;
+
+/**
+ *  Revokes access to a scope (action) for an entity previously
+ *  authorized by `[FIRInstanceID tokenWithAuthorizedEntity:scope:options:handler]`.
+ *
+ *  This is an asynchronous call. Call this on the main thread since InstanceID lib
+ *  is not thread safe. In case token deletion fails for some reason we invoke the
+ *  `handler` callback passed in with the appropriate error code.
+ *
+ *  Note, you can only have one `token` or `deleteToken` call for a given
+ *  authorizedEntity and scope at a point of time. Making another such call with the
+ *  same authorizedEntity and scope before the last one finishes will result in an error
+ *  with code `OperationInProgress`.
+ *
+ *  @param authorizedEntity Entity that must no longer have access.
+ *  @param scope            Action that entity is no longer authorized to perform.
+ *  @param handler          The handler that is invoked once the unsubscribe call ends.
+ *                          In case of error an appropriate error object is returned
+ *                          else error is nil.
+ */
+- (void)deleteTokenWithAuthorizedEntity:(nonnull NSString *)authorizedEntity
+                                  scope:(nonnull NSString *)scope
+                                handler:(nonnull FIRInstanceIDDeleteTokenHandler)handler;
+
+#pragma mark - Identity
+
+/**
+ *  Asynchronously fetch a stable identifier that uniquely identifies the app
+ *  instance. If the identifier has been revoked or has expired, this method will
+ *  return a new identifier.
+ *
+ *
+ *  @param handler The handler to invoke once the identifier has been fetched.
+ *                 In case of error an appropriate error object is returned else
+ *                 a valid identifier is returned and a valid identifier for the
+ *                 application instance.
+ */
+- (void)getIDWithHandler:(nonnull FIRInstanceIDHandler)handler;
+
+/**
+ *  Resets Instance ID and revokes all tokens.
+ */
+- (void)deleteIDWithHandler:(nonnull FIRInstanceIDDeleteHandler)handler;
+
+@end

+ 1 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseInstanceID/Frameworks/FirebaseInstanceID.framework/Headers/FirebaseInstanceID.h

@@ -0,0 +1 @@
+#import "FIRInstanceID.h"

+ 7 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseInstanceID/Frameworks/FirebaseInstanceID.framework/Modules/module.modulemap

@@ -0,0 +1,7 @@
+framework module FirebaseInstanceID {
+  umbrella header "FirebaseInstanceID.h"
+  export *
+  module * { export *}
+  link framework "Foundation"
+  link framework "UIKit"
+}

+ 10 - 0
RedAnt ERP Mobile/GoogleAnalytics/FirebaseInstanceID/README.md

@@ -0,0 +1,10 @@
+# InstanceID SDK for iOS
+
+Instance ID provides a unique ID per instance of your apps and also provides a
+mechanism to authenticate and authorize actions, like sending messages via
+Firebase Cloud Messaging (FCM).
+
+
+Please visit [our developer
+site](https://developers.google.com/instance-id/) for integration instructions,
+documentation, support information, and terms of service.

BIN
RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLAnalytics.framework/GGLAnalytics


+ 3 - 0
RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLAnalytics.framework/Headers/GGLAnalytics.h

@@ -0,0 +1,3 @@
+// Generated umbrella header for GGLAnalytics.
+
+#import "GGLContext+Analytics.h"

+ 39 - 0
RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLAnalytics.framework/Headers/GGLContext+Analytics.h

@@ -0,0 +1,39 @@
+#import <GGLCore/GGLCore.h>
+
+@protocol GAITracker;
+
+/**
+ * The Google Analytic dispatch time interval in seconds when using a simulator. Setting it to one
+ * second by default means the tracking information will be automatically dispatched every second
+ * when using an iPhone simulator.
+ *
+ * If running on a device, uses the default time interval set by Google
+ * Analytics, which is two minutes.
+ */
+extern const NSTimeInterval kSimulatorDispatchIntervalInSeconds;
+
+/**
+ * This category extends |GGLContext| with the analytics service. Import
+ * GGLContext+Analytics to use Google Analytics in your app.
+ *
+ * [GAI sharedInstance] and [[GAI sharedInstance] defaultTracker] should be ready to use after
+ * -[[GGLContext sharedInstance] configureWithError:] is called. The defaultTracker can also be
+ * fetched here through [GGLContext sharedInstance].tracker. The tracking ID of the tracker is the
+ * one defined in GoogleService-Info.plist.
+ *
+ * @see GGLContext
+ */
+@interface GGLContext (Analytics)
+
+/**
+ * Retrieve a configured GAITracker instance.
+ *
+ * Note that [[GAI sharedInstance] defaultTracker] is the first initialized tracker. If a developer
+ * initializes a tracker before calling -[[GGLContext sharedInstance] configureWithError:],
+ * -[[GAI sharedInstance] defaultTracker] is the one initialized first. The one initialized through
+ * GGLContext can be accessed by either [[GAI sharedInstance] trackerWithTrackingId:@"UA-XXXX-Y"]
+ * or [GGLContext sharedInstance].tracker.
+ */
+@property(nonatomic, readonly, strong) id<GAITracker> tracker;
+
+@end

+ 8 - 0
RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLAnalytics.framework/Modules/module.modulemap

@@ -0,0 +1,8 @@
+framework module GGLAnalytics {
+
+  export *
+
+  umbrella header "GGLAnalytics.h"
+
+  header "GGLContext+Analytics.h"
+}

BIN
RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLCore.framework/GGLCore


+ 45 - 0
RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLCore.framework/Headers/GGLConfiguration.h

@@ -0,0 +1,45 @@
+#import <Foundation/Foundation.h>
+
+/**
+ * This class provides configuration fields of Google APIs.
+ */
+@interface GGLConfiguration : NSObject
+
+/**
+ * The OAuth2 client ID for the iOS application, used to authenticate Google users. For example
+ * @"12345.apps.googleusercontent.com".
+ */
+@property(nonatomic, readonly, copy) NSString *clientID;
+
+/**
+ * The tracking ID for Google Analytics, e.g. @"UA-12345678-1", used to configure Google Analytics.
+ */
+@property(nonatomic, readonly, copy) NSString *trackingID;
+
+/**
+ * The Google App ID that is used to uniquely identify an instance of an app.
+ */
+@property(nonatomic, readonly, copy) NSString *googleAppID;
+
+/**
+ * Whether or not Analytics was enabled in the developer console.
+ */
+@property(nonatomic, readonly) BOOL isAnalyticsEnabled;
+
+/**
+ * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in
+ * GoogleService-Info.plist.
+ */
+@property(nonatomic, readonly) BOOL isMeasurementEnabled;
+
+/**
+ * Whether or not SignIn was enabled in the developer console.
+ */
+@property(nonatomic, readonly) BOOL isSignInEnabled;
+
+/**
+ * The version ID of the client library, e.g. @"1100000".
+ */
+@property(nonatomic, readonly, copy) NSString *libraryVersionID;
+
+@end

+ 55 - 0
RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLCore.framework/Headers/GGLContext.h

@@ -0,0 +1,55 @@
+#import <Foundation/Foundation.h>
+
+@class GGLConfiguration;
+
+/**
+ * Main entry point for Google API core configuration. Google services including Analytics and
+ * SignIn can be configured via this class and its categories. See GGLContext+<ServiceName> for
+ * details on the individual APIs.
+ *
+ * Once the appropriate categories are imported, you can configure all services via the
+ * |configureWithError:| method. For example:
+ *
+ * <pre>
+ * NSError *configureError;
+ * [[GGLContext sharedInstance] configureWithError:&configureError];
+ * if (configureError != nil) {
+ *   NSLog(@"Error configuring the Google context: %@", configureError);
+ * }
+ * </pre>
+ *
+ * The method |configureWithError:| will read from the file GoogleServices-Info.plist bundled with
+ * your app target for the keys to configure each individual API. To generate your
+ * GoogleServices-Info.plist, please go to https://developers.google.com/mobile/add
+ *
+ * @see GGLContext (Analytics)
+ * @see GGLContext (SignIn)
+ */
+@interface GGLContext : NSObject
+
+/**
+ * The configuration details for various Google APIs.
+ */
+@property(nonatomic, readonly) GGLConfiguration *configuration;
+
+/**
+ * Gets the singleton context.
+ * @return The singleton context.
+ */
++ (instancetype)sharedInstance;
+
+/**
+ * Configures integrated Google services Google Sign In and Google Analytics.
+ *
+ * This method should be called after the app is launched and before using other Google services.
+ * The services will be available in categories that extend this class, such as
+ * GGLContext+Analytics.
+ *
+ * @param error An ouput error, which will be populated if there was an error configuring the Google
+ *              services. Must not be nil.
+ *
+ * @warning error must not be nil.
+ */
+- (void)configureWithError:(NSError **)error;
+
+@end

+ 6 - 0
RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLCore.framework/Headers/GGLCore.h

@@ -0,0 +1,6 @@
+// Generated umbrella header for GGLCore.
+
+#import "GGLConfiguration.h"
+#import "GGLContext.h"
+#import "GGLErrorCode.h"
+#import "GMRConfiguration.h"

+ 45 - 0
RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLCore.framework/Headers/GGLErrorCode.h

@@ -0,0 +1,45 @@
+/** Error codes in Greenhouse error domain. */
+typedef enum {
+  /**
+   * Operation succeeded.
+   */
+  kGGLErrorCodeSucceeded = 0,
+  /**
+   * Default failure error code. This is a catch all error and indicates something has gone very
+   * wrong. There is no remediation for this case.
+   **/
+  kGGLErrorCodeUnknownFailure = -1,
+
+  /**
+   * Indicates that the calling method did not do anything in response to the call. This occurs in
+   * situations where the caller asked state to be mutated into its current state or selector wasn't
+   * present but it isn't considered a critical failure.
+   */
+  kGGLErrorCodeNoOp = -2,
+
+  /**
+   * Indicates that configuration failed. The userInfo dictionary will contain more information
+   * about the failure.
+   */
+  kGGLErrorCodeConfigurationFailed = -3,
+
+  // 100 series error codes are for GGLContext
+
+  /**
+   * Configuration of Analytics subspec failed. Additional details on the reason for the failure
+   * appear in the related NSError.
+   */
+  kGGLErrorCodeAnalyticsSubspecConfigFailed = -102,
+
+  /**
+   * Configuration of SignIn subspec failed. Additional details on the reason for the failure appear
+   * in the related NSError.
+   */
+  kGGLErrorCodeSignInSubspecConfigFailed = -105,
+
+  /**
+   * Missing expected subspec error.
+   */
+  kGGLErrorCodeMissingExpectedSubspec = -106,
+
+} GGLErrorCode;

+ 19 - 0
RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLCore.framework/Headers/GMRConfiguration.h

@@ -0,0 +1,19 @@
+#import <Foundation/Foundation.h>
+
+/**
+ * This class provides configuration fields for Google Measurement.
+ */
+@interface GMRConfiguration : NSObject
+
+/**
+ * Returns the shared instance of GMRConfiguration.
+ */
++ (GMRConfiguration *)sharedInstance;
+
+/**
+ * Sets whether measurement and reporting are enabled for this app on this device. By default they
+ * are enabled.
+ */
+- (void)setIsEnabled:(BOOL)isEnabled;
+
+@end

+ 14 - 0
RedAnt ERP Mobile/GoogleAnalytics/Google/Frameworks/GGLCore.framework/Modules/module.modulemap

@@ -0,0 +1,14 @@
+framework module GGLCore {
+
+  export *
+
+  umbrella header "GGLCore.h"
+
+  header "GGLConfiguration.h"
+  header "GGLContext.h"
+  header "GGLErrorCode.h"
+  header "GMRConfiguration.h"
+
+  link framework "SystemConfiguration"
+  link framework "UIKit"
+}

+ 15 - 0
RedAnt ERP Mobile/GoogleAnalytics/Google/Headers/Analytics.h

@@ -0,0 +1,15 @@
+#import <GGLCore/GGLCore.h>
+
+#import <GGLAnalytics/GGLAnalytics.h>
+
+#import "GAI.h"
+#import "GAIDictionaryBuilder.h"
+#import "GAIEcommerceFields.h"
+#import "GAIEcommerceProduct.h"
+#import "GAIEcommerceProductAction.h"
+#import "GAIEcommercePromotion.h"
+#import "GAIFields.h"
+#import "GAILogger.h"
+#import "GAITrackedViewController.h"
+#import "GAITracker.h"
+

+ 4 - 0
RedAnt ERP Mobile/GoogleAnalytics/Google/Headers/Core.h

@@ -0,0 +1,4 @@
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+#import <GGLCore/GGLCore.h>

+ 5 - 0
RedAnt ERP Mobile/GoogleAnalytics/Google/Headers/ModuleHeaders/Analytics-Module.h

@@ -0,0 +1,5 @@
+#if defined(__has_include)
+# if __has_include(<GGLAnalytics/GGLAnalytics.h>)
+#  include <GGLAnalytics/GGLAnalytics.h>
+# endif
+#endif

+ 5 - 0
RedAnt ERP Mobile/GoogleAnalytics/Google/Headers/ModuleHeaders/Core-Module.h

@@ -0,0 +1,5 @@
+#if defined(__has_include)
+# if __has_include(<GGLCore/GGLCore.h>)
+#  include <GGLCore/GGLCore.h>
+# endif
+#endif

+ 5 - 0
RedAnt ERP Mobile/GoogleAnalytics/Google/Headers/ModuleHeaders/SignIn-Module.h

@@ -0,0 +1,5 @@
+#if defined(__has_include)
+# if __has_include(<GGLSignIn/GGLSignIn.h>)
+#  include <GGLSignIn/GGLSignIn.h>
+# endif
+#endif

+ 15 - 0
RedAnt ERP Mobile/GoogleAnalytics/Google/Headers/module.modulemap

@@ -0,0 +1,15 @@
+module Google {
+  export *
+  module Analytics {
+    header "ModuleHeaders/Analytics-Module.h"
+    export *
+  }
+  module Core {
+    header "ModuleHeaders/Core-Module.h"
+    export *
+  }
+  module SignIn {
+    header "ModuleHeaders/SignIn-Module.h"
+    export *
+  }
+}

+ 66 - 0
RedAnt ERP Mobile/GoogleAnalytics/Google/README.md

@@ -0,0 +1,66 @@
+# Google APIs for iOS
+
+Simplify your iOS development, grow your user base, and monetize more
+effectively with Google services.
+
+Much more information can be found at https://developers.google.com/ios/.
+
+## Install a Google SDK using CocoaPods
+
+Google distributes several iOS specific APIs and SDKs via CocoaPods.
+You can install the CocoaPods tool on OS X by running the following command from
+the terminal. Detailed information is available in the [Getting Started
+guide](https://guides.cocoapods.org/using/getting-started.html#getting-started).
+
+```
+$ sudo gem install cocoapods
+```
+
+## Try out an SDK
+
+You can try any of the SDKs with `pod try`. Run the following command and select
+the SDK you are interested in when prompted:
+
+```
+$ pod try Google
+```
+
+Note that some SDKs may require credentials. More information is available in
+the SDK-specific documentation at https://developers.google.com/ios/.
+
+### Add a Google SDK to your iOS app
+
+CocoaPods is used to install and manage dependencies in existing Xcode projects.
+
+1. Create an Xcode project, and save it to your local machine.
+2. Create a file named `Podfile` in your project directory. This file defines
+   your project's dependencies, and is commonly referred to as a Podspec.
+3. Open `Podfile`, and add your dependencies. A simple Podspec is shown here:
+
+    ```
+    platform :ios, '8.1'
+    pod 'Google'
+    ```
+
+4. Save the file.
+5. Open a terminal and `cd` to the directory containing the Podfile.
+
+    ```
+    $ cd <path-to-project>/project/
+    ```
+
+6. Run the `pod install` command. This will install the SDKs specified in the
+   Podspec, along with any dependencies they may have.
+
+    ```
+    $ pod install
+    ```
+
+7. Open your app's `.xcworkspace` file to launch Xcode.
+   Use this file for all development on your app.
+
+### CocoaPods published by Google
+
+For a complete list of pods published by Google, please visit
+https://cocoapods.org/?q=author%3Agoogle
+

+ 55 - 0
RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalyst.h

@@ -0,0 +1,55 @@
+//
+//  GoogleAnalyst.h
+//  iSales-NPD
+//
+//  Created by Jack on 2017/3/28.
+//  Copyright © 2017年 United Software Applications, Inc. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+/**
+ 
+ 1.     Track all screens and sessions.
+        Network get_json:
+ 
+ 2.     Track user login and timing                  
+ 
+ 
+ 3.     When user clicks on “Add to cart”
+ 
+ 4.     user is just opening a model information to check on the item
+ 
+ 5.     user is using search/filter conditions on the app
+        Search 、Account、Advance Search、Category Filter、Item Search Filter
+ 
+ 6.     If user is browsing a particular category on home screen(new collection, dining…..)
+ 
+ 7.     track the user location of sign-in
+
+ 8.     How long the user used the App
+        AppDelegate
+ 
+ */
+
+@interface GoogleAnalyst : NSObject
+
++ (void)trackScreen:(NSString *)screenName;
+
++ (NSString *)currentTrackScreen;
+
++ (void)trackEventCategory:(NSString *)category action:(NSString *)action label:(NSString *)label value:(NSNumber *)value;
+
++ (void)trackTimingWithCategory:(NSString *)category interval:(NSTimeInterval)loadTime name:(NSString *)name label:(NSString *)label;
+
+
+
++ (void)trackSignInUserID:(NSString *)userID;
+
++ (void)trackSignOut;
+
++ (void)trackProduct:(NSString *)productName action:(NSString *)action count:(NSNumber *)count;
+
+
+
+@end

+ 119 - 0
RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalyst.m

@@ -0,0 +1,119 @@
+//
+//  GoogleAnalyst.m
+//  iSales-NPD
+//
+//  Created by Jack on 2017/3/28.
+//  Copyright © 2017年 United Software Applications, Inc. All rights reserved.
+//
+
+#import "GoogleAnalyst.h"
+#import "Analytics.h"
+#import "iSalesNetwork.h"
+
+@implementation GoogleAnalyst
+
+#pragma mark - Private
+
++ (NSString *)currentDateString {
+    NSDate *date = [NSDate date];
+    NSDateFormatter *formate = [[NSDateFormatter alloc] init];
+    formate.dateFormat = @"YYYY-MM-dd HH:mm:ss";
+    return [formate stringFromDate:date];
+}
+
+#pragma mark - Public
+
++ (void)trackScreen:(NSString *)screenName {
+    
+    if (!screenName.length) {
+        return;
+    }
+    // 屏幕追踪
+    id<GAITracker> tracker = [[GAI sharedInstance] defaultTracker];
+    [tracker set:kGAIScreenName value:screenName];
+    [tracker send:[[GAIDictionaryBuilder createScreenView] build]];
+//    [tracker set:kGAIScreenName value:nil]; // 清除值,直接在追踪器设置值将是持久值,并且会应用于多次匹配。
+    
+}
+
++ (NSString *)currentTrackScreen {
+    return [[[GAI sharedInstance] defaultTracker] get:kGAIScreenName];
+}
+
++ (void)trackEventCategory:(NSString *)category action:(NSString *)action label:(NSString *)label value:(NSNumber *)value {
+    
+    id<GAITracker> tracker = [[GAI sharedInstance] defaultTracker];
+
+    [tracker send:[[GAIDictionaryBuilder createEventWithCategory:category action:action label:label value:value] build]];
+}
+
+
++ (void)trackTimingWithCategory:(NSString *)category interval:(NSTimeInterval)loadTime name:(NSString *)name label:(NSString *)label {
+    
+    id tracker = [[GAI sharedInstance] defaultTracker];
+    
+    // 以毫秒表示的计时值
+    [tracker send:[[GAIDictionaryBuilder createTimingWithCategory:category
+                                                         interval:@((NSUInteger)(loadTime * 1000))
+                                                             name:name
+                                                            label:label] build]];
+    
+}
+
++ (void)trackSignInUserID:(NSString *)userID {
+    
+    
+    id<GAITracker> tracker = [[GAI sharedInstance] defaultTracker];
+    
+    [tracker set:kGAIUserId value:userID];
+    
+    
+}
+
++ (void)trackSignOut {
+    
+    id<GAITracker> tracker = [[GAI sharedInstance] defaultTracker];
+
+//    NSString *userId = [tracker get:kGAIUserId];
+    
+    [tracker set:kGAIUserId value:nil];
+}
+
++ (void)trackProduct:(NSString *)productName action:(NSString *)action count:(NSNumber *)count{
+    
+    id<GAITracker> tracker = [[GAI sharedInstance] defaultTracker];
+    
+    GAIDictionaryBuilder *builder = [GAIDictionaryBuilder createScreenView];
+    
+    for (NSString *product_name in [productName componentsSeparatedByString:@","]) {
+        
+        GAIEcommerceProduct *product = [[GAIEcommerceProduct alloc] init];
+        [product setName:product_name];
+        if (count) {
+            [product setQuantity:count];
+        }
+        [builder addProduct:product];
+        
+        [builder addProductImpression:product impressionList:@"Products" impressionSource:nil];
+        
+    }
+    GAIEcommerceProductAction *paction = [[GAIEcommerceProductAction alloc] init];
+    if ([action isEqualToString:@"Add To Cart"]) {
+        [paction setAction:kGAIPAAdd];
+    } else {
+        
+        [paction setAction:kGAIPADetail];
+    }
+    [builder setProductAction:paction];
+    
+    
+    [tracker send:[builder build]];
+    
+    
+}
+
+
+
+
+
+@end

+ 192 - 0
RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalytics/Sources/GAI.h

@@ -0,0 +1,192 @@
+/*!
+ @header    GAI.h
+ @abstract  Google Analytics iOS SDK Header
+ @version   3.17
+ @copyright Copyright 2015 Google Inc. All rights reserved.
+ */
+
+#import <Foundation/Foundation.h>
+
+#import "GAILogger.h"
+#import "GAITrackedViewController.h"
+#import "GAITracker.h"
+
+typedef NS_ENUM(NSUInteger, GAIDispatchResult) {
+  kGAIDispatchNoData,
+  kGAIDispatchGood,
+  kGAIDispatchError
+};
+
+/*! Google Analytics product string.  */
+extern NSString *const kGAIProduct;
+
+/*! Google Analytics version string.  */
+extern NSString *const kGAIVersion;
+
+/*!
+ NSError objects returned by the Google Analytics SDK may have this error domain
+ to indicate that the error originated in the Google Analytics SDK.
+ */
+extern NSString *const kGAIErrorDomain;
+
+/*! Google Analytics error codes.  */
+typedef enum {
+  // This error code indicates that there was no error. Never used.
+  kGAINoError = 0,
+
+  // This error code indicates that there was a database-related error.
+  kGAIDatabaseError,
+
+  // This error code indicates that there was a network-related error.
+  kGAINetworkError,
+} GAIErrorCode;
+
+/*!
+ Google Analytics iOS top-level class. Provides facilities to create trackers
+ and set behaviorial flags.
+ */
+@interface GAI : NSObject
+
+/*!
+ For convenience, this class exposes a default tracker instance.
+ This is initialized to `nil` and will be set to the first tracker that is
+ instantiated in trackerWithTrackingId:. It may be overridden as desired.
+
+ The GAITrackedViewController class will, by default, use this tracker instance.
+ */
+@property(nonatomic, assign) id<GAITracker> defaultTracker;
+
+/*!
+ The GAILogger to use.
+ */
+@property(nonatomic, retain) id<GAILogger> logger;
+
+/*!
+ When this is true, no tracking information will be gathered; tracking calls
+ will effectively become no-ops. When set to true, all tracking information that
+ has not yet been submitted. The value of this flag will be persisted
+ automatically by the SDK.  Developers can optionally use this flag to implement
+ an opt-out setting in the app to allows users to opt out of Google Analytics
+ tracking.
+
+ This is set to `NO` the first time the Google Analytics SDK is used on a
+ device, and is persisted thereafter.
+ */
+@property(nonatomic, assign) BOOL optOut;
+
+/*!
+ If this value is positive, tracking information will be automatically
+ dispatched every dispatchInterval seconds. Otherwise, tracking information must
+ be sent manually by calling dispatch.
+
+ By default, this is set to `120`, which indicates tracking information should
+ be dispatched automatically every 120 seconds.
+ */
+@property(nonatomic, assign) NSTimeInterval dispatchInterval;
+
+/*!
+ When set to true, the SDK will record the currently registered uncaught
+ exception handler, and then register an uncaught exception handler which tracks
+ the exceptions that occurred using defaultTracker. If defaultTracker is not
+ `nil`, this function will track the exception on the tracker and attempt to
+ dispatch any outstanding tracking information for 5 seconds. It will then call
+ the previously registered exception handler, if any. When set back to false,
+ the previously registered uncaught exception handler will be restored.
+ */
+@property(nonatomic, assign) BOOL trackUncaughtExceptions;
+
+/*!
+ When this is 'YES', no tracking information will be sent. Defaults to 'NO'.
+ */
+@property(nonatomic, assign) BOOL dryRun;
+
+/*! Get the shared instance of the Google Analytics for iOS class. */
++ (GAI *)sharedInstance;
+
+/*!
+ Creates or retrieves a GAITracker implementation with the specified name and
+ tracking ID. If the tracker for the specified name does not already exist, then
+ it will be created and returned; otherwise, the existing tracker will be
+ returned. If the existing tracker for the respective name has a different
+ tracking ID, that tracking ID is not changed by this method. If defaultTracker
+ is not set, it will be set to the tracker instance returned here.
+
+ @param name The name of this tracker. Must not be `nil` or empty.
+
+ @param trackingID The tracking ID to use for this tracker.  It should be of
+ the form `UA-xxxxx-y`.
+
+ @return A GAITracker associated with the specified name. The tracker
+ can be used to send tracking data to Google Analytics. The first time this
+ method is called with a particular name, the tracker for that name will be
+ returned, and subsequent calls with the same name will return the same
+ instance. It is not necessary to retain the tracker because the tracker will be
+ retained internally by the library.
+
+ If an error occurs or the name is not valid, this method will return
+ `nil`.
+ */
+- (id<GAITracker>)trackerWithName:(NSString *)name
+                       trackingId:(NSString *)trackingId;
+
+/*!
+ Creates or retrieves a GAITracker implementation with name equal to
+ the specified tracking ID. If the tracker for the respective name does not
+ already exist, it is created, has it's tracking ID set to |trackingId|,
+ and is returned; otherwise, the existing tracker is returned. If the existing
+ tracker for the respective name has a different tracking ID, that tracking ID
+ is not changed by this method. If defaultTracker is not set, it is set to the
+ tracker instance returned here.
+
+ @param trackingID The tracking ID to use for this tracker.  It should be of
+ the form `UA-xxxxx-y`. The name of the tracker will be the same as trackingID.
+
+ @return A GAITracker associated with the specified trackingID. The tracker
+ can be used to send tracking data to Google Analytics. The first time this
+ method is called with a particular trackingID, the tracker for the respective
+ name will be returned, and subsequent calls with the same trackingID
+ will return the same instance. It is not necessary to retain the tracker
+ because the tracker will be retained internally by the library.
+
+ If an error occurs or the trackingId is not valid, this method will return
+ `nil`.
+ */
+- (id<GAITracker>)trackerWithTrackingId:(NSString *)trackingId;
+
+/*!
+ Remove a tracker from the trackers dictionary. If it is the default tracker,
+ clears the default tracker as well.
+
+ @param name The name of the tracker.
+ */
+- (void)removeTrackerByName:(NSString *)name;
+
+/*!
+ Dispatches any pending tracking information.
+
+ Note that this does not have any effect on dispatchInterval, and can be used in
+ conjunction with periodic dispatch. */
+- (void)dispatch;
+
+/*!
+ Dispatches the next tracking beacon in the queue, calling completionHandler when
+ the tracking beacon has either been sent (returning kGAIDispatchGood) or an error has resulted
+ (returning kGAIDispatchError).  If there is no network connection or there is no data to send,
+ kGAIDispatchNoData is returned.
+
+ Note that calling this method with a non-nil completionHandler disables periodic dispatch.
+ Periodic dispatch can be reenabled by setting the dispatchInterval to a positive number when
+ the app resumes from the background.
+
+ Calling this method with a nil completionHandler is the same as calling the dispatch
+ above.
+
+ This method can be used for background data fetching in iOS 7.0 or later. It would be wise to
+ call this when the application is exiting to initiate the submission of any unsubmitted
+ tracking information.
+
+ @param completionHandler The block to run after a single dispatch request. The GAIDispatchResult
+        param indicates whether the dispatch succeeded, had an error, or had no hits to dispatch.
+ */
+- (void)dispatchWithCompletionHandler:(void (^)(GAIDispatchResult result))completionHandler;
+@end

+ 214 - 0
RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalytics/Sources/GAIDictionaryBuilder.h

@@ -0,0 +1,214 @@
+/*!
+ @header    GAIDictionaryBuilder.h
+ @abstract  Google Analytics iOS SDK Hit Format Header
+ @copyright Copyright 2013 Google Inc. All rights reserved.
+ */
+
+#import <Foundation/Foundation.h>
+
+#import "GAIEcommerceProduct.h"
+#import "GAIEcommerceProductAction.h"
+#import "GAIEcommercePromotion.h"
+
+/*!
+ * Helper class to build a dictionary of hit parameters and values.
+ * <br>
+ * Examples:
+ * <code>
+ * id<GAITracker> t = // get a tracker.
+ * [t send:[[[GAIDictionaryBuilder createEventWithCategory:@"EventCategory"
+ *                                                  action:@"EventAction"
+ *                                                   label:nil
+ *                                                   value:nil]
+ *     set:@"dimension1" forKey:[GAIFields customDimensionForIndex:1]] build]];
+ * </code>
+ * This will send an event hit type with the specified parameters
+ * and a custom dimension parameter.
+ * <br>
+ * If you want to send a parameter with all hits, set it on GAITracker directly.
+ * <code>
+ * [t set:kGAIScreenName value:@"Home"];
+ * [t send:[[GAIDictionaryBuilder createSocialWithNetwork:@"Google+"
+ *                                                 action:@"PlusOne"
+ *                                                 target:@"SOME_URL"] build]];
+ * [t send:[[GAIDictionaryBuilder createSocialWithNetwork:@"Google+"
+ *                                                 action:@"Share"
+ *                                                 target:@"SOME_POST"] build]];
+ * [t send:[[GAIDictionaryBuilder createSocialWithNetwork:@"Google+"
+ *                                                 action:@"HangOut"
+ *                                                 target:@"SOME_CIRCLE"]
+ *     build]];
+ * </code>
+ * You can override a value set on the tracker by adding it to the dictionary.
+ * <code>
+ * [t set:kGAIScreenName value:@"Home"];
+ * [t send:...];
+ * [t send[[[GAIDictionaryBuilder createEventWithCategory:@"click"
+ *                                                 action:@"popup"
+ *                                                  label:nil
+ *                                                  value:nil]
+ *     set:@"popup title" forKey:kGAIScreenName] build]];
+ * </code>
+ * The values set via [GAIDictionaryBuilder set] or
+ * [GAIDictionaryBuilder setAll] will override any existing values in the
+ * GAIDictionaryBuilder object (i.e. initialized by
+ * [GAIDictionaryBuilder createXYZ]). e.g.
+ * <code>
+ * GAIDictionaryBuilder *m =
+ *     GAIDictionaryBuilder createTimingWithCategory:@"category"
+ *                                          interval:@0
+ *                                              name:@"name"
+ *                                             label:nil];
+ * [t send:[m.set:@"10" forKey:kGAITimingVar] build];
+ * [t send:[m.set:@"20" forKey:kGAITimingVar] build];
+ * </code>
+ */
+@interface GAIDictionaryBuilder : NSObject
+
+- (GAIDictionaryBuilder *)set:(NSString *)value
+                       forKey:(NSString *)key;
+
+/*!
+ * Copies all the name-value pairs from params into this object, ignoring any
+ * keys that are not NSString and any values that are neither NSString or
+ * NSNull.
+ */
+- (GAIDictionaryBuilder *)setAll:(NSDictionary *)params;
+
+/*!
+ * Returns the value for the input parameter paramName, or nil if paramName
+ * is not present.
+ */
+- (NSString *)get:(NSString *)paramName;
+
+/*!
+ * Return an NSMutableDictionary object with all the parameters set in this
+ */
+- (NSMutableDictionary *)build;
+
+/*!
+ * Parses and translates utm campaign parameters to analytics campaign param
+ * and returns them as a map.
+ *
+ * @param params url containing utm campaign parameters.
+ *
+ * Valid campaign parameters are:
+ * <ul>
+ * <li>utm_id</li>
+ * <li>utm_campaign</li>
+ * <li>utm_content</li>
+ * <li>utm_medium</li>
+ * <li>utm_source</li>
+ * <li>utm_term</li>
+ * <li>dclid</li>
+ * <li>gclid</li>
+ * <li>gmob_t</li>
+ * <li>aclid</li>
+ * <li>anid</li>
+ * </ul>
+ * <p>
+ * Example:
+ * http://my.site.com/index.html?utm_campaign=wow&utm_source=source
+ * utm_campaign=wow&utm_source=source.
+ * <p>
+ * For more information on manual and auto-tagging, see
+ * https://support.google.com/analytics/answer/1733663?hl=en
+ */
+- (GAIDictionaryBuilder *)setCampaignParametersFromUrl:(NSString *)urlString;
+
+/*!
+ Returns a GAIDictionaryBuilder object with parameters specific to an appview
+ hit.
+
+ Note that using this method will not set the screen name for followon hits.  To
+ do that you need to call set:kGAIDescription value:<screenName> on the
+ GAITracker instance.
+
+ This method is deprecated.  Use createScreenView instead.
+ */
++ (GAIDictionaryBuilder *)createAppView DEPRECATED_MSG_ATTRIBUTE("Use createScreenView instead.");
+
+/*!
+ Returns a GAIDictionaryBuilder object with parameters specific to a screenview
+ hit.
+
+ Note that using this method will not set the screen name for followon hits.  To
+ do that you need to call set:kGAIDescription value:<screenName> on the
+ GAITracker instance.
+ */
++ (GAIDictionaryBuilder *)createScreenView;
+
+/*!
+ Returns a GAIDictionaryBuilder object with parameters specific to an event hit.
+ */
++ (GAIDictionaryBuilder *)createEventWithCategory:(NSString *)category
+                                           action:(NSString *)action
+                                            label:(NSString *)label
+                                            value:(NSNumber *)value;
+
+/*!
+ Returns a GAIDictionaryBuilder object with parameters specific to an exception
+ hit.
+ */
++ (GAIDictionaryBuilder *)createExceptionWithDescription:(NSString *)description
+                                               withFatal:(NSNumber *)fatal;
+
+/*!
+ Returns a GAIDictionaryBuilder object with parameters specific to an item hit.
+ */
++ (GAIDictionaryBuilder *)createItemWithTransactionId:(NSString *)transactionId
+                                                 name:(NSString *)name
+                                                  sku:(NSString *)sku
+                                             category:(NSString *)category
+                                                price:(NSNumber *)price
+                                             quantity:(NSNumber *)quantity
+                                         currencyCode:(NSString *)currencyCode;
+
+/*!
+ Returns a GAIDictionaryBuilder object with parameters specific to a social hit.
+ */
++ (GAIDictionaryBuilder *)createSocialWithNetwork:(NSString *)network
+                                           action:(NSString *)action
+                                           target:(NSString *)target;
+
+/*!
+ Returns a GAIDictionaryBuilder object with parameters specific to a timing hit.
+ */
++ (GAIDictionaryBuilder *)createTimingWithCategory:(NSString *)category
+                                          interval:(NSNumber *)intervalMillis
+                                              name:(NSString *)name
+                                             label:(NSString *)label;
+
+/*!
+ Returns a GAIDictionaryBuilder object with parameters specific to a transaction
+ hit.
+ */
++ (GAIDictionaryBuilder *)createTransactionWithId:(NSString *)transactionId
+                                      affiliation:(NSString *)affiliation
+                                          revenue:(NSNumber *)revenue
+                                              tax:(NSNumber *)tax
+                                         shipping:(NSNumber *)shipping
+                                     currencyCode:(NSString *)currencyCode;
+
+/*!
+ Set the product action field for this hit.
+ */
+- (GAIDictionaryBuilder *)setProductAction:(GAIEcommerceProductAction *)productAction;
+
+/*!
+ Adds a product to this hit.
+ */
+- (GAIDictionaryBuilder *)addProduct:(GAIEcommerceProduct *)product;
+
+/*!
+ Add a product impression to this hit.
+ */
+- (GAIDictionaryBuilder *)addProductImpression:(GAIEcommerceProduct *)product
+                                impressionList:(NSString *)name
+                                impressionSource:(NSString *)source;
+
+/*!
+ Add a promotion to this hit.
+ */
+- (GAIDictionaryBuilder *)addPromotion:(GAIEcommercePromotion *)promotion;
+@end

+ 124 - 0
RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalytics/Sources/GAIEcommerceFields.h

@@ -0,0 +1,124 @@
+/*!
+ @header    GAIEcommerceFields.h
+ @abstract  Google Analytics iOS SDK Ecommerce Hit Format Header
+ @copyright Copyright 2014 Google Inc. All rights reserved.
+ */
+
+#import <Foundation/Foundation.h>
+
+/*!
+ This class provides several fields and methods useful as wire format parameters for
+ Enhanced Ecommerce. See the online developer guides for Enhanced Ecommerce for details
+ on how to use the Enhanced Ecommerce features.
+ */
+
+// Enhanced Ecommerce Product fields
+extern NSString *const kGAIProductId;
+extern NSString *const kGAIProductName;
+extern NSString *const kGAIProductBrand;
+extern NSString *const kGAIProductCategory;
+extern NSString *const kGAIProductVariant;
+extern NSString *const kGAIProductPrice;
+extern NSString *const kGAIProductQuantity;
+extern NSString *const kGAIProductCouponCode;
+extern NSString *const kGAIProductPosition;
+
+extern NSString *const kGAIProductAction;
+
+// product action values
+extern NSString *const kGAIPADetail;
+extern NSString *const kGAIPAClick;
+extern NSString *const kGAIPAAdd;
+extern NSString *const kGAIPARemove;
+extern NSString *const kGAIPACheckout;
+extern NSString *const kGAIPACheckoutOption;
+extern NSString *const kGAIPAPurchase;
+extern NSString *const kGAIPARefund;
+
+// product action fields
+// used for 'purchase' and 'refund' actions
+extern NSString *const kGAIPATransactionId;
+extern NSString *const kGAIPAAffiliation;
+extern NSString *const kGAIPARevenue;
+extern NSString *const kGAIPATax;
+extern NSString *const kGAIPAShipping;
+extern NSString *const kGAIPACouponCode;
+// used for 'checkout' action
+extern NSString *const kGAICheckoutStep;
+extern NSString *const kGAICheckoutOption;
+// used for 'detail' and 'click' actions
+extern NSString *const kGAIProductActionList;
+extern NSString *const kGAIProductListSource;
+
+// Enhanced Ecommerce Impressions fields
+extern NSString *const kGAIImpressionName;
+extern NSString *const kGAIImpressionListSource;
+extern NSString *const kGAIImpressionProduct;
+extern NSString *const kGAIImpressionProductId;
+extern NSString *const kGAIImpressionProductName;
+extern NSString *const kGAIImpressionProductBrand;
+extern NSString *const kGAIImpressionProductCategory;
+extern NSString *const kGAIImpressionProductVariant;
+extern NSString *const kGAIImpressionProductPosition;
+extern NSString *const kGAIImpressionProductPrice;
+
+// Enhanced Ecommerce Promotions fields
+extern NSString *const kGAIPromotionId;
+extern NSString *const kGAIPromotionName;
+extern NSString *const kGAIPromotionCreative;
+extern NSString *const kGAIPromotionPosition;
+
+// Promotion actions
+extern NSString *const kGAIPromotionAction;
+extern NSString *const kGAIPromotionView;
+extern NSString *const kGAIPromotionClick;
+
+@interface GAIEcommerceFields : NSObject
+
+/*!
+ Generates an enhanced ecommerce product field.  Note that field names generated by
+ customDimensionForIndex and customMetricForIndex can be used as suffixes.
+
+ @param index the index of the product
+ @param suffix the product field suffix (such as kGAIProductPrice).
+
+ @return an NSString representing the product field parameter
+ */
++ (NSString *)productFieldForIndex:(NSUInteger)index suffix:(NSString *)suffix;
+
+/*!
+ Genrates an enhanced ecommerce impression list field name with an index.  The return value of
+ this method should also be used as input to the productImpressionForList method below.
+
+ @param index the index of the impression list
+
+ @return an NSString representing the impression list parameter
+ */
++ (NSString *)impressionListForIndex:(NSUInteger)index;
+
+/*!
+ Generates an enhanced ecommerce product impression field with the impression list, product index
+ and product suffix as parameters.  The output of the method impressionListForIndex above should be
+ used as the input list for this method.  The output of customDimensionForIndex and
+ customMetricForIndex can be used as suffixes.
+
+ @param list the impression list for this product impression
+ @param index the index of this product in the impression list
+ @param suffix the product impression suffix for this field
+
+ @return an NSString representing this product impression field parameter
+ */
++ (NSString *)productImpressionForList:(NSString *)list
+                                 index:(NSUInteger)index
+                                suffix:(NSString *)Suffix;
+
+/*!
+ Generates an enhanced ecommerce promotion field with an index and suffix.
+
+ @param index the index of the promotion
+ @param suffix the promotion suffix (such as kGAIPromotionId)
+
+ @return an NSString representing this promotion field paramter
+ */
++ (NSString *)promotionForIndex:(NSUInteger)index suffix:(NSString *)suffix;
+@end

+ 102 - 0
RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalytics/Sources/GAIEcommerceProduct.h

@@ -0,0 +1,102 @@
+/*!
+ @header    GAIEcommerceProduct.h
+ @abstract  Google Analytics iOS SDK Hit Format Header
+ @copyright Copyright 2014 Google Inc. All rights reserved.
+ */
+
+#import <Foundation/Foundation.h>
+
+/*!
+ * Class to construct product related information for a Google Analytics beacon. Use this class to
+ * report information about products sold by merchants or impressions of products seen by users.
+ * Instances of this class can be associated with both Product Actions and Product
+ * Impression Lists.
+ * <br>
+ * Typical usage:
+ * <code>
+ * [tracker set:kGAIScreenName value:@"MyScreen"];
+ * GAIDictionaryBuilder *builder = [GAIDictionaryBuilder createScreenView];
+ * GAIEcommerceProduct *product = [[GAIEcommerceProduct alloc] init];
+ * [product setId:@""PID-1234""];
+ * [product setName:@"Space Monkeys!"];
+ * [product setPrice:@100];
+ * [product setQuantity:@2];
+ * [builder addProductImpression:product impressionList:@"listName"];
+ * [tracker send:[builder build]];
+ * </code>
+ */
+@interface GAIEcommerceProduct : NSObject
+
+/*!
+ Sets the id that is used to identify a product in GA reports.
+ */
+- (GAIEcommerceProduct *)setId:(NSString *)productId;
+
+/*!
+ Sets the name that is used to indentify the product in GA reports.
+ */
+- (GAIEcommerceProduct *)setName:(NSString *)productName;
+
+/*!
+ Sets the brand associated with the product in GA reports.
+ */
+- (GAIEcommerceProduct *)setBrand:(NSString *)productBrand;
+
+/*!
+ Sets the category associated with the product in GA reports.
+ */
+- (GAIEcommerceProduct *)setCategory:(NSString *)productCategory;
+
+/*!
+ Sets the variant of the product.
+ */
+- (GAIEcommerceProduct *)setVariant:(NSString *)productVariant;
+
+/*!
+ Sets the price of the product.
+ */
+- (GAIEcommerceProduct *)setPrice:(NSNumber *)productPrice;
+
+/*!
+ Sets the quantity of the product.  This field is usually not used with product impressions.
+ */
+- (GAIEcommerceProduct *)setQuantity:(NSNumber *)productQuantity;
+
+/*!
+ Sets the coupon code associated with the product.  This field is usually not used with product
+ impressions.
+ */
+- (GAIEcommerceProduct *)setCouponCode:(NSString *)productCouponCode;
+
+/*!
+ Sets the position of the product on the screen/product impression list, etc.
+ */
+- (GAIEcommerceProduct *)setPosition:(NSNumber *)productPosition;
+
+/*!
+ Sets the custom dimension associated with this product.
+ */
+- (GAIEcommerceProduct *)setCustomDimension:(NSUInteger)index value:(NSString *)value;
+
+/*!
+ Sets the custom metric associated with this product.
+ */
+- (GAIEcommerceProduct *)setCustomMetric:(NSUInteger)index value:(NSNumber *)value;
+
+/*!
+ Builds an NSDictionary of fields stored in this instance suitable for a product action.  The
+ index parameter is the index of this product in the product action list.
+ <br>
+ Normally, users will have no need to call this method.
+ */
+- (NSDictionary *)buildWithIndex:(NSUInteger)index;
+
+/*!
+ Builds an NSDictionary of fields stored in this instance suitable for an impression list.  The
+ lIndex parameter is the index of the product impression list while the index parameter is the
+ index of this product in that impression list.
+ <br>
+ Normally, users will have no need to call this method.
+ */
+- (NSDictionary *)buildWithListIndex:(NSUInteger)lIndex index:(NSUInteger)index;
+@end

+ 107 - 0
RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalytics/Sources/GAIEcommerceProductAction.h

@@ -0,0 +1,107 @@
+/*!
+ @header    GAIProductAction.h
+ @abstract  Google Analytics iOS SDK Hit Format Header
+ @copyright Copyright 2014 Google Inc. All rights reserved.
+ */
+
+#import <Foundation/Foundation.h>
+
+/*!
+ * Class to construct transaction/checkout or other product interaction related information for a
+ * Google Analytics hit. Use this class to report information about products sold, viewed or
+ * refunded. This class is intended to be used with GAIDictionaryBuilder.
+ * <br>
+ * Typical usage:
+ * <code>
+ * [tracker set:kGAIScreenName value:@"MyScreen"];
+ * GAIDictionaryBuilder *builder = [GAIDictionaryBuilder createScreenView];
+ * GAIEcommerceProductAction *action = [[GAIEcommerceProductAction alloc] init];
+ * [action setAction:kGAIPAPurchase];
+ * [action setTransactionId:@"TT-1234"];
+ * [action setRevenue:@3.14];
+ * [action setCouponCode:@"EXTRA100"];
+ * [builder setProductAction:action];
+ * GAIEcommerceProduct *product = [[GAIEcommerceProduct alloc] init];
+ * [product setId:@""PID-1234""];
+ * [product setName:@"Space Monkeys!"];
+ * [product setPrice:@100];
+ * [product setQuantity:@2];
+ * [builder addProduct:product];
+ * [tracker send:[builder build]];
+ * </code>
+ */
+@interface GAIEcommerceProductAction : NSObject
+
+/*!
+ Sets the product action field for this product action. Valid values can be found in
+ GAIEcommerceFields.h under "product action values".
+ */
+- (GAIEcommerceProductAction *)setAction:(NSString *)productAction;
+
+/*!
+ The unique id associated with the transaction.  This value is used for kGAIPAPurchase and
+ kGAIPARefund product actions.
+ */
+- (GAIEcommerceProductAction *)setTransactionId:(NSString *)transactionId;
+
+/*!
+ Sets the transaction's affiliation value.  This value is used for kGAIPAPurchase and
+ kGAIPARefund product actions.
+ */
+- (GAIEcommerceProductAction *)setAffiliation:(NSString *)affiliation;
+
+/*!
+ Sets the transaction's total revenue.  This value is used for kGAIPAPurchase and kGAIPARefund
+ product actions.
+ */
+- (GAIEcommerceProductAction *)setRevenue:(NSNumber *)revenue;
+
+/*!
+ Sets the transaction's total tax.  This value is used for kGAIPAPurchase and kGAIPARefund
+ product actions.
+ */
+- (GAIEcommerceProductAction *)setTax:(NSNumber *)tax;
+
+/*!
+ Sets the transaction's total shipping costs.  This value is used for kGAIPAPurchase and
+ kGAIPARefund product actions.
+ */
+- (GAIEcommerceProductAction *)setShipping:(NSNumber *)shipping;
+
+/*!
+ Sets the coupon code used in this transaction.  This value is used for kGAIPAPurchase and
+ kGAIPARefund product actions.
+ */
+- (GAIEcommerceProductAction *)setCouponCode:(NSString *)couponCode;
+
+/*!
+ Sets the checkout process's progress.  This value is used for kGAICheckout and
+ kGAICheckoutOptions product actions.
+ */
+- (GAIEcommerceProductAction *)setCheckoutStep:(NSNumber *)checkoutStep;
+
+/*!
+ Sets the option associated with the checkout.  This value is used for kGAICheckout and
+ kGAICheckoutOptions product actions.
+ */
+- (GAIEcommerceProductAction *)setCheckoutOption:(NSString *)checkoutOption;
+
+/*!
+ Sets the list name associated with the products in Google Analytics beacons.  This value is
+ used in kGAIPADetail and kGAIPAClick product actions.
+ */
+- (GAIEcommerceProductAction *)setProductActionList:(NSString *)productActionList;
+
+/*!
+ Sets the list source name associated with the products in Google Analytics beacons.  This value
+ is used in kGAIPADetail and kGAIPAClick product actions.
+ */
+- (GAIEcommerceProductAction *)setProductListSource:(NSString *)productListSource;
+
+/*!
+ Builds an NSDictionary of fields stored in this instance representing this product action.
+ <br>
+ Normally, users will have no need to call this method.
+ */
+- (NSDictionary *)build;
+@end

+ 54 - 0
RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalytics/Sources/GAIEcommercePromotion.h

@@ -0,0 +1,54 @@
+/*!
+ @header    GAIEcommercePromotion.h
+ @abstract  Google Analytics iOS SDK Hit Format Header
+ @copyright Copyright 2014 Google Inc. All rights reserved.
+ */
+
+#import <Foundation/Foundation.h>
+
+/*!
+ * Class to construct promotion related fields for Google Analytics hits. The fields from this class
+ * can be used to represent internal promotions that run within an app, such as banners, banner ads
+ * etc.
+ *
+ * Typical usage:
+ * <code>
+ * GAIDictionaryBuilder *builder = [GAIDictionaryBuilder createScreenView];
+ * GAIEcommercePromotion *promotion = [[GAIEcommercePromotion alloc] init];
+ * [promotion setId:@"PROMO-ID1234"];
+ * [promotion setName:@"Home screen banner"];
+ * [builder set:kGAIPromotionClick forKey:kGAIPromotionAction];
+ * [builder addPromotion:promotion];
+ * [tracker send:builder.build]];
+ * </code>
+ */
+@interface GAIEcommercePromotion : NSObject
+
+/*!
+ Sets the id that is used to identify a promotion in GA reports.
+ */
+- (GAIEcommercePromotion *)setId:(NSString *)pid;
+
+/*!
+ Sets the name that is used to identify a promotion in GA reports.
+ */
+- (GAIEcommercePromotion *)setName:(NSString *)name;
+
+/*!
+ Sets the name of the creative associated with the promotion.
+ */
+- (GAIEcommercePromotion *)setCreative:(NSString *)creative;
+
+/*!
+ Sets the position of the promotion.
+ */
+- (GAIEcommercePromotion *)setPosition:(NSString *)position;
+
+/*!
+ Builds an NSDictionary of fields stored in this instance.  The index parameter is the
+ index of this promotion in that promotion list.
+ <br>
+ Normally, users will have no need to call this method.
+ */
+- (NSDictionary *)buildWithIndex:(NSUInteger)index;
+@end

+ 133 - 0
RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalytics/Sources/GAIFields.h

@@ -0,0 +1,133 @@
+/*!
+ @header    GAIFields.h
+ @abstract  Google Analytics iOS SDK Hit Format Header
+ @copyright Copyright 2013 Google Inc. All rights reserved.
+ */
+
+#import <Foundation/Foundation.h>
+
+/*!
+ These fields can be used for the wire format parameter names required by
+ the |GAITracker| get, set and send methods as well as the set methods in the
+ |GAIDictionaryBuilder| class.
+ */
+extern NSString *const kGAIUseSecure;
+
+extern NSString *const kGAIHitType;
+extern NSString *const kGAITrackingId;
+extern NSString *const kGAIClientId;
+extern NSString *const kGAIDataSource;
+extern NSString *const kGAIAnonymizeIp;
+extern NSString *const kGAISessionControl;
+extern NSString *const kGAIDeviceModelVersion;
+extern NSString *const kGAIScreenResolution;
+extern NSString *const kGAIViewportSize;
+extern NSString *const kGAIEncoding;
+extern NSString *const kGAIScreenColors;
+extern NSString *const kGAILanguage;
+extern NSString *const kGAIJavaEnabled;
+extern NSString *const kGAIFlashVersion;
+extern NSString *const kGAINonInteraction;
+extern NSString *const kGAIReferrer;
+extern NSString *const kGAILocation;
+extern NSString *const kGAIHostname;
+extern NSString *const kGAIPage;
+extern NSString *const kGAIDescription;  // synonym for kGAIScreenName
+extern NSString *const kGAIScreenName;   // synonym for kGAIDescription
+extern NSString *const kGAITitle;
+extern NSString *const kGAIAdMobHitId;
+extern NSString *const kGAIAppName;
+extern NSString *const kGAIAppVersion;
+extern NSString *const kGAIAppId;
+extern NSString *const kGAIAppInstallerId;
+extern NSString *const kGAIUserId;
+
+extern NSString *const kGAIEventCategory;
+extern NSString *const kGAIEventAction;
+extern NSString *const kGAIEventLabel;
+extern NSString *const kGAIEventValue;
+
+extern NSString *const kGAISocialNetwork;
+extern NSString *const kGAISocialAction;
+extern NSString *const kGAISocialTarget;
+
+extern NSString *const kGAITransactionId;
+extern NSString *const kGAITransactionAffiliation;
+extern NSString *const kGAITransactionRevenue;
+extern NSString *const kGAITransactionShipping;
+extern NSString *const kGAITransactionTax;
+extern NSString *const kGAICurrencyCode;
+
+extern NSString *const kGAIItemPrice;
+extern NSString *const kGAIItemQuantity;
+extern NSString *const kGAIItemSku;
+extern NSString *const kGAIItemName;
+extern NSString *const kGAIItemCategory;
+
+extern NSString *const kGAICampaignSource;
+extern NSString *const kGAICampaignMedium;
+extern NSString *const kGAICampaignName;
+extern NSString *const kGAICampaignKeyword;
+extern NSString *const kGAICampaignContent;
+extern NSString *const kGAICampaignId;
+extern NSString *const kGAICampaignAdNetworkClickId;
+extern NSString *const kGAICampaignAdNetworkId;
+
+extern NSString *const kGAITimingCategory;
+extern NSString *const kGAITimingVar;
+extern NSString *const kGAITimingValue;
+extern NSString *const kGAITimingLabel;
+
+extern NSString *const kGAIExDescription;
+extern NSString *const kGAIExFatal;
+
+extern NSString *const kGAISampleRate;
+
+extern NSString *const kGAIIdfa;
+extern NSString *const kGAIAdTargetingEnabled;
+
+// hit types
+extern NSString *const kGAIAppView DEPRECATED_MSG_ATTRIBUTE("Use kGAIScreenView instead.");
+extern NSString *const kGAIScreenView;
+extern NSString *const kGAIEvent;
+extern NSString *const kGAISocial;
+extern NSString *const kGAITransaction;
+extern NSString *const kGAIItem;
+extern NSString *const kGAIException;
+extern NSString *const kGAITiming;
+
+/*!
+ This class provides several fields and methods useful as wire format parameter
+ names.  The methods are used for wire format parameter names that are indexed.
+ */
+
+@interface GAIFields : NSObject
+
+/*!
+ Generates the correct parameter name for a content group with an index.
+
+ @param index the index of the content group.
+
+ @return an NSString representing the content group parameter for the index.
+ */
++ (NSString *)contentGroupForIndex:(NSUInteger)index;
+
+/*!
+ Generates the correct parameter name for a custon dimension with an index.
+
+ @param index the index of the custom dimension.
+
+ @return an NSString representing the custom dimension parameter for the index.
+ */
++ (NSString *)customDimensionForIndex:(NSUInteger)index;
+
+/*!
+ Generates the correct parameter name for a custom metric with an index.
+
+ @param index the index of the custom metric.
+
+ @return an NSString representing the custom metric parameter for the index.
+ */
++ (NSString *)customMetricForIndex:(NSUInteger)index;
+
+@end

+ 49 - 0
RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalytics/Sources/GAILogger.h

@@ -0,0 +1,49 @@
+/*!
+ @header    GAILogger.h
+ @abstract  Google Analytics iOS SDK Source
+ @copyright Copyright 2011 Google Inc. All rights reserved.
+ */
+
+#import <Foundation/Foundation.h>
+
+typedef NS_ENUM(NSUInteger, GAILogLevel) {
+  kGAILogLevelNone = 0,
+  kGAILogLevelError = 1,
+  kGAILogLevelWarning = 2,
+  kGAILogLevelInfo = 3,
+  kGAILogLevelVerbose = 4
+};
+
+/*!
+ Protocol to be used for logging debug and informational messages from the SDK.
+ Implementations of this protocol can be provided to the |GAI| class,
+ to be used as the logger by the SDK.  See the |logger| property in GAI.h.
+ */
+@protocol GAILogger<NSObject>
+@required
+
+/*!
+ Only messages of |logLevel| and below are logged.
+ */
+@property (nonatomic, assign) GAILogLevel logLevel;
+
+/*!
+ Logs message with log level |kGAILogLevelVerbose|.
+ */
+- (void)verbose:(NSString *)message;
+
+/*!
+ Logs message with log level |kGAILogLevelInfo|.
+ */
+- (void)info:(NSString *)message;
+
+/*!
+ Logs message with log level |kGAILogLevelWarning|.
+ */
+- (void)warning:(NSString *)message;
+
+/*!
+ Logs message with log level |kGAILogLevelError|.
+ */
+- (void)error:(NSString *)message;
+@end

+ 33 - 0
RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalytics/Sources/GAITrackedViewController.h

@@ -0,0 +1,33 @@
+/*!
+ @header    GAITrackedViewController.h
+ @abstract  Google Analytics for iOS Tracked View Controller Header
+ @copyright Copyright 2012 Google Inc. All rights reserved.
+ */
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+@protocol GAITracker;
+
+/*!
+ Extends UIViewController to generate Google Analytics screenview calls
+ whenever the view appears; this is done by overriding the `viewDidAppear:`
+ method. The screen name must be set for any tracking calls to be made.
+
+ By default, this will use [GAI defaultTracker] for tracking calls, but one can
+ override this by setting the tracker property.
+ */
+@interface GAITrackedViewController : UIViewController
+
+/*!
+ The tracker on which view tracking calls are be made, or `nil`, in which case
+ [GAI defaultTracker] will be used.
+ */
+@property(nonatomic, assign) id<GAITracker> tracker;
+/*!
+ The screen name, for purposes of Google Analytics tracking. If this is `nil`,
+ no tracking calls will be made.
+ */
+@property(nonatomic, copy)   NSString *screenName;
+
+@end

+ 57 - 0
RedAnt ERP Mobile/GoogleAnalytics/GoogleAnalytics/Sources/GAITracker.h

@@ -0,0 +1,57 @@
+/*!
+ @header    GAITracker.h
+ @abstract  Google Analytics iOS SDK Tracker Header
+ @copyright Copyright 2013 Google Inc. All rights reserved.
+*/
+
+#import <Foundation/Foundation.h>
+
+/*!
+ Google Analytics tracking interface. Obtain instances of this interface from
+ [GAI trackerWithTrackingId:] to track screens, events, transactions, timing,
+ and exceptions. The implementation of this interface is thread-safe, and no
+ calls are expected to block or take a long time.  All network and disk activity
+ will take place in the background.
+ */
+@protocol GAITracker<NSObject>
+
+/*!
+ Name of this tracker.
+ */
+@property(nonatomic, readonly) NSString *name;
+
+/*!
+ Allow collection of IDFA and related fields if set to true.  Default is false.
+ */
+@property(nonatomic) BOOL allowIDFACollection;
+
+/*!
+ Set a tracking parameter.
+
+ @param parameterName The parameter name.
+
+ @param value The value to set for the parameter. If this is nil, the
+ value for the parameter will be cleared.
+ */
+- (void)set:(NSString *)parameterName
+      value:(NSString *)value;
+
+/*!
+ Get a tracking parameter.
+
+ @param parameterName The parameter name.
+
+ @returns The parameter value, or nil if no value for the given parameter is
+ set.
+ */
+- (NSString *)get:(NSString *)parameterName;
+
+/*!
+ Queue tracking information with the given parameter values.
+
+ @param parameters A map from parameter names to parameter values which will be
+ set just for this piece of tracking information, or nil for none.
+ */
+- (void)send:(NSDictionary *)parameters;
+
+@end

+ 199 - 0
RedAnt ERP Mobile/GoogleAnalytics/GoogleToolboxForMac/Foundation/GTMNSData+zlib.h

@@ -0,0 +1,199 @@
+//
+//  GTMNSData+zlib.h
+//
+//  Copyright 2007-2008 Google Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License"); you may not
+//  use this file except in compliance with the License.  You may obtain a copy
+//  of the License at
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+//  License for the specific language governing permissions and limitations under
+//  the License.
+//
+
+#import <Foundation/Foundation.h>
+#import "GTMDefines.h"
+
+/// Helpers for dealing w/ zlib inflate/deflate calls.
+@interface NSData (GTMZLibAdditions)
+
+// NOTE: For 64bit, none of these apis handle input sizes >32bits, they will
+// return nil when given such data.  To handle data of that size you really
+// should be streaming it rather then doing it all in memory.
+
+#pragma mark Gzip Compression
+
+/// Return an autoreleased NSData w/ the result of gzipping the bytes.
+//
+//  Uses the default compression level.
++ (NSData *)gtm_dataByGzippingBytes:(const void *)bytes
+                             length:(NSUInteger)length;
++ (NSData *)gtm_dataByGzippingBytes:(const void *)bytes
+                             length:(NSUInteger)length
+                              error:(NSError **)error;
+
+/// Return an autoreleased NSData w/ the result of gzipping the payload of |data|.
+//
+//  Uses the default compression level.
++ (NSData *)gtm_dataByGzippingData:(NSData *)data __attribute__((deprecated("Use error variant")));
++ (NSData *)gtm_dataByGzippingData:(NSData *)data
+                             error:(NSError **)error;
+
+/// Return an autoreleased NSData w/ the result of gzipping the bytes using |level| compression level.
+//
+// |level| can be 1-9, any other values will be clipped to that range.
++ (NSData *)gtm_dataByGzippingBytes:(const void *)bytes
+                             length:(NSUInteger)length
+                   compressionLevel:(int)level __attribute__((deprecated("Use error variant")));
++ (NSData *)gtm_dataByGzippingBytes:(const void *)bytes
+                             length:(NSUInteger)length
+                   compressionLevel:(int)level
+                              error:(NSError **)error;
+
+/// Return an autoreleased NSData w/ the result of gzipping the payload of |data| using |level| compression level.
++ (NSData *)gtm_dataByGzippingData:(NSData *)data
+                  compressionLevel:(int)level __attribute__((deprecated("Use error variant")));
++ (NSData *)gtm_dataByGzippingData:(NSData *)data
+                  compressionLevel:(int)level
+                             error:(NSError **)error;
+
+#pragma mark Zlib "Stream" Compression
+
+// NOTE: deflate is *NOT* gzip.  deflate is a "zlib" stream.  pick which one
+// you really want to create.  (the inflate api will handle either)
+
+/// Return an autoreleased NSData w/ the result of deflating the bytes.
+//
+//  Uses the default compression level.
++ (NSData *)gtm_dataByDeflatingBytes:(const void *)bytes
+                              length:(NSUInteger)length __attribute__((deprecated("Use error variant")));
++ (NSData *)gtm_dataByDeflatingBytes:(const void *)bytes
+                              length:(NSUInteger)length
+                               error:(NSError **)error;
+
+/// Return an autoreleased NSData w/ the result of deflating the payload of |data|.
+//
+//  Uses the default compression level.
++ (NSData *)gtm_dataByDeflatingData:(NSData *)data __attribute__((deprecated("Use error variant")));
++ (NSData *)gtm_dataByDeflatingData:(NSData *)data
+                              error:(NSError **)error;
+
+/// Return an autoreleased NSData w/ the result of deflating the bytes using |level| compression level.
+//
+// |level| can be 1-9, any other values will be clipped to that range.
++ (NSData *)gtm_dataByDeflatingBytes:(const void *)bytes
+                              length:(NSUInteger)length
+                    compressionLevel:(int)level __attribute__((deprecated("Use error variant")));
++ (NSData *)gtm_dataByDeflatingBytes:(const void *)bytes
+                              length:(NSUInteger)length
+                    compressionLevel:(int)level
+                               error:(NSError **)error;
+
+/// Return an autoreleased NSData w/ the result of deflating the payload of |data| using |level| compression level.
++ (NSData *)gtm_dataByDeflatingData:(NSData *)data
+                   compressionLevel:(int)level __attribute__((deprecated("Use error variant")));
++ (NSData *)gtm_dataByDeflatingData:(NSData *)data
+                   compressionLevel:(int)level
+                              error:(NSError **)error;
+
+#pragma mark Uncompress of Gzip or Zlib
+
+/// Return an autoreleased NSData w/ the result of decompressing the bytes.
+//
+// The bytes to decompress can be zlib or gzip payloads.
++ (NSData *)gtm_dataByInflatingBytes:(const void *)bytes
+                              length:(NSUInteger)length __attribute__((deprecated("Use error variant")));
++ (NSData *)gtm_dataByInflatingBytes:(const void *)bytes
+                              length:(NSUInteger)length
+                               error:(NSError **)error;
+
+/// Return an autoreleased NSData w/ the result of decompressing the payload of |data|.
+//
+// The data to decompress can be zlib or gzip payloads.
++ (NSData *)gtm_dataByInflatingData:(NSData *)data __attribute__((deprecated("Use error variant")));
++ (NSData *)gtm_dataByInflatingData:(NSData *)data
+                              error:(NSError **)error;
+
+#pragma mark "Raw" Compression Support
+
+// NOTE: raw deflate is *NOT* gzip or deflate.  it does not include a header
+// of any form and should only be used within streams here an external crc/etc.
+// is done to validate the data.  The RawInflate apis can be used on data
+// processed like this.
+
+/// Return an autoreleased NSData w/ the result of *raw* deflating the bytes.
+//
+//  Uses the default compression level.
+//  *No* header is added to the resulting data.
++ (NSData *)gtm_dataByRawDeflatingBytes:(const void *)bytes
+                                 length:(NSUInteger)length __attribute__((deprecated("Use error variant")));
++ (NSData *)gtm_dataByRawDeflatingBytes:(const void *)bytes
+                                 length:(NSUInteger)length
+                                  error:(NSError **)error;
+
+/// Return an autoreleased NSData w/ the result of *raw* deflating the payload of |data|.
+//
+//  Uses the default compression level.
+//  *No* header is added to the resulting data.
++ (NSData *)gtm_dataByRawDeflatingData:(NSData *)data __attribute__((deprecated("Use error variant")));
++ (NSData *)gtm_dataByRawDeflatingData:(NSData *)data
+                                 error:(NSError **)error;
+
+/// Return an autoreleased NSData w/ the result of *raw* deflating the bytes using |level| compression level.
+//
+// |level| can be 1-9, any other values will be clipped to that range.
+//  *No* header is added to the resulting data.
++ (NSData *)gtm_dataByRawDeflatingBytes:(const void *)bytes
+                                 length:(NSUInteger)length
+                       compressionLevel:(int)level __attribute__((deprecated("Use error variant")));
++ (NSData *)gtm_dataByRawDeflatingBytes:(const void *)bytes
+                                 length:(NSUInteger)length
+                       compressionLevel:(int)level
+                                  error:(NSError **)error;
+
+/// Return an autoreleased NSData w/ the result of *raw* deflating the payload of |data| using |level| compression level.
+//  *No* header is added to the resulting data.
++ (NSData *)gtm_dataByRawDeflatingData:(NSData *)data
+                      compressionLevel:(int)level __attribute__((deprecated("Use error variant")));
++ (NSData *)gtm_dataByRawDeflatingData:(NSData *)data
+                      compressionLevel:(int)level
+                                 error:(NSError **)error;
+
+/// Return an autoreleased NSData w/ the result of *raw* decompressing the bytes.
+//
+// The data to decompress, it should *not* have any header (zlib nor gzip).
++ (NSData *)gtm_dataByRawInflatingBytes:(const void *)bytes
+                                 length:(NSUInteger)length __attribute__((deprecated("Use error variant")));
++ (NSData *)gtm_dataByRawInflatingBytes:(const void *)bytes
+                                 length:(NSUInteger)length
+                                  error:(NSError **)error;
+
+/// Return an autoreleased NSData w/ the result of *raw* decompressing the payload of |data|.
+//
+// The data to decompress, it should *not* have any header (zlib nor gzip).
++ (NSData *)gtm_dataByRawInflatingData:(NSData *)data __attribute__((deprecated("Use error variant")));
++ (NSData *)gtm_dataByRawInflatingData:(NSData *)data
+                                 error:(NSError **)error;
+
+@end
+
+FOUNDATION_EXPORT NSString *const GTMNSDataZlibErrorDomain;
+FOUNDATION_EXPORT NSString *const GTMNSDataZlibErrorKey;  // NSNumber
+FOUNDATION_EXPORT NSString *const GTMNSDataZlibRemainingBytesKey;  // NSNumber
+
+typedef NS_ENUM(NSInteger, GTMNSDataZlibError) {
+  GTMNSDataZlibErrorGreaterThan32BitsToCompress = 1024,
+  // An internal zlib error.
+  // GTMNSDataZlibErrorKey will contain the error value.
+  // NSLocalizedDescriptionKey may contain an error string from zlib.
+  // Look in zlib.h for list of errors.
+  GTMNSDataZlibErrorInternal,
+  // There was left over data in the buffer that was not used.
+  // GTMNSDataZlibRemainingBytesKey will contain number of remaining bytes.
+  GTMNSDataZlibErrorDataRemaining
+};

+ 531 - 0
RedAnt ERP Mobile/GoogleAnalytics/GoogleToolboxForMac/Foundation/GTMNSData+zlib.m

@@ -0,0 +1,531 @@
+//
+//  GTMNSData+zlib.m
+//
+//  Copyright 2007-2008 Google Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License"); you may not
+//  use this file except in compliance with the License.  You may obtain a copy
+//  of the License at
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+//  License for the specific language governing permissions and limitations under
+//  the License.
+//
+
+#import "GTMNSData+zlib.h"
+#import <zlib.h>
+#import "GTMDefines.h"
+
+#define kChunkSize 1024
+
+NSString *const GTMNSDataZlibErrorDomain = @"com.google.GTMNSDataZlibErrorDomain";
+NSString *const GTMNSDataZlibErrorKey = @"GTMNSDataZlibErrorKey";
+NSString *const GTMNSDataZlibRemainingBytesKey = @"GTMNSDataZlibRemainingBytesKey";
+
+typedef enum {
+  CompressionModeZlib,
+  CompressionModeGzip,
+  CompressionModeRaw,
+} CompressionMode;
+
+@interface NSData (GTMZlibAdditionsPrivate)
++ (NSData *)gtm_dataByCompressingBytes:(const void *)bytes
+                                length:(NSUInteger)length
+                      compressionLevel:(int)level
+                                  mode:(CompressionMode)mode
+                                 error:(NSError **)error;
++ (NSData *)gtm_dataByInflatingBytes:(const void *)bytes
+                              length:(NSUInteger)length
+                           isRawData:(BOOL)isRawData
+                               error:(NSError **)error;
+@end
+
+@implementation NSData (GTMZlibAdditionsPrivate)
+
++ (NSData *)gtm_dataByCompressingBytes:(const void *)bytes
+                                length:(NSUInteger)length
+                      compressionLevel:(int)level
+                                  mode:(CompressionMode)mode
+                                 error:(NSError **)error {
+  if (!bytes || !length) {
+    return nil;
+  }
+
+#if defined(__LP64__) && __LP64__
+  // Don't support > 32bit length for 64 bit, see note in header.
+  if (length > UINT_MAX) {
+    if (error) {
+      *error = [NSError errorWithDomain:GTMNSDataZlibErrorDomain
+                                   code:GTMNSDataZlibErrorGreaterThan32BitsToCompress
+                               userInfo:nil];
+    }
+    return nil;
+  }
+#endif
+
+  if (level == Z_DEFAULT_COMPRESSION) {
+    // the default value is actually outside the range, so we have to let it
+    // through specifically.
+  } else if (level < Z_BEST_SPEED) {
+    level = Z_BEST_SPEED;
+  } else if (level > Z_BEST_COMPRESSION) {
+    level = Z_BEST_COMPRESSION;
+  }
+
+  z_stream strm;
+  bzero(&strm, sizeof(z_stream));
+
+  int memLevel = 8; // the default
+  int windowBits = 15; // the default
+  switch (mode) {
+    case CompressionModeZlib:
+      // nothing to do
+      break;
+
+    case CompressionModeGzip:
+      windowBits += 16; // enable gzip header instead of zlib header
+      break;
+
+    case CompressionModeRaw:
+      windowBits *= -1; // Negative to mean no header.
+      break;
+  }
+  int retCode;
+  if ((retCode = deflateInit2(&strm, level, Z_DEFLATED, windowBits,
+                              memLevel, Z_DEFAULT_STRATEGY)) != Z_OK) {
+    // COV_NF_START - no real way to force this in a unittest (we guard all args)
+    if (error) {
+      NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode]
+                                                           forKey:GTMNSDataZlibErrorKey];
+      *error = [NSError errorWithDomain:GTMNSDataZlibErrorDomain
+                                   code:GTMNSDataZlibErrorInternal
+                               userInfo:userInfo];
+    }
+    return nil;
+    // COV_NF_END
+  }
+
+  // hint the size at 1/4 the input size
+  NSMutableData *result = [NSMutableData dataWithCapacity:(length/4)];
+  unsigned char output[kChunkSize];
+
+  // setup the input
+  strm.avail_in = (unsigned int)length;
+  strm.next_in = (unsigned char*)bytes;
+
+  // loop to collect the data
+  do {
+    // update what we're passing in
+    strm.avail_out = kChunkSize;
+    strm.next_out = output;
+    retCode = deflate(&strm, Z_FINISH);
+    if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) {
+      // COV_NF_START - no real way to force this in a unittest
+      // (in inflate, we can feed bogus/truncated data to test, but an error
+      // here would be some internal issue w/in zlib, and there isn't any real
+      // way to test it)
+      if (error) {
+        NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode]
+                                                             forKey:GTMNSDataZlibErrorKey];
+        *error = [NSError errorWithDomain:GTMNSDataZlibErrorDomain
+                                     code:GTMNSDataZlibErrorInternal
+                                 userInfo:userInfo];
+      }
+      deflateEnd(&strm);
+      return nil;
+      // COV_NF_END
+    }
+    // collect what we got
+    unsigned gotBack = kChunkSize - strm.avail_out;
+    if (gotBack > 0) {
+      [result appendBytes:output length:gotBack];
+    }
+
+  } while (retCode == Z_OK);
+
+  // if the loop exits, we used all input and the stream ended
+  _GTMDevAssert(strm.avail_in == 0,
+                @"thought we finished deflate w/o using all input, %u bytes left",
+                strm.avail_in);
+  _GTMDevAssert(retCode == Z_STREAM_END,
+                @"thought we finished deflate w/o getting a result of stream end, code %d",
+                retCode);
+
+  // clean up
+  deflateEnd(&strm);
+
+  return result;
+} // gtm_dataByCompressingBytes:length:compressionLevel:useGzip:
+
++ (NSData *)gtm_dataByInflatingBytes:(const void *)bytes
+                              length:(NSUInteger)length
+                           isRawData:(BOOL)isRawData
+                               error:(NSError **)error {
+  if (!bytes || !length) {
+    return nil;
+  }
+
+#if defined(__LP64__) && __LP64__
+  // Don't support > 32bit length for 64 bit, see note in header.
+  if (length > UINT_MAX) {
+    return nil;
+  }
+#endif
+
+  z_stream strm;
+  bzero(&strm, sizeof(z_stream));
+
+  // setup the input
+  strm.avail_in = (unsigned int)length;
+  strm.next_in = (unsigned char*)bytes;
+
+  int windowBits = 15; // 15 to enable any window size
+  if (isRawData) {
+    windowBits *= -1; // make it negative to signal no header.
+  } else {
+    windowBits += 32; // and +32 to enable zlib or gzip header detection.
+  }
+
+  int retCode;
+  if ((retCode = inflateInit2(&strm, windowBits)) != Z_OK) {
+    // COV_NF_START - no real way to force this in a unittest (we guard all args)
+    if (error) {
+      NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode]
+                                                           forKey:GTMNSDataZlibErrorKey];
+      *error = [NSError errorWithDomain:GTMNSDataZlibErrorDomain
+                                   code:GTMNSDataZlibErrorInternal
+                               userInfo:userInfo];
+    }
+    return nil;
+    // COV_NF_END
+  }
+
+  // hint the size at 4x the input size
+  NSMutableData *result = [NSMutableData dataWithCapacity:(length*4)];
+  unsigned char output[kChunkSize];
+
+  // loop to collect the data
+  do {
+    // update what we're passing in
+    strm.avail_out = kChunkSize;
+    strm.next_out = output;
+    retCode = inflate(&strm, Z_NO_FLUSH);
+    if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) {
+      if (error) {
+        NSMutableDictionary *userInfo =
+            [NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode]
+                                               forKey:GTMNSDataZlibErrorKey];
+        if (strm.msg) {
+          NSString *message = [NSString stringWithUTF8String:strm.msg];
+          if (message) {
+            [userInfo setObject:message forKey:NSLocalizedDescriptionKey];
+          }
+        }
+        *error = [NSError errorWithDomain:GTMNSDataZlibErrorDomain
+                                     code:GTMNSDataZlibErrorInternal
+                                 userInfo:userInfo];
+      }
+      inflateEnd(&strm);
+      return nil;
+    }
+    // collect what we got
+    unsigned gotBack = kChunkSize - strm.avail_out;
+    if (gotBack > 0) {
+      [result appendBytes:output length:gotBack];
+    }
+
+  } while (retCode == Z_OK);
+
+  // make sure there wasn't more data tacked onto the end of a valid compressed
+  // stream.
+  if (strm.avail_in != 0) {
+    if (error) {
+      NSDictionary *userInfo =
+          [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedInt:strm.avail_in]
+                                      forKey:GTMNSDataZlibRemainingBytesKey];
+      *error = [NSError errorWithDomain:GTMNSDataZlibErrorDomain
+                                   code:GTMNSDataZlibErrorDataRemaining
+                               userInfo:userInfo];
+    }
+    result = nil;
+  }
+  // the only way out of the loop was by hitting the end of the stream
+  _GTMDevAssert(retCode == Z_STREAM_END,
+                @"thought we finished inflate w/o getting a result of stream end, code %d",
+                retCode);
+
+  // clean up
+  inflateEnd(&strm);
+
+  return result;
+} // gtm_dataByInflatingBytes:length:windowBits:
+
+@end
+
+
+@implementation NSData (GTMZLibAdditions)
+
++ (NSData *)gtm_dataByGzippingBytes:(const void *)bytes
+                             length:(NSUInteger)length {
+  return [self gtm_dataByGzippingBytes:bytes length:length error:NULL];
+} // gtm_dataByGzippingBytes:length:
+
++ (NSData *)gtm_dataByGzippingBytes:(const void *)bytes
+                             length:(NSUInteger)length
+                              error:(NSError **)error {
+  return [self gtm_dataByCompressingBytes:bytes
+                                   length:length
+                         compressionLevel:Z_DEFAULT_COMPRESSION
+                                     mode:CompressionModeGzip
+                                    error:error];
+} // gtm_dataByGzippingBytes:length:error:
+
++ (NSData *)gtm_dataByGzippingData:(NSData *)data {
+  return [self gtm_dataByGzippingData:data error:NULL];
+} // gtm_dataByGzippingData:
+
++ (NSData *)gtm_dataByGzippingData:(NSData *)data error:(NSError **)error {
+  return [self gtm_dataByCompressingBytes:[data bytes]
+                                   length:[data length]
+                         compressionLevel:Z_DEFAULT_COMPRESSION
+                                     mode:CompressionModeGzip
+                                    error:error];
+} // gtm_dataByGzippingData:error:
+
++ (NSData *)gtm_dataByGzippingBytes:(const void *)bytes
+                             length:(NSUInteger)length
+                   compressionLevel:(int)level {
+  return [self gtm_dataByGzippingBytes:bytes
+                                length:length
+                      compressionLevel:level
+                                 error:NULL];
+} // gtm_dataByGzippingBytes:length:level:
+
++ (NSData *)gtm_dataByGzippingBytes:(const void *)bytes
+                             length:(NSUInteger)length
+                   compressionLevel:(int)level
+                              error:(NSError **)error{
+  return [self gtm_dataByCompressingBytes:bytes
+                                   length:length
+                         compressionLevel:level
+                                     mode:CompressionModeGzip
+                                    error:error];
+} // gtm_dataByGzippingBytes:length:level:error
+
++ (NSData *)gtm_dataByGzippingData:(NSData *)data
+                  compressionLevel:(int)level {
+  return [self gtm_dataByGzippingData:data
+                     compressionLevel:level
+                                error:NULL];
+} // gtm_dataByGzippingData:level:
+
++ (NSData *)gtm_dataByGzippingData:(NSData *)data
+                  compressionLevel:(int)level
+                             error:(NSError **)error{
+  return [self gtm_dataByCompressingBytes:[data bytes]
+                                   length:[data length]
+                         compressionLevel:level
+                                     mode:CompressionModeGzip
+                                    error:error];
+} // gtm_dataByGzippingData:level:error
+
+#pragma mark -
+
++ (NSData *)gtm_dataByDeflatingBytes:(const void *)bytes
+                              length:(NSUInteger)length {
+  return [self gtm_dataByDeflatingBytes:bytes
+                                 length:length
+                                  error:NULL];
+} // gtm_dataByDeflatingBytes:length:
+
++ (NSData *)gtm_dataByDeflatingBytes:(const void *)bytes
+                              length:(NSUInteger)length
+                               error:(NSError **)error{
+  return [self gtm_dataByCompressingBytes:bytes
+                                   length:length
+                         compressionLevel:Z_DEFAULT_COMPRESSION
+                                     mode:CompressionModeZlib
+                                    error:error];
+} // gtm_dataByDeflatingBytes:length:error
+
++ (NSData *)gtm_dataByDeflatingData:(NSData *)data {
+  return [self gtm_dataByDeflatingData:data error:NULL];
+} // gtm_dataByDeflatingData:
+
++ (NSData *)gtm_dataByDeflatingData:(NSData *)data error:(NSError **)error {
+  return [self gtm_dataByCompressingBytes:[data bytes]
+                                   length:[data length]
+                         compressionLevel:Z_DEFAULT_COMPRESSION
+                                     mode:CompressionModeZlib
+                                    error:error];
+} // gtm_dataByDeflatingData:
+
++ (NSData *)gtm_dataByDeflatingBytes:(const void *)bytes
+                              length:(NSUInteger)length
+                    compressionLevel:(int)level {
+  return [self gtm_dataByDeflatingBytes:bytes
+                                 length:length
+                       compressionLevel:level
+                                  error:NULL];
+} // gtm_dataByDeflatingBytes:length:level:
+
++ (NSData *)gtm_dataByDeflatingBytes:(const void *)bytes
+                              length:(NSUInteger)length
+                    compressionLevel:(int)level
+                               error:(NSError **)error {
+  return [self gtm_dataByCompressingBytes:bytes
+                                   length:length
+                         compressionLevel:level
+                                     mode:CompressionModeZlib
+                                    error:error];
+} // gtm_dataByDeflatingBytes:length:level:error:
+
++ (NSData *)gtm_dataByDeflatingData:(NSData *)data
+                   compressionLevel:(int)level {
+  return [self gtm_dataByDeflatingData:data
+                      compressionLevel:level
+                                 error:NULL];
+} // gtm_dataByDeflatingData:level:
+
++ (NSData *)gtm_dataByDeflatingData:(NSData *)data
+                   compressionLevel:(int)level
+                              error:(NSError **)error {
+  return [self gtm_dataByCompressingBytes:[data bytes]
+                                   length:[data length]
+                         compressionLevel:level
+                                     mode:CompressionModeZlib
+                                    error:error];
+} // gtm_dataByDeflatingData:level:error:
+
+#pragma mark -
+
++ (NSData *)gtm_dataByInflatingBytes:(const void *)bytes
+                              length:(NSUInteger)length {
+  return [self gtm_dataByInflatingBytes:bytes
+                                 length:length
+                                  error:NULL];
+} // gtm_dataByInflatingBytes:length:
+
++ (NSData *)gtm_dataByInflatingBytes:(const void *)bytes
+                              length:(NSUInteger)length
+                               error:(NSError **)error {
+  return [self gtm_dataByInflatingBytes:bytes
+                                 length:length
+                              isRawData:NO
+                                  error:error];
+} // gtm_dataByInflatingBytes:length:error:
+
++ (NSData *)gtm_dataByInflatingData:(NSData *)data {
+  return [self gtm_dataByInflatingData:data error:NULL];
+} // gtm_dataByInflatingData:
+
++ (NSData *)gtm_dataByInflatingData:(NSData *)data
+                              error:(NSError **)error {
+  return [self gtm_dataByInflatingBytes:[data bytes]
+                                 length:[data length]
+                              isRawData:NO
+                                  error:error];
+} // gtm_dataByInflatingData:
+
+#pragma mark -
+
++ (NSData *)gtm_dataByRawDeflatingBytes:(const void *)bytes
+                                 length:(NSUInteger)length {
+  return [self gtm_dataByRawDeflatingBytes:(const void *)bytes
+                                    length:(NSUInteger)length
+                                     error:NULL];
+} // gtm_dataByRawDeflatingBytes:length:
+
++ (NSData *)gtm_dataByRawDeflatingBytes:(const void *)bytes
+                                 length:(NSUInteger)length
+                                  error:(NSError **)error {
+  return [self gtm_dataByCompressingBytes:bytes
+                                   length:length
+                         compressionLevel:Z_DEFAULT_COMPRESSION
+                                     mode:CompressionModeRaw
+                                    error:error];
+} // gtm_dataByRawDeflatingBytes:length:error:
+
++ (NSData *)gtm_dataByRawDeflatingData:(NSData *)data {
+  return [self gtm_dataByRawDeflatingData:data error:NULL];
+} // gtm_dataByRawDeflatingData:
+
++ (NSData *)gtm_dataByRawDeflatingData:(NSData *)data error:(NSError **)error {
+  return [self gtm_dataByCompressingBytes:[data bytes]
+                                   length:[data length]
+                         compressionLevel:Z_DEFAULT_COMPRESSION
+                                     mode:CompressionModeRaw
+                                    error:error];
+} // gtm_dataByRawDeflatingData:error:
+
++ (NSData *)gtm_dataByRawDeflatingBytes:(const void *)bytes
+                                 length:(NSUInteger)length
+                       compressionLevel:(int)level {
+  return [self gtm_dataByRawDeflatingBytes:bytes
+                                    length:length
+                          compressionLevel:level
+                                     error:NULL];
+} // gtm_dataByRawDeflatingBytes:length:compressionLevel:
+
++ (NSData *)gtm_dataByRawDeflatingBytes:(const void *)bytes
+                                 length:(NSUInteger)length
+                       compressionLevel:(int)level
+                                  error:(NSError **)error{
+  return [self gtm_dataByCompressingBytes:bytes
+                                   length:length
+                         compressionLevel:level
+                                     mode:CompressionModeRaw
+                                    error:error];
+} // gtm_dataByRawDeflatingBytes:length:compressionLevel:error:
+
++ (NSData *)gtm_dataByRawDeflatingData:(NSData *)data
+                      compressionLevel:(int)level {
+  return [self gtm_dataByRawDeflatingData:data
+                         compressionLevel:level
+                                    error:NULL];
+} // gtm_dataByRawDeflatingData:compressionLevel:
+
++ (NSData *)gtm_dataByRawDeflatingData:(NSData *)data
+                      compressionLevel:(int)level
+                                 error:(NSError **)error {
+  return [self gtm_dataByCompressingBytes:[data bytes]
+                                   length:[data length]
+                         compressionLevel:level
+                                     mode:CompressionModeRaw
+                                    error:error];
+} // gtm_dataByRawDeflatingData:compressionLevel:error:
+
++ (NSData *)gtm_dataByRawInflatingBytes:(const void *)bytes
+                                 length:(NSUInteger)length {
+  return [self gtm_dataByInflatingBytes:bytes
+                                 length:length
+                                  error:NULL];
+} // gtm_dataByRawInflatingBytes:length:
+
++ (NSData *)gtm_dataByRawInflatingBytes:(const void *)bytes
+                                 length:(NSUInteger)length
+                                  error:(NSError **)error{
+  return [self gtm_dataByInflatingBytes:bytes
+                                 length:length
+                              isRawData:YES
+                                  error:error];
+} // gtm_dataByRawInflatingBytes:length:error:
+
++ (NSData *)gtm_dataByRawInflatingData:(NSData *)data {
+  return [self gtm_dataByRawInflatingData:data
+                                    error:NULL];
+} // gtm_dataByRawInflatingData:
+
++ (NSData *)gtm_dataByRawInflatingData:(NSData *)data
+                                 error:(NSError **)error {
+  return [self gtm_dataByInflatingBytes:[data bytes]
+                                 length:[data length]
+                              isRawData:YES
+                                  error:error];
+} // gtm_dataByRawInflatingData:error:
+
+@end

+ 392 - 0
RedAnt ERP Mobile/GoogleAnalytics/GoogleToolboxForMac/GTMDefines.h

@@ -0,0 +1,392 @@
+//
+// GTMDefines.h
+//
+//  Copyright 2008 Google Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License"); you may not
+//  use this file except in compliance with the License.  You may obtain a copy
+//  of the License at
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+//  License for the specific language governing permissions and limitations under
+//  the License.
+//
+
+// ============================================================================
+
+#include <AvailabilityMacros.h>
+#include <TargetConditionals.h>
+
+#ifdef __OBJC__
+#include <Foundation/NSObjCRuntime.h>
+#endif  // __OBJC__
+
+#if TARGET_OS_IPHONE
+#include <Availability.h>
+#endif  // TARGET_OS_IPHONE
+
+// ----------------------------------------------------------------------------
+// CPP symbols that can be overridden in a prefix to control how the toolbox
+// is compiled.
+// ----------------------------------------------------------------------------
+
+
+// By setting the GTM_CONTAINERS_VALIDATION_FAILED_LOG and
+// GTM_CONTAINERS_VALIDATION_FAILED_ASSERT macros you can control what happens
+// when a validation fails. If you implement your own validators, you may want
+// to control their internals using the same macros for consistency.
+#ifndef GTM_CONTAINERS_VALIDATION_FAILED_ASSERT
+  #define GTM_CONTAINERS_VALIDATION_FAILED_ASSERT 0
+#endif
+
+// Ensure __has_feature and __has_extension are safe to use.
+// See http://clang-analyzer.llvm.org/annotations.html
+#ifndef __has_feature      // Optional.
+  #define __has_feature(x) 0 // Compatibility with non-clang compilers.
+#endif
+
+#ifndef __has_extension
+  #define __has_extension __has_feature // Compatibility with pre-3.0 compilers.
+#endif
+
+// Give ourselves a consistent way to do inlines.  Apple's macros even use
+// a few different actual definitions, so we're based off of the foundation
+// one.
+#if !defined(GTM_INLINE)
+  #if (defined (__GNUC__) && (__GNUC__ == 4)) || defined (__clang__)
+    #define GTM_INLINE static __inline__ __attribute__((always_inline))
+  #else
+    #define GTM_INLINE static __inline__
+  #endif
+#endif
+
+// Give ourselves a consistent way of doing externs that links up nicely
+// when mixing objc and objc++
+#if !defined (GTM_EXTERN)
+  #if defined __cplusplus
+    #define GTM_EXTERN extern "C"
+    #define GTM_EXTERN_C_BEGIN extern "C" {
+    #define GTM_EXTERN_C_END }
+  #else
+    #define GTM_EXTERN extern
+    #define GTM_EXTERN_C_BEGIN
+    #define GTM_EXTERN_C_END
+  #endif
+#endif
+
+// Give ourselves a consistent way of exporting things if we have visibility
+// set to hidden.
+#if !defined (GTM_EXPORT)
+  #define GTM_EXPORT __attribute__((visibility("default")))
+#endif
+
+// Give ourselves a consistent way of declaring something as unused. This
+// doesn't use __unused because that is only supported in gcc 4.2 and greater.
+#if !defined (GTM_UNUSED)
+#define GTM_UNUSED(x) ((void)(x))
+#endif
+
+// _GTMDevLog & _GTMDevAssert
+//
+// _GTMDevLog & _GTMDevAssert are meant to be a very lightweight shell for
+// developer level errors.  This implementation simply macros to NSLog/NSAssert.
+// It is not intended to be a general logging/reporting system.
+//
+// Please see http://code.google.com/p/google-toolbox-for-mac/wiki/DevLogNAssert
+// for a little more background on the usage of these macros.
+//
+//    _GTMDevLog           log some error/problem in debug builds
+//    _GTMDevAssert        assert if condition isn't met w/in a method/function
+//                           in all builds.
+//
+// To replace this system, just provide different macro definitions in your
+// prefix header.  Remember, any implementation you provide *must* be thread
+// safe since this could be called by anything in what ever situtation it has
+// been placed in.
+//
+
+// We only define the simple macros if nothing else has defined this.
+#ifndef _GTMDevLog
+
+#ifdef DEBUG
+  #define _GTMDevLog(...) NSLog(__VA_ARGS__)
+#else
+  #define _GTMDevLog(...) do { } while (0)
+#endif
+
+#endif // _GTMDevLog
+
+#ifndef _GTMDevAssert
+// we directly invoke the NSAssert handler so we can pass on the varargs
+// (NSAssert doesn't have a macro we can use that takes varargs)
+#if !defined(NS_BLOCK_ASSERTIONS)
+  #define _GTMDevAssert(condition, ...)                                       \
+    do {                                                                      \
+      if (!(condition)) {                                                     \
+        [[NSAssertionHandler currentHandler]                                  \
+            handleFailureInFunction:(NSString *)                              \
+                                        [NSString stringWithUTF8String:__PRETTY_FUNCTION__] \
+                               file:(NSString *)[NSString stringWithUTF8String:__FILE__]  \
+                         lineNumber:__LINE__                                  \
+                        description:__VA_ARGS__];                             \
+      }                                                                       \
+    } while(0)
+#else // !defined(NS_BLOCK_ASSERTIONS)
+  #define _GTMDevAssert(condition, ...) do { } while (0)
+#endif // !defined(NS_BLOCK_ASSERTIONS)
+
+#endif // _GTMDevAssert
+
+// _GTMCompileAssert
+//
+// Note:  Software for current compilers should just use _Static_assert directly
+// instead of this macro.
+//
+// _GTMCompileAssert is an assert that is meant to fire at compile time if you
+// want to check things at compile instead of runtime. For example if you
+// want to check that a wchar is 4 bytes instead of 2 you would use
+// _GTMCompileAssert(sizeof(wchar_t) == 4, wchar_t_is_4_bytes_on_OS_X)
+// Note that the second "arg" is not in quotes, and must be a valid processor
+// symbol in it's own right (no spaces, punctuation etc).
+
+// Wrapping this in an #ifndef allows external groups to define their own
+// compile time assert scheme.
+#ifndef _GTMCompileAssert
+  #if __has_feature(c_static_assert) || __has_extension(c_static_assert)
+    #define _GTMCompileAssert(test, msg) _Static_assert((test), #msg)
+  #else
+    // Pre-Xcode 7 support.
+    //
+    // We got this technique from here:
+    // http://unixjunkie.blogspot.com/2007/10/better-compile-time-asserts_29.html
+    #define _GTMCompileAssertSymbolInner(line, msg) _GTMCOMPILEASSERT ## line ## __ ## msg
+    #define _GTMCompileAssertSymbol(line, msg) _GTMCompileAssertSymbolInner(line, msg)
+    #define _GTMCompileAssert(test, msg) \
+      typedef char _GTMCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ]
+  #endif  // __has_feature(c_static_assert) || __has_extension(c_static_assert)
+#endif // _GTMCompileAssert
+
+// ----------------------------------------------------------------------------
+// CPP symbols defined based on the project settings so the GTM code has
+// simple things to test against w/o scattering the knowledge of project
+// setting through all the code.
+// ----------------------------------------------------------------------------
+
+// Provide a single constant CPP symbol that all of GTM uses for ifdefing
+// iPhone code.
+#if TARGET_OS_IPHONE // iPhone SDK
+  // For iPhone specific stuff
+  #define GTM_IPHONE_SDK 1
+  #if TARGET_IPHONE_SIMULATOR
+    #define GTM_IPHONE_DEVICE 0
+    #define GTM_IPHONE_SIMULATOR 1
+  #else
+    #define GTM_IPHONE_DEVICE 1
+    #define GTM_IPHONE_SIMULATOR 0
+  #endif  // TARGET_IPHONE_SIMULATOR
+  // By default, GTM has provided it's own unittesting support, define this
+  // to use the support provided by Xcode, especially for the Xcode4 support
+  // for unittesting.
+  #ifndef GTM_USING_XCTEST
+    #define GTM_USING_XCTEST 0
+  #endif
+  #define GTM_MACOS_SDK 0
+#else
+  // For MacOS specific stuff
+  #define GTM_MACOS_SDK 1
+  #define GTM_IPHONE_SDK 0
+  #define GTM_IPHONE_SIMULATOR 0
+  #define GTM_IPHONE_DEVICE 0
+  #ifndef GTM_USING_XCTEST
+    #define GTM_USING_XCTEST 0
+  #endif
+#endif
+
+// Some of our own availability macros
+#if GTM_MACOS_SDK
+#define GTM_AVAILABLE_ONLY_ON_IPHONE UNAVAILABLE_ATTRIBUTE
+#define GTM_AVAILABLE_ONLY_ON_MACOS
+#else
+#define GTM_AVAILABLE_ONLY_ON_IPHONE
+#define GTM_AVAILABLE_ONLY_ON_MACOS UNAVAILABLE_ATTRIBUTE
+#endif
+
+// GC was dropped by Apple, define the old constant incase anyone still keys
+// off of it.
+#ifndef GTM_SUPPORT_GC
+  #define GTM_SUPPORT_GC 0
+#endif
+
+// Some support for advanced clang static analysis functionality
+#ifndef NS_RETURNS_RETAINED
+  #if __has_feature(attribute_ns_returns_retained)
+    #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
+  #else
+    #define NS_RETURNS_RETAINED
+  #endif
+#endif
+
+#ifndef NS_RETURNS_NOT_RETAINED
+  #if __has_feature(attribute_ns_returns_not_retained)
+    #define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
+  #else
+    #define NS_RETURNS_NOT_RETAINED
+  #endif
+#endif
+
+#ifndef CF_RETURNS_RETAINED
+  #if __has_feature(attribute_cf_returns_retained)
+    #define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
+  #else
+    #define CF_RETURNS_RETAINED
+  #endif
+#endif
+
+#ifndef CF_RETURNS_NOT_RETAINED
+  #if __has_feature(attribute_cf_returns_not_retained)
+    #define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained))
+  #else
+    #define CF_RETURNS_NOT_RETAINED
+  #endif
+#endif
+
+#ifndef NS_CONSUMED
+  #if __has_feature(attribute_ns_consumed)
+    #define NS_CONSUMED __attribute__((ns_consumed))
+  #else
+    #define NS_CONSUMED
+  #endif
+#endif
+
+#ifndef CF_CONSUMED
+  #if __has_feature(attribute_cf_consumed)
+    #define CF_CONSUMED __attribute__((cf_consumed))
+  #else
+    #define CF_CONSUMED
+  #endif
+#endif
+
+#ifndef NS_CONSUMES_SELF
+  #if __has_feature(attribute_ns_consumes_self)
+    #define NS_CONSUMES_SELF __attribute__((ns_consumes_self))
+  #else
+    #define NS_CONSUMES_SELF
+  #endif
+#endif
+
+#ifndef GTM_NONNULL
+  #if defined(__has_attribute)
+    #if __has_attribute(nonnull)
+      #define GTM_NONNULL(x) __attribute__((nonnull x))
+    #else
+      #define GTM_NONNULL(x)
+    #endif
+  #else
+    #define GTM_NONNULL(x)
+  #endif
+#endif
+
+// Invalidates the initializer from which it's called.
+#ifndef GTMInvalidateInitializer
+  #if __has_feature(objc_arc)
+    #define GTMInvalidateInitializer() \
+      do { \
+        [self class]; /* Avoid warning of dead store to |self|. */ \
+        _GTMDevAssert(NO, @"Invalid initializer."); \
+        return nil; \
+      } while (0)
+  #else
+    #define GTMInvalidateInitializer() \
+      do { \
+        [self release]; \
+        _GTMDevAssert(NO, @"Invalid initializer."); \
+        return nil; \
+      } while (0)
+  #endif
+#endif
+
+#ifndef GTMCFAutorelease
+  // GTMCFAutorelease returns an id.  In contrast, Apple's CFAutorelease returns
+  // a CFTypeRef.
+  #if __has_feature(objc_arc)
+    #define GTMCFAutorelease(x) CFBridgingRelease(x)
+  #else
+    #define GTMCFAutorelease(x) ([(id)x autorelease])
+  #endif
+#endif
+
+#ifdef __OBJC__
+
+
+// Macro to allow you to create NSStrings out of other macros.
+// #define FOO foo
+// NSString *fooString = GTM_NSSTRINGIFY(FOO);
+#if !defined (GTM_NSSTRINGIFY)
+  #define GTM_NSSTRINGIFY_INNER(x) @#x
+  #define GTM_NSSTRINGIFY(x) GTM_NSSTRINGIFY_INNER(x)
+#endif
+
+// Macro to allow fast enumeration when building for 10.5 or later, and
+// reliance on NSEnumerator for 10.4.  Remember, NSDictionary w/ FastEnumeration
+// does keys, so pick the right thing, nothing is done on the FastEnumeration
+// side to be sure you're getting what you wanted.
+#ifndef GTM_FOREACH_OBJECT
+  #if TARGET_OS_IPHONE || !(MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
+    #define GTM_FOREACH_ENUMEREE(element, enumeration) \
+      for (element in enumeration)
+    #define GTM_FOREACH_OBJECT(element, collection) \
+      for (element in collection)
+    #define GTM_FOREACH_KEY(element, collection) \
+      for (element in collection)
+  #else
+    #define GTM_FOREACH_ENUMEREE(element, enumeration) \
+      for (NSEnumerator *_ ## element ## _enum = enumeration; \
+           (element = [_ ## element ## _enum nextObject]) != nil; )
+    #define GTM_FOREACH_OBJECT(element, collection) \
+      GTM_FOREACH_ENUMEREE(element, [collection objectEnumerator])
+    #define GTM_FOREACH_KEY(element, collection) \
+      GTM_FOREACH_ENUMEREE(element, [collection keyEnumerator])
+  #endif
+#endif
+
+// ============================================================================
+
+// GTM_SEL_STRING is for specifying selector (usually property) names to KVC
+// or KVO methods.
+// In debug it will generate warnings for undeclared selectors if
+// -Wunknown-selector is turned on.
+// In release it will have no runtime overhead.
+#ifndef GTM_SEL_STRING
+  #ifdef DEBUG
+    #define GTM_SEL_STRING(selName) NSStringFromSelector(@selector(selName))
+  #else
+    #define GTM_SEL_STRING(selName) @#selName
+  #endif  // DEBUG
+#endif  // GTM_SEL_STRING
+
+#ifndef GTM_WEAK
+#if __has_feature(objc_arc_weak)
+    // With ARC enabled, __weak means a reference that isn't implicitly
+    // retained.  __weak objects are accessed through runtime functions, so
+    // they are zeroed out, but this requires OS X 10.7+.
+    // At clang r251041+, ARC-style zeroing weak references even work in
+    // non-ARC mode.
+    #define GTM_WEAK __weak
+  #elif __has_feature(objc_arc)
+    // ARC, but targeting 10.6 or older, where zeroing weak references don't
+    // exist.
+    #define GTM_WEAK __unsafe_unretained
+  #else
+    // With manual reference counting, __weak used to be silently ignored.
+    // clang r251041 gives it the ARC semantics instead.  This means they
+    // now require a deployment target of 10.7, while some clients of GTM
+    // still target 10.6.  In these cases, expand to __unsafe_unretained instead
+    #define GTM_WEAK
+  #endif
+#endif
+
+#endif  // __OBJC__

+ 202 - 0
RedAnt ERP Mobile/GoogleAnalytics/GoogleToolboxForMac/LICENSE

@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 15 - 0
RedAnt ERP Mobile/GoogleAnalytics/GoogleToolboxForMac/README.md

@@ -0,0 +1,15 @@
+# GTM: Google Toolbox for Mac #
+
+**Project site** <https://github.com/google/google-toolbox-for-mac><br>
+**Discussion group** <http://groups.google.com/group/google-toolbox-for-mac>
+
+# Google Toolbox for Mac #
+
+A collection of source from different Google projects that may be of use to
+developers working other iOS or OS X projects.
+
+If you find a problem/bug or want a new feature to be included in the Google
+Toolbox for Mac, please join the
+[discussion group](http://groups.google.com/group/google-toolbox-for-mac)
+or submit an
+[issue](https://github.com/google/google-toolbox-for-mac/issues).

+ 256 - 2
RedAnt ERP Mobile/HMLG Mobile.xcodeproj/project.pbxproj

@@ -44,6 +44,21 @@
 		42A85BFC1E6004180058A9CE /* NetworkUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 42A85BF81E6004180058A9CE /* NetworkUtils.m */; };
 		42A85BFD1E6004180058A9CE /* PDFUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 42A85BFA1E6004180058A9CE /* PDFUtils.m */; };
 		42BB2F081E28986B0025C6CE /* signature.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 42BB2F071E28986B0025C6CE /* signature.storyboard */; };
+		42BEF3931E8A4C7D00632AB6 /* FirebaseAnalytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42BEF3661E8A4C7D00632AB6 /* FirebaseAnalytics.framework */; };
+		42BEF3941E8A4C7D00632AB6 /* FirebaseCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42BEF3691E8A4C7D00632AB6 /* FirebaseCore.framework */; };
+		42BEF3951E8A4C7D00632AB6 /* CHANGELOG.md in Sources */ = {isa = PBXBuildFile; fileRef = 42BEF36B1E8A4C7D00632AB6 /* CHANGELOG.md */; };
+		42BEF3961E8A4C7D00632AB6 /* FirebaseInstanceID.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42BEF36D1E8A4C7D00632AB6 /* FirebaseInstanceID.framework */; };
+		42BEF3971E8A4C7D00632AB6 /* README.md in Sources */ = {isa = PBXBuildFile; fileRef = 42BEF36E1E8A4C7D00632AB6 /* README.md */; };
+		42BEF3981E8A4C7D00632AB6 /* GGLAnalytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42BEF3711E8A4C7D00632AB6 /* GGLAnalytics.framework */; };
+		42BEF3991E8A4C7D00632AB6 /* GGLCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42BEF3721E8A4C7D00632AB6 /* GGLCore.framework */; };
+		42BEF39A1E8A4C7D00632AB6 /* README.md in Sources */ = {isa = PBXBuildFile; fileRef = 42BEF37B1E8A4C7D00632AB6 /* README.md */; };
+		42BEF39B1E8A4C7D00632AB6 /* GoogleAnalyst.m in Sources */ = {isa = PBXBuildFile; fileRef = 42BEF37D1E8A4C7D00632AB6 /* GoogleAnalyst.m */; };
+		42BEF39C1E8A4C7D00632AB6 /* libGoogleAnalytics.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42BEF3801E8A4C7D00632AB6 /* libGoogleAnalytics.a */; };
+		42BEF39D1E8A4C7D00632AB6 /* GTMNSData+zlib.m in Sources */ = {isa = PBXBuildFile; fileRef = 42BEF38F1E8A4C7D00632AB6 /* GTMNSData+zlib.m */; };
+		42BEF39E1E8A4C7D00632AB6 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 42BEF3911E8A4C7D00632AB6 /* LICENSE */; };
+		42BEF39F1E8A4C7D00632AB6 /* README.md in Sources */ = {isa = PBXBuildFile; fileRef = 42BEF3921E8A4C7D00632AB6 /* README.md */; };
+		42BEF3A21E8A4D0000632AB6 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42BEF3A11E8A4D0000632AB6 /* SystemConfiguration.framework */; };
+		42BEF3A41E8A4D0700632AB6 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42BEF3A31E8A4D0700632AB6 /* CoreData.framework */; };
 		715002021D13CDBE00F5927F /* BundleDetailButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 715002011D13CDBE00F5927F /* BundleDetailButton.m */; };
 		715850431CF6F0C400856B20 /* DefaultAppearance.m in Sources */ = {isa = PBXBuildFile; fileRef = 715850421CF6F0C400856B20 /* DefaultAppearance.m */; };
 		716AF8DE1D792157001188E0 /* offline_status_filter_cadedate.json in Resources */ = {isa = PBXBuildFile; fileRef = 716AF8DD1D792157001188E0 /* offline_status_filter_cadedate.json */; };
@@ -297,6 +312,40 @@
 		42A85BF91E6004180058A9CE /* PDFUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PDFUtils.h; path = common/PDFUtils.h; sourceTree = SOURCE_ROOT; };
 		42A85BFA1E6004180058A9CE /* PDFUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PDFUtils.m; path = common/PDFUtils.m; sourceTree = SOURCE_ROOT; };
 		42BB2F071E28986B0025C6CE /* signature.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = signature.storyboard; path = common/Functions/signature/signature.storyboard; sourceTree = SOURCE_ROOT; };
+		42BEF3661E8A4C7D00632AB6 /* FirebaseAnalytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = FirebaseAnalytics.framework; sourceTree = "<group>"; };
+		42BEF3691E8A4C7D00632AB6 /* FirebaseCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = FirebaseCore.framework; sourceTree = "<group>"; };
+		42BEF36B1E8A4C7D00632AB6 /* CHANGELOG.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = "<group>"; };
+		42BEF36D1E8A4C7D00632AB6 /* FirebaseInstanceID.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = FirebaseInstanceID.framework; sourceTree = "<group>"; };
+		42BEF36E1E8A4C7D00632AB6 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
+		42BEF3711E8A4C7D00632AB6 /* GGLAnalytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = GGLAnalytics.framework; sourceTree = "<group>"; };
+		42BEF3721E8A4C7D00632AB6 /* GGLCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = GGLCore.framework; sourceTree = "<group>"; };
+		42BEF3741E8A4C7D00632AB6 /* Analytics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Analytics.h; sourceTree = "<group>"; };
+		42BEF3751E8A4C7D00632AB6 /* Core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Core.h; sourceTree = "<group>"; };
+		42BEF3761E8A4C7D00632AB6 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
+		42BEF3781E8A4C7D00632AB6 /* Analytics-Module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Analytics-Module.h"; sourceTree = "<group>"; };
+		42BEF3791E8A4C7D00632AB6 /* Core-Module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Core-Module.h"; sourceTree = "<group>"; };
+		42BEF37A1E8A4C7D00632AB6 /* SignIn-Module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SignIn-Module.h"; sourceTree = "<group>"; };
+		42BEF37B1E8A4C7D00632AB6 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
+		42BEF37C1E8A4C7D00632AB6 /* GoogleAnalyst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GoogleAnalyst.h; sourceTree = "<group>"; };
+		42BEF37D1E8A4C7D00632AB6 /* GoogleAnalyst.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GoogleAnalyst.m; sourceTree = "<group>"; };
+		42BEF3801E8A4C7D00632AB6 /* libGoogleAnalytics.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libGoogleAnalytics.a; sourceTree = "<group>"; };
+		42BEF3821E8A4C7D00632AB6 /* GAI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GAI.h; sourceTree = "<group>"; };
+		42BEF3831E8A4C7D00632AB6 /* GAIDictionaryBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GAIDictionaryBuilder.h; sourceTree = "<group>"; };
+		42BEF3841E8A4C7D00632AB6 /* GAIEcommerceFields.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GAIEcommerceFields.h; sourceTree = "<group>"; };
+		42BEF3851E8A4C7D00632AB6 /* GAIEcommerceProduct.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GAIEcommerceProduct.h; sourceTree = "<group>"; };
+		42BEF3861E8A4C7D00632AB6 /* GAIEcommerceProductAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GAIEcommerceProductAction.h; sourceTree = "<group>"; };
+		42BEF3871E8A4C7D00632AB6 /* GAIEcommercePromotion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GAIEcommercePromotion.h; sourceTree = "<group>"; };
+		42BEF3881E8A4C7D00632AB6 /* GAIFields.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GAIFields.h; sourceTree = "<group>"; };
+		42BEF3891E8A4C7D00632AB6 /* GAILogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GAILogger.h; sourceTree = "<group>"; };
+		42BEF38A1E8A4C7D00632AB6 /* GAITrackedViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GAITrackedViewController.h; sourceTree = "<group>"; };
+		42BEF38B1E8A4C7D00632AB6 /* GAITracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GAITracker.h; sourceTree = "<group>"; };
+		42BEF38E1E8A4C7D00632AB6 /* GTMNSData+zlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTMNSData+zlib.h"; sourceTree = "<group>"; };
+		42BEF38F1E8A4C7D00632AB6 /* GTMNSData+zlib.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSData+zlib.m"; sourceTree = "<group>"; };
+		42BEF3901E8A4C7D00632AB6 /* GTMDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMDefines.h; sourceTree = "<group>"; };
+		42BEF3911E8A4C7D00632AB6 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
+		42BEF3921E8A4C7D00632AB6 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
+		42BEF3A11E8A4D0000632AB6 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
+		42BEF3A31E8A4D0700632AB6 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
 		715002001D13CDBE00F5927F /* BundleDetailButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BundleDetailButton.h; path = common/Functions/BundleDetailButton.h; sourceTree = SOURCE_ROOT; };
 		715002011D13CDBE00F5927F /* BundleDetailButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BundleDetailButton.m; path = common/Functions/BundleDetailButton.m; sourceTree = SOURCE_ROOT; };
 		715850411CF6F0C400856B20 /* DefaultAppearance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DefaultAppearance.h; path = common/Functions/DefaultAppearance.h; sourceTree = SOURCE_ROOT; };
@@ -638,18 +687,26 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				42BEF3A41E8A4D0700632AB6 /* CoreData.framework in Frameworks */,
+				42BEF3A21E8A4D0000632AB6 /* SystemConfiguration.framework in Frameworks */,
 				7183EA4E1CF2A6DF00524787 /* libz.tbd in Frameworks */,
 				7183EA501CF2A70800524787 /* libScanApiCore.a in Frameworks */,
+				42BEF3991E8A4C7D00632AB6 /* GGLCore.framework in Frameworks */,
 				7183EA521CF2A71A00524787 /* AVFoundation.framework in Frameworks */,
 				7183EA561CF2A72D00524787 /* ExternalAccessory.framework in Frameworks */,
+				42BEF3981E8A4C7D00632AB6 /* GGLAnalytics.framework in Frameworks */,
+				42BEF3941E8A4C7D00632AB6 /* FirebaseCore.framework in Frameworks */,
 				7183EA541CF2A72300524787 /* AudioToolbox.framework in Frameworks */,
 				7183EA581CF2A74500524787 /* libsqlite3.tbd in Frameworks */,
+				42BEF3961E8A4C7D00632AB6 /* FirebaseInstanceID.framework in Frameworks */,
 				7183EA5A1CF2A75600524787 /* Accelerate.framework in Frameworks */,
 				7183EA5C1CF2A76000524787 /* QuartzCore.framework in Frameworks */,
 				7183EA5E1CF2A77000524787 /* CoreGraphics.framework in Frameworks */,
 				7183EA601CF2A77B00524787 /* UIKit.framework in Frameworks */,
 				7183EA621CF2A78700524787 /* Foundation.framework in Frameworks */,
 				7183EA641CF2A7B500524787 /* libPods.a in Frameworks */,
+				42BEF3931E8A4C7D00632AB6 /* FirebaseAnalytics.framework in Frameworks */,
+				42BEF39C1E8A4C7D00632AB6 /* libGoogleAnalytics.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -752,10 +809,179 @@
 			path = common/pdfCreator;
 			sourceTree = SOURCE_ROOT;
 		};
+		42BEF3631E8A4C7D00632AB6 /* GoogleAnalytics */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3641E8A4C7D00632AB6 /* FirebaseAnalytics */,
+				42BEF3671E8A4C7D00632AB6 /* FirebaseCore */,
+				42BEF36A1E8A4C7D00632AB6 /* FirebaseInstanceID */,
+				42BEF36F1E8A4C7D00632AB6 /* Google */,
+				42BEF37C1E8A4C7D00632AB6 /* GoogleAnalyst.h */,
+				42BEF37D1E8A4C7D00632AB6 /* GoogleAnalyst.m */,
+				42BEF37E1E8A4C7D00632AB6 /* GoogleAnalytics */,
+				42BEF38C1E8A4C7D00632AB6 /* GoogleToolboxForMac */,
+			);
+			path = GoogleAnalytics;
+			sourceTree = SOURCE_ROOT;
+		};
+		42BEF3641E8A4C7D00632AB6 /* FirebaseAnalytics */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3651E8A4C7D00632AB6 /* Frameworks */,
+			);
+			path = FirebaseAnalytics;
+			sourceTree = "<group>";
+		};
+		42BEF3651E8A4C7D00632AB6 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3661E8A4C7D00632AB6 /* FirebaseAnalytics.framework */,
+			);
+			path = Frameworks;
+			sourceTree = "<group>";
+		};
+		42BEF3671E8A4C7D00632AB6 /* FirebaseCore */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3681E8A4C7D00632AB6 /* Frameworks */,
+			);
+			path = FirebaseCore;
+			sourceTree = "<group>";
+		};
+		42BEF3681E8A4C7D00632AB6 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3691E8A4C7D00632AB6 /* FirebaseCore.framework */,
+			);
+			path = Frameworks;
+			sourceTree = "<group>";
+		};
+		42BEF36A1E8A4C7D00632AB6 /* FirebaseInstanceID */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF36B1E8A4C7D00632AB6 /* CHANGELOG.md */,
+				42BEF36C1E8A4C7D00632AB6 /* Frameworks */,
+				42BEF36E1E8A4C7D00632AB6 /* README.md */,
+			);
+			path = FirebaseInstanceID;
+			sourceTree = "<group>";
+		};
+		42BEF36C1E8A4C7D00632AB6 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF36D1E8A4C7D00632AB6 /* FirebaseInstanceID.framework */,
+			);
+			path = Frameworks;
+			sourceTree = "<group>";
+		};
+		42BEF36F1E8A4C7D00632AB6 /* Google */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3701E8A4C7D00632AB6 /* Frameworks */,
+				42BEF3731E8A4C7D00632AB6 /* Headers */,
+				42BEF37B1E8A4C7D00632AB6 /* README.md */,
+			);
+			path = Google;
+			sourceTree = "<group>";
+		};
+		42BEF3701E8A4C7D00632AB6 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3711E8A4C7D00632AB6 /* GGLAnalytics.framework */,
+				42BEF3721E8A4C7D00632AB6 /* GGLCore.framework */,
+			);
+			path = Frameworks;
+			sourceTree = "<group>";
+		};
+		42BEF3731E8A4C7D00632AB6 /* Headers */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3741E8A4C7D00632AB6 /* Analytics.h */,
+				42BEF3751E8A4C7D00632AB6 /* Core.h */,
+				42BEF3761E8A4C7D00632AB6 /* module.modulemap */,
+				42BEF3771E8A4C7D00632AB6 /* ModuleHeaders */,
+			);
+			path = Headers;
+			sourceTree = "<group>";
+		};
+		42BEF3771E8A4C7D00632AB6 /* ModuleHeaders */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3781E8A4C7D00632AB6 /* Analytics-Module.h */,
+				42BEF3791E8A4C7D00632AB6 /* Core-Module.h */,
+				42BEF37A1E8A4C7D00632AB6 /* SignIn-Module.h */,
+			);
+			path = ModuleHeaders;
+			sourceTree = "<group>";
+		};
+		42BEF37E1E8A4C7D00632AB6 /* GoogleAnalytics */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF37F1E8A4C7D00632AB6 /* Libraries */,
+				42BEF3811E8A4C7D00632AB6 /* Sources */,
+			);
+			path = GoogleAnalytics;
+			sourceTree = "<group>";
+		};
+		42BEF37F1E8A4C7D00632AB6 /* Libraries */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3801E8A4C7D00632AB6 /* libGoogleAnalytics.a */,
+			);
+			path = Libraries;
+			sourceTree = "<group>";
+		};
+		42BEF3811E8A4C7D00632AB6 /* Sources */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3821E8A4C7D00632AB6 /* GAI.h */,
+				42BEF3831E8A4C7D00632AB6 /* GAIDictionaryBuilder.h */,
+				42BEF3841E8A4C7D00632AB6 /* GAIEcommerceFields.h */,
+				42BEF3851E8A4C7D00632AB6 /* GAIEcommerceProduct.h */,
+				42BEF3861E8A4C7D00632AB6 /* GAIEcommerceProductAction.h */,
+				42BEF3871E8A4C7D00632AB6 /* GAIEcommercePromotion.h */,
+				42BEF3881E8A4C7D00632AB6 /* GAIFields.h */,
+				42BEF3891E8A4C7D00632AB6 /* GAILogger.h */,
+				42BEF38A1E8A4C7D00632AB6 /* GAITrackedViewController.h */,
+				42BEF38B1E8A4C7D00632AB6 /* GAITracker.h */,
+			);
+			path = Sources;
+			sourceTree = "<group>";
+		};
+		42BEF38C1E8A4C7D00632AB6 /* GoogleToolboxForMac */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF38D1E8A4C7D00632AB6 /* Foundation */,
+				42BEF3901E8A4C7D00632AB6 /* GTMDefines.h */,
+				42BEF3911E8A4C7D00632AB6 /* LICENSE */,
+				42BEF3921E8A4C7D00632AB6 /* README.md */,
+			);
+			path = GoogleToolboxForMac;
+			sourceTree = "<group>";
+		};
+		42BEF38D1E8A4C7D00632AB6 /* Foundation */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF38E1E8A4C7D00632AB6 /* GTMNSData+zlib.h */,
+				42BEF38F1E8A4C7D00632AB6 /* GTMNSData+zlib.m */,
+			);
+			path = Foundation;
+			sourceTree = "<group>";
+		};
+		42BEF3A01E8A4CFF00632AB6 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3A31E8A4D0700632AB6 /* CoreData.framework */,
+				42BEF3A11E8A4D0000632AB6 /* SystemConfiguration.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
 		7183E83B1CF2913E00524787 = {
 			isa = PBXGroup;
 			children = (
 				7183E8461CF2913E00524787 /* HMLG Mobile */,
+				42BEF3A01E8A4CFF00632AB6 /* Frameworks */,
 			);
 			sourceTree = "<group>";
 		};
@@ -888,6 +1114,7 @@
 			children = (
 				42A85BF11E60039A0058A9CE /* HWWeakTimer.h */,
 				42A85BF21E60039A0058A9CE /* HWWeakTimer.m */,
+				42BEF3631E8A4C7D00632AB6 /* GoogleAnalytics */,
 				428980731E24B2C2005F1BD8 /* pdfCreator */,
 				428980561E24935E005F1BD8 /* UIColor+HEX */,
 				428980491E249340005F1BD8 /* JKLock */,
@@ -1499,6 +1726,7 @@
 				7183EA1B1CF29FCB00524787 /* status_filter_cadedate_open.json in Resources */,
 				7183EA051CF29FCB00524787 /* customer_info_template_edit.json in Resources */,
 				7183E9231CF29F4500524787 /* softScanBeep.wav in Resources */,
+				42BEF39E1E8A4C7D00632AB6 /* LICENSE in Resources */,
 				7183E9F31CF29FCB00524787 /* debug_category_filter.json in Resources */,
 				7183EA441CF2A06600524787 /* Main.storyboard in Resources */,
 				7183EA411CF2A04D00524787 /* OLM.storyboard in Resources */,
@@ -1578,6 +1806,7 @@
 				7183EA361CF29FCB00524787 /* UserListViewController.m in Sources */,
 				7183E9131CF29F4500524787 /* CommonEditorCellLabel.m in Sources */,
 				7183EA111CF29FCB00524787 /* HomeTableViewCellTopic.m in Sources */,
+				42BEF39A1E8A4C7D00632AB6 /* README.md in Sources */,
 				7195623F1CF580E800C74A49 /* DefaultTableHeaderView.m in Sources */,
 				7183EA1F1CF29FCB00524787 /* PDFListViewController.m in Sources */,
 				7183E8A81CF29F3900524787 /* iSalesDB.m in Sources */,
@@ -1635,6 +1864,7 @@
 				7183E9111CF29F4500524787 /* CommonEditorCellEnum.m in Sources */,
 				7183E8A11CF29F3900524787 /* AESCrypt.m in Sources */,
 				7183EA141CF29FCB00524787 /* OrderDetailHtmlCell.m in Sources */,
+				42BEF39F1E8A4C7D00632AB6 /* README.md in Sources */,
 				7183EA321CF29FCB00524787 /* ScannerSettingViewController.m in Sources */,
 				428980901E24B2C2005F1BD8 /* PDFDrawable.m in Sources */,
 				7183E9FD1CF29FCB00524787 /* RATreeView+UIScrollView.m in Sources */,
@@ -1650,9 +1880,12 @@
 				7183EA1A1CF29FCB00524787 /* OrderListViewController.m in Sources */,
 				7183E91A1CF29F4500524787 /* DatePickerViewController.m in Sources */,
 				7183E8491CF2913E00524787 /* main.m in Sources */,
+				42BEF3971E8A4C7D00632AB6 /* README.md in Sources */,
+				42BEF39D1E8A4C7D00632AB6 /* GTMNSData+zlib.m in Sources */,
 				7183E9E91CF29FCB00524787 /* BundleModelViewController.m in Sources */,
 				7183E8991CF29F3900524787 /* bitstream.c in Sources */,
 				428980541E249340005F1BD8 /* JKLockController.m in Sources */,
+				42BEF3951E8A4C7D00632AB6 /* CHANGELOG.md in Sources */,
 				7183E9F51CF29FCB00524787 /* RATreeNodeCollectionController.m in Sources */,
 				7183EA281CF29FCB00524787 /* ItemSearchFilterViewController.m in Sources */,
 				7183E9201CF29F4500524787 /* CommonGridViewController.m in Sources */,
@@ -1695,6 +1928,7 @@
 				7183EA161CF29FCB00524787 /* OrderDetailModelCell.m in Sources */,
 				7183E9221CF29F4500524787 /* ScanApiHelper.mm in Sources */,
 				7183EA381CF29FCB00524787 /* WatchListViewController.m in Sources */,
+				42BEF39B1E8A4C7D00632AB6 /* GoogleAnalyst.m in Sources */,
 				7183EA131CF29FCB00524787 /* CreateOrderViewController.m in Sources */,
 				7183E9E21CF29FCB00524787 /* PDFViewController.m in Sources */,
 				7183E9FF1CF29FCB00524787 /* CreditCardEditorViewController.m in Sources */,
@@ -1847,6 +2081,13 @@
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				DEVELOPMENT_TEAM = HXWLAA5YN5;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(PROJECT_DIR)/GoogleAnalytics/FirebaseAnalytics/Frameworks",
+					"$(PROJECT_DIR)/GoogleAnalytics/FirebaseCore/Frameworks",
+					"$(PROJECT_DIR)/GoogleAnalytics/FirebaseInstanceID/Frameworks",
+					"$(PROJECT_DIR)/GoogleAnalytics/Google/Frameworks",
+				);
 				GCC_PREFIX_HEADER = "HMLG Mobile/PrefixHeader.pch";
 				HEADER_SEARCH_PATHS = (
 					"$(inherited)",
@@ -1856,7 +2097,10 @@
 				INFOPLIST_FILE = "HMLG Mobile/Info.plist";
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
-				LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/ScanApiSDK-10.2.227-2/lib";
+				LIBRARY_SEARCH_PATHS = (
+					"$(PROJECT_DIR)/ScanApiSDK-10.2.227-2/lib",
+					"$(PROJECT_DIR)/GoogleAnalytics/GoogleAnalytics/Libraries",
+				);
 				PODS_ROOT = "${SRCROOT}/Pods";
 				PRODUCT_BUNDLE_IDENTIFIER = "usai.apex.HMLG-Mobile";
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1870,6 +2114,13 @@
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				DEVELOPMENT_TEAM = HXWLAA5YN5;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(PROJECT_DIR)/GoogleAnalytics/FirebaseAnalytics/Frameworks",
+					"$(PROJECT_DIR)/GoogleAnalytics/FirebaseCore/Frameworks",
+					"$(PROJECT_DIR)/GoogleAnalytics/FirebaseInstanceID/Frameworks",
+					"$(PROJECT_DIR)/GoogleAnalytics/Google/Frameworks",
+				);
 				GCC_PREFIX_HEADER = "HMLG Mobile/PrefixHeader.pch";
 				HEADER_SEARCH_PATHS = (
 					"$(inherited)",
@@ -1879,7 +2130,10 @@
 				INFOPLIST_FILE = "HMLG Mobile/Info.plist";
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
-				LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/ScanApiSDK-10.2.227-2/lib";
+				LIBRARY_SEARCH_PATHS = (
+					"$(PROJECT_DIR)/ScanApiSDK-10.2.227-2/lib",
+					"$(PROJECT_DIR)/GoogleAnalytics/GoogleAnalytics/Libraries",
+				);
 				PODS_ROOT = "${SRCROOT}/Pods";
 				PRODUCT_BUNDLE_IDENTIFIER = "usai.apex.HMLG-Mobile";
 				PRODUCT_NAME = "$(TARGET_NAME)";

+ 2 - 0
RedAnt ERP Mobile/Pods/Pods.xcodeproj/project.pbxproj

@@ -572,6 +572,7 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 3EF5FD27EFB7130C197AC39BC76900BC /* AFNetworking.xcconfig */;
 			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				GCC_PREFIX_HEADER = "Target Support Files/AFNetworking/AFNetworking-prefix.pch";
 				IPHONEOS_DEPLOYMENT_TARGET = 7.0;
@@ -590,6 +591,7 @@
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 3EF5FD27EFB7130C197AC39BC76900BC /* AFNetworking.xcconfig */;
 			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				GCC_PREFIX_HEADER = "Target Support Files/AFNetworking/AFNetworking-prefix.pch";
 				IPHONEOS_DEPLOYMENT_TARGET = 7.0;

BIN
RedAnt ERP Mobile/RedAnt ERP Mobile.xcworkspace/xcuserdata/macmini1.xcuserdatad/UserInterfaceState.xcuserstate


+ 13 - 3
RedAnt ERP Mobile/RedAnt ERP Mobile.xcworkspace/xcuserdata/macmini1.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@@ -10,14 +10,24 @@
             ignoreCount = "0"
             continueAfterRunningActions = "No"
             filePath = "iSales-NPD/AppDelegate.m"
-            timestampString = "511169614.76319"
+            timestampString = "513142121.064533"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "500"
-            endingLineNumber = "500"
+            startingLineNumber = "511"
+            endingLineNumber = "511"
             landmarkName = "UncaughtExceptionHandler()"
             landmarkType = "9">
          </BreakpointContent>
       </BreakpointProxy>
+      <BreakpointProxy
+         BreakpointExtensionID = "Xcode.Breakpoint.ExceptionBreakpoint">
+         <BreakpointContent
+            shouldBeEnabled = "Yes"
+            ignoreCount = "0"
+            continueAfterRunningActions = "No"
+            scope = "0"
+            stopOnStyle = "0">
+         </BreakpointContent>
+      </BreakpointProxy>
    </Breakpoints>
 </Bucket>

+ 8 - 0
RedAnt ERP Mobile/common/ERPUtils.h

@@ -8,8 +8,16 @@
 
 #import <Foundation/Foundation.h>
 
+
+
+
+
 @interface ERPUtils : NSObject
 
 + (NSString *)orderStatus:(NSInteger)statusCode;
 
++ (NSString *)screenOfRequestString:(NSString *)urlString;
+
++ (void)googleAnalyticsSendRequestString:(NSString *)urlString WithScreen:(NSString *)screenName Action:(NSString *)action Extra:(NSDictionary *)extra;
+
 @end

+ 263 - 0
RedAnt ERP Mobile/common/ERPUtils.m

@@ -9,6 +9,11 @@
 #import "ERPUtils.h"
 #import "AppDelegate.h"
 #import "Singleton.h"
+#import "GoogleAnalyst.h"
+#import "iSalesNetwork.h"
+
+
+ 
 
 
 @implementation ERPUtils
@@ -55,4 +60,262 @@
     return status;
 }
 
++ (NSString *)screenOfRequestString:(NSString *)urlString {
+    
+    // Home View
+//    URL_LOAD_HOME // home
+//    URL_ITEM_SEARCH // particular category
+//    URL_ITEMSEARCHADDALL // add all
+
+    if ([urlString isEqualToString:URL_LOAD_HOME]) {
+        return @"HomeView";
+    }
+    
+    if ([urlString isEqualToString:URL_ITEM_SEARCH] || [urlString isEqualToString:URL_ITEMSEARCHADDALL]) {
+        return @"Particular Category";
+    }
+    
+    
+    // Category
+//    URL_REQUEST_CATMENU // category menu
+//    URL_CATEGORY_LOADMORE // category
+//    URL_CATEGORY // category
+//    URL_CATEGORYADDALL // add all
+
+    if ([urlString isEqualToString:URL_REQUEST_CATMENU] || [urlString isEqualToString:URL_CATEGORY_LOADMORE] || [urlString isEqualToString:URL_CATEGORY] || [urlString isEqualToString:URL_CATEGORYADDALL]) {
+        return @"Category";
+    }
+    
+    // Cart
+//    URL_CART
+//    URL_CART_SET_PRICE
+//    URL_CART_ITEM_NOTES
+//    URL_CART_GENERAL_NOTES
+//    URL_CART_INCRESEMENT
+//    URL_CARTDELIVERY
+//    URL_CART_REMOVE
+//    URL_CART2WISH
+//    URL_CUSTOMER_PENDINGORDER
+//    URL_EMAIL_CART
+    
+    if ([urlString isEqualToString:URL_CART] || [urlString isEqualToString:URL_CART_SET_PRICE] || [urlString isEqualToString:URL_CART_ITEM_NOTES] || [urlString isEqualToString:URL_CART_GENERAL_NOTES] || [urlString isEqualToString:URL_CART_INCRESEMENT] || [urlString isEqualToString:URL_CARTDELIVERY] || [urlString isEqualToString:URL_CART_REMOVE] || [urlString isEqualToString:URL_CART_REMOVE] || [urlString isEqualToString:URL_CART2WISH] || [urlString isEqualToString:URL_CUSTOMER_PENDINGORDER] || [urlString isEqualToString:URL_EMAIL_CART]) {
+        return @"Cart";
+    }
+    
+    // Order List
+//    URL_ORDER_LIST // order list
+//    URL_NEW_ORDER
+//    URL_DELETE_ORDER
+//    URL_CANCEL_ORDER
+    if ([urlString isEqualToString:URL_ORDER_LIST] || [urlString isEqualToString:URL_NEW_ORDER] || [urlString isEqualToString:URL_DELETE_ORDER] || [urlString isEqualToString:URL_CANCEL_ORDER]) {
+        return @"Order List";
+    }
+    
+    // Search
+//    URL_SEARCH // search
+//    URL_SEARCHADDALL // add all
+    if ([urlString isEqualToString:URL_SEARCH] || [urlString isEqualToString:URL_SEARCHADDALL]) {
+        return @"Search";
+    }
+
+    // Account
+//    URL_CUSTOMER_ADV_SEARCH // contact advanced search
+//    URL_CONTACT_LIST
+//    URL_SHIPTO_LIST
+//    URL_NEW_CUSTOMER
+    
+    if ([urlString isEqualToString:URL_CUSTOMER_ADV_SEARCH] || [urlString isEqualToString:URL_CONTACT_LIST] || [urlString isEqualToString:URL_SHIPTO_LIST] || [urlString isEqualToString:URL_NEW_CUSTOMER]) {
+        return @"Customer List";
+    }
+    
+    // Contact Info
+//    URL_CUSTOMER_INFO
+//    URL_EDIT_CUSTOMER
+//    URL_CUSTOMER_SAVE
+//    URL_CUSTOMER_UPDATE
+//    URL_UPDATE_CUSTOMER_BCARD // Update image
+//    URL_UPLOAD_IMG
+//    
+    if ([urlString isEqualToString:URL_CUSTOMER_INFO] || [urlString isEqualToString:URL_EDIT_CUSTOMER] || [urlString isEqualToString:URL_CUSTOMER_SAVE] || [urlString isEqualToString:URL_CUSTOMER_UPDATE] || [urlString isEqualToString:URL_UPDATE_CUSTOMER_BCARD] || [urlString isEqualToString:URL_UPLOAD_IMG]) {
+        return @"Customer Information";
+    }
+
+    // Wish List
+//    URL_WISH2CART
+//    URL_WATCHLIST
+//    URL_WATCHLIST_REMOVE
+    if ([urlString isEqualToString:URL_WISH2CART] || [urlString isEqualToString:URL_WATCHLIST] || [urlString isEqualToString:URL_WATCHLIST_REMOVE]) {
+        return @"Wish List";
+    }
+    
+    // Model Detail
+//    URL_ITEM_DETAIL
+//    URL_ADD_TO_WATCHLIST
+//    URL_ADD_TO_PORTFOLIO
+//    URL_NOTIFY_ME
+    if ([urlString isEqualToString:URL_NOTIFY_ME] || [urlString isEqualToString:URL_ADD_TO_PORTFOLIO] || [urlString isEqualToString:URL_ADD_TO_WATCHLIST] || [urlString isEqualToString:URL_ITEM_DETAIL] || [urlString isEqualToString:URL_ADD_TO_CART]) {
+        return @"Model Information";
+    }
+    
+    // Portfolio
+//    URL_PORTFOLIO_REMOVE
+//    URL_PORTFOLIO
+//    URL_PORTFOLIO_SET_PRICE
+//    URL_DM_PARAMS // Create Porfolio
+//    URL_REQUEST_DM // Save PDF
+//    URL_SAVE_DM // preview Save PDF
+//    URL_REQUEST_MODEL_QTY // Edit Portfolio
+    if ([urlString isEqualToString:URL_PORTFOLIO] || [urlString isEqualToString:URL_PORTFOLIO_REMOVE] || [urlString isEqualToString:URL_PORTFOLIO_SET_PRICE] || [urlString isEqualToString:URL_DM_PARAMS] || [urlString isEqualToString:URL_REQUEST_DM] || [urlString isEqualToString:URL_SAVE_DM] || [urlString isEqualToString:URL_REQUEST_MODEL_QTY]) {
+        return @"Portfolio";
+    }
+    
+    
+    // Portfolio List
+//    URL_DM_LIST
+//    URL_PORTFOLIOLIST_REMOVE
+    if ([urlString isEqualToString:URL_DM_LIST] || [urlString isEqualToString:URL_PORTFOLIOLIST_REMOVE]) {
+        return @"View Portfolio";
+    }
+    
+    // login logout
+//    URL_UPDATE_AUTH
+//    URL_LOGOUT
+//    URL_RETRIEVE_PASS // forget password
+//    URL_REQUEST_LOGIN // request login
+#ifdef BUILD_NPD
+    if ([urlString isEqualToString:URL_REQUEST_LOGIN] || [urlString isEqualToString:URL_RETRIEVE_PASS] || [urlString isEqualToString:URL_UPDATE_AUTH]) {
+        return @"Login View";
+    }
+#else
+    if ([urlString isEqualToString:URL_RETRIEVE_PASS] || [urlString isEqualToString:URL_UPDATE_AUTH]) {
+        return @"Login View";
+    }
+#endif
+    
+    // Place order
+//    URL_COMMIT_ORDER // place order
+//    URL_SAVE_ORDER // place order
+//    URL_UPDATE_ORDERCUSTOMER // place order
+//    URL_ADDRESS_EDOTOR // Address Editor
+//    URL_ADDRESS_SAVE // save address
+//    URL_CREDITCARD_EDOTOR // creditcard
+//    URL_CREDITCARD_SAVE //
+    if ([urlString isEqualToString:URL_CREDITCARD_SAVE] || [urlString isEqualToString:URL_CREDITCARD_EDOTOR] || [urlString isEqualToString:URL_ADDRESS_SAVE] || [urlString isEqualToString:URL_ADDRESS_EDOTOR] || [urlString isEqualToString:URL_UPDATE_ORDERCUSTOMER] || [urlString isEqualToString:URL_SAVE_ORDER] || [urlString isEqualToString:URL_COMMIT_ORDER]) {
+        return @"Place Order";
+    }
+    
+    
+    // Order Detail
+//    URL_ORDER_DETAIL // order detail
+//    URL_COPY_ORDER // order detail
+//    URL_SIGN_ORDER // order detail
+//    URL_OPEN_ORDER
+//    URL_RELEASE_ORDER
+    if ([urlString isEqualToString:URL_RELEASE_ORDER] || [urlString isEqualToString:URL_OPEN_ORDER] || [urlString isEqualToString:URL_SIGN_ORDER] || [urlString isEqualToString:URL_COPY_ORDER] || [urlString isEqualToString:URL_ORDER_DETAIL]) {
+        return @"Order Information";
+    }
+
+    
+    // Add To Cart
+//    URL_ADD_TO_CART
+    
+    
+
+    // offline
+//    URL_CHECK_OFFLINE
+//    URL_UPLOAD_OFFLINE
+//    URL_DOWNLOAD_OFFLINE
+//    URL_FINISH_DOWNLOAD_OFFLINE
+    
+    
+    // Price Setting
+//    URL_SET_PRICE_TYPE
+//    URL_GET_CIVEN_PRICE
+//    URL_SET_GIVEN_PRICE
+    if ([urlString isEqualToString:URL_SET_GIVEN_PRICE] || [urlString isEqualToString:URL_GET_CIVEN_PRICE] || [urlString isEqualToString:URL_SET_PRICE_TYPE]) {
+        return @"Price Setting";
+    }
+    
+    // Convert Order To NPD
+//    URL_SET_MERGE_ORDER
+    if ([urlString isEqualToString:URL_SET_MERGE_ORDER]) {
+        return @"Order List";
+    }
+    
+    
+    // NPD Policy
+//    URL_NPD_POLICY
+    
+
+    
+    return nil;
+}
+
++ (void)googleAnalyticsSendRequestString:(NSString *)urlString WithScreen:(NSString *)screenName Action:(NSString *)action Extra:(NSDictionary *)extra {
+    
+    if (!screenName && !action && !extra) {
+        return;
+    }
+    
+//    NSString *preScreenName = [GoogleAnalyst currentTrackScreen];
+    
+    // 1.   Track all screens and sessions.
+    [GoogleAnalyst trackScreen:screenName];
+    
+    if (action) {
+        
+        NSString *label = nil;
+        
+        if ([action isEqualToString:@"Login"]) { // 2.   Track user login and timing
+            
+            NSString *user = [extra objectForKey:@"user"];
+            [GoogleAnalyst trackSignInUserID:user];
+            
+        } else if ([action isEqualToString:@"Add To Cart"]) { // 3.   When user clicks on “Add to cart”
+            
+            if (extra) {
+                NSString *name = [extra objectForKey:@"ModelName"];
+                NSNumber *count = [extra objectForKey:@"Count"];
+                label = name;
+                
+                [GoogleAnalyst trackProduct:name action:action count:count];
+                
+                
+            }
+            
+        } else if ([action isEqualToString:@"Open A Model"]) { // 4.   user is just opening a model information to check on the item
+            
+            if (extra) {
+                NSString *name = [extra objectForKey:@"ModelName"];
+                label = name;
+                
+                [GoogleAnalyst trackProduct:name action:action count:nil];
+                
+                
+            }
+            
+        } else if ([action isEqualToString:@"Filter"] || [action isEqualToString:@"Search"]) { // 5.   user is using search/filter conditions on the app
+            
+            
+            
+        } else if ([action isEqualToString:@"Brow A Particular Category On Home"]){  // 6.   If user is browsing a particular category on home screen(new collection, dining…..)
+            
+            if (extra) {
+                NSString *coverName = extra[@"CoverName"];
+                label = coverName;
+            }
+            
+        } else {
+            
+        }
+        
+         [GoogleAnalyst trackEventCategory:screenName action:action label:label value:nil];
+
+    }
+
+
+}
+
+
+
 @end

+ 10 - 2
RedAnt ERP Mobile/common/Functions/camscan/ScannerViewController.m

@@ -26,6 +26,8 @@
 #import "MainViewController.h"
 #import "ContactListViewController.h"
 #import "CartUtils.h"
+#import "ERPUtils.h"
+#import "iSalesNetwork.h"
 
 #define SCANNER_TARGET_DETAIL 0
 #define SCANNER_TARGET_CART 1
@@ -401,12 +403,15 @@
     
     self.scan_val = [transformed stringValue];
     
+    NSString *action = nil;
     switch (self.target) {
         case SCANNER_TARGET_DETAIL:
         {
             DetailViewController* dvc = [self.storyboard instantiateViewControllerWithIdentifier:@"DetailViewController" ];
             //            dvc
             
+            action = @"Open A Model";
+            [ERPUtils googleAnalyticsSendRequestString:nil WithScreen:ScreenCodeCamScan Action:action Extra:nil];
             
             dvc.use_model_name = true;
             dvc.model_name=[transformed stringValue];
@@ -415,12 +420,13 @@
             
             [dvc reload];
             [self.navigationController pushViewController:dvc animated:true];
+            
+            
         }
             break;
         case SCANNER_TARGET_CART:
         {
             
-            
             [CartUtils add_to_cart:self selectorholder:self selector:@selector(addtocart)];
 //            return;
 //            [self add_toCart];
@@ -441,6 +447,8 @@
             break;
     }
     
+   
+    
 }
 
 
@@ -610,7 +618,7 @@
     
         dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
             
-            NSDictionary* return_json = [iSalesNetwork add_toCart_byName: self.scan_val];
+            NSDictionary* return_json = [iSalesNetwork add_toCart_byName: self.scan_val withScreen:ScreenCodeCamScan];
             
             dispatch_async(dispatch_get_main_queue(), ^{
                 

+ 5 - 3
RedAnt ERP Mobile/common/Functions/cart/CartViewController.m

@@ -425,6 +425,7 @@
     NSDictionary * item_json = self.content_arr[indexPath.row];//[self.content_data objectForKey:[NSString stringWithFormat:@"item_%ld",(long)indexPath.row]];
     
     NSString* product_id = [item_json valueForKey:@"product_id"];
+    NSString *name = [item_json valueForKey:@"model"];
     
     int is_rate = [item_json[@"is_rate"] intValue];
     if(is_rate==1)
@@ -436,6 +437,7 @@
     dvc.product_id=product_id;
     dvc.category_id=nil;
     dvc.ispush=true;
+    dvc.model_name = name;
     
     [dvc reload];
     [self.navigationController pushViewController:dvc animated:true];
@@ -1926,7 +1928,7 @@
             UIAlertView *waitting_alert = [RAUtils waiting_alert:@"Sending Email" title:@"Waiting"];
             dispatch_async(dispatch_get_global_queue(0,0), ^{
                 
-                NSDictionary *dic = [iSalesNetwork notifyModel:productID emailAddr:nil];
+                NSDictionary *dic = [iSalesNetwork notifyModel:productID emailAddr:nil withScreen:ScreenCodeCart];
                 
                 dispatch_async(dispatch_get_main_queue(), ^{
                     
@@ -2669,7 +2671,7 @@ commitEditingStyle:(UITableViewCellEditingStyle)editingStyle  forRowAtIndexPath:
     
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
         
-        NSDictionary* return_json = [iSalesNetwork add_toCart_byName: modelname];
+        NSDictionary* return_json = [iSalesNetwork add_toCart_byName: modelname withScreen:ScreenCodeCart];
         
         dispatch_async(dispatch_get_main_queue(), ^{
             
@@ -2957,7 +2959,7 @@ commitEditingStyle:(UITableViewCellEditingStyle)editingStyle  forRowAtIndexPath:
                 
                 dispatch_async(dispatch_get_global_queue(0, 0), ^{
                     
-                    NSDictionary *result = [iSalesNetwork notifyModel:productID emailAddr:text];
+                    NSDictionary *result = [iSalesNetwork notifyModel:productID emailAddr:text withScreen:ScreenCodeCart];
                     
                     dispatch_async(dispatch_get_main_queue(), ^{
                         

+ 2 - 0
RedAnt ERP Mobile/common/Functions/category/CategorySearchFilterViewController.m

@@ -12,6 +12,7 @@
 #import "RAUtils.h"
 
 
+
 @interface CategorySearchFilterViewController ()
 
 @end
@@ -454,6 +455,7 @@
 }
 - (IBAction)onSearchClick:(id)sender {
     
+
     NSString *ids = [[self get_checkedIDs:self.categoryMenu] componentsJoinedByString:@","];
     
     NSString* modelname = self.textModelName.text;

+ 6 - 5
RedAnt ERP Mobile/common/Functions/category/CategoryViewController.m

@@ -681,7 +681,7 @@
             AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
             return_json = [iSalesNetwork Category_addall:self.categoryid customid:0 price_template:0 sort:0 filter:nil keyword:nil offset:self.offset limit:20 alert:self.p_alert qty:self.p_QTY available:self.p_available price:self.p_price bestseller:self.p_bestseller modelname:self.modelname modeldescrip:self.modeldescrip orderCode:appDelegate.order_code  addTo:@"cart"];
         } else {
-            return_json = [iSalesNetwork add_toCart_byName:ids];
+            return_json = [iSalesNetwork add_toCart_byName:ids withScreen:ScreenCodeCategory];
         }
         
         dispatch_async(dispatch_get_main_queue(), ^{
@@ -805,7 +805,7 @@
 //            AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
             return_json = [iSalesNetwork Category_addall:self.categoryid customid:0 price_template:0 sort:0 filter:nil keyword:nil offset:self.offset limit:20 alert:self.p_alert qty:self.p_QTY available:self.p_available price:self.p_price bestseller:self.p_bestseller modelname:self.modelname modeldescrip:self.modeldescrip orderCode:nil  addTo:@"portfolio"];
         } else {
-            return_json = [iSalesNetwork add_toPortfolio:ids ];
+            return_json = [iSalesNetwork add_toPortfolio:ids withScreen:ScreenCodeCategory];
         }
         
         dispatch_async(dispatch_get_main_queue(), ^{
@@ -903,7 +903,7 @@
         if (self.addAll) {
             return_json = [iSalesNetwork Category_addall:self.categoryid customid:0 price_template:0 sort:0 filter:nil keyword:nil offset:self.offset limit:20 alert:self.p_alert qty:self.p_QTY available:self.p_available price:self.p_price bestseller:self.p_bestseller modelname:self.modelname modeldescrip:self.modeldescrip orderCode:nil  addTo:@"wishlist"];
         } else {
-            return_json = [iSalesNetwork add_toWatchList:ids ];
+            return_json = [iSalesNetwork add_toWatchList:ids withScreen:ScreenCodeCategory];
         }
 
         
@@ -2025,7 +2025,7 @@
 }
 #pragma mark --UICollectionViewDelegate
 
--(void) showDetailat:(NSString*) item_id category_id:(NSString*) category_id index:(long)index
+-(void) showDetailat:(NSString*) item_id category_id:(NSString*) category_id name:(NSString *)name index:(long)index
 {
     
     
@@ -2054,6 +2054,7 @@
     dvc.product_id = item_id;
     dvc.category_id=category_id;
     dvc.ispush = true;
+    dvc.model_name = name;
     
     [dvc reload];
     [self.navigationController pushViewController:dvc animated:true];
@@ -2178,7 +2179,7 @@
         item_category_id = self.categoryid;
 #endif
         
-        [self showDetailat:detail_id category_id:item_category_id index:indexPath.row];
+        [self showDetailat:detail_id category_id:item_category_id name:[item valueForKey:@"name"] index:indexPath.row];
     }
     
     //    UICollectionViewCell * cell = (UICollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath];

+ 3 - 0
RedAnt ERP Mobile/common/Functions/contact/ContactAdvanceSearchViewController.m

@@ -8,6 +8,8 @@
 
 #import "ContactAdvanceSearchViewController.h"
 #import "iSalesNetwork.h"
+
+
 @interface ContactAdvanceSearchViewController ()
 
 @end
@@ -182,6 +184,7 @@
 }
 - (IBAction)onSearchClick:(id)sender {
     
+    
     // add params check here.
     [self.lastedit endEditing:true];
     [self.lasttextview endEditing:true];

+ 2 - 1
RedAnt ERP Mobile/common/Functions/contact/ContactListViewController.m

@@ -702,7 +702,7 @@ self.label_net_err.hidden=true;
 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
 {
     // NSDictionary * item_json = [self.content_data objectForKey:@"items"];
-    if( self.content_data.count==0)
+    if( self.content_data.count==0 || self.refresh_type == REFRESH_DATA || self.isrefreshing) //
         return 0;
     return self.content_data.count+1;
     
@@ -851,6 +851,7 @@ self.label_net_err.hidden=true;
 #pragma mark - searchBar delegate;
 - (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
 {
+
     self.keywords=searchBar.text;
     self.offset = 0;
     [self.content_data removeAllObjects];

+ 1 - 1
RedAnt ERP Mobile/common/Functions/contact/CustomerInfoViewController.m

@@ -159,7 +159,7 @@
             UIAlertView * waitalert = [RAUtils waiting_alert:@"Please wait" title:@"Release Order"];
             dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                 
-                NSDictionary* order_json = [iSalesNetwork release_Order:appDelegate.order_code];
+                NSDictionary* order_json = [iSalesNetwork release_Order:appDelegate.order_code withScreen:ScreenCodeCustomerInfo];
                 
                 dispatch_async(dispatch_get_main_queue(), ^{
                     [waitalert dismissWithClickedButtonIndex:0 animated:FALSE];

+ 9 - 0
RedAnt ERP Mobile/common/Functions/home/HomeViewController.m

@@ -731,6 +731,8 @@
     
 }
 -(void)ButtonBannerClick:(id)sender{
+
+   
     //这个sender其实就是UIButton,因此通过sender.tag就可以拿到刚才的参数
     int tag = [sender tag];
     int section = tag/1000;
@@ -740,8 +742,11 @@
     NSDictionary* item_json = [view_json objectForKey:[NSString stringWithFormat:@"item_%d",idx]];
     NSString* action = [item_json valueForKeyPath:@"action"];
     
+    [Singleton sharedInstance].homeClickedItemName = item_json[@"description"];
+    
     if([action isEqualToString:@"itemSearch"])
     {
+        [Singleton sharedInstance].homeItemClick = YES;
         NSString* covertype = [item_json valueForKeyPath:@"covertype"];
         
         UIApplication * app = [UIApplication sharedApplication];
@@ -752,6 +757,7 @@
     }
     else if([action isEqualToString:@"category"])
     {
+        [Singleton sharedInstance].homeItemClick = YES;
         NSString* cid = [item_json valueForKeyPath:@"category_id"];
         
         UIApplication * app = [UIApplication sharedApplication];
@@ -781,6 +787,8 @@
         [self.navigationController pushViewController:ViewController animated:YES];
         
     }
+    
+    
 }
 #pragma mark TreeView Delegate methods
 - (CGFloat)treeView:(RATreeView *)treeView heightForRowForItem:(id)item treeNodeInfo:(RATreeNodeInfo *)treeNodeInfo
@@ -909,6 +917,7 @@
 #pragma mark - Topic cell delegate
 -(void) TopicItemClicked:(NSString*) product_id category:(NSString*) category
 {
+
     DetailViewController* dvc = [self.storyboard instantiateViewControllerWithIdentifier:@"DetailViewController" ];
     //            dvc
     

+ 8 - 8
RedAnt ERP Mobile/common/Functions/modelDetail/DetailHeaderCell.m

@@ -94,7 +94,7 @@
                 
                 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                     
-                    NSDictionary* return_json = [iSalesNetwork add_toPortfolio:self.product_id ];
+                    NSDictionary* return_json = [iSalesNetwork add_toPortfolio:self.product_id withScreen:ScreenCodeModelInfo];
                     
                     dispatch_async(dispatch_get_main_queue(), ^{
                         
@@ -160,7 +160,7 @@
     {
         dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
             
-            NSDictionary* return_json = [iSalesNetwork add_toPortfolio:self.product_id ];
+            NSDictionary* return_json = [iSalesNetwork add_toPortfolio:self.product_id withScreen:ScreenCodeModelInfo];
             
             dispatch_async(dispatch_get_main_queue(), ^{
                 
@@ -225,7 +225,7 @@
                 
                 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                     
-                    NSDictionary* return_json = [iSalesNetwork add_toWatchList:self.product_id ];
+                    NSDictionary* return_json = [iSalesNetwork add_toWatchList:self.product_id withScreen:ScreenCodeModelInfo];
                     
                     dispatch_async(dispatch_get_main_queue(), ^{
                         
@@ -291,7 +291,7 @@
     {
         dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
             
-            NSDictionary* return_json = [iSalesNetwork add_toWatchList:self.product_id ];
+            NSDictionary* return_json = [iSalesNetwork add_toWatchList:self.product_id withScreen:ScreenCodeModelInfo];
             
             dispatch_async(dispatch_get_main_queue(), ^{
                 
@@ -621,7 +621,7 @@
                     
                     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                         
-                        NSDictionary* return_json = [iSalesNetwork add_toCart:self.product_id count:count];
+                        NSDictionary* return_json = [iSalesNetwork add_toCart:self.product_id count:count name:self.model_label.text];
                         
                         dispatch_async(dispatch_get_main_queue(), ^{
                             
@@ -697,7 +697,7 @@
             {
                             dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                 
-                                NSDictionary* return_json = [iSalesNetwork add_toCart:self.product_id count:count];
+                                NSDictionary* return_json = [iSalesNetwork add_toCart:self.product_id count:count name:self.model_label.text];
                 
                                 dispatch_async(dispatch_get_main_queue(), ^{
                 
@@ -843,7 +843,7 @@
                 
                 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                     
-                    NSDictionary* return_json = [iSalesNetwork add_toCart:self.product_id count:count];
+                    NSDictionary* return_json = [iSalesNetwork add_toCart:self.product_id count:count name:self.model_label.text];
                     
                     dispatch_async(dispatch_get_main_queue(), ^{
                         
@@ -923,7 +923,7 @@
         {
             dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                 
-                NSDictionary* return_json = [iSalesNetwork add_toCart:self.product_id count:count];
+                NSDictionary* return_json = [iSalesNetwork add_toCart:self.product_id count:count name:self.model_label.text];
                 
                 dispatch_async(dispatch_get_main_queue(), ^{
                     

+ 2 - 2
RedAnt ERP Mobile/common/Functions/modelDetail/DetailViewController.m

@@ -974,7 +974,7 @@ self.isrefreshing=false;
                 UIAlertView *waitting_alert = [RAUtils waiting_alert:@"Sending Email" title:@"Waiting"];
                 dispatch_async(dispatch_get_global_queue(0,0), ^{
                     
-                    NSDictionary *dic = [iSalesNetwork notifyModel:self.product_id emailAddr:nil];
+                    NSDictionary *dic = [iSalesNetwork notifyModel:self.product_id emailAddr:nil withScreen:ScreenCodeModelInfo];
                     
                     dispatch_async(dispatch_get_main_queue(), ^{
                         
@@ -1899,7 +1899,7 @@ self.isrefreshing=false;
                 
                 dispatch_async(dispatch_get_global_queue(0, 0), ^{
                     
-                    NSDictionary *result = [iSalesNetwork notifyModel:weakself.product_id emailAddr:text];
+                    NSDictionary *result = [iSalesNetwork notifyModel:weakself.product_id emailAddr:text withScreen:ScreenCodeModelInfo];
                     DebugLog(@"email cart result: %@",result);
                     dispatch_async(dispatch_get_main_queue(), ^{
                         

+ 1 - 1
RedAnt ERP Mobile/common/Functions/offline/SelectUploadOrderViewController.m

@@ -164,7 +164,7 @@
                 [alertVC dismissViewControllerAnimated:YES completion:nil];
                 // 关闭订单
                 UIAlertView * waitalert = [RAUtils waiting_alert:@"Please wait" title:@"Release Order"];
-                NSDictionary* order_json = [iSalesNetwork release_Order:order_code];
+                NSDictionary* order_json = [iSalesNetwork release_Order:order_code withScreen:ScreenCodeOfflineSetting];
                 
                 dispatch_async(dispatch_get_main_queue(), ^{
                     

+ 2 - 2
RedAnt ERP Mobile/common/Functions/order/CreateOrderViewController.m

@@ -2517,7 +2517,7 @@
             UIAlertView * waitalert = [RAUtils waiting_alert:@"Please wait" title:@"Release Order"];
             dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                 
-                NSDictionary* order_json = [iSalesNetwork release_Order:appDelegate.order_code];
+                NSDictionary* order_json = [iSalesNetwork release_Order:appDelegate.order_code withScreen:nil];
                 
                 dispatch_async(dispatch_get_main_queue(), ^{
                     [waitalert dismissWithClickedButtonIndex:0 animated:FALSE];
@@ -2827,7 +2827,7 @@
 - (void)releaseOrderAfterSave {
     AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
 
-    [iSalesNetwork release_Order:appDelegate.order_code];
+    [iSalesNetwork release_Order:appDelegate.order_code withScreen:nil];
 
     [appDelegate closeOrder]; 
     [appDelegate SetSo:nil];

+ 2 - 2
RedAnt ERP Mobile/common/Functions/order/OrderDetailViewController.m

@@ -284,7 +284,7 @@
         UIAlertView * waitalert = [RAUtils waiting_alert:@"Please wait" title:@"Release Order"];
         dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
             
-            NSDictionary* order_json = [iSalesNetwork release_Order:self.order_code];
+            NSDictionary* order_json = [iSalesNetwork release_Order:self.order_code withScreen:ScreenCodeOrderInfo];
             
             dispatch_async(dispatch_get_main_queue(), ^{
                 [waitalert dismissWithClickedButtonIndex:0 animated:FALSE];
@@ -542,7 +542,7 @@
             
             dispatch_async(dispatch_get_global_queue(0, 0), ^{
                 
-                NSDictionary* order_json = [iSalesNetwork release_Order:appDelegate.order_code];
+                NSDictionary* order_json = [iSalesNetwork release_Order:appDelegate.order_code withScreen:ScreenCodeOrderInfo];
                 
                 dispatch_async(dispatch_get_main_queue(), ^{
                     

+ 1 - 0
RedAnt ERP Mobile/common/Functions/portfolio/PDFListViewController.m

@@ -557,6 +557,7 @@
 #pragma mark - searchBar delegate;
 - (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
 {
+
     self.keywords=searchBar.text;
     self.offset = 0;
     [self.content_data removeAllObjects];

+ 5 - 1
RedAnt ERP Mobile/common/Functions/portfolio/PortfolioViewController.m

@@ -239,7 +239,7 @@
     
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
         
-        NSDictionary* return_json = [iSalesNetwork add_toCart:ids count:-1];
+        NSDictionary* return_json = [iSalesNetwork add_toCart:ids count:-1 name:nil];
         
         dispatch_async(dispatch_get_main_queue(), ^{
             
@@ -1062,6 +1062,9 @@
     NSIndexPath *   indexPath = [self.itemListTable indexPathForCell:cell];
     //            DebugLog(@"shouldchangeedit %d_%d",indexPath.section,indexPath.row);
     NSDictionary * item_json = [self.content_data objectForKey:[NSString stringWithFormat:@"item_%ld",(long)indexPath.row]];
+    NSString *name = [item_json objectForKey:@"description"];
+    NSRange subRange = [name rangeOfString:@"\n"];
+    name = [name substringToIndex:subRange.location];
     
     NSString* product_id = [item_json valueForKey:@"product_id"];
     
@@ -1071,6 +1074,7 @@
     dvc.product_id=product_id;
     dvc.category_id=nil;
     dvc.ispush=true;
+    dvc.model_name = name;
     [dvc reload];
     [self.navigationController pushViewController:dvc animated:true];
     

+ 3 - 1
RedAnt ERP Mobile/common/Functions/search+itemsearch/ItemSearchFilterViewController.m

@@ -13,6 +13,8 @@
 #import "DefaultAppearance.h"
 #import "AppDelegate.h"
 #import "RAUtils.h"
+
+
 @interface ItemSearchFilterViewController ()
 
 @end
@@ -79,7 +81,7 @@
 }
 
 - (IBAction)onSearchClick:(id)sender {
-    
+
     NSString* ids= [[self get_checkedIDs:self.categoryMenu]componentsJoinedByString:@","];
     
     NSString* modelname = self.textModelName.text;

+ 6 - 5
RedAnt ERP Mobile/common/Functions/search+itemsearch/ItemSearchViewController.m

@@ -1138,7 +1138,7 @@
             AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
             return_json = [iSalesNetwork ItemSearch_addall:self.offset limit:20 covertype:self.covertype ctgid:self.ctgid modelname:self.modelname modeldescrip:self.modeldescrip alert:self.alert qty:self.p_QTY available:self.p_available price:self.p_price bestseller:self.p_bestseller orderCode:appDelegate.order_code addTo:@"cart"];
         } else {
-            return_json = [iSalesNetwork add_toCart_byName:ids];
+            return_json = [iSalesNetwork add_toCart_byName:ids withScreen:ScreenCodeParticularCategory];
         }
         
         dispatch_async(dispatch_get_main_queue(), ^{
@@ -1261,7 +1261,7 @@
             AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
             return_json = [iSalesNetwork ItemSearch_addall:self.offset limit:20 covertype:self.covertype ctgid:self.ctgid modelname:self.modelname modeldescrip:self.modeldescrip alert:self.alert qty:self.p_QTY available:self.p_available price:self.p_price bestseller:self.p_bestseller orderCode:nil addTo:@"portfolio"];
         } else {
-            return_json = [iSalesNetwork add_toPortfolio:ids ];
+            return_json = [iSalesNetwork add_toPortfolio:ids withScreen:ScreenCodeParticularCategory];
         }
 
         
@@ -1356,7 +1356,7 @@
             AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
             return_json = [iSalesNetwork ItemSearch_addall:self.offset limit:20 covertype:self.covertype ctgid:self.ctgid modelname:self.modelname modeldescrip:self.modeldescrip alert:self.alert qty:self.p_QTY available:self.p_available price:self.p_price bestseller:self.p_bestseller orderCode:nil addTo:@"wishlist"];
         } else {
-            return_json = [iSalesNetwork add_toWatchList:ids ];
+            return_json = [iSalesNetwork add_toWatchList:ids withScreen:ScreenCodeParticularCategory];
         }
 
         
@@ -1859,7 +1859,7 @@
 }
 #pragma mark --UICollectionViewDelegate
 
--(void) showDetailat:(NSString*) item_id category_id:(NSString*) category_id index:(long)index
+-(void) showDetailat:(NSString*) item_id category_id:(NSString*) category_id  name:(NSString *)name index:(long)index
 {
     DetailViewController* dvc = [self.storyboard instantiateViewControllerWithIdentifier:@"DetailViewController" ];
     //            dvc
@@ -1883,6 +1883,7 @@
     dvc.product_id = item_id;
     dvc.category_id=category_id;
     dvc.ispush = true;
+    dvc.model_name = name;
     
     [dvc reload];
     [self.navigationController pushViewController:dvc animated:true];
@@ -1995,7 +1996,7 @@
     {
         NSString* detail_id = [NSString stringWithFormat:@"%@",[item valueForKey:@"product_id"]];
         
-        [self showDetailat:detail_id category_id:nil index:indexPath.row];
+        [self showDetailat:detail_id category_id:nil name:[item objectForKey:@"fash_name"] index:indexPath.row];
     }
 
 }

+ 7 - 6
RedAnt ERP Mobile/common/Functions/search+itemsearch/SearchViewController.m

@@ -920,7 +920,7 @@
             AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
             return_json = [iSalesNetwork Search_addall:self.offset limit:20 keywords:self.keywords matchfull:self.loadmore_matchfull orderCode:appDelegate.order_code addTo:@"cart"];
         } else {
-            return_json = [iSalesNetwork add_toCart_byName:ids ];
+            return_json = [iSalesNetwork add_toCart_byName:ids withScreen:ScreenCodeSearch];
         }
 
         
@@ -1042,7 +1042,7 @@
             AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
             return_json = [iSalesNetwork Search_addall:self.offset limit:20 keywords:self.keywords matchfull:self.loadmore_matchfull orderCode:nil addTo:@"portfolio"];
         } else {
-            return_json = [iSalesNetwork add_toPortfolio:ids ];
+            return_json = [iSalesNetwork add_toPortfolio:ids withScreen:ScreenCodeSearch];
         }
 
         
@@ -1144,7 +1144,7 @@
             AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
             return_json = [iSalesNetwork Search_addall:self.offset limit:20 keywords:self.keywords matchfull:self.loadmore_matchfull orderCode:nil addTo:@"wishlist"];
         } else {
-            return_json = [iSalesNetwork add_toWatchList:ids ];
+            return_json = [iSalesNetwork add_toWatchList:ids withScreen:ScreenCodeSearch];
         }
 
         
@@ -1387,7 +1387,7 @@
                         NSDictionary * detail_item = [item_json objectForKey:@"item_0"];
                         NSString* detail_id=    [detail_item valueForKey:@"product_id"] ;
                         
-                        [self showDetailat:detail_id category_id:nil index:0];
+                        [self showDetailat:detail_id category_id:nil name:[detail_item objectForKey:@"fash_name"] index:0];
                     }
                 }
                 else
@@ -1884,7 +1884,7 @@
 }
 #pragma mark --UICollectionViewDelegate
 
--(void) showDetailat:(NSString*) item_id category_id:(NSString*) category_id index:(long)index
+-(void) showDetailat:(NSString*) item_id category_id:(NSString*) category_id name:(NSString *)name index:(long)index
 {
     DetailViewController* dvc = [self.storyboard instantiateViewControllerWithIdentifier:@"DetailViewController" ];
     //            dvc
@@ -1908,6 +1908,7 @@
     dvc.product_id = item_id;
     dvc.category_id=category_id;
     dvc.ispush = true;
+    dvc.model_name = name;
     
     [dvc reload];
     [self.navigationController pushViewController:dvc animated:true];
@@ -2020,7 +2021,7 @@
     {
         NSString* detail_id = [NSString stringWithFormat:@"%@",[item valueForKey:@"product_id"]];
         
-        [self showDetailat:detail_id category_id:nil index:indexPath.row];
+        [self showDetailat:detail_id category_id:nil name:[item objectForKey:@"fash_name"] index:indexPath.row];
     }
 
 }

+ 6 - 0
RedAnt ERP Mobile/common/Functions/watchlist/WatchListViewController.m

@@ -769,12 +769,18 @@
     
     NSString* product_id = [item_json valueForKey:@"product_id"];
     
+    NSString *name = [item_json objectForKey:@"description"];
+    NSRange subRange = [name rangeOfString:@"\n"];
+    name = [name substringToIndex:subRange.location];
+    
     DetailViewController* dvc = [self.storyboard instantiateViewControllerWithIdentifier:@"DetailViewController" ];
     //            dvc
     
     dvc.product_id=product_id;
     dvc.category_id=nil;
     dvc.ispush=true;
+    dvc.model_name = name;
+    
     [dvc reload];
     [self.navigationController pushViewController:dvc animated:true];
     

+ 3 - 0
RedAnt ERP Mobile/common/Singleton.h

@@ -18,6 +18,9 @@ typedef enum {
 
 @property (nonatomic,assign) sqlite3 *currentDB;///<当前打开的数据库
 
+@property (nonatomic,assign) BOOL homeItemClick;///<用于追踪“If user is browsing a particular category on home screen”
+@property (nonatomic,  copy) NSString *homeClickedItemName;
+
 #pragma mark - Customer
 
 @property (nonatomic,assign) BOOL permissions_price_setting;///<价格设置权限

+ 4 - 0
RedAnt ERP Mobile/common/customUI/ImageUploadViewController.m

@@ -15,6 +15,8 @@
 #import "RAUtils.h"
 #import "AppDelegate.h"
 #import "OLDataProvider.h"
+#import "ERPUtils.h"
+#import "iSalesNetwork.h"
 
 //#import "UIAlertView+AFNetworking.h"
 
@@ -250,6 +252,8 @@
         //    UIAlertView * waitalert = [[UIAlertView alloc] initWithTitle:@"wait" message:@"uploading" delegate:nil cancelButtonTitle:nil otherButtonTitles:nil, nil];
         //    [waitalert show];
         
+        [ERPUtils googleAnalyticsSendRequestString:nil WithScreen:ScreenCodeUploadImage Action:nil Extra:nil];
+        
         NSData *imageData = UIImagePNGRepresentation(self.imgview.image);
         
         AFHTTPRequestSerializer* serializer=[AFHTTPRequestSerializer serializer] ;

+ 42 - 6
RedAnt ERP Mobile/common/data_provider/iSalesNetwork.h

@@ -13,6 +13,42 @@
 #import "Reachability.h"
 #import "iSalesDB.h"
 #import "RAUtils.h"
+
+extern NSString *const kScreenName;
+extern NSString *const kAction;
+extern NSString *const kExtra;
+
+extern NSString *const ScreenCodeLoginView;
+extern NSString *const ScreenCodeHomeView;
+extern NSString *const ScreenCodeCategory;
+extern NSString *const ScreenCodeCart;
+extern NSString *const ScreenCodeOrderList;
+extern NSString *const ScreenCodeSearch;
+extern NSString *const ScreenCodeAccount;
+extern NSString *const ScreenCodeWishList;
+extern NSString *const ScreenCodePortfolio;
+extern NSString *const ScreenCodeViewPortfolios;
+extern NSString *const ScreenCodeCamScan;
+extern NSString *const ScreenCodeScannerSetting;
+extern NSString *const ScreenCodeOfflineSetting;
+extern NSString *const ScreenCodePlaceOrder;
+extern NSString *const ScreenCodeCustomerInfo;
+extern NSString *const ScreenCodeNewCustomer;
+extern NSString *const ScreenCodeEditCustomer;
+extern NSString *const ScreenCodeModelInfo;
+extern NSString *const ScreenCodeOrderInfo;
+extern NSString *const ScreenCodeUserSign;
+extern NSString *const ScreenCodeNewAddress;
+extern NSString *const ScreenCodeAdvanceSearch;
+extern NSString *const ScreenCodeCreatePortfolio;
+extern NSString *const ScreenCodeParticularCategory;
+extern NSString *const ScreenCodeEditPortfolio;
+extern NSString *const ScreenCodePriceSetting;
+extern NSString *const ScreenCodeCategoryPrice;
+extern NSString *const ScreenCodeSetCatetoryPrice;
+extern NSString *const ScreenCodeUploadImage;
+extern NSString *const ScreenCodeOfflineSync;
+
 @interface iSalesNetwork : NSObject
 +(void) LoadImage:(NSString*) url into:(UIImageView*) container;
 +(NSDictionary*) portfolio_remove:(NSString* ) item_ids;
@@ -20,7 +56,7 @@
 
 +(NSDictionary*) delete_portfoliolist:(NSString* ) listid;
 
-+(NSDictionary*) add_toPortfolio:(NSString* ) item_id;
++(NSDictionary*) add_toPortfolio:(NSString* ) item_id withScreen:(NSString *)screenName;
 +(NSData*)get_json : (NSString*) url parameters:(NSMutableDictionary *) params;
 +(int)Authorize : (NSString*) user password:(NSString*) password ;
 +(NSDictionary*)logout;
@@ -55,9 +91,9 @@
 +(NSDictionary*) download_Offline:(NSString* )vid;
 +(NSDictionary*) finish_download_Offline:(NSString* )vid;
 
-+(NSDictionary*) add_toCart:(NSString* ) item_id count:(int) count;
-+(NSDictionary*) add_toCart_byName:(NSString* ) model_name;
-+(NSDictionary*) add_toWatchList:(NSString* ) item_id;
++(NSDictionary*) add_toCart:(NSString* ) item_id count:(int) count name:(NSString *)name;
++(NSDictionary*) add_toCart_byName:(NSString* ) model_name withScreen:(NSString *)screenName;
++(NSDictionary*) add_toWatchList:(NSString* ) item_id withScreen:(NSString *)screenName;
 +(NSDictionary*)request_Cart:(int)sort;
 +(NSDictionary*)request_WatchList:(int)sort;
 +(NSDictionary*) portfolio_setPrice:(NSString*) watchlist_id price:(float) price discount:(float) discount QTY:(int)qty qty_p:(float) qty_p notes:(NSString*)notes;
@@ -79,7 +115,7 @@
 +(NSDictionary*)saveandcommit_Order:(NSMutableDictionary*)params;
 +(NSDictionary*) new_Order;
 +(NSDictionary*)open_Order:(NSString*) order_code;
-+(NSDictionary*)release_Order:(NSString*) order_code;
++(NSDictionary*)release_Order:(NSString*) order_code withScreen:(NSString *)screenName;
 +(NSDictionary*)save_Order:(NSMutableDictionary*)params;
 +(NSDictionary*)delete_Order:(NSString*) order_id;
 +(NSDictionary*)cancel_Order:(NSString*) order_id order_code:(NSString*) order_code;
@@ -141,6 +177,6 @@
 
 + (NSDictionary *)quoteOrder:(NSString *)so_id emailAddr:(NSString *)addr;// email cart as quote
 
-+ (NSDictionary *)notifyModel:(NSString *)modelID emailAddr:(NSString *)addr;
++ (NSDictionary *)notifyModel:(NSString *)modelID emailAddr:(NSString *)addr withScreen:(NSString *)screenName;
 
 @end

+ 302 - 12
RedAnt ERP Mobile/common/data_provider/iSalesNetwork.m

@@ -10,6 +10,45 @@
 #import "RAUtils.h"
 #import "OLDataProvider.h"
 #import "Singleton.h"
+#import "GoogleAnalyst.h"
+#import "ERPUtils.h"
+
+
+NSString *const kScreenName = @"kScreenName";
+NSString *const kAction = @"kAction";
+NSString *const kExtra = @"kExtra";
+
+
+NSString *const ScreenCodeLoginView = @"Login Screen";
+NSString *const ScreenCodeHomeView = @"Home Screen";
+NSString *const ScreenCodeCategory = @"Category Screen";
+NSString *const ScreenCodeCart = @"Cart Sceen";
+NSString *const ScreenCodeOrderList = @"Order History Screen";
+NSString *const ScreenCodeSearch = @"Search Screen";
+NSString *const ScreenCodeAccount = @"Account Screen";
+NSString *const ScreenCodeWishList = @"Wish List Screen";
+NSString *const ScreenCodePortfolio = @"Portfolio Screen";
+NSString *const ScreenCodeViewPortfolios = @"View Portfolios Screen";
+NSString *const ScreenCodeCamScan = @"Cam Scan Screen";
+NSString *const ScreenCodeScannerSetting = @"Scanner Setting Screen";
+NSString *const ScreenCodeOfflineSetting = @"Offline Setting Screen";
+NSString *const ScreenCodePlaceOrder = @"Place Order Screen";
+NSString *const ScreenCodeCustomerInfo = @"Customer Information Screen";
+NSString *const ScreenCodeNewCustomer = @"New Customer Screen";
+NSString *const ScreenCodeEditCustomer = @"Edit Customer Information Screen";
+NSString *const ScreenCodeModelInfo = @"Model Information Screen";
+NSString *const ScreenCodeOrderInfo = @"Order Information Screeen";
+NSString *const ScreenCodeUserSign = @"User Sign Screen";
+NSString *const ScreenCodeNewAddress = @"New Address Screen";
+NSString *const ScreenCodeAdvanceSearch = @"Account Advance Search Screen";
+NSString *const ScreenCodeCreatePortfolio = @"Create Portfolio Screen";
+NSString *const ScreenCodeParticularCategory = @"Particular Category Screen";
+NSString *const ScreenCodeEditPortfolio = @"Edit Portfolio Screen";
+NSString *const ScreenCodePriceSetting = @"Price Setting Screen";
+NSString *const ScreenCodeCategoryPrice = @"Category Price Screen";
+NSString *const ScreenCodeSetCatetoryPrice = @"Set Category Price Screen";
+NSString *const ScreenCodeUploadImage = @"Upload Image Screen";
+NSString *const ScreenCodeOfflineSync = @"Offline Sync Screen";
 
 @implementation iSalesNetwork
 
@@ -128,7 +167,15 @@
     [params setValue:uuid.UUIDString forKey:@"idfv"];
 #endif
     
-    
+    NSString *screenName = [params valueForKey:kScreenName];
+    NSString *userAction = [params valueForKey:kAction];
+    NSMutableDictionary *extra = [[params valueForKey:kExtra] mutableCopy];
+    if ([userAction isEqualToString:@"Login"]) {
+        if (!extra) {
+            extra = [NSMutableDictionary dictionary];
+        }
+        [extra setObject:[params objectForKey:@"user"] forKey:@"user"];
+    }
     
 repeat:
     {
@@ -283,6 +330,9 @@ repeat:
             {
                 [iSalesNetwork err_log:[RAUtils base64en:[RAUtils dict2string:params]] result:[RAUtils base64en:[RAUtils dict2string:ret]] module:url code:RESULT_NET_ERROR];
             }
+#ifdef BUILD_NPD
+            [ERPUtils googleAnalyticsSendRequestString:url WithScreen:screenName Action:userAction Extra:extra];
+#endif
             return jsonData;
             
         }
@@ -347,9 +397,13 @@ repeat:
             NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsobj
                                                                options:0
                                                                  error:nil];
+#ifdef BUILD_NPD
+            [ERPUtils googleAnalyticsSendRequestString:url WithScreen:screenName Action:userAction Extra:extra];
+#endif
             return jsonData;
             
         }
+
         return responseData;
     }
 }
@@ -387,6 +441,9 @@ repeat:
         [params setValue:appDelegate.password forKey:@"password"];
     [params setValue:listid forKey:@"tearsheetsId"];
     //    [params setValue:editor forKey:@"editor"];
+    [params setValue:ScreenCodeViewPortfolios forKey:kScreenName];
+//    [params setValue:@"Delete Portfolio" forKey:kAction];
+    
     NSData* json = nil;
     if(appDelegate.offline_mode)
     {
@@ -422,6 +479,9 @@ repeat:
         [params setValue:appDelegate.password forKey:@"password"];
     [params setValue:item_ids forKey:@"portfolioId"];
     //    [params setValue:editor forKey:@"editor"];
+    
+    [params setValue:ScreenCodePortfolio forKey:kScreenName];
+    
     NSData* json = nil;
     if(appDelegate.offline_mode)
     {
@@ -465,6 +525,8 @@ repeat:
     [params setValue:item_ids forKey:@"collectId"];
     //    [params setValue:editor forKey:@"editor"];
     
+    [params setValue:ScreenCodeWishList forKey:kScreenName];
+    
     if(appDelegate.offline_mode)
     {
         return [OLDataProvider offline_deletewishlist:params];
@@ -507,6 +569,10 @@ repeat:
         [params setValue:appDelegate.order_code forKey:@"orderCode"];
     [params setValue:item_ids forKey:@"cartItemId"];
     //    [params setValue:editor forKey:@"editor"];
+    
+    [params setValue:ScreenCodeCart forKey:kScreenName];
+//    [params setValue:@"Cart Move To Wish List" forKey:kAction];
+    
     NSData* json = nil;
     if(appDelegate.offline_mode)
     {
@@ -553,6 +619,10 @@ repeat:
         [params setValue:appDelegate.order_code forKey:@"orderCode"];
     [params setValue:item_ids forKey:@"collectId"];
     //    [params setValue:editor forKey:@"editor"];
+    
+    [params setValue:ScreenCodeWishList forKey:kScreenName];
+    [params setValue:@"Move To Cart" forKey:kAction];
+    
     NSData *json = nil;
     if(appDelegate.offline_mode)
     {
@@ -600,6 +670,10 @@ repeat:
         [params setValue:appDelegate.order_code forKey:@"orderCode"];
     [params setValue:item_ids forKey:@"cartItemId"];
     //    [params setValue:editor forKey:@"editor"];
+    
+    [params setValue:ScreenCodeCart forKey:kScreenName];
+//    [params setValue:@"" forKey:kAction];
+    
     NSData* json=nil;
     if(appDelegate.offline_mode)
     {
@@ -676,6 +750,9 @@ repeat:
         [params setValue:appDelegate.password forKey:@"password"];
     //    [params setValue:sourceid forKey:@"sourceid"];
     //    [params setValue:editor forKey:@"editor"];
+    
+    [params setValue:ScreenCodeNewAddress forKey:kScreenName];
+    
     NSData* json=nil;
     
     if(appDelegate.offline_mode)
@@ -716,6 +793,9 @@ repeat:
     [params setValue:order_code forKey:@"code"];
     //    [params setValue:sourceid forKey:@"sourceid"];
     //    [params setValue:editor forKey:@"editor"];
+    
+    [params setValue:ScreenCodeOrderInfo forKey:kScreenName];
+    
     NSData* json=nil;
     if(appDelegate.offline_mode)
     {
@@ -756,6 +836,9 @@ repeat:
     [params setValue:path forKey:@"picpath"];
     //    [params setValue:sourceid forKey:@"sourceid"];
     //    [params setValue:editor forKey:@"editor"];
+    
+    [params setValue:ScreenCodeUserSign forKey:kScreenName];
+    
     NSData* json=nil;
     if(appDelegate.offline_mode)
     {
@@ -796,6 +879,8 @@ repeat:
     //    [params setValue:sourceid forKey:@"sourceid"];
     //    [params setValue:editor forKey:@"editor"];
     
+     [params setValue:ScreenCodePlaceOrder forKey:kScreenName];
+    
     NSData* json = nil;
     
     if(appDelegate.offline_mode)
@@ -834,6 +919,8 @@ repeat:
     //    [params setValue:sourceid forKey:@"sourceid"];
     //    [params setValue:editor forKey:@"editor"];
     
+     [params setValue:ScreenCodeOrderInfo forKey:kScreenName];
+    
     NSData* json=nil;
     if(appDelegate.offline_mode)
     {
@@ -888,6 +975,9 @@ repeat:
     [params setValue:order_id forKey:@"orderId"];
     //    [params setValue:sourceid forKey:@"sourceid"];
     //    [params setValue:editor forKey:@"editor"];
+    
+     [params setValue:ScreenCodeOrderList forKey:kScreenName];
+    
     if(appDelegate.offline_mode)
     {
         return [OLDataProvider offline_notimpl];
@@ -923,6 +1013,9 @@ repeat:
     [params setValue:order_code forKey:@"orderCode"];
     //    [params setValue:sourceid forKey:@"sourceid"];
     //    [params setValue:editor forKey:@"editor"];
+    
+    [params setValue:ScreenCodeOrderList forKey:kScreenName];
+    
     NSData* json=nil;
     if(appDelegate.offline_mode)
     {
@@ -945,7 +1038,7 @@ repeat:
     else
         return nil;
 }
-+(NSDictionary*)release_Order:(NSString*) order_code
++(NSDictionary*)release_Order:(NSString*) order_code withScreen:(NSString *)screenName
 {
     NSMutableDictionary* params = [[NSMutableDictionary alloc] init];
     AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
@@ -959,6 +1052,11 @@ repeat:
     [params setValue:order_code forKey:@"orderCode"];
     //    [params setValue:sourceid forKey:@"sourceid"];
     //    [params setValue:editor forKey:@"editor"];
+    
+    if (screenName) {
+        [params setValue:screenName forKey:kScreenName];
+    }
+    
     NSData* json=nil;
     if(appDelegate.offline_mode)
     {
@@ -1001,6 +1099,8 @@ repeat:
     if(appDelegate.password!=nil)
         [info setValue:appDelegate.password forKey:@"password"];
     
+    [info setObject:ScreenCodeEditCustomer forKey:kScreenName];
+    
     [info setValue:order_code forKey:@"orderCode"];
     //    [params setValue:sourceid forKey:@"sourceid"];
     //    [params setValue:editor forKey:@"editor"];
@@ -1045,6 +1145,9 @@ repeat:
     //
     //    [params setValue:sourceid forKey:@"sourceid"];
     //    [params setValue:editor forKey:@"editor"];
+    
+    [params setObject:ScreenCodeModelInfo forKey:kScreenName];
+    
     if(appDelegate.offline_mode)
     {
         params[@"offline_Command"]=url;
@@ -1092,6 +1195,9 @@ repeat:
     //
     //    [params setValue:sourceid forKey:@"sourceid"];
     //    [params setValue:editor forKey:@"editor"];
+    
+    [params setObject:ScreenCodePlaceOrder forKey:kScreenName];
+    
     NSData* json=nil;
     if(appDelegate.offline_mode)
     {
@@ -1151,6 +1257,7 @@ repeat:
     //    [params setValue:sourceid forKey:@"sourceid"];
     //    [params setValue:editor forKey:@"editor"];
     
+    [params setObject:ScreenCodeEditCustomer forKey:kScreenName];
     
     NSData* json=nil;
     if(appDelegate.offline_mode)
@@ -1207,6 +1314,9 @@ repeat:
     
     //    [params setValue:sourceid forKey:@"sourceid"];
     //    [params setValue:editor forKey:@"editor"];
+    
+    [params setObject:ScreenCodeNewCustomer forKey:kScreenName];
+    
     NSData* json=nil;
     if(appDelegate.offline_mode)
     {
@@ -1266,6 +1376,9 @@ repeat:
     
     //    [params setValue:sourceid forKey:@"sourceid"];
     //    [params setValue:editor forKey:@"editor"];
+    
+    [params setObject:ScreenCodePlaceOrder forKey:kScreenName];
+    
     NSData* json=nil;
     
     if(appDelegate.offline_mode)
@@ -1316,6 +1429,31 @@ repeat:
     //    [params setValue:editor forKey:@"editor"];
     DebugLog(@"request editor url:%@",request_url);
     
+    
+    if([request_url isEqualToString:URL_NEW_CUSTOMER])
+    {
+        [params setObject:ScreenCodeNewCustomer forKey:kScreenName];
+    }
+    else if([request_url isEqualToString:URL_EDIT_CUSTOMER])
+    {
+        [params setObject:ScreenCodeEditCustomer forKey:kScreenName];
+    }
+    else if([request_url isEqualToString:URL_CUSTOMER_ADV_SEARCH])
+    {
+        [params setObject:ScreenCodeAdvanceSearch forKey:kScreenName];
+    }
+    else if([request_url isEqualToString:URL_CARTDELIVERY])
+    {
+        [params setObject:ScreenCodePlaceOrder forKey:kScreenName];
+    }
+    else if([request_url isEqualToString:URL_ADDRESS_EDOTOR])
+    {
+        [params setObject:ScreenCodeNewAddress forKey:kScreenName];
+    }
+    else if ([request_url isEqualToString:URL_DM_PARAMS]){
+        [params setObject:ScreenCodeCreatePortfolio forKey:kScreenName];
+    }
+    
     NSData* json = nil;
     if(appDelegate.offline_mode)
     {
@@ -1424,6 +1562,12 @@ repeat:
     [params setValue:[NSNumber numberWithBool:isMerged] forKey:@"isMerged"];
     
     [params setValue:status_code forKey:@"orderStatus"];
+    
+    [params setObject:ScreenCodeOrderList forKey:kScreenName];
+    if (keywords) {
+        [params setObject:@"Search" forKey:kAction];
+    }
+    
     NSData* json=nil;
     if(appDelegate.offline_mode)
     {
@@ -1467,6 +1611,11 @@ repeat:
     [params setValue:[NSString stringWithFormat:@"%d",limit]  forKey:@"limit"];
     [params setValue:[NSString stringWithFormat:@"%d",offset]  forKey:@"offset"];
 
+    [params setObject:ScreenCodeViewPortfolios forKey:kScreenName];
+    if (keywords) {
+        [params setObject:@"Search" forKey:kAction];
+    }
+    
     NSData* json = nil;
     if(appDelegate.offline_mode)
     {
@@ -1515,6 +1664,9 @@ repeat:
         [params setValue:appDelegate.contact_id forKey:@"contactId"];
     if(appDelegate.password!=nil)
         [params setValue:appDelegate.password forKey:@"password"];
+    
+    [params setObject:ScreenCodeCreatePortfolio forKey:kScreenName];
+    
     /*
     [params setValue:request_url forKey:@"pdfUrl"];
     [params setValue:name forKey:@"pdfName"];
@@ -1577,6 +1729,8 @@ repeat:
     if(appDelegate.password!=nil)
         [params setValue:appDelegate.password forKey:@"password"];
     
+     [params setObject:ScreenCodeCreatePortfolio forKey:kScreenName];
+    
 //    [params setValue:request_url forKey:@"pdfUrl"];
     NSData* json= nil;
     if(appDelegate.offline_mode)
@@ -1631,6 +1785,9 @@ repeat:
         [params setValue:appDelegate.contact_id forKey:@"contactId"];
     if(appDelegate.password!=nil)
         [params setValue:appDelegate.password forKey:@"password"];
+    
+    [params setObject:ScreenCodeCreatePortfolio forKey:kScreenName];
+    
    /*
     [params setValue:path forKey:@"pdfPath"];
     [params setValue:name forKey:@"pdfName"];
@@ -1717,6 +1874,14 @@ repeat:
     [params setValue:contact_type forKey:@"contactType"];
     [params setValue:keywords forKey:@"keyword"];
     
+    [params setObject:ScreenCodeAccount forKey:kScreenName];
+    if (keywords) {
+        [params setObject:@"Search" forKey:kAction];
+    }
+    if (upparams) {
+        [params setObject:@"Advance Search" forKey:kAction];
+    }
+    
     NSString* url=nil;
     if([contact_type isEqualToString:@"Sales_Order_Ship_To"])
         url=URL_SHIPTO_LIST;
@@ -1749,6 +1914,9 @@ repeat:
     
     [params setValue:orderid forKey:@"orderId"];
     //    [params setValue:[NSString stringWithFormat:@"%d",limit ] forKey:@"limit"];
+    
+    [params setObject:ScreenCodeOrderInfo forKey:kScreenName];
+    
     NSData* json=nil;
     if(appDelegate.offline_mode)
     {
@@ -1790,7 +1958,7 @@ repeat:
     NSDictionary *jsobj = [NSJSONSerialization JSONObjectWithData:json options:NSJSONReadingMutableLeaves error:&error];
     return jsobj;
 }
-+(NSDictionary*) add_toCart:(NSString* ) item_id count:(int) count
++(NSDictionary*) add_toCart:(NSString* ) item_id count:(int) count name:(NSString *)name
 {
     NSMutableDictionary* params = [[NSMutableDictionary alloc] init];
     AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
@@ -1806,6 +1974,12 @@ repeat:
     [params setValue:item_id forKey:@"product_id"];
     [params setValue:[NSString stringWithFormat:@"%d",count]  forKey:@"count"];
     
+    [params setObject:ScreenCodeModelInfo forKey:kScreenName];
+    [params setObject:@"Add To Cart" forKey:kAction];
+    if (name) {
+        NSDictionary *extra = @{@"ModelName" : name,@"Count" : @(count)};
+        [params setObject:extra forKey:kExtra];
+    }
     
     NSDictionary* customerinfo= appDelegate.customerInfo;
     
@@ -1849,7 +2023,7 @@ repeat:
     return jsobj;
 }
 
-+(NSDictionary*) add_toCart_byName:(NSString* ) model_name
++(NSDictionary*) add_toCart_byName:(NSString* ) model_name withScreen:(NSString *)screenName
 {
     NSMutableDictionary* params = [[NSMutableDictionary alloc] init];
     AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
@@ -1865,6 +2039,9 @@ repeat:
     [params setValue:model_name forKey:@"product_name"];
     [params setValue:[NSString stringWithFormat:@"%d",-1]  forKey:@"count"];
     
+    [params setObject:screenName forKey:kScreenName];
+    [params setObject:@"Add To Cart" forKey:kAction];
+    [params setObject:@{@"ModelName" : model_name} forKey:kExtra];
     
     NSDictionary* customerinfo= appDelegate.customerInfo;
     
@@ -1954,6 +2131,8 @@ repeat:
         [params setValue:appDelegate.order_code forKey:@"orderCode"];
     
     
+    [params setObject:ScreenCodeOrderList forKey:kScreenName];
+    
     NSDictionary* customerinfo= appDelegate.customerInfo;
     
     NSArray* keys=[customerinfo allKeys];
@@ -1998,7 +2177,7 @@ repeat:
     
     return jsobj;
 }
-+(NSDictionary*) add_toPortfolio:(NSString* ) item_id
++(NSDictionary*) add_toPortfolio:(NSString* ) item_id withScreen:(NSString *)screenName
 {
     NSMutableDictionary* params = [[NSMutableDictionary alloc] init];
     AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
@@ -2011,6 +2190,8 @@ repeat:
     
     [params setValue:item_id forKey:@"product_id"];
     
+    [params setObject:screenName forKey:kScreenName];
+    
     NSData* json = nil;
     if(appDelegate.offline_mode)
     {
@@ -2039,7 +2220,7 @@ repeat:
     }
     return jsobj;
 }
-+(NSDictionary*) add_toWatchList:(NSString* ) item_id
++(NSDictionary*) add_toWatchList:(NSString* ) item_id withScreen:(NSString *)screenName
 {
     NSMutableDictionary* params = [[NSMutableDictionary alloc] init];
     AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
@@ -2050,7 +2231,11 @@ repeat:
     if(appDelegate.password!=nil)
         [params setValue:appDelegate.password forKey:@"password"];
     
+    
     [params setValue:item_id forKey:@"product_id"];
+    
+    [params setObject:screenName forKey:kScreenName];
+    
     if(appDelegate.offline_mode)
     {
         return [OLDataProvider offline_add2wishlist:params];
@@ -2093,6 +2278,9 @@ repeat:
     [params setValue:[NSString stringWithFormat:@"%f",price] forKey:@"price"];
     
     [params setValue:[NSString stringWithFormat:@"%f",discount] forKey:@"discount"];
+    
+    [params setObject:ScreenCodeCart forKey:kScreenName];
+    
     NSData* json= nil;
     if(appDelegate.offline_mode)
     {
@@ -2166,6 +2354,8 @@ repeat:
     if(qty != -INT32_MAX)
         [params setValue:[NSString stringWithFormat:@"%d",qty] forKey:@"available_qty"];
     
+    [params setObject:ScreenCodePortfolio forKey:kScreenName];
+    
     NSData* json = nil;
     
     if(appDelegate.offline_mode)
@@ -2196,6 +2386,8 @@ repeat:
     
     [params setValue:order_code forKey:@"orderCode"];
     
+    [params setObject:ScreenCodeCart forKey:kScreenName];
+    
     if(notes.length==0)
         notes=@"";
     
@@ -2232,6 +2424,8 @@ repeat:
     
     [params setValue:cart_id forKey:@"cartitem_id"];
     
+    [params setObject:ScreenCodeCart forKey:kScreenName];
+    
     if(notes.length==0)
         notes=@"";
     
@@ -2268,7 +2462,7 @@ repeat:
     
     [params setValue:cart_id forKey:@"cartitem_id"];
     
-    
+    [params setObject:ScreenCodeCart forKey:kScreenName];
     
     NSString* free=nil;
     
@@ -2306,6 +2500,7 @@ repeat:
     
     [params setValue:cart_id forKey:@"cartitem_id"];
     
+    [params setObject:ScreenCodeCart forKey:kScreenName];
     
     [params setValue:[NSString stringWithFormat:@"%d",value] forKey:@"inputInt"];
     
@@ -2368,6 +2563,9 @@ repeat:
         return [RAUtils error_json:RESULT_NET_NOTAVAILABLE err_msg:nil];
     
     NSMutableDictionary* params = [[NSMutableDictionary alloc] init];
+    
+    [params setObject:ScreenCodeOfflineSetting forKey:kScreenName];
+    
     //    AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
     
     //    if(appDelegate.user!=nil)
@@ -2402,6 +2600,9 @@ repeat:
         return [RAUtils error_json:RESULT_NET_NOTAVAILABLE err_msg:nil];
     
     NSMutableDictionary* params = [[NSMutableDictionary alloc] init];
+    
+    [params setObject:ScreenCodeOfflineSync forKey:kScreenName];
+    
     //    AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
     
     //    if(appDelegate.user!=nil)
@@ -2449,6 +2650,9 @@ repeat:
         [params setValue:@"true" forKey:@"internal_address"];
     else
         [params setValue:@"false" forKey:@"internal_address"];
+    
+    [params setObject:ScreenCodeOfflineSync forKey:kScreenName];
+    
     NSData* json=[self get_json:URL_CHECK_OFFLINE parameters:params];
     if(json==nil)
         return nil;
@@ -2486,6 +2690,9 @@ repeat:
         [params setValue:appDelegate.order_code forKey:@"orderCode"];
     
     [params setValue:[NSNumber numberWithInt:sort] forKey:@"sort"];
+    
+    [params setObject:ScreenCodeCart forKey:kScreenName];
+    
     NSData* json=nil;
     if(appDelegate.offline_mode)
     {
@@ -2554,6 +2761,8 @@ repeat:
     [params setValue:[NSString stringWithFormat:@"%d",INT_MAX ] forKey:@"limit"];
     [params setValue:[NSNumber numberWithInt:sort] forKey:@"sort"];
     
+    [params setObject:ScreenCodePortfolio forKey:kScreenName];
+    
     NSData* json = nil;
     if(appDelegate.offline_mode)
     {
@@ -2599,6 +2808,9 @@ repeat:
     [params setValue:[NSString stringWithFormat:@"%d",INT_MAX ] forKey:@"limit"];
     
     [params setValue:[NSNumber numberWithInt:sort] forKey:@"sort"];
+    
+    [params setObject:ScreenCodeWishList forKey:kScreenName];
+    
     if(appDelegate.offline_mode)
     {
         return [OLDataProvider offline_wishlist:params];
@@ -2647,6 +2859,12 @@ repeat:
     
     [params setValue:category_id  forKey:@"category"];
     
+    [params setObject:ScreenCodeModelInfo forKey:kScreenName];
+    [params setObject:@"Open A Model" forKey:kAction];
+    if (model_name) {
+        NSDictionary *extra = @{@"ModelName" : model_name};
+        [params setObject:extra forKey:kExtra];
+    }
     
     if(appDelegate.offline_mode)
         return [OLDataProvider offline_model:params];
@@ -2729,6 +2947,12 @@ repeat:
     [params setValue:filter forKey:@"filter"];
     [params setValue:keyword forKey:@"keyword"];
     
+    [params setObject:ScreenCodeCategory forKey:kScreenName];
+    if ([addTo isEqualToString:@"cart"]) {
+        [params setObject:@"Add To Cart" forKey:kAction];
+    }
+    
+    
     NSData* json= nil;
     
     if(appDelegate.offline_mode)
@@ -2912,6 +3136,19 @@ repeat:
     [params setValue:filter forKey:@"filter"];
     [params setValue:keyword forKey:@"keyword"];
     
+    [params setObject:ScreenCodeCategory forKey:kScreenName];
+    if (alert) {
+        [params setObject:@"Filter" forKey:kAction];
+    }
+    if ([Singleton sharedInstance].homeItemClick) {
+        [params setObject:@"Brow A Particular Category On Home" forKey:kAction];
+        [Singleton sharedInstance].homeItemClick = NO;
+        
+        NSDictionary *extra = @{@"CoverName" : [Singleton sharedInstance].homeClickedItemName};
+        [Singleton sharedInstance].homeClickedItemName = nil;
+        [params setObject:extra forKey:kExtra];
+
+    }
     
     
     if(appDelegate.offline_mode)
@@ -2959,6 +3196,11 @@ repeat:
     else
         [params setValue:@"false"  forKey:@"exactMatch"];
     
+    [params setObject:ScreenCodeSearch forKey:kScreenName];
+    if ([addTo isEqualToString:@"cart"]) {
+        [params setObject:@"Add To Cart" forKey:kAction];
+    }
+    
     NSData* json=nil;
     if(appDelegate.offline_mode)
     {
@@ -3027,6 +3269,12 @@ repeat:
         [params setValue:@"true"  forKey:@"exactMatch"];
     else
         [params setValue:@"false"  forKey:@"exactMatch"];
+    
+    [params setObject:ScreenCodeSearch forKey:kScreenName];
+    if (keywords) {
+        [params setObject:@"Search" forKey:kAction];
+    }
+    
     if(appDelegate.offline_mode)
     {
         return [OLDataProvider offline_search:params];
@@ -3079,6 +3327,12 @@ repeat:
     
     [params setValue:[NSString stringWithFormat:@"%ld",limit]  forKey:@"limit"];
     [params setValue:[NSString stringWithFormat:@"%ld",offset]  forKey:@"offset"];
+    
+    [params setObject:ScreenCodeParticularCategory forKey:kScreenName];
+    if ([addTo isEqualToString:@"cart"]) {
+        [params setObject:@"Add To Cart" forKey:kAction];
+    }
+    
     NSData* json = nil;
     
     if(appDelegate.offline_mode)
@@ -3136,7 +3390,18 @@ repeat:
         [params setValue:appDelegate.order_code forKey:@"orderCode"];
     
     
-    
+    [params setObject:ScreenCodeParticularCategory forKey:kScreenName];
+    if (alert && qty && available && price && bestseller) {
+        [params setObject:@"Filter" forKey:kAction];
+    }
+    if ([Singleton sharedInstance].homeItemClick) {
+        [params setObject:@"Brow A Particular Category On Home" forKey:kAction];
+        [Singleton sharedInstance].homeItemClick = NO;
+        
+        NSDictionary *extra = @{@"CoverName" : [Singleton sharedInstance].homeClickedItemName};
+        [Singleton sharedInstance].homeClickedItemName = nil;
+        [params setObject:extra forKey:kExtra];
+    }
     
     
     //    [params setValue:[NSString stringWithFormat:@"%d",price_template]  forKey:@"price_template"];
@@ -3213,6 +3478,9 @@ repeat:
     if(appDelegate.password!=nil)
         [params setValue:appDelegate.password forKey:@"password"];
     [params setValue:fashionId  forKey:@"fashionId"];
+    
+    [params setObject:ScreenCodeEditPortfolio forKey:kScreenName];
+    
     NSData* json = nil;
     if(appDelegate.offline_mode)
     {
@@ -3244,6 +3512,9 @@ repeat:
     //        [params setValue:appDelegate.password forKey:@"password"];
     [params setValue:user  forKey:@"username"];
     [params setValue:email  forKey:@"email"];
+    
+    [params setObject:ScreenCodeLoginView forKey:kScreenName];
+    
     if(![self IsNetworkAvailable])
         return [RAUtils error_json:RESULT_NET_NOTAVAILABLE err_msg:nil];
     
@@ -3273,6 +3544,7 @@ repeat:
     [params setValue:[NSString stringWithFormat:@"%d",price_template]  forKey:@"price_template"];
     [params setValue:[NSString stringWithFormat:@"%d",customid]  forKey:@"custom_id"];
     
+    [params setObject:ScreenCodeHomeView forKey:kScreenName];
     
     //    AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
     if(appDelegate.offline_mode)
@@ -3417,6 +3689,9 @@ repeat:
     [params setValue:@"false" forKey:@"is_debug"];
 #endif
     
+    [params setObject:ScreenCodeLoginView forKey:kScreenName];
+    [params setObject:@"Login" forKey:kAction];
+    
     NSData* json= nil;
     if(appDelegate.offline_mode)
     {
@@ -3433,8 +3708,7 @@ repeat:
     
     if(json==nil)
         return RESULT_NET_ERROR;
-    
-    
+
     int ret = [self parse_authinfo:json user:user password:password];
     DebugLog(@"parse_authinfo return %d ",ret);
     
@@ -3459,6 +3733,8 @@ repeat:
     [params setValue:url forKey:@"business_card"];
     //   [params setValue:[NSNumber numberWithInt:index ] forKey:@"index"];
     
+    [params setObject:ScreenCodeEditCustomer forKey:kScreenName];
+    
     if(appDelegate.offline_mode)
     {
         return [OLDataProvider offline_notimpl];
@@ -3515,6 +3791,8 @@ repeat:
         [params setValue:appDelegate.password forKey:@"password"];
     [params setValue:contactid forKey:@"contactId"];
     
+    [params setObject:ScreenCodeCustomerInfo forKey:kScreenName];
+    
     if(appDelegate.offline_mode)
         return [OLDataProvider offline_contactinfo:params];
     if(![self IsNetworkAvailable])
@@ -3757,7 +4035,8 @@ repeat:
     if(appDelegate.password!=nil)
         [dic setValue:appDelegate.password forKey:@"password"];
     
-    [dic setValue:[NSString stringWithFormat:@"%d",priceType] forKey:@"price_type"];
+    [dic setValue:[NSString stringWithFormat:@"%ld",priceType] forKey:@"price_type"];
+    [dic setObject:ScreenCodePriceSetting forKey:kScreenName];
     
     NSData* json=nil;
     if(appDelegate.offline_mode)
@@ -3792,6 +4071,8 @@ repeat:
     
     if(appDelegate.password!=nil)
         [dic setValue:appDelegate.password forKey:@"password"];
+    
+    [dic setObject:ScreenCodeCategoryPrice forKey:kScreenName];
         
     NSData* json=nil;
     if(appDelegate.offline_mode)
@@ -3828,6 +4109,8 @@ repeat:
     if(appDelegate.password!=nil)
         [params setValue:appDelegate.password forKey:@"password"];
     
+    [params setObject:ScreenCodeSetCatetoryPrice forKey:kScreenName];
+    
     NSData* json=nil;
     if(appDelegate.offline_mode)
     {
@@ -3866,6 +4149,9 @@ repeat:
     [dic setValue:[params objectForKey:@"order_ids"] forKey:@"order_ids"];
     [dic setValue:[params objectForKey:@"targetOrderId"] forKey:@"targetOrderId"];
     [dic setValue:[params objectForKey:@"customerInfo"] forKey:@"customerInfo"];
+    
+    [dic setObject:ScreenCodeOrderList forKey:kScreenName];
+    
     NSData* json=nil;
     if(appDelegate.offline_mode)
     {
@@ -3939,6 +4225,8 @@ repeat:
     [dic setValue:so_id forKey:@"orderCode"];
     [dic setValue:addr forKey:@"email"];
     
+    [dic setObject:ScreenCodeCart forKey:kScreenName];
+    
     if (appDelegate.customerInfo) {
         NSString *customer_cid = [appDelegate.customerInfo objectForKey:@"customer_cid"];
         if (customer_cid) {
@@ -3970,7 +4258,7 @@ repeat:
     return @{@"result" : @(RESULT_FALSE)};
 }
 
-+ (NSDictionary *)notifyModel:(NSString *)modelID emailAddr:(NSString *)addr{
++ (NSDictionary *)notifyModel:(NSString *)modelID emailAddr:(NSString *)addr withScreen:(NSString *)screenName{
     
     NSMutableDictionary* dic = [[NSMutableDictionary alloc] init];
     AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
@@ -3987,6 +4275,8 @@ repeat:
         }
     }
     
+    [dic setObject:screenName forKey:kScreenName];
+    
     [dic setValue:modelID forKey:@"productId"];
     
     if (addr) { // 弹框输入

+ 260 - 2
RedAnt ERP Mobile/iSales-NPD.xcodeproj/project.pbxproj

@@ -31,6 +31,22 @@
 		42A51BF61D62F9AB00F13667 /* orderDetail.json in Resources */ = {isa = PBXBuildFile; fileRef = 42A51BF51D62F9AB00F13667 /* orderDetail.json */; };
 		42B309791E45BA32007AFC62 /* status_filter_cadedate_po.json in Resources */ = {isa = PBXBuildFile; fileRef = 42B309781E45BA32007AFC62 /* status_filter_cadedate_po.json */; };
 		42B3C9BB1D642C880053985C /* order_info.html in Resources */ = {isa = PBXBuildFile; fileRef = 42B3C9BA1D642C880053985C /* order_info.html */; };
+		42BEF34F1E89FE1100632AB6 /* FirebaseAnalytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42BEF3241E89FE1100632AB6 /* FirebaseAnalytics.framework */; };
+		42BEF3501E89FE1100632AB6 /* FirebaseCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42BEF3271E89FE1100632AB6 /* FirebaseCore.framework */; };
+		42BEF3511E89FE1200632AB6 /* CHANGELOG.md in Sources */ = {isa = PBXBuildFile; fileRef = 42BEF3291E89FE1100632AB6 /* CHANGELOG.md */; };
+		42BEF3521E89FE1200632AB6 /* FirebaseInstanceID.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42BEF32B1E89FE1100632AB6 /* FirebaseInstanceID.framework */; };
+		42BEF3531E89FE1200632AB6 /* README.md in Sources */ = {isa = PBXBuildFile; fileRef = 42BEF32C1E89FE1100632AB6 /* README.md */; };
+		42BEF3541E89FE1200632AB6 /* GGLAnalytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42BEF32F1E89FE1100632AB6 /* GGLAnalytics.framework */; };
+		42BEF3551E89FE1200632AB6 /* GGLCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42BEF3301E89FE1100632AB6 /* GGLCore.framework */; };
+		42BEF3561E89FE1200632AB6 /* README.md in Sources */ = {isa = PBXBuildFile; fileRef = 42BEF3391E89FE1100632AB6 /* README.md */; };
+		42BEF3571E89FE1200632AB6 /* libGoogleAnalytics.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42BEF33C1E89FE1100632AB6 /* libGoogleAnalytics.a */; };
+		42BEF3581E89FE1200632AB6 /* GTMNSData+zlib.m in Sources */ = {isa = PBXBuildFile; fileRef = 42BEF34B1E89FE1100632AB6 /* GTMNSData+zlib.m */; };
+		42BEF3591E89FE1200632AB6 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 42BEF34D1E89FE1100632AB6 /* LICENSE */; };
+		42BEF35A1E89FE1200632AB6 /* README.md in Sources */ = {isa = PBXBuildFile; fileRef = 42BEF34E1E89FE1100632AB6 /* README.md */; };
+		42BEF35D1E89FECD00632AB6 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42BEF35C1E89FECD00632AB6 /* SystemConfiguration.framework */; };
+		42BEF35F1E89FEE300632AB6 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42BEF35E1E89FEE300632AB6 /* CoreData.framework */; };
+		42BEF3621E8A005800632AB6 /* GoogleAnalyst.m in Sources */ = {isa = PBXBuildFile; fileRef = 42BEF3611E8A005800632AB6 /* GoogleAnalyst.m */; };
+		42BEF3A61E8A57F600632AB6 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 42BEF3A51E8A57F600632AB6 /* GoogleService-Info.plist */; };
 		42BF67CC1E5179970081F90A /* ERPUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 42BF67CB1E5179970081F90A /* ERPUtils.m */; };
 		42C2E8BC1DB49D02006C0495 /* TearSheet.json in Resources */ = {isa = PBXBuildFile; fileRef = 42C2E8BB1DB49D02006C0495 /* TearSheet.json */; };
 		42C9FB151D5B28FA001DCA8B /* contactAdvanceSearch.json in Resources */ = {isa = PBXBuildFile; fileRef = 42C9FB141D5B28FA001DCA8B /* contactAdvanceSearch.json */; };
@@ -288,6 +304,41 @@
 		42A51BF51D62F9AB00F13667 /* orderDetail.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = orderDetail.json; sourceTree = "<group>"; };
 		42B309781E45BA32007AFC62 /* status_filter_cadedate_po.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = status_filter_cadedate_po.json; path = common/Functions/order/status_filter_cadedate_po.json; sourceTree = SOURCE_ROOT; };
 		42B3C9BA1D642C880053985C /* order_info.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = order_info.html; sourceTree = "<group>"; };
+		42BEF3241E89FE1100632AB6 /* FirebaseAnalytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = FirebaseAnalytics.framework; sourceTree = "<group>"; };
+		42BEF3271E89FE1100632AB6 /* FirebaseCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = FirebaseCore.framework; sourceTree = "<group>"; };
+		42BEF3291E89FE1100632AB6 /* CHANGELOG.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = "<group>"; };
+		42BEF32B1E89FE1100632AB6 /* FirebaseInstanceID.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = FirebaseInstanceID.framework; sourceTree = "<group>"; };
+		42BEF32C1E89FE1100632AB6 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
+		42BEF32F1E89FE1100632AB6 /* GGLAnalytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = GGLAnalytics.framework; sourceTree = "<group>"; };
+		42BEF3301E89FE1100632AB6 /* GGLCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = GGLCore.framework; sourceTree = "<group>"; };
+		42BEF3321E89FE1100632AB6 /* Analytics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Analytics.h; sourceTree = "<group>"; };
+		42BEF3331E89FE1100632AB6 /* Core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Core.h; sourceTree = "<group>"; };
+		42BEF3341E89FE1100632AB6 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
+		42BEF3361E89FE1100632AB6 /* Analytics-Module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Analytics-Module.h"; sourceTree = "<group>"; };
+		42BEF3371E89FE1100632AB6 /* Core-Module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Core-Module.h"; sourceTree = "<group>"; };
+		42BEF3381E89FE1100632AB6 /* SignIn-Module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SignIn-Module.h"; sourceTree = "<group>"; };
+		42BEF3391E89FE1100632AB6 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
+		42BEF33C1E89FE1100632AB6 /* libGoogleAnalytics.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libGoogleAnalytics.a; sourceTree = "<group>"; };
+		42BEF33E1E89FE1100632AB6 /* GAI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GAI.h; sourceTree = "<group>"; };
+		42BEF33F1E89FE1100632AB6 /* GAIDictionaryBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GAIDictionaryBuilder.h; sourceTree = "<group>"; };
+		42BEF3401E89FE1100632AB6 /* GAIEcommerceFields.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GAIEcommerceFields.h; sourceTree = "<group>"; };
+		42BEF3411E89FE1100632AB6 /* GAIEcommerceProduct.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GAIEcommerceProduct.h; sourceTree = "<group>"; };
+		42BEF3421E89FE1100632AB6 /* GAIEcommerceProductAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GAIEcommerceProductAction.h; sourceTree = "<group>"; };
+		42BEF3431E89FE1100632AB6 /* GAIEcommercePromotion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GAIEcommercePromotion.h; sourceTree = "<group>"; };
+		42BEF3441E89FE1100632AB6 /* GAIFields.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GAIFields.h; sourceTree = "<group>"; };
+		42BEF3451E89FE1100632AB6 /* GAILogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GAILogger.h; sourceTree = "<group>"; };
+		42BEF3461E89FE1100632AB6 /* GAITrackedViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GAITrackedViewController.h; sourceTree = "<group>"; };
+		42BEF3471E89FE1100632AB6 /* GAITracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GAITracker.h; sourceTree = "<group>"; };
+		42BEF34A1E89FE1100632AB6 /* GTMNSData+zlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTMNSData+zlib.h"; sourceTree = "<group>"; };
+		42BEF34B1E89FE1100632AB6 /* GTMNSData+zlib.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSData+zlib.m"; sourceTree = "<group>"; };
+		42BEF34C1E89FE1100632AB6 /* GTMDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMDefines.h; sourceTree = "<group>"; };
+		42BEF34D1E89FE1100632AB6 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
+		42BEF34E1E89FE1100632AB6 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
+		42BEF35C1E89FECD00632AB6 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
+		42BEF35E1E89FEE300632AB6 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
+		42BEF3601E8A005800632AB6 /* GoogleAnalyst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GoogleAnalyst.h; sourceTree = "<group>"; };
+		42BEF3611E8A005800632AB6 /* GoogleAnalyst.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GoogleAnalyst.m; sourceTree = "<group>"; };
+		42BEF3A51E8A57F600632AB6 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
 		42BF67CA1E5179970081F90A /* ERPUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ERPUtils.h; path = common/ERPUtils.h; sourceTree = SOURCE_ROOT; };
 		42BF67CB1E5179970081F90A /* ERPUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ERPUtils.m; path = common/ERPUtils.m; sourceTree = SOURCE_ROOT; };
 		42C2E8BB1DB49D02006C0495 /* TearSheet.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = TearSheet.json; sourceTree = "<group>"; };
@@ -687,18 +738,26 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				42BEF35F1E89FEE300632AB6 /* CoreData.framework in Frameworks */,
+				42BEF35D1E89FECD00632AB6 /* SystemConfiguration.framework in Frameworks */,
 				71BBA2291CEAC17E00C91DED /* libz.tbd in Frameworks */,
 				7187162C1C43428100F25860 /* libScanApiCore.a in Frameworks */,
+				42BEF3551E89FE1200632AB6 /* GGLCore.framework in Frameworks */,
 				718716291C433DA400F25860 /* AVFoundation.framework in Frameworks */,
 				718716271C433D9700F25860 /* AudioToolbox.framework in Frameworks */,
+				42BEF3541E89FE1200632AB6 /* GGLAnalytics.framework in Frameworks */,
+				42BEF3501E89FE1100632AB6 /* FirebaseCore.framework in Frameworks */,
 				718716251C433D8B00F25860 /* ExternalAccessory.framework in Frameworks */,
 				716961B519594E1000B19FB4 /* libsqlite3.dylib in Frameworks */,
+				42BEF3521E89FE1200632AB6 /* FirebaseInstanceID.framework in Frameworks */,
 				71DEE876192DE00E003F645F /* Accelerate.framework in Frameworks */,
 				71DEE874192DE003003F645F /* QuartzCore.framework in Frameworks */,
 				713F76AC1929F4A7006A7305 /* CoreGraphics.framework in Frameworks */,
 				713F76AE1929F4A7006A7305 /* UIKit.framework in Frameworks */,
 				713F76AA1929F4A7006A7305 /* Foundation.framework in Frameworks */,
 				A31E80CF7BEA220BD1CC4B97 /* libPods.a in Frameworks */,
+				42BEF34F1E89FE1100632AB6 /* FirebaseAnalytics.framework in Frameworks */,
+				42BEF3571E89FE1200632AB6 /* libGoogleAnalytics.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -771,6 +830,174 @@
 			path = common/JKTimer;
 			sourceTree = SOURCE_ROOT;
 		};
+		42BEF3211E89FE1100632AB6 /* GoogleAnalytics */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3601E8A005800632AB6 /* GoogleAnalyst.h */,
+				42BEF3611E8A005800632AB6 /* GoogleAnalyst.m */,
+				42BEF3221E89FE1100632AB6 /* FirebaseAnalytics */,
+				42BEF3251E89FE1100632AB6 /* FirebaseCore */,
+				42BEF3281E89FE1100632AB6 /* FirebaseInstanceID */,
+				42BEF32D1E89FE1100632AB6 /* Google */,
+				42BEF33A1E89FE1100632AB6 /* GoogleAnalytics */,
+				42BEF3481E89FE1100632AB6 /* GoogleToolboxForMac */,
+			);
+			path = GoogleAnalytics;
+			sourceTree = SOURCE_ROOT;
+		};
+		42BEF3221E89FE1100632AB6 /* FirebaseAnalytics */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3231E89FE1100632AB6 /* Frameworks */,
+			);
+			path = FirebaseAnalytics;
+			sourceTree = "<group>";
+		};
+		42BEF3231E89FE1100632AB6 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3241E89FE1100632AB6 /* FirebaseAnalytics.framework */,
+			);
+			path = Frameworks;
+			sourceTree = "<group>";
+		};
+		42BEF3251E89FE1100632AB6 /* FirebaseCore */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3261E89FE1100632AB6 /* Frameworks */,
+			);
+			path = FirebaseCore;
+			sourceTree = "<group>";
+		};
+		42BEF3261E89FE1100632AB6 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3271E89FE1100632AB6 /* FirebaseCore.framework */,
+			);
+			path = Frameworks;
+			sourceTree = "<group>";
+		};
+		42BEF3281E89FE1100632AB6 /* FirebaseInstanceID */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3291E89FE1100632AB6 /* CHANGELOG.md */,
+				42BEF32A1E89FE1100632AB6 /* Frameworks */,
+				42BEF32C1E89FE1100632AB6 /* README.md */,
+			);
+			path = FirebaseInstanceID;
+			sourceTree = "<group>";
+		};
+		42BEF32A1E89FE1100632AB6 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF32B1E89FE1100632AB6 /* FirebaseInstanceID.framework */,
+			);
+			path = Frameworks;
+			sourceTree = "<group>";
+		};
+		42BEF32D1E89FE1100632AB6 /* Google */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF32E1E89FE1100632AB6 /* Frameworks */,
+				42BEF3311E89FE1100632AB6 /* Headers */,
+				42BEF3391E89FE1100632AB6 /* README.md */,
+			);
+			path = Google;
+			sourceTree = "<group>";
+		};
+		42BEF32E1E89FE1100632AB6 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF32F1E89FE1100632AB6 /* GGLAnalytics.framework */,
+				42BEF3301E89FE1100632AB6 /* GGLCore.framework */,
+			);
+			path = Frameworks;
+			sourceTree = "<group>";
+		};
+		42BEF3311E89FE1100632AB6 /* Headers */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3321E89FE1100632AB6 /* Analytics.h */,
+				42BEF3331E89FE1100632AB6 /* Core.h */,
+				42BEF3341E89FE1100632AB6 /* module.modulemap */,
+				42BEF3351E89FE1100632AB6 /* ModuleHeaders */,
+			);
+			path = Headers;
+			sourceTree = "<group>";
+		};
+		42BEF3351E89FE1100632AB6 /* ModuleHeaders */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3361E89FE1100632AB6 /* Analytics-Module.h */,
+				42BEF3371E89FE1100632AB6 /* Core-Module.h */,
+				42BEF3381E89FE1100632AB6 /* SignIn-Module.h */,
+			);
+			path = ModuleHeaders;
+			sourceTree = "<group>";
+		};
+		42BEF33A1E89FE1100632AB6 /* GoogleAnalytics */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF33B1E89FE1100632AB6 /* Libraries */,
+				42BEF33D1E89FE1100632AB6 /* Sources */,
+			);
+			path = GoogleAnalytics;
+			sourceTree = "<group>";
+		};
+		42BEF33B1E89FE1100632AB6 /* Libraries */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF33C1E89FE1100632AB6 /* libGoogleAnalytics.a */,
+			);
+			path = Libraries;
+			sourceTree = "<group>";
+		};
+		42BEF33D1E89FE1100632AB6 /* Sources */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF33E1E89FE1100632AB6 /* GAI.h */,
+				42BEF33F1E89FE1100632AB6 /* GAIDictionaryBuilder.h */,
+				42BEF3401E89FE1100632AB6 /* GAIEcommerceFields.h */,
+				42BEF3411E89FE1100632AB6 /* GAIEcommerceProduct.h */,
+				42BEF3421E89FE1100632AB6 /* GAIEcommerceProductAction.h */,
+				42BEF3431E89FE1100632AB6 /* GAIEcommercePromotion.h */,
+				42BEF3441E89FE1100632AB6 /* GAIFields.h */,
+				42BEF3451E89FE1100632AB6 /* GAILogger.h */,
+				42BEF3461E89FE1100632AB6 /* GAITrackedViewController.h */,
+				42BEF3471E89FE1100632AB6 /* GAITracker.h */,
+			);
+			path = Sources;
+			sourceTree = "<group>";
+		};
+		42BEF3481E89FE1100632AB6 /* GoogleToolboxForMac */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF3491E89FE1100632AB6 /* Foundation */,
+				42BEF34C1E89FE1100632AB6 /* GTMDefines.h */,
+				42BEF34D1E89FE1100632AB6 /* LICENSE */,
+				42BEF34E1E89FE1100632AB6 /* README.md */,
+			);
+			path = GoogleToolboxForMac;
+			sourceTree = "<group>";
+		};
+		42BEF3491E89FE1100632AB6 /* Foundation */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF34A1E89FE1100632AB6 /* GTMNSData+zlib.h */,
+				42BEF34B1E89FE1100632AB6 /* GTMNSData+zlib.m */,
+			);
+			path = Foundation;
+			sourceTree = "<group>";
+		};
+		42BEF35B1E89FECC00632AB6 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				42BEF35E1E89FEE300632AB6 /* CoreData.framework */,
+				42BEF35C1E89FECD00632AB6 /* SystemConfiguration.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
 		710212821B8D59DE00E1788B /* watchlist */ = {
 			isa = PBXGroup;
 			children = (
@@ -852,6 +1079,7 @@
 			isa = PBXGroup;
 			children = (
 				713F76AF1929F4A7006A7305 /* iSales-NPD */,
+				42BEF35B1E89FECC00632AB6 /* Frameworks */,
 			);
 			sourceTree = "<group>";
 		};
@@ -929,6 +1157,7 @@
 				713F76C11929F4A7006A7305 /* Images.xcassets */,
 				713F76B01929F4A7006A7305 /* Supporting Files */,
 				713F76B11929F4A7006A7305 /* iSales-NPD-Info.plist */,
+				42BEF3A51E8A57F600632AB6 /* GoogleService-Info.plist */,
 				713F76B21929F4A7006A7305 /* InfoPlist.strings */,
 				713F76B51929F4A7006A7305 /* main.m */,
 				713F76B71929F4A7006A7305 /* iSales-NPD-Prefix.pch */,
@@ -1075,6 +1304,7 @@
 			children = (
 				7155444D1E56E0B500A808AA /* HWWeakTimer.h */,
 				7155444E1E56E0B500A808AA /* HWWeakTimer.m */,
+				42BEF3211E89FE1100632AB6 /* GoogleAnalytics */,
 				4289809B1E24B526005F1BD8 /* JKTimer */,
 				4289805A1E249375005F1BD8 /* UIColor+HEX */,
 				4289803C1E249339005F1BD8 /* JKLock */,
@@ -1572,6 +1802,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				42BEF3591E89FE1200632AB6 /* LICENSE in Resources */,
 				7142E87E1DC300690077EFA2 /* DejaVuSans-Bold.ttf in Resources */,
 				7142E87F1DC300690077EFA2 /* DejaVuSans.ttf in Resources */,
 				7115D45D1E16317600EF4E4C /* CommonEditor.storyboard in Resources */,
@@ -1612,6 +1843,7 @@
 				7162A55E1C58724700AB630E /* customer_advanced_search.json in Resources */,
 				7162A5A11C58733400AB630E /* offline_status_filter_cadedate.json in Resources */,
 				42B309791E45BA32007AFC62 /* status_filter_cadedate_po.json in Resources */,
+				42BEF3A61E8A57F600632AB6 /* GoogleService-Info.plist in Resources */,
 				713F76BD1929F4A7006A7305 /* Main.storyboard in Resources */,
 				42A51BF41D62F60300F13667 /* more_info.html in Resources */,
 			);
@@ -1686,6 +1918,7 @@
 				712AFED81DBA050200254965 /* GridDrawable.m in Sources */,
 				7162A5C11C5873BB00AB630E /* FilterCellCadedate.m in Sources */,
 				71DF748A1C57608F00F2789C /* RTLabel.m in Sources */,
+				42BEF3581E89FE1200632AB6 /* GTMNSData+zlib.m in Sources */,
 				71DF742B1C57560600F2789C /* Reachability.m in Sources */,
 				7162A5701C58728D00AB630E /* DetailHeaderCell.m in Sources */,
 				71BBA2271CEAC16000C91DED /* ZipArchive.mm in Sources */,
@@ -1706,6 +1939,7 @@
 				7162A5E01C5876E300AB630E /* SettingViewController.m in Sources */,
 				712AFEDB1DBA050200254965 /* LineDrawable.m in Sources */,
 				71DF748B1C57608F00F2789C /* SimpleGrid.m in Sources */,
+				42BEF3621E8A005800632AB6 /* GoogleAnalyst.m in Sources */,
 				71DF74651C575E7900F2789C /* CommonEditorViewController.m in Sources */,
 				7162A5171C58704600AB630E /* BundleModelViewController.m in Sources */,
 				71DF745B1C575E7900F2789C /* CommonEditorCellAction.m in Sources */,
@@ -1738,6 +1972,7 @@
 				7162A5611C58724700AB630E /* CustomerInfoViewController.m in Sources */,
 				7162A5AB1C58735900AB630E /* PDFListViewController.m in Sources */,
 				71DF74681C575E7900F2789C /* EnumSelectViewController.m in Sources */,
+				42BEF3531E89FE1200632AB6 /* README.md in Sources */,
 				428980471E249339005F1BD8 /* JKLockController.m in Sources */,
 				71D99D301CEF02E700CA32DE /* CustomIOSAlertView.m in Sources */,
 				7162A5731C58728D00AB630E /* DetailTopicCell.m in Sources */,
@@ -1801,6 +2036,7 @@
 				7162A5601C58724700AB630E /* CustomerEditViewController.m in Sources */,
 				718B91831C75638100265FFF /* TouchImageView.m in Sources */,
 				7162A5DC1C5876E300AB630E /* LoginViewController.m in Sources */,
+				42BEF3561E89FE1200632AB6 /* README.md in Sources */,
 				4289805D1E249375005F1BD8 /* UIColor+JK_HEX.m in Sources */,
 				7162A5811C5872EF00AB630E /* HomeTableViewCellBanner.m in Sources */,
 				7162A5E61C58781000AB630E /* iSalesNavigationController.m in Sources */,
@@ -1818,6 +2054,8 @@
 				7162A5471C58719D00AB630E /* RATreeView+Private.m in Sources */,
 				428980041E2490C1005F1BD8 /* NotificationNameCenter.m in Sources */,
 				4289802C1E2492D2005F1BD8 /* CategoryPriceViewController.m in Sources */,
+				42BEF3511E89FE1200632AB6 /* CHANGELOG.md in Sources */,
+				42BEF35A1E89FE1200632AB6 /* README.md in Sources */,
 				71DF748D1C57608F00F2789C /* TouchLabel.m in Sources */,
 				428980171E24924D005F1BD8 /* SortItemViewController.m in Sources */,
 				7162A5711C58728D00AB630E /* DetailImageCell.m in Sources */,
@@ -1992,11 +2230,21 @@
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				DEVELOPMENT_TEAM = HXWLAA5YN5;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(PROJECT_DIR)/GoogleAnalytics/FirebaseAnalytics/Frameworks",
+					"$(PROJECT_DIR)/GoogleAnalytics/FirebaseCore/Frameworks",
+					"$(PROJECT_DIR)/GoogleAnalytics/FirebaseInstanceID/Frameworks",
+					"$(PROJECT_DIR)/GoogleAnalytics/Google/Frameworks",
+				);
 				GCC_PRECOMPILE_PREFIX_HEADER = YES;
 				GCC_PREFIX_HEADER = "iSales-NPD/iSales-NPD-Prefix.pch";
 				INFOPLIST_FILE = "$(SRCROOT)/iSales-NPD/iSales-NPD-Info.plist";
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
-				LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/ScanApiSDK-10.2.227-2/lib";
+				LIBRARY_SEARCH_PATHS = (
+					"$(PROJECT_DIR)/ScanApiSDK-10.2.227-2/lib",
+					"$(PROJECT_DIR)/GoogleAnalytics/GoogleAnalytics/Libraries",
+				);
 				PRODUCT_BUNDLE_IDENTIFIER = "usai.apex.iSales-NPD";
 				PRODUCT_NAME = "NPD Mobile";
 				PROVISIONING_PROFILE = "";
@@ -2012,11 +2260,21 @@
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				DEVELOPMENT_TEAM = HXWLAA5YN5;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(PROJECT_DIR)/GoogleAnalytics/FirebaseAnalytics/Frameworks",
+					"$(PROJECT_DIR)/GoogleAnalytics/FirebaseCore/Frameworks",
+					"$(PROJECT_DIR)/GoogleAnalytics/FirebaseInstanceID/Frameworks",
+					"$(PROJECT_DIR)/GoogleAnalytics/Google/Frameworks",
+				);
 				GCC_PRECOMPILE_PREFIX_HEADER = YES;
 				GCC_PREFIX_HEADER = "iSales-NPD/iSales-NPD-Prefix.pch";
 				INFOPLIST_FILE = "$(SRCROOT)/iSales-NPD/iSales-NPD-Info.plist";
 				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
-				LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/ScanApiSDK-10.2.227-2/lib";
+				LIBRARY_SEARCH_PATHS = (
+					"$(PROJECT_DIR)/ScanApiSDK-10.2.227-2/lib",
+					"$(PROJECT_DIR)/GoogleAnalytics/GoogleAnalytics/Libraries",
+				);
 				PRODUCT_BUNDLE_IDENTIFIER = "usai.apex.iSales-NPD";
 				PRODUCT_NAME = "NPD Mobile";
 				PROVISIONING_PROFILE = "";

+ 45 - 0
RedAnt ERP Mobile/iSales-NPD/AppDelegate.m

@@ -24,11 +24,22 @@
 #import "AddressEditorViewController.h"
 #import "config.h"
 #import "Singleton.h"
+#import "Analytics.h"
+#import "GoogleAnalyst.h"
+#import "ERPUtils.h"
+#import "iSalesNetwork.h"
+
 #define UNZIP_OPEN_FAILED 0
 #define UNZIP_SUCCESS 1
 #define UNZIP_NO_SPACE 2
 #define UNZIP_FILE_DAMAGE 3
 
+@interface AppDelegate ()
+
+@property (nonatomic,strong) NSDate *forgroundDate;
+
+@end
+
 @implementation AppDelegate
 {
 #ifdef USE_SOFTSCAN
@@ -787,6 +798,26 @@ void UncaughtExceptionHandler(NSException *exception) {
     [[NSNotificationCenter defaultCenter] removeObserver:self];
 }
 
+- (void)setUpGoogleAnalytics {
+    
+    // 初始化Google Analytics
+    NSError *configureError;
+    [[GGLContext sharedInstance] configureWithError:&configureError];
+    
+    if (configureError) {
+        DebugLog(@"congigure googleAnalytics error: %@",configureError);
+    }
+    
+    GAI *gai = [GAI sharedInstance];
+    gai.trackUncaughtExceptions = YES;
+//    gai.dispatchInterval = 120;// 每隔 2 分钟调度一次数据
+    
+    // 调试使用
+//    gai.logger.logLevel = kGAILogLevelVerbose;
+//    [[GAI sharedInstance] setDryRun:YES];
+//    
+}
+
 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
 {
 
@@ -796,6 +827,9 @@ void UncaughtExceptionHandler(NSException *exception) {
     self.disable_trigger = false;
     [self initialExceptionHandler];
     [self becomeObserver];
+#ifdef BUILD_NPD
+    [self setUpGoogleAnalytics];
+#endif
     
     [DefaultAppearance init_appearance];
     
@@ -1036,6 +1070,11 @@ void UncaughtExceptionHandler(NSException *exception) {
     
     // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
     // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
+    NSTimeInterval timing = [[NSDate date] timeIntervalSinceDate:self.forgroundDate];
+    self.forgroundDate = nil;
+#ifdef BUILD_NPD
+    [GoogleAnalyst trackTimingWithCategory:@"foreground" interval:timing name:@"user used time" label:nil];
+#endif
 }
 
 - (void)applicationWillEnterForeground:(UIApplication *)application
@@ -1048,6 +1087,10 @@ void UncaughtExceptionHandler(NSException *exception) {
     if(self.download_task!=nil)
         [self download_offline:true checkdiskspace:false];
     // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+    
+    self.forgroundDate = [NSDate date];
+    
+    
 }
 -(void)applicationDidReceiveMemoryWarning:(UIApplication *)application
 {
@@ -1170,6 +1213,7 @@ void UncaughtExceptionHandler(NSException *exception) {
         UIApplication * app = [UIApplication sharedApplication];
         AppDelegate *appDelegate = (AppDelegate *)[app delegate];
         
+        [ERPUtils googleAnalyticsSendRequestString:nil WithScreen:ScreenCodeOfflineSync Action:nil Extra:nil];
         
         AFHTTPRequestSerializer* serializer=[AFHTTPRequestSerializer serializer] ;
         
@@ -1547,6 +1591,7 @@ void UncaughtExceptionHandler(NSException *exception) {
 }
 -(void) download_offline:(bool) start checkdiskspace:(bool) checkdiskspace
 {
+    [ERPUtils googleAnalyticsSendRequestString:nil WithScreen:ScreenCodeOfflineSync Action:nil Extra:nil];
     if(start)
     {
         [ [ UIApplication sharedApplication] setIdleTimerDisabled:YES ] ;

+ 26 - 0
RedAnt ERP Mobile/iSales-NPD/GoogleService-Info.plist

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>TRACKING_ID</key>
+	<string>UA-96243475-2</string>
+	<key>PLIST_VERSION</key>
+	<string>1</string>
+	<key>BUNDLE_ID</key>
+	<string>usai.apex.iSales-NPD</string>
+	<key>PROJECT_ID</key>
+	<string>npd-mobile</string>
+	<key>IS_ADS_ENABLED</key>
+	<false/>
+	<key>IS_ANALYTICS_ENABLED</key>
+	<true/>
+	<key>IS_APPINVITE_ENABLED</key>
+	<false/>
+	<key>IS_GCM_ENABLED</key>
+	<false/>
+	<key>IS_SIGNIN_ENABLED</key>
+	<false/>
+	<key>GOOGLE_APP_ID</key>
+	<string>1:943128505895:ios:a8e066dbaab3a1d6</string>
+</dict>
+</plist>

+ 2 - 1
RedAnt ERP Mobile/iSales-NPD/config.h

@@ -11,7 +11,7 @@
 #define BUILD_NPD
 
 # ifdef DEBUG
-//#define test_server 
+#define test_server 
 # endif
 
 #define exception_switch 1
@@ -24,6 +24,7 @@
 #import "Singleton.h"
 
 
+
 #define PDF_DEBUG false
 
 //#define ENCRYPT_OFF