require 'mongoid' class DigitalAsset include Mongoid::Document include Mongoid::Timestamps field :title, type: String field :changed_at, type: DateTime field :audiences, type: Array, default: [] field :sami_code, type: String field :published_at, type: DateTime field :unpublished_at, type: DateTime field :expires_at, type: DateTime field :guid, type: String field :business_owner, type: String field :summary, type: String field :omniture_codes, type: Array, default: [] field :orderable, :type => Boolean, default: false field :product_ids, type: Array, default: [] field :program_ids, type: Array, default: [] # refactor version: field :path, type: String field :legacy_path, type: String field :doc_changed_at, type: DateTime field :content_type, type: String alias :doctype :content_type alias :doctype_id :content_type field :pages, type: Integer, default: 1 field :size, type: String field :mime_type, type: String field :subject, type: String field :keywords, type: Array, default: [] field :author, type: String field :finra_path, type: String field :fund_codes, type: Array, default: [] field :digital_asset_id, type: String key :digital_asset_id # field :documents, type: Hash # embeds_many :documents, :class_name => 'DigitalAsset::Document' # accepts_nested_attributes_for :documents #Exclude XBRL documents from all queries default_scope excludes(:'content_type' => "LDJDCMAIK") #Had to use static value instead of a Constant scope :title_is, ->(title) { where(:title => title)} scope :business_owner_is, ->(business_owner) { where(:business_owner => business_owner)} scope :guid_is, ->(guid) { where(:guid => guid)} scope :digital_asset_id_is, ->(id) { where(:digital_asset_id => id)} scope :fund_in, ->(fund_codes) {where(:fund_codes.in => fund_codes)} scope :audience_in, ->(audience_id) {where(:audiences.in => audience_id)} scope :audience_investor_approved, -> {where(:audiences.in => [Audience::INVESTOR_APPROVED])} scope :published_since, ->(since) {where(:published_at.gte => since)} scope :content_organization_in, ->(content_organization_id) {where(:content_organization_ids.in => content_organization_id)} scope :program_id_in, ->(program_id) {where(:program_ids.in => program_id)} scope :sami_is, ->(sami_code) {where(:sami_code => sami_code)} scope :sami_in, ->(sami_codes) {where(:sami_code.in => sami_codes)} scope :path_is, ->(path) {where(:'path' => path)} scope :doctype_in, ->(types) {where(:'content_type'.in => types)} scope :content_type_in, ->(types) {where(:'content_type'.in => types)} scope :product_in, ->(types) {where(:product_ids.in => types)} scope :stale, -> {where(:updated_at.lte => 2.minutes.ago)} scope :orderable_is, ->(orderable) {where(:orderable => orderable)} scope :orderable, -> {where(orderable: true)} scope :audience_in, ->(audience) {where(:audiences.in => audience)} scope :alphabetical, order_by(:title => :asc) scope :not_xbrl, -> {excludes(:'content_type' => ContentType::XBRL_DOCUMENT)} # validations validates_presence_of :digital_asset_id, :title, :changed_at, :published_at, :expires_at, :audiences, :path validates_uniqueness_of :path, :digital_asset_id validate :validate_future_expiration # def as_json(opts = {}) # super(opts).merge({:comp_fundcode => fund_codes, :content_type_id => content_type_id, :latest_doc_changed_at => latest_doc_changed_at}) # end def self.purge! DigitalAsset.stale.destroy_all if bulk_processed? end def latest_doc_changed_at doc_changed_at # documents.reduce(nil) do |latest_date, d| # unless d.content_type == '549' # latest_date = d.doc_changed_at if (latest_date == nil || latest_date < d.doc_changed_at) # end # latest_date # end end def validate_future_expiration errors.add(:expires_at, "Expiration date must be at least 1 minute from now") unless expires_at and expires_at > 1.minute.from_now end def self.bulk_processed? (stale.count.to_f / self.count) <= 0.05 end # def path_is(path) # documents.where(path: path).first unless documents.blank? # end # def doc_changed_at(path) # path_is(path).try(:doc_changed_at) # end # def doc_size # first_non_finra.try(:size) # end # def content_type_ids # ids = [] # documents.try(:each) do |d| # ids << d.content_type # end # ids # end # alias :doctype_ids :content_type_ids def has_finra? finra_path.present? end def expired? expires_at < Time.now end # def finra_document # finra_idx = documents.index {|d| d.content_type == ContentType::FINRA} # documents[finra_idx] if finra_idx # end def is_investor_approved? audiences.index(DigitalAsset::Audience::INVESTOR_APPROVED) end alias :investor_approved? :is_investor_approved? def is_institutional_use? audiences.index(DigitalAsset::Audience::INSTITUTIONAL_USE) end alias :institutional_use? :is_institutional_use? def product TaxonomyTerm.label_for_term(product_ids[0]) end def program TaxonomyTerm.label_for_term(program_ids[0]) end def content_org TaxonomyTerm.label_for_term(content_organization_ids[0]) end # def fund_code # pid = product_ids.find {|pid| TaxonomyTerm.term_id_is(pid)[0].try(:fund_code)} # pid and TaxonomyTerm.term_id_is(pid)[0].try(:fund_code).try(:rjust, 5, '0') # end def content_type_label TaxonomyTerm.label_for_term(content_type_id) end def audience TaxonomyTerm.label_for_term(audiences[0]) end def primary_path :path end def primary_extension self.try(:path).try(:split,'.').try(:last).try(:upcase) end private # def first_non_finra # documents.try(:detect) do |d| # d.content_type != ContentType::FINRA # end # end end # class DigitalAsset::Document # include Mongoid::Document # embedded_in :digital_asset # key :path # validates_uniqueness_of :path # validates_presence_of :path #, :doc_changed_at, :content_type # validates_format_of :path, without: /\/manifest|archives\// # dont accept manifest files # end class DigitalAsset::ContentType FINRA = '549' PROSPECTUS = '542' FACTSHEET = '533' COMMENTARY = '532' FUND_YIELD = '538' FLYER = '511' L_SHARE_YIELD_SHEET = 'MCOBX14FY' P_SHARE_YIELD_SHEET = 'MCOBYY7SX' ANNUAL_REPORT = '529' SEMIANNUAL_REPORT = '541' SAI = '540' SUMMARY_PROSPECTUS = '5380' DAILY_HOLDINGS = 'MA53THCZQ' MONTHLY_HOLDINGS = 'MA53Y14FY' BUSINESS_CALENDAR = 'MA540I7SX' WEEKLY_HOLDINGS = 'MA542HDIJ' FUND_DOCUMENTS = '528' FORMS_AND_APPLICATIONS = '496' XBRL_DOCUMENT = 'LDJDCMAIK' FUND_DOC_TYPES = [DAILY_HOLDINGS, WEEKLY_HOLDINGS, MONTHLY_HOLDINGS, COMMENTARY,FACTSHEET, PROSPECTUS,SUMMARY_PROSPECTUS,ANNUAL_REPORT,SEMIANNUAL_REPORT,SAI,BUSINESS_CALENDAR,FUND_YIELD, L_SHARE_YIELD_SHEET, P_SHARE_YIELD_SHEET ] end class DigitalAsset::Audience INVESTOR_APPROVED = '490' INSTITUTIONAL_USE = '491' end FUND_DOC_ORDER = { :daily_holdings => [DigitalAsset::ContentType::DAILY_HOLDINGS], :weekly_holdings => [DigitalAsset::ContentType::WEEKLY_HOLDINGS], :current_monthly_holdings => [ DigitalAsset::ContentType::MONTHLY_HOLDINGS, lambda {|docs| docs[0] ? [docs[0]] : [] } ], :commentary => [DigitalAsset::ContentType::COMMENTARY], :factsheet => [DigitalAsset::ContentType::FACTSHEET], :prospectus => [DigitalAsset::ContentType::PROSPECTUS], :summary_prospectus => [DigitalAsset::ContentType::SUMMARY_PROSPECTUS], :annual_report => [DigitalAsset::ContentType::ANNUAL_REPORT], :semiannual_report => [DigitalAsset::ContentType::SEMIANNUAL_REPORT], :sai => [DigitalAsset::ContentType::SAI], :business_calendar => [DigitalAsset::ContentType::BUSINESS_CALENDAR], :prior_monthly_holdings => [ DigitalAsset::ContentType::MONTHLY_HOLDINGS, lambda {|docs| docs } ], :fund_yield => [DigitalAsset::ContentType::FUND_YIELD] }