module AppManager module Model extend ActiveSupport::Concern def has_plan_old if !self[AppManager.configuration.plan_id_or_name_field] return false; end if self[AppManager.configuration.field_names['grandfathered']] return true; end plan_id = self[AppManager.configuration.plan_id_or_name_field] if !plan_id return false; end remaining_days = fetch_static_remaining_days if remaining_days.to_i > 0 return true end # plan_obj = AppManager::Client.new # shop_domain = self[AppManager.configuration.shopify_domain_field] # active_charge = plan_obj.get_charge(shop_domain) rescue nil active_charge = fetch_static_get_charge return active_charge && active_charge['active_charge'].present? && !active_charge['active_charge'].nil? ? true : false end def has_plan plan_id = self[AppManager.configuration.plan_id_or_name_field] if !plan_id return false; end grandfathered = self[AppManager.configuration.field_names['grandfathered']] grandfathered = grandfathered ? 1 : 0 shop_domain = self[AppManager.configuration.shopify_domain_field] rescue nil trial_activated_at_val = self[AppManager.configuration.field_names['trial_activated_at']] rescue nil plan_obj = AppManager::Client.new response = plan_obj.has_plan(shop_domain, plan_id, trial_activated_at_val, grandfathered) return (response && response['has_plan']) || false end def plan_features plan_id = self[AppManager.configuration.plan_id_or_name_field] if !plan_id return [] end plan_obj = AppManager::Client.new plans = plan_obj.get_plan(plan_id) if plans && plans['features'].blank? return [] end features_by_plan = plans['features'].map { |h| h.slice('value', 'feature_id') } all_features = AppManager.configuration.plan_features feature_plan_ids = features_by_plan.map { |c| c['feature_id'] } pf = all_features.select { |x| feature_plan_ids.include?(x['uuid']) }.each { |g| g["value"] = features_by_plan.find { |e| e['feature_id'] == g['uuid'] }['value'] } return pf end def has_feature(slug) self.plan_features.any? && self.plan_features.select { |x| x['slug'].to_s == slug }.size > 0 ? true : false end def get_feature(slug) plan_features = self.plan_features features = plan_features.select { |x| x['slug'].to_s == slug } if features.any? feature = features.first return casted_value(feature['value'], feature['value_type']) else nil end end def get_remaining_days begin shop_domain = self[AppManager.configuration.shopify_domain_field] trial_activated_at_field = AppManager.configuration.field_names['trial_activated_at'] trial_activated_at_val = self[trial_activated_at_field] plan_field = AppManager.configuration.field_names['plan_id'] plan_id = self[plan_field] plan_obj = AppManager::Client.new res = plan_obj.get_remaining_days(shop_domain, trial_activated_at_val, plan_id) return (res && !res.nil?) ? res : 0 rescue Exception => e return 0 end end def get_plan(plan_id = nil) req_plan_id = nil if !plan_id.nil? req_plan_id = plan_id else shop_plan_id = self[AppManager.configuration.plan_id_or_name_field] if shop_plan_id && !shop_plan_id.nil? req_plan_id = shop_plan_id else return {} end end plan_obj = AppManager::Client.new if req_plan_id return req_plan_id ? plan_obj.get_plan(req_plan_id) : {} end def get_charge shop_plan_id = self[AppManager.configuration.plan_id_or_name_field] found_free_plan = false if shop_plan_id && !shop_plan_id.nil? plan_obj = AppManager::Client.new plan = plan_obj.get_plan(shop_plan_id) rescue nil if plan && plan['price'] == 0 && plan['public'] == true found_free_plan = true return nil end end if !found_free_plan begin shop_domain = self[AppManager.configuration.shopify_domain_field] plan_obj = AppManager::Client.new return plan_obj.get_charge(shop_domain) rescue Exception => e return nil end end end def get_all_plans begin shop_domain = self[AppManager.configuration.shopify_domain_field] shop_plan_id = self[AppManager.configuration.plan_id_or_name_field] active_plan_id = shop_plan_id && shop_plan_id.nil? ? nil : shop_plan_id plan_obj = AppManager::Client.new return plan_obj.get_plans(shop_domain, active_plan_id) rescue Exception => e return [] end end def cancel_charge begin shop_plan_id = self[AppManager.configuration.plan_id_or_name_field] shop_domain = self[AppManager.configuration.shopify_domain_field] if shop_plan_id && shop_domain plan_obj = AppManager::Client.new plan_obj.cancel_charge(shop_domain, shop_plan_id) end rescue Exception => e return "#{e.inspect}-#{e.backtrace}" end end def cancel_current_shopify_charge begin @field_names = AppManager.configuration.field_names shopify_active_charge_id = self.active_shopify_charge_id if shopify_active_charge_id.present? gq_obj = AppManager::GraphqlHelper.new(self.shopify_domain, self.shopify_token) rec_cancel_data = gq_obj.recurring_charge_cancel_api_call(shopify_active_charge_id, self) if !rec_cancel_data["errors"].present? && (rec_cancel_data["data"].present? && rec_cancel_data["data"]["appSubscriptionCancel"].present? && !rec_cancel_data["data"]["appSubscriptionCancel"]["userErrors"].any? && (rec_cancel_data["data"]["appSubscriptionCancel"]["appSubscription"]["status"] == 'CANCELLED')) cancelled_charge_id = rec_cancel_data["data"]["appSubscriptionCancel"]["appSubscription"]["id"].split('/')[-1] self.cancel_charge grandfathered_field = @field_names['grandfathered'] update_info = {AppManager.configuration.plan_id_or_name_field => nil,grandfathered_field => false} if self.update(update_info) AppManager.clear_cache end end end rescue Exception => e return "#{e.inspect}-#{e.backtrace}" end end def get_current_shopify_charge begin gq_obj = AppManager::GraphqlHelper.new(self.shopify_domain, self.shopify_token) data = gq_obj.recurring_charge_current_api_call(self) if !data["errors"].present? && (data["data"].present? && data["data"]["currentAppInstallation"].present? && data["data"]["currentAppInstallation"]["activeSubscriptions"].present?) return data["data"]["currentAppInstallation"]["activeSubscriptions"].first end rescue Exception => e Rollbar.error("Warning in APP MANAGER, trying to get_current_shopify_charge >>>> #{e.inspect}-#{e.backtrace}") return nil end end def get_active_charge_app_manager active_charge = self.get_charge rescue nil return active_charge && active_charge['active_charge'].present? && !active_charge['active_charge'].nil? ? active_charge['active_charge'] : nil end def has_valid_app_manager_plan_id shop_plan_id = self[AppManager.configuration.plan_id_or_name_field] shop_domain = self[AppManager.configuration.shopify_domain_field] plan_obj = AppManager::Client.new plans = plan_obj.get_plans(shop_domain) rescue nil return shop_plan_id && (plans && plans.any? && plans.collect{|e| e['id']}.include?(shop_plan_id)) ? true : false end def update_app_manager_charge(current_shopify_charge_id=nil) charge_updated = nil begin shop_plan_id = self[AppManager.configuration.plan_id_or_name_field] shop_domain = self[AppManager.configuration.shopify_domain_field] if get_active_charge_app_manager.nil? current_charge_id = current_shopify_charge_id.present? ? current_shopify_charge_id : active_shopify_charge_id if current_charge_id.present? if has_valid_app_manager_plan_id if charge_update_call(self,shop_plan_id,current_charge_id) charge_updated = true end end end end return charge_updated rescue Exception => e Rollbar.error("Warning in APP MANAGER, trying to get update_app_manager_charge >>>> #{e.inspect}-#{e.backtrace}") return nil end end def update_app_manager_charge_with_plan_id(current_shopify_charge_id=nil,shop_custom_plan_id=nil) charge_updated = nil begin shop_plan_id = self[AppManager.configuration.plan_id_or_name_field] shop_domain = self[AppManager.configuration.shopify_domain_field] current_charge_id = current_shopify_charge_id.present? ? current_shopify_charge_id : active_shopify_charge_id plan_id = shop_custom_plan_id.present? ? shop_custom_plan_id : shop_plan_id if current_charge_id.present? if plan_id.present? if charge_update_call(self,plan_id,current_charge_id) charge_updated = true end end end return charge_updated rescue Exception => e Rollbar.error("Warning in APP MANAGER, trying to get update_app_manager_charge_with_plan_id >>>> #{e.inspect}-#{e.backtrace}") return nil end end def active_shopify_charge_id begin get_active_shopify_charge = self.get_current_shopify_charge if get_active_shopify_charge.present? && !get_active_shopify_charge.nil? current_shopify_charge_id = get_active_shopify_charge["id"] if current_shopify_charge_id return current_shopify_charge_id.split('/')[-1] rescue nil else return nil end else return nil end rescue Exception => e Rollbar.error("Warning in APP MANAGER, trying to get active shopify charge id >>>> #{e.inspect}-#{e.backtrace}") return nil end end def app_manager_charge_update(shop,shopify_current_charge_obj) if shop.present? && shop.plan_id.present? && shopify_current_charge_obj.present? charge_update_call(shop,shop.plan_id,shopify_current_charge_obj['id'],shopify_current_charge_obj) end end def charge_update_call(shop,shop_plan_id,current_charge_id,charge_obj={}) charge_callback_done = nil # begin @shop = shop @field_names = AppManager.configuration.field_names shopify_token = @field_names['shopify_token'] shopify_domain = @field_names['name'] grandfathered_field = @field_names['grandfathered'] shop_domain = @shop[AppManager.configuration.shopify_domain_field] if !@shop.nil? if charge_obj.present? && !charge_obj.nil? shopify_charge_obj = charge_obj else headers = {"X-Shopify-Access-Token" => @shop[shopify_token]} charges = HTTParty.get('https://' + shop_domain + '/admin/api/' + AppManager.configuration.shopify_api_version + '/recurring_application_charges/' + current_charge_id + '.json', :headers => headers) shopify_charge_obj = charges.parsed_response && charges.parsed_response.is_a?(Hash) && charges.parsed_response.has_key?('recurring_application_charge') ? charges.parsed_response['recurring_application_charge'] : {} end if shopify_charge_obj.present? plan_obj = AppManager::Client.new plan_data = plan_obj.get_plan(shop_plan_id, shop_domain) charge = shopify_charge_obj charge['charge_id'] = charge['id'] charge['type'] = 'recurring' charge['plan_id'] = shop_plan_id charge['shop_domain'] = shop_domain charge['interval'] = plan_data['interval']['value'] ['api_client_id', 'return_url', 'decorated_return_url','id','id','currency'].each { |k| charge.delete k } charge_ob = AppManager::Client.new(nil, json_req = true) response = charge_ob.store_charge(charge.to_json) if response['message'] == "success" AppManager.clear_cache update_info = {AppManager.configuration.plan_id_or_name_field => shop_plan_id,grandfathered_field => 0} if !config_trial_days.nil? && !plan_data.nil? trial_days = plan_data['trial_days'] || 0 update_info[config_trial_days] = trial_days end if @shop.update(update_info) charge_callback_done = true end Thread.new do charge_data = plan_obj.get_charge(@shop[shopify_domain]) begin AppManager::EventHandler.new('charge_created', { "plan" => plan_data, "charge" => charge, "previous_charge" => charge_data ? (charge_data['cancelled_charge'] || nil) : nil, "shopify_domain" => shop_domain }) rescue Exception => e Rollbar.error("Warning in APP MANAGER model Charge Created Callback Event Fire>>>> #{e.inspect}-#{e.backtrace}") end Thread.exit # Terminate the thread once processing is done end end end end return charge_callback_done # rescue Exception => e # Rollbar.error("Warning in APP MANAGER model charge_callback, trying to update active shopify charge in app manager>>>> #{e.inspect}-#{e.backtrace}") # return nil # end end def active_shopfiy_charge_full active_charge_id = self.active_shopify_charge_id if active_charge_id.present? gq_obj = AppManager::GraphqlHelper.new(self.shopify_domain, self.shopify_token) rac_data = gq_obj.current_rc_charge_gql(active_charge_id) return rac_data else return nil end end def config_trial_days @field_names = AppManager.configuration.field_names if !@field_names.nil? && @field_names.has_key?('total_trial_days') && !@field_names['total_trial_days'].nil? && !@field_names['total_trial_days'].blank? return @field_names['total_trial_days'] else return nil end end def set_default_plan(plan_id = nil) begin if plan_id.nil? shop_domain = self[AppManager.configuration.shopify_domain_field] plan_obj = AppManager::Client.new plans = plan_obj.get_plans(shop_domain) free_plans = plans.select { |x| x['price'] == 0 && x['public'] == true } if free_plans.any? self.plan_id = free_plans.first["id"] self.save else raise Error, "Free Plan is not available" end else self.plan_id = plan_id self.save end rescue Exception => e return "#{e.inspect}-#{e.backtrace}" end end def get_plans_by_features(feature_slugs, params = "false") if feature_slugs.any? shop_plan_id = self[AppManager.configuration.plan_id_or_name_field] plan_data = [] shop_domain = self[AppManager.configuration.shopify_domain_field] plan_obj = AppManager::Client.new plans = plan_obj.get_plans(shop_domain) plans = plans.select { |x| x['interval'] == 'EVERY_30_DAYS' && x['public'] == true } plans.each do |plan| next if (params && !params.nil? && params == "exclude_current_plan" && !shop_plan_id.nil? && !plan["id"].nil? && plan["id"] == shop_plan_id) if plan && (plan['features'] && plan['features'].any?) && (plan['features'].values && plan['features'].values.any?) && (plan['features'].values.collect { |c| c['slug'] } && plan['features'].values.collect { |c| c['slug'] }.any?) plan_feature_slugs = plan['features'].values.collect { |c| c['slug'] }.sort if plan_feature_slugs && (feature_slugs & plan_feature_slugs).any? && ((feature_slugs & plan_feature_slugs).sort == feature_slugs.sort) plan_data.push(plan) end end end return plan_data else return [] end end def fetch_static_remaining_days @remaining_cache_key = "app-manager-cache/#{self.shopify_domain}-remaining_days" if fetch_cached_static_remaining_days(@remaining_cache_key).present? return fetch_cached_static_remaining_days(@remaining_cache_key) end remaining_days = self.get_remaining_days Rails.cache.write(@remaining_cache_key, remaining_days, expires_in: AppManager.configuration.expires_in) return remaining_days end def fetch_cached_static_remaining_days(cache_key) if Rails.cache.read(cache_key).present? return Rails.cache.read(cache_key) end end def fetch_static_get_charge @get_charge_key = "app-manager-cache/#{self.shopify_domain}-get_charge" if fetch_cached_static_get_charge(@get_charge_key).present? return fetch_cached_static_get_charge(@get_charge_key) end charge = self.get_charge Rails.cache.write(@get_charge_key, charge, expires_in: AppManager.configuration.expires_in) return charge end def fetch_cached_static_get_charge(cache_key) if Rails.cache.read(cache_key).present? return Rails.cache.read(cache_key) end end private def casted_value(value, value_type) case value_type when "integer" value.to_i when "boolean" case value when true, 'true', 1, '1' return true when false, 'false', 0, '0' return false end when "string" value.to_s else value end end end end